MessageEvent's source property should be a (DOMWindow or MessagePort)? rather than...
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Oct 2016 21:52:09 +0000 (21:52 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Oct 2016 21:52:09 +0000 (21:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163475

Reviewed by Simon Fraser.

Source/WebCore:

Start fleshing out union support, starting with MessageEvent.
- Simplify things a bit for now by requiring interface types to use RefPtr<T> as their type when
  used in sequences and unions. We should revisit this later, and see if we can use Ref<T> where
  possible, but it causes complications for dictionaries, since they want a Ref<T> uninitialized.

* bindings/generic/IDLTypes.h:
Switch IDLInterface to use RefPtr<T> as its implementation type.

* bindings/js/JSDOMConvert.h:
(WebCore::Detail::VariadicConverterBase::convert):
- Remove isJSDOMWrapperType() optimization. It was not correct, due to not being able to detect window
  and window shell, and not always an optimization, e.g. in the case of a single interface.
- Switch from JSC::jsDynamicCast<WrapperType*>() to WrapperType::toWrapped() which can be faster and
  handles window and window shell correctly.
- Also fix an issue where we would wrongly assert that one interface had to match.

* bindings/js/JSDOMWrapper.h:
(WebCore::isJSDOMWrapperType): Deleted.
Remove unused predicate.

* bindings/scripts/IDLParser.pm:
(parseType):
Add missing support for nullable unions.

* bindings/scripts/test/JS/JSTestObj.cpp:
* bindings/scripts/test/TestObj.idl:
Add new tests for unions (both non-null and nullable) in dictionaries.

* dom/ContainerNode.cpp:
(WebCore::ContainerNode::append):
(WebCore::ContainerNode::prepend):
* dom/ContainerNode.h:
* dom/Node.cpp:
(WebCore::nodeSetPreTransformedFromNodeOrStringVector):
(WebCore::Node::convertNodesOrStringsIntoNode):
(WebCore::Node::before):
(WebCore::Node::after):
(WebCore::Node::replaceWith):
* dom/Node.h:
Add using declaration for NodeOrString and change it to use RefPtr<Node>.

* bindings/js/JSMessageEventCustom.cpp:
(WebCore::handleInitMessageEvent):
* dom/MessageEvent.cpp:
(WebCore::MessageEvent::MessageEvent):
(WebCore::MessageEvent::create):
(WebCore::MessageEvent::initMessageEvent):
(WebCore::MessageEvent::source):
(WebCore::isValidSource): Deleted.
* dom/MessageEvent.h:
* dom/MessageEvent.idl:
* page/DOMWindow.cpp:
(WebCore::PostMessageTimer::event):
Change MessageEvent's source to be a std::experimental::variant<RefPtr<DOMWindow>, RefPtr<MessagePort>>.
For now, we only enforce this on setting, and leave the getter a EventTarget?, but that should not be
observable, and will rectified in subsequent patches.

Source/WTF:

* wtf/Variant.h:
Add missing return statement that was tripping up some compilers.

LayoutTests:

* fast/dom/message-port-deleted-by-accessor.html:
Switch source parameter to null to avoid accidental type error.

* fast/events/constructors/message-event-constructor-expected.txt:
* fast/events/constructors/message-event-constructor.html:
Update test expect a thrown type error, as is now expected, for non-window or MessagePort EventTargets.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207381 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/message-port-deleted-by-accessor.html
LayoutTests/fast/events/constructors/message-event-constructor-expected.txt
LayoutTests/fast/events/constructors/message-event-constructor.html
Source/WTF/ChangeLog
Source/WTF/wtf/Variant.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/generic/IDLTypes.h
Source/WebCore/bindings/js/JSDOMConvert.h
Source/WebCore/bindings/js/JSDOMWrapper.h
Source/WebCore/bindings/js/JSMessageEventCustom.cpp
Source/WebCore/bindings/scripts/IDLParser.pm
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/TestObj.idl
Source/WebCore/dom/ContainerNode.cpp
Source/WebCore/dom/ContainerNode.h
Source/WebCore/dom/MessageEvent.cpp
Source/WebCore/dom/MessageEvent.h
Source/WebCore/dom/MessageEvent.idl
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/page/DOMWindow.cpp

index 0656740..8b69547 100644 (file)
@@ -1,3 +1,17 @@
+2016-10-15  Sam Weinig  <sam@webkit.org>
+
+        MessageEvent's source property should be a (DOMWindow or MessagePort)? rather than a EventTarget?
+        https://bugs.webkit.org/show_bug.cgi?id=163475
+
+        Reviewed by Simon Fraser.
+
+        * fast/dom/message-port-deleted-by-accessor.html:
+        Switch source parameter to null to avoid accidental type error.
+
+        * fast/events/constructors/message-event-constructor-expected.txt:
+        * fast/events/constructors/message-event-constructor.html:
+        Update test expect a thrown type error, as is now expected, for non-window or MessagePort EventTargets.
+
 2016-10-15  Antoine Quint  <graouts@apple.com>
 
         [Modern Media Controls] macOS inline controls
index 01d2e7c..3a8ffe9 100644 (file)
@@ -9,10 +9,10 @@ window.onload = function()
     channel = new MessageChannel;
     event = document.createEvent("MessageEvent");
 
-    event.initMessageEvent(0, 0, 0, 0, 0, 0, 0, [channel.port1, channel.port2]);
+    event.initMessageEvent(0, 0, 0, 0, 0, 0, null, [channel.port1, channel.port2]);
 
     Array.prototype.__defineSetter__(0, function() {
-        event.initMessageEvent(0, 0, 0, 0, 0, 0, 0, [ ]);
+        event.initMessageEvent(0, 0, 0, 0, 0, 0, null, [ ]);
     });
 
     event.ports;
index 257c339..e442f8a 100644 (file)
@@ -62,8 +62,8 @@ PASS new MessageEvent('eventType', { source: window }).source is window
 PASS new MessageEvent('eventType', { source: this }).source is this
 PASS new MessageEvent('eventType', { ports: [channel.port1], source: channel.port1 }).source is channel.port1
 PASS new MessageEvent('eventType', { source: test_object }).source threw exception TypeError: Type error.
-PASS new MessageEvent('eventType', { source: document }).source is null
-PASS new MessageEvent('eventType', { source: document.body }).source is null
+PASS new MessageEvent('eventType', { source: document }).source threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { source: document.body }).source threw exception TypeError: Type error.
 PASS new MessageEvent('eventType', { source: undefined }).source is null
 PASS new MessageEvent('eventType', { source: null }).source is null
 PASS new MessageEvent('eventType', { source: false }).source threw exception TypeError: Type error.
index e7107fb..d7e823d 100644 (file)
@@ -77,8 +77,8 @@ shouldBe("new MessageEvent('eventType', { ports: [channel.port1], source: channe
 
 // Unacceptable source objects (not a Window or a MessagePort).
 shouldThrowErrorName("new MessageEvent('eventType', { source: test_object }).source", "TypeError");
-shouldBe("new MessageEvent('eventType', { source: document }).source", "null");
-shouldBe("new MessageEvent('eventType', { source: document.body }).source", "null");
+shouldThrowErrorName("new MessageEvent('eventType', { source: document }).source", "TypeError");
+shouldThrowErrorName("new MessageEvent('eventType', { source: document.body }).source", "TypeError");
 shouldBe("new MessageEvent('eventType', { source: undefined }).source", "null");
 shouldBe("new MessageEvent('eventType', { source: null }).source", "null");
 shouldThrowErrorName("new MessageEvent('eventType', { source: false }).source", "TypeError");
index df9ef70..e76bbe0 100644 (file)
@@ -1,3 +1,13 @@
+2016-10-15  Sam Weinig  <sam@webkit.org>
+
+        MessageEvent's source property should be a (DOMWindow or MessagePort)? rather than a EventTarget?
+        https://bugs.webkit.org/show_bug.cgi?id=163475
+
+        Reviewed by Simon Fraser.
+
+        * wtf/Variant.h:
+        Add missing return statement that was tripping up some compilers.
+
 2016-10-12  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r207225.
index 102e656..b93a2d0 100644 (file)
@@ -1944,7 +1944,7 @@ struct __visit_helper2<-1,_VariantIndex,_Indices...>{
     template<typename _Visitor,typename ... _Variants>
     static constexpr typename __multi_visitor_return_type<_Visitor,_Variants...>::__type
     __visit(_Visitor&,_Variants&& ...){
-        __throw_bad_variant_access<typename __multi_visitor_return_type<_Visitor,_Variants...>::__type>("Visiting of empty variant");
+        return __throw_bad_variant_access<typename __multi_visitor_return_type<_Visitor,_Variants...>::__type>("Visiting of empty variant");
     }
 };
 
index 52f4c5b..c692480 100644 (file)
@@ -1,3 +1,67 @@
+2016-10-14  Sam Weinig  <sam@webkit.org>
+
+        MessageEvent's source property should be a (DOMWindow or MessagePort)? rather than a EventTarget?
+        https://bugs.webkit.org/show_bug.cgi?id=163475
+
+        Reviewed by Simon Fraser.
+
+        Start fleshing out union support, starting with MessageEvent.
+        - Simplify things a bit for now by requiring interface types to use RefPtr<T> as their type when
+          used in sequences and unions. We should revisit this later, and see if we can use Ref<T> where
+          possible, but it causes complications for dictionaries, since they want a Ref<T> uninitialized.
+
+        * bindings/generic/IDLTypes.h:
+        Switch IDLInterface to use RefPtr<T> as its implementation type.
+
+        * bindings/js/JSDOMConvert.h:
+        (WebCore::Detail::VariadicConverterBase::convert):
+        - Remove isJSDOMWrapperType() optimization. It was not correct, due to not being able to detect window
+          and window shell, and not always an optimization, e.g. in the case of a single interface.
+        - Switch from JSC::jsDynamicCast<WrapperType*>() to WrapperType::toWrapped() which can be faster and
+          handles window and window shell correctly.
+        - Also fix an issue where we would wrongly assert that one interface had to match.
+
+        * bindings/js/JSDOMWrapper.h:
+        (WebCore::isJSDOMWrapperType): Deleted.
+        Remove unused predicate.
+
+        * bindings/scripts/IDLParser.pm:
+        (parseType):
+        Add missing support for nullable unions.
+
+        * bindings/scripts/test/JS/JSTestObj.cpp:
+        * bindings/scripts/test/TestObj.idl:
+        Add new tests for unions (both non-null and nullable) in dictionaries.
+        * dom/ContainerNode.cpp:
+        (WebCore::ContainerNode::append):
+        (WebCore::ContainerNode::prepend):
+        * dom/ContainerNode.h:
+        * dom/Node.cpp:
+        (WebCore::nodeSetPreTransformedFromNodeOrStringVector):
+        (WebCore::Node::convertNodesOrStringsIntoNode):
+        (WebCore::Node::before):
+        (WebCore::Node::after):
+        (WebCore::Node::replaceWith):
+        * dom/Node.h:
+        Add using declaration for NodeOrString and change it to use RefPtr<Node>.
+
+        * bindings/js/JSMessageEventCustom.cpp:
+        (WebCore::handleInitMessageEvent):
+        * dom/MessageEvent.cpp:
+        (WebCore::MessageEvent::MessageEvent):
+        (WebCore::MessageEvent::create):
+        (WebCore::MessageEvent::initMessageEvent):
+        (WebCore::MessageEvent::source):
+        (WebCore::isValidSource): Deleted.
+        * dom/MessageEvent.h:
+        * dom/MessageEvent.idl:
+        * page/DOMWindow.cpp:
+        (WebCore::PostMessageTimer::event):
+        Change MessageEvent's source to be a std::experimental::variant<RefPtr<DOMWindow>, RefPtr<MessagePort>>.
+        For now, we only enforce this on setting, and leave the getter a EventTarget?, but that should not be
+        observable, and will rectified in subsequent patches.
+
 2016-10-15  Chris Dumez  <cdumez@apple.com>
 
         Add support for reportValidity() on form and form control elements
index 39d56c7..be8826e 100644 (file)
@@ -84,9 +84,9 @@ struct IDLUSVString : IDLString { };
 
 struct IDLObject : IDLUnsupportedType { };
 
-template<typename T> struct IDLInterface : IDLType<std::reference_wrapper<T>> {
+template<typename T> struct IDLInterface : IDLType<RefPtr<T>> {
     using RawType = T;
-    using NullableType = T*;
+    using NullableType = RefPtr<T>;
 };
 
 template<typename T> struct IDLDictionary : IDLType<T> { };
index 20ddb89..2a47288 100644 (file)
@@ -515,25 +515,23 @@ struct Converter<IDLUnion<T...>> : DefaultConverter<IDLUnion<T...>>
         //     2. If types includes object, then return the IDL value that is a reference to the object V.
         //         (FIXME: Add support for object and step 4.2)
         if (brigand::any<TypeList, IsIDLInterface<brigand::_1>>::value) {
-            if (isJSDOMWrapperType(value)) {
-                Optional<ReturnType> returnValue;
-                brigand::for_each<InterfaceTypeList>([&](auto&& type) {
-                    if (returnValue)
-                        return;
-                    
-                    using ImplementationType = typename WTF::RemoveCVAndReference<decltype(type)>::type::type::RawType;
-                    using WrapperType = typename JSDOMWrapperConverterTraits<ImplementationType>::WrapperClass;
-
-                    auto* castedValue = JSC::jsDynamicCast<WrapperType*>(value);
-                    if (!castedValue)
-                        return;
-                    
-                    returnValue = ReturnType(castedValue->wrapped());
-                });
-                ASSERT(returnValue);
+            Optional<ReturnType> returnValue;
+            brigand::for_each<InterfaceTypeList>([&](auto&& type) {
+                if (returnValue)
+                    return;
+                
+                using ImplementationType = typename WTF::RemoveCVAndReference<decltype(type)>::type::type::RawType;
+                using WrapperType = typename JSDOMWrapperConverterTraits<ImplementationType>::WrapperClass;
+
+                auto* castedValue = WrapperType::toWrapped(value);
+                if (!castedValue)
+                    return;
+                
+                returnValue = ReturnType(castedValue);
+            });
 
+            if (returnValue)
                 return WTFMove(returnValue.value());
-            }
         }
         
         // FIXME: Add support for steps 5 - 12.
@@ -592,13 +590,13 @@ namespace Detail {
             auto result = Converter<IDLType>::convert(state, value);
             RETURN_IF_EXCEPTION(scope, Nullopt);
 
-            return result;
+            return WTFMove(result);
         }
     };
 
     template<typename T>
     struct VariadicConverterBase<IDLInterface<T>> {
-        using Item = typename IDLInterface<T>::ImplementationType;
+        using Item = std::reference_wrapper<T>;
 
         static Optional<Item> convert(JSC::ExecState& state, JSC::JSValue value)
         {
index 6d01af5..319c775 100644 (file)
@@ -86,13 +86,6 @@ private:
     Ref<ImplementationClass> m_wrapped;
 };
 
-ALWAYS_INLINE bool isJSDOMWrapperType(JSC::JSValue value)
-{
-    if (UNLIKELY(!value.isCell()))
-        return false;
-    return value.asCell()->type() >= JSDOMWrapperType;
-}
-
 template<typename ImplementationClass> struct JSDOMWrapperConverterTraits;
 
 template<typename JSClass, typename Enable = void>
index 856d769..b025081 100644 (file)
@@ -35,6 +35,7 @@
 #include "JSDOMBinding.h"
 #include "JSDOMWindow.h"
 #include "JSEventTarget.h"
+#include "JSMessagePort.h"
 #include "JSMessagePortCustom.h"
 #include "MessageEvent.h"
 #include <runtime/JSArray.h>
@@ -112,7 +113,7 @@ static JSC::JSValue handleInitMessageEvent(JSMessageEvent* jsEvent, JSC::ExecSta
     bool cancelableArg = state.argument(2).toBoolean(&state);
     const String originArg = valueToUSVString(&state, state.argument(4));
     const String lastEventIdArg = state.argument(5).toString(&state)->value(&state);
-    DOMWindow* sourceArg = JSDOMWindow::toWrapped(state.argument(6));
+    auto sourceArg = convert<IDLNullable<IDLUnion<IDLInterface<DOMWindow>, IDLInterface<MessagePort>>>>(state, state.argument(6));
     std::unique_ptr<MessagePortArray> messagePorts;
     std::unique_ptr<ArrayBufferArray> arrayBuffers;
     if (!state.argument(7).isUndefinedOrNull()) {
@@ -125,7 +126,7 @@ static JSC::JSValue handleInitMessageEvent(JSMessageEvent* jsEvent, JSC::ExecSta
     RETURN_IF_EXCEPTION(scope, JSValue());
 
     MessageEvent& event = jsEvent->wrapped();
-    event.initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, sourceArg, WTFMove(messagePorts));
+    event.initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, WTFMove(sourceArg), WTFMove(messagePorts));
     jsEvent->m_data.set(vm, jsEvent, dataArg.jsValue());
     return jsUndefined();
 }
index e7b07e1..cd96839 100644 (file)
@@ -1951,7 +1951,9 @@ sub parseType
     my $self = shift;
     my $next = $self->nextToken();
     if ($next->value() eq "(") {
-        return $self->parseUnionType();
+        my $unionType = $self->parseUnionType();
+        $unionType->isNullable($self->parseNull());
+        return $unionType;
     }
     if ($next->type() == IdentifierToken || $next->value() =~ /$nextType_1/) {
         return $self->parseSingleType();
index cdf7cbc..612a9ba 100644 (file)
@@ -566,6 +566,12 @@ template<> Optional<TestObj::Dictionary> convertDictionary<TestObj::Dictionary>(
         RETURN_IF_EXCEPTION(throwScope, Nullopt);
     } else
         result.nullableStringWithDefault = String();
+    JSValue nullableUnionMemberValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "nullableUnionMember"));
+    if (!nullableUnionMemberValue.isUndefined()) {
+        result.nullableUnionMember = convert<IDLNullable<IDLUnion<IDLLong, IDLInterface<Node>>>>(state, nullableUnionMemberValue);
+        RETURN_IF_EXCEPTION(throwScope, Nullopt);
+    } else
+        result.nullableUnionMember = Nullopt;
     JSValue restrictedDoubleValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "restrictedDouble"));
     if (!restrictedDoubleValue.isUndefined()) {
         result.restrictedDouble = convert<IDLDouble>(state, restrictedDoubleValue);
@@ -625,6 +631,11 @@ template<> Optional<TestObj::Dictionary> convertDictionary<TestObj::Dictionary>(
         result.stringWithoutDefault = convert<IDLDOMString>(state, stringWithoutDefaultValue);
         RETURN_IF_EXCEPTION(throwScope, Nullopt);
     }
+    JSValue unionMemberValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "unionMember"));
+    if (!unionMemberValue.isUndefined()) {
+        result.unionMember = convert<IDLUnion<IDLLong, IDLInterface<Node>>>(state, unionMemberValue);
+        RETURN_IF_EXCEPTION(throwScope, Nullopt);
+    }
     JSValue unrestrictedDoubleValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "unrestrictedDouble"));
     if (!unrestrictedDoubleValue.isUndefined()) {
         result.unrestrictedDouble = convert<IDLUnrestrictedDouble>(state, unrestrictedDoubleValue);
index 8c4f4fa..aa6adf8 100644 (file)
@@ -458,6 +458,8 @@ dictionary TestDictionary {
     any anyValueWithNullDefault = null;
     AnyTypedef anyTypedefValue;
     TestDictionaryThatShouldTolerateNull dictionaryMember;
+    (long or Node) unionMember;
+    (long or Node)? nullableUnionMember = null;
 };
 
 dictionary TestDictionaryThatShouldNotTolerateNull {
index 653b50f..dfd38ed 100644 (file)
@@ -877,7 +877,7 @@ unsigned ContainerNode::childElementCount() const
     return std::distance(children.begin(), children.end());
 }
 
-void ContainerNode::append(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
+void ContainerNode::append(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
 {
     RefPtr<Node> node = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector), ec);
     if (ec || !node)
@@ -886,7 +886,7 @@ void ContainerNode::append(Vector<std::experimental::variant<std::reference_wrap
     appendChild(*node, ec);
 }
 
-void ContainerNode::prepend(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
+void ContainerNode::prepend(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
 {
     RefPtr<Node> node = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector), ec);
     if (ec || !node)
index 46c432e..a65f64a 100644 (file)
@@ -100,8 +100,8 @@ public:
     WEBCORE_EXPORT Element* firstElementChild() const;
     WEBCORE_EXPORT Element* lastElementChild() const;
     WEBCORE_EXPORT unsigned childElementCount() const;
-    void append(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&&, ExceptionCode&);
-    void prepend(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&&, ExceptionCode&);
+    void append(Vector<NodeOrString>&&, ExceptionCode&);
+    void prepend(Vector<NodeOrString>&&, ExceptionCode&);
 
     bool ensurePreInsertionValidity(Node& newChild, Node* refChild, ExceptionCode&);
 
index 4c834ef..6d32ca0 100644 (file)
@@ -29,7 +29,6 @@
 #include "MessageEvent.h"
 
 #include "Blob.h"
-#include "DOMWindow.h"
 #include "EventNames.h"
 #include <runtime/JSCInlines.h>
 
@@ -37,37 +36,31 @@ namespace WebCore {
 
 using namespace JSC;
 
-static inline bool isValidSource(EventTarget* source)
-{
-    return !source || source->toDOMWindow() || source->isMessagePort();
-}
-
 inline MessageEvent::MessageEvent()
     : m_dataType(DataTypeScriptValue)
 {
 }
 
-inline MessageEvent::MessageEvent(ExecState& state, const AtomicString& type, const Init& initializer, IsTrusted isTrusted)
+inline MessageEvent::MessageEvent(ExecState& state, const AtomicString& type, Init& initializer, IsTrusted isTrusted)
     : Event(type, initializer, isTrusted)
     , m_dataType(DataTypeScriptValue)
     , m_dataAsScriptValue(state.vm(), initializer.data)
     , m_origin(initializer.origin)
     , m_lastEventId(initializer.lastEventId)
-    , m_source(isValidSource(initializer.source.get()) ? initializer.source : nullptr)
+    , m_source(WTFMove(initializer.source))
     , m_ports(std::make_unique<MessagePortArray>(initializer.ports))
 {
 }
 
-inline MessageEvent::MessageEvent(RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId, EventTarget* source, std::unique_ptr<MessagePortArray> ports)
+inline MessageEvent::MessageEvent(RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId, Optional<MessageEventSource>&& source, std::unique_ptr<MessagePortArray> ports)
     : Event(eventNames().messageEvent, false, false)
     , m_dataType(DataTypeSerializedScriptValue)
     , m_dataAsSerializedScriptValue(WTFMove(data))
     , m_origin(origin)
     , m_lastEventId(lastEventId)
-    , m_source(source)
+    , m_source(WTFMove(source))
     , m_ports(WTFMove(ports))
 {
-    ASSERT(isValidSource(source));
 }
 
 inline MessageEvent::MessageEvent(const AtomicString& type, RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId)
@@ -103,9 +96,9 @@ inline MessageEvent::MessageEvent(Ref<ArrayBuffer>&& data, const String& origin)
 {
 }
 
-Ref<MessageEvent> MessageEvent::create(std::unique_ptr<MessagePortArray> ports, RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId, EventTarget* source)
+Ref<MessageEvent> MessageEvent::create(std::unique_ptr<MessagePortArray> ports, RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId, Optional<MessageEventSource>&& source)
 {
-    return adoptRef(*new MessageEvent(WTFMove(data), origin, lastEventId, source, WTFMove(ports)));
+    return adoptRef(*new MessageEvent(WTFMove(data), origin, lastEventId, WTFMove(source), WTFMove(ports)));
 }
 
 Ref<MessageEvent> MessageEvent::create(const AtomicString& type, RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId)
@@ -133,7 +126,7 @@ Ref<MessageEvent> MessageEvent::createForBindings()
     return adoptRef(*new MessageEvent);
 }
 
-Ref<MessageEvent> MessageEvent::create(ExecState& state, const AtomicString& type, const Init& initializer, IsTrusted isTrusted)
+Ref<MessageEvent> MessageEvent::create(ExecState& state, const AtomicString& type, Init& initializer, IsTrusted isTrusted)
 {
     return adoptRef(*new MessageEvent(state, type, initializer, isTrusted));
 }
@@ -142,7 +135,7 @@ MessageEvent::~MessageEvent()
 {
 }
 
-void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const Deprecated::ScriptValue& data, const String& origin, const String& lastEventId, DOMWindow* source, std::unique_ptr<MessagePortArray> ports)
+void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const Deprecated::ScriptValue& data, const String& origin, const String& lastEventId, Optional<MessageEventSource>&& source, std::unique_ptr<MessagePortArray> ports)
 {
     if (dispatched())
         return;
@@ -155,11 +148,11 @@ void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bo
     m_triedToSerialize = false;
     m_origin = origin;
     m_lastEventId = lastEventId;
-    m_source = source;
+    m_source = WTFMove(source);
     m_ports = WTFMove(ports);
 }
 
-void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, std::unique_ptr<MessagePortArray> ports)
+void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, Optional<MessageEventSource>&& source, std::unique_ptr<MessagePortArray> ports)
 {
     if (dispatched())
         return;
@@ -170,10 +163,23 @@ void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bo
     m_dataAsSerializedScriptValue = data;
     m_origin = origin;
     m_lastEventId = lastEventId;
-    m_source = source;
+    m_source = WTFMove(source);
     m_ports = WTFMove(ports);
 }
     
