aboutsummaryrefslogtreecommitdiff
path: root/src/javascript/jsc/javascript.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-07-28 20:56:29 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-07-28 20:56:29 -0700
commit4a8b2546526e97583a2743d17405f664cbf6a16e (patch)
tree7cfdef87ee13374afc908dd5b0860502036d1c70 /src/javascript/jsc/javascript.zig
parent86296897e55e0c80a3e93e27031e244525fb757c (diff)
downloadbun-4a8b2546526e97583a2743d17405f664cbf6a16e.tar.gz
bun-4a8b2546526e97583a2743d17405f664cbf6a16e.tar.zst
bun-4a8b2546526e97583a2743d17405f664cbf6a16e.zip
esmodules work?
Former-commit-id: 5cb5af4416c12518eb195d1b310990fc5c94d6c8
Diffstat (limited to 'src/javascript/jsc/javascript.zig')
-rw-r--r--src/javascript/jsc/javascript.zig182
1 files changed, 173 insertions, 9 deletions
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 51a287b27..9850f0c6a 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -19,10 +19,13 @@ usingnamespace @import("./config.zig");
usingnamespace @import("./bindings/exports.zig");
usingnamespace @import("./bindings/bindings.zig");
+const Runtime = @import("../../runtime.zig");
+
pub const GlobalClasses = [_]type{
Request.Class,
Response.Class,
Headers.Class,
+ EventListenerMixin.addEventListener(VirtualMachine),
};
pub const Module = struct {
@@ -39,9 +42,11 @@ pub const VirtualMachine = struct {
node_modules: ?*NodeModuleBundle = null,
bundler: Bundler,
watcher: ?*http.Watcher = null,
- console: ZigConsoleClient,
+ console: *ZigConsoleClient,
require_cache: RequireCacheType,
log: *logger.Log,
+ event_listeners: EventListenerMixin.Map,
+ pub threadlocal var vm_loaded = false;
pub threadlocal var vm: *VirtualMachine = undefined;
pub fn init(
@@ -58,21 +63,27 @@ pub const VirtualMachine = struct {
}
vm = try allocator.create(VirtualMachine);
+ var console = try allocator.create(ZigConsoleClient);
+ console.* = ZigConsoleClient.init(Output.errorWriter(), Output.writer());
+
vm.* = VirtualMachine{
.global = undefined,
.allocator = allocator,
.require_cache = RequireCacheType.init(allocator),
+ .event_listeners = EventListenerMixin.Map.init(allocator),
.bundler = try Bundler.init(
allocator,
log,
try configureTransformOptionsForSpeedy(allocator, _args),
existing_bundle,
),
- .console = ZigConsoleClient.init(Output.errorWriter(), Output.writer()),
+ .console = console,
.node_modules = existing_bundle,
.log = log,
};
+ vm.bundler.configureLinker();
+
var global_classes: [GlobalClasses.len]js.JSClassRef = undefined;
inline for (GlobalClasses) |Class, i| {
global_classes[i] = Class.get().*;
@@ -80,11 +91,150 @@ pub const VirtualMachine = struct {
vm.global = ZigGlobalObject.create(
&global_classes,
@intCast(i32, global_classes.len),
- &vm.console,
+ vm.console,
);
+ vm_loaded = true;
return vm;
}
+
+ // dynamic import
+ // pub fn import(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableZigString {
+
+ // }
+
+ threadlocal var source_code_printer: js_printer.BufferPrinter = undefined;
+ threadlocal var source_code_printer_loaded: bool = false;
+
+ inline fn _fetch(global: *JSGlobalObject, specifier: string, source: string) !string {
+ std.debug.assert(VirtualMachine.vm_loaded);
+ std.debug.assert(VirtualMachine.vm.global == global);
+
+ if (strings.eqlComptime(specifier, Runtime.Runtime.Imports.Name)) {
+ return Runtime.Runtime.sourceContent();
+ }
+
+ const result = vm.bundler.resolve_results.get(specifier) orelse return error.MissingResolveResult;
+ const path = result.path_pair.primary;
+ const loader = vm.bundler.options.loaders.get(path.name.ext) orelse .file;
+
+ switch (loader) {
+ .js, .jsx, .ts, .tsx, .json => {
+ vm.bundler.resetStore();
+ const hash = http.Watcher.getHash(path.text);
+
+ var fd: ?StoredFileDescriptorType = null;
+
+ if (vm.watcher) |watcher| {
+ if (watcher.indexOf(hash)) |index| {
+ fd = watcher.watchlist.items(.fd)[index];
+ }
+ }
+
+ var parse_result = vm.bundler.parse(
+ vm.bundler.allocator,
+ path,
+ loader,
+ result.dirname_fd,
+ fd,
+ hash,
+ ) orelse {
+ return error.ParseError;
+ };
+
+ // We _must_ link because:
+ // - node_modules bundle won't be properly
+ try vm.bundler.linker.link(
+ path,
+ &parse_result,
+ .absolute_path,
+ true,
+ );
+
+ if (!source_code_printer_loaded) {
+ var writer = try js_printer.BufferWriter.init(vm.allocator);
+ source_code_printer = js_printer.BufferPrinter.init(writer);
+ source_code_printer.ctx.append_null_byte = false;
+
+ source_code_printer_loaded = true;
+ }
+
+ source_code_printer.ctx.reset();
+
+ var written = try vm.bundler.print(
+ parse_result,
+ @TypeOf(&source_code_printer),
+ &source_code_printer,
+ .esm,
+ );
+
+ if (written == 0) {
+ return error.PrintingErrorWriteFailed;
+ }
+
+ return vm.allocator.dupe(u8, source_code_printer.ctx.written) catch unreachable;
+ },
+ else => {
+ return try strings.quotedAlloc(VirtualMachine.vm.allocator, path.pretty);
+ },
+ }
+ }
+ inline fn _resolve(global: *JSGlobalObject, specifier: string, source: string) !string {
+ std.debug.assert(VirtualMachine.vm_loaded);
+ std.debug.assert(VirtualMachine.vm.global == global);
+ if (strings.eqlComptime(specifier, Runtime.Runtime.Imports.Name)) {
+ return Runtime.Runtime.Imports.Name;
+ }
+
+ const result: resolver.Result = vm.bundler.resolve_results.get(specifier) orelse brk: {
+ // We don't want to write to the hash table if there's an error
+ // That's why we don't use getOrPut here
+ const res = try vm.bundler.resolver.resolve(
+ Fs.PathName.init(source).dirWithTrailingSlash(),
+ specifier,
+ .stmt,
+ );
+ try vm.bundler.resolve_results.put(res.path_pair.primary.text, res);
+ break :brk res;
+ };
+
+ return result.path_pair.primary.text;
+ }
+
+ pub fn resolve(global: *JSGlobalObject, specifier: ZigString, source: ZigString) ErrorableZigString {
+ const result = _resolve(global, specifier.slice(), source.slice()) catch |err| {
+ return ErrorableZigString.errFmt(err, "ResolveError {s} for \"{s}\"\nfrom\"{s}\"", .{
+ @errorName(err),
+ specifier.slice(),
+ source.slice(),
+ });
+ };
+
+ return ErrorableZigString.ok(ZigString.init(result));
+ }
+
+ pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) ErrorableZigString {
+ const result = _fetch(global, specifier.slice(), source.slice()) catch |err| {
+ return ErrorableZigString.errFmt(err, "{s}: \"{s}\"", .{
+ @errorName(err),
+ specifier.slice(),
+ });
+ };
+
+ return ErrorableZigString.ok(ZigString.init(result));
+ }
+
+ pub fn loadEntryPoint(this: *VirtualMachine, entry_point: string) !void {
+ var path = this.bundler.normalizeEntryPointPath(entry_point);
+
+ var promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(path));
+
+ this.global.vm().drainMicrotasks();
+ if (promise.status(this.global.vm()) == JSPromise.Status.Rejected) {
+ var str = promise.result(this.global.vm()).toWTFString(this.global);
+ Output.prettyErrorln("<r><red>Error<r>: <b>{s}<r>", .{str.slice()});
+ }
+ }
};
pub const Object = struct {
@@ -216,13 +366,14 @@ pub const EventListenerMixin = struct {
) type {
const Handler = struct {
pub fn addListener(
- ptr: *Struct,
ctx: js.JSContextRef,
function: js.JSObjectRef,
thisObject: js.JSObjectRef,
- arguments: []const js.JSValueRef,
+ argumentCount: usize,
+ _arguments: [*c]const js.JSValueRef,
exception: js.ExceptionRef,
- ) js.JSValueRef {
+ ) callconv(.C) js.JSValueRef {
+ const arguments = _arguments[0 .. argumentCount - 1];
if (arguments.len == 0 or arguments.len == 1 or !js.JSValueIsString(ctx, arguments[0]) or !js.JSValueIsObject(ctx, arguments[arguments.len - 1]) or !js.JSObjectIsFunction(ctx, arguments[arguments.len - 1])) {
return js.JSValueMakeUndefined(ctx);
}
@@ -235,10 +386,10 @@ pub const EventListenerMixin = struct {
const name_used_len = js.JSStringGetUTF8CString(arguments[0], &event_listener_names_buf, event_listener_names_buf.len);
const name = event_listener_names_buf[0 .. name_used_len - 1];
const event = EventType.match(name) orelse return js.JSValueMakeUndefined(ctx);
- var entry = VirtualMachine.instance.event_listeners.getOrPut(event) catch unreachable;
+ var entry = VirtualMachine.vm.event_listeners.getOrPut(event) catch unreachable;
if (!entry.found_existing) {
- entry.value_ptr.* = List.initCapacity(VirtualMachine.instance.allocator, 1) catch unreachable;
+ entry.value_ptr.* = List.initCapacity(VirtualMachine.vm.allocator, 1) catch unreachable;
}
var callback = arguments[arguments.len - 1];
@@ -249,6 +400,19 @@ pub const EventListenerMixin = struct {
}
};
- return Handler;
+ return NewClass(
+ Struct,
+ .{
+ .name = "addEventListener",
+ .read_only = true,
+ },
+ .{
+ .@"callAsFunction" = .{
+ .rfn = Handler.addListener,
+ .ts = d.ts{},
+ },
+ },
+ .{},
+ );
}
};