From 2e76922c79638f74d76669a875f7c531c81b65bf Mon Sep 17 00:00:00 2001 From: "rossberg@chromium.org" Date: Fri, 16 Nov 2012 09:35:27 +0000 Subject: [PATCH] Object.observe: Use [[DefineOwnProperty]] to create properties of changeRecord. Note: The test here requires https://codereview.chromium.org/11364237/ to land in order to pass because Object.freeze calls Object.getOwnPropertyNames(). BUG=v8:2411 Review URL: https://codereview.chromium.org/11377171 Patch from Rafael Weinstein . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12983 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/object-observe.js | 15 +++++++-------- test/mjsunit/harmony/object-observe.js | 18 +++++++++++++++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/object-observe.js b/src/object-observe.js index 1b0a491..ea5de1f 100644 --- a/src/object-observe.js +++ b/src/object-observe.js @@ -27,9 +27,6 @@ "use strict"; -var InternalObjectIsFrozen = $Object.isFrozen; -var InternalObjectFreeze = $Object.freeze; - var observationState = %GetObservationState(); if (IS_UNDEFINED(observationState.observerInfoMap)) { observationState.observerInfoMap = %CreateObjectHashTable(); @@ -74,7 +71,7 @@ function ObjectObserve(object, callback) { throw MakeTypeError("observe_non_object", ["observe"]); if (!IS_SPEC_FUNCTION(callback)) throw MakeTypeError("observe_non_function", ["observe"]); - if (InternalObjectIsFrozen(callback)) + if (ObjectIsFrozen(callback)) throw MakeTypeError("observe_callback_frozen"); if (!observerInfoMap.has(callback)) { @@ -134,7 +131,7 @@ function NotifyChange(type, object, name, oldValue) { var changeRecord = (arguments.length < 4) ? { type: type, object: object, name: name } : { type: type, object: object, name: name, oldValue: oldValue }; - InternalObjectFreeze(changeRecord); + ObjectFreeze(changeRecord); EnqueueChangeRecord(changeRecord, objectInfo.changeObservers); } @@ -164,9 +161,11 @@ function ObjectNotifierNotify(changeRecord) { for (var prop in changeRecord) { if (prop === 'object') continue; - newRecord[prop] = changeRecord[prop]; + + %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop], + READ_ONLY + DONT_DELETE); } - InternalObjectFreeze(newRecord); + ObjectFreeze(newRecord); EnqueueChangeRecord(newRecord, objectInfo.changeObservers); } @@ -175,7 +174,7 @@ function ObjectGetNotifier(object) { if (!IS_SPEC_OBJECT(object)) throw MakeTypeError("observe_non_object", ["getNotifier"]); - if (InternalObjectIsFrozen(object)) + if (ObjectIsFrozen(object)) return null; var objectInfo = objectInfoMap.get(object); diff --git a/test/mjsunit/harmony/object-observe.js b/test/mjsunit/harmony/object-observe.js index 83199f3..e2cc3f9 100644 --- a/test/mjsunit/harmony/object-observe.js +++ b/test/mjsunit/harmony/object-observe.js @@ -129,8 +129,24 @@ assertFalse(recordCreated); // not observed yet // Object.deliverChangeRecords assertThrows(function() { Object.deliverChangeRecords(nonFunction); }, TypeError); -// Multiple records are delivered. Object.observe(obj, observer.callback); + +// notify uses to [[CreateOwnProperty]] to create changeRecord; +reset(); +var protoExpandoAccessed = false; +Object.defineProperty(Object.prototype, 'protoExpando', + { + configurable: true, + set: function() { protoExpandoAccessed = true; } + } +); +notifier.notify({ type: 'foo', protoExpando: 'val'}); +assertFalse(protoExpandoAccessed); +delete Object.prototype.protoExpando; +Object.deliverChangeRecords(observer.callback); + +// Multiple records are delivered. +reset(); notifier.notify({ type: 'updated', name: 'foo', -- 2.7.4