Skip to content

Commit

Permalink
Upgrade AbortSignal & AbortController to latest from WebKit (#10106)
Browse files Browse the repository at this point in the history
Fixes #9977
Closes #10086

Thank you @lithdew for investigating and most of the fixes. This adds more of the changes we missed from WebKit into Bun like the ability to follow other signals

Co-authored-by: Kenta Iwasaki <[email protected]>
  • Loading branch information
Jarred-Sumner and lithdew authored Apr 9, 2024
1 parent 0dc0919 commit df49a5a
Show file tree
Hide file tree
Showing 19 changed files with 399 additions and 184 deletions.
34 changes: 8 additions & 26 deletions src/bun.js/bindings/WebCoreOpaqueRoot.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

#pragma once

#include "Node.h"

namespace WebCore {

class WebCoreOpaqueRoot {
Expand All @@ -38,48 +40,28 @@ class WebCoreOpaqueRoot {

WebCoreOpaqueRoot(std::nullptr_t) {}

bool isNode() const { return false; }
void* pointer() const { return m_pointer; }

private:
void* m_pointer { nullptr };
bool m_isNode { false };
};

template<typename Visitor>
ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, WebCoreOpaqueRoot root)
{
visitor.addOpaqueRoot(root.pointer());
}
inline void addWebCoreOpaqueRoot(Visitor&, WebCoreOpaqueRoot);

template<typename Visitor, typename ImplType>
ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, ImplType* impl)
{
addWebCoreOpaqueRoot(visitor, root(impl));
}
inline void addWebCoreOpaqueRoot(Visitor&, ImplType*);

template<typename Visitor, typename ImplType>
ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, ImplType& impl)
{
addWebCoreOpaqueRoot(visitor, root(&impl));
}
inline void addWebCoreOpaqueRoot(Visitor&, ImplType&);

template<typename Visitor>
ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, WebCoreOpaqueRoot root)
{
return visitor.containsOpaqueRoot(root.pointer());
}
inline bool containsWebCoreOpaqueRoot(Visitor&, WebCoreOpaqueRoot);

template<typename Visitor, typename ImplType>
ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, ImplType& impl)
{
return containsWebCoreOpaqueRoot(visitor, root(&impl));
}
inline bool containsWebCoreOpaqueRoot(Visitor&, ImplType&);

template<typename Visitor, typename ImplType>
ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, ImplType* impl)
{
return containsWebCoreOpaqueRoot(visitor, root(impl));
}
inline bool containsWebCoreOpaqueRoot(Visitor&, ImplType*);

} // namespace WebCore
68 changes: 68 additions & 0 deletions src/bun.js/bindings/WebCoreOpaqueRootInlines.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (C) 2023 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 "WebCoreOpaqueRoot.h"

namespace WebCore {

template<typename Visitor>
ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, WebCoreOpaqueRoot root)
{
visitor.addOpaqueRoot(root.pointer());
}

template<typename Visitor, typename ImplType>
ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, ImplType* impl)
{
addWebCoreOpaqueRoot(visitor, root(impl));
}

template<typename Visitor, typename ImplType>
ALWAYS_INLINE void addWebCoreOpaqueRoot(Visitor& visitor, ImplType& impl)
{
addWebCoreOpaqueRoot(visitor, root(&impl));
}

template<typename Visitor>
ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, WebCoreOpaqueRoot root)
{
return visitor.containsOpaqueRoot(root.pointer());
}

template<typename Visitor, typename ImplType>
ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, ImplType& impl)
{
return containsWebCoreOpaqueRoot(visitor, root(&impl));
}

template<typename Visitor, typename ImplType>
ALWAYS_INLINE bool containsWebCoreOpaqueRoot(Visitor& visitor, ImplType* impl)
{
return containsWebCoreOpaqueRoot(visitor, root(impl));
}

} // namespace WebCore
23 changes: 18 additions & 5 deletions src/bun.js/bindings/ZigGlobalObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1835,7 +1835,6 @@ JSC_DECLARE_HOST_FUNCTION(makeGetterTypeErrorForBuiltins);
JSC_DECLARE_HOST_FUNCTION(makeDOMExceptionForBuiltins);
JSC_DECLARE_HOST_FUNCTION(createWritableStreamFromInternal);
JSC_DECLARE_HOST_FUNCTION(getInternalWritableStream);
JSC_DECLARE_HOST_FUNCTION(whenSignalAborted);
JSC_DECLARE_HOST_FUNCTION(isAbortSignal);

