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