mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 12:51:30 -05:00
Fixes for review comments.
* rename _super to _superIndex and _superProps to _super. * reinstate early exit for transformers by marking super accesses as esnext/es2017 in `binder.ts`. * adjust comment in `checker.ts` to new emit.
This commit is contained in:
@@ -3445,7 +3445,9 @@ namespace ts {
|
||||
// ES6 syntax, and requires a lexical `this` binding.
|
||||
if (transformFlags & TransformFlags.Super) {
|
||||
transformFlags ^= TransformFlags.Super;
|
||||
transformFlags |= TransformFlags.ContainsSuper;
|
||||
// super inside of an async function requires hoisting the super access (ES2017).
|
||||
// same for super inside of an async generator, which is ESNext.
|
||||
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
@@ -3461,7 +3463,9 @@ namespace ts {
|
||||
// ES6 syntax, and requires a lexical `this` binding.
|
||||
if (expressionFlags & TransformFlags.Super) {
|
||||
transformFlags &= ~TransformFlags.Super;
|
||||
transformFlags |= TransformFlags.ContainsSuper;
|
||||
// super inside of an async function requires hoisting the super access (ES2017).
|
||||
// same for super inside of an async generator, which is ESNext.
|
||||
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
|
||||
@@ -16180,16 +16180,18 @@ namespace ts {
|
||||
// // js
|
||||
// ...
|
||||
// asyncMethod() {
|
||||
// const _super_asyncMethod = name => super.asyncMethod;
|
||||
// const _super = Object.create(null, {
|
||||
// asyncMethod: { get: () => super.asyncMethod },
|
||||
// });
|
||||
// return __awaiter(this, arguments, Promise, function *() {
|
||||
// let x = yield _super_asyncMethod.call(this);
|
||||
// let x = yield _super.asyncMethod.call(this);
|
||||
// return x;
|
||||
// });
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// The more complex case is when we wish to assign a value, especially as part of a destructuring assignment. As both cases
|
||||
// are legal in ES6, but also likely less frequent, we emit the same more complex helper for both scenarios:
|
||||
// are legal in ES6, but also likely less frequent, we only emit setters if there is an assignment:
|
||||
//
|
||||
// // ts
|
||||
// ...
|
||||
@@ -16201,17 +16203,18 @@ namespace ts {
|
||||
// // js
|
||||
// ...
|
||||
// asyncMethod(ar) {
|
||||
// const _super_a = {get value() { return super.a; }, set value(v) { super.a = v; }};
|
||||
// const _super_b = {get value() { return super.b; }, set value(v) { super.b = v; }};
|
||||
// const _super = Object.create(null, {
|
||||
// a: { get: () => super.a, set: (v) => super.a = v },
|
||||
// b: { get: () => super.b, set: (v) => super.b = v }
|
||||
// };
|
||||
// return __awaiter(this, arguments, Promise, function *() {
|
||||
// [_super_a.value, _super_b.value] = yield ar;
|
||||
// [_super.a, _super.b] = yield ar;
|
||||
// });
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// This helper creates an object with a "value" property that wraps the `super` property for both get and set. This is required for
|
||||
// destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment while a property
|
||||
// access can.
|
||||
// Creating an object that has getter and setters instead of just an accessor funtion is required for destructuring assignments
|
||||
// as a call expression cannot be used as the target of a destructuring assignment while a property access can.
|
||||
//
|
||||
// For element access expressions (`super[x]`), we emit a generic helper that forwards the element access in both situations.
|
||||
if (container.kind === SyntaxKind.MethodDeclaration && hasModifier(container, ModifierFlags.Async)) {
|
||||
|
||||
@@ -62,6 +62,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitor(node: Node): VisitResult<Node> {
|
||||
if ((node.transformFlags & TransformFlags.ContainsES2017) === 0) {
|
||||
return node;
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
// ES2017 async modifier should be elided for targets < ES2017
|
||||
@@ -553,7 +556,7 @@ namespace ts {
|
||||
// Disable substitution in the generated super accessor itself.
|
||||
else if (enabledSubstitutions && substitutedSuperAccessors[getNodeId(node)]) {
|
||||
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
|
||||
enclosingSuperContainerFlags = 0 as NodeCheckFlags;
|
||||
enclosingSuperContainerFlags = 0;
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
enclosingSuperContainerFlags = savedEnclosingSuperContainerFlags;
|
||||
return;
|
||||
@@ -592,7 +595,7 @@ namespace ts {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
createFileLevelUniqueName("_superProps"),
|
||||
createFileLevelUniqueName("_super"),
|
||||
node.name),
|
||||
node
|
||||
);
|
||||
@@ -642,7 +645,7 @@ namespace ts {
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
createCall(
|
||||
createFileLevelUniqueName("_super"),
|
||||
createFileLevelUniqueName("_superIndex"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression]
|
||||
),
|
||||
@@ -654,7 +657,7 @@ namespace ts {
|
||||
else {
|
||||
return setTextRange(
|
||||
createCall(
|
||||
createFileLevelUniqueName("_super"),
|
||||
createFileLevelUniqueName("_superIndex"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression]
|
||||
),
|
||||
@@ -729,7 +732,7 @@ namespace ts {
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
createVariableDeclaration(
|
||||
createFileLevelUniqueName("_superProps"),
|
||||
createFileLevelUniqueName("_super"),
|
||||
/* type */ undefined,
|
||||
createCall(
|
||||
createPropertyAccess(
|
||||
@@ -794,14 +797,14 @@ namespace ts {
|
||||
name: "typescript:async-super",
|
||||
scoped: true,
|
||||
text: helperString`
|
||||
const ${"_super"} = name => super[name];`
|
||||
const ${"_superIndex"} = name => super[name];`
|
||||
};
|
||||
|
||||
export const advancedAsyncSuperHelper: EmitHelper = {
|
||||
name: "typescript:advanced-async-super",
|
||||
scoped: true,
|
||||
text: helperString`
|
||||
const ${"_super"} = (function (geti, seti) {
|
||||
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);`
|
||||
|
||||
@@ -61,6 +61,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitorWorker(node: Node, noDestructuringValue: boolean): VisitResult<Node> {
|
||||
if ((node.transformFlags & TransformFlags.ContainsESNext) === 0) {
|
||||
return node;
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AwaitExpression:
|
||||
return visitAwaitExpression(node as AwaitExpression);
|
||||
@@ -854,7 +857,7 @@ namespace ts {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
createFileLevelUniqueName("_superProps"),
|
||||
createFileLevelUniqueName("_super"),
|
||||
node.name),
|
||||
node
|
||||
);
|
||||
@@ -904,7 +907,7 @@ namespace ts {
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
createCall(
|
||||
createIdentifier("_super"),
|
||||
createIdentifier("_superIndex"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression]
|
||||
),
|
||||
@@ -916,7 +919,7 @@ namespace ts {
|
||||
else {
|
||||
return setTextRange(
|
||||
createCall(
|
||||
createIdentifier("_super"),
|
||||
createIdentifier("_superIndex"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression]
|
||||
),
|
||||
|
||||
@@ -77,8 +77,8 @@ class A {
|
||||
class B extends A {
|
||||
// async method with only call/get on 'super' does not require a binding
|
||||
simple() {
|
||||
const _super_1 = name => super[name];
|
||||
const _superProps_1 = Object.create(null, {
|
||||
const _superIndex = name => super[name];
|
||||
const _super_1 = Object.create(null, {
|
||||
x: { get: () => super.x },
|
||||
y: { get: () => super.y }
|
||||
});
|
||||
@@ -86,24 +86,24 @@ class B extends A {
|
||||
const _super = null;
|
||||
const _superProps = null;
|
||||
// call with property access
|
||||
_superProps_1.x.call(this);
|
||||
_super_1.x.call(this);
|
||||
// call additional property.
|
||||
_superProps_1.y.call(this);
|
||||
_super_1.y.call(this);
|
||||
// call with element access
|
||||
_super_1("x").call(this);
|
||||
_superIndex("x").call(this);
|
||||
// property access (read)
|
||||
const a = _superProps_1.x;
|
||||
const a = _super_1.x;
|
||||
// element access (read)
|
||||
const b = _super_1("x");
|
||||
const b = _superIndex("x");
|
||||
});
|
||||
}
|
||||
// async method with assignment/destructuring on 'super' requires a binding
|
||||
advanced() {
|
||||
const _super_1 = (function (geti, seti) {
|
||||
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);
|
||||
const _superProps_1 = Object.create(null, {
|
||||
const _super_1 = Object.create(null, {
|
||||
x: { get: () => super.x, set: v => super.x = v }
|
||||
});
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
@@ -111,21 +111,21 @@ class B extends A {
|
||||
const _superProps = null;
|
||||
const f = () => { };
|
||||
// call with property access
|
||||
_superProps_1.x.call(this);
|
||||
_super_1.x.call(this);
|
||||
// call with element access
|
||||
_super_1("x").value.call(this);
|
||||
_superIndex("x").value.call(this);
|
||||
// property access (read)
|
||||
const a = _superProps_1.x;
|
||||
const a = _super_1.x;
|
||||
// element access (read)
|
||||
const b = _super_1("x").value;
|
||||
const b = _superIndex("x").value;
|
||||
// property access (assign)
|
||||
_superProps_1.x = f;
|
||||
_super_1.x = f;
|
||||
// element access (assign)
|
||||
_super_1("x").value = f;
|
||||
_superIndex("x").value = f;
|
||||
// destructuring assign with property access
|
||||
({ f: _superProps_1.x } = { f });
|
||||
({ f: _super_1.x } = { f });
|
||||
// destructuring assign with element access
|
||||
({ f: _super_1("x").value } = { f });
|
||||
({ f: _superIndex("x").value } = { f });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,51 +65,51 @@ class A {
|
||||
class B extends A {
|
||||
// async method with only call/get on 'super' does not require a binding
|
||||
simple() {
|
||||
const _super = name => super[name];
|
||||
const _superProps = Object.create(null, {
|
||||
const _superIndex = name => super[name];
|
||||
const _super = Object.create(null, {
|
||||
x: { get: () => super.x },
|
||||
y: { get: () => super.y }
|
||||
});
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// call with property access
|
||||
_superProps.x.call(this);
|
||||
_super.x.call(this);
|
||||
// call additional property.
|
||||
_superProps.y.call(this);
|
||||
_super.y.call(this);
|
||||
// call with element access
|
||||
_super("x").call(this);
|
||||
_superIndex("x").call(this);
|
||||
// property access (read)
|
||||
const a = _superProps.x;
|
||||
const a = _super.x;
|
||||
// element access (read)
|
||||
const b = _super("x");
|
||||
const b = _superIndex("x");
|
||||
});
|
||||
}
|
||||
// async method with assignment/destructuring on 'super' requires a binding
|
||||
advanced() {
|
||||
const _super = (function (geti, seti) {
|
||||
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);
|
||||
const _superProps = Object.create(null, {
|
||||
const _super = Object.create(null, {
|
||||
x: { get: () => super.x, set: v => super.x = v }
|
||||
});
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const f = () => { };
|
||||
// call with property access
|
||||
_superProps.x.call(this);
|
||||
_super.x.call(this);
|
||||
// call with element access
|
||||
_super("x").value.call(this);
|
||||
_superIndex("x").value.call(this);
|
||||
// property access (read)
|
||||
const a = _superProps.x;
|
||||
const a = _super.x;
|
||||
// element access (read)
|
||||
const b = _super("x").value;
|
||||
const b = _superIndex("x").value;
|
||||
// property access (assign)
|
||||
_superProps.x = f;
|
||||
_super.x = f;
|
||||
// element access (assign)
|
||||
_super("x").value = f;
|
||||
_superIndex("x").value = f;
|
||||
// destructuring assign with property access
|
||||
({ f: _superProps.x } = { f });
|
||||
({ f: _super.x } = { f });
|
||||
// destructuring assign with element access
|
||||
({ f: _super("x").value } = { f });
|
||||
({ f: _superIndex("x").value } = { f });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,11 +263,11 @@ class B9 {
|
||||
}
|
||||
class C9 extends B9 {
|
||||
f() {
|
||||
const _superProps = Object.create(null, {
|
||||
const _super = Object.create(null, {
|
||||
g: { get: () => super.g }
|
||||
});
|
||||
return __asyncGenerator(this, arguments, function* f_1() {
|
||||
_superProps.g.call(this);
|
||||
_super.g.call(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user