From 15befa5438e3f0e1c2ef3692a5801ad1bcb90b4c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 25 Aug 2011 11:15:02 +1000 Subject: Update v8 Change-Id: I576fb2215345aa6599cfb75c6a27544260b2c145 Reviewed-on: http://codereview.qt.nokia.com/3536 Reviewed-by: Qt Sanity Bot Reviewed-by: Aaron Kennedy --- ...shing-and-comparison-methods-to-v8-String.patch | 2 +- .../v8/0002-Add-a-bit-field-3-to-Map.patch | 2 +- ...back-mode-for-named-property-interceptors.patch | 2 +- ...0004-Generalize-external-object-resources.patch | 2 +- .../v8/0005-Introduce-a-QML-compilation-mode.patch | 2 +- ...6-Allow-access-to-the-calling-script-data.patch | 2 +- src/declarative/v8/0007-Fix-warnings.patch | 2 +- .../0008-Add-custom-object-compare-callback.patch | 2 +- ...unction-method-to-the-Object-class-in-the.patch | 286 +++++++++++++++ ...allAsConstructor-method-for-Object-in-the.patch | 397 +++++++++++++++++++++ ...-Add-new-v8-api-to-check-if-a-value-is-an.patch | 63 ++++ ...d-IsCallable-method-for-Object-in-the-API.patch | 116 ++++++ .../0013-Remove-execute-flag-from-v8-debug.h.patch | 15 + 13 files changed, 885 insertions(+), 8 deletions(-) create mode 100644 src/declarative/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch create mode 100644 src/declarative/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch create mode 100644 src/declarative/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch create mode 100644 src/declarative/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch create mode 100644 src/declarative/v8/0013-Remove-execute-flag-from-v8-debug.h.patch (limited to 'src/declarative') 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 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 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 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 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 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 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 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 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 +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 CallAsFunction(Handle recv, ++ int argc, ++ Handle argv[]); ++ + V8EXPORT static Local 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 Object::CallAsFunction(v8::Handle recv, int argc, ++ v8::Handle argv[]) { ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ ON_BAILOUT(isolate, "v8::Object::CallAsFunction()", ++ return Local()); ++ LOG_API(isolate, "Object::CallAsFunction"); ++ ENTER_V8(isolate); ++ HandleScope scope; ++ i::Handle obj = Utils::OpenHandle(this); ++ i::Handle recv_obj = Utils::OpenHandle(*recv); ++ STATIC_ASSERT(sizeof(v8::Handle) == sizeof(i::Object**)); ++ i::Object*** args = reinterpret_cast(argv); ++ i::Handle fun = i::Handle(); ++ if (obj->IsJSFunction()) { ++ fun = i::Handle::cast(obj); ++ } else { ++ EXCEPTION_PREAMBLE(isolate); ++ i::Handle delegate = ++ i::Execution::TryGetFunctionDelegate(obj, &has_pending_exception); ++ EXCEPTION_BAILOUT_CHECK(isolate, Local()); ++ fun = i::Handle::cast(delegate); ++ recv_obj = obj; ++ } ++ EXCEPTION_PREAMBLE(isolate); ++ i::Handle returned = ++ i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception); ++ EXCEPTION_BAILOUT_CHECK(isolate, Local()); ++ return scope.Close(Utils::ToLocal(returned)); ++} ++ ++ + Local 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 Execution::GetFunctionDelegate(Handle object) { + } + + ++Handle Execution::TryGetFunctionDelegate(Handle 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( ++ 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 error_obj = isolate->factory()->NewTypeError( ++ "called_non_callable", i::HandleVector(&object, 1)); ++ isolate->Throw(*error_obj); ++ *has_pending_exception = true; ++ ++ return isolate->factory()->undefined_value(); ++} ++ ++ + Handle Execution::GetConstructorDelegate(Handle 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 GetFunctionDelegate(Handle object); ++ static Handle TryGetFunctionDelegate(Handle 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 t = v8::FunctionTemplate::New(); +- Local instance_template = t->InstanceTemplate(); +- instance_template->SetCallAsFunctionHandler(call_as_function); +- Local instance = t->GetFunction()->NewInstance(); +- context->Global()->Set(v8_str("obj"), instance); +- v8::TryCatch try_catch; +- Local value; +- CHECK(!try_catch.HasCaught()); ++ { Local t = v8::FunctionTemplate::New(); ++ Local instance_template = t->InstanceTemplate(); ++ instance_template->SetCallAsFunctionHandler(call_as_function); ++ Local instance = t->GetFunction()->NewInstance(); ++ context->Global()->Set(v8_str("obj"), instance); ++ v8::TryCatch try_catch; ++ Local 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 args[] = { v8_num(28) }; ++ value = instance->CallAsFunction(instance, 1, args); ++ CHECK(!try_catch.HasCaught()); ++ CHECK_EQ(28, value->Int32Value()); ++ } ++ ++ { Local t = v8::FunctionTemplate::New(); ++ Local instance_template = t->InstanceTemplate(); ++ Local instance = t->GetFunction()->NewInstance(); ++ context->Global()->Set(v8_str("obj2"), instance); ++ v8::TryCatch try_catch; ++ Local 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 " ++ "# is not a function"); ++ try_catch.Reset(); ++ ++ // Call an object without call-as-function handler through the API ++ value = CompileRun("obj2(28)"); ++ v8::Handle 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 t = v8::FunctionTemplate::New(); ++ Local instance_template = t->InstanceTemplate(); ++ instance_template->SetCallAsFunctionHandler(ThrowValue); ++ Local instance = t->GetFunction()->NewInstance(); ++ context->Global()->Set(v8_str("obj3"), instance); ++ v8::TryCatch try_catch; ++ Local 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 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 +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 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 CallAsConstructor(int argc, ++ Handle argv[]); ++ + V8EXPORT static Local 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 Object::CallAsFunction(v8::Handle recv, int argc, + return Local()); + LOG_API(isolate, "Object::CallAsFunction"); + ENTER_V8(isolate); +- HandleScope scope; ++ i::HandleScope scope(isolate); + i::Handle obj = Utils::OpenHandle(this); + i::Handle recv_obj = Utils::OpenHandle(*recv); + STATIC_ASSERT(sizeof(v8::Handle) == sizeof(i::Object**)); +@@ -3286,7 +3286,44 @@ Local Object::CallAsFunction(v8::Handle recv, int argc, + i::Handle returned = + i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception); + EXCEPTION_BAILOUT_CHECK(isolate, Local()); +- return scope.Close(Utils::ToLocal(returned)); ++ return Utils::ToLocal(scope.CloseAndEscape(returned)); ++} ++ ++ ++Local Object::CallAsConstructor(int argc, ++ v8::Handle argv[]) { ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()", ++ return Local()); ++ LOG_API(isolate, "Object::CallAsConstructor"); ++ ENTER_V8(isolate); ++ i::HandleScope scope(isolate); ++ i::Handle obj = Utils::OpenHandle(this); ++ STATIC_ASSERT(sizeof(v8::Handle) == sizeof(i::Object**)); ++ i::Object*** args = reinterpret_cast(argv); ++ if (obj->IsJSFunction()) { ++ i::Handle fun = i::Handle::cast(obj); ++ EXCEPTION_PREAMBLE(isolate); ++ i::Handle returned = ++ i::Execution::New(fun, argc, args, &has_pending_exception); ++ EXCEPTION_BAILOUT_CHECK(isolate, Local()); ++ return Utils::ToLocal(scope.CloseAndEscape( ++ i::Handle::cast(returned))); ++ } ++ EXCEPTION_PREAMBLE(isolate); ++ i::Handle delegate = ++ i::Execution::TryGetConstructorDelegate(obj, &has_pending_exception); ++ EXCEPTION_BAILOUT_CHECK(isolate, Local()); ++ if (!delegate->IsUndefined()) { ++ i::Handle fun = i::Handle::cast(delegate); ++ EXCEPTION_PREAMBLE(isolate); ++ i::Handle returned = ++ i::Execution::Call(fun, obj, argc, args, &has_pending_exception); ++ EXCEPTION_BAILOUT_CHECK(isolate, Local()); ++ ASSERT(!delegate->IsUndefined()); ++ return Utils::ToLocal(scope.CloseAndEscape(returned)); ++ } ++ return Local(); + } + + +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 Execution::GetConstructorDelegate(Handle object) { + } + + ++Handle Execution::TryGetConstructorDelegate( ++ Handle 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( ++ 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 error_obj = isolate->factory()->NewTypeError( ++ "called_non_callable", i::HandleVector(&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 GetConstructorDelegate(Handle object); ++ static Handle TryGetConstructorDelegate(Handle 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 ConstructorCallback(const Arguments& args) { ++ ApiTestFuzzer::Fuzz(); ++ Local This; ++ ++ if (args.IsConstructCall()) { ++ Local Holder = args.Holder(); ++ This = Object::New(); ++ Local proto = Holder->GetPrototype(); ++ if (proto->IsObject()) { ++ This->SetPrototype(proto); ++ } ++ } else { ++ This = args.This(); ++ } ++ ++ This->Set(v8_str("a"), args[0]); ++ return This; ++} ++ ++ ++static Handle FakeConstructorCallback(const Arguments& args) { ++ ApiTestFuzzer::Fuzz(); ++ return args[0]; ++} ++ ++ ++THREADED_TEST(ConstructorForObject) { ++ v8::HandleScope handle_scope; ++ LocalContext context; ++ ++ { Local instance_template = ObjectTemplate::New(); ++ instance_template->SetCallAsFunctionHandler(ConstructorCallback); ++ Local instance = instance_template->NewInstance(); ++ context->Global()->Set(v8_str("obj"), instance); ++ v8::TryCatch try_catch; ++ Local 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 args1[] = { v8_num(28) }; ++ Local value_obj1 = instance->CallAsConstructor(1, args1); ++ CHECK(value_obj1->IsObject()); ++ Local object1 = Local::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 args2[] = { v8_str("tipli") }; ++ Local value_obj2 = instance->CallAsConstructor(1, args2); ++ CHECK(value_obj2->IsObject()); ++ Local object2 = Local::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 args3[] = { v8::Boolean::New(true) }; ++ Local value_obj3 = instance->CallAsConstructor(1, args3); ++ CHECK(value_obj3->IsObject()); ++ Local object3 = Local::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 args4[] = { v8::Undefined() }; ++ Local value_obj4 = instance->CallAsConstructor(1, args4); ++ CHECK(value_obj4->IsObject()); ++ Local object4 = Local::Cast(value_obj4); ++ value = object4->Get(v8_str("a")); ++ CHECK(!try_catch.HasCaught()); ++ CHECK(value->IsUndefined()); ++ ++ // Call the Object's constructor with null. ++ Handle args5[] = { v8::Null() }; ++ Local value_obj5 = instance->CallAsConstructor(1, args5); ++ CHECK(value_obj5->IsObject()); ++ Local object5 = Local::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 instance_template = ObjectTemplate::New(); ++ Local instance = instance_template->NewInstance(); ++ context->Global()->Set(v8_str("obj2"), instance); ++ v8::TryCatch try_catch; ++ Local 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 args[] = { v8_num(29) }; ++ value = instance->CallAsConstructor(1, args); ++ CHECK(try_catch.HasCaught()); ++ String::AsciiValue exception_value2(try_catch.Exception()); ++ CHECK_EQ("TypeError: # is not a function", *exception_value2); ++ try_catch.Reset(); ++ } ++ ++ // Check the case when constructor throws exception. ++ { Local instance_template = ObjectTemplate::New(); ++ instance_template->SetCallAsFunctionHandler(ThrowValue); ++ Local instance = instance_template->NewInstance(); ++ context->Global()->Set(v8_str("obj3"), instance); ++ v8::TryCatch try_catch; ++ Local 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 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 function_template = ++ FunctionTemplate::New(FakeConstructorCallback); ++ Local function = function_template->GetFunction(); ++ Local instance1 = function; ++ context->Global()->Set(v8_str("obj4"), instance1); ++ v8::TryCatch try_catch; ++ Local value; ++ CHECK(!try_catch.HasCaught()); ++ ++ CHECK(instance1->IsObject()); ++ CHECK(instance1->IsFunction()); ++ ++ value = CompileRun("new obj4(28)"); ++ CHECK(!try_catch.HasCaught()); ++ CHECK(value->IsObject()); ++ ++ Local args1[] = { v8_num(28) }; ++ value = instance1->CallAsConstructor(1, args1); ++ CHECK(!try_catch.HasCaught()); ++ CHECK(value->IsObject()); ++ ++ Local instance_template = ObjectTemplate::New(); ++ instance_template->SetCallAsFunctionHandler(FakeConstructorCallback); ++ Local 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 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 " +- "# is not a function"); ++ CHECK_EQ("TypeError: Property 'obj2' of 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 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 +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 ToBoolean() const; + V8EXPORT Local ToNumber() const; + V8EXPORT Local 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 obj = Utils::OpenHandle(this); ++ return obj->HasSpecificClassOf(HEAP->Error_symbol()); ++} ++ + + Local Value::ToString() const { + i::Handle 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 +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 obj = Utils::OpenHandle(this); ++ if (obj->IsJSFunction()) return true; ++ return i::Execution::GetFunctionDelegate(obj)->IsJSFunction(); ++} ++ ++ + Local Object::CallAsFunction(v8::Handle recv, int argc, + v8::Handle 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 instance_template = ObjectTemplate::New(); ++ instance_template->SetCallAsFunctionHandler(call_as_function); ++ Local instance = instance_template->NewInstance(); ++ v8::TryCatch try_catch; ++ ++ CHECK(instance->IsCallable()); ++ CHECK(!try_catch.HasCaught()); ++ } ++ ++ { Local instance_template = ObjectTemplate::New(); ++ Local instance = instance_template->NewInstance(); ++ v8::TryCatch try_catch; ++ ++ CHECK(!instance->IsCallable()); ++ CHECK(!try_catch.HasCaught()); ++ } ++ ++ { Local function_template = ++ FunctionTemplate::New(call_as_function); ++ Local function = function_template->GetFunction(); ++ Local instance = function; ++ v8::TryCatch try_catch; ++ ++ CHECK(instance->IsCallable()); ++ CHECK(!try_catch.HasCaught()); ++ } ++ ++ { Local function_template = FunctionTemplate::New(); ++ Local function = function_template->GetFunction(); ++ Local 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 +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 + -- cgit v1.2.3