From 24f19608d4dc319377f9eb260da2bbba618d6b23 Mon Sep 17 00:00:00 2001 From: "ager@chromium.org" Date: Wed, 4 May 2011 11:07:09 +0000 Subject: [PATCH] Actually revert "Add Call method to the Object class in the API" Tests are failing in debug mode. This also reapplies the change "Make Date and RegExp inherit from Object in the API" that I accidentally reverted. R=sgjesse@chromium.org BUG= TEST= Review URL: http://codereview.chromium.org/6927009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7775 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 170 +++++++++++++++++++--------------------- src/api.cc | 31 -------- src/api.h | 2 +- src/execution.cc | 24 ------ src/execution.h | 2 - test/cctest/test-api.cc | 146 +++++++++++----------------------- 6 files changed, 128 insertions(+), 247 deletions(-) diff --git a/include/v8.h b/include/v8.h index 1d1abe81f..4dcbf285e 100644 --- a/include/v8.h +++ b/include/v8.h @@ -1349,87 +1349,6 @@ class Uint32 : public Integer { }; -/** - * An instance of the built-in Date constructor (ECMA-262, 15.9). - */ -class Date : public Value { - public: - V8EXPORT static Local New(double time); - - /** - * A specialization of Value::NumberValue that is more efficient - * because we know the structure of this object. - */ - V8EXPORT double NumberValue() const; - - static inline Date* Cast(v8::Value* obj); - - /** - * Notification that the embedder has changed the time zone, - * daylight savings time, or other date / time configuration - * parameters. V8 keeps a cache of various values used for - * date / time computation. This notification will reset - * those cached values for the current context so that date / - * time configuration changes would be reflected in the Date - * object. - * - * This API should not be called more than needed as it will - * negatively impact the performance of date operations. - */ - V8EXPORT static void DateTimeConfigurationChangeNotification(); - - private: - V8EXPORT static void CheckCast(v8::Value* obj); -}; - - -/** - * An instance of the built-in RegExp constructor (ECMA-262, 15.10). - */ -class RegExp : public Value { - public: - /** - * Regular expression flag bits. They can be or'ed to enable a set - * of flags. - */ - enum Flags { - kNone = 0, - kGlobal = 1, - kIgnoreCase = 2, - kMultiline = 4 - }; - - /** - * Creates a regular expression from the given pattern string and - * the flags bit field. May throw a JavaScript exception as - * described in ECMA-262, 15.10.4.1. - * - * For example, - * RegExp::New(v8::String::New("foo"), - * static_cast(kGlobal | kMultiline)) - * is equivalent to evaluating "/foo/gm". - */ - V8EXPORT static Local New(Handle pattern, - Flags flags); - - /** - * Returns the value of the source property: a string representing - * the regular expression. - */ - V8EXPORT Local GetSource() const; - - /** - * Returns the flags bit field. - */ - V8EXPORT Flags GetFlags() const; - - static inline RegExp* Cast(v8::Value* obj); - - private: - V8EXPORT static void CheckCast(v8::Value* obj); -}; - - enum PropertyAttribute { None = 0, ReadOnly = 1 << 0, @@ -1687,14 +1606,6 @@ 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: @@ -1764,6 +1675,87 @@ class Function : public Object { }; +/** + * An instance of the built-in Date constructor (ECMA-262, 15.9). + */ +class Date : public Object { + public: + V8EXPORT static Local New(double time); + + /** + * A specialization of Value::NumberValue that is more efficient + * because we know the structure of this object. + */ + V8EXPORT double NumberValue() const; + + static inline Date* Cast(v8::Value* obj); + + /** + * Notification that the embedder has changed the time zone, + * daylight savings time, or other date / time configuration + * parameters. V8 keeps a cache of various values used for + * date / time computation. This notification will reset + * those cached values for the current context so that date / + * time configuration changes would be reflected in the Date + * object. + * + * This API should not be called more than needed as it will + * negatively impact the performance of date operations. + */ + V8EXPORT static void DateTimeConfigurationChangeNotification(); + + private: + V8EXPORT static void CheckCast(v8::Value* obj); +}; + + +/** + * An instance of the built-in RegExp constructor (ECMA-262, 15.10). + */ +class RegExp : public Object { + public: + /** + * Regular expression flag bits. They can be or'ed to enable a set + * of flags. + */ + enum Flags { + kNone = 0, + kGlobal = 1, + kIgnoreCase = 2, + kMultiline = 4 + }; + + /** + * Creates a regular expression from the given pattern string and + * the flags bit field. May throw a JavaScript exception as + * described in ECMA-262, 15.10.4.1. + * + * For example, + * RegExp::New(v8::String::New("foo"), + * static_cast(kGlobal | kMultiline)) + * is equivalent to evaluating "/foo/gm". + */ + V8EXPORT static Local New(Handle pattern, + Flags flags); + + /** + * Returns the value of the source property: a string representing + * the regular expression. + */ + V8EXPORT Local GetSource() const; + + /** + * Returns the flags bit field. + */ + V8EXPORT Flags GetFlags() const; + + static inline RegExp* Cast(v8::Value* obj); + + private: + V8EXPORT static void CheckCast(v8::Value* obj); +}; + + /** * A JavaScript value that wraps a C++ void*. This type of value is * mainly used to associate C++ data structures with JavaScript diff --git a/src/api.cc b/src/api.cc index de3c1a5dd..792e4886f 100644 --- a/src/api.cc +++ b/src/api.cc @@ -3255,37 +3255,6 @@ 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(i::Handle::cast(returned))); -} - - Local Function::NewInstance() const { return NewInstance(0, NULL); } diff --git a/src/api.h b/src/api.h index 7423d28e2..cd0205b2c 100644 --- a/src/api.h +++ b/src/api.h @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: diff --git a/src/execution.cc b/src/execution.cc index 850dec561..eb26438fe 100644 --- a/src/execution.cc +++ b/src/execution.cc @@ -234,30 +234,6 @@ 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 e89d6ba39..d4b80d274 100644 --- a/src/execution.h +++ b/src/execution.h @@ -138,8 +138,6 @@ 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 c7e9432c5..e2a7fb185 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -1050,8 +1050,10 @@ THREADED_TEST(Date) { v8::HandleScope scope; LocalContext env; double PI = 3.1415926; - Local date_obj = v8::Date::New(PI); - CHECK_EQ(3.0, date_obj->NumberValue()); + Local date = v8::Date::New(PI); + CHECK_EQ(3.0, date->NumberValue()); + date.As()->Set(v8_str("property"), v8::Integer::New(42)); + CHECK_EQ(42, date.As()->Get(v8_str("property"))->Int32Value()); } @@ -6960,111 +6962,50 @@ 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()); - - 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()); - - // 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()); - - // 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()); + 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()); - // 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()); + value = CompileRun("obj(42)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(42, 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()); - } + value = CompileRun("(function(o){return o(49)})(obj)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(49, 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()); + // test special case of call as function + value = CompileRun("[obj]['0'](45)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(45, value->Int32Value()); - // 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(); - } + value = CompileRun("obj.call = Function.prototype.call;" + "obj.call(null, 87)"); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(87, value->Int32Value()); - { 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()); + // 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()); - // 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(); + const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; + value = CompileRun(call_17); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(17, value->Int32Value()); - 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(); - } + // 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()); } @@ -13801,6 +13742,11 @@ TEST(RegExp) { context->Global()->Set(v8_str("re"), re); ExpectTrue("re.test('FoobarbaZ')"); + // RegExps are objects on which you can set properties. + re->Set(v8_str("property"), v8::Integer::New(32)); + v8::Handle value = CompileRun("re.property"); + ASSERT_EQ(32, value->Int32Value()); + v8::TryCatch try_catch; re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone); CHECK(re.IsEmpty()); -- 2.34.1