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.
@@ -1,7 +1,7 @@
1
1
  // src/plugin/index.ts
2
2
  import * as fs from "node:fs";
3
3
  import { createUnplugin } from "unplugin";
4
- import { parseSync } from "oxc-parser";
4
+ import { parseSync as parseSync2 } from "oxc-parser";
5
5
  import { ResolverFactory } from "oxc-resolver";
6
6
  import MagicString from "magic-string";
7
7
 
@@ -1474,6 +1474,12 @@ function scanTrivia(input, cur, ctx) {
1474
1474
  const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1475
1475
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1476
1476
  }
1477
+ function consumeTrivia(input, cur, ctx) {
1478
+ if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1479
+ const scan = scanTrivia(input, cur, ctx);
1480
+ scan.commit();
1481
+ return scan.end;
1482
+ }
1477
1483
  function fastTriviaScanner(trivia2) {
1478
1484
  const cached = fastTriviaCache.get(trivia2);
1479
1485
  if (cached !== void 0) return cached;
@@ -2217,6 +2223,98 @@ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
2217
2223
  return false;
2218
2224
  }
2219
2225
  }
2226
+ function parserHasTriviaSite(p, seen = /* @__PURE__ */ new Set()) {
2227
+ if (seen.has(p)) return true;
2228
+ seen.add(p);
2229
+ const d = p._def;
2230
+ switch (d.tag) {
2231
+ // Trivia is skipped between/around elements or iterations → a site.
2232
+ case "sequence":
2233
+ case "many":
2234
+ case "oneOrMore":
2235
+ case "sepBy":
2236
+ case "scanTo":
2237
+ case "recover":
2238
+ case "skip":
2239
+ return true;
2240
+ // Nested node manages its own trivia frame; none logs here.
2241
+ case "node":
2242
+ return false;
2243
+ // Pure terminals + trivia-suppressing token: no site.
2244
+ case "regex":
2245
+ case "literal":
2246
+ case "keywords":
2247
+ case "guard":
2248
+ case "token":
2249
+ return false;
2250
+ // Transparent single-child wrappers: recurse.
2251
+ case "optional":
2252
+ case "transform":
2253
+ case "trivia":
2254
+ case "label":
2255
+ case "expect":
2256
+ case "withCtx":
2257
+ case "not":
2258
+ case "field":
2259
+ return parserHasTriviaSite(d.parser, seen);
2260
+ case "choice":
2261
+ return d.parsers.some((x) => parserHasTriviaSite(x, seen));
2262
+ case "grammar":
2263
+ return parserHasTriviaSite(d.parser, seen);
2264
+ case "lazy": {
2265
+ try {
2266
+ return parserHasTriviaSite(d.thunk(), seen);
2267
+ } catch {
2268
+ return true;
2269
+ }
2270
+ }
2271
+ default:
2272
+ return true;
2273
+ }
2274
+ }
2275
+ function parserEnablesTriviaCapture(p, seen = /* @__PURE__ */ new Set()) {
2276
+ if (seen.has(p)) return false;
2277
+ seen.add(p);
2278
+ const d = p._def;
2279
+ switch (d.tag) {
2280
+ case "grammar":
2281
+ return d.captureTrivia === true || parserEnablesTriviaCapture(d.parser, seen);
2282
+ case "node":
2283
+ return false;
2284
+ case "sequence":
2285
+ case "choice":
2286
+ return d.parsers.some((x) => parserEnablesTriviaCapture(x, seen));
2287
+ case "sepBy":
2288
+ return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.separator, seen);
2289
+ case "skip":
2290
+ return parserEnablesTriviaCapture(d.main, seen) || parserEnablesTriviaCapture(d.skipped, seen);
2291
+ case "scanTo":
2292
+ return parserEnablesTriviaCapture(d.sentinel, seen) || d.skip.some((x) => parserEnablesTriviaCapture(x, seen));
2293
+ case "recover":
2294
+ return parserEnablesTriviaCapture(d.parser, seen) || parserEnablesTriviaCapture(d.sentinel, seen);
2295
+ case "many":
2296
+ case "oneOrMore":
2297
+ case "optional":
2298
+ case "transform":
2299
+ case "trivia":
2300
+ case "token":
2301
+ case "label":
2302
+ case "field":
2303
+ case "expect":
2304
+ case "withCtx":
2305
+ case "not":
2306
+ return parserEnablesTriviaCapture(d.parser, seen);
2307
+ case "lazy": {
2308
+ try {
2309
+ return parserEnablesTriviaCapture(d.thunk(), seen);
2310
+ } catch {
2311
+ return false;
2312
+ }
2313
+ }
2314
+ default:
2315
+ return false;
2316
+ }
2317
+ }
2220
2318
  function buildFieldMap(captures) {
2221
2319
  if (!captures?.length) return void 0;
2222
2320
  const out = {};
@@ -2254,11 +2352,13 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2254
2352
  };
