aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cache.zig15
-rw-r--r--src/javascript/jsc/javascript.zig114
-rw-r--r--src/javascript/jsc/webcore/response.zig2
-rw-r--r--src/js_ast.zig12
-rw-r--r--src/js_parser/js_parser.zig11
5 files changed, 103 insertions, 51 deletions
diff --git a/src/cache.zig b/src/cache.zig
index 3a3429105..25acce57a 100644
--- a/src/cache.zig
+++ b/src/cache.zig
@@ -48,6 +48,7 @@ pub const Set = struct {
.js = JavaScript.init(allocator),
.fs = Fs{
.shared_buffer = MutableString.init(allocator, 0) catch unreachable,
+ .macro_shared_buffer = MutableString.init(allocator, 0) catch unreachable,
},
.json = Json{},
};
@@ -57,6 +58,18 @@ pub const Fs = struct {
const Entry = FsCacheEntry;
shared_buffer: MutableString,
+ macro_shared_buffer: MutableString,
+
+ is_macro_mode: bool = false,
+
+ // When we are in a macro, the shared buffer may be in use by the in-progress macro.
+ // so we have to dynamically switch it out.
+ pub inline fn sharedBuffer(this: *Fs) *MutableString {
+ return if (!this.is_macro_mode)
+ &this.shared_buffer
+ else
+ &this.macro_shared_buffer;
+ }
pub fn deinit(c: *Fs) void {
var iter = c.entries.iterator();
@@ -138,7 +151,7 @@ pub const Fs = struct {
}
}
- const file = rfs.readFileWithHandle(path, null, file_handle, use_shared_buffer, &c.shared_buffer) catch |err| {
+ const file = rfs.readFileWithHandle(path, null, file_handle, use_shared_buffer, c.sharedBuffer()) catch |err| {
if (Environment.isDebug) {
Output.printError("{s}: readFile error -- {s}", .{ path, @errorName(err) });
}
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index 043bc7aea..d571def15 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -837,57 +837,81 @@ pub const VirtualMachine = struct {
origin_timer: std.time.Timer = undefined,
- ready_tasks_count: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0),
- pending_tasks_count: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0),
- microtasks_queue: std.ArrayList(Task) = std.ArrayList(Task).init(default_allocator),
-
- pub fn enqueueTask(this: *VirtualMachine, task: Task) !void {
- _ = this.pending_tasks_count.fetchAdd(1, .Monotonic);
- try this.microtasks_queue.append(task);
- }
-
- pub fn tick(this: *VirtualMachine) void {
- while (this.eventLoopTick() > 0) {}
- }
-
- pub fn waitForTasks(this: *VirtualMachine) void {
- while (this.pending_tasks_count.load(.Monotonic) > 0 or this.ready_tasks_count.load(.Monotonic) > 0) {
- while (this.eventLoopTick() > 0) {}
- }
+ macro_event_loop: EventLoop = EventLoop{},
+ regular_event_loop: EventLoop = EventLoop{},
+
+ pub inline fn eventLoop(this: *VirtualMachine) *EventLoop {
+ return if (this.macro_mode)
+ return &this.macro_event_loop
+ else
+ return &this.regular_event_loop;
}
- // 👶👶👶 event loop 👶👶👶
- pub fn eventLoopTick(this: *VirtualMachine) u32 {
- var finished: u32 = 0;
- var i: usize = 0;
- while (i < this.microtasks_queue.items.len) {
- var task: Task = this.microtasks_queue.items[i];
- switch (task.tag()) {
- .Microtask => {
- var micro: *Microtask = task.get(Microtask).?;
- _ = this.microtasks_queue.swapRemove(i);
- _ = this.pending_tasks_count.fetchSub(1, .Monotonic);
- micro.run(this.global);
-
- finished += 1;
- continue;
- },
- .FetchTasklet => {
- var fetch_task: *Fetch.FetchTasklet = task.get(Fetch.FetchTasklet).?;
- if (fetch_task.status == .done) {
- _ = this.ready_tasks_count.fetchSub(1, .Monotonic);
+ const EventLoop = struct {
+ ready_tasks_count: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0),
+ pending_tasks_count: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0),
+ tasks: std.ArrayList(Task) = std.ArrayList(Task).init(default_allocator),
+
+ pub fn tickWithCount(this: *EventLoop) u32 {
+ var finished: u32 = 0;
+ var i: usize = 0;
+ var global = VirtualMachine.vm.global;
+ while (i < this.tasks.items.len) {
+ var task: Task = this.tasks.items[i];
+ switch (task.tag()) {
+ .Microtask => {
+ var micro: *Microtask = task.get(Microtask).?;
+ _ = this.tasks.swapRemove(i);
_ = this.pending_tasks_count.fetchSub(1, .Monotonic);
- _ = this.microtasks_queue.swapRemove(i);
- fetch_task.onDone();
+ micro.run(global);
+
finished += 1;
continue;
- }
- },
- else => unreachable,
+ },
+ .FetchTasklet => {
+ var fetch_task: *Fetch.FetchTasklet = task.get(Fetch.FetchTasklet).?;
+ if (fetch_task.status == .done) {
+ _ = this.ready_tasks_count.fetchSub(1, .Monotonic);
+ _ = this.pending_tasks_count.fetchSub(1, .Monotonic);
+ _ = this.tasks.swapRemove(i);
+ fetch_task.onDone();
+ finished += 1;
+ continue;
+ }
+ },
+ else => unreachable,
+ }
+ i += 1;
}
- i += 1;
+ return finished;
}
- return finished;
+
+ pub fn tick(this: *EventLoop) void {
+ while (this.tickWithCount() > 0) {}
+ }
+
+ pub fn waitForTasks(this: *EventLoop) void {
+ while (this.pending_tasks_count.load(.Monotonic) > 0 or this.ready_tasks_count.load(.Monotonic) > 0) {
+ while (this.tickWithCount() > 0) {}
+ }
+ }
+
+ pub fn enqueueTask(this: *EventLoop, task: Task) !void {
+ _ = this.pending_tasks_count.fetchAdd(1, .Monotonic);
+ try this.tasks.append(task);
+ }
+ };
+
+ pub inline fn enqueueTask(this: *VirtualMachine, task: Task) !void {
+ try this.eventLoop().enqueueTask(task);
+ }
+
+ pub fn tick(this: *VirtualMachine) void {
+ while (this.eventLoop().tickWithCount() > 0) {}
+ }
+
+ pub fn waitForTasks(this: *VirtualMachine) void {
+ this.eventLoop().waitForTasks();
}
pub const MacroMap = std.AutoArrayHashMap(i32, js.JSObjectRef);
@@ -897,12 +921,14 @@ pub const VirtualMachine = struct {
pub fn enableMacroMode(this: *VirtualMachine) void {
this.bundler.options.platform = .bun_macro;
+ this.bundler.resolver.caches.fs.is_macro_mode = true;
this.macro_mode = true;
Analytics.Features.macros = true;
}
pub fn disableMacroMode(this: *VirtualMachine) void {
this.bundler.options.platform = .bun;
+ this.bundler.resolver.caches.fs.is_macro_mode = false;
this.macro_mode = false;
}
diff --git a/src/javascript/jsc/webcore/response.zig b/src/javascript/jsc/webcore/response.zig
index cb87f2e98..035b6b9e9 100644
--- a/src/javascript/jsc/webcore/response.zig
+++ b/src/javascript/jsc/webcore/response.zig
@@ -637,7 +637,7 @@ pub const Fetch = struct {
pub fn callback(http_: *HTTPClient.AsyncHTTP, sender: *HTTPClient.AsyncHTTP.HTTPSender) void {
var task: *FetchTasklet = @fieldParentPtr(FetchTasklet, "http", http_);
@atomicStore(Status, &task.status, Status.done, .Monotonic);
- _ = task.javascript_vm.ready_tasks_count.fetchAdd(1, .Monotonic);
+ _ = task.javascript_vm.eventLoop().ready_tasks_count.fetchAdd(1, .Monotonic);
sender.release();
}
};
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 55e7ff48d..e4d130f8d 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -3898,7 +3898,7 @@ pub const Macro = struct {
}
macro.vm.enableMacroMode();
defer macro.vm.disableMacroMode();
- return Macro.Runner.run(
+ return try Macro.Runner.run(
macro,
log,
default_allocator,
@@ -6725,6 +6725,8 @@ pub const Macro = struct {
threadlocal var args_buf: [2]js.JSObjectRef = undefined;
threadlocal var expr_nodes_buf: [1]JSNode = undefined;
threadlocal var exception_holder: Zig.ZigException.Holder = undefined;
+ pub const MacroError = error{MacroFailed};
+
pub fn run(
macro: Macro,
_: *logger.Log,
@@ -6736,7 +6738,7 @@ pub const Macro = struct {
id: i32,
comptime Visitor: type,
visitor: Visitor,
- ) Expr {
+ ) MacroError!Expr {
if (comptime Environment.isDebug) Output.prettyln("<r><d>[macro]<r> call <d><b>{s}<r>", .{function_name});
exception_holder = Zig.ZigException.Holder.init();
@@ -6755,9 +6757,13 @@ pub const Macro = struct {
var promise = JSC.JSPromise.resolvedPromise(macro.vm.global, result);
_ = macro.vm.tick();
+ while (promise.status(macro.vm.global.vm()) == .Pending) {
+ macro.vm.tick();
+ }
+
if (promise.status(macro.vm.global.vm()) == .Rejected) {
macro.vm.defaultErrorHandler(promise.result(macro.vm.global.vm()), null);
- return caller;
+ return error.MacroFailed;
}
const value = promise.result(macro.vm.global.vm());
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index 55b3f9449..3a64fd79b 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -6154,7 +6154,7 @@ pub fn NewParser(
}
}
- const macro_remap = if (FeatureFlags.is_macro_enabled and !is_macro and jsx_transform_type != .macro)
+ const macro_remap = if ((comptime FeatureFlags.is_macro_enabled and jsx_transform_type != .macro) and !is_macro)
p.options.macro_context.getRemap(path.text)
else
null;
@@ -12195,7 +12195,14 @@ pub fn NewParser(
name,
MacroVisitor,
MacroVisitor{ .p = p, .loc = expr.loc },
- ) catch return expr;
+ ) catch |err| {
+ if (err == error.MacroFailed) {
+ p.log.addError(p.source, expr.loc, "error in macro") catch unreachable;
+ } else {
+ p.log.addErrorFmt(p.source, expr.loc, p.allocator, "{s} error in macro", .{@errorName(err)}) catch unreachable;
+ }
+ return expr;
+ };
if (macro_result.data != .e_call) {
return p.visitExpr(macro_result);