@sprlab/wccompiler 0.11.2 → 0.11.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 CHANGED
@@ -864,6 +864,7 @@ export function generateComponent(parseResult, options = {}) {
864
864
  forBlocks = [],
865
865
  onMountHooks = [],
866
866
  onDestroyHooks = [],
867
+ onAdoptHooks = [],
867
868
  modelBindings = [],
868
869
  modelPropBindings = [],
869
870
  attrBindings = [],
@@ -1698,6 +1699,31 @@ export function generateComponent(parseResult, options = {}) {
1698
1699
  lines.push(' }');
1699
1700
  lines.push('');
1700
1701
 
1702
+ // adoptedCallback (if onAdopt hooks exist)
1703
+ if (onAdoptHooks.length > 0) {
1704
+ lines.push(' adoptedCallback() {');
1705
+ for (const hook of onAdoptHooks) {
1706
+ const body = transformMethodBody(hook.body, signalNames, computedNames, propsObjectName, propNames, emitsObjectName, refVarNames, constantNames, modelVarMap);
1707
+ if (hook.async) {
1708
+ lines.push(' ;(async () => {');
1709
+ const bodyLines = body.split('\n');
1710
+ for (const line of bodyLines) {
1711
+ lines.push(` ${line}`);
1712
+ }
1713
+ lines.push(' })();');
1714
+ } else {
1715
+ const bodyLines = body.split('\n');
1716
+ for (const line of bodyLines) {
1717
+ const trimmed = line.trimEnd();
1718
+ const needsSemi = trimmed && !trimmed.endsWith(';') && !trimmed.endsWith('{') && !trimmed.endsWith('}');
1719
+ lines.push(` ${trimmed}${needsSemi ? ';' : ''}`);
1720
+ }
1721
+ }
1722
+ }
1723
+ lines.push(' }');
1724
+ lines.push('');
1725
+ }
1726
+
1701
1727
  // attributeChangedCallback (if props or model props exist)
1702
1728
  if (propDefs.length > 0 || modelDefs.length > 0) {
1703
1729
  lines.push(' attributeChangedCallback(name, oldVal, newVal) {');
@@ -925,13 +925,15 @@ export function extractFunctions(source) {
925
925
  * Only extracts top-level calls (brace depth === 0 when the call is encountered).
926
926
  *
927
927
  * @param {string} script - The script content (after type stripping)
928
- * @returns {{ onMountHooks: LifecycleHook[], onDestroyHooks: LifecycleHook[] }}
928
+ * @returns {{ onMountHooks: LifecycleHook[], onDestroyHooks: LifecycleHook[], onAdoptHooks: LifecycleHook[] }}
929
929
  */
930
930
  export function extractLifecycleHooks(script) {
931
931
  /** @type {LifecycleHook[]} */
932
932
  const onMountHooks = [];
933
933
  /** @type {LifecycleHook[]} */
934
934
  const onDestroyHooks = [];
935
+ /** @type {LifecycleHook[]} */
936
+ const onAdoptHooks = [];
935
937
  const lines = script.split('\n');
936
938
  let i = 0;
937
939
 
@@ -939,8 +941,9 @@ export function extractLifecycleHooks(script) {
939
941
  const line = lines[i];
940
942
  const mountMatch = line.match(/\bonMount\s*\(\s*(?:async\s*)?\(\s*\)\s*=>\s*\{/);
941
943
  const destroyMatch = line.match(/\bonDestroy\s*\(\s*(?:async\s*)?\(\s*\)\s*=>\s*\{/);
944
+ const adoptMatch = line.match(/\bonAdopt\s*\(\s*(?:async\s*)?\(\s*\)\s*=>\s*\{/);
942
945
 
943
- if (mountMatch || destroyMatch) {
946
+ if (mountMatch || destroyMatch || adoptMatch) {
944
947
  // Detect if the callback is async
945
948
  const isAsync = /\basync\s*\(/.test(line);
946
949
 
@@ -998,14 +1001,16 @@ export function extractLifecycleHooks(script) {
998
1001
 
999
1002
  if (mountMatch) {
1000
1003
  onMountHooks.push({ body, async: isAsync });
1001
- } else {
1004
+ } else if (destroyMatch) {
1002
1005
  onDestroyHooks.push({ body, async: isAsync });
1006
+ } else {
1007
+ onAdoptHooks.push({ body, async: isAsync });
1003
1008
  }
1004
1009
  }
1005
1010
  i++;
1006
1011
  }
1007
1012
 
1008
- return { onMountHooks, onDestroyHooks };
1013
+ return { onMountHooks, onDestroyHooks, onAdoptHooks };
1009
1014
  }
1010
1015
 
1011
1016
  // ── Ref extraction ───────────────────────────────────────────────────
package/lib/parser.js CHANGED
@@ -153,12 +153,12 @@ export async function parse(filePath) {
153
153
  }
154
154
 
155
155
  // 8. Extract lifecycle hooks (before other extractions to avoid misidentification)
156
- const { onMountHooks, onDestroyHooks } = extractLifecycleHooks(source);
156
+ const { onMountHooks, onDestroyHooks, onAdoptHooks } = extractLifecycleHooks(source);
157
157
 
158
158
  // 8b. Strip lifecycle hook blocks from source to prevent signal/computed/effect/function
159
159
  // extractors from misidentifying code inside hook bodies
160
160
  let sourceForExtraction = source;
161
- const hookLinePattern = /\bonMount\s*\(|\bonDestroy\s*\(|\bwatch\s*\(/;
161
+ const hookLinePattern = /\bonMount\s*\(|\bonDestroy\s*\(|\bonAdopt\s*\(|\bwatch\s*\(/;
162
162
  const sourceLines = sourceForExtraction.split('\n');
163
163
  const filteredLines = [];
164
164
  let skipDepth = 0;
@@ -263,6 +263,7 @@ export async function parse(filePath) {
263
263
  processedTemplate: null,
264
264
  onMountHooks,
265
265
  onDestroyHooks,
266
+ onAdoptHooks,
266
267
  refs,
267
268
  };
268
269
  }
@@ -251,7 +251,7 @@ export function walkTree(rootEl, signalNames, computedNames, propNames = new Set
251
251
  prop = 'value'; event = 'input';
252
252
  }
253
253
 
254
- const varName = `__model_${signalName}`;
254
+ const varName = `__model_${signalName}_${modelIdx}`;
255
255
  modelIdx++;
256
256
  modelBindings.push({ varName, signal: signalName, prop, event, coerce, radioValue, path: [...pathParts] });
257
257
  el.removeAttribute('model');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprlab/wccompiler",
3
- "version": "0.11.2",
3
+ "version": "0.11.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": {
package/types/wcc.d.ts CHANGED
@@ -23,5 +23,6 @@ declare module 'wcc' {
23
23
 
24
24
  export function onMount(fn: () => void | Promise<void>): void;
25
25
  export function onDestroy(fn: () => void | Promise<void>): void;
26
+ export function onAdopt(fn: () => void | Promise<void>): void;
26
27
  export function defineExpose(bindings: Record<string, any>): void;
27
28
  }