parseman 0.26.3 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,7 +36,7 @@ __export(plugin_exports, {
36
36
  module.exports = __toCommonJS(plugin_exports);
37
37
  var fs = __toESM(require("node:fs"), 1);
38
38
  var import_unplugin = require("unplugin");
39
- var import_oxc_parser = require("oxc-parser");
39
+ var import_oxc_parser2 = require("oxc-parser");
40
40
  var import_oxc_resolver = require("oxc-resolver");
41
41
  var import_magic_string = __toESM(require("magic-string"), 1);
42
42
 
@@ -1509,6 +1509,12 @@ function scanTrivia(input, cur, ctx) {
1509
1509
  const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1510
1510
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1511
1511
  }
1512
+ function consumeTrivia(input, cur, ctx) {
1513
+ if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1514
+ const scan = scanTrivia(input, cur, ctx);
1515
+ scan.commit();
1516
+ return scan.end;
1517
+ }
1512
1518
  function fastTriviaScanner(trivia2) {
1513
1519
  const cached = fastTriviaCache.get(trivia2);
1514
1520
  if (cached !== void 0) return cached;
@@ -2252,6 +2258,98 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
2252
2258
  return false;
2253
2259
  }
2254
2260
  }
2261
+ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
2262
+ if (seen.has(p)) return true;
2263
+ seen.add(p);
2264
+ const d = p._def;
2265
+ switch (d.tag) {
2266
+ // Trivia is skipped between/around elements or iterations → a site.
2267
+ case "sequence":
2268
+ case "many":
2269
+ case "oneOrMore":
2270
+ case "sepBy":
2271
+ case "scanTo":
2272
+ case "recover":
2273
+ case "skip":
2274
+ return true;
2275
+ // Nested node manages its own trivia frame; none logs here.
2276
+ case "node":
2277
+ return false;
2278
+ // Pure terminals + trivia-suppressing token: no site.
2279
+ case "regex":
2280
+ case "literal":
2281
+ case "keywords":
2282
+ case "guard":
2283
+ case "token":
2284
+ return false;
2285
+ // Transparent single-child wrappers: recurse.
2286
+ case "optional":
2287
+ case "transform":
2288
+ case "trivia":
2289
+ case "label":
2290
+ case "expect":
2291
+ case "withCtx":
2292
+ case "not":
2293
+ case "field":
2294
+ return parserHasTriviaSite(d.parser, seen);
2295
+ case "choice":
2296
+ return d.parsers.some((x) => parserHasTriviaSite(x, seen));
2297
+ case "grammar":
2298
+ return parserHasTriviaSite(d.parser, seen);
2299
+ case "lazy": {
2300
+ try {
2301
+ return parserHasTriviaSite(d.thunk(), seen);
2302
+ } catch {
2303
+ return true;
2304
+ }
2305
+ }
2306
+ default:
2307
+ return true;
2308
+ }
2309
+ }
2310
+ function parserEnablesTriviaCapture(p, seen = /* @__PURE__ */ new Set()) {
2311
+ if (seen.has(p)) return false;
2312
+ seen.add(p);
2313
+ const d = p._def;
2314
+ switch (d.tag) {
2315
+ case "grammar":
2316
+ return d.captureTrivia === true || parserEnablesTriviaCapture(d.parser, seen);
2317
+ case "node":
2318
+ return false;
2319
+ case "sequence":
2320
+ case "choice":
2321
+ return d.parsers.some((x) => parserEnablesTriviaCapture(x, seen));
2322
+ case "sepBy":
2323
+ return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.separator, seen);
2324
+ case "skip":
2325
+ return parserEnablesTriviaCapture(d.main, seen) || parserEnablesTriviaCapture(d.skipped, seen);
2326
+ case "scanTo":
2327
+ return parserEnablesTriviaCapture(d.sentinel, seen) || d.skip.some((x) => parserEnablesTriviaCapture(x, seen));
2328
+ case "recover":
2329
+ return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.sentinel, seen);
2330
+ case "many":
2331
+ case "oneOrMore":
2332
+ case "optional":
2333
+ case "transform":
2334
+ case "trivia":
2335
+ case "token":
2336
+ case "label":
2337
+ case "field":
2338
+ case "expect":
2339
+ case "withCtx":
2340
+ case "not":
2341
+ return parserEnablesTriviaCapture(d.parser, seen);
2342
+ case "lazy": {
2343
+ try {
2344
+ return parserEnablesTriviaCapture(d.thunk(), seen);
2345
+ } catch {
2346
+ return false;
2347
+ }
2348
+ }
2349
+ default:
2350
+ return false;
2351
+ }
2352
+ }
2255
2353
  function buildFieldMap(captures) {
2256
2354
  if (!captures?.length) return void 0;
2257
2355
  const out = {};
@@ -2289,11 +2387,13 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2289
2387
  };
