diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bun.js/bindings/CallSite.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/CallSite.h | 3 | ||||
-rw-r--r-- | src/bun.js/bindings/ErrorStackTrace.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/ErrorStackTrace.h | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.cpp | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/node_util_types.cpp | 35 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/AbortSignal.cpp | 22 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/AbortSignal.h | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/JSAbortSignalCustom.cpp | 1 | ||||
-rw-r--r-- | src/bun.js/javascript.zig | 9 | ||||
-rw-r--r-- | src/bun.js/node/node_fs.zig | 83 | ||||
-rw-r--r-- | src/bun.js/readline.exports.js | 2 | ||||
-rw-r--r-- | src/bun.js/test/jest.zig | 12 | ||||
-rw-r--r-- | src/string_immutable.zig | 2 |
14 files changed, 153 insertions, 30 deletions
diff --git a/src/bun.js/bindings/CallSite.cpp b/src/bun.js/bindings/CallSite.cpp index 522c6db1c..02ac35168 100644 --- a/src/bun.js/bindings/CallSite.cpp +++ b/src/bun.js/bindings/CallSite.cpp @@ -88,4 +88,4 @@ void CallSite::visitChildrenImpl(JSCell* cell, Visitor& visitor) DEFINE_VISIT_CHILDREN(CallSite); -}
\ No newline at end of file +} diff --git a/src/bun.js/bindings/CallSite.h b/src/bun.js/bindings/CallSite.h index efe1b39d8..fe6b8ef5e 100644 --- a/src/bun.js/bindings/CallSite.h +++ b/src/bun.js/bindings/CallSite.h @@ -81,6 +81,7 @@ private: : Base(vm, structure) , m_lineNumber(-1) , m_columnNumber(-1) + , m_flags(0) { } @@ -89,4 +90,4 @@ private: DECLARE_VISIT_CHILDREN; }; -}
\ No newline at end of file +} diff --git a/src/bun.js/bindings/ErrorStackTrace.cpp b/src/bun.js/bindings/ErrorStackTrace.cpp index dddaa31ea..59e0e765b 100644 --- a/src/bun.js/bindings/ErrorStackTrace.cpp +++ b/src/bun.js/bindings/ErrorStackTrace.cpp @@ -372,4 +372,4 @@ bool JSCStackFrame::calculateSourcePositions() return true; } -}
\ No newline at end of file +} diff --git a/src/bun.js/bindings/ErrorStackTrace.h b/src/bun.js/bindings/ErrorStackTrace.h index 65ee60852..a8a6a192f 100644 --- a/src/bun.js/bindings/ErrorStackTrace.h +++ b/src/bun.js/bindings/ErrorStackTrace.h @@ -177,4 +177,4 @@ private: } }; -}
\ No newline at end of file +} diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index f43bfd4b8..7c1b3d82a 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -3961,7 +3961,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().getValue()); + return JSC::JSValue::encode(abortSignal->reason()); } extern "C" WebCore__AbortSignal* WebCore__AbortSignal__ref(WebCore__AbortSignal* arg0) @@ -3988,7 +3988,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().getValue())); + callback(ctx, JSC::JSValue::encode(abortSignal->reason())); return arg0; } diff --git a/src/bun.js/bindings/node_util_types.cpp b/src/bun.js/bindings/node_util_types.cpp index bf135ed0b..d53cb1786 100644 --- a/src/bun.js/bindings/node_util_types.cpp +++ b/src/bun.js/bindings/node_util_types.cpp @@ -11,6 +11,7 @@ #include "JavaScriptCore/ObjectConstructor.h" #include "JavaScriptCore/GeneratorFunctionPrototype.h" #include "JavaScriptCore/AsyncFunctionPrototype.h" +#include "JavaScriptCore/ErrorPrototype.h" using namespace JSC; @@ -84,7 +85,37 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsSymbolObject, (JSC::JSGlobalObject * global JSC_DEFINE_HOST_FUNCTION(jsFunctionIsNativeError, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) { GET_FIRST_VALUE - return JSValue::encode(jsBoolean(value.isCell() && (value.inherits<JSC::ErrorInstance>() || value.asCell()->type() == ErrorInstanceType))); + if (value.isCell()) { + if (value.inherits<JSC::ErrorInstance>() || value.asCell()->type() == ErrorInstanceType) + return JSValue::encode(jsBoolean(true)); + + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSObject* object = value.toObject(globalObject); + + // node util.isError relies on toString + // https://github.com/nodejs/node/blob/cf8c6994e0f764af02da4fa70bc5962142181bf3/doc/api/util.md#L2923 + PropertySlot slot(object, PropertySlot::InternalMethodType::VMInquiry, &vm); + if (object->getPropertySlot(globalObject, vm.propertyNames->toStringTagSymbol, slot)) { + EXCEPTION_ASSERT(!scope.exception()); + if (slot.isValue()) { + JSValue value = slot.getValue(globalObject, vm.propertyNames->toStringTagSymbol); + if (value.isString()) { + String tag = asString(value)->value(globalObject); + if (UNLIKELY(scope.exception())) + scope.clearException(); + if (tag == "Error"_s) + return JSValue::encode(jsBoolean(true)); + } + } + } + + JSValue proto = object->getPrototype(vm, globalObject); + if (proto.isCell() && (proto.inherits<JSC::ErrorInstance>() || proto.asCell()->type() == ErrorInstanceType || proto.inherits<JSC::ErrorPrototype>())) + return JSValue::encode(jsBoolean(true)); + } + + return JSValue::encode(jsBoolean(false)); } JSC_DEFINE_HOST_FUNCTION(jsFunctionIsRegExp, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) { @@ -349,4 +380,4 @@ void generateNodeUtilTypesSourceCode(JSC::JSGlobalObject* lexicalGlobalObject, exportNames.append(JSC::Identifier::fromString(vm, "default"_s)); exportValues.append(defaultObject); } -}
\ No newline at end of file +} diff --git a/src/bun.js/bindings/webcore/AbortSignal.cpp b/src/bun.js/bindings/webcore/AbortSignal.cpp index d20af5c81..febc610b7 100644 --- a/src/bun.js/bindings/webcore/AbortSignal.cpp +++ b/src/bun.js/bindings/webcore/AbortSignal.cpp @@ -78,7 +78,7 @@ Ref<AbortSignal> AbortSignal::timeout(ScriptExecutionContext& context, uint64_t AbortSignal::AbortSignal(ScriptExecutionContext* context, Aborted aborted, JSC::JSValue reason) : ContextDestructionObserver(context) , m_aborted(aborted == Aborted::Yes) - , m_reason(reason) + , m_reason(context->vm(), reason) { ASSERT(reason); } @@ -98,7 +98,8 @@ void AbortSignal::signalAbort(JSC::JSValue reason) // 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); + auto& vm = scriptExecutionContext()->vm(); + m_reason.set(vm, reason); Ref protectedThis { *this }; auto algorithms = std::exchange(m_algorithms, {}); @@ -107,7 +108,7 @@ void AbortSignal::signalAbort(JSC::JSValue reason) auto callbacks = std::exchange(m_native_callbacks, {}); for (auto callback : callbacks) { - const auto [ ctx, func ] = callback; + const auto [ctx, func] = callback; func(ctx, JSC::JSValue::encode(reason)); } @@ -115,11 +116,12 @@ void AbortSignal::signalAbort(JSC::JSValue reason) dispatchEvent(Event::create(eventNames().abortEvent, Event::CanBubble::No, Event::IsCancelable::No)); } -void AbortSignal::cleanNativeBindings(void* ref) { +void AbortSignal::cleanNativeBindings(void* ref) +{ auto callbacks = std::exchange(m_native_callbacks, {}); - callbacks.removeAllMatching([=](auto callback){ - const auto [ ctx, func ] = callback; + callbacks.removeAllMatching([=](auto callback) { + const auto [ctx, func] = callback; return ctx == ref; }); } @@ -131,7 +133,7 @@ void AbortSignal::signalFollow(AbortSignal& signal) return; if (signal.aborted()) { - signalAbort(signal.reason().getValue()); + signalAbort(signal.reason()); return; } @@ -140,7 +142,7 @@ void AbortSignal::signalFollow(AbortSignal& signal) signal.addAlgorithm([weakThis = WeakPtr { this }](JSC::JSValue reason) { if (weakThis) { if (reason.isEmpty() || reason.isUndefined()) { - weakThis->signalAbort(weakThis->m_followingSignal ? weakThis->m_followingSignal->reason().getValue() + weakThis->signalAbort(weakThis->m_followingSignal ? weakThis->m_followingSignal->reason() : JSC::jsUndefined()); } else { weakThis->signalAbort(reason); @@ -157,7 +159,7 @@ void AbortSignal::eventListenersDidChange() bool AbortSignal::whenSignalAborted(AbortSignal& signal, Ref<AbortAlgorithm>&& algorithm) { if (signal.aborted()) { - algorithm->handleEvent(signal.m_reason.getValue()); + algorithm->handleEvent(signal.m_reason.get()); return true; } signal.addAlgorithm([algorithm = WTFMove(algorithm)](JSC::JSValue value) mutable { @@ -173,7 +175,7 @@ void AbortSignal::throwIfAborted(JSC::JSGlobalObject& lexicalGlobalObject) auto& vm = lexicalGlobalObject.vm(); auto scope = DECLARE_THROW_SCOPE(vm); - throwException(&lexicalGlobalObject, scope, m_reason.getValue()); + throwException(&lexicalGlobalObject, scope, m_reason.get()); } } // namespace WebCore diff --git a/src/bun.js/bindings/webcore/AbortSignal.h b/src/bun.js/bindings/webcore/AbortSignal.h index 03374b248..6f4abf5ba 100644 --- a/src/bun.js/bindings/webcore/AbortSignal.h +++ b/src/bun.js/bindings/webcore/AbortSignal.h @@ -55,7 +55,7 @@ public: void signalFollow(AbortSignal&); bool aborted() const { return m_aborted; } - const JSValueInWrappedObject& reason() const { return m_reason; } + JSValue reason() const { return m_reason.get(); } bool hasActiveTimeoutTimer() const { return m_hasActiveTimeoutTimer; } bool hasAbortEventListener() const { return m_hasAbortEventListener; } @@ -90,7 +90,7 @@ private: Vector<Algorithm> m_algorithms; Vector<std::tuple<void*, void (*)(void*, JSC::EncodedJSValue)>> m_native_callbacks; WeakPtr<AbortSignal> m_followingSignal; - JSValueInWrappedObject m_reason; + JSC::Strong<JSC::Unknown> m_reason; bool m_hasActiveTimeoutTimer { false }; bool m_hasAbortEventListener { false }; }; diff --git a/src/bun.js/bindings/webcore/JSAbortSignalCustom.cpp b/src/bun.js/bindings/webcore/JSAbortSignalCustom.cpp index bc3bab081..88a94c7c0 100644 --- a/src/bun.js/bindings/webcore/JSAbortSignalCustom.cpp +++ b/src/bun.js/bindings/webcore/JSAbortSignalCustom.cpp @@ -54,7 +54,6 @@ bool JSAbortSignalOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> ha template<typename Visitor> void JSAbortSignal::visitAdditionalChildren(Visitor& visitor) { - wrapped().reason().visit(visitor); } DEFINE_VISIT_ADDITIONAL_CHILDREN(JSAbortSignal); diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index f54dd5fb8..3841a07e2 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -362,6 +362,7 @@ pub const VirtualMachine = struct { uws_event_loop: ?*uws.Loop = null, pending_unref_counter: i32 = 0, preload: []const string = &[_][]const u8{}, + unhandled_pending_rejection_to_capture: ?*JSC.JSValue = null, /// hide bun:wrap from stack traces /// bun:wrap is very noisy @@ -479,6 +480,14 @@ pub const VirtualMachine = struct { this.unhandled_error_counter += 1; } + pub fn onQuietUnhandledRejectionHandlerCaptureValue(this: *VirtualMachine, _: *JSC.JSGlobalObject, value: JSC.JSValue) void { + this.unhandled_error_counter += 1; + value.ensureStillAlive(); + if (this.unhandled_pending_rejection_to_capture) |ptr| { + ptr.* = value; + } + } + pub fn unhandledRejectionScope(this: *VirtualMachine) UnhandledRejectionScope { return .{ .onUnhandledRejection = this.onUnhandledRejection, diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index e068349a8..845992ecc 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -3582,8 +3582,82 @@ pub const NodeFS = struct { pub fn rmdir(this: *NodeFS, args: Arguments.RmDir, comptime flavor: Flavor) Maybe(Return.Rmdir) { switch (comptime flavor) { .sync => { - return Maybe(Return.Rmdir).errnoSysP(system.rmdir(args.path.sliceZ(&this.sync_error_buf)), .rmdir, args.path.slice()) orelse - Maybe(Return.Rmdir).success; + if (comptime Environment.isMac) { + if (args.recursive) { + var dest = args.path.sliceZ(&this.sync_error_buf); + + var flags: u32 = bun.C.darwin.RemoveFileFlags.cross_mount | + bun.C.darwin.RemoveFileFlags.allow_long_paths | + bun.C.darwin.RemoveFileFlags.recursive; + + while (true) { + if (Maybe(Return.Rmdir).errnoSys(bun.C.darwin.removefileat(std.os.AT.FDCWD, dest, null, flags), .rmdir)) |errno| { + switch (@intToEnum(os.E, errno.err.errno)) { + .AGAIN, .INTR => continue, + .NOENT => return Maybe(Return.Rmdir).success, + .MLINK => { + var copy: [bun.MAX_PATH_BYTES]u8 = undefined; + @memcpy(©, dest.ptr, dest.len); + copy[dest.len] = 0; + var dest_copy = copy[0..dest.len :0]; + switch (Syscall.unlink(dest_copy).getErrno()) { + .AGAIN, .INTR => continue, + .NOENT => return errno, + .SUCCESS => continue, + else => return errno, + } + }, + .SUCCESS => unreachable, + else => return errno, + } + } + + return Maybe(Return.Rmdir).success; + } + } + + return Maybe(Return.Rmdir).errnoSysP(system.rmdir(args.path.sliceZ(&this.sync_error_buf)), .rmdir, args.path.slice()) orelse + Maybe(Return.Rmdir).success; + } else if (comptime Environment.isLinux) { + if (args.recursive) { + std.fs.cwd().deleteTree(args.path.slice()) catch |err| { + const errno: std.os.E = switch (err) { + error.InvalidHandle => .BADF, + error.AccessDenied => .PERM, + error.FileTooBig => .FBIG, + error.SymLinkLoop => .LOOP, + error.ProcessFdQuotaExceeded => .NFILE, + error.NameTooLong => .NAMETOOLONG, + error.SystemFdQuotaExceeded => .MFILE, + error.SystemResources => .NOMEM, + error.ReadOnlyFileSystem => .ROFS, + error.FileSystem => .IO, + error.FileBusy => .BUSY, + error.DeviceBusy => .BUSY, + + // One of the path components was not a directory. + // This error is unreachable if `sub_path` does not contain a path separator. + error.NotDir => .NOTDIR, + // On Windows, file paths must be valid Unicode. + error.InvalidUtf8 => .INVAL, + + // On Windows, file paths cannot contain these characters: + // '/', '*', '?', '"', '<', '>', '|' + error.BadPathName => .INVAL, + + else => .FAULT, + }; + return Maybe(Return.Rm){ + .err = JSC.Node.Syscall.Error.fromCode(errno, .rmdir), + }; + }; + + return Maybe(Return.Rmdir).success; + } + + return Maybe(Return.Rmdir).errnoSysP(system.rmdir(args.path.sliceZ(&this.sync_error_buf)), .rmdir, args.path.slice()) orelse + Maybe(Return.Rmdir).success; + } }, else => {}, } @@ -3685,9 +3759,8 @@ pub const NodeFS = struct { std.os.unlinkZ(dest) catch |er| { // empircally, it seems to return AccessDenied when the // file is actually a directory on macOS. - if (er == error.IsDir or - er == error.NotDir or - er == error.AccessDenied) + if (args.recursive and + (er == error.IsDir or er == error.NotDir or er == error.AccessDenied)) { std.os.rmdirZ(dest) catch |err| { if (args.force) { diff --git a/src/bun.js/readline.exports.js b/src/bun.js/readline.exports.js index be7b75568..3044c5c20 100644 --- a/src/bun.js/readline.exports.js +++ b/src/bun.js/readline.exports.js @@ -2248,7 +2248,7 @@ var _Interface = class Interface extends InterfaceConstructor { var previousKey = this[kPreviousKey]; key = key || kEmptyObject; this[kPreviousKey] = key; - var { name: keyName, meta: keyMeta, ctrl: keyCtrl, shift: keyShift } = key; + var { name: keyName, meta: keyMeta, ctrl: keyCtrl, shift: keyShift, sequence: keySeq } = key; if (!keyMeta || keyName !== "y") { // Reset yanking state unless we are doing yank pop. diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 7aebf7e66..963a13967 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -2126,9 +2126,17 @@ pub const Expect = struct { const result_: ?JSValue = brk: { var vm = globalObject.bunVM(); + var return_value: JSValue = .zero; var scope = vm.unhandledRejectionScope(); - vm.onUnhandledRejection = &VirtualMachine.onQuietUnhandledRejectionHandler; - const return_value: JSValue = value.call(globalObject, &.{}); + var prev_unhandled_pending_rejection_to_capture = vm.unhandled_pending_rejection_to_capture; + vm.unhandled_pending_rejection_to_capture = &return_value; + vm.onUnhandledRejection = &VirtualMachine.onQuietUnhandledRejectionHandlerCaptureValue; + const return_value_from_fucntion: JSValue = value.call(globalObject, &.{}); + vm.unhandled_pending_rejection_to_capture = prev_unhandled_pending_rejection_to_capture; + + if (return_value == .zero) { + return_value = return_value_from_fucntion; + } if (return_value.asAnyPromise()) |promise| { globalObject.bunVM().waitForPromise(promise); diff --git a/src/string_immutable.zig b/src/string_immutable.zig index 321abb9f7..f4c6fae07 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -2146,7 +2146,7 @@ pub fn escapeHTMLForLatin1Input(allocator: std.mem.Allocator, latin1: []const u8 buf = try std.ArrayList(u8).initCapacity(allocator, latin1.len + @as(usize, Scalar.lengths[c])); const copy_len = @ptrToInt(ptr) - @ptrToInt(latin1.ptr); - @memcpy(buf.items.ptr, latin1.ptr, copy_len - 1); + @memcpy(buf.items.ptr, latin1.ptr, copy_len); buf.items.len = copy_len; any_needs_escape = true; break :scan_and_allocate_lazily; |