Decorators normative updates (#55276)

This commit is contained in:
Ron Buckton
2023-08-04 20:36:52 -04:00
committed by GitHub
parent b1c4dc475c
commit 8fc8c95830
35 changed files with 735 additions and 89 deletions
+3 -1
View File
@@ -32875,7 +32875,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)) {
+4 -4
View File
@@ -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")
+19 -7
View File
@@ -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<Node> {
// 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;
@@ -1846,10 +1858,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 isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ContainsConstructorReference;
+10
View File
@@ -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;
}