Re: Object.observe feedback

2014-02-21 Thread Rafael Weinstein
 native feature
 here.

 -  Given the five solutions in my document, as the champion of
 Object.observe, what solution would you recommend someone use to process
 the records?  Use a library?  Keep a copy and just compare yourself?  Your
 insight into how you expect this spec to be used would be appreciated.



 Thanks Rafael – again I love the standard.  I may still be
 misunderstanding how this works.  But you asked for feedback.  Let me know
 your thoughts.



 Don

 P.S. – happy to add any of this to jsbin if you’d like to see it more
 closely with my testing scripts.











 *From:* Rafael Weinstein [mailto:rafa...@google.com]
 *Sent:* Sunday, February 16, 2014 8:06 AM
 *To:* Woodlock, Don (GE Healthcare)
 *Cc:* es-discuss@mozilla.org; dfwoodl...@gmail.com
 *Subject:* Re: Object.observe feedback



 BTW, here's your example using observe-js:



 http://jsbin.com/leh/1/edit



 On Sun, Feb 16, 2014 at 7:50 AM, Rafael Weinstein rafa...@google.com
 wrote:

 Hi Don,



 Thanks for the thoughtful feedback. I'm very glad you're excited about the
 feature. The short answer to your question is: the data you want is
 provided, but your processing needs to be more sophisticated.



 [BTW, The Chrome/V8 implementation (to the best of my knowledge) fully
 implements the latest spec for Object.observe]



 Basically, you're making an assumption about processing log data which is
 understandable, but unfortunately false. Though it would be nice, it's
 simply not possible to process each change record by looking at the final
 state of the observed object.



 Object.observe provides full information about the changes that occur, but
 depending on what view you want, you may need to do some processing to get
 the right answer.



 Based on the use-case you describe, it sounds like you have a very common
 desire -- to synchronize two objects, one of which has changed. The pattern
 requires what I'll call a diff in time view of the changes. In other
 words: from time 0 to time 1, what's the minimal set of changes I would
 need to apply to a copy of the observed object at time 0 in order to
 transform it into a copy of object at time 1?



 As you've found, Object.observe doesn't provide you this view of things.
 It provides you with a log of what happened along the way. However, you can
 use the log view as input into a transform which will provide you with the
 diff view.



 I've provided a JS library which serves multiple purposes:



 -A handy library for those who want the diff view of things

 -A reference implementation of some of these algorithms

 -A polyfill so that you may use this functionality in browsers that don't
 implement Object.observe (the polyfil mode has less desirable performance
 -- specifically the cost to determine what has changed is proportional to
 the total set of observed objects -- as opposed to Object.observe where the
 cost is proportional to the number of changes which took place).



 The library is here: https://github.com/Polymer/observe-js



 It may be sufficient for your use case (as well as act as the polyfill you
 were attempting to create) or it may simply serve as documentation for the
 processing that is required.



 Thanks again for your feedback and have fun.



 Cheers

 Rafael





 On Sun, Feb 16, 2014 at 5:25 AM, Woodlock, Don (GE Healthcare) 
 don.woodl...@med.ge.com wrote:

 HI Rafael et al,

 I have some feedback into the Object.observe proposal.
 Now I may be missing something so any clarification or education would be
 appreciated as well.  But I do love this particular spec and can’t wait to
 see it implemented.  But while I was implementing a pseudo-polyfill of it
 for my own purposes, I noticed an ‘information hole’ in the ChangeRecords
 design.  This is due to the asynchronous nature of the notification
 delivery and that subsequent mutations may have occurred by the time the
 notification is ‘delivered’.   In particular I believe a new ‘added’
 property is needed to the ChangeRecords of the splice transaction of an
 array mutation in the Array.observe design.

 Here’s the particular situation:

 First of all I’m assuming that the purpose of the
 ChangeRecords is to give the ChangeObserver enough information, beyond the
 fact that a change occurred, so that it doesn’t have to reprocess
 everything, but can be specific and efficient based on what in particular
 has changed.  For example if I have a view that lists a bunch of students
 and it’s observing an array of students, if a student gets added to the
 array, I’d like to know enough so the view can just add the one student and
 doesn’t have to redisplay the entire list because it knows the array has
 changed somehow.  Secondly I’ll assuming that the Chrome Canary
 implementation of Array.observe is suitably similar to the spec as that’s
 where I have been learning about what this design looks like in practice.

 Let’s say

Re: Object.observe feedback

2014-02-16 Thread Rafael Weinstein
Hi Don,

Thanks for the thoughtful feedback. I'm very glad you're excited about the
feature. The short answer to your question is: the data you want is
provided, but your processing needs to be more sophisticated.

[BTW, The Chrome/V8 implementation (to the best of my knowledge) fully
implements the latest spec for Object.observe]

Basically, you're making an assumption about processing log data which is
understandable, but unfortunately false. Though it would be nice, it's
simply not possible to process each change record by looking at the final
state of the observed object.

Object.observe provides full information about the changes that occur, but
depending on what view you want, you may need to do some processing to get
the right answer.

Based on the use-case you describe, it sounds like you have a very common
desire -- to synchronize two objects, one of which has changed. The pattern
requires what I'll call a diff in time view of the changes. In other
words: from time 0 to time 1, what's the minimal set of changes I would
need to apply to a copy of the observed object at time 0 in order to
transform it into a copy of object at time 1?

As you've found, Object.observe doesn't provide you this view of things. It
provides you with a log of what happened along the way. However, you can
use the log view as input into a transform which will provide you with the
diff view.

I've provided a JS library which serves multiple purposes:

-A handy library for those who want the diff view of things
-A reference implementation of some of these algorithms
-A polyfill so that you may use this functionality in browsers that don't
implement Object.observe (the polyfil mode has less desirable performance
-- specifically the cost to determine what has changed is proportional to
the total set of observed objects -- as opposed to Object.observe where the
cost is proportional to the number of changes which took place).

The library is here: https://github.com/Polymer/observe-js

It may be sufficient for your use case (as well as act as the polyfill you
were attempting to create) or it may simply serve as documentation for the
processing that is required.

Thanks again for your feedback and have fun.

Cheers
Rafael