2255
2353
  const unwrap = opts?.unwrap === true;
2256
2354
  const collapse = opts?.collapse === true;
2355
+ const captureTrivia = opts?.captureTrivia === true;
2356
+ const trailingTrivia = opts?.trailingTrivia === true;
2257
2357
  if (unwrap && collapse) {
2258
2358
  throw new Error("node() options cannot set both unwrap and collapse");
2259
2359
  }
2260
- const def = unwrap || collapse ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {} } : baseDef;
2261
- const capturesTrivia = build ? buildReadsTrivia(def) : true;
2360
+ const def = unwrap || collapse || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
2361
+ const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
2262
2362
  const clonesState = build ? buildReadsState(def) : true;
2263
2363
  const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
2264
2364
  return {
@@ -2274,7 +2374,11 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2274
2374
  ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
2275
2375
  }
2276
2376
  if (!capturesTrivia) ctx.captureTrivia = false;
2277
- const r = combinator.parse(input, pos, ctx);
2377
+ let r = combinator.parse(input, pos, ctx);
2378
+ if (r.ok && trailingTrivia && ctx.trivia) {
2379
+ const end = consumeTrivia(input, r.span.end, ctx);
2380
+ r = { ...r, span: { start: r.span.start, end } };
2381
+ }
2278
2382
  const fields = capturesFields ? buildFieldMap(ctx._fields) : void 0;
2279
2383
  ctx._fields = savedFields;
2280
2384
  ctx._triviaCaptureMask = savedMask;
@@ -2282,8 +2386,9 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2282
2386
  if (!r.ok) return r;
2283
2387
  const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
2284
2388
  const nodeType = def.type ?? missingInferredType();
2285
- 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 };
2286
- const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : "", span: r.span };
2389
+ const cstOutput = ctx.build?._parsemanCstOutput === true;
2390
+ 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 };
2391
+ 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 };
2287
2392
  if (saved.buf !== void 0 || saved.ch !== void 0) {
2288
2393
  pushCstChild(ctx, built, rawEntry);
2289
2394
  }
@@ -2400,6 +2505,7 @@ function parser(opts, root) {
2400
2505
  parser: root,
2401
2506
  triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
2402
2507
  clearTrivia,
2508
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
2403
2509
  trackLines: opts.trackLines ?? false
2404
2510
  },
