Chromium Code Reviews| Index: test/cctest/test-object-observe.cc |
| diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc |
| index 44ddb6fa2061a482dacdf1c639080c922a0cd47a..677c3f891720bf2ee4acb9bdeeec854ed945fe29 100644 |
| --- a/test/cctest/test-object-observe.cc |
| +++ b/test/cctest/test-object-observe.cc |
| @@ -313,11 +313,13 @@ static void ExpectRecords(Handle<Value> records, |
| recordObj->Get(String::New("object")))); |
| CHECK(String::New(expectations[i].type)->Equals( |
| recordObj->Get(String::New("type")))); |
| - CHECK(String::New(expectations[i].name)->Equals( |
| - recordObj->Get(String::New("name")))); |
| - if (!expectations[i].old_value.IsEmpty()) { |
| - CHECK(expectations[i].old_value->Equals( |
| - recordObj->Get(String::New("oldValue")))); |
| + if (strcmp("splice", expectations[i].type) != 0) { |
| + CHECK(String::New(expectations[i].name)->Equals( |
| + recordObj->Get(String::New("name")))); |
| + if (!expectations[i].old_value.IsEmpty()) { |
| + CHECK(expectations[i].old_value->Equals( |
| + recordObj->Get(String::New("oldValue")))); |
| + } |
| } |
| } |
| } |
| @@ -446,3 +448,150 @@ TEST(ObservationWeakMap) { |
| CHECK_EQ(0, NumberOfElements(objectInfoMap)); |
| CHECK_EQ(0, NumberOfElements(notifierTargetMap)); |
| } |
| + |
| + |
| +static bool NamedAccessAlwaysAllowed(Local<Object>, Local<Value>, AccessType, |
| + Local<Value>) { |
| + return true; |
| +} |
| + |
| + |
| +static bool IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType, |
| + Local<Value>) { |
| + return true; |
| +} |
| + |
| + |
| +static bool NamedAccessAllowUnlessBlocked(Local<Object> host, Local<Value> key, |
| + AccessType type, Local<Value>) { |
| + Handle<Context> context = Context::GetCurrent(); |
| + return !context->Global()->Get(String::New("blockAccess"))->BooleanValue(); |
| +} |
| + |
| + |
| +static bool IndexedAccessAllowUnlessBlocked(Local<Object> host, uint32_t index, |
| + AccessType type, Local<Value>) { |
| + Handle<Context> context = Context::GetCurrent(); |
| + return !context->Global()->Get(String::New("blockAccess"))->BooleanValue(); |
| +} |
| + |
| + |
| +TEST(ObserveNamedAccessCheck) { |
|
rossberg
2013/08/16 13:51:54
Would be good to refine the test such that only in
adamk
2013/08/20 21:38:16
Done.
|
| + HarmonyIsolate isolate; |
| + HandleScope scope; |
| + LocalContext context; |
| + Handle<ObjectTemplate> tmpl = ObjectTemplate::New(); |
| + tmpl->SetAccessCheckCallbacks(NamedAccessAllowUnlessBlocked, |
| + IndexedAccessAlwaysAllowed); |
| + Handle<Object> instance = tmpl->NewInstance(); |
| + context->Global()->Set(String::New("obj"), instance); |
| + CompileRun("records = null;" |
|
rossberg
2013/08/16 13:51:54
Nit: can we make these proper 'var' declarations?
adamk
2013/08/20 21:38:16
Done.
|
| + "objNoCheck = {};" |
| + "blockAccess = true;" |
| + "observer = function(r) { records = r };" |
| + "Object.observe(obj, observer);" |
| + "Object.observe(objNoCheck, observer);"); |
| + Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| + { |
| + LocalContext context2; |
| + context2->Global()->Set(String::New("obj"), instance); |
| + context2->Global()->Set(String::New("objNoCheck"), obj_no_check); |
| + CompileRun("records2 = null;" |
|
rossberg
2013/08/16 13:51:54
Same here.
adamk
2013/08/20 21:38:16
Done.
|
| + "observer2 = function(r) { records2 = r };" |
| + "Object.observe(obj, observer2);" |
| + "Object.observe(objNoCheck, observer2);" |
| + "obj.foo = 'bar';" |
|
rossberg
2013/08/16 13:51:54
Please add other forms of mutation, in particular,
adamk
2013/08/20 21:38:16
Happy to expand this a little bit, but I'd be inte
|
| + "objNoCheck.baz = 'quux'"); |
| + const RecordExpectation expected_records2[] = { |
| + { instance, "new", "foo", Handle<Value>() }, |
| + { obj_no_check, "new", "baz", Handle<Value>() }, |
| + }; |
| + EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| + } |
| + const RecordExpectation expected_records[] = { |
| + { obj_no_check, "new", "baz", Handle<Value>() } |
| + }; |
| + EXPECT_RECORDS(CompileRun("records"), expected_records); |
| +} |
| + |
| + |
| +TEST(ObserveIndexedAccessCheck) { |
| + HarmonyIsolate isolate; |
| + HandleScope scope; |
| + LocalContext context; |
| + Handle<ObjectTemplate> tmpl = ObjectTemplate::New(); |
| + tmpl->SetAccessCheckCallbacks(NamedAccessAlwaysAllowed, |
| + IndexedAccessAllowUnlessBlocked); |
| + Handle<Object> instance = tmpl->NewInstance(); |
| + context->Global()->Set(String::New("obj"), instance); |
| + CompileRun("records = null;" |
| + "objNoCheck = {};" |
| + "blockAccess = true;" |
| + "observer = function(r) { records = r };" |
| + "Object.observe(obj, observer);" |
| + "Object.observe(objNoCheck, observer);"); |
| + Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| + { |
| + LocalContext context2; |
| + context2->Global()->Set(String::New("obj"), instance); |
| + context2->Global()->Set(String::New("objNoCheck"), obj_no_check); |
| + CompileRun("records2 = null;" |
| + "observer2 = function(r) { records2 = r };" |
| + "Object.observe(obj, observer2);" |
| + "Object.observe(objNoCheck, observer2);" |
| + "obj[7] = 'bar';" |
| + "objNoCheck[42] = 'quux'"); |
| + const RecordExpectation expected_records2[] = { |
| + { instance, "new", "7", Handle<Value>() }, |
| + { obj_no_check, "new", "42", Handle<Value>() } |
| + }; |
| + EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| + } |
| + const RecordExpectation expected_records[] = { |
| + { obj_no_check, "new", "42", Handle<Value>() } |
| + }; |
| + EXPECT_RECORDS(CompileRun("records"), expected_records); |
| +} |
| + |
| + |
| +TEST(ObserveSpliceAccessCheck) { |
| + HarmonyIsolate isolate; |
| + HandleScope scope; |
| + LocalContext context; |
| + Handle<ObjectTemplate> tmpl = ObjectTemplate::New(); |
| + tmpl->SetAccessCheckCallbacks(NamedAccessAlwaysAllowed, |
| + IndexedAccessAllowUnlessBlocked); |
| + Handle<Object> instance = tmpl->NewInstance(); |
| + context->Global()->Set(String::New("obj"), instance); |
| + CompileRun("records = null;" |
| + "obj[1] = 'foo';" |
| + "obj.length = 2;" |
| + "objNoCheck = {1: 'bar', length: 2};" |
| + "blockAccess = true;" |
| + "observer = function(r) { records = r };" |
| + "Array.observe(obj, observer);" |
| + "Array.observe(objNoCheck, observer);"); |
| + Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| + { |
| + LocalContext context2; |
| + context2->Global()->Set(String::New("obj"), instance); |
| + context2->Global()->Set(String::New("objNoCheck"), obj_no_check); |
| + CompileRun("records2 = null;" |
| + "observer2 = function(r) { records2 = r };" |
| + "Array.observe(obj, observer2);" |
| + "Array.observe(objNoCheck, observer2);" |
| + // No one should hear about this: no splice records are emitted |
| + // for access-checked objects |
| + "[].pop.call(obj);" |
|
rossberg
2013/08/16 13:51:54
Can we check some more complex array functions, to
adamk
2013/08/20 21:38:16
How complex do you want? It's not clear to me what
rossberg
2013/08/21 10:45:52
Doesn't have to be crazy. I'd be content with one
adamk
2013/08/21 17:18:36
The nature of splice records is that there aren't
|
| + "[].pop.call(objNoCheck);"); |
| + // TODO(adamk): Support splice records |
|
rossberg
2013/08/16 13:51:54
What is this TODO about?
adamk
2013/08/20 21:38:16
Made it longer.
|
| + const RecordExpectation expected_records2[] = { |
| + { obj_no_check, "splice", "", Handle<Value>() } |
| + }; |
| + EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| + } |
| + const RecordExpectation expected_records[] = { |
| + { obj_no_check, "splice", "", Handle<Value>() } |
| + }; |
| + EXPECT_RECORDS(CompileRun("records"), expected_records); |
| +} |