On Sun, Feb 16, 2014 at 5:25 AM, Woodlock, Don (GE Healthcare) 
don.woodl...@med.ge.com wrote:

  HI Rafael et al,

 I have some feedback into the Object.observe proposal.
 Now I may be missing something so any clarification or education would be
 appreciated as well.  But I do love this particular spec and can’t wait to
 see it implemented.  But while I was implementing a pseudo-polyfill of it
 for my own purposes, I noticed an ‘information hole’ in the ChangeRecords
 design.  This is due to the asynchronous nature of the notification
 delivery and that subsequent mutations may have occurred by the time the
 notification is ‘delivered’.   In particular I believe a new ‘added’
 property is needed to the ChangeRecords of the splice transaction of an
 array mutation in the Array.observe design.

 Here’s the particular situation:

 First of all I’m assuming that the purpose of the
 ChangeRecords is to give the ChangeObserver enough information, beyond the
 fact that a change occurred, so that it doesn’t have to reprocess
 everything, but can be specific and efficient based on what in particular
 has changed.  For example if I have a view that lists a bunch of students
 and it’s observing an array of students, if a student gets added to the
 array, I’d like to know enough so the view can just add the one student and
 doesn’t have to redisplay the entire list because it knows the array has
 changed somehow.  Secondly I’ll assuming that the Chrome Canary
 implementation of Array.observe is suitably similar to the spec as that’s
 where I have been learning about what this design looks like in practice.

 Let’s say you have the array: [“c”, “d”, “f”].  If you are
 observing the array, and this operation occurs myArray.unshift(“b”), you
 will get the following notification:

 type = “splice”,

 removed = [],

 object: pointer to the array

 index: 0

 addedCount: 1



 You would naturally determine what was
 added via changeRecord.object.slice(changeRecord.index, changeRecord.index
 + changeRecord.addedCount);  That would show you that “b” got added.

 Subsequently (and with a delay), if you did
 myArray.unshift(“a”);, you will get an identically looking notification,
 and through the same approach, you would see that “a” got added.  You can
 see this if you run the first attachment in Chrome Canary.  If you run
 this, you can see in the console log that the fact that the changeObserver
 determines ‘b’ and then ‘a’ were added 

Re: Object.observe feedback

2014-02-16 Thread Rafael Weinstein
BTW, here's your example using observe-js:

http://jsbin.com/leh/1/edit


On Sun, Feb 16, 2014 at 7:50 AM, Rafael Weinstein rafa...@google.comwrote:

 Hi Don,

 Thanks for the thoughtful feedback. I'm very glad you're excited about the
 feature. The short answer to your question is: the data you want is
 provided, but your processing needs to be more sophisticated.

 [BTW, The Chrome/V8 implementation (to the best of my knowledge) fully
 implements the latest spec for Object.observe]

 Basically, you're making an assumption about processing log data which is
 understandable, but unfortunately false. Though it would be nice, it's
 simply not possible to process each change record by looking at the final
 state of the observed object.

 Object.observe provides full information about the changes that occur, but
 depending on what view you want, you may need to do some processing to get
 the right answer.

 Based on the use-case you describe, it sounds like you have a very common
 desire -- to synchronize two objects, one of which has changed. The pattern
 requires what I'll call a diff in time view of the changes. In other
 words: from time 0 to time 1, what's the minimal set of changes I would
 need to apply to a copy of the observed object at time 0 in order to
 transform it into a copy of object at time 1?

 As you've found, Object.observe doesn't provide you this view of things.
 It provides you with a log of what happened along the way. However, you can
 use the log view as input into a transform which will provide you with the
 diff view.

 I've provided a JS library which serves multiple purposes:

 -A handy library for those who want the diff view of things
 -A reference implementation of some of these algorithms
 -A polyfill so that you may use this functionality in browsers that don't
 implement Object.observe (the polyfil mode has less desirable performance
 -- specifically the cost to determine what has changed is proportional to
 the total set of observed objects -- as opposed to Object.observe where the
 cost is proportional to the number of changes which took place).

 The library is here: https://github.com/Polymer/observe-js

 It may be sufficient for your use case (as well as act as the polyfill you
 were attempting to create) or it may simply serve as documentation for the
 processing that is required.

 Thanks again for your feedback and have fun.

 Cheers
 Rafael



 On Sun, Feb 16, 2014 at 5:25 AM, Woodlock, Don (GE Healthcare) 
 don.woodl...@med.ge.com wrote:

  HI Rafael et al,

 I have some feedback into the Object.observe proposal.
 Now I may be missing something so any clarification or education would be
 appreciated as well.  But I do love this particular spec and can’t wait to
 see it implemented.  But while I was implementing a pseudo-polyfill of it
 for my own purposes, I noticed an ‘information hole’ in the ChangeRecords
 design.  This is due to the asynchronous nature of the notification
 delivery and that subsequent mutations may have occurred by the time the
 notification is ‘delivered’.   In particular I believe a new ‘added’
 property is needed to the ChangeRecords of the splice transaction of an
 array mutation in the Array.observe design.

 Here’s the particular situation:

 First of all I’m assuming that the purpose of the
 ChangeRecords is to give the ChangeObserver enough information, beyond the
 fact that a change occurred, so that it doesn’t have to reprocess
 everything, but can be specific and efficient based on what in particular
 has changed.  For example if I have a view that lists a bunch of students
 and it’s observing an array of students, if a student gets added to the
 array, I’d like to know enough so the view can just add the one student and
 doesn’t have to redisplay the entire list because it knows the array has
 changed somehow.  Secondly I’ll assuming that the Chrome Canary
 implementation of Array.observe is suitably similar to the spec as that’s
 where I have been learning about what this design looks like in practice.

 Let’s say you have the array: [“c”, “d”, “f”].  If you
 are observing the array, and this operation occurs myArray.unshift(“b”),
 you will get the following notification:

 type = “splice”,

 removed = [],

 object: pointer to the array

 index: 0

 addedCount: 1



 You would naturally determine what was
 added via changeRecord.object.slice(changeRecord.index, changeRecord.index
 + changeRecord.addedCount);  That would show you that “b” got added.

 Subsequently (and with a delay), if you did
 myArray.unshift(“a”);, you will get an identically looking notification,
 and through the same approach, you would see that “a” got added.  You can
 see

Re: Rev21 ES6 Draft now available

2013-11-13 Thread Rafael Weinstein
Nit: 9.1.10 [[Delete]] (P)

Steps 5  6 should be steps 4a  4b (lost an indent)


On Fri, Nov 8, 2013 at 12:25 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote:

 PDFs and .doc file available at

 http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#november_8_2013_draft_rev_21


 New in this revision:
 • Updated Module Syntax and static semantics
 • Scripts no longer may contain import statements
 • Specified how to determine if a call is in tail position
 • The call and apply functions now internally do tail calls to the target
 function
 • Tweaked the new operator so it will work in tail position
 • Eliminated the [[Invoke]] MOP operation
 • Calling the next method of an completed generator returns a “done”
 result instead of throwing
 • The length property of bound functions is now configurable/non-writable
 • Clarified requirements of String localeCompare when no language
 sensitive comparison support is available.
 • Tweaked the ordering of a few steps in Array.from to enable self-hosting
 using for-of
 • Added ToInt8 and similar abstract operation
 • Defined name property of %TypedArray% and the individual typed array
 constructors
 • Significant fixed to yield * evaluation semantics
 • Fixed handling of identifier ‘yield’ in generator function parameter
 lists
 • A little static semantic cleanup making sure that FunctionDeclarations
 and GeneratorDeclarations have the same top level scoping rules



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2013-10-29 Thread Rafael Weinstein
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 rafa...@google.comwrote:

 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.


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2013-10-17 Thread Rafael Weinstein
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.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2013-10-17 Thread Rafael Weinstein
On Thu, Oct 17, 2013 at 3:09 PM, Rafael Weinstein rafa...@google.comwrote:

 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.


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


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