2290
2388
  const unwrap = opts?.unwrap === true;
2291
2389
  const collapse = opts?.collapse === true;
2390
+ const captureTrivia = opts?.captureTrivia === true;
2391
+ const trailingTrivia = opts?.trailingTrivia === true;
2292
2392
  if (unwrap && collapse) {
2293
2393
  throw new Error("node() options cannot set both unwrap and collapse");
2294
2394
  }
2295
- const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
2296
- const capturesTrivia = build ? buildReadsTrivia(def) : true;
2395
+ const def = unwrap || collapse || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
2396
+ const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
2297
2397
  const clonesState = build ? buildReadsState(def) : true;
2298
2398
  const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
2299
2399
  return {
@@ -2309,7 +2409,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2309
2409
  ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
2310
2410
  }
2311
2411
  if (!capturesTrivia) ctx.captureTrivia = false;
2312
- const r = combinator.parse(input, pos, ctx);
2412
+ let r = combinator.parse(input, pos, ctx);
2413
+ if (r.ok && trailingTrivia && ctx.trivia) {
2414
+ const end = consumeTrivia(input, r.span.end, ctx);
2415
+ r = { ...r, span: { start: r.span.start, end } };
2416
+ }
2313
2417
  const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
2314
2418
  ctx._fields = savedFields;
2315
2419
  ctx._triviaCaptureMask = savedMask;
@@ -2317,8 +2421,9 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2317
2421
  if (!r.ok) return r;
2318
2422
  const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
2319
2423
  const nodeType = def.type ?? missingInferredType();
2320
- const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : build ? build(children, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children };
2321
- const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
2424
+ const cstOutput = ctx.build?._parsemanCstOutput === true;
2425
+ const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : build(children, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children };
2426
+ const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span: r.span };
2322
2427
  if (saved.buf !== void 0 || saved.ch !== void 0) {
2323
2428
  pushCstChild(ctx, built, rawEntry);
2324
2429
  }
@@ -2435,6 +2540,7 @@ function parser(opts, root) {
2435
2540
  parser: root,
2436
2541
  triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
2437
2542
  clearTrivia,
2543
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
2438
2544
  trackLines: opts.trackLines ?? false
2439
2545
  },