2405
2511
  parse(input, pos, _ctx) {
@@ -3536,7 +3642,7 @@ function scanBranchLabeled(shape, kindIndex, mint) {
3536
3642
  ` if (${m.end} > _e) {`,
3537
3643
  ` if (_cap) {`,
3538
3644
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, ${m.end}, ${kindIndex})`,
3539
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << kindIndex}))) _ctx._cstTriviaLog.push(_e, ${m.end}, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${kindIndex})`,
3645
+ ` 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})`,
3540
3646
  ` }`,
3541
3647
  ` _e = ${m.end}`,
3542
3648
  ` continue`,
@@ -3592,7 +3698,7 @@ function analyzeTriviaFastPath(trivia2) {
3592
3698
  var CAP_RECORD = [
3593
3699
  ` if (_cap && _e > _pos) {`,
3594
3700
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
3595
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
3701
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
3596
3702
  ` }`
3597
3703
  ].join("\n");
3598
3704
  function composeFastLoop(shapes) {
@@ -3652,7 +3758,7 @@ function buildLabeledRegexTriviaFnDecl(fnName, spec, reNames) {
3652
3758
  ` const _ce = _e + _m${i}[0].length`,
3653
3759
  ` if (_cap) {`,
3654
3760
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
3655
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3761
+ ` 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})`,
3656
3762
  ` }`,
3657
3763
  ` _e = _ce`,
3658
3764
  ` _matched = true`,
@@ -3690,7 +3796,7 @@ function buildLabeledRuntimeTriviaFnDecl(fnName, spec, rpStartIndex) {
3690
3796
  ` const _ce = _r${i}.span.end`,
3691
3797
  ` if (_cap) {`,
3692
3798
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_e, _ce, ${k})`,
3693
- ` if (_ctx._cstTriviaLog !== undefined && (_ctx._triviaCaptureMask === undefined || (_ctx._triviaCaptureMask & ${1 << k}))) _ctx._cstTriviaLog.push(_e, _ce, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0, ${k})`,
3799
+ ` 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})`,
3694
3800
  ` }`,
3695
3801
  ` _e = _ce`,
3696
3802
  ` _matched = true`,
@@ -4041,7 +4147,7 @@ function ensureTriviaFn(ctx) {
4041
4147
  ` }`,
4042
4148
  ` if (_cap && _e > _pos) {`,
4043
4149
  ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
4044
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
4150
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
4045
4151
  ` }`,
4046
4152
  ` return _e`,
4047
4153
  `}`
@@ -5176,47 +5282,71 @@ function emitNode(def, ctx, pos) {
5176
5282
  ctx.buildSrcs.push(def.buildSrc ?? null);
5177
5283
  }
5178
5284
  const i = ind(ctx);
5179
- const capturesTrivia = mkType !== null || !structural && buildReadsTrivia(def);
5285
+ const capturesTrivia = mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && buildReadsTrivia(def);
5180
5286
  const clonesState = !structural && buildReadsState(def);
5181
5287
  const hasFields = parserHasOwnFields(def.parser);
5182
5288
  const capturesFields = hasFields && !structural && buildReadsFields(def);
5289
+ const innerEnablesTriviaCapture = parserEnablesTriviaCapture(def.parser);
5183
5290
  const chV = v(ctx, "_ch");
5184
5291
  const rawV = v(ctx, "_raw");
5185
- const capTLv = structural ? v(ctx, "_ctl") : null;
5292
+ const capTLv = structural || capturesTrivia ? v(ctx, "_ctl") : null;
5186
5293
  const capSTv = structural ? v(ctx, "_cst") : null;
5187
5294
  const capFv = structural && hasFields ? v(ctx, "_cf") : null;
5188
5295
  const tlV = capturesTrivia || structural ? v(ctx, "_tl") : "_EMPTY_TL";
5189
- if (!capturesTrivia) ctx.needsEmptyTl = true;
5296
+ if (!capturesTrivia || structural) ctx.needsEmptyTl = true;
5190
5297
  const sc = v(ctx, "_sc"), sl = v(ctx, "_sl"), sr = v(ctx, "_sr"), st = v(ctx, "_st"), stl = v(ctx, "_stl");
5191
5298
  const smk = structural ? v(ctx, "_smk") : null;
5192
5299
  if (structural) ctx.needsHostReads = true;
5193
5300
  const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
5194
- 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)` : ""}
5195
- ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capturesTrivia ? `${i}const ${chV} = [], ${rawV} = [], ${tlV} = []` : `${i}const ${chV} = [], ${rawV} = []`;
5196
- const innerTl = structural ? `${capTLv} ? ${tlV} : undefined` : capturesTrivia ? tlV : "undefined";
5197
- const fieldsOn = structural ? capFv ?? "false" : capturesFields ? "true" : "false";
5301
+ const pmV = v(ctx, "_pm"), recV = v(ctx, "_rec"), capV = v(ctx, "_cap");
5302
+ const profHoist = `${i}const ${pmV} = _ctx._pmProfile, ${recV} = ${pmV}?.phase === 'recognizer', ${capV} = ${pmV}?.phase === 'capture'`;
5303
+ const profileRecognizer = recV;
5304
+ const profileCapture = capV;
5305
+ const structuralCapturesTrivia = structural && (def.captureTrivia === true || def.trailingTrivia === true);
5306
+ 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)))` : ""}
5307
+ ${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 : []`;
5308
+ const innerTl = structural || capturesTrivia ? structural && !innerEnablesTriviaCapture ? `${capTLv} ? ${tlV} : undefined` : tlV : "undefined";
5309
+ const fieldsOn = structural ? capFv ?? "false" : `${profileRecognizer} ? false : ${capturesFields ? "true" : "false"}`;
5198
5310
  const sf = hasFields ? v(ctx, "_sf") : null;
5199
5311
  const fArr = hasFields ? v(ctx, "_fa") : null;
