From 938d88e193acb1111986bfb0298afc4fb5d3c310 Mon Sep 17 00:00:00 2001 From: "lrn@chromium.org" Date: Wed, 27 Oct 2010 09:19:43 +0000 Subject: [PATCH] Separate JSON parsing from the JavaScript parser. Switch JSON parsing to creating the value directly instead of createing code to create the value. Review URL: http://codereview.chromium.org/4135004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5715 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler.cc | 27 +--- src/compiler.h | 15 +- src/debug-debugger.js | 2 +- src/json.js | 3 +- src/objects.h | 3 +- src/parser.cc | 274 ++++++++++++++++-------------------- src/parser.h | 67 +++++---- src/runtime.cc | 32 +++-- src/runtime.h | 5 +- src/scanner.h | 3 + src/v8natives.js | 6 +- test/mjsunit/debug-compile-event.js | 18 +-- test/mjsunit/mirror-script.js | 4 +- 13 files changed, 209 insertions(+), 250 deletions(-) diff --git a/src/compiler.cc b/src/compiler.cc index 6cc0971..1674ca8 100755 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -152,10 +152,8 @@ static Handle MakeFunctionInfo(CompilationInfo* info) { script->set_context_data((*i::Top::global_context())->data()); #ifdef ENABLE_DEBUGGER_SUPPORT - if (info->is_eval() || info->is_json()) { - Script::CompilationType compilation_type = info->is_json() - ? Script::COMPILATION_TYPE_JSON - : Script::COMPILATION_TYPE_EVAL; + if (info->is_eval()) { + Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL; script->set_compilation_type(Smi::FromInt(compilation_type)); // For eval scripts add information on the function from which eval was // called. @@ -323,13 +321,7 @@ Handle Compiler::Compile(Handle source, Handle Compiler::CompileEval(Handle source, Handle context, - bool is_global, - ValidationState validate) { - // Note that if validation is required then no path through this function - // is allowed to return a value without validating that the input is legal - // json. - bool is_json = (validate == VALIDATE_JSON); - + bool is_global) { int source_length = source->length(); Counters::total_eval_size.Increment(source_length); Counters::total_compile_size.Increment(source_length); @@ -338,13 +330,9 @@ Handle Compiler::CompileEval(Handle source, VMState state(COMPILER); // Do a lookup in the compilation cache; if the entry is not there, invoke - // the compiler and add the result to the cache. If we're evaluating json - // we bypass the cache since we can't be sure a potential value in the - // cache has been validated. + // the compiler and add the result to the cache. Handle result; - if (!is_json) { - result = CompilationCache::LookupEval(source, context, is_global); - } + result = CompilationCache::LookupEval(source, context, is_global); if (result.is_null()) { // Create a script object describing the script to be compiled. @@ -352,12 +340,9 @@ Handle Compiler::CompileEval(Handle source, CompilationInfo info(script); info.MarkAsEval(); if (is_global) info.MarkAsGlobal(); - if (is_json) info.MarkAsJson(); info.SetCallingContext(context); result = MakeFunctionInfo(&info); - if (!result.is_null() && !is_json) { - // For json it's unlikely that we'll ever see exactly the same string - // again so we don't use the compilation cache. + if (!result.is_null()) { CompilationCache::PutEval(source, context, is_global, result); } } diff --git a/src/compiler.h b/src/compiler.h index d6f4e69..20868e5 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -49,7 +49,6 @@ class CompilationInfo BASE_EMBEDDED { bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; } bool is_eval() const { return (flags_ & IsEval::mask()) != 0; } bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; } - bool is_json() const { return (flags_ & IsJson::mask()) != 0; } bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; } FunctionLiteral* function() const { return function_; } Scope* scope() const { return scope_; } @@ -69,10 +68,6 @@ class CompilationInfo BASE_EMBEDDED { ASSERT(!is_lazy()); flags_ |= IsGlobal::encode(true); } - void MarkAsJson() { - ASSERT(!is_lazy()); - flags_ |= IsJson::encode(true); - } void MarkAsInLoop() { ASSERT(is_lazy()); flags_ |= IsInLoop::encode(true); @@ -108,16 +103,15 @@ class CompilationInfo BASE_EMBEDDED { // Flags that can be set for eager compilation. class IsEval: public BitField {}; class IsGlobal: public BitField {}; - class IsJson: public BitField {}; // Flags that can be set for lazy compilation. - class IsInLoop: public BitField {}; + class IsInLoop: public BitField {}; unsigned flags_; // Fields filled in by the compilation pipeline. // AST filled in by the parser. FunctionLiteral* function_; - // The scope of the function literal as a convenience. Set to indidicate + // The scope of the function literal as a convenience. Set to indicate // that scopes have been analyzed. Scope* scope_; // The compiled code. @@ -153,8 +147,6 @@ class CompilationInfo BASE_EMBEDDED { class Compiler : public AllStatic { public: - enum ValidationState { DONT_VALIDATE_JSON, VALIDATE_JSON }; - // All routines return a JSFunction. // If an error occurs an exception is raised and // the return handle contains NULL. @@ -172,8 +164,7 @@ class Compiler : public AllStatic { // Compile a String source within a context for Eval. static Handle CompileEval(Handle source, Handle context, - bool is_global, - ValidationState validation); + bool is_global); // Compile from function info (used for lazy compilation). Returns true on // success and false if the compilation resulted in a stack overflow. diff --git a/src/debug-debugger.js b/src/debug-debugger.js index a0c6808..0eab8d1 100644 --- a/src/debug-debugger.js +++ b/src/debug-debugger.js @@ -1301,7 +1301,7 @@ DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request) try { try { // Convert the JSON string to an object. - request = %CompileString('(' + json_request + ')', false)(); + request = %CompileString('(' + json_request + ')')(); // Create an initial response. response = this.createResponse(request); diff --git a/src/json.js b/src/json.js index a39d7c4..5993100 100644 --- a/src/json.js +++ b/src/json.js @@ -29,8 +29,7 @@ var $JSON = global.JSON; function ParseJSONUnfiltered(text) { var s = $String(text); - var f = %CompileString(s, true); - return f(); + return %ParseJson(s); } function Revive(holder, name, reviver) { diff --git a/src/objects.h b/src/objects.h index 87234ea..6029ad5 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3409,8 +3409,7 @@ class Script: public Struct { // Script compilation types. enum CompilationType { COMPILATION_TYPE_HOST = 0, - COMPILATION_TYPE_EVAL = 1, - COMPILATION_TYPE_JSON = 2 + COMPILATION_TYPE_EVAL = 1 }; // [source]: the script source. diff --git a/src/parser.cc b/src/parser.cc index 180d0d2..cc69b8d 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -1382,56 +1382,6 @@ FunctionLiteral* Parser::ParseLazy(Handle info) { } -FunctionLiteral* Parser::ParseJson(Handle source) { - CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); - - HistogramTimerScope timer(&Counters::parse); - Counters::total_parse_size.Increment(source->length()); - - // Initialize parser state. - source->TryFlatten(TENURED); - scanner_.Initialize(source, JSON); - ASSERT(target_stack_ == NULL); - - FunctionLiteral* result = NULL; - Handle no_name = factory()->EmptySymbol(); - - { - Scope* scope = factory()->NewScope(top_scope_, Scope::GLOBAL_SCOPE, false); - LexicalScope lexical_scope(this, scope); - TemporaryScope temp_scope(this); - bool ok = true; - Expression* expression = ParseJson(&ok); - if (ok) { - ZoneListWrapper statement = factory()->NewList(1); - statement.Add(new ExpressionStatement(expression)); - result = NEW(FunctionLiteral( - no_name, - top_scope_, - statement.elements(), - temp_scope.materialized_literal_count(), - temp_scope.expected_property_count(), - temp_scope.only_simple_this_property_assignments(), - temp_scope.this_property_assignments(), - 0, - 0, - source->length(), - false, - temp_scope.ContainsLoops())); - } else if (scanner().stack_overflow()) { - Top::StackOverflow(); - } - } - - // Make sure the target stack is empty. - ASSERT(target_stack_ == NULL); - - // If there was a syntax error we have to get rid of the AST - // and it is not safe to do so before the scope has been deleted. - if (result == NULL) zone_scope.DeleteOnExit(); - return result; -} - void Parser::ReportMessage(const char* type, Vector args) { Scanner::Location source_location = scanner_.location(); ReportMessageAt(source_location, type, args); @@ -4281,145 +4231,165 @@ Expression* Parser::NewThrowError(Handle constructor, // ---------------------------------------------------------------------------- // JSON -Expression* Parser::ParseJson(bool* ok) { - Expression* result = ParseJsonValue(CHECK_OK); - Expect(Token::EOS, CHECK_OK); +Handle JsonParser::ParseJson(Handle source) { + source->TryFlatten(); + scanner_.Initialize(source, JSON); + Handle result = ParseJsonValue(); + if (result.is_null() || scanner_.Next() != Token::EOS) { + if (scanner_.stack_overflow()) { + // Scanner failed. + Top::StackOverflow(); + } else { + // Parse failed. Scanner's current token is the unexpected token. + Token::Value token = scanner_.current_token(); + + const char* message; + const char* name_opt = NULL; + + switch (token) { + case Token::EOS: + message = "unexpected_eos"; + break; + case Token::NUMBER: + message = "unexpected_token_number"; + break; + case Token::STRING: + message = "unexpected_token_string"; + break; + case Token::IDENTIFIER: + message = "unexpected_token_identifier"; + break; + default: + message = "unexpected_token"; + name_opt = Token::String(token); + ASSERT(name_opt != NULL); + break; + } + + Scanner::Location source_location = scanner_.location(); + MessageLocation location(Factory::NewScript(source), + source_location.beg_pos, + source_location.end_pos); + int argc = (name_opt == NULL) ? 0 : 1; + Handle array = Factory::NewJSArray(argc); + if (name_opt != NULL) { + SetElement(array, + 0, + Factory::NewStringFromUtf8(CStrVector(name_opt))); + } + Handle result = Factory::NewSyntaxError(message, array); + Top::Throw(*result, &location); + return Handle::null(); + } + } return result; } +Handle JsonParser::GetString() { + int literal_length = scanner_.literal_length(); + if (literal_length == 0) { + return Factory::empty_string(); + } + const char* literal_string = scanner_.literal_string(); + Vector literal(literal_string, literal_length); + return Factory::NewStringFromUtf8(literal); +} + + // Parse any JSON value. -Expression* Parser::ParseJsonValue(bool* ok) { - Token::Value token = peek(); +Handle JsonParser::ParseJsonValue() { + Token::Value token = scanner_.Next(); switch (token) { case Token::STRING: { - Consume(Token::STRING); - int literal_length = scanner_.literal_length(); - const char* literal_string = scanner_.literal_string(); - if (literal_length == 0) { - return NEW(Literal(Factory::empty_string())); - } - Vector literal(literal_string, literal_length); - return NEW(Literal(Factory::NewStringFromUtf8(literal, TENURED))); + return GetString(); } case Token::NUMBER: { - Consume(Token::NUMBER); - ASSERT(scanner_.literal_length() > 0); double value = StringToDouble(scanner_.literal(), NO_FLAGS, // Hex, octal or trailing junk. OS::nan_value()); - return NewNumberLiteral(value); + return Factory::NewNumber(value); } case Token::FALSE_LITERAL: - Consume(Token::FALSE_LITERAL); - return NEW(Literal(Factory::false_value())); + return Factory::false_value(); case Token::TRUE_LITERAL: - Consume(Token::TRUE_LITERAL); - return NEW(Literal(Factory::true_value())); + return Factory::true_value(); case Token::NULL_LITERAL: - Consume(Token::NULL_LITERAL); - return NEW(Literal(Factory::null_value())); - case Token::LBRACE: { - Expression* result = ParseJsonObject(CHECK_OK); - return result; - } - case Token::LBRACK: { - Expression* result = ParseJsonArray(CHECK_OK); - return result; - } + return Factory::null_value(); + case Token::LBRACE: + return ParseJsonObject(); + case Token::LBRACK: + return ParseJsonArray(); default: - *ok = false; - ReportUnexpectedToken(token); - return NULL; + return ReportUnexpectedToken(); } } // Parse a JSON object. Scanner must be right after '{' token. -Expression* Parser::ParseJsonObject(bool* ok) { - Consume(Token::LBRACE); - ZoneListWrapper properties = - factory()->NewList(4); - int boilerplate_properties = 0; - if (peek() != Token::RBRACE) { +Handle JsonParser::ParseJsonObject() { + Handle object_constructor( + Top::global_context()->object_function()); + Handle json_object = Factory::NewJSObject(object_constructor); + if (scanner_.peek() == Token::RBRACE) { + scanner_.Next(); + } else { do { - Expect(Token::STRING, CHECK_OK); - Handle key = GetSymbol(CHECK_OK); - Expect(Token::COLON, CHECK_OK); - Expression* value = ParseJsonValue(CHECK_OK); - Literal* key_literal; + if (scanner_.Next() != Token::STRING) { + return ReportUnexpectedToken(); + } + Handle key = GetString(); + if (scanner_.Next() != Token::COLON) { + return ReportUnexpectedToken(); + } + Handle value = ParseJsonValue(); + if (value.is_null()) return Handle::null(); uint32_t index; if (key->AsArrayIndex(&index)) { - key_literal = NewNumberLiteral(index); + SetElement(json_object, index, value); } else { - key_literal = NEW(Literal(key)); - } - ObjectLiteral::Property* property = - NEW(ObjectLiteral::Property(key_literal, value)); - properties.Add(property); - - if (IsBoilerplateProperty(property)) { - boilerplate_properties++; + SetProperty(json_object, key, value, NONE); } - } while (Check(Token::COMMA)); + } while (scanner_.Next() == Token::COMMA); + if (scanner_.current_token() != Token::RBRACE) { + return ReportUnexpectedToken(); + } } - Expect(Token::RBRACE, CHECK_OK); - - int literal_index = temp_scope_->NextMaterializedLiteralIndex(); - if (is_pre_parsing_) return NULL; - - Handle constant_properties = - Factory::NewFixedArray(boilerplate_properties * 2, TENURED); - bool is_simple = true; - bool fast_elements = true; - int depth = 1; - BuildObjectLiteralConstantProperties(properties.elements(), - constant_properties, - &is_simple, - &fast_elements, - &depth); - return new ObjectLiteral(constant_properties, - properties.elements(), - literal_index, - is_simple, - fast_elements, - depth); + return json_object; } // Parse a JSON array. Scanner must be right after '[' token. -Expression* Parser::ParseJsonArray(bool* ok) { - Consume(Token::LBRACK); +Handle JsonParser::ParseJsonArray() { + ZoneScope zone_scope(DELETE_ON_EXIT); + ZoneList > elements(4); - ZoneListWrapper values = factory()->NewList(4); - if (peek() != Token::RBRACK) { + Token::Value token = scanner_.peek(); + if (token == Token::RBRACK) { + scanner_.Next(); + } else { do { - Expression* exp = ParseJsonValue(CHECK_OK); - values.Add(exp); - } while (Check(Token::COMMA)); + Handle element = ParseJsonValue(); + if (element.is_null()) return Handle::null(); + elements.Add(element); + token = scanner_.Next(); + } while (token == Token::COMMA); + if (token != Token::RBRACK) { + return ReportUnexpectedToken(); + } } - Expect(Token::RBRACK, CHECK_OK); - - // Update the scope information before the pre-parsing bailout. - int literal_index = temp_scope_->NextMaterializedLiteralIndex(); - if (is_pre_parsing_) return NULL; + // Allocate a fixed array with all the elements. + Handle fast_elements = + Factory::NewFixedArray(elements.length()); - // Allocate a fixed array with all the literals. - Handle literals = - Factory::NewFixedArray(values.length(), TENURED); + for (int i = 0, n = elements.length(); i < n; i++) { + fast_elements->set(i, *elements[i]); + } - bool is_simple; - int depth; - BuildArrayLiteralBoilerplateLiterals(values.elements(), - literals, - &is_simple, - &depth); - return NEW(ArrayLiteral(literals, values.elements(), - literal_index, is_simple, depth)); + return Factory::NewJSArrayWithElements(fast_elements); } - // ---------------------------------------------------------------------------- // Regular expressions @@ -5368,11 +5338,7 @@ bool Parser::Parse(CompilationInfo* info) { ASSERT(Top::has_pending_exception()); } else { Handle source = Handle(String::cast(script->source())); - // JSON is always global. - ASSERT(!info->is_json() || info->is_global()); - result = info->is_json() - ? parser.ParseJson(source) - : parser.ParseProgram(source, info->is_global()); + result = parser.ParseProgram(source, info->is_global()); } } diff --git a/src/parser.h b/src/parser.h index 7142551..59e6422 100644 --- a/src/parser.h +++ b/src/parser.h @@ -218,7 +218,6 @@ class Parser { FunctionLiteral* ParseProgram(Handle source, bool in_global_context); FunctionLiteral* ParseLazy(Handle info); - FunctionLiteral* ParseJson(Handle source); // The minimum number of contiguous assignment that will // be treated as an initialization block. Benchmarks show that @@ -411,29 +410,6 @@ class Parser { Handle type, Vector< Handle > arguments); - // JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5 - // specification section 15.12.1 (and appendix A.8). - // The grammar is given section 15.12.1.2 (and appendix A.8.2). - - // Parse JSON input as a single JSON value. - Expression* ParseJson(bool* ok); - - // Parse a single JSON value from input (grammar production JSONValue). - // A JSON value is either a (double-quoted) string literal, a number literal, - // one of "true", "false", or "null", or an object or array literal. - Expression* ParseJsonValue(bool* ok); - // Parse a JSON object literal (grammar production JSONObject). - // An object literal is a squiggly-braced and comma separated sequence - // (possibly empty) of key/value pairs, where the key is a JSON string - // literal, the value is a JSON value, and the two are spearated by a colon. - // A JavaScript object also allows numbers and identifiers as keys. - Expression* ParseJsonObject(bool* ok); - // Parses a JSON array literal (grammar production JSONArray). An array - // literal is a square-bracketed and comma separated sequence (possibly empty) - // of JSON values. - // A JavaScript array allows leaving out values from the sequence. - Expression* ParseJsonArray(bool* ok); - friend class Target; friend class TargetScope; friend class LexicalScope; @@ -472,6 +448,49 @@ class CompileTimeValue: public AllStatic { }; +// JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5 +// specification section 15.12.1 (and appendix A.8). +// The grammar is given section 15.12.1.2 (and appendix A.8.2). +class JsonParser BASE_EMBEDDED { + public: + // Parse JSON input as a single JSON value. + // Returns null handle and sets exception if parsing failed. + static Handle Parse(Handle source) { + return JsonParser().ParseJson(source); + } + + private: + JsonParser() { } + ~JsonParser() { } + + // Parse a string containing a single JSON value. + Handle ParseJson(Handle); + // Parse a single JSON value from input (grammar production JSONValue). + // A JSON value is either a (double-quoted) string literal, a number literal, + // one of "true", "false", or "null", or an object or array literal. + Handle ParseJsonValue(); + // Parse a JSON object literal (grammar production JSONObject). + // An object literal is a squiggly-braced and comma separated sequence + // (possibly empty) of key/value pairs, where the key is a JSON string + // literal, the value is a JSON value, and the two are separated by a colon. + // A JSON array dosn't allow numbers and identifiers as keys, like a + // JavaScript array. + Handle ParseJsonObject(); + // Parses a JSON array literal (grammar production JSONArray). An array + // literal is a square-bracketed and comma separated sequence (possibly empty) + // of JSON values. + // A JSON array doesn't allow leaving out values from the sequence, nor does + // it allow a terminal comma, like a JavaScript array does. + Handle ParseJsonArray(); + + // Mark that a parsing error has happened at the current token, and + // return a null handle. Primarily for readability. + Handle ReportUnexpectedToken() { return Handle::null(); } + // Converts the currently parsed literal to a JavaScript String. + Handle GetString(); + + Scanner scanner_; +}; } } // namespace v8::internal #endif // V8_PARSER_H_ diff --git a/src/runtime.cc b/src/runtime.cc index f701c03..fc1a023 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -7129,20 +7129,31 @@ static MaybeObject* Runtime_GlobalReceiver(Arguments args) { } +static MaybeObject* Runtime_ParseJson(Arguments args) { + HandleScope scope; + ASSERT_EQ(1, args.length()); + CONVERT_ARG_CHECKED(String, source, 0); + + Handle result = JsonParser::Parse(source); + if (result.is_null()) { + // Syntax error or stack overflow in scanner. + ASSERT(Top::has_pending_exception()); + return Failure::Exception(); + } + return *result; +} + + static MaybeObject* Runtime_CompileString(Arguments args) { HandleScope scope; - ASSERT_EQ(2, args.length()); + ASSERT_EQ(1, args.length()); CONVERT_ARG_CHECKED(String, source, 0); - CONVERT_ARG_CHECKED(Oddball, is_json, 1) // Compile source string in the global context. Handle context(Top::context()->global_context()); - Compiler::ValidationState validate = (is_json->IsTrue()) - ? Compiler::VALIDATE_JSON : Compiler::DONT_VALIDATE_JSON; Handle shared = Compiler::CompileEval(source, context, - true, - validate); + true); if (shared.is_null()) return Failure::Exception(); Handle fun = Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED); @@ -7157,8 +7168,7 @@ static ObjectPair CompileGlobalEval(Handle source, Handle shared = Compiler::CompileEval( source, Handle(Top::context()), - Top::context()->IsGlobalContext(), - Compiler::DONT_VALIDATE_JSON); + Top::context()->IsGlobalContext()); if (shared.is_null()) return MakePair(Failure::Exception(), NULL); Handle compiled = Factory::NewFunctionFromSharedFunctionInfo( shared, @@ -9370,8 +9380,7 @@ static MaybeObject* Runtime_DebugEvaluate(Arguments args) { Handle shared = Compiler::CompileEval(function_source, context, - context->IsGlobalContext(), - Compiler::DONT_VALIDATE_JSON); + context->IsGlobalContext()); if (shared.is_null()) return Failure::Exception(); Handle compiled_function = Factory::NewFunctionFromSharedFunctionInfo(shared, context); @@ -9442,8 +9451,7 @@ static MaybeObject* Runtime_DebugEvaluateGlobal(Arguments args) { Handle shared = Compiler::CompileEval(source, context, - true, - Compiler::DONT_VALIDATE_JSON); + true); if (shared.is_null()) return Failure::Exception(); Handle compiled_function = Handle(Factory::NewFunctionFromSharedFunctionInfo(shared, diff --git a/src/runtime.h b/src/runtime.h index 8057d8b..72a8037 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -164,6 +164,9 @@ namespace internal { F(RegExpConstructResult, 3, 1) \ F(RegExpCloneResult, 1, 1) \ \ + /* JSON */ \ + F(ParseJson, 1, 1) \ + \ /* Strings */ \ F(StringCharCodeAt, 2, 1) \ F(StringIndexOf, 3, 1) \ @@ -222,7 +225,7 @@ namespace internal { /* Numbers */ \ \ /* Globals */ \ - F(CompileString, 2, 1) \ + F(CompileString, 1, 1) \ F(GlobalPrint, 1, 1) \ \ /* Eval */ \ diff --git a/src/scanner.h b/src/scanner.h index 6e5333b..dab3d67 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -296,6 +296,9 @@ class Scanner { // Returns the next token. Token::Value Next(); + // Returns the current token again. + Token::Value current_token() { return current_.token; } + // One token look-ahead (past the token returned by Next()). Token::Value peek() const { return next_.token; } diff --git a/src/v8natives.js b/src/v8natives.js index 88aea9c..50a2774 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -140,7 +140,7 @@ function GlobalEval(x) { 'be the global object from which eval originated'); } - var f = %CompileString(x, false); + var f = %CompileString(x); if (!IS_FUNCTION(f)) return f; return f.call(this); @@ -151,7 +151,7 @@ function GlobalEval(x) { function GlobalExecScript(expr, lang) { // NOTE: We don't care about the character casing. if (!lang || /javascript/i.test(lang)) { - var f = %CompileString(ToString(expr), false); + var f = %CompileString(ToString(expr)); f.call(%GlobalReceiver(global)); } return null; @@ -1177,7 +1177,7 @@ function NewFunction(arg1) { // length == 1 // The call to SetNewFunctionAttributes will ensure the prototype // property of the resulting function is enumerable (ECMA262, 15.3.5.2). - var f = %CompileString(source, false)(); + var f = %CompileString(source)(); %FunctionSetName(f, "anonymous"); return %SetNewFunctionAttributes(f); } diff --git a/test/mjsunit/debug-compile-event.js b/test/mjsunit/debug-compile-event.js index e7ecf47..b00a907 100644 --- a/test/mjsunit/debug-compile-event.js +++ b/test/mjsunit/debug-compile-event.js @@ -36,7 +36,6 @@ var current_source = ''; // Current source being compiled. var source_count = 0; // Total number of scources compiled. var host_compilations = 0; // Number of scources compiled through the API. var eval_compilations = 0; // Number of scources compiled through eval. -var json_compilations = 0; // Number of scources compiled through JSON.parse. function compileSource(source) { @@ -62,9 +61,6 @@ function listener(event, exec_state, event_data, data) { case Debug.ScriptCompilationType.Eval: eval_compilations++; break; - case Debug.ScriptCompilationType.JSON: - json_compilations++; - break; } } @@ -74,13 +70,6 @@ function listener(event, exec_state, event_data, data) { // For source with 'eval' there will be compile events with substrings // as well as with with the exact source. assertTrue(current_source.indexOf(event_data.script().source()) >= 0); - } else if (current_source.indexOf('JSON.parse') == 0) { - // For JSON the JSON source will be in parentheses. - var s = event_data.script().source(); - if (s[0] == '(') { - s = s.substring(1, s.length - 2); - } - assertTrue(current_source.indexOf(s) >= 0); } else { // For source without 'eval' there will be a compile events with the // exact source. @@ -113,7 +102,7 @@ source_count++; // Using eval causes additional compilation event. compileSource('eval("eval(\'(function(){return a;})\')")'); source_count += 2; // Using eval causes additional compilation event. compileSource('JSON.parse(\'{"a":1,"b":2}\')'); -source_count++; // Using JSON.parse causes additional compilation event. +// Using JSON.parse does not causes additional compilation events. compileSource('x=1; //@ sourceURL=myscript.js'); // Make sure that the debug event listener was invoked. @@ -123,10 +112,9 @@ assertFalse(exception, "exception in listener") assertEquals(before_compile_count, after_compile_count); // Check the actual number of events (no compilation through the API as all -// source compiled through eval except for one JSON.parse call). +// source compiled through eval). assertEquals(source_count, after_compile_count); assertEquals(0, host_compilations); -assertEquals(source_count - 1, eval_compilations); -assertEquals(1, json_compilations); +assertEquals(source_count, eval_compilations); Debug.setListener(null); diff --git a/test/mjsunit/mirror-script.js b/test/mjsunit/mirror-script.js index 8631028..7156170 100644 --- a/test/mjsunit/mirror-script.js +++ b/test/mjsunit/mirror-script.js @@ -83,12 +83,10 @@ function testScriptMirror(f, file_name, file_lines, type, compilation_type, // Test the script mirror for different functions. -testScriptMirror(function(){}, 'mirror-script.js', 100, 2, 0); +testScriptMirror(function(){}, 'mirror-script.js', 98, 2, 0); testScriptMirror(Math.sin, 'native math.js', -1, 0, 0); testScriptMirror(eval('(function(){})'), null, 1, 2, 1, '(function(){})', 87); testScriptMirror(eval('(function(){\n })'), null, 2, 2, 1, '(function(){\n })', 88); -testScriptMirror(%CompileString('{"a":1,"b":2}', true), null, 1, 2, 2, '{"a":1,"b":2}'); -testScriptMirror(%CompileString('{"a":1,\n "b":2}', true), null, 2, 2, 2, '{"a":1,\n "b":2}'); // Test taking slices of source. var mirror = debug.MakeMirror(eval('(function(){\n 1;\n})')).script(); -- 2.7.4