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
37using ::v8::ObjectTemplate;
38using ::v8::Value;
39using ::v8::Context;
40using ::v8::Local;
41using ::v8::String;
42using ::v8::Script;
43using ::v8::Function;
44using ::v8::Extension;
45
46static 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
52static 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
59static 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
66THREADED_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
101static 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
110static 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
118int foo, bar, baz;
119
120THREADED_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
143static int x_register[2] = {0, 0};
144static v8::Handle<v8::Object> x_receiver;
145static v8::Handle<v8::Object> x_holder;
146
147template<class Info>
148static 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
157static 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
164static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
165  CHECK_EQ(x_receiver, info.Holder());
166  XGetter(info, 1);
167}
168
169
170template<class Info>
171static 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
181static void XSetter(Local<String> name,
182                    Local<Value> value,
183                    const v8::PropertyCallbackInfo<void>& info) {
184  XSetter(value, info, 0);
185}
186
187
188static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
189  CHECK_EQ(1, info.Length());
190  XSetter(info[0], info, 1);
191}
192
193
194THREADED_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
232template <int C>
233static 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
243THREADED_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
267static 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
288THREADED_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
309static 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
318THREADED_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
336THREADED_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
374static 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
382static void ThrowingSetAccessor(Local<String> name,
383                                Local<Value> value,
384                                const v8::PropertyCallbackInfo<void>& info) {
385  info.GetIsolate()->ThrowException(value);
386}
387
388
389THREADED_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
421static 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
428THREADED_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
446static 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
461THREADED_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
481static 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
490THREADED_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
509void 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
516void JSONStringifyGetter(Local<String> name,
517                         const v8::PropertyCallbackInfo<v8::Value>& info) {
518  info.GetReturnValue().Set(v8_str("crbug-161028"));
519}
520
521
522THREADED_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
536static v8::Local<v8::Context> expected_current_context;
537static v8::Local<v8::Context> expected_calling_context;
538
539
540static 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
547THREADED_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
564THREADED_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