2440
2546
  parse(input, pos, _ctx) {
@@ -3571,7 +3677,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
3571
3677
  ` if (${m.end} > _e) {`,
3572
3678
  ` if (_cap) {`,
3573
3679
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
3574
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
3680
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
3575
3681
  ` }`,
3576
3682
  ` _e = ${m.end}`,
3577
3683
  ` continue`,
@@ -3627,7 +3733,7 @@ function analyzeTriviaFastPath(trivia2) {
3627
3733
  var CAP_RECORD = [
3628
3734
  ` if (_cap && _e > _pos) {`,
3629
3735
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
3630
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
3736
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
3631
3737
  ` }`
3632
3738
  ].join("\n");
3633
3739
  function composeFastLoop(shapes) {
@@ -3687,7 +3793,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
3687
3793
  ` const _ce = _e + _m${i}[0].length`,
3688
3794
  ` if (_cap) {`,
3689
3795
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
3690
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3796
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3691
3797
  ` }`,
3692
3798
  ` _e = _ce`,
3693
3799
  ` _matched = true`,
@@ -3725,7 +3831,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
3725
3831
  ` const _ce = _r${i}.span.end`,
3726
3832
  ` if (_cap) {`,
3727
3833
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
3728
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3834
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3729
3835
  ` }`,
3730
3836
  ` _e = _ce`,
3731
3837
  ` _matched = true`,
@@ -4076,7 +4182,7 @@ function ensureTriviaFn(ctx) {
4076
4182
  ` }`,
4077
4183
  ` if (_cap && _e > _pos) {`,
4078
4184
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
4079
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
4185
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
4080
4186
  ` }`,
4081
4187
  ` return _e`,
4082
4188
  `}`
@@ -5211,47 +5317,71 @@ function emitNode(def, ctx, pos) {
5211
5317
  ctx.buildSrcs.push(def.buildSrc ?? null);
5212
5318
  }
5213
5319
  const i = ind(ctx);
5214
- const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
5320
+ const capturesTrivia = mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && buildReadsTrivia(def);
5215
5321
  const clonesState = !structural && buildReadsState(def);
5216
5322
  const hasFields = parserHasOwnFields(def.parser);
5217
5323
  const capturesFields = hasFields && !structural && buildReadsFields(def);
5324
+ const innerEnablesTriviaCapture = parserEnablesTriviaCapture(def.parser);
5218
5325
  const chV = v(ctx, "_ch");
5219
5326
  const rawV = v(ctx, "_raw");
5220
- const capTLv = structural ? v(ctx, "_ctl") : null;
5327
+ const capTLv = structural || capturesTrivia ? v(ctx, "_ctl") : null;
5221
5328
  const capSTv = structural ? v(ctx, "_cst") : null;
5222
5329
  const capFv = structural && hasFields ? v(ctx, "_cf") : null;
5223
5330
  const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
5224
- if (!capturesTrivia) ctx.needsEmptyTl = true;
5331
+ if (!capturesTrivia || structural) ctx.needsEmptyTl = true;
5225
5332
  const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
5226
5333
  const smk = structural ? v(ctx, "_smk") : null;
5227
5334
  if (structural) ctx.needsHostReads = true;
5228
5335
  const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
5229
- const allocStmt = structural ? `${i}const ${capTLv} = ${hostTriviaGate}, ${capSTv} = _ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6))${capFv ? `, ${capFv} = _ctx.build !== undefined && _hostReads(_ctx.build, 2)` : ""}
5230
- ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
5231
- const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
5232
- const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
5336
+ const pmV = v(ctx, "_pm"), recV = v(ctx, "_rec"), capV = v(ctx, "_cap");
5337
+ const profHoist = `${i}const ${pmV} = _ctx._pmProfile, ${recV} = ${pmV}?.phase === 'recognizer', ${capV} = ${pmV}?.phase === 'capture'`;
5338
+ const profileRecognizer = recV;
5339
+ const profileCapture = capV;
5340
+ const structuralCapturesTrivia = structural && (def.captureTrivia === true || def.trailingTrivia === true);
5341
+ const allocStmt = structural ? `${i}const ${capTLv} = !(${profileRecognizer}) && (${profileCapture} || ${structuralCapturesTrivia ? "true" : hostTriviaGate}), ${capSTv} = !(${profileRecognizer} || ${profileCapture}) && (_ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6)))${capFv ? `, ${capFv} = !(${profileRecognizer}) && (${profileCapture} || (_ctx.build !== undefined && _hostReads(_ctx.build, 2)))` : ""}
5342
+ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : [], ${tlV} = ${profileRecognizer} ? undefined : ${innerEnablesTriviaCapture ? "[]" : `${capTLv} ? [] : _EMPTY_TL`}` : capturesTrivia ? `${i}const ${capTLv} = !(${profileRecognizer}), ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : [], ${tlV} = ${profileRecognizer} ? undefined : []` : `${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRecognizer} ? undefined : []`;
5343
+ const innerTl = structural || capturesTrivia ? structural && !innerEnablesTriviaCapture ? `${capTLv} ? ${tlV} : undefined` : tlV : "undefined";
5344
+ const fieldsOn = structural ? capFv ?? "false" : `${profileRecognizer} ? false : ${capturesFields ? "true" : "false"}`;
5233
5345
  const sf = hasFields ? v(ctx, "_sf") : null;
5234
5346
  const fArr = hasFields ? v(ctx, "_fa") : null;
5235
5347
  const fObj = hasFields ? v(ctx, "_fields") : "undefined";
5348
+ const needsTriviaFrame = def.trailingTrivia === true || parserHasTriviaSite(def.parser);
5349
+ const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
5350
+ const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${capTLv ?? "false"}; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build !== undefined && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}` : "";
5351
+ const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
5236
5352
  const stmts = [
5353
+ profHoist,
5237
5354
  allocStmt,
5238
- `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}${sf ? `, ${sf} = _ctx._fields` : ""}`,
5239
- `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}; _ctx.captureTrivia = true; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
5355
+ `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
5356
+ `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
5240
5357
  ];
5241
- const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
5358
+ const { stmts: innerStmts, okVar, endVar: innerEndVar } = emitFallible(def.parser, ctx, pos);
5359
+ const endVar = def.trailingTrivia === true && ctx.activeTrivia ? v(ctx, "_trailend") : innerEndVar;
5242
5360
  stmts.push(...innerStmts);
5361
+ if (def.trailingTrivia === true && ctx.activeTrivia) {
5362
+ const triviaFn = ensureTriviaFn(ctx);
5363
+ stmts.push(`${i}const ${endVar} = ${okVar} ? ${triviaFn}(input, ${innerEndVar}, _ctx, 1) : ${innerEndVar}`);
5364
+ }
5243
5365
  if (sf && fArr) {
5244
5366
  stmts.push(`${i}const ${fArr} = _ctx._fields`);
5245
5367
  }
5246
- stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}${sf ? `; _ctx._fields = ${sf}` : ""}`);
5368
+ stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}${restoreTrivia}${sf ? `; _ctx._fields = ${sf}` : ""}`);
5247
5369
  stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
5370
+ stmts.push(
5371
+ `${i}if (_ctx._pmProfile) {`,
5372
+ `${i} _ctx._pmProfile.nodes++`,
5373
+ `${i} if (${profileCapture}) {`,
5374
+ `${i} _ctx._pmProfile.childSlots += ${chV}.length; _ctx._pmProfile.rawSlots += ${rawV}.length; _ctx._pmProfile.triviaSlots += ${tlV}.length${fArr ? `; _ctx._pmProfile.fieldSlots += ${fArr} ? ${fArr}.length : 0` : ""}`,
5375
+ `${i} }`,
5376
+ `${i}}`
5377
+ );
5248
5378
  let stV = "undefined";
5249
5379
  if (structural) {
5250
5380
  stV = v(ctx, "_nst");
5251
5381
  stmts.push(`${i}const ${stV} = ${capSTv} && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5252
5382
  } else if (clonesState) {
5253
5383
  stV = v(ctx, "_nst");
5254
- stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5384
+ stmts.push(`${i}const ${stV} = !(${profileRecognizer} || ${profileCapture}) && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5255
5385
  }
5256
5386
  if (sf && fArr) {
5257
5387
  const fe = v(ctx, "_fe");
@@ -5271,15 +5401,18 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
5271
5401
  }
5272
5402
  const ndV = v(ctx, "_nd");
5273
5403
  const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
5274
- const ndExpr = ctx.ns || structural ? `_ctx.build !== undefined ? _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV}) : (${buildExpr})` : buildExpr;
5275
- const hostCollapseExpr = ctx.ns || structural ? `_ctx.build !== undefined && _ctx.build._parsemanCstCollapse !== undefined && ${chV}.length === 1 && ${rawV}.length === 1 && _ctx.build._parsemanCstCollapse(${JSON.stringify(def.type)}, ${chV}[0], ${chV}, ${rawV}) ? ${chV}[0] : (${ndExpr})` : ndExpr;
5404
+ const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
5405
+ const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : `_ctx.build?._parsemanCstOutput === true ? (${hostBuildExpr}) : (${buildExpr})`;
5406
+ const hostCollapseExpr = structural ? `_ctx.build !== undefined && _ctx.build._parsemanCstCollapse !== undefined && ${chV}.length === 1 && ${rawV}.length === 1 && _ctx.build._parsemanCstCollapse(${JSON.stringify(def.type)}, ${chV}[0], ${chV}, ${rawV}) ? ${chV}[0] : (${ndExpr})` : ndExpr;
5276
5407
  const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
5277
5408
  const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
5278
5409
  const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
5279
5410
  stmts.push(
5280
- `${i}const ${ndV} = ${finalExpr}`,
5281
- `${i}if (${sc}) ${sc}.push(${ndV})`,
5282
- `${i}if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'parseError')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : '', span: { start: ${pos}, end: ${endVar} } })`
5411
+ `${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
5412
+ `${i}if (!(${profileRecognizer})) {`,
5413
+ `${i} if (${sc}) ${sc}.push(${ndV})`,
5414
+ `${i} if (${sr}) ${sr}.push((typeof ${ndV} === 'object' && ${ndV} !== null && (${ndV}._tag === 'node' || ${ndV}._tag === 'leaf' || ${ndV}._tag === 'parseError')) ? ${ndV} : { _tag: 'leaf', value: typeof ${ndV} === 'string' ? ${ndV} : (typeof ${ndV} === 'object' && ${ndV} !== null ? input.slice(${pos}, ${endVar}) : ''), span: { start: ${pos}, end: ${endVar} } })`,
5415
+ `${i}}`
5283
5416
  );
