Former-commit-id: 60cc85dc0652b34e9c7ec409f32ba635cc4b2e51
This commit is contained in:
Jarred Sumner
2021-07-28 10:56:36 -07:00
parent d18ff76912
commit 68fa7ec2d0
14 changed files with 660 additions and 222 deletions

9
docs/module-system.md Normal file
View File

@@ -0,0 +1,9 @@
# Modules (JavaScript Runtime Environment)
This is about the JavaScript Runtime Environment, so this doesn't apply when bundling for Node.js or Web.
The JavaScript Runtime treats modules as close as possible to what it does on the web.
That means:
- Modules are always transformed to ES Modules

View File

@@ -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(
JSC::VM& vm = globalObject->vm();
JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
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),
JSValue::encode(value1),
JSValue::encode(value2)
moduleKeyZig,
ZigStringEmpty
);
if (!res.success) {
throwException(scope, res.result.err.message, globalObject);
RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
}
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
)
);
scope.release();
promise->resolve(globalObject, sourceCode);
return promise;
}
JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, JSModuleLoader* loader, JSValue key, JSModuleRecord* record, JSValue val) {
auto res = Zig__GlobalObject__createImportMetaProperties(
globalObject,
loader,
JSValue::encode(key),
record,
JSValue::encode(val)
);
return nullptr;
// auto res = Zig__GlobalObject__createImportMetaProperties(
// globalObject,
// loader,
// JSValue::encode(key),
// record,
// JSValue::encode(val)
// );
return JSValue::decode(res).getObject();
// return JSValue::decode(res).getObject();
}
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)
);
return JSValue::decode(res);
// VM& vm = globalObject->vm();
return moduleLoader->evaluateNonVirtual(globalObject, key, moduleRecordValue, scriptFetcher, sentValue, resumeMode);
}
}

View File

@@ -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")) {

View File

@@ -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;
// }
pub fn import(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString {
if (comptime is_bindgen) {
unreachable;
}
return @call(.{ .modifier = .always_inline }, Interface.import, .{ global, loader, specifier, referrer, origin });
return @call(.{ .modifier = .always_inline }, Interface.import, .{ global, specifier, source });
}
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 is_bindgen) {
unreachable;
}
return @call(.{ .modifier = .always_inline }, Interface.resolve, .{ global, loader, specifier, value, origin });
return @call(.{ .modifier = .always_inline }, Interface.resolve, .{ global, specifier, source });
}
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 is_bindgen) {
unreachable;
}
return @call(.{ .modifier = .always_inline }, Interface.fetch, .{ global, loader, value1, value2, value3 });
}
pub fn eval(global: *JSGlobalObject, loader: *JSModuleLoader, key: JSValue, moduleRecordValue: JSValue, scriptFetcher: JSValue, awaitedValue: JSValue, resumeMode: JSValue) callconv(.C) JSValue {
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));
// },
// }
// }
// };

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
//-- AUTOGENERATED FILE -- 1627423545
//-- AUTOGENERATED FILE -- 1627447221
#pragma once
#include <stddef.h>

View File

@@ -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

File diff suppressed because one or more lines are too long

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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");
};
}
};

View File

@@ -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 {};

View File

@@ -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 {