mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Fix emit for nested object rest in assignment pattern (#52922)
This commit is contained in:
parent
718e63b9c9
commit
8becdf2b40
@ -58,6 +58,7 @@ import {
|
||||
ConstructorDeclaration,
|
||||
ConstructorTypeNode,
|
||||
ConstructSignatureDeclaration,
|
||||
containsObjectRestOrSpread,
|
||||
ContinueStatement,
|
||||
createBaseNodeFactory,
|
||||
createNodeConverters,
|
||||
@ -114,7 +115,6 @@ import {
|
||||
getAllUnscopedEmitHelpers,
|
||||
getBuildInfo,
|
||||
getCommentRange,
|
||||
getElementsOfBindingOrAssignmentPattern,
|
||||
getEmitFlags,
|
||||
getIdentifierTypeArguments,
|
||||
getJSDocTypeAliasName,
|
||||
@ -124,7 +124,6 @@ import {
|
||||
getSourceMapRange,
|
||||
getSyntheticLeadingComments,
|
||||
getSyntheticTrailingComments,
|
||||
getTargetOfBindingOrAssignmentElement,
|
||||
getTextOfIdentifierOrLiteral,
|
||||
hasInvalidEscape,
|
||||
HasModifiers,
|
||||
@ -150,7 +149,6 @@ import {
|
||||
isArray,
|
||||
isArrayLiteralExpression,
|
||||
isArrowFunction,
|
||||
isAssignmentPattern,
|
||||
isBinaryExpression,
|
||||
isCallChain,
|
||||
isClassDeclaration,
|
||||
@ -3326,24 +3324,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
|
||||
}
|
||||
|
||||
function propagateAssignmentPatternFlags(node: AssignmentPattern): TransformFlags {
|
||||
if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) return TransformFlags.ContainsObjectRestOrSpread;
|
||||
if (node.transformFlags & TransformFlags.ContainsES2018) {
|
||||
// check for nested spread assignments, otherwise '{ x: { a, ...b } = foo } = c'
|
||||
// will not be correctly interpreted by the ES2018 transformer
|
||||
for (const element of getElementsOfBindingOrAssignmentPattern(node)) {
|
||||
const target = getTargetOfBindingOrAssignmentElement(element);
|
||||
if (target && isAssignmentPattern(target)) {
|
||||
if (target.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
return TransformFlags.ContainsObjectRestOrSpread;
|
||||
}
|
||||
if (target.transformFlags & TransformFlags.ContainsES2018) {
|
||||
const flags = propagateAssignmentPatternFlags(target);
|
||||
if (flags) return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TransformFlags.None;
|
||||
return containsObjectRestOrSpread(node) ? TransformFlags.ContainsObjectRestOrSpread : TransformFlags.None;
|
||||
}
|
||||
|
||||
// @api
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
AssertionLevel,
|
||||
AssignmentExpression,
|
||||
AssignmentOperatorOrHigher,
|
||||
AssignmentPattern,
|
||||
BinaryExpression,
|
||||
BinaryOperator,
|
||||
BinaryOperatorToken,
|
||||
@ -76,6 +77,7 @@ import {
|
||||
InternalEmitFlags,
|
||||
isAssignmentExpression,
|
||||
isAssignmentOperator,
|
||||
isAssignmentPattern,
|
||||
isBlock,
|
||||
isCommaListExpression,
|
||||
isComputedPropertyName,
|
||||
@ -174,6 +176,7 @@ import {
|
||||
TextRange,
|
||||
ThisTypeNode,
|
||||
Token,
|
||||
TransformFlags,
|
||||
TypeNode,
|
||||
} from "../_namespaces/ts";
|
||||
|
||||
@ -1742,3 +1745,31 @@ export function flattenCommaList(node: Expression) {
|
||||
flattenCommaListWorker(node, expressions);
|
||||
return expressions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk an AssignmentPattern to determine if it contains object rest (`...`) syntax. We cannot rely on
|
||||
* propagation of `TransformFlags.ContainsObjectRestOrSpread` since it isn't propagated by default in
|
||||
* ObjectLiteralExpression and ArrayLiteralExpression since we do not know whether they belong to an
|
||||
* AssignmentPattern at the time the nodes are parsed.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function containsObjectRestOrSpread(node: AssignmentPattern): boolean {
|
||||
if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) return true;
|
||||
if (node.transformFlags & TransformFlags.ContainsES2018) {
|
||||
// check for nested spread assignments, otherwise '{ x: { a, ...b } = foo } = c'
|
||||
// will not be correctly interpreted by the ES2018 transformer
|
||||
for (const element of getElementsOfBindingOrAssignmentPattern(node)) {
|
||||
const target = getTargetOfBindingOrAssignmentElement(element);
|
||||
if (target && isAssignmentPattern(target)) {
|
||||
if (target.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
return true;
|
||||
}
|
||||
if (target.transformFlags & TransformFlags.ContainsES2018) {
|
||||
if (containsObjectRestOrSpread(target)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import {
|
||||
concatenate,
|
||||
ConciseBody,
|
||||
ConstructorDeclaration,
|
||||
containsObjectRestOrSpread,
|
||||
createForOfBindingStatement,
|
||||
createSuperAccessVariableStatement,
|
||||
Debug,
|
||||
@ -577,7 +578,7 @@ export function transformES2018(context: TransformationContext): (x: SourceFile
|
||||
* expression of an `ExpressionStatement`).
|
||||
*/
|
||||
function visitBinaryExpression(node: BinaryExpression, expressionResultIsUnused: boolean): Expression {
|
||||
if (isDestructuringAssignment(node) && node.left.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
if (isDestructuringAssignment(node) && containsObjectRestOrSpread(node.left)) {
|
||||
return flattenDestructuringAssignment(
|
||||
node,
|
||||
visitor,
|
||||
@ -703,7 +704,8 @@ export function transformES2018(context: TransformationContext): (x: SourceFile
|
||||
*/
|
||||
function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined): VisitResult<Statement> {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.IterationStatementExcludes, HierarchyFacts.IterationStatementIncludes);
|
||||
if (node.initializer.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
if (node.initializer.transformFlags & TransformFlags.ContainsObjectRestOrSpread ||
|
||||
isAssignmentPattern(node.initializer) && containsObjectRestOrSpread(node.initializer)) {
|
||||
node = transformForOfStatementWithObjectRest(node);
|
||||
}
|
||||
const result = node.awaitModifier ?
|
||||
|
||||
27
tests/baselines/reference/nestedObjectRest.js
Normal file
27
tests/baselines/reference/nestedObjectRest.js
Normal file
@ -0,0 +1,27 @@
|
||||
//// [nestedObjectRest.ts]
|
||||
// https://github.com/microsoft/TypeScript/issues/43400
|
||||
var x, y;
|
||||
|
||||
[{ ...x }] = [{ abc: 1 }];
|
||||
for ([{ ...y }] of [[{ abc: 1 }]]) ;
|
||||
|
||||
//// [nestedObjectRest.js]
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||||
t[p[i]] = s[p[i]];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
var _a, _b;
|
||||
// https://github.com/microsoft/TypeScript/issues/43400
|
||||
var x, y;
|
||||
[_a] = [{ abc: 1 }], x = __rest(_a, []);
|
||||
for (let _c of [[{ abc: 1 }]]) {
|
||||
[_b] = _c, y = __rest(_b, []);
|
||||
;
|
||||
}
|
||||
14
tests/baselines/reference/nestedObjectRest.symbols
Normal file
14
tests/baselines/reference/nestedObjectRest.symbols
Normal file
@ -0,0 +1,14 @@
|
||||
=== tests/cases/compiler/nestedObjectRest.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/43400
|
||||
var x, y;
|
||||
>x : Symbol(x, Decl(nestedObjectRest.ts, 1, 3))
|
||||
>y : Symbol(y, Decl(nestedObjectRest.ts, 1, 6))
|
||||
|
||||
[{ ...x }] = [{ abc: 1 }];
|
||||
>x : Symbol(x, Decl(nestedObjectRest.ts, 1, 3))
|
||||
>abc : Symbol(abc, Decl(nestedObjectRest.ts, 3, 15))
|
||||
|
||||
for ([{ ...y }] of [[{ abc: 1 }]]) ;
|
||||
>y : Symbol(y, Decl(nestedObjectRest.ts, 1, 6))
|
||||
>abc : Symbol(abc, Decl(nestedObjectRest.ts, 4, 22))
|
||||
|
||||
26
tests/baselines/reference/nestedObjectRest.types
Normal file
26
tests/baselines/reference/nestedObjectRest.types
Normal file
@ -0,0 +1,26 @@
|
||||
=== tests/cases/compiler/nestedObjectRest.ts ===
|
||||
// https://github.com/microsoft/TypeScript/issues/43400
|
||||
var x, y;
|
||||
>x : any
|
||||
>y : any
|
||||
|
||||
[{ ...x }] = [{ abc: 1 }];
|
||||
>[{ ...x }] = [{ abc: 1 }] : [{ abc: number; }]
|
||||
>[{ ...x }] : [any]
|
||||
>{ ...x } : any
|
||||
>x : any
|
||||
>[{ abc: 1 }] : [{ abc: number; }]
|
||||
>{ abc: 1 } : { abc: number; }
|
||||
>abc : number
|
||||
>1 : 1
|
||||
|
||||
for ([{ ...y }] of [[{ abc: 1 }]]) ;
|
||||
>[{ ...y }] : [any]
|
||||
>{ ...y } : any
|
||||
>y : any
|
||||
>[[{ abc: 1 }]] : { abc: number; }[][]
|
||||
>[{ abc: 1 }] : { abc: number; }[]
|
||||
>{ abc: 1 } : { abc: number; }
|
||||
>abc : number
|
||||
>1 : 1
|
||||
|
||||
@ -72,9 +72,7 @@ class Test {
|
||||
(_a = this, { o: ({ set value(_e) { __classPrivateFieldSet(_a, _Test_instances, _e, "a", _Test_value_set); } }).value } = { o: { foo } }); //ok
|
||||
(_b = this, ({ set value(_e) { __classPrivateFieldSet(_b, _Test_instances, _e, "a", _Test_value_set); } }).value = __rest({ foo }, [])); //ok
|
||||
({ foo: __classPrivateFieldGet(this, _Test_instances, "a").foo } = { foo }); //error
|
||||
({
|
||||
foo: Object.assign({}, __classPrivateFieldGet(this, _Test_instances, "a").foo),
|
||||
} = { foo }); //error
|
||||
(__classPrivateFieldGet(this, _Test_instances, "a").foo = __rest({ foo }.foo, [])); //error
|
||||
let r = { o: __classPrivateFieldGet(this, _Test_instances, "a") }; //error
|
||||
_c = this, _d = this, [({ set value(_e) { __classPrivateFieldSet(_c, _Test_instances, _e, "a", _Test_valueOne_set); } }).value, ...({ set value(_e) { __classPrivateFieldSet(_d, _Test_instances, _e, "a", _Test_valueRest_set); } }).value] = [1, 2, 3];
|
||||
let arr = [
|
||||
|
||||
7
tests/cases/compiler/nestedObjectRest.ts
Normal file
7
tests/cases/compiler/nestedObjectRest.ts
Normal file
@ -0,0 +1,7 @@
|
||||
// @target: es2017
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/43400
|
||||
var x, y;
|
||||
|
||||
[{ ...x }] = [{ abc: 1 }];
|
||||
for ([{ ...y }] of [[{ abc: 1 }]]) ;
|
||||
Loading…
x
Reference in New Issue
Block a user