diff options
Diffstat (limited to 'src/declarative')
13 files changed, 885 insertions, 8 deletions
diff --git a/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch b/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch index 4596202944..1fb3b90733 100644 --- a/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch +++ b/src/declarative/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch @@ -1,7 +1,7 @@ From e13ce09287a56c920d5ffdc5d4662d49f1838f16 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy <aaron.kennedy@nokia.com> Date: Mon, 23 May 2011 15:47:20 +1000 -Subject: [PATCH 1/8] Add hashing and comparison methods to v8::String +Subject: [PATCH 01/13] Add hashing and comparison methods to v8::String This allows us to more rapidly search for a v8::String inside a hash of QStrings. diff --git a/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch b/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch index cb578c0f96..daf8b35570 100644 --- a/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch +++ b/src/declarative/v8/0002-Add-a-bit-field-3-to-Map.patch @@ -1,7 +1,7 @@ From 7c9cfff80b7864d5687432d424074e51712c4a07 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy <aaron.kennedy@nokia.com> Date: Mon, 23 May 2011 15:55:26 +1000 -Subject: [PATCH 2/8] Add a bit field 3 to Map +Subject: [PATCH 02/13] Add a bit field 3 to Map Bit field 3 will be used to add QML specific map flags. --- diff --git a/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch index daa2250a25..1c81b2af9d 100644 --- a/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch +++ b/src/declarative/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch @@ -1,7 +1,7 @@ From ae8688b53d67044f2c9b0cce25fc282b078610c1 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy <aaron.kennedy@nokia.com> Date: Mon, 23 May 2011 16:21:02 +1000 -Subject: [PATCH 3/8] Add a "fallback" mode for named property interceptors +Subject: [PATCH 03/13] Add a "fallback" mode for named property interceptors By default interceptors are called before the normal property resolution on objects. When an interceptor is installed as a diff --git a/src/declarative/v8/0004-Generalize-external-object-resources.patch b/src/declarative/v8/0004-Generalize-external-object-resources.patch index 56e5e371fd..6b85666cf0 100644 --- a/src/declarative/v8/0004-Generalize-external-object-resources.patch +++ b/src/declarative/v8/0004-Generalize-external-object-resources.patch @@ -1,7 +1,7 @@ From 4827116b12c50f6662794017c5a662b5dbb2da0b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy <aaron.kennedy@nokia.com> Date: Mon, 23 May 2011 16:55:35 +1000 -Subject: [PATCH 4/8] Generalize external object resources +Subject: [PATCH 04/13] Generalize external object resources V8 was already able to manage and finalize an external string resource. This change generalizes that mechanism to handle a diff --git a/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch index 7ec10e9448..2dfd3d9699 100644 --- a/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch +++ b/src/declarative/v8/0005-Introduce-a-QML-compilation-mode.patch @@ -1,7 +1,7 @@ From fd7d475e298e5b63cd6383c78cc900635c82aa38 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy <aaron.kennedy@nokia.com> Date: Mon, 23 May 2011 18:26:19 +1000 -Subject: [PATCH 5/8] Introduce a QML compilation mode +Subject: [PATCH 05/13] Introduce a QML compilation mode In QML mode, there is a second global object - known as the QML global object. During property resolution, if a property is not diff --git a/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch b/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch index 7af81c3f69..b9c44654cd 100644 --- a/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch +++ b/src/declarative/v8/0006-Allow-access-to-the-calling-script-data.patch @@ -1,7 +1,7 @@ From f890f0d1a1e5bd62711815489c87755a4f382436 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy <aaron.kennedy@nokia.com> Date: Wed, 25 May 2011 10:36:13 +1000 -Subject: [PATCH 6/8] Allow access to the calling script data +Subject: [PATCH 06/13] Allow access to the calling script data --- include/v8.h | 1 + diff --git a/src/declarative/v8/0007-Fix-warnings.patch b/src/declarative/v8/0007-Fix-warnings.patch index 2efc8331aa..60fb24c138 100644 --- a/src/declarative/v8/0007-Fix-warnings.patch +++ b/src/declarative/v8/0007-Fix-warnings.patch @@ -1,7 +1,7 @@ From dac5d9db84cf20564621c679937ca7b9c6a8e880 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy <aaron.kennedy@nokia.com> Date: Fri, 27 May 2011 13:04:15 +1000 -Subject: [PATCH 7/8] Fix warnings +Subject: [PATCH 07/13] Fix warnings --- include/v8.h | 16 ++++++++-------- diff --git a/src/declarative/v8/0008-Add-custom-object-compare-callback.patch b/src/declarative/v8/0008-Add-custom-object-compare-callback.patch index 659cf4c167..fdb0895f06 100644 --- a/src/declarative/v8/0008-Add-custom-object-compare-callback.patch +++ b/src/declarative/v8/0008-Add-custom-object-compare-callback.patch @@ -1,7 +1,7 @@ From bec11b8b7f89d135e7d9a823ac4fe98c70d017cf Mon Sep 17 00:00:00 2001 From: Aaron Kennedy <aaron.kennedy@nokia.com> Date: Mon, 27 Jun 2011 14:57:28 +1000 -Subject: [PATCH 8/8] Add custom object compare callback +Subject: [PATCH 08/13] Add custom object compare callback A global custom object comparison callback can be set with: V8::SetUserObjectComparisonCallbackFunction() diff --git a/src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch b/src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch new file mode 100644 index 0000000000..89ec7b96bc --- /dev/null +++ b/src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch @@ -0,0 +1,286 @@ +From 4183b973ed3bd603784c798dfa63ba48f6b68003 Mon Sep 17 00:00:00 2001 +From: ager@chromium.org <ager@chromium.org> +Date: Wed, 4 May 2011 13:03:08 +0000 +Subject: [PATCH 09/13] Add CallAsFunction method to the Object class in the API + +Patch by Peter Varga. + +BUG=v8:1336 +TEST=cctest/test-api/CallAsFunction + +Review URL: http://codereview.chromium.org/6883045 + +git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 +--- + include/v8.h | 8 +++ + src/api.cc | 31 +++++++++++ + src/execution.cc | 24 ++++++++ + src/execution.h | 2 + + test/cctest/test-api.cc | 135 ++++++++++++++++++++++++++++++++++------------- + 5 files changed, 163 insertions(+), 37 deletions(-) + +diff --git a/include/v8.h b/include/v8.h +index d5d6972..8a8e1cd 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -1757,6 +1757,14 @@ class Object : public Value { + V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType(); + V8EXPORT int GetIndexedPropertiesExternalArrayDataLength(); + ++ /** ++ * Call an Object as a function if a callback is set by the ++ * ObjectTemplate::SetCallAsFunctionHandler method. ++ */ ++ V8EXPORT Local<Value> CallAsFunction(Handle<Object> recv, ++ 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 2436031..e412e51 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -3259,6 +3259,37 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { + } + + ++Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, ++ v8::Handle<v8::Value> argv[]) { ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ ON_BAILOUT(isolate, "v8::Object::CallAsFunction()", ++ return Local<v8::Value>()); ++ LOG_API(isolate, "Object::CallAsFunction"); ++ ENTER_V8(isolate); ++ HandleScope scope; ++ 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**)); ++ i::Object*** args = reinterpret_cast<i::Object***>(argv); ++ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>(); ++ if (obj->IsJSFunction()) { ++ fun = i::Handle<i::JSFunction>::cast(obj); ++ } else { ++ EXCEPTION_PREAMBLE(isolate); ++ i::Handle<i::Object> delegate = ++ i::Execution::TryGetFunctionDelegate(obj, &has_pending_exception); ++ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); ++ fun = i::Handle<i::JSFunction>::cast(delegate); ++ recv_obj = obj; ++ } ++ EXCEPTION_PREAMBLE(isolate); ++ 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)); ++} ++ ++ + Local<v8::Object> Function::NewInstance() const { + return NewInstance(0, NULL); + } +diff --git a/src/execution.cc b/src/execution.cc +index 1632076..894d741 100644 +--- a/src/execution.cc ++++ b/src/execution.cc +@@ -254,6 +254,30 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { + } + + ++Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object, ++ bool* has_pending_exception) { ++ ASSERT(!object->IsJSFunction()); ++ Isolate* isolate = Isolate::Current(); ++ ++ // 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_function_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(); ++} ++ ++ + Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { + ASSERT(!object->IsJSFunction()); + Isolate* isolate = Isolate::Current(); +diff --git a/src/execution.h b/src/execution.h +index a476eb4..0a0be51 100644 +--- a/src/execution.h ++++ b/src/execution.h +@@ -144,6 +144,8 @@ class Execution : public AllStatic { + // Get a function delegate (or undefined) for the given non-function + // object. Used for support calling objects as functions. + static Handle<Object> GetFunctionDelegate(Handle<Object> object); ++ static Handle<Object> TryGetFunctionDelegate(Handle<Object> object, ++ bool* has_pending_exception); + + // Get a function delegate (or undefined) for the given non-function + // object. Used for support calling objects as constructors. +diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc +index d7621d1..693d51e 100644 +--- a/test/cctest/test-api.cc ++++ b/test/cctest/test-api.cc +@@ -6962,50 +6962,111 @@ THREADED_TEST(CallAsFunction) { + v8::HandleScope scope; + LocalContext context; + +- Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); +- Local<ObjectTemplate> instance_template = t->InstanceTemplate(); +- instance_template->SetCallAsFunctionHandler(call_as_function); +- Local<v8::Object> instance = t->GetFunction()->NewInstance(); +- context->Global()->Set(v8_str("obj"), instance); +- v8::TryCatch try_catch; +- Local<Value> value; +- CHECK(!try_catch.HasCaught()); ++ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); ++ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); ++ instance_template->SetCallAsFunctionHandler(call_as_function); ++ Local<v8::Object> instance = t->GetFunction()->NewInstance(); ++ context->Global()->Set(v8_str("obj"), instance); ++ v8::TryCatch try_catch; ++ Local<Value> value; ++ CHECK(!try_catch.HasCaught()); + +- value = CompileRun("obj(42)"); +- CHECK(!try_catch.HasCaught()); +- CHECK_EQ(42, value->Int32Value()); ++ value = CompileRun("obj(42)"); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(42, value->Int32Value()); + +- value = CompileRun("(function(o){return o(49)})(obj)"); +- CHECK(!try_catch.HasCaught()); +- CHECK_EQ(49, value->Int32Value()); ++ value = CompileRun("(function(o){return o(49)})(obj)"); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(49, value->Int32Value()); + +- // test special case of call as function +- value = CompileRun("[obj]['0'](45)"); +- CHECK(!try_catch.HasCaught()); +- CHECK_EQ(45, value->Int32Value()); ++ // test special case of call as function ++ value = CompileRun("[obj]['0'](45)"); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(45, value->Int32Value()); + +- value = CompileRun("obj.call = Function.prototype.call;" +- "obj.call(null, 87)"); +- CHECK(!try_catch.HasCaught()); +- CHECK_EQ(87, value->Int32Value()); ++ value = CompileRun("obj.call = Function.prototype.call;" ++ "obj.call(null, 87)"); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(87, value->Int32Value()); + +- // Regression tests for bug #1116356: Calling call through call/apply +- // must work for non-function receivers. +- const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])"; +- value = CompileRun(apply_99); +- CHECK(!try_catch.HasCaught()); +- CHECK_EQ(99, value->Int32Value()); ++ // Regression tests for bug #1116356: Calling call through call/apply ++ // must work for non-function receivers. ++ const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])"; ++ value = CompileRun(apply_99); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(99, value->Int32Value()); + +- const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; +- value = CompileRun(call_17); +- CHECK(!try_catch.HasCaught()); +- CHECK_EQ(17, value->Int32Value()); ++ const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; ++ value = CompileRun(call_17); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(17, value->Int32Value()); + +- // Check that the call-as-function handler can be called through +- // new. +- value = CompileRun("new obj(43)"); +- CHECK(!try_catch.HasCaught()); +- CHECK_EQ(-43, value->Int32Value()); ++ // Check that the call-as-function handler can be called through ++ // new. ++ value = CompileRun("new obj(43)"); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(-43, value->Int32Value()); ++ ++ // Check that the call-as-function handler can be called through ++ // the API. ++ v8::Handle<Value> args[] = { v8_num(28) }; ++ value = instance->CallAsFunction(instance, 1, args); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(28, value->Int32Value()); ++ } ++ ++ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); ++ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); ++ Local<v8::Object> instance = t->GetFunction()->NewInstance(); ++ context->Global()->Set(v8_str("obj2"), instance); ++ v8::TryCatch try_catch; ++ Local<Value> value; ++ CHECK(!try_catch.HasCaught()); ++ ++ // Call an object without call-as-function handler through the JS ++ value = CompileRun("obj2(28)"); ++ 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"); ++ try_catch.Reset(); ++ ++ // Call an object without call-as-function handler through the API ++ value = CompileRun("obj2(28)"); ++ v8::Handle<Value> args[] = { v8_num(28) }; ++ value = instance->CallAsFunction(instance, 1, args); ++ 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"); ++ try_catch.Reset(); ++ } ++ ++ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); ++ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); ++ instance_template->SetCallAsFunctionHandler(ThrowValue); ++ Local<v8::Object> instance = t->GetFunction()->NewInstance(); ++ context->Global()->Set(v8_str("obj3"), instance); ++ v8::TryCatch try_catch; ++ Local<Value> value; ++ CHECK(!try_catch.HasCaught()); ++ ++ // Catch the exception which is thrown by call-as-function handler ++ value = CompileRun("obj3(22)"); ++ CHECK(try_catch.HasCaught()); ++ String::AsciiValue exception_value1(try_catch.Exception()); ++ CHECK_EQ(*exception_value1, "22"); ++ 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"); ++ try_catch.Reset(); ++ } + } + + +-- +1.7.2.3 + diff --git a/src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch b/src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch new file mode 100644 index 0000000000..09c2d4af1a --- /dev/null +++ b/src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch @@ -0,0 +1,397 @@ +From 3d6d4249878f7960eac4c9c94e0f2529f9a58c4a 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/13] 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 8a8e1cd..84462b5 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -1765,6 +1765,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.2.3 + diff --git a/src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch b/src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch new file mode 100644 index 0000000000..f4a15bf97a --- /dev/null +++ b/src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch @@ -0,0 +1,63 @@ +From f22d0312faeb93ced8747d9aae8c6d77e11b4aba Mon Sep 17 00:00:00 2001 +From: Jedrzej Nowacki <jedrzej.nowacki@nokia.com> +Date: Tue, 7 Dec 2010 11:56:42 +0100 +Subject: [PATCH 11/13] QtScript/V8: Add new v8 api to check if a value is an error. + +New function v8::Value::IsError was created. + +This API is experimental and added only for the purposes of our +research. +--- + include/v8.h | 5 +++++ + src/api.cc | 6 ++++++ + src/heap.h | 1 + + 3 files changed, 12 insertions(+), 0 deletions(-) + +diff --git a/include/v8.h b/include/v8.h +index 84462b5..08b0ec2 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -937,6 +937,11 @@ class Value : public Data { + */ + V8EXPORT bool IsRegExp() const; + ++ /** ++ * Returns true if this value is an Error. ++ */ ++ V8EXPORT bool IsError() const; ++ + V8EXPORT Local<Boolean> ToBoolean() const; + V8EXPORT Local<Number> ToNumber() const; + V8EXPORT Local<String> ToString() const; +diff --git a/src/api.cc b/src/api.cc +index 1a585d6..bd435eb 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -2108,6 +2108,12 @@ bool Value::IsRegExp() const { + return obj->IsJSRegExp(); + } + ++bool Value::IsError() const { ++ if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsError()")) return false; ++ i::Handle<i::Object> obj = Utils::OpenHandle(this); ++ return obj->HasSpecificClassOf(HEAP->Error_symbol()); ++} ++ + + Local<String> Value::ToString() const { + i::Handle<i::Object> obj = Utils::OpenHandle(this); +diff --git a/src/heap.h b/src/heap.h +index 8cbf378..db90bb9 100644 +--- a/src/heap.h ++++ b/src/heap.h +@@ -169,6 +169,7 @@ inline Heap* _inline_get_heap_(); + V(string_symbol, "string") \ + V(String_symbol, "String") \ + V(Date_symbol, "Date") \ ++ V(Error_symbol, "Error") \ + V(this_symbol, "this") \ + V(to_string_symbol, "toString") \ + V(char_at_symbol, "CharAt") \ +-- +1.7.2.3 + diff --git a/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch b/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch new file mode 100644 index 0000000000..e4c46b0cbf --- /dev/null +++ b/src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch @@ -0,0 +1,116 @@ +From 472c04c9e7a64e8734c76d2cf97a7cc5b773b788 Mon Sep 17 00:00:00 2001 +From: ager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00> +Date: Mon, 9 May 2011 15:24:48 +0000 +Subject: [PATCH 12/13] Add IsCallable method for Object in the API + +Patch by Peter Varga. + +BUG=none +TEST=cctest/test-api/CallableObject + +Review URL: http://codereview.chromium.org/6964005 + +git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7828 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 +--- + include/v8.h | 7 +++++++ + src/api.cc | 11 +++++++++++ + test/cctest/test-api.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 61 insertions(+), 0 deletions(-) + +diff --git a/include/v8.h b/include/v8.h +index 08b0ec2..4194d4a 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -1763,6 +1763,13 @@ class Object : public Value { + V8EXPORT int GetIndexedPropertiesExternalArrayDataLength(); + + /** ++ * Checks whether a callback is set by the ++ * ObjectTemplate::SetCallAsFunctionHandler method. ++ * When an Object is callable this method returns true. ++ */ ++ V8EXPORT bool IsCallable(); ++ ++ /** + * Call an Object as a function if a callback is set by the + * ObjectTemplate::SetCallAsFunctionHandler method. + */ +diff --git a/src/api.cc b/src/api.cc +index bd435eb..a5a637f 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -3265,6 +3265,17 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { + } + + ++bool v8::Object::IsCallable() { ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false); ++ ENTER_V8(isolate); ++ i::HandleScope scope(isolate); ++ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); ++ if (obj->IsJSFunction()) return true; ++ return i::Execution::GetFunctionDelegate(obj)->IsJSFunction(); ++} ++ ++ + Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, + v8::Handle<v8::Value> argv[]) { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); +diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc +index 1334f63..45db5a1 100644 +--- a/test/cctest/test-api.cc ++++ b/test/cctest/test-api.cc +@@ -7263,6 +7263,49 @@ THREADED_TEST(CallAsFunction) { + } + + ++// Check whether a non-function object is callable. ++THREADED_TEST(CallableObject) { ++ v8::HandleScope scope; ++ LocalContext context; ++ ++ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); ++ instance_template->SetCallAsFunctionHandler(call_as_function); ++ Local<Object> instance = instance_template->NewInstance(); ++ v8::TryCatch try_catch; ++ ++ CHECK(instance->IsCallable()); ++ CHECK(!try_catch.HasCaught()); ++ } ++ ++ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); ++ Local<Object> instance = instance_template->NewInstance(); ++ v8::TryCatch try_catch; ++ ++ CHECK(!instance->IsCallable()); ++ CHECK(!try_catch.HasCaught()); ++ } ++ ++ { Local<FunctionTemplate> function_template = ++ FunctionTemplate::New(call_as_function); ++ Local<Function> function = function_template->GetFunction(); ++ Local<Object> instance = function; ++ v8::TryCatch try_catch; ++ ++ CHECK(instance->IsCallable()); ++ CHECK(!try_catch.HasCaught()); ++ } ++ ++ { Local<FunctionTemplate> function_template = FunctionTemplate::New(); ++ Local<Function> function = function_template->GetFunction(); ++ Local<Object> instance = function; ++ v8::TryCatch try_catch; ++ ++ CHECK(instance->IsCallable()); ++ CHECK(!try_catch.HasCaught()); ++ } ++} ++ ++ + static int CountHandles() { + return v8::HandleScope::NumberOfHandles(); + } +-- +1.7.2.3 + diff --git a/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch b/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch new file mode 100644 index 0000000000..0a769921cd --- /dev/null +++ b/src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch @@ -0,0 +1,15 @@ +From dc2cad4f8fc88c52fcea09b8d0262d35cd32dc44 Mon Sep 17 00:00:00 2001 +From: Aaron Kennedy <aaron.kennedy@nokia.com> +Date: Thu, 25 Aug 2011 11:09:58 +1000 +Subject: [PATCH 13/13] Remove execute flag from v8-debug.h + +--- + 0 files changed, 0 insertions(+), 0 deletions(-) + mode change 100755 => 100644 include/v8-debug.h + +diff --git a/include/v8-debug.h b/include/v8-debug.h +old mode 100755 +new mode 100644 +-- +1.7.2.3 + |