diff options
author | 2021-12-18 21:07:07 -0800 | |
---|---|---|
committer | 2021-12-18 21:07:07 -0800 | |
commit | 0cee57f1d997fe21e519d5e771df0877ab489d5f (patch) | |
tree | 417d044ebbc47cc9b6ef49213620c07ae2927e0a /src/javascript/jsc/javascript.zig | |
parent | d1783babd99ff2a8020765837b3b9b3099137024 (diff) | |
parent | eab99b3bae9a810d76e6eb16afd9fb32cd7672bd (diff) | |
download | bun-0cee57f1d997fe21e519d5e771df0877ab489d5f.tar.gz bun-0cee57f1d997fe21e519d5e771df0877ab489d5f.tar.zst bun-0cee57f1d997fe21e519d5e771df0877ab489d5f.zip |
Merge pull request #80 from Jarred-Sumner/jarred/npm-install
bun install
Diffstat (limited to 'src/javascript/jsc/javascript.zig')
-rw-r--r-- | src/javascript/jsc/javascript.zig | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index 03ef373f7..d864c2d17 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -727,6 +727,13 @@ pub const Module = struct { reload_pending: bool = false, }; +const FetchTasklet = Fetch.FetchTasklet; +const TaggedPointerUnion = @import("../../tagged_pointer.zig").TaggedPointerUnion; +pub const Task = TaggedPointerUnion(.{ + FetchTasklet, + Microtask, +}); + // 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 // Its unavailable on Linux @@ -762,6 +769,52 @@ 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 { + this.global.vm().drainMicrotasks(); + _ = this.eventLoopTick(); + } + + // 👶👶👶 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); + 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); + _ = this.microtasks_queue.swapRemove(i); + fetch_task.onDone(); + finished += 1; + continue; + } + }, + else => unreachable, + } + i += 1; + } + return finished; + } + pub const MacroMap = std.AutoArrayHashMap(i32, js.JSObjectRef); pub threadlocal var vm_loaded = false; @@ -1212,7 +1265,15 @@ pub const VirtualMachine = struct { ret.path = result_path.text; } + pub fn queueMicrotaskToEventLoop( + global: *JSGlobalObject, + microtask: *Microtask, + ) void { + std.debug.assert(VirtualMachine.vm_loaded); + std.debug.assert(VirtualMachine.vm.global == global); + vm.enqueueTask(Task.init(microtask)) catch unreachable; + } pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: ZigString, source: ZigString) void { var result = ResolveFunctionResult{ .path = "", .result = null }; @@ -1411,10 +1472,10 @@ pub const VirtualMachine = struct { if (this.node_modules != null) { promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(std.mem.span(bun_file_import_path))); - this.global.vm().drainMicrotasks(); + this.tick(); while (promise.status(this.global.vm()) == JSPromise.Status.Pending) { - this.global.vm().drainMicrotasks(); + this.tick(); } if (promise.status(this.global.vm()) == JSPromise.Status.Rejected) { @@ -1426,10 +1487,10 @@ pub const VirtualMachine = struct { promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(std.mem.span(main_file_name))); - this.global.vm().drainMicrotasks(); + this.tick(); while (promise.status(this.global.vm()) == JSPromise.Status.Pending) { - this.global.vm().drainMicrotasks(); + this.tick(); } return promise; @@ -1446,30 +1507,13 @@ pub const VirtualMachine = struct { var entry_point = entry_point_entry.value_ptr.*; var promise: *JSInternalPromise = undefined; - // We first import the node_modules bundle. This prevents any potential TDZ issues. - // The contents of the node_modules bundle are lazy, so hopefully this should be pretty quick. - // if (this.node_modules != null) { - // promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(std.mem.span(bun_file_import_path))); - - // this.global.vm().drainMicrotasks(); - - // while (promise.status(this.global.vm()) == JSPromise.Status.Pending) { - // this.global.vm().drainMicrotasks(); - // } - - // if (promise.status(this.global.vm()) == JSPromise.Status.Rejected) { - // return promise; - // } - - // _ = promise.result(this.global.vm()); - // } promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.init(entry_point.source.path.text)); - this.global.vm().drainMicrotasks(); + this.tick(); while (promise.status(this.global.vm()) == JSPromise.Status.Pending) { - this.global.vm().drainMicrotasks(); + this.tick(); } return promise; @@ -1907,7 +1951,7 @@ pub const EventListenerMixin = struct { var result = js.JSObjectCallAsFunctionReturnValue(vm.global.ref(), listener_ref, null, 1, &fetch_args); var promise = JSPromise.resolvedPromise(vm.global, result); - vm.global.vm().drainMicrotasks(); + vm.tick(); if (fetch_event.rejected) return; @@ -1918,7 +1962,7 @@ pub const EventListenerMixin = struct { _ = promise.result(vm.global.vm()); } - vm.global.vm().drainMicrotasks(); + vm.tick(); if (fetch_event.request_context.has_called_done) { break; |