2013-10-17 Thread Rafael Weinstein
On Thu, Oct 17, 2013 at 3:09 PM, Rafael Weinstein rafa...@google.comwrote:

 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.


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: microtask timeouts (was Re: setImmediate)

2013-08-12 Thread Rafael Weinstein
FWIW,

I very much agree with Dave on this point. My conceptual model for
microtask work is just a re-ordering of work which otherwise would
have run synchronously, but wanted to be run with a fresh stack.

Microtask non-termination should not be different from regular
script non-termination.

On Mon, Aug 12, 2013 at 6:09 PM, David Herman dher...@mozilla.com wrote:
 On Aug 12, 2013, at 5:43 PM, David Bruant bruan...@gmail.com wrote:

 - I see *no* reasonable alternative to runaway microtask churn other than 
 slow-script dialog.
 So did Dominic [1]. I suggested something else [2] and he found the idea 
 interesting. What do you think?

 Quoting you from

 [2] https://mail.mozilla.org/pipermail/es-discuss/2013-August/032630.html

 you said:

 Maybe implementations could decide to break a microtask chain, but
 instead of prompting a dialog, they just break it and call a callback
 (later, in a different task, not microtask) so that the script knows and
 can try to recover.

 It is an interesting idea, I missed it the first time around; you might 
 describe it as an asynchronous TimeoutException. I'm thinking about it, but 
 I'm pretty skeptical. It's still effectively preemption semantics. At any 
 nondeterministic (and not portably defined) point, your code can simply be 
 stopped. It's not even clear what the atomicity guarantees would be around 
 valid preemption points in the semantics. For example, can you preempt code 
 halfway through the modification of a 64-bit word? Can you preempt code that 
 hasn't spilled its registers back to memory? Am I scaring you yet? ;-)

 Even if we could provide a fully well-specified definition for concurrent 
 interruption, I really have no idea how code could ever realistically recover 
 from such an event. The only thing the system tells you is at some point in 
 some turn we just stopped you from whatever you were doing, and now you're 
 expected to reconstruct your state. This reminds me of exception safety in 
 C++.

 Dave

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Synchronous Object.observe but Asynchronous Object.unobserve ?

2012-11-04 Thread Rafael Weinstein
If you wish, you can maintain a WeakMap of observed objects. If you
wish to never process a changeRecord for an object you've stopped
observing, you can simply check the WeakMap to see if it's still
observed.

On Fri, Nov 2, 2012 at 9:50 PM, Andrea Giammarchi
andrea.giammar...@gmail.com wrote:
 fair enough, but I want to know what I am seeing is recorded and the TV is
 switched off ... how? Flagging records? Flagging objects? Via getNotifier ?


 On Fri, Nov 2, 2012 at 11:56 AM, Erik Arvidsson erik.arvids...@gmail.com
 wrote:

 On Fri, Nov 2, 2012 at 12:22 PM, Andrea Giammarchi
 andrea.giammar...@gmail.com wrote:
  How to make this simple ... if I switch off the TV I don't expect any
  eco
  after ... I don't care about the program, it should not bother me.

 If you stick to the TV analogy... You don't want Tivo to erase what it
 just recorded just because you stopped recording.

 --
 erik


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Synchronous Object.observe but Asynchronous Object.unobserve ?

2012-11-02 Thread Rafael Weinstein
Andrea,

I believe the example is correct. The way the API works is this:

Object.observe and Object.unobserve both *synchronously*
register/unregister your callback as observing/unobserving any given
object. The asynchrony has to do with having changeRecords delivered
-- that happens asynchronously.

I don't understand the leak you are describing. Perhaps you can give a
concrete example and how it goes wrong.

On Thu, Nov 1, 2012 at 9:32 PM, Andrea Giammarchi
andrea.giammar...@gmail.com wrote:
 Just wondering if this is actually meant/expected, I am talking about the
 example here:

 http://wiki.ecmascript.org/doku.php?id=harmony:observe#example

 and the fact it should show something in console while in my opinion that
 should show nothing since the Object.unobserve is called in the same tick

 Then I read the algo and I wonder if this won't create many problems, i.e.
 enabling a new way to leak objects through observers that should not be
 called once the object is not observed anymore, specially because there's no
 way to understand if the object is observed or not, isn't it?

 Thanks for any sort of clarification.

 br

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Synchronous Object.observe but Asynchronous Object.unobserve ?

2012-11-02 Thread Rafael Weinstein
Take for example:

function myCallback(recs) {
  console.log(recs.length);
}

var obj = {};
Object.observe(obj, myCallback);
obj.a = 1; // enqueues changeRecord
obj.b = 2; // enqueues changeRecord
Object.unobserve(obj, myCallback);
obj.c = 3; // does not enqueue changeRecord



In the above example, myCallbacks will be invoked with two
changeRecords and output

 2

It sounds like you are worried about callbacks being delivered with
changeRecords pointing to objects that they have stopped observing.
This can and will happen. It's just something that users of the API
need to understand. It doesn't strike me as a problem, but perhaps I'm
missing something...?

On Fri, Nov 2, 2012 at 5:04 PM, Andrea Giammarchi
andrea.giammar...@gmail.com wrote:
 hey, thanks for coming back. The asynchronous unobserve in the meaning that
 Object.unobserve is performed synchronously but the delivery of records is
 asynchronous and performed regardless the object is not observed anymore.

 Inside the observer each record can point to an object that is no more
 observed and I am not sure if there is a way to understand this or if the
 observer should perform the getNotifier(obj) check.

 The way I would implement this is that when the Object.unobserve(obj) is
 called, the queue, if any, with all previous records, is delivered at that
 time, and not during the next tick.

 Thoughts?


 On Fri, Nov 2, 2012 at 5:17 AM, Rafael Weinstein rafa...@chromium.org
 wrote:

 Andrea,

 I believe the example is correct. The way the API works is this:

 Object.observe and Object.unobserve both *synchronously*
 register/unregister your callback as observing/unobserving any given
 object. The asynchrony has to do with having changeRecords delivered
 -- that happens asynchronously.

 I don't understand the leak you are describing. Perhaps you can give a
 concrete example and how it goes wrong.

 On Thu, Nov 1, 2012 at 9:32 PM, Andrea Giammarchi
 andrea.giammar...@gmail.com wrote:
  Just wondering if this is actually meant/expected, I am talking about
  the
  example here:
 
  http://wiki.ecmascript.org/doku.php?id=harmony:observe#example
 
  and the fact it should show something in console while in my opinion
  that
  should show nothing since the Object.unobserve is called in the same
  tick
 
  Then I read the algo and I wonder if this won't create many problems,
  i.e.
  enabling a new way to leak objects through observers that should not be
  called once the object is not observed anymore, specially because
  there's no
  way to understand if the object is observed or not, isn't it?
 
  Thanks for any sort of clarification.
 
  br
 
  ___
  es-discuss mailing list
  es-discuss@mozilla.org
  https://mail.mozilla.org/listinfo/es-discuss
 


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Object.observe and observing computed properties

