The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-accessors.cc @ f230a1cf

History | View | Annotate | Download (18.9 KB)

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 "v8.h"
31

    
32
#include "api.h"
33
#include "cctest.h"
34
#include "frames-inl.h"
35
#include "string-stream.h"
36

    
37
using ::v8::ObjectTemplate;
38
using ::v8::Value;
39
using ::v8::Context;
40
using ::v8::Local;
41
using ::v8::String;
42
using ::v8::Script;
43
using ::v8::Function;
44
using ::v8::Extension;
45

    
46
static void handle_property(Local<String> name,
47
                            const v8::PropertyCallbackInfo<v8::Value>& info) {
48
  ApiTestFuzzer::Fuzz();
49
  info.GetReturnValue().Set(v8_num(900));
50
}
51

    
52
static void handle_property_2(Local<String> name,
53
                              const v8::PropertyCallbackInfo<v8::Value>& info) {
54
  ApiTestFuzzer::Fuzz();
55
  info.GetReturnValue().Set(v8_num(902));
56
}
57

    
58

    
59
static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) {
60
  ApiTestFuzzer::Fuzz();
61
  CHECK_EQ(0, info.Length());
62
  info.GetReturnValue().Set(v8_num(907));
63
}
64

    
65

    
66
THREADED_TEST(PropertyHandler) {
67
  LocalContext env;
68
  v8::HandleScope scope(env->GetIsolate());
69
  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
70
  fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
71
  Local<v8::FunctionTemplate> getter_templ =
72
      v8::FunctionTemplate::New(handle_property);
73
  getter_templ->SetLength(0);
74
  fun_templ->
75
      InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ);
76
  fun_templ->InstanceTemplate()->
77
      SetNativeDataProperty(v8_str("instance_foo"), handle_property);
78
  fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2);
79
  Local<Function> fun = fun_templ->GetFunction();
80
  env->Global()->Set(v8_str("Fun"), fun);
81
  Local<Script> getter;
82
  Local<Script> setter;
83
  // check function instance accessors
84
  getter = v8_compile("var obj = new Fun(); obj.instance_foo;");
85
  CHECK_EQ(900, getter->Run()->Int32Value());
86
  setter = v8_compile("obj.instance_foo = 901;");
87
  CHECK_EQ(901, setter->Run()->Int32Value());
88
  getter = v8_compile("obj.bar;");
89
  CHECK_EQ(907, getter->Run()->Int32Value());
90
  setter = v8_compile("obj.bar = 908;");
91
  CHECK_EQ(908, setter->Run()->Int32Value());
92
  // check function static accessors
93
  getter = v8_compile("Fun.object_foo;");
94
  CHECK_EQ(902, getter->Run()->Int32Value());
95
  setter = v8_compile("Fun.object_foo = 903;");
96
  CHECK_EQ(903, setter->Run()->Int32Value());
97
}
98

    
99

    
100
static void GetIntValue(Local<String> property,
101
                        const v8::PropertyCallbackInfo<v8::Value>& info) {
102
  ApiTestFuzzer::Fuzz();
103
  int* value =
104
      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
105
  info.GetReturnValue().Set(v8_num(*value));
106
}
107

    
108

    
109
static void SetIntValue(Local<String> property,
110
                        Local<Value> value,
111
                        const v8::PropertyCallbackInfo<void>& info) {
112
  int* field =
113
      static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
114
  *field = value->Int32Value();
115
}
116

    
117
int foo, bar, baz;
118

    
119
THREADED_TEST(GlobalVariableAccess) {
120
  foo = 0;
121
  bar = -4;
122
  baz = 10;
123
  v8::HandleScope scope(CcTest::isolate());
124
  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
125
  templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
126
                                         GetIntValue,
127
                                         SetIntValue,
128
                                         v8::External::New(&foo));
129
  templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
130
                                         GetIntValue,
131
                                         SetIntValue,
132
                                         v8::External::New(&bar));
133
  templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
134
                                         GetIntValue,
135
                                         SetIntValue,
136
                                         v8::External::New(&baz));
137
  LocalContext env(0, templ->InstanceTemplate());
138
  v8_compile("foo = (++bar) + baz")->Run();
139
  CHECK_EQ(bar, -3);
140
  CHECK_EQ(foo, 7);
