@sprlab/wccompiler 0.16.3 → 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.
Files changed (2) hide show
  1. package/lib/codegen.js +30 -6
  2. package/package.json +1 -1
package/lib/codegen.js CHANGED
@@ -58,19 +58,43 @@ function slotPropRef(source, signalNames, computedNames, propNames) {
58
58
  }
59
59
 
60
60
  /**
61
- * Wrap an expression in parentheses if it contains a ternary operator.
62
- * This prevents operator precedence issues when combining with ?? (nullish coalescing).
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)
63
72
  *
64
73
  * @param {string} expr - Expression to potentially wrap
65
- * @returns {string} - Wrapped expression if it contains ternary, otherwise unchanged
74
+ * @returns {string} - Wrapped expression if it contains risky operators, otherwise unchanged
66
75
  */
67
76
  function wrapTernaryExpr(expr) {
68
77
  const trimmed = expr.trim();
69
- // Check if expression contains ternary operator (? followed by :)
70
- // Simple heuristic: if it has both ? and :, wrap it
71
- if (trimmed.includes('?') && trimmed.includes(':')) {
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) {
72
95
  return `(${trimmed})`;
73
96
  }
97
+
74
98
  return trimmed;
75
99
  }
76
100
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprlab/wccompiler",
3
- "version": "0.16.3",
3
+ "version": "0.16.4",
4
4
  "description": "Zero-runtime compiler that transforms .wcc single-file components into native web components with signals-based reactivity",
5
5
  "type": "module",
6
6
  "exports": {