OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/logging.h" | 5 #include "base/logging.h" |
6 #include "gin/arguments.h" | 6 #include "gin/arguments.h" |
7 #include "gin/handle.h" | 7 #include "gin/handle.h" |
8 #include "gin/object_template_builder.h" | 8 #include "gin/object_template_builder.h" |
9 #include "gin/per_isolate_data.h" | 9 #include "gin/per_isolate_data.h" |
10 #include "gin/public/isolate_holder.h" | 10 #include "gin/public/isolate_holder.h" |
11 #include "gin/test/v8_test.h" | 11 #include "gin/test/v8_test.h" |
12 #include "gin/try_catch.h" | 12 #include "gin/try_catch.h" |
13 #include "gin/wrappable.h" | 13 #include "gin/wrappable.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
15 | 15 |
16 namespace gin { | 16 namespace gin { |
17 | 17 |
18 class BaseClass { | 18 class MyObject : public Wrappable<MyObject> { |
19 public: | |
20 BaseClass() : value_(23) {} | |
21 virtual ~BaseClass() {} | |
22 | |
23 private: | |
24 int value_; | |
25 | |
26 DISALLOW_COPY_AND_ASSIGN(BaseClass); | |
27 }; | |
28 | |
29 class MyObject : public BaseClass, | |
30 public Wrappable<MyObject> { | |
31 public: | 19 public: |
32 static WrapperInfo kWrapperInfo; | 20 static WrapperInfo kWrapperInfo; |
33 | 21 |
34 static gin::Handle<MyObject> Create(v8::Isolate* isolate) { | 22 static gin::Handle<MyObject> Create(v8::Isolate* isolate) { |
35 return CreateHandle(isolate, new MyObject()); | 23 return CreateHandle(isolate, new MyObject()); |
36 } | 24 } |
37 | 25 |
38 int value() const { return value_; } | 26 int value() const { return value_; } |
39 void set_value(int value) { value_ = value; } | 27 void set_value(int value) { value_ = value; } |
40 | 28 |
41 protected: | 29 protected: |
42 MyObject() : value_(0) {} | 30 MyObject() : value_(0) {} |
43 ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) override; | 31 ObjectTemplateBuilder GetObjectTemplateBuilder( |
32 v8::Isolate* isolate) override { | |
33 return Wrappable<MyObject>::GetObjectTemplateBuilder(isolate) | |
34 .SetProperty("value", &MyObject::value, &MyObject::set_value); | |
35 } | |
44 ~MyObject() override {} | 36 ~MyObject() override {} |
45 | 37 |
46 private: | 38 private: |
47 int value_; | 39 int value_; |
48 }; | 40 }; |
49 | 41 |
50 class MyObjectSubclass : public MyObject { | 42 class SpacerClass { |
51 public: | 43 public: |
44 SpacerClass() : value_(23) {} | |
45 virtual ~SpacerClass() {} | |
46 | |
47 private: | |
48 int value_; | |
49 | |
50 DISALLOW_COPY_AND_ASSIGN(SpacerClass); | |
51 }; | |
52 | |
53 class MyObjectSubclass : public SpacerClass, public MyObject { | |
54 public: | |
55 static WrapperInfo kWrapperInfo; | |
56 | |
52 static gin::Handle<MyObjectSubclass> Create(v8::Isolate* isolate) { | 57 static gin::Handle<MyObjectSubclass> Create(v8::Isolate* isolate) { |
53 return CreateHandle(isolate, new MyObjectSubclass()); | 58 return CreateHandle(isolate, new MyObjectSubclass()); |
54 } | 59 } |
55 | 60 |
61 WrapperInfo* GetWrapperInfo() override { | |
62 return &MyObjectSubclass::kWrapperInfo; | |
63 } | |
64 | |
56 void SayHello(const std::string& name) { | 65 void SayHello(const std::string& name) { |
57 result = std::string("Hello, ") + name; | 66 result = std::string("Hello, ") + name; |
58 } | 67 } |
59 | 68 |
60 std::string result; | 69 std::string result; |
61 | 70 |
62 private: | 71 private: |
63 ObjectTemplateBuilder GetObjectTemplateBuilder( | 72 ObjectTemplateBuilder GetObjectTemplateBuilder( |
64 v8::Isolate* isolate) override { | 73 v8::Isolate* isolate) override { |
65 return MyObject::GetObjectTemplateBuilder(isolate) | 74 return MyObject::GetObjectTemplateBuilder(isolate) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
97 void Call(int val1, int val2, int val3, const gin::Arguments& arguments) { | 106 void Call(int val1, int val2, int val3, const gin::Arguments& arguments) { |
98 if (arguments.IsConstructCall()) | 107 if (arguments.IsConstructCall()) |
99 arguments.ThrowTypeError("Cannot be called as constructor."); | 108 arguments.ThrowTypeError("Cannot be called as constructor."); |
100 else | 109 else |
101 result_ = val1; | 110 result_ = val1; |
102 } | 111 } |
103 | 112 |
104 int result_; | 113 int result_; |
105 }; | 114 }; |
106 | 115 |
107 class MyObject2 : public Wrappable<MyObject2> { | |
108 public: | |
109 static WrapperInfo kWrapperInfo; | |
110 }; | |
111 | |
112 class MyObjectBlink : public Wrappable<MyObjectBlink> { | |
113 public: | |
114 static WrapperInfo kWrapperInfo; | |
115 }; | |
116 | |
117 WrapperInfo MyObject::kWrapperInfo = { kEmbedderNativeGin }; | 116 WrapperInfo MyObject::kWrapperInfo = { kEmbedderNativeGin }; |
118 ObjectTemplateBuilder MyObject::GetObjectTemplateBuilder(v8::Isolate* isolate) { | 117 WrapperInfo MyObjectSubclass::kWrapperInfo = { kEmbedderNativeGin }; |
119 return Wrappable<MyObject>::GetObjectTemplateBuilder(isolate) | |
120 .SetProperty("value", &MyObject::value, &MyObject::set_value); | |
121 } | |
122 | |
123 WrapperInfo MyCallableObject::kWrapperInfo = { kEmbedderNativeGin }; | 118 WrapperInfo MyCallableObject::kWrapperInfo = { kEmbedderNativeGin }; |
124 WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin }; | |
125 WrapperInfo MyObjectBlink::kWrapperInfo = { kEmbedderNativeGin }; | |
126 | 119 |
127 typedef V8Test WrappableTest; | 120 typedef V8Test WrappableTest; |
128 | 121 |
129 TEST_F(WrappableTest, WrapAndUnwrap) { | 122 TEST_F(WrappableTest, WrapAndUnwrap) { |
130 v8::Isolate* isolate = instance_->isolate(); | 123 v8::Isolate* isolate = instance_->isolate(); |
131 v8::HandleScope handle_scope(isolate); | 124 v8::HandleScope handle_scope(isolate); |
132 | 125 |
133 Handle<MyObject> obj = MyObject::Create(isolate); | 126 Handle<MyObject> obj = MyObject::Create(isolate); |
134 | 127 |
135 v8::Local<v8::Value> wrapper = ConvertToV8(isolate, obj.get()); | 128 v8::Local<v8::Value> wrapper = ConvertToV8(isolate, obj.get()); |
(...skipping 11 matching lines...) Expand all Loading... | |
147 // Something that isn't an object. | 140 // Something that isn't an object. |
148 v8::Local<v8::Value> thing = v8::Number::New(isolate, 42); | 141 v8::Local<v8::Value> thing = v8::Number::New(isolate, 42); |
149 MyObject* unwrapped = NULL; | 142 MyObject* unwrapped = NULL; |
150 EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped)); | 143 EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped)); |
151 EXPECT_FALSE(unwrapped); | 144 EXPECT_FALSE(unwrapped); |
152 | 145 |
153 // An object that's not wrapping anything. | 146 // An object that's not wrapping anything. |
154 thing = v8::Object::New(isolate); | 147 thing = v8::Object::New(isolate); |
155 EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped)); | 148 EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped)); |
156 EXPECT_FALSE(unwrapped); | 149 EXPECT_FALSE(unwrapped); |
157 | |
158 // An object that's wrapping a C++ object from Blink. | |
159 thing.Clear(); | |
160 thing = ConvertToV8(isolate, new MyObjectBlink()); | |
161 EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped)); | |
162 EXPECT_FALSE(unwrapped); | |
163 | |
164 // An object that's wrapping a C++ object of the wrong type. | |
165 thing.Clear(); | |
166 thing = ConvertToV8(isolate, new MyObject2()); | |
167 EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped)); | |
168 EXPECT_FALSE(unwrapped); | |
169 } | 150 } |
170 | 151 |
171 TEST_F(WrappableTest, GetAndSetProperty) { | 152 TEST_F(WrappableTest, GetAndSetProperty) { |
172 v8::Isolate* isolate = instance_->isolate(); | 153 v8::Isolate* isolate = instance_->isolate(); |
173 v8::HandleScope handle_scope(isolate); | 154 v8::HandleScope handle_scope(isolate); |
174 | 155 |
175 gin::Handle<MyObject> obj = MyObject::Create(isolate); | 156 gin::Handle<MyObject> obj = MyObject::Create(isolate); |
176 | 157 |
177 obj->set_value(42); | 158 obj->set_value(42); |
178 EXPECT_EQ(42, obj->value()); | 159 EXPECT_EQ(42, obj->value()); |
(...skipping 18 matching lines...) Expand all Loading... | |
197 EXPECT_FALSE(try_catch.HasCaught()); | 178 EXPECT_FALSE(try_catch.HasCaught()); |
198 EXPECT_EQ("", try_catch.GetStackTrace()); | 179 EXPECT_EQ("", try_catch.GetStackTrace()); |
199 | 180 |
200 EXPECT_EQ(191, obj->value()); | 181 EXPECT_EQ(191, obj->value()); |
201 } | 182 } |
202 | 183 |
203 TEST_F(WrappableTest, WrappableSubclass) { | 184 TEST_F(WrappableTest, WrappableSubclass) { |
204 v8::Isolate* isolate = instance_->isolate(); | 185 v8::Isolate* isolate = instance_->isolate(); |
205 v8::HandleScope handle_scope(isolate); | 186 v8::HandleScope handle_scope(isolate); |
206 | 187 |
188 // Create a base class first to ensure that MyObjectSubclass instances can | |
189 // co-exist and be distinguished from the base class. This will fail if | |
190 // the subclass doesn't provide an overridden GetWrapperInfo(). | |
191 gin::Handle<MyObject> base_class_instance = MyObject::Create(isolate); | |
tommycli
2015/06/02 22:01:23
This test tickles the problem that caused those my
| |
192 base_class_instance->set_value(42); | |
193 | |
207 gin::Handle<MyObjectSubclass> object(MyObjectSubclass::Create(isolate)); | 194 gin::Handle<MyObjectSubclass> object(MyObjectSubclass::Create(isolate)); |
208 v8::Local<v8::String> source = StringToV8(isolate, | 195 v8::Local<v8::String> source = StringToV8(isolate, |
209 "(function(obj) {" | 196 "(function(obj) {" |
210 "obj.sayHello('Lily');" | 197 "obj.sayHello('Lily');" |
211 "})"); | 198 "})"); |
199 | |
200 v8::Local<v8::Value> wrapper = ConvertToV8(isolate, object.get()); | |
201 EXPECT_FALSE(wrapper.IsEmpty()); | |
202 | |
203 // Ensure wrap and unwrap works for the subclass. | |
204 MyObjectSubclass* unwrapped = nullptr; | |
205 EXPECT_TRUE(ConvertFromV8(isolate, wrapper, &unwrapped)); | |
206 EXPECT_EQ(object.get(), unwrapped); | |
207 | |
208 // Ensure wrap and unwrap to the base class correctly adjusts the pointer. | |
209 // The static_cast is strictly speaking unnecessary, as MyObjectSubclass* | |
210 // pointers are transparently adjusted when compared to MyObject* pointers. | |
211 // MyObject* unwrapped_base = nullptr; | |
212 // EXPECT_TRUE(ConvertFromV8(isolate, wrapper, &unwrapped_base)); | |
213 // EXPECT_EQ(static_cast<MyObject*>(object.get()), unwrapped_base); | |
214 | |
215 // Ensure subclass-defined Javascript calls work. | |
212 gin::TryCatch try_catch(isolate); | 216 gin::TryCatch try_catch(isolate); |
213 v8::Local<v8::Script> script = v8::Script::Compile(source); | 217 v8::Local<v8::Script> script = v8::Script::Compile(source); |
214 v8::Local<v8::Value> val = script->Run(); | 218 v8::Local<v8::Value> val = script->Run(); |
215 v8::Local<v8::Function> func; | 219 v8::Local<v8::Function> func; |
216 EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); | 220 EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); |
217 v8::Local<v8::Value> argv[] = { | 221 v8::Local<v8::Value> argv[] = { |
218 ConvertToV8(isolate, object.get()) | 222 ConvertToV8(isolate, object.get()) |
219 }; | 223 }; |
220 func->Call(v8::Undefined(isolate), 1, argv); | 224 func->Call(v8::Undefined(isolate), 1, argv); |
221 EXPECT_FALSE(try_catch.HasCaught()); | 225 EXPECT_FALSE(try_catch.HasCaught()); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
261 v8::Local<v8::Function> func; | 265 v8::Local<v8::Function> func; |
262 EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); | 266 EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); |
263 v8::Local<v8::Value> argv[] = { | 267 v8::Local<v8::Value> argv[] = { |
264 ConvertToV8(isolate, object.get()) | 268 ConvertToV8(isolate, object.get()) |
265 }; | 269 }; |
266 func->Call(v8::Undefined(isolate), 1, argv); | 270 func->Call(v8::Undefined(isolate), 1, argv); |
267 EXPECT_TRUE(try_catch.HasCaught()); | 271 EXPECT_TRUE(try_catch.HasCaught()); |
268 } | 272 } |
269 | 273 |
270 } // namespace gin | 274 } // namespace gin |
OLD | NEW |