@@ -326,16 +326,31 @@ pub fn waitForModule(self: *ScriptManager, url: [:0]const u8) !GetResult {
326326 };
327327 const sync = entry .value_ptr .* ;
328328
329+ // We can have multiple scripts waiting for the same module in concurrency.
330+ // We use the waiters to ensures only the last waiter deinit the resources.
331+ sync .waiters += 1 ;
332+ defer sync .waiters -= 1 ;
333+
329334 var client = self .client ;
330335 while (true ) {
331336 switch (sync .state ) {
332337 .loading = > {},
333338 .done = > {
334- // Our caller has its own higher level cache (caching the
335- // actual compiled module). There's no reason for us to keep this
336- defer self .sync_module_pool .destroy (sync );
337- defer self .sync_modules .removeByPtr (entry .key_ptr );
339+ if (sync .waiters == 1 ) {
340+ // Our caller has its own higher level cache (caching the
341+ // actual compiled module). There's no reason for us to keep
342+ // this if we are the last waiter.
343+ defer self .sync_module_pool .destroy (sync );
344+ defer self .sync_modules .removeByPtr (entry .key_ptr );
345+ return .{
346+ .shared = false ,
347+ .buffer = sync .buffer ,
348+ .buffer_pool = & self .buffer_pool ,
349+ };
350+ }
351+
338352 return .{
353+ .shared = true ,
339354 .buffer = sync .buffer ,
340355 .buffer_pool = & self .buffer_pool ,
341356 };
@@ -882,6 +897,8 @@ const SyncModule = struct {
882897 manager : * ScriptManager ,
883898 buffer : std .ArrayListUnmanaged (u8 ) = .{},
884899 state : State = .loading ,
900+ // number of waiters for the module.
901+ waiters : u8 = 0 ,
885902
886903 const State = union (enum ) {
887904 done ,
@@ -997,6 +1014,7 @@ pub const AsyncModule = struct {
9971014 var self : * AsyncModule = @ptrCast (@alignCast (ctx ));
9981015 defer self .manager .async_module_pool .destroy (self );
9991016 self .cb (self .cb_data , .{
1017+ .shared = false ,
10001018 .buffer = self .buffer ,
10011019 .buffer_pool = & self .manager .buffer_pool ,
10021020 });
@@ -1020,8 +1038,13 @@ pub const AsyncModule = struct {
10201038pub const GetResult = struct {
10211039 buffer : std .ArrayListUnmanaged (u8 ),
10221040 buffer_pool : * BufferPool ,
1041+ shared : bool ,
10231042
10241043 pub fn deinit (self : * GetResult ) void {
1044+ // if the result is shared, don't deinit.
1045+ if (self .shared ) {
1046+ return ;
1047+ }
10251048 self .buffer_pool .release (self .buffer );
10261049 }
10271050
0 commit comments