Diff
Modified: trunk/LayoutTests/ChangeLog (107007 => 107008)
--- trunk/LayoutTests/ChangeLog 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/LayoutTests/ChangeLog 2012-02-08 00:40:31 UTC (rev 107008)
@@ -1,3 +1,20 @@
+2012-02-07 Adam Klein <ad...@chromium.org>
+
+ Add JSC support for delivering mutations when the outermost script context exits
+ https://bugs.webkit.org/show_bug.cgi?id=70289
+
+ Reviewed by Eric Seidel.
+
+ With the various fixes in this change, 8/10 tests in fast/mutation
+ pass under WebKit/Mac. Of the failing tests, only one is due to
+ a deficiency in the Mac port's code (end-of-task-delivery.html);
+ the other is due to lack of support for a feature (FILE_SYSTEM)
+ exercised by the test (non-event-delivery.html).
+
+ * fast/mutation/non-event-delivery.html: Made it fail fast if FileSystem support isn't available.
+ * fast/mutation/observe-attributes.html: Fixed calls to removeEventListener.
+ * fast/mutation/observe-characterdata.html: ditto.
+
2012-02-07 Levi Weintraub <le...@chromium.org>
[SVG] Use element disappears after scripted change
Modified: trunk/LayoutTests/fast/mutation/non-event-delivery.html (107007 => 107008)
--- trunk/LayoutTests/fast/mutation/non-event-delivery.html 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/LayoutTests/fast/mutation/non-event-delivery.html 2012-02-08 00:40:31 UTC (rev 107008)
@@ -116,9 +116,13 @@
description('Test that Mutation Records are delivered following non-event async callbacks.');
-if (!window.WebKitMutationObserver)
+if (!window.WebKitMutationObserver) {
testFailed('This test requires ENABLE(MUTATION_OBSERVERS)');
-else
+ finishJSTest();
+} else if (!window.webkitRequestFileSystem) {
+ testFailed('This test requires ENABLE(FILE_SYSTEM)');
+ finishJSTest();
+} else
runNextTest();
</script>
Modified: trunk/LayoutTests/fast/mutation/observe-attributes.html (107007 => 107008)
--- trunk/LayoutTests/fast/mutation/observe-attributes.html 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/LayoutTests/fast/mutation/observe-attributes.html 2012-02-08 00:40:31 UTC (rev 107008)
@@ -285,7 +285,7 @@
shouldBe('mutations[0].attributeName', '"foo"');
shouldBe('mutations[1].type', '"attributes"');
shouldBe('mutations[1].attributeName', '"baz"');
- div.removeEventListener(listener);
+ div.removeEventListener('DOMSubtreeModified', listener);
document.body.removeChild(div);
observer.disconnect();
debug('');
Modified: trunk/LayoutTests/fast/mutation/observe-characterdata.html (107007 => 107008)
--- trunk/LayoutTests/fast/mutation/observe-characterdata.html 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/LayoutTests/fast/mutation/observe-characterdata.html 2012-02-08 00:40:31 UTC (rev 107008)
@@ -182,7 +182,7 @@
shouldBe('mutations.length', '2');
shouldBe('mutations[0].type', '"characterData"');
shouldBe('mutations[1].type', '"attributes"');
- div.removeEventListener(listener);
+ div.removeEventListener('DOMSubtreeModified', listener);
document.body.removeChild(div);
observer.disconnect();
debug('');
Modified: trunk/Source/WebCore/ChangeLog (107007 => 107008)
--- trunk/Source/WebCore/ChangeLog 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/ChangeLog 2012-02-08 00:40:31 UTC (rev 107008)
@@ -1,3 +1,49 @@
+2012-02-07 Adam Klein <ad...@chromium.org>
+
+ Add JSC support for delivering mutations when the outermost script context exits
+ https://bugs.webkit.org/show_bug.cgi?id=70289
+
+ Reviewed by Eric Seidel.
+
+ The meat of this change is in JSMainThreadExecState, where a counter
+ is incremented every time WebCore calls into JSC and decremented every
+ time it returns. When the counter reaches zero, any pending mutations
+ are delivered (this mirrors very similar code in V8Proxy and V8RecursionScope).
+
+ The rest of the changes are of two sorts: compilation/logic fixes for
+ JSC code when ENABLE(MUTATION_OBSERVERS) is true, and additional
+ usages of JSMainThreadExecState so as to trigger the above
+ increment/decrements at the appropriate times.
+
+ * bindings/js/JSCustomXPathNSResolver.cpp:
+ (WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):
+ Use JSMainThreadExecState instead of JSC::call.
+ * bindings/js/JSDictionary.cpp:
+ (WebCore::JSDictionary::convertValue): Add support
+ for tryGetProperty with a HashMap<AtomicString>.
+ * bindings/js/JSDictionary.h:
+ * bindings/js/JSErrorHandler.cpp:
+ (WebCore::JSErrorHandler::handleEvent):
+ Use JSMainThreadExecState instead of JSC::call.
+ * bindings/js/JSHTMLDocumentCustom.cpp:
+ (WebCore::JSHTMLDocument::open):
+ Use JSMainThreadExecState instead of JSC::call.
+ * bindings/js/JSMainThreadExecState.cpp:
+ (WebCore::JSMainThreadExecState::didLeaveScriptContext):
+ * bindings/js/JSMainThreadExecState.h:
+ (WebCore::JSMainThreadExecState::JSMainThreadExecState):
+ Increment a static recursion level counter.
+ (WebCore::JSMainThreadExecState::~JSMainThreadExecState):
+ Decrement a static recursion level counter and, if we are
+ at zero (the outermost script invocation), deliver any
+ outstanding mutation records.
+ * bindings/js/JSNodeFilterCondition.cpp:
+ (WebCore::JSNodeFilterCondition::acceptNode):
+ Use JSMainThreadExecState instead of JSC::call.
+ * bindings/js/JSWebKitMutationObserverCustom.cpp:
+ (WebCore::JSWebKitMutationObserver::observe):
+ Fix JSDictionary logic, add support for attributeFilter.
+
2012-02-07 Anders Carlsson <ander...@apple.com>
Fix build.
Modified: trunk/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp 2012-02-08 00:40:31 UTC (rev 107008)
@@ -31,6 +31,7 @@
#include "ExceptionCode.h"
#include "Frame.h"
#include "JSDOMWindowCustom.h"
+#include "JSMainThreadExecState.h"
#include "SecurityOrigin.h"
#include <runtime/JSLock.h>
@@ -89,7 +90,7 @@
args.append(jsString(exec, prefix));
m_globalObject->globalData().timeoutChecker.start();
- JSValue retval = JSC::call(exec, function, callType, callData, m_customResolver, args);
+ JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver, args);
m_globalObject->globalData().timeoutChecker.stop();
String result;
Modified: trunk/Source/WebCore/bindings/js/JSDictionary.cpp (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSDictionary.cpp 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSDictionary.cpp 2012-02-08 00:40:31 UTC (rev 107008)
@@ -34,7 +34,9 @@
#include "JSTrackCustom.h"
#include "SerializedScriptValue.h"
#include "ScriptValue.h"
+#include <wtf/HashMap.h>
#include <wtf/MathExtras.h>
+#include <wtf/text/AtomicString.h>
using namespace JSC;
@@ -136,4 +138,26 @@
}
#endif
+#if ENABLE(MUTATION_OBSERVERS)
+void JSDictionary::convertValue(ExecState* exec, JSValue value, HashSet<AtomicString>& result)
+{
+ result.clear();
+
+ if (value.isUndefinedOrNull())
+ return;
+
+ unsigned length;
+ JSObject* object = toJSSequence(exec, value, length);
+ if (exec->hadException())
+ return;
+
+ for (unsigned i = 0 ; i < length; ++i) {
+ JSValue itemValue = object->get(exec, i);
+ if (exec->hadException())
+ return;
+ result.add(ustringToAtomicString(itemValue.toString(exec)->value(exec)));
+ }
+}
+#endif
+
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/js/JSDictionary.h (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSDictionary.h 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSDictionary.h 2012-02-08 00:40:31 UTC (rev 107008)
@@ -87,6 +87,9 @@
#if ENABLE(VIDEO_TRACK)
static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<TrackBase>& result);
#endif
+#if ENABLE(MUTATION_OBSERVERS)
+ static void convertValue(JSC::ExecState*, JSC::JSValue, HashSet<AtomicString>& result);
+#endif
JSC::ExecState* m_exec;
JSC::JSObject* m_initializerObject;
Modified: trunk/Source/WebCore/bindings/js/JSErrorHandler.cpp (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSErrorHandler.cpp 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSErrorHandler.cpp 2012-02-08 00:40:31 UTC (rev 107008)
@@ -36,6 +36,7 @@
#include "Event.h"
#include "EventNames.h"
#include "JSEvent.h"
+#include "JSMainThreadExecState.h"
#include <runtime/JSLock.h>
using namespace JSC;
@@ -94,7 +95,9 @@
JSValue thisValue = globalObject->methodTable()->toThisObject(globalObject, exec);
globalData.timeoutChecker.start();
- JSValue returnValue = JSC::call(exec, jsFunction, callType, callData, thisValue, args);
+ JSValue returnValue = scriptExecutionContext->isDocument()
+ ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, thisValue, args)
+ : JSC::call(exec, jsFunction, callType, callData, thisValue, args);
globalData.timeoutChecker.stop();
globalObject->setCurrentEvent(savedEvent);
Modified: trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp 2012-02-08 00:40:31 UTC (rev 107008)
@@ -38,6 +38,7 @@
#include "JSDOMWindowCustom.h"
#include "JSDOMWindowShell.h"
#include "JSHTMLCollection.h"
+#include "JSMainThreadExecState.h"
#include "SegmentedString.h"
#include "DocumentParser.h"
#include <runtime/Error.h>
@@ -113,7 +114,7 @@
CallType callType = ::getCallData(function, callData);
if (callType == CallTypeNone)
return throwTypeError(exec);
- return JSC::call(exec, function, callType, callData, wrapper, ArgList(exec));
+ return JSMainThreadExecState::call(exec, function, callType, callData, wrapper, ArgList(exec));
}
}
return jsUndefined();
Modified: trunk/Source/WebCore/bindings/js/JSMainThreadExecState.cpp (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSMainThreadExecState.cpp 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSMainThreadExecState.cpp 2012-02-08 00:40:31 UTC (rev 107008)
@@ -25,9 +25,19 @@
#include "config.h"
#include "JSMainThreadExecState.h"
+#include "WebKitMutationObserver.h"
namespace WebCore {
JSC::ExecState* JSMainThreadExecState::s_mainThreadState = 0;
+#if ENABLE(MUTATION_OBSERVERS)
+int JSMainThreadExecState::s_recursionLevel = 0;
+
+void JSMainThreadExecState::didLeaveScriptContext()
+{
+ WebKitMutationObserver::deliverAllMutations();
+}
+#endif
+
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h 2012-02-08 00:40:31 UTC (rev 107008)
@@ -91,17 +91,33 @@
{
ASSERT(isMainThread());
s_mainThreadState = exec;
+
+#if ENABLE(MUTATION_OBSERVERS)
+ ASSERT(s_recursionLevel >= 0);
+ ++s_recursionLevel;
+#endif
};
-
+
~JSMainThreadExecState()
{
ASSERT(isMainThread());
s_mainThreadState = m_previousState;
+
+#if ENABLE(MUTATION_OBSERVERS)
+ ASSERT(s_recursionLevel > 0);
+ if (!--s_recursionLevel)
+ didLeaveScriptContext();
+#endif
}
private:
static JSC::ExecState* s_mainThreadState;
JSC::ExecState* m_previousState;
+
+#if ENABLE(MUTATION_OBSERVERS)
+ static void didLeaveScriptContext();
+ static int s_recursionLevel;
+#endif
};
// Null state prevents origin security checks.
Modified: trunk/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp 2012-02-08 00:40:31 UTC (rev 107008)
@@ -20,6 +20,7 @@
#include "config.h"
#include "JSNodeFilterCondition.h"
+#include "JSMainThreadExecState.h"
#include "JSNode.h"
#include "JSNodeFilter.h"
#include "NodeFilter.h"
@@ -72,7 +73,7 @@
if (exec->hadException())
return NodeFilter::FILTER_REJECT;
- JSValue result = JSC::call(exec, function, callType, callData, m_filter.get(), args);
+ JSValue result = JSMainThreadExecState::call(exec, function, callType, callData, m_filter.get(), args);
if (exec->hadException())
return NodeFilter::FILTER_REJECT;
Modified: trunk/Source/WebCore/bindings/js/JSWebKitMutationObserverCustom.cpp (107007 => 107008)
--- trunk/Source/WebCore/bindings/js/JSWebKitMutationObserverCustom.cpp 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Source/WebCore/bindings/js/JSWebKitMutationObserverCustom.cpp 2012-02-08 00:40:31 UTC (rev 107008)
@@ -41,6 +41,8 @@
#include "Node.h"
#include "WebKitMutationObserver.h"
#include <runtime/Error.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/AtomicString.h>
using namespace JSC;
@@ -62,6 +64,22 @@
return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), WebKitMutationObserver::create(callback.release()))));
}
+struct BooleanOption {
+ const char* name;
+ MutationObserverOptions value;
+};
+
+static const BooleanOption booleanOptions[] = {
+ { "childList", WebKitMutationObserver::ChildList },
+ { "attributes", WebKitMutationObserver::Attributes },
+ { "characterData", WebKitMutationObserver::CharacterData },
+ { "subtree", WebKitMutationObserver::Subtree },
+ { "attributeOldValue", WebKitMutationObserver::AttributeOldValue },
+ { "characterDataOldValue", WebKitMutationObserver::CharacterDataOldValue }
+};
+
+static const size_t numBooleanOptions = sizeof(booleanOptions) / sizeof(BooleanOption);
+
JSValue JSWebKitMutationObserver::observe(ExecState* exec)
{
if (exec->argumentCount() < 2)
@@ -78,24 +96,22 @@
JSDictionary dictionary(exec, optionsObject);
MutationObserverOptions options = 0;
- // FIXME: Add support for parsing of the attributeFilter option.
- bool option;
- if (dictionary.tryGetProperty("childList", option) && option)
- options |= WebKitMutationObserver::ChildList;
- if (dictionary.tryGetProperty("attributes", option) && option)
- options |= WebKitMutationObserver::Attributes;
- if (dictionary.tryGetProperty("subtree", option) && option)
- options |= WebKitMutationObserver::Subtree;
- if (dictionary.tryGetProperty("attributeOldValue", option) && option)
- options |= WebKitMutationObserver::AttributeOldValue;
- if (dictionary.tryGetProperty("characterDataOldValue", option) && option)
- options |= WebKitMutationObserver::CharacterDataOldValue;
+ for (unsigned i = 0; i < numBooleanOptions; ++i) {
+ bool option = false;
+ if (!dictionary.tryGetProperty(booleanOptions[i].name, option))
+ return jsUndefined();
+ if (option)
+ options |= booleanOptions[i].value;
+ }
- if (exec->hadException())
+ HashSet<AtomicString> attributeFilter;
+ if (!dictionary.tryGetProperty("attributeFilter", attributeFilter))
return jsUndefined();
+ if (!attributeFilter.isEmpty())
+ options |= WebKitMutationObserver::AttributeFilter;
ExceptionCode ec = 0;
- impl()->observe(target, options, ec);
+ impl()->observe(target, options, attributeFilter, ec);
if (ec)
setDOMException(exec, ec);
return jsUndefined();
Modified: trunk/Tools/ChangeLog (107007 => 107008)
--- trunk/Tools/ChangeLog 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Tools/ChangeLog 2012-02-08 00:40:31 UTC (rev 107008)
@@ -1,3 +1,18 @@
+2012-02-07 Adam Klein <ad...@chromium.org>
+
+ Add JSC support for delivering mutations when the outermost script context exits
+ https://bugs.webkit.org/show_bug.cgi?id=70289
+
+ Reviewed by Eric Seidel.
+
+ * DumpRenderTree/mac/EventSendingController.mm: Add support for
+ eventSender.scheduleAsynchronousKeyDown.
+ (+[EventSendingController isSelectorExcludedFromWebScript:]):
+ (+[EventSendingController webScriptNameForSelector:]):
+ (-[EventSendingController keyDownWrapper:withModifiers:withLocation:]):
+ (-[EventSendingController scheduleAsynchronousKeyDown:withModifiers:withLocation:]):
+ * Scripts/build-webkit: Properly alphabetize --mutation-observers in the --help output.
+
2012-02-07 Chris Rogers <crog...@google.com>
Add Chris Rogers to reviewers section
Modified: trunk/Tools/DumpRenderTree/mac/EventSendingController.mm (107007 => 107008)
--- trunk/Tools/DumpRenderTree/mac/EventSendingController.mm 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Tools/DumpRenderTree/mac/EventSendingController.mm 2012-02-08 00:40:31 UTC (rev 107008)
@@ -131,6 +131,7 @@
|| aSelector == @selector(mouseMoveToX:Y:)
|| aSelector == @selector(mouseUp:withModifiers:)
|| aSelector == @selector(scheduleAsynchronousClick)
+ || aSelector == @selector(scheduleAsynchronousKeyDown:withModifiers:withLocation:)
|| aSelector == @selector(textZoomIn)
|| aSelector == @selector(textZoomOut)
|| aSelector == @selector(zoomPageIn)
@@ -161,6 +162,8 @@
return @"fireKeyboardEventsToElement";
if (aSelector == @selector(keyDown:withModifiers:withLocation:))
return @"keyDown";
+ if (aSelector == @selector(scheduleAsynchronousKeyDown:withModifiers:withLocation:))
+ return @"scheduleAsynchronousKeyDown";
if (aSelector == @selector(leapForward:))
return @"leapForward";
if (aSelector == @selector(mouseDown:withModifiers:))
@@ -722,6 +725,23 @@
[[[[mainFrame webView] window] firstResponder] keyUp:event];
}
+- (void)keyDownWrapper:(NSString *)character withModifiers:(WebScriptObject *)modifiers withLocation:(unsigned long)keyLocation
+{
+ [self keyDown:character withModifiers:modifiers withLocation:keyLocation];
+}
+
+- (void)scheduleAsynchronousKeyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers withLocation:(unsigned long)keyLocation
+{
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(keyDownWrapper:withModifiers:withLocation:)]];
+ [invocation retainArguments];
+ [invocation setTarget:self];
+ [invocation setSelector:@selector(keyDownWrapper:withModifiers:withLocation:)];
+ [invocation setArgument:&character atIndex:2];
+ [invocation setArgument:&modifiers atIndex:3];
+ [invocation setArgument:&keyLocation atIndex:4];
+ [invocation performSelector:@selector(invoke) withObject:nil afterDelay:0];
+}
+
- (void)enableDOMUIEventLogging:(WebScriptObject *)node
{
NSEnumerator *eventEnumerator = [webkitDomEventNames objectEnumerator];
Modified: trunk/Tools/Scripts/build-webkit (107007 => 107008)
--- trunk/Tools/Scripts/build-webkit 2012-02-08 00:26:45 UTC (rev 107007)
+++ trunk/Tools/Scripts/build-webkit 2012-02-08 00:40:31 UTC (rev 107008)
@@ -195,9 +195,6 @@
{ option => "directory-upload", desc => "Toogle Directory upload support",
define => "ENABLE_DIRECTORY_UPLOAD", default => 0, value => \$directoryUploadSupport },
- { option => "mutation-observers", desc => "Toggle DOM mutation observer support",
- define => "ENABLE_MUTATION_OBSERVERS", default => 0, value => \$mutationObserversSupport },
-
{ option => "file-system", desc => "Toggle FileSystem support",
define => "ENABLE_FILE_SYSTEM", default => 0, value => \$fileSystemSupport },
@@ -273,6 +270,9 @@
{ option => "microdata", desc => "Toggle Microdata support",
define => "ENABLE_MICRODATA", default => 0, value => \$microdataSupport },
+ { option => "mutation-observers", desc => "Toggle DOM mutation observer support",
+ define => "ENABLE_MUTATION_OBSERVERS", default => 0, value => \$mutationObserversSupport },
+
{ option => "netscape-plugin", desc => "Netscape Plugin support",
define => "ENABLE_NETSCAPE_PLUGIN_API", default => !isEfl(), value => \$netscapePluginSupport },