diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index e9e612f0c0941..9508613321c6e 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -420,8 +420,10 @@ namespace ts { const savedCapturedSuperProperties = capturedSuperProperties; const savedHasSuperElementAccess = hasSuperElementAccess; - capturedSuperProperties = createUnderscoreEscapedMap(); - hasSuperElementAccess = false; + if (!isArrowFunction) { + capturedSuperProperties = createUnderscoreEscapedMap(); + hasSuperElementAccess = false; + } let result: ConciseBody; if (!isArrowFunction) { @@ -446,9 +448,11 @@ namespace ts { if (emitSuperHelpers) { enableSubstitutionForAsyncMethodsWithSuper(); - const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties); - substitutedSuperAccessors[getNodeId(variableStatement)] = true; - insertStatementsAfterStandardPrologue(statements, [variableStatement]); + if (hasEntries(capturedSuperProperties)) { + const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties); + substitutedSuperAccessors[getNodeId(variableStatement)] = true; + insertStatementsAfterStandardPrologue(statements, [variableStatement]); + } } const block = createBlock(statements, /*multiLine*/ true); @@ -485,8 +489,10 @@ namespace ts { } enclosingFunctionParameterNames = savedEnclosingFunctionParameterNames; - capturedSuperProperties = savedCapturedSuperProperties; - hasSuperElementAccess = savedHasSuperElementAccess; + if (!isArrowFunction) { + capturedSuperProperties = savedCapturedSuperProperties; + hasSuperElementAccess = savedHasSuperElementAccess; + } return result; } diff --git a/tests/baselines/reference/asyncMethodWithSuper_es6.js b/tests/baselines/reference/asyncMethodWithSuper_es6.js index 5ff89d26e9404..b2a560a432a27 100644 --- a/tests/baselines/reference/asyncMethodWithSuper_es6.js +++ b/tests/baselines/reference/asyncMethodWithSuper_es6.js @@ -51,6 +51,78 @@ class B extends A { // destructuring assign with element access ({ f: super["x"] } = { f }); + + // property access in arrow + (() => super.x()); + + // element access in arrow + (() => super["x"]()); + + // property access in async arrow + (async () => super.x()); + + // element access in async arrow + (async () => super["x"]()); + } + + async property_access_only_read_only() { + // call with property access + super.x(); + + // property access (read) + const a = super.x; + + // property access in arrow + (() => super.x()); + + // property access in async arrow + (async () => super.x()); + } + + async property_access_only_write_only() { + const f = () => {}; + + // property access (assign) + super.x = f; + + // destructuring assign with property access + ({ f: super.x } = { f }); + + // property access (assign) in arrow + (() => super.x = f); + + // property access (assign) in async arrow + (async () => super.x = f); + } + + async element_access_only_read_only() { + // call with element access + super["x"](); + + // element access (read) + const a = super["x"]; + + // element access in arrow + (() => super["x"]()); + + // element access in async arrow + (async () => super["x"]()); + } + + async element_access_only_write_only() { + const f = () => {}; + + // element access (assign) + super["x"] = f; + + // destructuring assign with element access + ({ f: super["x"] } = { f }); + + // element access (assign) in arrow + (() => super["x"] = f); + + // element access (assign) in async arrow + (async () => super["x"] = f); } } @@ -110,6 +182,75 @@ class B extends A { ({ f: _super.x } = { f }); // destructuring assign with element access ({ f: _superIndex("x").value } = { f }); + // property access in arrow + (() => _super.x.call(this)); + // element access in arrow + (() => _superIndex("x").value.call(this)); + // property access in async arrow + (() => __awaiter(this, void 0, void 0, function* () { return _super.x.call(this); })); + // element access in async arrow + (() => __awaiter(this, void 0, void 0, function* () { return _superIndex("x").value.call(this); })); + }); + } + property_access_only_read_only() { + const _super = Object.create(null, { + x: { get: () => super.x } + }); + return __awaiter(this, void 0, void 0, function* () { + // call with property access + _super.x.call(this); + // property access (read) + const a = _super.x; + // property access in arrow + (() => _super.x.call(this)); + // property access in async arrow + (() => __awaiter(this, void 0, void 0, function* () { return _super.x.call(this); })); + }); + } + property_access_only_write_only() { + const _super = Object.create(null, { + x: { get: () => super.x, set: v => super.x = v } + }); + return __awaiter(this, void 0, void 0, function* () { + const f = () => { }; + // property access (assign) + _super.x = f; + // destructuring assign with property access + ({ f: _super.x } = { f }); + // property access (assign) in arrow + (() => _super.x = f); + // property access (assign) in async arrow + (() => __awaiter(this, void 0, void 0, function* () { return _super.x = f; })); + }); + } + element_access_only_read_only() { + const _superIndex = name => super[name]; + return __awaiter(this, void 0, void 0, function* () { + // call with element access + _superIndex("x").call(this); + // element access (read) + const a = _superIndex("x"); + // element access in arrow + (() => _superIndex("x").call(this)); + // element access in async arrow + (() => __awaiter(this, void 0, void 0, function* () { return _superIndex("x").call(this); })); + }); + } + element_access_only_write_only() { + const _superIndex = (function (geti, seti) { + const cache = Object.create(null); + return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); + })(name => super[name], (name, value) => super[name] = value); + return __awaiter(this, void 0, void 0, function* () { + const f = () => { }; + // element access (assign) + _superIndex("x").value = f; + // destructuring assign with element access + ({ f: _superIndex("x").value } = { f }); + // element access (assign) in arrow + (() => _superIndex("x").value = f); + // element access (assign) in async arrow + (() => __awaiter(this, void 0, void 0, function* () { return _superIndex("x").value = f; })); }); } } diff --git a/tests/baselines/reference/asyncMethodWithSuper_es6.symbols b/tests/baselines/reference/asyncMethodWithSuper_es6.symbols index d33bcf3449ae5..842930ce900ee 100644 --- a/tests/baselines/reference/asyncMethodWithSuper_es6.symbols +++ b/tests/baselines/reference/asyncMethodWithSuper_es6.symbols @@ -107,6 +107,150 @@ class B extends A { >super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) >"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) >f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 51, 30)) + + // property access in arrow + (() => super.x()); +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // element access in arrow + (() => super["x"]()); +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // property access in async arrow + (async () => super.x()); +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // element access in async arrow + (async () => super["x"]()); +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + } + + async property_access_only_read_only() { +>property_access_only_read_only : Symbol(B.property_access_only_read_only, Decl(asyncMethodWithSuper_es6.ts, 64, 5)) + + // call with property access + super.x(); +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // property access (read) + const a = super.x; +>a : Symbol(a, Decl(asyncMethodWithSuper_es6.ts, 71, 13)) +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // property access in arrow + (() => super.x()); +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // property access in async arrow + (async () => super.x()); +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + } + + async property_access_only_write_only() { +>property_access_only_write_only : Symbol(B.property_access_only_write_only, Decl(asyncMethodWithSuper_es6.ts, 78, 5)) + + const f = () => {}; +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 81, 13)) + + // property access (assign) + super.x = f; +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 81, 13)) + + // destructuring assign with property access + ({ f: super.x } = { f }); +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 87, 10)) +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 87, 27)) + + // property access (assign) in arrow + (() => super.x = f); +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 81, 13)) + + // property access (assign) in async arrow + (async () => super.x = f); +>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 81, 13)) + } + + async element_access_only_read_only() { +>element_access_only_read_only : Symbol(B.element_access_only_read_only, Decl(asyncMethodWithSuper_es6.ts, 94, 5)) + + // call with element access + super["x"](); +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // element access (read) + const a = super["x"]; +>a : Symbol(a, Decl(asyncMethodWithSuper_es6.ts, 101, 13)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // element access in arrow + (() => super["x"]()); +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + + // element access in async arrow + (async () => super["x"]()); +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) + } + + async element_access_only_write_only() { +>element_access_only_write_only : Symbol(B.element_access_only_write_only, Decl(asyncMethodWithSuper_es6.ts, 108, 5)) + + const f = () => {}; +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 111, 13)) + + // element access (assign) + super["x"] = f; +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 111, 13)) + + // destructuring assign with element access + ({ f: super["x"] } = { f }); +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 117, 10)) +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 117, 30)) + + // element access (assign) in arrow + (() => super["x"] = f); +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 111, 13)) + + // element access (assign) in async arrow + (async () => super["x"] = f); +>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0)) +>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9)) +>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 111, 13)) } } diff --git a/tests/baselines/reference/asyncMethodWithSuper_es6.types b/tests/baselines/reference/asyncMethodWithSuper_es6.types index 1333beb8f0484..92e132e97b2c0 100644 --- a/tests/baselines/reference/asyncMethodWithSuper_es6.types +++ b/tests/baselines/reference/asyncMethodWithSuper_es6.types @@ -128,6 +128,210 @@ class B extends A { >super : A >"x" : "x" >{ f } : { f: () => void; } +>f : () => void + + // property access in arrow + (() => super.x()); +>(() => super.x()) : () => void +>() => super.x() : () => void +>super.x() : void +>super.x : () => void +>super : A +>x : () => void + + // element access in arrow + (() => super["x"]()); +>(() => super["x"]()) : () => void +>() => super["x"]() : () => void +>super["x"]() : void +>super["x"] : () => void +>super : A +>"x" : "x" + + // property access in async arrow + (async () => super.x()); +>(async () => super.x()) : () => Promise +>async () => super.x() : () => Promise +>super.x() : void +>super.x : () => void +>super : A +>x : () => void + + // element access in async arrow + (async () => super["x"]()); +>(async () => super["x"]()) : () => Promise +>async () => super["x"]() : () => Promise +>super["x"]() : void +>super["x"] : () => void +>super : A +>"x" : "x" + } + + async property_access_only_read_only() { +>property_access_only_read_only : () => Promise + + // call with property access + super.x(); +>super.x() : void +>super.x : () => void +>super : A +>x : () => void + + // property access (read) + const a = super.x; +>a : () => void +>super.x : () => void +>super : A +>x : () => void + + // property access in arrow + (() => super.x()); +>(() => super.x()) : () => void +>() => super.x() : () => void +>super.x() : void +>super.x : () => void +>super : A +>x : () => void + + // property access in async arrow + (async () => super.x()); +>(async () => super.x()) : () => Promise +>async () => super.x() : () => Promise +>super.x() : void +>super.x : () => void +>super : A +>x : () => void + } + + async property_access_only_write_only() { +>property_access_only_write_only : () => Promise + + const f = () => {}; +>f : () => void +>() => {} : () => void + + // property access (assign) + super.x = f; +>super.x = f : () => void +>super.x : () => void +>super : A +>x : () => void +>f : () => void + + // destructuring assign with property access + ({ f: super.x } = { f }); +>({ f: super.x } = { f }) : { f: () => void; } +>{ f: super.x } = { f } : { f: () => void; } +>{ f: super.x } : { f: () => void; } +>f : () => void +>super.x : () => void +>super : A +>x : () => void +>{ f } : { f: () => void; } +>f : () => void + + // property access (assign) in arrow + (() => super.x = f); +>(() => super.x = f) : () => () => void +>() => super.x = f : () => () => void +>super.x = f : () => void +>super.x : () => void +>super : A +>x : () => void +>f : () => void + + // property access (assign) in async arrow + (async () => super.x = f); +>(async () => super.x = f) : () => Promise<() => void> +>async () => super.x = f : () => Promise<() => void> +>super.x = f : () => void +>super.x : () => void +>super : A +>x : () => void +>f : () => void + } + + async element_access_only_read_only() { +>element_access_only_read_only : () => Promise + + // call with element access + super["x"](); +>super["x"]() : void +>super["x"] : () => void +>super : A +>"x" : "x" + + // element access (read) + const a = super["x"]; +>a : () => void +>super["x"] : () => void +>super : A +>"x" : "x" + + // element access in arrow + (() => super["x"]()); +>(() => super["x"]()) : () => void +>() => super["x"]() : () => void +>super["x"]() : void +>super["x"] : () => void +>super : A +>"x" : "x" + + // element access in async arrow + (async () => super["x"]()); +>(async () => super["x"]()) : () => Promise +>async () => super["x"]() : () => Promise +>super["x"]() : void +>super["x"] : () => void +>super : A +>"x" : "x" + } + + async element_access_only_write_only() { +>element_access_only_write_only : () => Promise + + const f = () => {}; +>f : () => void +>() => {} : () => void + + // element access (assign) + super["x"] = f; +>super["x"] = f : () => void +>super["x"] : () => void +>super : A +>"x" : "x" +>f : () => void + + // destructuring assign with element access + ({ f: super["x"] } = { f }); +>({ f: super["x"] } = { f }) : { f: () => void; } +>{ f: super["x"] } = { f } : { f: () => void; } +>{ f: super["x"] } : { f: () => void; } +>f : () => void +>super["x"] : () => void +>super : A +>"x" : "x" +>{ f } : { f: () => void; } +>f : () => void + + // element access (assign) in arrow + (() => super["x"] = f); +>(() => super["x"] = f) : () => () => void +>() => super["x"] = f : () => () => void +>super["x"] = f : () => void +>super["x"] : () => void +>super : A +>"x" : "x" +>f : () => void + + // element access (assign) in async arrow + (async () => super["x"] = f); +>(async () => super["x"] = f) : () => Promise<() => void> +>async () => super["x"] = f : () => Promise<() => void> +>super["x"] = f : () => void +>super["x"] : () => void +>super : A +>"x" : "x" >f : () => void } } diff --git a/tests/cases/conformance/async/es6/asyncMethodWithSuper_es6.ts b/tests/cases/conformance/async/es6/asyncMethodWithSuper_es6.ts index 79d110e3d8595..c754ac26c003b 100644 --- a/tests/cases/conformance/async/es6/asyncMethodWithSuper_es6.ts +++ b/tests/cases/conformance/async/es6/asyncMethodWithSuper_es6.ts @@ -52,5 +52,77 @@ class B extends A { // destructuring assign with element access ({ f: super["x"] } = { f }); + + // property access in arrow + (() => super.x()); + + // element access in arrow + (() => super["x"]()); + + // property access in async arrow + (async () => super.x()); + + // element access in async arrow + (async () => super["x"]()); + } + + async property_access_only_read_only() { + // call with property access + super.x(); + + // property access (read) + const a = super.x; + + // property access in arrow + (() => super.x()); + + // property access in async arrow + (async () => super.x()); + } + + async property_access_only_write_only() { + const f = () => {}; + + // property access (assign) + super.x = f; + + // destructuring assign with property access + ({ f: super.x } = { f }); + + // property access (assign) in arrow + (() => super.x = f); + + // property access (assign) in async arrow + (async () => super.x = f); + } + + async element_access_only_read_only() { + // call with element access + super["x"](); + + // element access (read) + const a = super["x"]; + + // element access in arrow + (() => super["x"]()); + + // element access in async arrow + (async () => super["x"]()); + } + + async element_access_only_write_only() { + const f = () => {}; + + // element access (assign) + super["x"] = f; + + // destructuring assign with element access + ({ f: super["x"] } = { f }); + + // element access (assign) in arrow + (() => super["x"] = f); + + // element access (assign) in async arrow + (async () => super["x"] = f); } }