Changes to Object.observe based on feedback from the September discussion
On Thu, Oct 17, 2013 at 3:09 PM, Rafael Weinstein <rafaelw at google.com>wrote:
as short hand for
embiggin: function(int amount) { notifier.performChange('embiggened', () => { this.width *= amount; this.height *= amount; }); notifier.notify({ type: 'embiggened', amount: amount }); }
copy/paste error. This should have been:
as short hand for:
notifier.performChange('embiggened', () => {
this.width *= amount;
this.height *= amount;
});
notifier.notify({
type: 'embiggened',
amount: amount
});
On Thu, Oct 17, 2013 at 3:09 PM, Rafael Weinstein <rafaelw at google.com>wrote: > 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; > }); > > notifier.notify({ > type: 'embiggened', > amount: amount > }); > } > copy/paste error. This should have been: as short hand for: notifier.performChange('embiggened', () => { this.width *= amount; this.height *= amount; }); notifier.notify({ 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', > 'splice']) > } > > 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: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20131017/132b1caa/attachment-0001.html>
On Thu, Oct 17, 2013 at 3:09 PM, Rafael Weinstein <rafaelw at google.com> wrote:
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.
Put another way: If your use case includes observing changes which may partially succeed as a recoverable error-case, you should observe at a level of granularity which ensures you hear about which parts succeeded.
On Thu, Oct 17, 2013 at 3:09 PM, Rafael Weinstein <rafaelw at google.com>wrote: > 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; > }); > > notifier.notify({ > 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. > Put another way: If your use case includes observing changes which may partially succeed as a recoverable error-case, you should observe at a level of granularity which ensures you hear about which parts succeeded. > > > 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', > 'splice']) > } > > 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: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20131017/a045569a/attachment.html>
Note that these proposed changes are now reflected in the Object.observe spec text:
Note that these proposed changes are now reflected in the Object.observe spec text: http://wiki.ecmascript.org/doku.php?id=harmony:observe On Thu, Oct 17, 2013 at 3:09 PM, Rafael Weinstein <rafaelw at google.com>wrote: > 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; > }); > > notifier.notify({ > 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', > 'splice']) > } > > 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: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20131029/0546e959/attachment-0001.html>
At the September meeting, the committee discussed
Object.observe
. Below is a summary of the feedback, along with proposed changes to the spec.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'
An object becoming non-extensible isn't observable
Proposed change: Add a 'preventExtensions' type.
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.
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; }); notifier.notify({ 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.
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.
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', 'splice']) }
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.