Skip to content

Commit 8fc8c95

Browse files
authored
Decorators normative updates (#55276)
1 parent b1c4dc4 commit 8fc8c95

File tree

35 files changed

+735
-89
lines changed

35 files changed

+735
-89
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32875,7 +32875,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3287532875
*/
3287632876
function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression | undefined {
3287732877
const expression = node.kind === SyntaxKind.CallExpression ? node.expression :
32878-
node.kind === SyntaxKind.TaggedTemplateExpression ? node.tag : undefined;
32878+
node.kind === SyntaxKind.TaggedTemplateExpression ? node.tag :
32879+
node.kind === SyntaxKind.Decorator && !legacyDecorators ? node.expression :
32880+
undefined;
3287932881
if (expression) {
3288032882
const callee = skipOuterExpressions(expression);
3288132883
if (isAccessExpression(callee)) {

src/compiler/factory/utilities.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,7 +1645,7 @@ export function createAccessorPropertyBackingField(factory: NodeFactory, node: P
16451645
*
16461646
* @internal
16471647
*/
1648-
export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: ModifiersArray | undefined, name: PropertyName): GetAccessorDeclaration {
1648+
export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: readonly Modifier[] | undefined, name: PropertyName, receiver: Expression = factory.createThis()): GetAccessorDeclaration {
16491649
return factory.createGetAccessorDeclaration(
16501650
modifiers,
16511651
name,
@@ -1654,7 +1654,7 @@ export function createAccessorPropertyGetRedirector(factory: NodeFactory, node:
16541654
factory.createBlock([
16551655
factory.createReturnStatement(
16561656
factory.createPropertyAccessExpression(
1657-
factory.createThis(),
1657+
receiver,
16581658
factory.getGeneratedPrivateNameForNode(node.name, /*prefix*/ undefined, "_accessor_storage")
16591659
)
16601660
)
@@ -1667,7 +1667,7 @@ export function createAccessorPropertyGetRedirector(factory: NodeFactory, node:
16671667
*
16681668
* @internal
16691669
*/
1670-
export function createAccessorPropertySetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: ModifiersArray | undefined, name: PropertyName) {
1670+
export function createAccessorPropertySetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: readonly Modifier[] | undefined, name: PropertyName, receiver: Expression = factory.createThis()) {
16711671
return factory.createSetAccessorDeclaration(
16721672
modifiers,
16731673
name,
@@ -1680,7 +1680,7 @@ export function createAccessorPropertySetRedirector(factory: NodeFactory, node:
16801680
factory.createExpressionStatement(
16811681
factory.createAssignment(
16821682
factory.createPropertyAccessExpression(
1683-
factory.createThis(),
1683+
receiver,
16841684
factory.getGeneratedPrivateNameForNode(node.name, /*prefix*/ undefined, "_accessor_storage")
16851685
),
16861686
factory.createIdentifier("value")

src/compiler/transformers/classFields.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ import {
154154
Modifier,
155155
ModifierFlags,
156156
ModifierLike,
157+
modifiersToFlags,
157158
moveRangePastModifiers,
158159
moveRangePos,
159160
newPrivateEnvironment,
@@ -896,6 +897,12 @@ export function transformClassFields(context: TransformationContext): (x: Source
896897
}
897898
}
898899

900+
function getClassThis() {
901+
const lex = getClassLexicalEnvironment();
902+
const classThis = lex.classThis ?? lex.classConstructor ?? currentClassContainer?.name;
903+
return Debug.checkDefined(classThis);
904+
}
905+
899906
function transformAutoAccessor(node: AutoAccessorPropertyDeclaration): VisitResult<Node> {
900907
// transforms:
901908
// accessor x = 1;
@@ -935,12 +942,15 @@ export function transformClassFields(context: TransformationContext): (x: Source
935942
setEmitFlags(backingField, EmitFlags.NoComments);
936943
setSourceMapRange(backingField, sourceMapRange);
937944

938-
const getter = createAccessorPropertyGetRedirector(factory, node, modifiers, getterName);
945+
const receiver = isStatic(node) ? getClassThis() : factory.createThis();
946+
const getter = createAccessorPropertyGetRedirector(factory, node, modifiers, getterName, receiver);
939947
setOriginalNode(getter, node);
940948
setCommentRange(getter, commentRange);
941949
setSourceMapRange(getter, sourceMapRange);
942950

943-
const setter = createAccessorPropertySetRedirector(factory, node, modifiers, setterName);
951+
// create a fresh copy of the modifiers so that we don't duplicate comments
952+
const setterModifiers = factory.createModifiersFromModifierFlags(modifiersToFlags(modifiers));
953+
const setter = createAccessorPropertySetRedirector(factory, node, setterModifiers, setterName, receiver);
944954
setOriginalNode(setter, node);
945955
setEmitFlags(setter, EmitFlags.NoComments);
946956
setSourceMapRange(setter, sourceMapRange);
@@ -1692,11 +1702,13 @@ export function transformClassFields(context: TransformationContext): (x: Source
16921702
let containsInstanceAutoAccessors = false;
16931703
for (const member of node.members) {
16941704
if (isStatic(member)) {
1695-
if (member.name &&
1696-
(isPrivateIdentifier(member.name) || isAutoAccessorPropertyDeclaration(member)) &&
1705+
if (member.name && (isPrivateIdentifier(member.name) || isAutoAccessorPropertyDeclaration(member)) &&
16971706
shouldTransformPrivateElementsOrClassStaticBlocks) {
16981707
facts |= ClassFacts.NeedsClassConstructorReference;
16991708
}
1709+
else if (isAutoAccessorPropertyDeclaration(member) && shouldTransformAutoAccessors === Ternary.True && !node.name && !node.emitNode?.classThis) {
1710+
facts |= ClassFacts.NeedsClassConstructorReference;
1711+
}
17001712
if (isPropertyDeclaration(member) || isClassStaticBlockDeclaration(member)) {
17011713
if (shouldTransformThisInStaticInitializers && member.transformFlags & TransformFlags.ContainsLexicalThis) {
17021714
facts |= ClassFacts.NeedsSubstitutionForThisInClassStaticField;
@@ -1846,10 +1858,10 @@ export function transformClassFields(context: TransformationContext): (x: Source
18461858
getClassLexicalEnvironment().classConstructor = factory.cloneNode(temp);
18471859
pendingClassReferenceAssignment = factory.createAssignment(temp, factory.getInternalName(node));
18481860
}
1861+
}
18491862

1850-
if (node.emitNode?.classThis) {
1851-
getClassLexicalEnvironment().classThis = node.emitNode.classThis;
1852-
}
1863+
if (node.emitNode?.classThis) {
1864+
getClassLexicalEnvironment().classThis = node.emitNode.classThis;
18531865
}
18541866

18551867
const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsConstructorReference;

src/compiler/transformers/esDecorators.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
getAllDecoratorsOfClassElement,
4848
getCommentRange,
4949
getEffectiveBaseTypeNode,
50+
getEmitScriptTarget,
5051
getFirstConstructorWithBody,
5152
getHeritageClause,
5253
getNonAssignmentOperatorForCompoundAssignment,
@@ -62,6 +63,7 @@ import {
6263
injectClassNamedEvaluationHelperBlockIfMissing,
6364
injectClassThisAssignmentIfMissing,
6465
InternalEmitFlags,
66+
isAccessExpression,
6567
isAmbientPropertyDeclaration,
6668
isArrayBindingOrAssignmentElement,
6769
isArrayLiteralExpression,
@@ -289,6 +291,7 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc
289291
hoistVariableDeclaration,
290292
} = context;
291293

294+
const languageVersion = getEmitScriptTarget(context.getCompilerOptions());
292295
let top: LexicalEnvironmentStackEntry | undefined;
293296
let classInfo: ClassInfo | undefined;
294297
let classThis: Identifier | undefined;
@@ -2147,6 +2150,13 @@ export function transformESDecorators(context: TransformationContext): (x: Sourc
21472150
function transformDecorator(decorator: Decorator) {
21482151
const expression = visitNode(decorator.expression, visitor, isExpression);
21492152
setEmitFlags(expression, EmitFlags.NoComments);
2153+
2154+
// preserve the 'this' binding for an access expression
2155+
const innerExpression = skipOuterExpressions(expression);
2156+
if (isAccessExpression(innerExpression)) {
2157+
const { target, thisArg } = factory.createCallBinding(expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true);
2158+
return factory.restoreOuterExpressions(expression, factory.createFunctionBindCall(target, thisArg, []));
2159+
}
21502160
return expression;
21512161
}
21522162

tests/baselines/reference/autoAccessor1(target=es2015).js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ class C1 {
3131
set a(value) { __classPrivateFieldSet(this, _C1_a_accessor_storage, value, "f"); }
3232
get b() { return __classPrivateFieldGet(this, _C1_b_accessor_storage, "f"); }
3333
set b(value) { __classPrivateFieldSet(this, _C1_b_accessor_storage, value, "f"); }
34-
static get c() { return __classPrivateFieldGet(this, _a, "f", _C1_c_accessor_storage); }
35-
static set c(value) { __classPrivateFieldSet(this, _a, value, "f", _C1_c_accessor_storage); }
36-
static get d() { return __classPrivateFieldGet(this, _a, "f", _C1_d_accessor_storage); }
37-
static set d(value) { __classPrivateFieldSet(this, _a, value, "f", _C1_d_accessor_storage); }
34+
static get c() { return __classPrivateFieldGet(_a, _a, "f", _C1_c_accessor_storage); }
35+
static set c(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1_c_accessor_storage); }
36+
static get d() { return __classPrivateFieldGet(_a, _a, "f", _C1_d_accessor_storage); }
37+
static set d(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1_d_accessor_storage); }
3838
}
3939
_a = C1, _C1_a_accessor_storage = new WeakMap(), _C1_b_accessor_storage = new WeakMap();
4040
_C1_c_accessor_storage = { value: void 0 };

tests/baselines/reference/autoAccessor1(target=es2022).js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ class C1 {
1818
get b() { return this.#b_accessor_storage; }
1919
set b(value) { this.#b_accessor_storage = value; }
2020
static #c_accessor_storage;
21-
static get c() { return this.#c_accessor_storage; }
22-
static set c(value) { this.#c_accessor_storage = value; }
21+
static get c() { return C1.#c_accessor_storage; }
22+
static set c(value) { C1.#c_accessor_storage = value; }
2323
static #d_accessor_storage = 2;
24-
static get d() { return this.#d_accessor_storage; }
25-
static set d(value) { this.#d_accessor_storage = value; }
24+
static get d() { return C1.#d_accessor_storage; }
25+
static set d(value) { C1.#d_accessor_storage = value; }
2626
}

tests/baselines/reference/autoAccessor10.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ class C3 {
5757
}
5858
class C4_1 {
5959
static #a3_accessor_storage = 1;
60-
static get a3() { return this.#a3_accessor_storage; }
61-
static set a3(value) { this.#a3_accessor_storage = value; }
60+
static get a3() { return C4_1.#a3_accessor_storage; }
61+
static set a3(value) { C4_1.#a3_accessor_storage = value; }
6262
}
6363
class C4_2 {
6464
static #a3_accessor_storage = 1;
65-
static get a3() { return this.#a3_accessor_storage; }
66-
static set a3(value) { this.#a3_accessor_storage = value; }
65+
static get a3() { return C4_2.#a3_accessor_storage; }
66+
static set a3(value) { C4_2.#a3_accessor_storage = value; }
6767
}

tests/baselines/reference/autoAccessor2(target=es2015).js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class C1 {
4141
__classPrivateFieldSet(this, _C1_instances, 4, "a", _C1_b_set);
4242
}
4343
}
44-
_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); };
44+
_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); };
4545
_C1_c_accessor_storage = { value: void 0 };
4646
_C1_d_accessor_storage = { value: 2 };
4747
(() => {

tests/baselines/reference/autoAccessor2(target=es2022).js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ class C1 {
2828
get #b() { return this.#b_accessor_storage; }
2929
set #b(value) { this.#b_accessor_storage = value; }
3030
static #c_accessor_storage;
31-
static get #c() { return this.#c_accessor_storage; }
32-
static set #c(value) { this.#c_accessor_storage = value; }
31+
static get #c() { return C1.#c_accessor_storage; }
32+
static set #c(value) { C1.#c_accessor_storage = value; }
3333
static #d_accessor_storage = 2;
34-
static get #d() { return this.#d_accessor_storage; }
35-
static set #d(value) { this.#d_accessor_storage = value; }
34+
static get #d() { return C1.#d_accessor_storage; }
35+
static set #d(value) { C1.#d_accessor_storage = value; }
3636
constructor() {
3737
this.#a = 3;
3838
this.#b = 4;

tests/baselines/reference/autoAccessor3(target=es2015).js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ class C1 {
3131
set "w"(value) { __classPrivateFieldSet(this, _C1__a_accessor_storage, value, "f"); }
3232
get "x"() { return __classPrivateFieldGet(this, _C1__b_accessor_storage, "f"); }
3333
set "x"(value) { __classPrivateFieldSet(this, _C1__b_accessor_storage, value, "f"); }
34-
static get "y"() { return __classPrivateFieldGet(this, _a, "f", _C1__c_accessor_storage); }
35-
static set "y"(value) { __classPrivateFieldSet(this, _a, value, "f", _C1__c_accessor_storage); }
36-
static get "z"() { return __classPrivateFieldGet(this, _a, "f", _C1__d_accessor_storage); }
37-
static set "z"(value) { __classPrivateFieldSet(this, _a, value, "f", _C1__d_accessor_storage); }
34+
static get "y"() { return __classPrivateFieldGet(_a, _a, "f", _C1__c_accessor_storage); }
35+
static set "y"(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1__c_accessor_storage); }
36+
static get "z"() { return __classPrivateFieldGet(_a, _a, "f", _C1__d_accessor_storage); }
37+
static set "z"(value) { __classPrivateFieldSet(_a, _a, value, "f", _C1__d_accessor_storage); }
3838
}
3939
_a = C1, _C1__a_accessor_storage = new WeakMap(), _C1__b_accessor_storage = new WeakMap();
4040
_C1__c_accessor_storage = { value: void 0 };

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy