Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dc237b3

Browse filesBrowse files
Kingwlrbuckton
andauthored
Change static fields emits (microsoft#43114)
* use emit into iife * Update emit * Revert un-related changes * Allow super in static context * Allow this and super in static property declaration * Add more tests * Avoid errors * Accept baseline * Accept baseline * Add decorated classes test * Add errors * Avoid this in emitter * make lint happy * Add class expression tests * Add computed name test * Avoid super if target below es6 * Adjust function boundary * Add internal * Fix minor CR issues * accept baseline * Update behavior * Avoid spaces * Make lint happy * Avoid function boundary utils * Update baseline * Avoid errors * Accept baseline * Accept baseline * Accept baseline * Accept baseline * Use substitutions * Full coverage for super, this, merge static and private context * Fix use-before-def in static fields Co-authored-by: Ron Buckton <ron.buckton@microsoft.com>
1 parent 328e888 commit dc237b3
Copy full SHA for dc237b3

215 files changed

+9,184-781Lines changed: 9184 additions & 781 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/binder.ts‎

Copy file name to clipboardExpand all lines: src/compiler/binder.ts
+7-7Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ namespace ts {
669669
}
670670
// We create a return control flow graph for IIFEs and constructors. For constructors
671671
// we use the return control flow graph in strict property initialization checks.
672-
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
672+
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor || node.kind === SyntaxKind.ClassStaticBlockDeclaration || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
673673
currentExceptionTarget = undefined;
674674
currentBreakTarget = undefined;
675675
currentContinueTarget = undefined;
@@ -678,10 +678,10 @@ namespace ts {
678678
bindChildren(node);
679679
// Reset all reachability check related flags on node (for incremental scenarios)
680680
node.flags &= ~NodeFlags.ReachabilityAndEmitFlags;
681-
if (!(currentFlow.flags & FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((node as FunctionLikeDeclaration).body)) {
681+
if (!(currentFlow.flags & FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).body)) {
682682
node.flags |= NodeFlags.HasImplicitReturn;
683683
if (hasExplicitReturn) node.flags |= NodeFlags.HasExplicitReturn;
684-
(node as FunctionLikeDeclaration).endFlowNode = currentFlow;
684+
(node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).endFlowNode = currentFlow;
685685
}
686686
if (node.kind === SyntaxKind.SourceFile) {
687687
node.flags |= emitFlags;
@@ -691,8 +691,8 @@ namespace ts {
691691
if (currentReturnTarget) {
692692
addAntecedent(currentReturnTarget, currentFlow);
693693
currentFlow = finishFlowLabel(currentReturnTarget);
694-
if (node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) {
695-
(node as FunctionLikeDeclaration).returnFlowNode = currentFlow;
694+
if (node.kind === SyntaxKind.Constructor || node.kind === SyntaxKind.ClassStaticBlockDeclaration || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) {
695+
(node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).returnFlowNode = currentFlow;
696696
}
697697
}
698698
if (!isIIFE) {
@@ -1944,7 +1944,7 @@ namespace ts {
19441944
}
19451945

19461946
function declareClassMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
1947-
return hasSyntacticModifier(node, ModifierFlags.Static)
1947+
return isStatic(node)
19481948
? declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes)
19491949
: declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes);
19501950
}
@@ -2950,7 +2950,7 @@ namespace ts {
29502950
// this.foo assignment in a JavaScript class
29512951
// Bind this property to the containing class
29522952
const containingClass = thisContainer.parent;
2953-
const symbolTable = hasSyntacticModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports! : containingClass.symbol.members!;
2953+
const symbolTable = isStatic(thisContainer) ? containingClass.symbol.exports! : containingClass.symbol.members!;
29542954
if (hasDynamicName(node)) {
29552955
bindDynamicallyNamedThisPropertyAssignment(node, containingClass.symbol, symbolTable);
29562956
}
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+136-75Lines changed: 136 additions & 75 deletions
Large diffs are not rendered by default.
Collapse file

‎src/compiler/diagnosticMessages.json‎

Copy file name to clipboardExpand all lines: src/compiler/diagnosticMessages.json
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3344,6 +3344,14 @@
33443344
"category": "Error",
33453345
"code": 2815
33463346
},
3347+
"Cannot use 'this' in a static property initializer of a decorated class.": {
3348+
"category": "Error",
3349+
"code": 2816
3350+
},
3351+
"Property '{0}' has no initializer and is not definitely assigned in a class static block.": {
3352+
"category": "Error",
3353+
"code": 2817
3354+
},
33473355

33483356
"Import declaration '{0}' is using private name '{1}'.": {
33493357
"category": "Error",
Collapse file

‎src/compiler/factory/nodeFactory.ts‎

Copy file name to clipboardExpand all lines: src/compiler/factory/nodeFactory.ts
+52-2Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,11 @@ namespace ts {
496496
createArraySliceCall,
497497
createArrayConcatCall,
498498
createObjectDefinePropertyCall,
499+
createReflectGetCall,
500+
createReflectSetCall,
499501
createPropertyDescriptor,
500502
createCallBinding,
503+
createAssignmentTargetWrapper,
501504

502505
// Utilities
503506
inlineExpressions,
@@ -998,8 +1001,10 @@ namespace ts {
9981001
case SyntaxKind.UndefinedKeyword: // `undefined` is an Identifier in the expression case.
9991002
transformFlags = TransformFlags.ContainsTypeScript;
10001003
break;
1001-
case SyntaxKind.StaticKeyword:
10021004
case SyntaxKind.SuperKeyword:
1005+
transformFlags = TransformFlags.ContainsES2015 | TransformFlags.ContainsLexicalSuper;
1006+
break;
1007+
case SyntaxKind.StaticKeyword:
10031008
transformFlags = TransformFlags.ContainsES2015;
10041009
break;
10051010
case SyntaxKind.ThisKeyword:
@@ -2624,7 +2629,7 @@ namespace ts {
26242629
propagateChildFlags(node.equalsGreaterThanToken) |
26252630
TransformFlags.ContainsES2015;
26262631
if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
2627-
node.transformFlags |= TransformFlags.ContainsES2017;
2632+
node.transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsLexicalThis;
26282633
}
26292634
return node;
26302635
}
@@ -5435,6 +5440,15 @@ namespace ts {
54355440
}
54365441

54375442
function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) {
5443+
// Preserve the optionality of `object`.
5444+
if (isCallChain(object)) {
5445+
return createCallChain(
5446+
createPropertyAccessChain(object, /*questionDotToken*/ undefined, methodName),
5447+
/*questionDotToken*/ undefined,
5448+
/*typeArguments*/ undefined,
5449+
argumentsList
5450+
);
5451+
}
54385452
return createCallExpression(
54395453
createPropertyAccessExpression(object, methodName),
54405454
/*typeArguments*/ undefined,
@@ -5470,6 +5484,14 @@ namespace ts {
54705484
return createGlobalMethodCall("Object", "defineProperty", [target, asExpression(propertyName), attributes]);
54715485
}
54725486

5487+
function createReflectGetCall(target: Expression, propertyKey: Expression, receiver?: Expression): CallExpression {
5488+
return createGlobalMethodCall("Reflect", "get", receiver ? [target, propertyKey, receiver] : [target, propertyKey]);
5489+
}
5490+
5491+
function createReflectSetCall(target: Expression, propertyKey: Expression, value: Expression, receiver?: Expression): CallExpression {
5492+
return createGlobalMethodCall("Reflect", "set", receiver ? [target, propertyKey, value, receiver] : [target, propertyKey, value]);
5493+
}
5494+
54735495
function tryAddPropertyAssignment(properties: Push<PropertyAssignment>, propertyName: string, expression: Expression | undefined) {
54745496
if (expression) {
54755497
properties.push(createPropertyAssignment(propertyName, expression));
@@ -5645,6 +5667,34 @@ namespace ts {
56455667
return { target, thisArg };
56465668
}
56475669

5670+
function createAssignmentTargetWrapper(paramName: Identifier, expression: Expression): LeftHandSideExpression {
5671+
return createPropertyAccessExpression(
5672+
// Explicit parens required because of v8 regression (https://bugs.chromium.org/p/v8/issues/detail?id=9560)
5673+
createParenthesizedExpression(
5674+
createObjectLiteralExpression([
5675+
createSetAccessorDeclaration(
5676+
/*decorators*/ undefined,
5677+
/*modifiers*/ undefined,
5678+
"value",
5679+
[createParameterDeclaration(
5680+
/*decorators*/ undefined,
5681+
/*modifiers*/ undefined,
5682+
/*dotDotDotToken*/ undefined,
5683+
paramName,
5684+
/*questionToken*/ undefined,
5685+
/*type*/ undefined,
5686+
/*initializer*/ undefined
5687+
)],
5688+
createBlock([
5689+
createExpressionStatement(expression)
5690+
])
5691+
)
5692+
])
5693+
),
5694+
"value"
5695+
);
5696+
}
5697+
56485698
function inlineExpressions(expressions: readonly Expression[]) {
56495699
// Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call
56505700
// stack size exceeded" errors.
Collapse file

‎src/compiler/factory/utilities.ts‎

Copy file name to clipboardExpand all lines: src/compiler/factory/utilities.ts
+61Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,67 @@ namespace ts {
303303
}
304304
}
305305

306+
/**
307+
* Expand the read and increment/decrement operations a pre- or post-increment or pre- or post-decrement expression.
308+
*
309+
* ```ts
310+
* // input
311+
* <expression>++
312+
* // output (if result is not discarded)
313+
* var <temp>;
314+
* (<temp> = <expression>, <resultVariable> = <temp>++, <temp>)
315+
* // output (if result is discarded)
316+
* var <temp>;
317+
* (<temp> = <expression>, <temp>++, <temp>)
318+
*
319+
* // input
320+
* ++<expression>
321+
* // output (if result is not discarded)
322+
* var <temp>;
323+
* (<temp> = <expression>, <resultVariable> = ++<temp>)
324+
* // output (if result is discarded)
325+
* var <temp>;
326+
* (<temp> = <expression>, ++<temp>)
327+
* ```
328+
*
329+
* It is up to the caller to supply a temporary variable for `<resultVariable>` if one is needed.
330+
* The temporary variable `<temp>` is injected so that `++` and `--` work uniformly with `number` and `bigint`.
331+
* The result of the expression is always the final result of incrementing or decrementing the expression, so that it can be used for storage.
332+
*
333+
* @param factory {@link NodeFactory} used to create the expanded representation.
334+
* @param node The original prefix or postfix unary node.
335+
* @param expression The expression to use as the value to increment or decrement
336+
* @param resultVariable A temporary variable in which to store the result. Pass `undefined` if the result is discarded, or if the value of `<temp>` is the expected result.
337+
*/
338+
export function expandPreOrPostfixIncrementOrDecrementExpression(factory: NodeFactory, node: PrefixUnaryExpression | PostfixUnaryExpression, expression: Expression, recordTempVariable: (node: Identifier) => void, resultVariable: Identifier | undefined) {
339+
const operator = node.operator;
340+
Debug.assert(operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken, "Expected 'node' to be a pre- or post-increment or pre- or post-decrement expression");
341+
342+
const temp = factory.createTempVariable(recordTempVariable);
343+
expression = factory.createAssignment(temp, expression);
344+
setTextRange(expression, node.operand);
345+
346+
let operation: Expression = isPrefixUnaryExpression(node) ?
347+
factory.createPrefixUnaryExpression(operator, temp) :
348+
factory.createPostfixUnaryExpression(temp, operator);
349+
setTextRange(operation, node);
350+
351+
if (resultVariable) {
352+
operation = factory.createAssignment(resultVariable, operation);
353+
setTextRange(operation, node);
354+
}
355+
356+
expression = factory.createComma(expression, operation);
357+
setTextRange(expression, node);
358+
359+
if (isPostfixUnaryExpression(node)) {
360+
expression = factory.createComma(expression, temp);
361+
setTextRange(expression, node);
362+
}
363+
364+
return expression;
365+
}
366+
306367
/**
307368
* Gets whether an identifier should only be referred to by its internal name.
308369
*/

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.