diff options
| -rw-r--r-- | .vscode/launch.json | 1 | ||||
| -rw-r--r-- | build.zig | 3 | ||||
| -rw-r--r-- | src/bundler.zig | 2 | ||||
| -rw-r--r-- | src/fs.zig | 6 | ||||
| -rw-r--r-- | src/http.zig | 92 | ||||
| -rw-r--r-- | src/javascript/jsc/bindings/bindings.zig | 133 | ||||
| -rw-r--r-- | src/javascript/jsc/bindings/exports.zig | 4 | ||||
| -rw-r--r-- | src/javascript/jsc/bindings/headers-cpp.h | 2 | ||||
| -rw-r--r-- | src/javascript/jsc/bindings/headers-replacements.zig | 1 | ||||
| -rw-r--r-- | src/javascript/jsc/bindings/headers.h | 18 | ||||
| -rw-r--r-- | src/javascript/jsc/bindings/headers.zig | 51 | ||||
| -rw-r--r-- | src/javascript/jsc/javascript.zig | 114 | ||||
| -rw-r--r-- | src/javascript/jsc/webcore/response.zig | 89 | ||||
| -rw-r--r-- | src/main.zig | 8 | ||||
| -rw-r--r-- | src/main_javascript.zig | 7 |
15 files changed, 336 insertions, 195 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json index 41b9d64af..184131251 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -103,6 +103,7 @@ "./src/index.tsx", "--resolve=lazy", "--outdir=public", + "--framework=framework.tsx", "--serve", "--public-url=http://localhost:9000/" ], @@ -53,6 +53,9 @@ const HeadersMaker = struct { remainder = begin[end_struct..]; } + _ = std.mem.replace(u8, new_contents, "[*c][*c]JSC__Exception", "*?*JSC__Exception ", new_contents); + _ = std.mem.replace(u8, new_contents, "[*c]?*c_void", "[*c]*c_void", new_contents); + const js_value_start = std.mem.indexOf(u8, new_contents, "pub const JSC__JSValue") orelse unreachable; const js_value_end = std.mem.indexOf(u8, new_contents[js_value_start..], "\n") orelse unreachable; std.mem.set(u8, new_contents[js_value_start..][0..js_value_end], ' '); diff --git a/src/bundler.zig b/src/bundler.zig index d2488be89..161aeb6c0 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -1717,7 +1717,7 @@ pub fn NewBundler(cache_files: bool) type { ) !options.TransformResult { var bundler = try ThisBundler.init(allocator, log, opts, null); bundler.configureLinker(); - // try bundler.configureRouter(); + try bundler.configureRouter(); var skip_normalize = false; if (bundler.router) |router| { diff --git a/src/fs.zig b/src/fs.zig index a8da71588..f45c53c29 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -125,9 +125,9 @@ pub const FileSystem = struct { const tld = try allocator.alloc(u8, _top_level_dir.len + 1); std.mem.copy(u8, tld, _top_level_dir); tld[tld.len - 1] = std.fs.path.sep; - if (!isBrowser) { - allocator.free(_top_level_dir); - } + // if (!isBrowser) { + // allocator.free(_top_level_dir); + // } _top_level_dir = tld; } diff --git a/src/http.zig b/src/http.zig index 16daae48e..e876fb8fd 100644 --- a/src/http.zig +++ b/src/http.zig @@ -44,6 +44,7 @@ threadlocal var res_headers_buf: [100]picohttp.Header = undefined; const sync = @import("./sync.zig"); const JavaScript = @import("./javascript/jsc/JavaScript.zig"); const js = @import("javascript/jsc/javascript.zig"); +usingnamespace @import("javascript/jsc/bindings/bindings.zig"); const Router = @import("./router.zig"); pub const Watcher = watcher.NewWatcher(*Server); @@ -654,9 +655,9 @@ pub const RequestContext = struct { pub var channel: Channel = undefined; var has_loaded_channel = false; pub var javascript_disabled = false; - var thread: std.Thread = undefined; pub fn spawnThread(handler: HandlerThread) !void { - _ = try std.Thread.spawn(.{}, spawn, .{handler}); + var thread = try std.Thread.spawn(.{}, spawn, .{handler}); + // thread.detach(); } pub fn spawn(handler: HandlerThread) void { @@ -682,50 +683,45 @@ pub const RequestContext = struct { js_ast.Expr.Data.Store.create(std.heap.c_allocator); defer Output.flush(); - var vm = try JavaScript.VirtualMachine.init(std.heap.c_allocator, handler.args, handler.existing_bundle, handler.log); + var vm = JavaScript.VirtualMachine.init(std.heap.c_allocator, handler.args, handler.existing_bundle, handler.log) catch |err| { + Output.prettyErrorln( + "JavaScript VM failed to start: <r><red>{s}<r>", + .{@errorName(err)}, + ); + Output.flush(); + return; + }; + std.debug.assert(JavaScript.VirtualMachine.vm_loaded); + javascript_vm = vm; const boot = handler.framework.entry_point; + std.debug.assert(boot.len > 0); defer vm.deinit(); var resolved_entry_point = try vm.bundler.resolver.resolve( - std.fs.path.dirname(boot).?, - boot, + std.fs.path.dirname(boot) orelse vm.bundler.fs.top_level_dir, + vm.bundler.normalizeEntryPointPath(boot), .entry_point, ); - JavaScript.VirtualMachine.vm = vm; - javascript_vm = JavaScript.VirtualMachine.vm; - var exception: js.JSValueRef = null; - var load_result = try JavaScript.Module.loadFromResolveResult(vm, vm.ctx, resolved_entry_point, &exception); - - // We've already printed the exception here! - if (exception != null) { - Output.prettyErrorln( - "JavaScript VM failed to start", - .{}, - ); - Output.flush(); + var load_result = try vm.loadEntryPoint(resolved_entry_point.path_pair.primary.text); - return; - } - - switch (load_result) { - .Module => { - Output.prettyln( - "Loaded JavaScript VM: \"{s}\"", - .{vm.bundler.fs.relativeTo(boot)}, - ); - Output.flush(); - }, - .Path => { + switch (load_result.status(vm.global.vm())) { + JSPromise.Status.Fulfilled => {}, + else => { Output.prettyErrorln( - "Error loading JavaScript VM: Expected framework to be a path to a JavaScript-like file but received \"{s}\"", - .{boot}, + "JavaScript VM failed to start", + .{}, ); Output.flush(); return; }, } + if (vm.event_listeners.count() == 0) { + Output.prettyErrorln("<r><red>error<r>: Framework didn't run <b><cyan>addEventListener(\"fetch\", callback)<r>, which means it can't accept HTTP requests.\nShutting down JS.", .{}); + return; + } + js_ast.Stmt.Data.Store.reset(); js_ast.Expr.Data.Store.reset(); @@ -1675,25 +1671,25 @@ pub const Server = struct { } if (req_ctx.url.extname.len == 0 and !RequestContext.JavaScriptHandler.javascript_disabled) { - // if (server.bundler.options.framework != null) { - // RequestContext.JavaScriptHandler.enqueue(&req_ctx, server) catch unreachable; - // server.javascript_enabled = !RequestContext.JavaScriptHandler.javascript_disabled; - // } + if (server.bundler.options.framework != null) { + RequestContext.JavaScriptHandler.enqueue(&req_ctx, server) catch unreachable; + server.javascript_enabled = !RequestContext.JavaScriptHandler.javascript_disabled; + } } - // if (!req_ctx.controlled) { - req_ctx.handleRequest() catch |err| { - switch (err) { - error.ModuleNotFound => { - req_ctx.sendNotFound() catch {}; - }, - else => { - Output.printErrorln("FAIL [{s}] - {s}: {s}", .{ @errorName(err), req.method, req.path }); - return; - }, - } - }; - // } + if (!req_ctx.controlled) { + req_ctx.handleRequest() catch |err| { + switch (err) { + error.ModuleNotFound => { + req_ctx.sendNotFound() catch {}; + }, + else => { + Output.printErrorln("FAIL [{s}] - {s}: {s}", .{ @errorName(err), req.method, req.path }); + return; + }, + } + }; + } if (!req_ctx.controlled) { const status = req_ctx.status orelse @intCast(HTTPStatusCode, 500); diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig index 0701c515e..1ae5c1236 100644 --- a/src/javascript/jsc/bindings/bindings.zig +++ b/src/javascript/jsc/bindings/bindings.zig @@ -88,6 +88,8 @@ pub const ZigString = extern struct { }; }; +pub const ReturnableException = *?*Exception; + pub const JSCell = extern struct { pub const shim = Shimmer("JSC", "JSCell", @This()); bytes: shim.Bytes, @@ -548,29 +550,29 @@ pub const JSFunction = extern struct { pub const name = "JSC::JSFunction"; pub const namespace = "JSC"; - pub const NativeFunctionCallback = fn (ctx: ?*c_void, global: *JSGlobalObject, call_frame: *CallFrame) callconv(.C) JSValue; - - pub fn createFromSourceCode( - global: *JSGlobalObject, - function_name: ?[*]const u8, - function_name_len: u16, - args: ?[*]JSValue, - args_len: u16, - source: *const SourceCode, - origin: *SourceOrigin, - exception: *?*JSObject, - ) *JSFunction { - return cppFn("createFromSourceCode", .{ - global, - function_name, - function_name_len, - args, - args_len, - source, - origin, - exception, - }); - } + pub const NativeFunctionCallback = fn (ctx: ?*c_void, global: [*c]JSGlobalObject, call_frame: [*c]CallFrame) callconv(.C) JSValue; + + // pub fn createFromSourceCode( + // global: *JSGlobalObject, + // function_name: ?[*]const u8, + // function_name_len: u16, + // args: ?[*]JSValue, + // args_len: u16, + // source: *const SourceCode, + // origin: *SourceOrigin, + // exception: *?*JSObject, + // ) *JSFunction { + // return cppFn("createFromSourceCode", .{ + // global, + // function_name, + // function_name_len, + // args, + // args_len, + // source, + // origin, + // exception, + // }); + // } pub fn createFromNative( global: *JSGlobalObject, argument_count: u16, @@ -589,9 +591,9 @@ pub const JSFunction = extern struct { pub fn calculatedDisplayName(this: *JSFunction, vm: *VM) String { return cppFn("calculatedDisplayName", .{ this, vm }); } - pub fn toString(this: *JSFunction, globalThis: *JSGlobalObject) *const JSString { - return cppFn("toString", .{ this, globalThis }); - } + // pub fn toString(this: *JSFunction, globalThis: *JSGlobalObject) *const JSString { + // return cppFn("toString", .{ this, globalThis }); + // } pub fn callWithArgumentsAndThis( function: JSValue, @@ -599,13 +601,13 @@ pub const JSFunction = extern struct { globalThis: *JSGlobalObject, arguments_ptr: [*]JSValue, arguments_len: usize, - exception: *?*Exception, - error_message: *const c_char, + exception: ReturnableException, + error_message: [*c]const u8, ) JSValue { return cppFn("callWithArgumentsAndThis", .{ function, - globalThis, thisValue, + globalThis, arguments_ptr, arguments_len, exception, @@ -618,20 +620,27 @@ pub const JSFunction = extern struct { globalThis: *JSGlobalObject, arguments_ptr: [*]JSValue, arguments_len: usize, - exception: *?*Exception, - error_message: *const c_char, + exception: ReturnableException, + error_message: [*c]const u8, ) JSValue { - return cppFn("callWithArguments", .{ function, globalThis, arguments_ptr, arguments_len, exception, exception, error_message }); + return cppFn("callWithArguments", .{ + function, + globalThis, + arguments_ptr, + arguments_len, + exception, + error_message, + }); } pub fn callWithThis( function: JSValue, globalThis: *JSGlobalObject, thisValue: JSValue, - exception: *?*Exception, - error_message: *const c_char, + exception: ReturnableException, + error_message: [*c]const u8, ) JSValue { - return cppFn("callWithArguments", .{ + return cppFn("callWithThis", .{ function, globalThis, thisValue, @@ -643,10 +652,10 @@ pub const JSFunction = extern struct { pub fn callWithoutAnyArgumentsOrThis( function: JSValue, globalThis: *JSGlobalObject, - exception: *?*Exception, - error_message: *const c_char, + exception: ReturnableException, + error_message: [*c]const u8, ) JSValue { - return cppFn("callWithoutAnyArgumentsOrThis", .{ function, globalThis, exception, exception, error_message }); + return cppFn("callWithoutAnyArgumentsOrThis", .{ function, globalThis, exception, error_message }); } pub fn constructWithArgumentsAndNewTarget( @@ -655,13 +664,13 @@ pub const JSFunction = extern struct { globalThis: *JSGlobalObject, arguments_ptr: [*]JSValue, arguments_len: usize, - exception: *?*Exception, - error_message: *const c_char, + exception: ReturnableException, + error_message: [*c]const u8, ) JSValue { return cppFn("constructWithArgumentsAndNewTarget", .{ function, - globalThis, newTarget, + globalThis, arguments_ptr, arguments_len, exception, @@ -674,20 +683,27 @@ pub const JSFunction = extern struct { globalThis: *JSGlobalObject, arguments_ptr: [*]JSValue, arguments_len: usize, - exception: *?*Exception, - error_message: *const c_char, + exception: ReturnableException, + error_message: [*c]const u8, ) JSValue { - return cppFn("constructWithArguments", .{ function, globalThis, arguments_ptr, arguments_len, exception, exception, error_message }); + return cppFn("constructWithArguments", .{ + function, + globalThis, + arguments_ptr, + arguments_len, + exception, + error_message, + }); } pub fn constructWithNewTarget( function: JSValue, globalThis: *JSGlobalObject, newTarget: JSValue, - exception: *?*Exception, - error_message: *const c_char, + exception: ReturnableException, + error_message: [*c]const u8, ) JSValue { - return cppFn("constructWithArguments", .{ + return cppFn("constructWithNewTarget", .{ function, globalThis, newTarget, @@ -699,15 +715,20 @@ pub const JSFunction = extern struct { pub fn constructWithoutAnyArgumentsOrNewTarget( function: JSValue, globalThis: *JSGlobalObject, - exception: *?*Exception, - error_message: *const c_char, + exception: ReturnableException, + error_message: [*c]const u8, ) JSValue { - return cppFn("constructWithoutAnyArgumentsOrNewTarget", .{ function, globalThis, exception, exception, error_message }); + return cppFn("constructWithoutAnyArgumentsOrNewTarget", .{ + function, + globalThis, + exception, + error_message, + }); } pub const Extern = [_][]const u8{ "fromString", - "createFromSourceCode", + // "createFromSourceCode", "createFromNative", "getName", "displayName", @@ -1330,11 +1351,19 @@ pub const JSValue = enum(i64) { return @intToPtr(C_API.JSValueRef, @intCast(usize, @enumToInt(this))); } + pub inline fn fromRef(this: C_API.JSValueRef) JSValue { + return @intToEnum(JSValue, @intCast(i64, @ptrToInt(this))); + } + + pub inline fn asObjectRef(this: JSValue) C_API.JSObjectRef { + return @ptrCast(C_API.JSObjectRef, this.asVoid()); + } + pub inline fn asVoid(this: JSValue) *c_void { return @intToPtr(*c_void, @intCast(usize, @enumToInt(this))); } - pub const Extern = [_][]const u8{ "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "get", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isUndefined", "isNull", "isUndefinedOrNull", "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{ "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "get", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isUndefined", "isNull", "isUndefinedOrNull", "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 PropertyName = extern struct { diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig index 2678e9f8c..861b65e2b 100644 --- a/src/javascript/jsc/bindings/exports.zig +++ b/src/javascript/jsc/bindings/exports.zig @@ -17,7 +17,7 @@ pub const ZigGlobalObject = extern struct { pub const name = "Zig::GlobalObject"; pub const include = "\"ZigGlobalObject.h\""; pub const namespace = shim.namespace; - pub const Interface: type = NewGlobalObject(std.meta.globalOption("JavaScriptVirtualMachine", type) orelse struct {}); + pub const Interface: type = NewGlobalObject(JS.VirtualMachine); pub var sigaction: std.os.Sigaction = undefined; pub var sigaction_installed = false; @@ -533,6 +533,8 @@ pub const ZigConsoleClient = struct { }; } + /// TODO: support %s %d %f %o %O + /// https://console.spec.whatwg.org/#formatter pub fn messageWithTypeAndLevel( console_: ZigConsoleClient.Type, message_type: u32, diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h index cb4efcc4e..2978b8e9a 100644 --- a/src/javascript/jsc/bindings/headers-cpp.h +++ b/src/javascript/jsc/bindings/headers-cpp.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1627967644 +//-- AUTOGENERATED FILE -- 1628024438 // clang-format off #pragma once diff --git a/src/javascript/jsc/bindings/headers-replacements.zig b/src/javascript/jsc/bindings/headers-replacements.zig index 015c0eaf3..d58a50459 100644 --- a/src/javascript/jsc/bindings/headers-replacements.zig +++ b/src/javascript/jsc/bindings/headers-replacements.zig @@ -50,3 +50,4 @@ pub const ZigString = bindings.ZigString; pub const ZigException = bindings.ZigException; pub const ResolvedSource = bindings.ResolvedSource; pub const ZigStackTrace = bindings.ZigStackTrace; +pub const ReturnableException = bindings.ReturnableException; diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h index 1ec583f22..6c344cc16 100644 --- a/src/javascript/jsc/bindings/headers.h +++ b/src/javascript/jsc/bindings/headers.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1627967644 +//-- AUTOGENERATED FILE -- 1628024438 // clang-format: off #pragma once @@ -314,14 +314,14 @@ CPP_DECL void JSC__SourceCode__fromString(JSC__SourceCode* arg0, const WTF__Stri #pragma mark - JSC::JSFunction CPP_DECL bWTF__String JSC__JSFunction__calculatedDisplayName(JSC__JSFunction* arg0, JSC__VM* arg1); -CPP_DECL JSC__JSValue JSC__JSFunction__callWithArguments(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue* arg2, size_t arg3, JSC__Exception** arg4, const char* arg5); -CPP_DECL JSC__JSValue JSC__JSFunction__callWithArgumentsAndThis(JSC__JSValue JSValue0, JSC__JSValue JSValue1, JSC__JSGlobalObject* arg2, JSC__JSValue* arg3, size_t arg4, JSC__Exception** arg5, const char* arg6); -CPP_DECL JSC__JSValue JSC__JSFunction__callWithoutAnyArgumentsOrThis(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__Exception** arg2, const char* arg3); -CPP_DECL JSC__JSValue JSC__JSFunction__callWithThis(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2, JSC__Exception** arg3, const char* arg4); -CPP_DECL JSC__JSValue JSC__JSFunction__constructWithArguments(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue* arg2, size_t arg3, JSC__Exception** arg4, const char* arg5); -CPP_DECL JSC__JSValue JSC__JSFunction__constructWithArgumentsAndNewTarget(JSC__JSValue JSValue0, JSC__JSValue JSValue1, JSC__JSGlobalObject* arg2, JSC__JSValue* arg3, size_t arg4, JSC__Exception** arg5, const char* arg6); -CPP_DECL JSC__JSValue JSC__JSFunction__constructWithNewTarget(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2, JSC__Exception** arg3, const char* arg4); -CPP_DECL JSC__JSValue JSC__JSFunction__constructWithoutAnyArgumentsOrNewTarget(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__Exception** arg2, const char* arg3); +CPP_DECL JSC__JSValue JSC__JSFunction__callWithArguments(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue* arg2, size_t arg3, JSC__Exception** arg4, const unsigned char* arg5); +CPP_DECL JSC__JSValue JSC__JSFunction__callWithArgumentsAndThis(JSC__JSValue JSValue0, JSC__JSValue JSValue1, JSC__JSGlobalObject* arg2, JSC__JSValue* arg3, size_t arg4, JSC__Exception** arg5, const unsigned char* arg6); +CPP_DECL JSC__JSValue JSC__JSFunction__callWithoutAnyArgumentsOrThis(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__Exception** arg2, const unsigned char* arg3); +CPP_DECL JSC__JSValue JSC__JSFunction__callWithThis(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2, JSC__Exception** arg3, const unsigned char* arg4); +CPP_DECL JSC__JSValue JSC__JSFunction__constructWithArguments(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue* arg2, size_t arg3, JSC__Exception** arg4, const unsigned char* arg5); +CPP_DECL JSC__JSValue JSC__JSFunction__constructWithArgumentsAndNewTarget(JSC__JSValue JSValue0, JSC__JSValue JSValue1, JSC__JSGlobalObject* arg2, JSC__JSValue* arg3, size_t arg4, JSC__Exception** arg5, const unsigned char* arg6); +CPP_DECL JSC__JSValue JSC__JSFunction__constructWithNewTarget(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2, JSC__Exception** arg3, const unsigned char* arg4); +CPP_DECL JSC__JSValue JSC__JSFunction__constructWithoutAnyArgumentsOrNewTarget(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__Exception** arg2, const unsigned char* arg3); CPP_DECL JSC__JSFunction* JSC__JSFunction__createFromNative(JSC__JSGlobalObject* arg0, uint16_t arg1, const WTF__String* arg2, void* arg3, JSC__JSValue (* ArgFn4)(void* arg0, JSC__JSGlobalObject* arg1, JSC__CallFrame* arg2)); CPP_DECL JSC__JSFunction* JSC__JSFunction__createFromSourceCode(JSC__JSGlobalObject* arg0, const unsigned char* arg1, uint16_t arg2, JSC__JSValue* arg3, uint16_t arg4, const JSC__SourceCode* arg5, JSC__SourceOrigin* arg6, JSC__JSObject** arg7); CPP_DECL bWTF__String JSC__JSFunction__displayName(JSC__JSFunction* arg0, JSC__VM* arg1); diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig index 167d4f944..f18779751 100644 --- a/src/javascript/jsc/bindings/headers.zig +++ b/src/javascript/jsc/bindings/headers.zig @@ -37,64 +37,65 @@ pub const __mbstate_t = extern union { pub const __darwin_mbstate_t = __mbstate_t; pub const __darwin_ptrdiff_t = c_long; pub const __darwin_size_t = c_ulong; - + pub const JSC__RegExpPrototype = struct_JSC__RegExpPrototype; - + pub const JSC__GeneratorPrototype = struct_JSC__GeneratorPrototype; - + pub const JSC__ArrayIteratorPrototype = struct_JSC__ArrayIteratorPrototype; - + pub const JSC__StringPrototype = struct_JSC__StringPrototype; pub const WTF__StringView = bWTF__StringView; - + pub const JSC__JSPromisePrototype = struct_JSC__JSPromisePrototype; pub const JSC__CatchScope = bJSC__CatchScope; pub const JSC__ThrowScope = bJSC__ThrowScope; pub const JSC__PropertyName = bJSC__PropertyName; pub const JSC__JSObject = bJSC__JSObject; pub const WTF__ExternalStringImpl = bWTF__ExternalStringImpl; - + pub const JSC__AsyncIteratorPrototype = struct_JSC__AsyncIteratorPrototype; pub const WTF__StringImpl = bWTF__StringImpl; pub const JSC__JSLock = bJSC__JSLock; pub const JSC__JSModuleLoader = bJSC__JSModuleLoader; pub const JSC__VM = bJSC__VM; - + pub const JSC__AsyncGeneratorPrototype = struct_JSC__AsyncGeneratorPrototype; - + pub const JSC__AsyncGeneratorFunctionPrototype = struct_JSC__AsyncGeneratorFunctionPrototype; pub const JSC__JSGlobalObject = bJSC__JSGlobalObject; pub const JSC__JSFunction = bJSC__JSFunction; - + pub const JSC__ArrayPrototype = struct_JSC__ArrayPrototype; - + pub const JSC__AsyncFunctionPrototype = struct_JSC__AsyncFunctionPrototype; pub const JSC__Identifier = bJSC__Identifier; pub const JSC__JSPromise = bJSC__JSPromise; - + pub const JSC__SetIteratorPrototype = struct_JSC__SetIteratorPrototype; pub const JSC__SourceCode = bJSC__SourceCode; pub const JSC__JSCell = bJSC__JSCell; - + pub const JSC__BigIntPrototype = struct_JSC__BigIntPrototype; - + pub const JSC__GeneratorFunctionPrototype = struct_JSC__GeneratorFunctionPrototype; pub const JSC__SourceOrigin = bJSC__SourceOrigin; pub const JSC__JSModuleRecord = bJSC__JSModuleRecord; pub const WTF__String = bWTF__String; pub const WTF__URL = bWTF__URL; - + + pub const JSC__IteratorPrototype = struct_JSC__IteratorPrototype; pub const JSC__JSInternalPromise = bJSC__JSInternalPromise; - + pub const JSC__FunctionPrototype = struct_JSC__FunctionPrototype; pub const Inspector__ScriptArguments = bInspector__ScriptArguments; pub const JSC__Exception = bJSC__Exception; pub const JSC__JSString = bJSC__JSString; - + pub const JSC__ObjectPrototype = struct_JSC__ObjectPrototype; pub const JSC__CallFrame = bJSC__CallFrame; - + pub const JSC__MapIteratorPrototype = struct_JSC__MapIteratorPrototype; pub extern fn JSC__JSObject__getArrayLength(arg0: [*c]JSC__JSObject) usize; pub extern fn JSC__JSObject__getDirect(arg0: [*c]JSC__JSObject, arg1: [*c]JSC__JSGlobalObject, arg2: ZigString) JSC__JSValue; @@ -149,14 +150,14 @@ pub extern fn JSC__JSInternalPromise__then(arg0: [*c]JSC__JSInternalPromise, arg pub extern fn JSC__SourceOrigin__fromURL(arg0: [*c]const WTF__URL) bJSC__SourceOrigin; pub extern fn JSC__SourceCode__fromString(arg0: [*c]JSC__SourceCode, arg1: [*c]const WTF__String, arg2: [*c]const JSC__SourceOrigin, arg3: [*c]WTF__String, SourceType4: u8) void; pub extern fn JSC__JSFunction__calculatedDisplayName(arg0: [*c]JSC__JSFunction, arg1: [*c]JSC__VM) bWTF__String; -pub extern fn JSC__JSFunction__callWithArguments(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c]JSC__JSValue, arg3: usize, arg4: [*c][*c]JSC__Exception, arg5: [*c]const u8) JSC__JSValue; -pub extern fn JSC__JSFunction__callWithArgumentsAndThis(JSValue0: JSC__JSValue, JSValue1: JSC__JSValue, arg2: [*c]JSC__JSGlobalObject, arg3: [*c]JSC__JSValue, arg4: usize, arg5: [*c][*c]JSC__Exception, arg6: [*c]const u8) JSC__JSValue; -pub extern fn JSC__JSFunction__callWithoutAnyArgumentsOrThis(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c][*c]JSC__Exception, arg3: [*c]const u8) JSC__JSValue; -pub extern fn JSC__JSFunction__callWithThis(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, JSValue2: JSC__JSValue, arg3: [*c][*c]JSC__Exception, arg4: [*c]const u8) JSC__JSValue; -pub extern fn JSC__JSFunction__constructWithArguments(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c]JSC__JSValue, arg3: usize, arg4: [*c][*c]JSC__Exception, arg5: [*c]const u8) JSC__JSValue; -pub extern fn JSC__JSFunction__constructWithArgumentsAndNewTarget(JSValue0: JSC__JSValue, JSValue1: JSC__JSValue, arg2: [*c]JSC__JSGlobalObject, arg3: [*c]JSC__JSValue, arg4: usize, arg5: [*c][*c]JSC__Exception, arg6: [*c]const u8) JSC__JSValue; -pub extern fn JSC__JSFunction__constructWithNewTarget(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, JSValue2: JSC__JSValue, arg3: [*c][*c]JSC__Exception, arg4: [*c]const u8) JSC__JSValue; -pub extern fn JSC__JSFunction__constructWithoutAnyArgumentsOrNewTarget(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c][*c]JSC__Exception, arg3: [*c]const u8) JSC__JSValue; +pub extern fn JSC__JSFunction__callWithArguments(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c]JSC__JSValue, arg3: usize, arg4: *?*JSC__Exception , arg5: [*c]const u8) JSC__JSValue; +pub extern fn JSC__JSFunction__callWithArgumentsAndThis(JSValue0: JSC__JSValue, JSValue1: JSC__JSValue, arg2: [*c]JSC__JSGlobalObject, arg3: [*c]JSC__JSValue, arg4: usize, arg5: *?*JSC__Exception , arg6: [*c]const u8) JSC__JSValue; +pub extern fn JSC__JSFunction__callWithoutAnyArgumentsOrThis(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: *?*JSC__Exception , arg3: [*c]const u8) JSC__JSValue; +pub extern fn JSC__JSFunction__callWithThis(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, JSValue2: JSC__JSValue, arg3: *?*JSC__Exception , arg4: [*c]const u8) JSC__JSValue; +pub extern fn JSC__JSFunction__constructWithArguments(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c]JSC__JSValue, arg3: usize, arg4: *?*JSC__Exception , arg5: [*c]const u8) JSC__JSValue; +pub extern fn JSC__JSFunction__constructWithArgumentsAndNewTarget(JSValue0: JSC__JSValue, JSValue1: JSC__JSValue, arg2: [*c]JSC__JSGlobalObject, arg3: [*c]JSC__JSValue, arg4: usize, arg5: *?*JSC__Exception , arg6: [*c]const u8) JSC__JSValue; +pub extern fn JSC__JSFunction__constructWithNewTarget(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, JSValue2: JSC__JSValue, arg3: *?*JSC__Exception , arg4: [*c]const u8) JSC__JSValue; +pub extern fn JSC__JSFunction__constructWithoutAnyArgumentsOrNewTarget(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: *?*JSC__Exception , arg3: [*c]const u8) JSC__JSValue; pub extern fn JSC__JSFunction__createFromNative(arg0: [*c]JSC__JSGlobalObject, arg1: u16, arg2: [*c]const WTF__String, arg3: ?*c_void, ArgFn4: ?fn (?*c_void, [*c]JSC__JSGlobalObject, [*c]JSC__CallFrame) callconv(.C) JSC__JSValue) [*c]JSC__JSFunction; pub extern fn JSC__JSFunction__createFromSourceCode(arg0: [*c]JSC__JSGlobalObject, arg1: [*c]const u8, arg2: u16, arg3: [*c]JSC__JSValue, arg4: u16, arg5: [*c]const JSC__SourceCode, arg6: [*c]JSC__SourceOrigin, arg7: [*c][*c]JSC__JSObject) [*c]JSC__JSFunction; pub extern fn JSC__JSFunction__displayName(arg0: [*c]JSC__JSFunction, arg1: [*c]JSC__VM) bWTF__String; diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index 9d390d834..9576eed0e 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -50,8 +50,8 @@ pub const VirtualMachine = struct { require_cache: RequireCacheType, log: *logger.Log, event_listeners: EventListenerMixin.Map, - pub threadlocal var vm_loaded = false; - pub threadlocal var vm: *VirtualMachine = undefined; + pub var vm_loaded = false; + pub var vm: *VirtualMachine = undefined; pub fn init( allocator: *std.mem.Allocator, @@ -66,7 +66,7 @@ pub const VirtualMachine = struct { log = try allocator.create(logger.Log); } - vm = try allocator.create(VirtualMachine); + VirtualMachine.vm = try allocator.create(VirtualMachine); var console = try allocator.create(ZigConsoleClient); console.* = ZigConsoleClient.init(Output.errorWriter(), Output.writer()); const bundler = try Bundler.init( @@ -75,7 +75,7 @@ pub const VirtualMachine = struct { try configureTransformOptionsForSpeedy(allocator, _args), existing_bundle, ); - vm.* = VirtualMachine{ + VirtualMachine.vm.* = VirtualMachine{ .global = undefined, .allocator = allocator, .require_cache = RequireCacheType.init(allocator), @@ -86,20 +86,23 @@ pub const VirtualMachine = struct { .log = log, }; - vm.bundler.configureLinker(); + VirtualMachine.vm.bundler.configureLinker(); var global_classes: [GlobalClasses.len]js.JSClassRef = undefined; inline for (GlobalClasses) |Class, i| { global_classes[i] = Class.get().*; } - vm.global = ZigGlobalObject.create( + VirtualMachine.vm.global = ZigGlobalObject.create( &global_classes, @intCast(i32, global_classes.len), vm.console, ); - vm_loaded = true; + VirtualMachine.vm_loaded = true; + std.debug.print("VM IS LOADED {}", .{ + VirtualMachine.vm_loaded, + }); - return vm; + return VirtualMachine.vm; } // dynamic import @@ -110,7 +113,7 @@ pub const VirtualMachine = struct { threadlocal var source_code_printer: js_printer.BufferPrinter = undefined; threadlocal var source_code_printer_loaded: bool = false; - inline fn _fetch( + fn _fetch( global: *JSGlobalObject, specifier: string, source: string, @@ -242,7 +245,7 @@ pub const VirtualMachine = struct { path: string, }; - inline fn _resolve(ret: *ResolveFunctionResult, global: *JSGlobalObject, specifier: string, source: string) !void { + fn _resolve(ret: *ResolveFunctionResult, global: *JSGlobalObject, specifier: string, source: string) !void { std.debug.assert(VirtualMachine.vm_loaded); std.debug.assert(VirtualMachine.vm.global == global); if (vm.node_modules == null and strings.eqlComptime(specifier, Runtime.Runtime.Imports.Name)) { @@ -412,7 +415,30 @@ pub const VirtualMachine = struct { } } - pub fn loadEntryPoint(this: *VirtualMachine, entry_point: string) !void { + // TODO: + pub fn deinit(this: *VirtualMachine) void {} + + pub fn printException(this: *VirtualMachine, exception: *Exception) void { + if (Output.enable_ansi_colors) { + this.printErrorlikeObject(exception.value(), exception, true); + } else { + this.printErrorlikeObject(exception.value(), exception, false); + } + } + + pub fn defaultErrorHandler(this: *VirtualMachine, result: JSValue) void { + if (result.isException(this.global.vm())) { + var exception = @ptrCast(*Exception, result.asVoid()); + + this.printException(exception); + } else if (Output.enable_ansi_colors) { + this.printErrorlikeObject(result, null, true); + } else { + this.printErrorlikeObject(result, null, false); + } + } + + pub fn loadEntryPoint(this: *VirtualMachine, entry_point: string) !*JSInternalPromise { var path = this.bundler.normalizeEntryPointPath(entry_point); var promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(path)); @@ -423,23 +449,7 @@ pub const VirtualMachine = struct { this.global.vm().drainMicrotasks(); } - if (promise.status(this.global.vm()) == JSPromise.Status.Rejected) { - var result = promise.result(this.global.vm()); - - if (result.isException(this.global.vm())) { - var exception = @ptrCast(*Exception, result.asVoid()); - - if (Output.enable_ansi_colors) { - this.printErrorlikeObject(exception.value(), exception, true); - } else { - this.printErrorlikeObject(exception.value(), exception, false); - } - } else if (Output.enable_ansi_colors) { - this.printErrorlikeObject(result, null, true); - } else { - this.printErrorlikeObject(result, null, false); - } - } + return promise; } // When the Error-like object is one of our own, it's best to rely on the object directly instead of serializing it to a ZigException. @@ -797,7 +807,6 @@ pub const EventListenerMixin = struct { .{}, ); - var exception: js.JSValueRef = null; // Rely on JS finalizer var fetch_event = try vm.allocator.create(FetchEvent); fetch_event.* = FetchEvent{ @@ -805,32 +814,37 @@ pub const EventListenerMixin = struct { .request = Request{ .request_context = request_context }, }; - var fetch_args: [1]js.JSObjectRef = undefined; - for (listeners.items) |listener| { - fetch_args[0] = FetchEvent.Class.make(vm.global, fetch_event); - - _ = js.JSObjectCallAsFunction( - vm.ctx, - listener, - js.JSContextGetGlobalObject(vm.ctx), - 1, - &fetch_args, - &exception, - ); + var fetch_args: [1]JSValue = undefined; + var exception: ?*Exception = null; + const failed_str = "Failed"; + for (listeners.items) |listener_ref| { + var listener = @intToEnum(JSValue, @intCast(i64, @ptrToInt(listener_ref))); + + fetch_args[0] = JSValue.fromRef(FetchEvent.Class.make(vm.global.ref(), fetch_event)); + + var promise = JSPromise.resolvedPromise(vm.global, JSFunction.callWithArguments(listener, vm.global, &fetch_args, 1, &exception, failed_str)); + vm.global.vm().drainMicrotasks(); + + 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 { + _ = promise.result(vm.global.vm()); + } + + vm.global.vm().drainMicrotasks(); + if (request_context.has_called_done) { break; } } - if (exception != null) { - var message = js.JSValueToStringCopy(vm.ctx, exception, null); - defer js.JSStringRelease(message); - var buf = vm.allocator.alloc(u8, js.JSStringGetLength(message) + 1) catch unreachable; - defer vm.allocator.free(buf); - var note = buf[0 .. js.JSStringGetUTF8CString(message, buf.ptr, buf.len) - 1]; - - Output.prettyErrorln("<r><red>error<r>: <b>{s}<r>", .{note}); - Output.flush(); + if (exception) |except| { + vm.printException(except); if (!request_context.has_called_done) { request_context.sendInternalError(error.JavaScriptError) catch {}; diff --git a/src/javascript/jsc/webcore/response.zig b/src/javascript/jsc/webcore/response.zig index 2fcbd1d9a..579a8a9fe 100644 --- a/src/javascript/jsc/webcore/response.zig +++ b/src/javascript/jsc/webcore/response.zig @@ -2,7 +2,9 @@ usingnamespace @import("../base.zig"); const std = @import("std"); const Api = @import("../../../api/schema.zig").Api; const http = @import("../../../http.zig"); -const JavaScript = @import("../javascript.zig"); +usingnamespace @import("../javascript.zig"); +usingnamespace @import("../bindings/bindings.zig"); + pub const Response = struct { pub const Class = NewClass( Response, @@ -1089,7 +1091,26 @@ pub const FetchEvent = struct { return js.JSValueMakeUndefined(ctx); } - var arg = arguments[0]; + var resolved = JSInternalPromise.resolvedPromise(VirtualMachine.vm.global, JSValue.fromRef(arguments[0])); + + var status = resolved.status(VirtualMachine.vm.global.vm()); + + if (status == .Pending) { + VirtualMachine.vm.global.vm().drainMicrotasks(); + } + + status = resolved.status(VirtualMachine.vm.global.vm()); + + switch (status) { + .Fulfilled => {}, + else => { + this.request_context.sendInternalError(error.rejectedPromise) catch {}; + return js.JSValueMakeUndefined(ctx); + }, + } + + var arg = resolved.result(VirtualMachine.vm.global.vm()).asObjectRef(); + if (!js.JSValueIsObjectOfClass(ctx, arg, Response.Class.ref)) { JSError(getAllocator(ctx), "event.respondWith() must be a Response or a Promise<Response>.", .{}, ctx, exception); this.request_context.sendInternalError(error.respondWithWasEmpty) catch {}; @@ -1180,3 +1201,67 @@ pub const FetchEvent = struct { return js.JSValueMakeUndefined(ctx); } }; + +// pub const ReadableStream = struct { +// pub const Class = NewClass( +// ReadableStream, +// .{ +// .name = "ReadableStream", +// }, +// .{}, +// .{ + +// }, +// ); +// }; + +// pub const TextEncoder = struct { +// pub const Class = NewClass( +// TextEncoder, +// .{ +// .name = "TextEncoder", +// }, +// .{ +// .encoding = .{ +// .@"get" = getEncoding, +// .ro = true, +// }, +// }, +// .{ +// .encode = .{ +// .rfn = encode, +// }, +// .constructor = .{ +// .rfn = constructor, +// }, +// .encodeInto = .{ +// .rfn = encodeInto, +// }, +// }, +// ); + +// const encoding_str = "utf-8"; +// pub fn getEncoding( +// this: *TextEncoder, +// ctx: js.JSContextRef, +// thisObject: js.JSObjectRef, +// prop: js.JSStringRef, +// exception: js.ExceptionRef, +// ) js.JSValueRef { +// return ZigString.init(encoding_str).toValue(ctx).asRef() +// } +// }; + +// pub const TextDecoder = struct { +// pub const Class = NewClass( +// TextDecoder, +// .{ +// .name = "TextDecoder", +// }, +// .{}, +// .{ +// .decode = .{}, +// .constructor = .{}, +// }, +// ); +// }; diff --git a/src/main.zig b/src/main.zig index 8c19fb3f5..ea21f9599 100644 --- a/src/main.zig +++ b/src/main.zig @@ -14,6 +14,8 @@ usingnamespace @import("global.zig"); const panicky = @import("panic_handler.zig"); const cli = @import("cli.zig"); pub const MainPanicHandler = panicky.NewPanicHandler(panicky.default_panic); +const js = @import("javascript/jsc/bindings/bindings.zig"); +usingnamespace @import("javascript/jsc/javascript.zig"); pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { if (MainPanicHandler.Singleton) |singleton| { @@ -39,4 +41,10 @@ pub fn main() anyerror!void { Output.enable_ansi_colors = stderr.isTty(); defer Output.flush(); try cli.Cli.start(std.heap.c_allocator, stdout, stderr, MainPanicHandler); + + std.mem.doNotOptimizeAway(JavaScriptVirtualMachine.fetch); + std.mem.doNotOptimizeAway(JavaScriptVirtualMachine.init); + std.mem.doNotOptimizeAway(JavaScriptVirtualMachine.resolve); } + +pub const JavaScriptVirtualMachine = VirtualMachine; diff --git a/src/main_javascript.zig b/src/main_javascript.zig index be822c793..97bc012d3 100644 --- a/src/main_javascript.zig +++ b/src/main_javascript.zig @@ -30,8 +30,6 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) nore } } -pub const JSGlobalObject = struct {}; - const constStrToU8 = allocators.constStrToU8; pub fn main() anyerror!void { // The memory allocator makes a massive difference. @@ -386,7 +384,10 @@ pub const Cli = struct { // .entry_point, // ); - try vm.loadEntryPoint(vm.bundler.options.entry_points[0]); + var promise = try vm.loadEntryPoint(vm.bundler.options.entry_points[0]); + if (promise.status(vm.global.vm()) == js.JSPromise.Status.Rejected) { + vm.defaultRejectionHandler(promise.result(vm.global.vm())); + } } }; |