141
}
142

    
143

    
144
static int x_register[2] = {0, 0};
145
static v8::Handle<v8::Object> x_receiver;
146
static v8::Handle<v8::Object> x_holder;
147

    
148
template<class Info>
149
static void XGetter(const Info& info, int offset) {
150
  ApiTestFuzzer::Fuzz();
151
  v8::Isolate* isolate = CcTest::isolate();
152
  CHECK_EQ(isolate, info.GetIsolate());
153
  CHECK_EQ(x_receiver, info.This());
154
  info.GetReturnValue().Set(v8_num(x_register[offset]));
155
}
156

    
157

    
158
static void XGetter(Local<String> name,
159
                    const v8::PropertyCallbackInfo<v8::Value>& info) {
160
  CHECK_EQ(x_holder, info.Holder());
161
  XGetter(info, 0);
162
}
163

    
164

    
165
static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
166
  CHECK_EQ(x_receiver, info.Holder());
167
  XGetter(info, 1);
168
}
169

    
170

    
171
template<class Info>
172
static void XSetter(Local<Value> value, const Info& info, int offset) {
173
  v8::Isolate* isolate = CcTest::isolate();
174
  CHECK_EQ(isolate, info.GetIsolate());
175
  CHECK_EQ(x_holder, info.This());
176
  CHECK_EQ(x_holder, info.Holder());
177
  x_register[offset] = value->Int32Value();
178
}
179

    
180

    
181
static void XSetter(Local<String> name,
182
                    Local<Value> value,
183
                    const v8::PropertyCallbackInfo<void>& info) {
184
  XSetter(value, info, 0);
185
}
186

    
187

    
188
static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
189
  CHECK_EQ(1, info.Length());
190
  XSetter(info[0], info, 1);
191
}
192

    
193

    
194
THREADED_TEST(AccessorIC) {
195
  LocalContext context;
196
  v8::HandleScope scope(context->GetIsolate());
197
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
198
  obj->SetAccessor(v8_str("x0"), XGetter, XSetter);
199
  obj->SetAccessorProperty(v8_str("x1"),
200
                           v8::FunctionTemplate::New(XGetter),
201
                           v8::FunctionTemplate::New(XSetter));
202
  x_holder = obj->NewInstance();
203
  context->Global()->Set(v8_str("holder"), x_holder);
204
  x_receiver = v8::Object::New();
205
  context->Global()->Set(v8_str("obj"), x_receiver);
206
  v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
207
    "obj.__proto__ = holder;"
208
    "var result = [];"
209
    "var key_0 = 'x0';"
210
    "var key_1 = 'x1';"
211
    "for (var i = 0; i < 10; i++) {"
212
    "  holder.x0 = i;"
213
    "  result.push(obj.x0);"
214
    "  holder.x1 = i;"
215
    "  result.push(obj.x1);"
216
    "  holder[key_0] = i;"
217
    "  result.push(obj[key_0]);"
218
    "  holder[key_1] = i;"
219
    "  result.push(obj[key_1]);"
220
    "}"
221
    "result"));
222
  CHECK_EQ(40, array->Length());
223
  for (int i = 0; i < 40; i++) {
224
    v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
225
    CHECK_EQ(v8::Integer::New(i/4), entry);
226
  }
