deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / 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<Name> key);
74   virtual v8::Handle<Value> Set(Local<Name> key, Local<Value> value);
75   virtual v8::Handle<Integer> Query(Local<Name> 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<Name> key,
92                         const v8::PropertyCallbackInfo<v8::Value>& info);
93   static void HandleSet(Local<Name> key, Local<Value> value,
94                         const v8::PropertyCallbackInfo<v8::Value>& info);
95   static void HandleQuery(Local<Name> key,
96                           const v8::PropertyCallbackInfo<v8::Integer>& info);
97
98   v8::Isolate* isolate() const { return CcTest::isolate(); }
99
100  private:
101   bool is_initialized_;
102   Persistent<Context> context_;
103
104   int get_count_;
105   int set_count_;
106   int query_count_;
107
108   static DeclarationContext* GetInstance(Local<Value> data);
109 };
110
111
112 DeclarationContext::DeclarationContext()
113     : is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
114   // Do nothing.
115 }
116
117
118 void DeclarationContext::InitializeIfNeeded() {
119   if (is_initialized_) return;
120   Isolate* isolate = CcTest::isolate();
121   HandleScope scope(isolate);
122   Local<FunctionTemplate> function = FunctionTemplate::New(isolate);
123   Local<Value> data = External::New(CcTest::isolate(), this);
124   GetHolder(function)->SetHandler(v8::NamedPropertyHandlerConfiguration(
125       &HandleGet, &HandleSet, &HandleQuery, 0, 0, data));
126   Local<Context> context = Context::New(isolate,
127                                         0,
128                                         function->InstanceTemplate(),
129                                         Local<Value>());
130   context_.Reset(isolate, context);
131   context->Enter();
132   is_initialized_ = true;
133   PostInitializeContext(context);
134 }
135
136
137 void DeclarationContext::Check(const char* source,
138                                int get, int set, int query,
139                                Expectations expectations,
140                                v8::Handle<Value> value) {
141   InitializeIfNeeded();
142   // A retry after a GC may pollute the counts, so perform gc now
143   // to avoid that.
144   CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
145   HandleScope scope(CcTest::isolate());
146   TryCatch catcher;
147   catcher.SetVerbose(true);
148   Local<Script> script =
149       Script::Compile(String::NewFromUtf8(CcTest::isolate(), source));
150   if (expectations == EXPECT_ERROR) {
151     CHECK(script.IsEmpty());
152     return;
153   }
154   CHECK(!script.IsEmpty());
155   Local<Value> result = script->Run();
156   CHECK_EQ(get, get_count());
157   CHECK_EQ(set, set_count());
158   CHECK_EQ(query, query_count());
159   if (expectations == EXPECT_RESULT) {
160     CHECK(!catcher.HasCaught());
161     if (!value.IsEmpty()) {
162       CHECK(value->Equals(result));
163     }
164   } else {
165     CHECK(expectations == EXPECT_EXCEPTION);
166     CHECK(catcher.HasCaught());
167     if (!value.IsEmpty()) {
168       CHECK(value->Equals(catcher.Exception()));
169     }
170   }
171   // Clean slate for the next test.
172   CcTest::heap()->CollectAllAvailableGarbage();
173 }
174
175
176 void DeclarationContext::HandleGet(
177     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
178   DeclarationContext* context = GetInstance(info.Data());
179   context->get_count_++;
180   info.GetReturnValue().Set(context->Get(key));
181 }
182
183
184 void DeclarationContext::HandleSet(
185     Local<Name> key, Local<Value> value,
186     const v8::PropertyCallbackInfo<v8::Value>& info) {
187   DeclarationContext* context = GetInstance(info.Data());
188   context->set_count_++;
189   info.GetReturnValue().Set(context->Set(key, value));
190 }
191
192
193 void DeclarationContext::HandleQuery(
194     Local<Name> key, const v8::PropertyCallbackInfo<v8::Integer>& info) {
195   DeclarationContext* context = GetInstance(info.Data());
196   context->query_count_++;
197   info.GetReturnValue().Set(context->Query(key));
198 }
199
200
201 DeclarationContext* DeclarationContext::GetInstance(Local<Value> data) {
202   void* value = Local<External>::Cast(data)->Value();
203   return static_cast<DeclarationContext*>(value);
204 }
205
206
207 v8::Handle<Value> DeclarationContext::Get(Local<Name> key) {
208   return v8::Handle<Value>();
209 }
210
211
212 v8::Handle<Value> DeclarationContext::Set(Local<Name> key, Local<Value> value) {
213   return v8::Handle<Value>();
214 }
215
216
217 v8::Handle<Integer> DeclarationContext::Query(Local<Name> key) {
218   return v8::Handle<Integer>();
219 }
220
221
222 // Test global declaration of a property the interceptor doesn't know
223 // about and doesn't handle.
224 TEST(Unknown) {
225   HandleScope scope(CcTest::isolate());
226   v8::V8::Initialize();
227
228   { DeclarationContext context;
229     context.Check("var x; x",
230                   1,  // access
231                   0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
232   }
233
234   { DeclarationContext context;
235     context.Check("var x = 0; x",
236                   1,  // access
237                   1,  // initialization
238                   0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
239   }
240
241   { DeclarationContext context;
242     context.Check("function x() { }; x",
243                   1,  // access
244                   0,
245                   0,
246                   EXPECT_RESULT);
247   }
248
249   { DeclarationContext context;
250     context.Check("const x; x",
251                   1,  // access
252                   0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
253   }
254
255   { DeclarationContext context;
256     context.Check("const x = 0; x",
257                   1,  // access
258                   0,
259                   0,
260                   EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
261   }
262 }
263
264
265 class AbsentPropertyContext: public DeclarationContext {
266  protected:
267   virtual v8::Handle<Integer> Query(Local<Name> key) {
268     return v8::Handle<Integer>();
269   }
270 };
271
272
273 TEST(Absent) {
274   v8::Isolate* isolate = CcTest::isolate();
275   v8::V8::Initialize();
276   HandleScope scope(isolate);
277
278   { AbsentPropertyContext context;
279     context.Check("var x; x",
280                   1,  // access
281                   0, 0, EXPECT_RESULT, Undefined(isolate));
282   }
283
284   { AbsentPropertyContext context;
285     context.Check("var x = 0; x",
286                   1,  // access
287                   1,  // initialization
288                   0, EXPECT_RESULT, Number::New(isolate, 0));
289   }
290
291   { AbsentPropertyContext context;
292     context.Check("function x() { }; x",
293                   1,  // access
294                   0,
295                   0,
296                   EXPECT_RESULT);
297   }
298
299   { AbsentPropertyContext context;
300     context.Check("const x; x",
301                   1,  // access
302                   0, 0, EXPECT_RESULT, Undefined(isolate));
303   }
304
305   { AbsentPropertyContext context;
306     context.Check("const x = 0; x",
307                   1,  // access
308                   0, 0, EXPECT_RESULT, Number::New(isolate, 0));
309   }
310
311   { AbsentPropertyContext context;
312     context.Check("if (false) { var x = 0 }; x",
313                   1,  // access
314                   0, 0, EXPECT_RESULT, Undefined(isolate));
315   }
316 }
317
318
319
320 class AppearingPropertyContext: public DeclarationContext {
321  public:
322   enum State {
323     DECLARE,
324     INITIALIZE_IF_ASSIGN,
325     UNKNOWN
326   };
327
328   AppearingPropertyContext() : state_(DECLARE) { }
329
330  protected:
331   virtual v8::Handle<Integer> Query(Local<Name> key) {
332     switch (state_) {
333       case DECLARE:
334         // Force declaration by returning that the
335         // property is absent.
336         state_ = INITIALIZE_IF_ASSIGN;
337         return Handle<Integer>();
338       case INITIALIZE_IF_ASSIGN:
339         // Return that the property is present so we only get the
340         // setter called when initializing with a value.
341         state_ = UNKNOWN;
342         return Integer::New(isolate(), v8::None);
343       default:
344         CHECK(state_ == UNKNOWN);
345         break;
346     }
347     // Do the lookup in the object.
348     return v8::Handle<Integer>();
349   }
350
351  private:
352   State state_;
353 };
354
355
356 TEST(Appearing) {
357   v8::V8::Initialize();
358   HandleScope scope(CcTest::isolate());
359
360   { AppearingPropertyContext context;
361     context.Check("var x; x",
362                   1,  // access
363                   0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
364   }
365
366   { AppearingPropertyContext context;
367     context.Check("var x = 0; x",
368                   1,  // access
369                   1,  // initialization
370                   0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
371   }
372
373   { AppearingPropertyContext context;
374     context.Check("function x() { }; x",
375                   1,  // access
376                   0,
377                   0,
378                   EXPECT_RESULT);
379   }
380
381   { AppearingPropertyContext context;
382     context.Check("const x; x",
383                   1,  // access
384                   0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
385   }
386
387   { AppearingPropertyContext context;
388     context.Check("const x = 0; x",
389                   1,  // access
390                   0, 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
391   }
392 }
393
394
395
396 class ExistsInPrototypeContext: public DeclarationContext {
397  public:
398   ExistsInPrototypeContext() { InitializeIfNeeded(); }
399  protected:
400   virtual v8::Handle<Integer> Query(Local<Name> key) {
401     // Let it seem that the property exists in the prototype object.
402     return Integer::New(isolate(), v8::None);
403   }
404
405   // Use the prototype as the holder for the interceptors.
406   virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
407     return function->PrototypeTemplate();
408   }
409 };
410
411
412 TEST(ExistsInPrototype) {
413   HandleScope scope(CcTest::isolate());
414
415   // Sanity check to make sure that the holder of the interceptor
416   // really is the prototype object.
417   { ExistsInPrototypeContext context;
418     context.Check("this.x = 87; this.x", 0, 0, 1, EXPECT_RESULT,
419                   Number::New(CcTest::isolate(), 87));
420   }
421
422   { ExistsInPrototypeContext context;
423     context.Check("var x; x",
424                   0,
425                   0,
426                   0,
427                   EXPECT_RESULT, Undefined(CcTest::isolate()));
428   }
429
430   { ExistsInPrototypeContext context;
431     context.Check("var x = 0; x",
432                   0,
433                   0,
434                   0,
435                   EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
436   }
437
438   { ExistsInPrototypeContext context;
439     context.Check("const x; x",
440                   0,
441                   0,
442                   0,
443                   EXPECT_RESULT, Undefined(CcTest::isolate()));
444   }
445
446   { ExistsInPrototypeContext context;
447     context.Check("const x = 0; x",
448                   0,
449                   0,
450                   0,
451                   EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
452   }
453 }
454
455
456
457 class AbsentInPrototypeContext: public DeclarationContext {
458  protected:
459   virtual v8::Handle<Integer> Query(Local<Name> key) {
460     // Let it seem that the property is absent in the prototype object.
461     return Handle<Integer>();
462   }
463
464   // Use the prototype as the holder for the interceptors.
465   virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
466     return function->PrototypeTemplate();
467   }
468 };
469
470
471 TEST(AbsentInPrototype) {
472   v8::V8::Initialize();
473   HandleScope scope(CcTest::isolate());
474
475   { AbsentInPrototypeContext context;
476     context.Check("if (false) { var x = 0; }; x",
477                   0,
478                   0,
479                   0,
480                   EXPECT_RESULT, Undefined(CcTest::isolate()));
481   }
482 }
483
484
485
486 class ExistsInHiddenPrototypeContext: public DeclarationContext {
487  public:
488   ExistsInHiddenPrototypeContext() {
489     hidden_proto_ = FunctionTemplate::New(CcTest::isolate());
490     hidden_proto_->SetHiddenPrototype(true);
491   }
492
493  protected:
494   virtual v8::Handle<Integer> Query(Local<Name> key) {
495     // Let it seem that the property exists in the hidden prototype object.
496     return Integer::New(isolate(), v8::None);
497   }
498
499   // Install the hidden prototype after the global object has been created.
500   virtual void PostInitializeContext(Handle<Context> context) {
501     Local<Object> global_object = context->Global();
502     Local<Object> hidden_proto = hidden_proto_->GetFunction()->NewInstance();
503     Local<Object> inner_global =
504         Local<Object>::Cast(global_object->GetPrototype());
505     inner_global->SetPrototype(hidden_proto);
506   }
507
508   // Use the hidden prototype as the holder for the interceptors.
509   virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
510     return hidden_proto_->InstanceTemplate();
511   }
512
513  private:
514   Local<FunctionTemplate> hidden_proto_;
515 };
516
517
518 TEST(ExistsInHiddenPrototype) {
519   HandleScope scope(CcTest::isolate());
520
521   { ExistsInHiddenPrototypeContext context;
522     context.Check("var x; x", 0, 0, 0, EXPECT_RESULT,
523                   Undefined(CcTest::isolate()));
524   }
525
526   { ExistsInHiddenPrototypeContext context;
527     context.Check("var x = 0; x", 0, 0, 0, EXPECT_RESULT,
528                   Number::New(CcTest::isolate(), 0));
529   }
530
531   { ExistsInHiddenPrototypeContext context;
532     context.Check("function x() { }; x",
533                   0,
534                   0,
535                   0,
536                   EXPECT_RESULT);
537   }
538
539   // TODO(mstarzinger): The semantics of global const is vague.
540   { ExistsInHiddenPrototypeContext context;
541     context.Check("const x; x", 0, 0, 0, EXPECT_RESULT,
542                   Undefined(CcTest::isolate()));
543   }
544
545   // TODO(mstarzinger): The semantics of global const is vague.
546   { ExistsInHiddenPrototypeContext context;
547     context.Check("const x = 0; x", 0, 0, 0, EXPECT_RESULT,
548                   Number::New(CcTest::isolate(), 0));
549   }
550 }
551
552
553
554 class SimpleContext {
555  public:
556   SimpleContext()
557       : handle_scope_(CcTest::isolate()),
558         context_(Context::New(CcTest::isolate())) {
559     context_->Enter();
560   }
561
562   ~SimpleContext() {
563     context_->Exit();
564   }
565
566   void Check(const char* source,
567              Expectations expectations,
568              v8::Handle<Value> value = Local<Value>()) {
569     HandleScope scope(context_->GetIsolate());
570     TryCatch catcher;
571     catcher.SetVerbose(true);
572     Local<Script> script =
573         Script::Compile(String::NewFromUtf8(context_->GetIsolate(), source));
574     if (expectations == EXPECT_ERROR) {
575       CHECK(script.IsEmpty());
576       return;
577     }
578     CHECK(!script.IsEmpty());
579     Local<Value> result = script->Run();
580     if (expectations == EXPECT_RESULT) {
581       CHECK(!catcher.HasCaught());
582       if (!value.IsEmpty()) {
583         CHECK(value->Equals(result));
584       }
585     } else {
586       CHECK(expectations == EXPECT_EXCEPTION);
587       CHECK(catcher.HasCaught());
588       if (!value.IsEmpty()) {
589         CHECK(value->Equals(catcher.Exception()));
590       }
591     }
592   }
593
594  private:
595   HandleScope handle_scope_;
596   Local<Context> context_;
597 };
598
599
600 TEST(CrossScriptReferences) {
601   v8::Isolate* isolate = CcTest::isolate();
602   HandleScope scope(isolate);
603
604   { SimpleContext context;
605     context.Check("var x = 1; x",
606                   EXPECT_RESULT, Number::New(isolate, 1));
607     context.Check("var x = 2; x",
608                   EXPECT_RESULT, Number::New(isolate, 2));
609     context.Check("const x = 3; x", EXPECT_EXCEPTION);
610     context.Check("const x = 4; x", EXPECT_EXCEPTION);
611     context.Check("x = 5; x",
612                   EXPECT_RESULT, Number::New(isolate, 5));
613     context.Check("var x = 6; x",
614                   EXPECT_RESULT, Number::New(isolate, 6));
615     context.Check("this.x",
616                   EXPECT_RESULT, Number::New(isolate, 6));
617     context.Check("function x() { return 7 }; x()",
618                   EXPECT_RESULT, Number::New(isolate, 7));
619   }
620
621   { SimpleContext context;
622     context.Check("const x = 1; x",
623                   EXPECT_RESULT, Number::New(isolate, 1));
624     context.Check("var x = 2; x",  // assignment ignored
625                   EXPECT_RESULT, Number::New(isolate, 1));
626     context.Check("const x = 3; x", EXPECT_EXCEPTION);
627     context.Check("x = 4; x",  // assignment ignored
628                   EXPECT_RESULT, Number::New(isolate, 1));
629     context.Check("var x = 5; x",  // assignment ignored
630                   EXPECT_RESULT, Number::New(isolate, 1));
631     context.Check("this.x",
632                   EXPECT_RESULT, Number::New(isolate, 1));
633     context.Check("function x() { return 7 }; x",
634                   EXPECT_EXCEPTION);
635   }
636 }
637
638
639 TEST(CrossScriptReferences_Simple) {
640   i::FLAG_use_strict = true;
641
642   v8::Isolate* isolate = CcTest::isolate();
643   HandleScope scope(isolate);
644
645   {
646     SimpleContext context;
647     context.Check("let x = 1; x", EXPECT_RESULT, Number::New(isolate, 1));
648     context.Check("let x = 5; x", EXPECT_EXCEPTION);
649   }
650 }
651
652
653 TEST(CrossScriptReferences_Simple2) {
654   i::FLAG_use_strict = true;
655
656   v8::Isolate* isolate = CcTest::isolate();
657   HandleScope scope(isolate);
658
659   for (int k = 0; k < 100; k++) {
660     SimpleContext context;
661     bool cond = (k % 2) == 0;
662     if (cond) {
663       context.Check("let x = 1; x", EXPECT_RESULT, Number::New(isolate, 1));
664       context.Check("let z = 4; z", EXPECT_RESULT, Number::New(isolate, 4));
665     } else {
666       context.Check("let z = 1; z", EXPECT_RESULT, Number::New(isolate, 1));
667       context.Check("let x = 4; x", EXPECT_RESULT, Number::New(isolate, 4));
668     }
669     context.Check("let y = 2; x", EXPECT_RESULT,
670                   Number::New(isolate, cond ? 1 : 4));
671   }
672 }
673
674
675 TEST(CrossScriptReferencesHarmony) {
676   v8::Isolate* isolate = CcTest::isolate();
677   HandleScope scope(isolate);
678
679   // Check that simple cross-script global scope access works.
680   const char* decs[] = {
681     "'use strict'; var x = 1; x", "x",
682     "'use strict'; function x() { return 1 }; x()", "x()",
683     "'use strict'; let x = 1; x", "x",
684     "'use strict'; const x = 1; x", "x",
685     NULL
686   };
687
688   for (int i = 0; decs[i] != NULL; i += 2) {
689     SimpleContext context;
690     context.Check(decs[i], EXPECT_RESULT, Number::New(isolate, 1));
691     context.Check(decs[i+1], EXPECT_RESULT, Number::New(isolate, 1));
692   }
693
694   // Check that cross-script global scope access works with late declarations.
695   {
696     SimpleContext context;
697     context.Check("function d0() { return x0 }",  // dynamic lookup
698                   EXPECT_RESULT, Undefined(isolate));
699     context.Check("this.x0 = -1;"
700                   "d0()",
701                   EXPECT_RESULT, Number::New(isolate, -1));
702     context.Check("'use strict';"
703                   "function f0() { let y = 10; return x0 + y }"
704                   "function g0() { let y = 10; return eval('x0 + y') }"
705                   "function h0() { let y = 10; return (1,eval)('x0') + y }"
706                   "x0 + f0() + g0() + h0()",
707                   EXPECT_RESULT, Number::New(isolate, 26));
708
709     context.Check("'use strict';"
710                   "let x1 = 1;"
711                   "function f1() { let y = 10; return x1 + y }"
712                   "function g1() { let y = 10; return eval('x1 + y') }"
713                   "function h1() { let y = 10; return (1,eval)('x1') + y }"
714                   "function i1() { "
715                   "  let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
716                   "}"
717                   "function j1() { let y = 10; return eval('x2 + y') }"
718                   "function k1() { let y = 10; return (1,eval)('x2') + y }"
719                   "function cl() { "
720                   "  let y = 10; "
721                   "  return { "
722                   "    f: function(){ return x1 + y },"
723                   "    g: function(){ return eval('x1 + y') },"
724                   "    h: function(){ return (1,eval)('x1') + y },"
725                   "    i: function(){"
726                   "      return (typeof x2 == 'undefined' ? 0 : 2) + y"
727                   "    },"
728                   "    j: function(){ return eval('x2 + y') },"
729                   "    k: function(){ return (1,eval)('x2') + y },"
730                   "  }"
731                   "}"
732                   "let o = cl();"
733                   "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
734                   EXPECT_RESULT, Number::New(isolate, 36));
735     context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
736                   EXPECT_RESULT, Number::New(isolate, 36));
737     context.Check("o.f() + o.g() + o.h();",
738                   EXPECT_RESULT, Number::New(isolate, 33));
739     context.Check("i1() + o.i();",
740                   EXPECT_RESULT, Number::New(isolate, 20));
741
742     context.Check("'use strict';"
743                   "let x2 = 2;"
744                   "function f2() { let y = 20; return x2 + y }"
745                   "function g2() { let y = 20; return eval('x2 + y') }"
746                   "function h2() { let y = 20; return (1,eval)('x2') + y }"
747                   "function i2() { let y = 20; return x1 + y }"
748                   "function j2() { let y = 20; return eval('x1 + y') }"
749                   "function k2() { let y = 20; return (1,eval)('x1') + y }"
750                   "x2 + eval('x2') + (1,eval)('x2') + f2() + g2() + h2();",
751                   EXPECT_RESULT, Number::New(isolate, 72));
752     context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
753                   EXPECT_RESULT, Number::New(isolate, 36));
754     context.Check("i1() + j1() + k1();",
755                   EXPECT_RESULT, Number::New(isolate, 36));
756     context.Check("i2() + j2() + k2();",
757                   EXPECT_RESULT, Number::New(isolate, 63));
758     context.Check("o.f() + o.g() + o.h();",
759                   EXPECT_RESULT, Number::New(isolate, 33));
760     context.Check("o.i() + o.j() + o.k();",
761                   EXPECT_RESULT, Number::New(isolate, 36));
762     context.Check("i1() + o.i();",
763                   EXPECT_RESULT, Number::New(isolate, 24));
764
765     context.Check("'use strict';"
766                   "let x0 = 100;"
767                   "x0 + eval('x0') + (1,eval)('x0') + "
768                   "    d0() + f0() + g0() + h0();",
769                   EXPECT_RESULT, Number::New(isolate, 730));
770     context.Check("x0 + eval('x0') + (1,eval)('x0') + "
771                   "    d0() + f0() + g0() + h0();",
772                   EXPECT_RESULT, Number::New(isolate, 730));
773     context.Check("delete this.x0;"
774                   "x0 + eval('x0') + (1,eval)('x0') + "
775                   "    d0() + f0() + g0() + h0();",
776                   EXPECT_RESULT, Number::New(isolate, 730));
777     context.Check("this.x1 = 666;"
778                   "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
779                   EXPECT_RESULT, Number::New(isolate, 36));
780     context.Check("delete this.x1;"
781                   "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();",
782                   EXPECT_RESULT, Number::New(isolate, 36));
783   }
784
785   // Check that caching does respect scopes.
786   {
787     SimpleContext context;
788     const char* script1 = "(function(){ return y1 })()";
789     const char* script2 = "(function(){ return y2 })()";
790
791     context.Check(script1, EXPECT_EXCEPTION);
792     context.Check("this.y1 = 1; this.y2 = 2; 0;",
793                   EXPECT_RESULT, Number::New(isolate, 0));
794     context.Check(script1,
795                   EXPECT_RESULT, Number::New(isolate, 1));
796     context.Check("'use strict'; let y1 = 3; 0;",
797                   EXPECT_RESULT, Number::New(isolate, 0));
798     context.Check(script1,
799                   EXPECT_RESULT, Number::New(isolate, 3));
800     context.Check("y1 = 4;",
801                   EXPECT_RESULT, Number::New(isolate, 4));
802     context.Check(script1,
803                   EXPECT_RESULT, Number::New(isolate, 4));
804
805     context.Check(script2,
806                   EXPECT_RESULT, Number::New(isolate, 2));
807     context.Check("'use strict'; let y2 = 5; 0;",
808                   EXPECT_RESULT, Number::New(isolate, 0));
809     context.Check(script1,
810                   EXPECT_RESULT, Number::New(isolate, 4));
811     context.Check(script2,
812                   EXPECT_RESULT, Number::New(isolate, 5));
813   }
814 }
815
816
817 TEST(CrossScriptReferencesHarmonyRegress) {
818   v8::Isolate* isolate = CcTest::isolate();
819   HandleScope scope(isolate);
820   SimpleContext context;
821   context.Check(
822       "'use strict';"
823       "function i1() { "
824       "  let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
825       "}"
826       "i1();"
827       "i1();",
828       EXPECT_RESULT, Number::New(isolate, 10));
829   context.Check(
830       "'use strict';"
831       "let x2 = 2; i1();",
832       EXPECT_RESULT, Number::New(isolate, 12));
833 }
834
835
836 TEST(GlobalLexicalOSR) {
837   i::FLAG_use_strict = true;
838
839   v8::Isolate* isolate = CcTest::isolate();
840   HandleScope scope(isolate);
841   SimpleContext context;
842
843   context.Check("'use strict';"
844                 "let x = 1; x;",
845                 EXPECT_RESULT, Number::New(isolate, 1));
846   context.Check("'use strict';"
847                 "let y = 2*x;"
848                 "++x;"
849                 "let z = 0;"
850                 "const limit = 100000;"
851                 "for (var i = 0; i < limit; ++i) {"
852                 "  z += x + y;"
853                 "}"
854                 "z;",
855                 EXPECT_RESULT, Number::New(isolate, 400000));
856 }
857
858
859 TEST(CrossScriptConflicts) {
860   i::FLAG_use_strict = true;
861
862   HandleScope scope(CcTest::isolate());
863
864   const char* firsts[] = {
865     "var x = 1; x",
866     "function x() { return 1 }; x()",
867     "let x = 1; x",
868     "const x = 1; x",
869     NULL
870   };
871   const char* seconds[] = {
872     "var x = 2; x",
873     "function x() { return 2 }; x()",
874     "let x = 2; x",
875     "const x = 2; x",
876     NULL
877   };
878
879   for (int i = 0; firsts[i] != NULL; ++i) {
880     for (int j = 0; seconds[j] != NULL; ++j) {
881       SimpleContext context;
882       context.Check(firsts[i], EXPECT_RESULT,
883                     Number::New(CcTest::isolate(), 1));
884       bool success_case = i < 2 && j < 2;
885       Local<Value> success_result;
886       if (success_case) success_result = Number::New(CcTest::isolate(), 2);
887
888       context.Check(seconds[j], success_case ? EXPECT_RESULT : EXPECT_EXCEPTION,
889                     success_result);
890     }
891   }
892 }
893
894
895 TEST(CrossScriptDynamicLookup) {
896   HandleScope handle_scope(CcTest::isolate());
897
898   {
899     SimpleContext context;
900     Local<String> undefined_string = String::NewFromUtf8(
901         CcTest::isolate(), "undefined", String::kInternalizedString);
902     Local<String> number_string = String::NewFromUtf8(
903         CcTest::isolate(), "number", String::kInternalizedString);
904
905     context.Check(
906         "function f(o) { with(o) { return x; } }"
907         "function g(o) { with(o) { x = 15; } }"
908         "function h(o) { with(o) { return typeof x; } }",
909         EXPECT_RESULT, Undefined(CcTest::isolate()));
910     context.Check("h({})", EXPECT_RESULT, undefined_string);
911     context.Check(
912         "'use strict';"
913         "let x = 1;"
914         "f({})",
915         EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
916     context.Check(
917         "'use strict';"
918         "g({});0",
919         EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
920     context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
921     context.Check("h({})", EXPECT_RESULT, number_string);
922   }
923 }
924
925
926 TEST(CrossScriptGlobal) {
927   HandleScope handle_scope(CcTest::isolate());
928   {
929     SimpleContext context;
930
931     context.Check(
932         "var global = this;"
933         "global.x = 255;"
934         "x",
935         EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
936     context.Check(
937         "'use strict';"
938         "let x = 1;"
939         "global.x",
940         EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
941     context.Check("global.x = 15; x", EXPECT_RESULT,
942                   Number::New(CcTest::isolate(), 1));
943     context.Check("x = 221; global.x", EXPECT_RESULT,
944                   Number::New(CcTest::isolate(), 15));
945     context.Check(
946         "z = 15;"
947         "function f() { return z; };"
948         "for (var k = 0; k < 3; k++) { f(); }"
949         "f()",
950         EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
951     context.Check(
952         "'use strict';"
953         "let z = 5; f()",
954         EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
955     context.Check(
956         "function f() { konst = 10; return konst; };"
957         "f()",
958         EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
959     context.Check(
960         "'use strict';"
961         "const konst = 255;"
962         "f()",
963         EXPECT_EXCEPTION);
964   }
965 }
966
967
968 TEST(CrossScriptStaticLookupUndeclared) {
969   HandleScope handle_scope(CcTest::isolate());
970
971   {
972     SimpleContext context;
973     Local<String> undefined_string = String::NewFromUtf8(
974         CcTest::isolate(), "undefined", String::kInternalizedString);
975     Local<String> number_string = String::NewFromUtf8(
976         CcTest::isolate(), "number", String::kInternalizedString);
977
978     context.Check(
979         "function f(o) { return x; }"
980         "function g(v) { x = v; }"
981         "function h(o) { return typeof x; }",
982         EXPECT_RESULT, Undefined(CcTest::isolate()));
983     context.Check("h({})", EXPECT_RESULT, undefined_string);
984     context.Check(
985         "'use strict';"
986         "let x = 1;"
987         "f({})",
988         EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
989     context.Check(
990         "'use strict';"
991         "g(15);x",
992         EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
993     context.Check("h({})", EXPECT_RESULT, number_string);
994     context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
995     context.Check("h({})", EXPECT_RESULT, number_string);
996   }
997 }
998
999
1000 TEST(CrossScriptLoadICs) {
1001   i::FLAG_allow_natives_syntax = true;
1002
1003   HandleScope handle_scope(CcTest::isolate());
1004
1005   {
1006     SimpleContext context;
1007     context.Check(
1008         "x = 15;"
1009         "function f() { return x; }"
1010         "function g() { return x; }"
1011         "f()",
1012         EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
1013     context.Check(
1014         "'use strict';"
1015         "let x = 5;"
1016         "f()",
1017         EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1018     for (int k = 0; k < 3; k++) {
1019       context.Check("g()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1020     }
1021     for (int k = 0; k < 3; k++) {
1022       context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1023     }
1024     context.Check("%OptimizeFunctionOnNextCall(g); g()", EXPECT_RESULT,
1025                   Number::New(CcTest::isolate(), 5));
1026     context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
1027                   Number::New(CcTest::isolate(), 5));
1028   }
1029   {
1030     SimpleContext context;
1031     context.Check(
1032         "x = 15;"
1033         "function f() { return x; }"
1034         "f()",
1035         EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
1036     for (int k = 0; k < 3; k++) {
1037       context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
1038     }
1039     context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
1040                   Number::New(CcTest::isolate(), 15));
1041     context.Check(
1042         "'use strict';"
1043         "let x = 5;"
1044         "f()",
1045         EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1046     for (int k = 0; k < 3; k++) {
1047       context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
1048     }
1049     context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
1050                   Number::New(CcTest::isolate(), 5));
1051   }
1052 }
1053
1054
1055 TEST(CrossScriptStoreICs) {
1056   i::FLAG_allow_natives_syntax = true;
1057
1058   HandleScope handle_scope(CcTest::isolate());
1059
1060   {
1061     SimpleContext context;
1062     context.Check(
1063         "var global = this;"
1064         "x = 15;"
1065         "function f(v) { x = v; }"
1066         "function g(v) { x = v; }"
1067         "f(10); x",
1068         EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
1069     context.Check(
1070         "'use strict';"
1071         "let x = 5;"
1072         "f(7); x",
1073         EXPECT_RESULT, Number::New(CcTest::isolate(), 7));
1074     context.Check("global.x", EXPECT_RESULT,
1075                   Number::New(CcTest::isolate(), 10));
1076     for (int k = 0; k < 3; k++) {
1077       context.Check("g(31); x", EXPECT_RESULT,
1078                     Number::New(CcTest::isolate(), 31));
1079     }
1080     context.Check("global.x", EXPECT_RESULT,
1081                   Number::New(CcTest::isolate(), 10));
1082     for (int k = 0; k < 3; k++) {
1083       context.Check("f(32); x", EXPECT_RESULT,
1084                     Number::New(CcTest::isolate(), 32));
1085     }
1086     context.Check("global.x", EXPECT_RESULT,
1087                   Number::New(CcTest::isolate(), 10));
1088     context.Check("%OptimizeFunctionOnNextCall(g); g(18); x", EXPECT_RESULT,
1089                   Number::New(CcTest::isolate(), 18));
1090     context.Check("global.x", EXPECT_RESULT,
1091                   Number::New(CcTest::isolate(), 10));
1092     context.Check("%OptimizeFunctionOnNextCall(f); f(33); x", EXPECT_RESULT,
1093                   Number::New(CcTest::isolate(), 33));
1094     context.Check("global.x", EXPECT_RESULT,
1095                   Number::New(CcTest::isolate(), 10));
1096   }
1097   {
1098     SimpleContext context;
1099     context.Check(
1100         "var global = this;"
1101         "x = 15;"
1102         "function f(v) { x = v; }"
1103         "f(10); x",
1104         EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
1105     for (int k = 0; k < 3; k++) {
1106       context.Check("f(18); x", EXPECT_RESULT,
1107                     Number::New(CcTest::isolate(), 18));
1108     }
1109     context.Check("%OptimizeFunctionOnNextCall(f); f(20); x", EXPECT_RESULT,
1110                   Number::New(CcTest::isolate(), 20));
1111     context.Check(
1112         "'use strict';"
1113         "let x = 5;"
1114         "f(8); x",
1115         EXPECT_RESULT, Number::New(CcTest::isolate(), 8));
1116     context.Check("global.x", EXPECT_RESULT,
1117                   Number::New(CcTest::isolate(), 20));
1118     for (int k = 0; k < 3; k++) {
1119       context.Check("f(13); x", EXPECT_RESULT,
1120                     Number::New(CcTest::isolate(), 13));
1121     }
1122     context.Check("global.x", EXPECT_RESULT,
1123                   Number::New(CcTest::isolate(), 20));
1124     context.Check("%OptimizeFunctionOnNextCall(f); f(41); x", EXPECT_RESULT,
1125                   Number::New(CcTest::isolate(), 41));
1126     context.Check("global.x", EXPECT_RESULT,
1127                   Number::New(CcTest::isolate(), 20));
1128   }
1129 }
1130
1131
1132 TEST(CrossScriptAssignmentToConst) {
1133   i::FLAG_allow_natives_syntax = true;
1134
1135   HandleScope handle_scope(CcTest::isolate());
1136
1137   {
1138     SimpleContext context;
1139
1140     context.Check("function f() { x = 27; }", EXPECT_RESULT,
1141                   Undefined(CcTest::isolate()));
1142     context.Check("'use strict';const x = 1; x", EXPECT_RESULT,
1143                   Number::New(CcTest::isolate(), 1));
1144     context.Check("f();", EXPECT_EXCEPTION);
1145     context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1146     context.Check("f();", EXPECT_EXCEPTION);
1147     context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1148     context.Check("%OptimizeFunctionOnNextCall(f);f();", EXPECT_EXCEPTION);
1149     context.Check("x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1150   }
1151 }
1152
1153
1154 TEST(Regress425510) {
1155   i::FLAG_allow_natives_syntax = true;
1156
1157   HandleScope handle_scope(CcTest::isolate());
1158
1159   {
1160     SimpleContext context;
1161
1162     context.Check("'use strict'; o; const o = 10", EXPECT_EXCEPTION);
1163
1164     for (int i = 0; i < 100; i++) {
1165       context.Check("o.prototype", EXPECT_EXCEPTION);
1166     }
1167   }
1168 }
1169
1170
1171 TEST(Regress3941) {
1172   i::FLAG_allow_natives_syntax = true;
1173
1174   HandleScope handle_scope(CcTest::isolate());
1175
1176   {
1177     SimpleContext context;
1178     context.Check("function f() { x = 1; }", EXPECT_RESULT,
1179                   Undefined(CcTest::isolate()));
1180     context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1181   }
1182
1183
1184   {
1185     // Train ICs.
1186     SimpleContext context;
1187     context.Check("function f() { x = 1; }", EXPECT_RESULT,
1188                   Undefined(CcTest::isolate()));
1189     for (int i = 0; i < 4; i++) {
1190       context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1191     }
1192     context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1193   }
1194
1195
1196   {
1197     // Optimize.
1198     SimpleContext context;
1199     context.Check("function f() { x = 1; }", EXPECT_RESULT,
1200                   Undefined(CcTest::isolate()));
1201     for (int i = 0; i < 4; i++) {
1202       context.Check("f(); x", EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
1203     }
1204     context.Check("%OptimizeFunctionOnNextCall(f); f(); x", EXPECT_RESULT,
1205                   Number::New(CcTest::isolate(), 1));
1206
1207     context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1208   }
1209 }
1210
1211
1212 TEST(Regress3941_Reads) {
1213   i::FLAG_allow_natives_syntax = true;
1214
1215   HandleScope handle_scope(CcTest::isolate());
1216
1217   {
1218     SimpleContext context;
1219     context.Check("function f() { return x; }", EXPECT_RESULT,
1220                   Undefined(CcTest::isolate()));
1221     context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1222   }
1223
1224
1225   {
1226     // Train ICs.
1227     SimpleContext context;
1228     context.Check("function f() { return x; }", EXPECT_RESULT,
1229                   Undefined(CcTest::isolate()));
1230     for (int i = 0; i < 4; i++) {
1231       context.Check("f()", EXPECT_EXCEPTION);
1232     }
1233     context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1234   }
1235
1236
1237   {
1238     // Optimize.
1239     SimpleContext context;
1240     context.Check("function f() { return x; }", EXPECT_RESULT,
1241                   Undefined(CcTest::isolate()));
1242     for (int i = 0; i < 4; i++) {
1243       context.Check("f()", EXPECT_EXCEPTION);
1244     }
1245     context.Check("%OptimizeFunctionOnNextCall(f);", EXPECT_RESULT,
1246                   Undefined(CcTest::isolate()));
1247
1248     context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1249   }
1250 }