2012-09-19 Thread Rafael Weinstein
[Sorry, this time from the right email]

Object.deliverChangeRecords allows A to be a strategy in the possible
future that Steve describes (if reads were to generate changeRecords)

[Just to be clear: I *don't* think it makes sense to include reads in
the set of changeRecords generated by Object.observe() at this point]

The basic idea is that every computed property has around advice
that clears its pending delivery queue before and after invocation of
the actual function so it can disambiguate reads generated during the
invocation from outer (previous or later) or inner (sub-invocations of
computed properties) reads.

On Wed, Sep 19, 2012 at 2:09 PM, Brendan Eich bren...@mozilla.com wrote:
 From A, B and C as alternatives, especially A and C, it seems you want
 synchronous read intercession, but are happy with Object.observe's
 asynchronous write intercession?

 If so, then the plan interference objection is fatal.

 If not, then how would async read intercession work? Callbacks and promises
 are not going to fly.

 /be

 Steve Sanderson wrote:

 Following this discussion, Rafael and I talked about various strategies
 that an MV* library could use to detect dependencies from arbitrary
 expressions and code blocks, as would be needed to achieve the kinds of
 niceties present in Knockout.js/Batman.js etc. Some of these tie in with
 Object.observe more than others.

 The upshot is that we don't have a single most compelling way to do this
 kind of dependency detection with Object.observe, but it would be possible
 to augment Object.observe to add that ability in a future language version
 (see technique A below), or alternatively, libraries could use somewhat less
 clean techniques to achieve it with proxies/accessors alone, regardless of
 Object.observe (see techniques B and C below).

 So as a library developer I would in principle be happy to see
 Object.observe added to ES, since it appears to be a step in the right
 direction. But I would caution that unless read notifications were added
 (see technique A), my library (knockout.js) couldn't use it to achieve
 something as clean as its existing semantics, so we'd most likely be waiting
 for future improvements before being able to use Object.observe.

 Regards
 Steve

 *_Appendix: the techniques we considered_*

   * *Technique A: Add read notifications to Object.observe (either
 now, or in a future ECMAScript version)*
   o Just as the existing Object.observe proposal delivers

 notification of property writes for specific objects, a
 symmetrical API could deliver notification of property reads
 for specific objects
   o Pros: it requires no proxies or accessors, so works with raw data
   o Cons: requires language support, like Object.observe does for
 write notifications
   * *Technique B: Membrane-style proxies transitively capture all
 chains of properties read from a given object*
   o The logic that parses/evaluates binding expressions could

 supply a specially wrapped version of the underlying data that
 uses a proxy to log property reads
   o Pros: doesn't require language support; ties in with

 Object.observe in that once you know what properties were
 read, you can use Object.observe to subscribe to write
 notifications
   o Cons: because the proxies aren't the real underlying data

 objects, it's possible to get into confusing scenarios where
 things don't work, for example if you read a property of a
 closure-captured variable, that won't be logged and hence the
 framework can't auto-update when that property changes
   * *Technique C: Monkeypatch all model data properties with accessors
 that log reads*
   o Some utility function would walk the object graph and replace

 all properties with special accessors
   o Pros: doesn't require language support; also doesn't even

 require Object.observe since you might as well also replace
 setters with ones that trigger notification on change
   o Cons: very intrusive - permanently modifies the developer's
 data structures



 On Fri, Aug 31, 2012 at 10:38 AM, François REMY fremycompany_...@yahoo.fr
 mailto:fremycompany_...@yahoo.fr wrote:

 *From:* Alex Russell mailto:slightly...@google.com
 *Sent:* Thursday, August 30, 2012 7:44 PM
 *To:* ste...@stevensanderson.com mailto:ste...@stevensanderson.com
 *Cc:* es-discuss@mozilla.org mailto:es-discuss@mozilla.org
 *Subject:* Re: Object.observe and observing computed properties

 On Wed, Aug 29, 2012 at 11:09 AM, Steve Sanderson
 fla...@gmail.com mailto:fla...@gmail.com wrote:

 Knockout developers are used to this sort of thing updating
 automatically whenever you modify the price of any item, or
 when you add or remove items to the array. It would be very
 inconvenient to have to somehow declare dependencies 

Re: Experimental implementation of Object.observe JS Utilitylibrary now available

2012-08-28 Thread Rafael Weinstein
Hi François,

Thanks so much for your thoughtful consideration of the
Object.observe() proposal. Here's my take on your counter-proposal:

Interestingly, what you've focused on is the one thing we
intentionally left out of the Object.observe() proposal, namely:
observing computed properties. In that way, I don't see what you've
proposed as an alternative, but rather supplementary.

First, I'd like to point out that, while most people these days seem
to say databinding and specifically mean updating a UI, there are
important use cases which depend on observing mutations to objects
which are entirely distinct.

Note that what you've proposed, doesn't include the following abilities:

1) Discovering when new properties are added to objects -- which is
particularly important in the case of Arrays, where you often want to
bind to the *set* of elements in an Array

2) Knowing the order of changes which occurred -- this is important to
many use cases, including persisting changes to domain objects and
efficiently computing effective changes to complex data structures (a
DOM tree implemented in JS would be one example).

3) Discovering when properties have been reconfigured -- which is
important if your strategy for observing computed properties is
comparatively expensive, and you need to know *when* to employ it.

4) Generally, having full knowledge of what happened to an object so
as to able to efficiently mirror it -- which is important in some
synchronization strategies.

Ok, with that out of the way, I think the topic you've raised:
computed properties, deserves its own thread -- so I'll start a new
thread for that purpose and put my thoughts there.

