};
-/**
- * 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,
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:
};
+/**
+ * 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
}
-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);
}
-// 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:
}
-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();
// 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.
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());
}
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());
}
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());