Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // 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 :
30 : #include "src/v8.h"
31 :
32 : #include "src/api.h"
33 : #include "src/frames-inl.h"
34 : #include "src/string-stream.h"
35 : #include "test/cctest/cctest.h"
36 :
37 : using ::v8::ObjectTemplate;
38 : using ::v8::Value;
39 : using ::v8::Context;
40 : using ::v8::Local;
41 : using ::v8::Name;
42 : using ::v8::String;
43 : using ::v8::Script;
44 : using ::v8::Function;
45 : using ::v8::Extension;
46 :
47 6 : static void handle_property(Local<String> name,
48 : const v8::PropertyCallbackInfo<v8::Value>& info) {
49 6 : ApiTestFuzzer::Fuzz();
50 6 : info.GetReturnValue().Set(v8_num(900));
51 6 : }
52 :
53 6 : static void handle_property_2(Local<String> name,
54 : const v8::PropertyCallbackInfo<v8::Value>& info) {
55 6 : ApiTestFuzzer::Fuzz();
56 6 : info.GetReturnValue().Set(v8_num(902));
57 6 : }
58 :
59 :
60 183 : static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) {
61 61 : ApiTestFuzzer::Fuzz();
62 61 : CHECK_EQ(0, info.Length());
63 61 : info.GetReturnValue().Set(v8_num(907));
64 61 : }
65 :
66 :
67 23724 : THREADED_TEST(PropertyHandler) {
68 6 : LocalContext env;
69 6 : v8::Isolate* isolate = env->GetIsolate();
70 12 : v8::HandleScope scope(isolate);
71 6 : Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
72 12 : fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
73 : Local<v8::FunctionTemplate> getter_templ =
74 6 : v8::FunctionTemplate::New(isolate, handle_property);
75 6 : getter_templ->SetLength(0);
76 : fun_templ->
77 18 : InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ);
78 12 : fun_templ->InstanceTemplate()->
79 18 : SetNativeDataProperty(v8_str("instance_foo"), handle_property);
80 6 : fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2);
81 6 : Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
82 30 : CHECK(env->Global()->Set(env.local(), v8_str("Fun"), fun).FromJust());
83 : Local<Script> getter;
84 : Local<Script> setter;
85 : // check function instance accessors
86 : getter = v8_compile("var obj = new Fun(); obj.instance_foo;");
87 18 : CHECK_EQ(900, getter->Run(env.local())
88 : .ToLocalChecked()
89 : ->Int32Value(env.local())
90 : .FromJust());
91 : setter = v8_compile("obj.instance_foo = 901;");
92 18 : CHECK_EQ(901, setter->Run(env.local())
93 : .ToLocalChecked()
94 : ->Int32Value(env.local())
95 : .FromJust());
96 : getter = v8_compile("obj.bar;");
97 18 : CHECK_EQ(907, getter->Run(env.local())
98 : .ToLocalChecked()
99 : ->Int32Value(env.local())
100 : .FromJust());
101 : setter = v8_compile("obj.bar = 908;");
102 18 : CHECK_EQ(908, setter->Run(env.local())
103 : .ToLocalChecked()
104 : ->Int32Value(env.local())
105 : .FromJust());
106 : // check function static accessors
107 : getter = v8_compile("Fun.object_foo;");
108 18 : CHECK_EQ(902, getter->Run(env.local())
109 : .ToLocalChecked()
110 : ->Int32Value(env.local())
111 : .FromJust());
112 : setter = v8_compile("Fun.object_foo = 903;");
113 18 : CHECK_EQ(903, setter->Run(env.local())
114 : .ToLocalChecked()
115 : ->Int32Value(env.local())
116 6 : .FromJust());
117 6 : }
118 :
119 :
120 12 : static void GetIntValue(Local<String> property,
121 : const v8::PropertyCallbackInfo<v8::Value>& info) {
122 12 : ApiTestFuzzer::Fuzz();
123 : int* value =
124 12 : static_cast<int*>(v8::Local<v8::External>::Cast(info.Data())->Value());
125 12 : info.GetReturnValue().Set(v8_num(*value));
126 12 : }
127 :
128 :
129 12 : static void SetIntValue(Local<String> property,
130 : Local<Value> value,
131 : const v8::PropertyCallbackInfo<void>& info) {
132 : int* field =
133 12 : static_cast<int*>(v8::Local<v8::External>::Cast(info.Data())->Value());
134 36 : *field = value->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust();
135 12 : }
136 :
137 : int foo, bar, baz;
138 :
139 23724 : THREADED_TEST(GlobalVariableAccess) {
140 6 : foo = 0;
141 6 : bar = -4;
142 6 : baz = 10;
143 6 : v8::Isolate* isolate = CcTest::isolate();
144 6 : v8::HandleScope scope(isolate);
145 6 : v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
146 : templ->InstanceTemplate()->SetAccessor(
147 : v8_str("foo"), GetIntValue, SetIntValue,
148 18 : v8::External::New(isolate, &foo));
149 : templ->InstanceTemplate()->SetAccessor(
150 : v8_str("bar"), GetIntValue, SetIntValue,
151 18 : v8::External::New(isolate, &bar));
152 : templ->InstanceTemplate()->SetAccessor(
153 : v8_str("baz"), GetIntValue, SetIntValue,
154 18 : v8::External::New(isolate, &baz));
155 12 : LocalContext env(0, templ->InstanceTemplate());
156 12 : v8_compile("foo = (++bar) + baz")->Run(env.local()).ToLocalChecked();
157 6 : CHECK_EQ(-3, bar);
158 12 : CHECK_EQ(7, foo);
159 6 : }
160 :
161 :
162 : static int x_register[2] = {0, 0};
163 : static v8::Local<v8::Object> x_receiver;
164 : static v8::Local<v8::Object> x_holder;
165 :
166 : template<class Info>
167 600 : static void XGetter(const Info& info, int offset) {
168 240 : ApiTestFuzzer::Fuzz();
169 240 : v8::Isolate* isolate = CcTest::isolate();
170 240 : CHECK_EQ(isolate, info.GetIsolate());
171 720 : CHECK(
172 : x_receiver->Equals(isolate->GetCurrentContext(), info.This()).FromJust());
173 240 : info.GetReturnValue().Set(v8_num(x_register[offset]));
174 240 : }
175 :
176 :
177 120 : static void XGetter(Local<String> name,
178 : const v8::PropertyCallbackInfo<v8::Value>& info) {
179 360 : CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
180 : .FromJust());
181 120 : XGetter(info, 0);
182 120 : }
183 :
184 :
185 120 : static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
186 360 : CHECK(
187 : x_receiver->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
188 : .FromJust());
189 120 : XGetter(info, 1);
190 120 : }
191 :
192 :
193 : template<class Info>
194 840 : static void XSetter(Local<Value> value, const Info& info, int offset) {
195 240 : v8::Isolate* isolate = CcTest::isolate();
196 240 : CHECK_EQ(isolate, info.GetIsolate());
197 720 : CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.This())
198 : .FromJust());
199 720 : CHECK(x_holder->Equals(info.GetIsolate()->GetCurrentContext(), info.Holder())
200 : .FromJust());
201 720 : x_register[offset] =
202 : value->Int32Value(info.GetIsolate()->GetCurrentContext()).FromJust();
203 240 : info.GetReturnValue().Set(v8_num(-1));
204 240 : }
205 :
206 :
207 120 : static void XSetter(Local<String> name,
208 : Local<Value> value,
209 : const v8::PropertyCallbackInfo<void>& info) {
210 120 : XSetter(value, info, 0);
211 120 : }
212 :
213 :
214 120 : static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
215 120 : CHECK_EQ(1, info.Length());
216 120 : XSetter(info[0], info, 1);
217 120 : }
218 :
219 :
220 23724 : THREADED_TEST(AccessorIC) {
221 6 : LocalContext context;
222 6 : v8::Isolate* isolate = context->GetIsolate();
223 12 : v8::HandleScope scope(isolate);
224 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
225 6 : obj->SetAccessor(v8_str("x0"), XGetter, XSetter);
226 : obj->SetAccessorProperty(v8_str("x1"),
227 : v8::FunctionTemplate::New(isolate, XGetter),
228 18 : v8::FunctionTemplate::New(isolate, XSetter));
229 12 : x_holder = obj->NewInstance(context.local()).ToLocalChecked();
230 30 : CHECK(context->Global()
231 : ->Set(context.local(), v8_str("holder"), x_holder)
232 : .FromJust());
233 6 : x_receiver = v8::Object::New(isolate);
234 30 : 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 6 : CHECK_EQ(80u, array->Length());
255 480 : for (int i = 0; i < 80; i++) {
256 : v8::Local<Value> entry =
257 1440 : array->Get(context.local(), v8::Integer::New(isolate, i))
258 960 : .ToLocalChecked();
259 1440 : CHECK(v8::Integer::New(isolate, i / 2)
260 : ->Equals(context.local(), entry)
261 : .FromJust());
262 6 : }
263 6 : }
264 :
265 :
266 : template <int C>
267 12000 : static void HandleAllocatingGetter(
268 : Local<String> name,
269 : const v8::PropertyCallbackInfo<v8::Value>& info) {
270 12000 : ApiTestFuzzer::Fuzz();
271 6162000 : for (int i = 0; i < C; i++) {
272 : v8::String::NewFromUtf8(info.GetIsolate(), "foo",
273 : v8::NewStringType::kNormal)
274 6150000 : .ToLocalChecked();
275 : }
276 : info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "foo",
277 : v8::NewStringType::kNormal)
278 12000 : .ToLocalChecked());
279 12000 : }
280 :
281 :
282 23724 : THREADED_TEST(HandleScopePop) {
283 6 : LocalContext context;
284 6 : v8::Isolate* isolate = context->GetIsolate();
285 12 : v8::HandleScope scope(isolate);
286 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
287 6 : obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
288 6 : obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
289 : v8::Local<v8::Object> inst =
290 6 : obj->NewInstance(context.local()).ToLocalChecked();
291 30 : CHECK(
292 : context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
293 : int count_before =
294 6 : i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate));
295 : {
296 6 : v8::HandleScope scope(isolate);
297 : CompileRun(
298 : "for (var i = 0; i < 1000; i++) {"
299 : " obj.one;"
300 : " obj.many;"
301 6 : "}");
302 : }
303 : int count_after =
304 6 : i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate));
305 12 : CHECK_EQ(count_before, count_after);
306 6 : }
307 :
308 264 : static void CheckAccessorArgsCorrect(
309 : Local<String> name,
310 : const v8::PropertyCallbackInfo<v8::Value>& info) {
311 264 : CHECK(info.GetIsolate() == CcTest::isolate());
312 264 : CHECK(info.This() == info.Holder());
313 1056 : CHECK(info.Data()
314 : ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
315 : .FromJust());
316 264 : ApiTestFuzzer::Fuzz();
317 264 : CHECK(info.GetIsolate() == CcTest::isolate());
318 264 : CHECK(info.This() == info.Holder());
319 1056 : CHECK(info.Data()
320 : ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
321 : .FromJust());
322 264 : CcTest::CollectAllGarbage();
323 264 : CHECK(info.GetIsolate() == CcTest::isolate());
324 264 : CHECK(info.This() == info.Holder());
325 1056 : CHECK(info.Data()
326 : ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("data"))
327 : .FromJust());
328 : info.GetReturnValue().Set(17);
329 264 : }
330 :
331 :
332 23724 : THREADED_TEST(DirectCall) {
333 6 : LocalContext context;
334 6 : v8::Isolate* isolate = context->GetIsolate();
335 12 : v8::HandleScope scope(isolate);
336 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
337 : obj->SetAccessor(v8_str("xxx"), CheckAccessorArgsCorrect, nullptr,
338 12 : v8_str("data"));
339 : v8::Local<v8::Object> inst =
340 6 : obj->NewInstance(context.local()).ToLocalChecked();
341 30 : CHECK(
342 : context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
343 : Local<Script> scr =
344 6 : v8::Script::Compile(context.local(), v8_str("obj.xxx")).ToLocalChecked();
345 60 : for (int i = 0; i < 10; i++) {
346 60 : Local<Value> result = scr->Run(context.local()).ToLocalChecked();
347 60 : CHECK(!result.IsEmpty());
348 120 : CHECK_EQ(17, result->Int32Value(context.local()).FromJust());
349 6 : }
350 6 : }
351 :
352 72 : static void EmptyGetter(Local<String> name,
353 : const v8::PropertyCallbackInfo<v8::Value>& info) {
354 72 : CheckAccessorArgsCorrect(name, info);
355 72 : ApiTestFuzzer::Fuzz();
356 72 : CheckAccessorArgsCorrect(name, info);
357 : info.GetReturnValue().Set(v8::Local<v8::Value>());
358 72 : }
359 :
360 :
361 23724 : THREADED_TEST(EmptyResult) {
362 6 : LocalContext context;
363 6 : v8::Isolate* isolate = context->GetIsolate();
364 12 : v8::HandleScope scope(isolate);
365 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
366 12 : obj->SetAccessor(v8_str("xxx"), EmptyGetter, nullptr, v8_str("data"));
367 : v8::Local<v8::Object> inst =
368 6 : obj->NewInstance(context.local()).ToLocalChecked();
369 30 : CHECK(
370 : context->Global()->Set(context.local(), v8_str("obj"), inst).FromJust());
371 : Local<Script> scr =
372 6 : v8::Script::Compile(context.local(), v8_str("obj.xxx")).ToLocalChecked();
373 60 : for (int i = 0; i < 10; i++) {
374 60 : Local<Value> result = scr->Run(context.local()).ToLocalChecked();
375 60 : CHECK(result == v8::Undefined(isolate));
376 6 : }
377 6 : }
378 :
379 :
380 23724 : THREADED_TEST(NoReuseRegress) {
381 : // Check that the IC generated for the one test doesn't get reused
382 : // for the other.
383 6 : v8::Isolate* isolate = CcTest::isolate();
384 6 : v8::HandleScope scope(isolate);
385 : {
386 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
387 12 : obj->SetAccessor(v8_str("xxx"), EmptyGetter, nullptr, v8_str("data"));
388 6 : LocalContext context;
389 : v8::Local<v8::Object> inst =
390 6 : obj->NewInstance(context.local()).ToLocalChecked();
391 30 : CHECK(context->Global()
392 : ->Set(context.local(), v8_str("obj"), inst)
393 : .FromJust());
394 6 : Local<Script> scr = v8::Script::Compile(context.local(), v8_str("obj.xxx"))
395 6 : .ToLocalChecked();
396 12 : for (int i = 0; i < 2; i++) {
397 12 : Local<Value> result = scr->Run(context.local()).ToLocalChecked();
398 12 : CHECK(result == v8::Undefined(isolate));
399 6 : }
400 : }
401 : {
402 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
403 : obj->SetAccessor(v8_str("xxx"), CheckAccessorArgsCorrect, nullptr,
404 12 : v8_str("data"));
405 6 : LocalContext context;
406 : v8::Local<v8::Object> inst =
407 6 : obj->NewInstance(context.local()).ToLocalChecked();
408 30 : CHECK(context->Global()
409 : ->Set(context.local(), v8_str("obj"), inst)
410 : .FromJust());
411 6 : Local<Script> scr = v8::Script::Compile(context.local(), v8_str("obj.xxx"))
412 6 : .ToLocalChecked();
413 60 : for (int i = 0; i < 10; i++) {
414 60 : Local<Value> result = scr->Run(context.local()).ToLocalChecked();
415 60 : CHECK(!result.IsEmpty());
416 120 : CHECK_EQ(17, result->Int32Value(context.local()).FromJust());
417 6 : }
418 6 : }
419 6 : }
420 :
421 30 : static void ThrowingGetAccessor(
422 : Local<String> name,
423 : const v8::PropertyCallbackInfo<v8::Value>& info) {
424 30 : ApiTestFuzzer::Fuzz();
425 60 : info.GetIsolate()->ThrowException(v8_str("g"));
426 30 : }
427 :
428 :
429 30 : static void ThrowingSetAccessor(Local<String> name,
430 : Local<Value> value,
431 : const v8::PropertyCallbackInfo<void>& info) {
432 30 : info.GetIsolate()->ThrowException(value);
433 30 : }
434 :
435 :
436 23724 : THREADED_TEST(Regress1054726) {
437 6 : LocalContext env;
438 6 : v8::Isolate* isolate = env->GetIsolate();
439 12 : v8::HandleScope scope(isolate);
440 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
441 : obj->SetAccessor(v8_str("x"),
442 : ThrowingGetAccessor,
443 : ThrowingSetAccessor,
444 6 : Local<Value>());
445 :
446 36 : CHECK(env->Global()
447 : ->Set(env.local(), v8_str("obj"),
448 : obj->NewInstance(env.local()).ToLocalChecked())
449 : .FromJust());
450 :
451 : // Use the throwing property setter/getter in a loop to force
452 : // the accessor ICs to be initialized.
453 : 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 6 : "}; result"))
459 6 : .ToLocalChecked()
460 6 : ->Run(env.local())
461 12 : .ToLocalChecked();
462 18 : CHECK(v8_str("ggggg")->Equals(env.local(), result).FromJust());
463 :
464 : 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 6 : "}; result"))
470 6 : .ToLocalChecked()
471 6 : ->Run(env.local())
472 12 : .ToLocalChecked();
473 24 : CHECK(v8_str("01234")->Equals(env.local(), result).FromJust());
474 6 : }
475 :
476 :
477 12288 : static void AllocGetter(Local<String> name,
478 : const v8::PropertyCallbackInfo<v8::Value>& info) {
479 12288 : ApiTestFuzzer::Fuzz();
480 12288 : info.GetReturnValue().Set(v8::Array::New(info.GetIsolate(), 1000));
481 12288 : }
482 :
483 :
484 23724 : THREADED_TEST(Gc) {
485 6 : LocalContext env;
486 6 : v8::Isolate* isolate = env->GetIsolate();
487 12 : v8::HandleScope scope(isolate);
488 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
489 6 : obj->SetAccessor(v8_str("xxx"), AllocGetter);
490 36 : 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 6 : "}"))
500 6 : .ToLocalChecked()
501 6 : ->Run(env.local())
502 12 : .ToLocalChecked();
503 6 : }
504 :
505 :
506 600 : static void StackCheck(Local<String> name,
507 : const v8::PropertyCallbackInfo<v8::Value>& info) {
508 600 : i::StackFrameIterator iter(reinterpret_cast<i::Isolate*>(info.GetIsolate()));
509 4100 : for (int i = 0; !iter.done(); i++) {
510 : i::StackFrame* frame = iter.frame();
511 3500 : CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
512 3500 : i::Code* code = frame->LookupCode();
513 3500 : CHECK(code->IsCode());
514 : i::Address pc = frame->pc();
515 3500 : CHECK(code->contains(pc));
516 3500 : iter.Advance();
517 : }
518 600 : }
519 :
520 :
521 23724 : THREADED_TEST(StackIteration) {
522 6 : LocalContext env;
523 6 : v8::Isolate* isolate = env->GetIsolate();
524 12 : v8::HandleScope scope(isolate);
525 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
526 : i::StringStream::ClearMentionedObjectCache(
527 6 : reinterpret_cast<i::Isolate*>(isolate));
528 6 : obj->SetAccessor(v8_str("xxx"), StackCheck);
529 36 : 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 6 : "}"))
539 6 : .ToLocalChecked()
540 6 : ->Run(env.local())
541 12 : .ToLocalChecked();
542 6 : }
543 :
544 :
545 24 : static void AllocateHandles(Local<String> name,
546 : const v8::PropertyCallbackInfo<v8::Value>& info) {
547 24576 : for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
548 : v8::Local<v8::Value>::New(info.GetIsolate(), name);
549 : }
550 24 : info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 100));
551 24 : }
552 :
553 :
554 23724 : THREADED_TEST(HandleScopeSegment) {
555 : // Check that we can return values past popping of handle scope
556 : // segments.
557 6 : LocalContext env;
558 6 : v8::Isolate* isolate = env->GetIsolate();
559 12 : v8::HandleScope scope(isolate);
560 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
561 6 : obj->SetAccessor(v8_str("xxx"), AllocateHandles);
562 36 : 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 6 : "result;"))
571 6 : .ToLocalChecked()
572 6 : ->Run(env.local())
573 6 : .ToLocalChecked();
574 18 : CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
575 6 : }
576 :
577 :
578 6 : void JSONStringifyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
579 6 : v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), 1);
580 24 : CHECK(array->Set(info.GetIsolate()->GetCurrentContext(), 0, v8_str("regress"))
581 : .FromJust());
582 : info.GetReturnValue().Set(array);
583 6 : }
584 :
585 :
586 6 : void JSONStringifyGetter(Local<Name> name,
587 : const v8::PropertyCallbackInfo<v8::Value>& info) {
588 6 : info.GetReturnValue().Set(v8_str("crbug-161028"));
589 6 : }
590 :
591 :
592 23724 : THREADED_TEST(JSONStringifyNamedInterceptorObject) {
593 6 : LocalContext env;
594 6 : v8::Isolate* isolate = env->GetIsolate();
595 12 : v8::HandleScope scope(isolate);
596 :
597 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
598 : obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
599 6 : JSONStringifyGetter, nullptr, nullptr, nullptr, JSONStringifyEnumerator));
600 36 : CHECK(env->Global()
601 : ->Set(env.local(), v8_str("obj"),
602 : obj->NewInstance(env.local()).ToLocalChecked())
603 : .FromJust());
604 6 : v8::Local<v8::String> expected = v8_str("{\"regress\":\"crbug-161028\"}");
605 18 : CHECK(CompileRun("JSON.stringify(obj)")
606 : ->Equals(env.local(), expected)
607 6 : .FromJust());
608 6 : }
609 :
610 :
611 : static v8::Local<v8::Context> expected_current_context;
612 :
613 :
614 120 : static void check_contexts(const v8::FunctionCallbackInfo<v8::Value>& info) {
615 60 : ApiTestFuzzer::Fuzz();
616 120 : CHECK(expected_current_context == info.GetIsolate()->GetCurrentContext());
617 60 : }
618 :
619 :
620 23724 : THREADED_TEST(AccessorPropertyCrossContext) {
621 6 : LocalContext env;
622 6 : v8::Isolate* isolate = env->GetIsolate();
623 12 : v8::HandleScope scope(isolate);
624 : v8::Local<v8::Function> fun =
625 12 : v8::Function::New(env.local(), check_contexts).ToLocalChecked();
626 12 : LocalContext switch_context;
627 30 : CHECK(switch_context->Global()
628 : ->Set(switch_context.local(), v8_str("fun"), fun)
629 : .FromJust());
630 12 : v8::TryCatch try_catch(isolate);
631 6 : expected_current_context = env.local();
632 : CompileRun(
633 : "var o = Object.create(null, { n: { get:fun } });"
634 : "for (var i = 0; i < 10; i++) o.n;");
635 12 : CHECK(!try_catch.HasCaught());
636 6 : }
637 :
638 :
639 23724 : THREADED_TEST(GlobalObjectAccessor) {
640 6 : LocalContext env;
641 6 : v8::Isolate* isolate = env->GetIsolate();
642 12 : 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 6 : CHECK(v8::Utils::OpenHandle(*CompileRun("getter()"))->IsJSGlobalProxy());
653 12 : CHECK(v8::Utils::OpenHandle(*CompileRun("set_value"))->IsJSGlobalProxy());
654 6 : }
655 :
656 :
657 12 : static void EmptyGetter(Local<Name> name,
658 : const v8::PropertyCallbackInfo<v8::Value>& info) {
659 12 : ApiTestFuzzer::Fuzz();
660 12 : }
661 :
662 :
663 6 : static void OneProperty(Local<String> name,
664 : const v8::PropertyCallbackInfo<v8::Value>& info) {
665 6 : ApiTestFuzzer::Fuzz();
666 6 : info.GetReturnValue().Set(v8_num(1));
667 6 : }
668 :
669 :
670 23724 : THREADED_TEST(Regress433458) {
671 6 : LocalContext env;
672 6 : v8::Isolate* isolate = env->GetIsolate();
673 12 : v8::HandleScope scope(isolate);
674 6 : v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
675 6 : obj->SetHandler(v8::NamedPropertyHandlerConfiguration(EmptyGetter));
676 6 : obj->SetNativeDataProperty(v8_str("prop"), OneProperty);
677 36 : CHECK(env->Global()
678 : ->Set(env.local(), v8_str("obj"),
679 : obj->NewInstance(env.local()).ToLocalChecked())
680 : .FromJust());
681 : CompileRun(
682 : "Object.defineProperty(obj, 'prop', { writable: false });"
683 6 : "Object.defineProperty(obj, 'prop', { writable: true });");
684 6 : }
685 :
686 :
687 : static bool security_check_value = false;
688 :
689 125 : static bool SecurityTestCallback(Local<v8::Context> accessing_context,
690 : Local<v8::Object> accessed_object,
691 : Local<v8::Value> data) {
692 125 : return security_check_value;
693 : }
694 :
695 :
696 23723 : TEST(PrototypeGetterAccessCheck) {
697 5 : i::FLAG_allow_natives_syntax = true;
698 5 : LocalContext env;
699 5 : v8::Isolate* isolate = env->GetIsolate();
700 10 : v8::HandleScope scope(isolate);
701 5 : auto fun_templ = v8::FunctionTemplate::New(isolate);
702 5 : auto getter_templ = v8::FunctionTemplate::New(isolate, handle_property);
703 5 : getter_templ->SetAcceptAnyReceiver(false);
704 10 : fun_templ->InstanceTemplate()->SetAccessorProperty(v8_str("foo"),
705 15 : getter_templ);
706 5 : auto obj_templ = v8::ObjectTemplate::New(isolate);
707 5 : obj_templ->SetAccessCheckCallback(SecurityTestCallback);
708 30 : CHECK(env->Global()
709 : ->Set(env.local(), v8_str("Fun"),
710 : fun_templ->GetFunction(env.local()).ToLocalChecked())
711 : .FromJust());
712 30 : CHECK(env->Global()
713 : ->Set(env.local(), v8_str("obj"),
714 : obj_templ->NewInstance(env.local()).ToLocalChecked())
715 : .FromJust());
716 30 : CHECK(env->Global()
717 : ->Set(env.local(), v8_str("obj2"),
718 : obj_templ->NewInstance(env.local()).ToLocalChecked())
719 : .FromJust());
720 :
721 5 : security_check_value = true;
722 : CompileRun("var proto = new Fun();");
723 : CompileRun("obj.__proto__ = proto;");
724 5 : ExpectInt32("proto.foo", 907);
725 :
726 : // Test direct.
727 5 : security_check_value = true;
728 5 : ExpectInt32("obj.foo", 907);
729 5 : security_check_value = false;
730 : {
731 5 : v8::TryCatch try_catch(isolate);
732 : CompileRun("obj.foo");
733 5 : CHECK(try_catch.HasCaught());
734 : }
735 :
736 : // Test through call.
737 5 : security_check_value = true;
738 5 : ExpectInt32("proto.__lookupGetter__('foo').call(obj)", 907);
739 5 : security_check_value = false;
740 : {
741 5 : v8::TryCatch try_catch(isolate);
742 : CompileRun("proto.__lookupGetter__('foo').call(obj)");
743 5 : 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 5 : security_check_value = true;
757 5 : ExpectInt32("f()", 907);
758 5 : security_check_value = false;
759 : {
760 5 : v8::TryCatch try_catch(isolate);
761 : CompileRun("f();");
762 5 : CHECK(try_catch.HasCaught());
763 : }
764 :
765 : // Test crankshaft.
766 : CompileRun("%OptimizeFunctionOnNextCall(f);");
767 :
768 5 : security_check_value = true;
769 5 : ExpectInt32("f()", 907);
770 5 : security_check_value = false;
771 : {
772 5 : v8::TryCatch try_catch(isolate);
773 : CompileRun("f();");
774 5 : CHECK(try_catch.HasCaught());
775 5 : }
776 5 : }
777 :
778 15 : static void CheckReceiver(Local<String> name,
779 : const v8::PropertyCallbackInfo<v8::Value>& info) {
780 15 : CHECK(info.This()->IsObject());
781 15 : }
782 :
783 23723 : TEST(Regress609134) {
784 5 : LocalContext env;
785 5 : v8::Isolate* isolate = env->GetIsolate();
786 10 : v8::HandleScope scope(isolate);
787 5 : auto fun_templ = v8::FunctionTemplate::New(isolate);
788 10 : fun_templ->InstanceTemplate()->SetNativeDataProperty(v8_str("foo"),
789 15 : CheckReceiver);
790 :
791 30 : 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;"
799 : "var a = 42;"
800 5 : "for (var i = 0; i<3; i++) { a.foo; }");
801 71159 : }
|