@llui/vite-plugin 0.1.0 → 0.2.0

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 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAO3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EAIpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,qBAAqB,EAA2B,MAAM,sBAAsB,CAAA;AACrF,OAAO,EAAE,kBAAkB,EAAkB,MAAM,mBAAmB,CAAA;AAiOtE;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA;IAC/C,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IACzD,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;IACnD,YAAY,CAAC,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;CACtD;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,UAAQ,EACf,iBAAiB,UAAQ,EACzB,OAAO,GAAE,MAAM,GAAG,IAAW,EAC7B,OAAO,UAAQ,EACf,WAAW,CAAC,EAAE,mBAAmB,EACjC,YAAY,CAAC,EAAE,mBAAmB,GACjC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAA;CAAE,GAAG,IAAI,CAwYnD;AAgiJD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,wBAAwB,GAAG,IAAI,CAoGjC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA4B7D;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,GAAG,IAAI,CAcrF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CASzF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,GAChE,MAAM,CAYR"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAO3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EAIpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,qBAAqB,EAA2B,MAAM,sBAAsB,CAAA;AACrF,OAAO,EAAE,kBAAkB,EAAkB,MAAM,mBAAmB,CAAA;AAiOtE;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA;IAC/C,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IACzD,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;IACnD,YAAY,CAAC,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;CACtD;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,UAAQ,EACf,iBAAiB,UAAQ,EACzB,OAAO,GAAE,MAAM,GAAG,IAAW,EAC7B,OAAO,UAAQ,EACf,WAAW,CAAC,EAAE,mBAAmB,EACjC,YAAY,CAAC,EAAE,mBAAmB,GACjC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAA;CAAE,GAAG,IAAI,CAwYnD;AAo8ID,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,wBAAwB,GAAG,IAAI,CAoGjC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA4B7D;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,GAAG,IAAI,CAcrF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CASzF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,GAChE,MAAM,CAYR"}
package/dist/transform.js CHANGED
@@ -1097,46 +1097,20 @@ function tryInjectDirty(node, fieldBits, f, fieldBitsHi = new Map()) {
1097
1097
  return null;
1098
1098
  }
1099
1099
  }
1100
- // Build __dirty: (o, n) => (Object.is(o.field, n.field) ? 0 : bit) | ...
1101
- // Compare at top-level field (depth 1) nested path changes within a
1102
- // field must trigger the bit even if the specific sub-path isn't tracked.
1103
- // e.g., route.page tracked but route.data changes must fire.
1100
+ // Top-level field aggregated bit mask. Sub-paths under one field
1101
+ // (`route.page`, `route.data`) collapse into a single entry so
1102
+ // `tryBuildHandlers` and `__maskLegend` can reason per-field. Positions
1103
+ // 0..30 live here; 31..61 in the parallel high-word map below.
1104
1104
  const topLevelBits = new Map();
1105
1105
  for (const [path, bit] of fieldBits) {
1106
1106
  const topField = path.split('.')[0];
1107
1107
  topLevelBits.set(topField, (topLevelBits.get(topField) ?? 0) | bit);
1108
1108
  }
1109
- // Parallel high-word map: top-level fields whose paths fall at bit
1110
- // positions 31..61 contribute here instead of (or in addition to)
1111
- // `topLevelBits`. A field with sub-paths split across both words —
1112
- // e.g., `user.name` at position 30 and `user.email` at position 31 —
1113
- // ends up in both maps under the same top-level key.
1114
1109
  const topLevelBitsHi = new Map();
1115
1110
  for (const [path, bit] of fieldBitsHi) {
1116
1111
  const topField = path.split('.')[0];
1117
1112
  topLevelBitsHi.set(topField, (topLevelBitsHi.get(topField) ?? 0) | bit);
1118
1113
  }
1119
- const comparisons = [];
1120
- for (const [field, bit] of topLevelBits) {
1121
- const oAccess = buildAccess(f, 'o', [field]);
1122
- const nAccess = buildAccess(f, 'n', [field]);
1123
- comparisons.push(f.createParenthesizedExpression(f.createConditionalExpression(f.createCallExpression(f.createPropertyAccessExpression(f.createIdentifier('Object'), 'is'), undefined, [oAccess, nAccess]), f.createToken(ts.SyntaxKind.QuestionToken), f.createNumericLiteral(0), f.createToken(ts.SyntaxKind.ColonToken), createMaskLiteral(f, bit))));
1124
- }
1125
- let dirtyBody = comparisons[0];
1126
- for (let i = 1; i < comparisons.length; i++) {
1127
- dirtyBody = f.createBinaryExpression(dirtyBody, ts.SyntaxKind.BarToken, comparisons[i]);
1128
- }
1129
- // Fallback: if no tracked bit fired but the state reference changed, some
1130
- // untracked field must have changed — return FULL_MASK so bindings whose
1131
- // accessors came from external modules (spread parts) still fire.
1132
- // tracked || (Object.is(o, n) ? 0 : FULL_MASK)
1133
- const fallback = f.createParenthesizedExpression(f.createConditionalExpression(f.createCallExpression(f.createPropertyAccessExpression(f.createIdentifier('Object'), 'is'), undefined, [f.createIdentifier('o'), f.createIdentifier('n')]), f.createToken(ts.SyntaxKind.QuestionToken), f.createNumericLiteral(0), f.createToken(ts.SyntaxKind.ColonToken), createMaskLiteral(f, -1)));
1134
- dirtyBody = f.createBinaryExpression(f.createParenthesizedExpression(dirtyBody), ts.SyntaxKind.BarBarToken, fallback);
1135
- const dirtyFn = f.createArrowFunction(undefined, undefined, [
1136
- f.createParameterDeclaration(undefined, undefined, 'o'),
1137
- f.createParameterDeclaration(undefined, undefined, 'n'),
1138
- ], undefined, f.createToken(ts.SyntaxKind.EqualsGreaterThanToken), dirtyBody);
1139
- const dirtyProp = f.createPropertyAssignment('__dirty', dirtyFn);
1140
1114
  // __maskLegend: maps each top-level state field to the bit(s) that fire when
