Actually revert "Add Call method to the Object class in the API"
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 4 May 2011 11:07:09 +0000 (11:07 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 4 May 2011 11:07:09 +0000 (11:07 +0000)
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
src/api.cc
src/api.h
src/execution.cc
src/execution.h
test/cctest/test-api.cc

index 1d1abe81ff8716e8fdb3ad2677dfc97723179522..4dcbf285eaee3611da026ee3f616df71e570b380 100644 (file)
@@ -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 {
   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<Value> CallAsFunction(Handle<Object> recv,
-                                       int argc,
-                                       Handle<Value> argv[]);
-
   V8EXPORT static Local<Object> 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<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
  * mainly used to associate C++ data structures with JavaScript
index de3c1a5dd7f618be756b58087a952fb4f31f97fc..792e4886f8abacd9aeeaa288df313b95423e3aa6 100644 (file)
@@ -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 {
   return NewInstance(0, NULL);
 }
index 7423d28e2f807d9947604f7dc1503bb72d7aaf36..cd0205b2cc374b68612d965f30a8b13ae1e51f80 100644 (file)
--- 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:
index 850dec561f8151b66abd818831964c939e176a3e..eb26438fe87af6a1d264b3b9ad32ad0efab6e8e8 100644 (file)
@@ -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) {
   ASSERT(!object->IsJSFunction());
   Isolate* isolate = Isolate::Current();
index e89d6ba3971cbae35118c1b4c4dd4ea9b2ba1660..d4b80d274e24d34b96f1c9cee1caa9bc66b6da8a 100644 (file)
@@ -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<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.
index c7e9432c5211a5d4ba4048986fecc78eda12e3b4..e2a7fb1856c7c97398fa8e932652fbd275b295bf 100644 (file)
@@ -1050,8 +1050,10 @@ THREADED_TEST(Date) {
   v8::HandleScope scope;
   LocalContext env;
   double PI = 3.1415926;
-  Local<Value> date_obj = v8::Date::New(PI);
-  CHECK_EQ(3.0, date_obj->NumberValue());
+  Local<Value> date = v8::Date::New(PI);
+  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) {
   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());
-
-    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<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());
 
-    // 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<Value> 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<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());
+  // 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 "
-             "#<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();
-  }
+  value = CompileRun("obj.call = Function.prototype.call;"
+                     "obj.call(null, 87)");
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(87, value->Int32Value());
 
-  { 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());
+  // 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<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();
-  }
+  // 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<v8::Value> 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());