Parse classDeclaration in strict mode code for ES6

This commit is contained in:
Yui T 2015-03-12 15:19:45 -07:00
parent 56839604da
commit 0672923323
6 changed files with 128 additions and 2 deletions

View File

@ -11891,7 +11891,11 @@ module ts {
var identifier = <Identifier>name;
if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
var nameText = declarationNameToString(identifier);
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
// Always report 'eval' and 'arguments' invalid usage in strict mode code regardless of parser diagnostics
var sourceFile = getSourceFileOfNode(identifier);
diagnostics.add(createDiagnosticForNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, nameText));
return true;
}
}
}

View File

@ -4372,6 +4372,12 @@ module ts {
function parsePropertyOrMethodDeclaration(fullStart: number, modifiers: ModifiersArray): ClassElement {
var asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
// From ES6 Specification, "implements", "interface", "let", "package", "private", "protected", "public", "static", and "yield" are reserved words within strict mode code
if (inStrictModeContext() && (token > SyntaxKind.LastReservedWord)) {
parseErrorAtCurrentToken(Diagnostics.Invalid_use_of_0_in_strict_mode, tokenToString(token));
}
var name = parsePropertyName();
// Note: this is not legal as per the grammar. But we allow it in the parser and
@ -4517,6 +4523,12 @@ module ts {
}
function parseClassDeclaration(fullStart: number, modifiers: ModifiersArray): ClassDeclaration {
// In ES6 specification, All parts of a ClassDeclaration or a ClassExpression are strict mode code
if (languageVersion >= ScriptTarget.ES6) {
var savedStrictModeContext = inStrictModeContext();
setStrictModeContext(true);
}
var node = <ClassDeclaration>createNode(SyntaxKind.ClassDeclaration, fullStart);
setModifiers(node, modifiers);
parseExpected(SyntaxKind.ClassKeyword);
@ -4537,7 +4549,15 @@ module ts {
else {
node.members = createMissingList<ClassElement>();
}
return finishNode(node);
var finishedNode = finishNode(node);
if (languageVersion >= ScriptTarget.ES6) {
setStrictModeContext(savedStrictModeContext);
return finishedNode;
}
else {
return finishedNode;
}
}
function parseHeritageClauses(isClassHeritageClause: boolean): NodeArray<HeritageClause> {

View File

@ -0,0 +1,31 @@
tests/cases/conformance/es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts(2,5): error TS1100: Invalid use of 'interface' in strict mode.
tests/cases/conformance/es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts(3,12): error TS1100: Invalid use of 'implements' in strict mode.
tests/cases/conformance/es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts(4,16): error TS1100: Invalid use of 'arguments' in strict mode.
tests/cases/conformance/es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts(5,17): error TS1100: Invalid use of 'eval' in strict mode.
tests/cases/conformance/es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts(6,9): error TS1100: Invalid use of 'arguments' in strict mode.
tests/cases/conformance/es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts(6,9): error TS2322: Type 'string' is not assignable to type 'IArguments'.
Property 'callee' is missing in type 'String'.
==== tests/cases/conformance/es6/classDeclaration/parseClassDeclarationInStrictModeByDefaultInES6.ts (6 errors) ====
class C {
interface = 10;
~~~~~~~~~
!!! error TS1100: Invalid use of 'interface' in strict mode.
public implements() { }
~~~~~~~~~~
!!! error TS1100: Invalid use of 'implements' in strict mode.
public foo(arguments: any) { }
~~~~~~~~~
!!! error TS1100: Invalid use of 'arguments' in strict mode.
private bar(eval:any) {
~~~~
!!! error TS1100: Invalid use of 'eval' in strict mode.
arguments = "hello";
~~~~~~~~~
!!! error TS1100: Invalid use of 'arguments' in strict mode.
~~~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'IArguments'.
!!! error TS2322: Property 'callee' is missing in type 'String'.
}
}

View File

@ -0,0 +1,23 @@
//// [parseClassDeclarationInStrictModeByDefaultInES6.ts]
class C {
interface = 10;
public implements() { }
public foo(arguments: any) { }
private bar(eval:any) {
arguments = "hello";
}
}
//// [parseClassDeclarationInStrictModeByDefaultInES6.js]
class C {
constructor() {
this.interface = 10;
}
implements() {
}
foo(arguments) {
}
bar(eval) {
arguments = "hello";
}
}

View File

@ -0,0 +1,9 @@
// @target: es6
class C {
interface = 10;
public implements() { }
public foo(arguments: any) { }
private bar(eval:any) {
arguments = "hello";
}
}

View File

@ -719,6 +719,16 @@ module m3 { }\
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, 0, "var v =".length, "class C");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); // As specified in ES6 specification, all parts of a ClassDeclaration or a ClassExpression are strict mode code.
});
it('Moving methods from object literal to class in strict mode', () => {
debugger;
var source = "\"use strict\"; var v = { public A() { } public B() { } public C() { } }"
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, 14, "var v =".length, "class C");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4);
});
@ -728,6 +738,15 @@ module m3 { }\
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, 0, "class".length, "interface");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); // As specified in ES6 specification, all parts of a ClassDeclaration or a ClassExpression are strict mode code.
});
it('Moving index signatures from class to interface in strict mode', () => {
var source = "\"use strict\"; class C { public [a: number]: string; public [a: number]: string; public [a: number]: string }"
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, 14, "class".length, "interface");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 18);
});
@ -737,6 +756,16 @@ module m3 { }\
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, 0, "interface".length, "class");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); // As specified in ES6 specification, all parts of a ClassDeclaration or a ClassExpression are strict mode code.
});
it('Moving index signatures from interface to class in strict mode', () => {
var source = "\"use strict\"; interface C { public [a: number]: string; public [a: number]: string; public [a: number]: string }"
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, 14, "interface".length, "class");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 18);
});
@ -755,6 +784,16 @@ module m3 { }\
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, 0, "var v =".length, "class C");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); // As specified in ES6 specification, all parts of a ClassDeclaration or a ClassExpression are strict mode code.
});
it('Moving accessors from object literal to class in strict mode', () => {
var source = "\"use strict\"; var v = { public get A() { } public get B() { } public get C() { } }"
var oldText = ScriptSnapshot.fromString(source);
var newTextAndChange = withChange(oldText, 14, "var v =".length, "class C");
compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4);
});