From b6744812a02110a8cff461a54e6a8414295fe970 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 22 Oct 2019 11:00:16 -0700 Subject: [PATCH] Treat any mix of element/prop access as declaration in JS Fixes #34642 but, notably, doesn't actually make the assignment into a working declaration. It just fixes the crash. --- src/compiler/utilities.ts | 20 +++++++++++-------- ...pertyElementAccessAssignmentDeclaration.js | 10 ++++++++++ ...ElementAccessAssignmentDeclaration.symbols | 8 ++++++++ ...tyElementAccessAssignmentDeclaration.types | 17 ++++++++++++++++ ...pertyElementAccessAssignmentDeclaration.ts | 3 +++ 5 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.js create mode 100644 tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.symbols create mode 100644 tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.types create mode 100644 tests/cases/conformance/salsa/mixedPropertyElementAccessAssignmentDeclaration.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 12c83b71697b1..e86f79b360ab9 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2061,26 +2061,30 @@ namespace ts { isBindableStaticNameExpression(expr.arguments[0], /*excludeThisKeyword*/ true); } - export function isBindableStaticElementAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticElementAccessExpression { - return isLiteralLikeElementAccess(node) - && ((!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword) || - isEntityNameExpression(node.expression) || - isBindableStaticElementAccessExpression(node.expression, /*excludeThisKeyword*/ true)); - } - + /** x.y OR x[0] */ export function isLiteralLikeAccess(node: Node): node is LiteralLikeElementAccessExpression | PropertyAccessExpression { return isPropertyAccessExpression(node) || isLiteralLikeElementAccess(node); } + /** x[0] OR x['a'] OR x[Symbol.y] */ export function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAccessExpression { return isElementAccessExpression(node) && ( isStringOrNumericLiteralLike(node.argumentExpression) || isWellKnownSymbolSyntactically(node.argumentExpression)); } + /** Any series of property and element accesses. */ export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticAccessExpression { return isPropertyAccessExpression(node) && (!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword || isBindableStaticNameExpression(node.expression, /*excludeThisKeyword*/ true)) - || isBindableStaticElementAccessExpression(node, excludeThisKeyword); + || isBindableStaticElementAccessExpression(node, excludeThisKeyword); + } + + /** Any series of property and element accesses, ending in a literal element access */ + export function isBindableStaticElementAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticElementAccessExpression { + return isLiteralLikeElementAccess(node) + && ((!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword) || + isEntityNameExpression(node.expression) || + isBindableStaticAccessExpression(node.expression, /*excludeThisKeyword*/ true)); } export function isBindableStaticNameExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticNameExpression { diff --git a/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.js b/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.js new file mode 100644 index 0000000000000..ee5b3d9e89596 --- /dev/null +++ b/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.js @@ -0,0 +1,10 @@ +//// [mixedPropertyElementAccessAssignmentDeclaration.ts] +// Should not crash: #34642 +var arr = []; +arr[0].prop[2] = {}; + + +//// [mixedPropertyElementAccessAssignmentDeclaration.js] +// Should not crash: #34642 +var arr = []; +arr[0].prop[2] = {}; diff --git a/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.symbols b/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.symbols new file mode 100644 index 0000000000000..d414e979f178b --- /dev/null +++ b/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/salsa/mixedPropertyElementAccessAssignmentDeclaration.ts === +// Should not crash: #34642 +var arr = []; +>arr : Symbol(arr, Decl(mixedPropertyElementAccessAssignmentDeclaration.ts, 1, 3)) + +arr[0].prop[2] = {}; +>arr : Symbol(arr, Decl(mixedPropertyElementAccessAssignmentDeclaration.ts, 1, 3)) + diff --git a/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.types b/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.types new file mode 100644 index 0000000000000..18d20dfd936bf --- /dev/null +++ b/tests/baselines/reference/mixedPropertyElementAccessAssignmentDeclaration.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/salsa/mixedPropertyElementAccessAssignmentDeclaration.ts === +// Should not crash: #34642 +var arr = []; +>arr : any[] +>[] : undefined[] + +arr[0].prop[2] = {}; +>arr[0].prop[2] = {} : {} +>arr[0].prop[2] : any +>arr[0].prop : any +>arr[0] : any +>arr : any[] +>0 : 0 +>prop : any +>2 : 2 +>{} : {} + diff --git a/tests/cases/conformance/salsa/mixedPropertyElementAccessAssignmentDeclaration.ts b/tests/cases/conformance/salsa/mixedPropertyElementAccessAssignmentDeclaration.ts new file mode 100644 index 0000000000000..8dd13383df00c --- /dev/null +++ b/tests/cases/conformance/salsa/mixedPropertyElementAccessAssignmentDeclaration.ts @@ -0,0 +1,3 @@ +// Should not crash: #34642 +var arr = []; +arr[0].prop[2] = {};