Index: test/cctest/test-api.cc |
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
index 2093dbb29295db0389cb3ca1e50c506cf822347f..b4f962c1415544ca8812ab299a4cc27d9279cd6c 100644 |
--- a/test/cctest/test-api.cc |
+++ b/test/cctest/test-api.cc |
@@ -805,66 +805,211 @@ THREADED_TEST(GlobalProperties) { |
} |
+template<typename T> |
+static void CheckReturnValue(const T& t) { |
+ v8::ReturnValue<v8::Value> rv = t.GetReturnValue(); |
+ i::Object** o = *reinterpret_cast<i::Object***>(&rv); |
+ CHECK_EQ(t.GetIsolate(), v8::Isolate::GetCurrent()); |
+ CHECK((*o)->IsTheHole() || (*o)->IsUndefined()); |
+} |
+ |
static v8::Handle<Value> handle_call(const v8::Arguments& args) { |
ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(args); |
+ args.GetReturnValue().Set(v8_str("bad value")); |
return v8_num(102); |
} |
+static v8::Handle<Value> handle_call_indirect(const v8::Arguments& args) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(args); |
+ args.GetReturnValue().Set(v8_str("bad value")); |
+ args.GetReturnValue().Set(v8_num(102)); |
+ return v8::Handle<Value>(); |
+} |
+ |
+static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(info); |
+ info.GetReturnValue().Set(v8_str("bad value")); |
+ info.GetReturnValue().Set(v8_num(102)); |
+} |
+ |
static v8::Handle<Value> construct_call(const v8::Arguments& args) { |
ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(args); |
args.This()->Set(v8_str("x"), v8_num(1)); |
args.This()->Set(v8_str("y"), v8_num(2)); |
+ args.GetReturnValue().Set(v8_str("bad value")); |
return args.This(); |
} |
-static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) { |
+static v8::Handle<Value> construct_call_indirect(const v8::Arguments& args) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(args); |
+ args.This()->Set(v8_str("x"), v8_num(1)); |
+ args.This()->Set(v8_str("y"), v8_num(2)); |
+ args.GetReturnValue().Set(v8_str("bad value")); |
+ args.GetReturnValue().Set(args.This()); |
+ return v8::Handle<Value>(); |
+} |
+ |
+static void construct_callback( |
+ const v8::FunctionCallbackInfo<Value>& info) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(info); |
+ info.This()->Set(v8_str("x"), v8_num(1)); |
+ info.This()->Set(v8_str("y"), v8_num(2)); |
+ info.GetReturnValue().Set(v8_str("bad value")); |
+ info.GetReturnValue().Set(info.This()); |
+} |
+ |
+ |
+static v8::Handle<Value> Return239( |
+ Local<String> name, const AccessorInfo& info) { |
ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(info); |
+ info.GetReturnValue().Set(v8_str("bad value")); |
return v8_num(239); |
} |
+static v8::Handle<Value> Return239Indirect( |
+ Local<String> name, const AccessorInfo& info) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(info); |
+ Handle<Value> value = v8_num(239); |
+ info.GetReturnValue().Set(v8_str("bad value")); |
+ info.GetReturnValue().Set(value); |
+ return v8::Handle<Value>(); |
+} |
-THREADED_TEST(FunctionTemplate) { |
- LocalContext env; |
- v8::HandleScope scope(env->GetIsolate()); |
+static void Return239Callback( |
+ Local<String> name, const v8::PropertyCallbackInfo<Value>& info) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(info); |
+ info.GetReturnValue().Set(v8_str("bad value")); |
+ info.GetReturnValue().Set(v8_num(239)); |
+} |
+ |
+ |
+template<typename Handler> |
+static void TestFunctionTemplateInitializer(Handler handler) { |
+ // Test constructor calls. |
{ |
+ LocalContext env; |
+ v8::HandleScope scope(env->GetIsolate()); |
Local<v8::FunctionTemplate> fun_templ = |
- v8::FunctionTemplate::New(handle_call); |
+ v8::FunctionTemplate::New(handler); |
Local<Function> fun = fun_templ->GetFunction(); |
env->Global()->Set(v8_str("obj"), fun); |
Local<Script> script = v8_compile("obj()"); |
- CHECK_EQ(102, script->Run()->Int32Value()); |
+ for (int i = 0; i < 30; i++) { |
+ CHECK_EQ(102, script->Run()->Int32Value()); |
+ } |
} |
// Use SetCallHandler to initialize a function template, should work like the |
// previous one. |
{ |
+ LocalContext env; |
+ v8::HandleScope scope(env->GetIsolate()); |
Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
- fun_templ->SetCallHandler(handle_call); |
+ fun_templ->SetCallHandler(handler); |
Local<Function> fun = fun_templ->GetFunction(); |
env->Global()->Set(v8_str("obj"), fun); |
Local<Script> script = v8_compile("obj()"); |
- CHECK_EQ(102, script->Run()->Int32Value()); |
+ for (int i = 0; i < 30; i++) { |
+ CHECK_EQ(102, script->Run()->Int32Value()); |
+ } |
} |
- // Test constructor calls. |
- { |
- Local<v8::FunctionTemplate> fun_templ = |
- v8::FunctionTemplate::New(construct_call); |
- fun_templ->SetClassName(v8_str("funky")); |
- fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), Return239); |
- Local<Function> fun = fun_templ->GetFunction(); |
- env->Global()->Set(v8_str("obj"), fun); |
- Local<Script> script = v8_compile("var s = new obj(); s.x"); |
+} |
+ |
+ |
+template<typename Constructor, typename Accessor> |
+static void TestFunctionTemplateAccessor(Constructor constructor, |
+ Accessor accessor) { |
+ LocalContext env; |
+ v8::HandleScope scope(env->GetIsolate()); |
+ Local<v8::FunctionTemplate> fun_templ = |
+ v8::FunctionTemplate::New(constructor); |
+ fun_templ->SetClassName(v8_str("funky")); |
+ fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor); |
+ Local<Function> fun = fun_templ->GetFunction(); |
+ env->Global()->Set(v8_str("obj"), fun); |
+ Local<Value> result = v8_compile("(new obj()).toString()")->Run(); |
+ CHECK_EQ(v8_str("[object funky]"), result); |
+ CompileRun("var obj_instance = new obj();"); |
+ Local<Script> script; |
+ script = v8_compile("obj_instance.x"); |
+ for (int i = 0; i < 30; i++) { |
CHECK_EQ(1, script->Run()->Int32Value()); |
+ } |
+ script = v8_compile("obj_instance.m"); |
+ for (int i = 0; i < 30; i++) { |
+ CHECK_EQ(239, script->Run()->Int32Value()); |
+ } |
+} |
+ |
+ |
+THREADED_TEST(FunctionTemplate) { |
+ TestFunctionTemplateInitializer(handle_call); |
+ TestFunctionTemplateInitializer(handle_call_indirect); |
+ TestFunctionTemplateInitializer(handle_callback); |
+ |
+ TestFunctionTemplateAccessor(construct_call, Return239); |
+ TestFunctionTemplateAccessor(construct_call_indirect, Return239Indirect); |
+ TestFunctionTemplateAccessor(construct_callback, Return239Callback); |
+} |
+ |
+ |
+static v8::Handle<v8::Value> SimpleDirectCallback(const v8::Arguments& args) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(args); |
+ args.GetReturnValue().Set(v8_str("bad value")); |
+ return v8_num(51423 + args.Length()); |
+} |
+ |
+static v8::Handle<v8::Value> SimpleIndirectCallback(const v8::Arguments& args) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(args); |
+ args.GetReturnValue().Set(v8_num(51423 + args.Length())); |
+ return v8::Handle<v8::Value>(); |
+} |
+ |
+static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { |
+ ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(info); |
+ info.GetReturnValue().Set(v8_num(51423 + info.Length())); |
+} |
- Local<Value> result = v8_compile("(new obj()).toString()")->Run(); |
- CHECK_EQ(v8_str("[object funky]"), result); |
- result = v8_compile("(new obj()).m")->Run(); |
- CHECK_EQ(239, result->Int32Value()); |
+template<typename Callback> |
+static void TestSimpleCallback(Callback callback) { |
+ LocalContext env; |
+ v8::HandleScope scope(env->GetIsolate()); |
+ v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New(); |
+ object_template->Set("callback", v8::FunctionTemplate::New(callback)); |
+ v8::Local<v8::Object> object = object_template->NewInstance(); |
+ (*env)->Global()->Set(v8_str("callback_object"), object); |
+ v8::Handle<v8::Script> script; |
+ script = v8_compile("callback_object.callback(17)"); |
+ for (int i = 0; i < 30; i++) { |
+ CHECK_EQ(51424, script->Run()->Int32Value()); |
+ } |
+ script = v8_compile("callback_object.callback(17, 24)"); |
+ for (int i = 0; i < 30; i++) { |
+ CHECK_EQ(51425, script->Run()->Int32Value()); |
} |
} |
+THREADED_TEST(SimpleCallback) { |
+ TestSimpleCallback(SimpleDirectCallback); |
+ TestSimpleCallback(SimpleIndirectCallback); |
+ TestSimpleCallback(SimpleCallback); |
+} |
+ |
+ |
THREADED_TEST(FunctionTemplateSetLength) { |
LocalContext env; |
v8::HandleScope scope(env->GetIsolate()); |
@@ -4649,7 +4794,10 @@ THREADED_TEST(SetterOnly) { |
THREADED_TEST(NoAccessors) { |
v8::HandleScope scope(v8::Isolate::GetCurrent()); |
Local<ObjectTemplate> templ = ObjectTemplate::New(); |
- templ->SetAccessor(v8_str("x"), NULL, NULL, v8_str("donut")); |
+ templ->SetAccessor(v8_str("x"), |
+ static_cast<v8::AccessorGetter>(NULL), |
+ NULL, |
+ v8_str("donut")); |
LocalContext context; |
context->Global()->Set(v8_str("obj"), templ->NewInstance()); |
Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x")); |
@@ -5308,8 +5456,7 @@ THREADED_TEST(UndetectableObject) { |
LocalContext env; |
v8::HandleScope scope(env->GetIsolate()); |
- Local<v8::FunctionTemplate> desc = |
- v8::FunctionTemplate::New(0, v8::Handle<Value>()); |
+ Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(); |
desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable |
Local<v8::Object> obj = desc->GetFunction()->NewInstance(); |
@@ -5352,8 +5499,7 @@ THREADED_TEST(VoidLiteral) { |
LocalContext env; |
v8::HandleScope scope(env->GetIsolate()); |
- Local<v8::FunctionTemplate> desc = |
- v8::FunctionTemplate::New(0, v8::Handle<Value>()); |
+ Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(); |
desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable |
Local<v8::Object> obj = desc->GetFunction()->NewInstance(); |
@@ -5396,8 +5542,7 @@ THREADED_TEST(ExtensibleOnUndetectable) { |
LocalContext env; |
v8::HandleScope scope(env->GetIsolate()); |
- Local<v8::FunctionTemplate> desc = |
- v8::FunctionTemplate::New(0, v8::Handle<Value>()); |
+ Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(); |
desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable |
Local<v8::Object> obj = desc->GetFunction()->NewInstance(); |
@@ -10398,6 +10543,7 @@ THREADED_TEST(InterceptorCallICCachedFromGlobal) { |
static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, |
const AccessorInfo& info) { |
ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(info); |
int* call_count = |
reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value()); |
++(*call_count); |
@@ -10410,6 +10556,7 @@ static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, |
static v8::Handle<Value> FastApiCallback_TrivialSignature( |
const v8::Arguments& args) { |
ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(args); |
v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
CHECK_EQ(isolate, args.GetIsolate()); |
CHECK_EQ(args.This(), args.Holder()); |
@@ -10420,6 +10567,7 @@ static v8::Handle<Value> FastApiCallback_TrivialSignature( |
static v8::Handle<Value> FastApiCallback_SimpleSignature( |
const v8::Arguments& args) { |
ApiTestFuzzer::Fuzz(); |
+ CheckReturnValue(args); |
v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
CHECK_EQ(isolate, args.GetIsolate()); |
CHECK_EQ(args.This()->GetPrototype(), args.Holder()); |
@@ -10497,29 +10645,59 @@ THREADED_TEST(CallICFastApi_DirectCall_Throw) { |
} |
-v8::Handle<v8::Value> DirectGetterCallback(Local<String> name, |
- const v8::AccessorInfo& info) { |
+static Handle<Value> DoDirectGetter() { |
if (++p_getter_count % 3 == 0) { |
HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
GenerateSomeGarbage(); |
} |
+ return v8_str("Direct Getter Result"); |
+} |
+ |
+static v8::Handle<v8::Value> DirectGetter(Local<String> name, |
+ const v8::AccessorInfo& info) { |
+ CheckReturnValue(info); |
+ info.GetReturnValue().Set(v8_str("Garbage")); |
+ return DoDirectGetter(); |
+} |
+ |
+static v8::Handle<v8::Value> DirectGetterIndirect( |
+ Local<String> name, |
+ const v8::AccessorInfo& info) { |
+ CheckReturnValue(info); |
+ info.GetReturnValue().Set(DoDirectGetter()); |
return v8::Handle<v8::Value>(); |
} |
+static void DirectGetterCallback( |
+ Local<String> name, |
+ const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ CheckReturnValue(info); |
+ info.GetReturnValue().Set(DoDirectGetter()); |
+} |
-THREADED_TEST(LoadICFastApi_DirectCall_GCMoveStub) { |
+ |
+template<typename Accessor> |
+static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) { |
LocalContext context; |
v8::HandleScope scope(context->GetIsolate()); |
v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(); |
- obj->SetAccessor(v8_str("p1"), DirectGetterCallback); |
+ obj->SetAccessor(v8_str("p1"), accessor); |
context->Global()->Set(v8_str("o1"), obj->NewInstance()); |
p_getter_count = 0; |
- CompileRun( |
+ v8::Handle<v8::Value> result = CompileRun( |
"function f() {" |
" for (var i = 0; i < 30; i++) o1.p1;" |
+ " return o1.p1" |
"}" |
"f();"); |
- CHECK_EQ(30, p_getter_count); |
+ CHECK_EQ(v8_str("Direct Getter Result"), result); |
+ CHECK_EQ(31, p_getter_count); |
+} |
+ |
+THREADED_TEST(LoadICFastApi_DirectCall_GCMoveStub) { |
+ LoadICFastApi_DirectCall_GCMoveStub(DirectGetterIndirect); |
+ LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback); |
+ LoadICFastApi_DirectCall_GCMoveStub(DirectGetter); |
} |
@@ -11198,7 +11376,7 @@ THREADED_TEST(InterceptorICSetterExceptions) { |
THREADED_TEST(NullNamedInterceptor) { |
v8::HandleScope scope(v8::Isolate::GetCurrent()); |
v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(); |
- templ->SetNamedPropertyHandler(0); |
+ templ->SetNamedPropertyHandler(static_cast<v8::NamedPropertyGetter>(0)); |
LocalContext context; |
templ->Set("x", v8_num(42)); |
v8::Handle<v8::Object> obj = templ->NewInstance(); |
@@ -11213,7 +11391,7 @@ THREADED_TEST(NullNamedInterceptor) { |
THREADED_TEST(NullIndexedInterceptor) { |
v8::HandleScope scope(v8::Isolate::GetCurrent()); |
v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(); |
- templ->SetIndexedPropertyHandler(0); |
+ templ->SetIndexedPropertyHandler(static_cast<v8::IndexedPropertyGetter>(0)); |
LocalContext context; |
templ->Set("42", v8_num(42)); |
v8::Handle<v8::Object> obj = templ->NewInstance(); |