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 a8cbaf6ea75a49902e63bd75607fdc8860c62ca2..206ab66aa6873e9ca6e96905e2f13267403a2e65 100644 |
| --- a/test/cctest/test-object-observe.cc |
| +++ b/test/cctest/test-object-observe.cc |
| @@ -442,36 +442,268 @@ static bool IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType, |
| } |
| -static AccessType g_access_block_type = ACCESS_GET; |
| -static const uint32_t kBlockedContextIndex = 1337; |
| +static int TestObserveSecurity(Handle<Context> observer_context, |
| + Handle<Context> object_context, |
| + Handle<Context> mutation_context, |
| + bool use_access_checked_object = true) { |
| + Context::Scope observer_scope(observer_context); |
| + CompileRun("var records = null;" |
| + "var observer = function(r) { records = r };"); |
| + Handle<Value> observer = CompileRun("observer"); |
| + { |
| + Context::Scope object_scope(object_context); |
| + object_context->Global()->Set( |
| + String::NewFromUtf8(CcTest::isolate(), "observer"), observer); |
| + Handle<ObjectTemplate> tmpl = ObjectTemplate::New(CcTest::isolate()); |
| + if (use_access_checked_object) { |
| + tmpl->SetAccessCheckCallbacks(NamedAccessAlwaysAllowed, |
| + IndexedAccessAlwaysAllowed); |
| + } |
| + Handle<Object> obj = tmpl->NewInstance(); |
| + object_context->Global()->Set( |
| + String::NewFromUtf8(CcTest::isolate(), "obj"), obj); |
| + |
| + CompileRun("obj.length = 0;" |
| + "Object.observe(obj, observer," |
| + "['add', 'update', 'delete','reconfigure','splice']" |
| + ");"); |
| + { |
| + Context::Scope mutation_scope(mutation_context); |
| + mutation_context->Global()->Set( |
| + String::NewFromUtf8(CcTest::isolate(), "obj"), obj); |
| + CompileRun("obj.foo = 'bar';" |
| + "obj.foo = 'baz';" |
| + "delete obj.foo;" |
| + "Object.defineProperty(obj, 'bar', {value: 'bot'});" |
| + "Array.prototype.push.call(obj, 1, 2, 3);" |
| + "Array.prototype.splice.call(obj, 1, 2, 2, 4);" |
| + "Array.prototype.pop.call(obj);" |
| + "Array.prototype.shift.call(obj);"); |
| + } |
| + } |
| + return CompileRun("records ? records.length : 0")->Int32Value(); |
| +} |
| -static bool NamedAccessAllowUnlessBlocked(Local<Object> host, |
| - Local<Value> key, |
| - AccessType type, |
| - Local<Value> data) { |
| - if (type != g_access_block_type) return true; |
| - v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>( |
| - Utils::OpenHandle(*host)->GetIsolate()); |
| - Handle<Object> global = isolate->GetCurrentContext()->Global(); |
| - if (!global->Has(kBlockedContextIndex)) return true; |
| - return !key->IsString() || !key->Equals(data); |
| + |
| +TEST(ObserverSecurityAAA) { |
|
rossberg
2014/04/30 11:28:32
How about merging all these tests into a single on
|
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + CHECK_EQ(8, TestObserveSecurity(contextA, contextA, contextA)); |
| } |
| -static bool IndexedAccessAllowUnlessBlocked(Local<Object> host, |
| - uint32_t index, |
| - AccessType type, |
| - Local<Value> data) { |
| - if (type != g_access_block_type) return true; |
| - v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>( |
| - Utils::OpenHandle(*host)->GetIsolate()); |
| - Handle<Object> global = isolate->GetCurrentContext()->Global(); |
| - if (!global->Has(kBlockedContextIndex)) return true; |
| - return index != data->Uint32Value(); |
| +TEST(ObserverSecurityA1A2A3) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + |
| + v8::Local<Context> contextA1 = Context::New(isolate); |
| + v8::Local<Context> contextA2 = Context::New(isolate); |
| + v8::Local<Context> contextA3 = Context::New(isolate); |
| + |
| + Local<Value> foo = v8_str("foo"); |
| + contextA1->SetSecurityToken(foo); |
| + contextA2->SetSecurityToken(foo); |
| + contextA3->SetSecurityToken(foo); |
| + |
| + CHECK_EQ(8, TestObserveSecurity(contextA1, contextA2, contextA3)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityAAB) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + CHECK_EQ(0, TestObserveSecurity(contextA, contextA, contextB)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityA1A2B) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + |
| + v8::Local<Context> contextA1 = Context::New(isolate); |
| + v8::Local<Context> contextA2 = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + |
| + Local<Value> foo = v8_str("foo"); |
| + contextA1->SetSecurityToken(foo); |
| + contextA2->SetSecurityToken(foo); |
| + |
| + CHECK_EQ(0, TestObserveSecurity(contextA1, contextA2, contextB)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityABA) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + CHECK_EQ(0, TestObserveSecurity(contextA, contextB, contextA)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityA1BA2) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA1 = Context::New(isolate); |
| + v8::Local<Context> contextA2 = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + |
| + Local<Value> foo = v8_str("foo"); |
| + contextA1->SetSecurityToken(foo); |
| + contextA2->SetSecurityToken(foo); |
| + |
| + CHECK_EQ(0, TestObserveSecurity(contextA1, contextB, contextA2)); |
| } |
| +TEST(ObserverSecurityBA1A2) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA1 = Context::New(isolate); |
| + v8::Local<Context> contextA2 = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + |
| + Local<Value> foo = v8_str("foo"); |
| + contextA1->SetSecurityToken(foo); |
| + contextA2->SetSecurityToken(foo); |
| + |
| + CHECK_EQ(0, TestObserveSecurity(contextB, contextA1, contextA2)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityABB) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + CHECK_EQ(0, TestObserveSecurity(contextA, contextB, contextB)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityAB1B2) { |
|
rossberg
2014/04/30 11:28:32
How is this one different from BA1A2 above?
rafaelw
2014/05/02 03:22:32
yes. removed.
On 2014/04/30 11:28:32, rossberg wr
|
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB1 = Context::New(isolate); |
| + v8::Local<Context> contextB2 = Context::New(isolate); |
| + |
| + Local<Value> foo = v8_str("foo"); |
| + contextB1->SetSecurityToken(foo); |
| + contextB2->SetSecurityToken(foo); |
| + |
| + CHECK_EQ(0, TestObserveSecurity(contextA, contextB1, contextB2)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityB1B2A) { |
|
rossberg
2014/04/30 11:28:32
And this seems to be the same as A1A2B.
rafaelw
2014/05/02 03:22:32
yes. removed.
On 2014/04/30 11:28:32, rossberg wr
|
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB1 = Context::New(isolate); |
| + v8::Local<Context> contextB2 = Context::New(isolate); |
| + |
| + Local<Value> foo = v8_str("foo"); |
| + contextB1->SetSecurityToken(foo); |
| + contextB2->SetSecurityToken(foo); |
| + |
| + CHECK_EQ(0, TestObserveSecurity(contextB1, contextB2, contextA)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityBAB) { |
|
rossberg
2014/04/30 11:28:32
Same as ABA?
rafaelw
2014/05/02 03:22:32
yes. removed.
On 2014/04/30 11:28:32, rossberg wr
|
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + CHECK_EQ(0, TestObserveSecurity(contextB, contextA, contextB)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityB1AB2) { |
|
rossberg
2014/04/30 11:28:32
Same as A1BA2?
rafaelw
2014/05/02 03:22:32
yes. removed.
On 2014/04/30 11:28:32, rossberg wr
|
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB1 = Context::New(isolate); |
| + v8::Local<Context> contextB2 = Context::New(isolate); |
| + |
| + Local<Value> foo = v8_str("foo"); |
| + contextB1->SetSecurityToken(foo); |
| + contextB2->SetSecurityToken(foo); |
| + |
| + CHECK_EQ(0, TestObserveSecurity(contextB1, contextA, contextB2)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityNoAccessCheckOnObject) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + v8::Local<Context> contextC = Context::New(isolate); |
| + CHECK_EQ(8, TestObserveSecurity(contextA, contextB, contextC, false)); |
| +} |
| + |
| + |
| +TEST(ObserverSecurityNotify) { |
| + v8::Isolate* isolate = CcTest::isolate(); |
| + v8::HandleScope scope(isolate); |
| + v8::Local<Context> contextA = Context::New(isolate); |
| + v8::Local<Context> contextB = Context::New(isolate); |
| + |
| + Context::Scope scopeA(contextA); |
| + Handle<ObjectTemplate> tmpl = ObjectTemplate::New(CcTest::isolate()); |
| + tmpl->SetAccessCheckCallbacks(NamedAccessAlwaysAllowed, |
| + IndexedAccessAlwaysAllowed); |
| + Handle<Object> obj = tmpl->NewInstance(); |
| + contextA->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), obj); |
| + |
| + CompileRun("var recordsA = null;" |
| + "var observerA = function(r) { recordsA = r };" |
| + "Object.observe(obj, observerA);"); |
| + |
| + { |
| + Context::Scope scopeB(contextB); |
| + contextB->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), obj); |
| + CompileRun("var recordsB = null;" |
| + "var observerB = function(r) { recordsB = r };" |
| + "Object.observe(obj, observerB);"); |
| + } |
| + |
| + CompileRun("var notifier = Object.getNotifier(obj);" |
| + "notifier.notify({ type: 'update' });"); |
| + CHECK_EQ(1, CompileRun("recordsA ? recordsA.length : 0")->Int32Value()); |
| + |
| + { |
| + Context::Scope scopeB(contextB); |
| + CHECK_EQ(0, CompileRun("recordsB ? recordsB.length : 0")->Int32Value()); |
| + } |
| +} |
| + |
| + |
| +TEST(HiddenPropertiesLeakage) { |
| + HandleScope scope(CcTest::isolate()); |
| + LocalContext context(CcTest::isolate()); |
| + CompileRun("var obj = {};" |
| + "var records = null;" |
| + "var observer = function(r) { records = r };" |
| + "Object.observe(obj, observer);"); |
| + Handle<Value> obj = |
| + context->Global()->Get(String::NewFromUtf8(CcTest::isolate(), "obj")); |
| + Handle<Object>::Cast(obj) |
| + ->SetHiddenValue(String::NewFromUtf8(CcTest::isolate(), "foo"), |
| + Null(CcTest::isolate())); |
| + CompileRun(""); // trigger delivery |
| + CHECK(CompileRun("records")->IsNull()); |
| +} |
| + |
| + |
| +static const uint32_t kBlockedContextIndex = 1337; |
| + |
| + |
| static bool BlockAccessKeys(Local<Object> host, Local<Value> key, |
| AccessType type, Local<Value>) { |
| v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>( |
| @@ -496,234 +728,67 @@ static Handle<Object> CreateAccessCheckedObject( |
| } |
| -TEST(NamedAccessCheck) { |
| - const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; |
| - for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { |
| - HandleScope scope(CcTest::isolate()); |
| - LocalContext context(CcTest::isolate()); |
| - g_access_block_type = types[i]; |
| - Handle<Object> instance = CreateAccessCheckedObject( |
| - CcTest::isolate(), |
| - NamedAccessAllowUnlessBlocked, |
| - IndexedAccessAlwaysAllowed, |
| - String::NewFromUtf8(CcTest::isolate(), "foo")); |
| - CompileRun("var records = null;" |
| - "var objNoCheck = {};" |
| - "var observer = function(r) { records = r };" |
| - "Object.observe(obj, observer);" |
| - "Object.observe(objNoCheck, observer);"); |
| - Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| - { |
| - LocalContext context2(CcTest::isolate()); |
| - context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), |
| - instance); |
| - context2->Global()->Set( |
| - String::NewFromUtf8(CcTest::isolate(), "objNoCheck"), |
| - obj_no_check); |
| - CompileRun("var records2 = null;" |
| - "var observer2 = function(r) { records2 = r };" |
| - "Object.observe(obj, observer2);" |
| - "Object.observe(objNoCheck, observer2);" |
| - "obj.foo = 'bar';" |
| - "Object.defineProperty(obj, 'foo', {value: 5});" |
| - "Object.defineProperty(obj, 'foo', {get: function(){}});" |
| - "obj.bar = 'baz';" |
| - "objNoCheck.baz = 'quux'"); |
| - const RecordExpectation expected_records2[] = { |
| - { instance, "add", "foo", Handle<Value>() }, |
| - { instance, "update", "foo", |
| - String::NewFromUtf8(CcTest::isolate(), "bar") }, |
| - { instance, "reconfigure", "foo", |
| - Number::New(CcTest::isolate(), 5) }, |
| - { instance, "add", "bar", Handle<Value>() }, |
| - { obj_no_check, "add", "baz", Handle<Value>() }, |
| - }; |
| - EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| - } |
| - const RecordExpectation expected_records[] = { |
| - { instance, "add", "bar", Handle<Value>() }, |
| - { obj_no_check, "add", "baz", Handle<Value>() } |
| - }; |
| - EXPECT_RECORDS(CompileRun("records"), expected_records); |
| - } |
| -} |
| - |
| - |
| -TEST(IndexedAccessCheck) { |
| - const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; |
| - for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { |
| - HandleScope scope(CcTest::isolate()); |
| - LocalContext context(CcTest::isolate()); |
| - g_access_block_type = types[i]; |
| - Handle<Object> instance = CreateAccessCheckedObject( |
| - CcTest::isolate(), NamedAccessAlwaysAllowed, |
| - IndexedAccessAllowUnlessBlocked, Number::New(CcTest::isolate(), 7)); |
| - CompileRun("var records = null;" |
| - "var objNoCheck = {};" |
| - "var observer = function(r) { records = r };" |
| - "Object.observe(obj, observer);" |
| - "Object.observe(objNoCheck, observer);"); |
| - Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| - { |
| - LocalContext context2(CcTest::isolate()); |
| - context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), |
| - instance); |
| - context2->Global()->Set( |
| - String::NewFromUtf8(CcTest::isolate(), "objNoCheck"), |
| - obj_no_check); |
| - CompileRun("var records2 = null;" |
| - "var observer2 = function(r) { records2 = r };" |
| - "Object.observe(obj, observer2);" |
| - "Object.observe(objNoCheck, observer2);" |
| - "obj[7] = 'foo';" |
| - "Object.defineProperty(obj, '7', {value: 5});" |
| - "Object.defineProperty(obj, '7', {get: function(){}});" |
| - "obj[8] = 'bar';" |
| - "objNoCheck[42] = 'quux'"); |
| - const RecordExpectation expected_records2[] = { |
| - { instance, "add", "7", Handle<Value>() }, |
| - { instance, "update", "7", |
| - String::NewFromUtf8(CcTest::isolate(), "foo") }, |
| - { instance, "reconfigure", "7", Number::New(CcTest::isolate(), 5) }, |
| - { instance, "add", "8", Handle<Value>() }, |
| - { obj_no_check, "add", "42", Handle<Value>() } |
| - }; |
| - EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| - } |
| - const RecordExpectation expected_records[] = { |
| - { instance, "add", "8", Handle<Value>() }, |
| - { obj_no_check, "add", "42", Handle<Value>() } |
| - }; |
| - EXPECT_RECORDS(CompileRun("records"), expected_records); |
| - } |
| -} |
| - |
| - |
| -TEST(SpliceAccessCheck) { |
| +TEST(GetNotifierFromOtherContext) { |
| HandleScope scope(CcTest::isolate()); |
| LocalContext context(CcTest::isolate()); |
| - g_access_block_type = ACCESS_GET; |
| Handle<Object> instance = CreateAccessCheckedObject( |
| - CcTest::isolate(), NamedAccessAlwaysAllowed, |
| - IndexedAccessAllowUnlessBlocked, Number::New(CcTest::isolate(), 1)); |
| - CompileRun("var records = null;" |
| - "obj[1] = 'foo';" |
| - "obj.length = 2;" |
| - "var objNoCheck = {1: 'bar', length: 2};" |
| - "observer = function(r) { records = r };" |
| - "Array.observe(obj, observer);" |
| - "Array.observe(objNoCheck, observer);"); |
| - Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| + CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed); |
| { |
| LocalContext context2(CcTest::isolate()); |
| context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), |
| instance); |
| - context2->Global()->Set( |
| - String::NewFromUtf8(CcTest::isolate(), "objNoCheck"), obj_no_check); |
| - CompileRun("var records2 = null;" |
| - "var 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 |
| - "[].push.call(obj, 5);" |
| - "[].splice.call(obj, 1, 1);" |
| - "[].pop.call(obj);" |
| - "[].pop.call(objNoCheck);"); |
| - // TODO(adamk): Extend EXPECT_RECORDS to be able to assert more things |
| - // about splice records. For this test it's not so important since |
| - // we just want to guarantee the machinery is in operation at all. |
| - const RecordExpectation expected_records2[] = { |
| - { obj_no_check, "splice", "", Handle<Value>() } |
| - }; |
| - EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| + CHECK(CompileRun("Object.getNotifier(obj)")->IsNull()); |
| } |
| - const RecordExpectation expected_records[] = { |
| - { obj_no_check, "splice", "", Handle<Value>() } |
| - }; |
| - EXPECT_RECORDS(CompileRun("records"), expected_records); |
| } |
| -TEST(DisallowAllForAccessKeys) { |
| +TEST(GetNotifierFromOtherOrigin) { |
| HandleScope scope(CcTest::isolate()); |
| + Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo"); |
| + Handle<Value> bar = String::NewFromUtf8(CcTest::isolate(), "bar"); |
| LocalContext context(CcTest::isolate()); |
| + context->SetSecurityToken(foo); |
| Handle<Object> instance = CreateAccessCheckedObject( |
| CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed); |
| - CompileRun("var records = null;" |
| - "var objNoCheck = {};" |
| - "var observer = function(r) { records = r };" |
| - "Object.observe(obj, observer);" |
| - "Object.observe(objNoCheck, observer);"); |
| - Handle<Value> obj_no_check = CompileRun("objNoCheck"); |
| + |
| { |
| LocalContext context2(CcTest::isolate()); |
| + context2->SetSecurityToken(bar); |
| context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), |
| instance); |
| - context2->Global()->Set( |
| - String::NewFromUtf8(CcTest::isolate(), "objNoCheck"), obj_no_check); |
| - CompileRun("var records2 = null;" |
| - "var observer2 = function(r) { records2 = r };" |
| - "Object.observe(obj, observer2);" |
| - "Object.observe(objNoCheck, observer2);" |
| - "obj.foo = 'bar';" |
| - "obj[5] = 'baz';" |
| - "objNoCheck.baz = 'quux'"); |
| - const RecordExpectation expected_records2[] = { |
| - { instance, "add", "foo", Handle<Value>() }, |
| - { instance, "add", "5", Handle<Value>() }, |
| - { obj_no_check, "add", "baz", Handle<Value>() }, |
| - }; |
| - EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| + CHECK(CompileRun("Object.getNotifier(obj)")->IsNull()); |
| } |
| - const RecordExpectation expected_records[] = { |
| - { obj_no_check, "add", "baz", Handle<Value>() } |
| - }; |
| - EXPECT_RECORDS(CompileRun("records"), expected_records); |
| } |
| -TEST(AccessCheckDisallowApiModifications) { |
| +TEST(GetNotifierFromSameOrigin) { |
| HandleScope scope(CcTest::isolate()); |
| + Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo"); |
| LocalContext context(CcTest::isolate()); |
| + context->SetSecurityToken(foo); |
| Handle<Object> instance = CreateAccessCheckedObject( |
| CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed); |
| - CompileRun("var records = null;" |
| - "var observer = function(r) { records = r };" |
| - "Object.observe(obj, observer);"); |
| + |
| { |
| LocalContext context2(CcTest::isolate()); |
| + context2->SetSecurityToken(foo); |
| context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), |
| instance); |
| - CompileRun("var records2 = null;" |
| - "var observer2 = function(r) { records2 = r };" |
| - "Object.observe(obj, observer2);"); |
| - instance->Set(5, String::NewFromUtf8(CcTest::isolate(), "bar")); |
| - instance->Set(String::NewFromUtf8(CcTest::isolate(), "foo"), |
| - String::NewFromUtf8(CcTest::isolate(), "bar")); |
| - CompileRun(""); // trigger delivery |
| - const RecordExpectation expected_records2[] = { |
| - { instance, "add", "5", Handle<Value>() }, |
| - { instance, "add", "foo", Handle<Value>() } |
| - }; |
| - EXPECT_RECORDS(CompileRun("records2"), expected_records2); |
| + CHECK(CompileRun("Object.getNotifier(obj)")->IsObject()); |
| } |
| - CHECK(CompileRun("records")->IsNull()); |
| } |
| -TEST(HiddenPropertiesLeakage) { |
| +// This case should never happen in a well-behaved embedder, but there's |
| +// no way for V8 to prevent and API user from doing it. |
|
rossberg
2014/04/30 11:28:32
Typo: s/and/an/
rafaelw
2014/05/02 03:22:32
Test & comment removed.
On 2014/04/30 11:28:32,
|
| +TEST(GetNotifierFromOtherContextWithoutAccessChecks) { |
| HandleScope scope(CcTest::isolate()); |
| LocalContext context(CcTest::isolate()); |
| - CompileRun("var obj = {};" |
| - "var records = null;" |
| - "var observer = function(r) { records = r };" |
| - "Object.observe(obj, observer);"); |
| - Handle<Value> obj = |
| - context->Global()->Get(String::NewFromUtf8(CcTest::isolate(), "obj")); |
| - Handle<Object>::Cast(obj) |
| - ->SetHiddenValue(String::NewFromUtf8(CcTest::isolate(), "foo"), |
| - Null(CcTest::isolate())); |
| - CompileRun(""); // trigger delivery |
| - CHECK(CompileRun("records")->IsNull()); |
| + Handle<Object> instance = Object::New(CcTest::isolate()); |
| + { |
| + LocalContext context2(CcTest::isolate()); |
| + context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), |
| + instance); |
| + CHECK(CompileRun("Object.getNotifier(obj)")->IsObject()); |
| + } |
| } |