227
}
228

    
229

    
230
static void AccessorProhibitsOverwritingGetter(
231
    Local<String> name,
232
    const v8::PropertyCallbackInfo<v8::Value>& info) {
233
  ApiTestFuzzer::Fuzz();
234
  info.GetReturnValue().Set(true);
235
}
236

    
237

    
238
THREADED_TEST(AccessorProhibitsOverwriting) {
239
  LocalContext context;
240
  v8::HandleScope scope(context->GetIsolate());
241
  Local<ObjectTemplate> templ = ObjectTemplate::New();
242
  templ->SetAccessor(v8_str("x"),
243
                     AccessorProhibitsOverwritingGetter,
244
                     0,
245
                     v8::Handle<Value>(),
246
                     v8::PROHIBITS_OVERWRITING,
247
                     v8::ReadOnly);
248
  Local<v8::Object> instance = templ->NewInstance();
249
  context->Global()->Set(v8_str("obj"), instance);
250
  Local<Value> value = CompileRun(
251
      "obj.__defineGetter__('x', function() { return false; });"
252
      "obj.x");
253
  CHECK(value->BooleanValue());
254
  value = CompileRun(
255
      "var setter_called = false;"
256
      "obj.__defineSetter__('x', function() { setter_called = true; });"
257
      "obj.x = 42;"
258
      "setter_called");
259
  CHECK(!value->BooleanValue());
260
  value = CompileRun(
261
      "obj2 = {};"
262
      "obj2.__proto__ = obj;"
263
      "obj2.__defineGetter__('x', function() { return false; });"
264
      "obj2.x");
265
  CHECK(value->BooleanValue());
266
  value = CompileRun(
267
      "var setter_called = false;"
268
      "obj2 = {};"
269
      "obj2.__proto__ = obj;"
270
      "obj2.__defineSetter__('x', function() { setter_called = true; });"
271
      "obj2.x = 42;"
272
      "setter_called");
273
  CHECK(!value->BooleanValue());
274
}
275

    
276

    
277
template <int C>
278
static void HandleAllocatingGetter(
279
    Local<String> name,
280
    const v8::PropertyCallbackInfo<v8::Value>& info) {
281
  ApiTestFuzzer::Fuzz();
282
  for (int i = 0; i < C; i++)
283
    v8::String::New("foo");
284
  info.GetReturnValue().Set(v8::String::New("foo"));
285
}
286

    
287

    
288
THREADED_TEST(HandleScopePop) {
289
  LocalContext context;
290
  v8::HandleScope scope(context->GetIsolate());
291
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
292
  obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
293
  obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
294
  v8::Handle<v8::Object> inst = obj->NewInstance();
295
  context->Global()->Set(v8::String::New("obj"), inst);
296
  i::Isolate* isolate = CcTest::i_isolate();
297
  int count_before = i::HandleScope::NumberOfHandles(isolate);
298
  {
299
    v8::HandleScope scope(context->GetIsolate());
300
    CompileRun(
301
        "for (var i = 0; i < 1000; i++) {"
302
        "  obj.one;"
303
        "  obj.many;"
304
        "}");
305
  }
306
  int count_after = i::HandleScope::NumberOfHandles(isolate);
307
  CHECK_EQ(count_before, count_after);
308
}
309

    
310
static void CheckAccessorArgsCorrect(
311
    Local<String> name,
312
    const v8::PropertyCallbackInfo<v8::Value>& info) {
313
  CHECK(info.GetIsolate() == CcTest::isolate());
314
  CHECK(info.This() == info.Holder());
315
  CHECK(info.Data()->Equals(v8::String::New("data")));
316
  ApiTestFuzzer::Fuzz();
317
  CHECK(info.GetIsolate() == CcTest::isolate());
318
  CHECK(info.This() == info.Holder());
319
  CHECK(info.Data()->Equals(v8::String::New("data")));
320
  CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
321
  CHECK(info.GetIsolate() == CcTest::isolate());
322
  CHECK(info.This() == info.Holder());
323
  CHECK(info.Data()->Equals(v8::String::New("data")));
324
  info.GetReturnValue().Set(17);
325
}
326

    
327

    
328
THREADED_TEST(DirectCall) {
329
  LocalContext context;
330
  v8::HandleScope scope(context->GetIsolate());
331
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
332
  obj->SetAccessor(v8_str("xxx"),
333
                   CheckAccessorArgsCorrect,
334
                   NULL,
335
                   v8::String::New("data"));
336
  v8::Handle<v8::Object> inst = obj->NewInstance();
337
  context->Global()->Set(v8::String::New("obj"), inst);
338
  Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
339
  for (int i = 0; i < 10; i++) {
340
    Local<Value> result = scr->Run();
341
    CHECK(!result.IsEmpty());
342
    CHECK_EQ(17, result->Int32Value());
343
  }
344
}
345

    
346
static void EmptyGetter(Local<String> name,
347
                        const v8::PropertyCallbackInfo<v8::Value>& info) {
348
  CheckAccessorArgsCorrect(name, info);
349
  ApiTestFuzzer::Fuzz();
350
  CheckAccessorArgsCorrect(name, info);
351
  info.GetReturnValue().Set(v8::Handle<v8::Value>());
352
}
353

    
354

    
355
THREADED_TEST(EmptyResult) {
356
  LocalContext context;
357
  v8::Isolate* isolate = context->GetIsolate();
358
  v8::HandleScope scope(isolate);
359
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
360
  obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
361
  v8::Handle<v8::Object> inst = obj->NewInstance();
362
  context->Global()->Set(v8::String::New("obj"), inst);
363
  Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
364
  for (int i = 0; i < 10; i++) {
365
    Local<Value> result = scr->Run();
366
    CHECK(result == v8::Undefined(isolate));
367
  }
368
}
369

    
370

    
371
THREADED_TEST(NoReuseRegress) {
372
  // Check that the IC generated for the one test doesn't get reused
373
  // for the other.
374
  v8::Isolate* isolate = CcTest::isolate();
375
  v8::HandleScope scope(isolate);
376
  {
377
    v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
378
    obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
379
    LocalContext context;
380
    v8::Handle<v8::Object> inst = obj->NewInstance();
381
    context->Global()->Set(v8::String::New("obj"), inst);
382
    Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
383
    for (int i = 0; i < 2; i++) {
384
      Local<Value> result = scr->Run();
385
      CHECK(result == v8::Undefined(isolate));
386
    }
387
  }
388
  {
389
    v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
390
    obj->SetAccessor(v8_str("xxx"),
391
                     CheckAccessorArgsCorrect,
392
                     NULL,
393
                     v8::String::New("data"));
394
    LocalContext context;
395
    v8::Handle<v8::Object> inst = obj->NewInstance();
396
    context->Global()->Set(v8::String::New("obj"), inst);
397
    Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
398
    for (int i = 0; i < 10; i++) {
399
      Local<Value> result = scr->Run();
400
      CHECK(!result.IsEmpty());
401
      CHECK_EQ(17, result->Int32Value());
402
    }
403
  }
404
}
405

    
406
static void ThrowingGetAccessor(
407
    Local<String> name,
408
    const v8::PropertyCallbackInfo<v8::Value>& info) {
409
  ApiTestFuzzer::Fuzz();
410
  info.GetIsolate()->ThrowException(v8_str("g"));
411
}
412

    
413

    
414
static void ThrowingSetAccessor(Local<String> name,
415
                                Local<Value> value,
416
                                const v8::PropertyCallbackInfo<void>& info) {
417
  info.GetIsolate()->ThrowException(value);
418
}
419

    
420

    
421
THREADED_TEST(Regress1054726) {
422
  LocalContext env;
423
  v8::HandleScope scope(env->GetIsolate());
424
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
425
  obj->SetAccessor(v8_str("x"),
426
                   ThrowingGetAccessor,
427
                   ThrowingSetAccessor,
428
                   Local<Value>());
429

    
430
  env->Global()->Set(v8_str("obj"), obj->NewInstance());
431

    
432
  // Use the throwing property setter/getter in a loop to force
433
  // the accessor ICs to be initialized.
434
  v8::Handle<Value> result;
435
  result = Script::Compile(v8_str(
436
      "var result = '';"
437
      "for (var i = 0; i < 5; i++) {"
438
      "  try { obj.x; } catch (e) { result += e; }"
439
      "}; result"))->Run();
440
  CHECK_EQ(v8_str("ggggg"), result);
441

    
442
  result = Script::Compile(String::New(
443
      "var result = '';"
444
      "for (var i = 0; i < 5; i++) {"
445
      "  try { obj.x = i; } catch (e) { result += e; }"
446
      "}; result"))->Run();
447
  CHECK_EQ(v8_str("01234"), result);
448
}
449

    
450

    
451
static void AllocGetter(Local<String> name,
452
                        const v8::PropertyCallbackInfo<v8::Value>& info) {
453
  ApiTestFuzzer::Fuzz();
454
  info.GetReturnValue().Set(v8::Array::New(1000));
455
}
456

    
457

    
458
THREADED_TEST(Gc) {
459
  LocalContext env;
460
  v8::HandleScope scope(env->GetIsolate());
461
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
462
  obj->SetAccessor(v8_str("xxx"), AllocGetter);
463
  env->Global()->Set(v8_str("obj"), obj->NewInstance());
464
  Script::Compile(String::New(
465
      "var last = [];"
466
      "for (var i = 0; i < 2048; i++) {"
467
      "  var result = obj.xxx;"
468
      "  result[0] = last;"
469
      "  last = result;"
470
      "}"))->Run();
471
}
472

    
473

    
474
static void StackCheck(Local<String> name,
475
                       const v8::PropertyCallbackInfo<v8::Value>& info) {
476
  i::StackFrameIterator iter(reinterpret_cast<i::Isolate*>(info.GetIsolate()));
477
  for (int i = 0; !iter.done(); i++) {
478
    i::StackFrame* frame = iter.frame();
479
    CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
480
    i::Code* code = frame->LookupCode();
481
    CHECK(code->IsCode());
482
    i::Address pc = frame->pc();
483
    CHECK(code->contains(pc));
484
    iter.Advance();
485
  }
486
}
487

    
488

    
489
THREADED_TEST(StackIteration) {
490
  LocalContext env;
491
  v8::HandleScope scope(env->GetIsolate());
492
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
493
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
494
  i::StringStream::ClearMentionedObjectCache(isolate);
495
  obj->SetAccessor(v8_str("xxx"), StackCheck);
496
  env->Global()->Set(v8_str("obj"), obj->NewInstance());
497
  Script::Compile(String::New(
498
      "function foo() {"
499
      "  return obj.xxx;"
500
      "}"
501
      "for (var i = 0; i < 100; i++) {"
502
      "  foo();"
503
      "}"))->Run();
504
}
505

    
506

    
507
static void AllocateHandles(Local<String> name,
508
                            const v8::PropertyCallbackInfo<v8::Value>& info) {
509
  for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
510
    v8::Local<v8::Value>::New(info.GetIsolate(), name);
511
  }