On Sun, Aug 26, 2012 at 6:14 AM, François REMY
fremycompany_...@yahoo.fr wrote:
 Here’s my take on the binding thing:
 http://fremycompany.com/BG/2012/ECMAScript-Binding-Manager-951/

 Key features:
 - Do not require to have a reference on an object to bind to it (binding is
 implicit and managed by the browser).
 - Accessors, function calls and inner dependencies are managed
 automatically.
 - Since the browser manage most the binding wiring, it can makes tons of
 optimizations.
 - It’s trivial to use for developers.

 Have a look ;-)


 From: Alex Russell
 Sent: Thursday, August 23, 2012 11:47 AM
 To: Brandon Benvie
 Cc: ste...@stevensanderson.com ; es-discuss@mozilla.org
 Subject: Re: Re: Experimental implementation of Object.observe  JS
 Utilitylibrary now available
 On Thu, Aug 23, 2012 at 7:06 AM, Brandon Benvie bran...@brandonbenvie.com
 wrote:

 I would say it is most definitely not the concern of Observe to watch
 reads and between accessors and Proxies we have all the tools we need for
 that.


 I think that misreads the situation. Having proxies available might work for
 this, but is it the right (implied) *UI* for it? I.e., if you need to do
 half of your work with observe() and then pivot over to proxies for the
 other half...that strikes me as strange. There might be good reasons not to,
 but saying you can do it with what we've got is always tautological in a
 turing machine = )


 With the ability to keep present on notifications of changes via observe
 it's actually possible to implement a mirror that can be emit change events
 (by explicitly mirroring changes on the original target changes) and provide
 the benefits of the observe api to listeners, and then implement any kind of
 additional tracking on top of that either by using accessors or being a
 proxy.
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



 
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Object.observe and observing computed properties

2012-08-28 Thread Rafael Weinstein
Steve Sanderson (author of the excellent KnockoutJS framework) and
François REMY both raised the issue of observing computed properties
WRT to the Object.observe() proposal.

Having thought about this problem while helping to author
Object.observe, my thoughts are as follows:

First, I think you need to look at the problem the right way.
Observing computed properties is kind of non-sensical. What this
translates to is observe when the *return value* of an anonymous
function invocation *will be* different from the last invocation.

I think the only reasonable way to look at it is this: imagine that a
*data property* can be defined whose value can only be set by
assigning it the return value of a given function. Observing when a
data property changes value is trivial. The problem becomes: deciding
when the function should be re-evaluated.

Looked at like this, the first thing that becomes obvious is that
there are a class of functions which should never be used: those
functions that can spontaneously change value. e.g.

  var i = 1;
  function getVal { return ++i; }
  function getVal2 { return Math.random(); }
  function getVal3 { return myElement.offsetHeight; }

[I actually think at this point it becomes clear that, because the
task at hand isn't solvable in general, it's not appropriate to
include support for it at the language level, but lets continue].

That said, those functions:

-whose output is dependent only on the value of a discrete set of
inputs, (i.e. are stateless)
-don't modify their inputs
-will always return the same output value for the same set of inputs

can be sensibly used for computed property functions. It's worth
noting that even this can be easy to get wrong. For example, many
webdevs might not realize that

  var firstName = 'Rafael';
  var lastName = 'Weinstein';
  function getVal() { return [firstName, lastName]; }

doesn't meet this criteria as its return value is always a different
Array object.

Assuming that you've been careful to pick an appropriate function,
there are two approaches to knowing when to reevaluate it:

1) Dirty-checking: Immediately before each time you need the value
of the dependent property.
2) Dependency observation: When one or more of its inputs have changed value.

At this point, you have only trade-offs. (1) Is potentially expensive
and hard to do at exactly the right time, but (2) requires having
proper knowledge of the function's inputs.

Obtaining the set of inputs for (2) can be done in two ways:

2a) Require the function author to declare them.
2b) Attempt to discover them by running the function and observing
which inputs it accesses.

(2a) requires some careful attention on the part of the function
author, so in some sense, if (2b) were possible, it would be ideal.
This brings us to what KnockoutJS does and what François proposed, so
let's consider it.

The first problem is what I discussed above, that creating an
*appropriate* function is potentially tricky and/or hard to
understand, and there isn't any way to statically determine if a
function is or is not appropriate.

The second problem is that doing this risks discovering inputs that
aren't really inputs at all. In other words, the function, just be
being invoked happens to touch a wide swath of objects, even though
they aren't dependencies of the function. This is bad because it would
cause the system to observe these objects, which, given modern VMs,
will cause them to de-optimize and become slower to access

Thus, offering language-level support for (2b) puts developers in the
risky situations of authoring computed property functions which may

A) not fire their notifications, even though they appear to have changed value
B) become a go-slow button for their entire application

...with no good recourse to discover why either is happening.

Note that François's proposal included a mitigation of (B), in that
you need to whitelist objects as potential discoverable dependencies.
This helps some with the risk of discovering too many dependencies,
but it also risks not discovering enough dependencies, which becomes
problem (A) again.



Thus, what we have is a problem which is really solved through
convention, not through an abstract solution, and thus the most
sensible thing to do is leave it to authors to make trade-offs for
themselves about the pros  cons of the various approaches and the
conventions they imply.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Experimental implementation of Object.observe JS Utility library now available

2012-08-22 Thread Rafael Weinstein
Hi Steve,

Thanks for joining the conversation. =-)

The automatic dependency discovery that Knockout does is rather cool.
My sense has been that Proxy is a better tool for this job than is
expanding the semantics of Object.observe() to include reads.

Object.observe() only operates on objects which are specifically
observed, so something like

get val function() {
  this.foo.bar + this.bat.baz;
}

Would only report access to this.foo and this.bat, but not foo.bar and bat.baz.

While applying the function to a proxy wrapper allows for the creation
of a membrane through which you can discover dependencies not
available on the local object.

Is my thinking flawed?

Note that the Object.observe() specifically reports when properties
are reconfigured such that any approach you take to computed
properties can know when it needs to invoke its strategy and when it
can rely on the system-generated change records.

On Wed, Aug 22, 2012 at 3:34 AM, Steve Sanderson fla...@gmail.com wrote:
 This is fantastic - thanks for pushing this forwards, Rafael!

 For context, I'm part of the knockout.js (a JavaScript MV* library) team, so
 I have some interest in how this could work out. This spec has a lot of
 potential to make MVC-style coding far simpler and more robust, both for
 framework developers and web app developers. Although the semantics of the
 Object.observe proposal are different in a few ways from what Knockout and
 similar frameworks use for observability, it certainly looks applicable
 enough to the same design patterns and APIs.

 There's one significant extra aspect of observability that Knockout, Batman,
 CanJS, and other MVC-type frameworks rely on that isn't covered as far as I
 can tell by the proposal so far. These frameworks can automatically
 determine the dependencies of an arbitrary block of code. For example, if
 there is a block of code that determines the output of a computed property,
 like this:

 function fullName() { return firstName +   + lastName };

 ... then if you use such a function during a declarative binding, those
 frameworks' observability mechanisms will automatically know which
 underlying observable properties it depends on. This is possible because the
 frameworks' observabilty mechanisms can notify on read as well as on write.
 This ends up being a very powerful and flexible feature whereby the
 framework can manage arbitrary and dynamically-changing dependency chains,
 and the developer can robustly call arbitrary custom functions in computed
 property evaluators and bindings.

 These facilities could be made possible in the Object.observe proposal by
 adding one further primitive feature. Just as you can register for
 notifications on *write*, you'd ideally also be able to register for
 separate notifications on *read*. Typically only framework code would do
 that - application code wouldn't usually need to. The actual dependency
 detection logic would differ depending on whether read notifications were
 delivered synchronously or asynchronously, but then everything else can be
 built on top of that primitive.

 Please let me know if you want more detailed descriptions of how any of this
 works in Knockout/etc. I'd be happy to suggest how a comparable API might
 look in the Object.observe world!

 Regards
 Steve

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Experimental implementation of Object.observe JS Utility library now available

