1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
From 472c04c9e7a64e8734c76d2cf97a7cc5b773b788 Mon Sep 17 00:00:00 2001
From: ager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
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<i::JSObject> obj = Utils::OpenHandle(this);
+ if (obj->IsJSFunction()) return true;
+ return i::Execution::GetFunctionDelegate(obj)->IsJSFunction();
+}
+
+
Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc,
v8::Handle<v8::Value> 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<ObjectTemplate> instance_template = ObjectTemplate::New();
+ instance_template->SetCallAsFunctionHandler(call_as_function);
+ Local<Object> instance = instance_template->NewInstance();
+ v8::TryCatch try_catch;
+
+ CHECK(instance->IsCallable());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
+ Local<Object> instance = instance_template->NewInstance();
+ v8::TryCatch try_catch;
+
+ CHECK(!instance->IsCallable());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ { Local<FunctionTemplate> function_template =
+ FunctionTemplate::New(call_as_function);
+ Local<Function> function = function_template->GetFunction();
+ Local<Object> instance = function;
+ v8::TryCatch try_catch;
+
+ CHECK(instance->IsCallable());
+ CHECK(!try_catch.HasCaught());
+ }
+
+ { Local<FunctionTemplate> function_template = FunctionTemplate::New();
+ Local<Function> function = function_template->GetFunction();
+ Local<Object> instance = function;
+ v8::TryCatch try_catch;
+
+ CHECK(instance->IsCallable());
+ CHECK(!try_catch.HasCaught());
+ }
+}
+
+
static int CountHandles() {
return v8::HandleScope::NumberOfHandles();
}
--
1.7.2.3
|