On 7/3/2011 10:25 AM, Ryosuke Niwa wrote:
On Sun, Jul 3, 2011 at 10:04 AM, John J. Barton
<johnjbar...@johnjbarton.com <mailto:johnjbar...@johnjbarton.com>> wrote:
The only part that is async in the Mutation Event replacement is
further DOM events.
No! Consider execCommand. To notify scripts of node removals, we
have to pre-compute all nodes that are to be removed and make
*synchronous* callback for each before removing the node.
I guess there are two different issues here. One has to do with compound
operations and the other is synchrony.
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. If we are writing element-transformers, then we don't care if
the mutation was triggered by an atomic add or a compound operation.
Mutation-cancel is just one phase in the transformer. To put in another
way: Olli and Jonas are not proposing to add an
execCommandExcecutedListener and I'm not proposing an
execCommandExecutingListener so execCommand is not directly at issue.
The synchrony issue is not related to the atomic vs compound operation
problem. The proposed model mixes synchronous and asynchronous
mechanisms. How will developers know if the call they make is going to
work or fail in the proposed model? Trial and error?
I don't think we can address your use case here. Scripts'
intercepting and preventing mutations browser is about to make or
mutating DOM in the way browser doesn't expect is exactly what
we want
to avoid.
The stated properties (goals) of the replacement are (rephased):
1. No script operation in the middle of mutation,
2. Callback in order of mutation,
3. No propagation chain,
Importantly the current proposal has an undesirable feature:
4. DOM modification in listeners is asynchronous.
Preventing mutation in a 'before' listener still allows all of the
properties as far as I know.
Sure if we can disallow all mutations including all properties of DOM
nodes, all properties of window, document, etc... and anything that
implicitly adds new properties or changes values of those properties
or objects.
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.
A "two-phase-commit" like solution can have all of these
properties. Copy Jonas' AttributeChanged algorithm from the page
cited above. Replace "...ed" with "...ing". Add a flag
'cancelChange' initially false. Add step
8b. If cancelChange is true, abort these steps and the DOM
mutation. Fire event DOMMutationCanceled
We don't want to make the event cancelable because canceling a
mutation is itself a mutation.
I guess you mean: event cancel changes the program results. True. But
mutation cancel can't be a mutation since it does not mutate the DOM.
Consider the case of execCommand or user editing actions. As soon as
we prevent one mutation, the rest of execCommand or user editing
actions fall into parts.
Yes, it is true that mutation event handlers can break programs. But
that is not something the mutation event system can prevent. It's up to
developers to learn how to write correct programs. In particular, if
handlers that prevent an edit action, then it's up to them to deal with
the consequences.
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.
In fact we could go one step further and eliminate the undesirable
feature #4: if notifyingCallbacks is true, all DOM write
operations fail. That way developers are never surprised by DOM
functions that fail as in the current version. Instead developers
will explicitly have to cascade modifications via separate events.
This would be a much less mysterious solution. In some places
Firefox already works in the mystery way and speaking from
experience it is not fun to figure out why your function calls
have no effect.
If you have both a before and and after event and both events
prevent DOM write, then the programming paradigm could be clear:
before handlers cancel mutations and signal 'after' handlers to
stage alternatives
after handlers stage responses to mutation or alternatives to
canceled mutations.
This feature requires enormous amount of work in the user agent side.
We need to see more use cases outside of extensions and variants.
At this point, I'm still strongly against implementing such an API as
an user agent implementor.
I hope you will be open to alternatives. Sometimes we get very invested
in one point of view and it takes some time and discussion to give
alternatives reasonable consideration. Three different alternatives are
here:
1. use 'before' or onModelChanging rather than 'after' or
onModelChanged, add cancel.
2. as #1 but in addition to 'after'
3. avoid DOM-write during handlers explicitly rather than implicitly.
jjb