Title: [200552] trunk
Revision
200552
Author
[email protected]
Date
2016-05-07 23:39:23 -0700 (Sat, 07 May 2016)

Log Message

Change MutationObserver::observe to take an IDL dictionary, rather than WebCore::Dictionary
https://bugs.webkit.org/show_bug.cgi?id=157456

Reviewed by Chris Dumez.

Source/WebCore:

* bindings/js/JSDOMConvert.h:
(WebCore::convertOptional): Use a specific Optional null rather than Nullopt so we
can compile the ternary operator.
(WebCore::convert<bool>): Added.
(WebCore::convert<Vector<String>>): Added. Later we probably need to change convert to use
a member function of a class template rather than a function template so we can make partial
specialization work and do this just once for all Vector<T>.

* bindings/js/JSMutationObserverCustom.cpp:
(WebCore::JSMutationObserverOwner::isReachableFromOpaqueRoots): Streamlined code and removed
some local variables. Changed to call the new observedNodes rather than getObservedNodes.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateDictionaryImplementationContent): Fixed bug where we tried to call the version of
the convert function with a default value even when there was none.

* bindings/scripts/test/TestObj.idl: Added a test case basically identical to what's needed
in MutationObserver.idl.
* bindings/scripts/test/JS/JSTestObj.cpp: Regenerated.

* dom/MutationObserver.cpp:
(WebCore::MutationObserver::observe): Chagned function to take a MutationObserver::Init
instead of a Dictionary.
(WebCore::MutationObserver::observationStarted): Changed argument type to a reference.
(WebCore::MutationObserver::observationEnded): Ditto.
(WebCore::MutationObserverMicrotask): Removed unneeded explicit constructor and destructor.
(WebCore::queueMutationObserverCompoundMicrotask): Got rid of unnneeded local variable.
(WebCore::MutationObserver::observedNodes): Renamed to remove the "get" prefix.

* dom/MutationObserver.h: Reduced includes. Added MutationObserver::Init struct and
used it for the type of the argument to the observe function. Changed a few argument
types and removed unused forward declarations.

* dom/MutationObserver.idl: Added MutationObserverInit and used it instead of Dictionary.

* dom/MutationObserverRegistration.cpp:
(WebCore::MutationObserverRegistration::MutationObserverRegistration): Pass a reference.
(WebCore::MutationObserverRegistration::~MutationObserverRegistration): Ditto.

LayoutTests:

* fast/dom/MutationObserver/observe-exceptions-expected.txt: Updated to expect
the specific TypeError generated by the bindings code rather than the generic
TypeError we got before generated inside the C++ DOM.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (200551 => 200552)


--- trunk/LayoutTests/ChangeLog	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/LayoutTests/ChangeLog	2016-05-08 06:39:23 UTC (rev 200552)
@@ -1,3 +1,14 @@
+2016-05-07  Darin Adler  <[email protected]>
+
+        Change MutationObserver::observe to take an IDL dictionary, rather than WebCore::Dictionary
+        https://bugs.webkit.org/show_bug.cgi?id=157456
+
+        Reviewed by Chris Dumez.
+
+        * fast/dom/MutationObserver/observe-exceptions-expected.txt: Updated to expect
+        the specific TypeError generated by the bindings code rather than the generic
+        TypeError we got before generated inside the C++ DOM.
+
 2016-05-07  Joanmarie Diggs  <[email protected]>
 
         REGRESSION(r196222): [AX][GTK] accessibility/gtk/caret-offsets.html failing

Modified: trunk/LayoutTests/fast/dom/MutationObserver/observe-exceptions-expected.txt (200551 => 200552)


--- trunk/LayoutTests/fast/dom/MutationObserver/observe-exceptions-expected.txt	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/LayoutTests/fast/dom/MutationObserver/observe-exceptions-expected.txt	2016-05-08 06:39:23 UTC (rev 200552)
@@ -7,8 +7,8 @@
 PASS observer.observe(null) threw exception TypeError: Not enough arguments.
 PASS observer.observe(undefined) threw exception TypeError: Not enough arguments.
 PASS observer.observe(document.body) threw exception TypeError: Not enough arguments.
-PASS observer.observe(document.body, null) threw exception TypeError: Type error.
-PASS observer.observe(document.body, undefined) threw exception TypeError: Type error.
+PASS observer.observe(document.body, null) threw exception TypeError: null is not an object (evaluating 'observer.observe(document.body, null)').
+PASS observer.observe(document.body, undefined) threw exception TypeError: undefined is not an object (evaluating 'observer.observe(document.body, undefined)').
 PASS observer.observe(null, {attributes: true}) threw exception TypeError: Type error.
 PASS observer.observe(undefined, {attributes: true}) threw exception TypeError: Type error.
 PASS observer.observe(document.body, {subtree: true}) threw exception TypeError: Type error.

