@tsrx/core 0.1.51 → 0.1.53
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.
- package/package.json +1 -1
- package/src/plugin.js +46 -7
package/package.json
CHANGED
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
|
|
@@ -2452,13 +2453,20 @@ export function TSRXPlugin(config) {
|
|
|
2452
2453
|
// Closing token after the template at expression position. For `}`
|
|
2453
2454
|
// only pop if it actually closes this `b_expr` — otherwise the
|
|
2454
2455
|
// brace targets an inner callback/object body that should pop it
|
|
2455
|
-
// naturally on the next token step.
|
|
2456
|
+
// naturally on the next token step. Only compensate while the stack
|
|
2457
|
+
// has not unwound below the enclosing expression's depth: a balanced
|
|
2458
|
+
// element leaves the stack at that depth and the closing token's own
|
|
2459
|
+
// `updateContext` then pops its real opener (going one below), so a
|
|
2460
|
+
// remaining `(`/`[`/b_expr on top belongs to a still-open outer
|
|
2461
|
+
// group — popping it would make the group's own closer pop the
|
|
2462
|
+
// context underneath it (e.g. an attribute container's brace).
|
|
2456
2463
|
if (
|
|
2457
|
-
|
|
2464
|
+
ctx.length >= enclosing_context_depth &&
|
|
2465
|
+
((this.type === tt.braceR &&
|
|
2458
2466
|
top === b_expr &&
|
|
2459
2467
|
(this.#countFollowingRightBraces() === 0 || second === b_expr)) ||
|
|
2460
|
-
|
|
2461
|
-
|
|
2468
|
+
(this.type === tt.parenR && top?.token === '(') ||
|
|
2469
|
+
(this.type === tt.bracketR && top?.token === '['))
|
|
2462
2470
|
) {
|
|
2463
2471
|
ctx.pop();
|
|
2464
2472
|
this.exprAllowed = false;
|
|
@@ -4314,11 +4322,15 @@ export function TSRXPlugin(config) {
|
|
|
4314
4322
|
}
|
|
4315
4323
|
}
|
|
4316
4324
|
|
|
4325
|
+
// This element's `jsxTagStart` has already pushed its own `tc_expr` and
|
|
4326
|
+
// `tc_oTag`, so everything below them is the enclosing expression's
|
|
4327
|
+
// stack — the depth a balanced element parse must return to.
|
|
4328
|
+
const enclosing_context_depth = this.context.length - 2;
|
|
4317
4329
|
this.next();
|
|
4318
4330
|
const parsed = /** @type {import('estree-jsx').JSXElement} */ (
|
|
4319
4331
|
/** @type {unknown} */ (this.parseElement())
|
|
4320
4332
|
);
|
|
4321
|
-
this.#popTokenContextsAfterTemplateExpressionElement(parsed);
|
|
4333
|
+
this.#popTokenContextsAfterTemplateExpressionElement(parsed, enclosing_context_depth);
|
|
4322
4334
|
return parsed;
|
|
4323
4335
|
}
|
|
4324
4336
|
|
|
@@ -4595,7 +4607,34 @@ export function TSRXPlugin(config) {
|
|
|
4595
4607
|
// text never starts at `<`, so drop the leaked context and re-read the
|
|
4596
4608
|
// tag instead of emitting an empty node.
|
|
4597
4609
|
if (this.input.charCodeAt(this.start) === CharCode.lessThan) {
|
|
4598
|
-
if (this
|
|
4610
|
+
if (this.#jsxExpressionContainerDepth > 0) {
|
|
4611
|
+
// Inside a `{ … }` container the whole-stack counts below are
|
|
4612
|
+
// blind: the enclosing template's `tc_expr` contexts sit on the
|
|
4613
|
+
// stack but their elements are not on the container-scoped
|
|
4614
|
+
// `#path`. Scope both counts to the container instead — each
|
|
4615
|
+
// element opened inside it (all on `#path` above the container's
|
|
4616
|
+
// baseline) still owns one `tc_expr` that its closing tag's
|
|
4617
|
+
// `jsxTagEnd` pops itself, so only the run's excess above that
|
|
4618
|
+
// quota is leaked. Popping deeper would make a re-read closing
|
|
4619
|
+
// tag pop the container's brace or the enclosing tag context.
|
|
4620
|
+
const path_baseline = this.#expressionContainerPathBaselines.at(-1) ?? 0;
|
|
4621
|
+
let open_elements = 0;
|
|
4622
|
+
for (let i = path_baseline; i < this.#path.length; i++) {
|
|
4623
|
+
if (this.#isNativeTemplateNode(this.#path[i])) open_elements++;
|
|
4624
|
+
}
|
|
4625
|
+
let run = 0;
|
|
4626
|
+
for (
|
|
4627
|
+
let i = this.context.length - 1;
|
|
4628
|
+
i >= 0 && this.context[i] === tstc.tc_expr;
|
|
4629
|
+
i--
|
|
4630
|
+
) {
|
|
4631
|
+
run++;
|
|
4632
|
+
}
|
|
4633
|
+
while (run > open_elements && this.curContext() === tstc.tc_expr) {
|
|
4634
|
+
this.context.pop();
|
|
4635
|
+
run--;
|
|
4636
|
+
}
|
|
4637
|
+
} else if (this.input.charCodeAt(this.start + 1) === CharCode.slash) {
|
|
4599
4638
|
while (this.curContext() === tstc.tc_expr) {
|
|
4600
4639
|
this.context.pop();
|
|
4601
4640
|
}
|