while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
if (shouldCheckForUseStrict) {
if (shouldCheckForUseStrict) {
if (directive) {
if (directive) {
// "use strict" must be the exact literal without escape sequences or line continuation.
// "use strict" must be the exact literal without escape sequences or line continuation.
if (directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
if (directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
setStrictMode();
setStrictMode();
shouldCheckForUseStrict = false; // We saw "use strict", there is no need to keep checking for it.
shouldCheckForUseStrict = false; // We saw "use strict", there is no need to keep checking for it.
if (!isValidStrictMode()) {
if (!isValidStrictMode()) {
if (m_parserState.lastFunctionName) {
if (m_parserState.lastFunctionName) {
if (m_vm->propertyNames->arguments == *m_parserState.lastFunctionName)
if (m_vm->propertyNames->arguments == *m_parserState.lastFunctionName)
semanticFail("Cannot name a function 'arguments' in strict mode");
semanticFail("Cannot name a function 'arguments' in strict mode");
if (m_vm->propertyNames->eval == *m_parserState.lastFunctionName)
if (m_vm->propertyNames->eval == *m_parserState.lastFunctionName)
semanticFail("Cannot name a function 'eval' in strict mode");
semanticFail("Cannot name a function 'eval' in strict mode");
}
}
if (hasDeclaredVariable(m_vm->propertyNames->arguments))
if (hasDeclaredVariable(m_vm->propertyNames->arguments))
semanticFail("Cannot declare a variable named 'arguments' in strict mode");
semanticFail("Cannot declare a variable named 'arguments' in strict mode");
if (hasDeclaredVariable(m_vm->propertyNames->eval))
if (hasDeclaredVariable(m_vm->propertyNames->eval))
semanticFail("Cannot declare a variable named 'eval' in strict mode");
semanticFail("Cannot declare a variable named 'eval' in strict mode");
semanticFailIfTrue(currentScope()->hasNonSimpleParameterList(), "'use strict' directive not allowed inside a function with a non-simple parameter list");
semanticFailIfTrue(currentScope()->hasNonSimpleParameterList(), "'use strict' directive not allowed inside a function with a non-simple parameter list");
semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
}
}
// Since strict mode is changed, restoring lexer state by calling next() may cause errors.
// Since strict mode is changed, restoring lexer state by calling next() may cause errors.
restoreSavePoint(savePoint);
restoreSavePoint(savePoint);
propagateError();
propagateError();
continue;
continue;
}
}
// We saw a directive, but it wasn't "use strict". We reset our state to
// We saw a directive, but it wasn't "use strict". We reset our state to
// see if the next statement we parse is also a directive.
// see if the next statement we parse is also a directive.
directive = nullptr;
directive = nullptr;
} else {
} else {
// We saw a statement that wasn't in the form of a directive. The spec says that "use strict"
// We saw a statement that wasn't in the form of a directive. The spec says that "use strict"
// is only allowed as the first statement, or after a sequence of directives before it, but
// is only allowed as the first statement, or after a sequence of directives before it, but