Changes to Object.observe based on feedback from the September discussion

Rafael Weinstein rafaelw at
Thu Oct 17 15:09:05 PDT 2013

At the September meeting, the committee discussed Object.observe. Below is
a summary of the feedback, along with proposed changes to the spec.

1) Inconsistent naming of changeRecord types

The spec currently defines the following types: 'new', 'updated',
'deleted', 'reconfigured', 'prototype' & 'splice',

Proposed change: Make changeRecord types all be present tense:  'add',
'update', 'delete', 'reconfigure', 'setPrototype', 'splice'

2) An object becoming non-extensible isn't observable

Proposed change: Add a 'preventExtensions' type.

3) Concern about namespace collisions of future change type.

Proposed change: None. Adding an explicit namespace to changeRecords is
overkill. Future objects will simply need to ensure that added type names
are unique.

4) notifier.performChange should allow a returned object from its changeFn
to be used as the notification object. E.g.

  notifier.performChange('embiggened', () => {
    this.width *= amount;
    this.height *= amount;

    return {
      amount: amount

as short hand for

embiggin: function(int amount) {
  notifier.performChange('embiggened', () => {
    this.width *= amount;
    this.height *= amount;

    type: 'embiggened',
    amount: amount

Proposed change: Support this. If the return value of the changeFn is an
object, then emit a notification on the notifier's |target| with the same
type as that used for the performChange.

5) If a changeFn provided to performChange throws before completion, an
observer who accepts the performed change type won't get precise
information about which parts of the modification succeeded.

Proposed Change: None. The concern here about fault tolerance here is
valid. The problem is that a central motivation of the performChange
mechanism is performance, and the solution to this problem negates the main
performance benefit -- the ability in common cases to avoid the accounting
costs of generating the information for the lower-level changes. IOW, in
order to have failure result in the higher-level observer hearing about the
succeeded portion of the lower-level mutations, the system will have to
incur much of the cost of generating these records in all cases.

The bright spot here is that the success criteria that Mark proposed still
likely holds in that if a full mirror is maintained via observation, and
operations are deterministic, then the failure will occur on both sides in
the same way and the two sides will stay in sync.

6) Object.observe(obj, callback, opt_acceptList) implements a JS
antipattern: the callback argument isn't in the final position.

Proposed change: None. Use of the final argument will be *extremely* rare.
It's mostly there so that domain objects can expose custom observe methods
which specify the correct accept types, e.g.

Array.observe =~ function(object, callback) {
  return Object.observe(object, callback, ['add', 'update', 'delete',

There are three possible solutions to this concern: (1) make callback the
final argument, (2) Object.observe should take an arguments object, and (3)
Have Object.observe type check the second argument looking for either a
function or an array (support implicit multiple call signatures).

I'm interested in other's thoughts on this, but given the likely rarity of
providing the final argument, none of these seems like an improvement.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list