diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c150f281a3041..7b59a0b4ca8f5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -32894,7 +32894,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression | undefined { const expression = node.kind === SyntaxKind.CallExpression ? node.expression : - node.kind === SyntaxKind.TaggedTemplateExpression ? node.tag : undefined; + node.kind === SyntaxKind.TaggedTemplateExpression ? node.tag : + node.kind === SyntaxKind.Decorator && !legacyDecorators ? node.expression : + undefined; if (expression) { const callee = skipOuterExpressions(expression); if (isAccessExpression(callee)) { diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index bac8f690e1940..3aa6f5e654834 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -1645,7 +1645,7 @@ export function createAccessorPropertyBackingField(factory: NodeFactory, node: P * * @internal */ -export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: ModifiersArray | undefined, name: PropertyName): GetAccessorDeclaration { +export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: readonly Modifier[] | undefined, name: PropertyName, receiver: Expression = factory.createThis()): GetAccessorDeclaration { return factory.createGetAccessorDeclaration( modifiers, name, @@ -1654,7 +1654,7 @@ export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: factory.createBlock([ factory.createReturnStatement( factory.createPropertyAccessExpression( - factory.createThis(), + receiver, factory.getGeneratedPrivateNameForNode(node.name, /*prefix*/ undefined, "_accessor_storage") ) ) @@ -1667,7 +1667,7 @@ export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: * * @internal */ -export function createAccessorPropertySetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: ModifiersArray | undefined, name: PropertyName) { +export function createAccessorPropertySetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: readonly Modifier[] | undefined, name: PropertyName, receiver: Expression = factory.createThis()) { return factory.createSetAccessorDeclaration( modifiers, name, @@ -1680,7 +1680,7 @@ export function createAccessorPropertySetRedirector(factory: NodeFactory, node: factory.createExpressionStatement( factory.createAssignment( factory.createPropertyAccessExpression( - factory.createThis(), + receiver, factory.getGeneratedPrivateNameForNode(node.name, /*prefix*/ undefined, "_accessor_storage") ), factory.createIdentifier("value") diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index 7c7227697a985..35a37697a12e1 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -154,6 +154,7 @@ import { Modifier, ModifierFlags, ModifierLike, + modifiersToFlags, moveRangePastModifiers, moveRangePos, newPrivateEnvironment, @@ -896,6 +897,12 @@ export function transformClassFields(context: TransformationContext): (x: Source } } + function getClassThis() { + const lex = getClassLexicalEnvironment(); + const classThis = lex.classThis ?? lex.classConstructor ?? currentClassContainer?.name; + return Debug.checkDefined(classThis); + } + function transformAutoAccessor(node: AutoAccessorPropertyDeclaration): VisitResult { // transforms: // accessor x = 1; @@ -935,12 +942,15 @@ export function transformClassFields(context: TransformationContext): (x: Source setEmitFlags(backingField, EmitFlags.NoComments); setSourceMapRange(backingField, sourceMapRange); - const getter = createAccessorPropertyGetRedirector(factory, node, modifiers, getterName); + const receiver = isStatic(node) ? getClassThis() : factory.createThis(); + const getter = createAccessorPropertyGetRedirector(factory, node, modifiers, getterName, receiver); setOriginalNode(getter, node); setCommentRange(getter, commentRange); setSourceMapRange(getter, sourceMapRange); - const setter = createAccessorPropertySetRedirector(factory, node, modifiers, setterName); + // create a fresh copy of the modifiers so that we don't duplicate comments + const setterModifiers = factory.createModifiersFromModifierFlags(modifiersToFlags(modifiers)); + const setter = createAccessorPropertySetRedirector(factory, node, setterModifiers, setterName, receiver); setOriginalNode(setter, node); setEmitFlags(setter, EmitFlags.NoComments); setSourceMapRange(setter, sourceMapRange); @@ -1692,11 +1702,13 @@ export function transformClassFields(context: TransformationContext): (x: Source let containsInstanceAutoAccessors = false; for (const member of node.members) { if (isStatic(member)) { - if (member.name && - (isPrivateIdentifier(member.name) || isAutoAccessorPropertyDeclaration(member)) && + if (member.name && (isPrivateIdentifier(member.name) || isAutoAccessorPropertyDeclaration(member)) && shouldTransformPrivateElementsOrClassStaticBlocks) { facts |= ClassFacts.NeedsClassConstructorReference; } + else if (isAutoAccessorPropertyDeclaration(member) && shouldTransformAutoAccessors === Ternary.True && !node.name && !node.emitNode?.classThis) { + facts |= ClassFacts.NeedsClassConstructorReference; + } if (isPropertyDeclaration(member) || isClassStaticBlockDeclaration(member)) { if (shouldTransformThisInStaticInitializers && member.transformFlags & TransformFlags.ContainsLexicalThis) { facts |= ClassFacts.NeedsSubstitutionForThisInClassStaticField; @@ -1843,10 +1855,10 @@ export function transformClassFields(context: TransformationContext): (x: Source getClassLexicalEnvironment().classConstructor = factory.cloneNode(temp); pendingClassReferenceAssignment = factory.createAssignment(temp, factory.getInternalName(node)); } + } - if (node.emitNode?.classThis) { - getClassLexicalEnvironment().classThis = node.emitNode.classThis; - } + if (node.emitNode?.classThis) { + getClassLexicalEnvironment().classThis = node.emitNode.classThis; } const isExport = hasSyntacticModifier(node, ModifierFlags.Export); diff --git a/src/compiler/transformers/esDecorators.ts b/src/compiler/transformers/esDecorators.ts index 369c056a36a88..3ed8995d32d17 100644 --- a/src/compiler/transformers/esDecorators.ts +++ b/src/compiler/transformers/esDecorators.ts @@ -47,6 +47,7 @@ import { getAllDecoratorsOfClassElement, getCommentRange, getEffectiveBaseTypeNode, + getEmitScriptTarget, getFirstConstructorWithBody, getHeritageClause, getNonAssignmentOperatorForCompoundAssignment, @@ -62,6 +63,7 @@ import { injectClassNamedEvaluationHelperBlockIfMissing, injectClassThisAssignmentIfMissing, InternalEmitFlags, + isAccessExpression, isAmbientPropertyDeclaration, isArrayBindingOrAssignmentElement, isArrayLiteralExpression, @@ -289,6 +291,7 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc hoistVariableDeclaration, } = context; + const languageVersion = getEmitScriptTarget(context.getCompilerOptions()); let top: LexicalEnvironmentStackEntry | undefined; let classInfo: ClassInfo | undefined; let classThis: Identifier | undefined; @@ -2147,6 +2150,13 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc function transformDecorator(decorator: Decorator) { const expression = visitNode(decorator.expression, visitor, isExpression); setEmitFlags(expression, EmitFlags.NoComments); + + // preserve the 'this' binding for an access expression + const innerExpression = skipOuterExpressions(expression); + if (isAccessExpression(innerExpression)) { + const { target, thisArg } = factory.createCallBinding(expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true); + return factory.restoreOuterExpressions(expression, factory.createFunctionBindCall(target, thisArg, [])); + } return expression; } diff --git a/tests/baselines/reference/autoAccessor1(target=es2015).js b/tests/baselines/reference/autoAccessor1(target=es2015).js index 8377a3ce303b6..e05e19fa51df5 100644 --- a/tests/baselines/reference/autoAccessor1(target=es2015).js +++ b/tests/baselines/reference/autoAccessor1(target=es2015).js @@ -31,10 +31,10 @@ class C1 { set a(value) { __classPrivateFieldSet(this, _C1_a_accessor_storage, value, "f"); } get b() { return __classPrivateFieldGet(this, _C1_b_accessor_storage, "f"); } set b(value) { __classPrivateFieldSet(this, _C1_b_accessor_storage, value, "f"); } - static get c() { return __classPrivateFieldGet(this, _a, "f", _C1_c_accessor_storage); } - static set c(value) { __classPrivateFieldSet(this, _a, value, "f", _C1_c_accessor_storage); } - static get d() { return __classPrivateFieldGet(this, _a, "f", _C1_d_accessor_storage); } - static set d(value) { __classPrivateFieldSet(this, _a, value, "f", _C1_d_accessor_storage); } + static get c() { return __classPrivateFieldGet(_a, _a, "f", _C1_c_accessor_storage); } + static set c(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1_c_accessor_storage); } + static get d() { return __classPrivateFieldGet(_a, _a, "f", _C1_d_accessor_storage); } + static set d(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1_d_accessor_storage); } } _a = C1, _C1_a_accessor_storage = new WeakMap(), _C1_b_accessor_storage = new WeakMap(); _C1_c_accessor_storage = { value: void 0 }; diff --git a/tests/baselines/reference/autoAccessor1(target=es2022).js b/tests/baselines/reference/autoAccessor1(target=es2022).js index 4611516123e27..639219b1deb97 100644 --- a/tests/baselines/reference/autoAccessor1(target=es2022).js +++ b/tests/baselines/reference/autoAccessor1(target=es2022).js @@ -18,9 +18,9 @@ class C1 { get b() { return this.#b_accessor_storage; } set b(value) { this.#b_accessor_storage = value; } static #c_accessor_storage; - static get c() { return this.#c_accessor_storage; } - static set c(value) { this.#c_accessor_storage = value; } + static get c() { return C1.#c_accessor_storage; } + static set c(value) { C1.#c_accessor_storage = value; } static #d_accessor_storage = 2; - static get d() { return this.#d_accessor_storage; } - static set d(value) { this.#d_accessor_storage = value; } + static get d() { return C1.#d_accessor_storage; } + static set d(value) { C1.#d_accessor_storage = value; } } diff --git a/tests/baselines/reference/autoAccessor10.js b/tests/baselines/reference/autoAccessor10.js index 88c23c432e7df..77170c8e85b72 100644 --- a/tests/baselines/reference/autoAccessor10.js +++ b/tests/baselines/reference/autoAccessor10.js @@ -57,11 +57,11 @@ class C3 { } class C4_1 { static #a3_accessor_storage = 1; - static get a3() { return this.#a3_accessor_storage; } - static set a3(value) { this.#a3_accessor_storage = value; } + static get a3() { return C4_1.#a3_accessor_storage; } + static set a3(value) { C4_1.#a3_accessor_storage = value; } } class C4_2 { static #a3_accessor_storage = 1; - static get a3() { return this.#a3_accessor_storage; } - static set a3(value) { this.#a3_accessor_storage = value; } + static get a3() { return C4_2.#a3_accessor_storage; } + static set a3(value) { C4_2.#a3_accessor_storage = value; } } diff --git a/tests/baselines/reference/autoAccessor2(target=es2015).js b/tests/baselines/reference/autoAccessor2(target=es2015).js index 767c244a358f2..7f5a806a58777 100644 --- a/tests/baselines/reference/autoAccessor2(target=es2015).js +++ b/tests/baselines/reference/autoAccessor2(target=es2015).js @@ -41,7 +41,7 @@ class C1 { __classPrivateFieldSet(this, _C1_instances, 4, "a", _C1_b_set); } } -_a = C1, _C1_instances = new WeakSet(), _C1_a_accessor_storage = new WeakMap(), _C1_b_accessor_storage = new WeakMap(), _C1_a_get = function _C1_a_get() { return __classPrivateFieldGet(this, _C1_a_accessor_storage, "f"); }, _C1_a_set = function _C1_a_set(value) { __classPrivateFieldSet(this, _C1_a_accessor_storage, value, "f"); }, _C1_b_get = function _C1_b_get() { return __classPrivateFieldGet(this, _C1_b_accessor_storage, "f"); }, _C1_b_set = function _C1_b_set(value) { __classPrivateFieldSet(this, _C1_b_accessor_storage, value, "f"); }, _C1_c_get = function _C1_c_get() { return __classPrivateFieldGet(this, _a, "f", _C1_c_accessor_storage); }, _C1_c_set = function _C1_c_set(value) { __classPrivateFieldSet(this, _a, value, "f", _C1_c_accessor_storage); }, _C1_d_get = function _C1_d_get() { return __classPrivateFieldGet(this, _a, "f", _C1_d_accessor_storage); }, _C1_d_set = function _C1_d_set(value) { __classPrivateFieldSet(this, _a, value, "f", _C1_d_accessor_storage); }; +_a = C1, _C1_instances = new WeakSet(), _C1_a_accessor_storage = new WeakMap(), _C1_b_accessor_storage = new WeakMap(), _C1_a_get = function _C1_a_get() { return __classPrivateFieldGet(this, _C1_a_accessor_storage, "f"); }, _C1_a_set = function _C1_a_set(value) { __classPrivateFieldSet(this, _C1_a_accessor_storage, value, "f"); }, _C1_b_get = function _C1_b_get() { return __classPrivateFieldGet(this, _C1_b_accessor_storage, "f"); }, _C1_b_set = function _C1_b_set(value) { __classPrivateFieldSet(this, _C1_b_accessor_storage, value, "f"); }, _C1_c_get = function _C1_c_get() { return __classPrivateFieldGet(_a, _a, "f", _C1_c_accessor_storage); }, _C1_c_set = function _C1_c_set(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1_c_accessor_storage); }, _C1_d_get = function _C1_d_get() { return __classPrivateFieldGet(_a, _a, "f", _C1_d_accessor_storage); }, _C1_d_set = function _C1_d_set(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1_d_accessor_storage); }; _C1_c_accessor_storage = { value: void 0 }; _C1_d_accessor_storage = { value: 2 }; (() => { diff --git a/tests/baselines/reference/autoAccessor2(target=es2022).js b/tests/baselines/reference/autoAccessor2(target=es2022).js index 45a4b6066bdfa..7efd7c0b5c957 100644 --- a/tests/baselines/reference/autoAccessor2(target=es2022).js +++ b/tests/baselines/reference/autoAccessor2(target=es2022).js @@ -28,11 +28,11 @@ class C1 { get #b() { return this.#b_accessor_storage; } set #b(value) { this.#b_accessor_storage = value; } static #c_accessor_storage; - static get #c() { return this.#c_accessor_storage; } - static set #c(value) { this.#c_accessor_storage = value; } + static get #c() { return C1.#c_accessor_storage; } + static set #c(value) { C1.#c_accessor_storage = value; } static #d_accessor_storage = 2; - static get #d() { return this.#d_accessor_storage; } - static set #d(value) { this.#d_accessor_storage = value; } + static get #d() { return C1.#d_accessor_storage; } + static set #d(value) { C1.#d_accessor_storage = value; } constructor() { this.#a = 3; this.#b = 4; diff --git a/tests/baselines/reference/autoAccessor3(target=es2015).js b/tests/baselines/reference/autoAccessor3(target=es2015).js index fce1f25d1801d..4e664b01eff63 100644 --- a/tests/baselines/reference/autoAccessor3(target=es2015).js +++ b/tests/baselines/reference/autoAccessor3(target=es2015).js @@ -31,10 +31,10 @@ class C1 { set "w"(value) { __classPrivateFieldSet(this, _C1__a_accessor_storage, value, "f"); } get "x"() { return __classPrivateFieldGet(this, _C1__b_accessor_storage, "f"); } set "x"(value) { __classPrivateFieldSet(this, _C1__b_accessor_storage, value, "f"); } - static get "y"() { return __classPrivateFieldGet(this, _a, "f", _C1__c_accessor_storage); } - static set "y"(value) { __classPrivateFieldSet(this, _a, value, "f", _C1__c_accessor_storage); } - static get "z"() { return __classPrivateFieldGet(this, _a, "f", _C1__d_accessor_storage); } - static set "z"(value) { __classPrivateFieldSet(this, _a, value, "f", _C1__d_accessor_storage); } + static get "y"() { return __classPrivateFieldGet(_a, _a, "f", _C1__c_accessor_storage); } + static set "y"(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1__c_accessor_storage); } + static get "z"() { return __classPrivateFieldGet(_a, _a, "f", _C1__d_accessor_storage); } + static set "z"(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1__d_accessor_storage); } } _a = C1, _C1__a_accessor_storage = new WeakMap(), _C1__b_accessor_storage = new WeakMap(); _C1__c_accessor_storage = { value: void 0 }; diff --git a/tests/baselines/reference/autoAccessor3(target=es2022).js b/tests/baselines/reference/autoAccessor3(target=es2022).js index 4cabe04e4382b..142a66e96781a 100644 --- a/tests/baselines/reference/autoAccessor3(target=es2022).js +++ b/tests/baselines/reference/autoAccessor3(target=es2022).js @@ -18,9 +18,9 @@ class C1 { get "x"() { return this.#_b_accessor_storage; } set "x"(value) { this.#_b_accessor_storage = value; } static #_c_accessor_storage; - static get "y"() { return this.#_c_accessor_storage; } - static set "y"(value) { this.#_c_accessor_storage = value; } + static get "y"() { return C1.#_c_accessor_storage; } + static set "y"(value) { C1.#_c_accessor_storage = value; } static #_d_accessor_storage = 2; - static get "z"() { return this.#_d_accessor_storage; } - static set "z"(value) { this.#_d_accessor_storage = value; } + static get "z"() { return C1.#_d_accessor_storage; } + static set "z"(value) { C1.#_d_accessor_storage = value; } } diff --git a/tests/baselines/reference/autoAccessor4(target=es2015).js b/tests/baselines/reference/autoAccessor4(target=es2015).js index b577b88791c1f..3c774d990f336 100644 --- a/tests/baselines/reference/autoAccessor4(target=es2015).js +++ b/tests/baselines/reference/autoAccessor4(target=es2015).js @@ -31,10 +31,10 @@ class C1 { set 0(value) { __classPrivateFieldSet(this, _C1__a_accessor_storage, value, "f"); } get 1() { return __classPrivateFieldGet(this, _C1__b_accessor_storage, "f"); } set 1(value) { __classPrivateFieldSet(this, _C1__b_accessor_storage, value, "f"); } - static get 2() { return __classPrivateFieldGet(this, _a, "f", _C1__c_accessor_storage); } - static set 2(value) { __classPrivateFieldSet(this, _a, value, "f", _C1__c_accessor_storage); } - static get 3() { return __classPrivateFieldGet(this, _a, "f", _C1__d_accessor_storage); } - static set 3(value) { __classPrivateFieldSet(this, _a, value, "f", _C1__d_accessor_storage); } + static get 2() { return __classPrivateFieldGet(_a, _a, "f", _C1__c_accessor_storage); } + static set 2(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1__c_accessor_storage); } + static get 3() { return __classPrivateFieldGet(_a, _a, "f", _C1__d_accessor_storage); } + static set 3(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1__d_accessor_storage); } } _a = C1, _C1__a_accessor_storage = new WeakMap(), _C1__b_accessor_storage = new WeakMap(); _C1__c_accessor_storage = { value: void 0 }; diff --git a/tests/baselines/reference/autoAccessor4(target=es2022).js b/tests/baselines/reference/autoAccessor4(target=es2022).js index c3a0b5bf92580..96a732d592d4b 100644 --- a/tests/baselines/reference/autoAccessor4(target=es2022).js +++ b/tests/baselines/reference/autoAccessor4(target=es2022).js @@ -18,9 +18,9 @@ class C1 { get 1() { return this.#_b_accessor_storage; } set 1(value) { this.#_b_accessor_storage = value; } static #_c_accessor_storage; - static get 2() { return this.#_c_accessor_storage; } - static set 2(value) { this.#_c_accessor_storage = value; } + static get 2() { return C1.#_c_accessor_storage; } + static set 2(value) { C1.#_c_accessor_storage = value; } static #_d_accessor_storage = 2; - static get 3() { return this.#_d_accessor_storage; } - static set 3(value) { this.#_d_accessor_storage = value; } + static get 3() { return C1.#_d_accessor_storage; } + static set 3(value) { C1.#_d_accessor_storage = value; } } diff --git a/tests/baselines/reference/autoAccessor5(target=es2015).js b/tests/baselines/reference/autoAccessor5(target=es2015).js index 919278cb9fe68..edafc0c9da1d2 100644 --- a/tests/baselines/reference/autoAccessor5(target=es2015).js +++ b/tests/baselines/reference/autoAccessor5(target=es2015).js @@ -35,10 +35,10 @@ class C1 { set ["w"](value) { __classPrivateFieldSet(this, _C1__a_accessor_storage, value, "f"); } get ["x"]() { return __classPrivateFieldGet(this, _C1__b_accessor_storage, "f"); } set ["x"](value) { __classPrivateFieldSet(this, _C1__b_accessor_storage, value, "f"); } - static get ["y"]() { return __classPrivateFieldGet(this, _a, "f", _C1__c_accessor_storage); } - static set ["y"](value) { __classPrivateFieldSet(this, _a, value, "f", _C1__c_accessor_storage); } - static get ["z"]() { return __classPrivateFieldGet(this, _a, "f", _C1__d_accessor_storage); } - static set ["z"](value) { __classPrivateFieldSet(this, _a, value, "f", _C1__d_accessor_storage); } + static get ["y"]() { return __classPrivateFieldGet(_a, _a, "f", _C1__c_accessor_storage); } + static set ["y"](value) { __classPrivateFieldSet(_a, _a, value, "f", _C1__c_accessor_storage); } + static get ["z"]() { return __classPrivateFieldGet(_a, _a, "f", _C1__d_accessor_storage); } + static set ["z"](value) { __classPrivateFieldSet(_a, _a, value, "f", _C1__d_accessor_storage); } } _a = C1; _C1__c_accessor_storage = { value: void 0 }; diff --git a/tests/baselines/reference/autoAccessor5(target=es2022).js b/tests/baselines/reference/autoAccessor5(target=es2022).js index 6e333433961fd..12c663ef4b3d8 100644 --- a/tests/baselines/reference/autoAccessor5(target=es2022).js +++ b/tests/baselines/reference/autoAccessor5(target=es2022).js @@ -23,11 +23,11 @@ class C1 { get ["x"]() { return this.#_b_accessor_storage; } set ["x"](value) { this.#_b_accessor_storage = value; } static #_c_accessor_storage; - static get ["y"]() { return this.#_c_accessor_storage; } - static set ["y"](value) { this.#_c_accessor_storage = value; } + static get ["y"]() { return C1.#_c_accessor_storage; } + static set ["y"](value) { C1.#_c_accessor_storage = value; } static #_d_accessor_storage = 2; - static get ["z"]() { return this.#_d_accessor_storage; } - static set ["z"](value) { this.#_d_accessor_storage = value; } + static get ["z"]() { return C1.#_d_accessor_storage; } + static set ["z"](value) { C1.#_d_accessor_storage = value; } } class C2 { #_e_accessor_storage = 1; diff --git a/tests/baselines/reference/autoAccessor5(target=es5).js b/tests/baselines/reference/autoAccessor5(target=es5).js index 3e802faf6cb77..208bcefb2636e 100644 --- a/tests/baselines/reference/autoAccessor5(target=es5).js +++ b/tests/baselines/reference/autoAccessor5(target=es5).js @@ -48,14 +48,14 @@ var C1 = /** @class */ (function () { configurable: true }); Object.defineProperty(C1, "y", { - get: function () { return __classPrivateFieldGet(this, _b, "f", _C1__d_accessor_storage); }, - set: function (value) { __classPrivateFieldSet(this, _b, value, "f", _C1__d_accessor_storage); }, + get: function () { return __classPrivateFieldGet(_b, _b, "f", _C1__d_accessor_storage); }, + set: function (value) { __classPrivateFieldSet(_b, _b, value, "f", _C1__d_accessor_storage); }, enumerable: false, configurable: true }); Object.defineProperty(C1, "z", { - get: function () { return __classPrivateFieldGet(this, _b, "f", _C1__e_accessor_storage); }, - set: function (value) { __classPrivateFieldSet(this, _b, value, "f", _C1__e_accessor_storage); }, + get: function () { return __classPrivateFieldGet(_b, _b, "f", _C1__e_accessor_storage); }, + set: function (value) { __classPrivateFieldSet(_b, _b, value, "f", _C1__e_accessor_storage); }, enumerable: false, configurable: true }); diff --git a/tests/baselines/reference/autoAccessorExperimentalDecorators(target=es2015).js b/tests/baselines/reference/autoAccessorExperimentalDecorators(target=es2015).js index 2057c2e3a2f81..e2d1b03a64fa8 100644 --- a/tests/baselines/reference/autoAccessorExperimentalDecorators(target=es2015).js +++ b/tests/baselines/reference/autoAccessorExperimentalDecorators(target=es2015).js @@ -45,8 +45,8 @@ class C1 { } get a() { return __classPrivateFieldGet(this, _C1_a_accessor_storage, "f"); } set a(value) { __classPrivateFieldSet(this, _C1_a_accessor_storage, value, "f"); } - static get b() { return __classPrivateFieldGet(this, _a, "f", _C1_b_accessor_storage); } - static set b(value) { __classPrivateFieldSet(this, _a, value, "f", _C1_b_accessor_storage); } + static get b() { return __classPrivateFieldGet(_a, _a, "f", _C1_b_accessor_storage); } + static set b(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1_b_accessor_storage); } } _a = C1, _C1_a_accessor_storage = new WeakMap(); _C1_b_accessor_storage = { value: void 0 }; @@ -62,5 +62,5 @@ class C2 { _C2_a_1_accessor_storage.set(this, void 0); } } -_b = C2, _C2_instances = new WeakSet(), _C2_a_1_accessor_storage = new WeakMap(), _C2_a_get = function _C2_a_get() { return __classPrivateFieldGet(this, _C2_a_1_accessor_storage, "f"); }, _C2_a_set = function _C2_a_set(value) { __classPrivateFieldSet(this, _C2_a_1_accessor_storage, value, "f"); }, _C2_b_get = function _C2_b_get() { return __classPrivateFieldGet(this, _b, "f", _C2_b_1_accessor_storage); }, _C2_b_set = function _C2_b_set(value) { __classPrivateFieldSet(this, _b, value, "f", _C2_b_1_accessor_storage); }; +_b = C2, _C2_instances = new WeakSet(), _C2_a_1_accessor_storage = new WeakMap(), _C2_a_get = function _C2_a_get() { return __classPrivateFieldGet(this, _C2_a_1_accessor_storage, "f"); }, _C2_a_set = function _C2_a_set(value) { __classPrivateFieldSet(this, _C2_a_1_accessor_storage, value, "f"); }, _C2_b_get = function _C2_b_get() { return __classPrivateFieldGet(_b, _b, "f", _C2_b_1_accessor_storage); }, _C2_b_set = function _C2_b_set(value) { __classPrivateFieldSet(_b, _b, value, "f", _C2_b_1_accessor_storage); }; _C2_b_1_accessor_storage = { value: void 0 }; diff --git a/tests/baselines/reference/autoAccessorExperimentalDecorators(target=es2022).js b/tests/baselines/reference/autoAccessorExperimentalDecorators(target=es2022).js index e173147ff9bbd..9c65115067bbd 100644 --- a/tests/baselines/reference/autoAccessorExperimentalDecorators(target=es2022).js +++ b/tests/baselines/reference/autoAccessorExperimentalDecorators(target=es2022).js @@ -32,8 +32,8 @@ class C1 { get a() { return this.#a_accessor_storage; } set a(value) { this.#a_accessor_storage = value; } static #b_accessor_storage; - static get b() { return this.#b_accessor_storage; } - static set b(value) { this.#b_accessor_storage = value; } + static get b() { return C1.#b_accessor_storage; } + static set b(value) { C1.#b_accessor_storage = value; } } __decorate([ dec @@ -46,6 +46,6 @@ class C2 { get #a() { return this.#a_accessor_storage; } set #a(value) { this.#a_accessor_storage = value; } static #b_accessor_storage; - static get #b() { return this.#b_accessor_storage; } - static set #b(value) { this.#b_accessor_storage = value; } + static get #b() { return C2.#b_accessor_storage; } + static set #b(value) { C2.#b_accessor_storage = value; } } diff --git a/tests/baselines/reference/esDecorators-classDeclaration-classThisReference(target=es2015).js b/tests/baselines/reference/esDecorators-classDeclaration-classThisReference(target=es2015).js index b0ff6a31abc9d..66f15fe9c942f 100644 --- a/tests/baselines/reference/esDecorators-classDeclaration-classThisReference(target=es2015).js +++ b/tests/baselines/reference/esDecorators-classDeclaration-classThisReference(target=es2015).js @@ -21,8 +21,8 @@ let C = (() => { let _classExtraInitializers = []; let _classThis; var C = _classThis = class { - static get a() { return __classPrivateFieldGet(this, _classThis, "f", _C_a_accessor_storage); } - static set a(value) { __classPrivateFieldSet(this, _classThis, value, "f", _C_a_accessor_storage); } + static get a() { return __classPrivateFieldGet(_classThis, _classThis, "f", _C_a_accessor_storage); } + static set a(value) { __classPrivateFieldSet(_classThis, _classThis, value, "f", _C_a_accessor_storage); } static m() { this; } static get g() { return this; } }; diff --git a/tests/baselines/reference/esDecorators-classDeclaration-classThisReference(target=es2022).js b/tests/baselines/reference/esDecorators-classDeclaration-classThisReference(target=es2022).js index 5c5898b529cbc..ed7697f730fde 100644 --- a/tests/baselines/reference/esDecorators-classDeclaration-classThisReference(target=es2022).js +++ b/tests/baselines/reference/esDecorators-classDeclaration-classThisReference(target=es2022).js @@ -34,8 +34,8 @@ let C = (() => { static { _C_a_accessor_storage = { value: _classThis }; } - static get a() { return __classPrivateFieldGet(this, _classThis, "f", _C_a_accessor_storage); } - static set a(value) { __classPrivateFieldSet(this, _classThis, value, "f", _C_a_accessor_storage); } + static get a() { return __classPrivateFieldGet(_classThis, _classThis, "f", _C_a_accessor_storage); } + static set a(value) { __classPrivateFieldSet(_classThis, _classThis, value, "f", _C_a_accessor_storage); } static m() { this; } static get g() { return this; } static { diff --git a/tests/baselines/reference/esDecorators-classDeclaration-fields-staticAccessor(target=es2015).js b/tests/baselines/reference/esDecorators-classDeclaration-fields-staticAccessor(target=es2015).js index 018ee29d701fa..d2713fbf59fcc 100644 --- a/tests/baselines/reference/esDecorators-classDeclaration-fields-staticAccessor(target=es2015).js +++ b/tests/baselines/reference/esDecorators-classDeclaration-fields-staticAccessor(target=es2015).js @@ -33,12 +33,12 @@ let C = (() => { let _static_member_decorators_1; let _static_member_initializers_1 = []; return _a = class C { - static get field1() { return __classPrivateFieldGet(this, _a, "f", _C_field1_accessor_storage); } - static set field1(value) { __classPrivateFieldSet(this, _a, value, "f", _C_field1_accessor_storage); } - static get ["field2"]() { return __classPrivateFieldGet(this, _a, "f", _C__a_accessor_storage); } - static set ["field2"](value) { __classPrivateFieldSet(this, _a, value, "f", _C__a_accessor_storage); } - static get [(_static_field1_decorators = [dec(1)], _static_member_decorators = [dec(2)], _static_member_decorators_1 = [dec(3)], _b = __propKey(field3))]() { return __classPrivateFieldGet(this, _a, "f", _C__b_accessor_storage); } - static set [_b](value) { __classPrivateFieldSet(this, _a, value, "f", _C__b_accessor_storage); } + static get field1() { return __classPrivateFieldGet(_a, _a, "f", _C_field1_accessor_storage); } + static set field1(value) { __classPrivateFieldSet(_a, _a, value, "f", _C_field1_accessor_storage); } + static get ["field2"]() { return __classPrivateFieldGet(_a, _a, "f", _C__a_accessor_storage); } + static set ["field2"](value) { __classPrivateFieldSet(_a, _a, value, "f", _C__a_accessor_storage); } + static get [(_static_field1_decorators = [dec(1)], _static_member_decorators = [dec(2)], _static_member_decorators_1 = [dec(3)], _b = __propKey(field3))]() { return __classPrivateFieldGet(_a, _a, "f", _C__b_accessor_storage); } + static set [_b](value) { __classPrivateFieldSet(_a, _a, value, "f", _C__b_accessor_storage); } }, (() => { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; @@ -60,8 +60,8 @@ let D = (() => { let _classExtraInitializers = []; let _classThis; var D = _classThis = class { - static get field1() { return __classPrivateFieldGet(this, _classThis, "f", _D_field1_accessor_storage); } - static set field1(value) { __classPrivateFieldSet(this, _classThis, value, "f", _D_field1_accessor_storage); } + static get field1() { return __classPrivateFieldGet(_classThis, _classThis, "f", _D_field1_accessor_storage); } + static set field1(value) { __classPrivateFieldSet(_classThis, _classThis, value, "f", _D_field1_accessor_storage); } }; __setFunctionName(_classThis, "D"); (() => { diff --git a/tests/baselines/reference/esDecorators-classDeclaration-fields-staticAccessor(target=es2022).js b/tests/baselines/reference/esDecorators-classDeclaration-fields-staticAccessor(target=es2022).js index 0dd0ea8f4b0a8..12a84fd016301 100644 --- a/tests/baselines/reference/esDecorators-classDeclaration-fields-staticAccessor(target=es2022).js +++ b/tests/baselines/reference/esDecorators-classDeclaration-fields-staticAccessor(target=es2022).js @@ -41,14 +41,14 @@ let C = (() => { __runInitializers(this, _staticExtraInitializers); } static #field1_accessor_storage = __runInitializers(this, _static_field1_initializers, 1); - static get field1() { return this.#field1_accessor_storage; } - static set field1(value) { this.#field1_accessor_storage = value; } + static get field1() { return C.#field1_accessor_storage; } + static set field1(value) { C.#field1_accessor_storage = value; } static #_a_accessor_storage = __runInitializers(this, _static_member_initializers, 2); - static get ["field2"]() { return this.#_a_accessor_storage; } - static set ["field2"](value) { this.#_a_accessor_storage = value; } + static get ["field2"]() { return C.#_a_accessor_storage; } + static set ["field2"](value) { C.#_a_accessor_storage = value; } static #_b_accessor_storage = __runInitializers(this, _static_member_initializers_1, 3); - static get [(_static_field1_decorators = [dec(1)], _static_member_decorators = [dec(2)], _static_member_decorators_1 = [dec(3)], _a = __propKey(field3))]() { return this.#_b_accessor_storage; } - static set [_a](value) { this.#_b_accessor_storage = value; } + static get [(_static_field1_decorators = [dec(1)], _static_member_decorators = [dec(2)], _static_member_decorators_1 = [dec(3)], _a = __propKey(field3))]() { return C.#_b_accessor_storage; } + static set [_a](value) { C.#_b_accessor_storage = value; } }; })(); let D = (() => { @@ -69,8 +69,8 @@ let D = (() => { static { _D_field1_accessor_storage = { value: 1 }; } - static get field1() { return __classPrivateFieldGet(this, _classThis, "f", _D_field1_accessor_storage); } - static set field1(value) { __classPrivateFieldSet(this, _classThis, value, "f", _D_field1_accessor_storage); } + static get field1() { return __classPrivateFieldGet(_classThis, _classThis, "f", _D_field1_accessor_storage); } + static set field1(value) { __classPrivateFieldSet(_classThis, _classThis, value, "f", _D_field1_accessor_storage); } static { _classThis.field1; _classThis.field1 = 1; diff --git a/tests/baselines/reference/esDecorators-classDeclaration-fields-staticPrivateAccessor(target=es2015).js b/tests/baselines/reference/esDecorators-classDeclaration-fields-staticPrivateAccessor(target=es2015).js index cf72cc5483db8..da8fde6263e24 100644 --- a/tests/baselines/reference/esDecorators-classDeclaration-fields-staticPrivateAccessor(target=es2015).js +++ b/tests/baselines/reference/esDecorators-classDeclaration-fields-staticPrivateAccessor(target=es2015).js @@ -46,8 +46,8 @@ let D = (() => { let _classThis; var D = _classThis = class { }; - _D_field1_get = function _D_field1_get() { return __classPrivateFieldGet(this, _classThis, "f", _D_field1_accessor_storage); }; - _D_field1_set = function _D_field1_set(value) { __classPrivateFieldSet(this, _classThis, value, "f", _D_field1_accessor_storage); }; + _D_field1_get = function _D_field1_get() { return __classPrivateFieldGet(_classThis, _classThis, "f", _D_field1_accessor_storage); }; + _D_field1_set = function _D_field1_set(value) { __classPrivateFieldSet(_classThis, _classThis, value, "f", _D_field1_accessor_storage); }; __setFunctionName(_classThis, "D"); (() => { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; diff --git a/tests/baselines/reference/esDecorators-classDeclaration-fields-staticPrivateAccessor(target=es2022).js b/tests/baselines/reference/esDecorators-classDeclaration-fields-staticPrivateAccessor(target=es2022).js index d39870d3883d4..10b10964e1160 100644 --- a/tests/baselines/reference/esDecorators-classDeclaration-fields-staticPrivateAccessor(target=es2022).js +++ b/tests/baselines/reference/esDecorators-classDeclaration-fields-staticPrivateAccessor(target=es2022).js @@ -45,7 +45,7 @@ let D = (() => { var D = class { static { _classThis = this; } static { __setFunctionName(this, "D"); } - static { _D_field1_get = function _D_field1_get() { return __classPrivateFieldGet(this, _classThis, "f", _D_field1_accessor_storage); }, _D_field1_set = function _D_field1_set(value) { __classPrivateFieldSet(this, _classThis, value, "f", _D_field1_accessor_storage); }; } + static { _D_field1_get = function _D_field1_get() { return __classPrivateFieldGet(_classThis, _classThis, "f", _D_field1_accessor_storage); }, _D_field1_set = function _D_field1_set(value) { __classPrivateFieldSet(_classThis, _classThis, value, "f", _D_field1_accessor_storage); }; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); diff --git a/tests/baselines/reference/esDecorators-classDeclaration-missingEmitHelpers-staticComputedAutoAccessor.js b/tests/baselines/reference/esDecorators-classDeclaration-missingEmitHelpers-staticComputedAutoAccessor.js index 466c8b6efacb5..5178ab9627a4f 100644 --- a/tests/baselines/reference/esDecorators-classDeclaration-missingEmitHelpers-staticComputedAutoAccessor.js +++ b/tests/baselines/reference/esDecorators-classDeclaration-missingEmitHelpers-staticComputedAutoAccessor.js @@ -33,7 +33,7 @@ let C = (() => { tslib_1.__runInitializers(this, _staticExtraInitializers); } static #_a_accessor_storage = tslib_1.__runInitializers(this, _static_member_initializers, void 0); - static get [(_static_member_decorators = [dec], _a = tslib_1.__propKey(x))]() { return this.#_a_accessor_storage; } - static set [_a](value) { this.#_a_accessor_storage = value; } + static get [(_static_member_decorators = [dec], _a = tslib_1.__propKey(x))]() { return C.#_a_accessor_storage; } + static set [_a](value) { C.#_a_accessor_storage = value; } }; })(); diff --git a/tests/baselines/reference/esDecorators-preservesThis.js b/tests/baselines/reference/esDecorators-preservesThis.js new file mode 100644 index 0000000000000..d8db1c2729a8a --- /dev/null +++ b/tests/baselines/reference/esDecorators-preservesThis.js @@ -0,0 +1,134 @@ +//// [tests/cases/conformance/esDecorators/esDecorators-preservesThis.ts] //// + +//// [esDecorators-preservesThis.ts] +// https://github.com/microsoft/TypeScript/issues/53752 + +declare class DecoratorProvider { + decorate(this: DecoratorProvider, v: T, ctx: DecoratorContext): T; +} + +declare const instance: DecoratorProvider; + +// preserve `this` for access +class C { + @instance.decorate + method1() { } + + @(instance["decorate"]) + method2() { } + + // even in parens + @((instance.decorate)) + method3() { } +} + +// preserve `this` for `super` access +class D extends DecoratorProvider { + m() { + class C { + @super.decorate + method1() { } + + @(super["decorate"]) + method2() { } + + @((super.decorate)) + method3() { } + } + } +} + + +//// [esDecorators-preservesThis.js] +// https://github.com/microsoft/TypeScript/issues/53752 +var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { + function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } + var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; + var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; + var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); + var _, done = false; + for (var i = decorators.length - 1; i >= 0; i--) { + var context = {}; + for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; + for (var p in contextIn.access) context.access[p] = contextIn.access[p]; + context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; + var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); + if (kind === "accessor") { + if (result === void 0) continue; + if (result === null || typeof result !== "object") throw new TypeError("Object expected"); + if (_ = accept(result.get)) descriptor.get = _; + if (_ = accept(result.set)) descriptor.set = _; + if (_ = accept(result.init)) initializers.unshift(_); + } + else if (_ = accept(result)) { + if (kind === "field") initializers.unshift(_); + else descriptor[key] = _; + } + } + if (target) Object.defineProperty(target, contextIn.name, descriptor); + done = true; +}; +var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { + var useValue = arguments.length > 2; + for (var i = 0; i < initializers.length; i++) { + value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); + } + return useValue ? value : void 0; +}; +// preserve `this` for access +let C = (() => { + var _a, _b, _c; + let _instanceExtraInitializers = []; + let _method1_decorators; + let _method2_decorators; + let _method3_decorators; + return class C { + static { + const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; + _method1_decorators = [(_a = instance).decorate.bind(_a)]; + _method2_decorators = [((_b = instance)["decorate"].bind(_b))]; + _method3_decorators = [(((_c = instance).decorate.bind(_c)))]; + __esDecorate(this, null, _method1_decorators, { kind: "method", name: "method1", static: false, private: false, access: { has: obj => "method1" in obj, get: obj => obj.method1 }, metadata: _metadata }, null, _instanceExtraInitializers); + __esDecorate(this, null, _method2_decorators, { kind: "method", name: "method2", static: false, private: false, access: { has: obj => "method2" in obj, get: obj => obj.method2 }, metadata: _metadata }, null, _instanceExtraInitializers); + __esDecorate(this, null, _method3_decorators, { kind: "method", name: "method3", static: false, private: false, access: { has: obj => "method3" in obj, get: obj => obj.method3 }, metadata: _metadata }, null, _instanceExtraInitializers); + if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); + } + method1() { } + method2() { } + // even in parens + method3() { } + constructor() { + __runInitializers(this, _instanceExtraInitializers); + } + }; +})(); +// preserve `this` for `super` access +class D extends DecoratorProvider { + m() { + let C = (() => { + let _outerThis = this; + let _instanceExtraInitializers = []; + let _method1_decorators; + let _method2_decorators; + let _method3_decorators; + return class C { + static { + const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; + _method1_decorators = [super.decorate.bind(_outerThis)]; + _method2_decorators = [(super["decorate"].bind(_outerThis))]; + _method3_decorators = [((super.decorate.bind(_outerThis)))]; + __esDecorate(this, null, _method1_decorators, { kind: "method", name: "method1", static: false, private: false, access: { has: obj => "method1" in obj, get: obj => obj.method1 }, metadata: _metadata }, null, _instanceExtraInitializers); + __esDecorate(this, null, _method2_decorators, { kind: "method", name: "method2", static: false, private: false, access: { has: obj => "method2" in obj, get: obj => obj.method2 }, metadata: _metadata }, null, _instanceExtraInitializers); + __esDecorate(this, null, _method3_decorators, { kind: "method", name: "method3", static: false, private: false, access: { has: obj => "method3" in obj, get: obj => obj.method3 }, metadata: _metadata }, null, _instanceExtraInitializers); + if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); + } + method1() { } + method2() { } + method3() { } + constructor() { + __runInitializers(this, _instanceExtraInitializers); + } + }; + })(); + } +} diff --git a/tests/baselines/reference/esDecorators-preservesThis.symbols b/tests/baselines/reference/esDecorators-preservesThis.symbols new file mode 100644 index 0000000000000..e4337caf5c8a6 --- /dev/null +++ b/tests/baselines/reference/esDecorators-preservesThis.symbols @@ -0,0 +1,90 @@ +//// [tests/cases/conformance/esDecorators/esDecorators-preservesThis.ts] //// + +=== esDecorators-preservesThis.ts === +// https://github.com/microsoft/TypeScript/issues/53752 + +declare class DecoratorProvider { +>DecoratorProvider : Symbol(DecoratorProvider, Decl(esDecorators-preservesThis.ts, 0, 0)) + + decorate(this: DecoratorProvider, v: T, ctx: DecoratorContext): T; +>decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) +>T : Symbol(T, Decl(esDecorators-preservesThis.ts, 3, 13)) +>this : Symbol(this, Decl(esDecorators-preservesThis.ts, 3, 16)) +>DecoratorProvider : Symbol(DecoratorProvider, Decl(esDecorators-preservesThis.ts, 0, 0)) +>v : Symbol(v, Decl(esDecorators-preservesThis.ts, 3, 40)) +>T : Symbol(T, Decl(esDecorators-preservesThis.ts, 3, 13)) +>ctx : Symbol(ctx, Decl(esDecorators-preservesThis.ts, 3, 46)) +>DecoratorContext : Symbol(DecoratorContext, Decl(lib.decorators.d.ts, --, --)) +>T : Symbol(T, Decl(esDecorators-preservesThis.ts, 3, 13)) +} + +declare const instance: DecoratorProvider; +>instance : Symbol(instance, Decl(esDecorators-preservesThis.ts, 6, 13)) +>DecoratorProvider : Symbol(DecoratorProvider, Decl(esDecorators-preservesThis.ts, 0, 0)) + +// preserve `this` for access +class C { +>C : Symbol(C, Decl(esDecorators-preservesThis.ts, 6, 42)) + + @instance.decorate +>instance.decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) +>instance : Symbol(instance, Decl(esDecorators-preservesThis.ts, 6, 13)) +>decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) + + method1() { } +>method1 : Symbol(C.method1, Decl(esDecorators-preservesThis.ts, 9, 9)) + + @(instance["decorate"]) +>instance : Symbol(instance, Decl(esDecorators-preservesThis.ts, 6, 13)) +>"decorate" : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) + + method2() { } +>method2 : Symbol(C.method2, Decl(esDecorators-preservesThis.ts, 11, 17)) + + // even in parens + @((instance.decorate)) +>instance.decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) +>instance : Symbol(instance, Decl(esDecorators-preservesThis.ts, 6, 13)) +>decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) + + method3() { } +>method3 : Symbol(C.method3, Decl(esDecorators-preservesThis.ts, 14, 17)) +} + +// preserve `this` for `super` access +class D extends DecoratorProvider { +>D : Symbol(D, Decl(esDecorators-preservesThis.ts, 19, 1)) +>DecoratorProvider : Symbol(DecoratorProvider, Decl(esDecorators-preservesThis.ts, 0, 0)) + + m() { +>m : Symbol(D.m, Decl(esDecorators-preservesThis.ts, 22, 35)) + + class C { +>C : Symbol(C, Decl(esDecorators-preservesThis.ts, 23, 9)) + + @super.decorate +>super.decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) +>super : Symbol(DecoratorProvider, Decl(esDecorators-preservesThis.ts, 0, 0)) +>decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) + + method1() { } +>method1 : Symbol(C.method1, Decl(esDecorators-preservesThis.ts, 24, 17)) + + @(super["decorate"]) +>super : Symbol(DecoratorProvider, Decl(esDecorators-preservesThis.ts, 0, 0)) +>"decorate" : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) + + method2() { } +>method2 : Symbol(C.method2, Decl(esDecorators-preservesThis.ts, 26, 25)) + + @((super.decorate)) +>super.decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) +>super : Symbol(DecoratorProvider, Decl(esDecorators-preservesThis.ts, 0, 0)) +>decorate : Symbol(DecoratorProvider.decorate, Decl(esDecorators-preservesThis.ts, 2, 33)) + + method3() { } +>method3 : Symbol(C.method3, Decl(esDecorators-preservesThis.ts, 29, 25)) + } + } +} + diff --git a/tests/baselines/reference/esDecorators-preservesThis.types b/tests/baselines/reference/esDecorators-preservesThis.types new file mode 100644 index 0000000000000..139812e62e7df --- /dev/null +++ b/tests/baselines/reference/esDecorators-preservesThis.types @@ -0,0 +1,92 @@ +//// [tests/cases/conformance/esDecorators/esDecorators-preservesThis.ts] //// + +=== esDecorators-preservesThis.ts === +// https://github.com/microsoft/TypeScript/issues/53752 + +declare class DecoratorProvider { +>DecoratorProvider : DecoratorProvider + + decorate(this: DecoratorProvider, v: T, ctx: DecoratorContext): T; +>decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>this : DecoratorProvider +>v : T +>ctx : DecoratorContext +} + +declare const instance: DecoratorProvider; +>instance : DecoratorProvider + +// preserve `this` for access +class C { +>C : C + + @instance.decorate +>instance.decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>instance : DecoratorProvider +>decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T + + method1() { } +>method1 : () => void + + @(instance["decorate"]) +>(instance["decorate"]) : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>instance["decorate"] : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>instance : DecoratorProvider +>"decorate" : "decorate" + + method2() { } +>method2 : () => void + + // even in parens + @((instance.decorate)) +>((instance.decorate)) : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>(instance.decorate) : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>instance.decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>instance : DecoratorProvider +>decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T + + method3() { } +>method3 : () => void +} + +// preserve `this` for `super` access +class D extends DecoratorProvider { +>D : D +>DecoratorProvider : DecoratorProvider + + m() { +>m : () => void + + class C { +>C : C + + @super.decorate +>super.decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>super : DecoratorProvider +>decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T + + method1() { } +>method1 : () => void + + @(super["decorate"]) +>(super["decorate"]) : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>super["decorate"] : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>super : DecoratorProvider +>"decorate" : "decorate" + + method2() { } +>method2 : () => void + + @((super.decorate)) +>((super.decorate)) : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>(super.decorate) : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>super.decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T +>super : DecoratorProvider +>decorate : (this: DecoratorProvider, v: T, ctx: DecoratorContext) => T + + method3() { } +>method3 : () => void + } + } +} + diff --git a/tests/baselines/reference/staticAutoAccessors(target=es2017).js b/tests/baselines/reference/staticAutoAccessors(target=es2017).js new file mode 100644 index 0000000000000..35ee257ad662b --- /dev/null +++ b/tests/baselines/reference/staticAutoAccessors(target=es2017).js @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessors.ts] //// + +//// [staticAutoAccessors.ts] +// https://github.com/microsoft/TypeScript/issues/53752 + +class A { + // uses class reference + static accessor x = 1; + + // uses 'this' + accessor y = 2; +} + + + +//// [staticAutoAccessors.js] +// https://github.com/microsoft/TypeScript/issues/53752 +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _a, _A_x_accessor_storage, _A_y_accessor_storage; +class A { + constructor() { + _A_y_accessor_storage.set(this, 2); + } + // uses class reference + static get x() { return __classPrivateFieldGet(_a, _a, "f", _A_x_accessor_storage); } + static set x(value) { __classPrivateFieldSet(_a, _a, value, "f", _A_x_accessor_storage); } + // uses 'this' + get y() { return __classPrivateFieldGet(this, _A_y_accessor_storage, "f"); } + set y(value) { __classPrivateFieldSet(this, _A_y_accessor_storage, value, "f"); } +} +_a = A, _A_y_accessor_storage = new WeakMap(); +_A_x_accessor_storage = { value: 1 }; diff --git a/tests/baselines/reference/staticAutoAccessors(target=es2022).js b/tests/baselines/reference/staticAutoAccessors(target=es2022).js new file mode 100644 index 0000000000000..2337fa17b8d76 --- /dev/null +++ b/tests/baselines/reference/staticAutoAccessors(target=es2022).js @@ -0,0 +1,27 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessors.ts] //// + +//// [staticAutoAccessors.ts] +// https://github.com/microsoft/TypeScript/issues/53752 + +class A { + // uses class reference + static accessor x = 1; + + // uses 'this' + accessor y = 2; +} + + + +//// [staticAutoAccessors.js] +// https://github.com/microsoft/TypeScript/issues/53752 +class A { + static #x_accessor_storage = 1; + // uses class reference + static get x() { return A.#x_accessor_storage; } + static set x(value) { A.#x_accessor_storage = value; } + #y_accessor_storage = 2; + // uses 'this' + get y() { return this.#y_accessor_storage; } + set y(value) { this.#y_accessor_storage = value; } +} diff --git a/tests/baselines/reference/staticAutoAccessorsWithDecorators(target=es2017).js b/tests/baselines/reference/staticAutoAccessorsWithDecorators(target=es2017).js new file mode 100644 index 0000000000000..341c4ee4ede11 --- /dev/null +++ b/tests/baselines/reference/staticAutoAccessorsWithDecorators(target=es2017).js @@ -0,0 +1,96 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessorsWithDecorators.ts] //// + +//// [staticAutoAccessorsWithDecorators.ts] +// https://github.com/microsoft/TypeScript/issues/53752 + +class A { + // uses class reference + @((t, c) => {}) + static accessor x = 1; + + // uses 'this' + @((t, c) => {}) + accessor y = 2; +} + + +//// [staticAutoAccessorsWithDecorators.js] +// https://github.com/microsoft/TypeScript/issues/53752 +var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { + function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } + var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; + var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; + var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); + var _, done = false; + for (var i = decorators.length - 1; i >= 0; i--) { + var context = {}; + for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; + for (var p in contextIn.access) context.access[p] = contextIn.access[p]; + context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; + var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); + if (kind === "accessor") { + if (result === void 0) continue; + if (result === null || typeof result !== "object") throw new TypeError("Object expected"); + if (_ = accept(result.get)) descriptor.get = _; + if (_ = accept(result.set)) descriptor.set = _; + if (_ = accept(result.init)) initializers.unshift(_); + } + else if (_ = accept(result)) { + if (kind === "field") initializers.unshift(_); + else descriptor[key] = _; + } + } + if (target) Object.defineProperty(target, contextIn.name, descriptor); + done = true; +}; +var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { + var useValue = arguments.length > 2; + for (var i = 0; i < initializers.length; i++) { + value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); + } + return useValue ? value : void 0; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +let A = (() => { + var _a, _A_x_accessor_storage, _A_y_accessor_storage; + let _staticExtraInitializers = []; + let _instanceExtraInitializers = []; + let _static_x_decorators; + let _static_x_initializers = []; + let _y_decorators; + let _y_initializers = []; + return _a = class A { + constructor() { + _A_y_accessor_storage.set(this, (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _y_initializers, 2))); + } + // uses class reference + static get x() { return __classPrivateFieldGet(_a, _a, "f", _A_x_accessor_storage); } + static set x(value) { __classPrivateFieldSet(_a, _a, value, "f", _A_x_accessor_storage); } + // uses 'this' + get y() { return __classPrivateFieldGet(this, _A_y_accessor_storage, "f"); } + set y(value) { __classPrivateFieldSet(this, _A_y_accessor_storage, value, "f"); } + }, + _A_y_accessor_storage = new WeakMap(), + (() => { + const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; + _static_x_decorators = [((t, c) => { })]; + _y_decorators = [((t, c) => { })]; + __esDecorate(_a, null, _static_x_decorators, { kind: "accessor", name: "x", static: true, private: false, access: { has: obj => "x" in obj, get: obj => obj.x, set: (obj, value) => { obj.x = value; } }, metadata: _metadata }, _static_x_initializers, _staticExtraInitializers); + __esDecorate(_a, null, _y_decorators, { kind: "accessor", name: "y", static: false, private: false, access: { has: obj => "y" in obj, get: obj => obj.y, set: (obj, value) => { obj.y = value; } }, metadata: _metadata }, _y_initializers, _instanceExtraInitializers); + if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); + __runInitializers(_a, _staticExtraInitializers); + })(), + // uses class reference + _A_x_accessor_storage = { value: __runInitializers(_a, _static_x_initializers, 1) }, + _a; +})(); diff --git a/tests/baselines/reference/staticAutoAccessorsWithDecorators(target=es2022).js b/tests/baselines/reference/staticAutoAccessorsWithDecorators(target=es2022).js new file mode 100644 index 0000000000000..cc85e8e66fa40 --- /dev/null +++ b/tests/baselines/reference/staticAutoAccessorsWithDecorators(target=es2022).js @@ -0,0 +1,79 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessorsWithDecorators.ts] //// + +//// [staticAutoAccessorsWithDecorators.ts] +// https://github.com/microsoft/TypeScript/issues/53752 + +class A { + // uses class reference + @((t, c) => {}) + static accessor x = 1; + + // uses 'this' + @((t, c) => {}) + accessor y = 2; +} + + +//// [staticAutoAccessorsWithDecorators.js] +// https://github.com/microsoft/TypeScript/issues/53752 +var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { + function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } + var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; + var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; + var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); + var _, done = false; + for (var i = decorators.length - 1; i >= 0; i--) { + var context = {}; + for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; + for (var p in contextIn.access) context.access[p] = contextIn.access[p]; + context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; + var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); + if (kind === "accessor") { + if (result === void 0) continue; + if (result === null || typeof result !== "object") throw new TypeError("Object expected"); + if (_ = accept(result.get)) descriptor.get = _; + if (_ = accept(result.set)) descriptor.set = _; + if (_ = accept(result.init)) initializers.unshift(_); + } + else if (_ = accept(result)) { + if (kind === "field") initializers.unshift(_); + else descriptor[key] = _; + } + } + if (target) Object.defineProperty(target, contextIn.name, descriptor); + done = true; +}; +var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { + var useValue = arguments.length > 2; + for (var i = 0; i < initializers.length; i++) { + value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); + } + return useValue ? value : void 0; +}; +let A = (() => { + let _staticExtraInitializers = []; + let _instanceExtraInitializers = []; + let _static_x_decorators; + let _static_x_initializers = []; + let _y_decorators; + let _y_initializers = []; + return class A { + static { + const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0; + _static_x_decorators = [((t, c) => { })]; + _y_decorators = [((t, c) => { })]; + __esDecorate(this, null, _static_x_decorators, { kind: "accessor", name: "x", static: true, private: false, access: { has: obj => "x" in obj, get: obj => obj.x, set: (obj, value) => { obj.x = value; } }, metadata: _metadata }, _static_x_initializers, _staticExtraInitializers); + __esDecorate(this, null, _y_decorators, { kind: "accessor", name: "y", static: false, private: false, access: { has: obj => "y" in obj, get: obj => obj.y, set: (obj, value) => { obj.y = value; } }, metadata: _metadata }, _y_initializers, _instanceExtraInitializers); + if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); + __runInitializers(this, _staticExtraInitializers); + } + static #x_accessor_storage = __runInitializers(this, _static_x_initializers, 1); + // uses class reference + static get x() { return A.#x_accessor_storage; } + static set x(value) { A.#x_accessor_storage = value; } + #y_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _y_initializers, 2)); + // uses 'this' + get y() { return this.#y_accessor_storage; } + set y(value) { this.#y_accessor_storage = value; } + }; +})(); diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessors.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessors.ts new file mode 100644 index 0000000000000..8211df83e18f1 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessors.ts @@ -0,0 +1,12 @@ +// @target: es2022,es2017 +// @noTypesAndSymbols: true +// https://github.com/microsoft/TypeScript/issues/53752 + +class A { + // uses class reference + static accessor x = 1; + + // uses 'this' + accessor y = 2; +} + diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessorsWithDecorators.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessorsWithDecorators.ts new file mode 100644 index 0000000000000..638fdf2b9a640 --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/staticAutoAccessorsWithDecorators.ts @@ -0,0 +1,13 @@ +// @target: es2022,es2017 +// @noTypesAndSymbols: true +// https://github.com/microsoft/TypeScript/issues/53752 + +class A { + // uses class reference + @((t, c) => {}) + static accessor x = 1; + + // uses 'this' + @((t, c) => {}) + accessor y = 2; +} diff --git a/tests/cases/conformance/esDecorators/esDecorators-preservesThis.ts b/tests/cases/conformance/esDecorators/esDecorators-preservesThis.ts new file mode 100644 index 0000000000000..87e2a250d756f --- /dev/null +++ b/tests/cases/conformance/esDecorators/esDecorators-preservesThis.ts @@ -0,0 +1,37 @@ +// @target: es2022 +// https://github.com/microsoft/TypeScript/issues/53752 + +declare class DecoratorProvider { + decorate(this: DecoratorProvider, v: T, ctx: DecoratorContext): T; +} + +declare const instance: DecoratorProvider; + +// preserve `this` for access +class C { + @instance.decorate + method1() { } + + @(instance["decorate"]) + method2() { } + + // even in parens + @((instance.decorate)) + method3() { } +} + +// preserve `this` for `super` access +class D extends DecoratorProvider { + m() { + class C { + @super.decorate + method1() { } + + @(super["decorate"]) + method2() { } + + @((super.decorate)) + method3() { } + } + } +}