| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 // TODO(mythria): Remove this define after this flag is turned on globally |
| 29 #define V8_IMMINENT_DEPRECATION_WARNINGS |
| 30 |
| 28 #include "src/v8.h" | 31 #include "src/v8.h" |
| 29 | 32 |
| 30 #include "test/cctest/cctest.h" | 33 #include "test/cctest/cctest.h" |
| 31 | 34 |
| 32 using namespace v8; | 35 using namespace v8; |
| 33 namespace i = v8::internal; | 36 namespace i = v8::internal; |
| 34 | 37 |
| 38 inline int32_t ToInt32(v8::Local<v8::Value> value) { |
| 39 return value->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext()) |
| 40 .FromJust(); |
| 41 } |
| 42 |
| 35 | 43 |
| 36 TEST(PerIsolateState) { | 44 TEST(PerIsolateState) { |
| 37 HandleScope scope(CcTest::isolate()); | 45 HandleScope scope(CcTest::isolate()); |
| 38 LocalContext context1(CcTest::isolate()); | 46 LocalContext context1(CcTest::isolate()); |
| 39 | 47 |
| 40 Local<Value> foo = v8_str("foo"); | 48 Local<Value> foo = v8_str("foo"); |
| 41 context1->SetSecurityToken(foo); | 49 context1->SetSecurityToken(foo); |
| 42 | 50 |
| 43 CompileRun( | 51 CompileRun( |
| 44 "var count = 0;" | 52 "var count = 0;" |
| 45 "var calls = 0;" | 53 "var calls = 0;" |
| 46 "var observer = function(records) { count = records.length; calls++ };" | 54 "var observer = function(records) { count = records.length; calls++ };" |
| 47 "var obj = {};" | 55 "var obj = {};" |
| 48 "Object.observe(obj, observer);"); | 56 "Object.observe(obj, observer);"); |
| 49 Handle<Value> observer = CompileRun("observer"); | 57 Local<Value> observer = CompileRun("observer"); |
| 50 Handle<Value> obj = CompileRun("obj"); | 58 Local<Value> obj = CompileRun("obj"); |
| 51 Handle<Value> notify_fun1 = CompileRun( | 59 Local<Value> notify_fun1 = CompileRun("(function() { obj.foo = 'bar'; })"); |
| 52 "(function() { obj.foo = 'bar'; })"); | 60 Local<Value> notify_fun2; |
| 53 Handle<Value> notify_fun2; | |
| 54 { | 61 { |
| 55 LocalContext context2(CcTest::isolate()); | 62 LocalContext context2(CcTest::isolate()); |
| 56 context2->SetSecurityToken(foo); | 63 context2->SetSecurityToken(foo); |
| 57 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 64 context2->Global() |
| 58 obj); | 65 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 66 obj) |
| 67 .FromJust(); |
| 59 notify_fun2 = CompileRun( | 68 notify_fun2 = CompileRun( |
| 60 "(function() { obj.foo = 'baz'; })"); | 69 "(function() { obj.foo = 'baz'; })"); |
| 61 } | 70 } |
| 62 Handle<Value> notify_fun3; | 71 Local<Value> notify_fun3; |
| 63 { | 72 { |
| 64 LocalContext context3(CcTest::isolate()); | 73 LocalContext context3(CcTest::isolate()); |
| 65 context3->SetSecurityToken(foo); | 74 context3->SetSecurityToken(foo); |
| 66 context3->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 75 context3->Global() |
| 67 obj); | 76 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 68 notify_fun3 = CompileRun( | 77 obj) |
| 69 "(function() { obj.foo = 'bat'; })"); | 78 .FromJust(); |
| 79 notify_fun3 = CompileRun("(function() { obj.foo = 'bat'; })"); |
| 70 } | 80 } |
| 71 { | 81 { |
| 72 LocalContext context4(CcTest::isolate()); | 82 LocalContext context4(CcTest::isolate()); |
| 73 context4->SetSecurityToken(foo); | 83 context4->SetSecurityToken(foo); |
| 74 context4->Global()->Set( | 84 context4->Global() |
| 75 String::NewFromUtf8(CcTest::isolate(), "observer"), observer); | 85 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 76 context4->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "fun1"), | 86 v8_str("observer"), observer) |
| 77 notify_fun1); | 87 .FromJust(); |
| 78 context4->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "fun2"), | 88 context4->Global() |
| 79 notify_fun2); | 89 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("fun1"), |
| 80 context4->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "fun3"), | 90 notify_fun1) |
| 81 notify_fun3); | 91 .FromJust(); |
| 92 context4->Global() |
| 93 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("fun2"), |
| 94 notify_fun2) |
| 95 .FromJust(); |
| 96 context4->Global() |
| 97 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("fun3"), |
| 98 notify_fun3) |
| 99 .FromJust(); |
| 82 CompileRun("fun1(); fun2(); fun3(); Object.deliverChangeRecords(observer)"); | 100 CompileRun("fun1(); fun2(); fun3(); Object.deliverChangeRecords(observer)"); |
| 83 } | 101 } |
| 84 CHECK_EQ(1, CompileRun("calls")->Int32Value()); | 102 CHECK_EQ(1, ToInt32(CompileRun("calls"))); |
| 85 CHECK_EQ(3, CompileRun("count")->Int32Value()); | 103 CHECK_EQ(3, ToInt32(CompileRun("count"))); |
| 86 } | 104 } |
| 87 | 105 |
| 88 | 106 |
| 89 TEST(EndOfMicrotaskDelivery) { | 107 TEST(EndOfMicrotaskDelivery) { |
| 90 HandleScope scope(CcTest::isolate()); | 108 HandleScope scope(CcTest::isolate()); |
| 91 LocalContext context(CcTest::isolate()); | 109 LocalContext context(CcTest::isolate()); |
| 92 CompileRun( | 110 CompileRun( |
| 93 "var obj = {};" | 111 "var obj = {};" |
| 94 "var count = 0;" | 112 "var count = 0;" |
| 95 "var observer = function(records) { count = records.length };" | 113 "var observer = function(records) { count = records.length };" |
| 96 "Object.observe(obj, observer);" | 114 "Object.observe(obj, observer);" |
| 97 "obj.foo = 'bar';"); | 115 "obj.foo = 'bar';"); |
| 98 CHECK_EQ(1, CompileRun("count")->Int32Value()); | 116 CHECK_EQ(1, ToInt32(CompileRun("count"))); |
| 99 } | 117 } |
| 100 | 118 |
| 101 | 119 |
| 102 TEST(DeliveryOrdering) { | 120 TEST(DeliveryOrdering) { |
| 103 HandleScope scope(CcTest::isolate()); | 121 HandleScope scope(CcTest::isolate()); |
| 104 LocalContext context(CcTest::isolate()); | 122 LocalContext context(CcTest::isolate()); |
| 105 CompileRun( | 123 CompileRun( |
| 106 "var obj1 = {};" | 124 "var obj1 = {};" |
| 107 "var obj2 = {};" | 125 "var obj2 = {};" |
| 108 "var ordering = [];" | 126 "var ordering = [];" |
| 109 "function observer2() { ordering.push(2); };" | 127 "function observer2() { ordering.push(2); };" |
| 110 "function observer1() { ordering.push(1); };" | 128 "function observer1() { ordering.push(1); };" |
| 111 "function observer3() { ordering.push(3); };" | 129 "function observer3() { ordering.push(3); };" |
| 112 "Object.observe(obj1, observer1);" | 130 "Object.observe(obj1, observer1);" |
| 113 "Object.observe(obj1, observer2);" | 131 "Object.observe(obj1, observer2);" |
| 114 "Object.observe(obj1, observer3);" | 132 "Object.observe(obj1, observer3);" |
| 115 "obj1.foo = 'bar';"); | 133 "obj1.foo = 'bar';"); |
| 116 CHECK_EQ(3, CompileRun("ordering.length")->Int32Value()); | 134 CHECK_EQ(3, ToInt32(CompileRun("ordering.length"))); |
| 117 CHECK_EQ(1, CompileRun("ordering[0]")->Int32Value()); | 135 CHECK_EQ(1, ToInt32(CompileRun("ordering[0]"))); |
| 118 CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value()); | 136 CHECK_EQ(2, ToInt32(CompileRun("ordering[1]"))); |
| 119 CHECK_EQ(3, CompileRun("ordering[2]")->Int32Value()); | 137 CHECK_EQ(3, ToInt32(CompileRun("ordering[2]"))); |
| 120 CompileRun( | 138 CompileRun( |
| 121 "ordering = [];" | 139 "ordering = [];" |
| 122 "Object.observe(obj2, observer3);" | 140 "Object.observe(obj2, observer3);" |
| 123 "Object.observe(obj2, observer2);" | 141 "Object.observe(obj2, observer2);" |
| 124 "Object.observe(obj2, observer1);" | 142 "Object.observe(obj2, observer1);" |
| 125 "obj2.foo = 'baz'"); | 143 "obj2.foo = 'baz'"); |
| 126 CHECK_EQ(3, CompileRun("ordering.length")->Int32Value()); | 144 CHECK_EQ(3, ToInt32(CompileRun("ordering.length"))); |
| 127 CHECK_EQ(1, CompileRun("ordering[0]")->Int32Value()); | 145 CHECK_EQ(1, ToInt32(CompileRun("ordering[0]"))); |
| 128 CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value()); | 146 CHECK_EQ(2, ToInt32(CompileRun("ordering[1]"))); |
| 129 CHECK_EQ(3, CompileRun("ordering[2]")->Int32Value()); | 147 CHECK_EQ(3, ToInt32(CompileRun("ordering[2]"))); |
| 130 } | 148 } |
| 131 | 149 |
| 132 | 150 |
| 133 TEST(DeliveryCallbackThrows) { | 151 TEST(DeliveryCallbackThrows) { |
| 134 HandleScope scope(CcTest::isolate()); | 152 HandleScope scope(CcTest::isolate()); |
| 135 LocalContext context(CcTest::isolate()); | 153 LocalContext context(CcTest::isolate()); |
| 136 CompileRun( | 154 CompileRun( |
| 137 "var obj = {};" | 155 "var obj = {};" |
| 138 "var ordering = [];" | 156 "var ordering = [];" |
| 139 "function observer1() { ordering.push(1); };" | 157 "function observer1() { ordering.push(1); };" |
| 140 "function observer2() { ordering.push(2); };" | 158 "function observer2() { ordering.push(2); };" |
| 141 "function observer_throws() {" | 159 "function observer_throws() {" |
| 142 " ordering.push(0);" | 160 " ordering.push(0);" |
| 143 " throw new Error();" | 161 " throw new Error();" |
| 144 " ordering.push(-1);" | 162 " ordering.push(-1);" |
| 145 "};" | 163 "};" |
| 146 "Object.observe(obj, observer_throws.bind());" | 164 "Object.observe(obj, observer_throws.bind());" |
| 147 "Object.observe(obj, observer1);" | 165 "Object.observe(obj, observer1);" |
| 148 "Object.observe(obj, observer_throws.bind());" | 166 "Object.observe(obj, observer_throws.bind());" |
| 149 "Object.observe(obj, observer2);" | 167 "Object.observe(obj, observer2);" |
| 150 "Object.observe(obj, observer_throws.bind());" | 168 "Object.observe(obj, observer_throws.bind());" |
| 151 "obj.foo = 'bar';"); | 169 "obj.foo = 'bar';"); |
| 152 CHECK_EQ(5, CompileRun("ordering.length")->Int32Value()); | 170 CHECK_EQ(5, ToInt32(CompileRun("ordering.length"))); |
| 153 CHECK_EQ(0, CompileRun("ordering[0]")->Int32Value()); | 171 CHECK_EQ(0, ToInt32(CompileRun("ordering[0]"))); |
| 154 CHECK_EQ(1, CompileRun("ordering[1]")->Int32Value()); | 172 CHECK_EQ(1, ToInt32(CompileRun("ordering[1]"))); |
| 155 CHECK_EQ(0, CompileRun("ordering[2]")->Int32Value()); | 173 CHECK_EQ(0, ToInt32(CompileRun("ordering[2]"))); |
| 156 CHECK_EQ(2, CompileRun("ordering[3]")->Int32Value()); | 174 CHECK_EQ(2, ToInt32(CompileRun("ordering[3]"))); |
| 157 CHECK_EQ(0, CompileRun("ordering[4]")->Int32Value()); | 175 CHECK_EQ(0, ToInt32(CompileRun("ordering[4]"))); |
| 158 } | 176 } |
| 159 | 177 |
| 160 | 178 |
| 161 TEST(DeliveryChangesMutationInCallback) { | 179 TEST(DeliveryChangesMutationInCallback) { |
| 162 HandleScope scope(CcTest::isolate()); | 180 HandleScope scope(CcTest::isolate()); |
| 163 LocalContext context(CcTest::isolate()); | 181 LocalContext context(CcTest::isolate()); |
| 164 CompileRun( | 182 CompileRun( |
| 165 "var obj = {};" | 183 "var obj = {};" |
| 166 "var ordering = [];" | 184 "var ordering = [];" |
| 167 "function observer1(records) {" | 185 "function observer1(records) {" |
| 168 " ordering.push(100 + records.length);" | 186 " ordering.push(100 + records.length);" |
| 169 " records.push(11);" | 187 " records.push(11);" |
| 170 " records.push(22);" | 188 " records.push(22);" |
| 171 "};" | 189 "};" |
| 172 "function observer2(records) {" | 190 "function observer2(records) {" |
| 173 " ordering.push(200 + records.length);" | 191 " ordering.push(200 + records.length);" |
| 174 " records.push(33);" | 192 " records.push(33);" |
| 175 " records.push(44);" | 193 " records.push(44);" |
| 176 "};" | 194 "};" |
| 177 "Object.observe(obj, observer1);" | 195 "Object.observe(obj, observer1);" |
| 178 "Object.observe(obj, observer2);" | 196 "Object.observe(obj, observer2);" |
| 179 "obj.foo = 'bar';"); | 197 "obj.foo = 'bar';"); |
| 180 CHECK_EQ(2, CompileRun("ordering.length")->Int32Value()); | 198 CHECK_EQ(2, ToInt32(CompileRun("ordering.length"))); |
| 181 CHECK_EQ(101, CompileRun("ordering[0]")->Int32Value()); | 199 CHECK_EQ(101, ToInt32(CompileRun("ordering[0]"))); |
| 182 CHECK_EQ(201, CompileRun("ordering[1]")->Int32Value()); | 200 CHECK_EQ(201, ToInt32(CompileRun("ordering[1]"))); |
| 183 } | 201 } |
| 184 | 202 |
| 185 | 203 |
| 186 TEST(DeliveryOrderingReentrant) { | 204 TEST(DeliveryOrderingReentrant) { |
| 187 HandleScope scope(CcTest::isolate()); | 205 HandleScope scope(CcTest::isolate()); |
| 188 LocalContext context(CcTest::isolate()); | 206 LocalContext context(CcTest::isolate()); |
| 189 CompileRun( | 207 CompileRun( |
| 190 "var obj = {};" | 208 "var obj = {};" |
| 191 "var reentered = false;" | 209 "var reentered = false;" |
| 192 "var ordering = [];" | 210 "var ordering = [];" |
| 193 "function observer1() { ordering.push(1); };" | 211 "function observer1() { ordering.push(1); };" |
| 194 "function observer2() {" | 212 "function observer2() {" |
| 195 " if (!reentered) {" | 213 " if (!reentered) {" |
| 196 " obj.foo = 'baz';" | 214 " obj.foo = 'baz';" |
| 197 " reentered = true;" | 215 " reentered = true;" |
| 198 " }" | 216 " }" |
| 199 " ordering.push(2);" | 217 " ordering.push(2);" |
| 200 "};" | 218 "};" |
| 201 "function observer3() { ordering.push(3); };" | 219 "function observer3() { ordering.push(3); };" |
| 202 "Object.observe(obj, observer1);" | 220 "Object.observe(obj, observer1);" |
| 203 "Object.observe(obj, observer2);" | 221 "Object.observe(obj, observer2);" |
| 204 "Object.observe(obj, observer3);" | 222 "Object.observe(obj, observer3);" |
| 205 "obj.foo = 'bar';"); | 223 "obj.foo = 'bar';"); |
| 206 CHECK_EQ(5, CompileRun("ordering.length")->Int32Value()); | 224 CHECK_EQ(5, ToInt32(CompileRun("ordering.length"))); |
| 207 CHECK_EQ(1, CompileRun("ordering[0]")->Int32Value()); | 225 CHECK_EQ(1, ToInt32(CompileRun("ordering[0]"))); |
| 208 CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value()); | 226 CHECK_EQ(2, ToInt32(CompileRun("ordering[1]"))); |
| 209 CHECK_EQ(3, CompileRun("ordering[2]")->Int32Value()); | 227 CHECK_EQ(3, ToInt32(CompileRun("ordering[2]"))); |
| 210 // Note that we re-deliver to observers 1 and 2, while observer3 | 228 // Note that we re-deliver to observers 1 and 2, while observer3 |
| 211 // already received the second record during the first round. | 229 // already received the second record during the first round. |
| 212 CHECK_EQ(1, CompileRun("ordering[3]")->Int32Value()); | 230 CHECK_EQ(1, ToInt32(CompileRun("ordering[3]"))); |
| 213 CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value()); | 231 CHECK_EQ(2, ToInt32(CompileRun("ordering[1]"))); |
| 214 } | 232 } |
| 215 | 233 |
| 216 | 234 |
| 217 TEST(DeliveryOrderingDeliverChangeRecords) { | 235 TEST(DeliveryOrderingDeliverChangeRecords) { |
| 218 HandleScope scope(CcTest::isolate()); | 236 HandleScope scope(CcTest::isolate()); |
| 219 LocalContext context(CcTest::isolate()); | 237 LocalContext context(CcTest::isolate()); |
| 220 CompileRun( | 238 CompileRun( |
| 221 "var obj = {};" | 239 "var obj = {};" |
| 222 "var ordering = [];" | 240 "var ordering = [];" |
| 223 "function observer1() { ordering.push(1); if (!obj.b) obj.b = true };" | 241 "function observer1() { ordering.push(1); if (!obj.b) obj.b = true };" |
| 224 "function observer2() { ordering.push(2); };" | 242 "function observer2() { ordering.push(2); };" |
| 225 "Object.observe(obj, observer1);" | 243 "Object.observe(obj, observer1);" |
| 226 "Object.observe(obj, observer2);" | 244 "Object.observe(obj, observer2);" |
| 227 "obj.a = 1;" | 245 "obj.a = 1;" |
| 228 "Object.deliverChangeRecords(observer2);"); | 246 "Object.deliverChangeRecords(observer2);"); |
| 229 CHECK_EQ(4, CompileRun("ordering.length")->Int32Value()); | 247 CHECK_EQ(4, ToInt32(CompileRun("ordering.length"))); |
| 230 // First, observer2 is called due to deliverChangeRecords | 248 // First, observer2 is called due to deliverChangeRecords |
| 231 CHECK_EQ(2, CompileRun("ordering[0]")->Int32Value()); | 249 CHECK_EQ(2, ToInt32(CompileRun("ordering[0]"))); |
| 232 // Then, observer1 is called when the stack unwinds | 250 // Then, observer1 is called when the stack unwinds |
| 233 CHECK_EQ(1, CompileRun("ordering[1]")->Int32Value()); | 251 CHECK_EQ(1, ToInt32(CompileRun("ordering[1]"))); |
| 234 // observer1's mutation causes both 1 and 2 to be reactivated, | 252 // observer1's mutation causes both 1 and 2 to be reactivated, |
| 235 // with 1 having priority. | 253 // with 1 having priority. |
| 236 CHECK_EQ(1, CompileRun("ordering[2]")->Int32Value()); | 254 CHECK_EQ(1, ToInt32(CompileRun("ordering[2]"))); |
| 237 CHECK_EQ(2, CompileRun("ordering[3]")->Int32Value()); | 255 CHECK_EQ(2, ToInt32(CompileRun("ordering[3]"))); |
| 238 } | 256 } |
| 239 | 257 |
| 240 | 258 |
| 241 TEST(ObjectHashTableGrowth) { | 259 TEST(ObjectHashTableGrowth) { |
| 242 HandleScope scope(CcTest::isolate()); | 260 HandleScope scope(CcTest::isolate()); |
| 243 // Initializing this context sets up initial hash tables. | 261 // Initializing this context sets up initial hash tables. |
| 244 LocalContext context(CcTest::isolate()); | 262 LocalContext context(CcTest::isolate()); |
| 245 Handle<Value> obj = CompileRun("obj = {};"); | 263 Local<Value> obj = CompileRun("obj = {};"); |
| 246 Handle<Value> observer = CompileRun( | 264 Local<Value> observer = CompileRun( |
| 247 "var ran = false;" | 265 "var ran = false;" |
| 248 "(function() { ran = true })"); | 266 "(function() { ran = true })"); |
| 249 { | 267 { |
| 250 // As does initializing this context. | 268 // As does initializing this context. |
| 251 LocalContext context2(CcTest::isolate()); | 269 LocalContext context2(CcTest::isolate()); |
| 252 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 270 context2->Global() |
| 253 obj); | 271 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 254 context2->Global()->Set( | 272 obj) |
| 255 String::NewFromUtf8(CcTest::isolate(), "observer"), observer); | 273 .FromJust(); |
| 274 context2->Global() |
| 275 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 276 v8_str("observer"), observer) |
| 277 .FromJust(); |
| 256 CompileRun( | 278 CompileRun( |
| 257 "var objArr = [];" | 279 "var objArr = [];" |
| 258 // 100 objects should be enough to make the hash table grow | 280 // 100 objects should be enough to make the hash table grow |
| 259 // (and thus relocate). | 281 // (and thus relocate). |
| 260 "for (var i = 0; i < 100; ++i) {" | 282 "for (var i = 0; i < 100; ++i) {" |
| 261 " objArr.push({});" | 283 " objArr.push({});" |
| 262 " Object.observe(objArr[objArr.length-1], function(){});" | 284 " Object.observe(objArr[objArr.length-1], function(){});" |
| 263 "}" | 285 "}" |
| 264 "Object.observe(obj, observer);"); | 286 "Object.observe(obj, observer);"); |
| 265 } | 287 } |
| 266 // obj is now marked "is_observed", but our map has moved. | 288 // obj is now marked "is_observed", but our map has moved. |
| 267 CompileRun("obj.foo = 'bar'"); | 289 CompileRun("obj.foo = 'bar'"); |
| 268 CHECK(CompileRun("ran")->BooleanValue()); | 290 CHECK(CompileRun("ran") |
| 291 ->BooleanValue(v8::Isolate::GetCurrent()->GetCurrentContext()) |
| 292 .FromJust()); |
| 269 } | 293 } |
| 270 | 294 |
| 271 | 295 |
| 272 struct RecordExpectation { | 296 struct RecordExpectation { |
| 273 Handle<Value> object; | 297 Local<Value> object; |
| 274 const char* type; | 298 const char* type; |
| 275 const char* name; | 299 const char* name; |
| 276 Handle<Value> old_value; | 300 Local<Value> old_value; |
| 277 }; | 301 }; |
| 278 | 302 |
| 279 | 303 |
| 280 // TODO(adamk): Use this helper elsewhere in this file. | 304 // TODO(adamk): Use this helper elsewhere in this file. |
| 281 static void ExpectRecords(v8::Isolate* isolate, | 305 static void ExpectRecords(v8::Isolate* isolate, Local<Value> records, |
| 282 Handle<Value> records, | 306 const RecordExpectation expectations[], int num) { |
| 283 const RecordExpectation expectations[], | |
| 284 int num) { | |
| 285 CHECK(records->IsArray()); | 307 CHECK(records->IsArray()); |
| 286 Handle<Array> recordArray = records.As<Array>(); | 308 Local<Array> recordArray = records.As<Array>(); |
| 287 CHECK_EQ(num, static_cast<int>(recordArray->Length())); | 309 CHECK_EQ(num, static_cast<int>(recordArray->Length())); |
| 288 for (int i = 0; i < num; ++i) { | 310 for (int i = 0; i < num; ++i) { |
| 289 Handle<Value> record = recordArray->Get(i); | 311 Local<Value> record = |
| 312 recordArray->Get(v8::Isolate::GetCurrent()->GetCurrentContext(), i) |
| 313 .ToLocalChecked(); |
| 290 CHECK(record->IsObject()); | 314 CHECK(record->IsObject()); |
| 291 Handle<Object> recordObj = record.As<Object>(); | 315 Local<Object> recordObj = record.As<Object>(); |
| 292 CHECK(expectations[i].object->StrictEquals( | 316 Local<Value> value = |
| 293 recordObj->Get(String::NewFromUtf8(isolate, "object")))); | 317 recordObj->Get(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 294 CHECK(String::NewFromUtf8(isolate, expectations[i].type)->Equals( | 318 v8_str("object")) |
| 295 recordObj->Get(String::NewFromUtf8(isolate, "type")))); | 319 .ToLocalChecked(); |
| 320 CHECK(expectations[i].object->StrictEquals(value)); |
| 321 value = recordObj->Get(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 322 v8_str("type")) |
| 323 .ToLocalChecked(); |
| 324 CHECK(v8_str(expectations[i].type) |
| 325 ->Equals(v8::Isolate::GetCurrent()->GetCurrentContext(), value) |
| 326 .FromJust()); |
| 296 if (strcmp("splice", expectations[i].type) != 0) { | 327 if (strcmp("splice", expectations[i].type) != 0) { |
| 297 CHECK(String::NewFromUtf8(isolate, expectations[i].name)->Equals( | 328 Local<Value> name = |
| 298 recordObj->Get(String::NewFromUtf8(isolate, "name")))); | 329 recordObj->Get(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 330 v8_str("name")) |
| 331 .ToLocalChecked(); |
| 332 CHECK(v8_str(expectations[i].name) |
| 333 ->Equals(v8::Isolate::GetCurrent()->GetCurrentContext(), name) |
| 334 .FromJust()); |
| 299 if (!expectations[i].old_value.IsEmpty()) { | 335 if (!expectations[i].old_value.IsEmpty()) { |
| 300 CHECK(expectations[i].old_value->Equals( | 336 Local<Value> old_value = |
| 301 recordObj->Get(String::NewFromUtf8(isolate, "oldValue")))); | 337 recordObj->Get(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 338 v8_str("oldValue")) |
| 339 .ToLocalChecked(); |
| 340 CHECK(expectations[i] |
| 341 .old_value->Equals( |
| 342 v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 343 old_value) |
| 344 .FromJust()); |
| 302 } | 345 } |
| 303 } | 346 } |
| 304 } | 347 } |
| 305 } | 348 } |
| 306 | 349 |
| 307 #define EXPECT_RECORDS(records, expectations) \ | 350 #define EXPECT_RECORDS(records, expectations) \ |
| 308 ExpectRecords(CcTest::isolate(), records, expectations, \ | 351 ExpectRecords(CcTest::isolate(), records, expectations, \ |
| 309 arraysize(expectations)) | 352 arraysize(expectations)) |
| 310 | 353 |
| 311 TEST(APITestBasicMutation) { | 354 TEST(APITestBasicMutation) { |
| 312 v8::Isolate* v8_isolate = CcTest::isolate(); | 355 v8::Isolate* v8_isolate = CcTest::isolate(); |
| 313 HandleScope scope(v8_isolate); | 356 HandleScope scope(v8_isolate); |
| 314 LocalContext context(v8_isolate); | 357 LocalContext context(v8_isolate); |
| 315 Handle<Object> obj = Handle<Object>::Cast(CompileRun( | 358 Local<Object> obj = Local<Object>::Cast( |
| 316 "var records = [];" | 359 CompileRun("var records = [];" |
| 317 "var obj = {};" | 360 "var obj = {};" |
| 318 "function observer(r) { [].push.apply(records, r); };" | 361 "function observer(r) { [].push.apply(records, r); };" |
| 319 "Object.observe(obj, observer);" | 362 "Object.observe(obj, observer);" |
| 320 "obj")); | 363 "obj")); |
| 321 obj->Set(String::NewFromUtf8(v8_isolate, "foo"), | 364 obj->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("foo"), |
| 322 Number::New(v8_isolate, 7)); | 365 Number::New(v8_isolate, 7)) |
| 323 obj->Set(1, Number::New(v8_isolate, 2)); | 366 .FromJust(); |
| 324 // ForceSet should work just as well as Set | 367 obj->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), 1, |
| 325 obj->ForceSet(String::NewFromUtf8(v8_isolate, "foo"), | 368 Number::New(v8_isolate, 2)) |
| 326 Number::New(v8_isolate, 3)); | 369 .FromJust(); |
| 327 obj->ForceSet(Number::New(v8_isolate, 1), Number::New(v8_isolate, 4)); | 370 // CreateDataProperty should work just as well as Set |
| 371 obj->CreateDataProperty(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 372 v8_str("foo"), Number::New(v8_isolate, 3)) |
| 373 .FromJust(); |
| 374 obj->CreateDataProperty(v8::Isolate::GetCurrent()->GetCurrentContext(), 1, |
| 375 Number::New(v8_isolate, 4)) |
| 376 .FromJust(); |
| 328 // Setting an indexed element via the property setting method | 377 // Setting an indexed element via the property setting method |
| 329 obj->Set(Number::New(v8_isolate, 1), Number::New(v8_isolate, 5)); | 378 obj->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 379 Number::New(v8_isolate, 1), Number::New(v8_isolate, 5)) |
| 380 .FromJust(); |
| 330 // Setting with a non-String, non-uint32 key | 381 // Setting with a non-String, non-uint32 key |
| 331 obj->Set(Number::New(v8_isolate, 1.1), Number::New(v8_isolate, 6)); | 382 obj->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 332 obj->Delete(String::NewFromUtf8(v8_isolate, "foo")); | 383 Number::New(v8_isolate, 1.1), Number::New(v8_isolate, 6)) |
| 333 obj->Delete(1); | 384 .FromJust(); |
| 334 obj->Delete(Number::New(v8_isolate, 1.1)); | 385 obj->Delete(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("foo")) |
| 386 .FromJust(); |
| 387 obj->Delete(v8::Isolate::GetCurrent()->GetCurrentContext(), 1).FromJust(); |
| 388 obj->Delete(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 389 Number::New(v8_isolate, 1.1)) |
| 390 .FromJust(); |
| 335 | 391 |
| 336 // Force delivery | 392 // Force delivery |
| 337 // TODO(adamk): Should the above set methods trigger delivery themselves? | 393 // TODO(adamk): Should the above set methods trigger delivery themselves? |
| 338 CompileRun("void 0"); | 394 CompileRun("void 0"); |
| 339 CHECK_EQ(9, CompileRun("records.length")->Int32Value()); | 395 CHECK_EQ(9, ToInt32(CompileRun("records.length"))); |
| 340 const RecordExpectation expected_records[] = { | 396 const RecordExpectation expected_records[] = { |
| 341 { obj, "add", "foo", Handle<Value>() }, | 397 {obj, "add", "foo", Local<Value>()}, |
| 342 { obj, "add", "1", Handle<Value>() }, | 398 {obj, "add", "1", Local<Value>()}, |
| 343 // Note: use 7 not 1 below, as the latter triggers a nifty VS10 compiler bug | 399 // Note: use 7 not 1 below, as the latter triggers a nifty VS10 compiler |
| 344 // where instead of 1.0, a garbage value would be passed into Number::New. | 400 // bug |
| 345 { obj, "update", "foo", Number::New(v8_isolate, 7) }, | 401 // where instead of 1.0, a garbage value would be passed into Number::New. |
| 346 { obj, "update", "1", Number::New(v8_isolate, 2) }, | 402 {obj, "update", "foo", Number::New(v8_isolate, 7)}, |
| 347 { obj, "update", "1", Number::New(v8_isolate, 4) }, | 403 {obj, "update", "1", Number::New(v8_isolate, 2)}, |
| 348 { obj, "add", "1.1", Handle<Value>() }, | 404 {obj, "update", "1", Number::New(v8_isolate, 4)}, |
| 349 { obj, "delete", "foo", Number::New(v8_isolate, 3) }, | 405 {obj, "add", "1.1", Local<Value>()}, |
| 350 { obj, "delete", "1", Number::New(v8_isolate, 5) }, | 406 {obj, "delete", "foo", Number::New(v8_isolate, 3)}, |
| 351 { obj, "delete", "1.1", Number::New(v8_isolate, 6) } | 407 {obj, "delete", "1", Number::New(v8_isolate, 5)}, |
| 352 }; | 408 {obj, "delete", "1.1", Number::New(v8_isolate, 6)}}; |
| 353 EXPECT_RECORDS(CompileRun("records"), expected_records); | 409 EXPECT_RECORDS(CompileRun("records"), expected_records); |
| 354 } | 410 } |
| 355 | 411 |
| 356 | 412 |
| 357 TEST(HiddenPrototypeObservation) { | 413 TEST(HiddenPrototypeObservation) { |
| 358 v8::Isolate* v8_isolate = CcTest::isolate(); | 414 v8::Isolate* v8_isolate = CcTest::isolate(); |
| 359 HandleScope scope(v8_isolate); | 415 HandleScope scope(v8_isolate); |
| 360 LocalContext context(v8_isolate); | 416 LocalContext context(v8_isolate); |
| 361 Handle<FunctionTemplate> tmpl = FunctionTemplate::New(v8_isolate); | 417 Local<FunctionTemplate> tmpl = FunctionTemplate::New(v8_isolate); |
| 362 tmpl->SetHiddenPrototype(true); | 418 tmpl->SetHiddenPrototype(true); |
| 363 tmpl->InstanceTemplate()->Set( | 419 tmpl->InstanceTemplate()->Set(v8_str("foo"), Number::New(v8_isolate, 75)); |
| 364 String::NewFromUtf8(v8_isolate, "foo"), Number::New(v8_isolate, 75)); | 420 Local<Function> function = |
| 365 Handle<Object> proto = tmpl->GetFunction()->NewInstance(); | 421 tmpl->GetFunction(v8::Isolate::GetCurrent()->GetCurrentContext()) |
| 366 Handle<Object> obj = Object::New(v8_isolate); | 422 .ToLocalChecked(); |
| 367 obj->SetPrototype(proto); | 423 Local<Object> proto = |
| 368 context->Global()->Set(String::NewFromUtf8(v8_isolate, "obj"), obj); | 424 function->NewInstance(v8::Isolate::GetCurrent()->GetCurrentContext()) |
| 369 context->Global()->Set(String::NewFromUtf8(v8_isolate, "proto"), | 425 .ToLocalChecked(); |
| 370 proto); | 426 Local<Object> obj = Object::New(v8_isolate); |
| 427 obj->SetPrototype(v8::Isolate::GetCurrent()->GetCurrentContext(), proto) |
| 428 .FromJust(); |
| 429 context->Global() |
| 430 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), obj) |
| 431 .FromJust(); |
| 432 context->Global() |
| 433 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("proto"), |
| 434 proto) |
| 435 .FromJust(); |
| 371 CompileRun( | 436 CompileRun( |
| 372 "var records;" | 437 "var records;" |
| 373 "function observer(r) { records = r; };" | 438 "function observer(r) { records = r; };" |
| 374 "Object.observe(obj, observer);" | 439 "Object.observe(obj, observer);" |
| 375 "obj.foo = 41;" // triggers a notification | 440 "obj.foo = 41;" // triggers a notification |
| 376 "proto.foo = 42;"); // does not trigger a notification | 441 "proto.foo = 42;"); // does not trigger a notification |
| 377 const RecordExpectation expected_records[] = { | 442 const RecordExpectation expected_records[] = { |
| 378 { obj, "update", "foo", Number::New(v8_isolate, 75) } | 443 { obj, "update", "foo", Number::New(v8_isolate, 75) } |
| 379 }; | 444 }; |
| 380 EXPECT_RECORDS(CompileRun("records"), expected_records); | 445 EXPECT_RECORDS(CompileRun("records"), expected_records); |
| 381 obj->SetPrototype(Null(v8_isolate)); | 446 obj->SetPrototype(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 447 Null(v8_isolate)) |
| 448 .FromJust(); |
| 382 CompileRun("obj.foo = 43"); | 449 CompileRun("obj.foo = 43"); |
| 383 const RecordExpectation expected_records2[] = { | 450 const RecordExpectation expected_records2[] = { |
| 384 { obj, "add", "foo", Handle<Value>() } | 451 {obj, "add", "foo", Local<Value>()}}; |
| 385 }; | |
| 386 EXPECT_RECORDS(CompileRun("records"), expected_records2); | 452 EXPECT_RECORDS(CompileRun("records"), expected_records2); |
| 387 obj->SetPrototype(proto); | 453 obj->SetPrototype(v8::Isolate::GetCurrent()->GetCurrentContext(), proto) |
| 454 .FromJust(); |
| 388 CompileRun( | 455 CompileRun( |
| 389 "Object.observe(proto, observer);" | 456 "Object.observe(proto, observer);" |
| 390 "proto.bar = 1;" | 457 "proto.bar = 1;" |
| 391 "Object.unobserve(obj, observer);" | 458 "Object.unobserve(obj, observer);" |
| 392 "obj.foo = 44;"); | 459 "obj.foo = 44;"); |
| 393 const RecordExpectation expected_records3[] = { | 460 const RecordExpectation expected_records3[] = { |
| 394 { proto, "add", "bar", Handle<Value>() } | 461 {proto, "add", "bar", Local<Value>()} |
| 395 // TODO(adamk): The below record should be emitted since proto is observed | 462 // TODO(adamk): The below record should be emitted since proto is observed |
| 396 // and has been modified. Not clear if this happens in practice. | 463 // and has been modified. Not clear if this happens in practice. |
| 397 // { proto, "update", "foo", Number::New(43) } | 464 // { proto, "update", "foo", Number::New(43) } |
| 398 }; | 465 }; |
| 399 EXPECT_RECORDS(CompileRun("records"), expected_records3); | 466 EXPECT_RECORDS(CompileRun("records"), expected_records3); |
| 400 } | 467 } |
| 401 | 468 |
| 402 | 469 |
| 403 static int NumberOfElements(i::Handle<i::JSWeakMap> map) { | 470 static int NumberOfElements(i::Handle<i::JSWeakMap> map) { |
| 404 return i::ObjectHashTable::cast(map->table())->NumberOfElements(); | 471 return i::ObjectHashTable::cast(map->table())->NumberOfElements(); |
| 405 } | 472 } |
| 406 | 473 |
| 407 | 474 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 429 CHECK_EQ(1, NumberOfElements(callbackInfoMap)); | 496 CHECK_EQ(1, NumberOfElements(callbackInfoMap)); |
| 430 CHECK_EQ(1, NumberOfElements(objectInfoMap)); | 497 CHECK_EQ(1, NumberOfElements(objectInfoMap)); |
| 431 CHECK_EQ(1, NumberOfElements(notifierObjectInfoMap)); | 498 CHECK_EQ(1, NumberOfElements(notifierObjectInfoMap)); |
| 432 i_isolate->heap()->CollectAllGarbage(); | 499 i_isolate->heap()->CollectAllGarbage(); |
| 433 CHECK_EQ(0, NumberOfElements(callbackInfoMap)); | 500 CHECK_EQ(0, NumberOfElements(callbackInfoMap)); |
| 434 CHECK_EQ(0, NumberOfElements(objectInfoMap)); | 501 CHECK_EQ(0, NumberOfElements(objectInfoMap)); |
| 435 CHECK_EQ(0, NumberOfElements(notifierObjectInfoMap)); | 502 CHECK_EQ(0, NumberOfElements(notifierObjectInfoMap)); |
| 436 } | 503 } |
| 437 | 504 |
| 438 | 505 |
| 439 static int TestObserveSecurity(Handle<Context> observer_context, | 506 static int TestObserveSecurity(Local<Context> observer_context, |
| 440 Handle<Context> object_context, | 507 Local<Context> object_context, |
| 441 Handle<Context> mutation_context) { | 508 Local<Context> mutation_context) { |
| 442 Context::Scope observer_scope(observer_context); | 509 Context::Scope observer_scope(observer_context); |
| 443 CompileRun("var records = null;" | 510 CompileRun("var records = null;" |
| 444 "var observer = function(r) { records = r };"); | 511 "var observer = function(r) { records = r };"); |
| 445 Handle<Value> observer = CompileRun("observer"); | 512 Local<Value> observer = CompileRun("observer"); |
| 446 { | 513 { |
| 447 Context::Scope object_scope(object_context); | 514 Context::Scope object_scope(object_context); |
| 448 object_context->Global()->Set( | 515 object_context->Global() |
| 449 String::NewFromUtf8(CcTest::isolate(), "observer"), observer); | 516 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 517 v8_str("observer"), observer) |
| 518 .FromJust(); |
| 450 CompileRun("var obj = {};" | 519 CompileRun("var obj = {};" |
| 451 "obj.length = 0;" | 520 "obj.length = 0;" |
| 452 "Object.observe(obj, observer," | 521 "Object.observe(obj, observer," |
| 453 "['add', 'update', 'delete','reconfigure','splice']" | 522 "['add', 'update', 'delete','reconfigure','splice']" |
| 454 ");"); | 523 ");"); |
| 455 Handle<Value> obj = CompileRun("obj"); | 524 Local<Value> obj = CompileRun("obj"); |
| 456 { | 525 { |
| 457 Context::Scope mutation_scope(mutation_context); | 526 Context::Scope mutation_scope(mutation_context); |
| 458 mutation_context->Global()->Set( | 527 mutation_context->Global() |
| 459 String::NewFromUtf8(CcTest::isolate(), "obj"), obj); | 528 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 529 obj) |
| 530 .FromJust(); |
| 460 CompileRun("obj.foo = 'bar';" | 531 CompileRun("obj.foo = 'bar';" |
| 461 "obj.foo = 'baz';" | 532 "obj.foo = 'baz';" |
| 462 "delete obj.foo;" | 533 "delete obj.foo;" |
| 463 "Object.defineProperty(obj, 'bar', {value: 'bot'});" | 534 "Object.defineProperty(obj, 'bar', {value: 'bot'});" |
| 464 "Array.prototype.push.call(obj, 1, 2, 3);" | 535 "Array.prototype.push.call(obj, 1, 2, 3);" |
| 465 "Array.prototype.splice.call(obj, 1, 2, 2, 4);" | 536 "Array.prototype.splice.call(obj, 1, 2, 2, 4);" |
| 466 "Array.prototype.pop.call(obj);" | 537 "Array.prototype.pop.call(obj);" |
| 467 "Array.prototype.shift.call(obj);"); | 538 "Array.prototype.shift.call(obj);"); |
| 468 } | 539 } |
| 469 } | 540 } |
| 470 return CompileRun("records ? records.length : 0")->Int32Value(); | 541 return ToInt32(CompileRun("records ? records.length : 0")); |
| 471 } | 542 } |
| 472 | 543 |
| 473 | 544 |
| 474 TEST(ObserverSecurityAAA) { | 545 TEST(ObserverSecurityAAA) { |
| 475 v8::Isolate* isolate = CcTest::isolate(); | 546 v8::Isolate* isolate = CcTest::isolate(); |
| 476 v8::HandleScope scope(isolate); | 547 v8::HandleScope scope(isolate); |
| 477 v8::Local<Context> contextA = Context::New(isolate); | 548 v8::Local<Context> contextA = Context::New(isolate); |
| 478 CHECK_EQ(8, TestObserveSecurity(contextA, contextA, contextA)); | 549 CHECK_EQ(8, TestObserveSecurity(contextA, contextA, contextA)); |
| 479 } | 550 } |
| 480 | 551 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 v8::Isolate* isolate = CcTest::isolate(); | 644 v8::Isolate* isolate = CcTest::isolate(); |
| 574 v8::HandleScope scope(isolate); | 645 v8::HandleScope scope(isolate); |
| 575 v8::Local<Context> contextA = Context::New(isolate); | 646 v8::Local<Context> contextA = Context::New(isolate); |
| 576 v8::Local<Context> contextB = Context::New(isolate); | 647 v8::Local<Context> contextB = Context::New(isolate); |
| 577 | 648 |
| 578 Context::Scope scopeA(contextA); | 649 Context::Scope scopeA(contextA); |
| 579 CompileRun("var obj = {};" | 650 CompileRun("var obj = {};" |
| 580 "var recordsA = null;" | 651 "var recordsA = null;" |
| 581 "var observerA = function(r) { recordsA = r };" | 652 "var observerA = function(r) { recordsA = r };" |
| 582 "Object.observe(obj, observerA);"); | 653 "Object.observe(obj, observerA);"); |
| 583 Handle<Value> obj = CompileRun("obj"); | 654 Local<Value> obj = CompileRun("obj"); |
| 584 | 655 |
| 585 { | 656 { |
| 586 Context::Scope scopeB(contextB); | 657 Context::Scope scopeB(contextB); |
| 587 contextB->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), obj); | 658 contextB->Global() |
| 659 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 660 obj) |
| 661 .FromJust(); |
| 588 CompileRun("var recordsB = null;" | 662 CompileRun("var recordsB = null;" |
| 589 "var observerB = function(r) { recordsB = r };" | 663 "var observerB = function(r) { recordsB = r };" |
| 590 "Object.observe(obj, observerB);"); | 664 "Object.observe(obj, observerB);"); |
| 591 } | 665 } |
| 592 | 666 |
| 593 CompileRun("var notifier = Object.getNotifier(obj);" | 667 CompileRun("var notifier = Object.getNotifier(obj);" |
| 594 "notifier.notify({ type: 'update' });"); | 668 "notifier.notify({ type: 'update' });"); |
| 595 CHECK_EQ(1, CompileRun("recordsA ? recordsA.length : 0")->Int32Value()); | 669 CHECK_EQ(1, ToInt32(CompileRun("recordsA ? recordsA.length : 0"))); |
| 596 | 670 |
| 597 { | 671 { |
| 598 Context::Scope scopeB(contextB); | 672 Context::Scope scopeB(contextB); |
| 599 CHECK_EQ(0, CompileRun("recordsB ? recordsB.length : 0")->Int32Value()); | 673 CHECK_EQ(0, ToInt32(CompileRun("recordsB ? recordsB.length : 0"))); |
| 600 } | 674 } |
| 601 } | 675 } |
| 602 | 676 |
| 603 | 677 |
| 604 TEST(HiddenPropertiesLeakage) { | 678 TEST(HiddenPropertiesLeakage) { |
| 605 HandleScope scope(CcTest::isolate()); | 679 HandleScope scope(CcTest::isolate()); |
| 606 LocalContext context(CcTest::isolate()); | 680 LocalContext context(CcTest::isolate()); |
| 607 CompileRun("var obj = {};" | 681 CompileRun("var obj = {};" |
| 608 "var records = null;" | 682 "var records = null;" |
| 609 "var observer = function(r) { records = r };" | 683 "var observer = function(r) { records = r };" |
| 610 "Object.observe(obj, observer);"); | 684 "Object.observe(obj, observer);"); |
| 611 Handle<Value> obj = | 685 Local<Value> obj = |
| 612 context->Global()->Get(String::NewFromUtf8(CcTest::isolate(), "obj")); | 686 context->Global() |
| 613 Handle<Object>::Cast(obj) | 687 ->Get(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj")) |
| 614 ->SetHiddenValue(String::NewFromUtf8(CcTest::isolate(), "foo"), | 688 .ToLocalChecked(); |
| 615 Null(CcTest::isolate())); | 689 Local<Object>::Cast(obj) |
| 690 ->SetHiddenValue(v8_str("foo"), Null(CcTest::isolate())); |
| 616 CompileRun(""); // trigger delivery | 691 CompileRun(""); // trigger delivery |
| 617 CHECK(CompileRun("records")->IsNull()); | 692 CHECK(CompileRun("records")->IsNull()); |
| 618 } | 693 } |
| 619 | 694 |
| 620 | 695 |
| 621 TEST(GetNotifierFromOtherContext) { | 696 TEST(GetNotifierFromOtherContext) { |
| 622 HandleScope scope(CcTest::isolate()); | 697 HandleScope scope(CcTest::isolate()); |
| 623 LocalContext context(CcTest::isolate()); | 698 LocalContext context(CcTest::isolate()); |
| 624 CompileRun("var obj = {};"); | 699 CompileRun("var obj = {};"); |
| 625 Handle<Value> instance = CompileRun("obj"); | 700 Local<Value> instance = CompileRun("obj"); |
| 626 { | 701 { |
| 627 LocalContext context2(CcTest::isolate()); | 702 LocalContext context2(CcTest::isolate()); |
| 628 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 703 context2->Global() |
| 629 instance); | 704 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 705 instance) |
| 706 .FromJust(); |
| 630 CHECK(CompileRun("Object.getNotifier(obj)")->IsNull()); | 707 CHECK(CompileRun("Object.getNotifier(obj)")->IsNull()); |
| 631 } | 708 } |
| 632 } | 709 } |
| 633 | 710 |
| 634 | 711 |
| 635 TEST(GetNotifierFromOtherOrigin) { | 712 TEST(GetNotifierFromOtherOrigin) { |
| 636 HandleScope scope(CcTest::isolate()); | 713 HandleScope scope(CcTest::isolate()); |
| 637 Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo"); | 714 Local<Value> foo = v8_str("foo"); |
| 638 Handle<Value> bar = String::NewFromUtf8(CcTest::isolate(), "bar"); | 715 Local<Value> bar = v8_str("bar"); |
| 639 LocalContext context(CcTest::isolate()); | 716 LocalContext context(CcTest::isolate()); |
| 640 context->SetSecurityToken(foo); | 717 context->SetSecurityToken(foo); |
| 641 CompileRun("var obj = {};"); | 718 CompileRun("var obj = {};"); |
| 642 Handle<Value> instance = CompileRun("obj"); | 719 Local<Value> instance = CompileRun("obj"); |
| 643 { | 720 { |
| 644 LocalContext context2(CcTest::isolate()); | 721 LocalContext context2(CcTest::isolate()); |
| 645 context2->SetSecurityToken(bar); | 722 context2->SetSecurityToken(bar); |
| 646 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 723 context2->Global() |
| 647 instance); | 724 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 725 instance) |
| 726 .FromJust(); |
| 648 CHECK(CompileRun("Object.getNotifier(obj)")->IsNull()); | 727 CHECK(CompileRun("Object.getNotifier(obj)")->IsNull()); |
| 649 } | 728 } |
| 650 } | 729 } |
| 651 | 730 |
| 652 | 731 |
| 653 TEST(GetNotifierFromSameOrigin) { | 732 TEST(GetNotifierFromSameOrigin) { |
| 654 HandleScope scope(CcTest::isolate()); | 733 HandleScope scope(CcTest::isolate()); |
| 655 Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo"); | 734 Local<Value> foo = v8_str("foo"); |
| 656 LocalContext context(CcTest::isolate()); | 735 LocalContext context(CcTest::isolate()); |
| 657 context->SetSecurityToken(foo); | 736 context->SetSecurityToken(foo); |
| 658 CompileRun("var obj = {};"); | 737 CompileRun("var obj = {};"); |
| 659 Handle<Value> instance = CompileRun("obj"); | 738 Local<Value> instance = CompileRun("obj"); |
| 660 { | 739 { |
| 661 LocalContext context2(CcTest::isolate()); | 740 LocalContext context2(CcTest::isolate()); |
| 662 context2->SetSecurityToken(foo); | 741 context2->SetSecurityToken(foo); |
| 663 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 742 context2->Global() |
| 664 instance); | 743 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 744 instance) |
| 745 .FromJust(); |
| 665 CHECK(CompileRun("Object.getNotifier(obj)")->IsObject()); | 746 CHECK(CompileRun("Object.getNotifier(obj)")->IsObject()); |
| 666 } | 747 } |
| 667 } | 748 } |
| 668 | 749 |
| 669 | 750 |
| 670 static int GetGlobalObjectsCount() { | 751 static int GetGlobalObjectsCount() { |
| 671 int count = 0; | 752 int count = 0; |
| 672 i::HeapIterator it(CcTest::heap()); | 753 i::HeapIterator it(CcTest::heap()); |
| 673 for (i::HeapObject* object = it.next(); object != NULL; object = it.next()) | 754 for (i::HeapObject* object = it.next(); object != NULL; object = it.next()) |
| 674 if (object->IsJSGlobalObject()) count++; | 755 if (object->IsJSGlobalObject()) count++; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 687 int count = GetGlobalObjectsCount(); | 768 int count = GetGlobalObjectsCount(); |
| 688 #ifdef DEBUG | 769 #ifdef DEBUG |
| 689 if (count != expected) CcTest::heap()->TracePathToGlobal(); | 770 if (count != expected) CcTest::heap()->TracePathToGlobal(); |
| 690 #endif | 771 #endif |
| 691 CHECK_EQ(expected, count); | 772 CHECK_EQ(expected, count); |
| 692 } | 773 } |
| 693 | 774 |
| 694 | 775 |
| 695 TEST(DontLeakContextOnObserve) { | 776 TEST(DontLeakContextOnObserve) { |
| 696 HandleScope scope(CcTest::isolate()); | 777 HandleScope scope(CcTest::isolate()); |
| 697 Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo"); | 778 Local<Value> foo = v8_str("foo"); |
| 698 LocalContext context(CcTest::isolate()); | 779 LocalContext context(CcTest::isolate()); |
| 699 context->SetSecurityToken(foo); | 780 context->SetSecurityToken(foo); |
| 700 CompileRun("var obj = {};"); | 781 CompileRun("var obj = {};"); |
| 701 Handle<Value> object = CompileRun("obj"); | 782 Local<Value> object = CompileRun("obj"); |
| 702 { | 783 { |
| 703 HandleScope scope(CcTest::isolate()); | 784 HandleScope scope(CcTest::isolate()); |
| 704 LocalContext context2(CcTest::isolate()); | 785 LocalContext context2(CcTest::isolate()); |
| 705 context2->SetSecurityToken(foo); | 786 context2->SetSecurityToken(foo); |
| 706 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 787 context2->Global() |
| 707 object); | 788 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 789 object) |
| 790 .FromJust(); |
| 708 CompileRun("function observer() {};" | 791 CompileRun("function observer() {};" |
| 709 "Object.observe(obj, observer, ['foo', 'bar', 'baz']);" | 792 "Object.observe(obj, observer, ['foo', 'bar', 'baz']);" |
| 710 "Object.unobserve(obj, observer);"); | 793 "Object.unobserve(obj, observer);"); |
| 711 } | 794 } |
| 712 | 795 |
| 713 CcTest::isolate()->ContextDisposedNotification(); | 796 CcTest::isolate()->ContextDisposedNotification(); |
| 714 CheckSurvivingGlobalObjectsCount(2); | 797 CheckSurvivingGlobalObjectsCount(2); |
| 715 } | 798 } |
| 716 | 799 |
| 717 | 800 |
| 718 TEST(DontLeakContextOnGetNotifier) { | 801 TEST(DontLeakContextOnGetNotifier) { |
| 719 HandleScope scope(CcTest::isolate()); | 802 HandleScope scope(CcTest::isolate()); |
| 720 Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo"); | 803 Local<Value> foo = v8_str("foo"); |
| 721 LocalContext context(CcTest::isolate()); | 804 LocalContext context(CcTest::isolate()); |
| 722 context->SetSecurityToken(foo); | 805 context->SetSecurityToken(foo); |
| 723 CompileRun("var obj = {};"); | 806 CompileRun("var obj = {};"); |
| 724 Handle<Value> object = CompileRun("obj"); | 807 Local<Value> object = CompileRun("obj"); |
| 725 { | 808 { |
| 726 HandleScope scope(CcTest::isolate()); | 809 HandleScope scope(CcTest::isolate()); |
| 727 LocalContext context2(CcTest::isolate()); | 810 LocalContext context2(CcTest::isolate()); |
| 728 context2->SetSecurityToken(foo); | 811 context2->SetSecurityToken(foo); |
| 729 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 812 context2->Global() |
| 730 object); | 813 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 814 object) |
| 815 .FromJust(); |
| 731 CompileRun("Object.getNotifier(obj);"); | 816 CompileRun("Object.getNotifier(obj);"); |
| 732 } | 817 } |
| 733 | 818 |
| 734 CcTest::isolate()->ContextDisposedNotification(); | 819 CcTest::isolate()->ContextDisposedNotification(); |
| 735 CheckSurvivingGlobalObjectsCount(2); | 820 CheckSurvivingGlobalObjectsCount(2); |
| 736 } | 821 } |
| 737 | 822 |
| 738 | 823 |
| 739 TEST(DontLeakContextOnNotifierPerformChange) { | 824 TEST(DontLeakContextOnNotifierPerformChange) { |
| 740 HandleScope scope(CcTest::isolate()); | 825 HandleScope scope(CcTest::isolate()); |
| 741 Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo"); | 826 Local<Value> foo = v8_str("foo"); |
| 742 LocalContext context(CcTest::isolate()); | 827 LocalContext context(CcTest::isolate()); |
| 743 context->SetSecurityToken(foo); | 828 context->SetSecurityToken(foo); |
| 744 CompileRun("var obj = {};"); | 829 CompileRun("var obj = {};"); |
| 745 Handle<Value> object = CompileRun("obj"); | 830 Local<Value> object = CompileRun("obj"); |
| 746 Handle<Value> notifier = CompileRun("Object.getNotifier(obj)"); | 831 Local<Value> notifier = CompileRun("Object.getNotifier(obj)"); |
| 747 { | 832 { |
| 748 HandleScope scope(CcTest::isolate()); | 833 HandleScope scope(CcTest::isolate()); |
| 749 LocalContext context2(CcTest::isolate()); | 834 LocalContext context2(CcTest::isolate()); |
| 750 context2->SetSecurityToken(foo); | 835 context2->SetSecurityToken(foo); |
| 751 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), | 836 context2->Global() |
| 752 object); | 837 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 753 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "notifier"), | 838 object) |
| 754 notifier); | 839 .FromJust(); |
| 840 context2->Global() |
| 841 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 842 v8_str("notifier"), notifier) |
| 843 .FromJust(); |
| 755 CompileRun("var obj2 = {};" | 844 CompileRun("var obj2 = {};" |
| 756 "var notifier2 = Object.getNotifier(obj2);" | 845 "var notifier2 = Object.getNotifier(obj2);" |
| 757 "notifier2.performChange.call(" | 846 "notifier2.performChange.call(" |
| 758 "notifier, 'foo', function(){})"); | 847 "notifier, 'foo', function(){})"); |
| 759 } | 848 } |
| 760 | 849 |
| 761 CcTest::isolate()->ContextDisposedNotification(); | 850 CcTest::isolate()->ContextDisposedNotification(); |
| 762 CheckSurvivingGlobalObjectsCount(2); | 851 CheckSurvivingGlobalObjectsCount(2); |
| 763 } | 852 } |
| 764 | 853 |
| 765 | 854 |
| 766 static void ObserverCallback(const FunctionCallbackInfo<Value>& args) { | 855 static void ObserverCallback(const FunctionCallbackInfo<Value>& args) { |
| 767 *static_cast<int*>(Handle<External>::Cast(args.Data())->Value()) = | 856 *static_cast<int*>(Local<External>::Cast(args.Data())->Value()) = |
| 768 Handle<Array>::Cast(args[0])->Length(); | 857 Local<Array>::Cast(args[0])->Length(); |
| 769 } | 858 } |
| 770 | 859 |
| 771 | 860 |
| 772 TEST(ObjectObserveCallsCppFunction) { | 861 TEST(ObjectObserveCallsCppFunction) { |
| 773 Isolate* isolate = CcTest::isolate(); | 862 Isolate* isolate = CcTest::isolate(); |
| 774 HandleScope scope(isolate); | 863 HandleScope scope(isolate); |
| 775 LocalContext context(isolate); | 864 LocalContext context(isolate); |
| 776 int numRecordsSent = 0; | 865 int numRecordsSent = 0; |
| 777 Handle<Function> observer = | 866 Local<Function> observer = |
| 778 Function::New(CcTest::isolate(), ObserverCallback, | 867 Function::New(CcTest::isolate()->GetCurrentContext(), ObserverCallback, |
| 779 External::New(isolate, &numRecordsSent)); | 868 External::New(isolate, &numRecordsSent)) |
| 780 context->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "observer"), | 869 .ToLocalChecked(); |
| 781 observer); | 870 context->Global() |
| 871 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("observer"), |
| 872 observer) |
| 873 .FromJust(); |
| 782 CompileRun( | 874 CompileRun( |
| 783 "var obj = {};" | 875 "var obj = {};" |
| 784 "Object.observe(obj, observer);" | 876 "Object.observe(obj, observer);" |
| 785 "obj.foo = 1;" | 877 "obj.foo = 1;" |
| 786 "obj.bar = 2;"); | 878 "obj.bar = 2;"); |
| 787 CHECK_EQ(2, numRecordsSent); | 879 CHECK_EQ(2, numRecordsSent); |
| 788 } | 880 } |
| 789 | 881 |
| 790 | 882 |
| 791 TEST(ObjectObserveCallsFunctionTemplateInstance) { | 883 TEST(ObjectObserveCallsFunctionTemplateInstance) { |
| 792 Isolate* isolate = CcTest::isolate(); | 884 Isolate* isolate = CcTest::isolate(); |
| 793 HandleScope scope(isolate); | 885 HandleScope scope(isolate); |
| 794 LocalContext context(isolate); | 886 LocalContext context(isolate); |
| 795 int numRecordsSent = 0; | 887 int numRecordsSent = 0; |
| 796 Handle<FunctionTemplate> tmpl = FunctionTemplate::New( | 888 Local<FunctionTemplate> tmpl = FunctionTemplate::New( |
| 797 isolate, ObserverCallback, External::New(isolate, &numRecordsSent)); | 889 isolate, ObserverCallback, External::New(isolate, &numRecordsSent)); |
| 798 context->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "observer"), | 890 Local<Function> function = |
| 799 tmpl->GetFunction()); | 891 tmpl->GetFunction(v8::Isolate::GetCurrent()->GetCurrentContext()) |
| 892 .ToLocalChecked(); |
| 893 context->Global() |
| 894 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("observer"), |
| 895 function) |
| 896 .FromJust(); |
| 800 CompileRun( | 897 CompileRun( |
| 801 "var obj = {};" | 898 "var obj = {};" |
| 802 "Object.observe(obj, observer);" | 899 "Object.observe(obj, observer);" |
| 803 "obj.foo = 1;" | 900 "obj.foo = 1;" |
| 804 "obj.bar = 2;"); | 901 "obj.bar = 2;"); |
| 805 CHECK_EQ(2, numRecordsSent); | 902 CHECK_EQ(2, numRecordsSent); |
| 806 } | 903 } |
| 807 | 904 |
| 808 | 905 |
| 809 static void AccessorGetter(Local<String> property, | 906 static void AccessorGetter(Local<Name> property, |
| 810 const PropertyCallbackInfo<Value>& info) { | 907 const PropertyCallbackInfo<Value>& info) { |
| 811 info.GetReturnValue().Set(Integer::New(info.GetIsolate(), 42)); | 908 info.GetReturnValue().Set(Integer::New(info.GetIsolate(), 42)); |
| 812 } | 909 } |
| 813 | 910 |
| 814 | 911 |
| 815 static void AccessorSetter(Local<String> property, Local<Value> value, | 912 static void AccessorSetter(Local<Name> property, Local<Value> value, |
| 816 const PropertyCallbackInfo<void>& info) { | 913 const PropertyCallbackInfo<void>& info) { |
| 817 info.GetReturnValue().SetUndefined(); | 914 info.GetReturnValue().SetUndefined(); |
| 818 } | 915 } |
| 819 | 916 |
| 820 | 917 |
| 821 TEST(APIAccessorsShouldNotNotify) { | 918 TEST(APIAccessorsShouldNotNotify) { |
| 822 Isolate* isolate = CcTest::isolate(); | 919 Isolate* isolate = CcTest::isolate(); |
| 823 HandleScope handle_scope(isolate); | 920 HandleScope handle_scope(isolate); |
| 824 LocalContext context(isolate); | 921 LocalContext context(isolate); |
| 825 Handle<Object> object = Object::New(isolate); | 922 Local<Object> object = Object::New(isolate); |
| 826 object->SetAccessor(String::NewFromUtf8(isolate, "accessor"), &AccessorGetter, | 923 object->SetAccessor(v8::Isolate::GetCurrent()->GetCurrentContext(), |
| 827 &AccessorSetter); | 924 v8_str("accessor"), &AccessorGetter, &AccessorSetter) |
| 828 context->Global()->Set(String::NewFromUtf8(isolate, "obj"), object); | 925 .FromJust(); |
| 926 context->Global() |
| 927 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 928 object) |
| 929 .FromJust(); |
| 829 CompileRun( | 930 CompileRun( |
| 830 "var records = null;" | 931 "var records = null;" |
| 831 "Object.observe(obj, function(r) { records = r });" | 932 "Object.observe(obj, function(r) { records = r });" |
| 832 "obj.accessor = 43;"); | 933 "obj.accessor = 43;"); |
| 833 CHECK(CompileRun("records")->IsNull()); | 934 CHECK(CompileRun("records")->IsNull()); |
| 834 CompileRun("Object.defineProperty(obj, 'accessor', { value: 44 });"); | 935 CompileRun("Object.defineProperty(obj, 'accessor', { value: 44 });"); |
| 835 CHECK(CompileRun("records")->IsNull()); | 936 CHECK(CompileRun("records")->IsNull()); |
| 836 } | 937 } |
| 837 | 938 |
| 838 | 939 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 } | 996 } |
| 896 | 997 |
| 897 | 998 |
| 898 TEST(DisallowObserveAccessCheckedObject) { | 999 TEST(DisallowObserveAccessCheckedObject) { |
| 899 v8::Isolate* isolate = CcTest::isolate(); | 1000 v8::Isolate* isolate = CcTest::isolate(); |
| 900 v8::HandleScope scope(isolate); | 1001 v8::HandleScope scope(isolate); |
| 901 LocalContext env; | 1002 LocalContext env; |
| 902 v8::Local<v8::ObjectTemplate> object_template = | 1003 v8::Local<v8::ObjectTemplate> object_template = |
| 903 v8::ObjectTemplate::New(isolate); | 1004 v8::ObjectTemplate::New(isolate); |
| 904 object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL); | 1005 object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL); |
| 905 env->Global()->Set(v8_str("obj"), object_template->NewInstance()); | 1006 Local<Object> new_instance = |
| 1007 object_template->NewInstance( |
| 1008 v8::Isolate::GetCurrent()->GetCurrentContext()) |
| 1009 .ToLocalChecked(); |
| 1010 env->Global() |
| 1011 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 1012 new_instance) |
| 1013 .FromJust(); |
| 906 v8::TryCatch try_catch(isolate); | 1014 v8::TryCatch try_catch(isolate); |
| 907 CompileRun("Object.observe(obj, function(){})"); | 1015 CompileRun("Object.observe(obj, function(){})"); |
| 908 CHECK(try_catch.HasCaught()); | 1016 CHECK(try_catch.HasCaught()); |
| 909 } | 1017 } |
| 910 | 1018 |
| 911 | 1019 |
| 912 TEST(DisallowGetNotifierAccessCheckedObject) { | 1020 TEST(DisallowGetNotifierAccessCheckedObject) { |
| 913 v8::Isolate* isolate = CcTest::isolate(); | 1021 v8::Isolate* isolate = CcTest::isolate(); |
| 914 v8::HandleScope scope(isolate); | 1022 v8::HandleScope scope(isolate); |
| 915 LocalContext env; | 1023 LocalContext env; |
| 916 v8::Local<v8::ObjectTemplate> object_template = | 1024 v8::Local<v8::ObjectTemplate> object_template = |
| 917 v8::ObjectTemplate::New(isolate); | 1025 v8::ObjectTemplate::New(isolate); |
| 918 object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL); | 1026 object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL); |
| 919 env->Global()->Set(v8_str("obj"), object_template->NewInstance()); | 1027 Local<Object> new_instance = |
| 1028 object_template->NewInstance( |
| 1029 v8::Isolate::GetCurrent()->GetCurrentContext()) |
| 1030 .ToLocalChecked(); |
| 1031 env->Global() |
| 1032 ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), |
| 1033 new_instance) |
| 1034 .FromJust(); |
| 920 v8::TryCatch try_catch(isolate); | 1035 v8::TryCatch try_catch(isolate); |
| 921 CompileRun("Object.getNotifier(obj)"); | 1036 CompileRun("Object.getNotifier(obj)"); |
| 922 CHECK(try_catch.HasCaught()); | 1037 CHECK(try_catch.HasCaught()); |
| 923 } | 1038 } |
| OLD | NEW |