Re: Mutation events replacement

2011-07-05 Thread Adam Klein
On Mon, Jul 4, 2011 at 9:57 AM, Olli Pettay  wrote:
> On 07/04/2011 07:28 PM, Ojan Vafai wrote:
>>
>> Apologies in advance if my comment makes no sense. This is a long
>> thread, I tried to digest it all. :)
>>
>> On Sat, Jul 2, 2011 at 7:07 AM, Boris Zbarsky > > wrote:
>>
>>    That may be ok, if the use cases that incur this cost are rare and
>>    the common case can be better served by a different approach.
>>
>>    Or put another way, if 1% of consumers want the full list because it
>>    makes them 4x faster and the other 99% don't want the full list, and
>>    the full list is 3x slower for the browser to build than just
>>    providing the information the 99% want, what's the right tradeoff?
>>
>>
>> I'm not sure there really is a performance tradeoff. I believe that the
>> proposal Rafael put forward should almost always be faster. Storing the
>> list of changes and doing a JS callback once, for nearly all use-cases,
>> should be faster than frequent, semi-synchronous callbacks.
>>
>> The only bit that might be slower is what data you include in the
>> mutation list. I believe that all the data you'd need is cheap except
>> for possibly the following two:
>> -The index of the child that changed for ChildListChanged (is this
>> actually expensive?)
>
> You may need more than just an index. element.innerHTML = null removes
> all the child nodes.
> And element.inserBefore(some_document_fragment, element.lastChild)
> may insert several child nodes.
> Depending on whether we want to get notified for each mutation
> or batch the mutations, simple index may or may not be enough.

Would a node reference be better ("nextSibling")?  Assuming the
listeners have access to all inserted/removed nodes along the way,
using another as an anchor seems like it would work properly (though
the innerHTML case may need something special).

>
>> -The old value of an attribute/text node. I know this is expensive in
>> Gecko's engine at least.
>
> Shouldn't be that slow.
>
> Mutation listener could easily
> implement old/new value handling itself, especially if it knows which
> attributes it is interested in.

This only works if listeners don't care about intermediate values,
since all they'll have access to is the last value they saw and the
current value in the DOM. If it was set several times during a single
"mutation event" (whether that be your or Rafael's definition of a
"transaction"), they'll miss those in-between values.  Also, while
this would be acceptable for some use cases, the editing/undo use case
would need to keep values of all attributes at all nodes, which seems
likely to be worse than having the UA take care of this.

>> I'd be fine with excluding that information by default, but having a
>> flag you pass at some point saying to include those. That way, only
>> sites that need it take the performance hit.

Given that different use cases seem to have wildly different
requirements (some probably only care about one or two attributes
while others care about the entire document), this approach to
handling the availability of oldValue/newValue is appealing.

- Adam




Re: Mutation events replacement

2011-07-05 Thread Adam Klein
On Mon, Jul 4, 2011 at 1:45 PM, Olli Pettay  wrote:
> On 07/04/2011 08:16 PM, Adam Klein wrote:
>> On Mon, Jul 4, 2011 at 9:57 AM, Olli Pettay
>>  wrote:
>>> On 07/04/2011 07:28 PM, Ojan Vafai wrote:
>>>> The only bit that might be slower is what data you include in the
>>>> mutation list. I believe that all the data you'd need is cheap except
>>>> for possibly the following two:
>>>> -The index of the child that changed for ChildListChanged (is this
>>>> actually expensive?)
>>>
>>> You may need more than just an index. element.innerHTML = null removes
>>> all the child nodes.
>>> And element.inserBefore(some_document_fragment, element.lastChild)
>>> may insert several child nodes.
>>> Depending on whether we want to get notified for each mutation
>>> or batch the mutations, simple index may or may not be enough.
>>
>> Would a node reference be better ("nextSibling")?  Assuming the
>> listeners have access to all inserted/removed nodes along the way,
>> using another as an anchor seems like it would work properly (though
>> the innerHTML case may need something special).
>
> Where would the node reference be?
> What would the API look like?

In Rafael's API, each mutation is represented by an object, so I'd
simply put it there with its own key, something like:

interface MutationRecord {
  // e.g., 'ChildListChanged', 'AttributeChanged'
  readonly attribute DOMString type;
  // element whose childNodes changed, or whose attribute was changed
  readonly attribute Node target;
  readonly attribute NodeListinsertedNodes;
  readonly attribute NodeListremovedNodes;
  // reference to the node before which the above nodes were removed/inserted
  readonly attribute Node nextSibling;
};

