@@ -502,31 +502,34 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
502502
503503 // Callbacks are PesistendObjects. When the scope ends, we need
504504 // to free every callback we created.
505- callbacks : std .ArrayListUnmanaged (v8 .Persistent (v8 .Function )) = .{} ,
505+ callbacks : std .ArrayListUnmanaged (v8 .Persistent (v8 .Function )) = .empty ,
506506
507507 // Serves two purposes. Like `callbacks` above, this is used to free
508508 // every PeristentObjet we've created during the lifetime of the scope.
509509 // More importantly, it serves as an identity map - for a given Zig
510510 // instance, we map it to the same PersistentObject.
511511 // The key is the @intFromPtr of the Zig value
512- identity_map : std .AutoHashMapUnmanaged (usize , PersistentObject ) = .{} ,
512+ identity_map : std .AutoHashMapUnmanaged (usize , PersistentObject ) = .empty ,
513513
514514 // Similar to the identity map, but used much less frequently. Some
515515 // web APIs have to manage opaque values. Ideally, they use an
516516 // JsObject, but the JsObject has no lifetime guarantee beyond the
517517 // current call. They can call .persist() on their JsObject to get
518518 // a `*PersistentObject()`. We need to track these to free them.
519519 // The key is the @intFromPtr of the v8.Object.handle.
520- js_object_map : std .AutoHashMapUnmanaged (usize , PersistentObject ) = .{} ,
520+ js_object_map : std .AutoHashMapUnmanaged (usize , PersistentObject ) = .empty ,
521521
522522 // When we need to load a resource (i.e. an external script), we call
523523 // this function to get the source. This is always a reference to the
524524 // Page's fetchModuleSource, but we use a function pointer
525525 // since this js module is decoupled from the browser implementation.
526526 module_loader : ModuleLoader ,
527527
528+ // Some Zig types have code to execute to cleanup
529+ destructor_callbacks : std .ArrayListUnmanaged (DestructorCallback ) = .empty ,
530+
528531 // Some Zig types have code to execute when the call scope ends
529- call_scope_end_callbacks : std .ArrayListUnmanaged (CallScopeEndCallback ) = .{} ,
532+ call_scope_end_callbacks : std .ArrayListUnmanaged (CallScopeEndCallback ) = .empty ,
530533
531534 const ModuleLoader = struct {
532535 ptr : * anyopaque ,
@@ -536,6 +539,10 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
536539 // no init, started with executor.startScope()
537540
538541 fn deinit (self : * Scope ) void {
542+ for (self .destructor_callbacks .items ) | cb | {
543+ cb .destructor (self );
544+ }
545+
539546 {
540547 var it = self .identity_map .valueIterator ();
541548 while (it .next ()) | p | {
@@ -694,6 +701,10 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
694701 return gop .value_ptr .* ;
695702 }
696703
704+ if (comptime @hasDecl (ptr .child , "destructor" )) {
705+ try self .destructor_callbacks .append (scope_arena , DestructorCallback .init (value ));
706+ }
707+
697708 if (comptime @hasDecl (ptr .child , "jsCallScopeEnd" )) {
698709 try self .call_scope_end_callbacks .append (scope_arena , CallScopeEndCallback .init (value ));
699710 }
@@ -1672,7 +1683,35 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
16721683 }
16731684 }
16741685
1675- // An interface for types that want to their jsScopeEnd function to be
1686+ // An interface for types that want to have their jsDeinit function to be
1687+ // called when the call scope ends
1688+ const DestructorCallback = struct {
1689+ ptr : * anyopaque ,
1690+ destructorFn : * const fn (ptr : * anyopaque , scope : * Scope ) void ,
1691+
1692+ fn init (ptr : anytype ) DestructorCallback {
1693+ const T = @TypeOf (ptr );
1694+ const ptr_info = @typeInfo (T );
1695+
1696+ const gen = struct {
1697+ pub fn destructor (pointer : * anyopaque , scope : * Scope ) void {
1698+ const self : T = @ptrCast (@alignCast (pointer ));
1699+ return ptr_info .pointer .child .destructor (self , scope );
1700+ }
1701+ };
1702+
1703+ return .{
1704+ .ptr = ptr ,
1705+ .destructorFn = gen .destructor ,
1706+ };
1707+ }
1708+
1709+ pub fn destructor (self : DestructorCallback , scope : * Scope ) void {
1710+ self .destructorFn (self .ptr , scope );
1711+ }
1712+ };
1713+
1714+ // An interface for types that want to have their jsScopeEnd function be
16761715 // called when the call scope ends
16771716 const CallScopeEndCallback = struct {
16781717 ptr : * anyopaque ,
0 commit comments