Commit 24f19608 authored by ager@chromium.org's avatar ager@chromium.org

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
parent 26c775da
...@@ -1349,87 +1349,6 @@ class Uint32 : public Integer { ...@@ -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<Value> 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<RegExp::Flags>(kGlobal | kMultiline))
* is equivalent to evaluating "/foo/gm".
*/
V8EXPORT static Local<RegExp> New(Handle<String> pattern,
Flags flags);
/**
* Returns the value of the source property: a string representing
* the regular expression.
*/
V8EXPORT Local<String> 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 { enum PropertyAttribute {
None = 0, None = 0,
ReadOnly = 1 << 0, ReadOnly = 1 << 0,
...@@ -1687,14 +1606,6 @@ class Object : public Value { ...@@ -1687,14 +1606,6 @@ class Object : public Value {
V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType(); V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType();
V8EXPORT int GetIndexedPropertiesExternalArrayDataLength(); 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(); V8EXPORT static Local<Object> New();
static inline Object* Cast(Value* obj); static inline Object* Cast(Value* obj);
private: private:
...@@ -1764,6 +1675,87 @@ class Function : public Object { ...@@ -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<Value> 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<RegExp::Flags>(kGlobal | kMultiline))
* is equivalent to evaluating "/foo/gm".
*/
V8EXPORT static Local<RegExp> New(Handle<String> pattern,
Flags flags);
/**
* Returns the value of the source property: a string representing
* the regular expression.
*/
V8EXPORT Local<String> 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 * A JavaScript value that wraps a C++ void*. This type of value is
* mainly used to associate C++ data structures with JavaScript * mainly used to associate C++ data structures with JavaScript
......
...@@ -3255,37 +3255,6 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { ...@@ -3255,37 +3255,6 @@ 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(i::Handle<i::JSObject>::cast(returned)));
}
Local<v8::Object> Function::NewInstance() const { Local<v8::Object> Function::NewInstance() const {
return NewInstance(0, NULL); return NewInstance(0, NULL);
} }
......
// 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
......
...@@ -234,30 +234,6 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { ...@@ -234,30 +234,6 @@ 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) { Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
ASSERT(!object->IsJSFunction()); ASSERT(!object->IsJSFunction());
Isolate* isolate = Isolate::Current(); Isolate* isolate = Isolate::Current();
......
...@@ -138,8 +138,6 @@ class Execution : public AllStatic { ...@@ -138,8 +138,6 @@ class Execution : public AllStatic {
// Get a function delegate (or undefined) for the given non-function // Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as functions. // object. Used for support calling objects as functions.
static Handle<Object> GetFunctionDelegate(Handle<Object> object); 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 // Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as constructors. // object. Used for support calling objects as constructors.
......
...@@ -1050,8 +1050,10 @@ THREADED_TEST(Date) { ...@@ -1050,8 +1050,10 @@ THREADED_TEST(Date) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
double PI = 3.1415926; double PI = 3.1415926;
Local<Value> date_obj = v8::Date::New(PI); Local<Value> date = v8::Date::New(PI);
CHECK_EQ(3.0, date_obj->NumberValue()); CHECK_EQ(3.0, date->NumberValue());
date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42));
CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
} }
...@@ -6960,111 +6962,50 @@ THREADED_TEST(CallAsFunction) { ...@@ -6960,111 +6962,50 @@ THREADED_TEST(CallAsFunction) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext context; LocalContext context;
{ Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
Local<ObjectTemplate> instance_template = t->InstanceTemplate(); Local<ObjectTemplate> instance_template = t->InstanceTemplate();
instance_template->SetCallAsFunctionHandler(call_as_function); instance_template->SetCallAsFunctionHandler(call_as_function);
Local<v8::Object> instance = t->GetFunction()->NewInstance(); Local<v8::Object> instance = t->GetFunction()->NewInstance();
context->Global()->Set(v8_str("obj"), instance); context->Global()->Set(v8_str("obj"), instance);
v8::TryCatch try_catch; v8::TryCatch try_catch;
Local<Value> value; Local<Value> value;
CHECK(!try_catch.HasCaught()); 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());
// Check that the call-as-function handler can be called through value = CompileRun("obj(42)");
// new. CHECK(!try_catch.HasCaught());
value = CompileRun("new obj(43)"); CHECK_EQ(42, value->Int32Value());
CHECK(!try_catch.HasCaught());
CHECK_EQ(-43, value->Int32Value());
// Check that the call-as-function handler can be called through value = CompileRun("(function(o){return o(49)})(obj)");
// the API. CHECK(!try_catch.HasCaught());
v8::Handle<Value> args[] = { v8_num(28) }; CHECK_EQ(49, value->Int32Value());
value = instance->CallAsFunction(instance, 1, args);
CHECK(!try_catch.HasCaught());
CHECK_EQ(28, value->Int32Value());
}
{ Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); // test special case of call as function
Local<ObjectTemplate> instance_template = t->InstanceTemplate(); value = CompileRun("[obj]['0'](45)");
Local<v8::Object> instance = t->GetFunction()->NewInstance(); CHECK(!try_catch.HasCaught());
context->Global()->Set(v8_str("obj2"), instance); CHECK_EQ(45, value->Int32Value());
v8::TryCatch try_catch;
Local<Value> value;
CHECK(!try_catch.HasCaught());
// Call an object without call-as-function handler through the JS value = CompileRun("obj.call = Function.prototype.call;"
value = CompileRun("obj2(28)"); "obj.call(null, 87)");
CHECK(value.IsEmpty()); CHECK(!try_catch.HasCaught());
CHECK(try_catch.HasCaught()); CHECK_EQ(87, value->Int32Value());
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(); // Regression tests for bug #1116356: Calling call through call/apply
Local<ObjectTemplate> instance_template = t->InstanceTemplate(); // must work for non-function receivers.
instance_template->SetCallAsFunctionHandler(ThrowValue); const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
Local<v8::Object> instance = t->GetFunction()->NewInstance(); value = CompileRun(apply_99);
context->Global()->Set(v8_str("obj3"), instance); CHECK(!try_catch.HasCaught());
v8::TryCatch try_catch; CHECK_EQ(99, value->Int32Value());
Local<Value> value;
CHECK(!try_catch.HasCaught());
// Catch the exception which is thrown by call-as-function handler const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
value = CompileRun("obj3(22)"); value = CompileRun(call_17);
CHECK(try_catch.HasCaught()); CHECK(!try_catch.HasCaught());
String::AsciiValue exception_value1(try_catch.Exception()); CHECK_EQ(17, value->Int32Value());
CHECK_EQ(*exception_value1, "22");
try_catch.Reset();
v8::Handle<Value> args[] = { v8_num(23) }; // Check that the call-as-function handler can be called through
value = instance->CallAsFunction(instance, 1, args); // new.
CHECK(try_catch.HasCaught()); value = CompileRun("new obj(43)");
String::AsciiValue exception_value2(try_catch.Exception()); CHECK(!try_catch.HasCaught());
CHECK_EQ(*exception_value2, "23"); CHECK_EQ(-43, value->Int32Value());
try_catch.Reset();
}
} }
...@@ -13801,6 +13742,11 @@ TEST(RegExp) { ...@@ -13801,6 +13742,11 @@ TEST(RegExp) {
context->Global()->Set(v8_str("re"), re); context->Global()->Set(v8_str("re"), re);
ExpectTrue("re.test('FoobarbaZ')"); ExpectTrue("re.test('FoobarbaZ')");
// RegExps are objects on which you can set properties.
re->Set(v8_str("property"), v8::Integer::New(32));
v8::Handle<v8::Value> value = CompileRun("re.property");
ASSERT_EQ(32, value->Int32Value());
v8::TryCatch try_catch; v8::TryCatch try_catch;
re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone); re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
CHECK(re.IsEmpty()); CHECK(re.IsEmpty());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment