| 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 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 private: | 52 private: |
| 53 Isolate* isolate_; | 53 Isolate* isolate_; |
| 54 }; | 54 }; |
| 55 } | 55 } |
| 56 | 56 |
| 57 | 57 |
| 58 TEST(PerIsolateState) { | 58 TEST(PerIsolateState) { |
| 59 HarmonyIsolate isolate; | 59 HarmonyIsolate isolate; |
| 60 HandleScope scope(isolate.GetIsolate()); | 60 HandleScope scope(isolate.GetIsolate()); |
| 61 LocalContext context1; | 61 LocalContext context1(isolate.GetIsolate()); |
| 62 CompileRun( | 62 CompileRun( |
| 63 "var count = 0;" | 63 "var count = 0;" |
| 64 "var calls = 0;" | 64 "var calls = 0;" |
| 65 "var observer = function(records) { count = records.length; calls++ };" | 65 "var observer = function(records) { count = records.length; calls++ };" |
| 66 "var obj = {};" | 66 "var obj = {};" |
| 67 "Object.observe(obj, observer);"); | 67 "Object.observe(obj, observer);"); |
| 68 Handle<Value> observer = CompileRun("observer"); | 68 Handle<Value> observer = CompileRun("observer"); |
| 69 Handle<Value> obj = CompileRun("obj"); | 69 Handle<Value> obj = CompileRun("obj"); |
| 70 Handle<Value> notify_fun1 = CompileRun( | 70 Handle<Value> notify_fun1 = CompileRun( |
| 71 "(function() { obj.foo = 'bar'; })"); | 71 "(function() { obj.foo = 'bar'; })"); |
| 72 Handle<Value> notify_fun2; | 72 Handle<Value> notify_fun2; |
| 73 { | 73 { |
| 74 LocalContext context2; | 74 LocalContext context2(isolate.GetIsolate()); |
| 75 context2->Global()->Set(String::New("obj"), obj); | 75 context2->Global()->Set(String::New("obj"), obj); |
| 76 notify_fun2 = CompileRun( | 76 notify_fun2 = CompileRun( |
| 77 "(function() { obj.foo = 'baz'; })"); | 77 "(function() { obj.foo = 'baz'; })"); |
| 78 } | 78 } |
| 79 Handle<Value> notify_fun3; | 79 Handle<Value> notify_fun3; |
| 80 { | 80 { |
| 81 LocalContext context3; | 81 LocalContext context3(isolate.GetIsolate()); |
| 82 context3->Global()->Set(String::New("obj"), obj); | 82 context3->Global()->Set(String::New("obj"), obj); |
| 83 notify_fun3 = CompileRun( | 83 notify_fun3 = CompileRun( |
| 84 "(function() { obj.foo = 'bat'; })"); | 84 "(function() { obj.foo = 'bat'; })"); |
| 85 } | 85 } |
| 86 { | 86 { |
| 87 LocalContext context4; | 87 LocalContext context4(isolate.GetIsolate()); |
| 88 context4->Global()->Set(String::New("observer"), observer); | 88 context4->Global()->Set(String::New("observer"), observer); |
| 89 context4->Global()->Set(String::New("fun1"), notify_fun1); | 89 context4->Global()->Set(String::New("fun1"), notify_fun1); |
| 90 context4->Global()->Set(String::New("fun2"), notify_fun2); | 90 context4->Global()->Set(String::New("fun2"), notify_fun2); |
| 91 context4->Global()->Set(String::New("fun3"), notify_fun3); | 91 context4->Global()->Set(String::New("fun3"), notify_fun3); |
| 92 CompileRun("fun1(); fun2(); fun3(); Object.deliverChangeRecords(observer)"); | 92 CompileRun("fun1(); fun2(); fun3(); Object.deliverChangeRecords(observer)"); |
| 93 } | 93 } |
| 94 CHECK_EQ(1, CompileRun("calls")->Int32Value()); | 94 CHECK_EQ(1, CompileRun("calls")->Int32Value()); |
| 95 CHECK_EQ(3, CompileRun("count")->Int32Value()); | 95 CHECK_EQ(3, CompileRun("count")->Int32Value()); |
| 96 } | 96 } |
| 97 | 97 |
| 98 | 98 |
| 99 TEST(EndOfMicrotaskDelivery) { | 99 TEST(EndOfMicrotaskDelivery) { |
| 100 HarmonyIsolate isolate; | 100 HarmonyIsolate isolate; |
| 101 HandleScope scope(isolate.GetIsolate()); | 101 HandleScope scope(isolate.GetIsolate()); |
| 102 LocalContext context; | 102 LocalContext context(isolate.GetIsolate()); |
| 103 CompileRun( | 103 CompileRun( |
| 104 "var obj = {};" | 104 "var obj = {};" |
| 105 "var count = 0;" | 105 "var count = 0;" |
| 106 "var observer = function(records) { count = records.length };" | 106 "var observer = function(records) { count = records.length };" |
| 107 "Object.observe(obj, observer);" | 107 "Object.observe(obj, observer);" |
| 108 "obj.foo = 'bar';"); | 108 "obj.foo = 'bar';"); |
| 109 CHECK_EQ(1, CompileRun("count")->Int32Value()); | 109 CHECK_EQ(1, CompileRun("count")->Int32Value()); |
| 110 } | 110 } |
| 111 | 111 |
| 112 | 112 |
| 113 TEST(DeliveryOrdering) { | 113 TEST(DeliveryOrdering) { |
| 114 HarmonyIsolate isolate; | 114 HarmonyIsolate isolate; |
| 115 HandleScope scope(isolate.GetIsolate()); | 115 HandleScope scope(isolate.GetIsolate()); |
| 116 LocalContext context; | 116 LocalContext context(isolate.GetIsolate()); |
| 117 CompileRun( | 117 CompileRun( |
| 118 "var obj1 = {};" | 118 "var obj1 = {};" |
| 119 "var obj2 = {};" | 119 "var obj2 = {};" |
| 120 "var ordering = [];" | 120 "var ordering = [];" |
| 121 "function observer2() { ordering.push(2); };" | 121 "function observer2() { ordering.push(2); };" |
| 122 "function observer1() { ordering.push(1); };" | 122 "function observer1() { ordering.push(1); };" |
| 123 "function observer3() { ordering.push(3); };" | 123 "function observer3() { ordering.push(3); };" |
| 124 "Object.observe(obj1, observer1);" | 124 "Object.observe(obj1, observer1);" |
| 125 "Object.observe(obj1, observer2);" | 125 "Object.observe(obj1, observer2);" |
| 126 "Object.observe(obj1, observer3);" | 126 "Object.observe(obj1, observer3);" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 138 CHECK_EQ(3, CompileRun("ordering.length")->Int32Value()); | 138 CHECK_EQ(3, CompileRun("ordering.length")->Int32Value()); |
| 139 CHECK_EQ(1, CompileRun("ordering[0]")->Int32Value()); | 139 CHECK_EQ(1, CompileRun("ordering[0]")->Int32Value()); |
| 140 CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value()); | 140 CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value()); |
| 141 CHECK_EQ(3, CompileRun("ordering[2]")->Int32Value()); | 141 CHECK_EQ(3, CompileRun("ordering[2]")->Int32Value()); |
| 142 } | 142 } |
| 143 | 143 |
| 144 | 144 |
| 145 TEST(DeliveryOrderingReentrant) { | 145 TEST(DeliveryOrderingReentrant) { |
| 146 HarmonyIsolate isolate; | 146 HarmonyIsolate isolate; |
| 147 HandleScope scope(isolate.GetIsolate()); | 147 HandleScope scope(isolate.GetIsolate()); |
| 148 LocalContext context; | 148 LocalContext context(isolate.GetIsolate()); |
| 149 CompileRun( | 149 CompileRun( |
| 150 "var obj = {};" | 150 "var obj = {};" |
| 151 "var reentered = false;" | 151 "var reentered = false;" |
| 152 "var ordering = [];" | 152 "var ordering = [];" |
| 153 "function observer1() { ordering.push(1); };" | 153 "function observer1() { ordering.push(1); };" |
| 154 "function observer2() {" | 154 "function observer2() {" |
| 155 " if (!reentered) {" | 155 " if (!reentered) {" |
| 156 " obj.foo = 'baz';" | 156 " obj.foo = 'baz';" |
| 157 " reentered = true;" | 157 " reentered = true;" |
| 158 " }" | 158 " }" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 170 // Note that we re-deliver to observers 1 and 2, while observer3 | 170 // Note that we re-deliver to observers 1 and 2, while observer3 |
| 171 // already received the second record during the first round. | 171 // already received the second record during the first round. |
| 172 CHECK_EQ(1, CompileRun("ordering[3]")->Int32Value()); | 172 CHECK_EQ(1, CompileRun("ordering[3]")->Int32Value()); |
| 173 CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value()); | 173 CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value()); |
| 174 } | 174 } |
| 175 | 175 |
| 176 | 176 |
| 177 TEST(DeliveryOrderingDeliverChangeRecords) { | 177 TEST(DeliveryOrderingDeliverChangeRecords) { |
| 178 HarmonyIsolate isolate; | 178 HarmonyIsolate isolate; |
| 179 HandleScope scope(isolate.GetIsolate()); | 179 HandleScope scope(isolate.GetIsolate()); |
| 180 LocalContext context; | 180 LocalContext context(isolate.GetIsolate()); |
| 181 CompileRun( | 181 CompileRun( |
| 182 "var obj = {};" | 182 "var obj = {};" |
| 183 "var ordering = [];" | 183 "var ordering = [];" |
| 184 "function observer1() { ordering.push(1); if (!obj.b) obj.b = true };" | 184 "function observer1() { ordering.push(1); if (!obj.b) obj.b = true };" |
| 185 "function observer2() { ordering.push(2); };" | 185 "function observer2() { ordering.push(2); };" |
| 186 "Object.observe(obj, observer1);" | 186 "Object.observe(obj, observer1);" |
| 187 "Object.observe(obj, observer2);" | 187 "Object.observe(obj, observer2);" |
| 188 "obj.a = 1;" | 188 "obj.a = 1;" |
| 189 "Object.deliverChangeRecords(observer2);"); | 189 "Object.deliverChangeRecords(observer2);"); |
| 190 CHECK_EQ(4, CompileRun("ordering.length")->Int32Value()); | 190 CHECK_EQ(4, CompileRun("ordering.length")->Int32Value()); |
| 191 // First, observer2 is called due to deliverChangeRecords | 191 // First, observer2 is called due to deliverChangeRecords |
| 192 CHECK_EQ(2, CompileRun("ordering[0]")->Int32Value()); | 192 CHECK_EQ(2, CompileRun("ordering[0]")->Int32Value()); |
| 193 // Then, observer1 is called when the stack unwinds | 193 // Then, observer1 is called when the stack unwinds |
| 194 CHECK_EQ(1, CompileRun("ordering[1]")->Int32Value()); | 194 CHECK_EQ(1, CompileRun("ordering[1]")->Int32Value()); |
| 195 // observer1's mutation causes both 1 and 2 to be reactivated, | 195 // observer1's mutation causes both 1 and 2 to be reactivated, |
| 196 // with 1 having priority. | 196 // with 1 having priority. |
| 197 CHECK_EQ(1, CompileRun("ordering[2]")->Int32Value()); | 197 CHECK_EQ(1, CompileRun("ordering[2]")->Int32Value()); |
| 198 CHECK_EQ(2, CompileRun("ordering[3]")->Int32Value()); | 198 CHECK_EQ(2, CompileRun("ordering[3]")->Int32Value()); |
| 199 } | 199 } |
| 200 | 200 |
| 201 | 201 |
| 202 TEST(ObjectHashTableGrowth) { | 202 TEST(ObjectHashTableGrowth) { |
| 203 HarmonyIsolate isolate; | 203 HarmonyIsolate isolate; |
| 204 HandleScope scope(isolate.GetIsolate()); | 204 HandleScope scope(isolate.GetIsolate()); |
| 205 // Initializing this context sets up initial hash tables. | 205 // Initializing this context sets up initial hash tables. |
| 206 LocalContext context; | 206 LocalContext context(isolate.GetIsolate()); |
| 207 Handle<Value> obj = CompileRun("obj = {};"); | 207 Handle<Value> obj = CompileRun("obj = {};"); |
| 208 Handle<Value> observer = CompileRun( | 208 Handle<Value> observer = CompileRun( |
| 209 "var ran = false;" | 209 "var ran = false;" |
| 210 "(function() { ran = true })"); | 210 "(function() { ran = true })"); |
| 211 { | 211 { |
| 212 // As does initializing this context. | 212 // As does initializing this context. |
| 213 LocalContext context2; | 213 LocalContext context2(isolate.GetIsolate()); |
| 214 context2->Global()->Set(String::New("obj"), obj); | 214 context2->Global()->Set(String::New("obj"), obj); |
| 215 context2->Global()->Set(String::New("observer"), observer); | 215 context2->Global()->Set(String::New("observer"), observer); |
| 216 CompileRun( | 216 CompileRun( |
| 217 "var objArr = [];" | 217 "var objArr = [];" |
| 218 // 100 objects should be enough to make the hash table grow | 218 // 100 objects should be enough to make the hash table grow |
| 219 // (and thus relocate). | 219 // (and thus relocate). |
| 220 "for (var i = 0; i < 100; ++i) {" | 220 "for (var i = 0; i < 100; ++i) {" |
| 221 " objArr.push({});" | 221 " objArr.push({});" |
| 222 " Object.observe(objArr[objArr.length-1], function(){});" | 222 " Object.observe(objArr[objArr.length-1], function(){});" |
| 223 "}" | 223 "}" |
| 224 "Object.observe(obj, observer);"); | 224 "Object.observe(obj, observer);"); |
| 225 } | 225 } |
| 226 // obj is now marked "is_observed", but our map has moved. | 226 // obj is now marked "is_observed", but our map has moved. |
| 227 CompileRun("obj.foo = 'bar'"); | 227 CompileRun("obj.foo = 'bar'"); |
| 228 CHECK(CompileRun("ran")->BooleanValue()); | 228 CHECK(CompileRun("ran")->BooleanValue()); |
| 229 } | 229 } |
| 230 | 230 |
| 231 | 231 |
| 232 TEST(GlobalObjectObservation) { | 232 TEST(GlobalObjectObservation) { |
| 233 HarmonyIsolate isolate; | 233 HarmonyIsolate isolate; |
| 234 LocalContext context; | 234 LocalContext context(isolate.GetIsolate()); |
| 235 HandleScope scope(isolate.GetIsolate()); | 235 HandleScope scope(isolate.GetIsolate()); |
| 236 Handle<Object> global_proxy = context->Global(); | 236 Handle<Object> global_proxy = context->Global(); |
| 237 Handle<Object> inner_global = global_proxy->GetPrototype().As<Object>(); | 237 Handle<Object> inner_global = global_proxy->GetPrototype().As<Object>(); |
| 238 CompileRun( | 238 CompileRun( |
| 239 "var records = [];" | 239 "var records = [];" |
| 240 "var global = this;" | 240 "var global = this;" |
| 241 "Object.observe(global, function(r) { [].push.apply(records, r) });" | 241 "Object.observe(global, function(r) { [].push.apply(records, r) });" |
| 242 "global.foo = 'hello';"); | 242 "global.foo = 'hello';"); |
| 243 CHECK_EQ(1, CompileRun("records.length")->Int32Value()); | 243 CHECK_EQ(1, CompileRun("records.length")->Int32Value()); |
| 244 CHECK(global_proxy->StrictEquals(CompileRun("records[0].object"))); | 244 CHECK(global_proxy->StrictEquals(CompileRun("records[0].object"))); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 256 // Reattached, back to global proxy. | 256 // Reattached, back to global proxy. |
| 257 context->ReattachGlobal(global_proxy); | 257 context->ReattachGlobal(global_proxy); |
| 258 CompileRun("global.baz = 'again';"); | 258 CompileRun("global.baz = 'again';"); |
| 259 CHECK_EQ(3, CompileRun("records.length")->Int32Value()); | 259 CHECK_EQ(3, CompileRun("records.length")->Int32Value()); |
| 260 CHECK(global_proxy->StrictEquals(CompileRun("records[2].object"))); | 260 CHECK(global_proxy->StrictEquals(CompileRun("records[2].object"))); |
| 261 | 261 |
| 262 // Attached to a different context, should not leak mutations | 262 // Attached to a different context, should not leak mutations |
| 263 // to the old context. | 263 // to the old context. |
| 264 context->DetachGlobal(); | 264 context->DetachGlobal(); |
| 265 { | 265 { |
| 266 LocalContext context2; | 266 LocalContext context2(isolate.GetIsolate()); |
| 267 context2->DetachGlobal(); | 267 context2->DetachGlobal(); |
| 268 context2->ReattachGlobal(global_proxy); | 268 context2->ReattachGlobal(global_proxy); |
| 269 CompileRun( | 269 CompileRun( |
| 270 "var records2 = [];" | 270 "var records2 = [];" |
| 271 "Object.observe(this, function(r) { [].push.apply(records2, r) });" | 271 "Object.observe(this, function(r) { [].push.apply(records2, r) });" |
| 272 "this.bat = 'context2';"); | 272 "this.bat = 'context2';"); |
| 273 CHECK_EQ(1, CompileRun("records2.length")->Int32Value()); | 273 CHECK_EQ(1, CompileRun("records2.length")->Int32Value()); |
| 274 CHECK(global_proxy->StrictEquals(CompileRun("records2[0].object"))); | 274 CHECK(global_proxy->StrictEquals(CompileRun("records2[0].object"))); |
| 275 } | 275 } |
| 276 CHECK_EQ(3, CompileRun("records.length")->Int32Value()); | 276 CHECK_EQ(3, CompileRun("records.length")->Int32Value()); |
| 277 | 277 |
| 278 // Attaching by passing to Context::New | 278 // Attaching by passing to Context::New |
| 279 { | 279 { |
| 280 // Delegates to Context::New | 280 // Delegates to Context::New |
| 281 LocalContext context3(NULL, Handle<ObjectTemplate>(), global_proxy); | 281 LocalContext context3( |
| 282 isolate.GetIsolate(), NULL, Handle<ObjectTemplate>(), global_proxy); |
| 282 CompileRun( | 283 CompileRun( |
| 283 "var records3 = [];" | 284 "var records3 = [];" |
| 284 "Object.observe(this, function(r) { [].push.apply(records3, r) });" | 285 "Object.observe(this, function(r) { [].push.apply(records3, r) });" |
| 285 "this.qux = 'context3';"); | 286 "this.qux = 'context3';"); |
| 286 CHECK_EQ(1, CompileRun("records3.length")->Int32Value()); | 287 CHECK_EQ(1, CompileRun("records3.length")->Int32Value()); |
| 287 CHECK(global_proxy->StrictEquals(CompileRun("records3[0].object"))); | 288 CHECK(global_proxy->StrictEquals(CompileRun("records3[0].object"))); |
| 288 } | 289 } |
| 289 CHECK_EQ(3, CompileRun("records.length")->Int32Value()); | 290 CHECK_EQ(3, CompileRun("records.length")->Int32Value()); |
| 290 } | 291 } |
| 291 | 292 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 } | 324 } |
| 324 } | 325 } |
| 325 } | 326 } |
| 326 | 327 |
| 327 #define EXPECT_RECORDS(records, expectations) \ | 328 #define EXPECT_RECORDS(records, expectations) \ |
| 328 ExpectRecords(records, expectations, ARRAY_SIZE(expectations)) | 329 ExpectRecords(records, expectations, ARRAY_SIZE(expectations)) |
| 329 | 330 |
| 330 TEST(APITestBasicMutation) { | 331 TEST(APITestBasicMutation) { |
| 331 HarmonyIsolate isolate; | 332 HarmonyIsolate isolate; |
| 332 HandleScope scope(isolate.GetIsolate()); | 333 HandleScope scope(isolate.GetIsolate()); |
| 333 LocalContext context; | 334 LocalContext context(isolate.GetIsolate()); |
| 334 Handle<Object> obj = Handle<Object>::Cast(CompileRun( | 335 Handle<Object> obj = Handle<Object>::Cast(CompileRun( |
| 335 "var records = [];" | 336 "var records = [];" |
| 336 "var obj = {};" | 337 "var obj = {};" |
| 337 "function observer(r) { [].push.apply(records, r); };" | 338 "function observer(r) { [].push.apply(records, r); };" |
| 338 "Object.observe(obj, observer);" | 339 "Object.observe(obj, observer);" |
| 339 "obj")); | 340 "obj")); |
| 340 obj->Set(String::New("foo"), Number::New(7)); | 341 obj->Set(String::New("foo"), Number::New(7)); |
| 341 obj->Set(1, Number::New(2)); | 342 obj->Set(1, Number::New(2)); |
| 342 // ForceSet should work just as well as Set | 343 // ForceSet should work just as well as Set |
| 343 obj->ForceSet(String::New("foo"), Number::New(3)); | 344 obj->ForceSet(String::New("foo"), Number::New(3)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 367 { obj, "deleted", "1", Number::New(5) }, | 368 { obj, "deleted", "1", Number::New(5) }, |
| 368 { obj, "deleted", "1.1", Number::New(6) } | 369 { obj, "deleted", "1.1", Number::New(6) } |
| 369 }; | 370 }; |
| 370 EXPECT_RECORDS(CompileRun("records"), expected_records); | 371 EXPECT_RECORDS(CompileRun("records"), expected_records); |
| 371 } | 372 } |
| 372 | 373 |
| 373 | 374 |
| 374 TEST(HiddenPrototypeObservation) { | 375 TEST(HiddenPrototypeObservation) { |
| 375 HarmonyIsolate isolate; | 376 HarmonyIsolate isolate; |
| 376 HandleScope scope(isolate.GetIsolate()); | 377 HandleScope scope(isolate.GetIsolate()); |
| 377 LocalContext context; | 378 LocalContext context(isolate.GetIsolate()); |
| 378 Handle<FunctionTemplate> tmpl = FunctionTemplate::New(); | 379 Handle<FunctionTemplate> tmpl = FunctionTemplate::New(); |
| 379 tmpl->SetHiddenPrototype(true); | 380 tmpl->SetHiddenPrototype(true); |
| 380 tmpl->InstanceTemplate()->Set(String::New("foo"), Number::New(75)); | 381 tmpl->InstanceTemplate()->Set(String::New("foo"), Number::New(75)); |
| 381 Handle<Object> proto = tmpl->GetFunction()->NewInstance(); | 382 Handle<Object> proto = tmpl->GetFunction()->NewInstance(); |
| 382 Handle<Object> obj = Object::New(); | 383 Handle<Object> obj = Object::New(); |
| 383 obj->SetPrototype(proto); | 384 obj->SetPrototype(proto); |
| 384 context->Global()->Set(String::New("obj"), obj); | 385 context->Global()->Set(String::New("obj"), obj); |
| 385 context->Global()->Set(String::New("proto"), proto); | 386 context->Global()->Set(String::New("proto"), proto); |
| 386 CompileRun( | 387 CompileRun( |
| 387 "var records;" | 388 "var records;" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 416 | 417 |
| 417 | 418 |
| 418 static int NumberOfElements(i::Handle<i::JSWeakMap> map) { | 419 static int NumberOfElements(i::Handle<i::JSWeakMap> map) { |
| 419 return i::ObjectHashTable::cast(map->table())->NumberOfElements(); | 420 return i::ObjectHashTable::cast(map->table())->NumberOfElements(); |
| 420 } | 421 } |
| 421 | 422 |
| 422 | 423 |
| 423 TEST(ObservationWeakMap) { | 424 TEST(ObservationWeakMap) { |
| 424 HarmonyIsolate isolate; | 425 HarmonyIsolate isolate; |
| 425 HandleScope scope(isolate.GetIsolate()); | 426 HandleScope scope(isolate.GetIsolate()); |
| 426 LocalContext context; | 427 LocalContext context(isolate.GetIsolate()); |
| 427 CompileRun( | 428 CompileRun( |
| 428 "var obj = {};" | 429 "var obj = {};" |
| 429 "Object.observe(obj, function(){});" | 430 "Object.observe(obj, function(){});" |
| 430 "Object.getNotifier(obj);" | 431 "Object.getNotifier(obj);" |
| 431 "obj = null;"); | 432 "obj = null;"); |
| 432 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate.GetIsolate()); | 433 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate.GetIsolate()); |
| 433 i::Handle<i::JSObject> observation_state = | 434 i::Handle<i::JSObject> observation_state = |
| 434 i_isolate->factory()->observation_state(); | 435 i_isolate->factory()->observation_state(); |
| 435 i::Handle<i::JSWeakMap> callbackInfoMap = | 436 i::Handle<i::JSWeakMap> callbackInfoMap = |
| 436 i::Handle<i::JSWeakMap>::cast( | 437 i::Handle<i::JSWeakMap>::cast( |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 instance->CreationContext()->Global()->Set(String::New("obj"), instance); | 511 instance->CreationContext()->Global()->Set(String::New("obj"), instance); |
| 511 return instance; | 512 return instance; |
| 512 } | 513 } |
| 513 | 514 |
| 514 | 515 |
| 515 TEST(NamedAccessCheck) { | 516 TEST(NamedAccessCheck) { |
| 516 HarmonyIsolate isolate; | 517 HarmonyIsolate isolate; |
| 517 const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; | 518 const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; |
| 518 for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { | 519 for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { |
| 519 HandleScope scope(isolate.GetIsolate()); | 520 HandleScope scope(isolate.GetIsolate()); |
| 520 LocalContext context; | 521 LocalContext context(isolate.GetIsolate()); |
| 521 g_access_block_type = types[i]; | 522 g_access_block_type = types[i]; |
| 522 Handle<Object> instance = CreateAccessCheckedObject( | 523 Handle<Object> instance = CreateAccessCheckedObject( |
| 523 NamedAccessAllowUnlessBlocked, IndexedAccessAlwaysAllowed); | 524 NamedAccessAllowUnlessBlocked, IndexedAccessAlwaysAllowed); |
| 524 CompileRun("var records = null;" | 525 CompileRun("var records = null;" |
| 525 "var objNoCheck = {};" | 526 "var objNoCheck = {};" |
| 526 "var blacklist = {foo: true};" | 527 "var blacklist = {foo: true};" |
| 527 "var observer = function(r) { records = r };" | 528 "var observer = function(r) { records = r };" |
| 528 "Object.observe(obj, observer);" | 529 "Object.observe(obj, observer);" |
| 529 "Object.observe(objNoCheck, observer);"); | 530 "Object.observe(objNoCheck, observer);"); |
| 530 Handle<Value> obj_no_check = CompileRun("objNoCheck"); | 531 Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| 531 { | 532 { |
| 532 LocalContext context2; | 533 LocalContext context2(isolate.GetIsolate()); |
| 533 context2->Global()->Set(String::New("obj"), instance); | 534 context2->Global()->Set(String::New("obj"), instance); |
| 534 context2->Global()->Set(String::New("objNoCheck"), obj_no_check); | 535 context2->Global()->Set(String::New("objNoCheck"), obj_no_check); |
| 535 CompileRun("var records2 = null;" | 536 CompileRun("var records2 = null;" |
| 536 "var observer2 = function(r) { records2 = r };" | 537 "var observer2 = function(r) { records2 = r };" |
| 537 "Object.observe(obj, observer2);" | 538 "Object.observe(obj, observer2);" |
| 538 "Object.observe(objNoCheck, observer2);" | 539 "Object.observe(objNoCheck, observer2);" |
| 539 "obj.foo = 'bar';" | 540 "obj.foo = 'bar';" |
| 540 "Object.defineProperty(obj, 'foo', {value: 5});" | 541 "Object.defineProperty(obj, 'foo', {value: 5});" |
| 541 "Object.defineProperty(obj, 'foo', {get: function(){}});" | 542 "Object.defineProperty(obj, 'foo', {get: function(){}});" |
| 542 "obj.bar = 'baz';" | 543 "obj.bar = 'baz';" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 557 EXPECT_RECORDS(CompileRun("records"), expected_records); | 558 EXPECT_RECORDS(CompileRun("records"), expected_records); |
| 558 } | 559 } |
| 559 } | 560 } |
| 560 | 561 |
| 561 | 562 |
| 562 TEST(IndexedAccessCheck) { | 563 TEST(IndexedAccessCheck) { |
| 563 HarmonyIsolate isolate; | 564 HarmonyIsolate isolate; |
| 564 const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; | 565 const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; |
| 565 for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { | 566 for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { |
| 566 HandleScope scope(isolate.GetIsolate()); | 567 HandleScope scope(isolate.GetIsolate()); |
| 567 LocalContext context; | 568 LocalContext context(isolate.GetIsolate()); |
| 568 g_access_block_type = types[i]; | 569 g_access_block_type = types[i]; |
| 569 Handle<Object> instance = CreateAccessCheckedObject( | 570 Handle<Object> instance = CreateAccessCheckedObject( |
| 570 NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked); | 571 NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked); |
| 571 CompileRun("var records = null;" | 572 CompileRun("var records = null;" |
| 572 "var objNoCheck = {};" | 573 "var objNoCheck = {};" |
| 573 "var blacklist = {7: true};" | 574 "var blacklist = {7: true};" |
| 574 "var observer = function(r) { records = r };" | 575 "var observer = function(r) { records = r };" |
| 575 "Object.observe(obj, observer);" | 576 "Object.observe(obj, observer);" |
| 576 "Object.observe(objNoCheck, observer);"); | 577 "Object.observe(objNoCheck, observer);"); |
| 577 Handle<Value> obj_no_check = CompileRun("objNoCheck"); | 578 Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| 578 { | 579 { |
| 579 LocalContext context2; | 580 LocalContext context2(isolate.GetIsolate()); |
| 580 context2->Global()->Set(String::New("obj"), instance); | 581 context2->Global()->Set(String::New("obj"), instance); |
| 581 context2->Global()->Set(String::New("objNoCheck"), obj_no_check); | 582 context2->Global()->Set(String::New("objNoCheck"), obj_no_check); |
| 582 CompileRun("var records2 = null;" | 583 CompileRun("var records2 = null;" |
| 583 "var observer2 = function(r) { records2 = r };" | 584 "var observer2 = function(r) { records2 = r };" |
| 584 "Object.observe(obj, observer2);" | 585 "Object.observe(obj, observer2);" |
| 585 "Object.observe(objNoCheck, observer2);" | 586 "Object.observe(objNoCheck, observer2);" |
| 586 "obj[7] = 'foo';" | 587 "obj[7] = 'foo';" |
| 587 "Object.defineProperty(obj, '7', {value: 5});" | 588 "Object.defineProperty(obj, '7', {value: 5});" |
| 588 "Object.defineProperty(obj, '7', {get: function(){}});" | 589 "Object.defineProperty(obj, '7', {get: function(){}});" |
| 589 "obj[8] = 'bar';" | 590 "obj[8] = 'bar';" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 602 { obj_no_check, "new", "42", Handle<Value>() } | 603 { obj_no_check, "new", "42", Handle<Value>() } |
| 603 }; | 604 }; |
| 604 EXPECT_RECORDS(CompileRun("records"), expected_records); | 605 EXPECT_RECORDS(CompileRun("records"), expected_records); |
| 605 } | 606 } |
| 606 } | 607 } |
| 607 | 608 |
| 608 | 609 |
| 609 TEST(SpliceAccessCheck) { | 610 TEST(SpliceAccessCheck) { |
| 610 HarmonyIsolate isolate; | 611 HarmonyIsolate isolate; |
| 611 HandleScope scope(isolate.GetIsolate()); | 612 HandleScope scope(isolate.GetIsolate()); |
| 612 LocalContext context; | 613 LocalContext context(isolate.GetIsolate()); |
| 613 g_access_block_type = ACCESS_GET; | 614 g_access_block_type = ACCESS_GET; |
| 614 Handle<Object> instance = CreateAccessCheckedObject( | 615 Handle<Object> instance = CreateAccessCheckedObject( |
| 615 NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked); | 616 NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked); |
| 616 CompileRun("var records = null;" | 617 CompileRun("var records = null;" |
| 617 "obj[1] = 'foo';" | 618 "obj[1] = 'foo';" |
| 618 "obj.length = 2;" | 619 "obj.length = 2;" |
| 619 "var objNoCheck = {1: 'bar', length: 2};" | 620 "var objNoCheck = {1: 'bar', length: 2};" |
| 620 "var blacklist = {1: true};" | 621 "var blacklist = {1: true};" |
| 621 "observer = function(r) { records = r };" | 622 "observer = function(r) { records = r };" |
| 622 "Array.observe(obj, observer);" | 623 "Array.observe(obj, observer);" |
| 623 "Array.observe(objNoCheck, observer);"); | 624 "Array.observe(objNoCheck, observer);"); |
| 624 Handle<Value> obj_no_check = CompileRun("objNoCheck"); | 625 Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| 625 { | 626 { |
| 626 LocalContext context2; | 627 LocalContext context2(isolate.GetIsolate()); |
| 627 context2->Global()->Set(String::New("obj"), instance); | 628 context2->Global()->Set(String::New("obj"), instance); |
| 628 context2->Global()->Set(String::New("objNoCheck"), obj_no_check); | 629 context2->Global()->Set(String::New("objNoCheck"), obj_no_check); |
| 629 CompileRun("var records2 = null;" | 630 CompileRun("var records2 = null;" |
| 630 "var observer2 = function(r) { records2 = r };" | 631 "var observer2 = function(r) { records2 = r };" |
| 631 "Array.observe(obj, observer2);" | 632 "Array.observe(obj, observer2);" |
| 632 "Array.observe(objNoCheck, observer2);" | 633 "Array.observe(objNoCheck, observer2);" |
| 633 // No one should hear about this: no splice records are emitted | 634 // No one should hear about this: no splice records are emitted |
| 634 // for access-checked objects | 635 // for access-checked objects |
| 635 "[].push.call(obj, 5);" | 636 "[].push.call(obj, 5);" |
| 636 "[].splice.call(obj, 1, 1);" | 637 "[].splice.call(obj, 1, 1);" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 647 const RecordExpectation expected_records[] = { | 648 const RecordExpectation expected_records[] = { |
| 648 { obj_no_check, "splice", "", Handle<Value>() } | 649 { obj_no_check, "splice", "", Handle<Value>() } |
| 649 }; | 650 }; |
| 650 EXPECT_RECORDS(CompileRun("records"), expected_records); | 651 EXPECT_RECORDS(CompileRun("records"), expected_records); |
| 651 } | 652 } |
| 652 | 653 |
| 653 | 654 |
| 654 TEST(DisallowAllForAccessKeys) { | 655 TEST(DisallowAllForAccessKeys) { |
| 655 HarmonyIsolate isolate; | 656 HarmonyIsolate isolate; |
| 656 HandleScope scope(isolate.GetIsolate()); | 657 HandleScope scope(isolate.GetIsolate()); |
| 657 LocalContext context; | 658 LocalContext context(isolate.GetIsolate()); |
| 658 Handle<Object> instance = CreateAccessCheckedObject( | 659 Handle<Object> instance = CreateAccessCheckedObject( |
| 659 BlockAccessKeys, IndexedAccessAlwaysAllowed); | 660 BlockAccessKeys, IndexedAccessAlwaysAllowed); |
| 660 CompileRun("var records = null;" | 661 CompileRun("var records = null;" |
| 661 "var objNoCheck = {};" | 662 "var objNoCheck = {};" |
| 662 "var observer = function(r) { records = r };" | 663 "var observer = function(r) { records = r };" |
| 663 "var blacklist = {__block_access_keys: true};" | 664 "var blacklist = {__block_access_keys: true};" |
| 664 "Object.observe(obj, observer);" | 665 "Object.observe(obj, observer);" |
| 665 "Object.observe(objNoCheck, observer);"); | 666 "Object.observe(objNoCheck, observer);"); |
| 666 Handle<Value> obj_no_check = CompileRun("objNoCheck"); | 667 Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| 667 { | 668 { |
| 668 LocalContext context2; | 669 LocalContext context2(isolate.GetIsolate()); |
| 669 context2->Global()->Set(String::New("obj"), instance); | 670 context2->Global()->Set(String::New("obj"), instance); |
| 670 context2->Global()->Set(String::New("objNoCheck"), obj_no_check); | 671 context2->Global()->Set(String::New("objNoCheck"), obj_no_check); |
| 671 CompileRun("var records2 = null;" | 672 CompileRun("var records2 = null;" |
| 672 "var observer2 = function(r) { records2 = r };" | 673 "var observer2 = function(r) { records2 = r };" |
| 673 "Object.observe(obj, observer2);" | 674 "Object.observe(obj, observer2);" |
| 674 "Object.observe(objNoCheck, observer2);" | 675 "Object.observe(objNoCheck, observer2);" |
| 675 "obj.foo = 'bar';" | 676 "obj.foo = 'bar';" |
| 676 "obj[5] = 'baz';" | 677 "obj[5] = 'baz';" |
| 677 "objNoCheck.baz = 'quux'"); | 678 "objNoCheck.baz = 'quux'"); |
| 678 const RecordExpectation expected_records2[] = { | 679 const RecordExpectation expected_records2[] = { |
| 679 { instance, "new", "foo", Handle<Value>() }, | 680 { instance, "new", "foo", Handle<Value>() }, |
| 680 { instance, "new", "5", Handle<Value>() }, | 681 { instance, "new", "5", Handle<Value>() }, |
| 681 { obj_no_check, "new", "baz", Handle<Value>() }, | 682 { obj_no_check, "new", "baz", Handle<Value>() }, |
| 682 }; | 683 }; |
| 683 EXPECT_RECORDS(CompileRun("records2"), expected_records2); | 684 EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| 684 } | 685 } |
| 685 const RecordExpectation expected_records[] = { | 686 const RecordExpectation expected_records[] = { |
| 686 { obj_no_check, "new", "baz", Handle<Value>() } | 687 { obj_no_check, "new", "baz", Handle<Value>() } |
| 687 }; | 688 }; |
| 688 EXPECT_RECORDS(CompileRun("records"), expected_records); | 689 EXPECT_RECORDS(CompileRun("records"), expected_records); |
| 689 } | 690 } |
| 690 | 691 |
| 691 | 692 |
| 692 TEST(AccessCheckDisallowApiModifications) { | 693 TEST(AccessCheckDisallowApiModifications) { |
| 693 HarmonyIsolate isolate; | 694 HarmonyIsolate isolate; |
| 694 HandleScope scope(isolate.GetIsolate()); | 695 HandleScope scope(isolate.GetIsolate()); |
| 695 LocalContext context; | 696 LocalContext context(isolate.GetIsolate()); |
| 696 Handle<Object> instance = CreateAccessCheckedObject( | 697 Handle<Object> instance = CreateAccessCheckedObject( |
| 697 BlockAccessKeys, IndexedAccessAlwaysAllowed); | 698 BlockAccessKeys, IndexedAccessAlwaysAllowed); |
| 698 CompileRun("var records = null;" | 699 CompileRun("var records = null;" |
| 699 "var observer = function(r) { records = r };" | 700 "var observer = function(r) { records = r };" |
| 700 "var blacklist = {__block_access_keys: true};" | 701 "var blacklist = {__block_access_keys: true};" |
| 701 "Object.observe(obj, observer);"); | 702 "Object.observe(obj, observer);"); |
| 702 { | 703 { |
| 703 LocalContext context2; | 704 LocalContext context2(isolate.GetIsolate()); |
| 704 context2->Global()->Set(String::New("obj"), instance); | 705 context2->Global()->Set(String::New("obj"), instance); |
| 705 CompileRun("var records2 = null;" | 706 CompileRun("var records2 = null;" |
| 706 "var observer2 = function(r) { records2 = r };" | 707 "var observer2 = function(r) { records2 = r };" |
| 707 "Object.observe(obj, observer2);"); | 708 "Object.observe(obj, observer2);"); |
| 708 instance->Set(5, String::New("bar")); | 709 instance->Set(5, String::New("bar")); |
| 709 instance->Set(String::New("foo"), String::New("bar")); | 710 instance->Set(String::New("foo"), String::New("bar")); |
| 710 CompileRun(""); // trigger delivery | 711 CompileRun(""); // trigger delivery |
| 711 const RecordExpectation expected_records2[] = { | 712 const RecordExpectation expected_records2[] = { |
| 712 { instance, "new", "5", Handle<Value>() }, | 713 { instance, "new", "5", Handle<Value>() }, |
| 713 { instance, "new", "foo", Handle<Value>() } | 714 { instance, "new", "foo", Handle<Value>() } |
| 714 }; | 715 }; |
| 715 EXPECT_RECORDS(CompileRun("records2"), expected_records2); | 716 EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| 716 } | 717 } |
| 717 CHECK(CompileRun("records")->IsNull()); | 718 CHECK(CompileRun("records")->IsNull()); |
| 718 } | 719 } |
| OLD | NEW |