With your API, I think you'd want to change from passing nodes to the
callback to using something like the above, analogous to the
information hanging off of MutationEvent in the current spec.

- Adam




Re: Mutation events replacement

2011-07-21 Thread Adam Klein
On Thu, Jul 21, 2011 at 4:30 PM, Jonas Sicking  wrote:
> On Thu, Jul 21, 2011 at 8:19 AM, Olli Pettay  wrote:
>> On 07/21/2011 06:01 PM, Boris Zbarsky wrote:
>>>
>>> On 7/21/11 5:08 AM, Dave Raggett wrote:

 Thanks for the explanation. Apps would need a way to disable
 notifications during such animation sequences, and would be able to find
 another means to serialize the animation (at a higher level).
>>>
>>> I'm not sure I trust apps to do that, which is why I think the default
>>> behavior should be that they just don't get the information.
>>>
 This raises the question is unregistering and re-regtistering a mutation
 notification handler cheap or do we need an alternative mechanism for
 temporarily suspending notifications?
>>>
>>> Olli is better able than I to answer this for Gecko.
>>
>> In the current WIP patch for mutation event replacement registering and
>> unregistering listeners is cheap, and if there are no listeners,
>> performance isn't affected at all.
>> This is with the sync approach.
>>
>> If async approach is taken, listener handling becomes significantly
>> more complicated. What if the listener is added after the mutation has
>> happened, should it be called? If not, then we need to keep a list of
>> changes for all the listeners separately.
>
> Hmm.. the most trivial implementation is to keep different lists for
> different listeners no matter what.
>
> However maybe it's worth allowing listeners to be able to share
> mutation objects? Is that what you were thinking? That might be good
> for performance since it'll create fewer objects, but it'll also add
> more complexity since it requires more bookkeeping.
>
> Though note that the list of mutation objects will have to be
> per-listener no matter what (i.e. both in the mostly-sync and the
> almost-async suggestions) since different listeners will be observing
> different parts of the tree and thus will see different set of
> mutations.
>
> The simplest solution that I can think of is to say that the
> addMutationObserver function doesn't take effect until at the end of
> the task. So any listener registered during a task won't get
> notifications until at the end of the following task.
>
> There are other solutions that we could use, but they seem much more
> complex and so I'd rather avoid them unless there's a good reason to.

This is only complex because you're coalescing the mutations, right?
In Rafael's original proposal, each mutation would result in a single
immutable mutation record, so the semantics would be to "deliver" (by
appending to a queue associated with each observer) a mutation record
to any currently-registered observers.

Or is there some other concern with beginning notifications partway
through a task?

- Adam



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 registratio

Re: Mutation Observers: a replacement for DOM Mutation Events

2011-09-23 Thread Adam Klein
On Fri, Sep 23, 2011 at 4:44 PM, Tab Atkins Jr.  wrote:
> On Fri, Sep 23, 2011 at 2:16 PM, Adam Klein  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.

- Adam



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  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), 'att

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  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
>> c

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  wrote:
> On 09/26/2011 09:09 PM, Adam Klein wrote:
>>
>> On Mon, Sep 26, 2011 at 11:05 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();
>>>> };
>>>>
>>>> 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.
>>>>
>>>> - disconne

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  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-10-03 Thread Adam Klein
On Fri, Sep 30, 2011 at 7:03 PM, Ojan Vafai  wrote:
> On Fri, Sep 30, 2011 at 12:40 PM, 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 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.

What Ojan said. I'm happy to have this work be part of DOM4, and am
not particularly attached to editing it, though I'm ready to provide
whatever help would be useful.

- Adam



Re: [DOM4] NodeList should be deprecated

2012-03-12 Thread Adam Klein
On Thu, Mar 8, 2012 at 11:57 PM, Anne van Kesteren  wrote:

> On Thu, 08 Mar 2012 23:24:45 +0100, Ojan Vafai  wrote:
>
>> Dynamic NodeLists have a significant memory and performance cost. Static
>> NodeLists are basically just under-powered arrays. We should just return
>> Node arrays from any new APIs that return a list of Nodes. I'd like to
>> see NodeList get similar treatment to hasFeature, i.e. a note that it not be
>> used for new APIs and possibly even the explicitly list the APIs allowed
>> to return them.
>>
>> I don't see the Dynamic/Static distinction in DOM4 or the HTML spec. Is
>> this specified anywhere?
>>
>
> We use the words "live" and "static".
>
>
>
>  For reference, this came up in WebKit with some new Regions APIs
>> https://bugs.webkit.org/show_**bug.cgi?id=80638
>> .
>>
>
> Mutation observers uses NodeList too.


