Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / test / cctest / test-decls.cc
1 // Copyright 2007-2008 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/heap/heap.h"
33 #include "test/cctest/cctest.h"
34
35 using namespace v8;
36
37
38 enum Expectations {
39   EXPECT_RESULT,
40   EXPECT_EXCEPTION,
41   EXPECT_ERROR
42 };
43
44
45 // A DeclarationContext holds a reference to a v8::Context and keeps
46 // track of various declaration related counters to make it easier to
47 // track if global declarations in the presence of interceptors behave
48 // the right way.
49 class DeclarationContext {
50  public:
51   DeclarationContext();
52
53   virtual ~DeclarationContext() {
54     if (is_initialized_) {
55       Isolate* isolate = CcTest::isolate();
56       HandleScope scope(isolate);
57       Local<Context> context = Local<Context>::New(isolate, context_);
58       context->Exit();
59       context_.Reset();
60     }
61   }
62
63   void Check(const char* source,
64              int get, int set, int has,
65              Expectations expectations,
66              v8::Handle<Value> value = Local<Value>());
67
68   int get_count() const { return get_count_; }
69   int set_count() const { return set_count_; }
70   int query_count() const { return query_count_; }
71
72  protected:
73   virtual v8::Handle<Value> Get(Local<String> key);
74   virtual v8::Handle<Value> Set(Local<String> key, Local<Value> value);
75   virtual v8::Handle<Integer> Query(Local<String> key);
76
77   void InitializeIfNeeded();
78
79   // Perform optional initialization steps on the context after it has
80   // been created. Defaults to none but may be overwritten.
81   virtual void PostInitializeContext(Handle<Context> context) {}
82
83   // Get the holder for the interceptor. Default to the instance template
84   // but may be overwritten.
85   virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
86     return function->InstanceTemplate();
87   }
88
89   // The handlers are called as static functions that forward
90   // to the instance specific virtual methods.
91   static void HandleGet(Local<String> key,
92                         const v8::PropertyCallbackInfo<v8::Value>& info);
93   static void HandleSet(Local<String> key,
94                         Local<Value> value,
95                         const v8::PropertyCallbackInfo<v8::Value>& info);
96   static void HandleQuery(Local<String> key,
97                           const v8::PropertyCallbackInfo<v8::Integer>& info);
98
99   v8::Isolate* isolate() const { return CcTest::isolate(); }
100
101  private:
102   bool is_initialized_;
103   Persistent<Context> context_;
104
105   int get_count_;
106   int set_count_;
107   int query_count_;
108
109   static DeclarationContext* GetInstance(Local<Value> data);
110 };
111
112
113 DeclarationContext::DeclarationContext()
114     : is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
115   // Do nothing.
116 }
117
118
119 void DeclarationContext::InitializeIfNeeded() {
120   if (is_initialized_) return;
121   Isolate* isolate = CcTest::isolate();
122   HandleScope scope(isolate);
123   Local<FunctionTemplate> function = FunctionTemplate::New(isolate);
124   Local<Value> data = External::New(CcTest::isolate(), this);
125   GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
126                                                &HandleSet,
127                                                &HandleQuery,
128                                                0, 0,
129                                                data);
130   Local<Context> context = Context::New(isolate,
131                                         0,
132                                         function->InstanceTemplate(),
133                                         Local<Value>());
134   context_.Reset(isolate, context);
135   context->Enter();
136   is_initialized_ = true;
137   PostInitializeContext(context);
138 }
139
140
141 void DeclarationContext::Check(const char* source,
142                                int get, int set, int query,
143                                Expectations expectations,
144                                v8::Handle<Value> value) {
145   InitializeIfNeeded();
146   // A retry after a GC may pollute the counts, so perform gc now
147   // to avoid that.
148   CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
149   HandleScope scope(CcTest::isolate());
150   TryCatch catcher;
151   catcher.SetVerbose(true);
152   Local<Script> script =
153       Script::Compile(String::NewFromUtf8(CcTest::isolate(), source));
154   if (expectations == EXPECT_ERROR) {
155     CHECK(script.IsEmpty());
156     return;
157   }
158   CHECK(!script.IsEmpty());
159   Local<Value> result = script->Run();
160   CHECK_EQ(get, get_count());
161   CHECK_EQ(set, set_count());
162   CHECK_EQ(query, query_count());
163   if (expectations == EXPECT_RESULT) {
164     CHECK(!catcher.HasCaught());
165     if (!value.IsEmpty()) {
166       CHECK_EQ(value, result);
167     }
168   } else {
169     CHECK(expectations == EXPECT_EXCEPTION);
170     CHECK(catcher.HasCaught());
171     if (!value.IsEmpty()) {
172       CHECK_EQ(value, catcher.Exception());
173     }
174   }
175   // Clean slate for the next test.
176   CcTest::heap()->CollectAllAvailableGarbage();
177 }
178
179
180 void DeclarationContext::HandleGet(
181     Local<String> key,
182     const v8::PropertyCallbackInfo<v8::Value>& info) {
183   DeclarationContext* context = GetInstance(info.Data());
184   context->get_count_++;
185   info.GetReturnValue().Set(context->Get(key));
186 }
187
188
189 void DeclarationContext::HandleSet(
190     Local<String> key,
191     Local<Value> value,
192     const v8::PropertyCallbackInfo<v8::Value>& info) {
193   DeclarationContext* context = GetInstance(info.Data());
194   context->set_count_++;
195   info.GetReturnValue().Set(context->Set(key, value));
196 }
197
198
199 void DeclarationContext::HandleQuery(
200     Local<String> key,
201     const v8::PropertyCallbackInfo<v8::Integer>& info) {
202   DeclarationContext* context = GetInstance(info.Data());
203   context->query_count_++;
204   info.GetReturnValue().Set(context->Query(key));
205 }
206
207
208 DeclarationContext* DeclarationContext::GetInstance(Local<Value> data) {
209   void* value = Local<External>::Cast(data)->Value();
210   return static_cast<DeclarationContext*>(value);
211 }
212
213
214 v8::Handle<Value> DeclarationContext::Get(Local<String> key) {
215   return v8::Handle<Value>();
216 }
217
218
219 v8::Handle<Value> DeclarationContext::Set(Local<String> key,
220                                           Local<Value> value) {
221   return v8::Handle<Value>();
222 }
223
224
225 v8::Handle<Integer> DeclarationContext::Query(Local<String> key) {
226   return v8::Handle<Integer>();
227 }
228
229
230 // Test global declaration of a property the interceptor doesn't know
231 // about and doesn't handle.
232 TEST(Unknown) {
233   HandleScope scope(CcTest::isolate());
234   v8::V8::Initialize();
235
236   { DeclarationContext context;
237     context.Check("var x; x",
238                   1,  // access
239                   0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
240   }
241
242   { DeclarationContext context;
243     context.Check("var x = 0; x",
244                   1,  // access
245                   1,  // initialization
246                   0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
247   }
248
249   { DeclarationContext context;
250     context.Check("function x() { }; x",
251                   1,  // access
252                   0,
253                   0,
254                   EXPECT_RESULT);
255   }
256
257   { DeclarationContext context;
258     context.Check("const x; x",
259                   1,  // access
260                   0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
261   }
262
263   { DeclarationContext context;
264     context.Check("const x = 0; x",
265                   1,  // access
266                   0,
267                   0,
268                   EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
269   }
270 }
271
272
273 class AbsentPropertyContext: public DeclarationContext {
274  protected:
275   virtual v8::Handle<Integer> Query(Local<String> key) {
276     return v8::Handle<Integer>();
277   }
278 };
279
280
281 TEST(Absent) {
282   v8::Isolate* isolate = CcTest::isolate();
283   v8::V8::Initialize();
284   HandleScope scope(isolate);
285
286   { AbsentPropertyContext context;
287     context.Check("var x; x",
288                   1,  // access
289                   0, 0, EXPECT_RESULT, Undefined(isolate));
290   }
291
292   { AbsentPropertyContext context;
293     context.Check("var x = 0; x",
294                   1,  // access
295                   1,  // initialization
296                   0, EXPECT_RESULT, Number::New(isolate, 0));
297   }
298
299   { AbsentPropertyContext context;
300     context.Check("function x() { }; x",
301                   1,  // access
302                   0,
303                   0,
304                   EXPECT_RESULT);
305   }
306
307   { AbsentPropertyContext context;
308     context.Check("const x; x",
309                   1,  // access
310                   0, 0, EXPECT_RESULT, Undefined(isolate));
311   }
312
313   { AbsentPropertyContext context;
314     context.Check("const x = 0; x",
315                   1,  // access
316                   0, 0, EXPECT_RESULT, Number::New(isolate, 0));
317   }
318
319   { AbsentPropertyContext context;
320     context.Check("if (false) { var x = 0 }; x",
321                   1,  // access
322                   0, 0, EXPECT_RESULT, Undefined(isolate));
323   }
324 }
325
326
327
328 class AppearingPropertyContext: public DeclarationContext {
329  public:
330   enum State {
331     DECLARE,
332     INITIALIZE_IF_ASSIGN,
333     UNKNOWN
334   };
335
336   AppearingPropertyContext() : state_(DECLARE) { }
337
338  protected:
339   virtual v8::Handle<Integer> Query(Local<String> key) {
340     switch (state_) {
341       case DECLARE:
342         // Force declaration by returning that the
343         // property is absent.
344         state_ = INITIALIZE_IF_ASSIGN;
345         return Handle<Integer>();
346       case INITIALIZE_IF_ASSIGN:
347         // Return that the property is present so we only get the
348         // setter called when initializing with a value.
349         state_ = UNKNOWN;
350         return Integer::New(isolate(), v8::None);
351       default:
352         CHECK(state_ == UNKNOWN);
353         break;
354     }
355     // Do the lookup in the object.
356     return v8::Handle<Integer>();
357   }
358
359  private:
360   State state_;
361 };
362
363
364 TEST(Appearing) {
365   v8::V8::Initialize();
366   HandleScope scope(CcTest::isolate());
367
368   { AppearingPropertyContext context;
369     context.Check("var x; x",
370                   1,  // access
371                   0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
372   }
373
374   { AppearingPropertyContext context;
375     context.Check("var x = 0; x",
376                   1,  // access
377                   1,  // initialization
378                   0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
379   }
380
381   { AppearingPropertyContext context;
382     context.Check("function x() { }; x",
383                   1,  // access
384                   0,
385                   0,
386                   EXPECT_RESULT);
387   }
388
389   { AppearingPropertyContext context;
390     context.Check("const x; x",
391                   1,  // access
392                   0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
393   }
394
395   { AppearingPropertyContext context;
396     context.Check("const x = 0; x",
397                   1,  // access
398                   0, 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
399   }
400 }
401
402
403
404 class ExistsInPrototypeContext: public DeclarationContext {
405  public:
406   ExistsInPrototypeContext() { InitializeIfNeeded(); }
407  protected:
408   virtual v8::Handle<Integer> Query(Local<String> key) {
409     // Let it seem that the property exists in the prototype object.
410     return Integer::New(isolate(), v8::None);
411   }
412
413   // Use the prototype as the holder for the interceptors.
414   virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
415     return function->PrototypeTemplate();
416   }
417 };
418
419
420 TEST(ExistsInPrototype) {
421   HandleScope scope(CcTest::isolate());
422
423   // Sanity check to make sure that the holder of the interceptor
424   // really is the prototype object.
425   { ExistsInPrototypeContext context;
426     context.Check("this.x = 87; this.x", 0, 0, 1, EXPECT_RESULT,
427                   Number::New(CcTest::isolate(), 87));
428   }
429
430   { ExistsInPrototypeContext context;
431     context.Check("var x; x",
432                   0,
433                   0,
434                   0,
435                   EXPECT_RESULT, Undefined(CcTest::isolate()));
436   }
437
438   { ExistsInPrototypeContext context;
439     context.Check("var x = 0; x",
440                   0,
441                   0,
442                   0,
443                   EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
444   }
445
446   { ExistsInPrototypeContext context;
447     context.Check("const x; x",
448                   0,
449                   0,
450                   0,
451                   EXPECT_RESULT, Undefined(CcTest::isolate()));
452   }
453
454   { ExistsInPrototypeContext context;
455     context.Check("const x = 0; x",
456                   0,
457                   0,
458                   0,
459                   EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
460   }
461 }
462
463
464
465 class AbsentInPrototypeContext: public DeclarationContext {
466  protected:
467   virtual v8::Handle<Integer> Query(Local<String> key) {
468     // Let it seem that the property is absent in the prototype object.
469     return Handle<Integer>();
470   }
471
472   // Use the prototype as the holder for the interceptors.
473   virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
474     return function->PrototypeTemplate();
475   }
476 };
477
478
479 TEST(AbsentInPrototype) {
480   v8::V8::Initialize();
481   HandleScope scope(CcTest::isolate());
482
483   { AbsentInPrototypeContext context;
484     context.Check("if (false) { var x = 0; }; x",
485                   0,
486                   0,
487                   0,
488                   EXPECT_RESULT, Undefined(CcTest::isolate()));
489   }
490 }
491
492
493
494 class ExistsInHiddenPrototypeContext: public DeclarationContext {
495  public:
496   ExistsInHiddenPrototypeContext() {
497     hidden_proto_ = FunctionTemplate::New(CcTest::isolate());
498     hidden_proto_->SetHiddenPrototype(true);
499   }
500
501  protected:
502   virtual v8::Handle<Integer> Query(Local<String> key) {
503     // Let it seem that the property exists in the hidden prototype object.
504     return Integer::New(isolate(), v8::None);
505   }
506
507   // Install the hidden prototype after the global object has been created.
508   virtual void PostInitializeContext(Handle<Context> context) {
509     Local<Object> global_object = context->Global();
510     Local<Object> hidden_proto = hidden_proto_->GetFunction()->NewInstance();
511     Local<Object> inner_global =
512         Local<Object>::Cast(global_object->GetPrototype());
513     inner_global->SetPrototype(hidden_proto);
514   }
515
516   // Use the hidden prototype as the holder for the interceptors.
517   virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
518     return hidden_proto_->InstanceTemplate();
519   }
520
521  private:
522   Local<FunctionTemplate> hidden_proto_;
523 };
524
525
526 TEST(ExistsInHiddenPrototype) {
527   HandleScope scope(CcTest::isolate());
528
529   { ExistsInHiddenPrototypeContext context;
530     context.Check("var x; x", 0, 0, 0, EXPECT_RESULT,
531                   Undefined(CcTest::isolate()));
532   }
533
534   { ExistsInHiddenPrototypeContext context;
535     context.Check("var x = 0; x", 0, 0, 0, EXPECT_RESULT,
536                   Number::New(CcTest::isolate(), 0));
537   }
538
539   { ExistsInHiddenPrototypeContext context;
540     context.Check("function x() { }; x",
541                   0,
542                   0,
543                   0,
544                   EXPECT_RESULT);
545   }
546
547   // TODO(mstarzinger): The semantics of global const is vague.
548   { ExistsInHiddenPrototypeContext context;
549     context.Check("const x; x", 0, 0, 0, EXPECT_RESULT,
550                   Undefined(CcTest::isolate()));
551   }
552
553   // TODO(mstarzinger): The semantics of global const is vague.
554   { ExistsInHiddenPrototypeContext context;
555     context.Check("const x = 0; x", 0, 0, 0, EXPECT_RESULT,
556                   Number::New(CcTest::isolate(), 0));
557   }
558 }
559
560
561
562 class SimpleContext {
563  public:
564   SimpleContext()
565       : handle_scope_(CcTest::isolate()),
566         context_(Context::New(CcTest::isolate())) {
567     context_->Enter();
568   }
569
570   ~SimpleContext() {
571     context_->Exit();
572   }
573
574   void Check(const char* source,
575              Expectations expectations,
576              v8::Handle<Value> value = Local<Value>()) {
577     HandleScope scope(context_->GetIsolate());
578     TryCatch catcher;
579     catcher.SetVerbose(true);
580     Local<Script> script =
581         Script::Compile(String::NewFromUtf8(context_->GetIsolate(), source));
582     if (expectations == EXPECT_ERROR) {
583       CHECK(script.IsEmpty());
584       return;
585     }
586     CHECK(!script.IsEmpty());
587     Local<Value> result = script->Run();
588     if (expectations == EXPECT_RESULT) {
589       CHECK(!catcher.HasCaught());
590       if (!value.IsEmpty()) {
591         CHECK_EQ(value, result);
592       }
593     } else {
594       CHECK(expectations == EXPECT_EXCEPTION);
595       CHECK(catcher.HasCaught());
596       if (!value.IsEmpty()) {
597         CHECK_EQ(value, catcher.Exception());
598       }
599     }
600   }
601
602  private:
603   HandleScope handle_scope_;
604   Local<Context> context_;
605 };
606
607
608 TEST(CrossScriptReferences) {
609   v8::Isolate* isolate = CcTest::isolate();
610   HandleScope scope(isolate);
611
612   { SimpleContext context;
613     context.Check("var x = 1; x",
614                   EXPECT_RESULT, Number::New(isolate, 1));
615     context.Check("var x = 2; x",
616                   EXPECT_RESULT, Number::New(isolate, 2));
617     context.Check("const x = 3; x", EXPECT_EXCEPTION);
618     context.Check("const x = 4; x", EXPECT_EXCEPTION);
619     context.Check("x = 5; x",
620                   EXPECT_RESULT, Number::New(isolate, 5));
621     context.Check("var x = 6; x",
622                   EXPECT_RESULT, Number::New(isolate, 6));
623     context.Check("this.x",
624                   EXPECT_RESULT, Number::New(isolate, 6));
625     context.Check("function x() { return 7 }; x()",
626                   EXPECT_RESULT, Number::New(isolate, 7));
627   }
628
629   { SimpleContext context;
630     context.Check("const x = 1; x",
631                   EXPECT_RESULT, Number::New(isolate, 1));
632     context.Check("var x = 2; x",  // assignment ignored
633                   EXPECT_RESULT, Number::New(isolate, 1));
634     context.Check("const x = 3; x", EXPECT_EXCEPTION);
635     context.Check("x = 4; x",  // assignment ignored
636                   EXPECT_RESULT, Number::New(isolate, 1));
637     context.Check("var x = 5; x",  // assignment ignored
638                   EXPECT_RESULT, Number::New(isolate, 1));
639     context.Check("this.x",
640                   EXPECT_RESULT, Number::New(isolate, 1));
641     context.Check("function x() { return 7 }; x",
642                   EXPECT_EXCEPTION);
643   }
644 }
645
646
647 TEST(CrossScriptReferencesHarmony) {
648   i::FLAG_use_strict = true;
649   i::FLAG_harmony_scoping = true;
650   i::FLAG_harmony_modules = true;
651
652   v8::Isolate* isolate = CcTest::isolate();
653   HandleScope scope(isolate);
654
655   const char* decs[] = {
656     "var x = 1; x", "x", "this.x",
657     "function x() { return 1 }; x()", "x()", "this.x()",
658     "let x = 1; x", "x", "this.x",
659     "const x = 1; x", "x", "this.x",
660     "module x { export let a = 1 }; x.a", "x.a", "this.x.a",
661     NULL
662   };
663
664   for (int i = 0; decs[i] != NULL; i += 3) {
665     SimpleContext context;
666     context.Check(decs[i], EXPECT_RESULT, Number::New(isolate, 1));
667     context.Check(decs[i+1], EXPECT_RESULT, Number::New(isolate, 1));
668     // TODO(rossberg): The current ES6 draft spec does not reflect lexical
669     // bindings on the global object. However, this will probably change, in
670     // which case we reactivate the following test.
671     if (i/3 < 2) {
672       context.Check(decs[i+2], EXPECT_RESULT, Number::New(isolate, 1));
673     }
674   }
675 }
676
677
678 TEST(CrossScriptConflicts) {
679   i::FLAG_use_strict = true;
680   i::FLAG_harmony_scoping = true;
681   i::FLAG_harmony_modules = true;
682
683   HandleScope scope(CcTest::isolate());
684
685   const char* firsts[] = {
686     "var x = 1; x",
687     "function x() { return 1 }; x()",
688     "let x = 1; x",
689     "const x = 1; x",
690     "module x { export let a = 1 }; x.a",
691     NULL
692   };
693   const char* seconds[] = {
694     "var x = 2; x",
695     "function x() { return 2 }; x()",
696     "let x = 2; x",
697     "const x = 2; x",
698     "module x { export let a = 2 }; x.a",
699     NULL
700   };
701
702   for (int i = 0; firsts[i] != NULL; ++i) {
703     for (int j = 0; seconds[j] != NULL; ++j) {
704       SimpleContext context;
705       context.Check(firsts[i], EXPECT_RESULT,
706                     Number::New(CcTest::isolate(), 1));
707       // TODO(rossberg): All tests should actually be errors in Harmony,
708       // but we currently do not detect the cases where the first declaration
709       // is not lexical.
710       context.Check(seconds[j],
711                     i < 2 ? EXPECT_RESULT : EXPECT_ERROR,
712                     Number::New(CcTest::isolate(), 2));
713     }
714   }
715 }
716
717
718 TEST(CrossScriptDynamicLookup) {
719   i::FLAG_harmony_scoping = true;
720
721   HandleScope handle_scope(CcTest::isolate());
722
723   {
724     SimpleContext context;
725     Local<String> undefined_string = String::NewFromUtf8(
726         CcTest::isolate(), "undefined", String::kInternalizedString);
727     Local<String> number_string = String::NewFromUtf8(
728         CcTest::isolate(), "number", String::kInternalizedString);
729
730     context.Check(
731         "function f(o) { with(o) { return x; } }"
732         "function g(o) { with(o) { x = 15; } }"
733         "function h(o) { with(o) { return typeof x; } }",
734         EXPECT_RESULT, Undefined(CcTest::isolate()));
735     context.Check("h({})", EXPECT_RESULT, undefined_string);
736     context.Check(
737         "'use strict';"
738         "let x = 1;"
739         "f({})",
740         EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
741     context.Check(
742         "'use strict';"
743         "g({});"
744         "x",
745         EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
746     context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
747     context.Check("h({})", EXPECT_RESULT, number_string);
748   }
749 }