diff --git a/src/browser/Frame.zig b/src/browser/Frame.zig index 38e078594..237450ac3 100644 --- a/src/browser/Frame.zig +++ b/src/browser/Frame.zig @@ -133,6 +133,10 @@ _event_target_attr_listeners: GlobalEventHandlersLookup = .empty, // File objects (reference counted via their Blob proto); released at teardown. _file_lists: std.ArrayList(*FileList) = .empty, +// List of Documents which called document.open() and potentially need to have +// the parser freed. +_script_created_parser_docs: std.ArrayList(*Document) = .empty, + // Every matchMedia() result of this document, so a viewport change can fire // their `change`. _media_query_lists: std.ArrayList(*MediaQueryList) = .empty, @@ -456,6 +460,16 @@ pub fn deinit(self: *Frame) void { self._parse_state.deinit(self); + for (self._script_created_parser_docs.items) |doc| { + const parser = &(doc._script_created_parser orelse continue); + if (parser.parser.frame != self) { + // The document was closed and re-opened on another frame + continue; + } + parser.deinit(); + doc._script_created_parser = null; + } + // Unregister CookieStore from session notifications before the JS // context (and thus the scheduler) is destroyed, otherwise a late // mutation could schedule a callback that never runs. diff --git a/src/browser/webapi/Document.zig b/src/browser/webapi/Document.zig index 0a283a8e2..ee95c6d91 100644 --- a/src/browser/webapi/Document.zig +++ b/src/browser/webapi/Document.zig @@ -1157,6 +1157,11 @@ pub fn open(self: *Document, call_frame: *Frame) !*Document { // gone for good, as in Chrome. frame.cancelQueuedNavigation(); + if (std.mem.indexOfScalar(*Document, frame._script_created_parser_docs.items, self) == null) { + // have the page track this document (if it isn't already) + // so that, on shutdown, it can close the parser if needed. + try frame._script_created_parser_docs.append(frame.arena, self); + } self._script_created_parser = Parser.Streaming.init(frame.arena, doc_node, frame, .{ .allow_declarative_shadow = true }); try self._script_created_parser.?.start(); frame._parse_mode = .document;