| Index: src/parser.cc
|
| ===================================================================
|
| --- src/parser.cc (revision 7031)
|
| +++ src/parser.cc (working copy)
|
| @@ -1113,8 +1113,21 @@
|
| }
|
|
|
| Scanner::Location token_loc = scanner().peek_location();
|
| - Statement* stat = ParseStatement(NULL, CHECK_OK);
|
|
|
| + Statement* stat;
|
| + if (peek() == Token::FUNCTION) {
|
| + // FunctionDeclaration is only allowed in the context of SourceElements
|
| + // (Ecma 262 5th Edition, clause 14):
|
| + // SourceElement:
|
| + // Statement
|
| + // FunctionDeclaration
|
| + // Common language extension is to allow function declaration in place
|
| + // of any statement. This language extension is disabled in strict mode.
|
| + stat = ParseFunctionDeclaration(CHECK_OK);
|
| + } else {
|
| + stat = ParseStatement(NULL, CHECK_OK);
|
| + }
|
| +
|
| if (stat == NULL || stat->IsEmpty()) {
|
| directive_prologue = false; // End of directive prologue.
|
| continue;
|
| @@ -1270,8 +1283,17 @@
|
| return result;
|
| }
|
|
|
| - case Token::FUNCTION:
|
| + case Token::FUNCTION: {
|
| + // In strict mode, FunctionDeclaration is only allowed in the context
|
| + // of SourceElements.
|
| + if (temp_scope_->StrictMode()) {
|
| + ReportMessageAt(scanner().peek_location(), "strict_function",
|
| + Vector<const char*>::empty());
|
| + *ok = false;
|
| + return NULL;
|
| + }
|
| return ParseFunctionDeclaration(ok);
|
| + }
|
|
|
| case Token::NATIVE:
|
| return ParseNativeDeclaration(ok);
|
| @@ -1522,6 +1544,11 @@
|
| Consume(Token::VAR);
|
| } else if (peek() == Token::CONST) {
|
| Consume(Token::CONST);
|
| + if (temp_scope_->StrictMode()) {
|
| + ReportMessage("strict_const", Vector<const char*>::empty());
|
| + *ok = false;
|
| + return NULL;
|
| + }
|
| mode = Variable::CONST;
|
| is_const = true;
|
| } else {
|
| @@ -1641,34 +1668,49 @@
|
|
|
| if (top_scope_->is_global_scope()) {
|
| // Compute the arguments for the runtime call.
|
| - ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
|
| - // Be careful not to assign a value to the global variable if
|
| - // we're in a with. The initialization value should not
|
| - // necessarily be stored in the global object in that case,
|
| - // which is why we need to generate a separate assignment node.
|
| + ZoneList<Expression*>* arguments = new ZoneList<Expression*>(3);
|
| arguments->Add(new Literal(name)); // we have at least 1 parameter
|
| - if (is_const || (value != NULL && !inside_with())) {
|
| + CallRuntime* initialize;
|
| +
|
| + if (is_const) {
|
| arguments->Add(value);
|
| value = NULL; // zap the value to avoid the unnecessary assignment
|
| - }
|
| - // Construct the call to Runtime::DeclareGlobal{Variable,Const}Locally
|
| - // and add it to the initialization statement block. Note that
|
| - // this function does different things depending on if we have
|
| - // 1 or 2 parameters.
|
| - CallRuntime* initialize;
|
| - if (is_const) {
|
| +
|
| + // Construct the call to Runtime_InitializeConstGlobal
|
| + // and add it to the initialization statement block.
|
| + // Note that the function does different things depending on
|
| + // the number of arguments (1 or 2).
|
| initialize =
|
| - new CallRuntime(
|
| - isolate()->factory()->InitializeConstGlobal_symbol(),
|
| - Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
|
| - arguments);
|
| + new CallRuntime(
|
| + isolate()->factory()->InitializeConstGlobal_symbol(),
|
| + Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
|
| + arguments);
|
| } else {
|
| + // Add strict mode.
|
| + // We may want to pass singleton to avoid Literal allocations.
|
| + arguments->Add(NewNumberLiteral(
|
| + temp_scope_->StrictMode() ? kStrictMode : kNonStrictMode));
|
| +
|
| + // Be careful not to assign a value to the global variable if
|
| + // we're in a with. The initialization value should not
|
| + // necessarily be stored in the global object in that case,
|
| + // which is why we need to generate a separate assignment node.
|
| + if (value != NULL && !inside_with()) {
|
| + arguments->Add(value);
|
| + value = NULL; // zap the value to avoid the unnecessary assignment
|
| + }
|
| +
|
| + // Construct the call to Runtime_InitializeVarGlobal
|
| + // and add it to the initialization statement block.
|
| + // Note that the function does different things depending on
|
| + // the number of arguments (2 or 3).
|
| initialize =
|
| - new CallRuntime(
|
| - isolate()->factory()->InitializeVarGlobal_symbol(),
|
| - Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
|
| - arguments);
|
| + new CallRuntime(
|
| + isolate()->factory()->InitializeVarGlobal_symbol(),
|
| + Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
|
| + arguments);
|
| }
|
| +
|
| block->AddStatement(new ExpressionStatement(initialize));
|
| }
|
|
|
| @@ -2531,6 +2573,16 @@
|
| }
|
| }
|
|
|
| + // "delete identifier" is a syntax error in strict mode.
|
| + if (op == Token::DELETE && temp_scope_->StrictMode()) {
|
| + VariableProxy* operand = expression->AsVariableProxy();
|
| + if (operand != NULL && !operand->is_this()) {
|
| + ReportMessage("strict_delete", Vector<const char*>::empty());
|
| + *ok = false;
|
| + return NULL;
|
| + }
|
| + }
|
| +
|
| return new UnaryOperation(op, expression);
|
|
|
| } else if (Token::IsCountOp(op)) {
|
| @@ -3940,16 +3992,17 @@
|
| Handle<String> type,
|
| Vector< Handle<Object> > arguments) {
|
| int argc = arguments.length();
|
| - Handle<JSArray> array = isolate()->factory()->NewJSArray(argc, TENURED);
|
| - ASSERT(array->IsJSArray() && array->HasFastElements());
|
| + Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
|
| + TENURED);
|
| for (int i = 0; i < argc; i++) {
|
| Handle<Object> element = arguments[i];
|
| if (!element.is_null()) {
|
| - // We know this doesn't cause a GC here because we allocated the JSArray
|
| - // large enough.
|
| - array->SetFastElement(i, *element)->ToObjectUnchecked();
|
| + elements->set(i, *element);
|
| }
|
| }
|
| + Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(elements,
|
| + TENURED);
|
| +
|
| ZoneList<Expression*>* args = new ZoneList<Expression*>(2);
|
| args->Add(new Literal(type));
|
| args->Add(new Literal(array));
|
| @@ -4287,6 +4340,8 @@
|
| capture_index);
|
| }
|
| builder->AddAtom(body);
|
| + // For compatability with JSC and ES3, we allow quantifiers after
|
| + // lookaheads, and break in all cases.
|
| break;
|
| }
|
| case '|': {
|
| @@ -4360,7 +4415,7 @@
|
| type,
|
| captures_started());
|
| builder = stored_state->builder();
|
| - break;
|
| + continue;
|
| }
|
| case '[': {
|
| RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
|
| @@ -4383,11 +4438,11 @@
|
| builder->AddAssertion(
|
| new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
|
| continue;
|
| - // AtomEscape ::
|
| - // CharacterClassEscape
|
| - //
|
| - // CharacterClassEscape :: one of
|
| - // d D s S w W
|
| + // AtomEscape ::
|
| + // CharacterClassEscape
|
| + //
|
| + // CharacterClassEscape :: one of
|
| + // d D s S w W
|
| case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
|
| uc32 c = Next();
|
| Advance(2);
|
|
|