aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-01-08 07:36:42 -0800
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-01-08 07:37:51 -0800
commit83a5c9f3da91b677fd6c9f1bc06b69f292997bd6 (patch)
tree19b6b2fce484999da8e2499926f6eda5b704379b
parent791f8ab0a17d87d5fed6c53033d7f3d3b5dad6cc (diff)
downloadbun-83a5c9f3da91b677fd6c9f1bc06b69f292997bd6.tar.gz
bun-83a5c9f3da91b677fd6c9f1bc06b69f292997bd6.tar.zst
bun-83a5c9f3da91b677fd6c9f1bc06b69f292997bd6.zip
[internal] Fix checking for Error object
-rw-r--r--src/bun.js/api/bun.zig2
-rw-r--r--src/bun.js/api/bun/socket.zig34
-rw-r--r--src/bun.js/api/bun/subprocess.zig2
-rw-r--r--src/bun.js/base.zig4
-rw-r--r--src/bun.js/bindings/FFI.zig2
-rw-r--r--src/bun.js/bindings/bindings.cpp38
-rw-r--r--src/bun.js/bindings/bindings.zig137
-rw-r--r--src/bun.js/bindings/headers-cpp.h2
-rw-r--r--src/bun.js/bindings/headers.h8
-rw-r--r--src/bun.js/bindings/headers.zig4
-rw-r--r--src/bun.js/test/jest.zig20
-rw-r--r--src/bun.js/webcore/response.zig4
-rw-r--r--src/napi/napi.zig6
-rw-r--r--test/bun.js/serve.test.ts68
14 files changed, 259 insertions, 72 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 6b19f138d..e9b760de5 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -2849,7 +2849,7 @@ pub const Timer = struct {
return;
}
- if (result.isAnyError(globalThis)) {
+ if (result.isAnyError()) {
vm.runErrorHandlerWithDedupe(result, null);
this.deinit();
return;
diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig
index 329a6bbed..4073decde 100644
--- a/src/bun.js/api/bun/socket.zig
+++ b/src/bun.js/api/bun/socket.zig
@@ -117,7 +117,7 @@ const Handlers = struct {
}
const result = onError.callWithThis(this.globalObject, thisValue, err);
- if (result.isAnyError(this.globalObject)) {
+ if (result.isAnyError()) {
this.vm.onUnhandledError(this.globalObject, result);
}
@@ -862,8 +862,8 @@ fn NewSocket(comptime ssl: bool) type {
this_value,
});
- if (result.isAnyError(globalObject)) {
- _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, result });
+ if (result.toError()) |err_value| {
+ _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, err_value });
}
}
pub fn onTimeout(
@@ -888,8 +888,8 @@ fn NewSocket(comptime ssl: bool) type {
this_value,
});
- if (result.isAnyError(globalObject)) {
- _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, result });
+ if (result.toError()) |err_value| {
+ _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, err_value });
}
}
pub fn onConnectError(this: *This, _: Socket, errno: c_int) void {
@@ -927,9 +927,9 @@ fn NewSocket(comptime ssl: bool) type {
err_value,
});
- if (result.isAnyError(globalObject)) {
- if (handlers.rejectPromise(result)) return;
- _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, result });
+ if (result.toError()) |err_val| {
+ if (handlers.rejectPromise(err_val)) return;
+ _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, err_val });
} else if (handlers.promise.trySwap()) |val| {
// They've defined a `connectError` callback
// The error is effectively handled, but we should still reject the promise.
@@ -987,7 +987,7 @@ fn NewSocket(comptime ssl: bool) type {
this_value,
});
- if (result.isAnyError(globalObject)) {
+ if (result.toError()) |err| {
this.detached = true;
defer this.markInactive();
if (!this.socket.isClosed()) {
@@ -996,8 +996,8 @@ fn NewSocket(comptime ssl: bool) type {
log("Already closed", .{});
}
- if (handlers.rejectPromise(result)) return;
- _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, result });
+ if (handlers.rejectPromise(err)) return;
+ _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, err });
}
}
@@ -1030,8 +1030,8 @@ fn NewSocket(comptime ssl: bool) type {
this_value,
});
- if (result.isAnyError(globalObject)) {
- _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, result });
+ if (result.toError()) |err_value| {
+ _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, err_value });
}
}
@@ -1054,8 +1054,8 @@ fn NewSocket(comptime ssl: bool) type {
JSValue.jsNumber(@as(i32, err)),
});
- if (result.isAnyError(globalObject)) {
- _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, result });
+ if (result.toError()) |err_value| {
+ _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, err_value });
}
}
@@ -1077,8 +1077,8 @@ fn NewSocket(comptime ssl: bool) type {
output_value,
});
- if (result.isAnyError(globalObject)) {
- _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, result });
+ if (result.toError()) |err_value| {
+ _ = handlers.callErrorHandler(this_value, &[_]JSC.JSValue{ this_value, err_value });
}
}
diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig
index 3f667491b..614bff0ad 100644
--- a/src/bun.js/api/bun/subprocess.zig
+++ b/src/bun.js/api/bun/subprocess.zig
@@ -1553,7 +1553,7 @@ pub const Subprocess = struct {
&args,
);
- if (result.isAnyError(globalThis)) {
+ if (result.isAnyError()) {
globalThis.bunVM().onUnhandledError(globalThis, result);
}
}
diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig
index 333ea36c9..8e1ce2d59 100644
--- a/src/bun.js/base.zig
+++ b/src/bun.js/base.zig
@@ -2185,7 +2185,7 @@ pub fn getterWrap(comptime Container: type, comptime name: string) GetterType(Co
})
else
@call(.auto, @field(Container, name), .{ this, ctx.ptr() });
- if (!result.isUndefinedOrNull() and result.isError()) {
+ if (result.isError()) {
exception.* = result.asObjectRef();
return null;
}
@@ -2816,7 +2816,7 @@ pub fn wrapWithHasContainer(
}
var result: JSValue = @call(.auto, @field(Container, name), args);
- if (!result.isEmptyOrUndefinedOrNull() and result.isError()) {
+ if (result.isError()) {
exception.* = result.asObjectRef();
iter.deinit();
return null;
diff --git a/src/bun.js/bindings/FFI.zig b/src/bun.js/bindings/FFI.zig
index e9d55c9f3..087d8308c 100644
--- a/src/bun.js/bindings/FFI.zig
+++ b/src/bun.js/bindings/FFI.zig
@@ -24,7 +24,7 @@ pub export var ValueTrue: EncodedJSValue = EncodedJSValue{
.asInt64 = @bitCast(i64, @as(c_longlong, (@as(c_int, 2) | @as(c_int, 4)) | @as(c_int, 1))),
};
pub const JSContext = ?*anyopaque;
-pub inline fn JSVALUE_IS_CELL(arg_val: EncodedJSValue) @"bool" {
+pub inline fn JSVALUE_IS_CELL(arg_val: EncodedJSValue) bool {
const val = arg_val;
return !(((@bitCast(c_ulonglong, val.asInt64) & @as(c_ulonglong, 18446181123756130304)) | @bitCast(c_ulonglong, @as(c_longlong, @as(c_int, 2)))) != 0);
}
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index ebe23c09e..74ac79501 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -2005,6 +2005,20 @@ void JSC__JSPromise__resolveOnNextTick(JSC__JSPromise* promise, JSC__JSGlobalObj
}
}
+bool JSC__JSValue__isAnyError(JSC__JSValue JSValue0)
+{
+ JSC::JSValue value = JSC::JSValue::decode(JSValue0);
+
+ JSC::JSCell* cell = value.asCell();
+ JSC::JSType type = cell->type();
+
+ if (type == JSC::CellType) {
+ return cell->inherits<JSC::Exception>();
+ }
+
+ return type == JSC::ErrorInstanceType;
+}
+
// This implementation closely mimicks the one in JSC::JSPromise::reject
void JSC__JSPromise__rejectOnNextTickWithHandled(JSC__JSPromise* promise, JSC__JSGlobalObject* lexicalGlobalObject,
JSC__JSValue encoedValue, bool handled)
@@ -3168,18 +3182,28 @@ void JSC__JSValue__getNameProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* a
arg2->len = 0;
}
-JSC__JSValue JSC__JSValue__toError(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1)
+JSC__JSValue JSC__JSValue__toError_(JSC__JSValue JSValue0)
{
JSC::JSValue value = JSC::JSValue::decode(JSValue0);
- if (JSC::Exception* jscException = JSC::jsDynamicCast<JSC::Exception*>(value)) {
- if (JSC::ErrorInstance* error = JSC::jsDynamicCast<JSC::ErrorInstance*>(jscException->value())) {
- return JSC::JSValue::encode(JSC::JSValue(error));
+ if (!value.isCell())
+ return JSC::JSValue::encode({});
+
+ JSC::JSCell* cell = value.asCell();
+
+ switch (cell->type()) {
+ case JSC::ErrorInstanceType:
+ return JSC::JSValue::encode(value);
+
+ case JSC::CellType:
+ if (cell->inherits<JSC::Exception>()) {
+ JSC::Exception* exception = jsCast<JSC::Exception*>(cell);
+ return JSC::JSValue::encode(exception->value());
}
+ default: {
}
- if (JSC::ErrorInstance* error = JSC::jsDynamicCast<JSC::ErrorInstance*>(value)) {
- return JSC::JSValue::encode(JSC::JSValue(error));
}
- return JSC::JSValue::encode(JSC::jsUndefined());
+
+ return JSC::JSValue::encode({});
}
void JSC__JSValue__toZigException(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1,
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index d1861966e..415c48612 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -1514,7 +1514,7 @@ pub const JSPromise = extern struct {
return value;
}
- if (value.isAnyError(globalObject)) {
+ if (value.isAnyError()) {
return rejectedPromiseValue(globalObject, value);
}
@@ -3064,14 +3064,30 @@ pub const JSValue = enum(JSValueReprInt) {
}
pub fn isError(this: JSValue) bool {
- return cppFn("isError", .{this});
+ if (!this.isCell())
+ return false;
+
+ return this.jsType() == JSType.ErrorInstance;
}
- pub fn isAnyError(this: JSValue, global: *JSGlobalObject) bool {
- if (this.isEmptyOrUndefinedOrNull()) return false;
+ pub fn isAnyError(this: JSValue) bool {
+ if (!this.isCell())
+ return false;
+
+ return cppFn("isAnyError", .{this});
+ }
- return this.isError() or this.isException(global.vm()) or this.isAggregateError(global);
+ pub fn toError_(this: JSValue) JSValue {
+ return cppFn("toError_", .{this});
+ }
+
+ pub fn toError(this: JSValue) ?JSValue {
+ const res = this.toError_();
+ if (res == .zero)
+ return null;
+ return res;
}
+
pub fn isString(this: JSValue) bool {
return cppFn("isString", .{this});
}
@@ -3122,8 +3138,8 @@ pub const JSValue = enum(JSValueReprInt) {
cppFn("getClassName", .{ this, global, ret });
}
- pub fn isCell(this: JSValue) bool {
- return cppFn("isCell", .{this});
+ pub inline fn isCell(this: JSValue) bool {
+ return (@bitCast(u64, @enumToInt(this)) & FFI.NotCellMask) == 0;
}
pub fn asCell(this: JSValue) *JSCell {
@@ -3142,10 +3158,6 @@ pub const JSValue = enum(JSValueReprInt) {
return cppFn("isTerminationException", .{ this, vm });
}
- pub fn toError(this: JSValue, global: *JSGlobalObject) JSValue {
- return cppFn("toError", .{ this, global });
- }
-
pub fn toZigException(this: JSValue, global: *JSGlobalObject, exception: *ZigException) void {
return cppFn("toZigException", .{ this, global, exception });
}
@@ -3515,7 +3527,108 @@ pub const JSValue = enum(JSValueReprInt) {
return this.asNullableVoid().?;
}
- pub const Extern = [_][]const u8{ "putIndex", "createRopeString", "forEachProperty", "coerceToInt32", "fastGet_", "getStaticProperty", "createUninitializedUint8Array", "fromInt64NoTruncate", "fromUInt64NoTruncate", "toUInt64NoTruncate", "asPromise", "toInt64", "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "createEmptyArray", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable", "toBooleanSlow", "deepEquals", "strictDeepEquals", "getIfPropertyExistsFromPath", "asBigIntCompare" };
+ pub const Extern = [_][]const u8{
+ "_then",
+ "asArrayBuffer_",
+ "asBigIntCompare",
+ "asCell",
+ "asInternalPromise",
+ "asNumber",
+ "asObject",
+ "asPromise",
+ "asString",
+ "coerceToInt32",
+ "createEmptyArray",
+ "createEmptyObject",
+ "createInternalPromise",
+ "createObject2",
+ "createRangeError",
+ "createRopeString",
+ "createStringArray",
+ "createTypeError",
+ "createUninitializedUint8Array",
+ "deepEquals",
+ "eqlCell",
+ "eqlValue",
+ "fastGet_",
+ "forEach",
+ "forEachProperty",
+ "fromEntries",
+ "fromInt64NoTruncate",
+ "fromUInt64NoTruncate",
+ "getClassName",
+ "getDirect",
+ "getErrorsProperty",
+ "getIfExists",
+ "getIfPropertyExistsFromPath",
+ "getIfPropertyExistsImpl",
+ "getLengthOfArray",
+ "getNameProperty",
+ "getPropertyByPropertyName",
+ "getPropertyNames",
+ "getPrototype",
+ "getStaticProperty",
+ "getSymbolDescription",
+ "hasProperty",
+ "isAggregateError",
+ "isAnyError",
+ "isAnyInt",
+ "isBigInt",
+ "isBigInt32",
+ "isBoolean",
+ "isCallable",
+ "isClass",
+ "isCustomGetterSetter",
+ "isError",
+ "isException",
+ "isGetterSetter",
+ "isHeapBigInt",
+ "isInt32",
+ "isInt32AsAnyInt",
+ "isIterable",
+ "isNumber",
+ "isObject",
+ "isPrimitive",
+ "isSameValue",
+ "isString",
+ "isSymbol",
+ "isTerminationException",
+ "isUInt32AsAnyInt",
+ "jsBoolean",
+ "jsDoubleNumber",
+ "jsNull",
+ "jsNumberFromChar",
+ "jsNumberFromDouble",
+ "jsNumberFromInt64",
+ "jsNumberFromU16",
+ "jsTDZValue",
+ "jsType",
+ "jsUndefined",
+ "jsonStringify",
+ "kind_",
+ "makeWithNameAndPrototype",
+ "parseJSON",
+ "put",
+ "putDirect",
+ "putIndex",
+ "putRecord",
+ "strictDeepEquals",
+ "symbolFor",
+ "symbolKeyFor",
+ "toBoolean",
+ "toBooleanSlow",
+ "toError_",
+ "toInt32",
+ "toInt64",
+ "toObject",
+ "toPropertyKeyValue",
+ "toString",
+ "toStringOrNull",
+ "toUInt64NoTruncate",
+ "toWTFString",
+ "toZigException",
+ "toZigString",
+ };
};
extern "c" fn Microtask__run(*Microtask, *JSGlobalObject) void;
diff --git a/src/bun.js/bindings/headers-cpp.h b/src/bun.js/bindings/headers-cpp.h
index a37d11b37..5fe2fcf1c 100644
--- a/src/bun.js/bindings/headers-cpp.h
+++ b/src/bun.js/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1673163040
+//-- AUTOGENERATED FILE -- 1673176089
// clang-format off
#pragma once
diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h
index 1c0581c81..51f1ad00c 100644
--- a/src/bun.js/bindings/headers.h
+++ b/src/bun.js/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format off
-//-- AUTOGENERATED FILE -- 1673163040
+//-- AUTOGENERATED FILE -- 1673176089
#pragma once
#include <stddef.h>
@@ -252,7 +252,6 @@ CPP_DECL JSC__JSInternalPromise* JSC__JSValue__asInternalPromise(JSC__JSValue JS
CPP_DECL double JSC__JSValue__asNumber(JSC__JSValue JSValue0);
CPP_DECL bJSC__JSObject JSC__JSValue__asObject(JSC__JSValue JSValue0);
CPP_DECL JSC__JSPromise* JSC__JSValue__asPromise(JSC__JSValue JSValue0);
-CPP_DECL JSC__JSPromise* JSC__JSValue__asPromise(JSC__JSValue JSValue0);
CPP_DECL JSC__JSString* JSC__JSValue__asString(JSC__JSValue JSValue0);
CPP_DECL int32_t JSC__JSValue__coerceToInt32(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL JSC__JSValue JSC__JSValue__createEmptyArray(JSC__JSGlobalObject* arg0, size_t arg1);
@@ -282,12 +281,12 @@ CPP_DECL void JSC__JSValue__getNameProperty(JSC__JSValue JSValue0, JSC__JSGlobal
CPP_DECL JSC__JSValue JSC__JSValue__getPrototype(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL void JSC__JSValue__getSymbolDescription(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2);
CPP_DECL bool JSC__JSValue__isAggregateError(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
+CPP_DECL bool JSC__JSValue__isAnyError(JSC__JSValue JSValue0);
CPP_DECL bool JSC__JSValue__isAnyInt(JSC__JSValue JSValue0);
CPP_DECL bool JSC__JSValue__isBigInt(JSC__JSValue JSValue0);
CPP_DECL bool JSC__JSValue__isBigInt32(JSC__JSValue JSValue0);
CPP_DECL bool JSC__JSValue__isBoolean(JSC__JSValue JSValue0);
CPP_DECL bool JSC__JSValue__isCallable(JSC__JSValue JSValue0, JSC__VM* arg1);
-CPP_DECL bool JSC__JSValue__isCell(JSC__JSValue JSValue0);
CPP_DECL bool JSC__JSValue__isClass(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL bool JSC__JSValue__isCustomGetterSetter(JSC__JSValue JSValue0);
CPP_DECL bool JSC__JSValue__isError(JSC__JSValue JSValue0);
@@ -326,12 +325,11 @@ CPP_DECL JSC__JSValue JSC__JSValue__symbolFor(JSC__JSGlobalObject* arg0, ZigStri
CPP_DECL bool JSC__JSValue__symbolKeyFor(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2);
CPP_DECL bool JSC__JSValue__toBoolean(JSC__JSValue JSValue0);
CPP_DECL bool JSC__JSValue__toBooleanSlow(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
-CPP_DECL JSC__JSValue JSC__JSValue__toError(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
+CPP_DECL JSC__JSValue JSC__JSValue__toError_(JSC__JSValue JSValue0);
CPP_DECL int32_t JSC__JSValue__toInt32(JSC__JSValue JSValue0);
CPP_DECL int64_t JSC__JSValue__toInt64(JSC__JSValue JSValue0);
CPP_DECL JSC__JSObject* JSC__JSValue__toObject(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL JSC__JSString* JSC__JSValue__toString(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
-CPP_DECL JSC__JSString* JSC__JSValue__toString(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL JSC__JSString* JSC__JSValue__toStringOrNull(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL uint64_t JSC__JSValue__toUInt64NoTruncate(JSC__JSValue JSValue0);
CPP_DECL void JSC__JSValue__toZigException(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigException* arg2);
diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig
index 095fe30f6..207327b67 100644
--- a/src/bun.js/bindings/headers.zig
+++ b/src/bun.js/bindings/headers.zig
@@ -206,12 +206,12 @@ pub extern fn JSC__JSValue__getNameProperty(JSValue0: JSC__JSValue, arg1: *bindi
pub extern fn JSC__JSValue__getPrototype(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) JSC__JSValue;
pub extern fn JSC__JSValue__getSymbolDescription(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, arg2: [*c]ZigString) void;
pub extern fn JSC__JSValue__isAggregateError(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) bool;
+pub extern fn JSC__JSValue__isAnyError(JSValue0: JSC__JSValue) bool;
pub extern fn JSC__JSValue__isAnyInt(JSValue0: JSC__JSValue) bool;
pub extern fn JSC__JSValue__isBigInt(JSValue0: JSC__JSValue) bool;
pub extern fn JSC__JSValue__isBigInt32(JSValue0: JSC__JSValue) bool;
pub extern fn JSC__JSValue__isBoolean(JSValue0: JSC__JSValue) bool;
pub extern fn JSC__JSValue__isCallable(JSValue0: JSC__JSValue, arg1: *bindings.VM) bool;
-pub extern fn JSC__JSValue__isCell(JSValue0: JSC__JSValue) bool;
pub extern fn JSC__JSValue__isClass(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) bool;
pub extern fn JSC__JSValue__isCustomGetterSetter(JSValue0: JSC__JSValue) bool;
pub extern fn JSC__JSValue__isError(JSValue0: JSC__JSValue) bool;
@@ -250,7 +250,7 @@ pub extern fn JSC__JSValue__symbolFor(arg0: *bindings.JSGlobalObject, arg1: [*c]
pub extern fn JSC__JSValue__symbolKeyFor(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, arg2: [*c]ZigString) bool;
pub extern fn JSC__JSValue__toBoolean(JSValue0: JSC__JSValue) bool;
pub extern fn JSC__JSValue__toBooleanSlow(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) bool;
-pub extern fn JSC__JSValue__toError(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) JSC__JSValue;
+pub extern fn JSC__JSValue__toError_(JSValue0: JSC__JSValue) JSC__JSValue;
pub extern fn JSC__JSValue__toInt32(JSValue0: JSC__JSValue) i32;
pub extern fn JSC__JSValue__toInt64(JSValue0: JSC__JSValue) i64;
pub extern fn JSC__JSValue__toObject(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) [*c]bindings.JSObject;
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig
index 590d5ec2b..68469c7e8 100644
--- a/src/bun.js/test/jest.zig
+++ b/src/bun.js/test/jest.zig
@@ -1098,7 +1098,7 @@ pub const Expect = struct {
const value = arguments[0];
if (value.isEmptyOrUndefinedOrNull() or !value.isObject() and !value.isString()) {
var fmt = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject };
- globalObject.throw("Expected value must be string or Error: {any}", .{ value.toFmt(globalObject, &fmt) });
+ globalObject.throw("Expected value must be string or Error: {any}", .{value.toFmt(globalObject, &fmt)});
return .zero;
}
break :brk value;
@@ -1117,19 +1117,19 @@ pub const Expect = struct {
}
const not = this.op.contains(.not);
- const result = value.call(globalObject, &.{}).toError(globalObject);
- if (result.isUndefined()) {
+ const result = value.call(globalObject, &.{}).toError_();
+ if (result == .zero) {
if (not) return thisValue;
globalObject.throw("Expected function to throw", .{});
return .zero;
- } else if(not) {
+ } else if (not) {
globalObject.throw("Expected function not to throw", .{});
return .zero;
}
- if (expected_value == .zero) return thisValue;
+ if (expected_value == .zero or !expected_value.isCell()) return thisValue;
- const expected_error = expected_value.toError(globalObject);
+ const expected_error = expected_value.toError() orelse expected_value;
if (expected_value.isString() or !expected_error.isUndefined()) {
const expected = brk: {
@@ -1401,7 +1401,7 @@ pub const TestScope = struct {
initial_value = js.JSObjectCallAsFunctionReturnValue(vm.global, callback, null, 0, null);
}
- if (initial_value.isAnyError(vm.global)) {
+ if (initial_value.isAnyError()) {
vm.runErrorHandler(initial_value, null);
return .{ .fail = active_test_expectation_counter.actual };
}
@@ -1640,7 +1640,7 @@ pub const DescribeScope = struct {
}
Jest.runner.?.pending_test = pending_test;
- if (result.isAnyError(ctx)) return result;
+ if (result.isAnyError()) return result;
if (comptime hook == .beforeAll or hook == .afterAll) {
hooks[i] = JSC.JSValue.zero;
@@ -1725,8 +1725,8 @@ pub const DescribeScope = struct {
return null;
},
}
- } else if (result.isAnyError(ctx)) {
- exception.* = result.asObjectRef();
+ } else if (result.toError()) |err| {
+ exception.* = err.asObjectRef();
return null;
}
}
diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig
index 20a04137f..7ee20fdd5 100644
--- a/src/bun.js/webcore/response.zig
+++ b/src/bun.js/webcore/response.zig
@@ -3484,7 +3484,7 @@ pub const Blob = struct {
const value = Function(&blob, globalThis, bytes, .temporary);
// invalid JSON needs to be rejected
- if (value.isAnyError(globalThis)) {
+ if (value.isAnyError()) {
promise.reject(globalThis, value);
} else {
promise.resolve(globalThis, value);
@@ -4904,7 +4904,7 @@ pub const Body = struct {
const json_value = blob.toJSON(global, .share);
blob.detach();
- if (json_value.isAnyError(global)) {
+ if (json_value.isAnyError()) {
promise.reject(global, json_value);
} else {
promise.resolve(global, json_value);
diff --git a/src/napi/napi.zig b/src/napi/napi.zig
index b4f054a21..da7191590 100644
--- a/src/napi/napi.zig
+++ b/src/napi/napi.zig
@@ -656,7 +656,7 @@ pub export fn napi_make_callback(env: napi_env, _: *anyopaque, recv: napi_value,
result.* = res;
// TODO: this is likely incorrect
- if (res.isAnyError(env)) {
+ if (res.isAnyError()) {
return .pending_exception;
}
@@ -713,8 +713,8 @@ pub extern fn napi_throw(env: napi_env, @"error": napi_value) napi_status;
pub extern fn napi_throw_error(env: napi_env, code: [*c]const u8, msg: [*c]const u8) napi_status;
pub extern fn napi_throw_type_error(env: napi_env, code: [*c]const u8, msg: [*c]const u8) napi_status;
pub extern fn napi_throw_range_error(env: napi_env, code: [*c]const u8, msg: [*c]const u8) napi_status;
-pub export fn napi_is_error(env: napi_env, value: napi_value, result: *bool) napi_status {
- result.* = value.isAnyError(env);
+pub export fn napi_is_error(_: napi_env, value: napi_value, result: *bool) napi_status {
+ result.* = value.isAnyError();
return .ok;
}
pub extern fn napi_is_exception_pending(env: napi_env, result: *bool) napi_status;
diff --git a/test/bun.js/serve.test.ts b/test/bun.js/serve.test.ts
index c050e29b0..3e2e70bb1 100644
--- a/test/bun.js/serve.test.ts
+++ b/test/bun.js/serve.test.ts
@@ -39,6 +39,21 @@ afterAll(() => {
}
});
+it("should display a welcome message when the response value type is incorrect", async () => {
+ await runTest(
+ {
+ fetch(req) {
+ return Symbol("invalid response type");
+ },
+ },
+ async (server) => {
+ const response = await fetch(`http://${server.hostname}:${server.port}`);
+ const text = await response.text();
+ expect(text).toContain("Welcome to Bun!");
+ },
+ );
+});
+
it("should work for a file", async () => {
const fixture = resolve(import.meta.dir, "./fetch.js.txt");
const textToExpect = readFileSync(fixture, "utf-8");
@@ -104,7 +119,6 @@ describe("streaming", () => {
var pass = false;
await runTest(
{
- development: false,
error(e) {
pass = true;
return new Response("PASS", { status: 555 });
@@ -136,16 +150,16 @@ describe("streaming", () => {
var pass = true;
await runTest(
{
- development: false,
error(e) {
- pass = true;
+ pass = false;
return new Response("FAIL", { status: 555 });
},
fetch(req) {
return new Response(
new ReadableStream({
- pull(controller) {
+ async pull(controller) {
controller.enqueue("PASS");
+ controller.close();
throw new Error("error");
},
}),
@@ -157,7 +171,7 @@ describe("streaming", () => {
`http://${server.hostname}:${server.port}`,
);
// connection terminated
- expect(response.status).toBe(500);
+ expect(response.status).toBe(200);
expect(await response.text()).toBe("PASS");
expect(pass).toBe(true);
},
@@ -217,11 +231,14 @@ describe("streaming", () => {
);
});
- it("text from JS throws on start no error handler", async () => {
+ it("Error handler is called when a throwing stream hasn't written anything", async () => {
await runTest(
{
port: port++,
- development: false,
+ error(e) {
+ return new Response("Test Passed", { status: 200 });
+ },
+
fetch(req) {
return new Response(
new ReadableStream({
@@ -229,6 +246,42 @@ describe("streaming", () => {
throw new Error("Test Passed");
},
}),
+ {
+ status: 404,
+ },
+ );
+ },
+ },
+ async (server) => {
+ const response = await fetch(
+ `http://${server.hostname}:${server.port}`,
+ );
+ expect(response.status).toBe(200);
+ expect(await response.text()).toBe("Test Passed");
+ },
+ );
+ });
+
+ // TODO: this test fails because we write status/headers at start of stream
+ it("text from JS throws on start with no error handler", async () => {
+ await runTest(
+ {
+ port: port++,
+ error: undefined,
+
+ fetch(req) {
+ return new Response(
+ new ReadableStream({
+ start(controller) {
+ throw new Error("Test Passed");
+ },
+ }),
+ {
+ status: 420,
+ headers: {
+ "x-what": "123",
+ },
+ },
);
},
},
@@ -246,7 +299,6 @@ describe("streaming", () => {
var err;
await runTest(
{
- development: false,
error(e) {
pass = true;
err = e;