From a4aff9f9e5d19840a821a279e5ac0b8de0312e00 Mon Sep 17 00:00:00 2001 From: exoticknight Date: Thu, 3 Jun 2021 01:37:11 +0800 Subject: [PATCH 1/4] Fix 'arguments' check in class field initializer or static initialization block --- src/compiler/checker.ts | 5 ++ src/compiler/diagnosticMessages.json | 4 ++ ...izerOrStaticInitializationBlock.errors.txt | 44 ++++++++++++ ...dInitializerOrStaticInitializationBlock.js | 72 +++++++++++++++++++ ...ializerOrStaticInitializationBlock.symbols | 62 ++++++++++++++++ ...itializerOrStaticInitializationBlock.types | 72 +++++++++++++++++++ ...dInitializerOrStaticInitializationBlock.ts | 29 ++++++++ 7 files changed, 288 insertions(+) create mode 100644 tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.errors.txt create mode 100644 tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.js create mode 100644 tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.symbols create mode 100644 tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.types create mode 100644 tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 814c42af9b183..1306207ffdc23 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24223,6 +24223,11 @@ namespace ts { } } + const firstFunctionLikeContainerOrClassLikeContainer = findAncestor(node.parent, node => isClassLike(node) || isFunctionLike(node))!; + if (firstFunctionLikeContainerOrClassLikeContainer.kind === SyntaxKind.ClassExpression || firstFunctionLikeContainerOrClassLikeContainer.kind === SyntaxKind.ClassDeclaration) { + error(node, Diagnostics.arguments_is_not_allowed_in_class_field_initializer_or_static_initialization_block); + } + getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments; return getTypeOfSymbol(symbol); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 53de48b009186..959ea091b657c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3336,6 +3336,10 @@ "category": "Error", "code": 2812 }, + "'arguments' is not allowed in class field initializer or static initialization block.": { + "category": "Error", + "code": 2813 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.errors.txt b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.errors.txt new file mode 100644 index 0000000000000..a632ad70ea0e1 --- /dev/null +++ b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.errors.txt @@ -0,0 +1,44 @@ +tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(3,10): error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. +tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(9,10): error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. +tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(15,15): error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. +tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(21,15): error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. + + +==== tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts (4 errors) ==== + function A() { + return class T { + a = arguments + ~~~~~~~~~ +!!! error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. + } + } + + function A1() { + return new class T { + a = arguments + ~~~~~~~~~ +!!! error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. + } + } + + function B() { + return class T { + a = { b: arguments } + ~~~~~~~~~ +!!! error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. + } + } + + function B1() { + return new class T { + a = { b: arguments } + ~~~~~~~~~ +!!! error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. + } + } + + function C() { + return class T { + a = function () { arguments } + } + } \ No newline at end of file diff --git a/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.js b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.js new file mode 100644 index 0000000000000..a162ab0cb8430 --- /dev/null +++ b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.js @@ -0,0 +1,72 @@ +//// [argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts] +function A() { + return class T { + a = arguments + } +} + +function A1() { + return new class T { + a = arguments + } +} + +function B() { + return class T { + a = { b: arguments } + } +} + +function B1() { + return new class T { + a = { b: arguments } + } +} + +function C() { + return class T { + a = function () { arguments } + } +} + +//// [argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.js] +function A() { + return /** @class */ (function () { + function T() { + this.a = arguments; + } + return T; + }()); +} +function A1() { + return new /** @class */ (function () { + function T() { + this.a = arguments; + } + return T; + }()); +} +function B() { + return /** @class */ (function () { + function T() { + this.a = { b: arguments }; + } + return T; + }()); +} +function B1() { + return new /** @class */ (function () { + function T() { + this.a = { b: arguments }; + } + return T; + }()); +} +function C() { + return /** @class */ (function () { + function T() { + this.a = function () { arguments; }; + } + return T; + }()); +} diff --git a/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.symbols b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.symbols new file mode 100644 index 0000000000000..b087127c45773 --- /dev/null +++ b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.symbols @@ -0,0 +1,62 @@ +=== tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts === +function A() { +>A : Symbol(A, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 0, 0)) + + return class T { +>T : Symbol(T, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 1, 8)) + + a = arguments +>a : Symbol(T.a, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 1, 18)) +>arguments : Symbol(arguments) + } +} + +function A1() { +>A1 : Symbol(A1, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 4, 1)) + + return new class T { +>T : Symbol(T, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 7, 12)) + + a = arguments +>a : Symbol(T.a, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 7, 22)) +>arguments : Symbol(arguments) + } +} + +function B() { +>B : Symbol(B, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 10, 1)) + + return class T { +>T : Symbol(T, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 13, 8)) + + a = { b: arguments } +>a : Symbol(T.a, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 13, 18)) +>b : Symbol(b, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 14, 10)) +>arguments : Symbol(arguments) + } +} + +function B1() { +>B1 : Symbol(B1, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 16, 1)) + + return new class T { +>T : Symbol(T, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 19, 12)) + + a = { b: arguments } +>a : Symbol(T.a, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 19, 22)) +>b : Symbol(b, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 20, 10)) +>arguments : Symbol(arguments) + } +} + +function C() { +>C : Symbol(C, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 22, 1)) + + return class T { +>T : Symbol(T, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 25, 8)) + + a = function () { arguments } +>a : Symbol(T.a, Decl(argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts, 25, 18)) +>arguments : Symbol(arguments) + } +} diff --git a/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.types b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.types new file mode 100644 index 0000000000000..fda324ddb5cb6 --- /dev/null +++ b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.types @@ -0,0 +1,72 @@ +=== tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts === +function A() { +>A : () => typeof T + + return class T { +>class T { a = arguments } : typeof T +>T : typeof T + + a = arguments +>a : IArguments +>arguments : IArguments + } +} + +function A1() { +>A1 : () => T + + return new class T { +>new class T { a = arguments } : T +>class T { a = arguments } : typeof T +>T : typeof T + + a = arguments +>a : IArguments +>arguments : IArguments + } +} + +function B() { +>B : () => typeof T + + return class T { +>class T { a = { b: arguments } } : typeof T +>T : typeof T + + a = { b: arguments } +>a : { b: IArguments; } +>{ b: arguments } : { b: IArguments; } +>b : IArguments +>arguments : IArguments + } +} + +function B1() { +>B1 : () => T + + return new class T { +>new class T { a = { b: arguments } } : T +>class T { a = { b: arguments } } : typeof T +>T : typeof T + + a = { b: arguments } +>a : { b: IArguments; } +>{ b: arguments } : { b: IArguments; } +>b : IArguments +>arguments : IArguments + } +} + +function C() { +>C : () => typeof T + + return class T { +>class T { a = function () { arguments } } : typeof T +>T : typeof T + + a = function () { arguments } +>a : () => void +>function () { arguments } : () => void +>arguments : IArguments + } +} diff --git a/tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts b/tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts new file mode 100644 index 0000000000000..50e762e03fb9a --- /dev/null +++ b/tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts @@ -0,0 +1,29 @@ +function A() { + return class T { + a = arguments + } +} + +function A1() { + return new class T { + a = arguments + } +} + +function B() { + return class T { + a = { b: arguments } + } +} + +function B1() { + return new class T { + a = { b: arguments } + } +} + +function C() { + return class T { + a = function () { arguments } + } +} \ No newline at end of file From abed90c977064914bf84335a9a5d56b9d49d673b Mon Sep 17 00:00:00 2001 From: exoticknight Date: Thu, 3 Jun 2021 13:03:46 +0800 Subject: [PATCH 2/4] return errorType --- src/compiler/checker.ts | 1 + ...itializerOrStaticInitializationBlock.types | 24 +++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1306207ffdc23..6b6ebbb27f6da 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24226,6 +24226,7 @@ namespace ts { const firstFunctionLikeContainerOrClassLikeContainer = findAncestor(node.parent, node => isClassLike(node) || isFunctionLike(node))!; if (firstFunctionLikeContainerOrClassLikeContainer.kind === SyntaxKind.ClassExpression || firstFunctionLikeContainerOrClassLikeContainer.kind === SyntaxKind.ClassDeclaration) { error(node, Diagnostics.arguments_is_not_allowed_in_class_field_initializer_or_static_initialization_block); + return errorType; } getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments; diff --git a/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.types b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.types index fda324ddb5cb6..d68759ae2f99d 100644 --- a/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.types +++ b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.types @@ -7,8 +7,8 @@ function A() { >T : typeof T a = arguments ->a : IArguments ->arguments : IArguments +>a : any +>arguments : any } } @@ -21,8 +21,8 @@ function A1() { >T : typeof T a = arguments ->a : IArguments ->arguments : IArguments +>a : any +>arguments : any } } @@ -34,10 +34,10 @@ function B() { >T : typeof T a = { b: arguments } ->a : { b: IArguments; } ->{ b: arguments } : { b: IArguments; } ->b : IArguments ->arguments : IArguments +>a : { b: any; } +>{ b: arguments } : { b: any; } +>b : any +>arguments : any } } @@ -50,10 +50,10 @@ function B1() { >T : typeof T a = { b: arguments } ->a : { b: IArguments; } ->{ b: arguments } : { b: IArguments; } ->b : IArguments ->arguments : IArguments +>a : { b: any; } +>{ b: arguments } : { b: any; } +>b : any +>arguments : any } } From e98c4b7574689f8a4186573f59b795a8d4ef15cd Mon Sep 17 00:00:00 2001 From: exoticknight Date: Thu, 3 Jun 2021 13:06:10 +0800 Subject: [PATCH 3/4] Merge branch 'master' of https://github.com/exoticknight/TypeScript From 0d93e96f42703be4f03c0acf213b737efa5ba3e4 Mon Sep 17 00:00:00 2001 From: exoticknight Date: Sat, 5 Jun 2021 03:23:55 +0800 Subject: [PATCH 4/4] use isInPropertyInitializer fix Diagnostics message --- src/compiler/checker.ts | 5 +++++ src/compiler/diagnosticMessages.json | 8 +++++--- ...ializerOrStaticInitializationBlock.errors.txt | 16 ++++++++-------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 38c193758be7a..4df956538ce94 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24214,6 +24214,11 @@ namespace ts { // To avoid that we will give an error to users if they use arguments objects in arrow function so that they // can explicitly bound arguments objects if (symbol === argumentsSymbol) { + if (isInPropertyInitializer(node)) { + error(node, Diagnostics.arguments_cannot_be_referenced_in_property_initializers); + return errorType; + } + const container = getContainingFunction(node)!; if (languageVersion < ScriptTarget.ES2015) { if (container.kind === SyntaxKind.ArrowFunction) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index d2ddbc8b0a4ec..94082a4ed4667 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3344,6 +3344,10 @@ "category": "Error", "code": 2814 }, + "'arguments' cannot be referenced in property initializers.": { + "category": "Error", + "code": 2815 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", @@ -4919,7 +4923,6 @@ "code": 6257 }, - "Projects to reference": { "category": "Message", "code": 6300 @@ -5185,7 +5188,6 @@ "code": 6506 }, - "Include 'undefined' in index signature results": { "category": "Message", "code": 6800 @@ -5202,7 +5204,7 @@ "category": "Message", "code": 6803 }, - + "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.errors.txt b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.errors.txt index a632ad70ea0e1..3cd9988e78de3 100644 --- a/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.errors.txt +++ b/tests/baselines/reference/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(3,10): error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. -tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(9,10): error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. -tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(15,15): error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. -tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(21,15): error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. +tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(3,10): error TS2815: 'arguments' cannot be referenced in property initializers. +tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(9,10): error TS2815: 'arguments' cannot be referenced in property initializers. +tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(15,15): error TS2815: 'arguments' cannot be referenced in property initializers. +tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts(21,15): error TS2815: 'arguments' cannot be referenced in property initializers. ==== tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationBlock.ts (4 errors) ==== @@ -9,7 +9,7 @@ tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationB return class T { a = arguments ~~~~~~~~~ -!!! error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. +!!! error TS2815: 'arguments' cannot be referenced in property initializers. } } @@ -17,7 +17,7 @@ tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationB return new class T { a = arguments ~~~~~~~~~ -!!! error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. +!!! error TS2815: 'arguments' cannot be referenced in property initializers. } } @@ -25,7 +25,7 @@ tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationB return class T { a = { b: arguments } ~~~~~~~~~ -!!! error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. +!!! error TS2815: 'arguments' cannot be referenced in property initializers. } } @@ -33,7 +33,7 @@ tests/cases/compiler/argumentsUsedInClassFieldInitializerOrStaticInitializationB return new class T { a = { b: arguments } ~~~~~~~~~ -!!! error TS2813: 'arguments' is not allowed in class field initializer or static initialization block. +!!! error TS2815: 'arguments' cannot be referenced in property initializers. } }