2012-08-19 Thread Rafael Weinstein
On Sun, Aug 19, 2012 at 11:25 AM, John J Barton
johnjbar...@johnjbarton.com wrote:


 On Fri, Aug 17, 2012 at 9:49 PM, Rafael Weinstein rafa...@chromium.org
 wrote:

  A synchronous observation mechanism provides an attacker too many
  opportunities for a plan interference attack. If you'll recall, an
  earlier
  synchronous proposal died for this reason.

 That is an excellent reason. I have two others:

 1) It's a terrible design pattern to encourage. Webdevs will
 absolutely use it and learn the hard way, just like we did with
 Mutation Events that it works fine when we start, but down the road
 lies nothing but pain and suffering.

 2) Synchronous doesn't actually exist -- it's a false option.

 To explain: When people talk about synchronous what they expect is
 that they will be notified concurrent with the event happening (this
 *is happening*). The expectation is that when they are invoked they
 are observing the world as the event is describing.

 This is the appeal of synchronous delivery. Here's the rub: unless you
 plan to only allow a single observer per object, then you have to pick
 someone to go first. And unless you plan to prevent that person from
 further mutating the object, the next guy to be called may not observe
 the world in the state suggested by the synchronous call.

 In fact, an arbitrary number of mutations can always have occurred by
 the time any given observer is called, so it's just dishonest API
 which pretends that a single thing has happened. The correct thing is
 to inform each observer what *set* of things has happened.

 So the only questions are:

 1) Do you mislead the consumer with API which suggests that only one
 thing will has happened
 2) If not, when do you deliver the set of things: immediately after
 the mutation occurs, at the end of the turn or ask the UA to schedule
 a future task.

 Referring back to my reason (1) This question was debated extensively
 with DOM Mutation Observers and unanimously decided that the end of
 the turn was the only good solution. immediately puts all code in
 danger of having its runtime assumptions invalidated after every
 operation which mutates objects and future task is far too late to
 be useful for most almost all use cases.



 I can understand how batched changes and end-of-turn asynchronous calls are
 a good match.  The development model is now here are the changes from this
 turn rather than here is a change.

 But I don't understand how end-of-turn asynchronous calls helps with the
 multiple independent listeners problem. If a listener can mutate the DOM,
 then change-listeners depend upon change-listeners. The relative timing of
 the listener calls and the non-listener DOM mutations does not change that
 dependency.

 And once change-listeners mutate the DOM then the API of here are the
 changes from this turn again misleads the developer relying on it.

Actually, this isn't quite right. It's here are all the changes since
the last time you were invoked. I.e. every observer is always
delivered all changes to all entities it is observing up to the time
that it is invoked. To be concrete, the following invariants always
hold:

A) When an observer is invoked, is it delivered a sequence of change
records representing all changes to entities it is observing -- up to
the time of its invocation.
B) When an observer is invoked, it is free to mutate entities and do
work without risk of being preempted by other observers being notified
of changes it makes.
C) Conversely, when an observer is invoked, no other script is below
it on the stack.
D) An observer will be delivered all changes to entities it is
observing before the turn ends.

These are true for both Object.observe() and for DOM Mutation Observers.

In other words, any given observer can be blissfully ignorant of all
other actors in the system. It is always delivered a full picture of
what has happened in its world, it can act completely independently of
other actors, and it will always get all of its changes before the
turn ends.

Does this address your concern?


 (I think simplifying the internal browser logic for DOM mutation is all the
 justification needed for new API for DOM mutation observers).

 jjb
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Experimental implementation of Object.observe JS Utility library now available

2012-08-18 Thread Rafael Weinstein
On Sat, Aug 18, 2012 at 3:06 PM, Brendan Eich bren...@mozilla.org wrote:
 Rafael Weinstein wrote:

 On Fri, Aug 17, 2012 at 8:03 PM, Brendan Eichbren...@mozilla.org  wrote:

 Mark S. Miller wrote:

 On Fri, Aug 17, 2012 at 6:49 PM, Brendan Eichbren...@mozilla.org
 mailto:bren...@mozilla.org  wrote:

  All praise to Raf et al., my concern is that something
  synchronous, plus event loop concurrency and setImmediate, would
  suffice to bootstrap the rather more elaborate proposal on top of
  the simpler O.p.watch like fundament.

  This is not to say we shouldn't standardize higher-level APIs, and
  instead push that off on library authors to write, and users to
  download. There's a delicate balance here. We often screw up
  higher-level abstractions in annoying ways, but perhaps that risk
  is worth taking.

  What I'm really getting at is this: why not expose the synchronous
  primitive and e.l.c. building blocks as well?


 A synchronous observation mechanism provides an attacker too many
 opportunities for a plan interference attack. If you'll recall, an
 earlier
 synchronous proposal died for this reason.


 That is an excellent reason.


 It is, and I should have recited it to the Y U no kids but I hadn't found it
 expressed concisely. I should have looked harder -- it was recorded in the
 May 2011 meeting notes:

 https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html

 
 Allen: This allows people to break into abstractions by putting observers on
 objects they don't own.
 DaveH: Proxies are deliberately less powerful than this in that they don't
 allow you to attach behaviors to arbitrary objects that you don't own.
 MarkM: Notification happening synchronously is a security problem.
 Observers can run at times when code doesn't expect malicious changes.

 


   I have two others:

 1) It's a terrible design pattern to encourage. Webdevs will
 absolutely use it and learn the hard way, just like we did with
 Mutation Events that it works fine when we start, but down the road
 lies nothing but pain and suffering.


 This is not a complete reason -- see mutation events -- but I know that
 history too. What I remember mostly dissuading developers was bad
 performance -- use a mutation event listener and your DOM got slow -- but
 any more detailed history would be helpful, here if not in the spec (more
 below).


Apologies. My comment wasn't especially helpful or informative. You
are absolutely right that the main reason that webdevs avoided them
was because they were horrifically slow.

The pain and suffering I was (inelegantly) referring to was that of UA
implementors. The pain most acutely felt was that of having to write
code which needed to tolerate script tearing the DOM to shreds in the
middle of a multiple-step operation.