+EventTarget* MessageEvent::source() const
+{
+    if (!m_source)
+        return nullptr;
+
+    auto visitor = WTF::makeVisitor(
+        [](const RefPtr<DOMWindow>& window) -> EventTarget* { return const_cast<EventTarget*>(static_cast<const EventTarget*>(window.get())); },
+        [](const RefPtr<MessagePort>& messagePort) -> EventTarget* { return const_cast<EventTarget*>(static_cast<const EventTarget*>(messagePort.get())); }
+    );
+
+    return std::experimental::visit(visitor, m_source.value());
+}
+
 RefPtr<SerializedScriptValue> MessageEvent::trySerializeData(ExecState* exec)
 {
     ASSERT(!m_dataAsScriptValue.hasNoValue());
index 0c747cf..d0350c3 100644 (file)
 
 #pragma once
 
+#include "DOMWindow.h"
 #include "Event.h"
 #include "MessagePort.h"
 #include "SerializedScriptValue.h"
 #include <bindings/ScriptValue.h>
+#include <wtf/Variant.h>
 
 namespace WebCore {
 
 class Blob;
 
+using MessageEventSource = std::experimental::variant<RefPtr<DOMWindow>, RefPtr<MessagePort>>;
+
 class MessageEvent final : public Event {
 public:
-    static Ref<MessageEvent> create(std::unique_ptr<MessagePortArray>, RefPtr<SerializedScriptValue>&&, const String& origin = { }, const String& lastEventId = { }, EventTarget* source = nullptr);
+    static Ref<MessageEvent> create(std::unique_ptr<MessagePortArray>, RefPtr<SerializedScriptValue>&&, const String& origin = { }, const String& lastEventId = { }, Optional<MessageEventSource>&& source = Nullopt);
     static Ref<MessageEvent> create(const AtomicString& type, RefPtr<SerializedScriptValue>&&, const String& origin, const String& lastEventId);
     static Ref<MessageEvent> create(const String& data, const String& origin = { });
     static Ref<MessageEvent> create(Ref<Blob>&& data, const String& origin);
@@ -49,19 +53,19 @@ public:
         JSC::JSValue data;
         String origin;
         String lastEventId;
-        RefPtr<EventTarget> source;
+        Optional<MessageEventSource> source;
         MessagePortArray ports;
     };
-    static Ref<MessageEvent> create(JSC::ExecState&, const AtomicString& type, const Init&, IsTrusted = IsTrusted::No);
+    static Ref<MessageEvent> create(JSC::ExecState&, const AtomicString& type, Init&, IsTrusted = IsTrusted::No);
 
     virtual ~MessageEvent();
 
-    void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const Deprecated::ScriptValue& data, const String& origin, const String& lastEventId, DOMWindow* source, std::unique_ptr<MessagePortArray>);
-    void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, std::unique_ptr<MessagePortArray>);
+    void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const Deprecated::ScriptValue& data, const String& origin, const String& lastEventId, Optional<MessageEventSource>&& source, std::unique_ptr<MessagePortArray>);
+    void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, Optional<MessageEventSource>&& source, std::unique_ptr<MessagePortArray>);
 
     const String& origin() const { return m_origin; }
     const String& lastEventId() const { return m_lastEventId; }
