Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-13 Thread Sean Hogan

On 13/10/11 2:33 PM, Ryosuke Niwa wrote:
On Wed, Oct 12, 2011 at 8:14 PM, Sean Hogan shogu...@westnet.com.au 
mailto:shogu...@westnet.com.au wrote:


Maybe you can provide concrete examples (i.e. with code snippets,
actual instances of use cases, etc...)


Actually, it is the proponents of changing the status-quo and of
the more complex solution who bear more responsibility for
providing these. But if it helps, here's a specific example:

MathJax (http://mathjax.org) is a js lib for rendering math in
web-pages. One feature it provides is converting LaTeX into
(typically) a HTML representation of the math. It is desirable for
the LaTeX source to remain available in the document, and MathJax
stores it as the content of a script type=math/tex element.
MathJax provides an API for changing the LaTeX source and thus the
rendered output.

It might be desirable if MathJax could update the rendering
automatically in response to changes in the script content.
Mutation events would be necessary for this. But what is the
appropriate way to signal to other consumers of mutation events
that the math rendering changes are to be ignored?


Why do you assume that all other mutation observers should ignore such 
changes? If there's a library that's automatically syncing the 
document with a server, then such an observer certainly needs to know 
any mutations that happen in the document.


- Ryosuke



In the case of MathJax, the HTML rendering for math is generated in the 
browser. It is only the LaTeX that you would want synced on the server.


However, my main concern (which I probably haven't emphasized 
sufficiently) is that the current proposal is more complex than 
absolutely necessary. Therefore

- it will be complex to implement
- it is easy to imagine that the preliminary analysis has missed 
problems, and
- it still doesn't allow different mutation event listeners to safely 
ignore the possibility of each-other.


My concerns may be unreasonable. Given there is an implementation just 
around the corner, we'll soon have a better idea, rather than just 
speculating.


Sean



Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-13 Thread Ryosuke Niwa
On Wed, Oct 12, 2011 at 7:51 PM, Sean Hogan shogu...@westnet.com.au wrote:

 It is different to event listeners. The following

document.body.**addEventListener(**DOMAttrModified, handler, false);
document.getElementById(**target).addEventListener(**DOMAttrModified,
 preferred_handler, false);


What prevents scripts from then doing
document.getElementById(**target).addEventListener(**DOMAttrModified,
handler, false);
?

allows preferred_handler to prevent handler receiving the event.


The problem with allowing some event observer to prevent other observers to
receive certain mutation events is that we'll then lose any
integrity guarantee once we do that. e.g. when an observer is called with
some list of mutations, you wouldn't know whether the current DOM state is
the result of those mutations or there had been some other mutations.

Without this guarantee, you can't unwind mutation lists to restore the
original DOM state for example, and it makes mutation observation useless in
some use cases.

As such, I'll be strongly opposed to allow such a prevention mechanism.

On Wed, Oct 12, 2011 at 8:14 PM, Sean Hogan shogu...@westnet.com.au wrote:

 Another way of phrasing this deficiency is that the proposal provides a way
 to signal interest in mutations in regions of a page, but doesn't provide a
 way to ignore mutations within those regions. So the libs using this API may
 have to provide their own mechanism for this.


Right, and I'd argue that we should NOT provide such a mechanism.

On Thu, Oct 13, 2011 at 1:32 AM, Sean Hogan shogu...@westnet.com.au wrote:

 Why do you assume that all other mutation observers should ignore such
 changes? If there's a library that's automatically syncing the document with
 a server, then such an observer certainly needs to know any mutations that
 happen in the document.

 - Ryosuke


 In the case of MathJax, the HTML rendering for math is generated in the
 browser. It is only the LaTeX that you would want synced on the server.


No, my use case addresses the case where you want to mirror the exact DOM
state (except event handlers and script elements) elsewhere. And for that to
work, I need to be able to see whatever MathJax is generating, NOT the LaTeX
code.


 - it still doesn't allow different mutation event listeners to safely
 ignore the possibility of each-other.


I repeat myself again that we shouldn't allow mutation observers to do this.

- Ryosuke


Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-13 Thread Sean Hogan

On 13/10/11 7:58 PM, Ryosuke Niwa wrote:


On Thu, Oct 13, 2011 at 1:32 AM, Sean Hogan shogu...@westnet.com.au 
mailto:shogu...@westnet.com.au wrote:



Why do you assume that all other mutation observers should ignore
such changes? If there's a library that's automatically syncing
the document with a server, then such an observer certainly needs
to know any mutations that happen in the document.

- Ryosuke



In the case of MathJax, the HTML rendering for math is generated
in the browser. It is only the LaTeX that you would want synced on
the server.


No, my use case addresses the case where you want to mirror the exact 
DOM state (except event handlers and script elements) elsewhere. And 
for that to work, I need to be able to see whatever MathJax is 
generating, NOT the LaTeX code.


For that use case I think you would be happy with my proposal which 
doesn't implement any filtering of mutation events at all.


By the way, I'm not arguing that the mutation observers proposal should 
provide a mechanism for hiding some mutations. I'm arguing that whatever 
solution is provided (even a complex one) still won't make mutation 
handling straight-forward... so why not just provide the simplest 
solution and let the js libs sort out the details.


Sean



Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-13 Thread Olli Pettay

On 10/13/2011 05:51 AM, Sean Hogan wrote:

My main reservation towards the proposal is its complexity - it promises
a lot and I will be surprised if it is as trivial to implement as you
have implied. Even then, I'm expecting that it isn't the improvement
(over the status-quo) that everyone is speculating. It's great that
there is going to be an implementation real-soon-now so that my concerns
can be allayed / confirmed.



I haven't said this API is trivial to implement.
In fact, it is a bit tricky to implement, but while I've been
implementing it, the API itself has felt pretty good.


-Olli



Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-13 Thread Olli Pettay

On 10/13/2011 11:32 AM, Sean Hogan wrote:

On 13/10/11 2:33 PM, Ryosuke Niwa wrote:

On Wed, Oct 12, 2011 at 8:14 PM, Sean Hogan shogu...@westnet.com.au
mailto:shogu...@westnet.com.au wrote:

Maybe you can provide concrete examples (i.e. with code snippets,
actual instances of use cases, etc...)


Actually, it is the proponents of changing the status-quo and of
the more complex solution who bear more responsibility for
providing these. But if it helps, here's a specific example:

MathJax (http://mathjax.org) is a js lib for rendering math in
web-pages. One feature it provides is converting LaTeX into
(typically) a HTML representation of the math. It is desirable for
the LaTeX source to remain available in the document, and MathJax
stores it as the content of a script type=math/tex element.
MathJax provides an API for changing the LaTeX source and thus the
rendered output.

It might be desirable if MathJax could update the rendering
automatically in response to changes in the script content.
Mutation events would be necessary for this. But what is the
appropriate way to signal to other consumers of mutation events
that the math rendering changes are to be ignored?


Why do you assume that all other mutation observers should ignore such
changes? If there's a library that's automatically syncing the
document with a server, then such an observer certainly needs to know
any mutations that happen in the document.

- Ryosuke



In the case of MathJax, the HTML rendering for math is generated in the
browser. It is only the LaTeX that you would want synced on the server.

However, my main concern (which I probably haven't emphasized
sufficiently) is that the current proposal is more complex than
absolutely necessary. Therefore
- it will be complex to implement

If that is the case, it is implementation problem.
And the the API isn't *that* complex to implement. It has some 
complexity, especially, I could imagine, if the browser engine doesn't

have its internal mutation observing APIs.
But that is all implementation details.

Also, I'd rather add some complexity to browser implementations than to
each web page using the API.



- it is easy to imagine that the preliminary analysis has missed
problems, and

If you find any such problems, please tell us :)
It would be better to improve the API sooner than later.



- it still doesn't allow different mutation event listeners to safely
ignore the possibility of each-other.

Depending on how to interpret this, the API does exactly that.
a MutationObserver doesn't know, nor is handled differently, if there
are other MutationObservers. The old mutation event listeners affect
to each others and some listeners may not be called if
a listener happens to call stopPropagation(). And since you can't know 
where all document tree has mutation event listeners, and in which 
order, you don't actually always know what all effects calling 
stopPropagation() /   stopImmediatePropagation() has.





My concerns may be unreasonable. Given there is an implementation just
around the corner, we'll soon have a better idea, rather than just
speculating.


Yeah, hopefully real soon.



-Olli




Sean






Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-12 Thread Sean Hogan

On 12/10/11 3:26 AM, Tab Atkins Jr. wrote:

On Mon, Oct 10, 2011 at 7:51 PM, Sean Hoganshogu...@westnet.com.au  wrote:

On 24/09/11 7:16 AM, Adam Klein wrote:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

A simpler solution that is free from the faults listed in that email would
be to have (at max) one mutation observer for the whole page context. I
guess this would be called at the end of the task or immediately before page
reflows.

If a js lib (or multiple libs) want to provide finer grained mutation
handling then let them work out the details.

That seems unworkably restrictive.  It's very easy to imagine multiple
libraries listening for different kinds of things at the same time.
Libraries would just end up re-implementing event distribution, which
is something we can avoid by doing it correctly now.


This proposal doesn't entirely avoid the issue of event distribution. 
There is no equivalent of event.stopPropagation() and hence no way to 
prevent mutation records being delivered to observers. The observers may 
have to be written with this is in mind.


For example, what if two observers can potentially handle the same 
mutation - which one should handle it?


Alternatively, some code might respond to an attribute by adding content 
to the DOM. What if there are mutation listeners that could respond to 
that added content? Is it desired that they ignore or handle it?


Another pattern that doesn't seem to be reliably handled is mutations 
within DOM fragments that are temporarily removed from the document. 
That is:
- if the fragment always remains in the document then all mutations can 
be monitored by observers on the document (or document.body), but
- if the fragment is removed from the document followed by mutation 
observers being called, then  any further mutations won't be delivered 
to the observers, even when the fragment is reinserted into the document.


The exact behavior in this scenario depends on whether mutations 
complete within one microtask or more than one


Sean.





Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-12 Thread Olli Pettay

On 10/12/2011 02:00 PM, Sean Hogan wrote:

On 12/10/11 3:26 AM, Tab Atkins Jr. wrote:

On Mon, Oct 10, 2011 at 7:51 PM, Sean Hoganshogu...@westnet.com.au
wrote:

On 24/09/11 7:16 AM, Adam Klein wrote:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)