5200
5312
  const fObj = hasFields ? v(ctx, "_fields") : "undefined";
5313
+ const needsTriviaFrame = def.trailingTrivia === true || parserHasTriviaSite(def.parser);
5314
+ const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
5315
+ 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}` : ""}` : "";
5316
+ const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
5201
5317
  const stmts = [
5318
+ profHoist,
5202
5319
  allocStmt,
5203
- `${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` : ""}`,
5204
- `${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` : ""}`
5320
+ `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
5321
+ `${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
5205
5322
  ];
5206
- const { stmts: innerStmts, okVar, endVar } = emitFallible(def.parser, ctx, pos);
5323
+ const { stmts: innerStmts, okVar, endVar: innerEndVar } = emitFallible(def.parser, ctx, pos);
5324
+ const endVar = def.trailingTrivia === true && ctx.activeTrivia ? v(ctx, "_trailend") : innerEndVar;
5207
5325
  stmts.push(...innerStmts);
5326
+ if (def.trailingTrivia === true && ctx.activeTrivia) {
5327
+ const triviaFn = ensureTriviaFn(ctx);
5328
+ stmts.push(`${i}const ${endVar} = ${okVar} ? ${triviaFn}(input, ${innerEndVar}, _ctx, 1) : ${innerEndVar}`);
5329
+ }
5208
5330
  if (sf && fArr) {
5209
5331
  stmts.push(`${i}const ${fArr} = _ctx._fields`);
5210
5332
  }
5211
- 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}` : ""}`);
5333
+ stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}${restoreTrivia}${sf ? `; _ctx._fields = ${sf}` : ""}`);
5212
5334
  stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
5335
+ stmts.push(
5336
+ `${i}if (_ctx._pmProfile) {`,
5337
+ `${i} _ctx._pmProfile.nodes++`,
5338
+ `${i} if (${profileCapture}) {`,
5339
+ `${i} _ctx._pmProfile.childSlots += ${chV}.length; _ctx._pmProfile.rawSlots += ${rawV}.length; _ctx._pmProfile.triviaSlots += ${tlV}.length${fArr ? `; _ctx._pmProfile.fieldSlots += ${fArr} ? ${fArr}.length : 0` : ""}`,
5340
+ `${i} }`,
5341
+ `${i}}`
5342
+ );
5213
5343
  let stV = "undefined";
5214
5344
  if (structural) {
5215
5345
  stV = v(ctx, "_nst");
5216
5346
  stmts.push(`${i}const ${stV} = ${capSTv} && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5217
5347
  } else if (clonesState) {
5218
5348
  stV = v(ctx, "_nst");
5219
- stmts.push(`${i}const ${stV} = _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5349
+ stmts.push(`${i}const ${stV} = !(${profileRecognizer} || ${profileCapture}) && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
5220
5350
  }
5221
5351
  if (sf && fArr) {
5222
5352
  const fe = v(ctx, "_fe");
@@ -5236,15 +5366,18 @@ ${i}const ${chV} = [], ${rawV} = [], ${tlV} = ${capTLv} ? [] : _EMPTY_TL` : capt
5236
5366
  }
5237
5367
  const ndV = v(ctx, "_nd");
5238
5368
  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})`;
5239
- 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;
5240
- 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;
5369
+ const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
5370
+ const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : `_ctx.build?._parsemanCstOutput === true ? (${hostBuildExpr}) : (${buildExpr})`;
5371
+ 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;
5241
5372
  const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
5242
5373
  const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
5243
5374
  const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
5244
5375
  stmts.push(
5245
- `${i}const ${ndV} = ${finalExpr}`,
5246
- `${i}if (${sc}) ${sc}.push(${ndV})`,
5247
- `${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} } })`
5376
+ `${i}const ${ndV} = (${profileRecognizer} || ${profileCapture}) ? undefined : (${finalExpr})`,
5377
+ `${i}if (!(${profileRecognizer})) {`,
5378
+ `${i} if (${sc}) ${sc}.push(${ndV})`,
5379
+ `${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} } })`,
5380
+ `${i}}`
5248
5381
  );
5249
5382
  return { stmts, valueVar: ndV, endVar };
5250
5383
  }
@@ -5486,10 +5619,19 @@ function emitDispatch(p, ctx, pos) {
5486
5619
  ctx.triviaKindLabels = def.triviaParser._meta.triviaKindLabels;
5487
5620
  }
5488
5621
  }