Modified: trunk/Source/WebCore/ChangeLog (200551 => 200552)


--- trunk/Source/WebCore/ChangeLog	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/ChangeLog	2016-05-08 06:39:23 UTC (rev 200552)
@@ -1,3 +1,49 @@
+2016-05-07  Darin Adler  <[email protected]>
+
+        Change MutationObserver::observe to take an IDL dictionary, rather than WebCore::Dictionary
+        https://bugs.webkit.org/show_bug.cgi?id=157456
+
+        Reviewed by Chris Dumez.
+
+        * bindings/js/JSDOMConvert.h:
+        (WebCore::convertOptional): Use a specific Optional null rather than Nullopt so we
+        can compile the ternary operator.
+        (WebCore::convert<bool>): Added.
+        (WebCore::convert<Vector<String>>): Added. Later we probably need to change convert to use
+        a member function of a class template rather than a function template so we can make partial
+        specialization work and do this just once for all Vector<T>.
+
+        * bindings/js/JSMutationObserverCustom.cpp:
+        (WebCore::JSMutationObserverOwner::isReachableFromOpaqueRoots): Streamlined code and removed
+        some local variables. Changed to call the new observedNodes rather than getObservedNodes.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateDictionaryImplementationContent): Fixed bug where we tried to call the version of
+        the convert function with a default value even when there was none.
+
+        * bindings/scripts/test/TestObj.idl: Added a test case basically identical to what's needed
+        in MutationObserver.idl.
+        * bindings/scripts/test/JS/JSTestObj.cpp: Regenerated.
+
+        * dom/MutationObserver.cpp:
+        (WebCore::MutationObserver::observe): Chagned function to take a MutationObserver::Init
+        instead of a Dictionary.
+        (WebCore::MutationObserver::observationStarted): Changed argument type to a reference.
+        (WebCore::MutationObserver::observationEnded): Ditto.
+        (WebCore::MutationObserverMicrotask): Removed unneeded explicit constructor and destructor.
+        (WebCore::queueMutationObserverCompoundMicrotask): Got rid of unnneeded local variable.
+        (WebCore::MutationObserver::observedNodes): Renamed to remove the "get" prefix.
+
+        * dom/MutationObserver.h: Reduced includes. Added MutationObserver::Init struct and
+        used it for the type of the argument to the observe function. Changed a few argument
+        types and removed unused forward declarations.
+
+        * dom/MutationObserver.idl: Added MutationObserverInit and used it instead of Dictionary.
+
+        * dom/MutationObserverRegistration.cpp:
+        (WebCore::MutationObserverRegistration::MutationObserverRegistration): Pass a reference.
+        (WebCore::MutationObserverRegistration::~MutationObserverRegistration): Ditto.
+
 2016-05-07  Chris Dumez  <[email protected]>
 
         Reduce special handling of XPathNSResolver type in the bindings

Modified: trunk/Source/WebCore/bindings/js/JSDOMConvert.h (200551 => 200552)


--- trunk/Source/WebCore/bindings/js/JSDOMConvert.h	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/bindings/js/JSDOMConvert.h	2016-05-08 06:39:23 UTC (rev 200552)
@@ -40,7 +40,7 @@
 
 template<typename T> Optional<T> inline convertOptional(JSC::ExecState& state, JSC::JSValue value)
 {
-    return value.isUndefined() ? Nullopt : convert<T>(state, value);
+    return value.isUndefined() ? Optional<T>() : convert<T>(state, value);
 }
 
 template<typename T, typename U> inline T convertOptional(JSC::ExecState& state, JSC::JSValue value, U&& defaultValue)
@@ -48,6 +48,11 @@
     return value.isUndefined() ? std::forward<U>(defaultValue) : convert<T>(state, value);
 }
 
+template<> inline bool convert<bool>(JSC::ExecState& state, JSC::JSValue value)
+{
+    return value.toBoolean(&state);
+}
+
 template<> inline String convert<String>(JSC::ExecState& state, JSC::JSValue value)
 {
     return value.toWTFString(&state);
@@ -62,4 +67,25 @@
     return static_cast<T>(number);
 }
 
+template<> Vector<String> convert<Vector<String>>(JSC::ExecState& state, JSC::JSValue value)
+{
+    // FIXME: This code has a lot in common with toNativeArray.
+    // Should find a way to share code.
+    unsigned length;
+    auto* object = toJSSequence(&state, value, length);
+    if (state.hadException())
+        return { };
+    Vector<String> vector;
+    vector.reserveInitialCapacity(length);
+    for (unsigned i = 0 ; i < length; ++i) {
+        auto itemValue = object->get(&state, i);
+        if (state.hadException())
+            return { };
+        vector.uncheckedAppend(convert<String>(state, itemValue));
+        if (state.hadException())
+            return { };
+    }
+    return vector;
 }
+
+}

Modified: trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp (200551 => 200552)


--- trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp	2016-05-08 06:39:23 UTC (rev 200552)
@@ -29,7 +29,6 @@
  */
 
 #include "config.h"
-
 #include "JSMutationObserver.h"
 
 #include "ExceptionCode.h"
@@ -63,10 +62,8 @@
 
 bool JSMutationObserverOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
 {
-    MutationObserver& observer = jsCast<JSMutationObserver*>(handle.slot()->asCell())->wrapped();
-    auto observedNodes = observer.getObservedNodes();
-    for (auto it = observedNodes.begin(), end = observedNodes.end(); it != end; ++it) {
-        if (visitor.containsOpaqueRoot(root(*it)))
+    for (auto* node : jsCast<JSMutationObserver*>(handle.slot()->asCell())->wrapped().observedNodes()) {
+        if (visitor.containsOpaqueRoot(root(node)))
             return true;
     }
     return false;

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (200551 => 200552)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-05-08 06:39:23 UTC (rev 200552)
@@ -968,7 +968,7 @@
             }
             # FIXME: Eventually we will want this to call JSValueToNative.
             my $function = $member->isOptional ? "convertOptional" : "convert";
-            my $defaultValueWithLeadingComma = $member->isOptional ? ", " . $member->default : "";
+            my $defaultValueWithLeadingComma = $member->isOptional && defined $member->default ? ", " . $member->default : "";
             $result .= "    auto " . $member->name . " = " . $function . "<" . GetNativeTypeFromSignature($interface, $member) . ">"
                 . "(state, propertyValue(state, value, \"" . $member->name . "\")" . $defaultValueWithLeadingComma . ");\n";
             $needExceptionCheck = 1;

Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp (200551 => 200552)


--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp	2016-05-08 06:39:23 UTC (rev 200552)
@@ -495,20 +495,20 @@
     auto style = convertOptional<String>(state, propertyValue(state, value, "style"), "normal");
     if (UNLIKELY(state.hadException()))
         return { };
-    auto weight = convertOptional<String>(state, propertyValue(state, value, "weight"), "normal");
-    if (UNLIKELY(state.hadException()))
-        return { };
-    auto stretch = convertOptional<String>(state, propertyValue(state, value, "stretch"), "normal");
-    if (UNLIKELY(state.hadException()))
-        return { };
     auto unicodeRange = convertOptional<String>(state, propertyValue(state, value, "unicodeRange"), "U+0-10FFFF");
+    return { WTFMove(style), WTFMove(unicodeRange) };
+}
+
+template<> TestObj::MutationObserverInit convert<TestObj::MutationObserverInit>(ExecState& state, JSValue value)
+{
+    auto childList = convertOptional<bool>(state, propertyValue(state, value, "childList"), false);
     if (UNLIKELY(state.hadException()))
         return { };
-    auto variant = convertOptional<String>(state, propertyValue(state, value, "variant"), "normal");
+    auto attributes = convertOptional<bool>(state, propertyValue(state, value, "attributes"));
     if (UNLIKELY(state.hadException()))
         return { };
-    auto featureSettings = convertOptional<String>(state, propertyValue(state, value, "featureSettings"), "normal");
-    return { WTFMove(style), WTFMove(weight), WTFMove(stretch), WTFMove(unicodeRange), WTFMove(variant), WTFMove(featureSettings) };
+    auto attributeFilter = convertOptional<Vector<String>>(state, propertyValue(state, value, "attributeFilter"));
+    return { WTFMove(childList), WTFMove(attributes), WTFMove(attributeFilter) };
 }
 
 // Functions

Modified: trunk/Source/WebCore/bindings/scripts/test/TestObj.idl (200551 => 200552)


--- trunk/Source/WebCore/bindings/scripts/test/TestObj.idl	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/bindings/scripts/test/TestObj.idl	2016-05-08 06:39:23 UTC (rev 200552)
@@ -386,9 +386,11 @@
 
 dictionary FontFaceDescriptors {
     DOMString style = "normal";
-    DOMString weight = "normal";
-    DOMString stretch = "normal";
     DOMString unicodeRange = "U+0-10FFFF";
-    DOMString variant = "normal";
-    DOMString featureSettings = "normal";
 };
+
+dictionary MutationObserverInit {
+    boolean childList = false;
+    boolean attributes;
+    sequence<DOMString> attributeFilter;
+};

Modified: trunk/Source/WebCore/dom/MutationObserver.cpp (200551 => 200552)


--- trunk/Source/WebCore/dom/MutationObserver.cpp	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/dom/MutationObserver.cpp	2016-05-08 06:39:23 UTC (rev 200552)
@@ -71,34 +71,30 @@
         && ((options & CharacterData) || !(options & CharacterDataOldValue));
 }
 
-void MutationObserver::observe(Node& node, const Dictionary& optionsDictionary, ExceptionCode& ec)
+void MutationObserver::observe(Node& node, const Init& init, ExceptionCode& ec)
 {
-    static const struct {
-        const char* name;
-        MutationObserverOptions value;
-    } booleanOptions[] = {
-        { "childList", ChildList },
-        { "subtree", Subtree },
-        { "attributeOldValue", AttributeOldValue },
-        { "characterDataOldValue", CharacterDataOldValue }
-    };
     MutationObserverOptions options = 0;
-    bool value = false;
-    for (auto& booleanOption : booleanOptions) {
-        if (optionsDictionary.get(booleanOption.name, value) && value)
-            options |= booleanOption.value;
-    }
 
+    if (init.childList)
+        options |= ChildList;
+    if (init.subtree)
+        options |= Subtree;
+    if (init.attributeOldValue.valueOr(false))
+        options |= AttributeOldValue;
+    if (init.characterDataOldValue.valueOr(false))
+        options |= CharacterDataOldValue;
+
     HashSet<AtomicString> attributeFilter;
-    if (optionsDictionary.get("attributeFilter", attributeFilter))
+    if (init.attributeFilter) {
+        for (auto& value : init.attributeFilter.value())
+            attributeFilter.add(value);
         options |= AttributeFilter;
+    }
 
-    bool attributesOptionIsSet = optionsDictionary.get("attributes", value);
-    if ((attributesOptionIsSet && value) || (!attributesOptionIsSet && (options & (AttributeFilter | AttributeOldValue))))
+    if (init.attributes ? init.attributes.value() : (options & (AttributeFilter | AttributeOldValue)))
         options |= Attributes;
 
-    bool characterDataOptionIsSet = optionsDictionary.get("characterData", value);
-    if ((characterDataOptionIsSet && value) || (!characterDataOptionIsSet && (options & CharacterDataOldValue)))
+    if (init.characterData ? init.characterData.value() : (options & CharacterDataOldValue))
         options |= CharacterData;
 
     if (!validateOptions(options)) {
@@ -124,16 +120,16 @@
         MutationObserverRegistration::unregisterAndDelete(registration);
 }
 
-void MutationObserver::observationStarted(MutationObserverRegistration* registration)
+void MutationObserver::observationStarted(MutationObserverRegistration& registration)
 {
-    ASSERT(!m_registrations.contains(registration));
-    m_registrations.add(registration);
+    ASSERT(!m_registrations.contains(&registration));
+    m_registrations.add(&registration);
 }
 
-void MutationObserver::observationEnded(MutationObserverRegistration* registration)
+void MutationObserver::observationEnded(MutationObserverRegistration& registration)
 {
-    ASSERT(m_registrations.contains(registration));
-    m_registrations.remove(registration);
+    ASSERT(m_registrations.contains(&registration));
+    m_registrations.remove(&registration);
 }
 
 typedef HashSet<RefPtr<MutationObserver>> MutationObserverSet;
@@ -154,22 +150,11 @@
 
 class MutationObserverMicrotask final : public Microtask {
     WTF_MAKE_FAST_ALLOCATED;
-public:
-    MutationObserverMicrotask()
-    {
-    }
-
-    virtual ~MutationObserverMicrotask()
-    {
-    }
-
 private:
-    Result run() override
+    Result run() final
     {
         mutationObserverCompoundMicrotaskQueuedFlag = false;
-
         MutationObserver::deliverAllMutations();
-
         return Result::Done;
     }
 };
@@ -179,9 +164,7 @@
     if (mutationObserverCompoundMicrotaskQueuedFlag)
         return;
     mutationObserverCompoundMicrotaskQueuedFlag = true;
-
-    auto microtask = std::make_unique<MutationObserverMicrotask>();
-    MicrotaskQueue::mainThreadQueue().append(WTFMove(microtask));
+    MicrotaskQueue::mainThreadQueue().append(std::make_unique<MutationObserverMicrotask>());
 }
 
 void MutationObserver::enqueueMutationRecord(Ref<MutationRecord>&& mutation)
@@ -201,7 +184,7 @@
     queueMutationObserverCompoundMicrotask();
 }
 
-HashSet<Node*> MutationObserver::getObservedNodes() const
+HashSet<Node*> MutationObserver::observedNodes() const
 {
     HashSet<Node*> observedNodes;
     for (auto* registration : m_registrations)

Modified: trunk/Source/WebCore/dom/MutationObserver.h (200551 => 200552)


--- trunk/Source/WebCore/dom/MutationObserver.h	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/dom/MutationObserver.h	2016-05-08 06:39:23 UTC (rev 200552)
@@ -31,17 +31,14 @@
 #ifndef MutationObserver_h
 #define MutationObserver_h
 
-#include <wtf/HashMap.h>
+#include <wtf/Forward.h>
 #include <wtf/HashSet.h>
-#include <wtf/PassRefPtr.h>
+#include <wtf/Optional.h>
 #include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
-#include <wtf/text/AtomicString.h>
-#include <wtf/text/AtomicStringHash.h>
+#include <wtf/Vector.h>
 
 namespace WebCore {
 
-class Dictionary;
 class MutationCallback;
 class MutationObserverRegistration;
 class MutationRecord;
@@ -77,20 +74,29 @@
 
     ~MutationObserver();
 
-    void observe(Node&, const Dictionary&, ExceptionCode&);
+    struct Init {
+        bool childList;
+        Optional<bool> attributes;
+        Optional<bool> characterData;
+        bool subtree;
+        Optional<bool> attributeOldValue;
+        Optional<bool> characterDataOldValue;
+        Optional<Vector<String>> attributeFilter;
+    };
+
+    void observe(Node&, const Init&, ExceptionCode&);
     Vector<Ref<MutationRecord>> takeRecords();
     void disconnect();
-    void observationStarted(MutationObserverRegistration*);
-    void observationEnded(MutationObserverRegistration*);
+
+    void observationStarted(MutationObserverRegistration&);
+    void observationEnded(MutationObserverRegistration&);
     void enqueueMutationRecord(Ref<MutationRecord>&&);
     void setHasTransientRegistration();
     bool canDeliver();
 
-    HashSet<Node*> getObservedNodes() const;
+    HashSet<Node*> observedNodes() const;
 
 private:
-    struct ObserverLessThan;
-
     explicit MutationObserver(Ref<MutationCallback>&&);
     void deliver();
 

Modified: trunk/Source/WebCore/dom/MutationObserver.idl (200551 => 200552)


--- trunk/Source/WebCore/dom/MutationObserver.idl	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/dom/MutationObserver.idl	2016-05-08 06:39:23 UTC (rev 200552)
@@ -33,7 +33,17 @@
     CustomIsReachable,
     ImplementationLacksVTable,
 ] interface MutationObserver {
-    [RaisesException] void observe(Node target, Dictionary options);
+    [RaisesException] void observe(Node target, MutationObserverInit options);
     sequence<MutationRecord> takeRecords();
     void disconnect();
 };
+
+dictionary MutationObserverInit {
+    boolean childList = false;
+    boolean attributes;
+    boolean characterData;
+    boolean subtree = false;
+    boolean attributeOldValue;
+    boolean characterDataOldValue;
+    sequence<DOMString> attributeFilter;
+};

Modified: trunk/Source/WebCore/dom/MutationObserverRegistration.cpp (200551 => 200552)


--- trunk/Source/WebCore/dom/MutationObserverRegistration.cpp	2016-05-08 04:57:09 UTC (rev 200551)
+++ trunk/Source/WebCore/dom/MutationObserverRegistration.cpp	2016-05-08 06:39:23 UTC (rev 200552)
@@ -43,13 +43,13 @@
     , m_options(options)
     , m_attributeFilter(attributeFilter)
 {
-    m_observer->observationStarted(this);
+    m_observer->observationStarted(*this);
 }
 
 MutationObserverRegistration::~MutationObserverRegistration()
 {
     clearTransientRegistrations();
-    m_observer->observationEnded(this);
+    m_observer->observationEnded(*this);
 }
 
 void MutationObserverRegistration::resetObservation(MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to