Merge V8 at 3.8.9.11
Bug: 5688872
Change-Id: Ie3b1dd67a730ec5e82686b7b37dba26f6a9bb24f
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index cc20b6f..59d6d19 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -1189,7 +1189,6 @@
templ->Set("x", v8_num(200));
templ->SetAccessor(v8_str("m"), GetM);
LocalContext env(0, templ);
- v8::Handle<v8::Object> obj(env->Global());
v8::Handle<Script> script(v8_compile("dummy()"));
v8::Handle<Value> result(script->Run());
CHECK_EQ(13.4, result->NumberValue());
@@ -1423,6 +1422,40 @@
THREADED_TEST(SwitchFromInterceptorToAccessor) {
v8::HandleScope scope;
+ Handle<FunctionTemplate> templ = FunctionTemplate::New();
+ AddAccessor(templ, v8_str("age"),
+ SimpleAccessorGetter, SimpleAccessorSetter);
+ AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
+ LocalContext env;
+ env->Global()->Set(v8_str("Obj"), templ->GetFunction());
+ CompileRun("var obj = new Obj;"
+ "function setAge(i){ obj.age = i; };"
+ "for(var i = 0; i <= 10000; i++) setAge(i);");
+ // All i < 10000 go to the interceptor.
+ ExpectInt32("obj.interceptor_age", 9999);
+ // The last i goes to the accessor.
+ ExpectInt32("obj.accessor_age", 10000);
+}
+
+THREADED_TEST(SwitchFromAccessorToInterceptor) {
+ v8::HandleScope scope;
+ Handle<FunctionTemplate> templ = FunctionTemplate::New();
+ AddAccessor(templ, v8_str("age"),
+ SimpleAccessorGetter, SimpleAccessorSetter);
+ AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
+ LocalContext env;
+ env->Global()->Set(v8_str("Obj"), templ->GetFunction());
+ CompileRun("var obj = new Obj;"
+ "function setAge(i){ obj.age = i; };"
+ "for(var i = 20000; i >= 9999; i--) setAge(i);");
+ // All i >= 10000 go to the accessor.
+ ExpectInt32("obj.accessor_age", 10000);
+ // The last i goes to the interceptor.
+ ExpectInt32("obj.interceptor_age", 9999);
+}
+
+THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
+ v8::HandleScope scope;
Handle<FunctionTemplate> parent = FunctionTemplate::New();
Handle<FunctionTemplate> child = FunctionTemplate::New();
child->Inherit(parent);
@@ -1440,7 +1473,7 @@
ExpectInt32("child.accessor_age", 10000);
}
-THREADED_TEST(SwitchFromAccessorToInterceptor) {
+THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
v8::HandleScope scope;
Handle<FunctionTemplate> parent = FunctionTemplate::New();
Handle<FunctionTemplate> child = FunctionTemplate::New();
@@ -1459,6 +1492,54 @@
ExpectInt32("child.interceptor_age", 9999);
}
+THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
+ v8::HandleScope scope;
+ Handle<FunctionTemplate> templ = FunctionTemplate::New();
+ AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
+ LocalContext env;
+ env->Global()->Set(v8_str("Obj"), templ->GetFunction());
+ CompileRun("var obj = new Obj;"
+ "function setter(i) { this.accessor_age = i; };"
+ "function getter() { return this.accessor_age; };"
+ "function setAge(i) { obj.age = i; };"
+ "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
+ "for(var i = 0; i <= 10000; i++) setAge(i);");
+ // All i < 10000 go to the interceptor.
+ ExpectInt32("obj.interceptor_age", 9999);
+ // The last i goes to the JavaScript accessor.
+ ExpectInt32("obj.accessor_age", 10000);
+ // The installed JavaScript getter is still intact.
+ // This last part is a regression test for issue 1651 and relies on the fact
+ // that both interceptor and accessor are being installed on the same object.
+ ExpectInt32("obj.age", 10000);
+ ExpectBoolean("obj.hasOwnProperty('age')", true);
+ ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
+}
+
+THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
+ v8::HandleScope scope;
+ Handle<FunctionTemplate> templ = FunctionTemplate::New();
+ AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
+ LocalContext env;
+ env->Global()->Set(v8_str("Obj"), templ->GetFunction());
+ CompileRun("var obj = new Obj;"
+ "function setter(i) { this.accessor_age = i; };"
+ "function getter() { return this.accessor_age; };"
+ "function setAge(i) { obj.age = i; };"
+ "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
+ "for(var i = 20000; i >= 9999; i--) setAge(i);");
+ // All i >= 10000 go to the accessor.
+ ExpectInt32("obj.accessor_age", 10000);
+ // The last i goes to the interceptor.
+ ExpectInt32("obj.interceptor_age", 9999);
+ // The installed JavaScript getter is still intact.
+ // This last part is a regression test for issue 1651 and relies on the fact
+ // that both interceptor and accessor are being installed on the same object.
+ ExpectInt32("obj.age", 10000);
+ ExpectBoolean("obj.hasOwnProperty('age')", true);
+ ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
+}
+
THREADED_TEST(SwitchFromInterceptorToProperty) {
v8::HandleScope scope;
Handle<FunctionTemplate> parent = FunctionTemplate::New();
@@ -1765,7 +1846,7 @@
env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
call_recursively_script = v8_compile("callScriptRecursively()");
- v8::Handle<Value> result(call_recursively_script->Run());
+ call_recursively_script->Run();
call_recursively_script = v8::Handle<Script>();
env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
@@ -2785,6 +2866,16 @@
obj = env->Global()->Get(v8_str("obj"));
CHECK(!obj->IsInt32());
CHECK(!obj->IsUint32());
+ // Positive zero
+ CompileRun("var obj = 0.0;");
+ obj = env->Global()->Get(v8_str("obj"));
+ CHECK(obj->IsInt32());
+ CHECK(obj->IsUint32());
+ // Positive zero
+ CompileRun("var obj = -0.0;");
+ obj = env->Global()->Get(v8_str("obj"));
+ CHECK(!obj->IsInt32());
+ CHECK(!obj->IsUint32());
}
@@ -4384,7 +4475,7 @@
source = v8_str("undetectable.y = 2000;");
script = Script::Compile(source);
- Local<Value> result(script->Run());
+ script->Run();
ExpectBoolean("undetectable.y == undefined", true);
}
@@ -4737,9 +4828,10 @@
const char* extension_names[] = { name };
v8::ExtensionConfiguration extensions(1, extension_names);
v8::Handle<Context> context(Context::New(&extensions));
- ASSERT(context.IsEmpty());
+ CHECK(context.IsEmpty());
}
+
THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
v8::HandleScope handle_scope;
const char* name = "nativedeclerresc";
@@ -4751,7 +4843,7 @@
const char* extension_names[] = { name };
v8::ExtensionConfiguration extensions(1, extension_names);
v8::Handle<Context> context(Context::New(&extensions));
- ASSERT(context.IsEmpty());
+ CHECK(context.IsEmpty());
}
@@ -4917,7 +5009,7 @@
Local<Script> script =
Script::Compile(String::New(js_code_causing_huge_string_flattening));
last_location = NULL;
- Local<Value> result(script->Run());
+ script->Run();
CHECK(false); // Should not return.
}
@@ -5695,7 +5787,6 @@
v8::Handle<String> message = v8_str("message");
v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
CHECK(range_error->IsObject());
- v8::Handle<v8::Object> range_obj(range_error.As<v8::Object>());
CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
CHECK(reference_error->IsObject());
@@ -7265,7 +7356,7 @@
// Create new environment reusing the global object.
LocalContext env(NULL, instance_template, global_object);
env->Global()->Set(v8_str("foo"), foo);
- Local<Value> value(Script::Compile(v8_str("foo()"))->Run());
+ Script::Compile(v8_str("foo()"))->Run();
}
}
@@ -7591,6 +7682,7 @@
context->Global()->Set(v8_str("Fun"), cons);
Local<v8::Object> inst = cons->NewInstance();
i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
+ CHECK(obj->IsJSObject());
Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
CHECK(value->BooleanValue());
}
@@ -7859,7 +7951,7 @@
other->SetSecurityToken(token);
current->SetSecurityToken(token);
- // Setup reference from current to other.
+ // Set up reference from current to other.
current->Global()->Set(v8_str("other"), other->Global());
// Check that new variables are introduced in other context.
@@ -7939,7 +8031,7 @@
v8::Persistent<Context> context0 = Context::New();
v8::Persistent<Context> context1 = Context::New();
- // Setup function in context0 that uses eval from context0.
+ // Set up function in context0 that uses eval from context0.
context0->Enter();
v8::Handle<v8::Value> fun =
CompileRun("var x = 42;"
@@ -7977,7 +8069,7 @@
other->SetSecurityToken(token);
current->SetSecurityToken(token);
- // Setup reference from current to other.
+ // Set up reference from current to other.
current->Global()->Set(v8_str("other"), other->Global());
// Trigger lazy loading in other context.
@@ -8062,6 +8154,7 @@
{ Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
Local<ObjectTemplate> instance_template(t->InstanceTemplate());
+ USE(instance_template);
Local<v8::Object> instance = t->GetFunction()->NewInstance();
context->Global()->Set(v8_str("obj2"), instance);
v8::TryCatch try_catch;
@@ -8691,10 +8784,10 @@
0, 0, 0, v8_str("data"));
LocalContext context;
context->Global()->Set(v8_str("o"), templ->NewInstance());
- v8::Handle<Value> value(CompileRun(
- "for (var i = 0; i < 1000; i++) {"
- " o.x = 42;"
- "}"));
+ CompileRun(
+ "for (var i = 0; i < 1000; i++) {"
+ " o.x = 42;"
+ "}");
}
@@ -8820,17 +8913,6 @@
}
-static v8::Handle<Value> call_ic_function5;
-static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- if (v8_str("x")->Equals(name))
- return call_ic_function5;
- else
- return Local<Value>();
-}
-
-
// This test checks that if interceptor doesn't provide a function,
// cached constant function is used
THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
@@ -8851,6 +8933,17 @@
}
+static v8::Handle<Value> call_ic_function5;
+static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ if (v8_str("x")->Equals(name))
+ return call_ic_function5;
+ else
+ return Local<Value>();
+}
+
+
// This test checks that if interceptor provides a function,
// even if we cached constant function, interceptor's function
// is invoked
@@ -8874,6 +8967,48 @@
}
+static v8::Handle<Value> call_ic_function6;
+static v8::Handle<Value> InterceptorCallICGetter6(Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ if (v8_str("x")->Equals(name))
+ return call_ic_function6;
+ else
+ return Local<Value>();
+}
+
+
+// Same test as above, except the code is wrapped in a function
+// to test the optimized compiler.
+THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
+ i::FLAG_allow_natives_syntax = true;
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
+ LocalContext context;
+ context->Global()->Set(v8_str("o"), templ->NewInstance());
+ call_ic_function6 =
+ v8_compile("function f(x) { return x - 1; }; f")->Run();
+ v8::Handle<Value> value = CompileRun(
+ "function inc(x) { return x + 1; };"
+ "inc(1);"
+ "o.x = inc;"
+ "function test() {"
+ " var result = 0;"
+ " for (var i = 0; i < 1000; i++) {"
+ " result = o.x(42);"
+ " }"
+ " return result;"
+ "};"
+ "test();"
+ "test();"
+ "test();"
+ "%OptimizeFunctionOnNextCall(test);"
+ "test()");
+ CHECK_EQ(41, value->Int32Value());
+}
+
+
// Test the case when we stored constant function into
// a stub, but it got invalidated later on
THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
@@ -9120,11 +9255,11 @@
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"var result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = o.method(41);"
- "}"));
+ "}");
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(100, interceptor_call_count);
}
@@ -9147,14 +9282,14 @@
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
"var result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);"
- "}"));
+ "}");
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(100, interceptor_call_count);
}
@@ -9177,7 +9312,7 @@
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
@@ -9189,7 +9324,7 @@
" saved_result = result;"
" receiver = {method: function(x) { return x - 1 }};"
" }"
- "}"));
+ "}");
CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
CHECK_GE(interceptor_call_count, 50);
@@ -9213,7 +9348,7 @@
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
@@ -9225,7 +9360,7 @@
" saved_result = result;"
" o.method = function(x) { return x - 1 };"
" }"
- "}"));
+ "}");
CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
CHECK_GE(interceptor_call_count, 50);
@@ -9250,7 +9385,7 @@
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
@@ -9262,7 +9397,7 @@
" saved_result = result;"
" receiver = 333;"
" }"
- "}"));
+ "}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString());
@@ -9289,7 +9424,7 @@
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
@@ -9301,7 +9436,7 @@
" saved_result = result;"
" receiver = {method: receiver.method};"
" }"
- "}"));
+ "}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Illegal invocation"),
try_catch.Exception()->ToString());
@@ -9319,15 +9454,16 @@
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+ USE(templ);
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"var result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = o.method(41);"
- "}"));
+ "}");
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
}
@@ -9342,18 +9478,19 @@
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+ CHECK(!templ.IsEmpty());
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
"var result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);"
- "}"));
+ "}");
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
}
@@ -9368,11 +9505,12 @@
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+ CHECK(!templ.IsEmpty());
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
@@ -9384,7 +9522,7 @@
" saved_result = result;"
" receiver = {method: function(x) { return x - 1 }};"
" }"
- "}"));
+ "}");
CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
}
@@ -9399,12 +9537,13 @@
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
+ CHECK(!templ.IsEmpty());
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
@@ -9416,7 +9555,7 @@
" saved_result = result;"
" receiver = 333;"
" }"
- "}"));
+ "}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString());
@@ -9444,7 +9583,7 @@
templ->SetNamedPropertyHandler(NoBlockGetterX);
LocalContext context;
context->Global()->Set(v8_str("o"), templ->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"proto = new Object();"
"proto.y = function(x) { return x + 1; };"
"proto.z = function(x) { return x - 1; };"
@@ -9454,7 +9593,7 @@
"for (var i = 0; i < 10; i++) {"
" if (i == 5) { method = 'z'; };"
" result += o[method](41);"
- "}"));
+ "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
}
@@ -9470,7 +9609,7 @@
context->Global()->Set(v8_str("proto1"), templ->NewInstance());
keyed_call_ic_function =
v8_compile("function f(x) { return x - 1; }; f")->Run();
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"o = new Object();"
"proto2 = new Object();"
"o.y = function(x) { return x + 1; };"
@@ -9482,7 +9621,7 @@
"for (var i = 0; i < 10; i++) {"
" if (i == 5) { method = 'y'; };"
" result += o[method](41);"
- "}"));
+ "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
}
@@ -9495,7 +9634,7 @@
templ->SetNamedPropertyHandler(NoBlockGetterX);
LocalContext context;
context->Global()->Set(v8_str("o"), templ->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"function inc(x) { return x + 1; };"
"inc(1);"
"function dec(x) { return x - 1; };"
@@ -9508,7 +9647,7 @@
"for (var i = 0; i < 10; i++) {"
" if (i == 5) { method = 'y'; };"
" result += o[method](41);"
- "}"));
+ "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
}
@@ -9521,7 +9660,7 @@
LocalContext context;
context->Global()->Set(v8_str("o"), templ_o->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"function len(x) { return x.length; };"
"o.__proto__ = this;"
"var m = 'parseFloat';"
@@ -9532,7 +9671,7 @@
" saved_result = result;"
" };"
" result = o[m]('239');"
- "}"));
+ "}");
CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
}
@@ -9545,7 +9684,7 @@
LocalContext context;
context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"var o = new Object();"
"o.__proto__ = proto;"
"o.method = function(x) { return x + 1; };"
@@ -9554,7 +9693,7 @@
"for (var i = 0; i < 10; i++) {"
" if (i == 5) { o.method = function(x) { return x - 1; }; };"
" result += o[m](41);"
- "}"));
+ "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
}
@@ -9567,7 +9706,7 @@
LocalContext context;
context->Global()->Set(v8_str("o"), templ_o->NewInstance());
- v8::Handle<Value> value(CompileRun(
+ CompileRun(
"var proto = new Object();"
"o.__proto__ = proto;"
"proto.method = function(x) { return x + 1; };"
@@ -9576,7 +9715,7 @@
"for (var i = 0; i < 10; i++) {"
" if (i == 5) { proto.method = function(x) { return x - 1; }; };"
" result += o[m](41);"
- "}"));
+ "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
}
@@ -10088,7 +10227,7 @@
static unsigned linear_congruential_generator;
-void ApiTestFuzzer::Setup(PartOfTest part) {
+void ApiTestFuzzer::SetUp(PartOfTest part) {
linear_congruential_generator = i::FLAG_testing_prng_seed;
fuzzing_ = true;
int count = RegisterThreadedTest::count();
@@ -10152,25 +10291,25 @@
// Lets not be needlessly self-referential.
TEST(Threading) {
- ApiTestFuzzer::Setup(ApiTestFuzzer::FIRST_PART);
+ ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
ApiTestFuzzer::RunAllTests();
ApiTestFuzzer::TearDown();
}
TEST(Threading2) {
- ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART);
+ ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
ApiTestFuzzer::RunAllTests();
ApiTestFuzzer::TearDown();
}
TEST(Threading3) {
- ApiTestFuzzer::Setup(ApiTestFuzzer::THIRD_PART);
+ ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
ApiTestFuzzer::RunAllTests();
ApiTestFuzzer::TearDown();
}
TEST(Threading4) {
- ApiTestFuzzer::Setup(ApiTestFuzzer::FOURTH_PART);
+ ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
ApiTestFuzzer::RunAllTests();
ApiTestFuzzer::TearDown();
}
@@ -10493,6 +10632,7 @@
env->Enter();
v8::Handle<Value> value = NestedScope(env);
v8::Handle<String> str(value->ToString());
+ CHECK(!str.IsEmpty());
env->Exit();
env.Dispose();
}
@@ -10501,6 +10641,7 @@
THREADED_TEST(ExternalAllocatedMemory) {
v8::HandleScope outer;
v8::Persistent<Context> env(Context::New());
+ CHECK(!env.IsEmpty());
const int kSize = 1024*1024;
CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize);
CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0);
@@ -10839,6 +10980,7 @@
i::FunctionTemplateInfo::cast(internal_template->constructor()));
CHECK(!constructor->access_check_info()->IsUndefined());
v8::Persistent<Context> context0(Context::New(NULL, global_template));
+ CHECK(!context0.IsEmpty());
CHECK(!constructor->access_check_info()->IsUndefined());
}
@@ -12029,7 +12171,7 @@
callback_templ->GetFunction());
calling_context0->Exit();
- // Expose context0 in context1 and setup a function that calls the
+ // Expose context0 in context1 and set up a function that calls the
// callback function.
calling_context1->Enter();
calling_context1->Global()->Set(v8_str("context0"),
@@ -12187,18 +12329,18 @@
i::Handle<i::Smi> value(i::Smi::FromInt(2));
i::Handle<i::Object> no_failure;
- no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ no_failure = i::JSObject::SetElement(jsobj, 1, value, i::kNonStrictMode);
ASSERT(!no_failure.is_null());
i::USE(no_failure);
CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
*value.location() = i::Smi::FromInt(256);
- no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ no_failure = i::JSObject::SetElement(jsobj, 1, value, i::kNonStrictMode);
ASSERT(!no_failure.is_null());
i::USE(no_failure);
CHECK_EQ(255,
i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
*value.location() = i::Smi::FromInt(-1);
- no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode);
+ no_failure = i::JSObject::SetElement(jsobj, 1, value, i::kNonStrictMode);
ASSERT(!no_failure.is_null());
i::USE(no_failure);
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
@@ -12914,11 +13056,6 @@
const int kLargeElementCount = kXSize * kYSize * 4;
ElementType* large_array_data =
static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
- i::Handle<ExternalArrayClass> large_array(
- i::Handle<ExternalArrayClass>::cast(
- FACTORY->NewExternalArray(kLargeElementCount,
- array_type,
- array_data)));
v8::Handle<v8::Object> large_obj = v8::Object::New();
// Set the elements to be the external array.
large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
@@ -13319,8 +13456,8 @@
v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
v8::Handle<Value> overview_result(
v8::Script::New(overview_src, origin)->Run());
- ASSERT(!overview_result.IsEmpty());
- ASSERT(overview_result->IsObject());
+ CHECK(!overview_result.IsEmpty());
+ CHECK(overview_result->IsObject());
// Test getting DETAILED information.
const char *detailed_source =
@@ -13339,8 +13476,8 @@
v8::Handle<v8::Script> detailed_script(
v8::Script::New(detailed_src, &detailed_origin));
v8::Handle<Value> detailed_result(detailed_script->Run());
- ASSERT(!detailed_result.IsEmpty());
- ASSERT(detailed_result->IsObject());
+ CHECK(!detailed_result.IsEmpty());
+ CHECK(detailed_result->IsObject());
}
@@ -13438,7 +13575,23 @@
// Test that idle notification can be handled and eventually returns true.
+// This just checks the contract of the IdleNotification() function,
+// and does not verify that it does reasonable work.
THREADED_TEST(IdleNotification) {
+ v8::HandleScope scope;
+ LocalContext env;
+ CompileRun("function binom(n, m) {"
+ " var C = [[1]];"
+ " for (var i = 1; i <= n; ++i) {"
+ " C[i] = [1];"
+ " for (var j = 1; j < i; ++j) {"
+ " C[i][j] = C[i-1][j-1] + C[i-1][j];"
+ " }"
+ " C[i][i] = 1;"
+ " }"
+ " return C[n][m];"
+ "};"
+ "binom(1000, 500)");
bool rv = false;
for (int i = 0; i < 100; i++) {
rv = v8::V8::IdleNotification();
@@ -13448,6 +13601,40 @@
CHECK(rv == true);
}
+// Test that idle notification can be handled and eventually returns true.
+// This just checks the contract of the IdleNotification() function,
+// and does not verify that it does reasonable work.
+TEST(IdleNotificationWithHint) {
+ v8::HandleScope scope;
+ LocalContext env;
+ {
+ i::AlwaysAllocateScope always_allocate;
+ CompileRun("function binom(n, m) {"
+ " var C = [[1]];"
+ " for (var i = 1; i <= n; ++i) {"
+ " C[i] = [1];"
+ " for (var j = 1; j < i; ++j) {"
+ " C[i][j] = C[i-1][j-1] + C[i-1][j];"
+ " }"
+ " C[i][i] = 1;"
+ " }"
+ " return C[n][m];"
+ "};"
+ "binom(1000, 500)");
+ }
+ bool rv = false;
+ intptr_t old_size = HEAP->SizeOfObjects();
+ bool no_idle_work = v8::V8::IdleNotification(10);
+ for (int i = 0; i < 200; i++) {
+ rv = v8::V8::IdleNotification(10);
+ if (rv)
+ break;
+ }
+ CHECK(rv == true);
+ intptr_t new_size = HEAP->SizeOfObjects();
+ CHECK(no_idle_work || new_size < old_size);
+}
+
static uint32_t* stack_limit;
@@ -13536,6 +13723,63 @@
}
+class VisitorImpl : public v8::ExternalResourceVisitor {
+ public:
+ VisitorImpl(TestResource* r1, TestResource* r2)
+ : resource1_(r1),
+ resource2_(r2),
+ found_resource1_(false),
+ found_resource2_(false) {}
+ virtual ~VisitorImpl() {}
+ virtual void VisitExternalString(v8::Handle<v8::String> string) {
+ if (!string->IsExternal()) {
+ CHECK(string->IsExternalAscii());
+ return;
+ }
+ v8::String::ExternalStringResource* resource =
+ string->GetExternalStringResource();
+ CHECK(resource);
+ if (resource1_ == resource) {
+ CHECK(!found_resource1_);
+ found_resource1_ = true;
+ }
+ if (resource2_ == resource) {
+ CHECK(!found_resource2_);
+ found_resource2_ = true;
+ }
+ }
+ void CheckVisitedResources() {
+ CHECK(found_resource1_);
+ CHECK(found_resource2_);
+ }
+
+ private:
+ v8::String::ExternalStringResource* resource1_;
+ v8::String::ExternalStringResource* resource2_;
+ bool found_resource1_;
+ bool found_resource2_;
+};
+
+TEST(VisitExternalStrings) {
+ v8::HandleScope scope;
+ LocalContext env;
+ const char* string = "Some string";
+ uint16_t* two_byte_string = AsciiToTwoByteString(string);
+ TestResource* resource1 = new TestResource(two_byte_string);
+ v8::Local<v8::String> string1 = v8::String::NewExternal(resource1);
+ TestResource* resource2 = new TestResource(two_byte_string);
+ v8::Local<v8::String> string2 = v8::String::NewExternal(resource2);
+
+ // We need to add usages for string1 and string2 to avoid warnings in GCC 4.7
+ CHECK(string1->IsExternal());
+ CHECK(string2->IsExternal());
+
+ VisitorImpl visitor(resource1, resource2);
+ v8::V8::VisitExternalResources(&visitor);
+ visitor.CheckVisitedResources();
+}
+
+
static double DoubleFromBits(uint64_t value) {
double target;
memcpy(&target, &value, sizeof(target));
@@ -13653,6 +13897,7 @@
v8::HandleScope scope;
v8::TryCatch tc;
v8::Handle<v8::String> str(args[0]->ToString());
+ USE(str);
if (tc.HasCaught())
return tc.ReThrow();
return v8::Undefined();
@@ -13797,6 +14042,17 @@
CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
}
+THREADED_TEST(FunctionGetInferredName) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
+ v8::Handle<v8::String> script = v8::String::New(
+ "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
+ v8::Script::Compile(script, &origin)->Run();
+ v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("f")));
+ CHECK_EQ("foo.bar.baz", *v8::String::AsciiValue(f->GetInferredName()));
+}
THREADED_TEST(ScriptLineNumber) {
v8::HandleScope scope;
@@ -14109,7 +14365,7 @@
" for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
" for (var i = 0; i < 16; i++) {"
" var v = %_GetFromCache(0, keys[i]);"
- " if (v !== values[i])"
+ " if (v.toString() !== values[i].toString())"
" return 'Wrong value for ' + "
" keys[i] + ': ' + v + ' vs. ' + values[i];"
" };"
@@ -14951,7 +15207,7 @@
// RegExps are objects on which you can set properties.
re->Set(v8_str("property"), v8::Integer::New(32));
v8::Handle<v8::Value> value(CompileRun("re.property"));
- ASSERT_EQ(32, value->Int32Value());
+ CHECK_EQ(32, value->Int32Value());
v8::TryCatch try_catch;
re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
@@ -15597,3 +15853,98 @@
foreign_context.Dispose();
}
+
+
+uint8_t callback_fired = 0;
+
+
+void CallCompletedCallback1() {
+ i::OS::Print("Firing callback 1.\n");
+ callback_fired ^= 1; // Toggle first bit.
+}
+
+
+void CallCompletedCallback2() {
+ i::OS::Print("Firing callback 2.\n");
+ callback_fired ^= 2; // Toggle second bit.
+}
+
+
+Handle<Value> RecursiveCall(const Arguments& args) {
+ int32_t level = args[0]->Int32Value();
+ if (level < 3) {
+ level++;
+ i::OS::Print("Entering recursion level %d.\n", level);
+ char script[64];
+ i::Vector<char> script_vector(script, sizeof(script));
+ i::OS::SNPrintF(script_vector, "recursion(%d)", level);
+ CompileRun(script_vector.start());
+ i::OS::Print("Leaving recursion level %d.\n", level);
+ CHECK_EQ(0, callback_fired);
+ } else {
+ i::OS::Print("Recursion ends.\n");
+ CHECK_EQ(0, callback_fired);
+ }
+ return Undefined();
+}
+
+
+TEST(CallCompletedCallback) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::Handle<v8::FunctionTemplate> recursive_runtime =
+ v8::FunctionTemplate::New(RecursiveCall);
+ env->Global()->Set(v8_str("recursion"),
+ recursive_runtime->GetFunction());
+ // Adding the same callback a second time has no effect.
+ v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
+ v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
+ v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
+ i::OS::Print("--- Script (1) ---\n");
+ Local<Script> script =
+ v8::Script::Compile(v8::String::New("recursion(0)"));
+ script->Run();
+ CHECK_EQ(3, callback_fired);
+
+ i::OS::Print("\n--- Script (2) ---\n");
+ callback_fired = 0;
+ v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
+ script->Run();
+ CHECK_EQ(2, callback_fired);
+
+ i::OS::Print("\n--- Function ---\n");
+ callback_fired = 0;
+ Local<Function> recursive_function =
+ Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
+ v8::Handle<Value> args[] = { v8_num(0) };
+ recursive_function->Call(env->Global(), 1, args);
+ CHECK_EQ(2, callback_fired);
+}
+
+
+void CallCompletedCallbackNoException() {
+ v8::HandleScope scope;
+ CompileRun("1+1;");
+}
+
+
+void CallCompletedCallbackException() {
+ v8::HandleScope scope;
+ CompileRun("throw 'second exception';");
+}
+
+
+TEST(CallCompletedCallbackOneException) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
+ CompileRun("throw 'exception';");
+}
+
+
+TEST(CallCompletedCallbackTwoExceptions) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
+ CompileRun("throw 'first exception';");
+}