Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Unified Diff: test/cctest/test-object-observe.cc

Issue 265503002: Re-enable Object.observe and add enforcement for security invariants. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: cleanup Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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());
+ }
}

Powered by Google App Engine
This is Rietveld 408576698