JSC_DEFINE_HOST_FUNCTION(makeThisTypeErrorForBuiltins, (JSGlobalObject * globalObject, CallFrame* callFrame))
Expand Down Expand Up @@ -1918,7 +1917,7 @@ JSC_DEFINE_HOST_FUNCTION(createWritableStreamFromInternal, (JSGlobalObject * glo
return JSValue::encode(toJSNewlyCreated(globalObject, jsDOMGlobalObject, WritableStream::create(WTFMove(internalWritableStream))));
}

JSC_DEFINE_HOST_FUNCTION(whenSignalAborted, (JSGlobalObject * globalObject, CallFrame* callFrame))
JSC_DEFINE_HOST_FUNCTION(addAbortAlgorithmToSignal, (JSGlobalObject * globalObject, CallFrame* callFrame))
{
ASSERT(callFrame);
ASSERT(callFrame->argumentCount() == 2);
Expand All @@ -1930,8 +1929,21 @@ JSC_DEFINE_HOST_FUNCTION(whenSignalAborted, (JSGlobalObject * globalObject, Call

Ref<AbortAlgorithm> abortAlgorithm = JSAbortAlgorithm::create(vm, callFrame->uncheckedArgument(1).getObject());

bool result = WebCore::AbortSignal::whenSignalAborted(abortSignal->wrapped(), WTFMove(abortAlgorithm));
return JSValue::encode(result ? JSValue(JSC::JSValue::JSTrue) : JSValue(JSC::JSValue::JSFalse));
auto algorithmIdentifier = AbortSignal::addAbortAlgorithmToSignal(abortSignal->wrapped(), WTFMove(abortAlgorithm));
return JSValue::encode(JSC::jsNumber(algorithmIdentifier));
}

JSC_DEFINE_HOST_FUNCTION(removeAbortAlgorithmFromSignal, (JSGlobalObject*, CallFrame* callFrame))
{
ASSERT(callFrame);
ASSERT(callFrame->argumentCount() == 2);

auto* abortSignal = jsDynamicCast<JSAbortSignal*>(callFrame->uncheckedArgument(0));
if (UNLIKELY(!abortSignal))
return JSValue::encode(JSValue(JSC::JSValue::JSFalse));

AbortSignal::removeAbortAlgorithmFromSignal(abortSignal->wrapped(), callFrame->uncheckedArgument(1).asUInt32());
return JSValue::encode(JSC::jsUndefined());
}

JSC_DEFINE_HOST_FUNCTION(isAbortSignal, (JSGlobalObject*, CallFrame* callFrame))
Expand Down Expand Up @@ -3351,7 +3363,8 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm)
GlobalPropertyInfo(builtinNames.makeThisTypeErrorPrivateName(), JSFunction::create(vm, this, 2, String(), makeThisTypeErrorForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.makeGetterTypeErrorPrivateName(), JSFunction::create(vm, this, 2, String(), makeGetterTypeErrorForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.makeDOMExceptionPrivateName(), JSFunction::create(vm, this, 2, String(), makeDOMExceptionForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.whenSignalAbortedPrivateName(), JSFunction::create(vm, this, 2, String(), whenSignalAborted, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.addAbortAlgorithmToSignalPrivateName(), JSFunction::create(vm, this, 2, String(), addAbortAlgorithmToSignal, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.removeAbortAlgorithmFromSignalPrivateName(), JSFunction::create(vm, this, 2, String(), removeAbortAlgorithmFromSignal, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.cloneArrayBufferPrivateName(), JSFunction::create(vm, this, 3, String(), cloneArrayBuffer, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.structuredCloneForStreamPrivateName(), JSFunction::create(vm, this, 1, String(), structuredCloneForStream, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
GlobalPropertyInfo(builtinNames.isAbortSignalPrivateName(), JSFunction::create(vm, this, 1, String(), isAbortSignal, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly),
Expand Down
4 changes: 2 additions & 2 deletions src/bun.js/bindings/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5261,7 +5261,7 @@ extern "C" bool WebCore__AbortSignal__aborted(WebCore__AbortSignal* arg0)
extern "C" JSC__JSValue WebCore__AbortSignal__abortReason(WebCore__AbortSignal* arg0)
{
WebCore::AbortSignal* abortSignal = reinterpret_cast<WebCore::AbortSignal*>(arg0);
return JSC::JSValue::encode(abortSignal->reason());
return JSC::JSValue::encode(abortSignal->reason().getValue(jsNull()));
}

extern "C" WebCore__AbortSignal* WebCore__AbortSignal__ref(WebCore__AbortSignal* arg0)
Expand All @@ -5288,7 +5288,7 @@ extern "C" WebCore__AbortSignal* WebCore__AbortSignal__addListener(WebCore__Abor
WebCore::AbortSignal* abortSignal = reinterpret_cast<WebCore::AbortSignal*>(arg0);

if (abortSignal->aborted()) {
callback(ctx, JSC::JSValue::encode(abortSignal->reason()));
callback(ctx, JSC::JSValue::encode(abortSignal->reason().getValue(jsNull())));
return arg0;
}

Expand Down
18 changes: 15 additions & 3 deletions src/bun.js/bindings/webcore/AbortController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
#include "AbortSignal.h"
#include "DOMException.h"
#include "JSDOMException.h"
// #include <wtf/IsoMallocInlines.h>
#include <wtf/IsoMallocInlines.h>
#include "WebCoreOpaqueRoot.h"
#include "WebCoreOpaqueRootInlines.h"

namespace WebCore {

Expand All @@ -56,9 +58,19 @@ void AbortController::abort(JSDOMGlobalObject& globalObject, JSC::JSValue reason
{
ASSERT(reason);
if (reason.isUndefined())
reason = toJS(&globalObject, &globalObject, DOMException::create(AbortError));
reason = toJS(&globalObject, &globalObject, DOMException::create(ExceptionCode::AbortError));

m_signal->signalAbort(reason);
protectedSignal()->signalAbort(reason);
}

WebCoreOpaqueRoot AbortController::opaqueRoot()
{
return root(&signal());
}

Ref<AbortSignal> AbortController::protectedSignal() const
{
return m_signal;
}

}
5 changes: 5 additions & 0 deletions src/bun.js/bindings/webcore/AbortController.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class GlobalObject;

namespace WebCore {

class WebCoreOpaqueRoot;

class AbortSignal;

class ScriptExecutionContext;
Expand All @@ -55,8 +57,11 @@ class AbortController final : public ScriptWrappable, public RefCounted<AbortCon
~AbortController();

AbortSignal& signal();
Ref<AbortSignal> protectedSignal() const;
void abort(Zig::GlobalObject&, JSC::JSValue reason);

WebCoreOpaqueRoot opaqueRoot();

private:
explicit AbortController(ScriptExecutionContext&);

Expand Down
Loading

0 comments on commit df49a5a

Please sign in to comment.