Though there's no reason they couldn't use arrays instead (they're not
live). In fact, that would make the API more self-consistent, since arrays
(of MutationRecords) are already part of the interface.

- Adam


Re: Should MutationObservers be able to observe work done by the HTML parser?

2012-06-19 Thread Adam Klein
On Sun, Jun 17, 2012 at 12:17 PM, Ryosuke Niwa  wrote:

> On Sun, Jun 17, 2012 at 5:03 AM, Jonas Sicking  wrote:
>
>> On Sat, Jun 16, 2012 at 7:04 AM, Rafael Weinstein 
>> wrote:
>> > I too thought we had intentionally spec'd them to not fire during load.
>> >
>> > The HTML spec is clear about this WRT Mutation Events:
>> >
>> > http://www.whatwg.org/specs/web-apps/current-work/#tree-construction:
>> >
>> > "DOM mutation events must not fire for changes caused by the UA
>> > parsing the document. (Conceptually, the parser is not mutating the
>> > DOM, it is constructing it.) This includes the parsing of any content
>> > inserted using document.write() and document.writeln() calls."
>> >
>> > It seems like this should also apply to Mutation Observers, unless we
>> > have compelling reasons to do otherwise.
>>
>> This was something that we got people complaining about with mutation
>> events over the years. Our answer used to be that mutation events
>> generally suck and you can't depend on them anyway. Obviously not an
>> argument we'd want to use for MutationObservers.
>>
>> I can't think of any cases where you would *not* want these to fire
>> for parser mutations.
>>
>
> Agreed. I'm in favor of observers being notified for parser-initiated DOM
> mutations. The primary reason we don't fire mutation events for parser
> insertion & removal is because they're synchronous and introduces all sorts
> of problems including security vulnerabilities but that isn't the case with
> mutation observers.
>
> One question. Should we also notify mutation observers immediately before
> executing synchronous scripts (i.e. script elements without differ or async
> content attributes) to address Mihai's use case?
>

This is one part of a more general question (raised by Ojan on
webkit.org/b/89351): what should the timing be for delivery of these
parser-initiated mutations? Mihai's use case is one example where we might
want something other than end-of-task delivery. Ojan points out that simply
using end-of-task could expose low-level implementation detail of the
parser to script (such as how much parsing is done in a single task before
the parser yields).

Does Firefox do anything special here? Or does it simply use the same
end-of-task delivery as everywhere else?

- Adam


Re: Should MutationObservers be able to observe work done by the HTML parser?

2012-06-20 Thread Adam Klein
On Wed, Jun 20, 2012 at 12:36 AM, Ryosuke Niwa  wrote:

> On Tue, Jun 19, 2012 at 1:52 PM, Olli Pettay wrote:
>>
>>   Ojan points out
>>
>>> that simply using end-of-task could expose low-level implementation
>>> detail of the parser to script (such as how much parsing is done in a
>>> single task
>>> before the parser yields).
>>>
>>> Does Firefox do anything special here? Or does it simply use the same
>>> end-of-task delivery as everywhere else?
>>>
>>
>> end-of-microtask or end-of-task everywhere. And yes, some parsing /
>> networking details may unfortunately be exposed, but in a way which should
>> be quite random. Web devs just can't really rely on network packages to be
>> delivered to parser in some exact way.
>>
>
> That randomness seems undesirable. Can we delay the delivery until
> DOMContentLoaded is fired so that we can have more consisnte behavior here?
>

This doesn't seem very useful to me. Observing during page load will
clearly have a cost associated with it, and if you aren't notified until
DOMContentLoaded, you could have just listened for DOMContentLoaded
yourself, looked through the document for the stuff you care about, and
then attach an observer.

I'm not entirely opposed to notifying of parse-time mutations, but if we
did it seems like we'd want to deliver them during page load in some way.

- Adam


Re: Should MutationObservers be able to observe work done by the HTML parser?

2012-06-26 Thread Adam Klein
On Wed, Jun 20, 2012 at 12:29 AM, Anne van Kesteren wrote:

