Object.observe and observing "computed properties"

Steve Sanderson flares at gmail.com
Wed Sep 19 10:05:57 PDT 2012

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.


*Appendix: the techniques we considered*

   - *Technique A: Add read notifications to Object.observe (either now, or
   in a future ECMAScript version)*
      - 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
      - Pros: it requires no proxies or accessors, so works with raw data
      - Cons: requires language support, like Object.observe does for write
   - *Technique B: Membrane-style proxies transitively capture all chains
   of properties read from a given object*
      - 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
      - Pros: doesn't require language support; ties in with Object.observe
      in that once you know what properties were read, you can use
      to subscribe to write notifications
      - 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
   - *Technique C: Monkeypatch all model data properties with accessors
   that log reads*
      - Some utility function would walk the object graph and replace all
      properties with special accessors
      - 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
      - Cons: very intrusive - permanently modifies the developer's data

On Fri, Aug 31, 2012 at 10:38 AM, François REMY
<fremycompany_pub at yahoo.fr>wrote:

>   *From:* Alex Russell <slightlyoff at google.com>
> *Sent:* Thursday, August 30, 2012 7:44 PM
> *To:* steven at stevensanderson.com
> *Cc:* es-discuss at mozilla.org
> *Subject:* Re: Object.observe and observing "computed properties"
>  On Wed, Aug 29, 2012 at 11:09 AM, Steve Sanderson <flares at 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 manually (2a) - I'm not even sure what kind of syntax or
>> mechanism you could use when the set of dependencies changes over time.
>> That leaves option (2b) which works great, as long as dependency detection
>> is built into observability.
> I'm not sure that's true. Side-effects are a real pain and it seems to me
> that there's going to be some practical advice at the bottom of any of
> these systems that says, in effect, "don't do things we can't understand".
> That sort of advice is likely to be backed up with tools to assist you in
> helping developers understand those limits; say transpiler passes that
> analyze the dependencies in a function.
> Using a transpiler to detect the dependencies would be very difficult;
> avoiding memory leaks seems nearly impossible in this case. KnockoutJS
> features automatic dependency detection for years and I don’t think it has
> raised any issue at this time. Developers do not bind an UI element to a
> function that actually does something else than formatting a value or doing
> a computation (ie: readonly methods). I think it would be safe to say
> that, in “dependency tracking mode” the observable objects are read-only
> (you can’t modify them or it throws) so that it’s impossible to use
> ill-suited methods as a source of binding.
> Also, to continue on your ‘transpiler’ idea: how would a transpiler work
> to detect changes to the dependency properties? Would you require JS code
> to receive *every* read and write notifications for all properties
> observable objects (like it’s the case in Object.observe), filter them to
> find the interesting bits, and mark themselves the modified properties and
> the bindings which are not up-to-date anymore?
> In such case, a proxy polyfilling the API I propose will be way smarter...
> It strikes me that this is at some level a question of how deep your
> analysis of the target function is willing to go. So far the examples
> dependencies are only on in-scope objects inside a computed property's
> generator. But what about methods called there that might have inputs that
> change? How deep does the propagation go?
> If the arguments of the method “touch” observable objects, they will be
> watched for modifications, just like any other dependency. If they are
> static, they will not fire traps in observable objects and will not cause
> overhead.
> It seems that the implicitness of this strategy implies that some computed
> properties will be *always* marked "regenerate" as it'll be
> simpler/easier/faster than doing something more sophisticated.
> Could you develop? I don’t get that issue.
>> Overall, I've no wish to derail the Object.observe proposal, and fully
>> accept that dependency detection might end up being out of scope for it.
>> However if the ES recommendation will end up being "solve this problem
>> through convention, not language support", I'd love to have a sense of what
>> kinds of conventions (examples, preferably) we would actually be
>> recommending and how they would offer a similar level of convenience to
>> dependency detection.
> I don't think they will, frankly. The best of them will re-create
> dependency detection via compiler. The less aggressive may simply force
> enumeration of dependencies or create conventions which cause particular
> properties to be observed through participation.
> Avoiding memory leaks using a compile-time dependency tracking seems a
> nightmare to me, and detecting affected bindings would be a bummer. Bad
> idea flag raised.
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120919/f6cddfdd/attachment-0001.html>

More information about the es-discuss mailing list