diff options
author | 2021-07-28 10:56:36 -0700 | |
---|---|---|
committer | 2021-07-28 10:56:36 -0700 | |
commit | 68fa7ec2d0bc3549b398929ad9794783be451b7c (patch) | |
tree | feb1331ea93b6f69905f250269f72452304b0c6c /src | |
parent | d18ff76912f6c4522132adfb7c0af1db7c5b6726 (diff) | |
download | bun-68fa7ec2d0bc3549b398929ad9794783be451b7c.tar.gz bun-68fa7ec2d0bc3549b398929ad9794783be451b7c.tar.zst bun-68fa7ec2d0bc3549b398929ad9794783be451b7c.zip |
WIP
Former-commit-id: 60cc85dc0652b34e9c7ec409f32ba635cc4b2e51
Diffstat (limited to 'src')
-rw-r--r-- | src/javascript/jsc/bindings/ZigGlobalObject.cpp | 119 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/bindings.zig | 32 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/exports.zig | 197 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/header-gen.zig | 82 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers-cpp.h | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers.h | 16 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/headers.zig | 2 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/helpers.h | 85 | ||||
-rw-r--r-- | src/javascript/jsc/config.zig | 120 | ||||
-rw-r--r-- | src/javascript/jsc/javascript.zig | 106 | ||||
-rw-r--r-- | src/javascript/jsc/new.zig | 99 | ||||
-rw-r--r-- | src/main_javascript.zig | 5 | ||||
-rw-r--r-- | src/watcher.zig | 6 |
13 files changed, 650 insertions, 221 deletions
diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp index ec998b192..af975e79e 100644 --- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp +++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp @@ -123,59 +123,100 @@ JSC::Identifier GlobalObject::moduleLoaderResolve( ) { auto res = Zig__GlobalObject__resolve( globalObject, - loader, - JSValue::encode(key), - JSValue::encode(referrer), - nullptr + toZigString(key, globalObject), + toZigString(referrer, globalObject) ); - return toIdentifier(res, globalObject); + if (res.success) { + return toIdentifier(res.result.value, globalObject); + } else { + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + throwException(scope, res.result.err.message, globalObject); + return globalObject->vm().propertyNames->emptyIdentifier; + } + } -JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, JSModuleLoader* loader, JSString* specifierValue, JSValue referrer, const SourceOrigin& sourceOrigin) { - return Zig__GlobalObject__import( - globalObject, - loader, - specifierValue, - JSC::JSValue::encode(referrer), - &sourceOrigin - ); +JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin& sourceOrigin) +{ + JSC::VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); + RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope)); + + auto sourceURL = sourceOrigin.url(); + auto resolved = Zig__GlobalObject__resolve(globalObject, toZigString(moduleNameValue, globalObject), sourceURL.isEmpty() ? ZigStringCwd : toZigString(sourceURL.fileSystemPath())); + if (!resolved.success) { + throwException(scope, resolved.result.err.message, globalObject); + return promise->rejectWithCaughtException(globalObject, scope); + } + + auto result = JSC::importModule(globalObject, toIdentifier(resolved.result.value, globalObject), parameters, JSC::jsUndefined()); + RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope)); + + return result; } + JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, JSModuleLoader* loader, JSValue key, JSValue value1, JSValue value2) { - return Zig__GlobalObject__fetch( - globalObject, - loader, - JSValue::encode(key), - JSValue::encode(value1), - JSValue::encode(value2) - ); -} + JSC::VM& vm = globalObject->vm(); + JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); -JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, JSModuleLoader* loader, JSValue key, JSModuleRecord* record, JSValue val) { - auto res = Zig__GlobalObject__createImportMetaProperties( + auto scope = DECLARE_THROW_SCOPE(vm); + + auto rejectWithError = [&](JSC::JSValue error) { + promise->reject(globalObject, error); + return promise; + }; + + auto moduleKey = key.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope)); + auto moduleKeyZig = toZigString(moduleKey); + + auto res = Zig__GlobalObject__fetch( globalObject, - loader, - JSValue::encode(key), - record, - JSValue::encode(val) + moduleKeyZig, + ZigStringEmpty ); - return JSValue::decode(res).getObject(); -} + if (!res.success) { + throwException(scope, res.result.err.message, globalObject); + RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope)); + } -JSC::JSValue GlobalObject::moduleLoaderEvaluate(JSGlobalObject* globalObject, JSModuleLoader* moduleLoader, JSValue key, JSValue moduleRecordValue, JSValue scriptFetcher, JSValue sentValue, JSValue resumeMode) { - auto res = Zig__GlobalObject__eval( - globalObject, - moduleLoader, - JSValue::encode(key), - JSValue::encode(moduleRecordValue), - JSValue::encode(scriptFetcher), - JSValue::encode(sentValue), - JSValue::encode(resumeMode) + auto code = Zig::toString(res.result.value); + auto sourceCode = JSC::JSSourceCode::create( + vm, + JSC::makeSource( + code, + JSC::SourceOrigin { WTF::URL::fileURLWithFileSystemPath(moduleKey) }, + WTFMove(moduleKey), + TextPosition(), + JSC::SourceProviderSourceType::Module + ) ); - return JSValue::decode(res); + scope.release(); + promise->resolve(globalObject, sourceCode); + return promise; +} + +JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, JSModuleLoader* loader, JSValue key, JSModuleRecord* record, JSValue val) { + return nullptr; + // auto res = Zig__GlobalObject__createImportMetaProperties( + // globalObject, + // loader, + // JSValue::encode(key), + // record, + // JSValue::encode(val) + // ); + + // return JSValue::decode(res).getObject(); } +JSC::JSValue GlobalObject::moduleLoaderEvaluate(JSGlobalObject* globalObject, JSModuleLoader* moduleLoader, JSValue key, JSValue moduleRecordValue, JSValue scriptFetcher, JSValue sentValue, JSValue resumeMode) { + // VM& vm = globalObject->vm(); + return moduleLoader->evaluateNonVirtual(globalObject, key, moduleRecordValue, scriptFetcher, sentValue, resumeMode); +} }
\ No newline at end of file diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig index 6547d3160..0e585d49f 100644 --- a/src/javascript/jsc/bindings/bindings.zig +++ b/src/javascript/jsc/bindings/bindings.zig @@ -38,11 +38,15 @@ pub const ZigString = extern struct { ptr: [*]const u8, len: usize, - pub fn init(slice: []const u8) ZigString { - return ZigString{ .ptr = slice.ptr, .len = slice.len }; + pub fn init(slice_: []const u8) ZigString { + return ZigString{ .ptr = slice_.ptr, .len = slice_.len }; } pub const Empty = ZigString{ .ptr = "", .len = 0 }; + + pub fn slice(this: *const ZigString) []const u8 { + return this.ptr[0..this.len]; + } }; pub const JSCell = extern struct { @@ -168,29 +172,23 @@ pub const ScriptArguments = extern struct { pub fn NewGlobalObject(comptime Type: type) type { return struct { - pub fn import(global: *JSGlobalObject, loader: *JSModuleLoader, specifier: *JSString, referrer: JSValue, origin: *const SourceOrigin) callconv(.C) *JSInternalPromise { + pub fn import(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString { if (comptime @hasDecl(Type, "import")) { - return @call(.{ .modifier = .always_inline }, Interface.import, .{ global, loader, specifier, referrer, origin }); + return @call(.{ .modifier = .always_inline }, Interface.import, .{ global, specifier, source }); } - return JSInternalPromise.rejectedPromise(global, JSValue.jsUndefined()); + return ErrorableZigString.err(error.ImportFailed, "Import not implemented"); } - pub fn resolve(global: *JSGlobalObject, loader: *JSModuleLoader, specifier: JSValue, value: JSValue, origin: *const SourceOrigin) callconv(.C) ZigString { + pub fn resolve(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString { if (comptime @hasDecl(Type, "resolve")) { - return @call(.{ .modifier = .always_inline }, Interface.resolve, .{ global, loader, specifier, value, origin }); + return @call(.{ .modifier = .always_inline }, Interface.resolve, .{ global, specifier, source }); } - return ZigString.Empty; + return ErrorableZigString.err(error.ResolveFailed, "resolve not implemented"); } - pub fn fetch(global: *JSGlobalObject, loader: *JSModuleLoader, value1: JSValue, value2: JSValue, value3: JSValue) callconv(.C) *JSInternalPromise { + pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString { if (comptime @hasDecl(Type, "fetch")) { - return @call(.{ .modifier = .always_inline }, Interface.fetch, .{ global, loader, value1, value2, value3 }); + return @call(.{ .modifier = .always_inline }, Interface.fetch, .{ global, specifier, source }); } - return JSInternalPromise.rejectedPromise(global, JSValue.jsUndefined()); - } - pub fn eval(global: *JSGlobalObject, loader: *JSModuleLoader, key: JSValue, moduleRecordValue: JSValue, scriptFetcher: JSValue, awaitedValue: JSValue, resumeMode: JSValue) callconv(.C) JSValue { - if (comptime @hasDecl(Type, "eval")) { - return @call(.{ .modifier = .always_inline }, Interface.eval, .{ global, loader, key, moduleRecordValue, scriptFetcher, awaitedValue, resumeMode }); - } - return JSValue.jsUndefined(); + return ErrorableZigString.err(error.FetchFailed, "Module fetch not implemented"); } pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue { if (comptime @hasDecl(Type, "promiseRejectionTracker")) { diff --git a/src/javascript/jsc/bindings/exports.zig b/src/javascript/jsc/bindings/exports.zig index 199c181fc..e573c60b4 100644 --- a/src/javascript/jsc/bindings/exports.zig +++ b/src/javascript/jsc/bindings/exports.zig @@ -1,5 +1,7 @@ usingnamespace @import("./bindings.zig"); usingnamespace @import("./shared.zig"); +usingnamespace @import("../new.zig"); +const Fs = @import("../../../fs.zig"); const Handler = struct { pub export fn global_signal_handler_fn(sig: i32, info: *const std.os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void { @@ -32,31 +34,26 @@ pub const ZigGlobalObject = extern struct { return shim.cppFn("create", .{ vm, console }); } - pub fn import(global: *JSGlobalObject, loader: *JSModuleLoader, specifier: *JSString, referrer: JSValue, origin: *const SourceOrigin) callconv(.C) *JSInternalPromise { - // if (comptime is_bindgen) { - // unreachable; - // } - - return @call(.{ .modifier = .always_inline }, Interface.import, .{ global, loader, specifier, referrer, origin }); - } - pub fn resolve(global: *JSGlobalObject, loader: *JSModuleLoader, specifier: JSValue, value: JSValue, origin: *const SourceOrigin) callconv(.C) ZigString { + pub fn import(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString { if (comptime is_bindgen) { unreachable; } - return @call(.{ .modifier = .always_inline }, Interface.resolve, .{ global, loader, specifier, value, origin }); + + return @call(.{ .modifier = .always_inline }, Interface.import, .{ global, specifier, source }); } - pub fn fetch(global: *JSGlobalObject, loader: *JSModuleLoader, value1: JSValue, value2: JSValue, value3: JSValue) callconv(.C) *JSInternalPromise { + pub fn resolve(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString { if (comptime is_bindgen) { unreachable; } - return @call(.{ .modifier = .always_inline }, Interface.fetch, .{ global, loader, value1, value2, value3 }); + return @call(.{ .modifier = .always_inline }, Interface.resolve, .{ global, specifier, source }); } - pub fn eval(global: *JSGlobalObject, loader: *JSModuleLoader, key: JSValue, moduleRecordValue: JSValue, scriptFetcher: JSValue, awaitedValue: JSValue, resumeMode: JSValue) callconv(.C) JSValue { + pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString { if (comptime is_bindgen) { unreachable; } - return @call(.{ .modifier = .always_inline }, Interface.eval, .{ global, loader, key, moduleRecordValue, scriptFetcher, awaitedValue, resumeMode }); + return @call(.{ .modifier = .always_inline }, Interface.fetch, .{ global, specifier, source }); } + pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue { if (comptime is_bindgen) { unreachable; @@ -89,7 +86,7 @@ pub const ZigGlobalObject = extern struct { .@"import" = import, .@"resolve" = resolve, .@"fetch" = fetch, - .@"eval" = eval, + // .@"eval" = eval, .@"promiseRejectionTracker" = promiseRejectionTracker, .@"reportUncaughtException" = reportUncaughtException, .@"createImportMetaProperties" = createImportMetaProperties, @@ -102,14 +99,78 @@ pub const ZigGlobalObject = extern struct { @export(import, .{ .name = Export[0].symbol_name }); @export(resolve, .{ .name = Export[1].symbol_name }); @export(fetch, .{ .name = Export[2].symbol_name }); - @export(eval, .{ .name = Export[3].symbol_name }); - @export(promiseRejectionTracker, .{ .name = Export[4].symbol_name }); - @export(reportUncaughtException, .{ .name = Export[5].symbol_name }); - @export(createImportMetaProperties, .{ .name = Export[6].symbol_name }); - @export(onCrash, .{ .name = Export[7].symbol_name }); + @export(promiseRejectionTracker, .{ .name = Export[3].symbol_name }); + @export(reportUncaughtException, .{ .name = Export[4].symbol_name }); + @export(createImportMetaProperties, .{ .name = Export[5].symbol_name }); + @export(onCrash, .{ .name = Export[6].symbol_name }); + } +}; + +const ErrorCodeInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8); +pub const ErrorCode = enum(ErrorCodeInt) { + _, + + pub inline fn from(code: anyerror) ErrorCode { + return @intToEnum(ErrorCode, @errorToInt(code)); } + + pub const Type = switch (@sizeOf(anyerror)) { + 0, 1 => u8, + 2 => u16, + 3 => u32, + 4 => u64, + else => @compileError("anyerror is too big"), + }; }; +pub const ZigErrorType = extern struct { + code: ErrorCode, + message: ZigString, +}; + +pub fn Errorable(comptime Type: type) type { + return extern struct { + result: Result, + success: bool, + pub const name = "Errorable" ++ @typeName(Type); + + pub const Result = extern union { + value: Type, + err: ZigErrorType, + }; + + pub fn value(val: Type) @This() { + return @This(){ .result = .{ .value = val }, .success = true }; + } + + pub fn ok(val: Type) @This() { + return @This(){ .result = .{ .value = val }, .success = true }; + } + + threadlocal var err_buf: [4096]u8 = undefined; + pub fn errFmt(code: anyerror, comptime fmt: []const u8, args: anytype) @This() { + const message = std.fmt.bufPrint(&err_buf, fmt, args) catch @errorName(code); + + return @call(.{ .modifier = .always_inline }, err, .{ code, message }); + } + + pub fn err(code: anyerror, msg: []const u8) @This() { + return @This(){ + .result = .{ + .err = .{ + .code = ErrorCode.from(code), + .message = ZigString.init(msg), + }, + }, + .success = false, + }; + } + }; +} + +pub const ErrorableZigString = Errorable(ZigString); +pub const ErrorableJSValue = Errorable(JSValue); + pub const ZigConsoleClient = struct { pub const shim = Shimmer("Zig", "ConsoleClient", @This()); pub const Type = *c_void; @@ -131,13 +192,11 @@ pub const ZigConsoleClient = struct { error_writer: BufferedWriter, writer: BufferedWriter, - pub fn init(allocator: *std.mem.Allocator) !*ZigConsoleClient { - var console = try allocator.create(ZigConsoleClient); - console.* = ZigConsoleClient{ - .error_writer = BufferedWriter{ .unbuffered_writer = Output.errorWriter() }, - .writer = BufferedWriter{ .unbuffered_writer = Output.writer() }, + pub fn init(error_writer: Output.WriterType, writer: Output.WriterType) ZigConsoleClient { + return ZigConsoleClient{ + .error_writer = BufferedWriter{ .unbuffered_writer = error_writer }, + .writer = BufferedWriter{ .unbuffered_writer = writer }, }; - return console; } pub fn messageWithTypeAndLevel( @@ -241,3 +300,91 @@ pub const ZigConsoleClient = struct { }); } }; + +// pub const CommonJSModuleConstructor = struct { +// pub const shim = Shimmer("Zig", "CommonJSModuleConstructor", @This()); +// pub const name = "Zig::CommonJSModuleConstructor"; +// pub const include = "\"CommonJSModule.h\""; +// pub const namespace = shim.namespace; + +// pub fn construct(global: *JSGlobalObject, module: *CommonJSModule) callconv(.C) ErrorableJSValue {} +// }; + +// pub const CommonJSModulePrototype = struct { +// pub const shim = Shimmer("Zig", "CommonJSModulePrototype", @This()); +// pub const name = "Zig::CommonJSModulePrototype"; +// pub const include = "\"CommonJSModule.h\""; +// pub const namespace = shim.namespace; + +// bytes: shim.Bytes, +// }; + +// pub const CommonJSModule = struct { +// pub const shim = Shimmer("Zig", "CommonJSModule", @This()); +// pub const Type = *c_void; +// pub const name = "Zig::CommonJSModule"; +// pub const include = "\"CommonJSModule.h\""; +// pub const namespace = shim.namespace; + +// path: Fs.Path, +// reload_pending: bool = false, + +// exports: JSValue, +// instance: *CommonJSModulePrototype, +// loaded: bool = false, + +// pub fn finishLoading(module: *CommonJSModule, global: *JSGlobalObject, exports: JSValue, instance: *CommonJSModulePrototype) callconv(.C) ErrorableJSValue { +// module.loaded = true; +// module.instance = instance; +// module.exports = exports; +// } + +// pub fn onCallRequire(module: *CommonJSModule, global: *JSGlobalObject, input: []const u8) callconv(.C) ErrorableJSValue { +// const resolve = ModuleLoader.resolve(global, input, module) catch |err| { +// return ErrorableJSValue.errFmt( +// err, +// "ResolveError: {s} while resolving \"{s}\"\nfrom \"{s}\"", +// .{ +// @errorName(err), +// input, +// module.path.pretty, +// }, +// ); +// }; + +// const hash = ModuleLoader.hashid(resolve.path_pair.primary.text); +// var reload_pending = false; +// if (ModuleLoader.require_cache.get(hash)) |obj| { +// reload_pending = obj.reload_pending; + +// return ErrorableJSValue.ok(obj.exports); +// } + +// const result = ModuleLoader.load(global, resolve) catch |err| { +// return ErrorableJSValue.errFmt( +// err, +// "LoadError: {s} while loading \"{s}\"", +// .{ +// @errorName(err), +// input, +// module.path.pretty, +// }, +// ); +// }; + +// switch (result) { +// .value => |value| { +// return value; +// }, +// .module => |mod| { +// return ErrorableJSValue.ok(mod.exports); +// }, +// .bundled_module_export => |bundled_module_export| { +// return ErrorableJSValue.ok(bundled_module_export); +// }, +// .path => |path| { +// return ErrorableJSValue.ok(ZigString.init(path.text).toJSValue(global)); +// }, +// } +// } +// }; diff --git a/src/javascript/jsc/bindings/header-gen.zig b/src/javascript/jsc/bindings/header-gen.zig index a0790ce31..f6cbb1b2a 100644 --- a/src/javascript/jsc/bindings/header-gen.zig +++ b/src/javascript/jsc/bindings/header-gen.zig @@ -218,7 +218,12 @@ pub const C_Generator = struct { // } } - pub fn gen_struct(self: *Self, comptime name: []const u8, comptime meta: StructMeta) void { + pub fn gen_struct( + self: *Self, + comptime name: []const u8, + comptime meta: StructMeta, + comptime static_types: anytype, + ) void { self.write("typedef struct "); if (meta.layout == .Packed) @@ -232,9 +237,27 @@ pub const C_Generator = struct { const info = @typeInfo(field.field_type); if (info == .Array) { - self.writeType(info.Array.child); + const PrintType = comptime brk: { + for (static_types) |static_type| { + if (static_type.Type == info.Array.child) { + break :brk static_type.Type; + } + } + + break :brk info.Array.child; + }; + self.writeType(PrintType); } else { - self.writeType(field.field_type); + const PrintType = comptime brk: { + for (static_types) |static_type| { + if (static_type.Type == field.field_type) { + break :brk static_type.Type; + } + } + + break :brk field.field_type; + }; + self.writeType(PrintType); } self.write(" " ++ field.name); @@ -245,7 +268,7 @@ pub const C_Generator = struct { self.write(";\n"); } - self.write("} " ++ name ++ "_t;\n\n"); + self.write("} " ++ name ++ ";\n\n"); } pub fn gen_enum( @@ -276,17 +299,20 @@ pub const C_Generator = struct { self: *Self, comptime name: []const u8, comptime meta: UnionMeta, + comptime static_types: anytype, ) void { self.write("typedef union "); self.write(name ++ " {\n"); - inline for (meta.fields) |field| { + inline for (meta.fields) |field, i| { self.write(" "); - self.writeType(field.field_type); + + self.writeType(comptime FieldType); + self.write(" " ++ field.name ++ ";\n"); } - self.write("} " ++ name ++ "_t;\n\n"); + self.write("} " ++ name ++ ";\n\n"); } fn writeType( @@ -515,16 +541,7 @@ pub fn HeaderGen(comptime import: type, comptime fname: []const u8) type { Enum, ); }, - .Struct => |Struct| { - gen.gen_struct(decl.name, Struct, file); - }, - .Union => |Union| { - const layout = Union.layout; - gen.gen_union( - prefix ++ "__" ++ name, - Union, - ); - }, + .Fn => |func| { // if (func.) { // blocked by https://github.com/ziglang/zig/issues/8259 @@ -575,8 +592,11 @@ pub fn HeaderGen(comptime import: type, comptime fname: []const u8) type { \\#define CPP_DECL AUTO_EXTERN_C \\#define CPP_SIZE AUTO_EXTERN_C \\ - \\ + \\typedef uint16_t ZigErrorCode; \\typedef struct ZigString { const unsigned char* ptr; size_t len; } ZigString; + \\typedef struct ZigErrorType { ZigErrorCode code; ZigString message; } ZigErrorType; + \\typedef union ErrorableZigStringResult { ZigString value; ZigErrorType err; } ErrorableZigStringResult; + \\typedef struct ErrorableZigString { ErrorableZigStringResult result; bool success; } ErrorableZigString; \\ ) catch {}; @@ -601,13 +621,36 @@ pub fn HeaderGen(comptime import: type, comptime fname: []const u8) type { var impl_fourth_buffer = std.ArrayList(u8).init(std.heap.c_allocator); var impl_fourth_writer = impl_fourth_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); + // defer gen.deinit(); + + // switch (@typeInfo(Type)) { + // .Enum => |Enum| { + // gen.gen_enum( + // static_extern.name, + // Enum, + // ); + // }, + // .Union => |Union| { + // gen.gen_union(static_extern.name, Union, import.all_static_externs); + // }, + // .Struct => |Struct| { + // gen.gen_struct(static_extern.name, Struct, import.all_static_externs); + // }, + // else => {}, + // } + // } + var to_get_sizes: usize = 0; inline for (all_decls) |_decls| { if (comptime _decls.is_pub) { switch (_decls.data) { .Type => |Type| { @setEvalBranchQuota(99999); - const is_container_type = switch (@typeInfo(Type)) { + const TypeTypeInfo: std.builtin.TypeInfo = @typeInfo(Type); + const is_container_type = switch (TypeTypeInfo) { .Opaque, .Struct, .Enum => true, else => false, }; @@ -708,6 +751,7 @@ pub fn HeaderGen(comptime import: type, comptime fname: []const u8) type { } } } + impl.writer().print("\nconst size_t sizes[{d}] = {{", .{to_get_sizes}) catch unreachable; impl.writeAll(impl_third_buffer.items) catch unreachable; impl.writeAll("};\n") catch unreachable; diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h index 024969a3d..da84fd8ba 100644 --- a/src/javascript/jsc/bindings/headers-cpp.h +++ b/src/javascript/jsc/bindings/headers-cpp.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1627423545 +//-- AUTOGENERATED FILE -- 1627447221 #pragma once #include <stddef.h> diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h index d2675c4f0..bc92c8ad5 100644 --- a/src/javascript/jsc/bindings/headers.h +++ b/src/javascript/jsc/bindings/headers.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1627423545 +//-- AUTOGENERATED FILE -- 1627447221 #pragma once #include <stddef.h> @@ -14,8 +14,11 @@ #define CPP_DECL AUTO_EXTERN_C #define CPP_SIZE AUTO_EXTERN_C - +typedef uint16_t ZigErrorCode; typedef struct ZigString { const unsigned char* ptr; size_t len; } ZigString; +typedef struct ZigErrorType { ZigErrorCode code; ZigString message; } ZigErrorType; +typedef union ErrorableZigStringResult { ZigString value; ZigErrorType err; } ErrorableZigStringResult; +typedef struct ErrorableZigString { ErrorableZigStringResult result; bool success; } ErrorableZigString; typedef struct bJSC__JSModuleRecord { unsigned char bytes[216]; } bJSC__JSModuleRecord; typedef char* bJSC__JSModuleRecord_buf; typedef struct bJSC__ThrowScope { unsigned char bytes[8]; } bJSC__ThrowScope; @@ -78,6 +81,7 @@ typedef struct ZigString { const unsigned char* ptr; size_t len; } ZigString; typedef bJSC__ThrowScope JSC__ThrowScope; // JSC::ThrowScope typedef bJSC__PropertyName JSC__PropertyName; // JSC::PropertyName typedef bJSC__JSObject JSC__JSObject; // JSC::JSObject + typedef ErrorableZigString ErrorableZigString; typedef bWTF__ExternalStringImpl WTF__ExternalStringImpl; // WTF::ExternalStringImpl typedef struct JSC__AsyncIteratorPrototype JSC__AsyncIteratorPrototype; // JSC::AsyncIteratorPrototype typedef bWTF__StringImpl WTF__StringImpl; // WTF::StringImpl @@ -164,6 +168,7 @@ typedef struct ZigString { const unsigned char* ptr; size_t len; } ZigString; class ScriptArguments; } + typedef ErrorableZigString ErrorableZigString; typedef int64_t JSC__JSValue; using JSC__JSCell = JSC::JSCell; using JSC__Exception = JSC::Exception; @@ -531,13 +536,12 @@ CPP_DECL JSC__JSGlobalObject* Zig__GlobalObject__create(JSC__VM* arg0, void* arg #ifdef __cplusplus ZIG_DECL JSC__JSValue Zig__GlobalObject__createImportMetaProperties(JSC__JSGlobalObject* arg0, JSC__JSModuleLoader* arg1, JSC__JSValue JSValue2, JSC__JSModuleRecord* arg3, JSC__JSValue JSValue4); -ZIG_DECL JSC__JSValue Zig__GlobalObject__eval(JSC__JSGlobalObject* arg0, JSC__JSModuleLoader* arg1, JSC__JSValue JSValue2, JSC__JSValue JSValue3, JSC__JSValue JSValue4, JSC__JSValue JSValue5, JSC__JSValue JSValue6); -ZIG_DECL JSC__JSInternalPromise* Zig__GlobalObject__fetch(JSC__JSGlobalObject* arg0, JSC__JSModuleLoader* arg1, JSC__JSValue JSValue2, JSC__JSValue JSValue3, JSC__JSValue JSValue4); -ZIG_DECL JSC__JSInternalPromise* Zig__GlobalObject__import(JSC__JSGlobalObject* arg0, JSC__JSModuleLoader* arg1, JSC__JSString* arg2, JSC__JSValue JSValue3, const JSC__SourceOrigin* arg4); +ZIG_DECL ErrorableZigString Zig__GlobalObject__fetch(JSC__JSGlobalObject* arg0, ZigString arg1, ZigString arg2); +ZIG_DECL ErrorableZigString Zig__GlobalObject__import(JSC__JSGlobalObject* arg0, ZigString arg1, ZigString arg2); ZIG_DECL void Zig__GlobalObject__onCrash(); ZIG_DECL JSC__JSValue Zig__GlobalObject__promiseRejectionTracker(JSC__JSGlobalObject* arg0, JSC__JSPromise* arg1, uint32_t JSPromiseRejectionOperation2); ZIG_DECL JSC__JSValue Zig__GlobalObject__reportUncaughtException(JSC__JSGlobalObject* arg0, JSC__Exception* arg1); -ZIG_DECL ZigString Zig__GlobalObject__resolve(JSC__JSGlobalObject* arg0, JSC__JSModuleLoader* arg1, JSC__JSValue JSValue2, JSC__JSValue JSValue3, const JSC__SourceOrigin* arg4); +ZIG_DECL ErrorableZigString Zig__GlobalObject__resolve(JSC__JSGlobalObject* arg0, ZigString arg1, ZigString arg2); #endif diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig index 2e4b8af66..879c887d2 100644 --- a/src/javascript/jsc/bindings/headers.zig +++ b/src/javascript/jsc/bindings/headers.zig @@ -37,7 +37,7 @@ 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; diff --git a/src/javascript/jsc/bindings/helpers.h b/src/javascript/jsc/bindings/helpers.h index d4907ad72..591f9e4e4 100644 --- a/src/javascript/jsc/bindings/helpers.h +++ b/src/javascript/jsc/bindings/helpers.h @@ -1,11 +1,14 @@ - #include "headers.h" #include "root.h" #include <JavaScriptCore/JSCInlines.h> #include <JavaScriptCore/VM.h> #include <JavaScriptCore/Identifier.h> - +#include <JavaScriptCore/JSValue.h> +#include <JavaScriptCore/JSString.h> +#include <JavaScriptCore/ThrowScope.h> +#include <JavaScriptCore/Error.h> +#include <JavaScriptCore/Exception.h> template<class CppType, typename ZigType> class Wrap { @@ -83,6 +86,11 @@ static const JSC::ArgList makeArgs(JSC__JSValue* v, size_t count) { return JSC::ArgList(args); } +namespace Zig { + + + + static const JSC::Identifier toIdentifier(ZigString str, JSC::JSGlobalObject* global) { if (str.len == 0 || str.ptr == nullptr) { return JSC::Identifier::EmptyIdentifier; @@ -99,3 +107,76 @@ static const WTF::String toString(ZigString str) { return WTF::String(WTF::StringImpl::createWithoutCopying(str.ptr, str.len)); } +static const JSC::JSString* toJSString(ZigString str, JSC::JSGlobalObject* global) { + return JSC::jsOwnedString(global->vm(), toString(str)); +} + +static const ZigString ZigStringEmpty = ZigString{nullptr, 0}; +static const unsigned char __dot_char = '.'; +static const ZigString ZigStringCwd = ZigString{&__dot_char, 1}; + + + +static ZigString toZigString(WTF::String str) { + return str.isEmpty() ? ZigStringEmpty : ZigString{ str.characters8(), str.length() }; +} + + +static ZigString toZigString(WTF::String* str) { + return str->isEmpty() ? ZigStringEmpty : ZigString{ str->characters8(), str->length() }; +} + + +static ZigString toZigString(WTF::StringImpl& str) { + return str.isEmpty() ? ZigStringEmpty : ZigString{ str.characters8(), str.length() }; +} + +static ZigString toZigString(WTF::StringView& str) { + return str.isEmpty() ? ZigStringEmpty : ZigString{ str.characters8(), str.length() }; +} + +static ZigString toZigString(JSC::JSString& str, JSC::JSGlobalObject *global) { + return toZigString(str.value(global)); +} + + +static ZigString toZigString(JSC::JSString* str, JSC::JSGlobalObject *global) { + return toZigString(str->value(global)); +} + + +static ZigString toZigString(JSC::Identifier& str, JSC::JSGlobalObject *global) { + return toZigString(str.string()); +} + +static ZigString toZigString(JSC::Identifier* str, JSC::JSGlobalObject *global) { + return toZigString(str->string()); +} + + + +static void throwException(JSC::ThrowScope& scope, ZigString msg, JSC::JSGlobalObject* global) { + auto str = toJSString(msg, global); + scope.throwException(global, JSC::Exception::create(global->vm(), JSC::JSValue(str))); +} + + + +static ZigString toZigString(JSC::JSValue val, JSC::JSGlobalObject* global) { + auto scope = DECLARE_THROW_SCOPE(global->vm()); + WTF::String str = val.toWTFString(global); + + if (scope.exception()) { + scope.clearException(); + scope.release(); + return ZigStringEmpty; + } + + scope.release(); + + + return toZigString(str); +} + + +}
\ No newline at end of file diff --git a/src/javascript/jsc/config.zig b/src/javascript/jsc/config.zig new file mode 100644 index 000000000..0eabd5995 --- /dev/null +++ b/src/javascript/jsc/config.zig @@ -0,0 +1,120 @@ +const std = @import("std"); + +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 logger = @import("../../logger.zig"); +const Api = @import("../../api/schema.zig").Api; +const options = @import("../../options.zig"); +const Bundler = @import("../../bundler.zig").ServeBundler; +const js_printer = @import("../../js_printer.zig"); +const hash_map = @import("../../hash_map.zig"); +const http = @import("../../http.zig"); + +usingnamespace @import("./node_env_buf_map.zig"); + +pub const DefaultSpeedyDefines = struct { + pub const Keys = struct { + const window = "window"; + }; + pub const Values = struct { + const window = "undefined"; + }; +}; + +pub fn configureTransformOptionsForSpeedy(allocator: *std.mem.Allocator, _args: Api.TransformOptions) !Api.TransformOptions { + var args = _args; + + args.platform = Api.Platform.speedy; + args.serve = false; + args.write = false; + args.resolve = Api.ResolveMode.lazy; + args.generate_node_module_bundle = false; + + // We inline process.env.* at bundle time but process.env is a proxy object which will otherwise return undefined. + + var env_map = try getNodeEnvMap(allocator); + var env_count = env_map.count(); + + if (args.define) |def| { + for (def.keys) |key| { + env_count += @boolToInt((env_map.get(key) == null)); + } + } + var needs_node_env = env_map.get("NODE_ENV") == null; + var needs_window_undefined = true; + + var needs_regenerate = args.define == null and env_count > 0; + if (args.define) |def| { + if (def.keys.len != env_count) { + needs_regenerate = true; + } + for (def.keys) |key| { + if (strings.eql(key, "process.env.NODE_ENV")) { + needs_node_env = false; + } else if (strings.eql(key, "window")) { + needs_window_undefined = false; + } + } + } + + var extras_count = @intCast(usize, @boolToInt(needs_node_env)) + @intCast(usize, @boolToInt(needs_window_undefined)); + + if (needs_regenerate) { + var new_list = try allocator.alloc([]const u8, env_count * 2 + extras_count * 2); + var keys = new_list[0 .. new_list.len / 2]; + var values = new_list[keys.len..]; + var new_map = Api.StringMap{ + .keys = keys, + .values = values, + }; + var iter = env_map.iterator(); + + var last: usize = 0; + while (iter.next()) |entry| { + keys[last] = entry.key_ptr.*; + var value = entry.value_ptr.*; + + if (value.len == 0 or value[0] != '"' or value[value.len - 1] != '"') { + value = try std.fmt.allocPrint(allocator, "\"{s}\"", .{value}); + } + values[last] = value; + last += 1; + } + + if (args.define) |def| { + var from_env = keys[0..last]; + + for (def.keys) |pre, i| { + if (env_map.get(pre) != null) { + for (from_env) |key, j| { + if (strings.eql(key, pre)) { + values[j] = def.values[i]; + } + } + } else { + keys[last] = pre; + values[last] = def.values[i]; + last += 1; + } + } + } + + if (needs_node_env) { + keys[last] = options.DefaultUserDefines.NodeEnv.Key; + values[last] = options.DefaultUserDefines.NodeEnv.Value; + last += 1; + } + + if (needs_window_undefined) { + keys[last] = DefaultSpeedyDefines.Keys.window; + values[last] = DefaultSpeedyDefines.Values.window; + last += 1; + } + + args.define = new_map; + } + + return args; +} diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index 04e7a9d80..c8ce409af 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -15,111 +15,7 @@ const http = @import("../../http.zig"); usingnamespace @import("./node_env_buf_map.zig"); usingnamespace @import("./base.zig"); usingnamespace @import("./webcore/response.zig"); - -const DefaultSpeedyDefines = struct { - pub const Keys = struct { - const window = "window"; - }; - pub const Values = struct { - const window = "undefined"; - }; -}; - -pub fn configureTransformOptionsForSpeedy(allocator: *std.mem.Allocator, _args: Api.TransformOptions) !Api.TransformOptions { - var args = _args; - - args.platform = Api.Platform.speedy; - args.serve = false; - args.write = false; - args.resolve = Api.ResolveMode.lazy; - args.generate_node_module_bundle = false; - - // We inline process.env.* at bundle time but process.env is a proxy object which will otherwise return undefined. - - var env_map = try getNodeEnvMap(allocator); - var env_count = env_map.count(); - - if (args.define) |def| { - for (def.keys) |key| { - env_count += @boolToInt((env_map.get(key) == null)); - } - } - var needs_node_env = env_map.get("NODE_ENV") == null; - var needs_window_undefined = true; - - var needs_regenerate = args.define == null and env_count > 0; - if (args.define) |def| { - if (def.keys.len != env_count) { - needs_regenerate = true; - } - for (def.keys) |key| { - if (strings.eql(key, "process.env.NODE_ENV")) { - needs_node_env = false; - } else if (strings.eql(key, "window")) { - needs_window_undefined = false; - } - } - } - - var extras_count = @intCast(usize, @boolToInt(needs_node_env)) + @intCast(usize, @boolToInt(needs_window_undefined)); - - if (needs_regenerate) { - var new_list = try allocator.alloc([]const u8, env_count * 2 + extras_count * 2); - var keys = new_list[0 .. new_list.len / 2]; - var values = new_list[keys.len..]; - var new_map = Api.StringMap{ - .keys = keys, - .values = values, - }; - var iter = env_map.iterator(); - - var last: usize = 0; - while (iter.next()) |entry| { - keys[last] = entry.key_ptr.*; - var value = entry.value_ptr.*; - - if (value.len == 0 or value[0] != '"' or value[value.len - 1] != '"') { - value = try std.fmt.allocPrint(allocator, "\"{s}\"", .{value}); - } - values[last] = value; - last += 1; - } - - if (args.define) |def| { - var from_env = keys[0..last]; - - for (def.keys) |pre, i| { - if (env_map.get(pre) != null) { - for (from_env) |key, j| { - if (strings.eql(key, pre)) { - values[j] = def.values[i]; - } - } - } else { - keys[last] = pre; - values[last] = def.values[i]; - last += 1; - } - } - } - - if (needs_node_env) { - keys[last] = options.DefaultUserDefines.NodeEnv.Key; - values[last] = options.DefaultUserDefines.NodeEnv.Value; - last += 1; - } - - if (needs_window_undefined) { - keys[last] = DefaultSpeedyDefines.Keys.window; - values[last] = DefaultSpeedyDefines.Values.window; - last += 1; - } - - args.define = new_map; - } - - return args; -} +usingnamespace @import("./config.zig"); // 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 diff --git a/src/javascript/jsc/new.zig b/src/javascript/jsc/new.zig new file mode 100644 index 000000000..377558287 --- /dev/null +++ b/src/javascript/jsc/new.zig @@ -0,0 +1,99 @@ +const std = @import("std"); + +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 logger = @import("../../logger.zig"); +const Api = @import("../../api/schema.zig").Api; +const options = @import("../../options.zig"); +const Bundler = @import("../../bundler.zig").ServeBundler; +const js_printer = @import("../../js_printer.zig"); +const hash_map = @import("../../hash_map.zig"); +const http = @import("../../http.zig"); + +usingnamespace @import("./node_env_buf_map.zig"); +usingnamespace @import("./config.zig"); +usingnamespace @import("./bindings/bindings.zig"); +usingnamespace @import("./bindings/exports.zig"); + +pub const VirtualMachine = struct { + global: *JSGlobalObject, + allocator: *std.mem.Allocator, + node_modules: ?*NodeModuleBundle = null, + bundler: Bundler, + watcher: ?*http.Watcher = null, + console: ZigConsoleClient, + pub threadlocal var vm: *VirtualMachine = undefined; + + pub fn init( + allocator: *std.mem.Allocator, + _args: Api.TransformOptions, + existing_bundle: ?*NodeModuleBundle, + _log: ?*logger.Log, + ) !*VirtualMachine { + var log: *logger.Log = undefined; + if (_log) |__log| { + log = __log; + } else { + log = try allocator.create(logger.Log); + } + + vm = try allocator.create(VirtualMachine); + vm.* = VirtualMachine{ + .global = undefined, + .allocator = allocator, + .bundler = try Bundler.init( + allocator, + log, + try configureTransformOptionsForSpeedy(allocator, _args), + existing_bundle, + ), + .console = ZigConsoleClient.init(Output.errorWriter(), Output.writer()), + .node_modules = existing_bundle, + .log = log, + }; + + vm.global = js.ZigGlobalObject.create(null, &vm.console); + return vm; + } +}; + +pub const ModuleLoader = struct { + pub threadlocal var global_error_buf: [4096]u8 = undefined; + pub const RequireCacheType = std.AutoHashMap(http.Watcher.HashType, *CommonJSModule); + pub threadlocal var require_cache: RequireCacheType = undefined; + pub fn require(global: *JSGlobalObject, input: []const u8, from: *CommonJSModule) anyerror!resolver.Result {} + + pub inline fn hashid(input: []const u8) http.Watcher.HashType { + return http.Watcher.getHash(input); + } + + pub inline fn resolve(global: *JSGlobalObject, input: []const u8, from: *CommonJSModule) anyerror!resolver.Result { + std.debug.assert(global == VirtualMachine.vm.global); + return try VirtualMachine.vm.bundler.resolver.resolve(input, from.path.dirWithTrailingSlash(), .require); + } + + inline fn _requireResolve(global: *JSGlobalObject, specifier: []const u8, referrer: []const u8) anyerror![]const u8 { + std.debug.assert(global == VirtualMachine.vm.global); + var result: resolver.Result = try VirtualMachine.vm.bundler.resolver.resolve(specifier, Fs.PathName.init(referrer).dirWithTrailingSlash(), .import); + + return result.path_pair.primary.text; + } + + pub fn load(global: *JSGlobalObject, ) + + pub fn requireResolve(global: *JSGlobalObject, specifier: ZigString, referrer: ZigString) ErrorableZigString { + return _requireResolve(global, specifier.slice(), referrer.slice()) catch |err| { + return ErrorableZigString.err(err, std.fmt.bufPrint( + &global_error_buf, + "Resolve failed: {s} while resolving \"{s}\" in \"{s}\"", + .{ + @errorName(err), + specifier.slice(), + referrer.slice(), + }, + ) catch "ResolveError"); + }; + } +}; diff --git a/src/main_javascript.zig b/src/main_javascript.zig index a5f0ef13e..091ef3414 100644 --- a/src/main_javascript.zig +++ b/src/main_javascript.zig @@ -366,7 +366,6 @@ pub const Cli = struct { pub const src = "import Bacon from \"import-test\";\n\nconsole.log('hi'); \"HELLO\";"; }; pub fn demo(allocator: *std.mem.Allocator) !void { - var console = try js.ZigConsoleClient.init(allocator); var global: *js.JSGlobalObject = js.ZigGlobalObject.create(null, console); var exception = js.JSValue.jsUndefined(); @@ -410,6 +409,4 @@ pub const Cli = struct { } }; -pub const JavaScript = struct { - -}; +pub const JavaScript = struct {}; diff --git a/src/watcher.zig b/src/watcher.zig index 50d86781d..82ff530f6 100644 --- a/src/watcher.zig +++ b/src/watcher.zig @@ -70,8 +70,10 @@ pub fn NewWatcher(comptime ContextType: type) type { allocator: *std.mem.Allocator, watchloop_handle: ?std.Thread.Id = null, - pub fn getHash(filepath: string) u32 { - return @truncate(u32, std.hash.Wyhash.hash(0, filepath)); + pub const HashType = u32; + + pub fn getHash(filepath: string) HashType { + return @truncate(HashType, std.hash.Wyhash.hash(0, filepath)); } pub fn init(ctx: ContextType, fs: *Fs.FileSystem, allocator: *std.mem.Allocator) !*Watcher { |