From 1dba557c9a333cc7a71cede3a9dad1e690aa66cc Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 8 Nov 2023 22:33:01 -0500 Subject: [PATCH] Ensure CSSTree does not hold onto last parsed string When done compiling, force CSSTree to parse an empty string, so as to ensure it doesn't keep a reference to that string. Typically, the string passed to CSSTree is a small slice of a larger string which is a whole filter list. This means that holding a reference to the sliced string causes the JS engine to hold in memory to the whole filter list last parsed. --- src/js/static-filtering-parser.js | 12 ++++++++++++ src/js/storage.js | 1 + 2 files changed, 13 insertions(+) diff --git a/src/js/static-filtering-parser.js b/src/js/static-filtering-parser.js index a15d78906..8b56fa03e 100644 --- a/src/js/static-filtering-parser.js +++ b/src/js/static-filtering-parser.js @@ -908,6 +908,10 @@ export class AstFilterParser { this.scriptletArgListParser = new ArgListParser(','); } + finish() { + this.selectorCompiler.finish(); + } + parse(raw) { this.raw = raw; this.rawEnd = raw.length; @@ -3229,6 +3233,14 @@ class ExtSelectorCompiler { this.error = undefined; } + // CSSTree library holds onto last string parsed, and this is problematic + // when the string is a slice of a huge parent string (typically a whole + // filter lists), it causes the huge parent string to stay in memory. + // Asking CSSTree to parse an empty string resolves this issue. + finish() { + cssTree.parse(''); + } + compile(raw, out, compileOptions = {}) { this.asProcedural = compileOptions.asProcedural === true; diff --git a/src/js/storage.js b/src/js/storage.js index 730338382..e59b79558 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -1102,6 +1102,7 @@ import { } compiler.finish(writer); + parser.finish(); // https://github.com/uBlockOrigin/uBlock-issues/issues/1365 // Embed version into compiled list itself: it is encoded in as the