[MutationObservers] V8LazyEventHandler breaks microtask delivery semantics
https://bugs.webkit.org/show_bug.cgi?id=73492
Reviewed by Adam Barth.
Source/WebCore:
Test: fast/mutation/inline-event-listener.html
* bindings/v8/V8LazyEventListener.cpp:
(WebCore::V8LazyEventListener::prepareListenerObject): Call v8::Script::Run directly instead of going through V8Proxy.
Tools:
Add eventSender.scheduleAsynchronousKeyDown, needed to cause a
keypress event without any script on the stack.
* DumpRenderTree/chromium/EventSender.cpp:
(EventSender::EventSender):
(EventSender::keyDown):
(KeyDownTask::KeyDownTask):
(KeyDownTask::runIfValid):
(EventSender::scheduleAsynchronousKeyDown):
* DumpRenderTree/chromium/EventSender.h:
LayoutTests:
* fast/mutation/inline-event-listener-expected.txt: Added.
* fast/mutation/inline-event-listener.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@102424 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 96101fb..65c9d34 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2011-12-08 Adam Klein <adamk@chromium.org>
+
+ [MutationObservers] V8LazyEventHandler breaks microtask delivery semantics
+ https://bugs.webkit.org/show_bug.cgi?id=73492
+
+ Reviewed by Adam Barth.
+
+ * fast/mutation/inline-event-listener-expected.txt: Added.
+ * fast/mutation/inline-event-listener.html: Added.
+
2011-12-08 Hayato Ito <hayato@chromium.org>
Suppress rendering of light children when ShadowRoot is dynamically created.
diff --git a/LayoutTests/fast/mutation/inline-event-listener-expected.txt b/LayoutTests/fast/mutation/inline-event-listener-expected.txt
new file mode 100644
index 0000000..53cdf1e
--- /dev/null
+++ b/LayoutTests/fast/mutation/inline-event-listener-expected.txt
@@ -0,0 +1 @@
+PASSED
diff --git a/LayoutTests/fast/mutation/inline-event-listener.html b/LayoutTests/fast/mutation/inline-event-listener.html
new file mode 100644
index 0000000..30968e1
--- /dev/null
+++ b/LayoutTests/fast/mutation/inline-event-listener.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<ol contenteditable oninput="document.body.innerHTML = observerRan ? 'FAILED' : 'PASSED'; if (window.layoutTestController) layoutTestController.notifyDone()">
+ <li>Press enter
+</ol>
+<script>
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+ }
+
+ var list = document.querySelector('ol');
+ var observerRan = false;
+ var observer = new WebKitMutationObserver(function() { observerRan = true; });
+ observer.observe(list, {childList: true, characterData: true});
+ list.focus();
+ if (window.eventSender)
+ eventSender.scheduleAsynchronousKeyDown('\n');
+</script>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 0f2e584..c82b93f 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,15 @@
+2011-12-08 Adam Klein <adamk@chromium.org>
+
+ [MutationObservers] V8LazyEventHandler breaks microtask delivery semantics
+ https://bugs.webkit.org/show_bug.cgi?id=73492
+
+ Reviewed by Adam Barth.
+
+ Test: fast/mutation/inline-event-listener.html
+
+ * bindings/v8/V8LazyEventListener.cpp:
+ (WebCore::V8LazyEventListener::prepareListenerObject): Call v8::Script::Run directly instead of going through V8Proxy.
+
2011-12-08 Hayato Ito <hayato@chromium.org>
Suppress rendering of light children when ShadowRoot is dynamically created.
diff --git a/Source/WebCore/bindings/v8/V8LazyEventListener.cpp b/Source/WebCore/bindings/v8/V8LazyEventListener.cpp
index 789fbd2..92c2e79 100644
--- a/Source/WebCore/bindings/v8/V8LazyEventListener.cpp
+++ b/Source/WebCore/bindings/v8/V8LazyEventListener.cpp
@@ -123,7 +123,9 @@
v8::Handle<v8::String> codeExternalString = v8ExternalString(code);
v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_sourceURL, m_position);
if (!script.IsEmpty()) {
- v8::Local<v8::Value> value = proxy->runScript(script);
+ // Call v8::Script::Run() directly to avoid an erroneous call to V8RecursionScope::didLeaveScriptContext().
+ // FIXME: Remove this code when we stop doing the 'with' hack above.
+ v8::Local<v8::Value> value = script->Run();
if (!value.IsEmpty()) {
ASSERT(value->IsFunction());
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index 0070d87..23ba6de 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,21 @@
+2011-12-08 Adam Klein <adamk@chromium.org>
+
+ [MutationObservers] V8LazyEventHandler breaks microtask delivery semantics
+ https://bugs.webkit.org/show_bug.cgi?id=73492
+
+ Reviewed by Adam Barth.
+
+ Add eventSender.scheduleAsynchronousKeyDown, needed to cause a
+ keypress event without any script on the stack.
+
+ * DumpRenderTree/chromium/EventSender.cpp:
+ (EventSender::EventSender):
+ (EventSender::keyDown):
+ (KeyDownTask::KeyDownTask):
+ (KeyDownTask::runIfValid):
+ (EventSender::scheduleAsynchronousKeyDown):
+ * DumpRenderTree/chromium/EventSender.h:
+
2011-12-08 Hayato Ito <hayato@chromium.org>
[gdb] Pretty printer for a 8-bit version of WTF::StringImpl and LChar*.
diff --git a/Tools/DumpRenderTree/chromium/EventSender.cpp b/Tools/DumpRenderTree/chromium/EventSender.cpp
index debdd5e..9acc42d 100644
--- a/Tools/DumpRenderTree/chromium/EventSender.cpp
+++ b/Tools/DumpRenderTree/chromium/EventSender.cpp
@@ -270,6 +270,7 @@
bindMethod("mouseUp", &EventSender::mouseUp);
bindMethod("releaseTouchPoint", &EventSender::releaseTouchPoint);
bindMethod("scheduleAsynchronousClick", &EventSender::scheduleAsynchronousClick);
+ bindMethod("scheduleAsynchronousKeyDown", &EventSender::scheduleAsynchronousKeyDown);
bindMethod("setTouchModifier", &EventSender::setTouchModifier);
bindMethod("textZoomIn", &EventSender::textZoomIn);
bindMethod("textZoomOut", &EventSender::textZoomOut);
@@ -500,7 +501,8 @@
void EventSender::keyDown(const CppArgumentList& arguments, CppVariant* result)
{
- result->setNull();
+ if (result)
+ result->setNull();
if (arguments.size() < 1 || !arguments[0].isString())
return;
bool generateChar = false;
@@ -847,6 +849,22 @@
postTask(new MouseUpTask(this, arguments));
}
+class KeyDownTask : public MethodTask<EventSender> {
+public:
+ KeyDownTask(EventSender* obj, const CppArgumentList& arg)
+ : MethodTask<EventSender>(obj), m_arguments(arg) { }
+ virtual void runIfValid() { m_object->keyDown(m_arguments, 0); }
+
+private:
+ CppArgumentList m_arguments;
+};
+
+void EventSender::scheduleAsynchronousKeyDown(const CppArgumentList& arguments, CppVariant* result)
+{
+ result->setNull();
+ postTask(new KeyDownTask(this, arguments));
+}
+
void EventSender::beginDragWithFiles(const CppArgumentList& arguments, CppVariant* result)
{
currentDragData.initialize();
diff --git a/Tools/DumpRenderTree/chromium/EventSender.h b/Tools/DumpRenderTree/chromium/EventSender.h
index f3f8cf4..bbecc54 100644
--- a/Tools/DumpRenderTree/chromium/EventSender.h
+++ b/Tools/DumpRenderTree/chromium/EventSender.h
@@ -82,6 +82,7 @@
void mouseScrollBy(const CppArgumentList&, CppVariant*);
void continuousMouseScrollBy(const CppArgumentList&, CppVariant*);
void scheduleAsynchronousClick(const CppArgumentList&, CppVariant*);
+ void scheduleAsynchronousKeyDown(const CppArgumentList&, CppVariant*);
void beginDragWithFiles(const CppArgumentList&, CppVariant*);
CppVariant dragMode;