-    EventTarget* source() const { return m_source.get(); }
+    EventTarget* source() const;
     MessagePortArray ports() const { return m_ports ? *m_ports : MessagePortArray(); }
 
     // FIXME: Remove this when we have custom ObjC binding support.
@@ -87,8 +91,8 @@ public:
     
 private:
     MessageEvent();
-    MessageEvent(JSC::ExecState&, const AtomicString&, const Init&, IsTrusted);
-    MessageEvent(RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId, EventTarget* source, std::unique_ptr<MessagePortArray>);
+    MessageEvent(JSC::ExecState&, const AtomicString&, Init&, IsTrusted);
+    MessageEvent(RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId, Optional<MessageEventSource>&& source, std::unique_ptr<MessagePortArray>);
     MessageEvent(const AtomicString& type, RefPtr<SerializedScriptValue>&& data, const String& origin, const String& lastEventId);
     MessageEvent(const String& data, const String& origin);
     MessageEvent(Ref<Blob>&& data, const String& origin);
@@ -103,7 +107,7 @@ private:
     RefPtr<ArrayBuffer> m_dataAsArrayBuffer;
     String m_origin;
     String m_lastEventId;
-    RefPtr<EventTarget> m_source;
+    Optional<MessageEventSource> m_source;
     std::unique_ptr<MessagePortArray> m_ports;
 };
 
