From 8d9e85b5baf784727ecefaecda68716e03ec884e Mon Sep 17 00:00:00 2001 From: Konstantin Tokarev Date: Wed, 26 Feb 2020 04:40:09 +0300 Subject: Import QtWebKit commit bf94215feb57ddf9ce364bc6953eec8cd1387c3d Change-Id: Ifc9d2e79e39fbfdd21bd40ede609c7696d2efe62 Reviewed-by: Konstantin Tokarev --- Source/JavaScriptCore/heap/WeakInlines.h | 11 +- Source/WebCore/bindings/js/JSCustomEventCustom.cpp | 13 +- .../WebCore/bindings/js/JSValueInWrappedObject.h | 137 +++++++++++++++++++++ Source/WebCore/dom/CustomEvent.cpp | 4 +- Source/WebCore/dom/CustomEvent.h | 7 +- Source/WebCore/dom/CustomEvent.idl | 1 + 6 files changed, 160 insertions(+), 13 deletions(-) create mode 100644 Source/WebCore/bindings/js/JSValueInWrappedObject.h 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 inline auto Weak::operator=(Weak&& other) -> Weak& template inline T* Weak::operator->() const { ASSERT(m_impl && m_impl->state() == WeakImpl::Live); - return jsCast(m_impl->jsValue().asCell()); + // We can't use jsCast here since we could be called in a finalizer. + return static_cast(m_impl->jsValue().asCell()); } template inline T& Weak::operator*() const { ASSERT(m_impl && m_impl->state() == WeakImpl::Live); - return *jsCast(m_impl->jsValue().asCell()); + // We can't use jsCast here since we could be called in a finalizer. + return *static_cast(m_impl->jsValue().asCell()); } template inline T* Weak::get() const { if (!m_impl || m_impl->state() != WeakImpl::Live) - return 0; - return jsCast(m_impl->jsValue().asCell()); + return nullptr; + // We can't use jsCast here since we could be called in a finalizer. + return static_cast(m_impl->jsValue().asCell()); } template inline bool Weak::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 +#include +#include + +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::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 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 @@ -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 trySerializeDetail(JSC::ExecState*); @@ -62,7 +63,7 @@ private: CustomEvent(); CustomEvent(const AtomicString& type, const CustomEventInit& initializer); - Deprecated::ScriptValue m_detail; + JSValueInWrappedObject m_detail; RefPtr 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; -- cgit v1.2.1