5622
+ const savedCapture = def.captureTrivia ? v(ctx, "_gcap") : null;
5489
5623
  const r = emit(def.parser, ctx, pos);
5490
5624
  ctx.activeTrivia = savedTrivia;
5491
5625
  ctx.triviaKindLabels = savedKindLabels;
5492
- return r;
5626
+ if (!savedCapture) return r;
5627
+ return {
5628
+ ...r,
5629
+ stmts: [
5630
+ `${ind(ctx)}const ${savedCapture} = _ctx.captureTrivia; _ctx.captureTrivia = true`,
5631
+ ...r.stmts,
5632
+ `${ind(ctx)}_ctx.captureTrivia = ${savedCapture}`
5633
+ ]
5634
+ };
5493
5635
  }
5494
5636
  case "not":
5495
5637
  return emitNot(def, ctx, pos);
@@ -6337,9 +6479,15 @@ function evalRuleMapIR(ir) {
6337
6479
  t._def.fnSrc = src;
6338
6480
  return t;
6339
6481
  };
6340
- const _nd = (type, child, src, opts) => {
6341
- const n = node(type, child, void 0, opts);
6482
+ const _nd = (type, child, src, opts, staticError) => {
6483
+ if (staticError !== void 0 && staticError.length > 0) {
6484
+ throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
6485
+ }
6486
+ const n = node(type, child, (() => {
6487
+ throw new Error("IR node build requires static re-lowering");
6488
+ }), opts);
6342
6489
  n._def.buildSrc = src;
6490
+ if (staticError !== void 0) n._def.buildStaticError = staticError;
6343
6491
  return n;
6344
6492
  };
6345
6493
  const _gch = (items) => {
@@ -6589,17 +6737,26 @@ ${body}
6589
6737
  }
6590
6738
  case "node": {
6591
6739
  if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
6592
- const opts = def.unwrap || def.collapse ? `, { ${def.unwrap ? "unwrap: true" : "collapse: true"} }` : "";
6740
+ const optEntries = [
6741
+ ...def.unwrap ? ["unwrap: true"] : [],
6742
+ ...def.collapse ? ["collapse: true"] : [],
6743
+ ...def.captureTrivia ? ["captureTrivia: true"] : [],
6744
+ ...def.trailingTrivia ? ["trailingTrivia: true"] : []
6745
+ ];
6746
+ const opts = optEntries.length > 0 ? `, { ${optEntries.join(", ")} }` : "";
6593
6747
  if (def.type === void 0) {
6594
6748
  if (def.buildSrc !== void 0) throw new Unserializable("inferred node build without inferred type");
6595
6749
  return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
6596
6750
  }
6597
- if (def.buildSrc !== void 0) return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts})`;
6751
+ if (def.buildSrc !== void 0) {
6752
+ const staticError = def.buildStaticError === void 0 ? "" : `${opts ? "" : ", undefined"}, ${JSON.stringify(def.buildStaticError)}`;
6753
+ return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${staticError})`;
6754
+ }
6598
6755
  return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
6599
6756
  }
