Use a separate field on a node to specify parser context flags.

This commit is contained in:
Cyrus Najmabadi 2014-11-24 18:47:49 -08:00
parent 99eb271e78
commit f0b7315a2c
2 changed files with 34 additions and 22 deletions

View File

@ -897,6 +897,23 @@ module ts {
// understand when these values should be changed versus when they should be inherited.
var strictModeContext = false;
var disallowInContext = false;
var contextFlags: number = 0;
function updateContextFlags() {
contextFlags =
(strictModeContext ? NodeFlags.ParsedInStrictModeContext : 0) |
(disallowInContext ? NodeFlags.ParsedInDisallowInContext : 0);
}
function setStrictModeContext(val: boolean) {
strictModeContext = val;
updateContextFlags();
}
function setDisallowInContext(val: boolean) {
disallowInContext = val;
updateContextFlags();
}
function allowInAnd<T>(func: () => T): T {
if (disallowInContext) {
@ -922,10 +939,6 @@ module ts {
return result;
}
function setDisallowInContext(val: boolean) {
disallowInContext = val;
}
function getLineStarts(): number[] {
return lineStarts || (lineStarts = computeLineStarts(sourceText));
}
@ -1108,12 +1121,8 @@ module ts {
function finishNode<T extends Node>(node: T): T {
node.end = scanner.getStartPos();
if (strictModeContext) {
node.flags |= NodeFlags.ParsedInStrictModeContext;
}
if (disallowInContext) {
node.flags |= NodeFlags.ParsedInDisallowInContext
if (contextFlags) {
node.parserContextFlags = contextFlags;
}
return node;
@ -1310,7 +1319,7 @@ module ts {
if (!strictModeContext && checkForStrictMode) {
if (isPrologueDirective(element)) {
if (isUseStrictPrologueDirective(element)) {
strictModeContext = true;
setStrictModeContext(true);
checkForStrictMode = false;
}
}
@ -1327,7 +1336,7 @@ module ts {
nextToken();
}
}
strictModeContext = savedStrictModeContext;
setStrictModeContext(savedStrictModeContext);
result.end = getNodeEnd();
parsingContext = saveParsingContext;
return result;
@ -3750,7 +3759,7 @@ module ts {
}
function checkBinaryExpression(node: BinaryExpression) {
if (node.flags & NodeFlags.ParsedInStrictModeContext) {
if (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext) {
if (isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operator)) {
if (isEvalOrArgumentsIdentifier(node.left)) {
// ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
@ -3902,7 +3911,7 @@ module ts {
var colonStart = skipTrivia(sourceText, node.variable.end);
return grammarErrorAtPos(colonStart, ":".length, Diagnostics.Catch_clause_parameter_cannot_have_a_type_annotation);
}
if (node.flags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(node.variable)) {
if (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(node.variable)) {
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
// Catch production is eval or arguments
return reportInvalidUseInStrictMode(node.variable);
@ -4022,7 +4031,7 @@ module ts {
}
function checkFunctionName(name: Node) {
if (name && name.flags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(name)) {
if (name && name.parserContextFlags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(name)) {
// It is a SyntaxError to use within strict mode code the identifiers eval or arguments as the
// Identifier of a FunctionLikeDeclaration or FunctionExpression or as a formal parameter name(13.1)
return reportInvalidUseInStrictMode(<Identifier>name);
@ -4143,7 +4152,7 @@ module ts {
var GetAccessor = 2;
var SetAccesor = 4;
var GetOrSetAccessor = GetAccessor | SetAccesor;
var inStrictMode = (node.flags & NodeFlags.ParsedInStrictModeContext) !== 0;
var inStrictMode = (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext) !== 0;
for (var i = 0, n = node.properties.length; i < n; i++) {
var prop = node.properties[i];
@ -4207,7 +4216,7 @@ module ts {
function checkNumericLiteral(node: LiteralExpression): boolean {
if (node.flags & NodeFlags.OctalLiteral) {
if (node.flags & NodeFlags.ParsedInStrictModeContext) {
if (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext) {
return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode);
}
else if (languageVersion >= ScriptTarget.ES5) {
@ -4351,7 +4360,7 @@ module ts {
// or if its FunctionBody is strict code(11.1.5).
// It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
// strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
if (node.flags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(node.name)) {
if (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(node.name)) {
return reportInvalidUseInStrictMode(node.name);
}
}
@ -4410,13 +4419,13 @@ module ts {
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator.
if (node.flags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(node.operand)) {
if (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(node.operand)) {
return reportInvalidUseInStrictMode(<Identifier>node.operand);
}
}
function checkPrefixOperator(node: UnaryExpression) {
if (node.flags & NodeFlags.ParsedInStrictModeContext) {
if (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext) {
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator
@ -4601,7 +4610,7 @@ module ts {
if (!inAmbientContext && !node.initializer && isConst(node)) {
return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized);
}
if (node.flags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(node.name)) {
if (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext && isEvalOrArgumentsIdentifier(node.name)) {
// It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
// and its Identifier is eval or arguments
return reportInvalidUseInStrictMode(node.name);
@ -4663,7 +4672,7 @@ module ts {
}
function checkWithStatement(node: WithStatement): boolean {
if (node.flags & NodeFlags.ParsedInStrictModeContext) {
if (node.parserContextFlags & NodeFlags.ParsedInStrictModeContext) {
// Strict mode code may not include a WithStatement. The occurrence of a WithStatement in such
// a context is an
return grammarErrorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_strict_mode);

View File

@ -285,6 +285,9 @@ module ts {
export interface Node extends TextRange {
kind: SyntaxKind;
flags: NodeFlags;
// Specific context the parser was in when this node was created. Normally undefined.
// Only set when the parser was in some interesting context (like async/yield).
parserContextFlags?: NodeFlags;
id?: number; // Unique id (used to look up NodeLinks)
parent?: Node; // Parent node (initialized by binding)
symbol?: Symbol; // Symbol declared by node (initialized by binding)