diff options
author | 2022-03-28 06:35:14 -0700 | |
---|---|---|
committer | 2022-03-28 06:35:14 -0700 | |
commit | 04b5e87f42b9a04d7b106b8dc1d92b4f0d435d4f (patch) | |
tree | 76a38b88ca4c5915a76ba97b56ad9f100fd4acd9 | |
parent | 7a97f62c72dc04e011cc646707ab2b894fade477 (diff) | |
download | bun-04b5e87f42b9a04d7b106b8dc1d92b4f0d435d4f.tar.gz bun-04b5e87f42b9a04d7b106b8dc1d92b4f0d435d4f.tar.zst bun-04b5e87f42b9a04d7b106b8dc1d92b4f0d435d4f.zip |
[`bun.js`] Add `Event`, `EventTarget`, `AbortController`, `AbortSignal`
`AbortController` is not yet aware of `fetch`
111 files changed, 11463 insertions, 21 deletions
diff --git a/src/javascript/jsc/bindings/ActiveDOMCallback.cpp b/src/javascript/jsc/bindings/ActiveDOMCallback.cpp new file mode 100644 index 000000000..2f7936aef --- /dev/null +++ b/src/javascript/jsc/bindings/ActiveDOMCallback.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010. 2012 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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. + */ + +#include "config.h" +#include "ActiveDOMCallback.h" + +#include "ScriptExecutionContext.h" + +namespace WebCore { + +ActiveDOMCallback::ActiveDOMCallback(ScriptExecutionContext* context) + : ContextDestructionObserver(context) +{ +} + +ActiveDOMCallback::~ActiveDOMCallback() = default; + +bool ActiveDOMCallback::canInvokeCallback() const +{ + ScriptExecutionContext* context = scriptExecutionContext(); + return context && !context->activeDOMObjectsAreSuspended() && !context->activeDOMObjectsAreStopped(); +} + +bool ActiveDOMCallback::activeDOMObjectsAreSuspended() const +{ + auto* context = scriptExecutionContext(); + return context && context->activeDOMObjectsAreSuspended(); +} + +bool ActiveDOMCallback::activeDOMObjectAreStopped() const +{ + auto* context = scriptExecutionContext(); + return !context || context->activeDOMObjectsAreStopped(); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/ActiveDOMCallback.h b/src/javascript/jsc/bindings/ActiveDOMCallback.h new file mode 100644 index 000000000..1117b952f --- /dev/null +++ b/src/javascript/jsc/bindings/ActiveDOMCallback.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010, 2012 Google Inc. All rights reserved. + * Copyright (C) 2021 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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 "ContextDestructionObserver.h" + +namespace JSC { +class AbstractSlotVisitor; +class SlotVisitor; +} + +namespace WebCore { + +class ScriptExecutionContext; + +// A base class that prevents binding callbacks from executing when +// active dom objects are stopped or suspended. +// +// Should only be created, used, and destroyed on the script execution +// context thread. +class ActiveDOMCallback : public ContextDestructionObserver { +public: + WEBCORE_EXPORT ActiveDOMCallback(ScriptExecutionContext*); + WEBCORE_EXPORT virtual ~ActiveDOMCallback(); + + WEBCORE_EXPORT bool canInvokeCallback() const; + + WEBCORE_EXPORT bool activeDOMObjectsAreSuspended() const; + WEBCORE_EXPORT bool activeDOMObjectAreStopped() const; + + virtual void visitJSFunction(JSC::AbstractSlotVisitor&) { } + virtual void visitJSFunction(JSC::SlotVisitor&) { } +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/BunBuiltinNames.h b/src/javascript/jsc/bindings/BunBuiltinNames.h index bb8449c5e..26d151319 100644 --- a/src/javascript/jsc/bindings/BunBuiltinNames.h +++ b/src/javascript/jsc/bindings/BunBuiltinNames.h @@ -33,6 +33,7 @@ using namespace JSC; macro(cork) \ macro(cwd) \ macro(delimiter) \ + macro(whenSignalAborted) \ macro(destroy) \ macro(dir) \ macro(dirname) \ diff --git a/src/javascript/jsc/bindings/CachedScript.h b/src/javascript/jsc/bindings/CachedScript.h new file mode 100644 index 000000000..3f54613d8 --- /dev/null +++ b/src/javascript/jsc/bindings/CachedScript.h @@ -0,0 +1,9 @@ +#pragma once + +#include "root.h" + +namespace WebCore { + +class CachedScript { +}; +}
\ No newline at end of file diff --git a/src/javascript/jsc/bindings/JSDOMExceptionHandling.cpp b/src/javascript/jsc/bindings/JSDOMExceptionHandling.cpp index 70f3c4d87..494bf9e3a 100644 --- a/src/javascript/jsc/bindings/JSDOMExceptionHandling.cpp +++ b/src/javascript/jsc/bindings/JSDOMExceptionHandling.cpp @@ -30,10 +30,71 @@ #include "JavaScriptCore/ExceptionHelpers.h" #include "JavaScriptCore/ScriptCallStack.h" #include "JavaScriptCore/ScriptCallStackFactory.h" +#include "headers.h" + +#include "CachedScript.h" namespace WebCore { using namespace JSC; +void reportException(JSGlobalObject* lexicalGlobalObject, JSC::Exception* exception, CachedScript* cachedScript, bool fromModule, ExceptionDetails* exceptionDetails) +{ + VM& vm = lexicalGlobalObject->vm(); + RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); + if (vm.isTerminationException(exception)) + return; + + // We can declare a CatchScope here because we will clear the exception below if it's + // not a TerminationException. If it's a TerminationException, it'll remain sticky in + // the VM, but we have the check above to ensure that we do not re-enter this scope. + auto scope = DECLARE_CATCH_SCOPE(vm); + + ErrorHandlingScope errorScope(lexicalGlobalObject->vm()); + + // auto callStack = Inspector::createScriptCallStackFromException(lexicalGlobalObject, exception); + scope.clearException(); + vm.clearLastException(); + + auto* globalObject = jsCast<JSDOMGlobalObject*>(lexicalGlobalObject); + // if (auto* window = jsDynamicCast<JSDOMWindow*>(vm, globalObject)) { + // if (!window->wrapped().isCurrentlyDisplayedInFrame()) + // return; + // } + + int lineNumber = 0; + int columnNumber = 0; + String exceptionSourceURL; + // if (auto* callFrame = callStack->firstNonNativeCallFrame()) { + // lineNumber = callFrame->lineNumber(); + // columnNumber = callFrame->columnNumber(); + // exceptionSourceURL = callFrame->sourceURL(); + // } + + auto errorMessage = retrieveErrorMessage(*lexicalGlobalObject, vm, exception->value(), scope); + Zig__GlobalObject__reportUncaughtException(globalObject, exception); + + if (exceptionDetails) { + exceptionDetails->message = errorMessage; + exceptionDetails->lineNumber = lineNumber; + exceptionDetails->columnNumber = columnNumber; + exceptionDetails->sourceURL = exceptionSourceURL; + } +} + +void reportException(JSGlobalObject* lexicalGlobalObject, JSValue exceptionValue, CachedScript* cachedScript, bool fromModule) +{ + VM& vm = lexicalGlobalObject->vm(); + RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); + auto* exception = jsDynamicCast<JSC::Exception*>(vm, exceptionValue); + if (!exception) { + exception = vm.lastException(); + if (!exception) + exception = JSC::Exception::create(lexicalGlobalObject->vm(), exceptionValue, JSC::Exception::DoNotCaptureStack); + } + + reportException(lexicalGlobalObject, exception, cachedScript, fromModule); +} + String retrieveErrorMessageWithoutName(JSGlobalObject& lexicalGlobalObject, VM& vm, JSValue exception, CatchScope& catchScope) { // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions @@ -76,7 +137,7 @@ void reportCurrentException(JSGlobalObject* lexicalGlobalObject) auto scope = DECLARE_CATCH_SCOPE(vm); auto* exception = scope.exception(); scope.clearException(); - // reportException(lexicalGlobalObject, exception); + reportException(lexicalGlobalObject, exception); } JSValue createDOMException(JSGlobalObject* lexicalGlobalObject, ExceptionCode ec, const String& message) diff --git a/src/javascript/jsc/bindings/JSDOMExceptionHandling.h b/src/javascript/jsc/bindings/JSDOMExceptionHandling.h index e90f9aecf..bc95053e7 100644 --- a/src/javascript/jsc/bindings/JSDOMExceptionHandling.h +++ b/src/javascript/jsc/bindings/JSDOMExceptionHandling.h @@ -68,8 +68,8 @@ WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::JSGlobalObject&, JSC: String retrieveErrorMessageWithoutName(JSC::JSGlobalObject&, JSC::VM&, JSC::JSValue exception, JSC::CatchScope&); String retrieveErrorMessage(JSC::JSGlobalObject&, JSC::VM&, JSC::JSValue exception, JSC::CatchScope&); -// WEBCORE_EXPORT void reportException(JSC::JSGlobalObject*, JSC::JSValue exception, CachedScript* = nullptr, bool = false); -// WEBCORE_EXPORT void reportException(JSC::JSGlobalObject*, JSC::Exception*, CachedScript* = nullptr, bool = false, ExceptionDetails* = nullptr); +WEBCORE_EXPORT void reportException(JSC::JSGlobalObject*, JSC::JSValue exception, CachedScript* = nullptr, bool = false); +WEBCORE_EXPORT void reportException(JSC::JSGlobalObject*, JSC::Exception*, CachedScript* = nullptr, bool = false, ExceptionDetails* = nullptr); void reportCurrentException(JSC::JSGlobalObject*); JSC::JSValue createDOMException(JSC::JSGlobalObject&, Exception&&); diff --git a/src/javascript/jsc/bindings/JSDOMGlobalObject.cpp b/src/javascript/jsc/bindings/JSDOMGlobalObject.cpp index 98b9e9dec..cc0bb87de 100644 --- a/src/javascript/jsc/bindings/JSDOMGlobalObject.cpp +++ b/src/javascript/jsc/bindings/JSDOMGlobalObject.cpp @@ -4,6 +4,11 @@ namespace WebCore { +Zig::GlobalObject* toJSDOMGlobalObject(ScriptExecutionContext& ctx, DOMWrapperWorld& world) +{ + return JSC::jsCast<Zig::GlobalObject*>(ctx.jsGlobalObject()); +} + // static JSDOMGlobalObject& callerGlobalObject(JSC::JSGlobalObject& lexicalGlobalObject, JSC::CallFrame* callFrame, bool skipFirstFrame, bool lookUpFromVMEntryScope) // { // VM& vm = lexicalGlobalObject.vm(); diff --git a/src/javascript/jsc/bindings/JSDOMGlobalObject.h b/src/javascript/jsc/bindings/JSDOMGlobalObject.h index fe2c09954..fe5344aeb 100644 --- a/src/javascript/jsc/bindings/JSDOMGlobalObject.h +++ b/src/javascript/jsc/bindings/JSDOMGlobalObject.h @@ -8,10 +8,11 @@ #include "JavaScriptCore/JSGlobalObject.h" #include "JavaScriptCore/JSObjectInlines.h" #include "JavaScriptCore/WeakGCMap.h" +#include "ScriptExecutionContext.h" namespace WebCore { -// Zig::GlobalObject* toJSDOMGlobalObject(ScriptExecutionContext&, DOMWrapperWorld&); +Zig::GlobalObject* toJSDOMGlobalObject(ScriptExecutionContext& ctx, DOMWrapperWorld& world); WEBCORE_EXPORT Zig::GlobalObject& callerGlobalObject(JSC::JSGlobalObject&, JSC::CallFrame*); Zig::GlobalObject& legacyActiveGlobalObjectForAccessor(JSC::JSGlobalObject&, JSC::CallFrame*); diff --git a/src/javascript/jsc/bindings/JSDOMWrapper.h b/src/javascript/jsc/bindings/JSDOMWrapper.h index a28174543..726b2e8bf 100644 --- a/src/javascript/jsc/bindings/JSDOMWrapper.h +++ b/src/javascript/jsc/bindings/JSDOMWrapper.h @@ -30,8 +30,11 @@ namespace WebCore { using namespace Zig; +#ifndef RENAMED_JSDOM_GLOBAL_OBJECT +#define RENAMED_JSDOM_GLOBAL_OBJECT using JSDOMGlobalObject = Zig::GlobalObject; - +} +#endif class ScriptExecutionContext; // JSC allows us to extend JSType. If the highest 3 bits are set, we can add any Object types and they are @@ -67,7 +70,7 @@ public: static void subspaceFor(JSC::VM&) { RELEASE_ASSERT_NOT_REACHED(); } JSDOMGlobalObject* globalObject() const { return JSC::jsCast<JSDOMGlobalObject*>(JSC::JSNonFinalObject::globalObject()); } - // ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); } + ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); } protected: WEBCORE_EXPORT JSDOMObject(JSC::Structure*, JSC::JSGlobalObject&); diff --git a/src/javascript/jsc/bindings/ScriptExecutionContext.h b/src/javascript/jsc/bindings/ScriptExecutionContext.h index e69de29bb..3acd476d7 100644 --- a/src/javascript/jsc/bindings/ScriptExecutionContext.h +++ b/src/javascript/jsc/bindings/ScriptExecutionContext.h @@ -0,0 +1,95 @@ +#pragma once + +#include "root.h" +#include "ActiveDOMObject.h" +#include <wtf/CrossThreadTask.h> +#include <wtf/Function.h> +#include <wtf/HashSet.h> +#include <wtf/ObjectIdentifier.h> +#include <wtf/WeakPtr.h> +#include <wtf/text/WTFString.h> +#include "CachedScript.h" +#include "wtf/URL.h" +namespace WebCore { + +class ScriptExecutionContext : public CanMakeWeakPtr<ScriptExecutionContext> { + +public: + ScriptExecutionContext(JSC::VM* vm, JSC::JSGlobalObject* globalObject) + : m_vm(vm) + , m_globalObject(globalObject) + { + } + class Task { + WTF_MAKE_FAST_ALLOCATED; + + public: + enum CleanupTaskTag { CleanupTask }; + + template<typename T, typename = typename std::enable_if<!std::is_base_of<Task, T>::value && std::is_convertible<T, Function<void(ScriptExecutionContext&)>>::value>::type> + Task(T task) + : m_task(WTFMove(task)) + , m_isCleanupTask(false) + { + } + + Task(Function<void()>&& task) + : m_task([task = WTFMove(task)](ScriptExecutionContext&) { task(); }) + , m_isCleanupTask(false) + { + } + + template<typename T, typename = typename std::enable_if<std::is_convertible<T, Function<void(ScriptExecutionContext&)>>::value>::type> + Task(CleanupTaskTag, T task) + : m_task(WTFMove(task)) + , m_isCleanupTask(true) + { + } + + void performTask(ScriptExecutionContext& context) { m_task(context); } + bool isCleanupTask() const { return m_isCleanupTask; } + + protected: + Function<void(ScriptExecutionContext&)> m_task; + bool m_isCleanupTask; + }; + + JSC::JSGlobalObject* jsGlobalObject() + { + return m_globalObject; + } + const WTF::URL& url() const { return m_url; } + bool activeDOMObjectsAreSuspended() { return false; } + bool activeDOMObjectsAreStopped() { return false; } + bool isContextThread() { return true; } + bool isDocument() { return false; } + bool isWorkerGlobalScope() { return true; } + bool isJSExecutionForbidden() { return false; } + void reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception*, RefPtr<void*>&&, CachedScript* = nullptr, bool = false) + { + } + // void reportUnhandledPromiseRejection(JSC::JSGlobalObject&, JSC::JSPromise&, RefPtr<Inspector::ScriptCallStack>&&) + // { + // } + + void postTask(Task&&) + { + } // Executes the task on context's thread asynchronously. + + template<typename... Arguments> + void postCrossThreadTask(Arguments&&... arguments) + { + postTask([crossThreadTask = createCrossThreadTask(arguments...)](ScriptExecutionContext&) mutable { + crossThreadTask.performTask(); + }); + } + + JSC::VM& vm() { return *m_vm; } + +private: + int m_junk = 0; + JSC::VM* m_vm = nullptr; + JSC::JSGlobalObject* m_globalObject = nullptr; + WTF::URL m_url = WTF::URL(); +}; +}
\ No newline at end of file diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp index 5550b7de9..c484bbc2f 100644 --- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp +++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp @@ -80,6 +80,11 @@ #include "JSDOMURL.h" #include "JSURLSearchParams.h" #include "JSDOMException.h" +#include "JSEventTarget.h" +#include "EventTargetConcrete.h" +#include "JSAbortSignal.h" +#include "JSAbortController.h" +#include "JSEvent.h" #include "Process.h" @@ -277,6 +282,26 @@ const JSC::GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &Zig::deriveShadowRealmGlobalObject }; +GlobalObject::GlobalObject(JSC::VM& vm, JSC::Structure* structure) + : JSC::JSGlobalObject(vm, structure, &s_globalObjectMethodTable) + , m_constructors(makeUnique<WebCore::DOMConstructors>()) + , m_world(WebCore::DOMWrapperWorld::create(vm, WebCore::DOMWrapperWorld::Type::Normal)) + , m_worldIsNormal(true) + +{ + m_scriptExecutionContext = new WebCore::ScriptExecutionContext(&vm, this); +} + +WebCore::ScriptExecutionContext* GlobalObject::scriptExecutionContext() +{ + return m_scriptExecutionContext; +} + +WebCore::ScriptExecutionContext* GlobalObject::scriptExecutionContext() const +{ + return m_scriptExecutionContext; +} + void GlobalObject::reportUncaughtExceptionAtEventLoop(JSGlobalObject* globalObject, JSC::Exception* exception) { @@ -322,6 +347,50 @@ JSC_DEFINE_CUSTOM_GETTER(JSURLSearchParams_getter, WebCore::JSURLSearchParams::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); } +JSC_DECLARE_CUSTOM_GETTER(JSEvent_getter); + +JSC_DEFINE_CUSTOM_GETTER(JSEvent_getter, + (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, + JSC::PropertyName)) +{ + Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); + return JSC::JSValue::encode( + WebCore::JSEvent::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); +} + +JSC_DECLARE_CUSTOM_GETTER(JSEventTarget_getter); + +JSC_DEFINE_CUSTOM_GETTER(JSEventTarget_getter, + (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, + JSC::PropertyName)) +{ + Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); + return JSC::JSValue::encode( + WebCore::JSEventTarget::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); +} + +JSC_DECLARE_CUSTOM_GETTER(JSDOMAbortController_getter); + +JSC_DEFINE_CUSTOM_GETTER(JSDOMAbortController_getter, + (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, + JSC::PropertyName)) +{ + Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); + return JSC::JSValue::encode( + WebCore::JSAbortController::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); +} + +JSC_DECLARE_CUSTOM_GETTER(JSDOMAbortSignal_getter); + +JSC_DEFINE_CUSTOM_GETTER(JSDOMAbortSignal_getter, + (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, + JSC::PropertyName)) +{ + Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); + return JSC::JSValue::encode( + WebCore::JSAbortSignal::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); +} + JSC_DECLARE_CUSTOM_GETTER(JSDOMException_getter); JSC_DEFINE_CUSTOM_GETTER(JSDOMException_getter, @@ -751,6 +820,18 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "DOMException"), JSC::CustomGetterSetter::create(vm, JSDOMException_getter, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Event"), JSC::CustomGetterSetter::create(vm, JSEvent_getter, nullptr), + JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + + putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "EventTarget"), JSC::CustomGetterSetter::create(vm, JSEventTarget_getter, nullptr), + JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + + putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "AbortController"), JSC::CustomGetterSetter::create(vm, JSDOMAbortController_getter, nullptr), + JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + + putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "AbortSignal"), JSC::CustomGetterSetter::create(vm, JSDOMAbortSignal_getter, nullptr), + JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + extraStaticGlobals.releaseBuffer(); } @@ -987,4 +1068,4 @@ void GlobalObject::queueMicrotaskToEventLoop(JSC::JSGlobalObject& global, &global, &JSMicrotaskCallback::create(global, WTFMove(task)).leakRef()); } -} // namespace Zig
\ No newline at end of file +} // namespace Zig diff --git a/src/javascript/jsc/bindings/root.h b/src/javascript/jsc/bindings/root.h index aeb22dbab..00fd2dc75 100644 --- a/src/javascript/jsc/bindings/root.h +++ b/src/javascript/jsc/bindings/root.h @@ -69,4 +69,11 @@ #include "wtf/PlatformCallingConventions.h" #include "JavaScriptCore/Strong.h" #include "JavaScriptCore/Weak.h" -#include "JavaScriptCore/WeakInlines.h"
\ No newline at end of file +#include "JavaScriptCore/WeakInlines.h" + +#define WTF_MAKE_ISO_ALLOCATED(className) \ + WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(className) + +#define WTF_MAKE_ISO_ALLOCATED_EXPORT(className, a) WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(className); + +#define WTF_MAKE_ISO_ALLOCATED_IMPL(className) diff --git a/src/javascript/jsc/bindings/webcore/AbortAlgorithm.h b/src/javascript/jsc/bindings/webcore/AbortAlgorithm.h new file mode 100644 index 000000000..26dd666b4 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AbortAlgorithm.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 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 "ActiveDOMCallback.h" +#include "CallbackResult.h" +#include <wtf/ThreadSafeRefCounted.h> + +namespace WebCore { + +class AbortAlgorithm : public ThreadSafeRefCounted<AbortAlgorithm>, public ActiveDOMCallback { +public: + using ActiveDOMCallback::ActiveDOMCallback; + + virtual CallbackResult<void> handleEvent() = 0; +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/AbortAlgorithm.idl b/src/javascript/jsc/bindings/webcore/AbortAlgorithm.idl new file mode 100644 index 000000000..a28c77856 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AbortAlgorithm.idl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2020 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. + */ + +callback AbortAlgorithm = undefined (); diff --git a/src/javascript/jsc/bindings/webcore/AbortController.cpp b/src/javascript/jsc/bindings/webcore/AbortController.cpp new file mode 100644 index 000000000..8e419971a --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AbortController.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2017 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. + */ + +#include "config.h" +#include "AbortController.h" + +#include "AbortSignal.h" +#include "DOMException.h" +#include "JSDOMException.h" +// #include <wtf/IsoMallocInlines.h> + +namespace WebCore { + +WTF_MAKE_ISO_ALLOCATED_IMPL(AbortController); + +Ref<AbortController> AbortController::create(ScriptExecutionContext& context) +{ + return adoptRef(*new AbortController(context)); +} + +AbortController::AbortController(ScriptExecutionContext& context) + : m_signal(AbortSignal::create(&context)) +{ +} + +AbortController::~AbortController() = default; + +AbortSignal& AbortController::signal() +{ + return m_signal.get(); +} + +void AbortController::abort(JSDOMGlobalObject& globalObject, JSC::JSValue reason) +{ + ASSERT(reason); + if (reason.isUndefined()) + reason = toJS(&globalObject, &globalObject, DOMException::create(AbortError)); + + m_signal->signalAbort(reason); +} + +} diff --git a/src/javascript/jsc/bindings/webcore/AbortController.h b/src/javascript/jsc/bindings/webcore/AbortController.h new file mode 100644 index 000000000..853892d8a --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AbortController.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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 "ScriptWrappable.h" +#include <wtf/Ref.h> +#include <wtf/RefCounted.h> +#include "ZigGlobalObject.h" + +namespace JSC { +class JSValue; +} + +namespace WebCore { + +class AbortSignal; + +class ScriptExecutionContext; + +class AbortController final : public ScriptWrappable, public RefCounted<AbortController> { + WTF_MAKE_ISO_ALLOCATED(AbortController); + +public: + static Ref<AbortController> create(ScriptExecutionContext&); + ~AbortController(); + + AbortSignal& signal(); + void abort(JSDOMGlobalObject&, JSC::JSValue reason); + +private: + explicit AbortController(ScriptExecutionContext&); + + Ref<AbortSignal> m_signal; +}; + +} diff --git a/src/javascript/jsc/bindings/webcore/AbortController.idl b/src/javascript/jsc/bindings/webcore/AbortController.idl new file mode 100644 index 000000000..0d011e205 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AbortController.idl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 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. + */ + +[ + Exposed=*, + GenerateAddOpaqueRoot=signal +] interface AbortController { + [CallWith=CurrentScriptExecutionContext] constructor(); + + [SameObject] readonly attribute AbortSignal signal; + + [CallWith=CurrentGlobalObject] undefined abort(optional any reason); +}; diff --git a/src/javascript/jsc/bindings/webcore/AbortSignal.cpp b/src/javascript/jsc/bindings/webcore/AbortSignal.cpp new file mode 100644 index 000000000..8554b3b83 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AbortSignal.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2017-2022 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. + */ + +#include "config.h" +#include "AbortSignal.h" + +#include "AbortAlgorithm.h" +#include "DOMException.h" +// #include "DOMTimer.h" +#include "Event.h" +#include "EventNames.h" +#include "JSDOMException.h" +#include "ScriptExecutionContext.h" +#include <JavaScriptCore/Exception.h> +#include <JavaScriptCore/JSCast.h> +// #include <wtf/IsoMallocInlines.h> + +namespace WebCore { + +WTF_MAKE_ISO_ALLOCATED_IMPL(AbortSignal); + +Ref<AbortSignal> AbortSignal::create(ScriptExecutionContext* context) +{ + return adoptRef(*new AbortSignal(context)); +} + +// https://dom.spec.whatwg.org/#dom-abortsignal-abort +Ref<AbortSignal> AbortSignal::abort(JSDOMGlobalObject& globalObject, ScriptExecutionContext& context, JSC::JSValue reason) +{ + ASSERT(reason); + if (reason.isUndefined()) + reason = toJS(&globalObject, &globalObject, DOMException::create(AbortError)); + return adoptRef(*new AbortSignal(&context, Aborted::Yes, reason)); +} + +// https://dom.spec.whatwg.org/#dom-abortsignal-timeout +Ref<AbortSignal> AbortSignal::timeout(ScriptExecutionContext& context, uint64_t milliseconds) +{ + auto signal = adoptRef(*new AbortSignal(&context)); + // signal->setHasActiveTimeoutTimer(true); + // auto action = [signal](ScriptExecutionContext& context) mutable { + // signal->setHasActiveTimeoutTimer(false); + + // auto* globalObject = JSC::jsCast<JSDOMGlobalObject*>(context.globalObject()); + // if (!globalObject) + // return; + + // auto& vm = globalObject->vm(); + // Locker locker { vm.apiLock() }; + // signal->signalAbort(toJS(globalObject, globalObject, DOMException::create(TimeoutError))); + // }; + // DOMTimer::install(context, WTFMove(action), Seconds::fromMilliseconds(milliseconds), true); + return signal; +} + +AbortSignal::AbortSignal(ScriptExecutionContext* context, Aborted aborted, JSC::JSValue reason) + : ContextDestructionObserver(context) + , m_aborted(aborted == Aborted::Yes) + , m_reason(reason) +{ + ASSERT(reason); +} + +AbortSignal::~AbortSignal() = default; + +// https://dom.spec.whatwg.org/#abortsignal-signal-abort +void AbortSignal::signalAbort(JSC::JSValue reason) +{ + // 1. If signal's aborted flag is set, then return. + if (m_aborted) + return; + + // 2. Set signal’s aborted flag. + m_aborted = true; + + // FIXME: This code is wrong: we should emit a write-barrier. Otherwise, GC can collect it. + // https://bugs.webkit.org/show_bug.cgi?id=236353 + ASSERT(reason); + m_reason.setWeakly(reason); + + Ref protectedThis { *this }; + auto algorithms = std::exchange(m_algorithms, {}); + for (auto& algorithm : algorithms) + algorithm(); + + // 5. Fire an event named abort at signal. + dispatchEvent(Event::create(eventNames().abortEvent, Event::CanBubble::No, Event::IsCancelable::No)); +} + +// https://dom.spec.whatwg.org/#abortsignal-follow +void AbortSignal::signalFollow(AbortSignal& signal) +{ + if (aborted()) + return; + + if (signal.aborted()) { + signalAbort(signal.reason().getValue()); + return; + } + + ASSERT(!m_followingSignal); + m_followingSignal = signal; + signal.addAlgorithm([weakThis = WeakPtr { this }] { + if (weakThis) + weakThis->signalAbort(weakThis->m_followingSignal ? weakThis->m_followingSignal->reason().getValue() : JSC::jsUndefined()); + }); +} + +void AbortSignal::eventListenersDidChange() +{ + m_hasAbortEventListener = hasEventListeners(eventNames().abortEvent); +} + +bool AbortSignal::whenSignalAborted(AbortSignal& signal, Ref<AbortAlgorithm>&& algorithm) +{ + if (signal.aborted()) { + algorithm->handleEvent(); + return true; + } + signal.addAlgorithm([algorithm = WTFMove(algorithm)]() mutable { + algorithm->handleEvent(); + }); + return false; +} + +void AbortSignal::throwIfAborted(JSC::JSGlobalObject& lexicalGlobalObject) +{ + if (!aborted()) + return; + + auto& vm = lexicalGlobalObject.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + throwException(&lexicalGlobalObject, scope, m_reason.getValue()); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/AbortSignal.h b/src/javascript/jsc/bindings/webcore/AbortSignal.h new file mode 100644 index 000000000..24f893f22 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AbortSignal.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2017-2022 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 "ContextDestructionObserver.h" +#include "EventTarget.h" +// #include "JSDOMPromiseDeferred.h" +#include "JSValueInWrappedObject.h" +#include <wtf/Function.h> +#include <wtf/Ref.h> +#include <wtf/RefCounted.h> +#include <wtf/WeakPtr.h> + +namespace WebCore { + +class AbortAlgorithm; +class ScriptExecutionContext; + +class AbortSignal final : public RefCounted<AbortSignal>, public EventTargetWithInlineData, private ContextDestructionObserver { + WTF_MAKE_ISO_ALLOCATED_EXPORT(AbortSignal, WEBCORE_EXPORT); + +public: + static Ref<AbortSignal> create(ScriptExecutionContext*); + WEBCORE_EXPORT ~AbortSignal(); + + static Ref<AbortSignal> abort(JSDOMGlobalObject&, ScriptExecutionContext&, JSC::JSValue reason); + static Ref<AbortSignal> timeout(ScriptExecutionContext&, uint64_t milliseconds); + + static bool whenSignalAborted(AbortSignal&, Ref<AbortAlgorithm>&&); + + void signalAbort(JSC::JSValue reason); + void signalFollow(AbortSignal&); + + bool aborted() const { return m_aborted; } + const JSValueInWrappedObject& reason() const { return m_reason; } + + bool hasActiveTimeoutTimer() const { return m_hasActiveTimeoutTimer; } + bool hasAbortEventListener() const { return m_hasAbortEventListener; } + + using RefCounted::deref; + using RefCounted::ref; + + using Algorithm = Function<void()>; + void addAlgorithm(Algorithm&& algorithm) { m_algorithms.append(WTFMove(algorithm)); } + + bool isFollowingSignal() const { return !!m_followingSignal; } + + void throwIfAborted(JSC::JSGlobalObject&); + +private: + enum class Aborted : bool { No, + Yes }; + explicit AbortSignal(ScriptExecutionContext*, Aborted = Aborted::No, JSC::JSValue reason = JSC::jsUndefined()); + + void setHasActiveTimeoutTimer(bool hasActiveTimeoutTimer) { m_hasActiveTimeoutTimer = hasActiveTimeoutTimer; } + + // EventTarget. + EventTargetInterface eventTargetInterface() const final { return AbortSignalEventTargetInterfaceType; } + ScriptExecutionContext* scriptExecutionContext() const final { return ContextDestructionObserver::scriptExecutionContext(); } + void refEventTarget() final { ref(); } + void derefEventTarget() final { deref(); } + void eventListenersDidChange() final; + + bool m_aborted { false }; + Vector<Algorithm> m_algorithms; + WeakPtr<AbortSignal> m_followingSignal; + JSValueInWrappedObject m_reason; + bool m_hasActiveTimeoutTimer { false }; + bool m_hasAbortEventListener { false }; +}; + +} diff --git a/src/javascript/jsc/bindings/webcore/AbortSignal.idl b/src/javascript/jsc/bindings/webcore/AbortSignal.idl new file mode 100644 index 000000000..f81c5b0a2 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AbortSignal.idl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017-2022 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. + */ + +[ + CustomIsReachable, + Exposed=*, + JSCustomMarkFunction, + PrivateIdentifier, + PublicIdentifier +] interface AbortSignal : EventTarget { + [PrivateIdentifier] static boolean whenSignalAborted(AbortSignal object, AbortAlgorithm algorithm); + + [NewObject, CallWith=CurrentScriptExecutionContext&CurrentGlobalObject] static AbortSignal abort(optional any reason); + [Exposed=(Window, Worker), NewObject, CallWith=CurrentScriptExecutionContext] static AbortSignal timeout([EnforceRange] unsigned long long milliseconds); + + readonly attribute boolean aborted; + readonly attribute any reason; + [CallWith=CurrentGlobalObject] undefined throwIfAborted(); + + attribute EventHandler onabort; +}; diff --git a/src/javascript/jsc/bindings/webcore/AddEventListenerOptions.h b/src/javascript/jsc/bindings/webcore/AddEventListenerOptions.h new file mode 100644 index 000000000..79128ee15 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/AddEventListenerOptions.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016-2020 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. ``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 + * 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 "AbortSignal.h" +#include "EventListenerOptions.h" +#include <optional> + +namespace WebCore { + +struct AddEventListenerOptions : EventListenerOptions { + AddEventListenerOptions(bool capture = false, std::optional<bool> passive = std::nullopt, bool once = false, RefPtr<AbortSignal>&& signal = nullptr) + : EventListenerOptions(capture) + , passive(passive) + , once(once) + , signal(WTFMove(signal)) + { + } + + std::optional<bool> passive; + bool once { false }; + RefPtr<AbortSignal> signal; +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/CallbackResult.h b/src/javascript/jsc/bindings/webcore/CallbackResult.h new file mode 100644 index 000000000..878fe4221 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/CallbackResult.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2017 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 <wtf/Expected.h> + +namespace WebCore { + +enum class CallbackResultType { + Success, + ExceptionThrown, + UnableToExecute +}; + +template<typename ReturnType> class CallbackResult { +public: + CallbackResult(CallbackResultType); + CallbackResult(ReturnType&&); + + CallbackResultType type() const; + ReturnType&& releaseReturnValue(); + +private: + Expected<ReturnType, CallbackResultType> m_value; +}; + +template<> class CallbackResult<void> { +public: + CallbackResult() = default; + CallbackResult(CallbackResultType); + + CallbackResultType type() const; + +private: + CallbackResultType m_type = CallbackResultType::Success; +}; + + +template<typename ReturnType> inline CallbackResult<ReturnType>::CallbackResult(CallbackResultType type) + : m_value(makeUnexpected(type)) +{ +} + +template<typename ReturnType> inline CallbackResult<ReturnType>::CallbackResult(ReturnType&& returnValue) + : m_value(WTFMove(returnValue)) +{ +} + +template<typename ReturnType> inline CallbackResultType CallbackResult<ReturnType>::type() const +{ + return m_value.has_value() ? CallbackResultType::Success : m_value.error(); +} + +template<typename ReturnType> inline auto CallbackResult<ReturnType>::releaseReturnValue() -> ReturnType&& +{ + ASSERT(m_value.has_value()); + return WTFMove(m_value.value()); +} + + +// Void specialization + +inline CallbackResult<void>::CallbackResult(CallbackResultType type) + : m_type(type) +{ +} + +inline CallbackResultType CallbackResult<void>::type() const +{ + return m_type; +} + +} diff --git a/src/javascript/jsc/bindings/webcore/ContextDestructionObserver.h b/src/javascript/jsc/bindings/webcore/ContextDestructionObserver.h new file mode 100644 index 000000000..ccf20f301 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/ContextDestructionObserver.h @@ -0,0 +1,33 @@ + + +#pragma once + +#include "root.h" + +#include "ScriptExecutionContext.h" + +namespace WebCore { + +// TODO: +class ContextDestructionObserver { + +public: + WEBCORE_EXPORT void contextDestroyed() {} + + ScriptExecutionContext* scriptExecutionContext() const { return m_context; } + + ContextDestructionObserver(ScriptExecutionContext* context) + : m_context(context) + { + } + ContextDestructionObserver(ContextDestructionObserver& context) + : m_context(context.m_context) + { + } + +private: + int m_junk = 0; + ScriptExecutionContext* m_context; +}; + +}
\ No newline at end of file diff --git a/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h b/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h index af4a995a8..f9fc695ad 100644 --- a/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h +++ b/src/javascript/jsc/bindings/webcore/DOMClientIsoSubspaces.h @@ -379,8 +379,6 @@ public: // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCSSTransformValue; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCSSTransformValueIterator; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCSSTranslate; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForAbortController; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForAbortSignal; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForAbstractRange; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForAnimationEvent; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForAttr; @@ -412,10 +410,6 @@ public: // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDocumentType; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDragEvent; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForElement; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForErrorEvent; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForEvent; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForEventListener; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForEventTarget; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForFocusEvent; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForFormDataEvent; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForHashChangeEvent; @@ -869,5 +863,12 @@ public: // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForXPathNSResolver; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForXPathResult; // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForXSLTProcessor; + + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForAbortController; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForAbortSignal; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForErrorEvent; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForEvent; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForEventListener; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForEventTarget; }; } // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/DOMHighResTimeStamp.h b/src/javascript/jsc/bindings/webcore/DOMHighResTimeStamp.h new file mode 100644 index 000000000..11b678600 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/DOMHighResTimeStamp.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017 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 + +namespace WebCore { + +using DOMHighResTimeStamp = double; + +} diff --git a/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h b/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h index 36564a926..57be16805 100644 --- a/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h +++ b/src/javascript/jsc/bindings/webcore/DOMIsoSubspaces.h @@ -367,8 +367,7 @@ public: // std::unique_ptr<IsoSubspace> m_subspaceForCSSTransformValue; // std::unique_ptr<IsoSubspace> m_subspaceForCSSTransformValueIterator; // std::unique_ptr<IsoSubspace> m_subspaceForCSSTranslate; - // std::unique_ptr<IsoSubspace> m_subspaceForAbortController; - // std::unique_ptr<IsoSubspace> m_subspaceForAbortSignal; + // std::unique_ptr<IsoSubspace> m_subspaceForAbstractRange; // std::unique_ptr<IsoSubspace> m_subspaceForAnimationEvent; // std::unique_ptr<IsoSubspace> m_subspaceForAttr; @@ -401,10 +400,7 @@ public: // std::unique_ptr<IsoSubspace> m_subspaceForDocumentType; // std::unique_ptr<IsoSubspace> m_subspaceForDragEvent; // std::unique_ptr<IsoSubspace> m_subspaceForElement; - // std::unique_ptr<IsoSubspace> m_subspaceForErrorEvent; - // std::unique_ptr<IsoSubspace> m_subspaceForEvent; - // std::unique_ptr<IsoSubspace> m_subspaceForEventListener; - // std::unique_ptr<IsoSubspace> m_subspaceForEventTarget; + // std::unique_ptr<IsoSubspace> m_subspaceForFocusEvent; // std::unique_ptr<IsoSubspace> m_subspaceForFormDataEvent; // std::unique_ptr<IsoSubspace> m_subspaceForHashChangeEvent; @@ -859,6 +855,13 @@ public: // std::unique_ptr<IsoSubspace> m_subspaceForXPathResult; // std::unique_ptr<IsoSubspace> m_subspaceForXSLTProcessor; + std::unique_ptr<IsoSubspace> m_subspaceForAbortController; + std::unique_ptr<IsoSubspace> m_subspaceForAbortSignal; + std::unique_ptr<IsoSubspace> m_subspaceForErrorEvent; + std::unique_ptr<IsoSubspace> m_subspaceForEvent; + std::unique_ptr<IsoSubspace> m_subspaceForEventListener; + std::unique_ptr<IsoSubspace> m_subspaceForEventTarget; + std::unique_ptr<IsoSubspace> m_subspaceForGlobalObject; std::unique_ptr<IsoSubspace> m_subspaceForExposedToWorkerAndWindow; diff --git a/src/javascript/jsc/bindings/webcore/ErrorCallback.cpp b/src/javascript/jsc/bindings/webcore/ErrorCallback.cpp new file mode 100644 index 000000000..5b81eea06 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/ErrorCallback.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 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. + */ + +#include "config.h" +#include "ErrorCallback.h" + +#include "DOMException.h" +#include "ScriptExecutionContext.h" + +namespace WebCore { + +void ErrorCallback::scheduleCallback(ScriptExecutionContext& context, Ref<DOMException>&& exception) +{ + context.postTask([protectedThis = Ref { *this }, exception = WTFMove(exception)] (ScriptExecutionContext&) { + protectedThis->handleEvent(exception); + }); +} + +} diff --git a/src/javascript/jsc/bindings/webcore/ErrorCallback.h b/src/javascript/jsc/bindings/webcore/ErrorCallback.h new file mode 100644 index 000000000..8c1eaff9a --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/ErrorCallback.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2017 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 "ActiveDOMCallback.h" +#include "CallbackResult.h" +#include <wtf/Forward.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +class DOMException; + +class ErrorCallback : public RefCounted<ErrorCallback>, public ActiveDOMCallback { +public: + using ActiveDOMCallback::ActiveDOMCallback; + + virtual CallbackResult<void> handleEvent(DOMException&) = 0; + + // Helper to post callback task. + void scheduleCallback(ScriptExecutionContext&, Ref<DOMException>&&); +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/ErrorCallback.idl b/src/javascript/jsc/bindings/webcore/ErrorCallback.idl new file mode 100644 index 000000000..4dd3901da --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/ErrorCallback.idl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 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. + */ + +callback ErrorCallback = undefined (DOMException error); diff --git a/src/javascript/jsc/bindings/webcore/ErrorEvent.cpp b/src/javascript/jsc/bindings/webcore/ErrorEvent.cpp new file mode 100644 index 000000000..4f6c618f7 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/ErrorEvent.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2009 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 are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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. + */ + +#include "config.h" +#include "ErrorEvent.h" + +#include "DOMWrapperWorld.h" +#include "EventNames.h" +#include <JavaScriptCore/HeapInlines.h> +#include <JavaScriptCore/StrongInlines.h> +// #include <wtf/IsoMallocInlines.h> + +namespace WebCore { +using namespace JSC; + +WTF_MAKE_ISO_ALLOCATED_IMPL(ErrorEvent); + +ErrorEvent::ErrorEvent(const AtomString& type, const Init& initializer, IsTrusted isTrusted) + : Event(type, initializer, isTrusted) + , m_message(initializer.message) + , m_fileName(initializer.filename) + , m_lineNumber(initializer.lineno) + , m_columnNumber(initializer.colno) + , m_error(initializer.error) +{ +} + +ErrorEvent::ErrorEvent(const AtomString& type, const String& message, const String& fileName, unsigned lineNumber, unsigned columnNumber, JSC::Strong<JSC::Unknown> error) + : Event(type, CanBubble::No, IsCancelable::Yes) + , m_message(message) + , m_fileName(fileName) + , m_lineNumber(lineNumber) + , m_columnNumber(columnNumber) + , m_error(error.get()) +{ +} + +ErrorEvent::ErrorEvent(const String& message, const String& fileName, unsigned lineNumber, unsigned columnNumber, JSC::Strong<JSC::Unknown> error) + : ErrorEvent(eventNames().errorEvent, message, fileName, lineNumber, columnNumber, error) +{ +} + +ErrorEvent::~ErrorEvent() = default; + +EventInterface ErrorEvent::eventInterface() const +{ + return ErrorEventInterfaceType; +} + +JSValue ErrorEvent::error(JSGlobalObject& globalObject) +{ + if (!m_error) + return jsNull(); + + JSValue error = m_error.getValue(); + // if (!isWorldCompatible(globalObject, error)) { + // // We need to make sure ErrorEvents do not leak their error property across isolated DOM worlds. + // // Ideally, we would check that the worlds have different privileges but that's not possible yet. + // auto serializedError = trySerializeError(globalObject); + // if (!serializedError) + // return jsNull(); + // return serializedError->deserialize(globalObject, &globalObject); + // } + + return error; +} + +// RefPtr<SerializedScriptValue> ErrorEvent::trySerializeError(JSGlobalObject& exec) +// { +// // if (!m_serializedError && !m_triedToSerialize) { +// // m_serializedError = SerializedScriptValue::create(exec, m_error.getValue(), SerializationErrorMode::NonThrowing); +// // m_triedToSerialize = true; +// // } +// return 0; +// } + +bool ErrorEvent::isErrorEvent() const +{ + return true; +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/ErrorEvent.h b/src/javascript/jsc/bindings/webcore/ErrorEvent.h new file mode 100644 index 000000000..400c91dae --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/ErrorEvent.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2009 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 are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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 "Event.h" +#include "JSValueInWrappedObject.h" +// #include "SerializedScriptValue.h" +#include <JavaScriptCore/Strong.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class ErrorEvent final : public Event { + WTF_MAKE_ISO_ALLOCATED(ErrorEvent); + +public: + static Ref<ErrorEvent> create(const String& message, const String& fileName, unsigned lineNumber, unsigned columnNumber, JSC::Strong<JSC::Unknown> error) + { + return adoptRef(*new ErrorEvent(message, fileName, lineNumber, columnNumber, error)); + } + + static Ref<ErrorEvent> create(const AtomString& type, const String& message, const String& fileName, unsigned lineNumber, unsigned columnNumber, JSC::Strong<JSC::Unknown> error) + { + return adoptRef(*new ErrorEvent(type, message, fileName, lineNumber, columnNumber, error)); + } + + struct Init : EventInit { + String message; + String filename; + unsigned lineno { 0 }; + unsigned colno { 0 }; + JSC::JSValue error; + }; + + static Ref<ErrorEvent> create(const AtomString& type, const Init& initializer, IsTrusted isTrusted = IsTrusted::No) + { + return adoptRef(*new ErrorEvent(type, initializer, isTrusted)); + } + + virtual ~ErrorEvent(); + + const String& message() const { return m_message; } + const String& filename() const { return m_fileName; } + unsigned lineno() const { return m_lineNumber; } + unsigned colno() const { return m_columnNumber; } + JSC::JSValue error(JSC::JSGlobalObject&); + + const JSValueInWrappedObject& originalError() const { return m_error; } + // SerializedScriptValue* serializedError() const { return m_serializedError.get(); } + + EventInterface eventInterface() const override; + + // RefPtr<SerializedScriptValue> trySerializeError(JSC::JSGlobalObject&); + +private: + ErrorEvent(const AtomString& type, const String& message, const String& fileName, unsigned lineNumber, unsigned columnNumber, JSC::Strong<JSC::Unknown> error); + ErrorEvent(const String& message, const String& fileName, unsigned lineNumber, unsigned columnNumber, JSC::Strong<JSC::Unknown> error); + ErrorEvent(const AtomString&, const Init&, IsTrusted); + + bool isErrorEvent() const override; + + String m_message; + String m_fileName; + unsigned m_lineNumber; + unsigned m_columnNumber; + JSValueInWrappedObject m_error; + // RefPtr<SerializedScriptValue> m_serializedError; + bool m_triedToSerialize { false }; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_EVENT(ErrorEvent) diff --git a/src/javascript/jsc/bindings/webcore/ErrorEvent.idl b/src/javascript/jsc/bindings/webcore/ErrorEvent.idl new file mode 100644 index 000000000..1ea1ccff1 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/ErrorEvent.idl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2009 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 are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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. + */ + +[ + Exposed=*, + JSCustomMarkFunction, +] interface ErrorEvent : Event { + constructor(DOMString type, optional ErrorEventInit eventInitDict); + + readonly attribute DOMString message; + readonly attribute USVString filename; + readonly attribute unsigned long lineno; + readonly attribute unsigned long colno; + [CallWith=CurrentGlobalObject] readonly attribute any error; +}; + +dictionary ErrorEventInit : EventInit { + DOMString message = ""; + USVString filename = ""; + unsigned long lineno = 0; + unsigned long colno = 0; + any error = null; +}; diff --git a/src/javascript/jsc/bindings/webcore/Event.cpp b/src/javascript/jsc/bindings/webcore/Event.cpp new file mode 100644 index 000000000..f488f0106 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/Event.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de) + * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) + * Copyright (C) 2003-2017 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "Event.h" + +// #include "DOMWindow.h" +// #include "Document.h" +#include "EventNames.h" +#include "EventPath.h" +#include "EventTarget.h" +// #include "InspectorInstrumentation.h" +// #include "Performance.h" +// #include "UserGestureIndicator.h" +// #include "WorkerGlobalScope.h" +#include <wtf/HexNumber.h> +// #include <wtf/IsoMallocInlines.h> +#include <wtf/text/StringBuilder.h> +#include <wtf/text/TextStream.h> + +namespace WebCore { + +WTF_MAKE_ISO_ALLOCATED_IMPL(Event); + +ALWAYS_INLINE Event::Event(MonotonicTime createTime, const AtomString& type, IsTrusted isTrusted, CanBubble canBubble, IsCancelable cancelable, IsComposed composed) + : m_isInitialized { !type.isNull() } + , m_canBubble { canBubble == CanBubble::Yes } + , m_cancelable { cancelable == IsCancelable::Yes } + , m_composed { composed == IsComposed::Yes } + , m_propagationStopped { false } + , m_immediatePropagationStopped { false } + , m_wasCanceled { false } + , m_defaultHandled { false } + , m_isDefaultEventHandlerIgnored { false } + , m_isTrusted { isTrusted == IsTrusted::Yes } + , m_isExecutingPassiveEventListener { false } + , m_currentTargetIsInShadowTree { false } + , m_eventPhase { NONE } + , m_type { type } + , m_createTime { createTime } +{ +} + +Event::Event(IsTrusted isTrusted) + : Event { MonotonicTime::now(), {}, isTrusted, CanBubble::No, IsCancelable::No, IsComposed::No } +{ +} + +Event::Event(const AtomString& eventType, CanBubble canBubble, IsCancelable isCancelable, IsComposed isComposed) + : Event { MonotonicTime::now(), eventType, IsTrusted::Yes, canBubble, isCancelable, isComposed } +{ + ASSERT(!eventType.isNull()); +} + +Event::Event(const AtomString& eventType, CanBubble canBubble, IsCancelable isCancelable, IsComposed isComposed, MonotonicTime timestamp, IsTrusted isTrusted) + : Event { timestamp, eventType, isTrusted, canBubble, isCancelable, isComposed } +{ + ASSERT(!eventType.isNull()); +} + +Event::Event(const AtomString& eventType, const EventInit& initializer, IsTrusted isTrusted) + : Event { MonotonicTime::now(), eventType, isTrusted, + initializer.bubbles ? CanBubble::Yes : CanBubble::No, + initializer.cancelable ? IsCancelable::Yes : IsCancelable::No, + initializer.composed ? IsComposed::Yes : IsComposed::No } +{ + ASSERT(!eventType.isNull()); +} + +Event::~Event() = default; + +Ref<Event> Event::create(const AtomString& type, CanBubble canBubble, IsCancelable isCancelable, IsComposed isComposed) +{ + return adoptRef(*new Event(type, canBubble, isCancelable, isComposed)); +} + +Ref<Event> Event::createForBindings() +{ + return adoptRef(*new Event); +} + +Ref<Event> Event::create(const AtomString& type, const EventInit& initializer, IsTrusted isTrusted) +{ + return adoptRef(*new Event(type, initializer, isTrusted)); +} + +void Event::initEvent(const AtomString& eventTypeArg, bool canBubbleArg, bool cancelableArg) +{ + if (isBeingDispatched()) + return; + + m_isInitialized = true; + m_propagationStopped = false; + m_immediatePropagationStopped = false; + m_wasCanceled = false; + m_isTrusted = false; + m_target = nullptr; + m_type = eventTypeArg; + m_canBubble = canBubbleArg; + m_cancelable = cancelableArg; + + m_underlyingEvent = nullptr; +} + +void Event::setTarget(RefPtr<EventTarget>&& target) +{ + if (m_target == target) + return; + + m_target = WTFMove(target); + if (m_target) + receivedTarget(); +} + +void Event::setCurrentTarget(EventTarget* currentTarget, std::optional<bool> isInShadowTree) +{ + m_currentTarget = currentTarget; + m_currentTargetIsInShadowTree = false; // m_currentTargetIsInShadowTree = isInShadowTree ? *isInShadowTree : (is<Node>(currentTarget) && downcast<Node>(*currentTarget).isInShadowTree()); +} + +Vector<EventTarget*> Event::composedPath() const +{ + // if (!m_eventPath) + return Vector<EventTarget*>(); + // return m_eventPath->computePathUnclosedToTarget(*m_currentTarget); +} + +void Event::setUnderlyingEvent(Event* underlyingEvent) +{ + // Prohibit creation of a cycle by doing nothing if a cycle would be created. + for (Event* event = underlyingEvent; event; event = event->underlyingEvent()) { + if (event == this) + return; + } + m_underlyingEvent = underlyingEvent; +} + +DOMHighResTimeStamp Event::timeStampForBindings(ScriptExecutionContext& context) const +{ + // TODO: + return 0.0; + // Performance* performance = nullptr; + // if (is<WorkerGlobalScope>(context)) + // performance = &downcast<WorkerGlobalScope>(context).performance(); + // else if (auto* window = downcast<Document>(context).domWindow()) + // performance = &window->performance(); + + // if (!performance) + // return 0; + + // return std::max(performance->relativeTimeFromTimeOriginInReducedResolution(m_createTime), 0.); +} + +void Event::resetBeforeDispatch() +{ + m_defaultHandled = false; +} + +void Event::resetAfterDispatch() +{ + m_eventPath = nullptr; + setCurrentTarget(nullptr); + m_eventPhase = NONE; + m_propagationStopped = false; + m_immediatePropagationStopped = false; + + // InspectorInstrumentation::eventDidResetAfterDispatch(*this); +} + +String Event::debugDescription() const +{ + return makeString(type(), " phase ", eventPhase(), bubbles() ? " bubbles " : " ", cancelable() ? "cancelable " : " ", "0x"_s, hex(reinterpret_cast<uintptr_t>(this), Lowercase)); +} + +TextStream& operator<<(TextStream& ts, const Event& event) +{ + ts << event.debugDescription(); + return ts; +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/Event.h b/src/javascript/jsc/bindings/webcore/Event.h new file mode 100644 index 000000000..5b7d5cba2 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/Event.h @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de) + * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) + * Copyright (C) 2003-2017 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +#include "config.h" + +#include "DOMHighResTimeStamp.h" +#include "EventInit.h" +#include "EventInterfaces.h" +#include "EventOptions.h" +#include "ExceptionOr.h" +#include "ScriptWrappable.h" +#include <wtf/MonotonicTime.h> +#include <wtf/TypeCasts.h> +#include <wtf/text/AtomString.h> + +namespace WTF { +class TextStream; +} + +namespace WebCore { + +class EventPath; +class EventTarget; +class ScriptExecutionContext; + +class Event : public ScriptWrappable, public RefCounted<Event> { + WTF_MAKE_ISO_ALLOCATED(Event); + +public: + using IsTrusted = EventIsTrusted; + using CanBubble = EventCanBubble; + using IsCancelable = EventIsCancelable; + using IsComposed = EventIsComposed; + + enum PhaseType : uint8_t { + NONE = 0, + CAPTURING_PHASE = 1, + AT_TARGET = 2, + BUBBLING_PHASE = 3 + }; + + WEBCORE_EXPORT static Ref<Event> create(const AtomString& type, CanBubble, IsCancelable, IsComposed = IsComposed::No); + static Ref<Event> createForBindings(); + static Ref<Event> create(const AtomString& type, const EventInit&, IsTrusted = IsTrusted::No); + + virtual ~Event(); + + WEBCORE_EXPORT void initEvent(const AtomString& type, bool canBubble, bool cancelable); + + bool isInitialized() const { return m_isInitialized; } + + const AtomString& type() const { return m_type; } + void setType(const AtomString& type) { m_type = type; } + + EventTarget* target() const { return m_target.get(); } + void setTarget(RefPtr<EventTarget>&&); + + EventTarget* currentTarget() const { return m_currentTarget.get(); } + void setCurrentTarget(EventTarget*, std::optional<bool> isInShadowTree = std::nullopt); + bool currentTargetIsInShadowTree() const { return m_currentTargetIsInShadowTree; } + + unsigned short eventPhase() const { return m_eventPhase; } + void setEventPhase(PhaseType phase) { m_eventPhase = phase; } + + bool bubbles() const { return m_canBubble; } + bool cancelable() const { return m_cancelable; } + bool composed() const { return m_composed; } + + DOMHighResTimeStamp timeStampForBindings(ScriptExecutionContext&) const; + MonotonicTime timeStamp() const { return m_createTime; } + + void setEventPath(const EventPath& path) { UNUSED_PARAM(path); } + Vector<EventTarget*> composedPath() const; + + void stopPropagation() { m_propagationStopped = true; } + void stopImmediatePropagation() { m_immediatePropagationStopped = true; } + + bool isTrusted() const { return m_isTrusted; } + void setUntrusted() { m_isTrusted = false; } + + bool legacyReturnValue() const { return !m_wasCanceled; } + void setLegacyReturnValue(bool); + + virtual EventInterface eventInterface() const { return EventInterfaceType; } + + virtual bool isBeforeTextInsertedEvent() const { return false; } + virtual bool isBeforeUnloadEvent() const { return false; } + virtual bool isClipboardEvent() const { return false; } + virtual bool isCompositionEvent() const { return false; } + virtual bool isErrorEvent() const { return false; } + virtual bool isFocusEvent() const { return false; } + virtual bool isInputEvent() const { return false; } + virtual bool isKeyboardEvent() const { return false; } + virtual bool isMouseEvent() const { return false; } + virtual bool isPointerEvent() const { return false; } + virtual bool isTextEvent() const { return false; } + virtual bool isTouchEvent() const { return false; } + virtual bool isUIEvent() const { return false; } + virtual bool isVersionChangeEvent() const { return false; } + virtual bool isWheelEvent() const { return false; } + + bool propagationStopped() const { return m_propagationStopped || m_immediatePropagationStopped; } + bool immediatePropagationStopped() const { return m_immediatePropagationStopped; } + + void resetBeforeDispatch(); + void resetAfterDispatch(); + + bool defaultPrevented() const { return m_wasCanceled; } + void preventDefault(); + + bool defaultHandled() const { return m_defaultHandled; } + void setDefaultHandled() { m_defaultHandled = true; } + + bool isDefaultEventHandlerIgnored() const { return m_isDefaultEventHandlerIgnored; } + void setIsDefaultEventHandlerIgnored() { m_isDefaultEventHandlerIgnored = true; } + + void setInPassiveListener(bool value) { m_isExecutingPassiveEventListener = value; } + + bool cancelBubble() const { return propagationStopped(); } + void setCancelBubble(bool); + + Event* underlyingEvent() const { return m_underlyingEvent.get(); } + void setUnderlyingEvent(Event*); + + // Returns true if the dispatch flag is set. + // https://dom.spec.whatwg.org/#dispatch-flag + bool isBeingDispatched() const { return eventPhase(); } + + virtual EventTarget* relatedTarget() const { return nullptr; } + virtual void setRelatedTarget(EventTarget*) {} + + virtual String debugDescription() const; + +protected: + explicit Event(IsTrusted = IsTrusted::No); + Event(const AtomString& type, CanBubble, IsCancelable, IsComposed = IsComposed::No); + Event(const AtomString& type, CanBubble, IsCancelable, IsComposed, MonotonicTime timestamp, IsTrusted isTrusted = IsTrusted::Yes); + Event(const AtomString& type, const EventInit&, IsTrusted); + + virtual void receivedTarget() {} + +private: + explicit Event(MonotonicTime createTime, const AtomString& type, IsTrusted, CanBubble, IsCancelable, IsComposed); + + void setCanceledFlagIfPossible(); + + unsigned m_isInitialized : 1; + unsigned m_canBubble : 1; + unsigned m_cancelable : 1; + unsigned m_composed : 1; + + unsigned m_propagationStopped : 1; + unsigned m_immediatePropagationStopped : 1; + unsigned m_wasCanceled : 1; + unsigned m_defaultHandled : 1; + unsigned m_isDefaultEventHandlerIgnored : 1; + unsigned m_isTrusted : 1; + unsigned m_isExecutingPassiveEventListener : 1; + unsigned m_currentTargetIsInShadowTree : 1; + + unsigned m_eventPhase : 2; + + AtomString m_type; + + RefPtr<EventTarget> m_currentTarget; + const EventPath* m_eventPath { nullptr }; + RefPtr<EventTarget> m_target; + MonotonicTime m_createTime; + + RefPtr<Event> m_underlyingEvent; +}; + +inline void Event::preventDefault() +{ + setCanceledFlagIfPossible(); +} + +inline void Event::setLegacyReturnValue(bool returnValue) +{ + if (!returnValue) + setCanceledFlagIfPossible(); +} + +// https://dom.spec.whatwg.org/#set-the-canceled-flag +inline void Event::setCanceledFlagIfPossible() +{ + if (m_cancelable && !m_isExecutingPassiveEventListener) + m_wasCanceled = true; + // FIXME: Specification suggests we log something to the console when preventDefault is called but + // doesn't do anything because the event is not cancelable or is executing passive event listeners. +} + +inline void Event::setCancelBubble(bool cancel) +{ + if (cancel) + m_propagationStopped = true; +} + +WTF::TextStream& operator<<(WTF::TextStream&, const Event&); + +} // namespace WebCore + +#define SPECIALIZE_TYPE_TRAITS_EVENT(ToValueTypeName) \ + SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \ + static bool isType(const WebCore::Event& event) { return event.is##ToValueTypeName(); } \ + SPECIALIZE_TYPE_TRAITS_END() diff --git a/src/javascript/jsc/bindings/webcore/Event.idl b/src/javascript/jsc/bindings/webcore/Event.idl new file mode 100644 index 000000000..2d6ba61f7 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/Event.idl @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2006, 2007, 2009, 2011, 2017 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +typedef double DOMHighResTimeStamp; + +[ + CustomToJSObject, + DOMJIT, + ExportToWrappedFunction, + Exposed=*, + JSCustomHeader, +] interface Event { + constructor(DOMString type, optional EventInit eventInitDict); + + readonly attribute DOMString type; + readonly attribute EventTarget? target; + readonly attribute EventTarget? currentTarget; + sequence<EventTarget> composedPath(); + + const unsigned short NONE = 0; + const unsigned short CAPTURING_PHASE = 1; + const unsigned short AT_TARGET = 2; + const unsigned short BUBBLING_PHASE = 3; + readonly attribute unsigned short eventPhase; + + undefined stopPropagation(); + attribute boolean cancelBubble; // historical alias of .stopPropagation. + undefined stopImmediatePropagation(); + + readonly attribute boolean bubbles; + readonly attribute boolean cancelable; + undefined preventDefault(); + readonly attribute boolean defaultPrevented; + readonly attribute boolean composed; + + [LegacyUnforgeable] readonly attribute boolean isTrusted; + [CallWith=RelevantScriptExecutionContext, ImplementedAs=timeStampForBindings] readonly attribute DOMHighResTimeStamp timeStamp; + + undefined initEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false); // Historical. + + // IE extensions that may get standardized (https://github.com/whatwg/dom/issues/334). + [ImplementedAs=target] readonly attribute EventTarget srcElement; + [ImplementedAs=legacyReturnValue] attribute boolean returnValue; +}; diff --git a/src/javascript/jsc/bindings/webcore/EventContext.cpp b/src/javascript/jsc/bindings/webcore/EventContext.cpp new file mode 100644 index 000000000..c80863a7d --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventContext.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Google Inc. All Rights Reserved. + * Copyright (C) 2017 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. ``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 + * 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. + * + */ + +#include "config.h" +#include "EventContext.h" + +// #include "DOMWindow.h" +// #include "Document.h" +#include "EventNames.h" +// #include "FocusEvent.h" +// #include "HTMLFormElement.h" +// #include "MouseEvent.h" +// #include "TouchEvent.h" + +namespace WebCore { + +EventContext::~EventContext() = default; + +void EventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const +{ + event.setTarget(m_target.get()); + event.setCurrentTarget(m_currentTarget.get(), m_currentTargetIsInShadowTree); + + if (!m_node || UNLIKELY(m_type == Type::Window)) { + m_currentTarget->fireEventListeners(event, phase); + return; + } + + if (!m_node->hasEventTargetData()) + return; + + m_node->fireEventListeners(event, phase); +} + +#if ASSERT_ENABLED + +bool EventContext::isUnreachableNode(EventTarget* target) const +{ + // FIXME: Checks also for SVG elements. + return false; +} + +#endif + +} diff --git a/src/javascript/jsc/bindings/webcore/EventContext.h b/src/javascript/jsc/bindings/webcore/EventContext.h new file mode 100644 index 000000000..8fbd3c19f --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventContext.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2010 Google Inc. All Rights Reserved. + * Copyright (C) 2017 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. ``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 + * 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 "root.h" +#include "Event.h" + +#include "Node.h" + +namespace WebCore { + +class EventContext { + WTF_MAKE_FAST_ALLOCATED; + +public: + using EventInvokePhase = EventTarget::EventInvokePhase; + + enum class Type : uint8_t { + Normal = 0, + MouseOrFocus, + Touch, + Window, + }; + + EventContext(Type, Node*, EventTarget* currentTarget, EventTarget* origin, int closedShadowDepth); + EventContext(Type, Node&, Node* currentTarget, EventTarget* origin, int closedShadowDepth); + ~EventContext(); + + Node* node() const { return m_node.get(); } + EventTarget* currentTarget() const { return m_currentTarget.get(); } + // bool isCurrentTargetInShadowTree() const { return m_currentTargetIsInShadowTree; } + bool isCurrentTargetInShadowTree() const { return false; } + EventTarget* target() const { return m_target.get(); } + // int closedShadowDepth() const { return m_closedShadowDepth; } + int closedShadowDepth() const { return 0; } + + void handleLocalEvents(Event&, EventInvokePhase) const; + + // bool isMouseOrFocusEventContext() const { return m_type == Type::MouseOrFocus; } + bool isMouseOrFocusEventContext() const { return false; } + // bool isTouchEventContext() const { return m_type == Type::Touch; } + bool isTouchEventContext() const { return false; } + // bool isWindowContext() const { return m_type == Type::Window; } + bool isWindowContext() const { return false; } + + Node* relatedTarget() const { return m_relatedTarget.get(); } + void setRelatedTarget(Node*); + +#if ENABLE(TOUCH_EVENTS) + enum TouchListType { Touches, + TargetTouches, + ChangedTouches }; + TouchList& touchList(TouchListType); +#endif + +private: + inline EventContext(Type, Node* currentNode, RefPtr<EventTarget>&& currentTarget, EventTarget* origin, int closedShadowDepth, bool currentTargetIsInShadowTree = false); + +#if ENABLE(TOUCH_EVENTS) + void initializeTouchLists(); +#endif + +#if ASSERT_ENABLED + bool isUnreachableNode(EventTarget*) const; +#endif + + RefPtr<Node> m_node; + RefPtr<EventTarget> m_currentTarget; + RefPtr<EventTarget> m_target; + RefPtr<Node> m_relatedTarget; +#if ENABLE(TOUCH_EVENTS) + RefPtr<TouchList> m_touches; + RefPtr<TouchList> m_targetTouches; + RefPtr<TouchList> m_changedTouches; +#endif + int m_closedShadowDepth { 0 }; + bool m_currentTargetIsInShadowTree { false }; + bool m_contextNodeIsFormElement { false }; + Type m_type { Type::Normal }; +}; + +inline EventContext::EventContext(Type type, Node* node, RefPtr<EventTarget>&& currentTarget, EventTarget* origin, int closedShadowDepth, bool currentTargetIsInShadowTree) + : m_node { node } + , m_currentTarget { WTFMove(currentTarget) } + , m_target { origin } + , m_closedShadowDepth { closedShadowDepth } + , m_currentTargetIsInShadowTree { currentTargetIsInShadowTree } + , m_type { type } +{ + // ASSERT(!isUnreachableNode(m_target.get())); + // #if ENABLE(TOUCH_EVENTS) + // if (m_type == Type::Touch) + // initializeTouchLists(); + // #else + // ASSERT(m_type != Type::Touch); + // #endif +} + +inline EventContext::EventContext(Type type, Node* node, EventTarget* currentTarget, EventTarget* origin, int closedShadowDepth) + : EventContext(type, node, RefPtr { currentTarget }, origin, closedShadowDepth) +{ + // ASSERT(!is<Node>(currentTarget)); +} + +// This variant avoids calling EventTarget::ref() which is a virtual function call. +inline EventContext::EventContext(Type type, Node& node, Node* currentTarget, EventTarget* origin, int closedShadowDepth) + : EventContext(type, &node, RefPtr { currentTarget }, origin, closedShadowDepth, false) +{ + m_contextNodeIsFormElement = false; + // m_contextNodeIsFormElement = is<HTMLFormElement>(node); +} + +inline void EventContext::setRelatedTarget(Node* relatedTarget) +{ + ASSERT(!isUnreachableNode(relatedTarget)); + m_relatedTarget = relatedTarget; +} + +// #if ENABLE(TOUCH_EVENTS) + +// inline TouchList& EventContext::touchList(TouchListType type) +// { +// switch (type) { +// case Touches: +// return *m_touches; +// case TargetTouches: +// return *m_targetTouches; +// case ChangedTouches: +// return *m_changedTouches; +// } +// ASSERT_NOT_REACHED(); +// return *m_touches; +// } + +// #endif + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventDispatcher.cpp b/src/javascript/jsc/bindings/webcore/EventDispatcher.cpp new file mode 100644 index 000000000..9c83aa0e2 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventDispatcher.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2004-2022 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2010, 2011, 2012, 2013 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "Event.h" +#include "EventDispatcher.h" + +// #include "CompositionEvent.h" +#include "EventContext.h" +// #include "EventNames.h" +#include "EventPath.h" +// #include "Frame.h" +// #include "FrameLoader.h" +// #include "FrameView.h" +// #include "HTMLInputElement.h" +// #include "InputEvent.h" +// #include "KeyboardEvent.h" +// #include "Logging.h" +// #include "MouseEvent.h" +// #include "ScopedEventQueue.h" +// #include "ScriptDisallowedScope.h" +// #include "ShadowRoot.h" +// #include "TextEvent.h" +// #include "TouchEvent.h" +// #include <wtf/text/TextStream.h> + +namespace WebCore { + +// void EventDispatcher::dispatchScopedEvent(Node& node, Event& event) +// { +// // Need to set the target here so the scoped event queue knows which node to dispatch to. +// event.setTarget(EventPath::eventTargetRespectingTargetRules(node)); +// ScopedEventQueue::singleton().enqueueEvent(event); +// } + +static void callDefaultEventHandlersInBubblingOrder(Event& event, const EventPath& path) +{ + if (path.isEmpty()) + return; + + // Non-bubbling events call only one default event handler, the one for the target. + Ref rootNode { *path.contextAt(0).node() }; + rootNode->defaultEventHandler(event); + ASSERT(!event.defaultPrevented()); + + if (event.defaultHandled() || !event.bubbles()) + return; + + size_t size = path.size(); + for (size_t i = 1; i < size; ++i) { + Ref currentNode { *path.contextAt(i).node() }; + currentNode->defaultEventHandler(event); + ASSERT(!event.defaultPrevented()); + if (event.defaultHandled()) + return; + } +} + +// static bool isInShadowTree(EventTarget* target) +// { +// return is<Node>(target) && downcast<Node>(*target).isInShadowTree(); +// } + +static void dispatchEventInDOM(Event& event, const EventPath& path) +{ + // Invoke capturing event listeners in the reverse order. + for (size_t i = path.size(); i > 0; --i) { + const EventContext& eventContext = path.contextAt(i - 1); + if (eventContext.currentTarget() == eventContext.target()) + event.setEventPhase(Event::AT_TARGET); + else + event.setEventPhase(Event::CAPTURING_PHASE); + eventContext.handleLocalEvents(event, EventTarget::EventInvokePhase::Capturing); + if (event.propagationStopped()) + return; + } + + // Invoke bubbling event listeners. + size_t size = path.size(); + for (size_t i = 0; i < size; ++i) { + const EventContext& eventContext = path.contextAt(i); + if (eventContext.currentTarget() == eventContext.target()) + event.setEventPhase(Event::AT_TARGET); + else if (event.bubbles()) + event.setEventPhase(Event::BUBBLING_PHASE); + else + continue; + eventContext.handleLocalEvents(event, EventTarget::EventInvokePhase::Bubbling); + if (event.propagationStopped()) + return; + } +} + +static bool shouldSuppressEventDispatchInDOM(Node& node, Event& event) +{ + return false; + // if (!event.isTrusted()) + // return false; + + // auto frame = node.document().frame(); + // if (!frame) + // return false; + + // if (!frame->mainFrame().loader().shouldSuppressTextInputFromEditing()) + // return false; + + // if (is<TextEvent>(event)) { + // auto& textEvent = downcast<TextEvent>(event); + // return textEvent.isKeyboard() || textEvent.isComposition(); + // } + + // return is<CompositionEvent>(event) || is<InputEvent>(event) || is<KeyboardEvent>(event); +} + +// static HTMLInputElement* findInputElementInEventPath(const EventPath& path) +// { +// size_t size = path.size(); +// for (size_t i = 0; i < size; ++i) { +// const EventContext& eventContext = path.contextAt(i); +// if (is<HTMLInputElement>(eventContext.currentTarget())) +// return downcast<HTMLInputElement>(eventContext.currentTarget()); +// } +// return nullptr; +// } + +void EventDispatcher::dispatchEvent(Node& node, Event& event) +{ + // ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isEventDispatchAllowedInSubtree(node)); + + // LOG_WITH_STREAM(Events, stream << "EventDispatcher::dispatchEvent " << event << " on node " << node); + + Ref protectedNode { node }; + // RefPtr protectedView { node.document().view() }; + + EventPath eventPath { node, event }; + + std::optional<bool> shouldClearTargetsAfterDispatch; + // for (size_t i = eventPath.size(); i > 0; --i) { + // const EventContext& eventContext = eventPath.contextAt(i - 1); + // // FIXME: We should also set shouldClearTargetsAfterDispatch to true if an EventTarget object in eventContext's touch target list + // // is a node and its root is a shadow root. + // if (eventContext.target()) { + // shouldClearTargetsAfterDispatch = isInShadowTree(eventContext.target()) || isInShadowTree(eventContext.relatedTarget()); + // break; + // } + // } + + // ChildNodesLazySnapshot::takeChildNodesLazySnapshot(); + + event.resetBeforeDispatch(); + event.setTarget(node); + // event.setTarget(EventPath::eventTargetRespectingTargetRules(node)); + if (!event.target()) + return; + + // InputElementClickState clickHandlingState; + + // bool isActivationEvent = event.type() == eventNames().clickEvent; + // RefPtr inputForLegacyPreActivationBehavior = dynamicDowncast<HTMLInputElement>(node); + // if (!inputForLegacyPreActivationBehavior && isActivationEvent && event.bubbles()) + // inputForLegacyPreActivationBehavior = findInputElementInEventPath(eventPath); + // if (inputForLegacyPreActivationBehavior) + // inputForLegacyPreActivationBehavior->willDispatchEvent(event, clickHandlingState); + + if (shouldSuppressEventDispatchInDOM(node, event)) + event.stopPropagation(); + + if (!event.propagationStopped() && !eventPath.isEmpty()) { + event.setEventPath(eventPath); + dispatchEventInDOM(event, eventPath); + } + + event.resetAfterDispatch(); + + // if (clickHandlingState.stateful) + // inputForLegacyPreActivationBehavior->didDispatchClickEvent(event, clickHandlingState); + + // Call default event handlers. While the DOM does have a concept of preventing + // default handling, the detail of which handlers are called is an internal + // implementation detail and not part of the DOM. + if (!event.defaultPrevented() && !event.defaultHandled() && !event.isDefaultEventHandlerIgnored()) { + // FIXME: Not clear why we need to reset the target for the default event handlers. + // We should research this, and remove this code if possible. + auto* finalTarget = event.target(); + // event.setTarget(EventPath::eventTargetRespectingTargetRules(node)); + event.setTarget(node); + callDefaultEventHandlersInBubblingOrder(event, eventPath); + event.setTarget(finalTarget); + } + + if (shouldClearTargetsAfterDispatch.value_or(false)) { + event.setTarget(nullptr); + event.setRelatedTarget(nullptr); + // FIXME: We should also clear the event's touch target list. + } +} + +template<typename T> +static void dispatchEventWithType(const Vector<T*>& targets, Event& event) +{ + ASSERT(targets.size() >= 1); + ASSERT(*targets.begin()); + + EventPath eventPath { targets }; + event.setTarget(*targets.begin()); + event.setEventPath(eventPath); + event.resetBeforeDispatch(); + dispatchEventInDOM(event, eventPath); + event.resetAfterDispatch(); +} + +void EventDispatcher::dispatchEvent(const Vector<EventTarget*>& targets, Event& event) +{ + dispatchEventWithType<EventTarget>(targets, event); +} + +} diff --git a/src/javascript/jsc/bindings/webcore/EventDispatcher.h b/src/javascript/jsc/bindings/webcore/EventDispatcher.h new file mode 100644 index 000000000..63ee34bfb --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventDispatcher.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011-2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2017 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include <wtf/Forward.h> +#include "Node.h" + +namespace WebCore { + +class Element; +class Event; +class EventTarget; + +namespace EventDispatcher { + +void dispatchEvent(Node&, Event&); +void dispatchEvent(const Vector<EventTarget*>&, Event&); + +// void dispatchScopedEvent(Node&, Event&); + +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventFactory.cpp b/src/javascript/jsc/bindings/webcore/EventFactory.cpp new file mode 100644 index 000000000..2b9bc8afe --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventFactory.cpp @@ -0,0 +1,316 @@ +/* + * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. + * + * Copyright (C) 2011 Google 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 GOOGLE, INC. ``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 + * 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. + */ + +#include "config.h" +#include "EventHeaders.h" +#include "JSDOMWrapperCache.h" +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/StructureInlines.h> + +namespace WebCore { + +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<Event>&& impl) +{ + switch (impl->eventInterface()) { + // case AnimationEventInterfaceType: + // return createWrapper<AnimationEvent>(globalObject, WTFMove(impl)); + // case AnimationPlaybackEventInterfaceType: + // return createWrapper<AnimationPlaybackEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(APPLE_PAY) + // case ApplePayCancelEventInterfaceType: + // return createWrapper<ApplePayCancelEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(APPLE_PAY_COUPON_CODE) + // case ApplePayCouponCodeChangedEventInterfaceType: + // return createWrapper<ApplePayCouponCodeChangedEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(APPLE_PAY) + // case ApplePayPaymentAuthorizedEventInterfaceType: + // return createWrapper<ApplePayPaymentAuthorizedEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(APPLE_PAY) + // case ApplePayPaymentMethodSelectedEventInterfaceType: + // return createWrapper<ApplePayPaymentMethodSelectedEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(APPLE_PAY) + // case ApplePayShippingContactSelectedEventInterfaceType: + // return createWrapper<ApplePayShippingContactSelectedEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(APPLE_PAY) + // case ApplePayShippingMethodSelectedEventInterfaceType: + // return createWrapper<ApplePayShippingMethodSelectedEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(APPLE_PAY) + // case ApplePayValidateMerchantEventInterfaceType: + // return createWrapper<ApplePayValidateMerchantEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_AUDIO) + // case AudioProcessingEventInterfaceType: + // return createWrapper<AudioProcessingEvent>(globalObject, WTFMove(impl)); + // #endif + case EventInterfaceType: { + return createWrapper<Event>(globalObject, WTFMove(impl)); + } + // case BeforeUnloadEventInterfaceType: + // return createWrapper<BeforeUnloadEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(MEDIA_RECORDER) + // case BlobEventInterfaceType: + // return createWrapper<BlobEvent>(globalObject, WTFMove(impl)); + // #endif + // case ClipboardEventInterfaceType: + // return createWrapper<ClipboardEvent>(globalObject, WTFMove(impl)); + // case CloseEventInterfaceType: + // return createWrapper<CloseEvent>(globalObject, WTFMove(impl)); + // case CompositionEventInterfaceType: + // return createWrapper<CompositionEvent>(globalObject, WTFMove(impl)); + // case CustomEventInterfaceType: + // return createWrapper<CustomEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(DEVICE_ORIENTATION) + // case DeviceMotionEventInterfaceType: + // return createWrapper<DeviceMotionEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(DEVICE_ORIENTATION) + // case DeviceOrientationEventInterfaceType: + // return createWrapper<DeviceOrientationEvent>(globalObject, WTFMove(impl)); + // #endif + // case DragEventInterfaceType: + // return createWrapper<DragEvent>(globalObject, WTFMove(impl)); + // case ErrorEventInterfaceType: { + // return createWrapper<ErrorEvent>(globalObject, WTFMove(impl)); + // } + // #if ENABLE(SERVICE_WORKER) + // case ExtendableEventInterfaceType: + // return createWrapper<ExtendableEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(SERVICE_WORKER) + // case ExtendableMessageEventInterfaceType: + // return createWrapper<ExtendableMessageEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(SERVICE_WORKER) + // case FetchEventInterfaceType: + // return createWrapper<FetchEvent>(globalObject, WTFMove(impl)); + // #endif + // case FocusEventInterfaceType: + // return createWrapper<FocusEvent>(globalObject, WTFMove(impl)); + // case FormDataEventInterfaceType: + // return createWrapper<FormDataEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(GAMEPAD) + // case GamepadEventInterfaceType: + // return createWrapper<GamepadEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(IOS_GESTURE_EVENTS) || ENABLE(MAC_GESTURE_EVENTS) + // case GestureEventInterfaceType: + // return createWrapper<GestureEvent>(globalObject, WTFMove(impl)); + // #endif + // case HashChangeEventInterfaceType: + // return createWrapper<HashChangeEvent>(globalObject, WTFMove(impl)); + // case IDBVersionChangeEventInterfaceType: + // return createWrapper<IDBVersionChangeEvent>(globalObject, WTFMove(impl)); + // case InputEventInterfaceType: + // return createWrapper<InputEvent>(globalObject, WTFMove(impl)); + // case KeyboardEventInterfaceType: + // return createWrapper<KeyboardEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(ENCRYPTED_MEDIA) + // case MediaEncryptedEventInterfaceType: + // return createWrapper<MediaEncryptedEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(ENCRYPTED_MEDIA) + // case MediaKeyMessageEventInterfaceType: + // return createWrapper<MediaKeyMessageEvent>(globalObject, WTFMove(impl)); + // #endif + // case MediaQueryListEventInterfaceType: + // return createWrapper<MediaQueryListEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(MEDIA_RECORDER) + // case MediaRecorderErrorEventInterfaceType: + // return createWrapper<MediaRecorderErrorEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(MEDIA_STREAM) + // case MediaStreamTrackEventInterfaceType: + // return createWrapper<MediaStreamTrackEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(PAYMENT_REQUEST) + // case MerchantValidationEventInterfaceType: + // return createWrapper<MerchantValidationEvent>(globalObject, WTFMove(impl)); + // #endif + // case MessageEventInterfaceType: + // return createWrapper<MessageEvent>(globalObject, WTFMove(impl)); + // case MouseEventInterfaceType: + // return createWrapper<MouseEvent>(globalObject, WTFMove(impl)); + // case MutationEventInterfaceType: + // return createWrapper<MutationEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(NOTIFICATION_EVENT) + // case NotificationEventInterfaceType: + // return createWrapper<NotificationEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_AUDIO) + // case OfflineAudioCompletionEventInterfaceType: + // return createWrapper<OfflineAudioCompletionEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(MEDIA_STREAM) + // case OverconstrainedErrorEventInterfaceType: + // return createWrapper<OverconstrainedErrorEvent>(globalObject, WTFMove(impl)); + // #endif + // case OverflowEventInterfaceType: + // return createWrapper<OverflowEvent>(globalObject, WTFMove(impl)); + // case PageTransitionEventInterfaceType: + // return createWrapper<PageTransitionEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(PAYMENT_REQUEST) + // case PaymentMethodChangeEventInterfaceType: + // return createWrapper<PaymentMethodChangeEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(PAYMENT_REQUEST) + // case PaymentRequestUpdateEventInterfaceType: + // return createWrapper<PaymentRequestUpdateEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(PICTURE_IN_PICTURE_API) + // case PictureInPictureEventInterfaceType: + // return createWrapper<PictureInPictureEvent>(globalObject, WTFMove(impl)); + // #endif + // case PointerEventInterfaceType: + // return createWrapper<PointerEvent>(globalObject, WTFMove(impl)); + // case PopStateEventInterfaceType: + // return createWrapper<PopStateEvent>(globalObject, WTFMove(impl)); + // case ProgressEventInterfaceType: + // return createWrapper<ProgressEvent>(globalObject, WTFMove(impl)); + // case PromiseRejectionEventInterfaceType: + // return createWrapper<PromiseRejectionEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(SERVICE_WORKER) + // case PushEventInterfaceType: + // return createWrapper<PushEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(SERVICE_WORKER) + // case PushSubscriptionChangeEventInterfaceType: + // return createWrapper<PushSubscriptionChangeEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCDTMFToneChangeEventInterfaceType: + // return createWrapper<RTCDTMFToneChangeEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCDataChannelEventInterfaceType: + // return createWrapper<RTCDataChannelEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCErrorEventInterfaceType: + // return createWrapper<RTCErrorEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCPeerConnectionIceErrorEventInterfaceType: + // return createWrapper<RTCPeerConnectionIceErrorEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCPeerConnectionIceEventInterfaceType: + // return createWrapper<RTCPeerConnectionIceEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCRtpSFrameTransformErrorEventInterfaceType: + // return createWrapper<RTCRtpSFrameTransformErrorEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCTrackEventInterfaceType: + // return createWrapper<RTCTrackEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCTransformEventInterfaceType: + // return createWrapper<RTCTransformEvent>(globalObject, WTFMove(impl)); + // #endif + // case SVGZoomEventInterfaceType: + // return createWrapper<SVGZoomEvent>(globalObject, WTFMove(impl)); + // case SecurityPolicyViolationEventInterfaceType: + // return createWrapper<SecurityPolicyViolationEvent>(globalObject, WTFMove(impl)); + // case SpeechRecognitionErrorEventInterfaceType: + // return createWrapper<SpeechRecognitionErrorEvent>(globalObject, WTFMove(impl)); + // case SpeechRecognitionEventInterfaceType: + // return createWrapper<SpeechRecognitionEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(SPEECH_SYNTHESIS) + // case SpeechSynthesisErrorEventInterfaceType: + // return createWrapper<SpeechSynthesisErrorEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(SPEECH_SYNTHESIS) + // case SpeechSynthesisEventInterfaceType: + // return createWrapper<SpeechSynthesisEvent>(globalObject, WTFMove(impl)); + // #endif + // case StorageEventInterfaceType: + // return createWrapper<StorageEvent>(globalObject, WTFMove(impl)); + // case SubmitEventInterfaceType: + // return createWrapper<SubmitEvent>(globalObject, WTFMove(impl)); + // case TextEventInterfaceType: + // return createWrapper<TextEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(TOUCH_EVENTS) + // case TouchEventInterfaceType: + // return createWrapper<TouchEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(VIDEO) + // case TrackEventInterfaceType: + // return createWrapper<TrackEvent>(globalObject, WTFMove(impl)); + // #endif + // case TransitionEventInterfaceType: + // return createWrapper<TransitionEvent>(globalObject, WTFMove(impl)); + // case UIEventInterfaceType: + // return createWrapper<UIEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(WEBGL) + // case WebGLContextEventInterfaceType: + // return createWrapper<WebGLContextEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(LEGACY_ENCRYPTED_MEDIA) + // case WebKitMediaKeyMessageEventInterfaceType: + // return createWrapper<WebKitMediaKeyMessageEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(LEGACY_ENCRYPTED_MEDIA) + // case WebKitMediaKeyNeededEventInterfaceType: + // return createWrapper<WebKitMediaKeyNeededEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WIRELESS_PLAYBACK_TARGET) + // case WebKitPlaybackTargetAvailabilityEventInterfaceType: + // return createWrapper<WebKitPlaybackTargetAvailabilityEvent>(globalObject, WTFMove(impl)); + // #endif + // case WheelEventInterfaceType: + // return createWrapper<WheelEvent>(globalObject, WTFMove(impl)); + // case XMLHttpRequestProgressEventInterfaceType: + // return createWrapper<XMLHttpRequestProgressEvent>(globalObject, WTFMove(impl)); + // #if ENABLE(WEBXR) + // case XRInputSourceEventInterfaceType: + // return createWrapper<XRInputSourceEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEBXR) + // case XRInputSourcesChangeEventInterfaceType: + // return createWrapper<XRInputSourcesChangeEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEBXR) + // case XRReferenceSpaceEventInterfaceType: + // return createWrapper<XRReferenceSpaceEvent>(globalObject, WTFMove(impl)); + // #endif + // #if ENABLE(WEBXR) + // case XRSessionEventInterfaceType: + // return createWrapper<XRSessionEvent>(globalObject, WTFMove(impl)); + // #endif + // } + return createWrapper<Event>(globalObject, WTFMove(impl)); + } +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventHeaders.h b/src/javascript/jsc/bindings/webcore/EventHeaders.h new file mode 100644 index 000000000..3937c5c2b --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventHeaders.h @@ -0,0 +1,302 @@ +/* + * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. + * + * Copyright (C) 2011 Google 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 GOOGLE, INC. ``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 + * 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. + */ + +#ifndef EventHeaders_h +#define EventHeaders_h + +// #include "AnimationEvent.h" +// #include "JSAnimationEvent.h" +// #include "AnimationPlaybackEvent.h" +// #include "JSAnimationPlaybackEvent.h" +// #if ENABLE(APPLE_PAY) +// #include "ApplePayCancelEvent.h" +// #include "JSApplePayCancelEvent.h" +// #endif +// #if ENABLE(APPLE_PAY_COUPON_CODE) +// #include "ApplePayCouponCodeChangedEvent.h" +// #include "JSApplePayCouponCodeChangedEvent.h" +// #endif +// #if ENABLE(APPLE_PAY) +// #include "ApplePayPaymentAuthorizedEvent.h" +// #include "JSApplePayPaymentAuthorizedEvent.h" +// #endif +// #if ENABLE(APPLE_PAY) +// #include "ApplePayPaymentMethodSelectedEvent.h" +// #include "JSApplePayPaymentMethodSelectedEvent.h" +// #endif +// #if ENABLE(APPLE_PAY) +// #include "ApplePayShippingContactSelectedEvent.h" +// #include "JSApplePayShippingContactSelectedEvent.h" +// #endif +// #if ENABLE(APPLE_PAY) +// #include "ApplePayShippingMethodSelectedEvent.h" +// #include "JSApplePayShippingMethodSelectedEvent.h" +// #endif +// #if ENABLE(APPLE_PAY) +// #include "ApplePayValidateMerchantEvent.h" +// #include "JSApplePayValidateMerchantEvent.h" +// #endif +// #if ENABLE(WEB_AUDIO) +// #include "AudioProcessingEvent.h" +// #include "JSAudioProcessingEvent.h" +// #endif +#include "Event.h" +#include "JSEvent.h" +// #include "BeforeUnloadEvent.h" +// #include "JSBeforeUnloadEvent.h" +// #if ENABLE(MEDIA_RECORDER) +// #include "BlobEvent.h" +// #include "JSBlobEvent.h" +// #endif +// #include "ClipboardEvent.h" +// #include "JSClipboardEvent.h" +// #include "CloseEvent.h" +// #include "JSCloseEvent.h" +// #include "CompositionEvent.h" +// #include "JSCompositionEvent.h" +// #include "CustomEvent.h" +// #include "JSCustomEvent.h" +// #if ENABLE(DEVICE_ORIENTATION) +// #include "DeviceMotionEvent.h" +// #include "JSDeviceMotionEvent.h" +// #endif +// #if ENABLE(DEVICE_ORIENTATION) +// #include "DeviceOrientationEvent.h" +// #include "JSDeviceOrientationEvent.h" +// #endif +// #include "DragEvent.h" +// #include "JSDragEvent.h" +#include "ErrorEvent.h" +#include "JSErrorEvent.h" +// #if ENABLE(SERVICE_WORKER) +// #include "ExtendableEvent.h" +// #include "JSExtendableEvent.h" +// #endif +// #if ENABLE(SERVICE_WORKER) +// #include "ExtendableMessageEvent.h" +// #include "JSExtendableMessageEvent.h" +// #endif +// #if ENABLE(SERVICE_WORKER) +// #include "FetchEvent.h" +// #include "JSFetchEvent.h" +// #endif +// #include "FocusEvent.h" +// #include "JSFocusEvent.h" +// #include "FormDataEvent.h" +// #include "JSFormDataEvent.h" +// #if ENABLE(GAMEPAD) +// #include "GamepadEvent.h" +// #include "JSGamepadEvent.h" +// #endif +// #if ENABLE(IOS_GESTURE_EVENTS) || ENABLE(MAC_GESTURE_EVENTS) +// #include "GestureEvent.h" +// #include "JSGestureEvent.h" +// #endif +// #include "HashChangeEvent.h" +// #include "JSHashChangeEvent.h" +// #include "IDBVersionChangeEvent.h" +// #include "JSIDBVersionChangeEvent.h" +// #include "InputEvent.h" +// #include "JSInputEvent.h" +// #include "KeyboardEvent.h" +// #include "JSKeyboardEvent.h" +// #if ENABLE(ENCRYPTED_MEDIA) +// #include "MediaEncryptedEvent.h" +// #include "JSMediaEncryptedEvent.h" +// #endif +// #if ENABLE(ENCRYPTED_MEDIA) +// #include "MediaKeyMessageEvent.h" +// #include "JSMediaKeyMessageEvent.h" +// #endif +// #include "MediaQueryListEvent.h" +// #include "JSMediaQueryListEvent.h" +// #if ENABLE(MEDIA_RECORDER) +// #include "MediaRecorderErrorEvent.h" +// #include "JSMediaRecorderErrorEvent.h" +// #endif +// #if ENABLE(MEDIA_STREAM) +// #include "MediaStreamTrackEvent.h" +// #include "JSMediaStreamTrackEvent.h" +// #endif +// #if ENABLE(PAYMENT_REQUEST) +// #include "MerchantValidationEvent.h" +// #include "JSMerchantValidationEvent.h" +// #endif +// #include "MessageEvent.h" +// #include "JSMessageEvent.h" +// #include "MouseEvent.h" +// #include "JSMouseEvent.h" +// #include "MutationEvent.h" +// #include "JSMutationEvent.h" +// #if ENABLE(NOTIFICATION_EVENT) +// #include "NotificationEvent.h" +// #include "JSNotificationEvent.h" +// #endif +// #if ENABLE(WEB_AUDIO) +// #include "OfflineAudioCompletionEvent.h" +// #include "JSOfflineAudioCompletionEvent.h" +// #endif +// #if ENABLE(MEDIA_STREAM) +// #include "OverconstrainedErrorEvent.h" +// #include "JSOverconstrainedErrorEvent.h" +// #endif +// #include "OverflowEvent.h" +// #include "JSOverflowEvent.h" +// #include "PageTransitionEvent.h" +// #include "JSPageTransitionEvent.h" +// #if ENABLE(PAYMENT_REQUEST) +// #include "PaymentMethodChangeEvent.h" +// #include "JSPaymentMethodChangeEvent.h" +// #endif +// #if ENABLE(PAYMENT_REQUEST) +// #include "PaymentRequestUpdateEvent.h" +// #include "JSPaymentRequestUpdateEvent.h" +// #endif +// #if ENABLE(PICTURE_IN_PICTURE_API) +// #include "PictureInPictureEvent.h" +// #include "JSPictureInPictureEvent.h" +// #endif +// #include "PointerEvent.h" +// #include "JSPointerEvent.h" +// #include "PopStateEvent.h" +// #include "JSPopStateEvent.h" +// #include "ProgressEvent.h" +// #include "JSProgressEvent.h" +// #include "PromiseRejectionEvent.h" +// #include "JSPromiseRejectionEvent.h" +// #if ENABLE(SERVICE_WORKER) +// #include "PushEvent.h" +// #include "JSPushEvent.h" +// #endif +// #if ENABLE(SERVICE_WORKER) +// #include "PushSubscriptionChangeEvent.h" +// #include "JSPushSubscriptionChangeEvent.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "RTCDTMFToneChangeEvent.h" +// #include "JSRTCDTMFToneChangeEvent.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "RTCDataChannelEvent.h" +// #include "JSRTCDataChannelEvent.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "RTCErrorEvent.h" +// #include "JSRTCErrorEvent.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "RTCPeerConnectionIceErrorEvent.h" +// #include "JSRTCPeerConnectionIceErrorEvent.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "RTCPeerConnectionIceEvent.h" +// #include "JSRTCPeerConnectionIceEvent.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "RTCRtpSFrameTransformErrorEvent.h" +// #include "JSRTCRtpSFrameTransformErrorEvent.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "RTCTrackEvent.h" +// #include "JSRTCTrackEvent.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "RTCTransformEvent.h" +// #include "JSRTCTransformEvent.h" +// #endif +// #include "SVGZoomEvent.h" +// #include "JSSVGZoomEvent.h" +// #include "SecurityPolicyViolationEvent.h" +// #include "JSSecurityPolicyViolationEvent.h" +// #include "SpeechRecognitionErrorEvent.h" +// #include "JSSpeechRecognitionErrorEvent.h" +// #include "SpeechRecognitionEvent.h" +// #include "JSSpeechRecognitionEvent.h" +// #if ENABLE(SPEECH_SYNTHESIS) +// #include "SpeechSynthesisErrorEvent.h" +// #include "JSSpeechSynthesisErrorEvent.h" +// #endif +// #if ENABLE(SPEECH_SYNTHESIS) +// #include "SpeechSynthesisEvent.h" +// #include "JSSpeechSynthesisEvent.h" +// #endif +// #include "StorageEvent.h" +// #include "JSStorageEvent.h" +// #include "SubmitEvent.h" +// #include "JSSubmitEvent.h" +// #include "TextEvent.h" +// #include "JSTextEvent.h" +// #if ENABLE(TOUCH_EVENTS) +// #include "TouchEvent.h" +// #include "JSTouchEvent.h" +// #endif +// #if ENABLE(VIDEO) +// #include "TrackEvent.h" +// #include "JSTrackEvent.h" +// #endif +// #include "TransitionEvent.h" +// #include "JSTransitionEvent.h" +// #include "UIEvent.h" +// #include "JSUIEvent.h" +// #if ENABLE(WEBGL) +// #include "WebGLContextEvent.h" +// #include "JSWebGLContextEvent.h" +// #endif +// #if ENABLE(LEGACY_ENCRYPTED_MEDIA) +// #include "WebKitMediaKeyMessageEvent.h" +// #include "JSWebKitMediaKeyMessageEvent.h" +// #endif +// #if ENABLE(LEGACY_ENCRYPTED_MEDIA) +// #include "WebKitMediaKeyNeededEvent.h" +// #include "JSWebKitMediaKeyNeededEvent.h" +// #endif +// #if ENABLE(WIRELESS_PLAYBACK_TARGET) +// #include "WebKitPlaybackTargetAvailabilityEvent.h" +// #include "JSWebKitPlaybackTargetAvailabilityEvent.h" +// #endif +// #include "WheelEvent.h" +// #include "JSWheelEvent.h" +// #include "XMLHttpRequestProgressEvent.h" +// #include "JSXMLHttpRequestProgressEvent.h" +// #if ENABLE(WEBXR) +// #include "XRInputSourceEvent.h" +// #include "JSXRInputSourceEvent.h" +// #endif +// #if ENABLE(WEBXR) +// #include "XRInputSourcesChangeEvent.h" +// #include "JSXRInputSourcesChangeEvent.h" +// #endif +// #if ENABLE(WEBXR) +// #include "XRReferenceSpaceEvent.h" +// #include "JSXRReferenceSpaceEvent.h" +// #endif +// #if ENABLE(WEBXR) +// #include "XRSessionEvent.h" +// #include "JSXRSessionEvent.h" +// #endif + +#endif // EventHeaders_h diff --git a/src/javascript/jsc/bindings/webcore/EventInit.h b/src/javascript/jsc/bindings/webcore/EventInit.h new file mode 100644 index 000000000..0e588593c --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventInit.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016-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 + +namespace WebCore { + +struct EventInit { + bool bubbles { false }; + bool cancelable { false }; + bool composed { false }; + + template<class Encoder> void encode(Encoder&) const; + template<class Decoder> static WARN_UNUSED_RETURN bool decode(Decoder&, EventInit&); +}; + +template<class Encoder> +void EventInit::encode(Encoder& encoder) const +{ + encoder << bubbles; + encoder << cancelable; + encoder << composed; +} + +template<class Decoder> +bool EventInit::decode(Decoder& decoder, EventInit& eventInit) +{ + if (!decoder.decode(eventInit.bubbles)) + return false; + if (!decoder.decode(eventInit.cancelable)) + return false; + if (!decoder.decode(eventInit.composed)) + return false; + return true; +} + +} diff --git a/src/javascript/jsc/bindings/webcore/EventInit.idl b/src/javascript/jsc/bindings/webcore/EventInit.idl new file mode 100644 index 000000000..e55a03034 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventInit.idl @@ -0,0 +1,30 @@ +/* + * 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 + * 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. + */ + +dictionary EventInit { + boolean bubbles = false; + boolean cancelable = false; + boolean composed = false; +}; diff --git a/src/javascript/jsc/bindings/webcore/EventInterfaces.h b/src/javascript/jsc/bindings/webcore/EventInterfaces.h new file mode 100644 index 000000000..5bb0962b6 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventInterfaces.h @@ -0,0 +1,165 @@ +/* + * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. + * + * Copyright (C) 2011 Google 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 GOOGLE, INC. ``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 + * 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 + +namespace WebCore { + +enum EventInterface { +#if ENABLE(APPLE_PAY) + ApplePayCancelEventInterfaceType = 1, + ApplePayPaymentAuthorizedEventInterfaceType = 2, + ApplePayPaymentMethodSelectedEventInterfaceType = 3, + ApplePayShippingContactSelectedEventInterfaceType = 4, + ApplePayShippingMethodSelectedEventInterfaceType = 5, + ApplePayValidateMerchantEventInterfaceType = 6, +#endif +#if ENABLE(APPLE_PAY_COUPON_CODE) + ApplePayCouponCodeChangedEventInterfaceType = 7, +#endif +#if ENABLE(DEVICE_ORIENTATION) + DeviceMotionEventInterfaceType = 8, + DeviceOrientationEventInterfaceType = 9, +#endif +#if ENABLE(ENCRYPTED_MEDIA) + MediaEncryptedEventInterfaceType = 10, + MediaKeyMessageEventInterfaceType = 11, +#endif +#if ENABLE(GAMEPAD) + GamepadEventInterfaceType = 12, +#endif +#if ENABLE(IOS_GESTURE_EVENTS) || ENABLE(MAC_GESTURE_EVENTS) + GestureEventInterfaceType = 13, +#endif +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + WebKitMediaKeyMessageEventInterfaceType = 14, + WebKitMediaKeyNeededEventInterfaceType = 15, +#endif +#if ENABLE(MEDIA_RECORDER) + BlobEventInterfaceType = 16, + MediaRecorderErrorEventInterfaceType = 17, +#endif +#if ENABLE(MEDIA_STREAM) + MediaStreamTrackEventInterfaceType = 18, + OverconstrainedErrorEventInterfaceType = 19, +#endif +#if ENABLE(NOTIFICATION_EVENT) + NotificationEventInterfaceType = 20, +#endif +#if ENABLE(ORIENTATION_EVENTS) +#endif +#if ENABLE(PAYMENT_REQUEST) + MerchantValidationEventInterfaceType = 21, + PaymentMethodChangeEventInterfaceType = 22, + PaymentRequestUpdateEventInterfaceType = 23, +#endif +#if ENABLE(PICTURE_IN_PICTURE_API) + PictureInPictureEventInterfaceType = 24, +#endif +#if ENABLE(SERVICE_WORKER) + ExtendableEventInterfaceType = 25, + ExtendableMessageEventInterfaceType = 26, + FetchEventInterfaceType = 27, + PushEventInterfaceType = 28, + PushSubscriptionChangeEventInterfaceType = 29, +#endif +#if ENABLE(SPEECH_SYNTHESIS) + SpeechSynthesisErrorEventInterfaceType = 30, + SpeechSynthesisEventInterfaceType = 31, +#endif +#if ENABLE(TOUCH_EVENTS) + TouchEventInterfaceType = 32, +#endif +#if ENABLE(VIDEO) + TrackEventInterfaceType = 33, +#endif +#if ENABLE(WEBGL) + WebGLContextEventInterfaceType = 34, +#endif +#if ENABLE(WEBXR) + XRInputSourceEventInterfaceType = 35, + XRInputSourcesChangeEventInterfaceType = 36, + XRReferenceSpaceEventInterfaceType = 37, + XRSessionEventInterfaceType = 38, +#endif +#if ENABLE(WEB_AUDIO) + AudioProcessingEventInterfaceType = 39, + OfflineAudioCompletionEventInterfaceType = 40, +#endif +#if ENABLE(WEB_RTC) + RTCDTMFToneChangeEventInterfaceType = 41, + RTCDataChannelEventInterfaceType = 42, + RTCErrorEventInterfaceType = 43, + RTCPeerConnectionIceErrorEventInterfaceType = 44, + RTCPeerConnectionIceEventInterfaceType = 45, + RTCRtpSFrameTransformErrorEventInterfaceType = 46, + RTCTrackEventInterfaceType = 47, + RTCTransformEventInterfaceType = 48, +#endif +#if ENABLE(WIRELESS_PLAYBACK_TARGET) + WebKitPlaybackTargetAvailabilityEventInterfaceType = 49, +#endif + AnimationEventInterfaceType = 50, + AnimationPlaybackEventInterfaceType = 51, + BeforeUnloadEventInterfaceType = 52, + ClipboardEventInterfaceType = 53, + CloseEventInterfaceType = 54, + CompositionEventInterfaceType = 55, + CustomEventInterfaceType = 56, + DragEventInterfaceType = 57, + ErrorEventInterfaceType = 58, + EventInterfaceType = 59, + FocusEventInterfaceType = 60, + FormDataEventInterfaceType = 61, + HashChangeEventInterfaceType = 62, + IDBVersionChangeEventInterfaceType = 63, + InputEventInterfaceType = 64, + KeyboardEventInterfaceType = 65, + MediaQueryListEventInterfaceType = 66, + MessageEventInterfaceType = 67, + MouseEventInterfaceType = 68, + MutationEventInterfaceType = 69, + OverflowEventInterfaceType = 70, + PageTransitionEventInterfaceType = 71, + PointerEventInterfaceType = 72, + PopStateEventInterfaceType = 73, + ProgressEventInterfaceType = 74, + PromiseRejectionEventInterfaceType = 75, + SVGZoomEventInterfaceType = 76, + SecurityPolicyViolationEventInterfaceType = 77, + SpeechRecognitionErrorEventInterfaceType = 78, + SpeechRecognitionEventInterfaceType = 79, + StorageEventInterfaceType = 80, + SubmitEventInterfaceType = 81, + TextEventInterfaceType = 82, + TransitionEventInterfaceType = 83, + UIEventInterfaceType = 84, + WheelEventInterfaceType = 85, + XMLHttpRequestProgressEventInterfaceType = 86, +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventListener.h b/src/javascript/jsc/bindings/webcore/EventListener.h new file mode 100644 index 000000000..7ceb38b1e --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventListener.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2006-2021 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +#include <wtf/RefCounted.h> +#include <wtf/WeakPtr.h> + +namespace JSC { +class AbstractSlotVisitor; +class JSObject; +class SlotVisitor; +} + +namespace WebCore { + +class ScriptExecutionContext; +class Event; +class EventTarget; + +class EventListener : public RefCounted<EventListener>, public CanMakeWeakPtr<EventListener> { +public: + enum Type { + JSEventListenerType, + ImageEventListenerType, + ObjCEventListenerType, + CPPEventListenerType, + ConditionEventListenerType, + GObjectEventListenerType, + NativeEventListenerType, + SVGTRefTargetEventListenerType, + PDFDocumentEventListenerType, + }; + + virtual ~EventListener() = default; + virtual bool operator==(const EventListener&) const = 0; + virtual void handleEvent(ScriptExecutionContext&, Event&) = 0; + + virtual void visitJSFunction(JSC::AbstractSlotVisitor&) { } + virtual void visitJSFunction(JSC::SlotVisitor&) { } + + virtual bool isAttribute() const { return false; } + Type type() const { return m_type; } + +#if ASSERT_ENABLED + virtual void checkValidityForEventTarget(EventTarget&) { } +#endif + + virtual JSC::JSObject* jsFunction() const { return nullptr; } + virtual JSC::JSObject* wrapper() const { return nullptr; } + +protected: + explicit EventListener(Type type) + : m_type(type) + { + } + +private: + Type m_type; +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventListener.idl b/src/javascript/jsc/bindings/webcore/EventListener.idl new file mode 100644 index 000000000..5813a3500 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventListener.idl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2006 Apple Inc. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +// https://dom.spec.whatwg.org/#callbackdef-eventlistener +// FIXME: This should be a callback interface. +[ + LegacyNoInterfaceObject +] interface EventListener { + undefined handleEvent(Event event); +}; diff --git a/src/javascript/jsc/bindings/webcore/EventListenerMap.cpp b/src/javascript/jsc/bindings/webcore/EventListenerMap.cpp new file mode 100644 index 000000000..5014cfa00 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventListenerMap.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2011 Andreas Kling (kling@webkit.org) + * + * 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. ``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 + * 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. + * + */ + +#include "config.h" +#include "EventListenerMap.h" + +#include "AddEventListenerOptions.h" +#include "Event.h" +#include "EventTarget.h" +#include "JSEventListener.h" +#include <wtf/MainThread.h> +#include <wtf/StdLibExtras.h> +#include <wtf/Vector.h> + + +namespace WebCore { + +EventListenerMap::EventListenerMap() = default; + +bool EventListenerMap::containsCapturing(const AtomString& eventType) const +{ + auto* listeners = find(eventType); + if (!listeners) + return false; + + for (auto& eventListener : *listeners) { + if (eventListener->useCapture()) + return true; + } + return false; +} + +bool EventListenerMap::containsActive(const AtomString& eventType) const +{ + auto* listeners = find(eventType); + if (!listeners) + return false; + + for (auto& eventListener : *listeners) { + if (!eventListener->isPassive()) + return true; + } + return false; +} + +void EventListenerMap::clear() +{ + Locker locker { m_lock }; + + for (auto& entry : m_entries) { + for (auto& listener : entry.second) + listener->markAsRemoved(); + } + + m_entries.clear(); +} + +Vector<AtomString> EventListenerMap::eventTypes() const +{ + return m_entries.map([](auto& entry) { + return entry.first; + }); +} + +static inline size_t findListener(const EventListenerVector& listeners, EventListener& listener, bool useCapture) +{ + for (size_t i = 0; i < listeners.size(); ++i) { + auto& registeredListener = listeners[i]; + if (registeredListener->callback() == listener && registeredListener->useCapture() == useCapture) + return i; + } + return notFound; +} + +void EventListenerMap::replace(const AtomString& eventType, EventListener& oldListener, Ref<EventListener>&& newListener, const RegisteredEventListener::Options& options) +{ + Locker locker { m_lock }; + + auto* listeners = find(eventType); + ASSERT(listeners); + size_t index = findListener(*listeners, oldListener, options.capture); + ASSERT(index != notFound); + auto& registeredListener = listeners->at(index); + registeredListener->markAsRemoved(); + registeredListener = RegisteredEventListener::create(WTFMove(newListener), options); +} + +bool EventListenerMap::add(const AtomString& eventType, Ref<EventListener>&& listener, const RegisteredEventListener::Options& options) +{ + Locker locker { m_lock }; + + if (auto* listeners = find(eventType)) { + if (findListener(*listeners, listener, options.capture) != notFound) + return false; // Duplicate listener. + listeners->append(RegisteredEventListener::create(WTFMove(listener), options)); + return true; + } + + m_entries.append({ eventType, EventListenerVector { RegisteredEventListener::create(WTFMove(listener), options) } }); + return true; +} + +static bool removeListenerFromVector(EventListenerVector& listeners, EventListener& listener, bool useCapture) +{ + size_t indexOfRemovedListener = findListener(listeners, listener, useCapture); + if (UNLIKELY(indexOfRemovedListener == notFound)) + return false; + + listeners[indexOfRemovedListener]->markAsRemoved(); + listeners.remove(indexOfRemovedListener); + return true; +} + +bool EventListenerMap::remove(const AtomString& eventType, EventListener& listener, bool useCapture) +{ + Locker locker { m_lock }; + + for (unsigned i = 0; i < m_entries.size(); ++i) { + if (m_entries[i].first == eventType) { + bool wasRemoved = removeListenerFromVector(m_entries[i].second, listener, useCapture); + if (m_entries[i].second.isEmpty()) + m_entries.remove(i); + return wasRemoved; + } + } + + return false; +} + +EventListenerVector* EventListenerMap::find(const AtomString& eventType) +{ + for (auto& entry : m_entries) { + if (entry.first == eventType) + return &entry.second; + } + + return nullptr; +} + +static void removeFirstListenerCreatedFromMarkup(EventListenerVector& listenerVector) +{ + bool foundListener = listenerVector.removeFirstMatching([] (const auto& registeredListener) { + if (JSEventListener::wasCreatedFromMarkup(registeredListener->callback())) { + registeredListener->markAsRemoved(); + return true; + } + return false; + }); + ASSERT_UNUSED(foundListener, foundListener); +} + +void EventListenerMap::removeFirstEventListenerCreatedFromMarkup(const AtomString& eventType) +{ + Locker locker { m_lock }; + + for (unsigned i = 0; i < m_entries.size(); ++i) { + if (m_entries[i].first == eventType) { + removeFirstListenerCreatedFromMarkup(m_entries[i].second); + if (m_entries[i].second.isEmpty()) + m_entries.remove(i); + return; + } + } +} + +static void copyListenersNotCreatedFromMarkupToTarget(const AtomString& eventType, EventListenerVector& listenerVector, EventTarget* target) +{ + for (auto& registeredListener : listenerVector) { + // Event listeners created from markup have already been transfered to the shadow tree during cloning. + if (JSEventListener::wasCreatedFromMarkup(registeredListener->callback())) + continue; + target->addEventListener(eventType, registeredListener->callback(), registeredListener->useCapture()); + } +} + +void EventListenerMap::copyEventListenersNotCreatedFromMarkupToTarget(EventTarget* target) +{ + for (auto& entry : m_entries) + copyListenersNotCreatedFromMarkupToTarget(entry.first, entry.second, target); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventListenerMap.h b/src/javascript/jsc/bindings/webcore/EventListenerMap.h new file mode 100644 index 000000000..d5b83c220 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventListenerMap.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2011 Andreas Kling (kling@webkit.org) + * + * 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. ``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 + * 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 "RegisteredEventListener.h" +#include <atomic> +#include <memory> +#include <wtf/Forward.h> +#include <wtf/Lock.h> +#include <wtf/text/AtomString.h> + +namespace WebCore { + +class EventTarget; + +using EventListenerVector = Vector<RefPtr<RegisteredEventListener>, 1, CrashOnOverflow, 2>; + +class EventListenerMap { +public: + EventListenerMap(); + + bool isEmpty() const { return m_entries.isEmpty(); } + bool contains(const AtomString& eventType) const { return find(eventType); } + bool containsCapturing(const AtomString& eventType) const; + bool containsActive(const AtomString& eventType) const; + + void clear(); + + void replace(const AtomString& eventType, EventListener& oldListener, Ref<EventListener>&& newListener, const RegisteredEventListener::Options&); + bool add(const AtomString& eventType, Ref<EventListener>&&, const RegisteredEventListener::Options&); + bool remove(const AtomString& eventType, EventListener&, bool useCapture); + WEBCORE_EXPORT EventListenerVector* find(const AtomString& eventType); + const EventListenerVector* find(const AtomString& eventType) const { return const_cast<EventListenerMap*>(this)->find(eventType); } + Vector<AtomString> eventTypes() const; + + void removeFirstEventListenerCreatedFromMarkup(const AtomString& eventType); + void copyEventListenersNotCreatedFromMarkupToTarget(EventTarget*); + + template<typename Visitor> void visitJSEventListeners(Visitor&); + Lock& lock() { return m_lock; } + +private: + Vector<std::pair<AtomString, EventListenerVector>> m_entries; + Lock m_lock; +}; + +template<typename Visitor> +void EventListenerMap::visitJSEventListeners(Visitor& visitor) +{ + Locker locker { m_lock }; + for (auto& entry : m_entries) { + for (auto& eventListener : entry.second) + eventListener->callback().visitJSFunction(visitor); + } +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventListenerOptions.h b/src/javascript/jsc/bindings/webcore/EventListenerOptions.h new file mode 100644 index 000000000..101b44bce --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventListenerOptions.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016-2020 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. ``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 + * 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 + +namespace WebCore { + +struct EventListenerOptions { + EventListenerOptions(bool capture = false) + : capture(capture) + { } + + bool capture { false }; +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventListenerOptions.idl b/src/javascript/jsc/bindings/webcore/EventListenerOptions.idl new file mode 100644 index 000000000..70bb94225 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventListenerOptions.idl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016-2020 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. ``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 + * 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. + */ + +dictionary EventListenerOptions { + boolean capture = false; +}; diff --git a/src/javascript/jsc/bindings/webcore/EventModifierInit.h b/src/javascript/jsc/bindings/webcore/EventModifierInit.h new file mode 100644 index 000000000..82fe54e17 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventModifierInit.h @@ -0,0 +1,42 @@ +/* + * 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 + * 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 "UIEventInit.h" + +namespace WebCore { + +struct EventModifierInit : UIEventInit { + bool ctrlKey { false }; + bool shiftKey { false }; + bool altKey { false }; + bool metaKey { false }; + + bool modifierAltGraph { false }; + bool modifierCapsLock { false }; +}; + +} diff --git a/src/javascript/jsc/bindings/webcore/EventNames.cpp b/src/javascript/jsc/bindings/webcore/EventNames.cpp new file mode 100644 index 000000000..a15b086e2 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventNames.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005, 2015 Apple Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "EventNames.h" + +namespace WebCore { + +#define INITIALIZE_EVENT_NAME(name) \ + name##Event(#name, AtomString::ConstructFromLiteral), + +EventNames::EventNames() + : DOM_EVENT_NAMES_FOR_EACH(INITIALIZE_EVENT_NAME) dummy(0) +{ +} + +thread_local std::unique_ptr<EventNames> eventNames_; + +const EventNames& eventNames() +{ + if (!eventNames_) + eventNames_ = EventNames::create(); + return *eventNames_; +} + +} diff --git a/src/javascript/jsc/bindings/webcore/EventNames.h b/src/javascript/jsc/bindings/webcore/EventNames.h new file mode 100644 index 000000000..3938d62ca --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventNames.h @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2005, 2007, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2006 Jon Shier (jshier@iastate.edu) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +// #include "ThreadGlobalData.h" +#include "EventTarget.h" +#include <array> +#include <functional> +#include <wtf/text/AtomString.h> + +namespace WebCore { + +#define DOM_EVENT_NAMES_FOR_EACH(macro) \ + macro(error) \ + macro(abort) +// + +// macro(DOMActivate) \ + // macro(DOMCharacterDataModified) \ + // macro(DOMContentLoaded) \ + // macro(DOMNodeInserted) \ + // macro(DOMNodeInsertedIntoDocument) \ + // macro(DOMNodeRemoved) \ + // macro(DOMNodeRemovedFromDocument) \ + // macro(DOMSubtreeModified) \ + // macro(abort) \ + // macro(activate) \ + // macro(active) \ + // macro(addsourcebuffer) \ + // macro(addstream) \ + // macro(addtrack) \ + // macro(afterprint) \ + // macro(animationcancel) \ + // macro(animationend) \ + // macro(animationiteration) \ + // macro(animationstart) \ + // macro(audioend) \ + // macro(audioprocess) \ + // macro(audiostart) \ + // macro(autocomplete) \ + // macro(autocompleteerror) \ + // macro(beforecopy) \ + // macro(beforecut) \ + // macro(beforeinput) \ + // macro(beforeload) \ + // macro(beforepaste) \ + // macro(beforeprint) \ + // macro(beforeunload) \ + // macro(beginEvent) \ + // macro(blocked) \ + // macro(blur) \ + // macro(boundary) \ + // macro(bufferedamountlow) \ + // macro(cached) \ + // macro(cancel) \ + // macro(canplay) \ + // macro(canplaythrough) \ + // macro(change) \ + // macro(chargingchange) \ + // macro(chargingtimechange) \ + // macro(checking) \ + // macro(click) \ + // macro(close) \ + // macro(closing) \ + // macro(complete) \ + // macro(compositionend) \ + // macro(compositionstart) \ + // macro(compositionupdate) \ + // macro(connect) \ + // macro(connectionstatechange) \ + // macro(connecting) \ + // macro(contextmenu) \ + // macro(controllerchange) \ + // macro(coordinatorstatechange) \ + // macro(copy) \ + // macro(cuechange) \ + // macro(cut) \ + // macro(dataavailable) \ + // macro(datachannel) \ + // macro(dblclick) \ + // macro(devicechange) \ + // macro(devicemotion) \ + // macro(deviceorientation) \ + // macro(dischargingtimechange) \ + // macro(disconnect) \ + // macro(downloading) \ + // macro(drag) \ + // macro(dragend) \ + // macro(dragenter) \ + // macro(dragleave) \ + // macro(dragover) \ + // macro(dragstart) \ + // macro(drop) \ + // macro(durationchange) \ + // macro(emptied) \ + // macro(encrypted) \ + // macro(end) \ + // macro(endEvent) \ + // macro(ended) \ + // macro(enter) \ + // macro(enterpictureinpicture) \ + // macro(error) \ + // macro(exit) \ + // macro(fetch) \ + // macro(finish) \ + // macro(focus) \ + // macro(focusin) \ + // macro(focusout) \ + // macro(formdata) \ + // macro(gamepadconnected) \ + // macro(gamepaddisconnected) \ + // macro(gatheringstatechange) \ + // macro(gesturechange) \ + // macro(gestureend) \ + // macro(gesturescrollend) \ + // macro(gesturescrollstart) \ + // macro(gesturescrollupdate) \ + // macro(gesturestart) \ + // macro(gesturetap) \ + // macro(gesturetapdown) \ + // macro(gotpointercapture) \ + // macro(hashchange) \ + // macro(icecandidate) \ + // macro(icecandidateerror) \ + // macro(iceconnectionstatechange) \ + // macro(icegatheringstatechange) \ + // macro(inactive) \ + // macro(input) \ + // macro(inputsourceschange) \ + // macro(install) \ + // macro(invalid) \ + // macro(keydown) \ + // macro(keypress) \ + // macro(keystatuseschange) \ + // macro(keyup) \ + // macro(languagechange) \ + // macro(leavepictureinpicture) \ + // macro(levelchange) \ + // macro(load) \ + // macro(loadeddata) \ + // macro(loadedmetadata) \ + // macro(loadend) \ + // macro(loading) \ + // macro(loadingdone) \ + // macro(loadingerror) \ + // macro(loadstart) \ + // macro(lostpointercapture) \ + // macro(mark) \ + // macro(merchantvalidation) \ + // macro(message) \ + // macro(messageerror) \ + // macro(mousedown) \ + // macro(mouseenter) \ + // macro(mouseleave) \ + // macro(mousemove) \ + // macro(mouseout) \ + // macro(mouseover) \ + // macro(mouseup) \ + // macro(mousewheel) \ + // macro(mute) \ + // macro(negotiationneeded) \ + // macro(nexttrack) \ + // macro(nomatch) \ + // macro(notificationclick) \ + // macro(notificationclose) \ + // macro(noupdate) \ + // macro(obsolete) \ + // macro(offline) \ + // macro(online) \ + // macro(open) \ + // macro(orientationchange) \ + // macro(overflowchanged) \ + // macro(pagehide) \ + // macro(pageshow) \ + // macro(paste) \ + // macro(pause) \ + // macro(payerdetailchange) \ + // macro(paymentauthorized) \ + // macro(paymentmethodchange) \ + // macro(paymentmethodselected) \ + // macro(play) \ + // macro(playing) \ + // macro(pointerlockchange) \ + // macro(pointerlockerror) \ + // macro(pointercancel) \ + // macro(pointerdown) \ + // macro(pointerenter) \ + // macro(pointerleave) \ + // macro(pointermove) \ + // macro(pointerout) \ + // macro(pointerover) \ + // macro(pointerup) \ + // macro(popstate) \ + // macro(previoustrack) \ + // macro(processorerror) \ + // macro(progress) \ + // macro(push) \ + // macro(pushsubscriptionchange) \ + // macro(ratechange) \ + // macro(readystatechange) \ + // macro(rejectionhandled) \ + // macro(remove) \ + // macro(removesourcebuffer) \ + // macro(removestream) \ + // macro(removetrack) \ + // macro(reset) \ + // macro(resize) \ + // macro(resourcetimingbufferfull) \ + // macro(result) \ + // macro(resume) \ + // macro(rtctransform) \ + // macro(scroll) \ + // macro(search) \ + // macro(securitypolicyviolation) \ + // macro(seeked) \ + // macro(seeking) \ + // macro(select) \ + // macro(selectend) \ + // macro(selectionchange) \ + // macro(selectstart) \ + // macro(shippingaddresschange) \ + // macro(shippingcontactselected) \ + // macro(shippingmethodselected) \ + // macro(shippingoptionchange) \ + // macro(show) \ + // macro(signalingstatechange) \ + // macro(slotchange) \ + // macro(soundend) \ + // macro(soundstart) \ + // macro(sourceclose) \ + // macro(sourceended) \ + // macro(sourceopen) \ + // macro(speechend) \ + // macro(speechstart) \ + // macro(squeeze) \ + // macro(squeezestart) \ + // macro(squeezeend) \ + // macro(stalled) \ + // macro(start) \ + // macro(started) \ + // macro(statechange) \ + // macro(stop) \ + // macro(storage) \ + // macro(submit) \ + // macro(success) \ + // macro(suspend) \ + // macro(textInput) \ + // macro(timeout) \ + // macro(timeupdate) \ + // macro(toggle) \ + // macro(tonechange) \ + // macro(touchcancel) \ + // macro(touchend) \ + // macro(touchforcechange) \ + // macro(touchmove) \ + // macro(touchstart) \ + // macro(track) \ + // macro(transitioncancel) \ + // macro(transitionend) \ + // macro(transitionrun) \ + // macro(transitionstart) \ + // macro(uncapturederror) \ + // macro(unhandledrejection) \ + // macro(unload) \ + // macro(unmute) \ + // macro(update) \ + // macro(updateend) \ + // macro(updatefound) \ + // macro(updateready) \ + // macro(updatestart) \ + // macro(upgradeneeded) \ + // macro(validatemerchant) \ + // macro(versionchange) \ + // macro(visibilitychange) \ + // macro(voiceschanged) \ + // macro(volumechange) \ + // macro(waiting) \ + // macro(waitingforkey) \ + // macro(webglcontextchanged) \ + // macro(webglcontextcreationerror) \ + // macro(webglcontextlost) \ + // macro(webglcontextrestored) \ + // macro(webkitAnimationEnd) \ + // macro(webkitAnimationIteration) \ + // macro(webkitAnimationStart) \ + // macro(webkitBeforeTextInserted) \ + // macro(webkitTransitionEnd) \ + // macro(webkitbeginfullscreen) \ + // macro(webkitcurrentplaybacktargetiswirelesschanged) \ + // macro(webkitendfullscreen) \ + // macro(webkitfullscreenchange) \ + // macro(webkitfullscreenerror) \ + // macro(webkitkeyadded) \ + // macro(webkitkeyerror) \ + // macro(webkitkeymessage) \ + // macro(webkitmouseforcechanged) \ + // macro(webkitmouseforcedown) \ + // macro(webkitmouseforcewillbegin) \ + // macro(webkitmouseforceup) \ + // macro(webkitneedkey) \ + // macro(webkitnetworkinfochange) \ + // macro(webkitplaybacktargetavailabilitychanged) \ + // macro(webkitpresentationmodechanged) \ + // macro(webkitremovesourcebuffer) \ + // macro(webkitsourceclose) \ + // macro(webkitsourceended) \ + // macro(webkitsourceopen) \ + macro(wheel) \ + macro(write) \ + macro(writeend) \ + macro(writestart) \ + macro(zoom) \ +// end of DOM_EVENT_NAMES_FOR_EACH + +struct EventNames { + WTF_MAKE_NONCOPYABLE(EventNames); + WTF_MAKE_FAST_ALLOCATED; + +public: +#define DOM_EVENT_NAMES_DECLARE(name) const AtomString name##Event; + DOM_EVENT_NAMES_FOR_EACH(DOM_EVENT_NAMES_DECLARE) +#undef DOM_EVENT_NAMES_DECLARE + + // FIXME: The friend declaration to makeUnique below does not work in windows port. + // + // template<class T, class... Args> + // friend typename std::_Unique_if<T>::_Single_object makeUnique(Args&&...); + // + // This create function should be deleted later and is only for keeping EventNames as private. + // makeUnique should be used instead. + // + template<class... Args> + static std::unique_ptr<EventNames> create(Args&&... args) + { + return std::unique_ptr<EventNames>(new EventNames(std::forward<Args>(args)...)); + } + + // FIXME: Inelegant to call these both event names and event types. + // We should choose one term and stick to it. + bool isWheelEventType(const AtomString& eventType) const; + bool isGestureEventType(const AtomString& eventType) const; + bool isTouchRelatedEventType(const AtomString& eventType, EventTarget&) const; + bool isTouchScrollBlockingEventType(const AtomString& eventType) const; +#if ENABLE(GAMEPAD) + bool isGamepadEventType(const AtomString& eventType) const; +#endif + + std::array<std::reference_wrapper<const AtomString>, 0> touchRelatedEventNames() const; + std::array<std::reference_wrapper<const AtomString>, 0> extendedTouchRelatedEventNames() const; + std::array<std::reference_wrapper<const AtomString>, 0> gestureEventNames() const; + +private: + EventNames(); // Private to prevent accidental call to EventNames() instead of eventNames(). + // friend class ThreadGlobalData; // Allow ThreadGlobalData to create the per-thread EventNames object. + + int dummy; // Needed to make initialization macro work. +}; + +const EventNames& eventNames(); + +inline bool EventNames::isGestureEventType(const AtomString& eventType) const +{ + return false; // eventType == gesturestartEvent || eventType == gesturechangeEvent || eventType == gestureendEvent; +} + +inline bool EventNames::isTouchScrollBlockingEventType(const AtomString& eventType) const +{ + return false; +} + +inline bool EventNames::isTouchRelatedEventType(const AtomString& eventType, EventTarget& target) const +{ + return false; +} + +inline bool EventNames::isWheelEventType(const AtomString& eventType) const +{ + return false; +} + +inline std::array<std::reference_wrapper<const AtomString>, 0> EventNames::touchRelatedEventNames() const +{ + return { {} }; +} + +inline std::array<std::reference_wrapper<const AtomString>, 0> EventNames::extendedTouchRelatedEventNames() const +{ + return { {} }; +} + +inline std::array<std::reference_wrapper<const AtomString>, 0> EventNames::gestureEventNames() const +{ + return { {} }; +} + +// inline std::array<std::reference_wrapper<const AtomString>, 13> EventNames::touchRelatedEventNames() const +// { +// return { { touchstartEvent, touchmoveEvent, touchendEvent, touchcancelEvent, touchforcechangeEvent, pointeroverEvent, pointerenterEvent, pointerdownEvent, pointermoveEvent, pointerupEvent, pointeroutEvent, pointerleaveEvent, pointercancelEvent } }; +// } + +// inline std::array<std::reference_wrapper<const AtomString>, 16> EventNames::extendedTouchRelatedEventNames() const +// { +// return { { touchstartEvent, touchmoveEvent, touchendEvent, touchcancelEvent, touchforcechangeEvent, pointeroverEvent, pointerenterEvent, pointerdownEvent, pointermoveEvent, pointerupEvent, pointeroutEvent, pointerleaveEvent, pointercancelEvent, mousedownEvent, mousemoveEvent, mouseupEvent } }; +// } + +// inline std::array<std::reference_wrapper<const AtomString>, 3> EventNames::gestureEventNames() const +// { +// return { { gesturestartEvent, gesturechangeEvent, gestureendEvent } }; +// } + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventNames.in b/src/javascript/jsc/bindings/webcore/EventNames.in new file mode 100644 index 000000000..8c0fb6072 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventNames.in @@ -0,0 +1,101 @@ +namespace="Event" +factoryFunction=toNewlyCreated +useNamespaceAsSuffix=false + +Event +Events interfaceName=Event +HTMLEvents interfaceName=Event +AnimationEvent +AnimationPlaybackEvent +BeforeLoadEvent interfaceName=Event +BeforeUnloadEvent +ClipboardEvent +CloseEvent +CompositionEvent +CustomEvent +DragEvent +ExtendableEvent conditional=SERVICE_WORKER +ExtendableMessageEvent conditional=SERVICE_WORKER +ErrorEvent +FetchEvent conditional=SERVICE_WORKER +FocusEvent +FormDataEvent +HashChangeEvent +InputEvent +InputEvents interfaceName=InputEvent +KeyboardEvent +KeyboardEvents interfaceName=KeyboardEvent +MediaQueryListEvent +MessageEvent +MouseEvent +MouseEvents interfaceName=MouseEvent +MutationEvent +MutationEvents interfaceName=MutationEvent +OverflowEvent +PageTransitionEvent +PopStateEvent +ProgressEvent +PromiseRejectionEvent +PushEvent conditional=SERVICE_WORKER +PushSubscriptionChangeEvent conditional=SERVICE_WORKER +SubmitEvent +TextEvent +TransitionEvent +UIEvent +UIEvents interfaceName=UIEvent +WheelEvent +XMLHttpRequestProgressEvent +ApplePayCancelEvent conditional=APPLE_PAY +ApplePayCouponCodeChangedEvent conditional=APPLE_PAY_COUPON_CODE +ApplePayPaymentAuthorizedEvent conditional=APPLE_PAY +ApplePayPaymentMethodSelectedEvent conditional=APPLE_PAY +ApplePayShippingContactSelectedEvent conditional=APPLE_PAY +ApplePayShippingMethodSelectedEvent conditional=APPLE_PAY +ApplePayValidateMerchantEvent conditional=APPLE_PAY +AudioProcessingEvent conditional=WEB_AUDIO +BlobEvent conditional=MEDIA_RECORDER +OfflineAudioCompletionEvent conditional=WEB_AUDIO +MediaRecorderErrorEvent conditional=MEDIA_RECORDER +MediaStreamTrackEvent conditional=MEDIA_STREAM +MerchantValidationEvent conditional=PAYMENT_REQUEST +PaymentMethodChangeEvent conditional=PAYMENT_REQUEST +PaymentRequestUpdateEvent conditional=PAYMENT_REQUEST +RTCErrorEvent conditional=WEB_RTC +RTCPeerConnectionIceErrorEvent conditional=WEB_RTC +RTCPeerConnectionIceEvent conditional=WEB_RTC +RTCDataChannelEvent conditional=WEB_RTC +RTCDTMFToneChangeEvent conditional=WEB_RTC +RTCRtpSFrameTransformErrorEvent conditional=WEB_RTC +RTCTrackEvent conditional=WEB_RTC +RTCTransformEvent conditional=WEB_RTC +SpeechRecognitionErrorEvent +SpeechRecognitionEvent +SpeechSynthesisErrorEvent conditional=SPEECH_SYNTHESIS +SpeechSynthesisEvent conditional=SPEECH_SYNTHESIS +WebGLContextEvent conditional=WEBGL +StorageEvent +SVGEvents interfaceName=Event +SVGZoomEvent +SVGZoomEvents interfaceName=SVGZoomEvent +IDBVersionChangeEvent +TouchEvent conditional=TOUCH_EVENTS +DeviceMotionEvent conditional=DEVICE_ORIENTATION +DeviceOrientationEvent conditional=DEVICE_ORIENTATION +OrientationEvent interfaceName=Event, conditional=ORIENTATION_EVENTS +WebKitMediaKeyMessageEvent conditional=LEGACY_ENCRYPTED_MEDIA +WebKitMediaKeyNeededEvent conditional=LEGACY_ENCRYPTED_MEDIA +TrackEvent conditional=VIDEO +SecurityPolicyViolationEvent +GestureEvent conditional=IOS_GESTURE_EVENTS|MAC_GESTURE_EVENTS +WebKitPlaybackTargetAvailabilityEvent conditional=WIRELESS_PLAYBACK_TARGET +GamepadEvent conditional=GAMEPAD +OverconstrainedErrorEvent conditional=MEDIA_STREAM +MediaEncryptedEvent conditional=ENCRYPTED_MEDIA +MediaKeyMessageEvent conditional=ENCRYPTED_MEDIA +PointerEvent +PictureInPictureEvent conditional=PICTURE_IN_PICTURE_API +XRInputSourceEvent conditional=WEBXR +XRInputSourcesChangeEvent conditional=WEBXR +XRReferenceSpaceEvent conditional=WEBXR +XRSessionEvent conditional=WEBXR +NotificationEvent conditional=NOTIFICATION_EVENT diff --git a/src/javascript/jsc/bindings/webcore/EventOptions.h b/src/javascript/jsc/bindings/webcore/EventOptions.h new file mode 100644 index 000000000..ec59b6980 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventOptions.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 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 + +namespace WebCore { + +enum class EventIsTrusted : bool { No, Yes }; +enum class EventCanBubble : bool { No, Yes }; +enum class EventIsCancelable : bool { No, Yes }; +enum class EventIsComposed : bool { No, Yes }; + +} diff --git a/src/javascript/jsc/bindings/webcore/EventPath.cpp b/src/javascript/jsc/bindings/webcore/EventPath.cpp new file mode 100644 index 000000000..30dbb5de9 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventPath.cpp @@ -0,0 +1,423 @@ +// /* +// * Copyright (C) 2013 Google Inc. All rights reserved. +// * Copyright (C) 2013-2022 Apple Inc. All rights reserved. +// * +// * This library is free software; you can redistribute it and/or +// * modify it under the terms of the GNU Library General Public +// * License as published by the Free Software Foundation; either +// * version 2 of the License, or (at your option) any later version. +// * +// * This library is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// * Library General Public License for more details. +// * +// * You should have received a copy of the GNU Library General Public License +// * along with this library; see the file COPYING.LIB. If not, write to +// * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +// * Boston, MA 02110-1301, USA. +// */ + +// #include "config.h" +// #include "EventPath.h" + +// // #include "DOMWindow.h" +// #include "Event.h" +// #include "EventContext.h" +// #include "EventNames.h" +// // #include "FullscreenManager.h" +// // #include "HTMLSlotElement.h" +// // #include "MouseEvent.h" +// #include "Node.h" +// // #include "PseudoElement.h" +// // #include "ShadowRoot.h" +// // #include "TouchEvent.h" + +// namespace WebCore { + +// static inline bool shouldEventCrossShadowBoundary(Event& event, ShadowRoot& shadowRoot, EventTarget& target) +// { +// // #if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO) +// // // Video-only full screen is a mode where we use the shadow DOM as an implementation +// // // detail that should not be detectable by the web content. +// // if (is<Node>(target)) { +// // if (auto* element = downcast<Node>(target).document().fullscreenManager().currentFullscreenElement()) { +// // // FIXME: We assume that if the full screen element is a media element that it's +// // // the video-only full screen. Both here and elsewhere. But that is probably wrong. +// // if (element->isMediaElement() && shadowRoot.host() == element) +// // return false; +// // } +// // } +// // #endif + +// bool targetIsInShadowRoot = is<Node>(target) && &downcast<Node>(target).treeScope().rootNode() == &shadowRoot; +// return !targetIsInShadowRoot || event.composed(); +// } + +// static Node* nodeOrHostIfPseudoElement(Node* node) +// { +// retur nnode; +// // return is<PseudoElement>(*node) ? downcast<PseudoElement>(*node).hostElement() : node; +// } + +// class RelatedNodeRetargeter { +// public: +// RelatedNodeRetargeter(Node& relatedNode, Node& target); + +// Node* currentNode(Node& currentTreeScope); +// void moveToNewTreeScope(TreeScope* previousTreeScope, TreeScope& newTreeScope); + +// private: +// Node* nodeInLowestCommonAncestor(); +// void collectTreeScopes(); + +// void checkConsistency(Node& currentTarget); + +// Node& m_relatedNode; +// Node* m_retargetedRelatedNode; +// Vector<TreeScope*, 8> m_ancestorTreeScopes; +// unsigned m_lowestCommonAncestorIndex { 0 }; +// bool m_hasDifferentTreeRoot { false }; +// }; + +// EventPath::EventPath(Node& originalTarget, Event& event) +// { +// buildPath(originalTarget, event); + +// if (auto* relatedTarget = event.relatedTarget(); is<Node>(relatedTarget) && !m_path.isEmpty()) +// setRelatedTarget(originalTarget, downcast<Node>(*relatedTarget)); + +// #if ENABLE(TOUCH_EVENTS) +// if (is<TouchEvent>(event)) +// retargetTouchLists(downcast<TouchEvent>(event)); +// #endif +// } + +// void EventPath::buildPath(Node& originalTarget, Event& event) +// { +// UNUSED_PARAM(originalTarget); +// UNUSED_PARAM(event); +// // EventContext::Type contextType = [&]() { +// // if (is<MouseEvent>(event) || event.isFocusEvent()) +// // return EventContext::Type::MouseOrFocus; +// // #if ENABLE(TOUCH_EVENTS) +// // if (is<TouchEvent>(event)) +// // return EventContext::Type::Touch; +// // #endif +// // return EventContext::Type::Normal; +// // }(); + +// // Node* node = nodeOrHostIfPseudoElement(&originalTarget); +// // Node* target = node ? eventTargetRespectingTargetRules(*node) : nullptr; +// // int closedShadowDepth = 0; +// // // Depths are used to decided which nodes are excluded in event.composedPath when the tree is mutated during event dispatching. +// // // They could be negative for nodes outside the shadow tree of the target node. +// // while (node) { +// // while (node) { +// // m_path.append(EventContext { contextType, *node, eventTargetRespectingTargetRules(*node), target, closedShadowDepth }); + +// // if (is<ShadowRoot>(*node)) +// // break; + +// // ContainerNode* parent = node->parentNode(); +// // if (UNLIKELY(!parent)) { +// // // https://dom.spec.whatwg.org/#interface-document +// // if (is<Document>(*node) && event.type() != eventNames().loadEvent) { +// // ASSERT(target); +// // if (target) { +// // if (auto* window = downcast<Document>(*node).domWindow()) +// // m_path.append(EventContext { EventContext::Type::Window, node, window, target, closedShadowDepth }); +// // } +// // } +// // return; +// // } + +// // if (auto* shadowRootOfParent = parent->shadowRoot(); UNLIKELY(shadowRootOfParent)) { +// // if (auto* assignedSlot = shadowRootOfParent->findAssignedSlot(*node)) { +// // if (shadowRootOfParent->mode() != ShadowRootMode::Open) +// // closedShadowDepth++; +// // // node is assigned to a slot. Continue dispatching the event at this slot. +// // parent = assignedSlot; +// // } +// // } +// // node = parent; +// // } + +// // bool exitingShadowTreeOfTarget = &target->treeScope() == &node->treeScope(); +// // ShadowRoot& shadowRoot = downcast<ShadowRoot>(*node); +// // if (!shouldEventCrossShadowBoundary(event, shadowRoot, originalTarget)) +// // return; +// // node = shadowRoot.host(); +// // if (shadowRoot.mode() != ShadowRootMode::Open) +// // closedShadowDepth--; +// // if (exitingShadowTreeOfTarget) +// // target = eventTargetRespectingTargetRules(*node); +// } +// } + +// void EventPath::setRelatedTarget(Node& origin, Node& relatedNode) +// { +// UNUSED_PARAM(origin); +// UNUSED_PARAM(relatedNode); +// // RelatedNodeRetargeter retargeter(relatedNode, *m_path[0].node()); + +// // bool originIsRelatedTarget = &origin == &relatedNode; +// // Node& rootNodeInOriginTreeScope = origin.treeScope().rootNode(); +// // TreeScope* previousTreeScope = nullptr; +// // size_t originalEventPathSize = m_path.size(); +// // for (unsigned contextIndex = 0; contextIndex < originalEventPathSize; contextIndex++) { +// // auto& context = m_path[contextIndex]; +// // if (!context.isMouseOrFocusEventContext()) { +// // ASSERT(context.isWindowContext()); +// // continue; +// // } + +// // Node& currentTarget = *context.node(); +// // TreeScope& currentTreeScope = currentTarget.treeScope(); +// // if (UNLIKELY(previousTreeScope && ¤tTreeScope != previousTreeScope)) +// // retargeter.moveToNewTreeScope(previousTreeScope, currentTreeScope); + +// // Node* currentRelatedNode = retargeter.currentNode(currentTarget); +// // if (UNLIKELY(!originIsRelatedTarget && context.target() == currentRelatedNode)) { +// // m_path.shrink(contextIndex); +// // break; +// // } + +// // context.setRelatedTarget(currentRelatedNode); + +// // if (UNLIKELY(originIsRelatedTarget && context.node() == &rootNodeInOriginTreeScope)) { +// // m_path.shrink(contextIndex + 1); +// // break; +// // } + +// // previousTreeScope = ¤tTreeScope; +// // } +// } + +// #if ENABLE(TOUCH_EVENTS) + +// void EventPath::retargetTouch(EventContext::TouchListType type, const Touch& touch) +// { +// auto* eventTarget = touch.target(); +// if (!is<Node>(eventTarget)) +// return; + +// RelatedNodeRetargeter retargeter(downcast<Node>(*eventTarget), *m_path[0].node()); +// TreeScope* previousTreeScope = nullptr; +// for (auto& context : m_path) { +// Node& currentTarget = *context.node(); +// TreeScope& currentTreeScope = currentTarget.treeScope(); +// if (UNLIKELY(previousTreeScope && ¤tTreeScope != previousTreeScope)) +// retargeter.moveToNewTreeScope(previousTreeScope, currentTreeScope); + +// if (context.isTouchEventContext()) { +// Node* currentRelatedNode = retargeter.currentNode(currentTarget); +// context.touchList(type).append(touch.cloneWithNewTarget(currentRelatedNode)); +// } else +// ASSERT(context.isWindowContext()); + +// previousTreeScope = ¤tTreeScope; +// } +// } + +// void EventPath::retargetTouchList(EventContext::TouchListType type, const TouchList* list) +// { +// for (unsigned i = 0, length = list ? list->length() : 0; i < length; ++i) +// retargetTouch(type, *list->item(i)); +// } + +// void EventPath::retargetTouchLists(const TouchEvent& event) +// { +// retargetTouchList(EventContext::TouchListType::Touches, event.touches()); +// retargetTouchList(EventContext::TouchListType::TargetTouches, event.targetTouches()); +// retargetTouchList(EventContext::TouchListType::ChangedTouches, event.changedTouches()); +// } + +// #endif + +// // https://dom.spec.whatwg.org/#dom-event-composedpath +// // Any node whose depth computed in EventPath::buildPath is greater than the context object is excluded. +// // Because we can exit out of a closed shadow tree and re-enter another closed shadow tree via a slot, +// // we decrease the *allowed depth* whenever we moved to a "shallower" (closer-to-document) tree. +// Vector<EventTarget*> EventPath::computePathUnclosedToTarget(const EventTarget& target) const +// { +// Vector<EventTarget*> path; +// auto pathSize = m_path.size(); +// RELEASE_ASSERT(pathSize); +// path.reserveInitialCapacity(pathSize); + +// auto currentTargetIndex = m_path.findIf([&target](auto& context) { +// return context.currentTarget() == ⌖ +// }); +// RELEASE_ASSERT(currentTargetIndex != notFound); +// auto currentTargetDepth = m_path[currentTargetIndex].closedShadowDepth(); + +// auto appendTargetWithLesserDepth = [&path](const EventContext& currentContext, int& currentDepthAllowed) { +// auto depth = currentContext.closedShadowDepth(); +// bool contextIsInsideInnerShadowTree = depth > currentDepthAllowed; +// if (contextIsInsideInnerShadowTree) +// return; +// bool movedOutOfShadowTree = depth < currentDepthAllowed; +// if (movedOutOfShadowTree) +// currentDepthAllowed = depth; +// path.uncheckedAppend(currentContext.currentTarget()); +// }; + +// auto currentDepthAllowed = currentTargetDepth; +// auto i = currentTargetIndex; +// do { +// appendTargetWithLesserDepth(m_path[i], currentDepthAllowed); +// } while (i--); +// path.reverse(); + +// currentDepthAllowed = currentTargetDepth; +// for (auto i = currentTargetIndex + 1; i < pathSize; ++i) +// appendTargetWithLesserDepth(m_path[i], currentDepthAllowed); + +// return path; +// } + +// EventPath::EventPath(const Vector<EventTarget*>& targets) +// { +// m_path = targets.map([&](auto* target) { +// ASSERT(target); +// ASSERT(!is<Node>(target)); +// return EventContext { EventContext::Type::Normal, nullptr, target, *targets.begin(), 0 }; +// }); +// } + +// static Node* moveOutOfAllShadowRoots(Node& startingNode) +// { +// Node* node = &startingNode; +// while (node->isInShadowTree()) +// node = downcast<ShadowRoot>(node->treeScope().rootNode()).host(); +// return node; +// } + +// RelatedNodeRetargeter::RelatedNodeRetargeter(Node& relatedNode, Node& target) +// : m_relatedNode(relatedNode) +// , m_retargetedRelatedNode(&relatedNode) +// { +// auto& targetTreeScope = target.treeScope(); +// TreeScope* currentTreeScope = &m_relatedNode.treeScope(); +// if (LIKELY(currentTreeScope == &targetTreeScope && target.isConnected() && m_relatedNode.isConnected())) +// return; + +// if (¤tTreeScope->documentScope() != &targetTreeScope.documentScope()) { +// m_hasDifferentTreeRoot = true; +// m_retargetedRelatedNode = nullptr; +// return; +// } +// if (relatedNode.isConnected() != target.isConnected()) { +// m_hasDifferentTreeRoot = true; +// m_retargetedRelatedNode = moveOutOfAllShadowRoots(relatedNode); +// return; +// } + +// collectTreeScopes(); + +// // FIXME: We should collect this while constructing the event path. +// Vector<TreeScope*, 8> targetTreeScopeAncestors; +// for (TreeScope* currentTreeScope = &targetTreeScope; currentTreeScope; currentTreeScope = currentTreeScope->parentTreeScope()) +// targetTreeScopeAncestors.append(currentTreeScope); +// ASSERT_WITH_SECURITY_IMPLICATION(!targetTreeScopeAncestors.isEmpty()); + +// unsigned i = m_ancestorTreeScopes.size(); +// unsigned j = targetTreeScopeAncestors.size(); +// ASSERT_WITH_SECURITY_IMPLICATION(m_ancestorTreeScopes.last() == targetTreeScopeAncestors.last()); +// while (m_ancestorTreeScopes[i - 1] == targetTreeScopeAncestors[j - 1]) { +// i--; +// j--; +// if (!i || !j) +// break; +// } + +// bool lowestCommonAncestorIsDocumentScope = i + 1 == m_ancestorTreeScopes.size(); +// if (lowestCommonAncestorIsDocumentScope && !relatedNode.isConnected() && !target.isConnected()) { +// Node& relatedNodeAncestorInDocumentScope = i ? *downcast<ShadowRoot>(m_ancestorTreeScopes[i - 1]->rootNode()).shadowHost() : relatedNode; +// Node& targetAncestorInDocumentScope = j ? *downcast<ShadowRoot>(targetTreeScopeAncestors[j - 1]->rootNode()).shadowHost() : target; +// if (&targetAncestorInDocumentScope.rootNode() != &relatedNodeAncestorInDocumentScope.rootNode()) { +// m_hasDifferentTreeRoot = true; +// m_retargetedRelatedNode = moveOutOfAllShadowRoots(relatedNode); +// return; +// } +// } + +// m_lowestCommonAncestorIndex = i; +// m_retargetedRelatedNode = nodeInLowestCommonAncestor(); +// } + +// inline Node* RelatedNodeRetargeter::currentNode(Node& currentTarget) +// { +// checkConsistency(currentTarget); +// return m_retargetedRelatedNode; +// } + +// void RelatedNodeRetargeter::moveToNewTreeScope(TreeScope* previousTreeScope, TreeScope& newTreeScope) +// { +// if (m_hasDifferentTreeRoot) +// return; + +// auto& currentRelatedNodeScope = m_retargetedRelatedNode->treeScope(); +// if (previousTreeScope != ¤tRelatedNodeScope) { +// // currentRelatedNode is still outside our shadow tree. New tree scope may contain currentRelatedNode +// // but there is no need to re-target it. Moving into a slot (thereby a deeper shadow tree) doesn't matter. +// return; +// } + +// bool enteredSlot = newTreeScope.parentTreeScope() == previousTreeScope; +// if (enteredSlot) { +// if (m_lowestCommonAncestorIndex) { +// if (m_ancestorTreeScopes.isEmpty()) +// collectTreeScopes(); +// bool relatedNodeIsInSlot = m_ancestorTreeScopes[m_lowestCommonAncestorIndex - 1] == &newTreeScope; +// if (relatedNodeIsInSlot) { +// m_lowestCommonAncestorIndex--; +// m_retargetedRelatedNode = nodeInLowestCommonAncestor(); +// ASSERT(&newTreeScope == &m_retargetedRelatedNode->treeScope()); +// } +// } else +// ASSERT(m_retargetedRelatedNode == &m_relatedNode); +// } else { +// ASSERT(previousTreeScope->parentTreeScope() == &newTreeScope); +// m_lowestCommonAncestorIndex++; +// ASSERT_WITH_SECURITY_IMPLICATION(m_ancestorTreeScopes.isEmpty() || m_lowestCommonAncestorIndex < m_ancestorTreeScopes.size()); +// m_retargetedRelatedNode = downcast<ShadowRoot>(currentRelatedNodeScope.rootNode()).host(); +// ASSERT(&newTreeScope == &m_retargetedRelatedNode->treeScope()); +// } +// } + +// inline Node* RelatedNodeRetargeter::nodeInLowestCommonAncestor() +// { +// if (!m_lowestCommonAncestorIndex) +// return &m_relatedNode; +// auto& rootNode = m_ancestorTreeScopes[m_lowestCommonAncestorIndex - 1]->rootNode(); +// return downcast<ShadowRoot>(rootNode).host(); +// } + +// void RelatedNodeRetargeter::collectTreeScopes() +// { +// ASSERT(m_ancestorTreeScopes.isEmpty()); +// for (TreeScope* currentTreeScope = &m_relatedNode.treeScope(); currentTreeScope; currentTreeScope = currentTreeScope->parentTreeScope()) +// m_ancestorTreeScopes.append(currentTreeScope); +// ASSERT_WITH_SECURITY_IMPLICATION(!m_ancestorTreeScopes.isEmpty()); +// } + +// #if !ASSERT_ENABLED + +// inline void RelatedNodeRetargeter::checkConsistency(Node&) +// { +// } + +// #else // ASSERT_ENABLED + +// void RelatedNodeRetargeter::checkConsistency(Node& currentTarget) +// { +// if (!m_retargetedRelatedNode) +// return; +// ASSERT(!currentTarget.isClosedShadowHidden(*m_retargetedRelatedNode)); +// ASSERT(m_retargetedRelatedNode == currentTarget.treeScope().retargetToScope(m_relatedNode).ptr()); +// } + +// #endif // ASSERT_ENABLED +// } diff --git a/src/javascript/jsc/bindings/webcore/EventPath.h b/src/javascript/jsc/bindings/webcore/EventPath.h new file mode 100644 index 000000000..feb86fb7b --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventPath.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2017 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include "EventContext.h" +// #include "PseudoElement.h" +// #include "SVGElement.h" +// #include "SVGUseElement.h" +#include <wtf/Forward.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class Touch; + +class EventPath { +public: + EventPath(Node& origin, Event&); + explicit EventPath(const Vector<EventTarget*>&); + + bool isEmpty() const { return m_path.isEmpty(); } + size_t size() const { return m_path.size(); } + const EventContext& contextAt(size_t i) const { return m_path[i]; } + EventContext& contextAt(size_t i) { return m_path[i]; } + + Vector<EventTarget*> computePathUnclosedToTarget(const EventTarget&) const; + + static Node* eventTargetRespectingTargetRules(Node&); + +private: + void buildPath(Node& origin, Event&); + void setRelatedTarget(Node& origin, Node&); + +#if ENABLE(TOUCH_EVENTS) + void retargetTouch(EventContext::TouchListType, const Touch&); + void retargetTouchList(EventContext::TouchListType, const TouchList*); + void retargetTouchLists(const TouchEvent&); +#endif + + Vector<EventContext, 16> m_path; +}; + +inline Node* EventPath::eventTargetRespectingTargetRules(Node& referenceNode) +{ + // if (is<PseudoElement>(referenceNode)) + // return downcast<PseudoElement>(referenceNode).hostElement(); + + // // Events sent to elements inside an SVG use element's shadow tree go to the use element. + // if (is<SVGElement>(referenceNode)) { + // if (auto useElement = downcast<SVGElement>(referenceNode).correspondingUseElement()) + // return useElement.get(); + // } + + return &referenceNode; +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventSender.h b/src/javascript/jsc/bindings/webcore/EventSender.h new file mode 100644 index 000000000..d69a6e5e9 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventSender.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2012 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 "Timer.h" +#include <wtf/Vector.h> +#include <wtf/WeakPtr.h> + +namespace WebCore { + +class Page; + +template<typename T> class EventSender { + WTF_MAKE_NONCOPYABLE(EventSender); WTF_MAKE_FAST_ALLOCATED; +public: + explicit EventSender(const AtomString& eventType); + + const AtomString& eventType() const { return m_eventType; } + void dispatchEventSoon(T&); + void cancelEvent(T&); + void dispatchPendingEvents(Page*); + +#if ASSERT_ENABLED + bool hasPendingEvents(T& sender) const + { + return m_dispatchSoonList.find(&sender) != notFound || m_dispatchingList.find(&sender) != notFound; + } +#endif + +private: + void timerFired() { dispatchPendingEvents(nullptr); } + + AtomString m_eventType; + Timer m_timer; + Vector<WeakPtr<T>> m_dispatchSoonList; + Vector<WeakPtr<T>> m_dispatchingList; +}; + +template<typename T> EventSender<T>::EventSender(const AtomString& eventType) + : m_eventType(eventType) + , m_timer(*this, &EventSender::timerFired) +{ +} + +template<typename T> void EventSender<T>::dispatchEventSoon(T& sender) +{ + m_dispatchSoonList.append(sender); + if (!m_timer.isActive()) + m_timer.startOneShot(0_s); +} + +template<typename T> void EventSender<T>::cancelEvent(T& sender) +{ + // Remove instances of this sender from both lists. + // Use loops because we allow multiple instances to get into the lists. + for (auto& event : m_dispatchSoonList) { + if (event == &sender) + event = nullptr; + } + for (auto& event : m_dispatchingList) { + if (event == &sender) + event = nullptr; + } +} + +template<typename T> void EventSender<T>::dispatchPendingEvents(Page* page) +{ + // Need to avoid re-entering this function; if new dispatches are + // scheduled before the parent finishes processing the list, they + // will set a timer and eventually be processed. + if (!m_dispatchingList.isEmpty()) + return; + + m_timer.stop(); + + m_dispatchSoonList.checkConsistency(); + + m_dispatchingList = std::exchange(m_dispatchSoonList, { }); + for (auto& event : m_dispatchingList) { + if (auto sender = event.get()) { + event = nullptr; + if (!page || sender->document().page() == page) + sender->dispatchPendingEvent(this); + else + dispatchEventSoon(*sender); + } + } + m_dispatchingList.clear(); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventTarget.cpp b/src/javascript/jsc/bindings/webcore/EventTarget.cpp new file mode 100644 index 000000000..3b7128b7a --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventTarget.cpp @@ -0,0 +1,391 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2004-2021 Apple Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * + * 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. ``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 + * 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. + * + */ + +#include "config.h" +#include "Event.h" + +#include "EventTarget.h" + +#include "AddEventListenerOptions.h" +#include "DOMWrapperWorld.h" +#include "EventNames.h" +#include "EventTargetConcrete.h" +// #include "HTMLBodyElement.h" +// #include "HTMLHtmlElement.h" +// #include "InspectorInstrumentation.h" +#include "JSErrorHandler.h" +#include "JSEventListener.h" +// #include "Logging.h" +// #include "Quirks.h" +// #include "ScriptController.h" +// #include "ScriptDisallowedScope.h" +// #include "Settings.h" +// #include <wtf/IsoMallocInlines.h> +#include <wtf/MainThread.h> +#include <wtf/NeverDestroyed.h> +#include <wtf/Ref.h> +#include <wtf/SetForScope.h> +#include <wtf/StdLibExtras.h> +#include <wtf/Vector.h> + +namespace WebCore { + +WTF_MAKE_ISO_ALLOCATED_IMPL(EventTarget); +WTF_MAKE_ISO_ALLOCATED_IMPL(EventTargetWithInlineData); + +Ref<EventTarget> EventTarget::create(ScriptExecutionContext& context) +{ + return EventTargetConcrete::create(context); +} + +EventTarget::~EventTarget() = default; + +bool EventTarget::isNode() const +{ + return false; +} + +bool EventTarget::isPaymentRequest() const +{ + return false; +} + +bool EventTarget::addEventListener(const AtomString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options) +{ +#if ASSERT_ENABLED + listener->checkValidityForEventTarget(*this); +#endif + + if (options.signal && options.signal->aborted()) + return false; + + auto passive = options.passive; + + // if (!passive.has_value() && Quirks::shouldMakeEventListenerPassive(*this, eventType, listener.get())) + // passive = true; + + bool listenerCreatedFromScript = is<JSEventListener>(listener) && !downcast<JSEventListener>(listener.get()).wasCreatedFromMarkup(); + + if (!ensureEventTargetData().eventListenerMap.add(eventType, listener.copyRef(), { options.capture, passive.value_or(false), options.once })) + return false; + + if (options.signal) { + options.signal->addAlgorithm([weakThis = WeakPtr { *this }, eventType, listener = WeakPtr { listener }, capture = options.capture] { + if (weakThis && listener) + weakThis->removeEventListener(eventType, *listener, capture); + }); + } + + // if (listenerCreatedFromScript) + // InspectorInstrumentation::didAddEventListener(*this, eventType, listener.get(), options.capture); + + // if (eventNames().isWheelEventType(eventType)) + // invalidateEventListenerRegions(); + + eventListenersDidChange(); + return true; +} + +void EventTarget::addEventListenerForBindings(const AtomString& eventType, RefPtr<EventListener>&& listener, AddEventListenerOptionsOrBoolean&& variant) +{ + if (!listener) + return; + + auto visitor = WTF::makeVisitor([&](const AddEventListenerOptions& options) { addEventListener(eventType, listener.releaseNonNull(), options); }, [&](bool capture) { addEventListener(eventType, listener.releaseNonNull(), capture); }); + + std::visit(visitor, variant); +} + +void EventTarget::removeEventListenerForBindings(const AtomString& eventType, RefPtr<EventListener>&& listener, EventListenerOptionsOrBoolean&& variant) +{ + if (!listener) + return; + + auto visitor = WTF::makeVisitor([&](const EventListenerOptions& options) { removeEventListener(eventType, *listener, options); }, [&](bool capture) { removeEventListener(eventType, *listener, capture); }); + + std::visit(visitor, variant); +} + +bool EventTarget::removeEventListener(const AtomString& eventType, EventListener& listener, const EventListenerOptions& options) +{ + auto* data = eventTargetData(); + if (!data) + return false; + + // InspectorInstrumentation::willRemoveEventListener(*this, eventType, listener, options.capture); + + if (data->eventListenerMap.remove(eventType, listener, options.capture)) { + if (eventNames().isWheelEventType(eventType)) + invalidateEventListenerRegions(); + + eventListenersDidChange(); + return true; + } + return false; +} + +template<typename JSMaybeErrorEventListener> +void EventTarget::setAttributeEventListener(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget) +{ + auto& isolatedWorld = worldForDOMObject(jsEventTarget); + auto* existingListener = attributeEventListener(eventType, isolatedWorld); + if (!listener.isObject()) { + if (existingListener) + removeEventListener(eventType, *existingListener, false); + } else if (existingListener) { + bool capture = false; + + // InspectorInstrumentation::willRemoveEventListener(*this, eventType, *existingListener, capture); + existingListener->replaceJSFunctionForAttributeListener(asObject(listener), &jsEventTarget); + // InspectorInstrumentation::didAddEventListener(*this, eventType, *existingListener, capture); + } else + addEventListener(eventType, JSMaybeErrorEventListener::create(*asObject(listener), jsEventTarget, true, isolatedWorld), {}); +} + +template void EventTarget::setAttributeEventListener<JSErrorHandler>(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget); +template void EventTarget::setAttributeEventListener<JSEventListener>(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget); + +bool EventTarget::setAttributeEventListener(const AtomString& eventType, RefPtr<EventListener>&& listener, DOMWrapperWorld& isolatedWorld) +{ + auto* existingListener = attributeEventListener(eventType, isolatedWorld); + if (!listener) { + if (existingListener) + removeEventListener(eventType, *existingListener, false); + return false; + } + // if (existingListener) { + // InspectorInstrumentation::willRemoveEventListener(*this, eventType, *existingListener, false); + +#if ASSERT_ENABLED + listener->checkValidityForEventTarget(*this); +#endif + + auto listenerPointer = listener.copyRef(); + eventTargetData()->eventListenerMap.replace(eventType, *existingListener, listener.releaseNonNull(), {}); + + // InspectorInstrumentation::didAddEventListener(*this, eventType, *listenerPointer, false); + + return true; + + return addEventListener(eventType, listener.releaseNonNull(), {}); +} + +JSEventListener* EventTarget::attributeEventListener(const AtomString& eventType, DOMWrapperWorld& isolatedWorld) +{ + for (auto& eventListener : eventListeners(eventType)) { + auto& listener = eventListener->callback(); + if (listener.type() != EventListener::JSEventListenerType) + continue; + + auto& jsListener = downcast<JSEventListener>(listener); + if (jsListener.isAttribute() && &jsListener.isolatedWorld() == &isolatedWorld) + return &jsListener; + } + + return nullptr; +} + +bool EventTarget::hasActiveEventListeners(const AtomString& eventType) const +{ + auto* data = eventTargetData(); + return data && data->eventListenerMap.containsActive(eventType); +} + +ExceptionOr<bool> EventTarget::dispatchEventForBindings(Event& event) +{ + if (!event.isInitialized() || event.isBeingDispatched()) + return Exception { InvalidStateError }; + + if (!scriptExecutionContext()) + return false; + + event.setUntrusted(); + + dispatchEvent(event); + return event.legacyReturnValue(); +} + +void EventTarget::dispatchEvent(Event& event) +{ + // FIXME: We should always use EventDispatcher. + ASSERT(event.isInitialized()); + ASSERT(!event.isBeingDispatched()); + + event.setTarget(this); + event.setCurrentTarget(this); + event.setEventPhase(Event::AT_TARGET); + event.resetBeforeDispatch(); + fireEventListeners(event, EventInvokePhase::Capturing); + fireEventListeners(event, EventInvokePhase::Bubbling); + event.resetAfterDispatch(); +} + +void EventTarget::uncaughtExceptionInEventHandler() +{ +} + +static const AtomString& legacyType(const Event& event) +{ + + return nullAtom(); +} + +// https://dom.spec.whatwg.org/#concept-event-listener-invoke +void EventTarget::fireEventListeners(Event& event, EventInvokePhase phase) +{ + ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::isEventAllowedInMainThread()); + ASSERT(event.isInitialized()); + + auto* data = eventTargetData(); + if (!data) + return; + + SetForScope firingEventListenersScope(data->isFiringEventListeners, true); + + if (auto* listenersVector = data->eventListenerMap.find(event.type())) { + innerInvokeEventListeners(event, *listenersVector, phase); + return; + } + + // Only fall back to legacy types for trusted events. + if (!event.isTrusted()) + return; + + const AtomString& legacyTypeName = legacyType(event); + if (!legacyTypeName.isNull()) { + if (auto* legacyListenersVector = data->eventListenerMap.find(legacyTypeName)) { + AtomString typeName = event.type(); + event.setType(legacyTypeName); + innerInvokeEventListeners(event, *legacyListenersVector, phase); + event.setType(typeName); + } + } +} + +// Intentionally creates a copy of the listeners vector to avoid event listeners added after this point from being run. +// Note that removal still has an effect due to the removed field in RegisteredEventListener. +// https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke +void EventTarget::innerInvokeEventListeners(Event& event, EventListenerVector listeners, EventInvokePhase phase) +{ + Ref<EventTarget> protectedThis(*this); + ASSERT(!listeners.isEmpty()); + ASSERT(scriptExecutionContext()); + + auto& context = *scriptExecutionContext(); + // bool contextIsDocument = is<Document>(context); + // if (contextIsDocument) + // InspectorInstrumentation::willDispatchEvent(downcast<Document>(context), event); + + for (auto& registeredListener : listeners) { + if (UNLIKELY(registeredListener->wasRemoved())) + continue; + + if (phase == EventInvokePhase::Capturing && !registeredListener->useCapture()) + continue; + if (phase == EventInvokePhase::Bubbling && registeredListener->useCapture()) + continue; + + // if (InspectorInstrumentation::isEventListenerDisabled(*this, event.type(), registeredListener->callback(), registeredListener->useCapture())) + // continue; + + // If stopImmediatePropagation has been called, we just break out immediately, without + // handling any more events on this target. + if (event.immediatePropagationStopped()) + break; + + // Make sure the JS wrapper and function stay alive until the end of this scope. Otherwise, + // event listeners with 'once' flag may get collected as soon as they get unregistered below, + // before we call the js function. + JSC::EnsureStillAliveScope wrapperProtector(registeredListener->callback().wrapper()); + JSC::EnsureStillAliveScope jsFunctionProtector(registeredListener->callback().jsFunction()); + + // Do this before invocation to avoid reentrancy issues. + if (registeredListener->isOnce()) + removeEventListener(event.type(), registeredListener->callback(), registeredListener->useCapture()); + + if (registeredListener->isPassive()) + event.setInPassiveListener(true); + +#if ASSERT_ENABLED + registeredListener->callback().checkValidityForEventTarget(*this); +#endif + + // InspectorInstrumentation::willHandleEvent(context, event, *registeredListener); + registeredListener->callback().handleEvent(context, event); + // InspectorInstrumentation::didHandleEvent(context, event, *registeredListener); + + // if (registeredListener->isPassive()) + // event.setInPassiveListener(false); + } + + // if (contextIsDocument) + // InspectorInstrumentation::didDispatchEvent(downcast<Document>(context), event); +} + +Vector<AtomString> EventTarget::eventTypes() +{ + if (auto* data = eventTargetData()) + return data->eventListenerMap.eventTypes(); + return {}; +} + +const EventListenerVector& EventTarget::eventListeners(const AtomString& eventType) +{ + auto* data = eventTargetData(); + auto* listenerVector = data ? data->eventListenerMap.find(eventType) : nullptr; + static NeverDestroyed<EventListenerVector> emptyVector; + return listenerVector ? *listenerVector : emptyVector.get(); +} + +void EventTarget::removeAllEventListeners() +{ + // auto& threadData = threadGlobalData(); + // RELEASE_ASSERT(!threadData.isInRemoveAllEventListeners()); + + // threadData.setIsInRemoveAllEventListeners(true); + + auto* data = eventTargetData(); + if (data && !data->eventListenerMap.isEmpty()) { + // if (data->eventListenerMap.contains(eventNames().wheelEvent) || data->eventListenerMap.contains(eventNames().mousewheelEvent)) + // invalidateEventListenerRegions(); + + data->eventListenerMap.clear(); + eventListenersDidChange(); + } + + // threadData.setIsInRemoveAllEventListeners(false); +} + +void EventTarget::invalidateEventListenerRegions() +{ +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventTarget.h b/src/javascript/jsc/bindings/webcore/EventTarget.h new file mode 100644 index 000000000..b763393d7 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventTarget.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2004-2021 Apple Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * + * 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. ``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 + * 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 "EventListenerMap.h" +#include "EventListenerOptions.h" +#include "EventTargetInterfaces.h" +#include "ExceptionOr.h" +#include "ScriptWrappable.h" +#include <memory> +#include <variant> +#include <wtf/Forward.h> +// #include <wtf/IsoMalloc.h> + +#include <wtf/WeakPtr.h> + +#include "root.h" + +namespace JSC { +class JSValue; +class JSObject; +} + +namespace WebCore { + +struct AddEventListenerOptions; +class DOMWrapperWorld; +class JSEventListener; + +struct EventTargetData { + WTF_MAKE_NONCOPYABLE(EventTargetData); + WTF_MAKE_FAST_ALLOCATED; + +public: + EventTargetData() = default; + EventListenerMap eventListenerMap; + bool isFiringEventListeners { false }; +}; + +class EventTarget : public ScriptWrappable, public CanMakeWeakPtr<EventTarget> { + WTF_MAKE_ISO_ALLOCATED(EventTarget); + +public: + static Ref<EventTarget> create(ScriptExecutionContext&); + + void ref() { refEventTarget(); } + void deref() { derefEventTarget(); } + + virtual EventTargetInterface eventTargetInterface() const = 0; + virtual ScriptExecutionContext* scriptExecutionContext() const = 0; + + WEBCORE_EXPORT virtual bool isNode() const; + WEBCORE_EXPORT virtual bool isPaymentRequest() const; + + using AddEventListenerOptionsOrBoolean = std::variant<AddEventListenerOptions, bool>; + WEBCORE_EXPORT void addEventListenerForBindings(const AtomString& eventType, RefPtr<EventListener>&&, AddEventListenerOptionsOrBoolean&&); + using EventListenerOptionsOrBoolean = std::variant<EventListenerOptions, bool>; + WEBCORE_EXPORT void removeEventListenerForBindings(const AtomString& eventType, RefPtr<EventListener>&&, EventListenerOptionsOrBoolean&&); + WEBCORE_EXPORT ExceptionOr<bool> dispatchEventForBindings(Event&); + + WEBCORE_EXPORT virtual bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&); + WEBCORE_EXPORT virtual bool removeEventListener(const AtomString& eventType, EventListener&, const EventListenerOptions& = {}); + + WEBCORE_EXPORT virtual void removeAllEventListeners(); + WEBCORE_EXPORT virtual void dispatchEvent(Event&); + WEBCORE_EXPORT virtual void uncaughtExceptionInEventHandler(); + + // Used for legacy "onevent" attributes. + template<typename JSMaybeErrorEventListener> + void setAttributeEventListener(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget); + bool setAttributeEventListener(const AtomString& eventType, RefPtr<EventListener>&&, DOMWrapperWorld&); + JSEventListener* attributeEventListener(const AtomString& eventType, DOMWrapperWorld&); + + bool hasEventListeners() const; + bool hasEventListeners(const AtomString& eventType) const; + bool hasCapturingEventListeners(const AtomString& eventType); + bool hasActiveEventListeners(const AtomString& eventType) const; + + Vector<AtomString> eventTypes(); + const EventListenerVector& eventListeners(const AtomString& eventType); + + enum class EventInvokePhase { Capturing, + Bubbling }; + void fireEventListeners(Event&, EventInvokePhase); + bool isFiringEventListeners() const; + + template<typename Visitor> void visitJSEventListeners(Visitor&); + void invalidateJSEventListeners(JSC::JSObject*); + + const EventTargetData* eventTargetData() const; + +protected: + WEBCORE_EXPORT virtual ~EventTarget(); + + virtual EventTargetData* eventTargetData() = 0; + virtual EventTargetData* eventTargetDataConcurrently() = 0; + virtual EventTargetData& ensureEventTargetData() = 0; + + virtual void eventListenersDidChange() {} + +private: + virtual void refEventTarget() = 0; + virtual void derefEventTarget() = 0; + + void innerInvokeEventListeners(Event&, EventListenerVector, EventInvokePhase); + void invalidateEventListenerRegions(); +}; + +class EventTargetWithInlineData : public EventTarget { + WTF_MAKE_ISO_ALLOCATED_EXPORT(EventTargetWithInlineData, WEBCORE_EXPORT); + +protected: + EventTargetData* eventTargetData() final { return &m_eventTargetData; } + EventTargetData* eventTargetDataConcurrently() final { return &m_eventTargetData; } + EventTargetData& ensureEventTargetData() final { return m_eventTargetData; } + +private: + EventTargetData m_eventTargetData; +}; + +inline const EventTargetData* EventTarget::eventTargetData() const +{ + return const_cast<EventTarget*>(this)->eventTargetData(); +} + +inline bool EventTarget::isFiringEventListeners() const +{ + auto* data = eventTargetData(); + return data && data->isFiringEventListeners; +} + +inline bool EventTarget::hasEventListeners() const +{ + auto* data = eventTargetData(); + return data && !data->eventListenerMap.isEmpty(); +} + +inline bool EventTarget::hasEventListeners(const AtomString& eventType) const +{ + auto* data = eventTargetData(); + return data && data->eventListenerMap.contains(eventType); +} + +inline bool EventTarget::hasCapturingEventListeners(const AtomString& eventType) +{ + auto* data = eventTargetData(); + return data && data->eventListenerMap.containsCapturing(eventType); +} + +template<typename Visitor> +void EventTarget::visitJSEventListeners(Visitor& visitor) +{ + if (auto* data = eventTargetDataConcurrently()) + data->eventListenerMap.visitJSEventListeners(visitor); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventTarget.idl b/src/javascript/jsc/bindings/webcore/EventTarget.idl new file mode 100644 index 000000000..3c3264b6e --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventTarget.idl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2006-2017 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +[ + CustomToJSObject, + Exposed=*, + IsImmutablePrototypeExoticObjectOnPrototype, + JSCustomHeader, + JSCustomMarkFunction, + JSCustomToNativeObject, +] interface EventTarget { + [CallWith=CurrentScriptExecutionContext] constructor(); + + [ImplementedAs=addEventListenerForBindings] undefined addEventListener([AtomString] DOMString type, EventListener? listener, optional (AddEventListenerOptions or boolean) options = false); + [ImplementedAs=removeEventListenerForBindings] undefined removeEventListener([AtomString] DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options = false); + [ImplementedAs=dispatchEventForBindings] boolean dispatchEvent(Event event); +}; diff --git a/src/javascript/jsc/bindings/webcore/EventTargetConcrete.cpp b/src/javascript/jsc/bindings/webcore/EventTargetConcrete.cpp new file mode 100644 index 000000000..ded224beb --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventTargetConcrete.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 Alexey Shvayka <shvaikalesh@gmail.com>. + * + * 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. + */ + +#include "config.h" +#include "EventTargetConcrete.h" + +namespace WebCore { + +WTF_MAKE_ISO_ALLOCATED_IMPL(EventTargetConcrete); + +Ref<EventTargetConcrete> EventTargetConcrete::create(ScriptExecutionContext& context) +{ + return adoptRef(*new EventTargetConcrete(context)); +} + +EventTargetConcrete::EventTargetConcrete(ScriptExecutionContext& context) + : ContextDestructionObserver(&context) +{ +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventTargetConcrete.h b/src/javascript/jsc/bindings/webcore/EventTargetConcrete.h new file mode 100644 index 000000000..202be2d9e --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventTargetConcrete.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 Alexey Shvayka <shvaikalesh@gmail.com>. + * + * 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 "root.h" +#include "ContextDestructionObserver.h" +#include "EventTarget.h" +#include "EventTargetInterfaces.h" +#include "ScriptExecutionContext.h" +// #include <wtf/IsoMallocInlines.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +class EventTargetConcrete final : public RefCounted<EventTargetConcrete>, public EventTargetWithInlineData, private ContextDestructionObserver { + WTF_MAKE_ISO_ALLOCATED(EventTargetConcrete); + +public: + static Ref<EventTargetConcrete> create(ScriptExecutionContext&); + + bool hasEventTargetData() const { return true; } + + using RefCounted::deref; + using RefCounted::ref; + +private: + explicit EventTargetConcrete(ScriptExecutionContext&); + + EventTargetInterface eventTargetInterface() const final { return EventTargetInterfaceType; } + ScriptExecutionContext* scriptExecutionContext() const final { return ContextDestructionObserver::scriptExecutionContext(); } + + void refEventTarget() final { ref(); } + void derefEventTarget() final { deref(); } +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventTargetFactory.cpp b/src/javascript/jsc/bindings/webcore/EventTargetFactory.cpp new file mode 100644 index 000000000..133ac17dc --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventTargetFactory.cpp @@ -0,0 +1,281 @@ +/* + * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. + * + * Copyright (C) 2011 Google 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 GOOGLE, INC. ``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 + * 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. + */ + +#include "config.h" +#include "EventTargetHeaders.h" +#include "JSDOMWrapperCache.h" + +#include "JSDOMGlobalObject.h" +#include <JavaScriptCore/StructureInlines.h> + +namespace WebCore { + +JSC::JSValue toJS(JSC::JSGlobalObject* state, JSDOMGlobalObject* globalObject, EventTarget& impl) +{ + switch (impl.eventTargetInterface()) { + case EventTargetInterfaceType: + break; + case AbortSignalEventTargetInterfaceType: + return toJS(state, globalObject, static_cast<AbortSignal&>(impl)); + // #if ENABLE(APPLE_PAY) + // case ApplePaySessionEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<ApplePaySession&>(impl)); + // #endif + // #if ENABLE(WEB_AUDIO) + // case AudioNodeEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<AudioNode&>(impl)); + // #endif + // #if ENABLE(VIDEO) + // case AudioTrackListEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<AudioTrackList&>(impl)); + // #endif + // #if ENABLE(WEB_AUDIO) + // case BaseAudioContextEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<BaseAudioContext&>(impl)); + // #endif + // case BroadcastChannelEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<BroadcastChannel&>(impl)); + // case ClipboardEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<Clipboard&>(impl)); + // case DOMApplicationCacheEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<DOMApplicationCache&>(impl)); + // case DOMWindowEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<DOMWindow&>(impl)); + // case DedicatedWorkerGlobalScopeEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<DedicatedWorkerGlobalScope&>(impl)); + // case EventSourceEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<EventSource&>(impl)); + // case FileReaderEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<FileReader&>(impl)); + // case FontFaceSetEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<FontFaceSet&>(impl)); + // case GPUDeviceEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<GPUDevice&>(impl)); + // case IDBDatabaseEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<IDBDatabase&>(impl)); + // case IDBOpenDBRequestEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<IDBOpenDBRequest&>(impl)); + // case IDBRequestEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<IDBRequest&>(impl)); + // case IDBTransactionEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<IDBTransaction&>(impl)); + // #if ENABLE(VIDEO) + // case MediaControllerEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaController&>(impl)); + // #endif + // #if ENABLE(MEDIA_STREAM) + // case MediaDevicesEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaDevices&>(impl)); + // #endif + // #if ENABLE(ENCRYPTED_MEDIA) + // case MediaKeySessionEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaKeySession&>(impl)); + // #endif + // case MediaQueryListEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaQueryList&>(impl)); + // #if ENABLE(MEDIA_RECORDER) + // case MediaRecorderEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaRecorder&>(impl)); + // #endif + // #if ENABLE(MEDIA_SESSION_COORDINATOR) + // case MediaSessionCoordinatorEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaSessionCoordinator&>(impl)); + // #endif + // #if ENABLE(MEDIA_SOURCE) + // case MediaSourceEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaSource&>(impl)); + // #endif + // #if ENABLE(MEDIA_STREAM) + // case MediaStreamEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaStream&>(impl)); + // #endif + // #if ENABLE(MEDIA_STREAM) + // case MediaStreamTrackEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MediaStreamTrack&>(impl)); + // #endif + // case MessagePortEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<MessagePort&>(impl)); + // case NodeEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<Node&>(impl)); + // #if ENABLE(NOTIFICATIONS) + // case NotificationEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<Notification&>(impl)); + // #endif + // #if ENABLE(OFFSCREEN_CANVAS) + // case OffscreenCanvasEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<OffscreenCanvas&>(impl)); + // #endif + // #if ENABLE(PAYMENT_REQUEST) + // case PaymentRequestEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<PaymentRequest&>(impl)); + // #endif + // #if ENABLE(PAYMENT_REQUEST) + // case PaymentResponseEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<PaymentResponse&>(impl)); + // #endif + // case PerformanceEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<Performance&>(impl)); + // case PermissionStatusEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<PermissionStatus&>(impl)); + // #if ENABLE(PICTURE_IN_PICTURE_API) + // case PictureInPictureWindowEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<PictureInPictureWindow&>(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCDTMFSenderEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RTCDTMFSender&>(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCDataChannelEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RTCDataChannel&>(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCDtlsTransportEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RTCDtlsTransport&>(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCIceTransportEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RTCIceTransport&>(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCPeerConnectionEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RTCPeerConnection&>(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCRtpSFrameTransformEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RTCRtpSFrameTransform&>(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCRtpScriptTransformEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RTCRtpScriptTransform&>(impl)); + // #endif + // #if ENABLE(WEB_RTC) + // case RTCSctpTransportEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RTCSctpTransport&>(impl)); + // #endif + // #if ENABLE(WIRELESS_PLAYBACK_TARGET) + // case RemotePlaybackEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<RemotePlayback&>(impl)); + // #endif + // #if ENABLE(SERVICE_WORKER) + // case ServiceWorkerEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<ServiceWorker&>(impl)); + // #endif + // #if ENABLE(SERVICE_WORKER) + // case ServiceWorkerContainerEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<ServiceWorkerContainer&>(impl)); + // #endif + // #if ENABLE(SERVICE_WORKER) + // case ServiceWorkerGlobalScopeEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<ServiceWorkerGlobalScope&>(impl)); + // #endif + // #if ENABLE(SERVICE_WORKER) + // case ServiceWorkerRegistrationEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<ServiceWorkerRegistration&>(impl)); + // #endif + // case SharedWorkerEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<SharedWorker&>(impl)); + // case SharedWorkerGlobalScopeEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<SharedWorkerGlobalScope&>(impl)); + // #if ENABLE(MEDIA_SOURCE) + // case SourceBufferEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<SourceBuffer&>(impl)); + // #endif + // #if ENABLE(MEDIA_SOURCE) + // case SourceBufferListEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<SourceBufferList&>(impl)); + // #endif + // case SpeechRecognitionEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<SpeechRecognition&>(impl)); + // #if ENABLE(SPEECH_SYNTHESIS) + // case SpeechSynthesisEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<SpeechSynthesis&>(impl)); + // #endif + // #if ENABLE(SPEECH_SYNTHESIS) + // case SpeechSynthesisUtteranceEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<SpeechSynthesisUtterance&>(impl)); + // #endif + // #if ENABLE(VIDEO) + // case TextTrackEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<TextTrack&>(impl)); + // #endif + // #if ENABLE(VIDEO) + // case TextTrackCueEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<TextTrackCue&>(impl)); + // #endif + // #if ENABLE(VIDEO) + // case TextTrackCueGenericEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<TextTrackCueGeneric&>(impl)); + // #endif + // #if ENABLE(VIDEO) + // case TextTrackListEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<TextTrackList&>(impl)); + // #endif + // #if ENABLE(VIDEO) + // case VideoTrackListEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<VideoTrackList&>(impl)); + // #endif + // case VisualViewportEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<VisualViewport&>(impl)); + // case WebAnimationEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<WebAnimation&>(impl)); + // #if ENABLE(LEGACY_ENCRYPTED_MEDIA) + // case WebKitMediaKeySessionEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<WebKitMediaKeySession&>(impl)); + // #endif + // case WebSocketEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<WebSocket&>(impl)); + // #if ENABLE(WEBXR) + // case WebXRLayerEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<WebXRLayer&>(impl)); + // #endif + // #if ENABLE(WEBXR) + // case WebXRSessionEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<WebXRSession&>(impl)); + // #endif + // #if ENABLE(WEBXR) + // case WebXRSpaceEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<WebXRSpace&>(impl)); + // #endif + // #if ENABLE(WEBXR) + // case WebXRSystemEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<WebXRSystem&>(impl)); + // #endif + // case WorkerEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<Worker&>(impl)); + // case WorkletGlobalScopeEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<WorkletGlobalScope&>(impl)); + // case XMLHttpRequestEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<XMLHttpRequest&>(impl)); + // case XMLHttpRequestUploadEventTargetInterfaceType: + // return toJS(state, globalObject, static_cast<XMLHttpRequestUpload&>(impl)); + // } + } + return wrap(state, globalObject, impl); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/EventTargetHeaders.h b/src/javascript/jsc/bindings/webcore/EventTargetHeaders.h new file mode 100644 index 000000000..785ededd5 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventTargetHeaders.h @@ -0,0 +1,266 @@ +/* + * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. + * + * Copyright (C) 2011 Google 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 GOOGLE, INC. ``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 + * 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. + */ + +#ifndef EventTargetHeaders_h +#define EventTargetHeaders_h + +#include "AbortSignal.h" +#include "JSAbortSignal.h" +// #if ENABLE(APPLE_PAY) +// #include "ApplePaySession.h" +// #include "JSApplePaySession.h" +// #endif +// #if ENABLE(WEB_AUDIO) +// #include "AudioNode.h" +// #include "JSAudioNode.h" +// #endif +// #if ENABLE(VIDEO) +// #include "AudioTrackList.h" +// #include "JSAudioTrackList.h" +// #endif +// #if ENABLE(WEB_AUDIO) +// #include "BaseAudioContext.h" +// #include "JSBaseAudioContext.h" +// #endif +// #include "BroadcastChannel.h" +// #include "Clipboard.h" +// #include "DOMApplicationCache.h" +// #include "DOMWindow.h" +// #include "DedicatedWorkerGlobalScope.h" +// #include "EventSource.h" +// #include "FileReader.h" +// #include "FontFaceSet.h" +// #include "GPUDevice.h" +// #include "IDBDatabase.h" +// #include "IDBOpenDBRequest.h" +// #include "IDBRequest.h" +// #include "IDBTransaction.h" +// #include "JSBroadcastChannel.h" +// #include "JSClipboard.h" +// #include "JSDOMApplicationCache.h" +// #include "JSDOMWindow.h" +// #include "JSDedicatedWorkerGlobalScope.h" +// #include "JSEventSource.h" +// #include "JSFileReader.h" +// #include "JSFontFaceSet.h" +// #include "JSGPUDevice.h" +// #include "JSIDBDatabase.h" +// #include "JSIDBOpenDBRequest.h" +// #include "JSIDBRequest.h" +// #include "JSIDBTransaction.h" +// #if ENABLE(VIDEO) +// #include "JSMediaController.h" +// #include "MediaController.h" +// #endif +// #if ENABLE(MEDIA_STREAM) +// #include "JSMediaDevices.h" +// #include "MediaDevices.h" +// #endif +// #if ENABLE(ENCRYPTED_MEDIA) +// #include "JSMediaKeySession.h" +// #include "MediaKeySession.h" +// #endif +// #include "JSMediaQueryList.h" +// #include "MediaQueryList.h" +// #if ENABLE(MEDIA_RECORDER) +// #include "JSMediaRecorder.h" +// #include "MediaRecorder.h" +// #endif +// #if ENABLE(MEDIA_SESSION_COORDINATOR) +// #include "JSMediaSessionCoordinator.h" +// #include "MediaSessionCoordinator.h" +// #endif +// #if ENABLE(MEDIA_SOURCE) +// #include "JSMediaSource.h" +// #include "MediaSource.h" +// #endif +// #if ENABLE(MEDIA_STREAM) +// #include "JSMediaStream.h" +// #include "MediaStream.h" +// #endif +// #if ENABLE(MEDIA_STREAM) +// #include "JSMediaStreamTrack.h" +// #include "MediaStreamTrack.h" +// #endif +// #include "MessagePort.h" +// #include "JSMessagePort.h" +// #include "JSNode.h" +#include "Node.h" +// #if ENABLE(NOTIFICATIONS) +// #include "JSNotification.h" +// #include "Notification.h" +// #endif +// #if ENABLE(OFFSCREEN_CANVAS) +// #include "JSOffscreenCanvas.h" +// #include "OffscreenCanvas.h" +// #endif +// #if ENABLE(PAYMENT_REQUEST) +// #include "JSPaymentRequest.h" +// #include "PaymentRequest.h" +// #endif +// #if ENABLE(PAYMENT_REQUEST) +// #include "JSPaymentResponse.h" +// #include "PaymentResponse.h" +// #endif +// #include "JSPerformance.h" +// #include "JSPermissionStatus.h" +// #include "Performance.h" +// #include "PermissionStatus.h" +// #if ENABLE(PICTURE_IN_PICTURE_API) +// #include "JSPictureInPictureWindow.h" +// #include "PictureInPictureWindow.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "JSRTCDTMFSender.h" +// #include "RTCDTMFSender.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "JSRTCDataChannel.h" +// #include "RTCDataChannel.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "JSRTCDtlsTransport.h" +// #include "RTCDtlsTransport.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "JSRTCIceTransport.h" +// #include "RTCIceTransport.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "JSRTCPeerConnection.h" +// #include "RTCPeerConnection.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "JSRTCRtpSFrameTransform.h" +// #include "RTCRtpSFrameTransform.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "JSRTCRtpScriptTransform.h" +// #include "RTCRtpScriptTransform.h" +// #endif +// #if ENABLE(WEB_RTC) +// #include "JSRTCSctpTransport.h" +// #include "RTCSctpTransport.h" +// #endif +// #if ENABLE(WIRELESS_PLAYBACK_TARGET) +// #include "JSRemotePlayback.h" +// #include "RemotePlayback.h" +// #endif +// #if ENABLE(SERVICE_WORKER) +// #include "JSServiceWorker.h" +// #include "ServiceWorker.h" +// #endif +// #if ENABLE(SERVICE_WORKER) +// #include "JSServiceWorkerContainer.h" +// #include "ServiceWorkerContainer.h" +// #endif +// #if ENABLE(SERVICE_WORKER) +// #include "JSServiceWorkerGlobalScope.h" +// #include "ServiceWorkerGlobalScope.h" +// #endif +// #if ENABLE(SERVICE_WORKER) +// #include "JSServiceWorkerRegistration.h" +// #include "ServiceWorkerRegistration.h" +// #endif +// #include "JSSharedWorker.h" +// #include "JSSharedWorkerGlobalScope.h" +// #include "SharedWorker.h" +// #include "SharedWorkerGlobalScope.h" +// #if ENABLE(MEDIA_SOURCE) +// #include "JSSourceBuffer.h" +// #include "SourceBuffer.h" +// #endif +// #if ENABLE(MEDIA_SOURCE) +// #include "JSSourceBufferList.h" +// #include "SourceBufferList.h" +// #endif +// #include "JSSpeechRecognition.h" +// #include "SpeechRecognition.h" +// #if ENABLE(SPEECH_SYNTHESIS) +// #include "JSSpeechSynthesis.h" +// #include "SpeechSynthesis.h" +// #endif +// #if ENABLE(SPEECH_SYNTHESIS) +// #include "JSSpeechSynthesisUtterance.h" +// #include "SpeechSynthesisUtterance.h" +// #endif +// #if ENABLE(VIDEO) +// #include "JSTextTrack.h" +// #include "TextTrack.h" +// #endif +// #if ENABLE(VIDEO) +// #include "JSTextTrackCue.h" +// #include "TextTrackCue.h" +// #endif +// #if ENABLE(VIDEO) +// #include "JSTextTrackCueGeneric.h" +// #include "TextTrackCueGeneric.h" +// #endif +// #if ENABLE(VIDEO) +// #include "JSTextTrackList.h" +// #include "TextTrackList.h" +// #endif +// #if ENABLE(VIDEO) +// #include "JSVideoTrackList.h" +// #include "VideoTrackList.h" +// #endif +// #include "VisualViewport.h" +// #include "JSVisualViewport.h" +// #include "WebAnimation.h" +// #include "JSWebAnimation.h" +// #if ENABLE(LEGACY_ENCRYPTED_MEDIA) +// #include "JSWebKitMediaKeySession.h" +// #include "WebKitMediaKeySession.h" +// #endif +// #include "WebSocket.h" +// #include "JSWebSocket.h" +// #if ENABLE(WEBXR) +// #include "JSWebXRLayer.h" +// #include "WebXRLayer.h" +// #endif +// #if ENABLE(WEBXR) +// #include "JSWebXRSession.h" +// #include "WebXRSession.h" +// #endif +// #if ENABLE(WEBXR) +// #include "JSWebXRSpace.h" +// #include "WebXRSpace.h" +// #endif +// #if ENABLE(WEBXR) +// #include "JSWebXRSystem.h" +// #include "WebXRSystem.h" +// #endif +// #include "Worker.h" +// #include "JSWorker.h" +// #include "WorkletGlobalScope.h" +// #include "JSWorkletGlobalScope.h" +// #include "XMLHttpRequest.h" +// #include "JSXMLHttpRequest.h" +// #include "XMLHttpRequestUpload.h" +// #include "JSXMLHttpRequestUpload.h" + +#endif // EventTargetHeaders_h diff --git a/src/javascript/jsc/bindings/webcore/EventTargetInterfaces.h b/src/javascript/jsc/bindings/webcore/EventTargetInterfaces.h new file mode 100644 index 000000000..0226d0c0e --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/EventTargetInterfaces.h @@ -0,0 +1,145 @@ +/* + * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. + * + * Copyright (C) 2011 Google 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 GOOGLE, INC. ``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 + * 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 + +namespace WebCore { + +enum EventTargetInterface { +#if ENABLE(APPLE_PAY) + ApplePaySessionEventTargetInterfaceType = 1, +#endif +#if ENABLE(ENCRYPTED_MEDIA) + MediaKeySessionEventTargetInterfaceType = 2, +#endif +#if ENABLE(LEGACY_ENCRYPTED_MEDIA) + WebKitMediaKeySessionEventTargetInterfaceType = 3, +#endif +#if ENABLE(MEDIA_RECORDER) + MediaRecorderEventTargetInterfaceType = 4, +#endif +#if ENABLE(MEDIA_SESSION_COORDINATOR) + MediaSessionCoordinatorEventTargetInterfaceType = 5, +#endif +#if ENABLE(MEDIA_SOURCE) + MediaSourceEventTargetInterfaceType = 6, + SourceBufferEventTargetInterfaceType = 7, + SourceBufferListEventTargetInterfaceType = 8, +#endif +#if ENABLE(MEDIA_STREAM) + MediaDevicesEventTargetInterfaceType = 9, + MediaStreamEventTargetInterfaceType = 10, + MediaStreamTrackEventTargetInterfaceType = 11, +#endif +#if ENABLE(NOTIFICATIONS) + NotificationEventTargetInterfaceType = 12, +#endif +#if ENABLE(OFFSCREEN_CANVAS) + OffscreenCanvasEventTargetInterfaceType = 13, +#endif +#if ENABLE(PAYMENT_REQUEST) + PaymentRequestEventTargetInterfaceType = 14, + PaymentResponseEventTargetInterfaceType = 15, +#endif +#if ENABLE(PICTURE_IN_PICTURE_API) + PictureInPictureWindowEventTargetInterfaceType = 16, +#endif +#if ENABLE(SERVICE_WORKER) + ServiceWorkerEventTargetInterfaceType = 17, + ServiceWorkerContainerEventTargetInterfaceType = 18, + ServiceWorkerGlobalScopeEventTargetInterfaceType = 19, + ServiceWorkerRegistrationEventTargetInterfaceType = 20, +#endif +#if ENABLE(SPEECH_SYNTHESIS) + SpeechSynthesisEventTargetInterfaceType = 21, + SpeechSynthesisUtteranceEventTargetInterfaceType = 22, +#endif +#if ENABLE(VIDEO) + AudioTrackListEventTargetInterfaceType = 23, + MediaControllerEventTargetInterfaceType = 24, + TextTrackEventTargetInterfaceType = 25, + TextTrackCueEventTargetInterfaceType = 26, + TextTrackCueGenericEventTargetInterfaceType = 27, + TextTrackListEventTargetInterfaceType = 28, + VideoTrackListEventTargetInterfaceType = 29, +#endif +#if ENABLE(WEBXR) + WebXRLayerEventTargetInterfaceType = 30, + WebXRSessionEventTargetInterfaceType = 31, + WebXRSpaceEventTargetInterfaceType = 32, + WebXRSystemEventTargetInterfaceType = 33, +#endif +#if ENABLE(WEB_AUDIO) + AudioNodeEventTargetInterfaceType = 34, + BaseAudioContextEventTargetInterfaceType = 35, +#endif +#if ENABLE(WEB_RTC) + RTCDTMFSenderEventTargetInterfaceType = 36, + RTCDataChannelEventTargetInterfaceType = 37, + RTCDtlsTransportEventTargetInterfaceType = 38, + RTCIceTransportEventTargetInterfaceType = 39, + RTCPeerConnectionEventTargetInterfaceType = 40, + RTCRtpSFrameTransformEventTargetInterfaceType = 41, + RTCRtpScriptTransformEventTargetInterfaceType = 42, + RTCSctpTransportEventTargetInterfaceType = 43, +#endif +#if ENABLE(WIRELESS_PLAYBACK_TARGET) + RemotePlaybackEventTargetInterfaceType = 44, +#endif + EventTargetInterfaceType = 45, + AbortSignalEventTargetInterfaceType = 46, + BroadcastChannelEventTargetInterfaceType = 47, + ClipboardEventTargetInterfaceType = 48, + DOMApplicationCacheEventTargetInterfaceType = 49, + DOMWindowEventTargetInterfaceType = 50, + DedicatedWorkerGlobalScopeEventTargetInterfaceType = 51, + EventSourceEventTargetInterfaceType = 52, + FileReaderEventTargetInterfaceType = 53, + FontFaceSetEventTargetInterfaceType = 54, + GPUDeviceEventTargetInterfaceType = 55, + IDBDatabaseEventTargetInterfaceType = 56, + IDBOpenDBRequestEventTargetInterfaceType = 57, + IDBRequestEventTargetInterfaceType = 58, + IDBTransactionEventTargetInterfaceType = 59, + MediaQueryListEventTargetInterfaceType = 60, + MessagePortEventTargetInterfaceType = 61, + NodeEventTargetInterfaceType = 62, + PerformanceEventTargetInterfaceType = 63, + PermissionStatusEventTargetInterfaceType = 64, + SharedWorkerEventTargetInterfaceType = 65, + SharedWorkerGlobalScopeEventTargetInterfaceType = 66, + SpeechRecognitionEventTargetInterfaceType = 67, + VisualViewportEventTargetInterfaceType = 68, + WebAnimationEventTargetInterfaceType = 69, + WebSocketEventTargetInterfaceType = 70, + WorkerEventTargetInterfaceType = 71, + WorkletGlobalScopeEventTargetInterfaceType = 72, + XMLHttpRequestEventTargetInterfaceType = 73, + XMLHttpRequestUploadEventTargetInterfaceType = 74, +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSAbortAlgorithm.cpp b/src/javascript/jsc/bindings/webcore/JSAbortAlgorithm.cpp new file mode 100644 index 000000000..0d7765ddf --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortAlgorithm.cpp @@ -0,0 +1,86 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSAbortAlgorithm.h" + +#include "JSDOMConvertBase.h" +#include "JSDOMExceptionHandling.h" +#include "ScriptExecutionContext.h" + + +namespace WebCore { +using namespace JSC; + +JSAbortAlgorithm::JSAbortAlgorithm(VM& vm, JSObject* callback) + : AbortAlgorithm(jsCast<JSDOMGlobalObject*>(callback->globalObject(vm))->scriptExecutionContext()) + , m_data(new JSCallbackDataStrong(vm, callback, this)) +{ +} + +JSAbortAlgorithm::~JSAbortAlgorithm() +{ + ScriptExecutionContext* context = scriptExecutionContext(); + // When the context is destroyed, all tasks with a reference to a callback + // should be deleted. So if the context is 0, we are on the context thread. + if (!context || context->isContextThread()) + delete m_data; + else + context->postTask(DeleteCallbackDataTask(m_data)); +#ifndef NDEBUG + m_data = nullptr; +#endif +} + +CallbackResult<typename IDLUndefined::ImplementationType> JSAbortAlgorithm::handleEvent() +{ + if (!canInvokeCallback()) + return CallbackResultType::UnableToExecute; + + Ref<JSAbortAlgorithm> protectedThis(*this); + + auto& globalObject = *jsCast<JSDOMGlobalObject*>(m_data->callback()->globalObject()); + auto& vm = globalObject.vm(); + + JSLockHolder lock(vm); + auto& lexicalGlobalObject = globalObject; + JSValue thisValue = jsUndefined(); + MarkedArgumentBuffer args; + ASSERT(!args.hasOverflowed()); + + NakedPtr<JSC::Exception> returnedException; + m_data->invokeCallback(vm, thisValue, args, JSCallbackData::CallbackType::Function, Identifier(), returnedException); + if (returnedException) { + reportException(&lexicalGlobalObject, returnedException); + return CallbackResultType::ExceptionThrown; + } + + return { }; +} + +JSC::JSValue toJS(AbortAlgorithm& impl) +{ + if (!static_cast<JSAbortAlgorithm&>(impl).callbackData()) + return jsNull(); + + return static_cast<JSAbortAlgorithm&>(impl).callbackData()->callback(); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSAbortAlgorithm.h b/src/javascript/jsc/bindings/webcore/JSAbortAlgorithm.h new file mode 100644 index 000000000..9193ac7e6 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortAlgorithm.h @@ -0,0 +1,54 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "AbortAlgorithm.h" +#include "IDLTypes.h" +#include "JSCallbackData.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class JSAbortAlgorithm final : public AbortAlgorithm { +public: + static Ref<JSAbortAlgorithm> create(JSC::VM& vm, JSC::JSObject* callback) + { + return adoptRef(*new JSAbortAlgorithm(vm, callback)); + } + + ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); } + + ~JSAbortAlgorithm() final; + JSCallbackDataStrong* callbackData() { return m_data; } + + // Functions + CallbackResult<typename IDLUndefined::ImplementationType> handleEvent() override; + +private: + JSAbortAlgorithm(JSC::VM&, JSC::JSObject* callback); + + JSCallbackDataStrong* m_data; +}; + +JSC::JSValue toJS(AbortAlgorithm&); +inline JSC::JSValue toJS(AbortAlgorithm* impl) { return impl ? toJS(*impl) : JSC::jsNull(); } + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSAbortController.cpp b/src/javascript/jsc/bindings/webcore/JSAbortController.cpp new file mode 100644 index 000000000..5c93b9d83 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortController.cpp @@ -0,0 +1,323 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSAbortController.h" + +#include "ActiveDOMObject.h" +#include "ExtendedDOMClientIsoSubspaces.h" +#include "ExtendedDOMIsoSubspaces.h" +#include "IDLTypes.h" +#include "JSAbortSignal.h" +#include "JSDOMAttribute.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructor.h" +#include "JSDOMConvertAny.h" +#include "JSDOMConvertBase.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMOperation.h" +#include "JSDOMWrapperCache.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include <JavaScriptCore/FunctionPrototype.h> +#include <JavaScriptCore/HeapAnalyzer.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h> +#include <JavaScriptCore/SlotVisitorMacros.h> +#include <JavaScriptCore/SubspaceInlines.h> +#include <wtf/GetPtr.h> +#include <wtf/PointerPreparations.h> +#include <wtf/URL.h> + +namespace WebCore { +using namespace JSC; + +// Functions + +static JSC_DECLARE_HOST_FUNCTION(jsAbortControllerPrototypeFunction_abort); + +// Attributes + +static JSC_DECLARE_CUSTOM_GETTER(jsAbortControllerConstructor); +static JSC_DECLARE_CUSTOM_GETTER(jsAbortController_signal); + +class JSAbortControllerPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSAbortControllerPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure) + { + JSAbortControllerPrototype* ptr = new (NotNull, JSC::allocateCell<JSAbortControllerPrototype>(vm)) JSAbortControllerPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSAbortControllerPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSAbortControllerPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) + : JSC::JSNonFinalObject(vm, structure) + { + } + + void finishCreation(JSC::VM&); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSAbortControllerPrototype, JSAbortControllerPrototype::Base); + +using JSAbortControllerDOMConstructor = JSDOMConstructor<JSAbortController>; + +template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSAbortControllerDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +{ + VM& vm = lexicalGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* castedThis = jsCast<JSAbortControllerDOMConstructor*>(callFrame->jsCallee()); + ASSERT(castedThis); + auto* context = castedThis->scriptExecutionContext(); + if (UNLIKELY(!context)) + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "AbortController"); + auto object = AbortController::create(*context); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + static_assert(TypeOrExceptionOrUnderlyingType<decltype(object)>::isRef); + auto jsValue = toJSNewlyCreated<IDLInterface<AbortController>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + setSubclassStructureIfNeeded<AbortController>(lexicalGlobalObject, callFrame, asObject(jsValue)); + RETURN_IF_EXCEPTION(throwScope, {}); + return JSValue::encode(jsValue); +} +JSC_ANNOTATE_HOST_FUNCTION(JSAbortControllerDOMConstructorConstruct, JSAbortControllerDOMConstructor::construct); + +template<> const ClassInfo JSAbortControllerDOMConstructor::s_info = { "AbortController"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAbortControllerDOMConstructor) }; + +template<> JSValue JSAbortControllerDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject) +{ + UNUSED_PARAM(vm); + return globalObject.functionPrototype(); +} + +template<> void JSAbortControllerDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) +{ + putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSString* nameString = jsNontrivialString(vm, "AbortController"_s); + m_originalName.set(vm, this, nameString); + putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + putDirect(vm, vm.propertyNames->prototype, JSAbortController::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); +} + +/* Hash table for prototype */ + +static const HashTableValue JSAbortControllerPrototypeTableValues[] = { + { "constructor", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsAbortControllerConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "signal", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsAbortController_signal), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "abort", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsAbortControllerPrototypeFunction_abort), (intptr_t)(0) } }, +}; + +const ClassInfo JSAbortControllerPrototype::s_info = { "AbortController"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAbortControllerPrototype) }; + +void JSAbortControllerPrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSAbortController::info(), JSAbortControllerPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +const ClassInfo JSAbortController::s_info = { "AbortController"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAbortController) }; + +JSAbortController::JSAbortController(Structure* structure, JSDOMGlobalObject& globalObject, Ref<AbortController>&& impl) + : JSDOMWrapper<AbortController>(structure, globalObject, WTFMove(impl)) +{ +} + +void JSAbortController::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + + // static_assert(!std::is_base_of<ActiveDOMObject, AbortController>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); +} + +JSObject* JSAbortController::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSAbortControllerPrototype::create(vm, &globalObject, JSAbortControllerPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); +} + +JSObject* JSAbortController::prototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return getDOMPrototype<JSAbortController>(vm, globalObject); +} + +JSValue JSAbortController::getConstructor(VM& vm, const JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSAbortControllerDOMConstructor, DOMConstructorID::AbortController>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject)); +} + +void JSAbortController::destroy(JSC::JSCell* cell) +{ + JSAbortController* thisObject = static_cast<JSAbortController*>(cell); + thisObject->JSAbortController::~JSAbortController(); +} + +JSC_DEFINE_CUSTOM_GETTER(jsAbortControllerConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* prototype = jsDynamicCast<JSAbortControllerPrototype*>(vm, JSValue::decode(thisValue)); + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(JSAbortController::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject())); +} + +static inline JSValue jsAbortController_signalGetter(JSGlobalObject& lexicalGlobalObject, JSAbortController& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLInterface<AbortSignal>>(lexicalGlobalObject, *thisObject.globalObject(), throwScope, impl.signal()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsAbortController_signal, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSAbortController>::get<jsAbortController_signalGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSC::EncodedJSValue jsAbortControllerPrototypeFunction_abortBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSAbortController>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + EnsureStillAliveScope argument0 = callFrame->argument(0); + auto reason = convert<IDLAny>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.abort(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), WTFMove(reason)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsAbortControllerPrototypeFunction_abort, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSAbortController>::call<jsAbortControllerPrototypeFunction_abortBody>(*lexicalGlobalObject, *callFrame, "abort"); +} + +JSC::GCClient::IsoSubspace* JSAbortController::subspaceForImpl(JSC::VM& vm) +{ + return WebCore::subspaceForImpl<JSAbortController, UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForAbortController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForAbortController = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForAbortController.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForAbortController = WTFMove(space); }); +} + +template<typename Visitor> +void JSAbortController::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + auto* thisObject = jsCast<JSAbortController*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + visitor.addOpaqueRoot(WTF::getPtr(thisObject->wrapped().signal())); +} + +DEFINE_VISIT_CHILDREN(JSAbortController); + +void JSAbortController::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSAbortController*>(cell); + analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); + if (thisObject->scriptExecutionContext()) + analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + Base::analyzeHeap(cell, analyzer); +} + +bool JSAbortControllerOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, AbstractSlotVisitor& visitor, const char** reason) +{ + UNUSED_PARAM(handle); + UNUSED_PARAM(visitor); + UNUSED_PARAM(reason); + return false; +} + +void JSAbortControllerOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) +{ + auto* jsAbortController = static_cast<JSAbortController*>(handle.slot()->asCell()); + auto& world = *static_cast<DOMWrapperWorld*>(context); + uncacheWrapper(world, &jsAbortController->wrapped(), jsAbortController); +} + +#if ENABLE(BINDING_INTEGRITY) +#if PLATFORM(WIN) +#pragma warning(disable : 4483) +extern "C" { +extern void (*const __identifier("??_7AbortController@WebCore@@6B@")[])(); +} +#else +extern "C" { +extern void* _ZTVN7WebCore15AbortControllerE[]; +} +#endif +#endif + +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<AbortController>&& impl) +{ + + if constexpr (std::is_polymorphic_v<AbortController>) { +#if ENABLE(BINDING_INTEGRITY) + const void* actualVTablePointer = getVTablePointer(impl.ptr()); +#if PLATFORM(WIN) + void* expectedVTablePointer = __identifier("??_7AbortController@WebCore@@6B@"); +#else + void* expectedVTablePointer = &_ZTVN7WebCore15AbortControllerE[2]; +#endif + + // If you hit this assertion you either have a use after free bug, or + // AbortController has subclasses. If AbortController has subclasses that get passed + // to toJS() we currently require AbortController you to opt out of binding hardening + // by adding the SkipVTableValidation attribute to the interface IDL definition + RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); +#endif + } + return createWrapper<AbortController>(globalObject, WTFMove(impl)); +} + +JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, AbortController& impl) +{ + return wrap(lexicalGlobalObject, globalObject, impl); +} + +AbortController* JSAbortController::toWrapped(JSC::VM& vm, JSC::JSValue value) +{ + if (auto* wrapper = jsDynamicCast<JSAbortController*>(vm, value)) + return &wrapper->wrapped(); + return nullptr; +} + +} diff --git a/src/javascript/jsc/bindings/webcore/JSAbortController.dep b/src/javascript/jsc/bindings/webcore/JSAbortController.dep new file mode 100644 index 000000000..c62eba8ee --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortController.dep @@ -0,0 +1 @@ +JSAbortController.h : diff --git a/src/javascript/jsc/bindings/webcore/JSAbortController.h b/src/javascript/jsc/bindings/webcore/JSAbortController.h new file mode 100644 index 000000000..4b5d02f72 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortController.h @@ -0,0 +1,95 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "AbortController.h" +#include "JSDOMWrapper.h" +#include <wtf/NeverDestroyed.h> + +namespace WebCore { + +class JSAbortController : public JSDOMWrapper<AbortController> { +public: + using Base = JSDOMWrapper<AbortController>; + static JSAbortController* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<AbortController>&& impl) + { + JSAbortController* ptr = new (NotNull, JSC::allocateCell<JSAbortController>(globalObject->vm())) JSAbortController(structure, *globalObject, WTFMove(impl)); + ptr->finishCreation(globalObject->vm()); + return ptr; + } + + static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&); + static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&); + static AbortController* toWrapped(JSC::VM&, JSC::JSValue); + static void destroy(JSC::JSCell*); + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info(), JSC::NonArray); + } + + static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*); + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return subspaceForImpl(vm); + } + static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); + DECLARE_VISIT_CHILDREN; + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); +protected: + JSAbortController(JSC::Structure*, JSDOMGlobalObject&, Ref<AbortController>&&); + + void finishCreation(JSC::VM&); +}; + +class JSAbortControllerOwner final : public JSC::WeakHandleOwner { +public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) final; + void finalize(JSC::Handle<JSC::Unknown>, void* context) final; +}; + +inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, AbortController*) +{ + static NeverDestroyed<JSAbortControllerOwner> owner; + return &owner.get(); +} + +inline void* wrapperKey(AbortController* wrappableObject) +{ + return wrappableObject; +} + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, AbortController&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, AbortController* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<AbortController>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<AbortController>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +template<> struct JSDOMWrapperConverterTraits<AbortController> { + using WrapperClass = JSAbortController; + using ToWrappedReturnType = AbortController*; +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSAbortSignal.cpp b/src/javascript/jsc/bindings/webcore/JSAbortSignal.cpp new file mode 100644 index 000000000..24320ba82 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortSignal.cpp @@ -0,0 +1,424 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSAbortSignal.h" + +#include "ActiveDOMObject.h" +#include "EventNames.h" +#include "ExtendedDOMClientIsoSubspaces.h" +#include "ExtendedDOMIsoSubspaces.h" +#include "IDLTypes.h" +#include "JSAbortAlgorithm.h" +#include "JSAbortSignal.h" +#include "JSDOMAttribute.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructorNotConstructable.h" +#include "JSDOMConvertAny.h" +#include "JSDOMConvertBase.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertCallbacks.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMOperation.h" +#include "JSDOMWrapperCache.h" +#include "JSEventListener.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include <JavaScriptCore/HeapAnalyzer.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h> +#include <JavaScriptCore/SlotVisitorMacros.h> +#include <JavaScriptCore/SubspaceInlines.h> +#include <wtf/GetPtr.h> +#include <wtf/PointerPreparations.h> +#include <wtf/URL.h> + + +namespace WebCore { +using namespace JSC; + +// Functions + +static JSC_DECLARE_HOST_FUNCTION(jsAbortSignalConstructorFunction_whenSignalAborted); +static JSC_DECLARE_HOST_FUNCTION(jsAbortSignalConstructorFunction_abort); +static JSC_DECLARE_HOST_FUNCTION(jsAbortSignalConstructorFunction_timeout); +static JSC_DECLARE_HOST_FUNCTION(jsAbortSignalPrototypeFunction_throwIfAborted); + +// Attributes + +static JSC_DECLARE_CUSTOM_GETTER(jsAbortSignalConstructor); +static JSC_DECLARE_CUSTOM_GETTER(jsAbortSignal_aborted); +static JSC_DECLARE_CUSTOM_GETTER(jsAbortSignal_reason); +static JSC_DECLARE_CUSTOM_GETTER(jsAbortSignal_onabort); +static JSC_DECLARE_CUSTOM_SETTER(setJSAbortSignal_onabort); + +class JSAbortSignalPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSAbortSignalPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure) + { + JSAbortSignalPrototype* ptr = new (NotNull, JSC::allocateCell<JSAbortSignalPrototype>(vm)) JSAbortSignalPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSAbortSignalPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSAbortSignalPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) + : JSC::JSNonFinalObject(vm, structure) + { + } + + void finishCreation(JSC::VM&); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSAbortSignalPrototype, JSAbortSignalPrototype::Base); + +using JSAbortSignalDOMConstructor = JSDOMConstructorNotConstructable<JSAbortSignal>; + +/* Hash table for constructor */ + +static const HashTableValue JSAbortSignalConstructorTableValues[] = +{ + { "whenSignalAborted", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t)static_cast<RawNativeFunction>(jsAbortSignalConstructorFunction_whenSignalAborted), (intptr_t) (2) } }, + { "abort", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t)static_cast<RawNativeFunction>(jsAbortSignalConstructorFunction_abort), (intptr_t) (0) } }, + { "timeout", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t)static_cast<RawNativeFunction>(jsAbortSignalConstructorFunction_timeout), (intptr_t) (1) } }, +}; + +template<> const ClassInfo JSAbortSignalDOMConstructor::s_info = { "AbortSignal"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAbortSignalDOMConstructor) }; + +template<> JSValue JSAbortSignalDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject) +{ + return JSEventTarget::getConstructor(vm, &globalObject); +} + +template<> void JSAbortSignalDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) +{ + putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSString* nameString = jsNontrivialString(vm, "AbortSignal"_s); + m_originalName.set(vm, this, nameString); + putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + putDirect(vm, vm.propertyNames->prototype, JSAbortSignal::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); + reifyStaticProperties(vm, JSAbortSignal::info(), JSAbortSignalConstructorTableValues, *this); + if (!(jsCast<JSDOMGlobalObject*>(&globalObject)->scriptExecutionContext()->isDocument() || jsCast<JSDOMGlobalObject*>(&globalObject)->scriptExecutionContext()->isWorkerGlobalScope())) { + auto propertyName = Identifier::fromString(vm, reinterpret_cast<const LChar*>("timeout"), strlen("timeout")); + VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable); + DeletePropertySlot slot; + JSObject::deleteProperty(this, &globalObject, propertyName, slot); + } +} + +/* Hash table for prototype */ + +static const HashTableValue JSAbortSignalPrototypeTableValues[] = +{ + { "constructor", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsAbortSignalConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "aborted", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsAbortSignal_aborted), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "reason", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsAbortSignal_reason), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "onabort", static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsAbortSignal_onabort), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSAbortSignal_onabort) } }, + { "throwIfAborted", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t)static_cast<RawNativeFunction>(jsAbortSignalPrototypeFunction_throwIfAborted), (intptr_t) (0) } }, +}; + +const ClassInfo JSAbortSignalPrototype::s_info = { "AbortSignal"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAbortSignalPrototype) }; + +void JSAbortSignalPrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSAbortSignal::info(), JSAbortSignalPrototypeTableValues, *this); + putDirect(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().whenSignalAbortedPrivateName(), JSFunction::create(vm, globalObject(), 0, String(), jsAbortSignalConstructorFunction_whenSignalAborted), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +const ClassInfo JSAbortSignal::s_info = { "AbortSignal"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAbortSignal) }; + +JSAbortSignal::JSAbortSignal(Structure* structure, JSDOMGlobalObject& globalObject, Ref<AbortSignal>&& impl) + : JSEventTarget(structure, globalObject, WTFMove(impl)) +{ +} + +void JSAbortSignal::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + +} + +JSObject* JSAbortSignal::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSAbortSignalPrototype::create(vm, &globalObject, JSAbortSignalPrototype::createStructure(vm, &globalObject, JSEventTarget::prototype(vm, globalObject))); +} + +JSObject* JSAbortSignal::prototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return getDOMPrototype<JSAbortSignal>(vm, globalObject); +} + +JSValue JSAbortSignal::getConstructor(VM& vm, const JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSAbortSignalDOMConstructor, DOMConstructorID::AbortSignal>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject)); +} + +JSC_DEFINE_CUSTOM_GETTER(jsAbortSignalConstructor, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* prototype = jsDynamicCast<JSAbortSignalPrototype*>(vm, JSValue::decode(thisValue)); + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(JSAbortSignal::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject())); +} + +static inline JSValue jsAbortSignal_abortedGetter(JSGlobalObject& lexicalGlobalObject, JSAbortSignal& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.aborted()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsAbortSignal_aborted, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSAbortSignal>::get<jsAbortSignal_abortedGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsAbortSignal_reasonGetter(JSGlobalObject& lexicalGlobalObject, JSAbortSignal& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLAny>(lexicalGlobalObject, throwScope, impl.reason()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsAbortSignal_reason, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSAbortSignal>::get<jsAbortSignal_reasonGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsAbortSignal_onabortGetter(JSGlobalObject& lexicalGlobalObject, JSAbortSignal& thisObject) +{ + UNUSED_PARAM(lexicalGlobalObject); + return eventHandlerAttribute(thisObject.wrapped(), eventNames().abortEvent, worldForDOMObject(thisObject)); +} + +JSC_DEFINE_CUSTOM_GETTER(jsAbortSignal_onabort, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSAbortSignal>::get<jsAbortSignal_onabortGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline bool setJSAbortSignal_onabortSetter(JSGlobalObject& lexicalGlobalObject, JSAbortSignal& thisObject, JSValue value) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + setEventHandlerAttribute<JSEventListener>(thisObject.wrapped(), eventNames().abortEvent, value, thisObject); + vm.writeBarrier(&thisObject, value); + ensureStillAliveHere(value); + + return true; +} + +JSC_DEFINE_CUSTOM_SETTER(setJSAbortSignal_onabort, (JSGlobalObject* lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName)) +{ + return IDLAttribute<JSAbortSignal>::set<setJSAbortSignal_onabortSetter>(*lexicalGlobalObject, thisValue, encodedValue, attributeName); +} + +static inline JSC::EncodedJSValue jsAbortSignalConstructorFunction_whenSignalAbortedBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + if (UNLIKELY(callFrame->argumentCount() < 2)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto object = convert<IDLInterface<AbortSignal>>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "object", "AbortSignal", "whenSignalAborted", "AbortSignal"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto algorithm = convert<IDLCallbackFunction<JSAbortAlgorithm>>(*lexicalGlobalObject, argument1.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeFunctionError(lexicalGlobalObject, scope, 1, "algorithm", "AbortSignal", "whenSignalAborted"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLBoolean>(*lexicalGlobalObject, throwScope, AbortSignal::whenSignalAborted(*object, algorithm.releaseNonNull())))); +} + +JSC_DEFINE_HOST_FUNCTION(jsAbortSignalConstructorFunction_whenSignalAborted, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSAbortSignal>::callStatic<jsAbortSignalConstructorFunction_whenSignalAbortedBody, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, *callFrame, "whenSignalAborted"); +} + +static inline JSC::EncodedJSValue jsAbortSignalConstructorFunction_abortBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto* context = jsCast<JSDOMGlobalObject*>(lexicalGlobalObject)->scriptExecutionContext(); + if (UNLIKELY(!context)) + return JSValue::encode(jsUndefined()); + EnsureStillAliveScope argument0 = callFrame->argument(0); + auto reason = convert<IDLAny>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJSNewlyCreated<IDLInterface<AbortSignal>>(*lexicalGlobalObject, *jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), throwScope, AbortSignal::abort(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), *context, WTFMove(reason))))); +} + +JSC_DEFINE_HOST_FUNCTION(jsAbortSignalConstructorFunction_abort, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSAbortSignal>::callStatic<jsAbortSignalConstructorFunction_abortBody>(*lexicalGlobalObject, *callFrame, "abort"); +} + +static inline JSC::EncodedJSValue jsAbortSignalConstructorFunction_timeoutBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + auto* context = jsCast<JSDOMGlobalObject*>(lexicalGlobalObject)->scriptExecutionContext(); + if (UNLIKELY(!context)) + return JSValue::encode(jsUndefined()); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto milliseconds = convert<IDLEnforceRangeAdaptor<IDLUnsignedLongLong>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJSNewlyCreated<IDLInterface<AbortSignal>>(*lexicalGlobalObject, *jsCast<JSDOMGlobalObject*>(lexicalGlobalObject), throwScope, AbortSignal::timeout(*context, WTFMove(milliseconds))))); +} + +JSC_DEFINE_HOST_FUNCTION(jsAbortSignalConstructorFunction_timeout, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSAbortSignal>::callStatic<jsAbortSignalConstructorFunction_timeoutBody>(*lexicalGlobalObject, *callFrame, "timeout"); +} + +static inline JSC::EncodedJSValue jsAbortSignalPrototypeFunction_throwIfAbortedBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSAbortSignal>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.throwIfAborted(*jsCast<JSDOMGlobalObject*>(lexicalGlobalObject)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsAbortSignalPrototypeFunction_throwIfAborted, (JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSAbortSignal>::call<jsAbortSignalPrototypeFunction_throwIfAbortedBody>(*lexicalGlobalObject, *callFrame, "throwIfAborted"); +} + +JSC::GCClient::IsoSubspace* JSAbortSignal::subspaceForImpl(JSC::VM& vm) +{ + return WebCore::subspaceForImpl<JSAbortSignal, UseCustomHeapCellType::No>(vm, + [] (auto& spaces) { return spaces.m_clientSubspaceForAbortSignal.get(); }, + [] (auto& spaces, auto&& space) { spaces.m_clientSubspaceForAbortSignal = WTFMove(space); }, + [] (auto& spaces) { return spaces.m_subspaceForAbortSignal.get(); }, + [] (auto& spaces, auto&& space) { spaces.m_subspaceForAbortSignal = WTFMove(space); } + ); +} + +template<typename Visitor> +void JSAbortSignal::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + auto* thisObject = jsCast<JSAbortSignal*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + thisObject->visitAdditionalChildren(visitor); +} + +DEFINE_VISIT_CHILDREN(JSAbortSignal); + +template<typename Visitor> +void JSAbortSignal::visitOutputConstraints(JSCell* cell, Visitor& visitor) +{ + auto* thisObject = jsCast<JSAbortSignal*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitOutputConstraints(thisObject, visitor); + thisObject->visitAdditionalChildren(visitor); +} + +template void JSAbortSignal::visitOutputConstraints(JSCell*, AbstractSlotVisitor&); +template void JSAbortSignal::visitOutputConstraints(JSCell*, SlotVisitor&); +void JSAbortSignal::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSAbortSignal*>(cell); + analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); + if (thisObject->scriptExecutionContext()) + analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + Base::analyzeHeap(cell, analyzer); +} + +void JSAbortSignalOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) +{ + auto* jsAbortSignal = static_cast<JSAbortSignal*>(handle.slot()->asCell()); + auto& world = *static_cast<DOMWrapperWorld*>(context); + uncacheWrapper(world, &jsAbortSignal->wrapped(), jsAbortSignal); +} + +#if ENABLE(BINDING_INTEGRITY) +#if PLATFORM(WIN) +#pragma warning(disable: 4483) +extern "C" { extern void (*const __identifier("??_7AbortSignal@WebCore@@6B@")[])(); } +#else +extern "C" { extern void* _ZTVN7WebCore11AbortSignalE[]; } +#endif +#endif + +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<AbortSignal>&& impl) +{ + + if constexpr (std::is_polymorphic_v<AbortSignal>) { +#if ENABLE(BINDING_INTEGRITY) + const void* actualVTablePointer = getVTablePointer(impl.ptr()); +#if PLATFORM(WIN) + void* expectedVTablePointer = __identifier("??_7AbortSignal@WebCore@@6B@"); +#else + void* expectedVTablePointer = &_ZTVN7WebCore11AbortSignalE[2]; +#endif + + // If you hit this assertion you either have a use after free bug, or + // AbortSignal has subclasses. If AbortSignal has subclasses that get passed + // to toJS() we currently require AbortSignal you to opt out of binding hardening + // by adding the SkipVTableValidation attribute to the interface IDL definition + RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); +#endif + } + return createWrapper<AbortSignal>(globalObject, WTFMove(impl)); +} + +JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, AbortSignal& impl) +{ + return wrap(lexicalGlobalObject, globalObject, impl); +} + +AbortSignal* JSAbortSignal::toWrapped(JSC::VM& vm, JSC::JSValue value) +{ + if (auto* wrapper = jsDynamicCast<JSAbortSignal*>(vm, value)) + return &wrapper->wrapped(); + return nullptr; +} + +} diff --git a/src/javascript/jsc/bindings/webcore/JSAbortSignal.dep b/src/javascript/jsc/bindings/webcore/JSAbortSignal.dep new file mode 100644 index 000000000..ae214b504 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortSignal.dep @@ -0,0 +1,2 @@ +JSAbortSignal.h : EventTarget.idl +EventTarget.idl : diff --git a/src/javascript/jsc/bindings/webcore/JSAbortSignal.h b/src/javascript/jsc/bindings/webcore/JSAbortSignal.h new file mode 100644 index 000000000..afca5f42c --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortSignal.h @@ -0,0 +1,102 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "AbortSignal.h" +#include "JSDOMWrapper.h" +#include "JSEventTarget.h" +#include <wtf/NeverDestroyed.h> + +namespace WebCore { + +class JSAbortSignal : public JSEventTarget { +public: + using Base = JSEventTarget; + using DOMWrapped = AbortSignal; + static JSAbortSignal* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<AbortSignal>&& impl) + { + JSAbortSignal* ptr = new (NotNull, JSC::allocateCell<JSAbortSignal>(globalObject->vm())) JSAbortSignal(structure, *globalObject, WTFMove(impl)); + ptr->finishCreation(globalObject->vm()); + return ptr; + } + + static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&); + static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&); + static AbortSignal* toWrapped(JSC::VM&, JSC::JSValue); + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info(), JSC::NonArray); + } + + static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*); + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return subspaceForImpl(vm); + } + static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + + template<typename Visitor> static void visitOutputConstraints(JSCell*, Visitor&); + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + AbortSignal& wrapped() const + { + return static_cast<AbortSignal&>(Base::wrapped()); + } +protected: + JSAbortSignal(JSC::Structure*, JSDOMGlobalObject&, Ref<AbortSignal>&&); + + void finishCreation(JSC::VM&); +}; + +class JSAbortSignalOwner final : public JSC::WeakHandleOwner { +public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) final; + void finalize(JSC::Handle<JSC::Unknown>, void* context) final; +}; + +inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, AbortSignal*) +{ + static NeverDestroyed<JSAbortSignalOwner> owner; + return &owner.get(); +} + +inline void* wrapperKey(AbortSignal* wrappableObject) +{ + return wrappableObject; +} + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, AbortSignal&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, AbortSignal* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<AbortSignal>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<AbortSignal>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +template<> struct JSDOMWrapperConverterTraits<AbortSignal> { + using WrapperClass = JSAbortSignal; + using ToWrappedReturnType = AbortSignal*; +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSAbortSignalCustom.cpp b/src/javascript/jsc/bindings/webcore/JSAbortSignalCustom.cpp new file mode 100644 index 000000000..41e0f3376 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAbortSignalCustom.cpp @@ -0,0 +1,60 @@ +/* +* Copyright (C) 2019-2022 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. ``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 +* 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. +*/ + +#include "config.h" +#include "JSAbortSignal.h" + +namespace WebCore { + +bool JSAbortSignalOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, JSC::AbstractSlotVisitor& visitor, const char** reason) +{ + auto& abortSignal = JSC::jsCast<JSAbortSignal*>(handle.slot()->asCell())->wrapped(); + if (abortSignal.isFiringEventListeners()) { + if (UNLIKELY(reason)) + *reason = "EventTarget firing event listeners"; + return true; + } + + if (abortSignal.aborted()) + return false; + + if (abortSignal.isFollowingSignal()) + return true; + + if (abortSignal.hasAbortEventListener() && abortSignal.hasActiveTimeoutTimer()) + return true; + + return visitor.containsOpaqueRoot(&abortSignal); +} + +template<typename Visitor> +void JSAbortSignal::visitAdditionalChildren(Visitor& visitor) +{ + wrapped().reason().visit(visitor); +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSAbortSignal); + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.cpp b/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.cpp new file mode 100644 index 000000000..9eaa310a7 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.cpp @@ -0,0 +1,93 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSAddEventListenerOptions.h" + +#include "JSAbortSignal.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertInterface.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +template<> AddEventListenerOptions convertDictionary<AddEventListenerOptions>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + AddEventListenerOptions result; + JSValue captureValue; + if (isNullOrUndefined) + captureValue = jsUndefined(); + else { + captureValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "capture")); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!captureValue.isUndefined()) { + result.capture = convert<IDLBoolean>(lexicalGlobalObject, captureValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else + result.capture = false; + JSValue onceValue; + if (isNullOrUndefined) + onceValue = jsUndefined(); + else { + onceValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "once")); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!onceValue.isUndefined()) { + result.once = convert<IDLBoolean>(lexicalGlobalObject, onceValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else + result.once = false; + JSValue passiveValue; + if (isNullOrUndefined) + passiveValue = jsUndefined(); + else { + passiveValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "passive")); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!passiveValue.isUndefined()) { + result.passive = convert<IDLBoolean>(lexicalGlobalObject, passiveValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + JSValue signalValue; + if (isNullOrUndefined) + signalValue = jsUndefined(); + else { + signalValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "signal")); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!signalValue.isUndefined()) { + result.signal = convert<IDLInterface<AbortSignal>>(lexicalGlobalObject, signalValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } + return result; +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.dep b/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.dep new file mode 100644 index 000000000..da4d55f61 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.dep @@ -0,0 +1,2 @@ +AddEventListenerOptions.h : EventListenerOptions.idl +EventListenerOptions.idl : diff --git a/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.h b/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.h new file mode 100644 index 000000000..77b1ca7ed --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSAddEventListenerOptions.h @@ -0,0 +1,30 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "AddEventListenerOptions.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> AddEventListenerOptions convertDictionary<AddEventListenerOptions>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSCallbackData.cpp b/src/javascript/jsc/bindings/webcore/JSCallbackData.cpp new file mode 100644 index 000000000..e0cf4a9e9 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSCallbackData.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2007-2021 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. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +#include "config.h" + +#include "ZigGlobalObject.h" + +#include "JSCallbackData.h" + +#include "JSDOMBinding.h" +// #include "JSExecState.h" +// #include "JSExecStateInstrumentation.h" +#include <JavaScriptCore/Exception.h> + +namespace WebCore { +using namespace JSC; + +// https://webidl.spec.whatwg.org/#call-a-user-objects-operation +JSValue JSCallbackData::invokeCallback(VM& vm, JSObject* callback, JSValue thisValue, MarkedArgumentBuffer& args, CallbackType method, PropertyName functionName, NakedPtr<JSC::Exception>& returnedException) +{ + ASSERT(callback); + + // https://webidl.spec.whatwg.org/#ref-for-prepare-to-run-script makes callback's [[Realm]] a running JavaScript execution context, + // which is used for creating TypeError objects: https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist (step 4). + JSGlobalObject* lexicalGlobalObject = callback->globalObject(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + + JSValue function; + CallData callData; + + if (method != CallbackType::Object) { + function = callback; + callData = getCallData(vm, callback); + } + if (callData.type == CallData::Type::None) { + if (method == CallbackType::Function) { + returnedException = JSC::Exception::create(vm, createTypeError(lexicalGlobalObject)); + return JSValue(); + } + + ASSERT(!functionName.isNull()); + function = callback->get(lexicalGlobalObject, functionName); + if (UNLIKELY(scope.exception())) { + returnedException = scope.exception(); + scope.clearException(); + return JSValue(); + } + + callData = getCallData(vm, function); + if (callData.type == CallData::Type::None) { + returnedException = JSC::Exception::create(vm, createTypeError(lexicalGlobalObject, makeString("'", String(functionName.uid()), "' property of callback interface should be callable"))); + return JSValue(); + } + + thisValue = callback; + } + + ASSERT(!function.isEmpty()); + ASSERT(callData.type != CallData::Type::None); + + ScriptExecutionContext* context = jsCast<JSDOMGlobalObject*>(lexicalGlobalObject)->scriptExecutionContext(); + // We will fail to get the context if the frame has been detached. + if (!context) + return JSValue(); + + // JSExecState::instrumentFunction(context, callData); + + returnedException = nullptr; + JSValue result = JSC::profiledCall(lexicalGlobalObject, JSC::ProfilingReason::Other, function, callData, thisValue, args, returnedException); + + // InspectorInstrumentation::didCallFunction(context); + + return result; +} + +template<typename Visitor> +void JSCallbackDataWeak::visitJSFunction(Visitor& visitor) +{ + visitor.append(m_callback); +} + +template void JSCallbackDataWeak::visitJSFunction(JSC::AbstractSlotVisitor&); +template void JSCallbackDataWeak::visitJSFunction(JSC::SlotVisitor&); + +bool JSCallbackDataWeak::WeakOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, AbstractSlotVisitor& visitor, const char** reason) +{ + if (UNLIKELY(reason)) + *reason = "Context is opaque root"; // FIXME: what is the context. + return visitor.containsOpaqueRoot(context); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSCallbackData.h b/src/javascript/jsc/bindings/webcore/JSCallbackData.h new file mode 100644 index 000000000..07114ce41 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSCallbackData.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2007-2021 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. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "JSDOMBinding.h" +#include "ScriptExecutionContext.h" +#include <JavaScriptCore/JSObject.h> +#include <JavaScriptCore/Strong.h> +#include <JavaScriptCore/StrongInlines.h> +#include <wtf/Threading.h> + +namespace WebCore { + +// We have to clean up this data on the context thread because unprotecting a +// JSObject on the wrong thread without synchronization would corrupt the heap +// (and synchronization would be slow). + +class JSCallbackData { + WTF_MAKE_FAST_ALLOCATED; + +public: + enum class CallbackType { Function, + Object, + FunctionOrObject }; + + WEBCORE_EXPORT static JSC::JSValue invokeCallback(JSC::VM&, JSC::JSObject* callback, JSC::JSValue thisValue, JSC::MarkedArgumentBuffer&, CallbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException); + +protected: + explicit JSCallbackData() = default; + + ~JSCallbackData() + { +#if !PLATFORM(IOS_FAMILY) + ASSERT(m_thread.ptr() == &Thread::current()); +#endif + } + +private: +#if ASSERT_ENABLED + Ref<Thread> m_thread { Thread::current() }; +#endif +}; + +class JSCallbackDataStrong : public JSCallbackData { +public: + JSCallbackDataStrong(JSC::VM& vm, JSC::JSObject* callback, void* = nullptr) + : m_callback(vm, callback) + { + } + + JSC::JSObject* callback() { return m_callback.get(); } + + JSC::JSValue invokeCallback(JSC::VM& vm, JSC::JSValue thisValue, JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException) + { + return JSCallbackData::invokeCallback(vm, callback(), thisValue, args, callbackType, functionName, returnedException); + } + +private: + JSC::Strong<JSC::JSObject> m_callback; +}; + +class JSCallbackDataWeak : public JSCallbackData { +public: + JSCallbackDataWeak(JSC::VM&, JSC::JSObject* callback, void* owner) + : m_callback(callback, &m_weakOwner, owner) + { + } + + JSC::JSObject* callback() { return m_callback.get(); } + + JSC::JSValue invokeCallback(JSC::VM& vm, JSC::JSValue thisValue, JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException) + { + return JSCallbackData::invokeCallback(vm, callback(), thisValue, args, callbackType, functionName, returnedException); + } + + template<typename Visitor> void visitJSFunction(Visitor&); + +private: + class WeakOwner : public JSC::WeakHandleOwner { + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) override; + }; + WeakOwner m_weakOwner; + JSC::Weak<JSC::JSObject> m_callback; +}; + +class DeleteCallbackDataTask : public ScriptExecutionContext::Task { +public: + template<typename CallbackDataType> + explicit DeleteCallbackDataTask(CallbackDataType* data) + : ScriptExecutionContext::Task(ScriptExecutionContext::Task::CleanupTask, [data = std::unique_ptr<CallbackDataType>(data)](ScriptExecutionContext&) { + }) + { + } +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSDOMConstructorBase.h b/src/javascript/jsc/bindings/webcore/JSDOMConstructorBase.h index a5b644d19..335c112d3 100644 --- a/src/javascript/jsc/bindings/webcore/JSDOMConstructorBase.h +++ b/src/javascript/jsc/bindings/webcore/JSDOMConstructorBase.h @@ -49,7 +49,7 @@ public: static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM&); JSDOMGlobalObject* globalObject() const { return JSC::jsCast<JSDOMGlobalObject*>(Base::globalObject()); } - // ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); } + ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); } protected: JSDOMConstructorBase(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction functionForConstruct) diff --git a/src/javascript/jsc/bindings/webcore/JSErrorCallback.cpp b/src/javascript/jsc/bindings/webcore/JSErrorCallback.cpp new file mode 100644 index 000000000..a227058a3 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSErrorCallback.cpp @@ -0,0 +1,90 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSErrorCallback.h" + +#include "JSDOMConvertBase.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMException.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" +#include "ScriptExecutionContext.h" + + +namespace WebCore { +using namespace JSC; + +JSErrorCallback::JSErrorCallback(VM& vm, JSObject* callback) + : ErrorCallback(jsCast<JSDOMGlobalObject*>(callback->globalObject(vm))->scriptExecutionContext()) + , m_data(new JSCallbackDataStrong(vm, callback, this)) +{ +} + +JSErrorCallback::~JSErrorCallback() +{ + ScriptExecutionContext* context = scriptExecutionContext(); + // When the context is destroyed, all tasks with a reference to a callback + // should be deleted. So if the context is 0, we are on the context thread. + if (!context || context->isContextThread()) + delete m_data; + else + context->postTask(DeleteCallbackDataTask(m_data)); +#ifndef NDEBUG + m_data = nullptr; +#endif +} + +CallbackResult<typename IDLUndefined::ImplementationType> JSErrorCallback::handleEvent(typename IDLInterface<DOMException>::ParameterType error) +{ + if (!canInvokeCallback()) + return CallbackResultType::UnableToExecute; + + Ref<JSErrorCallback> protectedThis(*this); + + auto& globalObject = *jsCast<JSDOMGlobalObject*>(m_data->callback()->globalObject()); + auto& vm = globalObject.vm(); + + JSLockHolder lock(vm); + auto& lexicalGlobalObject = globalObject; + JSValue thisValue = jsUndefined(); + MarkedArgumentBuffer args; + args.append(toJS<IDLInterface<DOMException>>(lexicalGlobalObject, globalObject, error)); + ASSERT(!args.hasOverflowed()); + + NakedPtr<JSC::Exception> returnedException; + m_data->invokeCallback(vm, thisValue, args, JSCallbackData::CallbackType::Function, Identifier(), returnedException); + if (returnedException) { + reportException(&lexicalGlobalObject, returnedException); + return CallbackResultType::ExceptionThrown; + } + + return { }; +} + +JSC::JSValue toJS(ErrorCallback& impl) +{ + if (!static_cast<JSErrorCallback&>(impl).callbackData()) + return jsNull(); + + return static_cast<JSErrorCallback&>(impl).callbackData()->callback(); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSErrorCallback.h b/src/javascript/jsc/bindings/webcore/JSErrorCallback.h new file mode 100644 index 000000000..ecfd5f04f --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSErrorCallback.h @@ -0,0 +1,54 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "ErrorCallback.h" +#include "IDLTypes.h" +#include "JSCallbackData.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class JSErrorCallback final : public ErrorCallback { +public: + static Ref<JSErrorCallback> create(JSC::VM& vm, JSC::JSObject* callback) + { + return adoptRef(*new JSErrorCallback(vm, callback)); + } + + ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); } + + ~JSErrorCallback() final; + JSCallbackDataStrong* callbackData() { return m_data; } + + // Functions + CallbackResult<typename IDLUndefined::ImplementationType> handleEvent(typename IDLInterface<DOMException>::ParameterType error) override; + +private: + JSErrorCallback(JSC::VM&, JSC::JSObject* callback); + + JSCallbackDataStrong* m_data; +}; + +JSC::JSValue toJS(ErrorCallback&); +inline JSC::JSValue toJS(ErrorCallback* impl) { return impl ? toJS(*impl) : JSC::jsNull(); } + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSErrorEvent.cpp b/src/javascript/jsc/bindings/webcore/JSErrorEvent.cpp new file mode 100644 index 000000000..4f6db111f --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSErrorEvent.cpp @@ -0,0 +1,454 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSErrorEvent.h" + +#include "ZigGlobalObject.h" + +#include "ActiveDOMObject.h" +#include "ExtendedDOMClientIsoSubspaces.h" +#include "ExtendedDOMIsoSubspaces.h" +#include "JSDOMAttribute.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructor.h" +#include "JSDOMConvertAny.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMWrapperCache.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include <JavaScriptCore/HeapAnalyzer.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h> +#include <JavaScriptCore/SlotVisitorMacros.h> +#include <JavaScriptCore/SubspaceInlines.h> +#include <wtf/GetPtr.h> +#include <wtf/PointerPreparations.h> +#include <wtf/URL.h> + +namespace WebCore { +using namespace JSC; + +template<> ErrorEvent::Init convertDictionary<ErrorEvent::Init>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return {}; + } + ErrorEvent::Init result; + JSValue bubblesValue; + if (isNullOrUndefined) + bubblesValue = jsUndefined(); + else { + bubblesValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "bubbles")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!bubblesValue.isUndefined()) { + result.bubbles = convert<IDLBoolean>(lexicalGlobalObject, bubblesValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.bubbles = false; + JSValue cancelableValue; + if (isNullOrUndefined) + cancelableValue = jsUndefined(); + else { + cancelableValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "cancelable")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!cancelableValue.isUndefined()) { + result.cancelable = convert<IDLBoolean>(lexicalGlobalObject, cancelableValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.cancelable = false; + JSValue composedValue; + if (isNullOrUndefined) + composedValue = jsUndefined(); + else { + composedValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "composed")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!composedValue.isUndefined()) { + result.composed = convert<IDLBoolean>(lexicalGlobalObject, composedValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.composed = false; + JSValue colnoValue; + if (isNullOrUndefined) + colnoValue = jsUndefined(); + else { + colnoValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "colno")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!colnoValue.isUndefined()) { + result.colno = convert<IDLUnsignedLong>(lexicalGlobalObject, colnoValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.colno = 0; + JSValue errorValue; + if (isNullOrUndefined) + errorValue = jsUndefined(); + else { + errorValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "error")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!errorValue.isUndefined()) { + result.error = convert<IDLAny>(lexicalGlobalObject, errorValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.error = jsNull(); + JSValue filenameValue; + if (isNullOrUndefined) + filenameValue = jsUndefined(); + else { + filenameValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "filename")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!filenameValue.isUndefined()) { + result.filename = convert<IDLUSVString>(lexicalGlobalObject, filenameValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.filename = emptyString(); + JSValue linenoValue; + if (isNullOrUndefined) + linenoValue = jsUndefined(); + else { + linenoValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "lineno")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!linenoValue.isUndefined()) { + result.lineno = convert<IDLUnsignedLong>(lexicalGlobalObject, linenoValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.lineno = 0; + JSValue messageValue; + if (isNullOrUndefined) + messageValue = jsUndefined(); + else { + messageValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "message")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!messageValue.isUndefined()) { + result.message = convert<IDLDOMString>(lexicalGlobalObject, messageValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.message = emptyString(); + return result; +} + +// Attributes + +static JSC_DECLARE_CUSTOM_GETTER(jsErrorEventConstructor); +static JSC_DECLARE_CUSTOM_GETTER(jsErrorEvent_message); +static JSC_DECLARE_CUSTOM_GETTER(jsErrorEvent_filename); +static JSC_DECLARE_CUSTOM_GETTER(jsErrorEvent_lineno); +static JSC_DECLARE_CUSTOM_GETTER(jsErrorEvent_colno); +static JSC_DECLARE_CUSTOM_GETTER(jsErrorEvent_error); + +class JSErrorEventPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSErrorEventPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure) + { + JSErrorEventPrototype* ptr = new (NotNull, JSC::allocateCell<JSErrorEventPrototype>(vm)) JSErrorEventPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSErrorEventPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSErrorEventPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) + : JSC::JSNonFinalObject(vm, structure) + { + } + + void finishCreation(JSC::VM&); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSErrorEventPrototype, JSErrorEventPrototype::Base); + +using JSErrorEventDOMConstructor = JSDOMConstructor<JSErrorEvent>; + +template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSErrorEventDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +{ + VM& vm = lexicalGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* castedThis = jsCast<JSErrorEventDOMConstructor*>(callFrame->jsCallee()); + ASSERT(castedThis); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto type = convert<IDLDOMString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->argument(1); + auto eventInitDict = convert<IDLDictionary<ErrorEvent::Init>>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + auto object = ErrorEvent::create(WTFMove(type), WTFMove(eventInitDict)); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + static_assert(TypeOrExceptionOrUnderlyingType<decltype(object)>::isRef); + auto jsValue = toJSNewlyCreated<IDLInterface<ErrorEvent>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + setSubclassStructureIfNeeded<ErrorEvent>(lexicalGlobalObject, callFrame, asObject(jsValue)); + RETURN_IF_EXCEPTION(throwScope, {}); + return JSValue::encode(jsValue); +} +JSC_ANNOTATE_HOST_FUNCTION(JSErrorEventDOMConstructorConstruct, JSErrorEventDOMConstructor::construct); + +template<> const ClassInfo JSErrorEventDOMConstructor::s_info = { "ErrorEvent"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSErrorEventDOMConstructor) }; + +template<> JSValue JSErrorEventDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject) +{ + return JSEvent::getConstructor(vm, &globalObject); +} + +template<> void JSErrorEventDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) +{ + putDirect(vm, vm.propertyNames->length, jsNumber(1), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSString* nameString = jsNontrivialString(vm, "ErrorEvent"_s); + m_originalName.set(vm, this, nameString); + putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + putDirect(vm, vm.propertyNames->prototype, JSErrorEvent::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); +} + +/* Hash table for prototype */ + +static const HashTableValue JSErrorEventPrototypeTableValues[] = { + { "constructor", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsErrorEventConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "message", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsErrorEvent_message), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "filename", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsErrorEvent_filename), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "lineno", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsErrorEvent_lineno), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "colno", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsErrorEvent_colno), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "error", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsErrorEvent_error), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, +}; + +const ClassInfo JSErrorEventPrototype::s_info = { "ErrorEvent"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSErrorEventPrototype) }; + +void JSErrorEventPrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSErrorEvent::info(), JSErrorEventPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +const ClassInfo JSErrorEvent::s_info = { "ErrorEvent"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSErrorEvent) }; + +JSErrorEvent::JSErrorEvent(Structure* structure, JSDOMGlobalObject& globalObject, Ref<ErrorEvent>&& impl) + : JSEvent(structure, globalObject, WTFMove(impl)) +{ +} + +void JSErrorEvent::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + + // static_assert(!std::is_base_of<ActiveDOMObject, ErrorEvent>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); +} + +JSObject* JSErrorEvent::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSErrorEventPrototype::create(vm, &globalObject, JSErrorEventPrototype::createStructure(vm, &globalObject, JSEvent::prototype(vm, globalObject))); +} + +JSObject* JSErrorEvent::prototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return getDOMPrototype<JSErrorEvent>(vm, globalObject); +} + +JSValue JSErrorEvent::getConstructor(VM& vm, const JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSErrorEventDOMConstructor, DOMConstructorID::ErrorEvent>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject)); +} + +JSC_DEFINE_CUSTOM_GETTER(jsErrorEventConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* prototype = jsDynamicCast<JSErrorEventPrototype*>(vm, JSValue::decode(thisValue)); + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(JSErrorEvent::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject())); +} + +static inline JSValue jsErrorEvent_messageGetter(JSGlobalObject& lexicalGlobalObject, JSErrorEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLDOMString>(lexicalGlobalObject, throwScope, impl.message()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsErrorEvent_message, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSErrorEvent>::get<jsErrorEvent_messageGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsErrorEvent_filenameGetter(JSGlobalObject& lexicalGlobalObject, JSErrorEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLUSVString>(lexicalGlobalObject, throwScope, impl.filename()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsErrorEvent_filename, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSErrorEvent>::get<jsErrorEvent_filenameGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsErrorEvent_linenoGetter(JSGlobalObject& lexicalGlobalObject, JSErrorEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLUnsignedLong>(lexicalGlobalObject, throwScope, impl.lineno()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsErrorEvent_lineno, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSErrorEvent>::get<jsErrorEvent_linenoGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsErrorEvent_colnoGetter(JSGlobalObject& lexicalGlobalObject, JSErrorEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLUnsignedLong>(lexicalGlobalObject, throwScope, impl.colno()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsErrorEvent_colno, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSErrorEvent>::get<jsErrorEvent_colnoGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsErrorEvent_errorGetter(JSGlobalObject& lexicalGlobalObject, JSErrorEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLAny>(lexicalGlobalObject, throwScope, impl.error(*jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject))))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsErrorEvent_error, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSErrorEvent>::get<jsErrorEvent_errorGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +JSC::GCClient::IsoSubspace* JSErrorEvent::subspaceForImpl(JSC::VM& vm) +{ + return WebCore::subspaceForImpl<JSErrorEvent, UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForErrorEvent.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForErrorEvent = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForErrorEvent.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForErrorEvent = WTFMove(space); }); +} + +template<typename Visitor> +void JSErrorEvent::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + auto* thisObject = jsCast<JSErrorEvent*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + thisObject->visitAdditionalChildren(visitor); +} + +DEFINE_VISIT_CHILDREN(JSErrorEvent); + +template<typename Visitor> +void JSErrorEvent::visitOutputConstraints(JSCell* cell, Visitor& visitor) +{ + auto* thisObject = jsCast<JSErrorEvent*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitOutputConstraints(thisObject, visitor); + thisObject->visitAdditionalChildren(visitor); +} + +template void JSErrorEvent::visitOutputConstraints(JSCell*, AbstractSlotVisitor&); +template void JSErrorEvent::visitOutputConstraints(JSCell*, SlotVisitor&); +void JSErrorEvent::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSErrorEvent*>(cell); + analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); + if (thisObject->scriptExecutionContext()) + analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + Base::analyzeHeap(cell, analyzer); +} + +// #if ENABLE(BINDING_INTEGRITY) +// #if PLATFORM(WIN) +// #pragma warning(disable : 4483) +// extern "C" { +// extern void (*const __identifier("??_7ErrorEvent@WebCore@@6B@")[])(); +// } +// #else +// extern "C" { +// extern void* _ZTVN7WebCore10ErrorEventE[]; +// } +// #endif +// #endif + +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<ErrorEvent>&& impl) +{ + + // if constexpr (std::is_polymorphic_v<ErrorEvent>) { + // #if ENABLE(BINDING_INTEGRITY) + // const void* actualVTablePointer = getVTablePointer(impl.ptr()); + // #if PLATFORM(WIN) + // void* expectedVTablePointer = __identifier("??_7ErrorEvent@WebCore@@6B@"); + // #else + // void* expectedVTablePointer = &_ZTVN7WebCore10ErrorEventE[2]; + // #endif + + // // If you hit this assertion you either have a use after free bug, or + // // ErrorEvent has subclasses. If ErrorEvent has subclasses that get passed + // // to toJS() we currently require ErrorEvent you to opt out of binding hardening + // // by adding the SkipVTableValidation attribute to the interface IDL definition + // RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); + // #endif + return createWrapper<ErrorEvent>(globalObject, WTFMove(impl)); +} + +JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, ErrorEvent& impl) +{ + return wrap(lexicalGlobalObject, globalObject, impl); +} +} diff --git a/src/javascript/jsc/bindings/webcore/JSErrorEvent.dep b/src/javascript/jsc/bindings/webcore/JSErrorEvent.dep new file mode 100644 index 000000000..bc136344b --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSErrorEvent.dep @@ -0,0 +1,3 @@ +JSErrorEvent.h : Event.idl EventInit.idl +Event.idl : +EventInit.idl : diff --git a/src/javascript/jsc/bindings/webcore/JSErrorEvent.h b/src/javascript/jsc/bindings/webcore/JSErrorEvent.h new file mode 100644 index 000000000..5f8bbd802 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSErrorEvent.h @@ -0,0 +1,87 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "root.h" +#include "ErrorEvent.h" +#include "JSDOMConvertDictionary.h" +#include "JSDOMWrapper.h" +#include "JSEvent.h" + +namespace WebCore { + +class JSErrorEvent : public JSEvent { +public: + using Base = JSEvent; + using DOMWrapped = ErrorEvent; + static JSErrorEvent* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<ErrorEvent>&& impl) + { + JSErrorEvent* ptr = new (NotNull, JSC::allocateCell<JSErrorEvent>(globalObject->vm())) JSErrorEvent(structure, *globalObject, WTFMove(impl)); + ptr->finishCreation(globalObject->vm()); + return ptr; + } + + static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&); + static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&); + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSEventType), StructureFlags), info(), JSC::NonArray); + } + + static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*); + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return subspaceForImpl(vm); + } + static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + + template<typename Visitor> static void visitOutputConstraints(JSCell*, Visitor&); + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + ErrorEvent& wrapped() const + { + return static_cast<ErrorEvent&>(Base::wrapped()); + } + +protected: + JSErrorEvent(JSC::Structure*, JSDOMGlobalObject&, Ref<ErrorEvent>&&); + + void finishCreation(JSC::VM&); +}; + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, ErrorEvent&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, ErrorEvent* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<ErrorEvent>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<ErrorEvent>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +template<> struct JSDOMWrapperConverterTraits<ErrorEvent> { + using WrapperClass = JSErrorEvent; + using ToWrappedReturnType = ErrorEvent*; +}; +template<> ErrorEvent::Init convertDictionary<ErrorEvent::Init>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSErrorHandler.cpp b/src/javascript/jsc/bindings/webcore/JSErrorHandler.cpp new file mode 100644 index 000000000..228f247ce --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSErrorHandler.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2013-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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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. + */ + +#include "config.h" +#include "JSErrorHandler.h" + +// #include "Document.h" +#include "ErrorEvent.h" +#include "Event.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" +// #include "JSDOMWindow.h" +#include "JSEvent.h" +// #include "JSExecState.h" +// #include "JSExecStateInstrumentation.h" +#include <JavaScriptCore/JSLock.h> +#include <JavaScriptCore/VMEntryScope.h> +#include <wtf/Ref.h> + +namespace WebCore { +using namespace JSC; + +inline JSErrorHandler::JSErrorHandler(JSObject& listener, JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) + : JSEventListener(&listener, &wrapper, isAttribute, CreatedFromMarkup::No, world) +{ +} + +Ref<JSErrorHandler> JSErrorHandler::create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) +{ + return adoptRef(*new JSErrorHandler(listener, wrapper, isAttribute, world)); +} + +JSErrorHandler::~JSErrorHandler() = default; + +void JSErrorHandler::handleEvent(ScriptExecutionContext& scriptExecutionContext, Event& event) +{ + if (!is<ErrorEvent>(event)) + return JSEventListener::handleEvent(scriptExecutionContext, event); + + VM& vm = scriptExecutionContext.vm(); + JSLockHolder lock(vm); + + JSObject* jsFunction = this->ensureJSFunction(scriptExecutionContext); + if (!jsFunction) + return; + + auto* globalObject = toJSDOMGlobalObject(scriptExecutionContext, isolatedWorld()); + if (!globalObject) + return; + + auto callData = getCallData(vm, jsFunction); + if (callData.type != CallData::Type::None) { + Ref<JSErrorHandler> protectedThis(*this); + + RefPtr<Event> savedEvent; + // auto* jsFunctionWindow = jsDynamicCast<JSDOMWindow*>(vm, jsFunction->globalObject()); + // if (jsFunctionWindow) { + // savedEvent = jsFunctionWindow->currentEvent(); + + // // window.event should not be set when the target is inside a shadow tree, as per the DOM specification. + // if (!event.currentTargetIsInShadowTree()) + // jsFunctionWindow->setCurrentEvent(&event); + // } + + auto& errorEvent = downcast<ErrorEvent>(event); + + MarkedArgumentBuffer args; + args.append(toJS<IDLDOMString>(*globalObject, errorEvent.message())); + args.append(toJS<IDLUSVString>(*globalObject, errorEvent.filename())); + args.append(toJS<IDLUnsignedLong>(errorEvent.lineno())); + args.append(toJS<IDLUnsignedLong>(errorEvent.colno())); + args.append(errorEvent.error(*globalObject)); + ASSERT(!args.hasOverflowed()); + + VM& vm = globalObject->vm(); + VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject); + + // JSExecState::instrumentFunction(&scriptExecutionContext, callData); + + NakedPtr<JSC::Exception> exception; + JSValue returnValue = JSC::profiledCall(globalObject, JSC::ProfilingReason::Other, jsFunction, callData, globalObject, args, exception); + + // InspectorInstrumentation::didCallFunction(&scriptExecutionContext); + + // if (jsFunctionWindow) + // jsFunctionWindow->setCurrentEvent(savedEvent.get()); + + if (exception) + reportException(globalObject, exception); + else { + if (returnValue.isTrue()) + event.preventDefault(); + } + } +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSErrorHandler.h b/src/javascript/jsc/bindings/webcore/JSErrorHandler.h new file mode 100644 index 000000000..d32c55a86 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSErrorHandler.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2017 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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 "JSEventListener.h" + +namespace WebCore { + +class JSErrorHandler final : public JSEventListener { +public: + static Ref<JSErrorHandler> create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); + virtual ~JSErrorHandler(); + +private: + JSErrorHandler(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); + void handleEvent(ScriptExecutionContext&, Event&) final; +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEvent.cpp b/src/javascript/jsc/bindings/webcore/JSEvent.cpp new file mode 100644 index 000000000..28eb8c389 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEvent.cpp @@ -0,0 +1,620 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "root.h" +#include "JSEvent.h" + +#include "ActiveDOMObject.h" +#include "ExtendedDOMClientIsoSubspaces.h" +#include "ExtendedDOMIsoSubspaces.h" +#include "IDLTypes.h" +#include "JSDOMAttribute.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructor.h" +#include "JSDOMConvertBase.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertDictionary.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertNullable.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertSequences.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMOperation.h" +#include "JSDOMWrapperCache.h" +#include "JSEventInit.h" +#include "JSEventTarget.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include <JavaScriptCore/FunctionPrototype.h> +#include <JavaScriptCore/HeapAnalyzer.h> +#include <JavaScriptCore/JSArray.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h> +#include <JavaScriptCore/SlotVisitorMacros.h> +#include <JavaScriptCore/SubspaceInlines.h> +#include <wtf/GetPtr.h> +#include <wtf/PointerPreparations.h> +#include <wtf/URL.h> + +namespace WebCore { +using namespace JSC; + +// Functions + +static JSC_DECLARE_HOST_FUNCTION(jsEventPrototypeFunction_composedPath); +static JSC_DECLARE_HOST_FUNCTION(jsEventPrototypeFunction_stopPropagation); +static JSC_DECLARE_HOST_FUNCTION(jsEventPrototypeFunction_stopImmediatePropagation); +static JSC_DECLARE_HOST_FUNCTION(jsEventPrototypeFunction_preventDefault); +static JSC_DECLARE_HOST_FUNCTION(jsEventPrototypeFunction_initEvent); + +// Attributes + +static JSC_DECLARE_CUSTOM_GETTER(jsEventConstructor); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_type); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_target); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_currentTarget); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_eventPhase); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_cancelBubble); +static JSC_DECLARE_CUSTOM_SETTER(setJSEvent_cancelBubble); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_bubbles); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_cancelable); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_defaultPrevented); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_composed); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_isTrusted); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_timeStamp); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_srcElement); +static JSC_DECLARE_CUSTOM_GETTER(jsEvent_returnValue); +static JSC_DECLARE_CUSTOM_SETTER(setJSEvent_returnValue); + +class JSEventPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSEventPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure) + { + JSEventPrototype* ptr = new (NotNull, JSC::allocateCell<JSEventPrototype>(vm)) JSEventPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSEventPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSEventPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) + : JSC::JSNonFinalObject(vm, structure) + { + } + + void finishCreation(JSC::VM&); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSEventPrototype, JSEventPrototype::Base); + +using JSEventDOMConstructor = JSDOMConstructor<JSEvent>; + +/* Hash table */ + +static const struct CompactHashIndex JSEventTableIndex[2] = { + { 0, -1 }, + { -1, -1 }, +}; + +static const HashTableValue JSEventTableValues[] = { + { "isTrusted", static_cast<unsigned>(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_isTrusted), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, +}; + +static const HashTable JSEventTable = { 1, 1, true, JSEvent::info(), JSEventTableValues, JSEventTableIndex }; +/* Hash table for constructor */ + +static const HashTableValue JSEventConstructorTableValues[] = { + { "NONE", JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(0) } }, + { "CAPTURING_PHASE", JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(1) } }, + { "AT_TARGET", JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(2) } }, + { "BUBBLING_PHASE", JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(3) } }, +}; + +static_assert(Event::NONE == 0, "NONE in Event does not match value from IDL"); +static_assert(Event::CAPTURING_PHASE == 1, "CAPTURING_PHASE in Event does not match value from IDL"); +static_assert(Event::AT_TARGET == 2, "AT_TARGET in Event does not match value from IDL"); +static_assert(Event::BUBBLING_PHASE == 3, "BUBBLING_PHASE in Event does not match value from IDL"); + +template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +{ + VM& vm = lexicalGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* castedThis = jsCast<JSEventDOMConstructor*>(callFrame->jsCallee()); + ASSERT(castedThis); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto type = convert<IDLDOMString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->argument(1); + auto eventInitDict = convert<IDLDictionary<EventInit>>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + auto object = Event::create(WTFMove(type), WTFMove(eventInitDict)); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + static_assert(TypeOrExceptionOrUnderlyingType<decltype(object)>::isRef); + auto jsValue = toJSNewlyCreated<IDLInterface<Event>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + setSubclassStructureIfNeeded<Event>(lexicalGlobalObject, callFrame, asObject(jsValue)); + RETURN_IF_EXCEPTION(throwScope, {}); + return JSValue::encode(jsValue); +} +JSC_ANNOTATE_HOST_FUNCTION(JSEventDOMConstructorConstruct, JSEventDOMConstructor::construct); + +template<> const ClassInfo JSEventDOMConstructor::s_info = { "Event"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSEventDOMConstructor) }; + +template<> JSValue JSEventDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject) +{ + UNUSED_PARAM(vm); + return globalObject.functionPrototype(); +} + +template<> void JSEventDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) +{ + putDirect(vm, vm.propertyNames->length, jsNumber(1), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSString* nameString = jsNontrivialString(vm, "Event"_s); + m_originalName.set(vm, this, nameString); + putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + putDirect(vm, vm.propertyNames->prototype, JSEvent::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); + reifyStaticProperties(vm, JSEvent::info(), JSEventConstructorTableValues, *this); +} + +/* Hash table for prototype */ + +static const HashTableValue JSEventPrototypeTableValues[] = { + { "constructor", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEventConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "type", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_type), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "target", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_target), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "currentTarget", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_currentTarget), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "eventPhase", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_eventPhase), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "cancelBubble", static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_cancelBubble), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSEvent_cancelBubble) } }, + { "bubbles", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_bubbles), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "cancelable", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_cancelable), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "defaultPrevented", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_defaultPrevented), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "composed", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_composed), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "timeStamp", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_timeStamp), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "srcElement", static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_srcElement), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "returnValue", static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEvent_returnValue), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSEvent_returnValue) } }, + { "composedPath", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsEventPrototypeFunction_composedPath), (intptr_t)(0) } }, + { "stopPropagation", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsEventPrototypeFunction_stopPropagation), (intptr_t)(0) } }, + { "stopImmediatePropagation", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsEventPrototypeFunction_stopImmediatePropagation), (intptr_t)(0) } }, + { "preventDefault", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsEventPrototypeFunction_preventDefault), (intptr_t)(0) } }, + { "initEvent", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsEventPrototypeFunction_initEvent), (intptr_t)(1) } }, + { "NONE", JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(0) } }, + { "CAPTURING_PHASE", JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(1) } }, + { "AT_TARGET", JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(2) } }, + { "BUBBLING_PHASE", JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(3) } }, +}; + +const ClassInfo JSEventPrototype::s_info = { "Event"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSEventPrototype) }; + +void JSEventPrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSEvent::info(), JSEventPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +const ClassInfo JSEvent::s_info = { "Event"_s, &Base::s_info, &JSEventTable +#if 0 + , + &checkSubClassSnippetForJSEvent +#else + , + nullptr +#endif + , + CREATE_METHOD_TABLE(JSEvent) }; + +JSEvent::JSEvent(Structure* structure, JSDOMGlobalObject& globalObject, Ref<Event>&& impl) + : JSDOMWrapper<Event>(structure, globalObject, WTFMove(impl)) +{ +} + +void JSEvent::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + + // static_assert(!std::is_base_of<ActiveDOMObject, Event>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); +} + +JSObject* JSEvent::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSEventPrototype::create(vm, &globalObject, JSEventPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); +} + +JSObject* JSEvent::prototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return getDOMPrototype<JSEvent>(vm, globalObject); +} + +JSValue JSEvent::getConstructor(VM& vm, const JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSEventDOMConstructor, DOMConstructorID::Event>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject)); +} + +void JSEvent::destroy(JSC::JSCell* cell) +{ + JSEvent* thisObject = static_cast<JSEvent*>(cell); + thisObject->JSEvent::~JSEvent(); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEventConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* prototype = jsDynamicCast<JSEventPrototype*>(vm, JSValue::decode(thisValue)); + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(JSEvent::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject())); +} + +static inline JSValue jsEvent_typeGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLDOMString>(lexicalGlobalObject, throwScope, impl.type()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_type, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_typeGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_targetGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLNullable<IDLInterface<EventTarget>>>(lexicalGlobalObject, *thisObject.globalObject(), throwScope, impl.target()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_target, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_targetGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_currentTargetGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLNullable<IDLInterface<EventTarget>>>(lexicalGlobalObject, *thisObject.globalObject(), throwScope, impl.currentTarget()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_currentTarget, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_currentTargetGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_eventPhaseGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLUnsignedShort>(lexicalGlobalObject, throwScope, impl.eventPhase()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_eventPhase, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_eventPhaseGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_cancelBubbleGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.cancelBubble()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_cancelBubble, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_cancelBubbleGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline bool setJSEvent_cancelBubbleSetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject, JSValue value) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + auto nativeValue = convert<IDLBoolean>(lexicalGlobalObject, value); + RETURN_IF_EXCEPTION(throwScope, false); + invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] { + return impl.setCancelBubble(WTFMove(nativeValue)); + }); + return true; +} + +JSC_DEFINE_CUSTOM_SETTER(setJSEvent_cancelBubble, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::set<setJSEvent_cancelBubbleSetter>(*lexicalGlobalObject, thisValue, encodedValue, attributeName); +} + +static inline JSValue jsEvent_bubblesGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.bubbles()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_bubbles, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_bubblesGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_cancelableGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.cancelable()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_cancelable, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_cancelableGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_defaultPreventedGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.defaultPrevented()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_defaultPrevented, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_defaultPreventedGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_composedGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.composed()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_composed, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_composedGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_isTrustedGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.isTrusted()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_isTrusted, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_isTrustedGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_timeStampGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* context = (thisObject).globalObject()->scriptExecutionContext(); + if (UNLIKELY(!context)) + return jsUndefined(); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLDouble>(lexicalGlobalObject, throwScope, impl.timeStampForBindings(*context)))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_timeStamp, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_timeStampGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_srcElementGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLInterface<EventTarget>>(lexicalGlobalObject, *thisObject.globalObject(), throwScope, impl.target()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_srcElement, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_srcElementGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline JSValue jsEvent_returnValueGetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + RELEASE_AND_RETURN(throwScope, (toJS<IDLBoolean>(lexicalGlobalObject, throwScope, impl.legacyReturnValue()))); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEvent_returnValue, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::get<jsEvent_returnValueGetter, CastedThisErrorBehavior::Assert>(*lexicalGlobalObject, thisValue, attributeName); +} + +static inline bool setJSEvent_returnValueSetter(JSGlobalObject& lexicalGlobalObject, JSEvent& thisObject, JSValue value) +{ + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto& impl = thisObject.wrapped(); + auto nativeValue = convert<IDLBoolean>(lexicalGlobalObject, value); + RETURN_IF_EXCEPTION(throwScope, false); + invokeFunctorPropagatingExceptionIfNecessary(lexicalGlobalObject, throwScope, [&] { + return impl.setLegacyReturnValue(WTFMove(nativeValue)); + }); + return true; +} + +JSC_DEFINE_CUSTOM_SETTER(setJSEvent_returnValue, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName)) +{ + return IDLAttribute<JSEvent>::set<setJSEvent_returnValueSetter>(*lexicalGlobalObject, thisValue, encodedValue, attributeName); +} + +static inline JSC::EncodedJSValue jsEventPrototypeFunction_composedPathBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSEvent>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLSequence<IDLInterface<EventTarget>>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, impl.composedPath()))); +} + +JSC_DEFINE_HOST_FUNCTION(jsEventPrototypeFunction_composedPath, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSEvent>::call<jsEventPrototypeFunction_composedPathBody>(*lexicalGlobalObject, *callFrame, "composedPath"); +} + +static inline JSC::EncodedJSValue jsEventPrototypeFunction_stopPropagationBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSEvent>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.stopPropagation(); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsEventPrototypeFunction_stopPropagation, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSEvent>::call<jsEventPrototypeFunction_stopPropagationBody>(*lexicalGlobalObject, *callFrame, "stopPropagation"); +} + +static inline JSC::EncodedJSValue jsEventPrototypeFunction_stopImmediatePropagationBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSEvent>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.stopImmediatePropagation(); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsEventPrototypeFunction_stopImmediatePropagation, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSEvent>::call<jsEventPrototypeFunction_stopImmediatePropagationBody>(*lexicalGlobalObject, *callFrame, "stopImmediatePropagation"); +} + +static inline JSC::EncodedJSValue jsEventPrototypeFunction_preventDefaultBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSEvent>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.preventDefault(); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsEventPrototypeFunction_preventDefault, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSEvent>::call<jsEventPrototypeFunction_preventDefaultBody>(*lexicalGlobalObject, *callFrame, "preventDefault"); +} + +static inline JSC::EncodedJSValue jsEventPrototypeFunction_initEventBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSEvent>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto type = convert<IDLDOMString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->argument(1); + auto bubbles = convert<IDLBoolean>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->argument(2); + auto cancelable = convert<IDLBoolean>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.initEvent(WTFMove(type), WTFMove(bubbles), WTFMove(cancelable)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsEventPrototypeFunction_initEvent, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSEvent>::call<jsEventPrototypeFunction_initEventBody>(*lexicalGlobalObject, *callFrame, "initEvent"); +} + +JSC::GCClient::IsoSubspace* JSEvent::subspaceForImpl(JSC::VM& vm) +{ + return WebCore::subspaceForImpl<JSEvent, UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForEvent.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForEvent = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForEvent.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForEvent = WTFMove(space); }); +} + +void JSEvent::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSEvent*>(cell); + analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); + if (thisObject->scriptExecutionContext()) + analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + Base::analyzeHeap(cell, analyzer); +} + +bool JSEventOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, AbstractSlotVisitor& visitor, const char** reason) +{ + UNUSED_PARAM(handle); + UNUSED_PARAM(visitor); + UNUSED_PARAM(reason); + return false; +} + +void JSEventOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) +{ + auto* jsEvent = static_cast<JSEvent*>(handle.slot()->asCell()); + auto& world = *static_cast<DOMWrapperWorld*>(context); + uncacheWrapper(world, &jsEvent->wrapped(), jsEvent); +} + +Event* JSEvent::toWrapped(JSC::VM& vm, JSC::JSValue value) +{ + if (auto* wrapper = jsDynamicCast<JSEvent*>(vm, value)) + return &wrapper->wrapped(); + return nullptr; +} + +} diff --git a/src/javascript/jsc/bindings/webcore/JSEvent.dep b/src/javascript/jsc/bindings/webcore/JSEvent.dep new file mode 100644 index 000000000..573e0bba5 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEvent.dep @@ -0,0 +1 @@ +JSEvent.h : diff --git a/src/javascript/jsc/bindings/webcore/JSEvent.h b/src/javascript/jsc/bindings/webcore/JSEvent.h new file mode 100644 index 000000000..1f4c5f80a --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEvent.h @@ -0,0 +1,102 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "Event.h" +#include "JSDOMWrapper.h" +#include <JavaScriptCore/Snippet.h> +#include <wtf/NeverDestroyed.h> + +namespace WebCore { + +class JSEvent : public JSDOMWrapper<Event> { +public: + using Base = JSDOMWrapper<Event>; + static JSEvent* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<Event>&& impl) + { + JSEvent* ptr = new (NotNull, JSC::allocateCell<JSEvent>(globalObject->vm())) JSEvent(structure, *globalObject, WTFMove(impl)); + ptr->finishCreation(globalObject->vm()); + return ptr; + } + + static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&); + static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&); + static WEBCORE_EXPORT Event* toWrapped(JSC::VM&, JSC::JSValue); + static void destroy(JSC::JSCell*); + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSEventType), StructureFlags), info(), JSC::NonArray); + } + + static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*); + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return subspaceForImpl(vm); + } + static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + +public: + static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::HasStaticPropertyTable; + +protected: + JSEvent(JSC::Structure*, JSDOMGlobalObject&, Ref<Event>&&); + + void finishCreation(JSC::VM&); +}; + +class JSEventOwner final : public JSC::WeakHandleOwner { +public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) final; + void finalize(JSC::Handle<JSC::Unknown>, void* context) final; +}; + +inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, Event*) +{ + static NeverDestroyed<JSEventOwner> owner; + return &owner.get(); +} + +inline void* wrapperKey(Event* wrappableObject) +{ + return wrappableObject; +} + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, Event&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, Event* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<Event>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<Event>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +// #if ENABLE(JIT) +// Ref<JSC::Snippet> checkSubClassSnippetForJSEvent(); +// #endif +template<> struct JSDOMWrapperConverterTraits<Event> { + using WrapperClass = JSEvent; + using ToWrappedReturnType = Event*; +}; + +} // namespace WebCore +#include "JSEventCustom.h" diff --git a/src/javascript/jsc/bindings/webcore/JSEventCustom.cpp b/src/javascript/jsc/bindings/webcore/JSEventCustom.cpp new file mode 100644 index 000000000..2f8a9b04d --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventCustom.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007, 2008 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. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +#include "config.h" +#include "JSEvent.h" + +#include "JSDOMWrapperCache.h" +#include <JavaScriptCore/JSCJSValue.h> + +namespace WebCore { + +JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, Event& event) +{ + return wrap(lexicalGlobalObject, globalObject, event); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventCustom.h b/src/javascript/jsc/bindings/webcore/JSEventCustom.h new file mode 100644 index 000000000..8271b933d --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventCustom.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>. + * + * 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. ``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 + * 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 "JSDOMBinding.h" +#include "JSEvent.h" + +namespace JSC { +namespace JSCastingHelpers { + +template<> +struct InheritsTraits<WebCore::JSEvent> { + static constexpr std::optional<JSTypeRange> typeRange { { static_cast<JSType>(WebCore::JSEventType), static_cast<JSType>(WebCore::JSEventType) } }; + template<typename From> + static inline bool inherits(VM& vm, From* from) + { + return inheritsJSTypeImpl<WebCore::JSEvent>(vm, from, *typeRange); + } +}; + +} // namespace JSCastingHelpers +} // namespace JSC diff --git a/src/javascript/jsc/bindings/webcore/JSEventInit.cpp b/src/javascript/jsc/bindings/webcore/JSEventInit.cpp new file mode 100644 index 000000000..f7ef28f92 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventInit.cpp @@ -0,0 +1,81 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSEventInit.h" + +#include "JSDOMConvertBoolean.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +template<> EventInit convertDictionary<EventInit>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + EventInit result; + JSValue bubblesValue; + if (isNullOrUndefined) + bubblesValue = jsUndefined(); + else { + bubblesValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "bubbles")); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!bubblesValue.isUndefined()) { + result.bubbles = convert<IDLBoolean>(lexicalGlobalObject, bubblesValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else + result.bubbles = false; + JSValue cancelableValue; + if (isNullOrUndefined) + cancelableValue = jsUndefined(); + else { + cancelableValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "cancelable")); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!cancelableValue.isUndefined()) { + result.cancelable = convert<IDLBoolean>(lexicalGlobalObject, cancelableValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else + result.cancelable = false; + JSValue composedValue; + if (isNullOrUndefined) + composedValue = jsUndefined(); + else { + composedValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "composed")); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!composedValue.isUndefined()) { + result.composed = convert<IDLBoolean>(lexicalGlobalObject, composedValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else + result.composed = false; + return result; +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventInit.dep b/src/javascript/jsc/bindings/webcore/JSEventInit.dep new file mode 100644 index 000000000..e1d78f2d8 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventInit.dep @@ -0,0 +1 @@ +EventInit.h : diff --git a/src/javascript/jsc/bindings/webcore/JSEventInit.h b/src/javascript/jsc/bindings/webcore/JSEventInit.h new file mode 100644 index 000000000..c7cd96b65 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventInit.h @@ -0,0 +1,30 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "EventInit.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> EventInit convertDictionary<EventInit>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventListener.cpp b/src/javascript/jsc/bindings/webcore/JSEventListener.cpp new file mode 100644 index 000000000..244ee934f --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventListener.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003-2021 Apple Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "JSEventListener.h" + +// #include "BeforeUnloadEvent.h" +// #include "ContentSecurityPolicy.h" +#include "EventNames.h" +// #include "Frame.h" +// #include "HTMLElement.h" +#include "JSDOMConvertNullable.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMGlobalObject.h" +// #include "JSDocument.h" +#include "JSEvent.h" +#include "JSEventTarget.h" +// #include "JSExecState.h" +// #include "JSExecStateInstrumentation.h" +// #include "JSWorkerGlobalScope.h" +// #include "ScriptController.h" +// #include "WorkerGlobalScope.h" +#include <JavaScriptCore/ExceptionHelpers.h> +#include <JavaScriptCore/JSLock.h> +#include <JavaScriptCore/VMEntryScope.h> +#include <JavaScriptCore/Watchdog.h> +#include <wtf/Ref.h> +#include <wtf/Scope.h> + +namespace WebCore { +using namespace JSC; + +JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isAttribute, CreatedFromMarkup createdFromMarkup, DOMWrapperWorld& isolatedWorld) + : EventListener(JSEventListenerType) + , m_isAttribute(isAttribute) + , m_wasCreatedFromMarkup(createdFromMarkup == CreatedFromMarkup::Yes) + , m_isInitialized(false) + , m_wrapper(wrapper) + , m_isolatedWorld(isolatedWorld) +{ + if (function) { + ASSERT(wrapper); + m_jsFunction = JSC::Weak<JSC::JSObject>(function); + m_isInitialized = true; + } +} + +JSEventListener::~JSEventListener() = default; + +Ref<JSEventListener> JSEventListener::create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) +{ + return adoptRef(*new JSEventListener(&listener, &wrapper, isAttribute, CreatedFromMarkup::No, world)); +} + +JSObject* JSEventListener::initializeJSFunction(ScriptExecutionContext&) const +{ + return nullptr; +} + +void JSEventListener::replaceJSFunctionForAttributeListener(JSObject* function, JSObject* wrapper) +{ + ASSERT(m_isAttribute); + ASSERT(function); + ASSERT(wrapper); + + m_wasCreatedFromMarkup = false; + m_jsFunction = Weak { function }; + if (m_isInitialized) + ASSERT(m_wrapper.get() == wrapper); + else { + m_wrapper = Weak { wrapper }; + m_isInitialized = true; + } +} + +JSValue eventHandlerAttribute(EventTarget& eventTarget, const AtomString& eventType, DOMWrapperWorld& isolatedWorld) +{ + if (auto* jsListener = eventTarget.attributeEventListener(eventType, isolatedWorld)) { + if (auto* context = eventTarget.scriptExecutionContext()) { + if (auto* jsFunction = jsListener->ensureJSFunction(*context)) + return jsFunction; + } + } + + return jsNull(); +} + +template<typename Visitor> +inline void JSEventListener::visitJSFunctionImpl(Visitor& visitor) +{ + // If m_wrapper is null, we are not keeping m_jsFunction alive. + if (!m_wrapper) + return; + + visitor.append(m_jsFunction); +} + +void JSEventListener::visitJSFunction(AbstractSlotVisitor& visitor) { visitJSFunctionImpl(visitor); } +void JSEventListener::visitJSFunction(SlotVisitor& visitor) { visitJSFunctionImpl(visitor); } + +// static void handleBeforeUnloadEventReturnValue(BeforeUnloadEvent& event, const String& returnValue) +// { +// if (returnValue.isNull()) +// return; + +// event.preventDefault(); +// if (event.returnValue().isEmpty()) +// event.setReturnValue(returnValue); +// } + +void JSEventListener::handleEvent(ScriptExecutionContext& scriptExecutionContext, Event& event) +{ + if (scriptExecutionContext.isJSExecutionForbidden()) + return; + + VM& vm = scriptExecutionContext.vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + + // See https://dom.spec.whatwg.org/#dispatching-events spec on calling handleEvent. + // "If this throws an exception, report the exception." It should not propagate the + // exception. + + JSObject* jsFunction = ensureJSFunction(scriptExecutionContext); + if (!jsFunction) + return; + + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld); + if (!globalObject) + return; + + // if (scriptExecutionContext.isDocument()) { + // JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject); + // if (!window->wrapped().isCurrentlyDisplayedInFrame()) + // return; + // if (wasCreatedFromMarkup()) { + // Element* element = event.target()->isNode() && !downcast<Node>(*event.target()).isDocumentNode() ? dynamicDowncast<Element>(*event.target()) : nullptr; + // if (!scriptExecutionContext.contentSecurityPolicy()->allowInlineEventHandlers(sourceURL().string(), sourcePosition().m_line, code(), element)) + // return; + // } + // // FIXME: Is this check needed for other contexts? + // ScriptController& script = window->wrapped().frame()->script(); + // if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused()) + // return; + // } + + // RefPtr<Event> savedEvent; + // auto* jsFunctionWindow = jsDynamicCast<JSDOMWindow*>(vm, jsFunction->globalObject(vm)); + // if (jsFunctionWindow) { + // savedEvent = jsFunctionWindow->currentEvent(); + + // // window.event should not be set when the target is inside a shadow tree, as per the DOM specification. + // if (!event.currentTargetIsInShadowTree()) + // jsFunctionWindow->setCurrentEvent(&event); + // } + + // auto restoreCurrentEventOnExit = makeScopeExit([&] { + // if (jsFunctionWindow) + // jsFunctionWindow->setCurrentEvent(savedEvent.get()); + // }); + + JSGlobalObject* lexicalGlobalObject = jsFunction->globalObject(); + + JSValue handleEventFunction = jsFunction; + + auto callData = getCallData(vm, handleEventFunction); + + // If jsFunction is not actually a function and this is an EventListener, see if it implements callback interface. + if (callData.type == CallData::Type::None) { + if (m_isAttribute) + return; + + handleEventFunction = jsFunction->get(lexicalGlobalObject, Identifier::fromString(vm, "handleEvent")); + if (UNLIKELY(scope.exception())) { + auto* exception = scope.exception(); + scope.clearException(); + event.target()->uncaughtExceptionInEventHandler(); + reportException(lexicalGlobalObject, exception); + return; + } + callData = getCallData(vm, handleEventFunction); + if (callData.type == CallData::Type::None) { + event.target()->uncaughtExceptionInEventHandler(); + reportException(lexicalGlobalObject, createTypeError(lexicalGlobalObject, "'handleEvent' property of event listener should be callable"_s)); + return; + } + } + + Ref<JSEventListener> protectedThis(*this); + + MarkedArgumentBuffer args; + args.append(toJS(lexicalGlobalObject, globalObject, &event)); + ASSERT(!args.hasOverflowed()); + + VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : lexicalGlobalObject); + + // JSExecState::instrumentFunction(&scriptExecutionContext, callData); + + JSValue thisValue = handleEventFunction == jsFunction ? toJS(lexicalGlobalObject, globalObject, event.currentTarget()) : jsFunction; + NakedPtr<JSC::Exception> uncaughtException; + JSValue retval = JSC::profiledCall(lexicalGlobalObject, JSC::ProfilingReason::Other, handleEventFunction, callData, thisValue, args, uncaughtException); + + // InspectorInstrumentation::didCallFunction(&scriptExecutionContext); + + auto handleExceptionIfNeeded = [&](JSC::Exception* exception) -> bool { + // if (is<WorkerGlobalScope>(scriptExecutionContext)) { + // auto* scriptController = downcast<WorkerGlobalScope>(scriptExecutionContext).script(); + // bool terminatorCausedException = (exception && vm.isTerminationException(exception)); + // if (terminatorCausedException || (scriptController && scriptController->isTerminatingExecution())) + // scriptController->forbidExecution(); + // } + + if (exception) { + event.target()->uncaughtExceptionInEventHandler(); + reportException(lexicalGlobalObject, exception); + return true; + } + return false; + }; + + if (handleExceptionIfNeeded(uncaughtException)) + return; + + if (!m_isAttribute) { + // This is an EventListener and there is therefore no need for any return value handling. + return; + } + + // Do return value handling for event handlers (https://html.spec.whatwg.org/#the-event-handler-processing-algorithm). + + // if (event.type() == eventNames().beforeunloadEvent) { + // // This is a OnBeforeUnloadEventHandler, and therefore the return value must be coerced into a String. + // if (is<BeforeUnloadEvent>(event)) { + // String resultStr = convert<IDLNullable<IDLDOMString>>(*lexicalGlobalObject, retval); + // if (UNLIKELY(scope.exception())) { + // if (handleExceptionIfNeeded(scope.exception())) + // return; + // } + // handleBeforeUnloadEventReturnValue(downcast<BeforeUnloadEvent>(event), resultStr); + // } + // return; + // } + + if (retval.isFalse()) + event.preventDefault(); +} + +bool JSEventListener::operator==(const EventListener& listener) const +{ + if (!is<JSEventListener>(listener)) + return false; + auto& other = downcast<JSEventListener>(listener); + return m_jsFunction == other.m_jsFunction && m_isAttribute == other.m_isAttribute; +} + +String JSEventListener::functionName() const +{ + if (!m_wrapper || !m_jsFunction) + return {}; + + auto& vm = isolatedWorld().vm(); + JSC::JSLockHolder lock(vm); + + auto* handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(vm, m_jsFunction.get()); + if (!handlerFunction) + return {}; + + return handlerFunction->name(vm); +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventListener.h b/src/javascript/jsc/bindings/webcore/JSEventListener.h new file mode 100644 index 000000000..fb8da1bb6 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventListener.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003-2021 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +// #include "DOMWindow.h" +#include "DOMWrapperWorld.h" +#include "EventListener.h" +#include "EventNames.h" +// #include "HTMLElement.h" +#include <JavaScriptCore/StrongInlines.h> +#include <JavaScriptCore/Weak.h> +#include <JavaScriptCore/WeakInlines.h> +#include <wtf/Ref.h> +#include <wtf/TypeCasts.h> +#include <wtf/text/TextPosition.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class JSEventListener : public EventListener { +public: + WEBCORE_EXPORT static Ref<JSEventListener> create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&); + + virtual ~JSEventListener(); + + bool operator==(const EventListener&) const final; + + // Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick". + bool isAttribute() const final { return m_isAttribute; } + + bool wasCreatedFromMarkup() const { return m_wasCreatedFromMarkup; } + + JSC::JSObject* ensureJSFunction(ScriptExecutionContext&) const; + DOMWrapperWorld& isolatedWorld() const { return m_isolatedWorld; } + + JSC::JSObject* jsFunction() const final { return m_jsFunction.get(); } + JSC::JSObject* wrapper() const final { return m_wrapper.get(); } + + virtual URL sourceURL() const { return {}; } + virtual TextPosition sourcePosition() const { return TextPosition(); } + + String functionName() const; + + void replaceJSFunctionForAttributeListener(JSC::JSObject* function, JSC::JSObject* wrapper); + static bool wasCreatedFromMarkup(const EventListener& listener) + { + return is<JSEventListener>(listener) && downcast<JSEventListener>(listener).wasCreatedFromMarkup(); + } + +private: + virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext&) const; + + template<typename Visitor> void visitJSFunctionImpl(Visitor&); + void visitJSFunction(JSC::AbstractSlotVisitor&) final; + void visitJSFunction(JSC::SlotVisitor&) final; + virtual String code() const { return String(); } + +protected: + enum class CreatedFromMarkup : bool { No, + Yes }; + + JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, CreatedFromMarkup, DOMWrapperWorld&); + void handleEvent(ScriptExecutionContext&, Event&) override; + void setWrapperWhenInitializingJSFunction(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); } + +private: + bool m_isAttribute : 1; + bool m_wasCreatedFromMarkup : 1; + + mutable bool m_isInitialized : 1; + mutable JSC::Weak<JSC::JSObject> m_jsFunction; + mutable JSC::Weak<JSC::JSObject> m_wrapper; + + Ref<DOMWrapperWorld> m_isolatedWorld; +}; + +// For "onxxx" attributes that automatically set up JavaScript event listeners. +JSC::JSValue eventHandlerAttribute(EventTarget&, const AtomString& eventType, DOMWrapperWorld&); + +template<typename JSMaybeErrorEventListener> +inline void setEventHandlerAttribute(EventTarget& eventTarget, const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget) +{ + eventTarget.setAttributeEventListener<JSMaybeErrorEventListener>(eventType, listener, jsEventTarget); +} + +// // Like the functions above, but for attributes that forward event handlers to the window object rather than setting them on the target. +// inline JSC::JSValue windowEventHandlerAttribute(DOMWindow& window, const AtomString& eventType, DOMWrapperWorld& isolatedWorld) +// { +// return eventHandlerAttribute(window, eventType, isolatedWorld); +// } + +// inline JSC::JSValue windowEventHandlerAttribute(HTMLElement& element, const AtomString& eventType, DOMWrapperWorld& isolatedWorld) +// { +// if (auto* domWindow = element.document().domWindow()) +// return eventHandlerAttribute(*domWindow, eventType, isolatedWorld); +// return JSC::jsNull(); +// } + +// template<typename JSMaybeErrorEventListener> +// inline void setWindowEventHandlerAttribute(DOMWindow& window, const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget) +// { +// window.setAttributeEventListener<JSMaybeErrorEventListener>(eventType, listener, *jsEventTarget.globalObject()); +// } + +// template<typename JSMaybeErrorEventListener> +// inline void setWindowEventHandlerAttribute(HTMLElement& element, const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget) +// { +// if (auto* domWindow = element.document().domWindow()) +// domWindow->setAttributeEventListener<JSMaybeErrorEventListener>(eventType, listener, *jsEventTarget.globalObject()); +// } + +inline JSC::JSObject* JSEventListener::ensureJSFunction(ScriptExecutionContext& scriptExecutionContext) const +{ + // initializeJSFunction can trigger code that deletes this event listener + // before we're done. It should always return null in this case. + JSC::VM& vm = m_isolatedWorld->vm(); + Ref protect = const_cast<JSEventListener&>(*this); + JSC::EnsureStillAliveScope protectedWrapper(m_wrapper.get()); + + if (!m_isInitialized) { + ASSERT(!m_jsFunction); + auto* function = initializeJSFunction(scriptExecutionContext); + if (function) { + m_jsFunction = JSC::Weak<JSC::JSObject>(function); + // When JSFunction is initialized, initializeJSFunction must ensure that m_wrapper should be initialized too. + ASSERT(m_wrapper); + vm.writeBarrier(m_wrapper.get(), function); + m_isInitialized = true; + } + } + + // m_wrapper and m_jsFunction are Weak<>. nullptr of these fields do not mean that this event-listener is not initialized yet. + // If this is initialized once, m_isInitialized should be true, and then m_wrapper and m_jsFunction must be alive. m_wrapper's + // liveness should be kept correctly by using ActiveDOMObject, output-constraints, etc. And m_jsFunction must be alive if m_wrapper + // is alive since JSEventListener marks m_jsFunction in JSEventListener::visitJSFunction if m_wrapper is alive. + // If the event-listener is not initialized yet, we should skip invoking this event-listener. + if (!m_isInitialized) + return nullptr; + + ASSERT(m_wrapper); + ASSERT(m_jsFunction); + // Ensure m_jsFunction is live JSObject as a quick sanity check (while it is already ensured by Weak<>). If this fails, this is possibly JSC GC side's bug. + ASSERT(static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject()); + + return m_jsFunction.get(); +} + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::JSEventListener) +static bool isType(const WebCore::EventListener& input) { return input.type() == WebCore::JSEventListener::JSEventListenerType; } +SPECIALIZE_TYPE_TRAITS_END() diff --git a/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.cpp b/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.cpp new file mode 100644 index 000000000..72c01abd0 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.cpp @@ -0,0 +1,57 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSEventListenerOptions.h" + +#include "JSDOMConvertBoolean.h" +#include <JavaScriptCore/JSCInlines.h> + + +namespace WebCore { +using namespace JSC; + +template<> EventListenerOptions convertDictionary<EventListenerOptions>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return { }; + } + EventListenerOptions result; + JSValue captureValue; + if (isNullOrUndefined) + captureValue = jsUndefined(); + else { + captureValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "capture")); + RETURN_IF_EXCEPTION(throwScope, { }); + } + if (!captureValue.isUndefined()) { + result.capture = convert<IDLBoolean>(lexicalGlobalObject, captureValue); + RETURN_IF_EXCEPTION(throwScope, { }); + } else + result.capture = false; + return result; +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.dep b/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.dep new file mode 100644 index 000000000..6a7075b90 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.dep @@ -0,0 +1 @@ +EventListenerOptions.h : diff --git a/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.h b/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.h new file mode 100644 index 000000000..1b4e2027e --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventListenerOptions.h @@ -0,0 +1,30 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "EventListenerOptions.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> EventListenerOptions convertDictionary<EventListenerOptions>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventModifierInit.cpp b/src/javascript/jsc/bindings/webcore/JSEventModifierInit.cpp new file mode 100644 index 000000000..53fd87c95 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventModifierInit.cpp @@ -0,0 +1,180 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSEventModifierInit.h" + +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertNullable.h" +#include "JSDOMConvertNumbers.h" +// #include "JSWindowProxy.h" +#include <JavaScriptCore/JSCInlines.h> + +namespace WebCore { +using namespace JSC; + +template<> EventModifierInit convertDictionary<EventModifierInit>(JSGlobalObject& lexicalGlobalObject, JSValue value) +{ + VM& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + bool isNullOrUndefined = value.isUndefinedOrNull(); + auto* object = isNullOrUndefined ? nullptr : value.getObject(); + if (UNLIKELY(!isNullOrUndefined && !object)) { + throwTypeError(&lexicalGlobalObject, throwScope); + return {}; + } + EventModifierInit result; + JSValue bubblesValue; + if (isNullOrUndefined) + bubblesValue = jsUndefined(); + else { + bubblesValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "bubbles")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!bubblesValue.isUndefined()) { + result.bubbles = convert<IDLBoolean>(lexicalGlobalObject, bubblesValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.bubbles = false; + JSValue cancelableValue; + if (isNullOrUndefined) + cancelableValue = jsUndefined(); + else { + cancelableValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "cancelable")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!cancelableValue.isUndefined()) { + result.cancelable = convert<IDLBoolean>(lexicalGlobalObject, cancelableValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.cancelable = false; + JSValue composedValue; + if (isNullOrUndefined) + composedValue = jsUndefined(); + else { + composedValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "composed")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!composedValue.isUndefined()) { + result.composed = convert<IDLBoolean>(lexicalGlobalObject, composedValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.composed = false; + JSValue detailValue; + if (isNullOrUndefined) + detailValue = jsUndefined(); + else { + detailValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "detail")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!detailValue.isUndefined()) { + result.detail = convert<IDLLong>(lexicalGlobalObject, detailValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.detail = 0; + JSValue viewValue; + if (isNullOrUndefined) + viewValue = jsUndefined(); + else { + viewValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "view")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + // if (!viewValue.isUndefined()) { + // result.view = convert<IDLNullable<IDLInterface<WindowProxy>>>(lexicalGlobalObject, viewValue); + // RETURN_IF_EXCEPTION(throwScope, { }); + // } else + result.view = nullptr; + JSValue altKeyValue; + if (isNullOrUndefined) + altKeyValue = jsUndefined(); + else { + altKeyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "altKey")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!altKeyValue.isUndefined()) { + result.altKey = convert<IDLBoolean>(lexicalGlobalObject, altKeyValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.altKey = false; + JSValue ctrlKeyValue; + if (isNullOrUndefined) + ctrlKeyValue = jsUndefined(); + else { + ctrlKeyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "ctrlKey")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!ctrlKeyValue.isUndefined()) { + result.ctrlKey = convert<IDLBoolean>(lexicalGlobalObject, ctrlKeyValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.ctrlKey = false; + JSValue metaKeyValue; + if (isNullOrUndefined) + metaKeyValue = jsUndefined(); + else { + metaKeyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "metaKey")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!metaKeyValue.isUndefined()) { + result.metaKey = convert<IDLBoolean>(lexicalGlobalObject, metaKeyValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.metaKey = false; + JSValue modifierAltGraphValue; + if (isNullOrUndefined) + modifierAltGraphValue = jsUndefined(); + else { + modifierAltGraphValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modifierAltGraph")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!modifierAltGraphValue.isUndefined()) { + result.modifierAltGraph = convert<IDLBoolean>(lexicalGlobalObject, modifierAltGraphValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.modifierAltGraph = false; + JSValue modifierCapsLockValue; + if (isNullOrUndefined) + modifierCapsLockValue = jsUndefined(); + else { + modifierCapsLockValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "modifierCapsLock")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!modifierCapsLockValue.isUndefined()) { + result.modifierCapsLock = convert<IDLBoolean>(lexicalGlobalObject, modifierCapsLockValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.modifierCapsLock = false; + JSValue shiftKeyValue; + if (isNullOrUndefined) + shiftKeyValue = jsUndefined(); + else { + shiftKeyValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "shiftKey")); + RETURN_IF_EXCEPTION(throwScope, {}); + } + if (!shiftKeyValue.isUndefined()) { + result.shiftKey = convert<IDLBoolean>(lexicalGlobalObject, shiftKeyValue); + RETURN_IF_EXCEPTION(throwScope, {}); + } else + result.shiftKey = false; + return result; +} + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventModifierInit.dep b/src/javascript/jsc/bindings/webcore/JSEventModifierInit.dep new file mode 100644 index 000000000..f6b60a42f --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventModifierInit.dep @@ -0,0 +1,3 @@ +EventModifierInit.h : UIEventInit.idl EventInit.idl +UIEventInit.idl : +EventInit.idl : diff --git a/src/javascript/jsc/bindings/webcore/JSEventModifierInit.h b/src/javascript/jsc/bindings/webcore/JSEventModifierInit.h new file mode 100644 index 000000000..2f35a2fd2 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventModifierInit.h @@ -0,0 +1,30 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "EventModifierInit.h" +#include "JSDOMConvertDictionary.h" + +namespace WebCore { + +template<> EventModifierInit convertDictionary<EventModifierInit>(JSC::JSGlobalObject&, JSC::JSValue); + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventTarget.cpp b/src/javascript/jsc/bindings/webcore/JSEventTarget.cpp new file mode 100644 index 000000000..705e020c3 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventTarget.cpp @@ -0,0 +1,351 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSEventTarget.h" + +#include "ActiveDOMObject.h" +#include "ExtendedDOMClientIsoSubspaces.h" +#include "ExtendedDOMIsoSubspaces.h" +#include "IDLTypes.h" +#include "JSAddEventListenerOptions.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructor.h" +#include "JSDOMConvertBase.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertDictionary.h" +#include "JSDOMConvertEventListener.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertNullable.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMOperation.h" +#include "JSDOMWrapperCache.h" +#include "JSEvent.h" +#include "JSEventListener.h" +#include "JSEventListenerOptions.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include <JavaScriptCore/FunctionPrototype.h> +#include <JavaScriptCore/HeapAnalyzer.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h> +#include <JavaScriptCore/SlotVisitorMacros.h> +#include <JavaScriptCore/SubspaceInlines.h> +#include <variant> +#include <wtf/GetPtr.h> +#include <wtf/PointerPreparations.h> +#include <wtf/URL.h> + +namespace WebCore { +using namespace JSC; + +// Functions + +static JSC_DECLARE_HOST_FUNCTION(jsEventTargetPrototypeFunction_addEventListener); +static JSC_DECLARE_HOST_FUNCTION(jsEventTargetPrototypeFunction_removeEventListener); +static JSC_DECLARE_HOST_FUNCTION(jsEventTargetPrototypeFunction_dispatchEvent); + +// Attributes + +static JSC_DECLARE_CUSTOM_GETTER(jsEventTargetConstructor); + +class JSEventTargetPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSEventTargetPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure) + { + JSEventTargetPrototype* ptr = new (NotNull, JSC::allocateCell<JSEventTargetPrototype>(vm)) JSEventTargetPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSEventTargetPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSEventTargetPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) + : JSC::JSNonFinalObject(vm, structure) + { + } + + void finishCreation(JSC::VM&); + +public: + static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::IsImmutablePrototypeExoticObject; +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSEventTargetPrototype, JSEventTargetPrototype::Base); + +using JSEventTargetDOMConstructor = JSDOMConstructor<JSEventTarget>; + +template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventTargetDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +{ + VM& vm = lexicalGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* castedThis = jsCast<JSEventTargetDOMConstructor*>(callFrame->jsCallee()); + ASSERT(castedThis); + auto* context = castedThis->scriptExecutionContext(); + if (UNLIKELY(!context)) + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "EventTarget"); + auto object = EventTarget::create(*context); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + static_assert(TypeOrExceptionOrUnderlyingType<decltype(object)>::isRef); + auto jsValue = toJSNewlyCreated<IDLInterface<EventTarget>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + setSubclassStructureIfNeeded<EventTarget>(lexicalGlobalObject, callFrame, asObject(jsValue)); + RETURN_IF_EXCEPTION(throwScope, {}); + return JSValue::encode(jsValue); +} +JSC_ANNOTATE_HOST_FUNCTION(JSEventTargetDOMConstructorConstruct, JSEventTargetDOMConstructor::construct); + +template<> const ClassInfo JSEventTargetDOMConstructor::s_info = { "EventTarget"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSEventTargetDOMConstructor) }; + +template<> JSValue JSEventTargetDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject) +{ + UNUSED_PARAM(vm); + return globalObject.functionPrototype(); +} + +template<> void JSEventTargetDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) +{ + putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSString* nameString = jsNontrivialString(vm, "EventTarget"_s); + m_originalName.set(vm, this, nameString); + putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + putDirect(vm, vm.propertyNames->prototype, JSEventTarget::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); +} + +/* Hash table for prototype */ + +static const HashTableValue JSEventTargetPrototypeTableValues[] = { + { "constructor", static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsEventTargetConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, + { "addEventListener", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsEventTargetPrototypeFunction_addEventListener), (intptr_t)(2) } }, + { "removeEventListener", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsEventTargetPrototypeFunction_removeEventListener), (intptr_t)(2) } }, + { "dispatchEvent", static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsEventTargetPrototypeFunction_dispatchEvent), (intptr_t)(1) } }, +}; + +const ClassInfo JSEventTargetPrototype::s_info = { "EventTarget"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSEventTargetPrototype) }; + +void JSEventTargetPrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSEventTarget::info(), JSEventTargetPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +const ClassInfo JSEventTarget::s_info = { "EventTarget"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSEventTarget) }; + +JSEventTarget::JSEventTarget(Structure* structure, JSDOMGlobalObject& globalObject, Ref<EventTarget>&& impl) + : JSDOMWrapper<EventTarget>(structure, globalObject, WTFMove(impl)) +{ +} + +void JSEventTarget::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + + // static_assert(!std::is_base_of<ActiveDOMObject, EventTarget>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); +} + +JSObject* JSEventTarget::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSEventTargetPrototype::create(vm, &globalObject, JSEventTargetPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); +} + +JSObject* JSEventTarget::prototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return getDOMPrototype<JSEventTarget>(vm, globalObject); +} + +JSValue JSEventTarget::getConstructor(VM& vm, const JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSEventTargetDOMConstructor, DOMConstructorID::EventTarget>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject)); +} + +void JSEventTarget::destroy(JSC::JSCell* cell) +{ + JSEventTarget* thisObject = static_cast<JSEventTarget*>(cell); + thisObject->JSEventTarget::~JSEventTarget(); +} + +JSC_DEFINE_CUSTOM_GETTER(jsEventTargetConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* prototype = jsDynamicCast<JSEventTargetPrototype*>(vm, JSValue::decode(thisValue)); + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(JSEventTarget::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject())); +} + +static inline JSC::EncodedJSValue jsEventTargetPrototypeFunction_addEventListenerBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSEventTarget>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 2)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto type = convert<IDLAtomStringAdaptor<IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto listener = convert<IDLNullable<IDLEventListener<JSEventListener>>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventTarget", "addEventListener"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->argument(2); + auto options = argument2.value().isUndefined() ? false : convert<IDLUnion<IDLDictionary<AddEventListenerOptions>, IDLBoolean>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + auto result = JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.addEventListenerForBindings(WTFMove(type), WTFMove(listener), WTFMove(options)); })); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + vm.writeBarrier(&static_cast<JSObject&>(*castedThis), argument1.value()); + return result; +} + +JSC_DEFINE_HOST_FUNCTION(jsEventTargetPrototypeFunction_addEventListener, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSEventTarget>::call<jsEventTargetPrototypeFunction_addEventListenerBody>(*lexicalGlobalObject, *callFrame, "addEventListener"); +} + +static inline JSC::EncodedJSValue jsEventTargetPrototypeFunction_removeEventListenerBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSEventTarget>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 2)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto type = convert<IDLAtomStringAdaptor<IDLDOMString>>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto listener = convert<IDLNullable<IDLEventListener<JSEventListener>>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventTarget", "removeEventListener"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument2 = callFrame->argument(2); + auto options = argument2.value().isUndefined() ? false : convert<IDLUnion<IDLDictionary<EventListenerOptions>, IDLBoolean>>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + auto result = JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.removeEventListenerForBindings(WTFMove(type), WTFMove(listener), WTFMove(options)); })); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + vm.writeBarrier(&static_cast<JSObject&>(*castedThis), argument1.value()); + return result; +} + +JSC_DEFINE_HOST_FUNCTION(jsEventTargetPrototypeFunction_removeEventListener, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSEventTarget>::call<jsEventTargetPrototypeFunction_removeEventListenerBody>(*lexicalGlobalObject, *callFrame, "removeEventListener"); +} + +static inline JSC::EncodedJSValue jsEventTargetPrototypeFunction_dispatchEventBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSEventTarget>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto event = convert<IDLInterface<Event>>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "event", "EventTarget", "dispatchEvent", "Event"); }); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLBoolean>(*lexicalGlobalObject, throwScope, impl.dispatchEventForBindings(*event)))); +} + +JSC_DEFINE_HOST_FUNCTION(jsEventTargetPrototypeFunction_dispatchEvent, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSEventTarget>::call<jsEventTargetPrototypeFunction_dispatchEventBody>(*lexicalGlobalObject, *callFrame, "dispatchEvent"); +} + +JSC::GCClient::IsoSubspace* JSEventTarget::subspaceForImpl(JSC::VM& vm) +{ + return WebCore::subspaceForImpl<JSEventTarget, UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForEventTarget.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForEventTarget = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForEventTarget.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForEventTarget = WTFMove(space); }); +} + +template<typename Visitor> +void JSEventTarget::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + auto* thisObject = jsCast<JSEventTarget*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + thisObject->visitAdditionalChildren(visitor); +} + +DEFINE_VISIT_CHILDREN(JSEventTarget); + +template<typename Visitor> +void JSEventTarget::visitOutputConstraints(JSCell* cell, Visitor& visitor) +{ + auto* thisObject = jsCast<JSEventTarget*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitOutputConstraints(thisObject, visitor); + thisObject->visitAdditionalChildren(visitor); +} + +template void JSEventTarget::visitOutputConstraints(JSCell*, AbstractSlotVisitor&); +template void JSEventTarget::visitOutputConstraints(JSCell*, SlotVisitor&); +void JSEventTarget::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSEventTarget*>(cell); + analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); + if (thisObject->scriptExecutionContext()) + analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + Base::analyzeHeap(cell, analyzer); +} + +bool JSEventTargetOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, AbstractSlotVisitor& visitor, const char** reason) +{ + auto* jsEventTarget = jsCast<JSEventTarget*>(handle.slot()->asCell()); + if (jsEventTarget->wrapped().isFiringEventListeners()) { + if (UNLIKELY(reason)) + *reason = "EventTarget firing event listeners"; + return true; + } + UNUSED_PARAM(visitor); + UNUSED_PARAM(reason); + return false; +} + +void JSEventTargetOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) +{ + auto* jsEventTarget = static_cast<JSEventTarget*>(handle.slot()->asCell()); + auto& world = *static_cast<DOMWrapperWorld*>(context); + uncacheWrapper(world, &jsEventTarget->wrapped(), jsEventTarget); +} + +} diff --git a/src/javascript/jsc/bindings/webcore/JSEventTarget.h b/src/javascript/jsc/bindings/webcore/JSEventTarget.h new file mode 100644 index 000000000..ac19a2d35 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventTarget.h @@ -0,0 +1,100 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "root.h" +#include "EventTarget.h" +#include "JSDOMWrapper.h" +#include <wtf/NeverDestroyed.h> + +namespace WebCore { + +class JSEventTarget : public JSDOMWrapper<EventTarget> { +public: + using Base = JSDOMWrapper<EventTarget>; + static JSEventTarget* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<EventTarget>&& impl) + { + JSEventTarget* ptr = new (NotNull, JSC::allocateCell<JSEventTarget>(globalObject->vm())) JSEventTarget(structure, *globalObject, WTFMove(impl)); + ptr->finishCreation(globalObject->vm()); + return ptr; + } + + static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&); + static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&); + static EventTarget* toWrapped(JSC::VM&, JSC::JSValue); + static void destroy(JSC::JSCell*); + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info(), JSC::NonArray); + } + + static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*); + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return subspaceForImpl(vm); + } + static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + + template<typename Visitor> static void visitOutputConstraints(JSCell*, Visitor&); + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + +protected: + JSEventTarget(JSC::Structure*, JSDOMGlobalObject&, Ref<EventTarget>&&); + + void finishCreation(JSC::VM&); +}; + +class JSEventTargetOwner final : public JSC::WeakHandleOwner { +public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) final; + void finalize(JSC::Handle<JSC::Unknown>, void* context) final; +}; + +inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, EventTarget*) +{ + static NeverDestroyed<JSEventTargetOwner> owner; + return &owner.get(); +} + +inline void* wrapperKey(EventTarget* wrappableObject) +{ + return wrappableObject; +} + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, EventTarget&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, EventTarget* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<EventTarget>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<EventTarget>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +template<> struct JSDOMWrapperConverterTraits<EventTarget> { + using WrapperClass = JSEventTarget; + using ToWrappedReturnType = EventTarget*; +}; + +} // namespace WebCore +#include "JSEventTargetCustom.h" diff --git a/src/javascript/jsc/bindings/webcore/JSEventTargetCustom.cpp b/src/javascript/jsc/bindings/webcore/JSEventTargetCustom.cpp new file mode 100644 index 000000000..cc63b0c0c --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventTargetCustom.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008-2021 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. ``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 + * 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. + */ + +#include "config.h" +#include "JSEventTarget.h" + +// #include "DOMWindow.h" +#include "EventTarget.h" +// #include "EventTargetHeaders.h" +#include "EventTargetInterfaces.h" +// #include "JSDOMWindow.h" +#include "JSDOMWrapperCache.h" +#include "JSEventListener.h" +// #include "JSWindowProxy.h" +// #include "JSWorkerGlobalScope.h" +// #include "WorkerGlobalScope.h" + +#if ENABLE(OFFSCREEN_CANVAS) +#include "OffscreenCanvas.h" +#endif + +namespace WebCore { +using namespace JSC; + +JSValue toJSNewlyCreated(JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<EventTarget>&& value) +{ + return createWrapper<EventTarget>(globalObject, WTFMove(value)); +} + +EventTarget* JSEventTarget::toWrapped(VM& vm, JSValue value) +{ + // if (value.inherits<JSWindowProxy>(vm)) + // return &jsCast<JSWindowProxy*>(asObject(value))->wrapped(); + // if (value.inherits<JSDOMWindow>(vm)) + // return &jsCast<JSDOMWindow*>(asObject(value))->wrapped(); + // if (value.inherits<JSWorkerGlobalScope>(vm)) + // return &jsCast<JSWorkerGlobalScope*>(asObject(value))->wrapped(); + if (value.inherits<JSEventTarget>(vm)) + return &jsCast<JSEventTarget*>(asObject(value))->wrapped(); + return nullptr; +} + +std::unique_ptr<JSEventTargetWrapper> jsEventTargetCast(VM& vm, JSValue thisValue) +{ + if (auto* target = jsDynamicCast<JSEventTarget*>(vm, thisValue)) + return makeUnique<JSEventTargetWrapper>(target->wrapped(), *target); + // if (auto* window = toJSDOMGlobalObject<JSDOMWindow>(vm, thisValue)) + // return makeUnique<JSEventTargetWrapper>(window->wrapped(), *window); + // if (auto* scope = toJSDOMGlobalObject<JSWorkerGlobalScope>(vm, thisValue)) + // return makeUnique<JSEventTargetWrapper>(scope->wrapped(), *scope); + return nullptr; +} + +template<typename Visitor> +void JSEventTarget::visitAdditionalChildren(Visitor& visitor) +{ + wrapped().visitJSEventListeners(visitor); +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSEventTarget); + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/JSEventTargetCustom.h b/src/javascript/jsc/bindings/webcore/JSEventTargetCustom.h new file mode 100644 index 000000000..5e2d4671e --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/JSEventTargetCustom.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2016-2020 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 "DOMWindow.h" +#include "JSDOMBinding.h" +// #include "JSDOMBindingSecurity.h";/ +#include "JSDOMOperation.h" + +namespace WebCore { + +// Wrapper type for JSEventTarget's castedThis because JSDOMWindow and JSWorkerGlobalScope do not inherit JSEventTarget. +class JSEventTargetWrapper { + WTF_MAKE_FAST_ALLOCATED; + +public: + JSEventTargetWrapper(EventTarget& wrapped, JSC::JSObject& wrapper) + : m_wrapped(wrapped) + , m_wrapper(wrapper) + { + } + + EventTarget& wrapped() { return m_wrapped; } + + operator JSC::JSObject&() { return m_wrapper; } + +private: + EventTarget& m_wrapped; + JSC::JSObject& m_wrapper; +}; + +std::unique_ptr<JSEventTargetWrapper> jsEventTargetCast(JSC::VM&, JSC::JSValue thisValue); + +template<> class IDLOperation<JSEventTarget> { +public: + using ClassParameter = JSEventTargetWrapper*; + using Operation = JSC::EncodedJSValue(JSC::JSGlobalObject*, JSC::CallFrame*, ClassParameter); + + template<Operation operation, CastedThisErrorBehavior = CastedThisErrorBehavior::Throw> + static JSC::EncodedJSValue call(JSC::JSGlobalObject& lexicalGlobalObject, JSC::CallFrame& callFrame, const char* operationName) + { + auto& vm = JSC::getVM(&lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto thisValue = callFrame.thisValue().toThis(&lexicalGlobalObject, JSC::ECMAMode::strict()); + auto thisObject = jsEventTargetCast(vm, thisValue.isUndefinedOrNull() ? JSC::JSValue(&lexicalGlobalObject) : thisValue); + if (UNLIKELY(!thisObject)) + return throwThisTypeError(lexicalGlobalObject, throwScope, "EventTarget", operationName); + + auto& wrapped = thisObject->wrapped(); + // if (is<DOMWindow>(wrapped)) { + // auto& window = downcast<DOMWindow>(wrapped); + // if (!window.frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(&lexicalGlobalObject, window, ThrowSecurityError)) + // return JSC::JSValue::encode(JSC::jsUndefined()); + // } + + RELEASE_AND_RETURN(throwScope, (operation(&lexicalGlobalObject, &callFrame, thisObject.get()))); + } +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/Node.h b/src/javascript/jsc/bindings/webcore/Node.h new file mode 100644 index 000000000..df9917a25 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/Node.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2004-2020 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +#include "root.h" + +#include "EventTarget.h" +#include "ExceptionOr.h" +#include <wtf/CompactUniquePtrTuple.h> +#include <wtf/FixedVector.h> +#include <wtf/Forward.h> +// #include <wtf/IsoMalloc.h> +#include <wtf/ListHashSet.h> +#include <wtf/MainThread.h> +#include <wtf/OptionSet.h> +#include <wtf/URLHash.h> +#include <wtf/WeakPtr.h> +#include "EventTargetConcrete.h" + +namespace WebCore { + +// The full Node type is way too much stuff +// this ones just a baby +class Node : public RefPtr<Node>, CanMakeWeakPtr<Node>, public EventTarget { + WTF_MAKE_ISO_ALLOCATED(Node); + + static constexpr uint32_t s_refCountIncrement = 2; + static constexpr uint32_t s_refCountMask = ~static_cast<uint32_t>(1); + +public: + void defaultEventHandler(Event&) + { + // do nothing + } + + void handleEvent(ScriptExecutionContext&, Event&) + { + } + + bool hasEventTargetData() + { + return true; + } + + void ref() const; + void deref() const; + bool hasOneRef() const; + unsigned refCount() const; + + void removedLastRef() {} + + mutable uint32_t m_refCountAndParentBit { s_refCountIncrement }; + // mutable OptionSet<NodeFlag> m_nodeFlags; +}; + +#if ASSERT_ENABLED + +inline void adopted(Node* node) +{ + if (!node) + return; + ASSERT(!node->m_deletionHasBegun); + ASSERT(!node->m_inRemovedLastRefFunction); + node->m_adoptionIsRequired = false; +} + +#endif // ASSERT_ENABLED + +ALWAYS_INLINE void Node::ref() const +{ + ASSERT(isMainThread()); + ASSERT(!m_deletionHasBegun); + ASSERT(!m_inRemovedLastRefFunction); + ASSERT(!m_adoptionIsRequired); + m_refCountAndParentBit += s_refCountIncrement; +} + +ALWAYS_INLINE void Node::deref() const +{ + ASSERT(isMainThread()); + ASSERT(refCount()); + ASSERT(!m_deletionHasBegun); + ASSERT(!m_inRemovedLastRefFunction); + ASSERT(!m_adoptionIsRequired); + auto updatedRefCount = m_refCountAndParentBit - s_refCountIncrement; + if (!updatedRefCount) { + // Don't update m_refCountAndParentBit to avoid double destruction through use of Ref<T>/RefPtr<T>. + // (This is a security mitigation in case of programmer error. It will ASSERT in debug builds.) +#if ASSERT_ENABLED + m_inRemovedLastRefFunction = true; +#endif + const_cast<Node&>(*this).removedLastRef(); + return; + } + m_refCountAndParentBit = updatedRefCount; +} + +ALWAYS_INLINE bool Node::hasOneRef() const +{ + ASSERT(!m_deletionHasBegun); + ASSERT(!m_inRemovedLastRefFunction); + return refCount() == 1; +} + +ALWAYS_INLINE unsigned Node::refCount() const +{ + return m_refCountAndParentBit / s_refCountIncrement; +} + +}
\ No newline at end of file diff --git a/src/javascript/jsc/bindings/webcore/RegisteredEventListener.h b/src/javascript/jsc/bindings/webcore/RegisteredEventListener.h new file mode 100644 index 000000000..1b2f48af4 --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/RegisteredEventListener.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de) + * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) + * Copyright (C) 2003-2021 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +#include "EventListener.h" +#include <wtf/Ref.h> + +namespace WebCore { + +// https://dom.spec.whatwg.org/#concept-event-listener +class RegisteredEventListener : public RefCounted<RegisteredEventListener> { +public: + struct Options { + Options(bool capture = false, bool passive = false, bool once = false) + : capture(capture) + , passive(passive) + , once(once) + { } + + bool capture; + bool passive; + bool once; + }; + + static Ref<RegisteredEventListener> create(Ref<EventListener>&& listener, const Options& options) + { + return adoptRef(*new RegisteredEventListener(WTFMove(listener), options)); + } + + EventListener& callback() const { return m_callback; } + bool useCapture() const { return m_useCapture; } + bool isPassive() const { return m_isPassive; } + bool isOnce() const { return m_isOnce; } + bool wasRemoved() const { return m_wasRemoved; } + + void markAsRemoved() { m_wasRemoved = true; } + +private: + RegisteredEventListener(Ref<EventListener>&& listener, const Options& options) + : m_useCapture(options.capture) + , m_isPassive(options.passive) + , m_isOnce(options.once) + , m_wasRemoved(false) + , m_callback(WTFMove(listener)) + { + } + + bool m_useCapture : 1; + bool m_isPassive : 1; + bool m_isOnce : 1; + bool m_wasRemoved : 1; + Ref<EventListener> m_callback; +}; + +} // namespace WebCore diff --git a/src/javascript/jsc/bindings/webcore/UIEventInit.h b/src/javascript/jsc/bindings/webcore/UIEventInit.h new file mode 100644 index 000000000..4511ba84a --- /dev/null +++ b/src/javascript/jsc/bindings/webcore/UIEventInit.h @@ -0,0 +1,53 @@ +/* + * 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 + * 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 "EventInit.h" +// #include "WindowProxy.h" +#include <wtf/RefPtr.h> +#include <wtf/Ref.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +struct UIEventInitView { + int garbage; + + void ref() + { + } + + void deref() + { + } +}; + +struct UIEventInit : public EventInit { + RefPtr<UIEventInitView> view; + int detail { 0 }; +}; + +} |