6600
6757
  case "grammar": {
6601
6758
  const trivia2 = def.clearTrivia ? "null" : def.triviaParser ? kid(def.triviaParser) : "undefined";
6602
- return `parser({ trivia: ${trivia2}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6759
+ return `parser({ trivia: ${trivia2}${def.captureTrivia ? ", captureTrivia: true" : ""}${def.trackLines ? ", trackLines: true" : ""} }, ${kid(def.parser)})`;
6603
6760
  }
6604
6761
  case "withCtx": {
6605
6762
  if (def.extraSrc === void 0) throw new Unserializable("withCtx without extraSrc");
@@ -6614,6 +6771,28 @@ ${body}
6614
6771
  };
6615
6772
 
6616
6773
  // src/compiler/linker.ts
6774
+ function normalizeCstCollapse(collapse) {
6775
+ if (collapse === true) return () => true;
6776
+ if (Array.isArray(collapse)) {
6777
+ const types = new Set(collapse);
6778
+ return (type) => types.has(type);
6779
+ }
6780
+ return typeof collapse === "function" ? collapse : void 0;
6781
+ }
6782
+ function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
6783
+ return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children] };
6784
+ }
6785
+ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
6786
+ if (typeof typeOrOptions === "string") {
6787
+ return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
6788
+ }
6789
+ const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
6790
+ const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2, fields, span2, rawChildren2, triviaLog2, state2);
6791
+ host._parsemanCstOutput = true;
6792
+ if (collapse) host._parsemanCstCollapse = collapse;
6793
+ return host;
6794
+ }
6795
+ cstBuildHost._parsemanCstOutput = true;
6617
6796
  function pickPieces(pieces, names) {
6618
6797
  const winner = /* @__PURE__ */ new Map();
6619
6798
  for (const pc of pieces) for (const k of pc.keys) winner.set(k, pc);
@@ -6723,6 +6902,152 @@ var { isFinite } = Number;
6723
6902
  // src/index.ts
6724
6903
  registerRegexAnalyzer(firstSetFromRegex);
6725
6904
 
6905
+ // src/plugin/direct-builder-static.ts
6906
+ import { parseSync } from "oxc-parser";
6907
+ var STATIC_BUILDER_GLOBALS = /* @__PURE__ */ new Set([
6908
+ "Array",
6909
+ "Boolean",
6910
+ "Date",
6911
+ "JSON",
6912
+ "Math",
6913
+ "NaN",
6914
+ "Number",
6915
+ "Object",
6916
+ "String",
6917
+ "Infinity",
6918
+ "parseFloat",
6919
+ "parseInt",
6920
+ "undefined"
6921
+ ]);
6922
+ function astArray(value) {
6923
+ return Array.isArray(value) ? value : [];
6924
+ }
6925
+ function astChild(value) {
6926
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
6927
+ }
6928
+ function unwrapCallbackExpression(node2) {
6929
+ let current = node2;
6930
+ while (current?.type === "ParenthesizedExpression") current = astChild(current.expression) ?? void 0;
6931
+ return current;
6932
+ }
6933
+ function directBuilderUnsupportedBindings(src) {
6934
+ let init;
6935
+ try {
6936
+ const parsed = parseSync("parseman-direct-builder.ts", `const _direct = (${src})`);
6937
+ if (parsed.errors.length > 0) return ["invalid callback source"];
6938
+ const program = parsed.program;
6939
+ const statement = program.body?.[0];
6940
+ const declaration = statement?.declarations?.[0];
6941
+ init = unwrapCallbackExpression(declaration?.init);
6942
+ } catch {
6943
+ return ["invalid callback source"];
6944
+ }
6945
+ if (init?.type !== "ArrowFunctionExpression" || !Array.isArray(init.params)) return ["unsupported callback shape"];
6946
+ const allowed = new Set(STATIC_BUILDER_GLOBALS);
6947
+ for (const param of init.params) {
6948
+ if (param.type !== "Identifier" || typeof param.name !== "string") return ["unsupported parameter pattern"];
6949
+ allowed.add(param.name);
6950
+ }
6951
+ const unsupported = /* @__PURE__ */ new Set();
6952
+ const reportUnsupportedNode = (ast) => {
6953
+ unsupported.add(`unsupported ${ast.type}`);
6954
+ };
6955
+ const read = (ast, allowedNames) => {
6956
+ if (typeof ast.name === "string" && allowedNames.has(ast.name)) return;
6957
+ unsupported.add(typeof ast.name === "string" ? ast.name : "identifier");
6958
+ };
6959
+ const expression = (node2, allowedNames) => {
6960
+ const ast = astChild(node2);
6961
+ if (!ast) return;
6962
+ switch (ast.type) {
6963
+ case "Literal":
6964
+ return;
6965
+ case "Identifier":
6966
+ read(ast, allowedNames);
6967
+ return;
6968
+ case "ParenthesizedExpression":
6969
+ case "ChainExpression":
6970
+ case "TSAsExpression":
6971
+ case "TSTypeAssertion":
6972
+ case "TSNonNullExpression":
6973
+ expression(ast.expression, allowedNames);
6974
+ return;
6975
+ case "ArrayExpression":
6976
+ for (const element of astArray(ast.elements)) expression(element, allowedNames);
6977
+ return;
6978
+ case "ObjectExpression":
6979
+ for (const property of astArray(ast.properties)) {
6980
+ if (property.type === "SpreadElement") {
6981
+ expression(property.argument, allowedNames);
6982
+ continue;
6983
+ }
6984
+ if (property.type !== "Property" || property.method === true || property.kind !== "init") {
6985
+ reportUnsupportedNode(property);
6986
+ continue;
6987
+ }
6988
+ if (property.computed === true) expression(property.key, allowedNames);
6989
+ expression(property.value, allowedNames);
6990
+ }
6991
+ return;
6992
+ case "MemberExpression":
6993
+ expression(ast.object, allowedNames);
6994
+ if (ast.computed === true) expression(ast.property, allowedNames);
6995
+ return;
6996
+ case "CallExpression":
6997
+ case "NewExpression":
6998
+ expression(ast.callee, allowedNames);
6999
+ for (const argument of astArray(ast.arguments)) expression(argument, allowedNames);
7000
+ return;
7001
+ case "UnaryExpression":
7002
+ case "UpdateExpression":
7003
+ expression(ast.argument, allowedNames);
7004
+ return;
7005
+ case "BinaryExpression":
7006
+ case "LogicalExpression":
7007
+ case "AssignmentExpression":
7008
+ expression(ast.left, allowedNames);
7009
+ expression(ast.right, allowedNames);
7010
+ return;
7011
+ case "ConditionalExpression":
7012
+ expression(ast.test, allowedNames);
7013
+ expression(ast.consequent, allowedNames);
7014
+ expression(ast.alternate, allowedNames);
7015
+ return;
7016
+ case "SequenceExpression":
7017
+ for (const value of astArray(ast.expressions)) expression(value, allowedNames);
7018
+ return;
7019
+ case "TemplateLiteral":
7020
+ for (const value of astArray(ast.expressions)) expression(value, allowedNames);
7021
+ return;
7022
+ case "SpreadElement":
7023
+ expression(ast.argument, allowedNames);
7024
+ return;
7025
+ case "ArrowFunctionExpression": {
7026
+ const nested = new Set(allowedNames);
7027
+ for (const param of astArray(ast.params)) {
7028
+ if (param.type !== "Identifier" || typeof param.name !== "string") {
7029
+ reportUnsupportedNode(param);
7030
+ continue;
7031
+ }
7032
+ nested.add(param.name);
7033
+ }
7034
+ if (astChild(ast.body)?.type === "BlockStatement") {
7035
+ reportUnsupportedNode(astChild(ast.body));
7036
+ return;
7037
+ }
7038
+ expression(ast.body, nested);
7039
+ return;
7040
+ }
7041
+ default:
7042
+ reportUnsupportedNode(ast);
7043
+ return;
7044
+ }
7045
+ };
7046
+ if (astChild(init.body)?.type === "BlockStatement") unsupported.add("unsupported BlockStatement");
7047
+ else expression(init.body, allowed);
7048
+ return [...unsupported];
7049
+ }
7050
+
6726
7051
  // src/plugin/evaluator.ts
6727
7052
  function stripTsFromSource(node2, code) {
6728
7053
  const cuts = [];
@@ -6779,6 +7104,7 @@ var SUPPORTED = {
6779
7104
  many: (...a) => many(a[0]),
6780
7105
  oneOrMore: (...a) => oneOrMore(a[0]),
6781
7106
  optional: (...a) => optional(a[0]),
7107
+ skip: (...a) => skip(a[0], a[1]),
6782
7108
  sepBy: (...a) => sepBy(a[0], a[1]),
6783
7109
  trivia: (...a) => trivia(a[0]),
6784
7110
  label: (...a) => label(a[0], a[1]),
@@ -6840,12 +7166,12 @@ function staticNodeOptions(expr) {
6840
7166
  if (p.computed) continue;
6841
7167
  const key = p.key;
6842
7168
  const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
6843
- if (name === "unwrap" || name === "collapse") {
7169
+ if (name === "unwrap" || name === "collapse" || name === "captureTrivia" || name === "trailingTrivia") {
6844
7170
  const val = p.value;
6845
7171
  if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
6846
7172
  }
6847
7173
  }
6848
- return opts.unwrap || opts.collapse ? opts : void 0;
7174
+ return opts.unwrap || opts.collapse || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
6849
7175
  }
6850
7176
  function exprToCombi(node2, scope, code, mfs) {
6851
7177
  if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
@@ -6907,11 +7233,15 @@ function exprToCombi(node2, scope, code, mfs) {
6907
7233
  if (!isCombinator(inner)) return null;
6908
7234
  const be = buildArg;
6909
7235
  const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
6910
- const buildSrc = hasBuild ? code.slice(be.start, be.end) : void 0;
7236
+ const buildSrc = hasBuild ? stripTsFromSource(be, code) : void 0;
6911
7237
  const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
6912
7238
  try {
6913
7239
  const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
6914
- if (combi._def.tag === "node" && buildSrc !== void 0) combi._def.buildSrc = buildSrc;
7240
+ if (combi._def.tag === "node" && buildSrc !== void 0) {
7241
+ combi._def.buildSrc = buildSrc;
7242
+ const staticError = directBuilderUnsupportedBindings(buildSrc);
7243
+ if (staticError.length > 0) combi._def.buildStaticError = staticError;
7244
+ }
6915
7245
  return combi;
6916
7246
  } catch {
6917
7247
  return null;
@@ -7004,7 +7334,7 @@ function exprToCombi(node2, scope, code, mfs) {
7004
7334
  if (code === void 0 || mfs === void 0) return null;
7005
7335
  const [predArg] = node2.arguments;
7006
7336
  if (!predArg || predArg.type === "SpreadElement") return null;
7007
- const predSrc = code.slice(predArg.start, predArg.end);
7337
+ const predSrc = stripTsFromSource(predArg, code);
7008
7338
  mfs.push(predSrc);
7009
7339
  try {
7010
7340
  const combi = guard(() => true);
@@ -7019,7 +7349,7 @@ function exprToCombi(node2, scope, code, mfs) {
7019
7349
  if (code === void 0 || mfs === void 0) return null;
7020
7350
  const [extraArg, innerArg] = node2.arguments;
7021
7351
  if (!extraArg || !innerArg || extraArg.type === "SpreadElement" || innerArg.type === "SpreadElement") return null;
7022
- const extraSrc = code.slice(extraArg.start, extraArg.end);
7352
+ const extraSrc = stripTsFromSource(extraArg, code);
7023
7353
  mfs.push(extraSrc);
7024
7354
  const inner = anyValue(innerArg, scope, code, mfs);
7025
7355
  if (!isCombinator(inner)) return null;
@@ -7355,7 +7685,7 @@ function parseModuleCached(filePath) {
7355
7685
  let parsed = null;
7356
7686
  try {
7357
7687
  const src = fs.readFileSync(filePath, "utf8");
7358
- const r = parseSync(filePath, src);
7688
+ const r = parseSync2(filePath, src);
7359
7689
  if (r.errors.length === 0) parsed = { body: r.program.body, src };
7360
7690
  } catch {
7361
7691
  }
@@ -7482,7 +7812,7 @@ function extractImportBindings(body) {
7482
7812
  function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSEMAN_MODULE]), warnUnloweredRegex = false, recovery = false) {
7483
7813
  let result;
7484
7814
  try {
7485
- result = parseSync(id, code);
7815
+ result = parseSync2(id, code);
7486
7816
  } catch {
7487
7817
  return null;
7488
7818
  }
@@ -7520,6 +7850,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7520
7850
  const warnings = [];
7521
7851
  beginLoweringCapture();
7522
7852
  let anyUnresolved = false;
7853
+ let runtimeComposeFallback = false;
7523
7854
  let ruleMapHolderCounter = 0;
7524
7855
  const lineOf = (pos) => {
7525
7856
  let line = 1;
@@ -7852,7 +8183,10 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7852
8183
  }
7853
8184
  if (isComposeCall(init)) {
7854
8185
  const fused = compileComposeCall(init);
7855
- if (!fused) continue;
8186
+ if (!fused) {
8187
+ runtimeComposeFallback = true;
8188
+ continue;
8189
+ }
7856
8190
  localComposedCarried.set(varName, fused.carried);
7857
8191
  if (fused.trivia) localComposedTrivia.set(varName, fused.trivia);
7858
8192
  const replacement = exportPrefix ? withCarriedPieces(fused.replacement, fused.carried) : fused.replacement;
@@ -7952,7 +8286,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
7952
8286
  ms.overwrite(imp.start, imp.end, stripped);
7953
8287
  }
7954
8288
  }
7955
- for (const { start, end, replacement } of [...replacements].sort((a, b) => b.start - a.start)) {
8289
+ for (const { start, end, replacement } of (runtimeComposeFallback ? [] : replacements).sort((a, b) => b.start - a.start)) {
7956
8290
  ms.overwrite(start, end, replacement);
7957
8291
  }
7958
8292
  const unlowered = endLoweringCapture();