From 889123b45b659856652eb490a6e7e605719bfdd4 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Fri, 15 Feb 2019 15:33:03 +0500 Subject: [PATCH 1/3] Add weak collections --- package.json | 2 +- src/LuaLib.ts | 4 + src/LuaTransformer.ts | 6 ++ src/lualib/WeakMap.ts | 51 +++++++++++ src/lualib/WeakSet.ts | 46 ++++++++++ src/lualib/tslint.json | 6 ++ test/unit/lualib/weakMap.spec.ts | 148 +++++++++++++++++++++++++++++++ test/unit/lualib/weakSet.spec.ts | 101 +++++++++++++++++++++ 8 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 src/lualib/WeakMap.ts create mode 100644 src/lualib/WeakSet.ts create mode 100644 src/lualib/tslint.json create mode 100644 test/unit/lualib/weakMap.spec.ts create mode 100644 test/unit/lualib/weakSet.spec.ts diff --git a/package.json b/package.json index a7df3d544..2339b7ce1 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "release-major": "npm version major", "preversion": "npm run build && npm test", "postversion": "git push && git push --tags", - "style-check": "tslint -p . && tslint -c ./tslint.json src/lualib/*.ts" + "style-check": "tslint -p . && tslint -c src/lualib/tslint.json src/lualib/*.ts" }, "bin": { "tstl": "./dist/index.js" diff --git a/src/LuaLib.ts b/src/LuaLib.ts index b39b3e4c4..a7b80e5e5 100644 --- a/src/LuaLib.ts +++ b/src/LuaLib.ts @@ -23,6 +23,8 @@ export enum LuaLibFeature { Iterator = "Iterator", Map = "Map", Set = "Set", + WeakMap = "WeakMap", + WeakSet = "WeakSet", StringReplace = "StringReplace", StringSplit = "StringSplit", StringConcat = "StringConcat", @@ -33,6 +35,8 @@ const luaLibDependencies: {[lib in LuaLibFeature]?: LuaLibFeature[]} = { Iterator: [LuaLibFeature.Symbol], Map: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol], Set: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol], + WeakMap: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol], + WeakSet: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol], }; export class LuaLib { diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 91c63a775..bb9dc5acc 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -3544,6 +3544,12 @@ export class LuaTransformer { case "Set": this.importLuaLibFeature(LuaLibFeature.Set); return; + case "WeakMap": + this.importLuaLibFeature(LuaLibFeature.WeakMap); + return; + case "WeakSet": + this.importLuaLibFeature(LuaLibFeature.WeakSet); + return; } } } diff --git a/src/lualib/WeakMap.ts b/src/lualib/WeakMap.ts new file mode 100644 index 000000000..0d1496e3e --- /dev/null +++ b/src/lualib/WeakMap.ts @@ -0,0 +1,51 @@ +declare function setmetatable(obj: T, metatable: any): T; + +class WeakMap { + private items: {[key: string]: TValue}; // Type of key is actually TKey + + constructor(other: Iterable<[TKey, TValue]> | Array<[TKey, TValue]>) { + this.items = {}; + setmetatable(this.items, { __mode: 'k' }); + + if (other) { + const iterable = other as Iterable<[TKey, TValue]>; + if (iterable[Symbol.iterator]) { + // Iterate manually because WeakMap is compiled with ES5 which doesn't support Iterables in for...of + const iterator = iterable[Symbol.iterator](); + while (true) { + const result = iterator.next(); + if (result.done) { + break; + } + const value: [TKey, TValue] = result.value; // Ensures index is offset when tuple is accessed + this.set(value[0], value[1]); + } + } else { + for (const kvp of other as Array<[TKey, TValue]>) { + this.set(kvp[0], kvp[1]); + } + } + } + } + + public delete(key: TKey): boolean { + const contains = this.has(key); + this.items[key as any] = undefined; + return contains; + } + + public get(key: TKey): TValue { + return this.items[key as any]; + } + + public has(key: TKey): boolean { + return this.items[key as any] !== undefined; + } + + public set(key: TKey, value: TValue): WeakMap { + const keyType = typeof key; + if (keyType !== "object" && keyType !== "function") throw "​​Invalid value used as weak map key​​"; + this.items[key as any] = value; + return this; + } +} diff --git a/src/lualib/WeakSet.ts b/src/lualib/WeakSet.ts new file mode 100644 index 000000000..aaafdb07a --- /dev/null +++ b/src/lualib/WeakSet.ts @@ -0,0 +1,46 @@ +declare function setmetatable(obj: T, metatable: any): T; + +class WeakSet { + private items: {[key: string]: boolean}; // Key type is actually TValue + + constructor(other: Iterable | TValue[]) { + this.items = {}; + setmetatable(this.items, { __mode: 'k' }); + + if (other) { + const iterable = other as Iterable; + if (iterable[Symbol.iterator]) { + // Iterate manually because WeakSet is compiled with ES5 which doesn't support Iterables in for...of + const iterator = iterable[Symbol.iterator](); + while (true) { + const result = iterator.next(); + if (result.done) { + break; + } + this.add(result.value); + } + } else { + for (const value of other as TValue[]) { + this.add(value); + } + } + } + } + + public add(value: TValue): WeakSet { + const valueType = typeof value; + if (valueType !== "object" && valueType !== "function") throw "​​​​​​Invalid value used in weak set​​"; + this.items[value as any] = true; + return this; + } + + public delete(value: TValue): boolean { + const contains = this.has(value); + this.items[value as any] = undefined; + return contains; + } + + public has(value: TValue): boolean { + return this.items[value as any] === true; + } +} diff --git a/src/lualib/tslint.json b/src/lualib/tslint.json new file mode 100644 index 000000000..2398d44cd --- /dev/null +++ b/src/lualib/tslint.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tslint.json", + "rules": { + "no-string-throw": false + } +} diff --git a/test/unit/lualib/weakMap.spec.ts b/test/unit/lualib/weakMap.spec.ts new file mode 100644 index 000000000..6d4a59b21 --- /dev/null +++ b/test/unit/lualib/weakMap.spec.ts @@ -0,0 +1,148 @@ +import { Expect, Test } from "alsatian"; +import * as util from "../../src/util"; + +export class WeakMapTests { + private initRefsTs = `let ref = {}; + let ref2 = () => {};`; + + @Test("weakMap constructor") + public weakMapConstructor(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap([[ref, 1]]); + return mymap.get(ref); + `); + + Expect(result).toBe(1); + } + + @Test("weakMap invalid constructor") + public weakMapInvalidConstructor(): void + { + Expect(() => util.transpileAndExecute(`new WeakMap([["a", true]])`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakMap([[0, true]])`)).toThrow(); + } + + @Test("weakMap iterable constructor") + public weakMapIterableConstructor(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap([[ref, 1], [ref2, 2]]); + return mymap.has(ref) && mymap.has(ref2); + `); + + Expect(result).toBe(true); + } + + @Test("weakMap iterable constructor map") + public weakMapIterableConstructor2(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap(new Map([[ref, 1], [ref2, 2]])); + return mymap.has(ref) && mymap.has(ref2); + `); + + Expect(result).toBe(true); + } + + @Test("weakMap delete") + public weakMapDelete(): void + { + const contains = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap([[ref, true], [ref2, true]]); + mymap.delete(ref2); + return mymap.has(ref) && !mymap.has(ref2); + `); + + Expect(contains).toBe(true); + } + + @Test("weakMap get") + public weakMapGet(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap([[ref, 1], [{}, 2]]); + return mymap.get(ref); + `); + + Expect(result).toBe(1); + } + + @Test("weakMap get missing") + public weakMapGetMissing(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap([[{}, true]]); + return mymap.get({}); + `); + + Expect(result).toBe(undefined); + } + + @Test("weakMap has") + public weakMapHas(): void + { + const contains = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap([[ref, true]]); + return mymap.has(ref); + `); + + Expect(contains).toBe(true); + } + + @Test("weakMap has false") + public weakMapHasFalse(): void + { + const contains = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap([[ref, true]]); + return mymap.has(ref2); + `); + + Expect(contains).toBe(false); + } + + @Test("weakMap has null") + public weakMapHasNull(): void + { + const contains = util.transpileAndExecute(this.initRefsTs + ` + let mymap = new WeakMap([[{}, true]]); + return mymap.has(null); + `); + + Expect(contains).toBe(false); + } + + @Test("weakMap set") + public weakMapSet(): void + { + const init = this.initRefsTs + ` + let mymap = new WeakMap(); + mymap.set(ref, 5); + `; + + const has = util.transpileAndExecute(init + `return mymap.has(ref);`); + Expect(has).toBe(true); + + const value = util.transpileAndExecute(init + `return mymap.get(ref)`); + Expect(value).toBe(5); + } + + @Test("weakMap set invalid") + public weakMapSetInvalid(): void + { + Expect(() => util.transpileAndExecute(`new WeakMap().set("a", true)`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakMap().set(0, true)`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakMap().set(null, true)`)).toThrow(); + } + + @Test("weakMap has no map features") + public weakMapHasNoMapFeatures(): void + { + Expect(util.transpileAndExecute(`return new WeakMap().size`)).toBe(undefined); + Expect(() => util.transpileAndExecute(`new WeakMap().clear()`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakMap().keys()`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakMap().values()`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakMap().entries()`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakMap().forEach(() => {})`)).toThrow(); + } +} diff --git a/test/unit/lualib/weakSet.spec.ts b/test/unit/lualib/weakSet.spec.ts new file mode 100644 index 000000000..4b9961cdb --- /dev/null +++ b/test/unit/lualib/weakSet.spec.ts @@ -0,0 +1,101 @@ +import { Expect, Test } from "alsatian"; +import * as util from "../../src/util"; + +export class WeakSetTests { + private initRefsTs = `let ref = {}; + let ref2 = () => {};`; + + @Test("weakSet constructor") + public weakSetConstructor(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let myset = new WeakSet([ref]); + return myset.has(ref) + `); + + Expect(result).toBe(true); + } + + @Test("weakSet invalid constructor") + public weakSetInvalidConstructor(): void + { + Expect(() => util.transpileAndExecute(`new WeakSet(["a"])`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakSet([0])`)).toThrow(); + } + + @Test("weakSet iterable constructor") + public weakSetIterableConstructor(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let myset = new WeakSet([ref, ref2]); + return myset.has(ref) && myset.has(ref2); + `); + + Expect(result).toBe(true); + } + + @Test("weakSet iterable constructor set") + public weakSetIterableConstructorSet(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let myset = new WeakSet(new Set([ref, ref2])); + return myset.has(ref) && myset.has(ref2); + `); + + Expect(result).toBe(true); + } + + @Test("weakSet add") + public weakSetAdd(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let myset = new WeakSet(); + myset.add(ref); + return myset.has(ref); + `); + + Expect(result).toBe(true); + } + + @Test("weakSet add different references") + public weakSetAddDifferentReferences(): void + { + const result = util.transpileAndExecute(this.initRefsTs + ` + let myset = new WeakSet(); + myset.add({}); + return myset.has({}); + `); + + Expect(result).toBe(false); + } + + @Test("weakSet add invalid") + public weakSetAddInvalid(): void + { + Expect(() => util.transpileAndExecute(`new WeakSet().add("a")`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakSet().add(0)`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakSet().add(null)`)).toThrow(); + } + + @Test("weakSet delete") + public weakSetDelete(): void + { + const contains = util.transpileAndExecute(this.initRefsTs + ` + let myset = new WeakSet([ref, ref2]); + myset.delete(ref); + return myset.has(ref2) && !myset.has(ref); + `); + Expect(contains).toBe(true); + } + + @Test("weakSet has no set features") + public weakSetHasNoSetFeatures(): void + { + Expect(util.transpileAndExecute(`return new WeakSet().size`)).toBe(undefined); + Expect(() => util.transpileAndExecute(`new WeakSet().clear()`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakSet().keys()`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakSet().values()`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakSet().entries()`)).toThrow(); + Expect(() => util.transpileAndExecute(`new WeakSet().forEach(() => {})`)).toThrow(); + } +} From 540c544187f746133f0d5eb4560fee2afea7964c Mon Sep 17 00:00:00 2001 From: ark120202 Date: Fri, 15 Feb 2019 16:01:29 +0500 Subject: [PATCH 2/3] Remove runtime weak reference type checks --- package.json | 2 +- src/lualib/Set.ts | 2 +- src/lualib/WeakMap.ts | 4 +--- src/lualib/WeakSet.ts | 4 +--- src/lualib/tslint.json | 6 ------ test/unit/lualib/weakMap.spec.ts | 15 --------------- test/unit/lualib/weakSet.spec.ts | 15 --------------- 7 files changed, 4 insertions(+), 44 deletions(-) delete mode 100644 src/lualib/tslint.json diff --git a/package.json b/package.json index 2339b7ce1..a7df3d544 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "release-major": "npm version major", "preversion": "npm run build && npm test", "postversion": "git push && git push --tags", - "style-check": "tslint -p . && tslint -c src/lualib/tslint.json src/lualib/*.ts" + "style-check": "tslint -p . && tslint -c ./tslint.json src/lualib/*.ts" }, "bin": { "tstl": "./dist/index.js" diff --git a/src/lualib/Set.ts b/src/lualib/Set.ts index b81bc25c8..2b06ee1d4 100644 --- a/src/lualib/Set.ts +++ b/src/lualib/Set.ts @@ -26,7 +26,7 @@ class Set { const arr = other as TValue[]; this.size = arr.length; for (const value of arr) { - this.items[value as any] = true as any; + this.items[value as any] = true; } } } diff --git a/src/lualib/WeakMap.ts b/src/lualib/WeakMap.ts index 0d1496e3e..3f92cf3df 100644 --- a/src/lualib/WeakMap.ts +++ b/src/lualib/WeakMap.ts @@ -22,7 +22,7 @@ class WeakMap { } } else { for (const kvp of other as Array<[TKey, TValue]>) { - this.set(kvp[0], kvp[1]); + this.items[kvp[0] as any] = kvp[1]; } } } @@ -43,8 +43,6 @@ class WeakMap { } public set(key: TKey, value: TValue): WeakMap { - const keyType = typeof key; - if (keyType !== "object" && keyType !== "function") throw "​​Invalid value used as weak map key​​"; this.items[key as any] = value; return this; } diff --git a/src/lualib/WeakSet.ts b/src/lualib/WeakSet.ts index aaafdb07a..7cfae57f3 100644 --- a/src/lualib/WeakSet.ts +++ b/src/lualib/WeakSet.ts @@ -21,15 +21,13 @@ class WeakSet { } } else { for (const value of other as TValue[]) { - this.add(value); + this.items[value as any] = true; } } } } public add(value: TValue): WeakSet { - const valueType = typeof value; - if (valueType !== "object" && valueType !== "function") throw "​​​​​​Invalid value used in weak set​​"; this.items[value as any] = true; return this; } diff --git a/src/lualib/tslint.json b/src/lualib/tslint.json deleted file mode 100644 index 2398d44cd..000000000 --- a/src/lualib/tslint.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../../tslint.json", - "rules": { - "no-string-throw": false - } -} diff --git a/test/unit/lualib/weakMap.spec.ts b/test/unit/lualib/weakMap.spec.ts index 6d4a59b21..faea5fb2d 100644 --- a/test/unit/lualib/weakMap.spec.ts +++ b/test/unit/lualib/weakMap.spec.ts @@ -16,13 +16,6 @@ export class WeakMapTests { Expect(result).toBe(1); } - @Test("weakMap invalid constructor") - public weakMapInvalidConstructor(): void - { - Expect(() => util.transpileAndExecute(`new WeakMap([["a", true]])`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakMap([[0, true]])`)).toThrow(); - } - @Test("weakMap iterable constructor") public weakMapIterableConstructor(): void { @@ -127,14 +120,6 @@ export class WeakMapTests { Expect(value).toBe(5); } - @Test("weakMap set invalid") - public weakMapSetInvalid(): void - { - Expect(() => util.transpileAndExecute(`new WeakMap().set("a", true)`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakMap().set(0, true)`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakMap().set(null, true)`)).toThrow(); - } - @Test("weakMap has no map features") public weakMapHasNoMapFeatures(): void { diff --git a/test/unit/lualib/weakSet.spec.ts b/test/unit/lualib/weakSet.spec.ts index 4b9961cdb..5bb1cd22d 100644 --- a/test/unit/lualib/weakSet.spec.ts +++ b/test/unit/lualib/weakSet.spec.ts @@ -16,13 +16,6 @@ export class WeakSetTests { Expect(result).toBe(true); } - @Test("weakSet invalid constructor") - public weakSetInvalidConstructor(): void - { - Expect(() => util.transpileAndExecute(`new WeakSet(["a"])`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakSet([0])`)).toThrow(); - } - @Test("weakSet iterable constructor") public weakSetIterableConstructor(): void { @@ -69,14 +62,6 @@ export class WeakSetTests { Expect(result).toBe(false); } - @Test("weakSet add invalid") - public weakSetAddInvalid(): void - { - Expect(() => util.transpileAndExecute(`new WeakSet().add("a")`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakSet().add(0)`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakSet().add(null)`)).toThrow(); - } - @Test("weakSet delete") public weakSetDelete(): void { From c6062ad43181c383acce6dc9867794a9534c2d74 Mon Sep 17 00:00:00 2001 From: ark120202 Date: Fri, 15 Feb 2019 16:10:22 +0500 Subject: [PATCH 3/3] Fix weak collections tests with enabled diagnostics --- test/src/util.ts | 4 ++-- test/unit/lualib/weakMap.spec.ts | 13 +++++++------ test/unit/lualib/weakSet.spec.ts | 13 +++++++------ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/test/src/util.ts b/test/src/util.ts index ea122719e..9e9635ec9 100644 --- a/test/src/util.ts +++ b/test/src/util.ts @@ -84,14 +84,14 @@ export function transpileAndExecute( tsStr: string, compilerOptions?: CompilerOptions, luaHeader?: string, - tsHeader?: string + tsHeader?: string, + ignoreDiagnosticsOverride = process.argv[2] === "--ignoreDiagnostics" ): any { const wrappedTsString = `declare function JSONStringify(p: any): string; ${tsHeader ? tsHeader : ""} function __runTest(): any {${tsStr}}`; - const ignoreDiagnosticsOverride = process.argv[2] === "--ignoreDiagnostics"; const lua = `${luaHeader ? luaHeader : ""} ${transpileString(wrappedTsString, compilerOptions, ignoreDiagnosticsOverride)} return __runTest();`; diff --git a/test/unit/lualib/weakMap.spec.ts b/test/unit/lualib/weakMap.spec.ts index faea5fb2d..d9e829778 100644 --- a/test/unit/lualib/weakMap.spec.ts +++ b/test/unit/lualib/weakMap.spec.ts @@ -123,11 +123,12 @@ export class WeakMapTests { @Test("weakMap has no map features") public weakMapHasNoMapFeatures(): void { - Expect(util.transpileAndExecute(`return new WeakMap().size`)).toBe(undefined); - Expect(() => util.transpileAndExecute(`new WeakMap().clear()`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakMap().keys()`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakMap().values()`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakMap().entries()`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakMap().forEach(() => {})`)).toThrow(); + const transpileAndExecute = (tsStr: string) => util.transpileAndExecute(tsStr, undefined, undefined, undefined, true); + Expect(transpileAndExecute(`return new WeakMap().size`)).toBe(undefined); + Expect(() => transpileAndExecute(`new WeakMap().clear()`)).toThrow(); + Expect(() => transpileAndExecute(`new WeakMap().keys()`)).toThrow(); + Expect(() => transpileAndExecute(`new WeakMap().values()`)).toThrow(); + Expect(() => transpileAndExecute(`new WeakMap().entries()`)).toThrow(); + Expect(() => transpileAndExecute(`new WeakMap().forEach(() => {})`)).toThrow(); } } diff --git a/test/unit/lualib/weakSet.spec.ts b/test/unit/lualib/weakSet.spec.ts index 5bb1cd22d..e4425618e 100644 --- a/test/unit/lualib/weakSet.spec.ts +++ b/test/unit/lualib/weakSet.spec.ts @@ -76,11 +76,12 @@ export class WeakSetTests { @Test("weakSet has no set features") public weakSetHasNoSetFeatures(): void { - Expect(util.transpileAndExecute(`return new WeakSet().size`)).toBe(undefined); - Expect(() => util.transpileAndExecute(`new WeakSet().clear()`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakSet().keys()`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakSet().values()`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakSet().entries()`)).toThrow(); - Expect(() => util.transpileAndExecute(`new WeakSet().forEach(() => {})`)).toThrow(); + const transpileAndExecute = (tsStr: string) => util.transpileAndExecute(tsStr, undefined, undefined, undefined, true); + Expect(transpileAndExecute(`return new WeakSet().size`)).toBe(undefined); + Expect(() => transpileAndExecute(`new WeakSet().clear()`)).toThrow(); + Expect(() => transpileAndExecute(`new WeakSet().keys()`)).toThrow(); + Expect(() => transpileAndExecute(`new WeakSet().values()`)).toThrow(); + Expect(() => transpileAndExecute(`new WeakSet().entries()`)).toThrow(); + Expect(() => transpileAndExecute(`new WeakSet().forEach(() => {})`)).toThrow(); } }