1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "src/v8.h"
29
30 #include "test/cctest/cctest.h"
31
32 namespace i = v8::internal;
33
34 namespace {
35 class HarmonyIsolate {
36 public:
HarmonyIsolate()37 HarmonyIsolate() {
38 v8::Isolate::CreateParams create_params;
39 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
40 isolate_ = v8::Isolate::New(create_params);
41 isolate_->Enter();
42 }
43
~HarmonyIsolate()44 ~HarmonyIsolate() {
45 isolate_->Exit();
46 isolate_->Dispose();
47 }
48
GetIsolate() const49 v8::Isolate* GetIsolate() const { return isolate_; }
50
51 private:
52 v8::Isolate* isolate_;
53 };
54 } // namespace
55
56
TEST(MicrotaskDeliverySimple)57 TEST(MicrotaskDeliverySimple) {
58 i::FLAG_harmony_object_observe = true;
59 HarmonyIsolate isolate;
60 v8::HandleScope scope(isolate.GetIsolate());
61 LocalContext context(isolate.GetIsolate());
62 CompileRun(
63 "var ordering = [];"
64 "var resolver = {};"
65 "function handler(resolve) { resolver.resolve = resolve; }"
66 "var obj = {};"
67 "var observeOrders = [1, 4];"
68 "function observer() {"
69 "ordering.push(observeOrders.shift());"
70 "resolver.resolve();"
71 "}"
72 "var p = new Promise(handler);"
73 "p.then(function() {"
74 "ordering.push(2);"
75 "}).then(function() {"
76 "ordering.push(3);"
77 "obj.id++;"
78 "return new Promise(handler);"
79 "}).then(function() {"
80 "ordering.push(5);"
81 "}).then(function() {"
82 "ordering.push(6);"
83 "});"
84 "Object.observe(obj, observer);"
85 "obj.id = 1;");
86 CHECK_EQ(
87 6, CompileRun("ordering.length")->Int32Value(context.local()).FromJust());
88 CHECK_EQ(1,
89 CompileRun("ordering[0]")->Int32Value(context.local()).FromJust());
90 CHECK_EQ(2,
91 CompileRun("ordering[1]")->Int32Value(context.local()).FromJust());
92 CHECK_EQ(3,
93 CompileRun("ordering[2]")->Int32Value(context.local()).FromJust());
94 CHECK_EQ(4,
95 CompileRun("ordering[3]")->Int32Value(context.local()).FromJust());
96 CHECK_EQ(5,
97 CompileRun("ordering[4]")->Int32Value(context.local()).FromJust());
98 CHECK_EQ(6,
99 CompileRun("ordering[5]")->Int32Value(context.local()).FromJust());
100 }
101
102
TEST(MicrotaskPerIsolateState)103 TEST(MicrotaskPerIsolateState) {
104 i::FLAG_harmony_object_observe = true;
105 HarmonyIsolate isolate;
106 v8::HandleScope scope(isolate.GetIsolate());
107 LocalContext context1(isolate.GetIsolate());
108 isolate.GetIsolate()->SetAutorunMicrotasks(false);
109 CompileRun(
110 "var obj = { calls: 0 };");
111 v8::Local<v8::Value> obj = CompileRun("obj");
112 {
113 LocalContext context2(isolate.GetIsolate());
114 context2->Global()
115 ->Set(context2.local(),
116 v8::String::NewFromUtf8(isolate.GetIsolate(), "obj",
117 v8::NewStringType::kNormal)
118 .ToLocalChecked(),
119 obj)
120 .FromJust();
121 CompileRun(
122 "var resolver = {};"
123 "new Promise(function(resolve) {"
124 "resolver.resolve = resolve;"
125 "}).then(function() {"
126 "obj.calls++;"
127 "});"
128 "(function() {"
129 "resolver.resolve();"
130 "})();");
131 }
132 {
133 LocalContext context3(isolate.GetIsolate());
134 context3->Global()
135 ->Set(context3.local(),
136 v8::String::NewFromUtf8(isolate.GetIsolate(), "obj",
137 v8::NewStringType::kNormal)
138 .ToLocalChecked(),
139 obj)
140 .FromJust();
141 CompileRun(
142 "var foo = { id: 1 };"
143 "Object.observe(foo, function() {"
144 "obj.calls++;"
145 "});"
146 "foo.id++;");
147 }
148 {
149 LocalContext context4(isolate.GetIsolate());
150 context4->Global()
151 ->Set(context4.local(),
152 v8::String::NewFromUtf8(isolate.GetIsolate(), "obj",
153 v8::NewStringType::kNormal)
154 .ToLocalChecked(),
155 obj)
156 .FromJust();
157 isolate.GetIsolate()->RunMicrotasks();
158 CHECK_EQ(2,
159 CompileRun("obj.calls")->Int32Value(context4.local()).FromJust());
160 }
161 }
162