Fix handling of aruments in the emitter

Two problems are fixed:

* `isArgumentsLocalBinding` did only `PropertyAccessExpression`, now
  it's also doing `PropertyAssignment` (doesn't affect other files,
  since it's only used in the emitter).

* `visitShorthandPropertyAssignment` should call `visitIdentifier` on
  the synthesized id.  (For completion it might be better to make it
  visit the the original?)

Fixes #38594.
This commit is contained in:
Eli Barzilay 2020-06-01 11:53:38 -04:00
parent b63ea4b6df
commit f447838f95
6 changed files with 130 additions and 16 deletions

View File

@ -36095,15 +36095,16 @@ namespace ts {
// Emitter support
function isArgumentsLocalBinding(nodeIn: Identifier): boolean {
if (!isGeneratedIdentifier(nodeIn)) {
const node = getParseTreeNode(nodeIn, isIdentifier);
if (node) {
const isPropertyName = node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node;
return !isPropertyName && getReferencedValueSymbol(node) === argumentsSymbol;
}
}
return false;
// Note: does not handle isShorthandPropertyAssignment (and probably a few more)
if (isGeneratedIdentifier(nodeIn)) return false;
const node = getParseTreeNode(nodeIn, isIdentifier);
if (!node) return false;
const parent = node.parent;
if (!parent) return false;
const isPropertyName = ((isPropertyAccessExpression(parent)
|| isPropertyAssignment(parent))
&& parent.name === node);
return !isPropertyName && getReferencedValueSymbol(node) === argumentsSymbol;
}
function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {

View File

@ -583,13 +583,10 @@ namespace ts {
if (!convertedLoopState) {
return node;
}
if (isGeneratedIdentifier(node)) {
return node;
if (resolver.isArgumentsLocalBinding(node)) {
return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = createUniqueName("arguments"));
}
if (node.escapedText !== "arguments" || !resolver.isArgumentsLocalBinding(node)) {
return node;
}
return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = createUniqueName("arguments"));
return node;
}
function visitBreakOrContinueStatement(node: BreakOrContinueStatement): Statement {
@ -3517,7 +3514,7 @@ namespace ts {
return setTextRange(
createPropertyAssignment(
node.name,
getSynthesizedClone(node.name)
visitIdentifier(getSynthesizedClone(node.name))
),
/*location*/ node
);

View File

@ -0,0 +1,29 @@
//// [argumentsAsPropertyName2.ts]
// target: es5
function foo() {
for (let x = 0; x < 1; ++x) {
let i : number;
[].forEach(function () { i });
({ arguments: 0 });
({ arguments });
({ arguments: arguments });
}
}
//// [argumentsAsPropertyName2.js]
// target: es5
function foo() {
var _loop_1 = function (x) {
var i;
[].forEach(function () { i; });
({ arguments: 0 });
({ arguments: arguments_1 });
({ arguments: arguments_1 });
};
var arguments_1 = arguments;
for (var x = 0; x < 1; ++x) {
_loop_1(x);
}
}

View File

@ -0,0 +1,31 @@
=== tests/cases/compiler/argumentsAsPropertyName2.ts ===
// target: es5
function foo() {
>foo : Symbol(foo, Decl(argumentsAsPropertyName2.ts, 0, 0))
for (let x = 0; x < 1; ++x) {
>x : Symbol(x, Decl(argumentsAsPropertyName2.ts, 3, 12))
>x : Symbol(x, Decl(argumentsAsPropertyName2.ts, 3, 12))
>x : Symbol(x, Decl(argumentsAsPropertyName2.ts, 3, 12))
let i : number;
>i : Symbol(i, Decl(argumentsAsPropertyName2.ts, 4, 11))
[].forEach(function () { i });
>[].forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
>i : Symbol(i, Decl(argumentsAsPropertyName2.ts, 4, 11))
({ arguments: 0 });
>arguments : Symbol(arguments, Decl(argumentsAsPropertyName2.ts, 6, 10))
({ arguments });
>arguments : Symbol(arguments, Decl(argumentsAsPropertyName2.ts, 7, 10))
({ arguments: arguments });
>arguments : Symbol(arguments, Decl(argumentsAsPropertyName2.ts, 8, 10))
>arguments : Symbol(arguments)
}
}

View File

@ -0,0 +1,45 @@
=== tests/cases/compiler/argumentsAsPropertyName2.ts ===
// target: es5
function foo() {
>foo : () => void
for (let x = 0; x < 1; ++x) {
>x : number
>0 : 0
>x < 1 : boolean
>x : number
>1 : 1
>++x : number
>x : number
let i : number;
>i : number
[].forEach(function () { i });
>[].forEach(function () { i }) : void
>[].forEach : (callbackfn: (value: any, index: number, array: any[]) => void, thisArg?: any) => void
>[] : undefined[]
>forEach : (callbackfn: (value: any, index: number, array: any[]) => void, thisArg?: any) => void
>function () { i } : () => void
>i : number
({ arguments: 0 });
>({ arguments: 0 }) : { arguments: number; }
>{ arguments: 0 } : { arguments: number; }
>arguments : number
>0 : 0
({ arguments });
>({ arguments }) : { arguments: IArguments; }
>{ arguments } : { arguments: IArguments; }
>arguments : IArguments
({ arguments: arguments });
>({ arguments: arguments }) : { arguments: IArguments; }
>{ arguments: arguments } : { arguments: IArguments; }
>arguments : IArguments
>arguments : IArguments
}
}

View File

@ -0,0 +1,11 @@
// target: es5
function foo() {
for (let x = 0; x < 1; ++x) {
let i : number;
[].forEach(function () { i });
({ arguments: 0 });
({ arguments });
({ arguments: arguments });
}
}