RESOLVED FIXED 105810
[Mutation Observers] prevent delivery while recipient context is suspended
https://bugs.webkit.org/show_bug.cgi?id=105810
Summary [Mutation Observers] prevent delivery while recipient context is suspended
Rafael Weinstein
Reported 2012-12-27 15:29:46 PST
If the execution context is paused, but triggers a mutation (e.g. by stepping through code), Mutation Observers should refrain from attempting delivery until the context is resumed. Currently, the delivery just gets dropped on the floor.
Attachments
Patch (8.42 KB, patch)
2012-12-27 15:34 PST, Rafael Weinstein
no flags
Patch (9.16 KB, patch)
2013-01-03 12:19 PST, Rafael Weinstein
no flags
Patch (10.05 KB, patch)
2013-01-03 12:39 PST, Rafael Weinstein
no flags
Patch (10.05 KB, patch)
2013-01-03 13:33 PST, Rafael Weinstein
no flags
Rafael Weinstein
Comment 1 2012-12-27 15:34:36 PST
Rafael Weinstein
Comment 2 2012-12-27 15:36:42 PST
Pavel, This is my first crack at an inspector test, please let me know if this is ok. Adam/Ojan, I'm guessing the way I'm accessing the ActiveDOMCallback is wrong here. What's a better way to do this? It seems like maybe the MutationCallback should have a virtual canDeliver(), which JSC and V8 can implement respectively, but I'm not sure how to do that. Once I get the two above sorted, I'll attempt to implement JSC.
Early Warning System Bot
Comment 3 2012-12-27 15:45:20 PST
Early Warning System Bot
Comment 4 2012-12-27 15:46:40 PST
EFL EWS Bot
Comment 5 2012-12-27 16:12:37 PST
Build Bot
Comment 6 2012-12-27 16:37:18 PST
kov's GTK+ EWS bot
Comment 7 2012-12-27 17:17:39 PST
Build Bot
Comment 8 2013-01-02 15:59:37 PST
Adam Barth
Comment 9 2013-01-03 11:27:03 PST
Comment on attachment 180827 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=180827&action=review > Source/WebCore/dom/MutationObserver.cpp:193 > +bool MutationObserver::canDeliver() > +{ > +// FIXME: How does JSC suspend for inspection? > +#if USE(V8) > + return reinterpret_cast<V8MutationCallback*>(m_callback.get())->canInvokeCallback(); > +#else > + return true; > +#endif > +} This isn't right. You mean to ask the callback's context whether active DOM objects are suspended.
Rafael Weinstein
Comment 10 2013-01-03 12:19:23 PST
Early Warning System Bot
Comment 11 2013-01-03 12:30:45 PST
Early Warning System Bot
Comment 12 2013-01-03 12:31:53 PST
Elliott Sprehn
Comment 13 2013-01-03 12:36:04 PST
Comment on attachment 181201 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=181201&action=review > Source/WebCore/dom/MutationObserver.cpp:241 > + suspendedMutationObservers().add(observers[i]); Why not just call activeMutationObservers().add() and put the suspended ones back into the list? I don't think you need the two lists and all the copying logic above.
Rafael Weinstein
Comment 14 2013-01-03 12:39:38 PST
Early Warning System Bot
Comment 15 2013-01-03 13:00:11 PST
Early Warning System Bot
Comment 16 2013-01-03 13:00:21 PST
EFL EWS Bot
Comment 17 2013-01-03 13:05:15 PST
Build Bot
Comment 18 2013-01-03 13:16:03 PST
Build Bot
Comment 19 2013-01-03 13:29:33 PST
Rafael Weinstein
Comment 20 2013-01-03 13:33:24 PST
Rafael Weinstein
Comment 21 2013-01-03 13:39:01 PST
Comment on attachment 181201 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=181201&action=review >> Source/WebCore/dom/MutationObserver.cpp:241 >> + suspendedMutationObservers().add(observers[i]); > > Why not just call activeMutationObservers().add() and put the suspended ones back into the list? I don't think you need the two lists and all the copying logic above. That would case this loop to non-terminate. deliverAllMutations will get called at the end of every task. By putting observers into the suspended list, it means that each task makes an attempt to redeliver to any pending. Notice that this loop is while(!activeMutationObservers().isEmpty()). We can't keep adding suspended back into it. Within this loop, nothing is going to cause them to become unsuspended.
Elliott Sprehn
Comment 22 2013-01-03 13:44:10 PST
(In reply to comment #21) > (From update of attachment 181201 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=181201&action=review > > >> Source/WebCore/dom/MutationObserver.cpp:241 > >> + suspendedMutationObservers().add(observers[i]); > > > > Why not just call activeMutationObservers().add() and put the suspended ones back into the list? I don't think you need the two lists and all the copying logic above. > > That would case this loop to non-terminate. deliverAllMutations will get called at the end of every task. By putting observers into the suspended list, it means that each task makes an attempt to redeliver to any pending. Notice that this loop is while(!activeMutationObservers().isEmpty()). We can't keep adding suspended back into it. Within this loop, nothing is going to cause them to become unsuspended. I see, could we just put a stack allocated set outside the loop and copy into that then? Right after the loop add them all back. That's like 3 lines of code instead of all this.
Adam Barth
Comment 23 2013-01-03 13:53:27 PST
Comment on attachment 181210 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=181210&action=review > Source/WebCore/bindings/scripts/CodeGeneratorJS.pm:2833 > + push(@headerContent, " virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }\n\n"); Can't we just write: "using ContextDestructionObserver::scriptExecutionContext;" ?
Rafael Weinstein
Comment 24 2013-01-03 14:01:36 PST
Comment on attachment 181201 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=181201&action=review >>>> Source/WebCore/dom/MutationObserver.cpp:241 >>>> + suspendedMutationObservers().add(observers[i]); >>> >>> Why not just call activeMutationObservers().add() and put the suspended ones back into the list? I don't think you need the two lists and all the copying logic above. >> >> That would case this loop to non-terminate. deliverAllMutations will get called at the end of every task. By putting observers into the suspended list, it means that each task makes an attempt to redeliver to any pending. Notice that this loop is while(!activeMutationObservers().isEmpty()). We can't keep adding suspended back into it. Within this loop, nothing is going to cause them to become unsuspended. > > I see, could we just put a stack allocated set outside the loop and copy into that then? Right after the loop add them all back. That's like 3 lines of code instead of all this. No. Observers aren't going to move from suspended->ready within the same stack. They will change states with later calls from a run loop.
Rafael Weinstein
Comment 25 2013-01-03 14:54:24 PST
Comment on attachment 181210 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=181210&action=review >> Source/WebCore/bindings/scripts/CodeGeneratorJS.pm:2833 >> + push(@headerContent, " virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }\n\n"); > > Can't we just write: > > "using ContextDestructionObserver::scriptExecutionContext;" ? nope. that doesn't appear to work.
WebKit Review Bot
Comment 26 2013-01-03 15:24:04 PST
Comment on attachment 181210 [details] Patch Clearing flags on attachment: 181210 Committed r138754: <http://trac.webkit.org/changeset/138754>
WebKit Review Bot
Comment 27 2013-01-03 15:24:10 PST
All reviewed patches have been landed. Closing bug.
Note You need to log in before you can comment on or make changes to this bug.