blob: 9667afb703972e5bd136067027baa766d60da78b [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blockd0582a62009-12-15 09:54:21 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
Steve Blockd0582a62009-12-15 09:54:21 +000031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/api.h"
33#include "src/frames-inl.h"
34#include "src/string-stream.h"
35#include "test/cctest/cctest.h"
Steve Blockd0582a62009-12-15 09:54:21 +000036
37using ::v8::ObjectTemplate;
38using ::v8::Value;
39using ::v8::Context;
40using ::v8::Local;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041using ::v8::Name;
Steve Blockd0582a62009-12-15 09:54:21 +000042using ::v8::String;
43using ::v8::Script;
44using ::v8::Function;
Steve Blockd0582a62009-12-15 09:54:21 +000045using ::v8::Extension;
46
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047static void handle_property(Local<String> name,
48 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blockd0582a62009-12-15 09:54:21 +000049 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 info.GetReturnValue().Set(v8_num(900));
51}
52
53static void handle_property_2(Local<String> name,
54 const v8::PropertyCallbackInfo<v8::Value>& info) {
55 ApiTestFuzzer::Fuzz();
56 info.GetReturnValue().Set(v8_num(902));
57}
58
59
60static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) {
61 ApiTestFuzzer::Fuzz();
62 CHECK_EQ(0, info.Length());
63 info.GetReturnValue().Set(v8_num(907));
Steve Blockd0582a62009-12-15 09:54:21 +000064}
65
66
67THREADED_TEST(PropertyHandler) {
Steve Blockd0582a62009-12-15 09:54:21 +000068 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 v8::Isolate* isolate = env->GetIsolate();
70 v8::HandleScope scope(isolate);
71 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
72 fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
73 Local<v8::FunctionTemplate> getter_templ =
74 v8::FunctionTemplate::New(isolate, handle_property);
75 getter_templ->SetLength(0);
76 fun_templ->
77 InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ);
78 fun_templ->InstanceTemplate()->
79 SetNativeDataProperty(v8_str("instance_foo"), handle_property);
80 fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
82 CHECK(env->Global()->Set(env.local(), v8_str("Fun"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 Local<Script> getter;
84 Local<Script> setter;
85 // check function instance accessors
86 getter = v8_compile("var obj = new Fun(); obj.instance_foo;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 CHECK_EQ(900, getter->Run(env.local())
88 .ToLocalChecked()
89 ->Int32Value(env.local())
90 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091 setter = v8_compile("obj.instance_foo = 901;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 CHECK_EQ(901, setter->Run(env.local())
93 .ToLocalChecked()
94 ->Int32Value(env.local())
95 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096 getter = v8_compile("obj.bar;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 CHECK_EQ(907, getter->Run(env.local())
98 .ToLocalChecked()
99 ->Int32Value(env.local())
100 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101 setter = v8_compile("obj.bar = 908;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 CHECK_EQ(908, setter->Run(env.local())
103 .ToLocalChecked()
104 ->Int32Value(env.local())
105 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000106 // check function static accessors
107 getter = v8_compile("Fun.object_foo;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 CHECK_EQ(902, getter->Run(env.local())
109 .ToLocalChecked()
110 ->Int32Value(env.local())
111 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 setter = v8_compile("Fun.object_foo = 903;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113 CHECK_EQ(903, setter->Run(env.local())
114 .ToLocalChecked()
115 ->Int32Value(env.local())
116 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000117}
118
119
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120static void GetIntValue(Local<String> property,
121 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blockd0582a62009-12-15 09:54:21 +0000122 ApiTestFuzzer::Fuzz();
123 int* value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 static_cast<int*>(v8::Local<v8::External>::Cast(info.Data())->Value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125 info.GetReturnValue().Set(v8_num(*value));
Steve Blockd0582a62009-12-15 09:54:21 +0000126}
127
128
129static void SetIntValue(Local<String> property,
130 Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131 const v8::PropertyCallbackInfo<void>& info) {
Steve Blockd0582a62009-12-15 09:54:21 +0000132 int* field =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 static_cast<int*>(v8::Local<v8::External>::Cast(info.Data())->Value());
134 *field = value->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust();
Steve Blockd0582a62009-12-15 09:54:21 +0000135}
136
137int foo, bar, baz;
138
139THREADED_TEST(GlobalVariableAccess) {
140 foo = 0;
141 bar = -4;
142 baz = 10;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 v8::Isolate* isolate = CcTest::isolate();
144 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 templ->InstanceTemplate()->SetAccessor(
147 v8_str("foo"), GetIntValue, SetIntValue,
148 v8::External::New(isolate, &foo));
149 templ->InstanceTemplate()->SetAccessor(
150 v8_str("bar"), GetIntValue, SetIntValue,
151 v8::External::New(isolate, &bar));
152 templ->InstanceTemplate()->SetAccessor(
153 v8_str("baz"), GetIntValue, SetIntValue,
154 v8::External::New(isolate, &baz));
Steve Blockd0582a62009-12-15 09:54:21 +0000155 LocalContext env(0, templ->InstanceTemplate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 v8_compile("foo = (++bar) + baz")->Run(env.local()).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000157 CHECK_EQ(bar, -3);
158 CHECK_EQ(foo, 7);
159}
160
161
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162static int x_register[2] = {0, 0};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000163static v8::Local<v8::Object> x_receiver;
164static v8::Local<v8::Object> x_holder;
Steve Blockd0582a62009-12-15 09:54:21 +0000165
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166template<class Info>
167static void XGetter(const Info& info, int offset) {
Steve Blockd0582a62009-12-15 09:54:21 +0000168 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 v8::Isolate* isolate = CcTest::isolate();
170 CHECK_EQ(isolate, info.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 CHECK(
172 x_receiver->Equals(isolate->GetCurrentContext(), info.This()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 info.GetReturnValue().Set(v8_num(x_register[offset]));
174}
175
176
177static void XGetter(Local<String> name,
178 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
180 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181 XGetter(info, 0);
182}
183
184
185static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 CHECK(
187 x_receiver->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
188 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 XGetter(info, 1);
190}
191
192
193template<class Info>
194static void XSetter(Local<Value> value, const Info& info, int offset) {
195 v8::Isolate* isolate = CcTest::isolate();
196 CHECK_EQ(isolate, info.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.This())
198 .FromJust());
199 CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
200 .FromJust());
201 x_register[offset] =
202 value->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 info.GetReturnValue().Set(v8_num(-1));
Steve Blockd0582a62009-12-15 09:54:21 +0000204}
205
206
207static void XSetter(Local<String> name,
208 Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 const v8::PropertyCallbackInfo<void>& info) {
210 XSetter(value, info, 0);
211}
212
213
214static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
215 CHECK_EQ(1, info.Length());
216 XSetter(info[0], info, 1);
Steve Blockd0582a62009-12-15 09:54:21 +0000217}
218
219
220THREADED_TEST(AccessorIC) {
Steve Blockd0582a62009-12-15 09:54:21 +0000221 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 v8::Isolate* isolate = context->GetIsolate();
223 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 obj->SetAccessor(v8_str("x0"), XGetter, XSetter);
226 obj->SetAccessorProperty(v8_str("x1"),
227 v8::FunctionTemplate::New(isolate, XGetter),
228 v8::FunctionTemplate::New(isolate, XSetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 x_holder = obj->NewInstance(context.local()).ToLocalChecked();
230 CHECK(context->Global()
231 ->Set(context.local(), v8_str("holder"), x_holder)
232 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 x_receiver = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 CHECK(context->Global()
235 ->Set(context.local(), v8_str("obj"), x_receiver)
236 .FromJust());
237 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(
238 CompileRun("obj.__proto__ = holder;"
239 "var result = [];"
240 "var key_0 = 'x0';"
241 "var key_1 = 'x1';"
242 "for (var j = 0; j < 10; j++) {"
243 " var i = 4*j;"
244 " result.push(holder.x0 = i);"
245 " result.push(obj.x0);"
246 " result.push(holder.x1 = i + 1);"
247 " result.push(obj.x1);"
248 " result.push(holder[key_0] = i + 2);"
249 " result.push(obj[key_0]);"
250 " result.push(holder[key_1] = i + 3);"
251 " result.push(obj[key_1]);"
252 "}"
253 "result"));
254 CHECK_EQ(80u, array->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 for (int i = 0; i < 80; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 v8::Local<Value> entry =
257 array->Get(context.local(), v8::Integer::New(isolate, i))
258 .ToLocalChecked();
259 CHECK(v8::Integer::New(isolate, i / 2)
260 ->Equals(context.local(), entry)
261 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000262 }
263}
264
265
Steve Blockd0582a62009-12-15 09:54:21 +0000266template <int C>
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267static void HandleAllocatingGetter(
268 Local<String> name,
269 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blockd0582a62009-12-15 09:54:21 +0000270 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 for (int i = 0; i < C; i++) {
272 v8::String::NewFromUtf8(info.GetIsolate(), "foo",
273 v8::NewStringType::kNormal)
274 .ToLocalChecked();
275 }
276 info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "foo",
277 v8::NewStringType::kNormal)
278 .ToLocalChecked());
Steve Blockd0582a62009-12-15 09:54:21 +0000279}
280
281
282THREADED_TEST(HandleScopePop) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283 LocalContext context;
284 v8::Isolate* isolate = context->GetIsolate();
285 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000287 obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
288 obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 v8::Local<v8::Object> inst =
290 obj->NewInstance(context.local()).ToLocalChecked();
291 CHECK(
292 context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 int count_before =
294 i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +0000295 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000297 CompileRun(
298 "for (var i = 0; i < 1000; i++) {"
299 " obj.one;"
300 " obj.many;"
301 "}");
302 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 int count_after =
304 i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +0000305 CHECK_EQ(count_before, count_after);
306}
307
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308static void CheckAccessorArgsCorrect(
309 Local<String> name,
310 const v8::PropertyCallbackInfo<v8::Value>& info) {
311 CHECK(info.GetIsolate() == CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +0000312 CHECK(info.This() == info.Holder());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 CHECK(info.Data()
314 ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
315 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000316 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 CHECK(info.GetIsolate() == CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +0000318 CHECK(info.This() == info.Holder());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319 CHECK(info.Data()
320 ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
321 .FromJust());
322 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 CHECK(info.GetIsolate() == CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +0000324 CHECK(info.This() == info.Holder());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325 CHECK(info.Data()
326 ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
327 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 info.GetReturnValue().Set(17);
Steve Blockd0582a62009-12-15 09:54:21 +0000329}
330
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000331
Steve Blockd0582a62009-12-15 09:54:21 +0000332THREADED_TEST(DirectCall) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333 LocalContext context;
334 v8::Isolate* isolate = context->GetIsolate();
335 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
337 obj->SetAccessor(v8_str("xxx"), CheckAccessorArgsCorrect, NULL,
338 v8_str("data"));
339 v8::Local<v8::Object> inst =
340 obj->NewInstance(context.local()).ToLocalChecked();
341 CHECK(
342 context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
343 Local<Script> scr =
344 v8::Script::Compile(context.local(), v8_str("obj.xxx")).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000345 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 Local<Value> result = scr->Run(context.local()).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000347 CHECK(!result.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348 CHECK_EQ(17, result->Int32Value(context.local()).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000349 }
350}
351
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352static void EmptyGetter(Local<String> name,
353 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blockd0582a62009-12-15 09:54:21 +0000354 CheckAccessorArgsCorrect(name, info);
355 ApiTestFuzzer::Fuzz();
356 CheckAccessorArgsCorrect(name, info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 info.GetReturnValue().Set(v8::Local<v8::Value>());
Steve Blockd0582a62009-12-15 09:54:21 +0000358}
359
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360
Steve Blockd0582a62009-12-15 09:54:21 +0000361THREADED_TEST(EmptyResult) {
Steve Blockd0582a62009-12-15 09:54:21 +0000362 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 v8::Isolate* isolate = context->GetIsolate();
364 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000365 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
366 obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8_str("data"));
367 v8::Local<v8::Object> inst =
368 obj->NewInstance(context.local()).ToLocalChecked();
369 CHECK(
370 context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 Local<Script> scr =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372 v8::Script::Compile(context.local(), v8_str("obj.xxx")).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000373 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374 Local<Value> result = scr->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000375 CHECK(result == v8::Undefined(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +0000376 }
377}
378
379
380THREADED_TEST(NoReuseRegress) {
381 // Check that the IC generated for the one test doesn't get reused
382 // for the other.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000383 v8::Isolate* isolate = CcTest::isolate();
384 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000385 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000386 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
387 obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8_str("data"));
Steve Blockd0582a62009-12-15 09:54:21 +0000388 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 v8::Local<v8::Object> inst =
390 obj->NewInstance(context.local()).ToLocalChecked();
391 CHECK(context->Global()
392 ->Set(context.local(), v8_str("obj"), inst)
393 .FromJust());
394 Local<Script> scr = v8::Script::Compile(context.local(), v8_str("obj.xxx"))
395 .ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000396 for (int i = 0; i < 2; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397 Local<Value> result = scr->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 CHECK(result == v8::Undefined(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +0000399 }
400 }
401 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
403 obj->SetAccessor(v8_str("xxx"), CheckAccessorArgsCorrect, NULL,
404 v8_str("data"));
Steve Blockd0582a62009-12-15 09:54:21 +0000405 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 v8::Local<v8::Object> inst =
407 obj->NewInstance(context.local()).ToLocalChecked();
408 CHECK(context->Global()
409 ->Set(context.local(), v8_str("obj"), inst)
410 .FromJust());
411 Local<Script> scr = v8::Script::Compile(context.local(), v8_str("obj.xxx"))
412 .ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000413 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000414 Local<Value> result = scr->Run(context.local()).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000415 CHECK(!result.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 CHECK_EQ(17, result->Int32Value(context.local()).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000417 }
418 }
419}
420
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421static void ThrowingGetAccessor(
422 Local<String> name,
423 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blockd0582a62009-12-15 09:54:21 +0000424 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 info.GetIsolate()->ThrowException(v8_str("g"));
Steve Blockd0582a62009-12-15 09:54:21 +0000426}
427
428
429static void ThrowingSetAccessor(Local<String> name,
430 Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 const v8::PropertyCallbackInfo<void>& info) {
432 info.GetIsolate()->ThrowException(value);
Steve Blockd0582a62009-12-15 09:54:21 +0000433}
434
435
436THREADED_TEST(Regress1054726) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437 LocalContext env;
438 v8::Isolate* isolate = env->GetIsolate();
439 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000441 obj->SetAccessor(v8_str("x"),
442 ThrowingGetAccessor,
443 ThrowingSetAccessor,
444 Local<Value>());
445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 CHECK(env->Global()
447 ->Set(env.local(), v8_str("obj"),
448 obj->NewInstance(env.local()).ToLocalChecked())
449 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000450
451 // Use the throwing property setter/getter in a loop to force
452 // the accessor ICs to be initialized.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 v8::Local<Value> result;
454 result = Script::Compile(env.local(),
455 v8_str("var result = '';"
456 "for (var i = 0; i < 5; i++) {"
457 " try { obj.x; } catch (e) { result += e; }"
458 "}; result"))
459 .ToLocalChecked()
460 ->Run(env.local())
461 .ToLocalChecked();
462 CHECK(v8_str("ggggg")->Equals(env.local(), result).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000463
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 result =
465 Script::Compile(env.local(),
466 v8_str("var result = '';"
467 "for (var i = 0; i < 5; i++) {"
468 " try { obj.x = i; } catch (e) { result += e; }"
469 "}; result"))
470 .ToLocalChecked()
471 ->Run(env.local())
472 .ToLocalChecked();
473 CHECK(v8_str("01234")->Equals(env.local(), result).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000474}
475
476
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000477static void AllocGetter(Local<String> name,
478 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blockd0582a62009-12-15 09:54:21 +0000479 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000480 info.GetReturnValue().Set(v8::Array::New(info.GetIsolate(), 1000));
Steve Blockd0582a62009-12-15 09:54:21 +0000481}
482
483
484THREADED_TEST(Gc) {
Steve Blockd0582a62009-12-15 09:54:21 +0000485 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486 v8::Isolate* isolate = env->GetIsolate();
487 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489 obj->SetAccessor(v8_str("xxx"), AllocGetter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 CHECK(env->Global()
491 ->Set(env.local(), v8_str("obj"),
492 obj->NewInstance(env.local()).ToLocalChecked())
493 .FromJust());
494 Script::Compile(env.local(), v8_str("var last = [];"
495 "for (var i = 0; i < 2048; i++) {"
496 " var result = obj.xxx;"
497 " result[0] = last;"
498 " last = result;"
499 "}"))
500 .ToLocalChecked()
501 ->Run(env.local())
502 .ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000503}
504
505
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506static void StackCheck(Local<String> name,
507 const v8::PropertyCallbackInfo<v8::Value>& info) {
508 i::StackFrameIterator iter(reinterpret_cast<i::Isolate*>(info.GetIsolate()));
Steve Blockd0582a62009-12-15 09:54:21 +0000509 for (int i = 0; !iter.done(); i++) {
510 i::StackFrame* frame = iter.frame();
511 CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100512 i::Code* code = frame->LookupCode();
Steve Block44f0eee2011-05-26 01:26:41 +0100513 CHECK(code->IsCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000514 i::Address pc = frame->pc();
Steve Blockd0582a62009-12-15 09:54:21 +0000515 CHECK(code->contains(pc));
516 iter.Advance();
517 }
Steve Blockd0582a62009-12-15 09:54:21 +0000518}
519
520
521THREADED_TEST(StackIteration) {
Steve Blockd0582a62009-12-15 09:54:21 +0000522 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 v8::Isolate* isolate = env->GetIsolate();
524 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000526 i::StringStream::ClearMentionedObjectCache(
527 reinterpret_cast<i::Isolate*>(isolate));
528 obj->SetAccessor(v8_str("xxx"), StackCheck);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 CHECK(env->Global()
530 ->Set(env.local(), v8_str("obj"),
531 obj->NewInstance(env.local()).ToLocalChecked())
532 .FromJust());
533 Script::Compile(env.local(), v8_str("function foo() {"
534 " return obj.xxx;"
535 "}"
536 "for (var i = 0; i < 100; i++) {"
537 " foo();"
538 "}"))
539 .ToLocalChecked()
540 ->Run(env.local())
541 .ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +0000542}
543
544
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545static void AllocateHandles(Local<String> name,
546 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blockd0582a62009-12-15 09:54:21 +0000547 for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000548 v8::Local<v8::Value>::New(info.GetIsolate(), name);
Steve Blockd0582a62009-12-15 09:54:21 +0000549 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000550 info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 100));
Steve Blockd0582a62009-12-15 09:54:21 +0000551}
552
553
554THREADED_TEST(HandleScopeSegment) {
555 // Check that we can return values past popping of handle scope
556 // segments.
Steve Blockd0582a62009-12-15 09:54:21 +0000557 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 v8::Isolate* isolate = env->GetIsolate();
559 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561 obj->SetAccessor(v8_str("xxx"), AllocateHandles);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562 CHECK(env->Global()
563 ->Set(env.local(), v8_str("obj"),
564 obj->NewInstance(env.local()).ToLocalChecked())
565 .FromJust());
566 v8::Local<v8::Value> result =
567 Script::Compile(env.local(), v8_str("var result;"
568 "for (var i = 0; i < 4; i++)"
569 " result = obj.xxx;"
570 "result;"))
571 .ToLocalChecked()
572 ->Run(env.local())
573 .ToLocalChecked();
574 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +0000575}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576
577
578void JSONStringifyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), 1);
580 CHECK(array->Set(info.GetIsolate()->GetCurrentContext(), 0, v8_str("regress"))
581 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000582 info.GetReturnValue().Set(array);
583}
584
585
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400586void JSONStringifyGetter(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587 const v8::PropertyCallbackInfo<v8::Value>& info) {
588 info.GetReturnValue().Set(v8_str("crbug-161028"));
589}
590
591
592THREADED_TEST(JSONStringifyNamedInterceptorObject) {
593 LocalContext env;
594 v8::Isolate* isolate = env->GetIsolate();
595 v8::HandleScope scope(isolate);
596
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400598 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
599 JSONStringifyGetter, NULL, NULL, NULL, JSONStringifyEnumerator));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600 CHECK(env->Global()
601 ->Set(env.local(), v8_str("obj"),
602 obj->NewInstance(env.local()).ToLocalChecked())
603 .FromJust());
604 v8::Local<v8::String> expected = v8_str("{\"regress\":\"crbug-161028\"}");
605 CHECK(CompileRun("JSON.stringify(obj)")
606 ->Equals(env.local(), expected)
607 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000608}
609
610
611static v8::Local<v8::Context> expected_current_context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612
613
614static void check_contexts(const v8::FunctionCallbackInfo<v8::Value>& info) {
615 ApiTestFuzzer::Fuzz();
616 CHECK(expected_current_context == info.GetIsolate()->GetCurrentContext());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617}
618
619
620THREADED_TEST(AccessorPropertyCrossContext) {
621 LocalContext env;
622 v8::Isolate* isolate = env->GetIsolate();
623 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 v8::Local<v8::Function> fun =
625 v8::Function::New(env.local(), check_contexts).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000626 LocalContext switch_context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627 CHECK(switch_context->Global()
628 ->Set(switch_context.local(), v8_str("fun"), fun)
629 .FromJust());
630 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 expected_current_context = env.local();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632 CompileRun(
633 "var o = Object.create(null, { n: { get:fun } });"
634 "for (var i = 0; i < 10; i++) o.n;");
635 CHECK(!try_catch.HasCaught());
636}
637
638
639THREADED_TEST(GlobalObjectAccessor) {
640 LocalContext env;
641 v8::Isolate* isolate = env->GetIsolate();
642 v8::HandleScope scope(isolate);
643 CompileRun(
644 "var set_value = 1;"
645 "Object.defineProperty(this.__proto__, 'x', {"
646 " get : function() { return this; },"
647 " set : function() { set_value = this; }"
648 "});"
649 "function getter() { return x; }"
650 "function setter() { x = 1; }"
651 "for (var i = 0; i < 4; i++) { getter(); setter(); }");
652 CHECK(v8::Utils::OpenHandle(*CompileRun("getter()"))->IsJSGlobalProxy());
653 CHECK(v8::Utils::OpenHandle(*CompileRun("set_value"))->IsJSGlobalProxy());
654}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400655
656
657static void EmptyGetter(Local<Name> name,
658 const v8::PropertyCallbackInfo<v8::Value>& info) {
659 ApiTestFuzzer::Fuzz();
660}
661
662
663static void OneProperty(Local<String> name,
664 const v8::PropertyCallbackInfo<v8::Value>& info) {
665 ApiTestFuzzer::Fuzz();
666 info.GetReturnValue().Set(v8_num(1));
667}
668
669
670THREADED_TEST(Regress433458) {
671 LocalContext env;
672 v8::Isolate* isolate = env->GetIsolate();
673 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400675 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(EmptyGetter));
676 obj->SetNativeDataProperty(v8_str("prop"), OneProperty);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000677 CHECK(env->Global()
678 ->Set(env.local(), v8_str("obj"),
679 obj->NewInstance(env.local()).ToLocalChecked())
680 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400681 CompileRun(
682 "Object.defineProperty(obj, 'prop', { writable: false });"
683 "Object.defineProperty(obj, 'prop', { writable: true });");
684}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000685
686
687static bool security_check_value = false;
688
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689static bool SecurityTestCallback(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100690 Local<v8::Object> accessed_object,
691 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 return security_check_value;
693}
694
695
696TEST(PrototypeGetterAccessCheck) {
697 i::FLAG_allow_natives_syntax = true;
698 LocalContext env;
699 v8::Isolate* isolate = env->GetIsolate();
700 v8::HandleScope scope(isolate);
701 auto fun_templ = v8::FunctionTemplate::New(isolate);
702 auto getter_templ = v8::FunctionTemplate::New(isolate, handle_property);
703 getter_templ->SetAcceptAnyReceiver(false);
704 fun_templ->InstanceTemplate()->SetAccessorProperty(v8_str("foo"),
705 getter_templ);
706 auto obj_templ = v8::ObjectTemplate::New(isolate);
707 obj_templ->SetAccessCheckCallback(SecurityTestCallback);
708 CHECK(env->Global()
709 ->Set(env.local(), v8_str("Fun"),
710 fun_templ->GetFunction(env.local()).ToLocalChecked())
711 .FromJust());
712 CHECK(env->Global()
713 ->Set(env.local(), v8_str("obj"),
714 obj_templ->NewInstance(env.local()).ToLocalChecked())
715 .FromJust());
716 CHECK(env->Global()
717 ->Set(env.local(), v8_str("obj2"),
718 obj_templ->NewInstance(env.local()).ToLocalChecked())
719 .FromJust());
720
721 security_check_value = true;
722 CompileRun("var proto = new Fun();");
723 CompileRun("obj.__proto__ = proto;");
724 ExpectInt32("proto.foo", 907);
725
726 // Test direct.
727 security_check_value = true;
728 ExpectInt32("obj.foo", 907);
729 security_check_value = false;
730 {
731 v8::TryCatch try_catch(isolate);
732 CompileRun("obj.foo");
733 CHECK(try_catch.HasCaught());
734 }
735
736 // Test through call.
737 security_check_value = true;
738 ExpectInt32("proto.__lookupGetter__('foo').call(obj)", 907);
739 security_check_value = false;
740 {
741 v8::TryCatch try_catch(isolate);
742 CompileRun("proto.__lookupGetter__('foo').call(obj)");
743 CHECK(try_catch.HasCaught());
744 }
745
746 // Test ics.
747 CompileRun(
748 "function f() {"
749 " var x;"
750 " for (var i = 0; i < 4; i++) {"
751 " x = obj.foo;"
752 " }"
753 " return x;"
754 "}");
755
756 security_check_value = true;
757 ExpectInt32("f()", 907);
758 security_check_value = false;
759 {
760 v8::TryCatch try_catch(isolate);
761 CompileRun("f();");
762 CHECK(try_catch.HasCaught());
763 }
764
765 // Test crankshaft.
766 CompileRun("%OptimizeFunctionOnNextCall(f);");
767
768 security_check_value = true;
769 ExpectInt32("f()", 907);
770 security_check_value = false;
771 {
772 v8::TryCatch try_catch(isolate);
773 CompileRun("f();");
774 CHECK(try_catch.HasCaught());
775 }
776}
Ben Murdochda12d292016-06-02 14:46:10 +0100777
Ben Murdochc5610432016-08-08 18:44:38 +0100778static void CheckReceiver(Local<String> name,
779 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochda12d292016-06-02 14:46:10 +0100780 CHECK(info.This()->IsObject());
781}
782
783TEST(Regress609134) {
Ben Murdochda12d292016-06-02 14:46:10 +0100784 LocalContext env;
785 v8::Isolate* isolate = env->GetIsolate();
786 v8::HandleScope scope(isolate);
787 auto fun_templ = v8::FunctionTemplate::New(isolate);
788 fun_templ->InstanceTemplate()->SetNativeDataProperty(v8_str("foo"),
Ben Murdochc5610432016-08-08 18:44:38 +0100789 CheckReceiver);
Ben Murdochda12d292016-06-02 14:46:10 +0100790
791 CHECK(env->Global()
792 ->Set(env.local(), v8_str("Fun"),
793 fun_templ->GetFunction(env.local()).ToLocalChecked())
794 .FromJust());
795
796 CompileRun(
797 "var f = new Fun();"
798 "Number.prototype.__proto__ = f;"
Ben Murdochc5610432016-08-08 18:44:38 +0100799 "var a = 42;"
800 "for (var i = 0; i<3; i++) { a.foo; }");
Ben Murdochda12d292016-06-02 14:46:10 +0100801}