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