I found this working on

https://codereview.chromium.org/19541010/

The main problem is that if you called Object.getNotifier(obj) on an object, %SetObserved(object) would never get called on it, and thus it would be unobservable (new test added for this).

Additionally, Runtime::SetObserved was asserting obj->IsJSObject() which would fail if called on a proxy.

It just happens that our existing test always called getNotifier() before Object.observe on proxies, and thus we never previously attempted to transition the map of a proxy.

Both issues are now fixed and properly tested.

R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/21891008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16074 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
rossberg@chromium.org 2013-08-06 13:49:10 +00:00
parent bc6fe88030
commit 92bd4d1f2d
3 changed files with 21 additions and 1 deletions

View File

@ -394,7 +394,10 @@ function ObjectGetNotifier(object) {
if (ObjectIsFrozen(object)) return null;
var objectInfo = objectInfoMap.get(object);
if (IS_UNDEFINED(objectInfo)) objectInfo = CreateObjectInfo(object);
if (IS_UNDEFINED(objectInfo)) {
objectInfo = CreateObjectInfo(object);
%SetIsObserved(object);
}
if (IS_NULL(objectInfo.notifier)) {
objectInfo.notifier = { __proto__: notifierPrototype };

View File

@ -13931,6 +13931,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
ASSERT(proto->IsJSGlobalObject());
obj = JSReceiver::cast(proto);
}
if (obj->IsJSProxy())
return isolate->heap()->undefined_value();
ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
JSObject::cast(obj)->HasFastElements()));
ASSERT(obj->IsJSObject());

View File

@ -259,6 +259,16 @@ records = undefined;
Object.deliverChangeRecords(observer.callback);
observer.assertRecordCount(1);
// Get notifier prior to observing
reset();
var obj = {};
Object.getNotifier(obj);
Object.observe(obj, observer.callback);
obj.id = 1;
Object.deliverChangeRecords(observer.callback);
observer.assertCallbackRecords([
{ object: obj, type: 'new', name: 'id' },
]);
// Observing a continuous stream of changes, while itermittantly unobserving.
reset();
@ -783,6 +793,8 @@ observer.assertNotCalled();
// Test all kinds of objects generically.
function TestObserveConfigurable(obj, prop) {
reset();
Object.observe(obj, observer.callback);
Object.unobserve(obj, observer.callback);
obj[prop] = 1;
Object.observe(obj, observer.callback);
obj[prop] = 2;
@ -852,6 +864,8 @@ function TestObserveConfigurable(obj, prop) {
function TestObserveNonConfigurable(obj, prop, desc) {
reset();
Object.observe(obj, observer.callback);
Object.unobserve(obj, observer.callback);
obj[prop] = 1;
Object.observe(obj, observer.callback);
obj[prop] = 4;