1141
1115
  // it changes. Lets introspection tools decode runtime dirty masks to field names.
1142
1116
  const legendProps = [];
@@ -1149,8 +1123,7 @@ function tryInjectDirty(node, fieldBits, f, fieldBitsHi = new Map()) {
1149
1123
  const legendProp = f.createPropertyAssignment('__maskLegend', f.createObjectLiteralExpression(legendProps, false));
1150
1124
  // Structural mask — used by both __update and __handlers
1151
1125
  const structuralMask = computeStructuralMask(configArg, fieldBits);
1152
- const phase2Mask = computePhase2Mask(configArg, fieldBits);
1153
- const updateBody = buildUpdateBody(f, structuralMask, phase2Mask);
1126
+ const updateBody = buildUpdateBody(f, structuralMask);
1154
1127
  // `dHi` is the high-word dirty mask, appended as the trailing
1155
1128
  // positional arg so stale 5-param compiled bundles continue to gate
1156
1129
  // correctly: the runtime calls `__update(s, d, b, bl, p, dHi)`,
@@ -1170,21 +1143,14 @@ function tryInjectDirty(node, fieldBits, f, fieldBitsHi = new Map()) {
1170
1143
  // Analyzes the update() switch/case and generates direct handlers
1171
1144
  // that bypass the generic Phase 1/2 pipeline for single-message updates.
1172
1145
  const handlersProp = tryBuildHandlers(configArg, topLevelBits, topLevelBitsHi, structuralMask, f);
1173
- // Both `__update` and `__handlers` carry two-word gates now —
1174
- // `__update`'s Phase 1 block loop uses `(mask & d) | (maskHi & dHi)`
1175
- // with `dHi` as the trailing parameter (defaults to 0 for backward
1176
- // compat with old 5-arg call sites), and `__handlers` passes
1177
- // `caseDirtyHi` to `_handleMsg` which gates blocks against both
1178
- // words. Safe to emit for any prefix count.
1179
- // `__dirty` emission was removed in 2026-05: `__prefixes` is strictly
1180
- // more precise (per-prefix rather than per-top-level-field), supports
1181
- // 62 paths via two-word masks, and the runtime throws if it sees a
1182
- // hand-authored `__dirty`. `legendProp` (`__maskLegend`) is still
1183
- // emitted for the agent layer's introspection — it surfaces the
1184
- // top-level-field-to-bit mapping for `whyDidUpdate` / dispatch
1185
- // tracing without depending on `__dirty` at runtime.
1186
- void dirtyFn;
1187
- void dirtyProp;
1146
+ // Both `__update` and `__handlers` carry two-word gates: `__update`'s
1147
+ // Phase 1 block loop uses `(mask & d) | (maskHi & dHi)`, and
1148
+ // `__handlers` passes `caseDirtyHi` to `_handleMsg` which gates blocks
1149
+ // against both words. `dHi` defaults to 0 so any stale 5-arg call site
1150
+ // still works. `__dirty` is no longer emitted — `__prefixes` (below)
1151
+ // is strictly more precise, and the runtime throws on hand-authored
1152
+ // `__dirty`. `__maskLegend` survives because the agent layer uses it
1153
+ // to decode runtime dirty masks back to top-level field names.
1188
1154
  const extraProps = [legendProp, updateProp];
1189
1155
  if (handlersProp)
1190
1156
  extraProps.push(handlersProp);
@@ -2099,17 +2065,6 @@ function computeStructuralMask(configArg, fieldBits) {
2099
2065
  walk(viewProp.initializer);
2100
2066
  return foundStructural ? mask || 0xffffffff | 0 : 0;
2101
2067
  }
2102
- /**
2103
- * Compute the OR of all component-level binding masks from text() calls
2104
- * and element bindings in the view. Returns 0 if no component-level bindings.
2105
- */
2106
- function computePhase2Mask(_configArg, _fieldBits) {
2107
- // For now, return FULL_MASK — a future pass can analyze all binding sites
2108
- // in the view to compute the precise aggregate. The key optimization is
2109
- // already in Phase 1 gating: when structuralMask doesn't intersect dirty,
2110
- // the entire reconciliation is skipped.
2111
- return 0xffffffff | 0;
2112
- }
2113
2068
  /**
2114
2069
  * Build the __update function body:
2115
2070
  * {
@@ -2142,7 +2097,7 @@ function computePhase2Mask(_configArg, _fieldBits) {
2142
2097
  * }
2143
2098
  * }
2144
2099
  */
2145
- function buildUpdateBody(f, structuralMask, _phase2Mask) {
2100
+ function buildUpdateBody(f, structuralMask) {
2146
2101
  const stmts = [];
2147
2102
  // Phase 1: structural block reconciliation, gated by aggregate mask
2148
2103
  if (structuralMask !== 0) {