@sprlab/wccompiler 0.16.2 → 0.16.4
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/lib/codegen.js +46 -5
- package/package.json +1 -1
package/lib/codegen.js
CHANGED
|
@@ -57,6 +57,47 @@ function slotPropRef(source, signalNames, computedNames, propNames) {
|
|
|
57
57
|
return `'${source}'`;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Wrap an expression in parentheses if it contains operators that could have
|
|
62
|
+
* precedence issues when combined with ?? (nullish coalescing).
|
|
63
|
+
*
|
|
64
|
+
* This prevents bugs like: this._count() || 'No items' ?? ''
|
|
65
|
+
* which JavaScript interprets as: this._count() || ('No items' ?? '')
|
|
66
|
+
*
|
|
67
|
+
* Operators that need wrapping:
|
|
68
|
+
* - Ternary: ? :
|
|
69
|
+
* - Logical OR: ||
|
|
70
|
+
* - Logical AND: &&
|
|
71
|
+
* - Nullish coalescing: ?? (nested)
|
|
72
|
+
*
|
|
73
|
+
* @param {string} expr - Expression to potentially wrap
|
|
74
|
+
* @returns {string} - Wrapped expression if it contains risky operators, otherwise unchanged
|
|
75
|
+
*/
|
|
76
|
+
function wrapTernaryExpr(expr) {
|
|
77
|
+
const trimmed = expr.trim();
|
|
78
|
+
|
|
79
|
+
// Check for operators that have lower precedence than ?? or can cause ambiguity
|
|
80
|
+
// Ternary operator (? :)
|
|
81
|
+
const hasTernary = trimmed.includes('?') && trimmed.includes(':');
|
|
82
|
+
|
|
83
|
+
// Logical OR (||)
|
|
84
|
+
const hasLogicalOr = trimmed.includes('||');
|
|
85
|
+
|
|
86
|
+
// Logical AND (&&)
|
|
87
|
+
const hasLogicalAnd = trimmed.includes('&&');
|
|
88
|
+
|
|
89
|
+
// Nested nullish coalescing (??)
|
|
90
|
+
// If expression contains ??, wrap it to avoid conflict with the trailing ?? ''
|
|
91
|
+
const hasNullish = trimmed.includes('??');
|
|
92
|
+
|
|
93
|
+
// Wrap if any risky operator is found
|
|
94
|
+
if (hasTernary || hasLogicalOr || hasLogicalAnd || hasNullish) {
|
|
95
|
+
return `(${trimmed})`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return trimmed;
|
|
99
|
+
}
|
|
100
|
+
|
|
60
101
|
/**
|
|
61
102
|
* Transform an expression by rewriting signal/computed variable references
|
|
62
103
|
* to use `this._x()` / `this._c_x()` syntax for auto-unwrapping.
|
|
@@ -444,7 +485,7 @@ function generateItemSetup(lines, forBlock, itemVar, indexVar, propNames, signal
|
|
|
444
485
|
lines.push(`${indent} ${nodeRef}.textContent = ${b.name} ?? '';`);
|
|
445
486
|
} else {
|
|
446
487
|
const expr = transformForExpr(b.name, itemVar, indexVar, propNames, signalNamesSet, computedNamesSet);
|
|
447
|
-
lines.push(`${indent} __effect(() => { ${nodeRef}.textContent = ${expr} ?? ''; });`);
|
|
488
|
+
lines.push(`${indent} __effect(() => { ${nodeRef}.textContent = ${wrapTernaryExpr(expr)} ?? ''; });`);
|
|
448
489
|
}
|
|
449
490
|
}
|
|
450
491
|
|
|
@@ -650,7 +691,7 @@ function generateItemSetup(lines, forBlock, itemVar, indexVar, propNames, signal
|
|
|
650
691
|
lines.push(`${indent} ${nodeRef}.textContent = ${b.name} ?? '';`);
|
|
651
692
|
} else {
|
|
652
693
|
const expr = transformForExpr(b.name, itemVar, indexVar, propNames, signalNamesSet, computedNamesSet);
|
|
653
|
-
lines.push(`${indent} __effect(() => { ${nodeRef}.textContent = ${expr} ?? ''; });`);
|
|
694
|
+
lines.push(`${indent} __effect(() => { ${nodeRef}.textContent = ${wrapTernaryExpr(expr)} ?? ''; });`);
|
|
654
695
|
}
|
|
655
696
|
}
|
|
656
697
|
|
|
@@ -779,7 +820,7 @@ function generateNestedItemSetup(lines, innerFor, outerItemVar, outerIndexVar, i
|
|
|
779
820
|
lines.push(`${indent}${nodeRef}.textContent = ${b.name} ?? '';`);
|
|
780
821
|
} else {
|
|
781
822
|
const expr = transformNested(b.name);
|
|
782
|
-
lines.push(`${indent}__effect(() => { ${nodeRef}.textContent = ${expr} ?? ''; });`);
|
|
823
|
+
lines.push(`${indent}__effect(() => { ${nodeRef}.textContent = ${wrapTernaryExpr(expr)} ?? ''; });`);
|
|
783
824
|
}
|
|
784
825
|
}
|
|
785
826
|
|
|
@@ -1328,7 +1369,7 @@ export function generateComponent(parseResult, options = {}) {
|
|
|
1328
1369
|
ref = transformExpr(exprWithParens, signalNames, computedNames, propsObjectName, propNames, emitsObjectName, constantNames, methodNames, modelVarMap);
|
|
1329
1370
|
}
|
|
1330
1371
|
lines.push(' this.__disposers.push(__effect(() => {');
|
|
1331
|
-
lines.push(` this.${b.varName}.textContent = ${ref} ?? '';`);
|
|
1372
|
+
lines.push(` this.${b.varName}.textContent = ${wrapTernaryExpr(ref)} ?? '';`);
|
|
1332
1373
|
lines.push(' }));');
|
|
1333
1374
|
}
|
|
1334
1375
|
}
|
|
@@ -2016,7 +2057,7 @@ export function generateComponent(parseResult, options = {}) {
|
|
|
2016
2057
|
} else {
|
|
2017
2058
|
ref = transformExpr(b.name, signalNames, computedNames, propsObjectName, propNames, emitsObjectName, constantNames, methodNames, modelVarMap);
|
|
2018
2059
|
}
|
|
2019
|
-
lines.push(` __effect(() => { ${b.varName}.textContent = ${ref} ?? ''; });`);
|
|
2060
|
+
lines.push(` __effect(() => { ${b.varName}.textContent = ${wrapTernaryExpr(ref)} ?? ''; });`);
|
|
2020
2061
|
}
|
|
2021
2062
|
}
|
|
2022
2063
|
|
package/package.json
CHANGED