diff options
Diffstat (limited to 'src/javascript/jsc')
-rw-r--r-- | src/javascript/jsc/api/bun.zig | 26 | ||||
-rw-r--r-- | src/javascript/jsc/api/server.zig | 320 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/BunBuiltinNames.h | 8 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/ZigGlobalObject.cpp | 3 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/bindings.cpp | 43 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/bindings.zig | 44 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers-cpp.h | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers.h | 3 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers.zig | 1 | ||||
-rw-r--r-- | src/javascript/jsc/javascript.zig | 6 | ||||
-rw-r--r-- | src/javascript/jsc/node/node_fs.zig | 2 |
11 files changed, 449 insertions, 9 deletions
diff --git a/src/javascript/jsc/api/bun.zig b/src/javascript/jsc/api/bun.zig index 64cc72ecc..d3b230243 100644 --- a/src/javascript/jsc/api/bun.zig +++ b/src/javascript/jsc/api/bun.zig @@ -954,6 +954,10 @@ pub const Class = NewClass( .rfn = Bun.readAllStdinSync, .ts = d.ts{}, }, + .startServer = .{ + .rfn = Bun.startServer, + .ts = d.ts{}, + }, }, .{ .main = .{ @@ -1001,6 +1005,28 @@ pub const Class = NewClass( }, ); +pub fn startServer( + _: void, + ctx: js.JSContextRef, + _: js.JSObjectRef, + _: js.JSObjectRef, + arguments: []const js.JSValueRef, + _: js.ExceptionRef, +) js.JSValueRef { + var vm = JSC.VirtualMachine.vm; + const handler = if (arguments.len > 0) JSC.JSValue.fromRef(arguments[0]) else JSC.JSValue.zero; + if (handler.isEmpty() or handler.isUndefinedOrNull() or !handler.isCell() or !handler.isCallable(ctx.ptr().vm())) { + Output.prettyWarnln("\"serverless\" export should be a function", .{}); + Output.flush(); + return JSC.JSValue.jsUndefined().asObjectRef(); + } + + JSC.C.JSValueProtect(ctx.ptr().ref(), handler.asObjectRef()); + var server = JSC.API.Server.init(vm.bundler.options.origin.getPortAuto(), handler, ctx.ptr()); + server.listen(); + return JSC.JSValue.jsUndefined().asObjectRef(); +} + pub fn allocUnsafe( _: void, ctx: js.JSContextRef, diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig new file mode 100644 index 000000000..4b7805adb --- /dev/null +++ b/src/javascript/jsc/api/server.zig @@ -0,0 +1,320 @@ +const Bun = @This(); +const default_allocator = @import("../../../global.zig").default_allocator; +const bun = @import("../../../global.zig"); +const Environment = bun.Environment; +const NetworkThread = @import("http").NetworkThread; +const Global = bun.Global; +const strings = bun.strings; +const string = bun.string; +const Output = @import("../../../global.zig").Output; +const MutableString = @import("../../../global.zig").MutableString; +const std = @import("std"); +const Allocator = std.mem.Allocator; +const IdentityContext = @import("../../../identity_context.zig").IdentityContext; +const Fs = @import("../../../fs.zig"); +const Resolver = @import("../../../resolver/resolver.zig"); +const ast = @import("../../../import_record.zig"); +const NodeModuleBundle = @import("../../../node_module_bundle.zig").NodeModuleBundle; +const MacroEntryPoint = @import("../../../bundler.zig").MacroEntryPoint; +const logger = @import("../../../logger.zig"); +const Api = @import("../../../api/schema.zig").Api; +const options = @import("../../../options.zig"); +const Bundler = @import("../../../bundler.zig").Bundler; +const ServerEntryPoint = @import("../../../bundler.zig").ServerEntryPoint; +const js_printer = @import("../../../js_printer.zig"); +const js_parser = @import("../../../js_parser.zig"); +const js_ast = @import("../../../js_ast.zig"); +const hash_map = @import("../../../hash_map.zig"); +const http = @import("../../../http.zig"); +const NodeFallbackModules = @import("../../../node_fallbacks.zig"); +const ImportKind = ast.ImportKind; +const Analytics = @import("../../../analytics/analytics_thread.zig"); +const ZigString = @import("../../../jsc.zig").ZigString; +const Runtime = @import("../../../runtime.zig"); +const Router = @import("./router.zig"); +const ImportRecord = ast.ImportRecord; +const DotEnv = @import("../../../env_loader.zig"); +const ParseResult = @import("../../../bundler.zig").ParseResult; +const PackageJSON = @import("../../../resolver/package_json.zig").PackageJSON; +const MacroRemap = @import("../../../resolver/package_json.zig").MacroMap; +const WebCore = @import("../../../jsc.zig").WebCore; +const Request = WebCore.Request; +const Response = WebCore.Response; +const Headers = WebCore.Headers; +const Fetch = WebCore.Fetch; +const HTTP = @import("http"); +const FetchEvent = WebCore.FetchEvent; +const js = @import("../../../jsc.zig").C; +const JSC = @import("../../../jsc.zig"); +const JSError = @import("../base.zig").JSError; +const d = @import("../base.zig").d; +const MarkedArrayBuffer = @import("../base.zig").MarkedArrayBuffer; +const getAllocator = @import("../base.zig").getAllocator; +const JSValue = @import("../../../jsc.zig").JSValue; +const NewClass = @import("../base.zig").NewClass; +const Microtask = @import("../../../jsc.zig").Microtask; +const JSGlobalObject = @import("../../../jsc.zig").JSGlobalObject; +const ExceptionValueRef = @import("../../../jsc.zig").ExceptionValueRef; +const JSPrivateDataPtr = @import("../../../jsc.zig").JSPrivateDataPtr; +const ZigConsoleClient = @import("../../../jsc.zig").ZigConsoleClient; +const Node = @import("../../../jsc.zig").Node; +const ZigException = @import("../../../jsc.zig").ZigException; +const ZigStackTrace = @import("../../../jsc.zig").ZigStackTrace; +const ErrorableResolvedSource = @import("../../../jsc.zig").ErrorableResolvedSource; +const ResolvedSource = @import("../../../jsc.zig").ResolvedSource; +const JSPromise = @import("../../../jsc.zig").JSPromise; +const JSInternalPromise = @import("../../../jsc.zig").JSInternalPromise; +const JSModuleLoader = @import("../../../jsc.zig").JSModuleLoader; +const JSPromiseRejectionOperation = @import("../../../jsc.zig").JSPromiseRejectionOperation; +const Exception = @import("../../../jsc.zig").Exception; +const ErrorableZigString = @import("../../../jsc.zig").ErrorableZigString; +const ZigGlobalObject = @import("../../../jsc.zig").ZigGlobalObject; +const VM = @import("../../../jsc.zig").VM; +const JSFunction = @import("../../../jsc.zig").JSFunction; +const Config = @import("../config.zig"); +const URL = @import("../../../url.zig").URL; +const Transpiler = @import("./transpiler.zig"); +const VirtualMachine = @import("../javascript.zig").VirtualMachine; +const IOTask = JSC.IOTask; +const is_bindgen = JSC.is_bindgen; +const uws = @import("uws"); + +pub fn NewServer(comptime ssl_enabled: bool) type { + return struct { + const ThisServer = @This(); + const RequestContextStackAllocator = std.heap.StackFallbackAllocator(@sizeOf(RequestContext) * 2048 + 4096); + + pub const App = uws.NewApp(ssl_enabled); + + listener: ?*App.ListenSocket = null, + callback: JSC.JSValue = JSC.JSValue.zero, + port: u16 = 3000, + app: *App = undefined, + globalThis: *JSGlobalObject, + default_server: URL = URL{ .host = "localhost", .port = "3000" }, + + request_pool_allocator: std.mem.Allocator = undefined, + + pub fn init(port: u16, callback: JSC.JSValue, globalThis: *JSGlobalObject) *ThisServer { + var server = bun.default_allocator.create(ThisServer) catch @panic("Out of memory!"); + server.* = .{ + .port = port, + .callback = callback, + .globalThis = globalThis, + }; + RequestContext.pool = bun.default_allocator.create(RequestContextStackAllocator) catch @panic("Out of memory!"); + server.request_pool_allocator = RequestContext.pool.get(); + return server; + } + + pub fn onListen(this: *ThisServer, socket: ?*App.ListenSocket, _: uws.uws_app_listen_config_t) void { + if (socket == null) { + Output.prettyErrorln("Failed to start socket", .{}); + Output.flush(); + return; + } + + this.listener = socket; + VirtualMachine.vm.uws_event_loop = uws.Loop.get(); + this.app.run(); + } + + pub const RequestContext = struct { + server: *ThisServer, + resp: *App.Response, + req: *uws.Request, + url: string, + method: HTTP.Method, + aborted: bool = false, + response_jsvalue: JSC.JSValue = JSC.JSValue.zero, + blob: JSC.WebCore.Blob = JSC.WebCore.Blob{}, + promise: ?*JSC.JSValue = null, + response_headers: ?*JSC.WebCore.Headers.RefCountedHeaders = null, + + pub threadlocal var pool: *RequestContextStackAllocator = undefined; + + pub fn onResolve( + ctx: *RequestContext, + _: *JSC.JSGlobalObject, + arguments: []const JSC.JSValue, + ) void { + if (ctx.aborted) { + ctx.finalize(); + return; + } + + if (arguments.len == 0) { + ctx.req.setYield(true); + ctx.finalize(); + return; + } + + var response = arguments[0].as(JSC.WebCore.Response) orelse { + Output.prettyErrorln("Expected serverless to return a Response", .{}); + ctx.req.setYield(true); + ctx.finalize(); + return; + }; + ctx.render(response); + } + + pub fn onReject( + ctx: *RequestContext, + _: *JSC.JSGlobalObject, + arguments: []const JSC.JSValue, + ) void { + if (ctx.aborted) { + ctx.finalize(); + return; + } + + JSC.VirtualMachine.vm.defaultErrorHandler(arguments[0], null); + ctx.req.setYield(true); + ctx.finalize(); + } + + pub fn create(this: *RequestContext, server: *ThisServer, req: *uws.Request, resp: *App.Response) void { + this.* = .{ + .resp = resp, + .req = req, + .url = req.url(), + .method = HTTP.Method.which(req.method()) orelse .GET, + .server = server, + }; + resp.onAborted(*RequestContext, onAbort, this); + } + + pub fn onAbort(this: *RequestContext, _: *App.Response) void { + this.aborted = true; + this.req = undefined; + if (!this.response_jsvalue.isEmpty()) { + JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.response_jsvalue.asObjectRef()); + this.response_jsvalue = JSC.JSValue.zero; + } + } + + pub fn finalize(this: *RequestContext) void { + this.blob.detach(); + if (!this.response_jsvalue.isEmpty()) { + JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.response_jsvalue.asObjectRef()); + this.response_jsvalue = JSC.JSValue.zero; + } + + if (this.promise != null) { + JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.promise.?.asObjectRef()); + this.promise = null; + } + + if (this.response_headers != null) { + this.response_headers.?.deref(); + this.response_headers = null; + } + + this.server.request_pool_allocator.destroy(this); + } + + pub fn render(this: *RequestContext, response: *JSC.WebCore.Response) void { + if (this.aborted) { + return; + } + + this.blob = response.body.use(); + const status = response.statusCode(); + + if (response.body.init.headers) |headers_| { + var headers: *JSC.WebCore.Headers = headers_.get(); + defer headers_.deref(); + var entries = headers.entries.slice(); + const names = entries.items(.name); + const values = entries.items(.value); + + var status_text_buf: [48]u8 = undefined; + + if (status == 302) { + this.resp.writeStatus("302 Found"); + } else { + this.resp.writeStatus(std.fmt.bufPrint(&status_text_buf, "{d} HM", .{response.body.init.status_code}) catch unreachable); + } + + for (names) |name, i| { + this.resp.writeHeader(headers.asStr(name), headers.asStr(values[i])); + } + } + + if (status == 302 or status == 202 or this.blob.size == 0) { + this.resp.endWithoutBody(); + this.finalize(); + return; + } + + this.resp.end(this.blob.sharedView(), false); + this.finalize(); + } + }; + + pub fn onRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void { + req.setYield(false); + var ctx = this.request_pool_allocator.create(RequestContext) catch @panic("ran out of memory"); + ctx.create(this, req, resp); + + var request_object = bun.default_allocator.create(JSC.WebCore.Request) catch unreachable; + request_object.* = .{ + .url = JSC.ZigString.init(ctx.url), + .method = ctx.method, + }; + var args = [_]JSC.C.JSValueRef{JSC.WebCore.Request.Class.make(this.globalThis.ref(), request_object)}; + ctx.response_jsvalue = JSC.C.JSObjectCallAsFunctionReturnValue(this.globalThis.ref(), this.callback.asObjectRef(), null, 1, &args); + defer JSC.VirtualMachine.vm.tick(); + if (ctx.aborted) { + ctx.finalize(); + + return; + } + + if (ctx.response_jsvalue.isUndefinedOrNull()) { + req.setYield(true); + ctx.finalize(); + return; + } + + JSC.C.JSValueProtect(this.globalThis.ref(), ctx.response_jsvalue.asObjectRef()); + + if (ctx.response_jsvalue.as(JSC.WebCore.Response)) |response| { + ctx.render(response); + + return; + } + + if (ctx.response_jsvalue.jsTypeLoose() == .JSPromise) { + JSC.VirtualMachine.vm.tick(); + + ctx.response_jsvalue.then( + this.globalThis, + RequestContext, + ctx, + RequestContext.onResolve, + RequestContext.onReject, + ); + } + + // switch (ctx.response_jsvalue.jsTypeLoose()) { + // .JSPromise => { + // JSPromise. + // }, + // } + } + + pub fn listen(this: *ThisServer) void { + this.app = App.create(.{}); + this.app.any("/*", *ThisServer, this, onRequest); + this.app.listenWithConfig(*ThisServer, this, onListen, .{ + .port = this.default_server.getPort().?, + .host = bun.default_allocator.dupeZ(u8, this.default_server.displayHostname()) catch unreachable, + .options = 0, + }); + } + }; +} + +pub const Server = NewServer(false); +pub const SSLServer = NewServer(true); diff --git a/src/javascript/jsc/bindings/BunBuiltinNames.h b/src/javascript/jsc/bindings/BunBuiltinNames.h index 709ab28a5..9619f62a6 100644 --- a/src/javascript/jsc/bindings/BunBuiltinNames.h +++ b/src/javascript/jsc/bindings/BunBuiltinNames.h @@ -72,6 +72,14 @@ using namespace JSC; macro(delimiter) \ macro(toNamespacedPath) \ macro(isWindows) \ + macro(get) \ + macro(put) \ + macro(post) \ + macro(patch) \ + macro(trace) \ + macro(connect) \ + macro(options) \ + macro(port) \ BUN_ADDITIONAL_PRIVATE_IDENTIFIERS(macro) \ class BunBuiltinNames { diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp index 4c6a0f9c2..cf853e2d4 100644 --- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp +++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp @@ -557,7 +557,8 @@ static JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve, } } -extern "C" void Bun__reportError(JSC::JSGlobalObject*, JSC__JSValue); +extern "C" void Bun__reportError(JSC__JSGlobalObject*, JSC__JSValue); + static JSC_DECLARE_HOST_FUNCTION(functionReportError); static JSC_DEFINE_HOST_FUNCTION(functionReportError, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp index 112ca81b7..85f7e6f1e 100644 --- a/src/javascript/jsc/bindings/bindings.cpp +++ b/src/javascript/jsc/bindings/bindings.cpp @@ -246,6 +246,45 @@ unsigned char JSC__JSValue__jsType(JSC__JSValue JSValue0) return 0; } +// 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, JSC__JSValue arg2, size_t arg3), void (*ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3)) +{ + + JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create( + globalObject->vm(), globalObject, 1, String(), [ctx, ArgFn3](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))); + } + } + + ArgFn3(globalObject, ctx, reinterpret_cast<JSC__JSValue>(arguments.data()), argCount); + return JSC::JSValue::encode(JSC::jsUndefined()); + }); + JSC::JSNativeStdFunction* rejecterFunction = JSC::JSNativeStdFunction::create( + globalObject->vm(), globalObject, 1, String(), + [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<JSC__JSValue>(arguments.data()), argCount); + return JSC::JSValue::encode(JSC::jsUndefined()); + }); + + globalObject->vm().drainMicrotasks(); + JSC::JSPromise* promise = JSC::jsDynamicCast<JSC::JSPromise*>(globalObject->vm(), JSC::JSValue::decode(JSValue0).asCell()); + promise->performPromiseThen(globalObject, resolverFunction, rejecterFunction, JSC::jsUndefined()); +} + JSC__JSValue JSC__JSValue__parseJSON(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1) { JSC::JSValue jsValue = JSC::JSValue::decode(JSValue0); @@ -728,10 +767,8 @@ JSC__JSValue JSC__JSGlobalObject__createAggregateError(JSC__JSGlobalObject* glob } JSC::Structure* errorStructure = globalObject->errorStructure(JSC::ErrorType::AggregateError); - scope.release(); - return JSC::JSValue::encode(JSC::createAggregateError( - globalObject, vm, errorStructure, array, message, options, nullptr, JSC::TypeNothing, false)); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::createAggregateError(globalObject, vm, errorStructure, array, message, options, nullptr, JSC::TypeNothing, false))); } // static JSC::JSNativeStdFunction* resolverFunction; // static JSC::JSNativeStdFunction* rejecterFunction; diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig index 88ecb6bfe..da65d38d5 100644 --- a/src/javascript/jsc/bindings/bindings.zig +++ b/src/javascript/jsc/bindings/bindings.zig @@ -2179,6 +2179,48 @@ pub const JSValue = enum(u64) { return cppFn("symbolKeyFor", .{ this, global, str }); } + const Thenable = fn ( + global: [*c]JSGlobalObject, + ctx: ?*anyopaque, + arguments_ptr: JSC.JSValue, + arguments_len: usize, + ) callconv(.C) void; + pub fn _then(this: JSValue, global: *JSGlobalObject, ctx: ?*anyopaque, resolve: Thenable, reject: Thenable) 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_: JSC.JSValue, + arguments_len: usize, + ) callconv(.C) void { + @setRuntimeSafety(false); + var arguments_ptr = @intToPtr([*]const JSC.JSValue, @enumToInt(arguments_ptr_)); + onResolve(bun.cast(*Then, ptr.?), globalThis, arguments_ptr[0..arguments_len]); + } + + pub fn reject( + globalThis: [*c]JSGlobalObject, + ptr: ?*anyopaque, + arguments_ptr_: JSC.JSValue, + arguments_len: usize, + ) callconv(.C) void { + @setRuntimeSafety(false); + var arguments_ptr = @intToPtr([*]const JSC.JSValue, @enumToInt(arguments_ptr_)); + onReject(bun.cast(*Then, ptr.?), globalThis, arguments_ptr[0..arguments_len]); + } + }; + + this._then( + global, + ctx, + Handler.resolve, + Handler.reject, + ); + } + pub fn getDescription(this: JSValue, global: *JSGlobalObject) ZigString { var zig_str = ZigString.init(""); getSymbolDescription(this, global, &zig_str); @@ -2314,7 +2356,7 @@ pub const JSValue = enum(u64) { return @intToPtr(*anyopaque, @enumToInt(this)); } - pub const Extern = [_][]const u8{ "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "getReadableStreamState", "getWritableStreamState", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" }; + pub const Extern = [_][]const u8{ "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "getReadableStreamState", "getWritableStreamState", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" }; }; extern "c" fn Microtask__run(*Microtask, *JSGlobalObject) void; diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h index ba8175a74..3e8e7af5d 100644 --- a/src/javascript/jsc/bindings/headers-cpp.h +++ b/src/javascript/jsc/bindings/headers-cpp.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1647600299 +//-- AUTOGENERATED FILE -- 1647769923 // clang-format off #pragma once diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h index 1d36062da..fb72e3798 100644 --- a/src/javascript/jsc/bindings/headers.h +++ b/src/javascript/jsc/bindings/headers.h @@ -1,5 +1,5 @@ // clang-format: off -//-- AUTOGENERATED FILE -- 1647600299 +//-- AUTOGENERATED FILE -- 1647769923 #pragma once #include <stddef.h> @@ -426,6 +426,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, JSC__JSValue arg2, size_t arg3), void (* ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3)); 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); diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig index f9d09821a..f920c74d9 100644 --- a/src/javascript/jsc/bindings/headers.zig +++ b/src/javascript/jsc/bindings/headers.zig @@ -274,6 +274,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, JSC__JSValue, usize) callconv(.C) void, ArgFn4: ?fn ([*c]JSC__JSGlobalObject, ?*anyopaque, JSC__JSValue, usize) 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/javascript.zig b/src/javascript/jsc/javascript.zig index 7bd8e0244..4a8fefd3c 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -422,6 +422,7 @@ pub const SavedSourceMap = struct { return SourceMap.Mapping.find(mappings, line, column); } }; +const uws = @import("uws"); // If you read JavascriptCore/API/JSVirtualMachine.mm - https://github.com/WebKit/WebKit/blob/acff93fb303baa670c055cb24c2bad08691a01a0/Source/JavaScriptCore/API/JSVirtualMachine.mm#L101 // We can see that it's sort of like std.mem.Allocator but for JSGlobalContextRef, to support Automatic Reference Counting @@ -450,6 +451,7 @@ pub const VirtualMachine = struct { node_fs: ?*Node.NodeFS = null, has_loaded_node_modules: bool = false, timer: Bun.Timer = Bun.Timer{}, + uws_event_loop: ?*uws.Loop = null, arena: *Arena = undefined, has_loaded: bool = false, @@ -596,6 +598,9 @@ pub const VirtualMachine = struct { this.concurrent_lock.lock(); defer this.concurrent_lock.unlock(); this.concurrent_tasks.writeItem(task) catch unreachable; + if (this.virtual_machine.uws_event_loop) |loop| { + loop.nextTick(*EventLoop, this, EventLoop.tick); + } _ = this.ready_tasks_count.fetchAdd(1, .Monotonic); } }; @@ -728,7 +733,6 @@ pub const VirtualMachine = struct { .origin_timer = std.time.Timer.start() catch @panic("Please don't mess with timers."), .ref_strings = JSC.RefString.Map.init(allocator), }; - VirtualMachine.vm.regular_event_loop.tasks = EventLoop.Queue.init( default_allocator, ); diff --git a/src/javascript/jsc/node/node_fs.zig b/src/javascript/jsc/node/node_fs.zig index 0c47d3aa9..b7aacbf97 100644 --- a/src/javascript/jsc/node/node_fs.zig +++ b/src/javascript/jsc/node/node_fs.zig @@ -2168,7 +2168,7 @@ const Arguments = struct { }; }; -pub const Constants = struct { +const Constants = struct { // File Access Constants /// Constant for fs.access(). File is visible to the calling process. pub const F_OK = std.os.F_OK; |