Home | History | Annotate | Download | only in cctest
      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::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::Isolate* isolate = env->GetIsolate();
     69   v8::HandleScope scope(isolate);
     70   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
     71   fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
     72   Local<v8::FunctionTemplate> getter_templ =
     73       v8::FunctionTemplate::New(isolate, handle_property);
     74   getter_templ->SetLength(0);
     75   fun_templ->
     76       InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ);
     77   fun_templ->InstanceTemplate()->
     78       SetNativeDataProperty(v8_str("instance_foo"), handle_property);
     79   fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2);
     80   Local<Function> fun = fun_templ->GetFunction();
     81   env->Global()->Set(v8_str("Fun"), fun);
     82   Local<Script> getter;
     83   Local<Script> setter;
     84   // check function instance accessors
     85   getter = v8_compile("var obj = new Fun(); obj.instance_foo;");
     86   CHECK_EQ(900, getter->Run()->Int32Value());
     87   setter = v8_compile("obj.instance_foo = 901;");
     88   CHECK_EQ(901, setter->Run()->Int32Value());
     89   getter = v8_compile("obj.bar;");
     90   CHECK_EQ(907, getter->Run()->Int32Value());
     91   setter = v8_compile("obj.bar = 908;");
     92   CHECK_EQ(908, setter->Run()->Int32Value());
     93   // check function static accessors
     94   getter = v8_compile("Fun.object_foo;");
     95   CHECK_EQ(902, getter->Run()->Int32Value());
     96   setter = v8_compile("Fun.object_foo = 903;");
     97   CHECK_EQ(903, setter->Run()->Int32Value());
     98 }
     99 
    100 
    101 static void GetIntValue(Local<String> property,
    102                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    103   ApiTestFuzzer::Fuzz();
    104   int* value =
    105       static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
    106   info.GetReturnValue().Set(v8_num(*value));
    107 }
    108 
    109 
    110 static void SetIntValue(Local<String> property,
    111                         Local<Value> value,
    112                         const v8::PropertyCallbackInfo<void>& info) {
    113   int* field =
    114       static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
    115   *field = value->Int32Value();
    116 }
    117 
    118 int foo, bar, baz;
    119 
    120 THREADED_TEST(GlobalVariableAccess) {
    121   foo = 0;
    122   bar = -4;
    123   baz = 10;
    124   v8::Isolate* isolate = CcTest::isolate();
    125   v8::HandleScope scope(isolate);
    126   v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    127   templ->InstanceTemplate()->SetAccessor(
    128       v8_str("foo"), GetIntValue, SetIntValue,
    129       v8::External::New(isolate, &foo));
    130   templ->InstanceTemplate()->SetAccessor(
    131       v8_str("bar"), GetIntValue, SetIntValue,
    132       v8::External::New(isolate, &bar));
    133   templ->InstanceTemplate()->SetAccessor(
    134       v8_str("baz"), GetIntValue, SetIntValue,
    135       v8::External::New(isolate, &baz));
    136   LocalContext env(0, templ->InstanceTemplate());
    137   v8_compile("foo = (++bar) + baz")->Run();
    138   CHECK_EQ(bar, -3);
    139   CHECK_EQ(foo, 7);
    140 }
    141 
    142 
    143 static int x_register[2] = {0, 0};
    144 static v8::Handle<v8::Object> x_receiver;
    145 static v8::Handle<v8::Object> x_holder;
    146 
    147 template<class Info>
    148 static void XGetter(const Info& info, int offset) {
    149   ApiTestFuzzer::Fuzz();
    150   v8::Isolate* isolate = CcTest::isolate();
    151   CHECK_EQ(isolate, info.GetIsolate());
    152   CHECK_EQ(x_receiver, info.This());
    153   info.GetReturnValue().Set(v8_num(x_register[offset]));
    154 }
    155 
    156 
    157 static void XGetter(Local<String> name,
    158                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    159   CHECK_EQ(x_holder, info.Holder());
    160   XGetter(info, 0);
    161 }
    162 
    163 
    164 static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
    165   CHECK_EQ(x_receiver, info.Holder());
    166   XGetter(info, 1);
    167 }
    168 
    169 
    170 template<class Info>
    171 static void XSetter(Local<Value> value, const Info& info, int offset) {
    172   v8::Isolate* isolate = CcTest::isolate();
    173   CHECK_EQ(isolate, info.GetIsolate());
    174   CHECK_EQ(x_holder, info.This());
    175   CHECK_EQ(x_holder, info.Holder());
    176   x_register[offset] = value->Int32Value();
    177   info.GetReturnValue().Set(v8_num(-1));
    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::Isolate* isolate = context->GetIsolate();
    197   v8::HandleScope scope(isolate);
    198   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    199   obj->SetAccessor(v8_str("x0"), XGetter, XSetter);
    200   obj->SetAccessorProperty(v8_str("x1"),
    201                            v8::FunctionTemplate::New(isolate, XGetter),
    202                            v8::FunctionTemplate::New(isolate, XSetter));
    203   x_holder = obj->NewInstance();
    204   context->Global()->Set(v8_str("holder"), x_holder);
    205   x_receiver = v8::Object::New(isolate);
    206   context->Global()->Set(v8_str("obj"), x_receiver);
    207   v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
    208     "obj.__proto__ = holder;"
    209     "var result = [];"
    210     "var key_0 = 'x0';"
    211     "var key_1 = 'x1';"
    212     "for (var j = 0; j < 10; j++) {"
    213     "  var i = 4*j;"
    214     "  result.push(holder.x0 = i);"
    215     "  result.push(obj.x0);"
    216     "  result.push(holder.x1 = i + 1);"
    217     "  result.push(obj.x1);"
    218     "  result.push(holder[key_0] = i + 2);"
    219     "  result.push(obj[key_0]);"
    220     "  result.push(holder[key_1] = i + 3);"
    221     "  result.push(obj[key_1]);"
    222     "}"
    223     "result"));
    224   CHECK_EQ(80, array->Length());
    225   for (int i = 0; i < 80; i++) {
    226     v8::Handle<Value> entry = array->Get(v8::Integer::New(isolate, i));
    227     CHECK_EQ(v8::Integer::New(isolate, i/2), entry);
    228   }
    229 }
    230 
    231 
    232 template <int C>
    233 static void HandleAllocatingGetter(
    234     Local<String> name,
    235     const v8::PropertyCallbackInfo<v8::Value>& info) {
    236   ApiTestFuzzer::Fuzz();
    237   for (int i = 0; i < C; i++)
    238     v8::String::NewFromUtf8(info.GetIsolate(), "foo");
    239   info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "foo"));
    240 }
    241 
    242 
    243 THREADED_TEST(HandleScopePop) {
    244   LocalContext context;
    245   v8::Isolate* isolate = context->GetIsolate();
    246   v8::HandleScope scope(isolate);
    247   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    248   obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
    249   obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
    250   v8::Handle<v8::Object> inst = obj->NewInstance();
    251   context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), inst);
    252   int count_before =
    253       i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate));
    254   {
    255     v8::HandleScope scope(isolate);
    256     CompileRun(
    257         "for (var i = 0; i < 1000; i++) {"
    258         "  obj.one;"
    259         "  obj.many;"
    260         "}");
    261   }
    262   int count_after =
    263       i::HandleScope::NumberOfHandles(reinterpret_cast<i::Isolate*>(isolate));
    264   CHECK_EQ(count_before, count_after);
    265 }
    266 
    267 static void CheckAccessorArgsCorrect(
    268     Local<String> name,
    269     const v8::PropertyCallbackInfo<v8::Value>& info) {
    270   CHECK(info.GetIsolate() == CcTest::isolate());
    271   CHECK(info.This() == info.Holder());
    272   CHECK(
    273       info.Data()->Equals(v8::String::NewFromUtf8(CcTest::isolate(), "data")));
    274   ApiTestFuzzer::Fuzz();
    275   CHECK(info.GetIsolate() == CcTest::isolate());
    276   CHECK(info.This() == info.Holder());
    277   CHECK(
    278       info.Data()->Equals(v8::String::NewFromUtf8(CcTest::isolate(), "data")));
    279   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
    280   CHECK(info.GetIsolate() == CcTest::isolate());
    281   CHECK(info.This() == info.Holder());
    282   CHECK(
    283       info.Data()->Equals(v8::String::NewFromUtf8(CcTest::isolate(), "data")));
    284   info.GetReturnValue().Set(17);
    285 }
    286 
    287 
    288 THREADED_TEST(DirectCall) {
    289   LocalContext context;
    290   v8::Isolate* isolate = context->GetIsolate();
    291   v8::HandleScope scope(isolate);
    292   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    293   obj->SetAccessor(v8_str("xxx"),
    294                    CheckAccessorArgsCorrect,
    295                    NULL,
    296                    v8::String::NewFromUtf8(isolate, "data"));
    297   v8::Handle<v8::Object> inst = obj->NewInstance();
    298   context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"),
    299                          inst);
    300   Local<Script> scr = v8::Script::Compile(
    301       v8::String::NewFromUtf8(isolate, "obj.xxx"));
    302   for (int i = 0; i < 10; i++) {
    303     Local<Value> result = scr->Run();
    304     CHECK(!result.IsEmpty());
    305     CHECK_EQ(17, result->Int32Value());
    306   }
    307 }
    308 
    309 static void EmptyGetter(Local<String> name,
    310                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    311   CheckAccessorArgsCorrect(name, info);
    312   ApiTestFuzzer::Fuzz();
    313   CheckAccessorArgsCorrect(name, info);
    314   info.GetReturnValue().Set(v8::Handle<v8::Value>());
    315 }
    316 
    317 
    318 THREADED_TEST(EmptyResult) {
    319   LocalContext context;
    320   v8::Isolate* isolate = context->GetIsolate();
    321   v8::HandleScope scope(isolate);
    322   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    323   obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL,
    324                    v8::String::NewFromUtf8(isolate, "data"));
    325   v8::Handle<v8::Object> inst = obj->NewInstance();
    326   context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), inst);
    327   Local<Script> scr =
    328       v8::Script::Compile(v8::String::NewFromUtf8(isolate, "obj.xxx"));
    329   for (int i = 0; i < 10; i++) {
    330     Local<Value> result = scr->Run();
    331     CHECK(result == v8::Undefined(isolate));
    332   }
    333 }
    334 
    335 
    336 THREADED_TEST(NoReuseRegress) {
    337   // Check that the IC generated for the one test doesn't get reused
    338   // for the other.
    339   v8::Isolate* isolate = CcTest::isolate();
    340   v8::HandleScope scope(isolate);
    341   {
    342     v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    343     obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL,
    344                      v8::String::NewFromUtf8(isolate, "data"));
    345     LocalContext context;
    346     v8::Handle<v8::Object> inst = obj->NewInstance();
    347     context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), inst);
    348     Local<Script> scr =
    349         v8::Script::Compile(v8::String::NewFromUtf8(isolate, "obj.xxx"));
    350     for (int i = 0; i < 2; i++) {
    351       Local<Value> result = scr->Run();
    352       CHECK(result == v8::Undefined(isolate));
    353     }
    354   }
    355   {
    356     v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    357     obj->SetAccessor(v8_str("xxx"),
    358                      CheckAccessorArgsCorrect,
    359                      NULL,
    360                      v8::String::NewFromUtf8(isolate, "data"));
    361     LocalContext context;
    362     v8::Handle<v8::Object> inst = obj->NewInstance();
    363     context->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"), inst);
    364     Local<Script> scr =
    365         v8::Script::Compile(v8::String::NewFromUtf8(isolate, "obj.xxx"));
    366     for (int i = 0; i < 10; i++) {
    367       Local<Value> result = scr->Run();
    368       CHECK(!result.IsEmpty());
    369       CHECK_EQ(17, result->Int32Value());
    370     }
    371   }
    372 }
    373 
    374 static void ThrowingGetAccessor(
    375     Local<String> name,
    376     const v8::PropertyCallbackInfo<v8::Value>& info) {
    377   ApiTestFuzzer::Fuzz();
    378   info.GetIsolate()->ThrowException(v8_str("g"));
    379 }
    380 
    381 
    382 static void ThrowingSetAccessor(Local<String> name,
    383                                 Local<Value> value,
    384                                 const v8::PropertyCallbackInfo<void>& info) {
    385   info.GetIsolate()->ThrowException(value);
    386 }
    387 
    388 
    389 THREADED_TEST(Regress1054726) {
    390   LocalContext env;
    391   v8::Isolate* isolate = env->GetIsolate();
    392   v8::HandleScope scope(isolate);
    393   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    394   obj->SetAccessor(v8_str("x"),
    395                    ThrowingGetAccessor,
    396                    ThrowingSetAccessor,
    397                    Local<Value>());
    398 
    399   env->Global()->Set(v8_str("obj"), obj->NewInstance());
    400 
    401   // Use the throwing property setter/getter in a loop to force
    402   // the accessor ICs to be initialized.
    403   v8::Handle<Value> result;
    404   result = Script::Compile(v8_str(
    405       "var result = '';"
    406       "for (var i = 0; i < 5; i++) {"
    407       "  try { obj.x; } catch (e) { result += e; }"
    408       "}; result"))->Run();
    409   CHECK_EQ(v8_str("ggggg"), result);
    410 
    411   result = Script::Compile(String::NewFromUtf8(
    412       isolate,
    413       "var result = '';"
    414       "for (var i = 0; i < 5; i++) {"
    415       "  try { obj.x = i; } catch (e) { result += e; }"
    416       "}; result"))->Run();
    417   CHECK_EQ(v8_str("01234"), result);
    418 }
    419 
    420 
    421 static void AllocGetter(Local<String> name,
    422                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    423   ApiTestFuzzer::Fuzz();
    424   info.GetReturnValue().Set(v8::Array::New(info.GetIsolate(), 1000));
    425 }
    426 
    427 
    428 THREADED_TEST(Gc) {
    429   LocalContext env;
    430   v8::Isolate* isolate = env->GetIsolate();
    431   v8::HandleScope scope(isolate);
    432   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    433   obj->SetAccessor(v8_str("xxx"), AllocGetter);
    434   env->Global()->Set(v8_str("obj"), obj->NewInstance());
    435   Script::Compile(String::NewFromUtf8(
    436       isolate,
    437       "var last = [];"
    438       "for (var i = 0; i < 2048; i++) {"
    439       "  var result = obj.xxx;"
    440       "  result[0] = last;"
    441       "  last = result;"
    442       "}"))->Run();
    443 }
    444 
    445 
    446 static void StackCheck(Local<String> name,
    447                        const v8::PropertyCallbackInfo<v8::Value>& info) {
    448   i::StackFrameIterator iter(reinterpret_cast<i::Isolate*>(info.GetIsolate()));
    449   for (int i = 0; !iter.done(); i++) {
    450     i::StackFrame* frame = iter.frame();
    451     CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
    452     i::Code* code = frame->LookupCode();
    453     CHECK(code->IsCode());
    454     i::Address pc = frame->pc();
    455     CHECK(code->contains(pc));
    456     iter.Advance();
    457   }
    458 }
    459 
    460 
    461 THREADED_TEST(StackIteration) {
    462   LocalContext env;
    463   v8::Isolate* isolate = env->GetIsolate();
    464   v8::HandleScope scope(isolate);
    465   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    466   i::StringStream::ClearMentionedObjectCache(
    467       reinterpret_cast<i::Isolate*>(isolate));
    468   obj->SetAccessor(v8_str("xxx"), StackCheck);
    469   env->Global()->Set(v8_str("obj"), obj->NewInstance());
    470   Script::Compile(String::NewFromUtf8(
    471       isolate,
    472       "function foo() {"
    473       "  return obj.xxx;"
    474       "}"
    475       "for (var i = 0; i < 100; i++) {"
    476       "  foo();"
    477       "}"))->Run();
    478 }
    479 
    480 
    481 static void AllocateHandles(Local<String> name,
    482                             const v8::PropertyCallbackInfo<v8::Value>& info) {
    483   for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
    484     v8::Local<v8::Value>::New(info.GetIsolate(), name);
    485   }
    486   info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 100));
    487 }
    488 
    489 
    490 THREADED_TEST(HandleScopeSegment) {
    491   // Check that we can return values past popping of handle scope
    492   // segments.
    493   LocalContext env;
    494   v8::Isolate* isolate = env->GetIsolate();
    495   v8::HandleScope scope(isolate);
    496   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    497   obj->SetAccessor(v8_str("xxx"), AllocateHandles);
    498   env->Global()->Set(v8_str("obj"), obj->NewInstance());
    499   v8::Handle<v8::Value> result = Script::Compile(String::NewFromUtf8(
    500       isolate,
    501       "var result;"
    502       "for (var i = 0; i < 4; i++)"
    503       "  result = obj.xxx;"
    504       "result;"))->Run();
    505   CHECK_EQ(100, result->Int32Value());
    506 }
    507 
    508 
    509 void JSONStringifyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
    510   v8::Handle<v8::Array> array = v8::Array::New(info.GetIsolate(), 1);
    511   array->Set(0, v8_str("regress"));
    512   info.GetReturnValue().Set(array);
    513 }
    514 
    515 
    516 void JSONStringifyGetter(Local<String> name,
    517                          const v8::PropertyCallbackInfo<v8::Value>& info) {
    518   info.GetReturnValue().Set(v8_str("crbug-161028"));
    519 }
    520 
    521 
    522 THREADED_TEST(JSONStringifyNamedInterceptorObject) {
    523   LocalContext env;
    524   v8::Isolate* isolate = env->GetIsolate();
    525   v8::HandleScope scope(isolate);
    526 
    527   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    528   obj->SetNamedPropertyHandler(
    529       JSONStringifyGetter, NULL, NULL, NULL, JSONStringifyEnumerator);
    530   env->Global()->Set(v8_str("obj"), obj->NewInstance());
    531   v8::Handle<v8::String> expected = v8_str("{\"regress\":\"crbug-161028\"}");
    532   CHECK(CompileRun("JSON.stringify(obj)")->Equals(expected));
    533 }
    534 
    535 
    536 static v8::Local<v8::Context> expected_current_context;
    537 static v8::Local<v8::Context> expected_calling_context;
    538 
    539 
    540 static void check_contexts(const v8::FunctionCallbackInfo<v8::Value>& info) {
    541   ApiTestFuzzer::Fuzz();
    542   CHECK(expected_current_context == info.GetIsolate()->GetCurrentContext());
    543   CHECK(expected_calling_context == info.GetIsolate()->GetCallingContext());
    544 }
    545 
    546 
    547 THREADED_TEST(AccessorPropertyCrossContext) {
    548   LocalContext env;
    549   v8::Isolate* isolate = env->GetIsolate();
    550   v8::HandleScope scope(isolate);
    551   v8::Handle<v8::Function> fun = v8::Function::New(isolate, check_contexts);
    552   LocalContext switch_context;
    553   switch_context->Global()->Set(v8_str("fun"), fun);
    554   v8::TryCatch try_catch;
    555   expected_current_context = env.local();
    556   expected_calling_context = switch_context.local();
    557   CompileRun(
    558       "var o = Object.create(null, { n: { get:fun } });"
    559       "for (var i = 0; i < 10; i++) o.n;");
    560   CHECK(!try_catch.HasCaught());
    561 }
    562 
    563 
    564 THREADED_TEST(GlobalObjectAccessor) {
    565   LocalContext env;
    566   v8::Isolate* isolate = env->GetIsolate();
    567   v8::HandleScope scope(isolate);
    568   CompileRun(
    569       "var set_value = 1;"
    570       "Object.defineProperty(this.__proto__, 'x', {"
    571       "    get : function() { return this; },"
    572       "    set : function() { set_value = this; }"
    573       "});"
    574       "function getter() { return x; }"
    575       "function setter() { x = 1; }"
    576       "for (var i = 0; i < 4; i++) { getter(); setter(); }");
    577   CHECK(v8::Utils::OpenHandle(*CompileRun("getter()"))->IsJSGlobalProxy());
    578   CHECK(v8::Utils::OpenHandle(*CompileRun("set_value"))->IsJSGlobalProxy());
    579 }
    580