5284
5417
  return { stmts, valueVar: ndV, endVar };
5285
5418
  }
@@ -5521,10 +5654,19 @@ function emitDispatch(p, ctx, pos) {
5521
5654
  ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
5522
5655
  }
5523
5656
  }
5657
+ const savedCapture = def.captureTrivia ? v(ctx, "_gcap") : null;
5524
5658
  const r = emit(def.parser, ctx, pos);
5525
5659
  ctx.activeTrivia = savedTrivia;
5526
5660
  ctx.triviaKindLabels = savedKindLabels;
5527
- return r;
5661
+ if (!savedCapture) return r;
5662
+ return {
5663
+ ...r,
5664
+ stmts: [
5665
+ `${ind(ctx)}const ${savedCapture} = _ctx.captureTrivia; _ctx.captureTrivia = true`,
5666
+ ...r.stmts,
5667
+ `${ind(ctx)}_ctx.captureTrivia = ${savedCapture}`
5668
+ ]
5669
+ };
5528
5670
  }
5529
5671
  case "not":
5530
5672
  return emitNot(def, ctx, pos);
@@ -6372,9 +6514,15 @@ function evalRuleMapIR(ir) {
6372
6514
  t._def.fnSrc = src;
6373
6515
  return t;
6374
6516
  };
6375
- const _nd = (type, child, src, opts) => {
6376
- const n = node(type, child, void 0, opts);
6517
+ const _nd = (type, child, src, opts, staticError) => {
6518
+ if (staticError !== void 0 && staticError.length > 0) {
6519
+ throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
6520
+ }
6521
+ const n = node(type, child, (() => {
6522
+ throw new Error("IR node build requires static re-lowering");
6523
+ }), opts);
6377
6524
  n._def.buildSrc = src;
6525
+ if (staticError !== void 0) n._def.buildStaticError = staticError;
6378
6526
  return n;
6379
6527
  };
6380
6528
  const _gch = (items) => {
@@ -6624,17 +6772,26 @@ ${body}
6624
6772
  }
6625
6773
  case "node": {
6626
6774
  if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
6627
- const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
6775
+ const optEntries = [
6776
+ ...def.unwrap ? ["unwrap: true"] : [],
6777
+ ...def.collapse ? ["collapse: true"] : [],
6778
+ ...def.captureTrivia ? ["captureTrivia: true"] : [],
6779
+ ...def.trailingTrivia ? ["trailingTrivia: true"] : []
6780
+ ];
6781
+ const opts = optEntries.length > 0 ? `, { ${optEntries.join(", ")} }` : "";
6628
6782
  if (def.type === void 0) {
6629
6783
  if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
6630
6784
  return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
6631
6785
  }
6632
- if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
6786
+ if (def.buildSrc !== void 0) {
6787
+ const staticError = def.buildStaticError === void 0 ? "" : `${opts ? "" : ", undefined"}, ${JSON.stringify(def.buildStaticError)}`;
6788
+ return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${staticError})`;
6789
+ }
6633
6790
  return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
6634
6791
  }
6635
6792
  case "grammar": {
6636
6793
  const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
6637
- return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6794
+ return `parser({ trivia: ${trivia2}${def.captureTrivia ? ", captureTrivia: true" : ""}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6638
6795
  }
6639
6796
  case "withCtx": {
6640
6797
  if (def.extraSrc === void 0) throw new Unserializable("withCtx without extraSrc");
@@ -6649,6 +6806,28 @@ ${body}
6649
6806
  };
6650
6807
 
6651
6808
  // src/compiler/linker.ts
6809
+ function normalizeCstCollapse(collapse) {
6810
+ if (collapse === true) return () => true;
6811
+ if (Array.isArray(collapse)) {
6812
+ const types = new Set(collapse);
6813
+ return (type) => types.has(type);
6814
+ }
6815
+ return typeof collapse === "function" ? collapse : void 0;
6816
+ }
6817
+ function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
6818
+ return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children] };
6819
+ }
6820
+ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
6821
+ if (typeof typeOrOptions === "string") {
6822
+ return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
6823
+ }
6824
+ const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
6825
+ const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2, fields, span2, rawChildren2, triviaLog2, state2);
6826
+ host._parsemanCstOutput = true;
6827
+ if (collapse) host._parsemanCstCollapse = collapse;
6828
+ return host;
6829
+ }
6830
+ cstBuildHost._parsemanCstOutput = true;
6652
6831
  function pickPieces(pieces, names) {
6653
6832
  const winner = /* @__PURE__ */ new Map();
6654
6833
  for (const pc of pieces) for (const k of pc.keys) winner.set(k, pc);
@@ -6758,6 +6937,152 @@ var { isFinite } = Number;
6758
6937
  // src/index.ts
6759
6938
  registerRegexAnalyzer(firstSetFromRegex);
6760
6939
 
6940
+ // src/plugin/direct-builder-static.ts
6941
+ var import_oxc_parser = require("oxc-parser");
6942
+ var STATIC_BUILDER_GLOBALS = /* @__PURE__ */ new Set([
6943
+ "Array",
6944
+ "Boolean",
6945
+ "Date",
6946
+ "JSON",
6947
+ "Math",
6948
+ "NaN",
6949
+ "Number",
6950
+ "Object",
6951
+ "String",
6952
+ "Infinity",
6953
+ "parseFloat",
6954
+ "parseInt",
6955
+ "undefined"
6956
+ ]);
6957
+ function astArray(value) {
6958
+ return Array.isArray(value) ? value : [];
6959
+ }
6960
+ function astChild(value) {
6961
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
6962
+ }
6963
+ function unwrapCallbackExpression(node2) {
6964
+ let current = node2;
6965
+ while (current?.type === "ParenthesizedExpression") current = astChild(current.expression) ?? void 0;
6966
+ return current;
6967
+ }
6968
+ function directBuilderUnsupportedBindings(src) {
6969
+ let init;
6970
+ try {
6971
+ const parsed = (0, import_oxc_parser.parseSync)("parseman-direct-builder.ts", `const _direct = (${src})`);
6972
+ if (parsed.errors.length > 0) return ["invalid callback source"];
6973
+ const program = parsed.program;
6974
+ const statement = program.body?.[0];
6975
+ const declaration = statement?.declarations?.[0];
6976
+ init = unwrapCallbackExpression(declaration?.init);
6977
+ } catch {
6978
+ return ["invalid callback source"];
6979
+ }
6980
+ if (init?.type !== "ArrowFunctionExpression" || !Array.isArray(init.params)) return ["unsupported callback shape"];
6981
+ const allowed = new Set(STATIC_BUILDER_GLOBALS);
6982
+ for (const param of init.params) {
6983
+ if (param.type !== "Identifier" || typeof param.name !== "string") return ["unsupported parameter pattern"];
6984
+ allowed.add(param.name);
6985
+ }
6986
+ const unsupported = /* @__PURE__ */ new Set();
6987
+ const reportUnsupportedNode = (ast) => {
6988
+ unsupported.add(`unsupported ${ast.type}`);
6989
+ };
6990
+ const read = (ast, allowedNames) => {
6991
+ if (typeof ast.name === "string" && allowedNames.has(ast.name)) return;
6992
+ unsupported.add(typeof ast.name === "string" ? ast.name : "identifier");
6993
+ };
6994
+ const expression = (node2, allowedNames) => {
6995
+ const ast = astChild(node2);
6996
+ if (!ast) return;
6997
+ switch (ast.type) {
6998
+ case "Literal":
6999
+ return;
7000
+ case "Identifier":
7001
+ read(ast, allowedNames);
7002
+ return;
7003
+ case "ParenthesizedExpression":
7004
+ case "ChainExpression":
7005
+ case "TSAsExpression":
7006
+ case "TSTypeAssertion":
7007
+ case "TSNonNullExpression":
7008
+ expression(ast.expression, allowedNames);
7009
+ return;
7010
+ case "ArrayExpression":
7011
+ for (const element of astArray(ast.elements)) expression(element, allowedNames);
7012
+ return;
7013
+ case "ObjectExpression":
7014
+ for (const property of astArray(ast.properties)) {
7015
+ if (property.type === "SpreadElement") {
7016
+ expression(property.argument, allowedNames);
7017
+ continue;
7018
+ }
7019
+ if (property.type !== "Property" || property.method === true || property.kind !== "init") {
7020
+ reportUnsupportedNode(property);
7021
+ continue;
7022
+ }
7023
+ if (property.computed === true) expression(property.key, allowedNames);
7024
+ expression(property.value, allowedNames);
7025
+ }
7026
+ return;
7027
+ case "MemberExpression":
7028
+ expression(ast.object, allowedNames);
7029
+ if (ast.computed === true) expression(ast.property, allowedNames);
7030
+ return;
7031
+ case "CallExpression":
7032
+ case "NewExpression":
7033
+ expression(ast.callee, allowedNames);
7034
+ for (const argument of astArray(ast.arguments)) expression(argument, allowedNames);
7035
+ return;
7036
+ case "UnaryExpression":
7037
+ case "UpdateExpression":
7038
+ expression(ast.argument, allowedNames);
7039
+ return;
7040
+ case "BinaryExpression":
7041
+ case "LogicalExpression":
7042
+ case "AssignmentExpression":
7043
+ expression(ast.left, allowedNames);
7044
+ expression(ast.right, allowedNames);
7045
+ return;
7046
+ case "ConditionalExpression":
7047
+ expression(ast.test, allowedNames);
7048
+ expression(ast.consequent, allowedNames);
7049
+ expression(ast.alternate, allowedNames);
7050
+ return;
7051
+ case "SequenceExpression":
7052
+ for (const value of astArray(ast.expressions)) expression(value, allowedNames);
7053
+ return;
7054
+ case "TemplateLiteral":
7055
+ for (const value of astArray(ast.expressions)) expression(value, allowedNames);
7056
+ return;
7057
+ case "SpreadElement":
7058
+ expression(ast.argument, allowedNames);
7059
+ return;
7060
+ case "ArrowFunctionExpression": {
7061
+ const nested = new Set(allowedNames);
7062
+ for (const param of astArray(ast.params)) {
7063
+ if (param.type !== "Identifier" || typeof param.name !== "string") {
7064
+ reportUnsupportedNode(param);
7065
+ continue;
7066
+ }
7067
+ nested.add(param.name);
7068
+ }
7069
+ if (astChild(ast.body)?.type === "BlockStatement") {
7070
+ reportUnsupportedNode(astChild(ast.body));
7071
+ return;
7072
+ }
7073
+ expression(ast.body, nested);
7074
+ return;
7075
+ }
7076
+ default:
7077
+ reportUnsupportedNode(ast);
7078
+ return;
7079
+ }
7080
+ };
7081
+ if (astChild(init.body)?.type === "BlockStatement") unsupported.add("unsupported BlockStatement");
7082
+ else expression(init.body, allowed);
7083
+ return [...unsupported];
7084
+ }
7085
+
6761
7086
  // src/plugin/evaluator.ts
6762
7087
  function stripTsFromSource(node2, code) {
6763
7088
  const cuts = [];
@@ -6814,6 +7139,7 @@ var SUPPORTED = {
6814
7139
  many: (...a) => many(a[0]),
6815
7140
  oneOrMore: (...a) => oneOrMore(a[0]),
6816
7141
  optional: (...a) => optional(a[0]),
7142
+ skip: (...a) => skip(a[0], a[1]),
6817
7143
  sepBy: (...a) => sepBy(a[0], a[1]),
6818
7144
  trivia: (...a) => trivia(a[0]),
6819
7145
  label: (...a) => label(a[0], a[1]),
@@ -6875,12 +7201,12 @@ function staticNodeOptions(expr) {
6875
7201
  if (p.computed) continue;
6876
7202
  const key = p.key;
6877
7203
  const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
6878
- if (name === "unwrap" || name === "collapse") {
7204
+ if (name === "unwrap" || name === "collapse" || name === "captureTrivia" || name === "trailingTrivia") {
6879
7205
  const val = p.value;
6880
7206
  if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
6881
7207
  }
6882
7208
  }
6883
- return opts.unwrap || opts.collapse ? opts : void 0;
7209
+ return opts.unwrap || opts.collapse || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
6884
7210
  }
6885
7211
  function exprToCombi(node2, scope, code, mfs) {
6886
7212
  if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
@@ -6942,11 +7268,15 @@ function exprToCombi(node2, scope, code, mfs) {
6942
7268
  if (!isCombinator(inner)) return null;
6943
7269
  const be = buildArg;
6944
7270
  const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
6945
- const buildSrc = hasBuild ? code.slice(be.start, be.end) : void 0;
7271
+ const buildSrc = hasBuild ? stripTsFromSource(be, code) : void 0;
6946
7272
  const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
6947
7273
  try {
6948
7274
  const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
6949
- if (combi._def.tag === "node" && buildSrc !== void 0) combi._def.buildSrc = buildSrc;
7275
+ if (combi._def.tag === "node" && buildSrc !== void 0) {
7276
+ combi._def.buildSrc = buildSrc;
7277
+ const staticError = directBuilderUnsupportedBindings(buildSrc);
7278
+ if (staticError.length > 0) combi._def.buildStaticError = staticError;
7279
+ }
6950
7280
  return combi;
6951
7281
  } catch {
6952
7282
  return null;
@@ -7039,7 +7369,7 @@ function exprToCombi(node2, scope, code, mfs) {
7039
7369
  if (code === void 0 || mfs === void 0) return null;
7040
7370
  const [predArg] = node2.arguments;
7041
7371
  if (!predArg || predArg.type === "SpreadElement") return null;
7042
- const predSrc = code.slice(predArg.start, predArg.end);
7372
+ const predSrc = stripTsFromSource(predArg, code);
7043
7373
  mfs.push(predSrc);
7044
7374
  try {
7045
7375
  const combi = guard(() => true);
@@ -7054,7 +7384,7 @@ function exprToCombi(node2, scope, code, mfs) {
7054
7384
  if (code === void 0 || mfs === void 0) return null;
7055
7385
  const [extraArg, innerArg] = node2.arguments;
7056
7386
  if (!extraArg || !innerArg || extraArg.type === "SpreadElement" || innerArg.type === "SpreadElement") return null;
7057
- const extraSrc = code.slice(extraArg.start, extraArg.end);
7387
+ const extraSrc = stripTsFromSource(extraArg, code);
7058
7388
  mfs.push(extraSrc);
7059
7389
  const inner = anyValue(innerArg, scope, code, mfs);
7060
7390
  if (!isCombinator(inner)) return null;
@@ -7390,7 +7720,7 @@ function parseModuleCached(filePath) {
7390
7720
  let parsed = null;
7391
7721
  try {
7392
7722
  const src = fs.readFileSync(filePath, "utf8");
7393
- const r = (0, import_oxc_parser.parseSync)(filePath, src);
7723
+ const r = (0, import_oxc_parser2.parseSync)(filePath, src);
7394
7724
  if (r.errors.length === 0) parsed = { body: r.program.body, src };
7395
7725
  } catch {
7396
7726
  }
@@ -7517,7 +7847,7 @@ function extractImportBindings(body) {
7517
7847
  function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false) {
7518
7848
  let result;
7519
7849
  try {
7520
- result = (0, import_oxc_parser.parseSync)(id, code);
7850
+ result = (0, import_oxc_parser2.parseSync)(id, code);
7521
7851
  } catch {
7522
7852
  return null;
7523
7853
  }
@@ -7555,6 +7885,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7555
7885
  const warnings = [];
7556
7886
  beginLoweringCapture();
7557
7887
  let anyUnresolved = false;
7888
+ let runtimeComposeFallback = false;
7558
7889
  let ruleMapHolderCounter = 0;
7559
7890
  const lineOf = (pos) => {
7560
7891
  let line = 1;
@@ -7887,7 +8218,10 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7887
8218
  }
7888
8219
  if (isComposeCall(init)) {
7889
8220
  const fused = compileComposeCall(init);
7890
- if (!fused) continue;
8221
+ if (!fused) {
8222
+ runtimeComposeFallback = true;
8223
+ continue;
8224
+ }
7891
8225
  localComposedCarried.set(varName, fused.carried);
7892
8226
  if (fused.trivia) localComposedTrivia.set(varName, fused.trivia);
7893
8227
  const replacement = exportPrefix ? withCarriedPieces(fused.replacement, fused.carried) : fused.replacement;
@@ -7987,7 +8321,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7987
8321
  ms.overwrite(imp.start, imp.end, stripped);
7988
8322
  }
7989
8323
  }
7990
- for (const { start, end, replacement } of [...replacements].sort((a, b) => b.start - a.start)) {
8324
+ for (const { start, end, replacement } of (runtimeComposeFallback ? [] : replacements).sort((a, b) => b.start - a.start)) {
7991
8325
  ms.overwrite(start, end, replacement);
7992
8326
  }
7993
8327
  const unlowered = endLoweringCapture();