Basically, if Mutation Events had been fast enough and fully deployed
(and thus actually used), webdevs would have ended up feeling that
pain that UA implementors were trying to ride themselves of
(essentially, writing code that couldn't be counted on to run in
isolation)


 2) Synchronous doesn't actually exist -- it's a false option.

 To explain: When people talk about synchronous what they expect is
 that they will be notified concurrent with the event happening (this
 *is happening*). The expectation is that when they are invoked they
 are observing the world as the event is describing.

 This is the appeal of synchronous delivery. Here's the rub: unless you
 plan to only allow a single observer per object, then you have to pick
 someone to go first. And unless you plan to prevent that person from
 further mutating the object, the next guy to be called may not observe
 the world in the state suggested by the synchronous call.


 Synchronous != synchronized.



 In fact, an arbitrary number of mutations can always have occurred by
 the time any given observer is called, so it's just dishonest API
 which pretends that a single thing has happened. The correct thing is
 to inform each observer what *set* of things has happened.


 Right, the is happening = has happened implies the set.


 So the only questions are:

 1) Do you mislead the consumer with API which suggests that only one
 thing will has happened
 2) If not, when do you deliver the set of things: immediately after
 the mutation occurs, at the end of the turn or ask the UA to schedule
 a future task.

 Referring back to my reason (1) This question was debated extensively
 with DOM Mutation Observers and unanimously decided that the end of
 the turn was the only good solution. immediately puts all code in
 danger of having its runtime assumptions invalidated after every
 operation which mutates objects and future task is far too late to
 be useful for most almost all use cases.


 Thanks, this is good and perhaps we don't need to dig up and summarize the
 mutation observer debate. But I think the spec (proposal and ECMA-262)
 should record an informative note

Re: Experimental implementation of Object.observe JS Utility library now available

2012-08-17 Thread Rafael Weinstein
Hi gaz,

Thanks so much for your time.

Much care has been taking with this proposal to ensure that it is
neutral with respect to the existing JS Object/Security model.

As I understand it, the core vulnerability with JSON hacking is the
ability to define getters on the Object prototype. Object.observe()
does not affect that ability.

In order to be notified of changes to an object, you need a reference
to it first. E.g.

Object.observe(Object.prototype, function doBadThings() { .. });

But if you were able to do this, you could have just as easily gone
ahead and done bad things directly to the Object.prototype.
Object.observe() doesn't increase your access.

If there is something I'm missing, perhaps you can provide a code
example of how the attack would work.

On Fri, Aug 17, 2012 at 2:50 AM, gaz Heyes gazhe...@gmail.com wrote:
 Hi Rafael

 Would this proposal work on the Object prototype? If so then it could be
 used for JSON hijacking. I'd recommend it didn't.

 Cheers

 Gareth
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Experimental implementation of Object.observe JS Utility library now available

2012-08-17 Thread Rafael Weinstein
On Fri, Aug 17, 2012 at 8:03 PM, Brendan Eich bren...@mozilla.org wrote:
 Mark S. Miller wrote:

 On Fri, Aug 17, 2012 at 6:49 PM, Brendan Eich bren...@mozilla.org
 mailto:bren...@mozilla.org wrote:

 All praise to Raf et al., my concern is that something
 synchronous, plus event loop concurrency and setImmediate, would
 suffice to bootstrap the rather more elaborate proposal on top of
 the simpler O.p.watch like fundament.

 This is not to say we shouldn't standardize higher-level APIs, and
 instead push that off on library authors to write, and users to
 download. There's a delicate balance here. We often screw up
 higher-level abstractions in annoying ways, but perhaps that risk
 is worth taking.

 What I'm really getting at is this: why not expose the synchronous
 primitive and e.l.c. building blocks as well?


 A synchronous observation mechanism provides an attacker too many
 opportunities for a plan interference attack. If you'll recall, an earlier
 synchronous proposal died for this reason.

That is an excellent reason. I have two others:

1) It's a terrible design pattern to encourage. Webdevs will
absolutely use it and learn the hard way, just like we did with
Mutation Events that it works fine when we start, but down the road
lies nothing but pain and suffering.

2) Synchronous doesn't actually exist -- it's a false option.

To explain: When people talk about synchronous what they expect is
that they will be notified concurrent with the event happening (this
*is happening*). The expectation is that when they are invoked they
are observing the world as the event is describing.

This is the appeal of synchronous delivery. Here's the rub: unless you
plan to only allow a single observer per object, then you have to pick
someone to go first. And unless you plan to prevent that person from
further mutating the object, the next guy to be called may not observe
the world in the state suggested by the synchronous call.

In fact, an arbitrary number of mutations can always have occurred by
the time any given observer is called, so it's just dishonest API
which pretends that a single thing has happened. The correct thing is
to inform each observer what *set* of things has happened.

So the only questions are:

1) Do you mislead the consumer with API which suggests that only one
thing will has happened
2) If not, when do you deliver the set of things: immediately after
the mutation occurs, at the end of the turn or ask the UA to schedule
a future task.

Referring back to my reason (1) This question was debated extensively
with DOM Mutation Observers and unanimously decided that the end of
the turn was the only good solution. immediately puts all code in
danger of having its runtime assumptions invalidated after every
operation which mutates objects and future task is far too late to
be useful for most almost all use cases.



 Thanks, I recall -- but this needs to be stated clearly in the spec. I hear
 from people all the time asking Y U no Object.prototype.watch.

Which spec? Is there something you're wanting to see in the text of
the Object.observe proposal?


 /be


 Object.observe has been carefully designed to strike a good balance
 between providing non-malicious code useful new powers without providing
 attackers significant new attack opportunities. The core principle is that a
 client of an object can anyway observe changes to observable state
 asynchronously by polling between turns. And a client of an object, if it
 receives control during a turn, can poll while it has control. To a first
 approximation, Object.observe can be understood as an optimization of
 polling. It is actually more powerful than that, but in ways that are
 beneficial without IMO creating significant new hazards.


 /be

 Brandon Benvie wrote:

 I agree on the above with regard to Proxies. They are awesome
 and allow for incredible things, but Object.observe fills a
 different use case that I think is more common at at the user
 standpoint or at least library standpoint. When you look
 around at the major JS libraries that exist the problem they
 are trying to solve (after DOM normalization) is data-binding.
 Proxy can be used to solve this for new objects or wrapped
 objects, but that's overkill and may have performance
 consequences, and has no support for working with existing
 objects. Proxy and observe end up filling two completely
 different use-cases, and I would venture to say that observe
 is the one that most people could make better use of if they
 had it in their hands today.
 ___
 es-discuss mailing list
 es-discuss@mozilla.org mailto:es-discuss@mozilla.org

 https://mail.mozilla.org/listinfo/es-discuss

 ___
 es-discuss mailing 