512
  info.GetReturnValue().Set(v8::Integer::New(100));
513
}
514

    
515

    
516
THREADED_TEST(HandleScopeSegment) {
517
  // Check that we can return values past popping of handle scope
518
  // segments.
519
  LocalContext env;
520
  v8::HandleScope scope(env->GetIsolate());
521
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
522
  obj->SetAccessor(v8_str("xxx"), AllocateHandles);
523
  env->Global()->Set(v8_str("obj"), obj->NewInstance());
524
  v8::Handle<v8::Value> result = Script::Compile(String::New(
525
      "var result;"
526
      "for (var i = 0; i < 4; i++)"
527
      "  result = obj.xxx;"
528
      "result;"))->Run();
529
  CHECK_EQ(100, result->Int32Value());
530
}
531

    
532

    
533
void JSONStringifyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
534
  v8::Handle<v8::Array> array = v8::Array::New(1);
535
  array->Set(0, v8_str("regress"));
536
  info.GetReturnValue().Set(array);
537
}
538

    
539

    
540
void JSONStringifyGetter(Local<String> name,
541
                         const v8::PropertyCallbackInfo<v8::Value>& info) {
542
  info.GetReturnValue().Set(v8_str("crbug-161028"));
543
}
544

    
545

    
546
THREADED_TEST(JSONStringifyNamedInterceptorObject) {
547
  LocalContext env;
548
  v8::HandleScope scope(env->GetIsolate());
549

    
550
  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
551
  obj->SetNamedPropertyHandler(
552
      JSONStringifyGetter, NULL, NULL, NULL, JSONStringifyEnumerator);
553
  env->Global()->Set(v8_str("obj"), obj->NewInstance());
554
  v8::Handle<v8::String> expected = v8_str("{\"regress\":\"crbug-161028\"}");
555
  CHECK(CompileRun("JSON.stringify(obj)")->Equals(expected));
556
}
557

    
558

    
559
THREADED_TEST(AccessorPropertyCrossContext) {
560
  LocalContext env;
561
  v8::Isolate* isolate = env->GetIsolate();
562
  v8::HandleScope scope(isolate);
563
  v8::Handle<v8::Function> fun = v8::Function::New(isolate, handle_property);
564
  LocalContext switch_context;
565
  switch_context->Global()->Set(v8_str("fun"), fun);
566
  v8::TryCatch try_catch;
567
  CompileRun(
568
      "var o = Object.create(null, { n: { get:fun } });"
569
      "for (var i = 0; i < 10; i++) o.n;");
570
  CHECK(!try_catch.HasCaught());
571
}