Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / v8 / test / cctest / test-accessors.cc
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 }