| 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..a096828ff66dd13234d67a176b62d1faf6d09efb 100644
|
| --- a/test/cctest/test-object-observe.cc
|
| +++ b/test/cctest/test-object-observe.cc
|
| @@ -36,6 +36,10 @@ namespace i = v8::internal;
|
| TEST(PerIsolateState) {
|
| HandleScope scope(CcTest::isolate());
|
| LocalContext context1(CcTest::isolate());
|
| +
|
| + Local<Value> foo = v8_str("foo");
|
| + context1->SetSecurityToken(foo);
|
| +
|
| CompileRun(
|
| "var count = 0;"
|
| "var calls = 0;"
|
| @@ -49,6 +53,7 @@ TEST(PerIsolateState) {
|
| Handle<Value> notify_fun2;
|
| {
|
| LocalContext context2(CcTest::isolate());
|
| + context2->SetSecurityToken(foo);
|
| context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
|
| obj);
|
| notify_fun2 = CompileRun(
|
| @@ -57,6 +62,7 @@ TEST(PerIsolateState) {
|
| Handle<Value> notify_fun3;
|
| {
|
| LocalContext context3(CcTest::isolate());
|
| + context3->SetSecurityToken(foo);
|
| context3->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
|
| obj);
|
| notify_fun3 = CompileRun(
|
| @@ -64,6 +70,7 @@ TEST(PerIsolateState) {
|
| }
|
| {
|
| LocalContext context4(CcTest::isolate());
|
| + context4->SetSecurityToken(foo);
|
| context4->Global()->Set(
|
| String::NewFromUtf8(CcTest::isolate(), "observer"), observer);
|
| context4->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "fun1"),
|
| @@ -209,59 +216,6 @@ TEST(ObjectHashTableGrowth) {
|
| }
|
|
|
|
|
| -TEST(GlobalObjectObservation) {
|
| - LocalContext context(CcTest::isolate());
|
| - HandleScope scope(CcTest::isolate());
|
| - Handle<Object> global_proxy = context->Global();
|
| - CompileRun(
|
| - "var records = [];"
|
| - "var global = this;"
|
| - "Object.observe(global, function(r) { [].push.apply(records, r) });"
|
| - "global.foo = 'hello';");
|
| - CHECK_EQ(1, CompileRun("records.length")->Int32Value());
|
| - CHECK(global_proxy->StrictEquals(CompileRun("records[0].object")));
|
| -
|
| - // Detached, mutating the proxy has no effect.
|
| - context->DetachGlobal();
|
| - CompileRun("global.bar = 'goodbye';");
|
| - CHECK_EQ(1, CompileRun("records.length")->Int32Value());
|
| - CompileRun("this.baz = 'goodbye';");
|
| - CHECK_EQ(1, CompileRun("records.length")->Int32Value());
|
| -
|
| - // Attached to a different context, should not leak mutations
|
| - // to the old context.
|
| - context->DetachGlobal();
|
| - {
|
| - LocalContext context2(CcTest::isolate());
|
| - CompileRun(
|
| - "var records2 = [];"
|
| - "var global = this;"
|
| - "Object.observe(this, function(r) { [].push.apply(records2, r) });"
|
| - "this.v1 = 'context2';");
|
| - context2->DetachGlobal();
|
| - CompileRun(
|
| - "global.v2 = 'context2';"
|
| - "this.v3 = 'context2';");
|
| - CHECK_EQ(1, CompileRun("records2.length")->Int32Value());
|
| - }
|
| - CHECK_EQ(1, CompileRun("records.length")->Int32Value());
|
| -
|
| - // Attaching by passing to Context::New
|
| - {
|
| - // Delegates to Context::New
|
| - LocalContext context3(
|
| - CcTest::isolate(), NULL, Handle<ObjectTemplate>(), global_proxy);
|
| - CompileRun(
|
| - "var records3 = [];"
|
| - "Object.observe(this, function(r) { [].push.apply(records3, r) });"
|
| - "this.qux = 'context3';");
|
| - CHECK_EQ(1, CompileRun("records3.length")->Int32Value());
|
| - CHECK(global_proxy->StrictEquals(CompileRun("records3[0].object")));
|
| - }
|
| - CHECK_EQ(1, CompileRun("records.length")->Int32Value());
|
| -}
|
| -
|
| -
|
| struct RecordExpectation {
|
| Handle<Value> object;
|
| const char* type;
|
| @@ -430,300 +384,232 @@ TEST(ObservationWeakMap) {
|
| }
|
|
|
|
|
| -static bool NamedAccessAlwaysAllowed(Local<Object>, Local<Value>, AccessType,
|
| - Local<Value>) {
|
| - return true;
|
| +static int TestObserveSecurity(Handle<Context> observer_context,
|
| + Handle<Context> object_context,
|
| + Handle<Context> mutation_context) {
|
| + 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);
|
| + CompileRun("var obj = {};"
|
| + "obj.length = 0;"
|
| + "Object.observe(obj, observer,"
|
| + "['add', 'update', 'delete','reconfigure','splice']"
|
| + ");");
|
| + Handle<Value> obj = CompileRun("obj");
|
| + {
|
| + 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 IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType,
|
| - Local<Value>) {
|
| - return true;
|
| +TEST(ObserverSecurityAAA) {
|
| + v8::Isolate* isolate = CcTest::isolate();
|
| + v8::HandleScope scope(isolate);
|
| + v8::Local<Context> contextA = Context::New(isolate);
|
| + CHECK_EQ(8, TestObserveSecurity(contextA, contextA, contextA));
|
| }
|
|
|
|
|
| -static AccessType g_access_block_type = ACCESS_GET;
|
| -static const uint32_t kBlockedContextIndex = 1337;
|
| +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);
|
|
|
| -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);
|
| + CHECK_EQ(8, TestObserveSecurity(contextA1, contextA2, contextA3));
|
| }
|
|
|
|
|
| -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(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));
|
| }
|
|
|
|
|
| -static bool BlockAccessKeys(Local<Object> host, Local<Value> key,
|
| - AccessType type, Local<Value>) {
|
| - v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(
|
| - Utils::OpenHandle(*host)->GetIsolate());
|
| - Handle<Object> global = isolate->GetCurrentContext()->Global();
|
| - return type != ACCESS_KEYS || !global->Has(kBlockedContextIndex);
|
| +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));
|
| }
|
|
|
|
|
| -static Handle<Object> CreateAccessCheckedObject(
|
| - v8::Isolate* isolate,
|
| - NamedSecurityCallback namedCallback,
|
| - IndexedSecurityCallback indexedCallback,
|
| - Handle<Value> data = Handle<Value>()) {
|
| - Handle<ObjectTemplate> tmpl = ObjectTemplate::New(isolate);
|
| - tmpl->SetAccessCheckCallbacks(namedCallback, indexedCallback, data);
|
| - Handle<Object> instance = tmpl->NewInstance();
|
| - Handle<Object> global = instance->CreationContext()->Global();
|
| - global->Set(String::NewFromUtf8(isolate, "obj"), instance);
|
| - global->Set(kBlockedContextIndex, v8::True(isolate));
|
| - return instance;
|
| +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(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(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(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(ObserverSecurityBAA) {
|
| + 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, contextA));
|
| }
|
|
|
|
|
| -TEST(SpliceAccessCheck) {
|
| - 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");
|
| +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(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);
|
| + CompileRun("var obj = {};"
|
| + "var recordsA = null;"
|
| + "var observerA = function(r) { recordsA = r };"
|
| + "Object.observe(obj, observerA);");
|
| + Handle<Value> obj = CompileRun("obj");
|
| +
|
| {
|
| - 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);
|
| + 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());
|
| }
|
| - const RecordExpectation expected_records[] = {
|
| - { obj_no_check, "splice", "", Handle<Value>() }
|
| - };
|
| - EXPECT_RECORDS(CompileRun("records"), expected_records);
|
| }
|
|
|
|
|
| -TEST(DisallowAllForAccessKeys) {
|
| +TEST(HiddenPropertiesLeakage) {
|
| HandleScope scope(CcTest::isolate());
|
| LocalContext context(CcTest::isolate());
|
| - Handle<Object> instance = CreateAccessCheckedObject(
|
| - CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed);
|
| - CompileRun("var records = null;"
|
| - "var objNoCheck = {};"
|
| + CompileRun("var obj = {};"
|
| + "var records = null;"
|
| "var observer = function(r) { records = r };"
|
| - "Object.observe(obj, observer);"
|
| - "Object.observe(objNoCheck, observer);");
|
| - Handle<Value> obj_no_check = CompileRun("objNoCheck");
|
| + "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());
|
| +}
|
| +
|
| +
|
| +TEST(GetNotifierFromOtherContext) {
|
| + HandleScope scope(CcTest::isolate());
|
| + LocalContext context(CcTest::isolate());
|
| + CompileRun("var obj = {};");
|
| + Handle<Value> instance = CompileRun("obj");
|
| {
|
| 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';"
|
| - "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(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());
|
| - Handle<Object> instance = CreateAccessCheckedObject(
|
| - CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed);
|
| - CompileRun("var records = null;"
|
| - "var observer = function(r) { records = r };"
|
| - "Object.observe(obj, observer);");
|
| + context->SetSecurityToken(foo);
|
| + CompileRun("var obj = {};");
|
| + Handle<Value> instance = CompileRun("obj");
|
| {
|
| LocalContext context2(CcTest::isolate());
|
| + context2->SetSecurityToken(bar);
|
| 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)")->IsNull());
|
| }
|
| - CHECK(CompileRun("records")->IsNull());
|
| }
|
|
|
|
|
| -TEST(HiddenPropertiesLeakage) {
|
| +TEST(GetNotifierFromSameOrigin) {
|
| HandleScope scope(CcTest::isolate());
|
| + Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo");
|
| 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());
|
| + context->SetSecurityToken(foo);
|
| + CompileRun("var obj = {};");
|
| + Handle<Value> instance = CompileRun("obj");
|
| + {
|
| + LocalContext context2(CcTest::isolate());
|
| + context2->SetSecurityToken(foo);
|
| + context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
|
| + instance);
|
| + CHECK(CompileRun("Object.getNotifier(obj)")->IsObject());
|
| + }
|
| }
|
|
|