A simpler solution that is free from the faults listed in that email
would
be to have (at max) one mutation observer for the whole page context. I
guess this would be called at the end of the task or immediately
before page
reflows.

If a js lib (or multiple libs) want to provide finer grained mutation
handling then let them work out the details.

That seems unworkably restrictive. It's very easy to imagine multiple
libraries listening for different kinds of things at the same time.
Libraries would just end up re-implementing event distribution, which
is something we can avoid by doing it correctly now.


This proposal doesn't entirely avoid the issue of event distribution.
There is no equivalent of event.stopPropagation() and hence no way to
prevent mutation records being delivered to observers. The observers may
have to be written with this is in mind.

For example, what if two observers can potentially handle the same
mutation - which one should handle it?
Both. Or the observers need to somehow communicate with each others to 
decide who handles it. This is no different to event listeners.
Event listeners don't know if there are other listeners before them or 
after them. You can have several listeners in the same target and 
different script libraries may have added them without knowing about 
each others.






Alternatively, some code might respond to an attribute by adding content
to the DOM. What if there are mutation listeners that could respond to
that added content? Is it desired that they ignore or handle it?

Another pattern that doesn't seem to be reliably handled is mutations
within DOM fragments that are temporarily removed from the document.
That is:
- if the fragment always remains in the document then all mutations can
be monitored by observers on the document (or document.body), but
- if the fragment is removed from the document followed by mutation
observers being called, then any further mutations won't be delivered to
the observers, even when the fragment is reinserted into the document.


 The exact behavior in this scenario depends on whether mutations
 complete within one microtask or more than one

If the modifications to the fragment are done during the same microtask, 
then the observer will just get notified about those modifications. If 
in different microtask, then observer should observe
that fragment (so when the fragment is removed from document, 
observer.observe(root_of_fragement, options) should be called.).


If there was just a global - per document observers, those wouldn't
handle all the cases when node is adopted to and from other documents.
Also, such observers would make all the DOM mutations slower, since
the callback would need to be called all the time.

The proposed API allows one to restrict mutation observing to certain 
set of nodes. Mutations outside that set can be kept as fast as having 
no mutationobservers at all.
And also, since the observed set can expand, and isn't limited to same 
document handling, it can easily handle cases when nodes are moved to 
some other document.



-Olli



Sean.








Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-12 Thread Rafael Weinstein
Hi Sean,

I find it hard to reason about cases in the abstract. None of the
examples you list seem concerning to me (i.e. I believe they can be
properly handled), but perhaps it's a failure of my imagination.

Maybe you can provide concrete examples (i.e. with code snippets,
actual instances of use cases, etc...)

On Wed, Oct 12, 2011 at 4:00 AM, Sean Hogan shogu...@westnet.com.au wrote:
 On 12/10/11 3:26 AM, Tab Atkins Jr. wrote:

 On Mon, Oct 10, 2011 at 7:51 PM, Sean Hoganshogu...@westnet.com.au
  wrote:

 On 24/09/11 7:16 AM, Adam Klein wrote:

 - Is free of the faults of the existing Mutation Events mechanism
 (enumerated in detail here:
 http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

 A simpler solution that is free from the faults listed in that email
 would
 be to have (at max) one mutation observer for the whole page context. I
 guess this would be called at the end of the task or immediately before
 page
 reflows.

 If a js lib (or multiple libs) want to provide finer grained mutation
 handling then let them work out the details.

 That seems unworkably restrictive.  It's very easy to imagine multiple
 libraries listening for different kinds of things at the same time.
 Libraries would just end up re-implementing event distribution, which
 is something we can avoid by doing it correctly now.

 This proposal doesn't entirely avoid the issue of event distribution. There
 is no equivalent of event.stopPropagation() and hence no way to prevent
 mutation records being delivered to observers. The observers may have to be
 written with this is in mind.

 For example, what if two observers can potentially handle the same mutation
 - which one should handle it?

 Alternatively, some code might respond to an attribute by adding content to
 the DOM. What if there are mutation listeners that could respond to that
 added content? Is it desired that they ignore or handle it?

 Another pattern that doesn't seem to be reliably handled is mutations within
 DOM fragments that are temporarily removed from the document. That is:
 - if the fragment always remains in the document then all mutations can be
 monitored by observers on the document (or document.body), but
 - if the fragment is removed from the document followed by mutation
 observers being called, then  any further mutations won't be delivered to
 the observers, even when the fragment is reinserted into the document.

 The exact behavior in this scenario depends on whether mutations complete
 within one microtask or more than one

 Sean.






Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-12 Thread Sean Hogan

On 13/10/11 12:34 AM, Olli Pettay wrote:

On 10/12/2011 02:00 PM, Sean Hogan wrote:

On 12/10/11 3:26 AM, Tab Atkins Jr. wrote:

On Mon, Oct 10, 2011 at 7:51 PM, Sean Hoganshogu...@westnet.com.au
wrote:

On 24/09/11 7:16 AM, Adam Klein wrote:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html) 




A simpler solution that is free from the faults listed in that email
would
be to have (at max) one mutation observer for the whole page 
context. I

guess this would be called at the end of the task or immediately
before page
reflows.

If a js lib (or multiple libs) want to provide finer grained mutation
handling then let them work out the details.

That seems unworkably restrictive. It's very easy to imagine multiple
libraries listening for different kinds of things at the same time.
Libraries would just end up re-implementing event distribution, which
is something we can avoid by doing it correctly now.


This proposal doesn't entirely avoid the issue of event distribution.
There is no equivalent of event.stopPropagation() and hence no way to
prevent mutation records being delivered to observers. The observers may
have to be written with this is in mind.

For example, what if two observers can potentially handle the same
mutation - which one should handle it?
Both. Or the observers need to somehow communicate with each others to 
decide who handles it. This is no different to event listeners.
Event listeners don't know if there are other listeners before them or 
after them. You can have several listeners in the same target and 
different script libraries may have added them without knowing about 
each others.




It is different to event listeners. The following

document.body.addEventListener(DOMAttrModified, handler, false);

document.getElementById(target).addEventListener(DOMAttrModified, 
preferred_handler, false);


allows preferred_handler to prevent handler receiving the event. The 
observer solution (something like):


handler_observer.observe(document.body, ...);

preferred_handler_observer.observe(document.getElementById(target), ...);


does not.

My argument may be weak, but you don't help this discussion by providing 
an even weaker argument to counter it.







Alternatively, some code might respond to an attribute by adding content
to the DOM. What if there are mutation listeners that could respond to
that added content? Is it desired that they ignore or handle it?

Another pattern that doesn't seem to be reliably handled is mutations
within DOM fragments that are temporarily removed from the document.
That is:
- if the fragment always remains in the document then all mutations can
be monitored by observers on the document (or document.body), but
- if the fragment is removed from the document followed by mutation
observers being called, then any further mutations won't be delivered to
the observers, even when the fragment is reinserted into the document.


 The exact behavior in this scenario depends on whether mutations
 complete within one microtask or more than one

If the modifications to the fragment are done during the same 
microtask, then the observer will just get notified about those 
modifications. If in different microtask, then observer should observe
that fragment (so when the fragment is removed from document, 
observer.observe(root_of_fragement, options) should be called.).


If there was just a global - per document observers, those wouldn't
handle all the cases when node is adopted to and from other documents.


I didn't think of that but I don't think it's a good idea anyway. If 
observing mutations in another document is required then use their per 
document observer. Or have I missed something?



Also, such observers would make all the DOM mutations slower, since
the callback would need to be called all the time.



Yes, but you have to remember that many DOM mutations necessitate page 
reflow, and the cost of mutation listeners has to be weighed against 
that, not the execution time of one DOM operation.


In the extreme case, per document observers won't be any slower than

observer.observe(document, all_options);


The proposed API allows one to restrict mutation observing to certain 
set of nodes. Mutations outside that set can be kept as fast as having 
no mutationobservers at all.
And also, since the observed set can expand, and isn't limited to same 
document handling, it can easily handle cases when nodes are moved to 
some other document.




My main reservation towards the proposal is its complexity - it promises 
a lot and I will be surprised if it is as trivial to implement as you 
have implied. Even then, I'm expecting that it isn't the improvement 
(over the status-quo) that everyone is speculating. It's great that 
there is going to be an implementation real-soon-now so that my concerns 
can be allayed / confirmed.



Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-12 Thread Sean Hogan

On 13/10/11 4:50 AM, Rafael Weinstein wrote:

Hi Sean,

I find it hard to reason about cases in the abstract. None of the
examples you list seem concerning to me (i.e. I believe they can be
properly handled), but perhaps it's a failure of my imagination.


I didn't say they can't be properly handled. I said that the proposal by 
itself doesn't properly handle them, and I suggested a similar but 
simpler solution that also doesn't properly handle them by itself.


Another way of phrasing this deficiency is that the proposal provides a 
way to signal interest in mutations in regions of a page, but doesn't 
provide a way to ignore mutations within those regions. So the libs 
using this API may have to provide their own mechanism for this.



Maybe you can provide concrete examples (i.e. with code snippets,
actual instances of use cases, etc...)


Actually, it is the proponents of changing the status-quo and of the 
more complex solution who bear more responsibility for providing these. 
But if it helps, here's a specific example:


MathJax (http://mathjax.org) is a js lib for rendering math in 
web-pages. One feature it provides is converting LaTeX into (typically) 
a HTML representation of the math. It is desirable for the LaTeX source 
to remain available in the document, and MathJax stores it as the 
content of a script type=math/tex element. MathJax provides an API 
for changing the LaTeX source and thus the rendered output.


It might be desirable if MathJax could update the rendering 
automatically in response to changes in the script content. Mutation 
events would be necessary for this. But what is the appropriate way to 
signal to other consumers of mutation events that the math rendering 
changes are to be ignored?





On Wed, Oct 12, 2011 at 4:00 AM, Sean Hoganshogu...@westnet.com.au  wrote:

On 12/10/11 3:26 AM, Tab Atkins Jr. wrote:

On Mon, Oct 10, 2011 at 7:51 PM, Sean Hoganshogu...@westnet.com.au
  wrote:

On 24/09/11 7:16 AM, Adam Klein wrote:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

A simpler solution that is free from the faults listed in that email
would
be to have (at max) one mutation observer for the whole page context. I
guess this would be called at the end of the task or immediately before
page
reflows.

If a js lib (or multiple libs) want to provide finer grained mutation
handling then let them work out the details.

That seems unworkably restrictive.  It's very easy to imagine multiple
libraries listening for different kinds of things at the same time.
Libraries would just end up re-implementing event distribution, which
is something we can avoid by doing it correctly now.

This proposal doesn't entirely avoid the issue of event distribution. There
is no equivalent of event.stopPropagation() and hence no way to prevent
mutation records being delivered to observers. The observers may have to be
written with this is in mind.

For example, what if two observers can potentially handle the same mutation
- which one should handle it?

Alternatively, some code might respond to an attribute by adding content to
the DOM. What if there are mutation listeners that could respond to that
added content? Is it desired that they ignore or handle it?

Another pattern that doesn't seem to be reliably handled is mutations within
DOM fragments that are temporarily removed from the document. That is:
- if the fragment always remains in the document then all mutations can be
monitored by observers on the document (or document.body), but
- if the fragment is removed from the document followed by mutation
observers being called, then  any further mutations won't be delivered to
the observers, even when the fragment is reinserted into the document.

The exact behavior in this scenario depends on whether mutations complete
within one microtask or more than one

Sean.








Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-12 Thread Ryosuke Niwa
On Wed, Oct 12, 2011 at 8:14 PM, Sean Hogan shogu...@westnet.com.au wrote:

  Maybe you can provide concrete examples (i.e. with code snippets,
 actual instances of use cases, etc...)


 Actually, it is the proponents of changing the status-quo and of the more
 complex solution who bear more responsibility for providing these. But if it
 helps, here's a specific example:

 MathJax (http://mathjax.org) is a js lib for rendering math in web-pages.
 One feature it provides is converting LaTeX into (typically) a HTML
 representation of the math. It is desirable for the LaTeX source to remain
 available in the document, and MathJax stores it as the content of a script
 type=math/tex element. MathJax provides an API for changing the LaTeX
 source and thus the rendered output.

 It might be desirable if MathJax could update the rendering automatically
 in response to changes in the script content. Mutation events would be
 necessary for this. But what is the appropriate way to signal to other
 consumers of mutation events that the math rendering changes are to be
 ignored?


Why do you assume that all other mutation observers should ignore such
changes? If there's a library that's automatically syncing the document with
a server, then such an observer certainly needs to know any mutations that
happen in the document.

- Ryosuke


Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-11 Thread Tab Atkins Jr.
On Mon, Oct 10, 2011 at 7:51 PM, Sean Hogan shogu...@westnet.com.au wrote:
 On 24/09/11 7:16 AM, Adam Klein wrote:
 - Is free of the faults of the existing Mutation Events mechanism
 (enumerated in detail here:
 http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

 A simpler solution that is free from the faults listed in that email would
 be to have (at max) one mutation observer for the whole page context. I
 guess this would be called at the end of the task or immediately before page
 reflows.

 If a js lib (or multiple libs) want to provide finer grained mutation
 handling then let them work out the details.

That seems unworkably restrictive.  It's very easy to imagine multiple
libraries listening for different kinds of things at the same time.
Libraries would just end up re-implementing event distribution, which
is something we can avoid by doing it correctly now.

~TJ



Re: Mutation Observers: a replacement for DOM Mutation Events

2011-10-10 Thread Sean Hogan

On 24/09/11 7:16 AM, Adam Klein wrote:

Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
proposal for a replacement for Mutation Events.

This proposal represents our best attempt to date at making a set of
sensible trade offs which allows for a new mutation observation
mechanism that:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)


A simpler solution that is free from the faults listed in that email 
would be to have (at max) one mutation observer for the whole page 
context. I guess this would be called at the end of the task or 
immediately before page reflows.


If a js lib (or multiple libs) want to provide finer grained mutation 
handling then let them work out the details.


Sean




CfC: adding Mutation Observers to DOM4; deadline Oct 14 [Was: Re: Mutation Observers: a replacement for DOM Mutation Events]

2011-10-07 Thread Arthur Barstow

On 10/6/11 9:11 AM, ext Arthur Barstow wrote:

On 9/30/11 3:40 PM, ext Ms2ger wrote:

On 09/29/2011 04:32 PM, Doug Schepers wrote:

Hi, Adam-

I'm glad to see some progress on a replacement for Mutation Events.

Would you be interested in being the editor for this spec? It's already
in our charter, we just need someone to take it up. Olli has offered
offlist to be a co-editor, so between the two of you, I think it would
be pretty manageable.

I'd be happy to help get you started.


I repeat my objections to speccing this outside DOM4. I would, of 
course, welcome Olli or Adam to become co-editors if they would wish 
that.


I scanned the list archive and did not find your objection. Which 
message(s) includes your objection?


Ms2ger responded in IRC that [1] includes his objection (not sure how I 
could have missed that one ;-)). I don't know why, but I never received 
the Oct 1 response from Ojan [2] nor the Oct 3 response from Adam [3] 
and just learned about them today.


It appears a next step is to determine if anyone objects to Mutation 
Observers [4] being added to DOM4. As such, this is a CfC to do so and 
if anyone has any comments, please reply to this e-mail by October 14.


-AB

[1] http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0790.html
[2] http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/0029.html
[3] http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/0003.html
[4] http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/1622.html




Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-30 Thread Ms2ger

On 09/29/2011 04:32 PM, Doug Schepers wrote:

Hi, Adam-

I'm glad to see some progress on a replacement for Mutation Events.

Would you be interested in being the editor for this spec? It's already
in our charter, we just need someone to take it up. Olli has offered
offlist to be a co-editor, so between the two of you, I think it would
be pretty manageable.

I'd be happy to help get you started.


I repeat my objections to speccing this outside DOM4. I would, of 
course, welcome Olli or Adam to become co-editors if they would wish that.


Ms2ger




Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-30 Thread Ojan Vafai
On Fri, Sep 30, 2011 at 12:40 PM, Ms2ger ms2...@gmail.com wrote:

 On 09/29/2011 04:32 PM, Doug Schepers wrote:

 Hi, Adam-

 I'm glad to see some progress on a replacement for Mutation Events.

 Would you be interested in being the editor for this spec? It's already
 in our charter, we just need someone to take it up. Olli has offered
 offlist to be a co-editor, so between the two of you, I think it would
 be pretty manageable.

 I'd be happy to help get you started.


 I repeat my objections to speccing this outside DOM4. I would, of course,
 welcome Olli or Adam to become co-editors if they would wish that.


I expect Adam and Rafael, the two people on the Google side most appropriate
to edit this spec don't care either way. If the rest of the DOM4 editors
would like it in DOM4, and Olli is OK with that, then I'm sure we (Google)
would be OK with it as well.


Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-29 Thread Doug Schepers

Hi, Adam-

I'm glad to see some progress on a replacement for Mutation Events.

Would you be interested in being the editor for this spec?  It's already 
in our charter, we just need someone to take it up.  Olli has offered 
offlist to be a co-editor, so between the two of you, I think it would 
be pretty manageable.


I'd be happy to help get you started.

Thanks-
-Doug (W3C staff contact for WebApps WG)

On 9/23/11 5:16 PM, Adam Klein wrote:

Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
proposal for a replacement for Mutation Events.

This proposal represents our best attempt to date at making a set of
sensible trade offs which allows for a new mutation observation
mechanism that:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

- Meets the goal of having the main “questions” that use-cases will
need answered about the net-effect of changes, be computable in linear
time complexity roughly proportional to the number of changes that
occurred.

Significant aspects of this design:

- Delivery of MutationRecords happens asynchronously, at the end of
the current “microtask”. This is between Options 2 and 3 from this
discussion 
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
Instead of calling listeners at the end of outermost DOM operation or
at the end of a Task, listeners are called at the end of outermost
script invocation. If there are no script invocations, listeners are
called at the end of Task.

- Information about mutations is delivered to observers as an ordered
sequence of MutationRecords, representing an observed sequence of
changes that have occurred.

- Subtree observation properly handles the case where nodes are
transiently removed from, mutated outside of and then returned to the
subtree.

- Observers specify the types of changes they are interested in and
(in some cases) level of detail they require.

Sample usage:

var observer = new MutationObserver(function(mutationRecords) {
   // Handle mutations
});

observer.observe(myNode,
{  // options:
   subtree: true;  // observe the subtree rooted at myNode
   childList: true;  // include information childNode insertion/removals
   attribute: true;  // include information about changes to attributes
within the subtree
});

…

observer.disconnect();  // Cease observation

Details:

We introduce a new interface MutationObserver with a constructor on DOMWindow:

[Constructor(in MutationCallback callback)]
interface MutationObserver {
void observe(in Node target, in MutationObserverOptions options);
void disconnect();
};

where MutationCallback is

[Callback, NoInterfaceObject]
interface MutationCallback {
 void handleEvent(in MutationRecord[] mutations, in
MutationObserver observer);
};

Registration  Observation
- A call to observe creates a registration for the observer to be
delivered mutations made to |target|, and optionally, its descendants.

- Subsequent calls to the same MutationObserver made with the same
|target| have the effect of resetting the options associated with the
registration.

- Subsequent calls to the same MutationObserver made with different
|targets| have the effect of expanding the set of nodes which are
being observed by the observer. All mutations made to all observed
nodes in all registrations for a given observer are delivered, in
time-ordered sequence, via a single invocation of the
MutationCallback’s handleEvent method.

- disconnect ceases observation over the observer’s set of observed nodes.

Registration Options
The |options| argument provided in observe is defined by the
MutationObserverOptions interface:

interface MutationObserverOptions {
 // Mutation types
 boolean childList;  // If true, mutations affecting node’s
childNodes are included.
 boolean attribute;  // If true, mutations affecting element’s
attributes are included.
 boolean characterData;  // If true, mutations affecting the value
of CharacterData
 //nodes are included.
 // [Note: If none of the known mutation types is specified, an
Error is thrown]

 // Subtree observation
 boolean subtree;  // If true, the observed set of nodes for this
registration should include
  // descendants of MutationTarget
(behavior described below).

 // Old values
 boolean attributeOldValue;
 // If true, MutationRecords describing changes to attributes should
 // contain the value of the attribute before the change. If true
 // without attribute: true specified, an Error is thrown.

 boolean characterDataOldValue;
 // If true, MutationRecords describing changes to
 // CharacterData nodes should contain the value
 // of the node before the change. If true without
 // characterData: 

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-28 Thread Adam Klein
On Tue, Sep 27, 2011 at 1:12 PM, Olli Pettay olli.pet...@helsinki.fi wrote:
 On 09/24/2011 12:16 AM, Adam Klein wrote:

 For each observer, if a registration exists which requests the
 matching mutation type and whose observed node set contains the target
 node of the mutation, a MutationRecord is appended to the observer's
 pending mutation queue. If multiple such registrations exist for a
 given observer, a single MutationRecord is delivered having the union
 of the information requested by all registrations (e.g.
 attributeOldValue).


 This is actually still ambiguous.
 What if attributeOldValue is first set to true for document.documentElement,
 and then false (implicitly or explicitly)
 for document, should attribute values be reported?

 Another problematic case is that if we have subtree A and B and both
 are being observed by same observer but different options. Then some
 node from A is moved to B. Which options should be used?

 So, should we define that union means that 'true' values override
 'false' values, and attributeFilter values are union'ed the usual way?

Yes, I think this is what I actually had in mind: true values override
false values.

 To make API somewhat more consistent, should we change
 Subsequent calls to the same MutationObserver made with the same |target|
 have the effect of resetting the options associated with the registration. 
 to follow the union-ing.

If we're going to do that, I think we need to add the ability to stop
listening to a single target (rather than disconnecting from all).
But I'm not convinced we need this consistency, as I suspect the above
case (covering multiple nodes with different registrations and
different options) is quite unusual.

- Adam



Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-28 Thread Olli Pettay

On 09/28/2011 07:01 PM, Adam Klein wrote:

On Tue, Sep 27, 2011 at 1:12 PM, Olli Pettayolli.pet...@helsinki.fi  wrote:

On 09/24/2011 12:16 AM, Adam Klein wrote:


For each observer, if a registration exists which requests the
matching mutation type and whose observed node set contains the target
node of the mutation, a MutationRecord is appended to the observer's
pending mutation queue. If multiple such registrations exist for a
given observer, a single MutationRecord is delivered having the union
of the information requested by all registrations (e.g.
attributeOldValue).



This is actually still ambiguous.
What if attributeOldValue is first set to true for document.documentElement,
and then false (implicitly or explicitly)
for document, should attribute values be reported?

Another problematic case is that if we have subtree A and B and both
are being observed by same observer but different options. Then some
node from A is moved to B. Which options should be used?

So, should we define that union means that 'true' values override
'false' values, and attributeFilter values are union'ed the usual way?


Yes, I think this is what I actually had in mind: true values override
false values.



Actually attributeFilter is union'ed the usual way only if it is defined 
always (in all the options). If it is missing, all the

attributes should be observed.





To make API somewhat more consistent, should we change
Subsequent calls to the same MutationObserver made with the same |target|
have the effect of resetting the options associated with the registration. 
to follow the union-ing.


If we're going to do that, I think we need to add the ability to stop
listening to a single target (rather than disconnecting from all).
But I'm not convinced we need this consistency, as I suspect the above
case (covering multiple nodes with different registrations and
different options) is quite unusual.


OK, let's keep the re-observe a target the way it is.

-Olli



- Adam






Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-27 Thread Olli Pettay

On 09/24/2011 12:16 AM, Adam Klein wrote:


For each observer, if a registration exists which requests the
matching mutation type and whose observed node set contains the target
node of the mutation, a MutationRecord is appended to the observer's
pending mutation queue. If multiple such registrations exist for a
given observer, a single MutationRecord is delivered having the union
of the information requested by all registrations (e.g.
attributeOldValue).



This is actually still ambiguous.
What if attributeOldValue is first set to true for 
document.documentElement, and then false (implicitly or explicitly)

for document, should attribute values be reported?

Another problematic case is that if we have subtree A and B and both
are being observed by same observer but different options. Then some
node from A is moved to B. Which options should be used?

So, should we define that union means that 'true' values override
'false' values, and attributeFilter values are union'ed the usual way?

To make API somewhat more consistent, should we change
Subsequent calls to the same MutationObserver made with the same 
|target| have the effect of resetting the options associated with the 
registration.  to follow the union-ing.


-Olli   



Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-26 Thread Olli Pettay

On 09/24/2011 12:16 AM, Adam Klein wrote:

Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
proposal for a replacement for Mutation Events.

This proposal represents our best attempt to date at making a set of
sensible trade offs which allows for a new mutation observation
mechanism that:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

- Meets the goal of having the main “questions” that use-cases will
need answered about the net-effect of changes, be computable in linear
time complexity roughly proportional to the number of changes that
occurred.

Significant aspects of this design:

- Delivery of MutationRecords happens asynchronously, at the end of
the current “microtask”. This is between Options 2 and 3 from this
discussion 
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
Instead of calling listeners at the end of outermost DOM operation or
at the end of a Task, listeners are called at the end of outermost
script invocation. If there are no script invocations, listeners are
called at the end of Task.

- Information about mutations is delivered to observers as an ordered
sequence of MutationRecords, representing an observed sequence of
changes that have occurred.

- Subtree observation properly handles the case where nodes are
transiently removed from, mutated outside of and then returned to the
subtree.

- Observers specify the types of changes they are interested in and
(in some cases) level of detail they require.

Sample usage:

var observer = new MutationObserver(function(mutationRecords) {
   // Handle mutations
});

observer.observe(myNode,
{  // options:
   subtree: true;  // observe the subtree rooted at myNode
   childList: true;  // include information childNode insertion/removals
   attribute: true;  // include information about changes to attributes
within the subtree
});

…

observer.disconnect();  // Cease observation

Details:

We introduce a new interface MutationObserver with a constructor on DOMWindow:

[Constructor(in MutationCallback callback)]
interface MutationObserver {
void observe(in Node target, in MutationObserverOptions options);
void disconnect();
};


Yeah, these methods could return mutationobserver.
(Although I don't like the o.observe(foo).observe(bar) kind of coding
 style, since it doesn't make it clear which instance's method you're
 calling. But one doesn't need to use that.)




where MutationCallback is

[Callback, NoInterfaceObject]
interface MutationCallback {
 void handleEvent(in MutationRecord[] mutations, in
MutationObserver observer);
};


s/handleEvent/handleMutations/




Registration  Observation
- A call to observe creates a registration for the observer to be
delivered mutations made to |target|, and optionally, its descendants.

- Subsequent calls to the same MutationObserver made with the same
|target| have the effect of resetting the options associated with the
registration.

- Subsequent calls to the same MutationObserver made with different
|targets| have the effect of expanding the set of nodes which are
being observed by the observer. All mutations made to all observed
nodes in all registrations for a given observer are delivered, in
time-ordered sequence, via a single invocation of the
MutationCallback’s handleEvent method.

- disconnect ceases observation over the observer’s set of observed nodes.

Registration Options
The |options| argument provided in observe is defined by the
MutationObserverOptions interface:

interface MutationObserverOptions {
 // Mutation types
 boolean childList;  // If true, mutations affecting node’s
childNodes are included.
 boolean attribute;  // If true, mutations affecting element’s
attributes are included.
 boolean characterData;  // If true, mutations affecting the value
of CharacterData
 //nodes are included.
 // [Note: If none of the known mutation types is specified, an
Error is thrown]

 // Subtree observation
 boolean subtree;  // If true, the observed set of nodes for this
registration should include
  // descendants of MutationTarget
(behavior described below).

 // Old values
 boolean attributeOldValue;
 // If true, MutationRecords describing changes to attributes should
 // contain the value of the attribute before the change. If true
 // without attribute: true specified, an Error is thrown.

 boolean characterDataOldValue;
 // If true, MutationRecords describing changes to
 // CharacterData nodes should contain the value
 // of the node before the change. If true without
 // characterData: true, an Error is thrown.

 // Filtering
 DOMString[] attributeFilter;
 // If provided, only changes to attributes with 

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-26 Thread Olli Pettay

On 09/26/2011 11:47 AM, Olli Pettay wrote:

On 09/24/2011 12:16 AM, Adam Klein wrote:

Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
proposal for a replacement for Mutation Events.

This proposal represents our best attempt to date at making a set of
sensible trade offs which allows for a new mutation observation
mechanism that:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

- Meets the goal of having the main “questions” that use-cases will
need answered about the net-effect of changes, be computable in linear
time complexity roughly proportional to the number of changes that
occurred.

Significant aspects of this design:

- Delivery of MutationRecords happens asynchronously, at the end of
the current “microtask”. This is between Options 2 and 3 from this
discussion
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
Instead of calling listeners at the end of outermost DOM operation or
at the end of a Task, listeners are called at the end of outermost
script invocation. If there are no script invocations, listeners are
called at the end of Task.

- Information about mutations is delivered to observers as an ordered
sequence of MutationRecords, representing an observed sequence of
changes that have occurred.

- Subtree observation properly handles the case where nodes are
transiently removed from, mutated outside of and then returned to the
subtree.

- Observers specify the types of changes they are interested in and
(in some cases) level of detail they require.

Sample usage:

var observer = new MutationObserver(function(mutationRecords) {
// Handle mutations
});

observer.observe(myNode,
{ // options:
subtree: true; // observe the subtree rooted at myNode
childList: true; // include information childNode insertion/removals
attribute: true; // include information about changes to attributes
within the subtree
});

…

observer.disconnect(); // Cease observation

Details:

We introduce a new interface MutationObserver with a constructor on
DOMWindow:

[Constructor(in MutationCallback callback)]
interface MutationObserver {
void observe(in Node target, in MutationObserverOptions options);
void disconnect();
};


Yeah, these methods could return mutationobserver.
(Although I don't like the o.observe(foo).observe(bar) kind of coding
style, since it doesn't make it clear which instance's method you're
calling. But one doesn't need to use that.)




where MutationCallback is

[Callback, NoInterfaceObject]
interface MutationCallback {
void handleEvent(in MutationRecord[] mutations, in
MutationObserver observer);
};


s/handleEvent/handleMutations/




Registration Observation
- A call to observe creates a registration for the observer to be
delivered mutations made to |target|, and optionally, its descendants.

- Subsequent calls to the same MutationObserver made with the same
|target| have the effect of resetting the options associated with the
registration.

- Subsequent calls to the same MutationObserver made with different
|targets| have the effect of expanding the set of nodes which are
being observed by the observer. All mutations made to all observed
nodes in all registrations for a given observer are delivered, in
time-ordered sequence, via a single invocation of the
MutationCallback’s handleEvent method.

- disconnect ceases observation over the observer’s set of observed
nodes.

Registration Options
The |options| argument provided in observe is defined by the
MutationObserverOptions interface:

interface MutationObserverOptions {
// Mutation types
boolean childList; // If true, mutations affecting node’s
childNodes are included.
boolean attribute; // If true, mutations affecting element’s
attributes are included.
boolean characterData; // If true, mutations affecting the value
of CharacterData
//nodes are included.
// [Note: If none of the known mutation types is specified, an
Error is thrown]

// Subtree observation
boolean subtree; // If true, the observed set of nodes for this
registration should include
// descendants of MutationTarget
(behavior described below).

// Old values
boolean attributeOldValue;
// If true, MutationRecords describing changes to attributes should
// contain the value of the attribute before the change. If true
// without attribute: true specified, an Error is thrown.

boolean characterDataOldValue;
// If true, MutationRecords describing changes to
// CharacterData nodes should contain the value
// of the node before the change. If true without
// characterData: true, an Error is thrown.

// Filtering
DOMString[] attributeFilter;
// If provided, only changes to attributes with localName equaling
// one of the provided strings will be delivered. If provided without
// attribute: true, an Error is thrown.
};

Subtree Observation
If the subtree option 

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-26 Thread Olli Pettay

On 09/24/2011 12:16 AM, Adam Klein wrote:

Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
proposal for a replacement for Mutation Events.

This proposal represents our best attempt to date at making a set of
sensible trade offs which allows for a new mutation observation
mechanism that:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

- Meets the goal of having the main “questions” that use-cases will
need answered about the net-effect of changes, be computable in linear
time complexity roughly proportional to the number of changes that
occurred.

Significant aspects of this design:

- Delivery of MutationRecords happens asynchronously, at the end of
the current “microtask”. This is between Options 2 and 3 from this
discussion 
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
Instead of calling listeners at the end of outermost DOM operation or
at the end of a Task, listeners are called at the end of outermost
script invocation. If there are no script invocations, listeners are
called at the end of Task.

- Information about mutations is delivered to observers as an ordered
sequence of MutationRecords, representing an observed sequence of
changes that have occurred.

- Subtree observation properly handles the case where nodes are
transiently removed from, mutated outside of and then returned to the
subtree.

- Observers specify the types of changes they are interested in and
(in some cases) level of detail they require.

Sample usage:

var observer = new MutationObserver(function(mutationRecords) {
   // Handle mutations
});

observer.observe(myNode,
{  // options:
   subtree: true;  // observe the subtree rooted at myNode
   childList: true;  // include information childNode insertion/removals
   attribute: true;  // include information about changes to attributes
within the subtree
});

…

observer.disconnect();  // Cease observation

Details:

We introduce a new interface MutationObserver with a constructor on DOMWindow:

[Constructor(in MutationCallback callback)]
interface MutationObserver {
void observe(in Node target, in MutationObserverOptions options);
void disconnect();
};

where MutationCallback is

[Callback, NoInterfaceObject]
interface MutationCallback {
 void handleEvent(in MutationRecord[] mutations, in
MutationObserver observer);
};

Registration  Observation
- A call to observe creates a registration for the observer to be
delivered mutations made to |target|, and optionally, its descendants.

- Subsequent calls to the same MutationObserver made with the same
|target| have the effect of resetting the options associated with the
registration.

- Subsequent calls to the same MutationObserver made with different
|targets| have the effect of expanding the set of nodes which are
being observed by the observer. All mutations made to all observed
nodes in all registrations for a given observer are delivered, in
time-ordered sequence, via a single invocation of the
MutationCallback’s handleEvent method.

- disconnect ceases observation over the observer’s set of observed nodes.

Registration Options
The |options| argument provided in observe is defined by the
MutationObserverOptions interface:

interface MutationObserverOptions {
 // Mutation types
 boolean childList;  // If true, mutations affecting node’s
childNodes are included.
 boolean attribute;  // If true, mutations affecting element’s
attributes are included.


We need to change this name, since per WebIDL 'attribute' can't be used 
here.


I propose we use attr everywhere in the API. MutationRecord has already 
attrName.

attributeOldValue - attrOldValue and attributeFilter - attrFilter


-Olli



 boolean characterData;  // If true, mutations affecting the value
of CharacterData
 //nodes are included.
 // [Note: If none of the known mutation types is specified, an
Error is thrown]

 // Subtree observation
 boolean subtree;  // If true, the observed set of nodes for this
registration should include
  // descendants of MutationTarget
(behavior described below).

 // Old values
 boolean attributeOldValue;
 // If true, MutationRecords describing changes to attributes should
 // contain the value of the attribute before the change. If true
 // without attribute: true specified, an Error is thrown.

 boolean characterDataOldValue;
 // If true, MutationRecords describing changes to
 // CharacterData nodes should contain the value
 // of the node before the change. If true without
 // characterData: true, an Error is thrown.

 // Filtering
 DOMString[] attributeFilter;
 // If provided, only changes to attributes with localName equaling
 // one of 

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-26 Thread Adam Klein
On Mon, Sep 26, 2011 at 11:05 AM, Olli Pettay olli.pet...@helsinki.fi wrote:
 On 09/24/2011 12:16 AM, Adam Klein wrote:

 Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
 Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
 proposal for a replacement for Mutation Events.

 This proposal represents our best attempt to date at making a set of
 sensible trade offs which allows for a new mutation observation
 mechanism that:

 - Is free of the faults of the existing Mutation Events mechanism
 (enumerated in detail here:
 http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

 - Meets the goal of having the main “questions” that use-cases will
 need answered about the net-effect of changes, be computable in linear
 time complexity roughly proportional to the number of changes that
 occurred.

 Significant aspects of this design:

 - Delivery of MutationRecords happens asynchronously, at the end of
 the current “microtask”. This is between Options 2 and 3 from this
 discussion
 http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
 Instead of calling listeners at the end of outermost DOM operation or
 at the end of a Task, listeners are called at the end of outermost
 script invocation. If there are no script invocations, listeners are
 called at the end of Task.

 - Information about mutations is delivered to observers as an ordered
 sequence of MutationRecords, representing an observed sequence of
 changes that have occurred.

 - Subtree observation properly handles the case where nodes are
 transiently removed from, mutated outside of and then returned to the
 subtree.

 - Observers specify the types of changes they are interested in and
 (in some cases) level of detail they require.

 Sample usage:

 var observer = new MutationObserver(function(mutationRecords) {
   // Handle mutations
 });

 observer.observe(myNode,
 {  // options:
   subtree: true;  // observe the subtree rooted at myNode
   childList: true;  // include information childNode insertion/removals
   attribute: true;  // include information about changes to attributes
 within the subtree
 });

 …

 observer.disconnect();  // Cease observation

 Details:

 We introduce a new interface MutationObserver with a constructor on
 DOMWindow:

 [Constructor(in MutationCallback callback)]
 interface MutationObserver {
    void observe(in Node target, in MutationObserverOptions options);
    void disconnect();
 };

 where MutationCallback is

 [Callback, NoInterfaceObject]
 interface MutationCallback {
     void handleEvent(in MutationRecord[] mutations, in
 MutationObserver observer);
 };

 Registration  Observation
 - A call to observe creates a registration for the observer to be
 delivered mutations made to |target|, and optionally, its descendants.

 - Subsequent calls to the same MutationObserver made with the same
 |target| have the effect of resetting the options associated with the
 registration.

 - Subsequent calls to the same MutationObserver made with different
 |targets| have the effect of expanding the set of nodes which are
 being observed by the observer. All mutations made to all observed
 nodes in all registrations for a given observer are delivered, in
 time-ordered sequence, via a single invocation of the
 MutationCallback’s handleEvent method.

 - disconnect ceases observation over the observer’s set of observed nodes.

 Registration Options
 The |options| argument provided in observe is defined by the
 MutationObserverOptions interface:

 interface MutationObserverOptions {
     // Mutation types
     boolean childList;  // If true, mutations affecting node’s
 childNodes are included.
     boolean attribute;  // If true, mutations affecting element’s
 attributes are included.

 We need to change this name, since per WebIDL 'attribute' can't be used
 here.

 I propose we use attr everywhere in the API. MutationRecord has already
 attrName.
 attributeOldValue - attrOldValue and attributeFilter - attrFilter

Good catch (and I should've caught it when typing this up, as it's
pseudo-idl), 'attr' works for me.  If that shortening isn't
appreciated, we could go with 'attributes' instead.

- Adam



     boolean characterData;  // If true, mutations affecting the value
 of CharacterData
                                             //nodes are included.
     // [Note: If none of the known mutation types is specified, an
 Error is thrown]

     // Subtree observation
     boolean subtree;  // If true, the observed set of nodes for this
 registration should include
                                  // descendants of MutationTarget
 (behavior described below).

     // Old values
     boolean attributeOldValue;
     // If true, MutationRecords describing changes to attributes should
     // contain the value of the attribute before the change. If true
     // without attribute: true specified, an Error is thrown.

     boolean characterDataOldValue;
     // If true, 

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-26 Thread Adam Klein
On Mon, Sep 26, 2011 at 1:47 AM, Olli Pettay olli.pet...@helsinki.fi wrote:
 On 09/24/2011 12:16 AM, Adam Klein wrote:

 Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
 Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
 proposal for a replacement for Mutation Events.

 This proposal represents our best attempt to date at making a set of
 sensible trade offs which allows for a new mutation observation
 mechanism that:

 - Is free of the faults of the existing Mutation Events mechanism
 (enumerated in detail here:
 http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

 - Meets the goal of having the main “questions” that use-cases will
 need answered about the net-effect of changes, be computable in linear
 time complexity roughly proportional to the number of changes that
 occurred.

 Significant aspects of this design:

 - Delivery of MutationRecords happens asynchronously, at the end of
 the current “microtask”. This is between Options 2 and 3 from this
 discussion
 http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
 Instead of calling listeners at the end of outermost DOM operation or
 at the end of a Task, listeners are called at the end of outermost
 script invocation. If there are no script invocations, listeners are
 called at the end of Task.

 - Information about mutations is delivered to observers as an ordered
 sequence of MutationRecords, representing an observed sequence of
 changes that have occurred.

 - Subtree observation properly handles the case where nodes are
 transiently removed from, mutated outside of and then returned to the
 subtree.

 - Observers specify the types of changes they are interested in and
 (in some cases) level of detail they require.

 Sample usage:

 var observer = new MutationObserver(function(mutationRecords) {
   // Handle mutations
 });

 observer.observe(myNode,
 {  // options:
   subtree: true;  // observe the subtree rooted at myNode
   childList: true;  // include information childNode insertion/removals
   attribute: true;  // include information about changes to attributes
 within the subtree
 });

 …

 observer.disconnect();  // Cease observation

 Details:

 We introduce a new interface MutationObserver with a constructor on
 DOMWindow:

 [Constructor(in MutationCallback callback)]
 interface MutationObserver {
    void observe(in Node target, in MutationObserverOptions options);
    void disconnect();
 };

 Yeah, these methods could return mutationobserver.
 (Although I don't like the o.observe(foo).observe(bar) kind of coding
  style, since it doesn't make it clear which instance's method you're
  calling. But one doesn't need to use that.)



 where MutationCallback is

 [Callback, NoInterfaceObject]
 interface MutationCallback {
     void handleEvent(in MutationRecord[] mutations, in
 MutationObserver observer);
 };

 s/handleEvent/handleMutations/

I've yet to see a WebIDL callback that uses a method other than
handleEvent (it's not just EventListeners).  Any reason why
MutationCallbacks should be different?



 Registration  Observation
 - A call to observe creates a registration for the observer to be
 delivered mutations made to |target|, and optionally, its descendants.

 - Subsequent calls to the same MutationObserver made with the same
 |target| have the effect of resetting the options associated with the
 registration.

 - Subsequent calls to the same MutationObserver made with different
 |targets| have the effect of expanding the set of nodes which are
 being observed by the observer. All mutations made to all observed
 nodes in all registrations for a given observer are delivered, in
 time-ordered sequence, via a single invocation of the
 MutationCallback’s handleEvent method.

 - disconnect ceases observation over the observer’s set of observed nodes.

 Registration Options
 The |options| argument provided in observe is defined by the
 MutationObserverOptions interface:

 interface MutationObserverOptions {
     // Mutation types
     boolean childList;  // If true, mutations affecting node’s
 childNodes are included.
     boolean attribute;  // If true, mutations affecting element’s
 attributes are included.
     boolean characterData;  // If true, mutations affecting the value
 of CharacterData
                                             //nodes are included.
     // [Note: If none of the known mutation types is specified, an
 Error is thrown]

     // Subtree observation
     boolean subtree;  // If true, the observed set of nodes for this
 registration should include
                                  // descendants of MutationTarget
 (behavior described below).

     // Old values
     boolean attributeOldValue;
     // If true, MutationRecords describing changes to attributes should
     // contain the value of the attribute before the change. If true
     // without attribute: true specified, an Error is thrown.

     boolean characterDataOldValue;
     

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-26 Thread Olli Pettay

On 09/26/2011 09:09 PM, Adam Klein wrote:

On Mon, Sep 26, 2011 at 11:05 AM, Olli Pettayolli.pet...@helsinki.fi  wrote:

On 09/24/2011 12:16 AM, Adam Klein wrote:


Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
proposal for a replacement for Mutation Events.

This proposal represents our best attempt to date at making a set of
sensible trade offs which allows for a new mutation observation
mechanism that:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

- Meets the goal of having the main “questions” that use-cases will
need answered about the net-effect of changes, be computable in linear
time complexity roughly proportional to the number of changes that
occurred.

Significant aspects of this design:

- Delivery of MutationRecords happens asynchronously, at the end of
the current “microtask”. This is between Options 2 and 3 from this
discussion
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
Instead of calling listeners at the end of outermost DOM operation or
at the end of a Task, listeners are called at the end of outermost
script invocation. If there are no script invocations, listeners are
called at the end of Task.

- Information about mutations is delivered to observers as an ordered
sequence of MutationRecords, representing an observed sequence of
changes that have occurred.

- Subtree observation properly handles the case where nodes are
transiently removed from, mutated outside of and then returned to the
subtree.

- Observers specify the types of changes they are interested in and
(in some cases) level of detail they require.

Sample usage:

var observer = new MutationObserver(function(mutationRecords) {
   // Handle mutations
});

observer.observe(myNode,
{  // options:
   subtree: true;  // observe the subtree rooted at myNode
   childList: true;  // include information childNode insertion/removals
   attribute: true;  // include information about changes to attributes
within the subtree
});

…

observer.disconnect();  // Cease observation

Details:

We introduce a new interface MutationObserver with a constructor on
DOMWindow:

[Constructor(in MutationCallback callback)]
interface MutationObserver {
void observe(in Node target, in MutationObserverOptions options);
void disconnect();
};

where MutationCallback is

[Callback, NoInterfaceObject]
interface MutationCallback {
 void handleEvent(in MutationRecord[] mutations, in
MutationObserver observer);
};

RegistrationObservation
- A call to observe creates a registration for the observer to be
delivered mutations made to |target|, and optionally, its descendants.

- Subsequent calls to the same MutationObserver made with the same
|target| have the effect of resetting the options associated with the
registration.

- Subsequent calls to the same MutationObserver made with different
|targets| have the effect of expanding the set of nodes which are
being observed by the observer. All mutations made to all observed
nodes in all registrations for a given observer are delivered, in
time-ordered sequence, via a single invocation of the
MutationCallback’s handleEvent method.

- disconnect ceases observation over the observer’s set of observed nodes.

Registration Options
The |options| argument provided in observe is defined by the
MutationObserverOptions interface:

interface MutationObserverOptions {
 // Mutation types
 boolean childList;  // If true, mutations affecting node’s
childNodes are included.
 boolean attribute;  // If true, mutations affecting element’s
attributes are included.


We need to change this name, since per WebIDL 'attribute' can't be used
here.

I propose we use attr everywhere in the API. MutationRecord has already
attrName.
attributeOldValue -  attrOldValue and attributeFilter -  attrFilter


Good catch (and I should've caught it when typing this up, as it's
pseudo-idl), 'attr' works for me.  If that shortening isn't
appreciated, we could go with 'attributes' instead.



Apparently I was wrong.
In WebIDL one can escape names using _ prefix.

But actually, attributes sounds more right than
attribute. One really does want to observe all the attributes, unless
names are filtered.

so:
attributes
attributeName
attributeNamespace
attributeOldValue
attributeFilter



-Olli




- Adam





 boolean characterData;  // If true, mutations affecting the value
of CharacterData
 //nodes are included.
 // [Note: If none of the known mutation types is specified, an
Error is thrown]

 // Subtree observation
 boolean subtree;  // If true, the observed set of nodes for this
registration should include
  // descendants of MutationTarget
(behavior described below).

 // Old values
 boolean 

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-26 Thread Adam Klein
On Mon, Sep 26, 2011 at 12:08 PM, Olli Pettay olli.pet...@helsinki.fi wrote:
 On 09/26/2011 09:09 PM, Adam Klein wrote:

 On Mon, Sep 26, 2011 at 11:05 AM, Olli Pettayolli.pet...@helsinki.fi
  wrote:

 On 09/24/2011 12:16 AM, Adam Klein wrote:

 Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
 Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
 proposal for a replacement for Mutation Events.

 This proposal represents our best attempt to date at making a set of
 sensible trade offs which allows for a new mutation observation
 mechanism that:

 - Is free of the faults of the existing Mutation Events mechanism
 (enumerated in detail here:
 http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

 - Meets the goal of having the main “questions” that use-cases will
 need answered about the net-effect of changes, be computable in linear
 time complexity roughly proportional to the number of changes that
 occurred.

 Significant aspects of this design:

 - Delivery of MutationRecords happens asynchronously, at the end of
 the current “microtask”. This is between Options 2 and 3 from this
 discussion
 http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
 Instead of calling listeners at the end of outermost DOM operation or
 at the end of a Task, listeners are called at the end of outermost
 script invocation. If there are no script invocations, listeners are
 called at the end of Task.

 - Information about mutations is delivered to observers as an ordered
 sequence of MutationRecords, representing an observed sequence of
 changes that have occurred.

 - Subtree observation properly handles the case where nodes are
 transiently removed from, mutated outside of and then returned to the
 subtree.

 - Observers specify the types of changes they are interested in and
 (in some cases) level of detail they require.

 Sample usage:

 var observer = new MutationObserver(function(mutationRecords) {
   // Handle mutations
 });

 observer.observe(myNode,
 {  // options:
   subtree: true;  // observe the subtree rooted at myNode
   childList: true;  // include information childNode insertion/removals
   attribute: true;  // include information about changes to attributes
 within the subtree
 });

 …

 observer.disconnect();  // Cease observation

 Details:

 We introduce a new interface MutationObserver with a constructor on
 DOMWindow:

 [Constructor(in MutationCallback callback)]
 interface MutationObserver {
    void observe(in Node target, in MutationObserverOptions options);
    void disconnect();
 };

 where MutationCallback is

 [Callback, NoInterfaceObject]
 interface MutationCallback {
     void handleEvent(in MutationRecord[] mutations, in
 MutationObserver observer);
 };

 Registration    Observation
 - A call to observe creates a registration for the observer to be
 delivered mutations made to |target|, and optionally, its descendants.

 - Subsequent calls to the same MutationObserver made with the same
 |target| have the effect of resetting the options associated with the
 registration.

 - Subsequent calls to the same MutationObserver made with different
 |targets| have the effect of expanding the set of nodes which are
 being observed by the observer. All mutations made to all observed
 nodes in all registrations for a given observer are delivered, in
 time-ordered sequence, via a single invocation of the
 MutationCallback’s handleEvent method.

 - disconnect ceases observation over the observer’s set of observed
 nodes.

 Registration Options
 The |options| argument provided in observe is defined by the
 MutationObserverOptions interface:

 interface MutationObserverOptions {
     // Mutation types
     boolean childList;  // If true, mutations affecting node’s
 childNodes are included.
     boolean attribute;  // If true, mutations affecting element’s
 attributes are included.

 We need to change this name, since per WebIDL 'attribute' can't be used
 here.

 I propose we use attr everywhere in the API. MutationRecord has already
 attrName.
 attributeOldValue -  attrOldValue and attributeFilter -  attrFilter

 Good catch (and I should've caught it when typing this up, as it's
 pseudo-idl), 'attr' works for me.  If that shortening isn't
 appreciated, we could go with 'attributes' instead.


 Apparently I was wrong.
 In WebIDL one can escape names using _ prefix.

 But actually, attributes sounds more right than
 attribute. One really does want to observe all the attributes, unless
 names are filtered.

 so:
 attributes
 attributeName
 attributeNamespace
 attributeOldValue
 attributeFilter

I like 'attributes' as the type, for readability. I'm not entirely
convinced we need to lengthen the rest of the names, but I'm all for
consistency, so on that basis I think it's OK.

- Adam



 -Olli



 - Adam



     boolean characterData;  // If true, mutations affecting the value
 of CharacterData
                                             //nodes 

Mutation Observers: a replacement for DOM Mutation Events

2011-09-23 Thread Adam Klein
Chromium (myself, Rafael Weinstein, Erik Arvidsson, Ryosuke Niwa) and
Mozilla (Olli Pettay, Jonas Sicking) have worked together on a
proposal for a replacement for Mutation Events.

This proposal represents our best attempt to date at making a set of
sensible trade offs which allows for a new mutation observation
mechanism that:

- Is free of the faults of the existing Mutation Events mechanism
(enumerated in detail here:
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0779.html)

- Meets the goal of having the main “questions” that use-cases will
need answered about the net-effect of changes, be computable in linear
time complexity roughly proportional to the number of changes that
occurred.

Significant aspects of this design:

- Delivery of MutationRecords happens asynchronously, at the end of
the current “microtask”. This is between Options 2 and 3 from this
discussion 
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/0780.html.
Instead of calling listeners at the end of outermost DOM operation or
at the end of a Task, listeners are called at the end of outermost
script invocation. If there are no script invocations, listeners are
called at the end of Task.

- Information about mutations is delivered to observers as an ordered
sequence of MutationRecords, representing an observed sequence of
changes that have occurred.

- Subtree observation properly handles the case where nodes are
transiently removed from, mutated outside of and then returned to the
subtree.

- Observers specify the types of changes they are interested in and
(in some cases) level of detail they require.

Sample usage:

var observer = new MutationObserver(function(mutationRecords) {
  // Handle mutations
});

observer.observe(myNode,
{  // options:
  subtree: true;  // observe the subtree rooted at myNode
  childList: true;  // include information childNode insertion/removals
  attribute: true;  // include information about changes to attributes
within the subtree
});

…

observer.disconnect();  // Cease observation

Details:

We introduce a new interface MutationObserver with a constructor on DOMWindow:

[Constructor(in MutationCallback callback)]
interface MutationObserver {
   void observe(in Node target, in MutationObserverOptions options);
   void disconnect();
};

where MutationCallback is

[Callback, NoInterfaceObject]
interface MutationCallback {
void handleEvent(in MutationRecord[] mutations, in
MutationObserver observer);
};

Registration  Observation
- A call to observe creates a registration for the observer to be
delivered mutations made to |target|, and optionally, its descendants.

- Subsequent calls to the same MutationObserver made with the same
|target| have the effect of resetting the options associated with the
registration.

- Subsequent calls to the same MutationObserver made with different
|targets| have the effect of expanding the set of nodes which are
being observed by the observer. All mutations made to all observed
nodes in all registrations for a given observer are delivered, in
time-ordered sequence, via a single invocation of the
MutationCallback’s handleEvent method.

- disconnect ceases observation over the observer’s set of observed nodes.

Registration Options
The |options| argument provided in observe is defined by the
MutationObserverOptions interface:

interface MutationObserverOptions {
// Mutation types
boolean childList;  // If true, mutations affecting node’s
childNodes are included.
boolean attribute;  // If true, mutations affecting element’s
attributes are included.
boolean characterData;  // If true, mutations affecting the value
of CharacterData
//nodes are included.
// [Note: If none of the known mutation types is specified, an
Error is thrown]

// Subtree observation
boolean subtree;  // If true, the observed set of nodes for this
registration should include
 // descendants of MutationTarget
(behavior described below).

// Old values
boolean attributeOldValue;
// If true, MutationRecords describing changes to attributes should
// contain the value of the attribute before the change. If true
// without attribute: true specified, an Error is thrown.

boolean characterDataOldValue;
// If true, MutationRecords describing changes to
// CharacterData nodes should contain the value
// of the node before the change. If true without
// characterData: true, an Error is thrown.

// Filtering
DOMString[] attributeFilter;
// If provided, only changes to attributes with localName equaling
// one of the provided strings will be delivered. If provided without
// attribute: true, an Error is thrown.
};

Subtree Observation
If the subtree option is requested during registration, the observer
is delivered mutations which occur to a set of observed nodes which is
computed as follows:

- At the time of 

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-23 Thread Tab Atkins Jr.
On Fri, Sep 23, 2011 at 2:16 PM, Adam Klein ad...@chromium.org wrote:
 [Constructor(in MutationCallback callback)]
 interface MutationObserver {
   void observe(in Node target, in MutationObserverOptions options);
   void disconnect();
 };

It would be nice to have both of these return the MutationObserver
rather than void, so you can chain calls.

~TJ



Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-23 Thread Tab Atkins Jr.
On Fri, Sep 23, 2011 at 4:46 PM, Adam Klein ad...@chromium.org wrote:
 On Fri, Sep 23, 2011 at 4:44 PM, Tab Atkins Jr. jackalm...@gmail.com wrote:
 On Fri, Sep 23, 2011 at 2:16 PM, Adam Klein ad...@chromium.org wrote:
 [Constructor(in MutationCallback callback)]
 interface MutationObserver {
   void observe(in Node target, in MutationObserverOptions options);
   void disconnect();
 };

 It would be nice to have both of these return the MutationObserver
 rather than void, so you can chain calls.

 I don't think that makes sense for disconnect() (at least the version
 specced here), since it stops observation of all nodes so chaining
 wouldn't make sense.  But I definitely see that chaining observe could
 be convenient.

// Resetting the observation list
observer
  .disconnect()
  .observe(node1,{...})
  .observe(node2,{...});

~TJ