You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf: reduce CSS parser CPU and retained comment state (#21202)
* perf: hoist CSS parser regexes and release per-module comments
* perf: avoid transient string in CSS @container pure-mode keyword check
* refactor: scope CSS parser comments locally, mirroring HtmlParser
Comments are now kept in a per-parse local array instead of the reused
parser instance, and the internal-only getComments/parseCommentOptions
methods become local closures — matching HtmlParser, which holds no
per-parse comment state. No behavior or measurable perf/memory change.
* chore: broaden CSS parser changeset to cover the @container keyword check
* test: cover CSS @container keyword check and magic-comment vm path
Adds a pure css/module config case whose named @container rules exercise
each arm of the container-keyword byte check, plus a non-fast-path url
magic comment that drives the parseCommentOptions vm.runInContext path.
Reduce CSS parser CPU (hoisted per-call regexes, byte-compared `@container` pure-mode keywords) and stop retaining parsed comments on the reused parser instance between modules.
// A parsed CSS comment. `loc` is computed on demand — only magic-comment error
77
77
// warnings read it, so comment-heavy CSS skips the per-comment line/col work.
78
-
// Comments are kept in a flat `this.comments` side array (not AST nodes); `loc` is derived lazily via `rangeLoc` only where needed (magic-comment errors).
78
+
// Comments are kept in a flat per-parse `comments` side array (not AST nodes); `loc` is derived lazily via `rangeLoc` only where needed (magic-comment errors).
79
79
/** @typedef {{ value: string, range: Range }} Comment */
80
80
81
81
// Newlines (CSS Syntax 3 §3.3) — listed explicitly since there's no preprocessing stage.
// `@value` recognizers (postcss-modules-values shape): the import form `<names> from <source>`, and the `<importName> as <localName>` alias inside it.
* Whether the ident byte-range is a `@container` prelude keyword (`none`/`and`/`or`/`not`, lowercase only) — byte comparison avoids slicing a transient string per prelude ident.
@@ -1217,15 +1244,14 @@ class CssParser extends Parser {
1217
1244
modeData ? modeData==="local" : mode==="local";
1218
1245
1219
1246
/**
1220
-
* Comment callback: push every comment-token (in source order) onto `this.comments`, read back by `advanceCommentCursor` (pure-mode flags) and `parseCommentOptions` (magic comments).
1247
+
* Comment callback: push every comment-token (in source order) onto the local `comments`, read back by `advanceCommentCursor` (pure-mode flags) and `parseCommentOptions` (magic comments).
1221
1248
* @param {string} input input
1222
1249
* @param {number} start start
1223
1250
* @param {number} end end
1224
1251
* @returns {number} end
1225
1252
*/
1226
1253
constcomment=(input,start,end)=>{
1227
-
if(!this.comments)this.comments=[];
1228
-
this.comments.push({
1254
+
comments.push({
1229
1255
value: input.slice(start+2,end-2),
1230
1256
range: [start,end]
1231
1257
});
@@ -1240,16 +1266,98 @@ class CssParser extends Parser {
1240
1266
letcursor=0;
1241
1267
/** @param {number} until source position to advance the cursor to */
0 commit comments