mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 13:51:47 +00:00
Fallback, fragments, printer compat, better errors
Former-commit-id: 486e8c9d460eeebea024e96dbabcb7f2bfaffafb
This commit is contained in:
@@ -5,6 +5,7 @@ const CAPI = @import("../JavaScriptCore.zig");
|
||||
const JS = @import("../javascript.zig");
|
||||
const JSBase = @import("../base.zig");
|
||||
const ZigURL = @import("../../../query_string_map.zig").URL;
|
||||
const Api = @import("../../../api/schema.zig").Api;
|
||||
const Handler = struct {
|
||||
pub export fn global_signal_handler_fn(sig: i32, info: *const std.os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void {
|
||||
var stdout = std.io.getStdOut();
|
||||
@@ -169,40 +170,6 @@ pub const ZigErrorType = extern struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const JSErrorCode = enum(u8) {
|
||||
Error = 0,
|
||||
EvalError = 1,
|
||||
RangeError = 2,
|
||||
ReferenceError = 3,
|
||||
SyntaxError = 4,
|
||||
TypeError = 5,
|
||||
URIError = 6,
|
||||
AggregateError = 7,
|
||||
|
||||
// StackOverflow & OutOfMemoryError is not an ErrorType in <JavaScriptCore/ErrorType.h> within JSC, so the number here is just totally made up
|
||||
OutOfMemoryError = 8,
|
||||
BundlerError = 252,
|
||||
StackOverflow = 253,
|
||||
UserErrorCode = 254,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const JSRuntimeType = enum(u16) {
|
||||
Nothing = 0x0,
|
||||
Function = 0x1,
|
||||
Undefined = 0x2,
|
||||
Null = 0x4,
|
||||
Boolean = 0x8,
|
||||
AnyInt = 0x10,
|
||||
Number = 0x20,
|
||||
String = 0x40,
|
||||
Object = 0x80,
|
||||
Symbol = 0x100,
|
||||
BigInt = 0x200,
|
||||
|
||||
_,
|
||||
};
|
||||
|
||||
pub fn Errorable(comptime Type: type) type {
|
||||
return extern struct {
|
||||
result: Result,
|
||||
@@ -251,6 +218,40 @@ pub const ResolvedSource = extern struct {
|
||||
bytecodecache_fd: u64,
|
||||
};
|
||||
|
||||
pub const JSErrorCode = enum(u8) {
|
||||
Error = 0,
|
||||
EvalError = 1,
|
||||
RangeError = 2,
|
||||
ReferenceError = 3,
|
||||
SyntaxError = 4,
|
||||
TypeError = 5,
|
||||
URIError = 6,
|
||||
AggregateError = 7,
|
||||
|
||||
// StackOverflow & OutOfMemoryError is not an ErrorType in <JavaScriptCore/ErrorType.h> within JSC, so the number here is just totally made up
|
||||
OutOfMemoryError = 8,
|
||||
BundlerError = 252,
|
||||
StackOverflow = 253,
|
||||
UserErrorCode = 254,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const JSRuntimeType = enum(u16) {
|
||||
Nothing = 0x0,
|
||||
Function = 0x1,
|
||||
Undefined = 0x2,
|
||||
Null = 0x4,
|
||||
Boolean = 0x8,
|
||||
AnyInt = 0x10,
|
||||
Number = 0x20,
|
||||
String = 0x40,
|
||||
Object = 0x80,
|
||||
Symbol = 0x100,
|
||||
BigInt = 0x200,
|
||||
|
||||
_,
|
||||
};
|
||||
|
||||
pub const ZigStackFrameCode = enum(u8) {
|
||||
None = 0,
|
||||
// 🏃
|
||||
@@ -301,6 +302,49 @@ pub const ZigStackTrace = extern struct {
|
||||
frames_ptr: [*c]ZigStackFrame,
|
||||
frames_len: u8,
|
||||
|
||||
pub fn toAPI(this: *const ZigStackTrace, allocator: *std.mem.Allocator) !Api.StackTrace {
|
||||
var stack_trace: Api.StackTrace = std.mem.zeroes(Api.StackTrace);
|
||||
{
|
||||
var source_lines_iter = this.sourceLineIterator();
|
||||
|
||||
var source_line_len: usize = 0;
|
||||
var count: usize = 0;
|
||||
while (source_lines_iter.next()) |source| {
|
||||
count += 1;
|
||||
source_line_len += source.text.len;
|
||||
}
|
||||
|
||||
if (count > 0 and source_line_len > 0) {
|
||||
var source_lines = try allocator.alloc(Api.SourceLine, count);
|
||||
var source_line_buf = try allocator.alloc(u8, source_line_len);
|
||||
source_lines_iter = this.sourceLineIterator();
|
||||
var remain_buf = source_line_buf[0..];
|
||||
var i: usize = 0;
|
||||
while (source_lines_iter.next()) |source| {
|
||||
std.mem.copy(u8, remain_buf, source.text);
|
||||
const copied_line = remain_buf[0..source.text.len];
|
||||
remain_buf = remain_buf[source.text.len..];
|
||||
source_lines[i] = .{ .text = copied_line, .line = source.line };
|
||||
i += 1;
|
||||
}
|
||||
stack_trace.source_lines = source_lines;
|
||||
}
|
||||
}
|
||||
{
|
||||
var _frames = this.frames();
|
||||
if (_frames.len > 0) {
|
||||
var stack_frames = try allocator.alloc(Api.StackFrame, _frames.len);
|
||||
stack_trace.frames = stack_frames;
|
||||
|
||||
for (_frames) |frame, i| {
|
||||
stack_frames[i] = try frame.toAPI(allocator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stack_trace;
|
||||
}
|
||||
|
||||
pub fn frames(this: *const ZigStackTrace) []const ZigStackFrame {
|
||||
return this.frames_ptr[0..this.frames_len];
|
||||
}
|
||||
@@ -344,6 +388,34 @@ pub const ZigStackTrace = extern struct {
|
||||
};
|
||||
|
||||
pub const ZigStackFrame = extern struct {
|
||||
function_name: ZigString,
|
||||
source_url: ZigString,
|
||||
position: ZigStackFramePosition,
|
||||
code_type: ZigStackFrameCode,
|
||||
|
||||
pub fn toAPI(this: *const ZigStackFrame, allocator: *std.mem.Allocator) !Api.StackFrame {
|
||||
var frame: Api.StackFrame = std.mem.zeroes(Api.StackFrame);
|
||||
if (this.function_name.len > 0) {
|
||||
frame.function_name = try allocator.dupe(u8, this.function_name.slice());
|
||||
}
|
||||
|
||||
if (this.source_url.len > 0) {
|
||||
frame.file = try allocator.dupe(u8, this.source_url.slice());
|
||||
}
|
||||
|
||||
frame.position.source_offset = this.position.source_offset;
|
||||
frame.position.line = this.position.line;
|
||||
frame.position.line_start = this.position.line_start;
|
||||
frame.position.line_stop = this.position.line_stop;
|
||||
frame.position.column_start = this.position.column_start;
|
||||
frame.position.column_stop = this.position.column_stop;
|
||||
frame.position.expression_start = this.position.expression_start;
|
||||
frame.position.expression_stop = this.position.expression_stop;
|
||||
frame.scope = @intToEnum(Api.StackFrameScope, @enumToInt(this.code_type));
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
pub const SourceURLFormatter = struct {
|
||||
source_url: ZigString,
|
||||
position: ZigStackFramePosition,
|
||||
@@ -415,11 +487,6 @@ pub const ZigStackFrame = extern struct {
|
||||
.position = ZigStackFramePosition.Invalid,
|
||||
};
|
||||
|
||||
function_name: ZigString,
|
||||
source_url: ZigString,
|
||||
position: ZigStackFramePosition,
|
||||
code_type: ZigStackFrameCode,
|
||||
|
||||
pub fn nameFormatter(this: *const ZigStackFrame, comptime enable_color: bool) NameFormatter {
|
||||
return NameFormatter{ .function_name = this.function_name, .code_type = this.code_type, .enable_color = enable_color };
|
||||
}
|
||||
@@ -455,10 +522,6 @@ pub const ZigStackFramePosition = extern struct {
|
||||
};
|
||||
|
||||
pub const ZigException = extern struct {
|
||||
pub const shim = Shimmer("Zig", "Exception", @This());
|
||||
pub const name = "ZigException";
|
||||
pub const namespace = shim.namespace;
|
||||
|
||||
code: JSErrorCode,
|
||||
runtime_type: JSRuntimeType,
|
||||
name: ZigString,
|
||||
@@ -467,6 +530,10 @@ pub const ZigException = extern struct {
|
||||
|
||||
exception: ?*c_void,
|
||||
|
||||
pub const shim = Shimmer("Zig", "Exception", @This());
|
||||
pub const name = "ZigException";
|
||||
pub const namespace = shim.namespace;
|
||||
|
||||
pub const Holder = extern struct {
|
||||
const frame_count = 24;
|
||||
const source_lines_count = 6;
|
||||
@@ -529,6 +596,36 @@ pub const ZigException = extern struct {
|
||||
return shim.cppFn("fromException", .{exception});
|
||||
}
|
||||
|
||||
pub fn addToErrorList(this: *ZigException, error_list: *std.ArrayList(Api.JsException)) !void {
|
||||
const _name: string = @field(this, "name").slice();
|
||||
const message: string = @field(this, "message").slice();
|
||||
|
||||
var is_empty = true;
|
||||
var api_exception = Api.JsException{
|
||||
.runtime_type = @enumToInt(this.runtime_type),
|
||||
.code = @enumToInt(this.code),
|
||||
};
|
||||
|
||||
if (_name.len > 0) {
|
||||
api_exception.name = try error_list.allocator.dupe(u8, _name);
|
||||
is_empty = false;
|
||||
}
|
||||
|
||||
if (message.len > 0) {
|
||||
api_exception.message = try error_list.allocator.dupe(u8, message);
|
||||
is_empty = false;
|
||||
}
|
||||
|
||||
if (this.stack.frames_len > 0) {
|
||||
api_exception.stack = try this.stack.toAPI(error_list.allocator);
|
||||
is_empty = false;
|
||||
}
|
||||
|
||||
if (!is_empty) {
|
||||
try error_list.append(api_exception);
|
||||
}
|
||||
}
|
||||
|
||||
pub const Extern = [_][]const u8{"fromException"};
|
||||
};
|
||||
|
||||
@@ -656,7 +753,7 @@ pub const ZigConsoleClient = struct {
|
||||
|
||||
switch (@intToEnum(CellType, value.asCell().getType())) {
|
||||
CellType.ErrorInstanceType => {
|
||||
JS.VirtualMachine.printErrorlikeObject(JS.VirtualMachine.vm, value, null, enable_ansi_colors);
|
||||
JS.VirtualMachine.printErrorlikeObject(JS.VirtualMachine.vm, value, null, null, enable_ansi_colors);
|
||||
return;
|
||||
},
|
||||
|
||||
|
||||
@@ -761,8 +761,10 @@ pub const VirtualMachine = struct {
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
||||
// This double prints
|
||||
pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue {
|
||||
VirtualMachine.vm.defaultErrorHandler(promise.result(global.vm()));
|
||||
// VirtualMachine.vm.defaultErrorHandler(promise.result(global.vm()), null);
|
||||
return JSValue.jsUndefined();
|
||||
}
|
||||
|
||||
@@ -854,30 +856,52 @@ pub const VirtualMachine = struct {
|
||||
// TODO:
|
||||
pub fn deinit(this: *VirtualMachine) void {}
|
||||
|
||||
pub fn printException(this: *VirtualMachine, exception: *Exception) void {
|
||||
pub const ExceptionList = std.ArrayList(Api.JsException);
|
||||
|
||||
pub fn printException(this: *VirtualMachine, exception: *Exception, exception_list: ?*ExceptionList) void {
|
||||
if (Output.enable_ansi_colors) {
|
||||
this.printErrorlikeObject(exception.value(), exception, true);
|
||||
this.printErrorlikeObject(exception.value(), exception, exception_list, true);
|
||||
} else {
|
||||
this.printErrorlikeObject(exception.value(), exception, false);
|
||||
this.printErrorlikeObject(exception.value(), exception, exception_list, false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn defaultErrorHandler(this: *VirtualMachine, result: JSValue) void {
|
||||
pub fn defaultErrorHandler(this: *VirtualMachine, result: JSValue, exception_list: ?*ExceptionList) void {
|
||||
if (result.isException(this.global.vm())) {
|
||||
var exception = @ptrCast(*Exception, result.asVoid());
|
||||
|
||||
this.printException(exception);
|
||||
this.printException(exception, exception_list);
|
||||
} else if (Output.enable_ansi_colors) {
|
||||
this.printErrorlikeObject(result, null, true);
|
||||
this.printErrorlikeObject(result, null, exception_list, true);
|
||||
} else {
|
||||
this.printErrorlikeObject(result, null, false);
|
||||
this.printErrorlikeObject(result, null, exception_list, false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn loadEntryPoint(this: *VirtualMachine, entry_path: string) !*JSInternalPromise {
|
||||
try this.entry_point.generate(@TypeOf(this.bundler), &this.bundler, Fs.PathName.init(entry_path), main_file_name);
|
||||
this.main = entry_path;
|
||||
var promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(std.mem.span(main_file_name)));
|
||||
|
||||
var promise: *JSInternalPromise = undefined;
|
||||
// We first import the node_modules bundle. This prevents any potential TDZ issues.
|
||||
// The contents of the node_modules bundle are lazy, so hopefully this should be pretty quick.
|
||||
if (this.node_modules != null) {
|
||||
promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(std.mem.span(vm.bundler.linker.nodeModuleBundleImportPath())));
|
||||
|
||||
this.global.vm().drainMicrotasks();
|
||||
|
||||
while (promise.status(this.global.vm()) == JSPromise.Status.Pending) {
|
||||
this.global.vm().drainMicrotasks();
|
||||
}
|
||||
|
||||
if (promise.status(this.global.vm()) == JSPromise.Status.Rejected) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
_ = promise.result(this.global.vm());
|
||||
}
|
||||
|
||||
promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(std.mem.span(main_file_name)));
|
||||
|
||||
this.global.vm().drainMicrotasks();
|
||||
|
||||
@@ -896,14 +920,14 @@ pub const VirtualMachine = struct {
|
||||
// In that case, this function becomes recursive.
|
||||
// In all other cases, we will convert it to a ZigException.
|
||||
const errors_property = ZigString.init("errors");
|
||||
pub fn printErrorlikeObject(this: *VirtualMachine, value: JSValue, exception: ?*Exception, comptime allow_ansi_color: bool) void {
|
||||
pub fn printErrorlikeObject(this: *VirtualMachine, value: JSValue, exception: ?*Exception, exception_list: ?*ExceptionList, comptime allow_ansi_color: bool) void {
|
||||
var was_internal = false;
|
||||
|
||||
defer {
|
||||
if (was_internal) {
|
||||
if (exception) |exception_| {
|
||||
var holder = ZigException.Holder.init();
|
||||
var zig_exception = holder.zigException();
|
||||
var zig_exception: *ZigException = holder.zigException();
|
||||
exception_.getStackTrace(&zig_exception.stack);
|
||||
if (zig_exception.stack.frames_len > 0) {
|
||||
var buffered_writer = std.io.bufferedWriter(Output.errorWriter());
|
||||
@@ -917,12 +941,17 @@ pub const VirtualMachine = struct {
|
||||
|
||||
buffered_writer.flush() catch {};
|
||||
}
|
||||
|
||||
if (exception_list) |list| {
|
||||
zig_exception.addToErrorList(list) catch {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value.isAggregateError(this.global)) {
|
||||
const AggregateErrorIterator = struct {
|
||||
pub var current_exception_list: ?*ExceptionList = null;
|
||||
pub fn iteratorWithColor(_vm: [*c]VM, globalObject: [*c]JSGlobalObject, nextValue: JSValue) callconv(.C) void {
|
||||
iterator(_vm, globalObject, nextValue, true);
|
||||
}
|
||||
@@ -930,9 +959,11 @@ pub const VirtualMachine = struct {
|
||||
iterator(_vm, globalObject, nextValue, false);
|
||||
}
|
||||
inline fn iterator(_vm: [*c]VM, globalObject: [*c]JSGlobalObject, nextValue: JSValue, comptime color: bool) void {
|
||||
VirtualMachine.vm.printErrorlikeObject(nextValue, null, color);
|
||||
VirtualMachine.vm.printErrorlikeObject(nextValue, null, current_exception_list, color);
|
||||
}
|
||||
};
|
||||
AggregateErrorIterator.current_exception_list = exception_list;
|
||||
defer AggregateErrorIterator.current_exception_list = null;
|
||||
if (comptime allow_ansi_color) {
|
||||
value.getErrorsProperty(this.global).forEach(this.global, AggregateErrorIterator.iteratorWithColor);
|
||||
} else {
|
||||
@@ -943,34 +974,51 @@ pub const VirtualMachine = struct {
|
||||
|
||||
if (js.JSValueIsObject(vm.global.ref(), value.asRef())) {
|
||||
if (js.JSObjectGetPrivate(value.asRef())) |priv| {
|
||||
was_internal = this.printErrorFromMaybePrivateData(priv, allow_ansi_color);
|
||||
was_internal = this.printErrorFromMaybePrivateData(priv, exception_list, allow_ansi_color);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
was_internal = this.printErrorFromMaybePrivateData(value.asRef(), allow_ansi_color);
|
||||
was_internal = this.printErrorFromMaybePrivateData(value.asRef(), exception_list, allow_ansi_color);
|
||||
}
|
||||
|
||||
pub fn printErrorFromMaybePrivateData(this: *VirtualMachine, value: ?*c_void, comptime allow_ansi_color: bool) bool {
|
||||
pub fn printErrorFromMaybePrivateData(this: *VirtualMachine, value: ?*c_void, exception_list: ?*ExceptionList, comptime allow_ansi_color: bool) bool {
|
||||
const private_data_ptr = JSPrivateDataPtr.from(value);
|
||||
|
||||
switch (private_data_ptr.tag()) {
|
||||
.BuildError => {
|
||||
defer Output.flush();
|
||||
const build_error = private_data_ptr.as(BuildError);
|
||||
var writer = Output.errorWriter();
|
||||
build_error.msg.formatWriter(@TypeOf(writer), writer, allow_ansi_color) catch {};
|
||||
var build_error = private_data_ptr.as(BuildError);
|
||||
if (!build_error.logged) {
|
||||
var writer = Output.errorWriter();
|
||||
build_error.msg.formatWriter(@TypeOf(writer), writer, allow_ansi_color) catch {};
|
||||
build_error.logged = true;
|
||||
}
|
||||
if (exception_list != null) {
|
||||
this.log.addMsg(
|
||||
build_error.msg,
|
||||
) catch {};
|
||||
}
|
||||
return true;
|
||||
},
|
||||
.ResolveError => {
|
||||
defer Output.flush();
|
||||
const resolve_error = private_data_ptr.as(ResolveError);
|
||||
var writer = Output.errorWriter();
|
||||
resolve_error.msg.formatWriter(@TypeOf(writer), writer, allow_ansi_color) catch {};
|
||||
var resolve_error = private_data_ptr.as(ResolveError);
|
||||
if (!resolve_error.logged) {
|
||||
var writer = Output.errorWriter();
|
||||
resolve_error.msg.formatWriter(@TypeOf(writer), writer, allow_ansi_color) catch {};
|
||||
resolve_error.logged = true;
|
||||
}
|
||||
|
||||
if (exception_list != null) {
|
||||
this.log.addMsg(
|
||||
resolve_error.msg,
|
||||
) catch {};
|
||||
}
|
||||
return true;
|
||||
},
|
||||
else => {
|
||||
this.printErrorInstance(@intToEnum(JSValue, @intCast(i64, (@ptrToInt(value)))), allow_ansi_color) catch |err| {
|
||||
this.printErrorInstance(@intToEnum(JSValue, @intCast(i64, (@ptrToInt(value)))), exception_list, allow_ansi_color) catch |err| {
|
||||
if (comptime isDebug) {
|
||||
// yo dawg
|
||||
Output.printErrorln("Error while printing Error-like object: {s}", .{@errorName(err)});
|
||||
@@ -1053,10 +1101,13 @@ pub const VirtualMachine = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn printErrorInstance(this: *VirtualMachine, error_instance: JSValue, comptime allow_ansi_color: bool) !void {
|
||||
pub fn printErrorInstance(this: *VirtualMachine, error_instance: JSValue, exception_list: ?*ExceptionList, comptime allow_ansi_color: bool) !void {
|
||||
var exception_holder = ZigException.Holder.init();
|
||||
var exception = exception_holder.zigException();
|
||||
error_instance.toZigException(vm.global, exception);
|
||||
if (exception_list) |list| {
|
||||
try exception.addToErrorList(list);
|
||||
}
|
||||
|
||||
var stderr: std.fs.File = Output.errorStream();
|
||||
var buffered = std.io.bufferedWriter(stderr.writer());
|
||||
@@ -1223,40 +1274,36 @@ pub const EventListenerMixin = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn emitFetchEventError(
|
||||
request: *http.RequestContext,
|
||||
comptime fmt: string,
|
||||
args: anytype,
|
||||
) void {
|
||||
Output.prettyErrorln(fmt, args);
|
||||
request.sendInternalError(error.FetchEventError) catch {};
|
||||
}
|
||||
|
||||
pub fn emitFetchEvent(
|
||||
vm: *VirtualMachine,
|
||||
request_context: *http.RequestContext,
|
||||
comptime CtxType: type,
|
||||
ctx: *CtxType,
|
||||
comptime onError: fn (ctx: *CtxType, err: anyerror, value: JSValue, request_ctx: *http.RequestContext) anyerror!void,
|
||||
) !void {
|
||||
var listeners = vm.event_listeners.get(EventType.fetch) orelse return emitFetchEventError(
|
||||
request_context,
|
||||
"Missing \"fetch\" handler. Did you run \"addEventListener(\"fetch\", (event) => {{}})\"?",
|
||||
.{},
|
||||
);
|
||||
if (listeners.items.len == 0) return emitFetchEventError(
|
||||
request_context,
|
||||
"Missing \"fetch\" handler. Did you run \"addEventListener(\"fetch\", (event) => {{}})\"?",
|
||||
.{},
|
||||
);
|
||||
var listeners = vm.event_listeners.get(EventType.fetch) orelse (return onError(ctx, error.NoListeners, JSValue.jsUndefined(), request_context) catch {});
|
||||
if (listeners.items.len == 0) return onError(ctx, error.NoListeners, JSValue.jsUndefined(), request_context) catch {};
|
||||
const FetchEventRejectionHandler = struct {
|
||||
pub fn onRejection(_ctx: *c_void, err: anyerror, fetch_event: *FetchEvent, value: JSValue) void {
|
||||
onError(
|
||||
@intToPtr(*CtxType, @ptrToInt(_ctx)),
|
||||
err,
|
||||
value,
|
||||
fetch_event.request_context,
|
||||
) catch {};
|
||||
}
|
||||
};
|
||||
|
||||
// Rely on JS finalizer
|
||||
var fetch_event = try vm.allocator.create(FetchEvent);
|
||||
fetch_event.* = FetchEvent{
|
||||
.request_context = request_context,
|
||||
.request = Request{ .request_context = request_context },
|
||||
.onPromiseRejectionCtx = @as(*c_void, ctx),
|
||||
.onPromiseRejectionHandler = FetchEventRejectionHandler.onRejection,
|
||||
};
|
||||
|
||||
var fetch_args: [1]js.JSObjectRef = undefined;
|
||||
var exception: ?*Exception = null;
|
||||
const failed_str = "Failed";
|
||||
for (listeners.items) |listener_ref| {
|
||||
var listener = @intToEnum(JSValue, @intCast(i64, @ptrToInt(listener_ref)));
|
||||
|
||||
@@ -1266,19 +1313,11 @@ pub const EventListenerMixin = struct {
|
||||
var promise = JSPromise.resolvedPromise(vm.global, result);
|
||||
vm.global.vm().drainMicrotasks();
|
||||
|
||||
if (fetch_event.rejected) return;
|
||||
|
||||
if (promise.status(vm.global.vm()) == .Rejected) {
|
||||
if (exception == null) {
|
||||
var res = promise.result(vm.global.vm());
|
||||
if (res.isException(vm.global.vm())) {
|
||||
exception = @ptrCast(*Exception, res.asVoid());
|
||||
} else {
|
||||
vm.defaultErrorHandler(res);
|
||||
if (!request_context.has_called_done) {
|
||||
request_context.sendInternalError(error.JavaScriptErrorNeedARealErrorPageSorryAboutThisSeeTheTerminal) catch {};
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
onError(ctx, error.JSError, promise.result(vm.global.vm()), request_context) catch {};
|
||||
return;
|
||||
} else {
|
||||
_ = promise.result(vm.global.vm());
|
||||
}
|
||||
@@ -1290,21 +1329,9 @@ pub const EventListenerMixin = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (exception) |except| {
|
||||
vm.printException(except);
|
||||
|
||||
if (!request_context.has_called_done) {
|
||||
request_context.sendInternalError(error.JavaScriptErrorNeedARealErrorPageSorryAboutThisSeeTheTerminal) catch {};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!request_context.has_called_done) {
|
||||
return emitFetchEventError(
|
||||
request_context,
|
||||
"\"fetch\" handler never called event.respondWith()",
|
||||
.{},
|
||||
);
|
||||
onError(ctx, error.FetchHandlerRespondWithNeverCalled, JSValue.jsUndefined(), request_context) catch {};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1368,6 +1395,7 @@ pub const ResolveError = struct {
|
||||
msg: logger.Msg,
|
||||
allocator: *std.mem.Allocator,
|
||||
referrer: ?Fs.Path = null,
|
||||
logged: bool = false,
|
||||
|
||||
pub fn fmt(allocator: *std.mem.Allocator, specifier: string, referrer: string, err: anyerror) !string {
|
||||
switch (err) {
|
||||
@@ -1515,6 +1543,7 @@ pub const BuildError = struct {
|
||||
msg: logger.Msg,
|
||||
// resolve_result: Resolver.Result,
|
||||
allocator: *std.mem.Allocator,
|
||||
logged: bool = false,
|
||||
|
||||
pub const Class = NewClass(
|
||||
BuildError,
|
||||
|
||||
@@ -1009,6 +1009,10 @@ pub const FetchEvent = struct {
|
||||
request_context: *http.RequestContext,
|
||||
request: Request,
|
||||
|
||||
onPromiseRejectionCtx: *c_void = undefined,
|
||||
onPromiseRejectionHandler: ?fn (ctx: *c_void, err: anyerror, fetch_event: *FetchEvent, value: JSValue) void = null,
|
||||
rejected: bool = false,
|
||||
|
||||
pub const Class = NewClass(
|
||||
FetchEvent,
|
||||
.{
|
||||
@@ -1101,8 +1105,13 @@ pub const FetchEvent = struct {
|
||||
switch (status) {
|
||||
.Fulfilled => {},
|
||||
else => {
|
||||
VirtualMachine.vm.defaultErrorHandler(resolved.result(VirtualMachine.vm.global.vm()));
|
||||
this.request_context.sendInternalError(error.rejectedPromiseSeeConsole) catch {};
|
||||
this.rejected = true;
|
||||
this.onPromiseRejectionHandler.?(
|
||||
this.onPromiseRejectionCtx,
|
||||
error.PromiseRejection,
|
||||
this,
|
||||
resolved.result(VirtualMachine.vm.global.vm()),
|
||||
);
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
},
|
||||
}
|
||||
@@ -1110,14 +1119,16 @@ pub const FetchEvent = struct {
|
||||
var arg = resolved.result(VirtualMachine.vm.global.vm()).asObjectRef();
|
||||
|
||||
if (!js.JSValueIsObjectOfClass(ctx, arg, Response.Class.ref)) {
|
||||
this.rejected = true;
|
||||
JSError(getAllocator(ctx), "event.respondWith() must be a Response or a Promise<Response>.", .{}, ctx, exception);
|
||||
this.request_context.sendInternalError(error.respondWithWasEmpty) catch {};
|
||||
this.onPromiseRejectionHandler.?(this.onPromiseRejectionCtx, error.RespondWithInvalidType, this, JSValue.fromRef(exception.*));
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
var response: *Response = GetJSPrivateData(Response, arg) orelse {
|
||||
this.rejected = true;
|
||||
JSError(getAllocator(ctx), "event.respondWith()'s Response object was invalid. This may be an internal error.", .{}, ctx, exception);
|
||||
this.request_context.sendInternalError(error.respondWithWasInvalid) catch {};
|
||||
this.onPromiseRejectionHandler.?(this.onPromiseRejectionCtx, error.RespondWithInvalidTypeInternal, this, JSValue.fromRef(exception.*));
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user