aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/javascript/jsc/api/server.zig40
-rw-r--r--src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h10
-rw-r--r--src/javascript/jsc/bindings/bindings-generator.zig6
-rw-r--r--src/javascript/jsc/bindings/bindings.cpp40
-rw-r--r--src/javascript/jsc/bindings/bindings.zig116
-rw-r--r--src/javascript/jsc/bindings/exports.zig18
-rw-r--r--src/javascript/jsc/bindings/header-gen.zig138
-rw-r--r--src/javascript/jsc/bindings/headers.h40
-rw-r--r--src/javascript/jsc/bindings/headers.zig6
-rw-r--r--src/javascript/jsc/bindings/shimmer.zig31
-rw-r--r--src/javascript/jsc/bindings/webcore/WebSocket.cpp105
11 files changed, 413 insertions, 137 deletions
diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig
index bec079e90..9a9628094 100644
--- a/src/javascript/jsc/api/server.zig
+++ b/src/javascript/jsc/api/server.zig
@@ -505,6 +505,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
pub threadlocal var pool_allocator: std.mem.Allocator = undefined;
pub const RequestContextStackAllocator = NewRequestContextStackAllocator(RequestContext, 2048);
+ pub const name = "HTTPRequestContext" ++ (if (debug_mode) "Debug" else "") ++ (if (ThisServer.ssl_enabled) "TLS" else "");
+ pub const shim = JSC.Shimmer("Bun", name, @This());
server: *ThisServer,
resp: *App.Response,
@@ -542,6 +544,15 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
// TODO: support builtin compression
const can_sendfile = !ssl_enabled;
+ pub const thenables = shim.thenables(.{
+ PromiseHandler,
+ });
+
+ pub const lazy_static_functions = thenables;
+ pub const Export = lazy_static_functions;
+
+ const PromiseHandler = JSC.Thenable(RequestContext, onResolve, onReject);
+
pub fn setAbortHandler(this: *RequestContext) void {
if (this.has_abort_handler) return;
this.has_abort_handler = true;
@@ -1196,6 +1207,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
value: JSC.JSValue,
status: u16,
) void {
+ JSC.markBinding();
if (this.resp.hasResponded()) return;
var exception_list: std.ArrayList(Api.JsException) = std.ArrayList(Api.JsException).init(this.allocator);
@@ -1399,12 +1411,23 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
pub fn onPullCallback(this: *anyopaque) void {
onPull(bun.cast(*RequestContext, this));
}
+
+ comptime {
+ if (!JSC.is_bindgen) {
+ @export(PromiseHandler.resolve, .{
+ .name = Export[0].symbol_name,
+ });
+ @export(PromiseHandler.reject, .{
+ .name = Export[1].symbol_name,
+ });
+ }
+ }
};
}
pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
return struct {
- const ssl_enabled = ssl_enabled_;
+ pub const ssl_enabled = ssl_enabled_;
const debug_mode = debug_mode_;
const ThisServer = @This();
@@ -1627,7 +1650,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
}
pub fn onBunInfoRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void {
- if (comptime JSC.is_bindgen) return undefined;
+ JSC.markBinding();
this.pending_requests += 1;
defer this.pending_requests -= 1;
req.setYield(false);
@@ -1654,7 +1677,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
}
pub fn onSrcRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void {
- if (comptime JSC.is_bindgen) return undefined;
+ JSC.markBinding();
this.pending_requests += 1;
defer this.pending_requests -= 1;
req.setYield(false);
@@ -1684,7 +1707,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
}
pub fn onRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void {
- if (comptime JSC.is_bindgen) return undefined;
+ JSC.markBinding();
this.pending_requests += 1;
var vm = this.vm;
req.setYield(false);
@@ -1768,13 +1791,8 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
if (wait_for_promise) {
ctx.setAbortHandler();
- response_value.then(
- this.globalThis,
- RequestContext,
- ctx,
- RequestContext.onResolve,
- RequestContext.onReject,
- );
+
+ RequestContext.PromiseHandler.then(ctx, response_value, this.globalThis);
return;
}
diff --git a/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h b/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h
index d533abeec..c52f65d85 100644
--- a/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h
+++ b/src/javascript/jsc/bindings/WebCoreJSBuiltinInternals.h
@@ -1,7 +1,5 @@
//clang-format off
-namespace Zig {
-class GlobalObject;
-}
+namespace Zig { class GlobalObject; }
/*
* Copyright (c) 2015 Igalia
* Copyright (c) 2015 Igalia S.L.
@@ -10,7 +8,7 @@ class GlobalObject;
* Copyright (c) 2015, 2016, 2017 Canon Inc.
* Copyright (c) 2016, 2020 Apple Inc. All rights reserved.
* Copyright (c) 2022 Codeblog Corp. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -19,7 +17,7 @@ class GlobalObject;
* 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
@@ -31,7 +29,7 @@ class GlobalObject;
* 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.
- *
+ *
*/
// DO NOT EDIT THIS FILE. It is automatically generated from JavaScript files for
diff --git a/src/javascript/jsc/bindings/bindings-generator.zig b/src/javascript/jsc/bindings/bindings-generator.zig
index 4e44fb9c0..a828c5f9e 100644
--- a/src/javascript/jsc/bindings/bindings-generator.zig
+++ b/src/javascript/jsc/bindings/bindings-generator.zig
@@ -25,16 +25,20 @@ pub fn main() anyerror!void {
{
const paths = [_][]const u8{ std.fs.path.dirname(src.file) orelse return error.BadPath, "headers.h" };
const paths2 = [_][]const u8{ std.fs.path.dirname(src.file) orelse return error.BadPath, "headers-cpp.h" };
+ const paths3 = [_][]const u8{ std.fs.path.dirname(src.file) orelse return error.BadPath, "ZigLazyStaticFunctions.h" };
+ const paths4 = [_][]const u8{ std.fs.path.dirname(src.file) orelse return error.BadPath, "ZigLazyStaticFunctions-inlines.h" };
const cpp = try std.fs.createFileAbsolute(try std.fs.path.join(allocator, &paths2), .{});
const file = try std.fs.createFileAbsolute(try std.fs.path.join(allocator, &paths), .{});
+ const static = try std.fs.createFileAbsolute(try std.fs.path.join(allocator, &paths3), .{});
+ const staticInlines = try std.fs.createFileAbsolute(try std.fs.path.join(allocator, &paths4), .{});
const HeaderGenerator = HeaderGen(
Bindings,
Exports,
"src/javascript/jsc/bindings/bindings.zig",
);
- HeaderGenerator.exec(HeaderGenerator{}, file, cpp);
+ HeaderGenerator.exec(HeaderGenerator{}, file, cpp, static, staticInlines);
}
// TODO: finish this
const use_cpp_generator = false;
diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp
index a8770005a..69d836754 100644
--- a/src/javascript/jsc/bindings/bindings.cpp
+++ b/src/javascript/jsc/bindings/bindings.cpp
@@ -87,39 +87,18 @@ static void copyToUWS(WebCore::FetchHeaders* headers, UWSResponse* res)
}
template<typename PromiseType, bool isInternal>
-static void handlePromise(PromiseType* promise, JSC__JSGlobalObject* globalObject, void* ctx, void (*ArgFn3)(JSC__JSGlobalObject* arg0, void* arg1, void** arg2, size_t arg3), void (*ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, void** arg2, size_t arg3))
+static void handlePromise(PromiseType* promise, JSC__JSGlobalObject* globalObject, void* ctx, void (*ArgFn3)(void*, JSC__JSGlobalObject* arg0, JSC__CallFrame* callFrame), void (*ArgFn4)(void*, JSC__JSGlobalObject* arg0, JSC__CallFrame* callFrame))
{
- JSC::Strong<PromiseType> strongValue = { globalObject->vm(), promise };
- JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create(
- globalObject->vm(), globalObject, 1, String(), [&strongValue, ctx, ArgFn3](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> const JSC::EncodedJSValue {
- auto argCount = static_cast<uint16_t>(callFrame->argumentCount());
-
- WTF::Vector<JSC::EncodedJSValue, 16> arguments;
- arguments.reserveInitialCapacity(argCount);
- if (argCount) {
- for (uint16_t i = 0; i < argCount; ++i) {
- arguments.uncheckedAppend(JSC::JSValue::encode(callFrame->uncheckedArgument(i)));
- }
- }
- ArgFn3(globalObject, ctx, reinterpret_cast<void**>(arguments.data()), argCount);
- strongValue.clear();
+ JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create(
+ globalObject->vm(), globalObject, 1, String(), [ctx, ArgFn3](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> const JSC::EncodedJSValue {
+ ArgFn3(ctx, globalObject, callFrame);
return JSC::JSValue::encode(JSC::jsUndefined());
});
JSC::JSNativeStdFunction* rejecterFunction = JSC::JSNativeStdFunction::create(
globalObject->vm(), globalObject, 1, String(),
- [&strongValue, ctx, ArgFn4](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> JSC::EncodedJSValue {
- auto argCount = static_cast<uint16_t>(callFrame->argumentCount());
- WTF::Vector<JSC::EncodedJSValue, 16> arguments;
- arguments.reserveInitialCapacity(argCount);
- if (argCount) {
- for (uint16_t i = 0; i < argCount; ++i) {
- arguments.uncheckedAppend(JSC::JSValue::encode(callFrame->uncheckedArgument(i)));
- }
- }
-
- ArgFn4(globalObject, ctx, reinterpret_cast<void**>(arguments.data()), argCount);
- strongValue.clear();
+ [ctx, ArgFn4](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> JSC::EncodedJSValue {
+ ArgFn4(ctx, globalObject, callFrame);
return JSC::JSValue::encode(JSC::jsUndefined());
});
@@ -537,7 +516,7 @@ JSC__JSPromise* JSC__JSPromise__create(JSC__JSGlobalObject* arg0)
}
// TODO: prevent this from allocating so much memory
-void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* ctx, void (*ArgFn3)(JSC__JSGlobalObject* arg0, void* arg1, void** arg2, size_t arg3), void (*ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, void** arg2, size_t arg3))
+void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* ctx, void (*ArgFn3)(void*, JSC__JSGlobalObject* arg0, JSC__CallFrame* callFrame), void (*ArgFn4)(void*, JSC__JSGlobalObject* arg0, JSC__CallFrame* callFrame))
{
auto* cell = JSC::JSValue::decode(JSValue0).asCell();
@@ -624,8 +603,9 @@ JSC__JSInternalPromise* JSC__VM__reloadModule(JSC__VM* vm, JSC__JSGlobalObject*
bool JSC__JSValue__isSameValue(JSC__JSValue JSValue0, JSC__JSValue JSValue1,
JSC__JSGlobalObject* globalObject)
{
- return JSC::sameValue(globalObject, JSC::JSValue::decode(JSValue0),
- JSC::JSValue::decode(JSValue1));
+ JSC::JSValue left = JSC::JSValue::decode(JSValue0);
+ JSC::JSValue right = JSC::JSValue::decode(JSValue1);
+ return JSC::sameValue(globalObject, left, right);
}
// This is the same as the C API version, except it returns a JSValue which may be a *Exception
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig
index 1b6524826..a2757fc62 100644
--- a/src/javascript/jsc/bindings/bindings.zig
+++ b/src/javascript/jsc/bindings/bindings.zig
@@ -214,9 +214,12 @@ pub const ZigString = extern struct {
return from16(slice_.ptr, slice_.len);
}
+ /// Globally-allocated memory only
pub fn from16(slice_: [*]const u16, len: usize) ZigString {
var str = init(@ptrCast([*]const u8, slice_)[0..len]);
str.markUTF16();
+ str.mark();
+ str.assertGlobal();
return str;
}
@@ -350,7 +353,7 @@ pub const ZigString = extern struct {
}
pub fn trimmedSlice(this: *const ZigString) []const u8 {
- return strings.trim(this.ptr[0..@minimum(this.len, std.math.maxInt(u32))], " \r\n");
+ return strings.trim(this.full(), " \r\n");
}
pub fn toValueAuto(this: *const ZigString, global: *JSGlobalObject) JSValue {
@@ -361,11 +364,27 @@ pub const ZigString = extern struct {
}
}
+ fn assertGlobalIfNeeded(this: *const ZigString) void {
+ if (comptime bun.Environment.allow_assert) {
+ if (this.isGloballyAllocated()) {
+ this.assertGlobal();
+ }
+ }
+ }
+
+ fn assertGlobal(this: *const ZigString) void {
+ if (comptime bun.Environment.allow_assert) {
+ std.debug.assert(bun.Global.Mimalloc.mi_is_in_heap_region(untagged(this.ptr)) or bun.Global.Mimalloc.mi_check_owned(untagged(this.ptr)));
+ }
+ }
+
pub fn toValue(this: *const ZigString, global: *JSGlobalObject) JSValue {
+ this.assertGlobalIfNeeded();
return shim.cppFn("toValue", .{ this, global });
}
pub fn toExternalValue(this: *const ZigString, global: *JSGlobalObject) JSValue {
+ this.assertGlobal();
return shim.cppFn("toExternalValue", .{ this, global });
}
@@ -387,6 +406,7 @@ pub const ZigString = extern struct {
}
pub fn to16BitValue(this: *const ZigString, global: *JSGlobalObject) JSValue {
+ this.assertGlobal();
return shim.cppFn("to16BitValue", .{ this, global });
}
@@ -406,9 +426,9 @@ pub const ZigString = extern struct {
}
return if (this.is16Bit())
- C_API.JSStringCreateWithCharactersNoCopy(@ptrCast([*]const u16, @alignCast(@alignOf([*]const u16), this.ptr)), this.len)
+ C_API.JSStringCreateWithCharactersNoCopy(@ptrCast([*]const u16, @alignCast(@alignOf([*]const u16), untagged(this.ptr))), this.len)
else
- C_API.JSStringCreateStatic(this.ptr, this.len);
+ C_API.JSStringCreateStatic(untagged(this.ptr), this.len);
}
pub fn toErrorInstance(this: *const ZigString, global: *JSGlobalObject) JSValue {
@@ -1429,6 +1449,8 @@ pub const SourceCode = extern struct {
};
};
+pub const Thenables = opaque {};
+
pub const JSFunction = extern struct {
pub const shim = Shimmer("JSC", "JSFunction", @This());
bytes: shim.Bytes,
@@ -1720,6 +1742,8 @@ fn _WTF(comptime str: []const u8) type {
return opaque {};
}
}
+pub const JSNativeFn = fn (*JSGlobalObject, *JSC.CallFrame) callconv(.C) JSValue;
+pub const JSNativeFnWithCtx = fn (?*anyopaque, [*c]JSGlobalObject, ?*JSC.CallFrame) callconv(.C) void;
pub const URL = extern struct {
pub const shim = Shimmer("WTF", "URL", @This());
@@ -1939,13 +1963,17 @@ pub const String = extern struct {
};
};
-pub const JSValue = enum(i64) {
- @"undefined" = 0xa,
+pub const JSValueReprInt = i64;
+pub const JSValue = enum(JSValueReprInt) {
+ zero = 0,
+ @"undefined" = @bitCast(JSValueReprInt, @as(i64, 0xa)),
_,
+ pub const Type = JSValueReprInt;
+
pub const shim = Shimmer("JSC", "JSValue", @This());
pub const is_pointer = false;
- pub const Type = i64;
+
const cppFn = shim.cppFn;
pub const Encoded = extern union {
@@ -1959,7 +1987,6 @@ pub const JSValue = enum(i64) {
pub const include = "JavaScriptCore/JSValue.h";
pub const name = "JSC::JSValue";
pub const namespace = "JSC";
- pub const zero = @intToEnum(JSValue, @as(i64, 0));
pub const JSType = enum(u8) {
// The Cell value must come before any JS that is a JSCell.
Cell,
@@ -2200,16 +2227,15 @@ pub const JSValue = enum(i64) {
?*JSInternalPromise => asInternalPromise(this),
?*JSPromise => asPromise(this),
- u52 => @truncate(u52, this.to(u64)),
+ u52 => @truncate(u52, @intCast(u64, @maximum(this.toInt64(), 0))),
- u64 => @intCast(u64, @maximum(toInt64(this), 0)),
+ u64 => toUInt64NoTruncate(this),
u8 => @truncate(u8, toU32(this)),
i16 => @truncate(i16, toInt32(this)),
i8 => @truncate(i8, toInt32(this)),
i32 => @truncate(i32, toInt32(this)),
- // TODO: BigInt64
i64 => this.toInt64(),
bool => this.toBoolean(),
@@ -2693,44 +2719,12 @@ pub const JSValue = enum(i64) {
return cppFn("symbolKeyFor", .{ this, global, str });
}
- const Thenable = fn (
- global: [*c]JSGlobalObject,
- ctx: ?*anyopaque,
- arguments_ptr: [*c]*anyopaque,
- arguments_len: usize,
- ) callconv(.C) void;
- pub fn _then(this: JSValue, global: *JSGlobalObject, ctx: ?*anyopaque, resolve: Thenable, reject: Thenable) void {
+ pub fn _then(this: JSValue, global: *JSGlobalObject, ctx: ?*anyopaque, resolve: JSNativeFnWithCtx, reject: JSNativeFnWithCtx) void {
return cppFn("_then", .{ this, global, ctx, resolve, reject });
}
- pub fn then(this: JSValue, global: *JSGlobalObject, comptime Then: type, ctx: *Then, comptime onResolve: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void, comptime onReject: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void) void {
- const Handler = struct {
- fn resolve(
- globalThis: [*c]JSGlobalObject,
- ptr: ?*anyopaque,
- arguments_ptr: [*c]*anyopaque,
- arguments_len: usize,
- ) callconv(.C) void {
- @setRuntimeSafety(false);
- onResolve(bun.cast(*Then, ptr.?), globalThis, @ptrCast([*]const JSC.JSValue, arguments_ptr)[0..arguments_len]);
- }
- pub fn reject(
- globalThis: [*c]JSGlobalObject,
- ptr: ?*anyopaque,
- arguments_ptr: [*c]*anyopaque,
- arguments_len: usize,
- ) callconv(.C) void {
- @setRuntimeSafety(false);
- onReject(bun.cast(*Then, ptr.?), globalThis, @ptrCast([*]const JSC.JSValue, arguments_ptr)[0..arguments_len]);
- }
- };
-
- this._then(
- global,
- ctx,
- Handler.resolve,
- Handler.reject,
- );
+ pub fn then(this: JSValue, global: *JSGlobalObject, comptime Then: type, ctx: *Then, comptime onResolve: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void, comptime onReject: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void) void {
+ Thenable(Then, onResolve, onReject).then(this, global, ctx);
}
pub fn getDescription(this: JSValue, global: *JSGlobalObject) ZigString {
@@ -2846,7 +2840,7 @@ pub const JSValue = enum(i64) {
}
pub fn asBoolean(this: JSValue) bool {
- return @enumToInt(this) == @bitCast(c_longlong, @as(c_longlong, (@as(c_int, 2) | @as(c_int, 4)) | @as(c_int, 1)));
+ return FFI.JSVALUE_TO_BOOL(.{ .asJSValue = this });
}
pub fn toInt32(this: JSValue) i32 {
@@ -2864,11 +2858,11 @@ pub const JSValue = enum(i64) {
}
pub fn asInt32(this: JSValue) i32 {
- return @bitCast(i32, @truncate(c_int, @enumToInt(this)));
+ return FFI.JSVALUE_TO_INT32(.{ .asJSValue = this });
}
pub inline fn toU16(this: JSValue) u16 {
- return @intCast(u16, this.toInt32());
+ return @truncate(u16, this.toU32());
}
pub inline fn toU32(this: JSValue) u32 {
@@ -3651,3 +3645,29 @@ pub const WTF = struct {
pub const Callback = struct {
// zig: Value,
};
+
+pub fn Thenable(comptime Then: type, comptime onResolve: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void, comptime onReject: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void) type {
+ return struct {
+ pub fn resolve(
+ ctx: ?*anyopaque,
+ globalThis: [*c]JSGlobalObject,
+ callframe: ?*JSC.CallFrame,
+ ) callconv(.C) void {
+ @setRuntimeSafety(false);
+ onResolve(@ptrCast(*Then, @alignCast(std.meta.alignment(Then), ctx.?)), globalThis, callframe.?.arguments());
+ }
+
+ pub fn reject(
+ ctx: ?*anyopaque,
+ globalThis: [*c]JSGlobalObject,
+ callframe: ?*JSC.CallFrame,
+ ) callconv(.C) void {
+ @setRuntimeSafety(false);
+ onReject(@ptrCast(*Then, @alignCast(std.meta.alignment(Then), ctx.?)), globalThis, callframe.?.arguments());
+ }
+
+ pub fn then(ctx: *Then, this: JSValue, globalThis: *JSGlobalObject) void {
+ this._then(globalThis, ctx, resolve, reject);
+ }
+ };
+}
diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig
index fa7884a50..cb62ba383 100644
--- a/src/javascript/jsc/bindings/exports.zig
+++ b/src/javascript/jsc/bindings/exports.zig
@@ -1340,6 +1340,8 @@ pub const ZigConsoleClient = struct {
JSValue.JSType.BigUint64Array,
=> .TypedArray,
+ .HeapBigInt => .BigInt,
+
// None of these should ever exist here
// But we're going to check anyway
.GetterSetter,
@@ -1367,6 +1369,7 @@ pub const ZigConsoleClient = struct {
.StrictEvalActivation,
.WithScope,
=> .NativeCode,
+
else => .JSON,
},
.cell = js_type,
@@ -1610,11 +1613,11 @@ pub const ZigConsoleClient = struct {
writer.print(comptime Output.prettyFmt("<r><yellow>{d}<r>", enable_ansi_colors), .{value.toInt64()});
},
.BigInt => {
- var wtf = value.toWTFString(this.globalThis);
- writer.print(comptime Output.prettyFmt("<r><yellow>{s}n<r>", enable_ansi_colors), .{wtf.slice()});
+ var out_str = value.getZigString(this.globalThis).slice();
+ writer.print(comptime Output.prettyFmt("<r><yellow>{s}n<r>", enable_ansi_colors), .{out_str});
},
.Double => {
- writer.print(comptime Output.prettyFmt("<r><yellow>{d}<r>", enable_ansi_colors), .{value.asNumber()});
+ writer.print(comptime Output.prettyFmt("<r><yellow>{d}n<r>", enable_ansi_colors), .{value.asNumber()});
},
.Undefined => {
writer.print(comptime Output.prettyFmt("<r><d>undefined<r>", enable_ansi_colors), .{});
@@ -2510,6 +2513,10 @@ comptime {
const Bun = @import("../api/bun.zig");
pub const BunTimer = Bun.Timer;
pub const Formatter = ZigConsoleClient.Formatter;
+pub const HTTPServerRequestContext = JSC.API.Server.RequestContext;
+pub const HTTPSSLServerRequestContext = JSC.API.SSLServer.RequestContext;
+pub const HTTPDebugServerRequestContext = JSC.API.DebugServer.RequestContext;
+pub const HTTPDebugSSLServerRequestContext = JSC.API.DebugSSLServer.RequestContext;
comptime {
WebSocketHTTPClient.shim.ref();
@@ -2517,6 +2524,11 @@ comptime {
WebSocketClient.shim.ref();
WebSocketClientTLS.shim.ref();
+ HTTPServerRequestContext.shim.ref();
+ HTTPSSLServerRequestContext.shim.ref();
+ HTTPDebugServerRequestContext.shim.ref();
+ HTTPDebugSSLServerRequestContext.shim.ref();
+
if (!is_bindgen) {
_ = Process.getTitle;
_ = Process.setTitle;
diff --git a/src/javascript/jsc/bindings/header-gen.zig b/src/javascript/jsc/bindings/header-gen.zig
index 3ec73ea94..c11241233 100644
--- a/src/javascript/jsc/bindings/header-gen.zig
+++ b/src/javascript/jsc/bindings/header-gen.zig
@@ -482,6 +482,7 @@ pub fn getCStruct(comptime T: type) ?NamedStruct {
return null;
}
+var thenables = std.ArrayListUnmanaged([]const u8){};
pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comptime fname: []const u8) type {
return struct {
source_file: []const u8 = fname,
@@ -543,6 +544,10 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp
);
}
+ pub fn processThenable(comptime _: Self, _: anytype, comptime static_export: StaticExport) void {
+ thenables.append(std.heap.c_allocator, comptime static_export.symbol_name) catch unreachable;
+ }
+
pub fn processDecl(
comptime _: Self,
_: anytype,
@@ -593,11 +598,11 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp
}
}
- pub fn exec(comptime self: Self, file: std.fs.File, impl: std.fs.File) void {
+ pub fn exec(comptime self: Self, file: std.fs.File, impl: std.fs.File, lazy_functions_header: std.fs.File, lazy_functions_impl: std.fs.File) void {
const Generator = C_Generator;
validateGenerator(Generator);
var file_writer = file.writer();
- file_writer.print("// clang-format: off\n//-- AUTOGENERATED FILE -- {d}\n", .{std.time.timestamp()}) catch unreachable;
+ file_writer.print("// clang-format off\n//-- AUTOGENERATED FILE -- {d}\n", .{std.time.timestamp()}) catch unreachable;
file.writeAll(
\\#pragma once
\\
@@ -649,6 +654,15 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp
var impl_fourth_buffer = std.ArrayList(u8).init(std.heap.c_allocator);
var impl_fourth_writer = impl_fourth_buffer.writer();
+ var lazy_functions_buffer = std.ArrayList(u8).init(std.heap.c_allocator);
+ var lazy_functions_buffer_writer = lazy_functions_buffer.writer();
+
+ var lazy_function_definitions_buffer = std.ArrayList(u8).init(std.heap.c_allocator);
+ var lazy_function_definitions_writer = lazy_function_definitions_buffer.writer();
+
+ var lazy_function_visitor_buffer = std.ArrayList(u8).init(std.heap.c_allocator);
+ var lazy_function_visitor_writer = lazy_function_visitor_buffer.writer();
+
// inline for (import.all_static_externs) |static_extern, i| {
// const Type = static_extern.Type;
// var gen = C_Generator.init(static_extern.name, @TypeOf(writer), writer);
@@ -688,7 +702,7 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp
else => false,
};
- if (is_container_type and (@hasDecl(Type, "Extern") or @hasDecl(Type, "Export"))) {
+ if (is_container_type and (@hasDecl(Type, "Extern") or @hasDecl(Type, "Export") or @hasDecl(Type, "lazy_static_functions"))) {
const identifier = comptime std.fmt.comptimePrint("{s}_{s}", .{ Type.shim.name, Type.shim.namespace });
if (!bufset.contains(identifier)) {
self.startFile(
@@ -782,6 +796,75 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp
gen.write("\n#endif\n");
}
}
+
+ if (@hasDecl(Type, "lazy_static_functions")) {
+ const ExportLIst = comptime brk: {
+ const Sorder = struct {
+ pub fn lessThan(_: @This(), comptime lhs: StaticExport, comptime rhs: StaticExport) bool {
+ return std.ascii.orderIgnoreCase(lhs.symbol_name, rhs.symbol_name) == std.math.Order.lt;
+ }
+ };
+ var extern_list = Type.lazy_static_functions;
+ std.sort.sort(StaticExport, &extern_list, Sorder{}, Sorder.lessThan);
+ break :brk extern_list;
+ };
+
+ gen.direction = C_Generator.Direction.export_zig;
+ if (ExportLIst.len > 0) {
+ lazy_function_definitions_writer.writeAll("\n#pragma mark ") catch unreachable;
+ lazy_function_definitions_writer.writeAll(Type.shim.name) catch unreachable;
+ lazy_function_definitions_writer.writeAll("\n\n") catch unreachable;
+
+ inline for (ExportLIst) |static_export| {
+ const exp: StaticExport = static_export;
+ lazy_function_definitions_writer.print(" JSC::LazyProperty<Zig::GlobalObject, Zig::JSFFIFunction> m_{s};", .{exp.symbol_name}) catch unreachable;
+ lazy_function_definitions_writer.writeAll("\n") catch unreachable;
+
+ lazy_function_definitions_writer.print(
+ " Zig::JSFFIFunction* get__{s}(Zig::GlobalObject *globalObject) {{ return m_{s}.getInitializedOnMainThread(globalObject); }}",
+ .{ exp.symbol_name, exp.symbol_name },
+ ) catch unreachable;
+ lazy_function_definitions_writer.writeAll("\n") catch unreachable;
+
+ const impl_format =
+ \\
+ \\ m_{s}.initLater(
+ \\ [](const JSC::LazyProperty<Zig::GlobalObject, Zig::JSFFIFunction>::Initializer& init) {{
+ \\ WTF::String functionName = WTF::String("{s}"_s);
+ \\ Zig::JSFFIFunction* function = Zig::JSFFIFunction::create(
+ \\ init.vm,
+ \\ init.owner,
+ \\ 1,
+ \\ functionName,
+ \\ {s},
+ \\ JSC::NoIntrinsic,
+ \\ {s}
+ \\ );
+ \\ init.set(function);
+ \\ }});
+ \\
+ ;
+
+ lazy_functions_buffer_writer.print(
+ impl_format,
+ .{
+ exp.symbol_name,
+ exp.local_name,
+ exp.symbol_name,
+ exp.symbol_name,
+ },
+ ) catch unreachable;
+
+ lazy_function_visitor_writer.print(
+ \\ this->m_{s}.visit(visitor);
+ \\
+ ,
+ .{exp.symbol_name},
+ ) catch unreachable;
+ }
+ gen.write("\n");
+ }
+ }
}
}
}
@@ -800,6 +883,55 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp
impl.writeAll("};\n") catch unreachable;
var iter = type_names.iterator();
+ lazy_functions_header.writer().print(
+ \\// GENERATED FILE
+ \\#pragma once
+ \\#include "root.h"
+ \\
+ \\namespace Zig {{
+ \\ class GlobalObject;
+ \\ class JSFFIFunction;
+ \\
+ \\ class LazyStaticFunctions {{
+ \\ public:
+ \\
+ \\ void init(Zig::GlobalObject* globalObject);
+ \\
+ \\ template<typename Visitor>
+ \\ void visit(Visitor& visitor);
+ \\
+ \\
+ \\ /* -- BEGIN FUNCTION DEFINITIONS -- */
+ \\ {s}
+ \\ /* -- END FUNCTION DEFINITIONS-- */
+ \\ }};
+ \\
+ \\}} // namespace Zig
+ \\
+ , .{lazy_function_definitions_buffer.items}) catch unreachable;
+
+ lazy_functions_impl.writer().print(
+ \\// GENERATED FILE
+ \\#pragma once
+ \\
+ \\namespace Zig {{
+ \\
+ \\ template<typename Visitor>
+ \\ void LazyStaticFunctions::visit(Visitor& visitor) {{
+ \\ {s}
+ \\ }}
+ \\
+ \\ void LazyStaticFunctions::init(Zig::GlobalObject *globalObject) {{
+ \\ {s}
+ \\ }}
+ \\
+ \\}} // namespace Zig
+ \\
+ , .{
+ lazy_function_visitor_buffer.items,
+ lazy_functions_buffer.items,
+ }) catch unreachable;
+
const NamespaceMap = std.StringArrayHashMap(std.BufMap);
var namespaces = NamespaceMap.init(std.heap.c_allocator);
diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h
index 3db8ed275..925291a7d 100644
--- a/src/javascript/jsc/bindings/headers.h
+++ b/src/javascript/jsc/bindings/headers.h
@@ -1,5 +1,5 @@
-// clang-format: off
-//-- AUTOGENERATED FILE -- 1655637924
+// clang-format off
+//-- AUTOGENERATED FILE -- 1655893003
#pragma once
#include <stddef.h>
@@ -106,9 +106,9 @@ typedef void* JSClassRef;
typedef bJSC__JSInternalPromise JSC__JSInternalPromise; // JSC::JSInternalPromise
typedef Bun__Readable Bun__Readable;
typedef struct JSC__RegExpPrototype JSC__RegExpPrototype; // JSC::RegExpPrototype
+ typedef struct JSC__CallFrame JSC__CallFrame; // JSC::CallFrame
typedef struct JSC__MapIteratorPrototype JSC__MapIteratorPrototype; // JSC::MapIteratorPrototype
typedef struct WebCore__FetchHeaders WebCore__FetchHeaders; // WebCore::FetchHeaders
- typedef struct JSC__CallFrame JSC__CallFrame; // JSC::CallFrame
typedef bWTF__StringView WTF__StringView; // WTF::StringView
typedef bJSC__ThrowScope JSC__ThrowScope; // JSC::ThrowScope
typedef bWTF__StringImpl WTF__StringImpl; // WTF::StringImpl
@@ -462,7 +462,7 @@ CPP_DECL size_t WTF__String__length(WTF__String* arg0);
#pragma mark - JSC::JSValue
-CPP_DECL void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, void* arg2, void (* ArgFn3)(JSC__JSGlobalObject* arg0, void* arg1, void** arg2, size_t arg3), void (* ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, void** arg2, size_t arg3));
+CPP_DECL void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, void* arg2, void (* ArgFn3)(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2), void (* ArgFn4)(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2));
CPP_DECL bool JSC__JSValue__asArrayBuffer_(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, Bun__ArrayBuffer* arg2);
CPP_DECL JSC__JSCell* JSC__JSValue__asCell(JSC__JSValue JSValue0);
CPP_DECL JSC__JSInternalPromise* JSC__JSValue__asInternalPromise(JSC__JSValue JSValue0);
@@ -836,3 +836,35 @@ ZIG_DECL JSC__JSValue Bun__Timer__setInterval(JSC__JSGlobalObject* arg0, JSC__JS
ZIG_DECL JSC__JSValue Bun__Timer__setTimeout(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1, JSC__JSValue JSValue2);
#endif
+
+#ifdef __cplusplus
+
+ZIG_DECL void Bun__HTTPRequestContext__reject(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
+ZIG_DECL void Bun__HTTPRequestContext__resolve(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
+
+#endif
+
+
+#ifdef __cplusplus
+
+ZIG_DECL void Bun__HTTPRequestContextTLS__reject(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
+ZIG_DECL void Bun__HTTPRequestContextTLS__resolve(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
+
+#endif
+
+
+#ifdef __cplusplus
+
+ZIG_DECL void Bun__HTTPRequestContextDebug__reject(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
+ZIG_DECL void Bun__HTTPRequestContextDebug__resolve(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
+
+#endif
+
+
+#ifdef __cplusplus
+
+ZIG_DECL void Bun__HTTPRequestContextDebugTLS__reject(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
+ZIG_DECL void Bun__HTTPRequestContextDebugTLS__resolve(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2);
+
+#endif
+
diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig
index 306ee44f2..1a42b9532 100644
--- a/src/javascript/jsc/bindings/headers.zig
+++ b/src/javascript/jsc/bindings/headers.zig
@@ -120,11 +120,11 @@ pub const JSC__JSInternalPromise = bJSC__JSInternalPromise;
pub const JSC__RegExpPrototype = struct_JSC__RegExpPrototype;
+pub const JSC__CallFrame = struct_JSC__CallFrame;
+
pub const JSC__MapIteratorPrototype = struct_JSC__MapIteratorPrototype;
pub const WebCore__FetchHeaders = struct_WebCore__FetchHeaders;
-
-pub const JSC__CallFrame = struct_JSC__CallFrame;
pub const WTF__StringView = bWTF__StringView;
pub const JSC__ThrowScope = bJSC__ThrowScope;
pub const WTF__StringImpl = bWTF__StringImpl;
@@ -311,7 +311,7 @@ pub extern fn WTF__String__isEmpty(arg0: [*c]WTF__String) bool;
pub extern fn WTF__String__isExternal(arg0: [*c]WTF__String) bool;
pub extern fn WTF__String__isStatic(arg0: [*c]WTF__String) bool;
pub extern fn WTF__String__length(arg0: [*c]WTF__String) usize;
-pub extern fn JSC__JSValue___then(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?fn ([*c]JSC__JSGlobalObject, ?*anyopaque, [*c]*anyopaque, usize) callconv(.C) void, ArgFn4: ?fn ([*c]JSC__JSGlobalObject, ?*anyopaque, [*c]*anyopaque, usize) callconv(.C) void) void;
+pub extern fn JSC__JSValue___then(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?fn (?*anyopaque, [*c]JSC__JSGlobalObject, ?*JSC__CallFrame) callconv(.C) void, ArgFn4: ?fn (?*anyopaque, [*c]JSC__JSGlobalObject, ?*JSC__CallFrame) callconv(.C) void) void;
pub extern fn JSC__JSValue__asArrayBuffer_(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c]Bun__ArrayBuffer) bool;
pub extern fn JSC__JSValue__asCell(JSValue0: JSC__JSValue) [*c]JSC__JSCell;
pub extern fn JSC__JSValue__asInternalPromise(JSValue0: JSC__JSValue) [*c]JSC__JSInternalPromise;
diff --git a/src/javascript/jsc/bindings/shimmer.zig b/src/javascript/jsc/bindings/shimmer.zig
index 8d8fda591..c180fc864 100644
--- a/src/javascript/jsc/bindings/shimmer.zig
+++ b/src/javascript/jsc/bindings/shimmer.zig
@@ -126,6 +126,37 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp
};
}
+ pub fn thenables(comptime Functions: anytype) [std.meta.fieldNames(@TypeOf(Functions)).len * 2]StaticExport {
+ const FunctionsType = @TypeOf(Functions);
+ return comptime brk: {
+ var functions: [std.meta.fieldNames(FunctionsType).len * 2]StaticExport = undefined;
+ var j: usize = 0;
+ inline for (Functions) |thenable| {
+ inline for ([_][]const u8{ "resolve", "reject" }) |fn_name| {
+ const Function = @TypeOf(@field(thenable, fn_name));
+ if (@typeInfo(Function) != .Fn) {
+ @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(Function) ++ " to be a function but received " ++ @tagName(@typeInfo(Function)));
+ }
+ var Fn: std.builtin.TypeInfo.Fn = @typeInfo(Function).Fn;
+ if (Fn.calling_convention != .C) {
+ @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(Function) ++ " to have a C Calling Convention.");
+ }
+
+ const export_name = symbolName(fn_name);
+ functions[j] = StaticExport{
+ .Type = Function,
+ .symbol_name = export_name,
+ .local_name = fn_name,
+ .Parent = thenable,
+ };
+ j += 1;
+ }
+ }
+
+ break :brk functions;
+ };
+ }
+
pub inline fn matchNullable(comptime ExpectedReturnType: type, comptime ExternReturnType: type, value: ExternReturnType) ExpectedReturnType {
if (comptime isNullableType(ExpectedReturnType) != isNullableType(ExternReturnType)) {
return value.?;
diff --git a/src/javascript/jsc/bindings/webcore/WebSocket.cpp b/src/javascript/jsc/bindings/webcore/WebSocket.cpp
index 7748f2ae8..d9ffd7278 100644
--- a/src/javascript/jsc/bindings/webcore/WebSocket.cpp
+++ b/src/javascript/jsc/bindings/webcore/WebSocket.cpp
@@ -723,12 +723,23 @@ void WebSocket::didConnect()
didClose(0, 0, emptyString());
return;
}
- ASSERT(scriptExecutionContext());
m_state = OPEN;
- // m_subprotocol = m_channel->subprotocol();
- // m_extensions = m_channel->extensions();
- dispatchEvent(Event::create(eventNames().openEvent, Event::CanBubble::No, Event::IsCancelable::No));
- // });
+
+ if (auto* context = scriptExecutionContext()) {
+ if (this->hasEventListeners("open"_s)) {
+ // the main reason for dispatching on a separate tick is to handle when you haven't yet attached an event listener
+ dispatchEvent(Event::create(eventNames().openEvent, Event::CanBubble::No, Event::IsCancelable::No));
+ } else {
+ context->postTask([this, protectedThis = Ref { *this }](ScriptExecutionContext& context) {
+ ASSERT(scriptExecutionContext());
+
+ // m_subprotocol = m_channel->subprotocol();
+ // m_extensions = m_channel->extensions();
+ protectedThis->dispatchEvent(Event::create(eventNames().openEvent, Event::CanBubble::No, Event::IsCancelable::No));
+ // });
+ });
+ }
+ }
}
void WebSocket::didReceiveMessage(String&& message)
@@ -744,8 +755,21 @@ void WebSocket::didReceiveMessage(String&& message)
// inspector->didReceiveWebSocketFrame(WebSocketChannelInspector::createFrame(utf8Message.dataAsUInt8Ptr(), utf8Message.length(), WebSocketFrame::OpCode::OpCodeText));
// }
// }
- ASSERT(scriptExecutionContext());
- dispatchEvent(MessageEvent::create(WTFMove(message), m_url.string()));
+
+ if (this->hasEventListeners("message"_s)) {
+ // the main reason for dispatching on a separate tick is to handle when you haven't yet attached an event listener
+ dispatchEvent(MessageEvent::create(WTFMove(message), m_url.string()));
+ return;
+ }
+
+ if (auto* context = scriptExecutionContext()) {
+
+ context->postTask([this, message_ = message, protectedThis = Ref { *this }](ScriptExecutionContext& context) {
+ ASSERT(scriptExecutionContext());
+ protectedThis->dispatchEvent(MessageEvent::create(message_, protectedThis->m_url.string()));
+ });
+ }
+
// });
}
@@ -766,10 +790,24 @@ void WebSocket::didReceiveBinaryData(Vector<uint8_t>&& binaryData)
// // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient.
// dispatchEvent(MessageEvent::create(Blob::create(scriptExecutionContext(), WTFMove(binaryData), emptyString()), SecurityOrigin::create(m_url)->toString()));
// break;
- case BinaryType::ArrayBuffer:
- dispatchEvent(MessageEvent::create(ArrayBuffer::create(binaryData.data(), binaryData.size()), m_url.string()));
+ case BinaryType::ArrayBuffer: {
+ if (this->hasEventListeners("message"_s)) {
+ // the main reason for dispatching on a separate tick is to handle when you haven't yet attached an event listener
+ dispatchEvent(MessageEvent::create(ArrayBuffer::create(binaryData.data(), binaryData.size()), m_url.string()));
+ return;
+ }
+
+ if (auto* context = scriptExecutionContext()) {
+
+ context->postTask([this, message_ = message, protectedThis = Ref { *this }](ScriptExecutionContext& context) {
+ ASSERT(scriptExecutionContext());
+ protectedThis->dispatchEvent(MessageEvent::create(ArrayBuffer::create(binaryData.data(), binaryData.size()), m_url.string()));
+ });
+ }
+
break;
}
+ }
// });
}
@@ -780,16 +818,18 @@ void WebSocket::didReceiveMessageError(WTF::StringImpl::StaticStringImpl* reason
if (m_state == CLOSED)
return;
m_state = CLOSED;
- ASSERT(scriptExecutionContext());
-
- // if (UNLIKELY(InspectorInstrumentation::hasFrontends())) {
- // if (auto* inspector = m_channel->channelInspector())
- // inspector->didReceiveWebSocketFrameError(reason);
- // }
-
- // FIXME: As per https://html.spec.whatwg.org/multipage/web-sockets.html#feedback-from-the-protocol:concept-websocket-closed, we should synchronously fire a close event.
- dispatchEvent(CloseEvent::create(false, 0, WTF::String(reason)));
- // });
+ if (auto* context = scriptExecutionContext()) {
+ context->postTask([this, reason, protectedThis = Ref { *this }](ScriptExecutionContext& context) {
+ ASSERT(scriptExecutionContext());
+ // if (UNLIKELY(InspectorInstrumentation::hasFrontends())) {
+ // if (auto* inspector = m_channel->channelInspector())
+ // inspector->didReceiveWebSocketFrameError(reason);
+ // }
+
+ // FIXME: As per https://html.spec.whatwg.org/multipage/web-sockets.html#feedback-from-the-protocol:concept-websocket-closed, we should synchronously fire a close event.
+ dispatchEvent(CloseEvent::create(false, 0, WTF::String(reason)));
+ });
+ }
}
void WebSocket::didUpdateBufferedAmount(unsigned bufferedAmount)
@@ -832,11 +872,16 @@ void WebSocket::didClose(unsigned unhandledBufferedAmount, unsigned short code,
m_state = CLOSED;
m_bufferedAmount = unhandledBufferedAmount;
ASSERT(scriptExecutionContext());
-
- dispatchEvent(CloseEvent::create(wasClean, code, reason));
-
this->m_connectedWebSocketKind = ConnectedWebSocketKind::None;
this->m_upgradeClient = nullptr;
+
+ if (auto* context = scriptExecutionContext()) {
+ context->postTask([this, code, wasClean, reason, protectedThis = Ref { *this }](ScriptExecutionContext& context) {
+ ASSERT(scriptExecutionContext());
+ protectedThis->dispatchEvent(CloseEvent::create(wasClean, code, reason));
+ });
+ }
+
// m_pendingActivity = nullptr;
// });
}
@@ -853,7 +898,13 @@ void WebSocket::dispatchErrorEventIfNeeded()
return;
m_dispatchedErrorEvent = true;
- dispatchEvent(Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No));
+
+ if (auto* context = scriptExecutionContext()) {
+ context->postTask([this, protectedThis = Ref { *this }](ScriptExecutionContext& context) {
+ ASSERT(scriptExecutionContext());
+ protectedThis->dispatchEvent(Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No));
+ });
+ }
}
void WebSocket::didConnect(us_socket_t* socket, char* bufferedData, size_t bufferedDataSize)
@@ -873,12 +924,8 @@ void WebSocket::didConnect(us_socket_t* socket, char* bufferedData, size_t buffe
}
void WebSocket::didFailWithErrorCode(int32_t code)
{
- m_state = CLOSED;
-
- // this means we already handled it
- if (this->m_upgradeClient == nullptr && this->m_connectedWebSocketKind == ConnectedWebSocketKind::None) {
+ if (m_state == CLOSED)
return;
- }
this->m_upgradeClient = nullptr;
this->m_connectedWebSocketKind = ConnectedWebSocketKind::None;
@@ -1047,6 +1094,8 @@ void WebSocket::didFailWithErrorCode(int32_t code)
break;
}
}
+
+ m_state = CLOSED;
}
} // namespace WebCore