@tsrx/core 0.1.52 → 0.1.54

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/plugin.js +25 -7
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Core compiler infrastructure for TSRX syntax",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.1.52",
6
+ "version": "0.1.54",
7
7
  "type": "module",
8
8
  "repository": {
9
9
  "type": "git",
package/src/plugin.js CHANGED
@@ -2348,8 +2348,9 @@ export function TSRXPlugin(config) {
2348
2348
 
2349
2349
  /**
2350
2350
  * @param {ESTreeJSX.JSXElement | ESTreeJSX.JSXFragment} node
2351
+ * @param {number} enclosing_context_depth
2351
2352
  */
2352
- #popTokenContextsAfterTemplateExpressionElement(node) {
2353
+ #popTokenContextsAfterTemplateExpressionElement(node, enclosing_context_depth) {
2353
2354
  // A fragment in expression position (`() => <>…</>`) leaves the tokenizer
2354
2355
  // at `exprAllowed === false`, unlike a self-closing element. When the next
2355
2356
  // token is a `;` or ASI can insert one, the following statement may
@@ -2439,9 +2440,15 @@ export function TSRXPlugin(config) {
2439
2440
  }
2440
2441
  // Statement-bodied native template attributes can leave the attribute's
2441
2442
  // expression contexts above the still-open JSX tag context. Strip
2442
- // those so a following `/>` stays in JSX opening-tag mode.
2443
+ // those so a following `/>` stays in JSX opening-tag mode. Once the
2444
+ // stack has unwound below the enclosing expression's depth the same
2445
+ // tail shape means something else: the `}` closed an inner child
2446
+ // container (its own brace context already popped) and the tc_expr
2447
+ // belongs to a still-open element between the attribute brace and
2448
+ // this one — stripping would drop the attribute container's brace.
2443
2449
  if (
2444
2450
  this.type === tt.braceR &&
2451
+ ctx.length >= enclosing_context_depth &&
2445
2452
  top === tstc.tc_expr &&
2446
2453
  second === b_expr &&
2447
2454
  ctx[ci - 2] === tstc.tc_oTag
@@ -2452,13 +2459,20 @@ export function TSRXPlugin(config) {
2452
2459
  // Closing token after the template at expression position. For `}`
2453
2460
  // only pop if it actually closes this `b_expr` — otherwise the
2454
2461
  // brace targets an inner callback/object body that should pop it
2455
- // naturally on the next token step.
2462
+ // naturally on the next token step. Only compensate while the stack
2463
+ // has not unwound below the enclosing expression's depth: a balanced
2464
+ // element leaves the stack at that depth and the closing token's own
2465
+ // `updateContext` then pops its real opener (going one below), so a
2466
+ // remaining `(`/`[`/b_expr on top belongs to a still-open outer
2467
+ // group — popping it would make the group's own closer pop the
2468
+ // context underneath it (e.g. an attribute container's brace).
2456
2469
  if (
2457
- (this.type === tt.braceR &&
2470
+ ctx.length >= enclosing_context_depth &&
2471
+ ((this.type === tt.braceR &&
2458
2472
  top === b_expr &&
2459
2473
  (this.#countFollowingRightBraces() === 0 || second === b_expr)) ||
2460
- (this.type === tt.parenR && top?.token === '(') ||
2461
- (this.type === tt.bracketR && top?.token === '[')
2474
+ (this.type === tt.parenR && top?.token === '(') ||
2475
+ (this.type === tt.bracketR && top?.token === '['))
2462
2476
  ) {
2463
2477
  ctx.pop();
2464
2478
  this.exprAllowed = false;
@@ -4314,11 +4328,15 @@ export function TSRXPlugin(config) {
4314
4328
  }
4315
4329
  }
4316
4330
 
4331
+ // This element's `jsxTagStart` has already pushed its own `tc_expr` and
4332
+ // `tc_oTag`, so everything below them is the enclosing expression's
4333
+ // stack — the depth a balanced element parse must return to.
4334
+ const enclosing_context_depth = this.context.length - 2;
4317
4335
  this.next();
4318
4336
  const parsed = /** @type {import('estree-jsx').JSXElement} */ (
4319
4337
  /** @type {unknown} */ (this.parseElement())
4320
4338
  );
4321
- this.#popTokenContextsAfterTemplateExpressionElement(parsed);
4339
+ this.#popTokenContextsAfterTemplateExpressionElement(parsed, enclosing_context_depth);
4322
4340
  return parsed;
4323
4341
  }
4324
4342