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
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.
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.
32 #include "src/heap/heap.h"
33 #include "test/cctest/cctest.h"
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
49 class DeclarationContext {
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_);
63 void Check(const char* source,
64 int get, int set, int has,
65 Expectations expectations,
66 v8::Handle<Value> value = Local<Value>());
68 int get_count() const { return get_count_; }
69 int set_count() const { return set_count_; }
70 int query_count() const { return query_count_; }
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);
77 void InitializeIfNeeded();
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) {}
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();
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);
98 v8::Isolate* isolate() const { return CcTest::isolate(); }
101 bool is_initialized_;
102 Persistent<Context> context_;
108 static DeclarationContext* GetInstance(Local<Value> data);
112 DeclarationContext::DeclarationContext()
113 : is_initialized_(false), get_count_(0), set_count_(0), query_count_(0) {
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,
128 function->InstanceTemplate(),
130 context_.Reset(isolate, context);
132 is_initialized_ = true;
133 PostInitializeContext(context);
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
144 CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
145 HandleScope scope(CcTest::isolate());
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());
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));
165 CHECK(expectations == EXPECT_EXCEPTION);
166 CHECK(catcher.HasCaught());
167 if (!value.IsEmpty()) {
168 CHECK(value->Equals(catcher.Exception()));
171 // Clean slate for the next test.
172 CcTest::heap()->CollectAllAvailableGarbage();
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));
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));
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));
201 DeclarationContext* DeclarationContext::GetInstance(Local<Value> data) {
202 void* value = Local<External>::Cast(data)->Value();
203 return static_cast<DeclarationContext*>(value);
207 v8::Handle<Value> DeclarationContext::Get(Local<Name> key) {
208 return v8::Handle<Value>();
212 v8::Handle<Value> DeclarationContext::Set(Local<Name> key, Local<Value> value) {
213 return v8::Handle<Value>();
217 v8::Handle<Integer> DeclarationContext::Query(Local<Name> key) {
218 return v8::Handle<Integer>();
222 // Test global declaration of a property the interceptor doesn't know
223 // about and doesn't handle.
225 HandleScope scope(CcTest::isolate());
226 v8::V8::Initialize();
228 { DeclarationContext context;
229 context.Check("var x; x",
231 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
234 { DeclarationContext context;
235 context.Check("var x = 0; x",
238 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
241 { DeclarationContext context;
242 context.Check("function x() { }; x",
249 { DeclarationContext context;
250 context.Check("const x; x",
252 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
255 { DeclarationContext context;
256 context.Check("const x = 0; x",
260 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
265 class AbsentPropertyContext: public DeclarationContext {
267 virtual v8::Handle<Integer> Query(Local<Name> key) {
268 return v8::Handle<Integer>();
274 v8::Isolate* isolate = CcTest::isolate();
275 v8::V8::Initialize();
276 HandleScope scope(isolate);
278 { AbsentPropertyContext context;
279 context.Check("var x; x",
281 0, 0, EXPECT_RESULT, Undefined(isolate));
284 { AbsentPropertyContext context;
285 context.Check("var x = 0; x",
288 0, EXPECT_RESULT, Number::New(isolate, 0));
291 { AbsentPropertyContext context;
292 context.Check("function x() { }; x",
299 { AbsentPropertyContext context;
300 context.Check("const x; x",
302 0, 0, EXPECT_RESULT, Undefined(isolate));
305 { AbsentPropertyContext context;
306 context.Check("const x = 0; x",
308 0, 0, EXPECT_RESULT, Number::New(isolate, 0));
311 { AbsentPropertyContext context;
312 context.Check("if (false) { var x = 0 }; x",
314 0, 0, EXPECT_RESULT, Undefined(isolate));
320 class AppearingPropertyContext: public DeclarationContext {
324 INITIALIZE_IF_ASSIGN,
328 AppearingPropertyContext() : state_(DECLARE) { }
331 virtual v8::Handle<Integer> Query(Local<Name> key) {
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.
342 return Integer::New(isolate(), v8::None);
344 CHECK(state_ == UNKNOWN);
347 // Do the lookup in the object.
348 return v8::Handle<Integer>();
357 v8::V8::Initialize();
358 HandleScope scope(CcTest::isolate());
360 { AppearingPropertyContext context;
361 context.Check("var x; x",
363 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
366 { AppearingPropertyContext context;
367 context.Check("var x = 0; x",
370 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
373 { AppearingPropertyContext context;
374 context.Check("function x() { }; x",
381 { AppearingPropertyContext context;
382 context.Check("const x; x",
384 0, 0, EXPECT_RESULT, Undefined(CcTest::isolate()));
387 { AppearingPropertyContext context;
388 context.Check("const x = 0; x",
390 0, 0, EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
396 class ExistsInPrototypeContext: public DeclarationContext {
398 ExistsInPrototypeContext() { InitializeIfNeeded(); }
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);
405 // Use the prototype as the holder for the interceptors.
406 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
407 return function->PrototypeTemplate();
412 TEST(ExistsInPrototype) {
413 HandleScope scope(CcTest::isolate());
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));
422 { ExistsInPrototypeContext context;
423 context.Check("var x; x",
427 EXPECT_RESULT, Undefined(CcTest::isolate()));
430 { ExistsInPrototypeContext context;
431 context.Check("var x = 0; x",
435 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
438 { ExistsInPrototypeContext context;
439 context.Check("const x; x",
443 EXPECT_RESULT, Undefined(CcTest::isolate()));
446 { ExistsInPrototypeContext context;
447 context.Check("const x = 0; x",
451 EXPECT_RESULT, Number::New(CcTest::isolate(), 0));
457 class AbsentInPrototypeContext: public DeclarationContext {
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>();
464 // Use the prototype as the holder for the interceptors.
465 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
466 return function->PrototypeTemplate();
471 TEST(AbsentInPrototype) {
472 v8::V8::Initialize();
473 HandleScope scope(CcTest::isolate());
475 { AbsentInPrototypeContext context;
476 context.Check("if (false) { var x = 0; }; x",
480 EXPECT_RESULT, Undefined(CcTest::isolate()));
486 class ExistsInHiddenPrototypeContext: public DeclarationContext {
488 ExistsInHiddenPrototypeContext() {
489 hidden_proto_ = FunctionTemplate::New(CcTest::isolate());
490 hidden_proto_->SetHiddenPrototype(true);
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);
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);
508 // Use the hidden prototype as the holder for the interceptors.
509 virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
510 return hidden_proto_->InstanceTemplate();
514 Local<FunctionTemplate> hidden_proto_;
518 TEST(ExistsInHiddenPrototype) {
519 HandleScope scope(CcTest::isolate());
521 { ExistsInHiddenPrototypeContext context;
522 context.Check("var x; x", 0, 0, 0, EXPECT_RESULT,
523 Undefined(CcTest::isolate()));
526 { ExistsInHiddenPrototypeContext context;
527 context.Check("var x = 0; x", 0, 0, 0, EXPECT_RESULT,
528 Number::New(CcTest::isolate(), 0));
531 { ExistsInHiddenPrototypeContext context;
532 context.Check("function x() { }; x",
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()));
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));
554 class SimpleContext {
557 : handle_scope_(CcTest::isolate()),
558 context_(Context::New(CcTest::isolate())) {
566 void Check(const char* source,
567 Expectations expectations,
568 v8::Handle<Value> value = Local<Value>()) {
569 HandleScope scope(context_->GetIsolate());
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());
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));
586 CHECK(expectations == EXPECT_EXCEPTION);
587 CHECK(catcher.HasCaught());
588 if (!value.IsEmpty()) {
589 CHECK(value->Equals(catcher.Exception()));
595 HandleScope handle_scope_;
596 Local<Context> context_;
600 TEST(CrossScriptReferences) {
601 v8::Isolate* isolate = CcTest::isolate();
602 HandleScope scope(isolate);
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));
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",
639 TEST(CrossScriptReferences_Simple) {
640 i::FLAG_use_strict = true;
642 v8::Isolate* isolate = CcTest::isolate();
643 HandleScope scope(isolate);
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);
653 TEST(CrossScriptReferences_Simple2) {
654 i::FLAG_use_strict = true;
656 v8::Isolate* isolate = CcTest::isolate();
657 HandleScope scope(isolate);
659 for (int k = 0; k < 100; k++) {
660 SimpleContext context;
661 bool cond = (k % 2) == 0;
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));
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));
669 context.Check("let y = 2; x", EXPECT_RESULT,
670 Number::New(isolate, cond ? 1 : 4));
675 TEST(CrossScriptReferencesHarmony) {
676 v8::Isolate* isolate = CcTest::isolate();
677 HandleScope scope(isolate);
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",
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));
694 // Check that cross-script global scope access works with late declarations.
696 SimpleContext context;
697 context.Check("function d0() { return x0 }", // dynamic lookup
698 EXPECT_RESULT, Undefined(isolate));
699 context.Check("this.x0 = -1;"
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));
709 context.Check("'use strict';"
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 }"
715 " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
717 "function j1() { let y = 10; return eval('x2 + y') }"
718 "function k1() { let y = 10; return (1,eval)('x2') + y }"
722 " f: function(){ return x1 + y },"
723 " g: function(){ return eval('x1 + y') },"
724 " h: function(){ return (1,eval)('x1') + y },"
726 " return (typeof x2 == 'undefined' ? 0 : 2) + y"
728 " j: function(){ return eval('x2 + y') },"
729 " k: function(){ return (1,eval)('x2') + y },"
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));
742 context.Check("'use strict';"
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));
765 context.Check("'use strict';"
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));
785 // Check that caching does respect scopes.
787 SimpleContext context;
788 const char* script1 = "(function(){ return y1 })()";
789 const char* script2 = "(function(){ return y2 })()";
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));
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));
817 TEST(CrossScriptReferencesHarmonyRegress) {
818 v8::Isolate* isolate = CcTest::isolate();
819 HandleScope scope(isolate);
820 SimpleContext context;
824 " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y"
828 EXPECT_RESULT, Number::New(isolate, 10));
832 EXPECT_RESULT, Number::New(isolate, 12));
836 TEST(GlobalLexicalOSR) {
837 i::FLAG_use_strict = true;
839 v8::Isolate* isolate = CcTest::isolate();
840 HandleScope scope(isolate);
841 SimpleContext context;
843 context.Check("'use strict';"
845 EXPECT_RESULT, Number::New(isolate, 1));
846 context.Check("'use strict';"
850 "const limit = 100000;"
851 "for (var i = 0; i < limit; ++i) {"
855 EXPECT_RESULT, Number::New(isolate, 400000));
859 TEST(CrossScriptConflicts) {
860 i::FLAG_use_strict = true;
862 HandleScope scope(CcTest::isolate());
864 const char* firsts[] = {
866 "function x() { return 1 }; x()",
871 const char* seconds[] = {
873 "function x() { return 2 }; x()",
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);
888 context.Check(seconds[j], success_case ? EXPECT_RESULT : EXPECT_EXCEPTION,
895 TEST(CrossScriptDynamicLookup) {
896 HandleScope handle_scope(CcTest::isolate());
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);
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);
915 EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
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);
926 TEST(CrossScriptGlobal) {
927 HandleScope handle_scope(CcTest::isolate());
929 SimpleContext context;
935 EXPECT_RESULT, Number::New(CcTest::isolate(), 255));
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));
947 "function f() { return z; };"
948 "for (var k = 0; k < 3; k++) { f(); }"
950 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
954 EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
956 "function f() { konst = 10; return konst; };"
958 EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
968 TEST(CrossScriptStaticLookupUndeclared) {
969 HandleScope handle_scope(CcTest::isolate());
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);
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);
988 EXPECT_RESULT, Number::New(CcTest::isolate(), 1));
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);
1000 TEST(CrossScriptLoadICs) {
1001 i::FLAG_allow_natives_syntax = true;
1003 HandleScope handle_scope(CcTest::isolate());
1006 SimpleContext context;
1009 "function f() { return x; }"
1010 "function g() { return x; }"
1012 EXPECT_RESULT, Number::New(CcTest::isolate(), 15));
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));
1021 for (int k = 0; k < 3; k++) {
1022 context.Check("f()", EXPECT_RESULT, Number::New(CcTest::isolate(), 5));
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));
1030 SimpleContext context;
1033 "function f() { return x; }"
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));
1039 context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
1040 Number::New(CcTest::isolate(), 15));
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));
1049 context.Check("%OptimizeFunctionOnNextCall(f); f()", EXPECT_RESULT,
1050 Number::New(CcTest::isolate(), 5));
1055 TEST(CrossScriptStoreICs) {
1056 i::FLAG_allow_natives_syntax = true;
1058 HandleScope handle_scope(CcTest::isolate());
1061 SimpleContext context;
1063 "var global = this;"
1065 "function f(v) { x = v; }"
1066 "function g(v) { x = v; }"
1068 EXPECT_RESULT, Number::New(CcTest::isolate(), 10));
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));
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));
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));
1098 SimpleContext context;
1100 "var global = this;"
1102 "function f(v) { x = v; }"
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));
1109 context.Check("%OptimizeFunctionOnNextCall(f); f(20); x", EXPECT_RESULT,
1110 Number::New(CcTest::isolate(), 20));
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));
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));
1132 TEST(CrossScriptAssignmentToConst) {
1133 i::FLAG_allow_natives_syntax = true;
1135 HandleScope handle_scope(CcTest::isolate());
1138 SimpleContext context;
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));
1154 TEST(Regress425510) {
1155 i::FLAG_allow_natives_syntax = true;
1157 HandleScope handle_scope(CcTest::isolate());
1160 SimpleContext context;
1162 context.Check("'use strict'; o; const o = 10", EXPECT_EXCEPTION);
1164 for (int i = 0; i < 100; i++) {
1165 context.Check("o.prototype", EXPECT_EXCEPTION);
1172 i::FLAG_allow_natives_syntax = true;
1174 HandleScope handle_scope(CcTest::isolate());
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);
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));
1192 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
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));
1204 context.Check("%OptimizeFunctionOnNextCall(f); f(); x", EXPECT_RESULT,
1205 Number::New(CcTest::isolate(), 1));
1207 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
1212 TEST(Regress3941_Reads) {
1213 i::FLAG_allow_natives_syntax = true;
1215 HandleScope handle_scope(CcTest::isolate());
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);
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);
1233 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);
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);
1245 context.Check("%OptimizeFunctionOnNextCall(f);", EXPECT_RESULT,
1246 Undefined(CcTest::isolate()));
1248 context.Check("'use strict'; f(); let x = 2; x", EXPECT_EXCEPTION);