On 7/3/11 2:43 PM, John J. Barton wrote:
I guess there are two different issues here. One has to do with compound
operations and the other is synchrony.
Keep in mind that insertBefore and appendChild are compound operations
for our purposes here, by the way.
If you imagine that mutation-cancel implies canceling the compound
operation, then I understand your concern. But if mutation-cancel is
just mutation-cancel, then you won't need to pre-compute nodes. The
developer is responsible for dealing with the consequence of compound
changes.
That's not acceptable if the consequence is the browser crashing. That
de-facto pushes the responsibility for dealing onto UA implementors.
And what we're doing right now is dealing with those consequences. At
the moment, the "dealing" is in the form of arbitrary restrictions that
cause some actions inside mutation listeners to fail, cause other
actions that come after the mutation listener to fail, or some
combination, different in different browsers. We're trying to
standardize a mutation notification model that doesn't make it possible
to shoot yourself in the foot, while still handling as many use cases
for mutation events as possible.
Given the "can't shoot yourself in the foot" requirement, the power of
this model has to be somewhat limited. This means that some things just
can't be done in this model.
You want a model where you have more power but _can_ shoot yourself in
the foot. There may be room for that too, but we do need to standardize
the exact way the browser blows your foot off in that case.
The synchrony issue is not related to the atomic vs compound operation
problem.
It is, though, because basically all operations in the DOM are compound
operations; removeNode is the only exception (well, and maybe setting
and unsetting attributes, but even there the problem of notifying _what_
changed makes things difficult).
How will developers know if the call they make is going to
work or fail in the proposed model? Trial and error?
I'm not sure what you're asking... The whole point of the proposed
model is that if someone tries to do a mutation the mutation _will_
happen and will complete. _Then_ listeners, if any, will be notified.
What are you worried about working or failing?
Ok, that's good, whatever it takes. A DOM API that switches between
read-only and read-write would much better for developers than a DOM API
that partly switches to async.
Well, it sounds better to you. I'm not sure it sounds better to
"developers".
If you think it's ok for assigning to a global variable to throw in a
mutation listener, and that this is better than some delay in the
listener firing (not actually async; Jonas' proposal doesn't really fire
things async, if you note), then I suspect developers might disagree
with you.
Consider the alternative. In this use case, the developer wants to
modify an execCommand. In the current replacement solution they have to
wait for the execCommand to take effect, then undo the execCommand and
redo it modified. Creating a good user experience may not be possible.
Quite honestly, that's the developer's problem.
Now the developer of course wants to push as much of the cost of this
problem onto the UA as possible, and this makes sense: there are a lot
fewer UAs than developers. But if the UA then has to push part of that
cost on other developers in the form of reduced performance, reduced
feature set due to the complexity of dealing with mutations, increased
memory usage, etc, then you have to ask yourself how the number of
developers wanting to modify execCommand compares to the number of
developers that want to just use the DOM and have it be fast and not
take too much memory. It's possible that the right tradeoff is for the
rare case to involve some pain so that the common case is less painful.
1. use 'before' or onModelChanging rather than 'after' or
onModelChanged, add cancel.
I don't think this would be acceptable to Gecko.
2. as #1 but in addition to 'after'
This is no better than #1 from a UA perspective.
3. avoid DOM-write during handlers explicitly rather than implicitly.
This requires an absurdly broad definition of DOM-write.
You're missing at least the following options:
4. Restrict any APIs that have this sort of power so they're not usable
by untrusted web pages (e.g. move them into browser extension systems).
5. Accept that certain levels of the platform just can't be hooked, at
least for the time being.
Again, I think trying to shoehorn all mutation consumers into the same
API is a bad idea that gave us the current mutation events. Some
consumers just want to know things have changed and not much more than
that. Some want to know details of the changes. Some want to rewrite
parts of the browser on the fly. It's not clear to me that the same API
for all three sets of consumers is the right solution.
-Boris