index 0f77405..145e4e5 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2007 Henry Mason <hmason@mac.com>
  * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 ] interface MessageEvent : Event {
     readonly attribute USVString origin;
     readonly attribute DOMString lastEventId;
-    readonly attribute EventTarget? source; // May be a DOMWindow or a MessagePort.
+    readonly attribute EventTarget? source;
     [CachedAttribute, CustomGetter] readonly attribute any data;
     readonly attribute FrozenArray<MessagePort> ports;
 
     [Custom] void initMessageEvent(optional DOMString typeArg, optional boolean canBubbleArg, optional boolean cancelableArg,
-        optional any dataArg, optional USVString originArg, optional DOMString lastEventIdArg, optional DOMWindow sourceArg,
+        optional any dataArg, optional USVString originArg, optional DOMString lastEventIdArg, optional (DOMWindow or MessagePort)? sourceArg,
         optional Array messagePorts);
 
     [Custom] void webkitInitMessageEvent(optional DOMString typeArg, optional boolean canBubbleArg, optional boolean cancelableArg,
-        optional any dataArg, optional USVString originArg, optional DOMString lastEventIdArg, optional DOMWindow sourceArg,
+        optional any dataArg, optional USVString originArg, optional DOMString lastEventIdArg, optional (DOMWindow or MessagePort)? sourceArg,
         optional Array transferables);
 };
 
@@ -49,6 +50,6 @@ dictionary MessageEventInit : EventInit {
       any data = null;
       USVString origin = "";
       DOMString lastEventId = "";
-      EventTarget? source = null;
+      (DOMWindow or MessagePort)? source = null;
       sequence<MessagePort> ports = [];
 };
index 148012b..7fd57e5 100644 (file)
@@ -435,12 +435,12 @@ bool Node::appendChild(Node& newChild, ExceptionCode& ec)
     return downcast<ContainerNode>(*this).appendChild(newChild, ec);
 }
 
-static HashSet<RefPtr<Node>> nodeSetPreTransformedFromNodeOrStringVector(const Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>& vector)
+static HashSet<RefPtr<Node>> nodeSetPreTransformedFromNodeOrStringVector(const Vector<NodeOrString>& vector)
 {
     HashSet<RefPtr<Node>> nodeSet;
 
     auto visitor = WTF::makeVisitor(
-        [&](const std::reference_wrapper<Node>& node) { nodeSet.add(const_cast<Node*>(&node.get())); },
+        [&](const RefPtr<Node>& node) { nodeSet.add(const_cast<Node*>(node.get())); },
         [](const String&) { }
     );
 
@@ -468,7 +468,7 @@ static RefPtr<Node> firstFollowingSiblingNotInNodeSet(Node& context, const HashS
     return nullptr;
 }
 
-RefPtr<Node> Node::convertNodesOrStringsIntoNode(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
+RefPtr<Node> Node::convertNodesOrStringsIntoNode(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
 {
     if (nodeOrStringVector.isEmpty())
         return nullptr;
@@ -477,7 +477,7 @@ RefPtr<Node> Node::convertNodesOrStringsIntoNode(Vector<std::experimental::varia
     nodes.reserveInitialCapacity(nodeOrStringVector.size());
 
     auto visitor = WTF::makeVisitor(
-        [&](std::reference_wrapper<Node>& node) { nodes.uncheckedAppend(node); },
+        [&](RefPtr<Node>& node) { nodes.uncheckedAppend(*node.get()); },
         [&](String& string) { nodes.uncheckedAppend(Text::create(document(), string)); }
     );
 
@@ -495,7 +495,7 @@ RefPtr<Node> Node::convertNodesOrStringsIntoNode(Vector<std::experimental::varia
     return WTFMove(nodeToReturn);
 }
 
-void Node::before(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
+void Node::before(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
 {
     RefPtr<ContainerNode> parent = parentNode();
     if (!parent)
@@ -516,7 +516,7 @@ void Node::before(Vector<std::experimental::variant<std::reference_wrapper<Node>
     parent->insertBefore(*node, viablePreviousSibling.get(), ec);
 }
 
-void Node::after(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
+void Node::after(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
 {
     RefPtr<ContainerNode> parent = parentNode();
     if (!parent)
@@ -532,7 +532,7 @@ void Node::after(Vector<std::experimental::variant<std::reference_wrapper<Node>,
     parent->insertBefore(*node, viableNextSibling.get(), ec);
 }
 
-void Node::replaceWith(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
+void Node::replaceWith(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
 {
     RefPtr<ContainerNode> parent = parentNode();
     if (!parent)
index 88714e1..9ffa2c4 100644 (file)
@@ -63,6 +63,8 @@ class UIRequestEvent;
 
 const int nodeStyleChangeShift = 14;
 
+using NodeOrString = std::experimental::variant<RefPtr<Node>, String>;
+
 // SyntheticStyleChange means that we need to go through the entire style change logic even though
 // no style property has actually changed. It is used to restructure the tree when, for instance,
 // RenderLayers are created or destroyed due to animation changes.
@@ -202,9 +204,9 @@ public:
     WEBCORE_EXPORT Element* nextElementSibling() const;
 
     // From the ChildNode - https://dom.spec.whatwg.org/#childnode
-    void before(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&&, ExceptionCode&);
-    void after(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&&, ExceptionCode&);
-    void replaceWith(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&&, ExceptionCode&);
+    void before(Vector<NodeOrString>&&, ExceptionCode&);
+    void after(Vector<NodeOrString>&&, ExceptionCode&);
+    void replaceWith(Vector<NodeOrString>&&, ExceptionCode&);
     WEBCORE_EXPORT void remove(ExceptionCode&);
 
     // Other methods (not part of DOM)
@@ -660,7 +662,7 @@ protected:
     void setStyleChange(StyleChangeType changeType) { m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType; }
     void updateAncestorsForStyleRecalc();
 
-    RefPtr<Node> convertNodesOrStringsIntoNode(Vector<std::experimental::variant<std::reference_wrapper<Node>, String>>&&, ExceptionCode&);
+    RefPtr<Node> convertNodesOrStringsIntoNode(Vector<NodeOrString>&&, ExceptionCode&);
 
 private:
     virtual PseudoId customPseudoId() const
index 243e0d8..eb82e72 100644 (file)
@@ -160,7 +160,7 @@ public:
 
     Ref<MessageEvent> event(ScriptExecutionContext& context)
     {
-        return MessageEvent::create(MessagePort::entanglePorts(context, WTFMove(m_channels)), WTFMove(m_message), m_origin, { }, m_source.ptr());
+        return MessageEvent::create(MessagePort::entanglePorts(context, WTFMove(m_channels)), WTFMove(m_message), m_origin, { }, MessageEventSource(RefPtr<DOMWindow>(WTFMove(m_source))));
     }
 
     SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }