diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2020-02-26 04:40:09 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2020-02-26 04:41:40 +0300 |
commit | 8d9e85b5baf784727ecefaecda68716e03ec884e (patch) | |
tree | 37785846b69c9f0b8361175c413e07dc3f542a2f | |
parent | cd875b317ba9ef63f946d2a07b7e67c1e05f93ac (diff) |
Import QtWebKit commit bf94215feb57ddf9ce364bc6953eec8cd1387c3d
Change-Id: Ifc9d2e79e39fbfdd21bd40ede609c7696d2efe62
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
-rw-r--r-- | Source/JavaScriptCore/heap/WeakInlines.h | 11 | ||||
-rw-r--r-- | Source/WebCore/bindings/js/JSCustomEventCustom.cpp | 13 | ||||
-rw-r--r-- | Source/WebCore/bindings/js/JSValueInWrappedObject.h | 137 | ||||
-rw-r--r-- | Source/WebCore/dom/CustomEvent.cpp | 4 | ||||
-rw-r--r-- | Source/WebCore/dom/CustomEvent.h | 7 | ||||
-rw-r--r-- | Source/WebCore/dom/CustomEvent.idl | 1 |
6 files changed, 160 insertions, 13 deletions
diff --git a/Source/JavaScriptCore/heap/WeakInlines.h b/Source/JavaScriptCore/heap/WeakInlines.h index 4653a9f8c..d5bd2ea2f 100644 --- a/Source/JavaScriptCore/heap/WeakInlines.h +++ b/Source/JavaScriptCore/heap/WeakInlines.h @@ -73,20 +73,23 @@ template<typename T> inline auto Weak<T>::operator=(Weak&& other) -> Weak& template<typename T> inline T* Weak<T>::operator->() const { ASSERT(m_impl && m_impl->state() == WeakImpl::Live); - return jsCast<T*>(m_impl->jsValue().asCell()); + // We can't use jsCast here since we could be called in a finalizer. + return static_cast<T*>(m_impl->jsValue().asCell()); } template<typename T> inline T& Weak<T>::operator*() const { ASSERT(m_impl && m_impl->state() == WeakImpl::Live); - return *jsCast<T*>(m_impl->jsValue().asCell()); + // We can't use jsCast here since we could be called in a finalizer. + return *static_cast<T*>(m_impl->jsValue().asCell()); } template<typename T> inline T* Weak<T>::get() const { if (!m_impl || m_impl->state() != WeakImpl::Live) - return 0; - return jsCast<T*>(m_impl->jsValue().asCell()); + return nullptr; + // We can't use jsCast here since we could be called in a finalizer. + return static_cast<T*>(m_impl->jsValue().asCell()); } template<typename T> inline bool Weak<T>::was(T* other) const diff --git a/Source/WebCore/bindings/js/JSCustomEventCustom.cpp b/Source/WebCore/bindings/js/JSCustomEventCustom.cpp index c556c9e2e..a2d26b5af 100644 --- a/Source/WebCore/bindings/js/JSCustomEventCustom.cpp +++ b/Source/WebCore/bindings/js/JSCustomEventCustom.cpp @@ -38,13 +38,13 @@ namespace WebCore { JSValue JSCustomEvent::detail(ExecState& state) const { - CustomEvent& event = wrapped(); + auto& event = wrapped(); + + JSValue detail = event.detail(); - if (event.detail().hasNoValue()) + if (!detail) return jsNull(); - JSValue detail = event.detail().jsValue(); - if (detail.isObject() && &worldForDOMObject(detail.getObject()) != ¤tWorld(&state)) { // We need to make sure CustomEvents do not leak their detail property across isolated DOM worlds. // Ideally, we would check that the worlds have different privileges but that's not possible yet. @@ -59,5 +59,10 @@ JSValue JSCustomEvent::detail(ExecState& state) const return detail; } +void JSCustomEvent::visitAdditionalChildren(JSC::SlotVisitor& visitor) +{ + wrapped().detail().visit(visitor); +} + } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSValueInWrappedObject.h b/Source/WebCore/bindings/js/JSValueInWrappedObject.h new file mode 100644 index 000000000..f1ee30b7e --- /dev/null +++ b/Source/WebCore/bindings/js/JSValueInWrappedObject.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2018 Apple Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "DOMWrapperWorld.h" +#include "JSDOMWrapper.h" +#include <JavaScriptCore/JSCJSValue.h> +#include <JavaScriptCore/SlotVisitor.h> +#include <JavaScriptCore/Weak.h> + +namespace WebCore { + +class JSValueInWrappedObject { +public: + JSValueInWrappedObject(JSC::JSValue = { }); + JSValueInWrappedObject(const JSValueInWrappedObject&); + operator JSC::JSValue() const; + explicit operator bool() const; + JSValueInWrappedObject& operator=(const JSValueInWrappedObject& other); + void visit(JSC::SlotVisitor&); + void clear(); + +private: + // Use a weak pointer here so that if this code or client code has a visiting mistake, + // we get null rather than a dangling pointer to a deleted object. + using Weak = JSC::Weak<JSC::JSCell>; + + JSC::JSValue m_jsValue; + Weak m_weakValue; + bool m_isWeak; +}; + +inline JSValueInWrappedObject::JSValueInWrappedObject(JSC::JSValue value) +{ + if (!value.isCell()) { + m_jsValue = value; + m_isWeak = false; + } else { + // FIXME: This is not quite right. It is possible that this value is being + // stored in a wrapped object that does not yet have a wrapper. If garbage + // collection occurs before the wrapped object gets a wrapper, it's possible + // the value object could be collected, and this will become null. A future + // version of this class should prevent the value from being collected in + // that case. Unclear if this can actually happen in practice. + m_weakValue = Weak { value.asCell() }; + m_isWeak = true; + } +} + +inline JSValueInWrappedObject::JSValueInWrappedObject(const JSValueInWrappedObject& other) +{ + JSC::JSValue value = other; + if (!value.isCell()) { + m_jsValue = value; + m_isWeak = false; + } else { + // FIXME: This is not quite right. It is possible that this value is being + // stored in a wrapped object that does not yet have a wrapper. If garbage + // collection occurs before the wrapped object gets a wrapper, it's possible + // the value object could be collected, and this will become null. A future + // version of this class should prevent the value from being collected in + // that case. Unclear if this can actually happen in practice. + m_weakValue = Weak { value.asCell() }; + m_isWeak = true; + } +} + +inline JSValueInWrappedObject::operator JSC::JSValue() const +{ + if (!m_isWeak) + return m_jsValue; + + return m_weakValue.get(); +} + +inline JSValueInWrappedObject::operator bool() const +{ + return JSC::JSValue { *this }.operator bool(); +} + +inline JSValueInWrappedObject& JSValueInWrappedObject::operator=(const JSValueInWrappedObject& other) +{ + JSC::JSValue value = other; + if (!value.isCell()) { + m_jsValue = value; + m_isWeak = false; + } else { + // FIXME: This is not quite right. It is possible that this value is being + // stored in a wrapped object that does not yet have a wrapper. If garbage + // collection occurs before the wrapped object gets a wrapper, it's possible + // the value object could be collected, and this will become null. A future + // version of this class should prevent the value from being collected in + // that case. Unclear if this can actually happen in practice. + m_weakValue = Weak { value.asCell() }; + m_isWeak = true; + } + return *this; +} + +inline void JSValueInWrappedObject::visit(JSC::SlotVisitor& visitor) +{ + if (!m_isWeak) { + // Nothing to visit. + } else { + visitor.appendUnbarrieredWeak(&m_weakValue); + }; +} + +inline void JSValueInWrappedObject::clear() +{ + if (m_isWeak) + m_weakValue.clear(); +} + +} // namespace WebCore diff --git a/Source/WebCore/dom/CustomEvent.cpp b/Source/WebCore/dom/CustomEvent.cpp index 495b5ab4b..fa1bc745d 100644 --- a/Source/WebCore/dom/CustomEvent.cpp +++ b/Source/WebCore/dom/CustomEvent.cpp @@ -45,7 +45,7 @@ CustomEvent::~CustomEvent() { } -void CustomEvent::initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, const Deprecated::ScriptValue& detail) +void CustomEvent::initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, JSC::JSValue detail) { if (dispatched()) return; @@ -60,7 +60,7 @@ void CustomEvent::initCustomEvent(const AtomicString& type, bool canBubble, bool RefPtr<SerializedScriptValue> CustomEvent::trySerializeDetail(JSC::ExecState* exec) { if (!m_serializedDetail && !m_triedToSerialize) { - m_serializedDetail = SerializedScriptValue::create(exec, m_detail.jsValue(), nullptr, nullptr, NonThrowing); + m_serializedDetail = SerializedScriptValue::create(exec, m_detail, nullptr, nullptr, NonThrowing); m_triedToSerialize = true; } diff --git a/Source/WebCore/dom/CustomEvent.h b/Source/WebCore/dom/CustomEvent.h index 2cb5c164d..ac369d951 100644 --- a/Source/WebCore/dom/CustomEvent.h +++ b/Source/WebCore/dom/CustomEvent.h @@ -27,6 +27,7 @@ #define CustomEvent_h #include "Event.h" +#include "JSValueInWrappedObject.h" #include "SerializedScriptValue.h" #include <bindings/ScriptValue.h> @@ -50,11 +51,11 @@ public: return adoptRef(*new CustomEvent(type, initializer)); } - void initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, const Deprecated::ScriptValue& detail); + void initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, JSC::JSValue detail); virtual EventInterface eventInterface() const override; - const Deprecated::ScriptValue& detail() const { return m_detail; } + JSValueInWrappedObject& detail() { return m_detail; } RefPtr<SerializedScriptValue> trySerializeDetail(JSC::ExecState*); @@ -62,7 +63,7 @@ private: CustomEvent(); CustomEvent(const AtomicString& type, const CustomEventInit& initializer); - Deprecated::ScriptValue m_detail; + JSValueInWrappedObject m_detail; RefPtr<SerializedScriptValue> m_serializedDetail; bool m_triedToSerialize { false }; }; diff --git a/Source/WebCore/dom/CustomEvent.idl b/Source/WebCore/dom/CustomEvent.idl index 12e0ec37b..899ad1a97 100644 --- a/Source/WebCore/dom/CustomEvent.idl +++ b/Source/WebCore/dom/CustomEvent.idl @@ -26,6 +26,7 @@ // Introduced in DOM Level 3: [ ConstructorTemplate=Event, + JSCustomMarkFunction, ] interface CustomEvent : Event { [InitializedByEventConstructor, CustomGetter] readonly attribute any detail; |