> On Tue, Jun 19, 2012 at 10:52 PM, Olli Pettay 
> wrote:
> > end-of-microtask or end-of-task everywhere. And yes, some parsing /
> > networking details may unfortunately be exposed,
> > but in a way which should be quite random. Web devs just can't really
> rely
> > on network packages to be delivered to parser in
> > some exact way.
>
> I think the original solution we had to not expose parser mutations
> was better. Exposing this can lead to all kinds of subtle bugs that
> are hard to detect for developers.
>

I take it from your reply that you and I had the same view of what's
specced in DOM4. That is, that MutationObservers are not specified to be
notified of actions taken by the parser. Given that fact, it seems that
either the spec should be changed (and by "spec" here I think the required
changes are in HTML, not DOM), or Firefox's implementation ought to be
changed.

Anne, Ian, Olli, Jonas, your thoughts?

- Adam


Re: Should MutationObservers be able to observe work done by the HTML parser?

2012-06-29 Thread Adam Klein
On Fri, Jun 29, 2012 at 2:44 AM, Jonas Sicking  wrote:

> All in all I think that as soon as we introduce exceptions to when
> MutationObserver callbacks fire we change the API from being a
> reliable way to track DOM mutations to a unreliable way where all
> callers have to be aware of exceptions and deal with them in other
> ways. I.e. it feels like it significantly reduces the value of
> MutationObservers.
>
> And so far I don't see any good arguments made for making that
> reduction in value. Did I miss any arguments other then the randomness
> argument?
>

Performance was one concern that's come up in discussing this with Ojan and
Rafael. Imagine a MutationObserver attached to the document near the top of
the page. Now we need to create basically one MutationRecord per node
inserted (because the parser operates in a depth-first sort of order). I'm
not at all sure this is a show-stopper (we might be able to introduce some
new MutationRecord type that could compactly represent parser-style
operation), but it definitely seems worrisome, especially given that one of
the common uses for MutationObservers is extensions which might run on many
(all?) pages.

- Adam


Re: Making play nice with XML and tags-and-text

2012-07-18 Thread Adam Klein
On Wed, Jul 18, 2012 at 9:19 AM, Adam Barth  wrote:

> Inspired by a conversation with hsivonen in #whatwg, I spend some time
> thinking about how we would design  for an XML world.  One idea I
> had was to put the elements inside the template into a namespace other than
> http://www.w3.org/1999/xhtml.


Interesting idea! We considered something like this back before Rafael's
initial email to WebApps but discarded it for reasons discussed below.

One question about your proposal: do the contents of  in an HTML
document parse as HTML or XHTML (I'm not as familiar as I should be with
how the contents of  are parsed in HTML)? For example, can I omit
closing  tags?


> Unlike the existing "wormhole"  semantics, in this approach the
> tags-and-text inside  would translate into DOM as usual for XML.
>  We'd get the "inert" behavior for free because we'd avoid defining any
> behavior for elements in the http://www.w3.org/2012/xhtml-templatenamespace 
> (just as no behavior is defined today).
>

This does get you inertness, but doesn't avoid querySelector matching
elements inside .

Also, the elements inside , though they appear to be HTML,
wouldn't have any of the IDL attributes one might expect, e.g.,  would have no "href" property in JS (nor would  have
src, etc). They are, perhaps, too inert.

When combined with the querySelector problem, this seems especially bad,
since jQuery-style invocations would expect everything matching, say,
$('img') to behave the same way (I guess we already have this problem with
SVG  tags, but it seems especially weird in a document that one might
think is all-HTML).

- Adam


Re: Why can't we just use constructor instead of createdCallback?

2014-02-18 Thread Adam Klein
On Tue, Feb 18, 2014 at 3:26 PM, Dimitri Glazkov  wrote:
> On Tue, Feb 18, 2014 at 2:59 PM, Jonas Sicking  wrote:
> > On Tue, Feb 18, 2014 at 10:35 AM, Dimitri Glazkov  
> > wrote:
> > > The thing that really bothers me is that this approach is contradicting
> > > itself. We go to into pretty elaborate lengths to enable running
> > > constructors during parsing, but the key performance lesson developers 
> > > will
> > > immediately learn is to avoid constructors on custom elements, because 
> > > they
> > > will trigger the two-phase code path during parsing. Here's a thing that 
> > > you
> > > can use, but you probably don't want to ever use it.
> >
> > The above paragraph appears to assume that creating this list is slow.
> > Do you have data to back that up?
>
> No, of course not :) It's a first intuitive reaction.

One example that seems intuitively problematic about this approach (to
me, anyway) are those parts of the parser that inspect the tree during
parsing: foster parenting. I'm not sure it's a performance issue so
much as a complexity issue. Consider:


  

  

When following the spec
(http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#appropriate-place-for-inserting-a-node),
any text in that algorithm which says "parent node" need to be patched
to say something about this new list of to-be-attached nodes.

Patching all such references seems likely to be difficult and
error-prone, but I admit that I can't quantify those worries.

- Adam



Re: Indexed DB Transactions vs. Microtasks

2014-06-18 Thread Adam Klein
On Fri, Jun 6, 2014 at 5:51 PM, Jonas Sicking  wrote:

> On Thu, Jun 5, 2014 at 12:59 PM, Joshua Bell  wrote:
> > case 1:
> >
> >   var tx;
> >   Promise.resolve().then(function() {
> > tx = db.transaction(storeName);
> > // tx should be active here...
> >   }).then(function() {
> > // is tx active here?
> >   });
> >
> > For case 1, ISTM that "yes" matches the IDB spec, since control has not
> > returned to the event loop while the microtasks are running.
> Implementations
> > appear to agree.
>
> Yes. I believe that this is what the spec currently calls for.
>
> However I think it would actually be good to change the spec to say
> that the transaction is closed at the end of the current microtask.
>
> When we originally designed microtasks for Mutation Observers, one of
> the goals was to ensure that there were not accidental
> interdependencies between different event handlers to the same event.
> By flushing end-of-microtask work after each event handler you ensure
> that each event handler gets a clean slate.
>
> I realize that this is a backwards-incompatible change. However it
> seems pretty unlikely to break any existing content. So it'd be nice
> to give it a try.


While I agree that the original microtask intent would suggest we change
this, and I concur that it seems unlikely to break content, I worry about
the spec and implementation complexity that would be incurred by having to
support the notion of "at the end of the current microtask". It suggests
one of:

1. A new task queue, which runs after microtasks (nanotasks?)
2. The ability to put tasks at the start of the microtask queue rather than
at the end

(1) seems like a bad idea for a variety of reasons, not least of which that
it would soon lead us to need picotasks once an actor other than IDB saw a
need for it.

(2) strikes me as just plain hard to reason about. And again, if anyone
other than IDB tried to use that capability, it would become problematic.

Code running at end-of-microtask already has to deal with being in a
slightly different environment than "normal" event-handling code. I think
it might be worth avoiding additional complexity to make this quirk one of
those caveats.

- Adam

(resending from correct address, a dup may show up at some point)


Re: Indexed DB Transactions vs. Microtasks

2014-06-18 Thread Adam Klein
On Wed, Jun 18, 2014 at 9:13 PM, Domenic Denicola <
dome...@domenicdenicola.com> wrote:

> [+Yehuda, +Raf]
>
> From: Jonas Sicking [mailto:jo...@sicking.cc]
>
> > On Thu, Jun 19, 2014 at 8:44 AM, Adam Klein  wrote:
> >> While I agree that the original microtask intent would suggest we
> >> change this, and I concur that it seems unlikely to break content, I
> >> worry about the spec and implementation complexity that would be
> >> incurred by having to support the notion of "at the end of the current
> >> microtask". It suggests one
> >> of:
> >>
> >> 1. A new task queue, which runs after microtasks (nanotasks?) 2. The
> >> ability to put tasks at the start of the microtask queue rather than
> >> at the end
> >
> > I was just thinking to hardcode this into the algorithm that's run at
> the end of the microtask. Note that closing the transaction never runs
> code, which means that very little implementation complexity is needed.
>
> > I definitely agree that both of the above options are pretty
> unattractive.
>
> This recalls Yehuda's proposal for a "bucketed" microtask queue. It seems
> like this is a very strong argument for it.
>

This seems orthogonal to bucketing. The IDB transaction deactivation step
isn't a sort of work that we'd want to bucket (as I argued in my previous
message, treating this IDB work as a task leads down some bad roads); as
Jonas says, we would actually want to hardcode it as a thing that "just
happens" after each microtask is run (an idea that would have unappealing
consequences for the Chromium implementation of microtasks, but one which
I'll mull over).

- Adam


Re: Indexed DB Transactions vs. Microtasks

2014-06-19 Thread Adam Klein
On Fri, Jun 6, 2014 at 5:51 PM, Jonas Sicking  wrote:

> On Thu, Jun 5, 2014 at 12:59 PM, Joshua Bell  wrote:
> > case 1:
> >
> >   var tx;
> >   Promise.resolve().then(function() {
> > tx = db.transaction(storeName);
> > // tx should be active here...
> >   }).then(function() {
> > // is tx active here?
> >   });
> >
> > For case 1, ISTM that "yes" matches the IDB spec, since control has not
> > returned to the event loop while the microtasks are running.
> Implementations
> > appear to agree.
>
> Yes. I believe that this is what the spec currently calls for.
>
> However I think it would actually be good to change the spec to say
> that the transaction is closed at the end of the current microtask.
>
> When we originally designed microtasks for Mutation Observers, one of
> the goals was to ensure that there were not accidental
> interdependencies between different event handlers to the same event.
> By flushing end-of-microtask work after each event handler you ensure
> that each event handler gets a clean slate.
>
> I realize that this is a backwards-incompatible change. However it
> seems pretty unlikely to break any existing content. So it'd be nice
> to give it a try.


While I agree that the original microtask intent would suggest we change
this, and I concur that it seems unlikely to break content, I worry about
the spec and implementation complexity that would be incurred by having to
support the notion of "at the end of the current microtask". It suggests
one of:

1. A new task queue, which runs after microtasks (nanotasks?)
2. The ability to put tasks at the start of the microtask queue rather than
at the end

(1) seems like a bad idea for a variety of reasons, not least of which that
it would soon lead us to need picotasks once an actor other than IDB saw a
need for it.

(2) strikes me as just plain hard to reason about. And again, if anyone
other than IDB tried to use that capability, it would become problematic.

Code running at end-of-microtask already has to deal with being in a
slightly different environment than "normal" event-handling code. I think
it might be worth avoiding additional complexity to make this quirk one of
those caveats.

- Adam


Re: Custom element lifecycle callbacks

2015-01-08 Thread Adam Klein
On Thu, Jan 8, 2015 at 7:56 AM, Anne van Kesteren  wrote:

> 1) Can we use symbols to identify these instead? That gives us a
> guarantee they won't be used for other things and makes it somewhat
> safer to put them where they are located now.
>

As Dimitri noted, I've expressed mild concerns about this in the past, but
I may be coming around to the idea. The main advantage of using Symbols is
that it would guarantee us the ability to add new callbacks in the future
without fear of breaking existing elements, though I don't know how
realistic a concern that is given the "Callback" suffix all these names
have.

Do you have a proposal for where these symbols would be vended? In ES,
builtin symbols are available as properties on the Symbol object, but
clearly WebIDL shouldn't be adding things there. This might be a good
question for public-script-coord.

- Adam


Re: template namespace attribute proposal

2015-03-12 Thread Adam Klein
On Wed, Mar 11, 2015 at 8:32 PM, Benjamin Lesh  wrote:

> I'd like to propose that the  tag have a namespace="" attribute
> that allows the user to specify namespaces such as "
> http://www.w3.org/2000/svg";, so that the document fragment that comes
> from `.content` is created properly.
>
> e.g.:
>
> http://www.w3.org/2000/svg>
>   
> 
>

For clarity, is this significantly different from the below (which works
today)?


  

  


Clearly there's an extra step here, in that accessing the SVG elements
requires hopping into firstElementChild, but adding new namespace-related
features seems unfortunate.

- Adam


Re: template namespace attribute proposal

2015-03-12 Thread Adam Klein
On Thu, Mar 12, 2015 at 11:22 AM, Anne van Kesteren 
wrote:

> On Thu, Mar 12, 2015 at 7:16 PM, Adam Klein  wrote:
> > For clarity, is this significantly different from the below (which works
> > today)?
> >
> > 
> >   
> > 
> >   
> > 
> >
> > Clearly there's an extra step here, in that accessing the SVG elements
> > requires hopping into firstElementChild, but adding new namespace-related
> > features seems unfortunate.
>
> That was going to be my argument, but then I remembered that we went
> out of our way to make , , , etc. work as direct
> children of .
>

Is your thinking that adding special-casing for SVG-"looking" (as in, tag
names appearing in the list of SVG tags but not in the list of HTML tags)
inside  has fewer compat risks than a wholesale change of the
HTML parser to recognize SVG-looking tags anywhere?


Re: Privileged context features and JavaScript

2015-04-17 Thread Adam Klein
On Fri, Apr 17, 2015 at 7:06 AM, Boris Zbarsky  wrote:

> On 4/17/15 3:38 AM, Elliott Sprehn wrote:
>
>> It's preferable not to do that for us because you can then create a
>> static heap snapshot at compile time and memcpy to start JS contexts
>> faster.
>>
>
> For this specific case, where there are only two possibilities (privileged
> or not) it seems like you can just have two different snapshots and pick
> the right one.  I agree this uses more memory; there are all sorts of
> tradeoffs here.
>
> But yes, this is an argument against having any sort of dynamic behavior.
> In the case of Gecko, we have to have _something_ somewhat dynamic anyway,
> since we expose APIs to extensions that we don't expose to web pages...
> which I'm sure you do too.


In Blink, we don't include host objects in our snapshot anyway, so this
point is probably moot for web APIs. Or at least it's moot until more
things are self-hosted.

- Adam


Re: Custom Elements: insert/remove callbacks

2015-05-08 Thread Adam Klein
On Thu, May 7, 2015 at 10:56 PM, Elliott Sprehn 
wrote:

>
> On Thu, May 7, 2015 at 10:44 PM, Anne van Kesteren 
> wrote:
>
>> On Fri, May 8, 2015 at 7:42 AM, Elliott Sprehn 
>> wrote:
>> > That actually seems pretty similar to what we have, ours is in the form
>> of:
>> >
>> > Node#insertedInto(Node insertionPoint)
>> > Node#removedFrom(Node insertionPoint)
>> >
>> > where insertionPoint is the ancestor in the tree where a connection was
>> > added or removed which may be arbitrarily far up the ancestor chain.
>> From
>> > that you can figure out all the cases Boris is describing.
>>
>> Cool. So maybe the DOM specification needs to be updated to have that
>> model and we should expose that as low-level hook to web developers.
>>
>
> We'd consider adding a new MutationObserver type, we'd prefer not to add
> any more tree mutation callbacks. Anything you can do with those you can do
> with an ancestorChanged record type and takeRecords().
>

We should think hard before adding ancestor information to
MutationObservers; like other DOM-tree-related APIs, they are very much
based around the model of information coming up the tree from below (you
can imagine how odd it would be to add event dispatch that flowed down the
tree towards the leaves).

- Adam


Re: Writing spec algorithms in ES6?

2015-06-11 Thread Adam Klein
On Thu, Jun 11, 2015 at 1:32 PM, Dimitri Glazkov 
wrote:

> Folks,
>
> Many specs nowadays opt for a more imperative method of expressing
> normative requirements, and using algorithms. For example, both HTML and
> DOM spec do the "run following steps" list that looks a lot like
> pseudocode, and the Web components specs use their own flavor of
> prose-pseudo-code.
>
> I wonder if it would be good the pseudo-code would actually be ES6, with
> comments where needed?
>
> I noticed that the CSS Color Module Level 4 actually does this, and it
> seems pretty nice:
> http://dev.w3.org/csswg/css-color/#dom-rgbcolor-rgbcolorcolor
>
> WDYT?
>

I love the idea of specifying algorithms in something other than English.
But I'm afraid that ECMAScript is not a good language for this purpose, for
the same reasons Boris cites in his response (which arrived as I was typing
this).

- Adam


Re: TPAC Topic: Using ES2015 Modules in HTML

2015-10-16 Thread Adam Klein
Consider this a second vote for a California-compatible time for such a
discussion. V8 also has a partial ES2015 module implementation that's
blocked on the loader, and I'm very interested in pushing forward support
for modules in HTML.

On Fri, Oct 16, 2015 at 5:39 AM, Ryosuke Niwa  wrote:

> Hi all,
>
> Can we discuss how we can integrate ES2015 modules into HTML on Tuesday,
> October 27th at TPAC?
>
> Both Gecko and WebKit are basically done implementing ES6 module supports
> in their respective JavaScript engines but blocked on
> http://whatwg.github.io/loader/ to support in web contents.
>
> Since my colleague who is interested in this topic cannot attend TPAC in
> person, it would be great if we could have it in Tuesday Morning (Monday
> evening in California).
>
> - R. Niwa
>
>