From 92d7d1c9536f1b02ae50f2ace609f5c1e627ac16 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 8 Dec 2015 10:11:29 -0800 Subject: [PATCH 1/4] Disallow modifiers in object literal property assignment Fixes bug #5994 --- src/compiler/checker.ts | 5 ++++ src/compiler/parser.ts | 1 + .../modifiersInObjectLiterals.errors.txt | 24 +++++++++++++++++++ .../reference/modifiersInObjectLiterals.js | 19 +++++++++++++++ .../compiler/modifiersInObjectLiterals.ts | 8 +++++++ 5 files changed, 57 insertions(+) create mode 100644 tests/baselines/reference/modifiersInObjectLiterals.errors.txt create mode 100644 tests/baselines/reference/modifiersInObjectLiterals.js create mode 100644 tests/cases/compiler/modifiersInObjectLiterals.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 30d4818592b..9b694d9084e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15969,6 +15969,11 @@ namespace ts { return grammarErrorOnNode((prop).equalsToken, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } + // Modifiers cannot appear in property assignments + if (prop.modifiers && prop.modifiers.length > 0) { + grammarErrorOnNode(prop.modifiers[0], Diagnostics.Modifiers_cannot_appear_here); + } + // ECMA-262 11.1.5 Object Initialiser // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true // a.This production is contained in strict code and IsDataDescriptor(previous) is true and diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e4262458d30..ad108fe4115 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3981,6 +3981,7 @@ namespace ts { } else { const propertyAssignment = createNode(SyntaxKind.PropertyAssignment, fullStart); + propertyAssignment.modifiers = modifiers; propertyAssignment.name = propertyName; propertyAssignment.questionToken = questionToken; parseExpected(SyntaxKind.ColonToken); diff --git a/tests/baselines/reference/modifiersInObjectLiterals.errors.txt b/tests/baselines/reference/modifiersInObjectLiterals.errors.txt new file mode 100644 index 00000000000..c23a8c3c630 --- /dev/null +++ b/tests/baselines/reference/modifiersInObjectLiterals.errors.txt @@ -0,0 +1,24 @@ +tests/cases/compiler/modifiersInObjectLiterals.ts(2,2): error TS1184: Modifiers cannot appear here. +tests/cases/compiler/modifiersInObjectLiterals.ts(3,2): error TS1184: Modifiers cannot appear here. +tests/cases/compiler/modifiersInObjectLiterals.ts(4,2): error TS1184: Modifiers cannot appear here. +tests/cases/compiler/modifiersInObjectLiterals.ts(5,2): error TS1184: Modifiers cannot appear here. + + +==== tests/cases/compiler/modifiersInObjectLiterals.ts (4 errors) ==== + let data = { + public foo: 'hey', + ~~~~~~ +!!! error TS1184: Modifiers cannot appear here. + private bar: 'nay', + ~~~~~~~ +!!! error TS1184: Modifiers cannot appear here. + protected baz: 'oh my', + ~~~~~~~~~ +!!! error TS1184: Modifiers cannot appear here. + abstract noWay: 'yes' + ~~~~~~~~ +!!! error TS1184: Modifiers cannot appear here. + }; + + data.foo + data.bar + data.baz + data.noWay + \ No newline at end of file diff --git a/tests/baselines/reference/modifiersInObjectLiterals.js b/tests/baselines/reference/modifiersInObjectLiterals.js new file mode 100644 index 00000000000..0a59b13c21e --- /dev/null +++ b/tests/baselines/reference/modifiersInObjectLiterals.js @@ -0,0 +1,19 @@ +//// [modifiersInObjectLiterals.ts] +let data = { + public foo: 'hey', + private bar: 'nay', + protected baz: 'oh my', + abstract noWay: 'yes' +}; + +data.foo + data.bar + data.baz + data.noWay + + +//// [modifiersInObjectLiterals.js] +var data = { + foo: 'hey', + bar: 'nay', + baz: 'oh my', + noWay: 'yes' +}; +data.foo + data.bar + data.baz + data.noWay; diff --git a/tests/cases/compiler/modifiersInObjectLiterals.ts b/tests/cases/compiler/modifiersInObjectLiterals.ts new file mode 100644 index 00000000000..58fa64f82e9 --- /dev/null +++ b/tests/cases/compiler/modifiersInObjectLiterals.ts @@ -0,0 +1,8 @@ +let data = { + public foo: 'hey', + private bar: 'nay', + protected baz: 'oh my', + abstract noWay: 'yes' +}; + +data.foo + data.bar + data.baz + data.noWay From 964fbea9c110faa384edec3f45ea1d5caff8c1a4 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 8 Dec 2015 10:57:33 -0800 Subject: [PATCH 2/4] Fix up for 'async' --- src/compiler/checker.ts | 11 ++++++++--- .../modifiersInObjectLiterals.errors.txt | 16 ++++++++-------- .../objectLiteralMemberWithModifiers1.errors.txt | 5 ++++- .../objectLiteralMemberWithModifiers2.errors.txt | 5 ++++- .../reference/parserAccessors10.errors.txt | 5 ++++- 5 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9b694d9084e..6b25b47d26c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15970,9 +15970,14 @@ namespace ts { } // Modifiers cannot appear in property assignments - if (prop.modifiers && prop.modifiers.length > 0) { - grammarErrorOnNode(prop.modifiers[0], Diagnostics.Modifiers_cannot_appear_here); - } + forEach(prop.modifiers, mod => { + if (mod.kind !== SyntaxKind.AsyncKeyword) { + grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); + } + else if (prop.kind !== SyntaxKind.MethodDeclaration) { + grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); + } + }); // ECMA-262 11.1.5 Object Initialiser // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true diff --git a/tests/baselines/reference/modifiersInObjectLiterals.errors.txt b/tests/baselines/reference/modifiersInObjectLiterals.errors.txt index c23a8c3c630..25382123390 100644 --- a/tests/baselines/reference/modifiersInObjectLiterals.errors.txt +++ b/tests/baselines/reference/modifiersInObjectLiterals.errors.txt @@ -1,23 +1,23 @@ -tests/cases/compiler/modifiersInObjectLiterals.ts(2,2): error TS1184: Modifiers cannot appear here. -tests/cases/compiler/modifiersInObjectLiterals.ts(3,2): error TS1184: Modifiers cannot appear here. -tests/cases/compiler/modifiersInObjectLiterals.ts(4,2): error TS1184: Modifiers cannot appear here. -tests/cases/compiler/modifiersInObjectLiterals.ts(5,2): error TS1184: Modifiers cannot appear here. +tests/cases/compiler/modifiersInObjectLiterals.ts(2,2): error TS1042: 'public' modifier cannot be used here. +tests/cases/compiler/modifiersInObjectLiterals.ts(3,2): error TS1042: 'private' modifier cannot be used here. +tests/cases/compiler/modifiersInObjectLiterals.ts(4,2): error TS1042: 'protected' modifier cannot be used here. +tests/cases/compiler/modifiersInObjectLiterals.ts(5,2): error TS1042: 'abstract' modifier cannot be used here. ==== tests/cases/compiler/modifiersInObjectLiterals.ts (4 errors) ==== let data = { public foo: 'hey', ~~~~~~ -!!! error TS1184: Modifiers cannot appear here. +!!! error TS1042: 'public' modifier cannot be used here. private bar: 'nay', ~~~~~~~ -!!! error TS1184: Modifiers cannot appear here. +!!! error TS1042: 'private' modifier cannot be used here. protected baz: 'oh my', ~~~~~~~~~ -!!! error TS1184: Modifiers cannot appear here. +!!! error TS1042: 'protected' modifier cannot be used here. abstract noWay: 'yes' ~~~~~~~~ -!!! error TS1184: Modifiers cannot appear here. +!!! error TS1042: 'abstract' modifier cannot be used here. }; data.foo + data.bar + data.baz + data.noWay diff --git a/tests/baselines/reference/objectLiteralMemberWithModifiers1.errors.txt b/tests/baselines/reference/objectLiteralMemberWithModifiers1.errors.txt index 9e739194f54..182eab1b4cf 100644 --- a/tests/baselines/reference/objectLiteralMemberWithModifiers1.errors.txt +++ b/tests/baselines/reference/objectLiteralMemberWithModifiers1.errors.txt @@ -1,7 +1,10 @@ +tests/cases/compiler/objectLiteralMemberWithModifiers1.ts(1,11): error TS1042: 'public' modifier cannot be used here. tests/cases/compiler/objectLiteralMemberWithModifiers1.ts(1,11): error TS1184: Modifiers cannot appear here. -==== tests/cases/compiler/objectLiteralMemberWithModifiers1.ts (1 errors) ==== +==== tests/cases/compiler/objectLiteralMemberWithModifiers1.ts (2 errors) ==== var v = { public foo() { } } ~~~~~~ +!!! error TS1042: 'public' modifier cannot be used here. + ~~~~~~ !!! error TS1184: Modifiers cannot appear here. \ No newline at end of file diff --git a/tests/baselines/reference/objectLiteralMemberWithModifiers2.errors.txt b/tests/baselines/reference/objectLiteralMemberWithModifiers2.errors.txt index be2bea5e241..0d1822339b6 100644 --- a/tests/baselines/reference/objectLiteralMemberWithModifiers2.errors.txt +++ b/tests/baselines/reference/objectLiteralMemberWithModifiers2.errors.txt @@ -1,9 +1,12 @@ +tests/cases/compiler/objectLiteralMemberWithModifiers2.ts(1,11): error TS1042: 'public' modifier cannot be used here. tests/cases/compiler/objectLiteralMemberWithModifiers2.ts(1,22): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/compiler/objectLiteralMemberWithModifiers2.ts(1,22): error TS2378: A 'get' accessor must return a value. -==== tests/cases/compiler/objectLiteralMemberWithModifiers2.ts (2 errors) ==== +==== tests/cases/compiler/objectLiteralMemberWithModifiers2.ts (3 errors) ==== var v = { public get foo() { } } + ~~~~~~ +!!! error TS1042: 'public' modifier cannot be used here. ~~~ !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. ~~~ diff --git a/tests/baselines/reference/parserAccessors10.errors.txt b/tests/baselines/reference/parserAccessors10.errors.txt index d6a2b99eaca..b309b5e3947 100644 --- a/tests/baselines/reference/parserAccessors10.errors.txt +++ b/tests/baselines/reference/parserAccessors10.errors.txt @@ -1,9 +1,12 @@ +tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors10.ts(2,3): error TS1042: 'public' modifier cannot be used here. tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors10.ts(2,14): error TS2378: A 'get' accessor must return a value. -==== tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors10.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors10.ts (2 errors) ==== var v = { public get foo() { } + ~~~~~~ +!!! error TS1042: 'public' modifier cannot be used here. ~~~ !!! error TS2378: A 'get' accessor must return a value. }; \ No newline at end of file From 58427c4d18fe64b849f0ef73945ddbf2e2cb28b1 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 8 Dec 2015 16:59:52 -0800 Subject: [PATCH 3/4] Use logic for win --- src/compiler/checker.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6b25b47d26c..53900f90ffa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15971,10 +15971,7 @@ namespace ts { // Modifiers cannot appear in property assignments forEach(prop.modifiers, mod => { - if (mod.kind !== SyntaxKind.AsyncKeyword) { - grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); - } - else if (prop.kind !== SyntaxKind.MethodDeclaration) { + if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) { grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); } }); From d3c98155266cf5257600d3d2df8c31e5df1b66e2 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 8 Dec 2015 17:37:38 -0800 Subject: [PATCH 4/4] Improve comment --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 53900f90ffa..ceadceab20f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15969,7 +15969,7 @@ namespace ts { return grammarErrorOnNode((prop).equalsToken, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } - // Modifiers cannot appear in property assignments + // Modifiers are never allowed on properties except for 'async' on a method declaration forEach(prop.modifiers, mod => { if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) { grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod));