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.
Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> 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);
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<SharedFunctionInfo> 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.
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);
}
}
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_; }
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);
// Flags that can be set for eager compilation.
class IsEval: public BitField<bool, 1, 1> {};
class IsGlobal: public BitField<bool, 2, 1> {};
- class IsJson: public BitField<bool, 3, 1> {};
// Flags that can be set for lazy compilation.
- class IsInLoop: public BitField<bool, 4, 1> {};
+ class IsInLoop: public BitField<bool, 3, 1> {};
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.
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.
// Compile a String source within a context for Eval.
static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
Handle<Context> 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.
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);
function ParseJSONUnfiltered(text) {
var s = $String(text);
- var f = %CompileString(s, true);
- return f();
+ return %ParseJson(s);
}
function Revive(holder, name, reviver) {
// 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.
}
-FunctionLiteral* Parser::ParseJson(Handle<String> 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<String> 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> statement = factory()->NewList<Statement>(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<const char*> args) {
Scanner::Location source_location = scanner_.location();
ReportMessageAt(source_location, type, args);
// ----------------------------------------------------------------------------
// JSON
-Expression* Parser::ParseJson(bool* ok) {
- Expression* result = ParseJsonValue(CHECK_OK);
- Expect(Token::EOS, CHECK_OK);
+Handle<Object> JsonParser::ParseJson(Handle<String> source) {
+ source->TryFlatten();
+ scanner_.Initialize(source, JSON);
+ Handle<Object> 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<JSArray> array = Factory::NewJSArray(argc);
+ if (name_opt != NULL) {
+ SetElement(array,
+ 0,
+ Factory::NewStringFromUtf8(CStrVector(name_opt)));
+ }
+ Handle<Object> result = Factory::NewSyntaxError(message, array);
+ Top::Throw(*result, &location);
+ return Handle<Object>::null();
+ }
+ }
return result;
}
+Handle<String> JsonParser::GetString() {
+ int literal_length = scanner_.literal_length();
+ if (literal_length == 0) {
+ return Factory::empty_string();
+ }
+ const char* literal_string = scanner_.literal_string();
+ Vector<const char> literal(literal_string, literal_length);
+ return Factory::NewStringFromUtf8(literal);
+}
+
+
// Parse any JSON value.
-Expression* Parser::ParseJsonValue(bool* ok) {
- Token::Value token = peek();
+Handle<Object> 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<const char> 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<ObjectLiteral::Property> properties =
- factory()->NewList<ObjectLiteral::Property>(4);
- int boilerplate_properties = 0;
- if (peek() != Token::RBRACE) {
+Handle<Object> JsonParser::ParseJsonObject() {
+ Handle<JSFunction> object_constructor(
+ Top::global_context()->object_function());
+ Handle<JSObject> json_object = Factory::NewJSObject(object_constructor);
+ if (scanner_.peek() == Token::RBRACE) {
+ scanner_.Next();
+ } else {
do {
- Expect(Token::STRING, CHECK_OK);
- Handle<String> 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<String> key = GetString();
+ if (scanner_.Next() != Token::COLON) {
+ return ReportUnexpectedToken();
+ }
+ Handle<Object> value = ParseJsonValue();
+ if (value.is_null()) return Handle<Object>::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<FixedArray> 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<Object> JsonParser::ParseJsonArray() {
+ ZoneScope zone_scope(DELETE_ON_EXIT);
+ ZoneList<Handle<Object> > elements(4);
- ZoneListWrapper<Expression> values = factory()->NewList<Expression>(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<Object> element = ParseJsonValue();
+ if (element.is_null()) return Handle<Object>::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<FixedArray> fast_elements =
+ Factory::NewFixedArray(elements.length());
- // Allocate a fixed array with all the literals.
- Handle<FixedArray> 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
ASSERT(Top::has_pending_exception());
} else {
Handle<String> source = Handle<String>(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());
}
}
FunctionLiteral* ParseProgram(Handle<String> source,
bool in_global_context);
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
- FunctionLiteral* ParseJson(Handle<String> source);
// The minimum number of contiguous assignment that will
// be treated as an initialization block. Benchmarks show that
Handle<String> type,
Vector< Handle<Object> > 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;
};
+// 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<Object> Parse(Handle<String> source) {
+ return JsonParser().ParseJson(source);
+ }
+
+ private:
+ JsonParser() { }
+ ~JsonParser() { }
+
+ // Parse a string containing a single JSON value.
+ Handle<Object> ParseJson(Handle<String>);
+ // 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<Object> 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<Object> 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<Object> ParseJsonArray();
+
+ // Mark that a parsing error has happened at the current token, and
+ // return a null handle. Primarily for readability.
+ Handle<Object> ReportUnexpectedToken() { return Handle<Object>::null(); }
+ // Converts the currently parsed literal to a JavaScript String.
+ Handle<String> GetString();
+
+ Scanner scanner_;
+};
} } // namespace v8::internal
#endif // V8_PARSER_H_
}
+static MaybeObject* Runtime_ParseJson(Arguments args) {
+ HandleScope scope;
+ ASSERT_EQ(1, args.length());
+ CONVERT_ARG_CHECKED(String, source, 0);
+
+ Handle<Object> 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> context(Top::context()->global_context());
- Compiler::ValidationState validate = (is_json->IsTrue())
- ? Compiler::VALIDATE_JSON : Compiler::DONT_VALIDATE_JSON;
Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
context,
- true,
- validate);
+ true);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED);
Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
source,
Handle<Context>(Top::context()),
- Top::context()->IsGlobalContext(),
- Compiler::DONT_VALIDATE_JSON);
+ Top::context()->IsGlobalContext());
if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo(
shared,
Handle<SharedFunctionInfo> shared =
Compiler::CompileEval(function_source,
context,
- context->IsGlobalContext(),
- Compiler::DONT_VALIDATE_JSON);
+ context->IsGlobalContext());
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Factory::NewFunctionFromSharedFunctionInfo(shared, context);
Handle<SharedFunctionInfo> shared =
Compiler::CompileEval(source,
context,
- true,
- Compiler::DONT_VALIDATE_JSON);
+ true);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Handle<JSFunction>(Factory::NewFunctionFromSharedFunctionInfo(shared,
F(RegExpConstructResult, 3, 1) \
F(RegExpCloneResult, 1, 1) \
\
+ /* JSON */ \
+ F(ParseJson, 1, 1) \
+ \
/* Strings */ \
F(StringCharCodeAt, 2, 1) \
F(StringIndexOf, 3, 1) \
/* Numbers */ \
\
/* Globals */ \
- F(CompileString, 2, 1) \
+ F(CompileString, 1, 1) \
F(GlobalPrint, 1, 1) \
\
/* Eval */ \
// 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; }
'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);
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;
// 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);
}
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) {
case Debug.ScriptCompilationType.Eval:
eval_compilations++;
break;
- case Debug.ScriptCompilationType.JSON:
- json_compilations++;
- break;
}
}
// 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.
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.
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);
// 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();