diff options
Diffstat (limited to 'src/javascript')
-rw-r--r-- | src/javascript/jsc/api/router.zig | 80 | ||||
-rw-r--r-- | src/javascript/jsc/base.zig | 83 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/exports.zig | 22 | ||||
-rw-r--r-- | src/javascript/jsc/javascript.zig | 31 |
4 files changed, 124 insertions, 92 deletions
diff --git a/src/javascript/jsc/api/router.zig b/src/javascript/jsc/api/router.zig index 84dad71ef..6e6fea896 100644 --- a/src/javascript/jsc/api/router.zig +++ b/src/javascript/jsc/api/router.zig @@ -4,10 +4,12 @@ const Api = @import("../../../api/schema.zig").Api; const FilesystemRouter = @import("../../../router.zig"); const http = @import("../../../http.zig"); const JavaScript = @import("../javascript.zig"); - +usingnamespace @import("../bindings/bindings.zig"); usingnamespace @import("../webcore/response.zig"); const Router = @This(); +const VirtualMachine = JavaScript.VirtualMachine; + route: *const FilesystemRouter.Match, file_path_str: js.JSStringRef = null, pathname_str: js.JSStringRef = null, @@ -20,16 +22,13 @@ pub fn importRoute( arguments: []const js.JSValueRef, exception: js.ExceptionRef, ) js.JSObjectRef { - return JavaScript.VirtualMachine.instance.require( - ctx, - std.fs.path.dirname(this.route.file_path).?, - this.route.file_path, - exception, - ); + const prom = JSModuleLoader.loadAndEvaluateModule(VirtualMachine.vm.global, ZigString.init(this.route.file_path)); + VirtualMachine.vm.global.vm().drainMicrotasks(); + return prom.result(VirtualMachine.vm.global.vm()).asRef(); } pub fn match( - obj: *c_void, + obj: void, ctx: js.JSContextRef, function: js.JSObjectRef, thisObject: js.JSObjectRef, @@ -96,10 +95,10 @@ fn createRouteObject(ctx: js.JSContextRef, req: *const http.RequestContext, exce .route = route, }; - return Class.new(ctx, router); + return Instance.make(ctx, router); } -const match_type_definition = &[_]d.ts{ +pub const match_type_definition = &[_]d.ts{ .{ .tsdoc = "Match a {@link https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent FetchEvent} to a `Route` from the local filesystem. Returns `null` if there is no match.", .args = &[_]d.ts.arg{ @@ -132,29 +131,6 @@ const match_type_definition = &[_]d.ts{ }, }; -pub const Class = NewClass( - c_void, - .{ - .name = "Router", - .read_only = true, - .ts = .{ - .module = .{ - .path = "speedy.js/router", - .tsdoc = "Filesystem Router supporting dynamic routes, exact routes, catch-all routes, and optional catch-all routes. Implemented in native code and only available with Speedy.js.", - }, - }, - }, - .{ - .match = .{ - .rfn = match, - .ts = match_type_definition, - }, - }, - .{ - .Route = Instance.GetClass(c_void){}, - }, -); - pub const Instance = NewClass( Router, .{ @@ -249,16 +225,11 @@ pub fn getFilePath( prop: js.JSStringRef, exception: js.ExceptionRef, ) js.JSValueRef { - if (this.file_path_str == null) { - this.file_path_str = js.JSStringCreateWithUTF8CString(this.route.file_path.ptr); - } - - return js.JSValueMakeString(ctx, this.file_path_str); + return ZigString.init(this.route.file_path).toValue(VirtualMachine.vm.global).asRef(); } pub fn finalize( this: *Router, - ctx: js.JSObjectRef, ) void { // this.deinit(); } @@ -270,11 +241,7 @@ pub fn getPathname( prop: js.JSStringRef, exception: js.ExceptionRef, ) js.JSValueRef { - if (this.pathname_str == null) { - this.pathname_str = js.JSStringCreateWithUTF8CString(this.route.pathname.ptr); - } - - return js.JSValueMakeString(ctx, this.pathname_str); + return ZigString.init(this.route.pathname).toValue(VirtualMachine.vm.global).asRef(); } pub fn getRoute( @@ -284,9 +251,28 @@ pub fn getRoute( prop: js.JSStringRef, exception: js.ExceptionRef, ) js.JSValueRef { - return js.JSValueMakeString(ctx, Properties.Refs.default); + return ZigString.init(this.route.name).toValue(VirtualMachine.vm.global).asRef(); } +const KindEnum = struct { + pub const exact = "exact"; + pub const catch_all = "catch-all"; + pub const optional_catch_all = "optional-catch-all"; + pub const dynamic = "dynamic"; + + pub fn init(name: string) ZigString { + if (strings.contains(name, "[[...")) { + return ZigString.init(optional_catch_all); + } else if (strings.contains(name, "[...")) { + return ZigString.init(catch_all); + } else if (strings.contains(name, "[")) { + return ZigString.init(dynamic); + } else { + return ZigString.init(exact); + } + } +}; + pub fn getKind( this: *Router, ctx: js.JSContextRef, @@ -294,7 +280,7 @@ pub fn getKind( prop: js.JSStringRef, exception: js.ExceptionRef, ) js.JSValueRef { - return js.JSValueMakeString(ctx, Properties.Refs.default); + return KindEnum.init(this.route.name).toValue(VirtualMachine.vm.global).asRef(); } pub fn getQuery( @@ -304,5 +290,5 @@ pub fn getQuery( prop: js.JSStringRef, exception: js.ExceptionRef, ) js.JSValueRef { - return js.JSValueMakeString(ctx, Properties.Refs.default); + return ZigString.init(this.route.query_string).toValue(VirtualMachine.vm.global).asRef(); } diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig index 55ce93164..5c2b630e3 100644 --- a/src/javascript/jsc/base.zig +++ b/src/javascript/jsc/base.zig @@ -3,6 +3,7 @@ const std = @import("std"); pub usingnamespace @import("../../global.zig"); usingnamespace @import("./javascript.zig"); usingnamespace @import("./webcore/response.zig"); +const Router = @import("./api/router.zig"); const TaggedPointerTypes = @import("../../tagged_pointer.zig"); const TaggedPointerUnion = TaggedPointerTypes.TaggedPointerUnion; @@ -10,6 +11,11 @@ const TaggedPointerUnion = TaggedPointerTypes.TaggedPointerUnion; pub const ExceptionValueRef = [*c]js.JSValueRef; pub const JSValueRef = js.JSValueRef; +fn ObjectPtrType(comptime Type: type) type { + if (Type == void) return Type; + return *Type; +} + pub const To = struct { pub const JS = struct { pub inline fn str(ref: anytype, val: anytype) js.JSStringRef { @@ -18,11 +24,11 @@ pub const To = struct { pub fn functionWithCallback( comptime ZigContextType: type, - zig: *ZigContextType, + zig: ObjectPtrType(ZigContextType), name: js.JSStringRef, ctx: js.JSContextRef, comptime callback: fn ( - obj: *ZigContextType, + obj: ObjectPtrType(ZigContextType), ctx: js.JSContextRef, function: js.JSObjectRef, thisObject: js.JSObjectRef, @@ -41,7 +47,7 @@ pub const To = struct { pub fn Finalize( comptime ZigContextType: type, comptime ctxfn: fn ( - this: *ZigContextType, + this: ObjectPtrType(ZigContextType), ) void, ) type { return struct { @@ -109,7 +115,7 @@ pub const To = struct { pub fn Callback( comptime ZigContextType: type, comptime ctxfn: fn ( - obj: *ZigContextType, + obj: ObjectPtrType(ZigContextType), ctx: js.JSContextRef, function: js.JSObjectRef, thisObject: js.JSObjectRef, @@ -137,6 +143,15 @@ pub const To = struct { if (arguments) |args| args[0..argumentCount] else &[_]js.JSValueRef{}, exception, ); + } else if (comptime ZigContextType == void) { + return ctxfn( + void{}, + ctx, + function, + thisObject, + if (arguments) |args| args[0..argumentCount] else &[_]js.JSValueRef{}, + exception, + ); } else { return ctxfn( GetJSPrivateData(ZigContextType, function) orelse GetJSPrivateData(ZigContextType, thisObject) orelse return js.JSValueMakeUndefined(ctx), @@ -168,32 +183,6 @@ pub const To = struct { }; }; -pub const RuntimeImports = struct { - pub fn resolve(ctx: js.JSContextRef, str: string) ?js.JSObjectRef { - switch (ModuleList.Map.get(str) orelse ModuleList.none) { - .Router => { - const Router = @import("./api/router.zig"); - return js.JSObjectMake(ctx, Router.Class.get().*, null); - }, - else => { - return null; - }, - } - } - - pub const ModuleList = enum(u8) { - Router = 0, - none = std.math.maxInt(u8), - - pub const Map = std.ComptimeStringMap( - ModuleList, - .{ - .{ "speedy.js/router", ModuleList.Router }, - }, - ); - }; -}; - pub const Properties = struct { pub const UTF8 = struct { pub const module: string = "module"; @@ -751,6 +740,23 @@ pub fn NewClass( } }; + pub fn throwInvalidConstructorError(ctx: js.JSContextRef, obj: js.JSObjectRef, c: usize, a: [*c]const js.JSValueRef, exception: js.ExceptionRef) callconv(.C) js.JSObjectRef { + JSError(getAllocator(ctx), "" ++ name ++ " is not a constructor", .{}, ctx, exception); + return null; + } + + pub fn throwInvalidFunctionError( + ctx: js.JSContextRef, + function: js.JSObjectRef, + thisObject: js.JSObjectRef, + argumentCount: usize, + arguments: [*c]const js.JSValueRef, + exception: js.ExceptionRef, + ) callconv(.C) js.JSValueRef { + JSError(getAllocator(ctx), "" ++ name ++ " is not a function", .{}, ctx, exception); + return null; + } + pub const Constructor = ConstructorWrapper.rfn; pub const static_value_count = static_properties.len; @@ -872,7 +878,7 @@ pub fn NewClass( prop: js.JSStringRef, exception: js.ExceptionRef, ) callconv(.C) js.JSValueRef { - var this = GetJSPrivateData(ZigType, obj) orelse return js.JSValueMakeUndefined(ctx); + var this: ObjectPtrType(ZigType) = if (comptime ZigType == void) void{} else GetJSPrivateData(ZigType, obj) orelse return js.JSValueMakeUndefined(ctx); var exc: js.JSValueRef = null; const Field = @TypeOf(@field( @@ -902,7 +908,7 @@ pub fn NewClass( const Func = @typeInfo(@TypeOf(func)); const WithPropFn = fn ( - *ZigType, + ObjectPtrType(ZigType), js.JSContextRef, js.JSObjectRef, js.JSStringRef, @@ -910,7 +916,7 @@ pub fn NewClass( ) js.JSValueRef; const WithoutPropFn = fn ( - *ZigType, + ObjectPtrType(ZigType), js.JSContextRef, js.JSObjectRef, js.ExceptionRef, @@ -1292,7 +1298,7 @@ pub fn NewClass( const ctxfn = CtxField.rfn; const Func: std.builtin.TypeInfo.Fn = @typeInfo(@TypeOf(ctxfn)).Fn; - const PointerType = std.meta.Child(Func.args[0].arg_type.?); + const PointerType = if (Func.args[0].arg_type.? == void) void else std.meta.Child(Func.args[0].arg_type.?); var callback = if (Func.calling_convention == .C) ctxfn else To.JS.Callback( PointerType, @@ -1361,6 +1367,14 @@ pub fn NewClass( def.className = class_name_str; // def.getProperty = getPropertyCallback; + if (def.callAsConstructor == null) { + def.callAsConstructor = throwInvalidConstructorError; + } + + if (def.callAsFunction == null) { + def.callAsFunction = throwInvalidFunctionError; + } + if (!singleton) def.hasInstance = customHasInstance; return def; @@ -1422,6 +1436,7 @@ pub const JSPrivateDataPtr = TaggedPointerUnion(.{ FetchEvent, Headers, Body, + Router, }); pub inline fn GetJSPrivateData(comptime Type: type, ref: js.JSObjectRef) ?*Type { diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig index 89297aaf6..f1996ae0f 100644 --- a/src/javascript/jsc/bindings/exports.zig +++ b/src/javascript/jsc/bindings/exports.zig @@ -91,16 +91,18 @@ pub const ZigGlobalObject = extern struct { return @call(.{ .modifier = .always_inline }, Interface.onCrash, .{}); } - pub const Export = shim.exportFunctions(.{ - .@"import" = import, - .@"resolve" = resolve, - .@"fetch" = fetch, - // .@"eval" = eval, - .@"promiseRejectionTracker" = promiseRejectionTracker, - .@"reportUncaughtException" = reportUncaughtException, - .@"createImportMetaProperties" = createImportMetaProperties, - .@"onCrash" = onCrash, - }); + pub const Export = shim.exportFunctions( + .{ + .@"import" = import, + .@"resolve" = resolve, + .@"fetch" = fetch, + // .@"eval" = eval, + .@"promiseRejectionTracker" = promiseRejectionTracker, + .@"reportUncaughtException" = reportUncaughtException, + .@"createImportMetaProperties" = createImportMetaProperties, + .@"onCrash" = onCrash, + }, + ); pub const Extern = [_][]const u8{ "create", "getModuleRegistryMap", "resetModuleRegistryMap" }; diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index b681a4cee..1de47d46e 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -18,8 +18,8 @@ usingnamespace @import("./webcore/response.zig"); usingnamespace @import("./config.zig"); usingnamespace @import("./bindings/exports.zig"); usingnamespace @import("./bindings/bindings.zig"); - const Runtime = @import("../../runtime.zig"); +const Router = @import("./api/router.zig"); pub const GlobalClasses = [_]type{ Request.Class, @@ -28,6 +28,34 @@ pub const GlobalClasses = [_]type{ EventListenerMixin.addEventListener(VirtualMachine), BuildError.Class, ResolveError.Class, + Wundle.Class, +}; + +pub const Wundle = struct { + top_level_dir: string, + + pub const Class = NewClass( + void, + .{ + .name = "Wundle", + .read_only = true, + .ts = .{ + .module = .{ + .path = "speedy.js/router", + .tsdoc = "Filesystem Router supporting dynamic routes, exact routes, catch-all routes, and optional catch-all routes. Implemented in native code and only available with Speedy.js.", + }, + }, + }, + .{ + .match = .{ + .rfn = Router.match, + .ts = Router.match_type_definition, + }, + }, + .{ + .Route = Router.Instance.GetClass(void){}, + }, + ); }; pub const LazyClasses = [_]type{}; @@ -317,6 +345,7 @@ pub const VirtualMachine = struct { pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void { var result = ResolveFunctionResult{ .path = "", .result = null }; + _resolve(&result, global, specifier.slice(), source.slice()) catch |err| { // This should almost always just apply to dynamic imports |