Re: Experimental implementation of Object.observe JS Utility library now available

2012-08-16 Thread Rafael Weinstein
I've created a bunch of cool demos and a video which attempts to
explain the use cases  need for Object.observe().

https://plus.google.com/u/1/111386188573471152118

On Mon, Aug 13, 2012 at 12:28 PM, Rafael Weinstein rafa...@chromium.org wrote:
 Hi all,

 As promised, here is an experimental implementation of the
 Object.observe strawman in a branch of v8:

 https://github.com/rafaelw/v8

 [Note that there are Mac  Windows binaries of Chromium for everyone's
 convenience. The links to the binaries are contained in the README.md
 -- and also at the bottom of the page].

 Also, here is a JS Utility library which uses the Object.observe()
 mechanism and exposes some higher-level and more convenient
 abstractions (such as path observation  array splice computations):

 https://github.com/rafaelw/ChangeSummary.

 [Note that this library is to Object.observe as MutationSummary
 (http://code.google.com/p/mutation-summary/) is to DOM Mutation
 Observers]

 

 Expect (and report) bugs in both and crashes in the v8 impl, but it
 should be stable enough now for actual experimentation  prototyping.

 Unless someone feels otherwise, we just assume any feedback go
 directly es-discuss (to this thread is fine) so as not to split away
 from here any substantive discussion about the feature.

 

 Our next step is to align our tests and the ChangeSummary library with
 Tom's excellent proxy implementation so we'll have two experimental
 versions which pass the same set of tests (and we can continue to use
 Tom's proxy impl as a reference spec-in-code].

 Enjoy
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Experimental implementation of Object.observe JS Utility library now available

2012-08-13 Thread Rafael Weinstein
Hi all,

As promised, here is an experimental implementation of the
Object.observe strawman in a branch of v8:

https://github.com/rafaelw/v8

[Note that there are Mac  Windows binaries of Chromium for everyone's
convenience. The links to the binaries are contained in the README.md
-- and also at the bottom of the page].

Also, here is a JS Utility library which uses the Object.observe()
mechanism and exposes some higher-level and more convenient
abstractions (such as path observation  array splice computations):

https://github.com/rafaelw/ChangeSummary.

[Note that this library is to Object.observe as MutationSummary
(http://code.google.com/p/mutation-summary/) is to DOM Mutation
Observers]



Expect (and report) bugs in both and crashes in the v8 impl, but it
should be stable enough now for actual experimentation  prototyping.

Unless someone feels otherwise, we just assume any feedback go
directly es-discuss (to this thread is fine) so as not to split away
from here any substantive discussion about the feature.



Our next step is to align our tests and the ChangeSummary library with
Tom's excellent proxy implementation so we'll have two experimental
versions which pass the same set of tests (and we can continue to use
Tom's proxy impl as a reference spec-in-code].

Enjoy
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: July 25, 2012 - TC39 Meeting Notes

2012-07-30 Thread Rafael Weinstein
On Mon, Jul 30, 2012 at 2:56 PM, Aymeric Vitte vitteayme...@gmail.com wrote:

 Le 28/07/2012 01:55, Rick Waldron a écrit :


 Explanation of specification history and roots in newer DOM mutation
 mechanism.

 AWB: Is this sufficient for implementing DOM mutation event mechanisms?

 RWS: Yes, those could be built on top of Object.observe


 Probably I must be misreading the proposal (again), but if you take a js DOM
 project where almost all attributes are handled via getters/setters, how can
 we observe something ?

The point wouldn't be to observe DOM changes directly via
Object.observe() by user script. The DOM Mutation API is different in
several ways from Object.observe() (different API surface area,
different vocabulary of changes, etc...)

One approach would be have the DOM storage internally be graphs of
simple data. The implementation can observe changes and then compute a
transform of the data changes it receives into the necessary DOM
mutations, which it then broadcasts.

I don't have an opinion of whether it would be a good idea to take
this approach (my guess is that standard trade-offs of complexity 
memory vs speed would apply). Allen's question was whether it would be
possible.


 --
 jCore
 Email :  avi...@jcore.fr
 Web :www.jcore.fr
 Webble : www.webble.it
 Extract Widget Mobile : www.extractwidget.com
 BlimpMe! : www.blimpme.com


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Updates to Object.observe

2012-07-18 Thread Rafael Weinstein
On Wed, Jul 18, 2012 at 3:20 PM, Erik Arvidsson
erik.arvids...@gmail.com wrote:
 On Tue, Jul 17, 2012 at 8:25 PM, Russell Leggett
 russell.legg...@gmail.com wrote:
 One of the absolutely most useful things I would not want to live without in
 a databinding framework is bind to properties or property paths. It is
 extremely common to want a handler to only listen for changes to a single
 property - the same way event handlers do. Something like:

 Object.observe(o,x,observer);

 Which would only be notified of changes to x, instead of having to check
 which property each time. Its a minor thing, but common.

 In my framework it is also possible to databind to a whole path - so lets
 say something like:

 Object.observe(o,x.y, observer);

 This would be attached at o, but it listens down the whole path, so a
 change to the y on x would fire, but a change to x would fire also fire with
 the new x's y property. This would automatically remove any observers from
 the old x.y path and attach observers to the next x.y path. This sort of
 thing is incredibly common and powerful in data bound templates.

 I agree that this is a very common feature. For this iteration, we
 wanted to provide the minimal building blocks to allow these kind of
 things to be built.

 A way of firing the callback immediately on attaching - as a way of sort of
 priming any state that depends on the binding. If I have o1 and o2 and I
 want them to stay in sync one way - if I attach an observer to o1, I might
 want it to immediately fire with all of the current values of o1 so that o2
 is up to date. I find there are many cases where one is better than the
 other so this is nice to be configurable.
 A way of making a block of changes atomically, so that multiple changes to
 the same object can be performed without firing callbacks, and then firing

Callbacks will never fire synchronously. All changes within a given
unit are done atomically and observers are notified after this. In
the browser context, a unit will most often be a single event
handler. When the event handler exits, observers will be delivered
change records.

 the callbacks at the end. This can be important for ensuring a consistent
 state before any observer callbacks fire. Alternatively to creating some
 kind of block, it would be powerful to have the option of tying the
 callbacks to the event loop - I believe this is what ember.js does, though
 I'm sure it could be done a lot more efficiently natively.

 This is something that the proposal intentionally is not covering. The
 idea is that [[DeliverAllChangeRecords]] would be called be the
 embedder at the end of microtask which. Rafael spent a lot of time
 getting the timing of DOM mutation observer callbacks right so I'm
 sure he can provide more details.

 http://www.whatwg.org/specs/web-apps/current-work/#perform-a-microtask-checkpoint

 --
 erik
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss