diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-10-11 15:06:25 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-19 20:48:25 +0200 |
commit | 7dc5973bf12919d2d35230844beabe558d4faa00 (patch) | |
tree | 88d6128a911d2ec3b9a72d8e45d56fc2b250c714 /src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch | |
parent | 4dc25c1f2995a5e02da47f0f6f3522af9eb6f78c (diff) |
Update V8
Change-Id: I7a9da7dbb2116a441788407d60ed10155cded941
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch')
-rw-r--r-- | src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch | 398 |
1 files changed, 0 insertions, 398 deletions
diff --git a/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch b/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch deleted file mode 100644 index 847cb8657e..0000000000 --- a/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch +++ /dev/null @@ -1,398 +0,0 @@ -From 3ba270e3b93d292dc53a675a21479bdb0b50bbbe Mon Sep 17 00:00:00 2001 -From: ager@chromium.org <ager@chromium.org> -Date: Fri, 6 May 2011 11:07:52 +0000 -Subject: [PATCH 10/16] Implement CallAsConstructor method for Object in the - API - -Patch by Peter Varga. - -BUG=v8:1348 -TEST=cctest/test-api/ConstructorForObject - -Review URL: http://codereview.chromium.org/6902108 - -git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7803 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 ---- - include/v8.h | 8 ++ - src/api.cc | 41 +++++++++- - src/execution.cc | 28 +++++++ - src/execution.h | 2 + - test/cctest/test-api.cc | 205 +++++++++++++++++++++++++++++++++++++++++++++-- - 5 files changed, 276 insertions(+), 8 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 277153e..18527e1 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1766,6 +1766,14 @@ class Object : public Value { - int argc, - Handle<Value> argv[]); - -+ /** -+ * Call an Object as a consturctor if a callback is set by the -+ * ObjectTemplate::SetCallAsFunctionHandler method. -+ * Note: This method behaves like the Function::NewInstance method. -+ */ -+ V8EXPORT Local<Value> CallAsConstructor(int argc, -+ Handle<Value> argv[]); -+ - V8EXPORT static Local<Object> New(); - static inline Object* Cast(Value* obj); - private: -diff --git a/src/api.cc b/src/api.cc -index e412e51..1a585d6 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3266,7 +3266,7 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, - return Local<v8::Value>()); - LOG_API(isolate, "Object::CallAsFunction"); - ENTER_V8(isolate); -- HandleScope scope; -+ i::HandleScope scope(isolate); - i::Handle<i::JSObject> obj = Utils::OpenHandle(this); - i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); - STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); -@@ -3286,7 +3286,44 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, - i::Handle<i::Object> returned = - i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception); - EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); -- return scope.Close(Utils::ToLocal(returned)); -+ return Utils::ToLocal(scope.CloseAndEscape(returned)); -+} -+ -+ -+Local<v8::Value> Object::CallAsConstructor(int argc, -+ v8::Handle<v8::Value> argv[]) { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()", -+ return Local<v8::Object>()); -+ LOG_API(isolate, "Object::CallAsConstructor"); -+ ENTER_V8(isolate); -+ i::HandleScope scope(isolate); -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); -+ i::Object*** args = reinterpret_cast<i::Object***>(argv); -+ if (obj->IsJSFunction()) { -+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj); -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> returned = -+ i::Execution::New(fun, argc, args, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ return Utils::ToLocal(scope.CloseAndEscape( -+ i::Handle<i::JSObject>::cast(returned))); -+ } -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> delegate = -+ i::Execution::TryGetConstructorDelegate(obj, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ if (!delegate->IsUndefined()) { -+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate); -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> returned = -+ i::Execution::Call(fun, obj, argc, args, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ ASSERT(!delegate->IsUndefined()); -+ return Utils::ToLocal(scope.CloseAndEscape(returned)); -+ } -+ return Local<v8::Object>(); - } - - -diff --git a/src/execution.cc b/src/execution.cc -index 894d741..afb352c 100644 ---- a/src/execution.cc -+++ b/src/execution.cc -@@ -297,6 +297,34 @@ Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { - } - - -+Handle<Object> Execution::TryGetConstructorDelegate( -+ Handle<Object> object, -+ bool* has_pending_exception) { -+ ASSERT(!object->IsJSFunction()); -+ Isolate* isolate = Isolate::Current(); -+ -+ // If you return a function from here, it will be called when an -+ // attempt is made to call the given object as a constructor. -+ -+ // Objects created through the API can have an instance-call handler -+ // that should be used when calling the object as a function. -+ if (object->IsHeapObject() && -+ HeapObject::cast(*object)->map()->has_instance_call_handler()) { -+ return Handle<JSFunction>( -+ isolate->global_context()->call_as_constructor_delegate()); -+ } -+ -+ // If the Object doesn't have an instance-call handler we should -+ // throw a non-callable exception. -+ i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( -+ "called_non_callable", i::HandleVector<i::Object>(&object, 1)); -+ isolate->Throw(*error_obj); -+ *has_pending_exception = true; -+ -+ return isolate->factory()->undefined_value(); -+} -+ -+ - bool StackGuard::IsStackOverflow() { - ExecutionAccess access(isolate_); - return (thread_local_.jslimit_ != kInterruptLimit && -diff --git a/src/execution.h b/src/execution.h -index 0a0be51..ec2a195 100644 ---- a/src/execution.h -+++ b/src/execution.h -@@ -150,6 +150,8 @@ class Execution : public AllStatic { - // Get a function delegate (or undefined) for the given non-function - // object. Used for support calling objects as constructors. - static Handle<Object> GetConstructorDelegate(Handle<Object> object); -+ static Handle<Object> TryGetConstructorDelegate(Handle<Object> object, -+ bool* has_pending_exception); - }; - - -diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc -index 693d51e..1334f63 100644 ---- a/test/cctest/test-api.cc -+++ b/test/cctest/test-api.cc -@@ -6746,6 +6746,200 @@ THREADED_TEST(Constructor) { - CHECK(value->BooleanValue()); - } - -+ -+static Handle<Value> ConstructorCallback(const Arguments& args) { -+ ApiTestFuzzer::Fuzz(); -+ Local<Object> This; -+ -+ if (args.IsConstructCall()) { -+ Local<Object> Holder = args.Holder(); -+ This = Object::New(); -+ Local<Value> proto = Holder->GetPrototype(); -+ if (proto->IsObject()) { -+ This->SetPrototype(proto); -+ } -+ } else { -+ This = args.This(); -+ } -+ -+ This->Set(v8_str("a"), args[0]); -+ return This; -+} -+ -+ -+static Handle<Value> FakeConstructorCallback(const Arguments& args) { -+ ApiTestFuzzer::Fuzz(); -+ return args[0]; -+} -+ -+ -+THREADED_TEST(ConstructorForObject) { -+ v8::HandleScope handle_scope; -+ LocalContext context; -+ -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(ConstructorCallback); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ // Call the Object's constructor with a 32-bit signed integer. -+ value = CompileRun("(function() { var o = new obj(28); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsInt32()); -+ CHECK_EQ(28, value->Int32Value()); -+ -+ Local<Value> args1[] = { v8_num(28) }; -+ Local<Value> value_obj1 = instance->CallAsConstructor(1, args1); -+ CHECK(value_obj1->IsObject()); -+ Local<Object> object1 = Local<Object>::Cast(value_obj1); -+ value = object1->Get(v8_str("a")); -+ CHECK(value->IsInt32()); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(28, value->Int32Value()); -+ -+ // Call the Object's constructor with a String. -+ value = CompileRun( -+ "(function() { var o = new obj('tipli'); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsString()); -+ String::AsciiValue string_value1(value->ToString()); -+ CHECK_EQ("tipli", *string_value1); -+ -+ Local<Value> args2[] = { v8_str("tipli") }; -+ Local<Value> value_obj2 = instance->CallAsConstructor(1, args2); -+ CHECK(value_obj2->IsObject()); -+ Local<Object> object2 = Local<Object>::Cast(value_obj2); -+ value = object2->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsString()); -+ String::AsciiValue string_value2(value->ToString()); -+ CHECK_EQ("tipli", *string_value2); -+ -+ // Call the Object's constructor with a Boolean. -+ value = CompileRun("(function() { var o = new obj(true); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsBoolean()); -+ CHECK_EQ(true, value->BooleanValue()); -+ -+ Handle<Value> args3[] = { v8::Boolean::New(true) }; -+ Local<Value> value_obj3 = instance->CallAsConstructor(1, args3); -+ CHECK(value_obj3->IsObject()); -+ Local<Object> object3 = Local<Object>::Cast(value_obj3); -+ value = object3->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsBoolean()); -+ CHECK_EQ(true, value->BooleanValue()); -+ -+ // Call the Object's constructor with undefined. -+ Handle<Value> args4[] = { v8::Undefined() }; -+ Local<Value> value_obj4 = instance->CallAsConstructor(1, args4); -+ CHECK(value_obj4->IsObject()); -+ Local<Object> object4 = Local<Object>::Cast(value_obj4); -+ value = object4->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsUndefined()); -+ -+ // Call the Object's constructor with null. -+ Handle<Value> args5[] = { v8::Null() }; -+ Local<Value> value_obj5 = instance->CallAsConstructor(1, args5); -+ CHECK(value_obj5->IsObject()); -+ Local<Object> object5 = Local<Object>::Cast(value_obj5); -+ value = object5->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsNull()); -+ } -+ -+ // Check exception handling when there is no constructor set for the Object. -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj2"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ value = CompileRun("new obj2(28)"); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ("TypeError: object is not a function", *exception_value1); -+ try_catch.Reset(); -+ -+ Local<Value> args[] = { v8_num(29) }; -+ value = instance->CallAsConstructor(1, args); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2); -+ try_catch.Reset(); -+ } -+ -+ // Check the case when constructor throws exception. -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(ThrowValue); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj3"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ value = CompileRun("new obj3(22)"); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ("22", *exception_value1); -+ try_catch.Reset(); -+ -+ Local<Value> args[] = { v8_num(23) }; -+ value = instance->CallAsConstructor(1, args); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ("23", *exception_value2); -+ try_catch.Reset(); -+ } -+ -+ // Check whether constructor returns with an object or non-object. -+ { Local<FunctionTemplate> function_template = -+ FunctionTemplate::New(FakeConstructorCallback); -+ Local<Function> function = function_template->GetFunction(); -+ Local<Object> instance1 = function; -+ context->Global()->Set(v8_str("obj4"), instance1); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ CHECK(instance1->IsObject()); -+ CHECK(instance1->IsFunction()); -+ -+ value = CompileRun("new obj4(28)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsObject()); -+ -+ Local<Value> args1[] = { v8_num(28) }; -+ value = instance1->CallAsConstructor(1, args1); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsObject()); -+ -+ Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(FakeConstructorCallback); -+ Local<Object> instance2 = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj5"), instance2); -+ CHECK(!try_catch.HasCaught()); -+ -+ CHECK(instance2->IsObject()); -+ CHECK(!instance2->IsFunction()); -+ -+ value = CompileRun("new obj5(28)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(!value->IsObject()); -+ -+ Local<Value> args2[] = { v8_num(28) }; -+ value = instance2->CallAsConstructor(1, args2); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(!value->IsObject()); -+ } -+} -+ -+ - THREADED_TEST(FunctionDescriptorException) { - v8::HandleScope handle_scope; - LocalContext context; -@@ -7028,9 +7222,8 @@ THREADED_TEST(CallAsFunction) { - CHECK(value.IsEmpty()); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value1(try_catch.Exception()); -- CHECK_EQ(*exception_value1, -- "TypeError: Property 'obj2' of object " -- "#<Object> is not a function"); -+ CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function", -+ *exception_value1); - try_catch.Reset(); - - // Call an object without call-as-function handler through the API -@@ -7040,7 +7233,7 @@ THREADED_TEST(CallAsFunction) { - CHECK(value.IsEmpty()); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value2(try_catch.Exception()); -- CHECK_EQ(*exception_value2, "TypeError: [object Object] is not a function"); -+ CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2); - try_catch.Reset(); - } - -@@ -7057,14 +7250,14 @@ THREADED_TEST(CallAsFunction) { - value = CompileRun("obj3(22)"); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value1(try_catch.Exception()); -- CHECK_EQ(*exception_value1, "22"); -+ CHECK_EQ("22", *exception_value1); - try_catch.Reset(); - - v8::Handle<Value> args[] = { v8_num(23) }; - value = instance->CallAsFunction(instance, 1, args); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value2(try_catch.Exception()); -- CHECK_EQ(*exception_value2, "23"); -+ CHECK_EQ("23", *exception_value2); - try_catch.Reset(); - } - } --- -1.7.4.4 - |