@sprlab/wccompiler 0.4.3 → 0.5.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.
package/bin/wcc.js CHANGED
@@ -15,16 +15,28 @@ async function build(config, cwd) {
15
15
 
16
16
  if (!existsSync(outputDir)) mkdirSync(outputDir, { recursive: true });
17
17
 
18
+ // Generate shared reactive runtime
19
+ const __filename = fileURLToPath(import.meta.url);
20
+ const __dirname = dirname(__filename);
21
+ const { reactiveRuntime } = await import('../lib/reactive-runtime.js');
22
+ const signalsContent = reactiveRuntime.trim().replace(/^/gm, '') + '\nexport { __signal, __computed, __effect, __batch };\n';
23
+ const signalsDest = join(outputDir, '__wcc-signals.js');
24
+ writeFileSync(signalsDest, signalsContent);
25
+
18
26
  // Discover source files
19
27
  const files = discoverFiles(inputDir);
20
28
  let errors = 0;
21
29
 
22
30
  for (const file of files) {
23
31
  try {
24
- const output = await compile(file);
32
+ // Calculate relative path from component output to __wcc-signals.js
25
33
  const relPath = relative(inputDir, file);
26
34
  const outPath = resolve(outputDir, relPath.replace(/\.wcc$/, '.js'));
27
35
  const outDir = dirname(outPath);
36
+ const runtimeRelPath = relative(outDir, signalsDest).replace(/\\/g, '/');
37
+ const runtimeImportPath = runtimeRelPath.startsWith('.') ? runtimeRelPath : './' + runtimeRelPath;
38
+
39
+ const output = await compile(file, { runtimeImportPath });
28
40
  if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
29
41
  writeFileSync(outPath, output);
30
42
  } catch (err) {
@@ -34,8 +46,6 @@ async function build(config, cwd) {
34
46
  }
35
47
 
36
48
  // Copy wcc-runtime.js to output directory
37
- const __filename = fileURLToPath(import.meta.url);
38
- const __dirname = dirname(__filename);
39
49
  const runtimeSrc = resolve(__dirname, '../lib/wcc-runtime.js');
40
50
  const runtimeDest = join(outputDir, 'wcc-runtime.js');
41
51
  copyFileSync(runtimeSrc, runtimeDest);
package/lib/codegen.js CHANGED
@@ -485,9 +485,10 @@ function generateItemSetup(lines, forBlock, itemVar, indexVar, propNames, signal
485
485
  * Generate a fully self-contained JS component from a ParseResult.
486
486
  *
487
487
  * @param {ParseResult} parseResult — Complete IR with bindings/events
488
+ * @param {{ runtimeImportPath?: string }} [options] — Optional generation options
488
489
  * @returns {string} JavaScript source code
489
490
  */
490
- export function generateComponent(parseResult) {
491
+ export function generateComponent(parseResult, options = {}) {
491
492
  const {
492
493
  tagName,
493
494
  className,
@@ -529,8 +530,12 @@ export function generateComponent(parseResult) {
529
530
 
530
531
  const lines = [];
531
532
 
532
- // ── 1. Inline reactive runtime ──
533
- lines.push(reactiveRuntime.trim());
533
+ // ── 1. Reactive runtime (shared import or inline) ──
534
+ if (options.runtimeImportPath) {
535
+ lines.push(`import { __signal, __computed, __effect, __batch } from '${options.runtimeImportPath}';`);
536
+ } else {
537
+ lines.push(reactiveRuntime.trim());
538
+ }
534
539
  lines.push('');
535
540
 
536
541
  // ── 1b. Child component imports ──
package/lib/compiler.js CHANGED
@@ -323,7 +323,7 @@ async function compileSFC(filePath, config) {
323
323
  parseResult.processedTemplate = rootEl.innerHTML;
324
324
 
325
325
  // 20. Generate component
326
- return generateComponent(parseResult);
326
+ return generateComponent(parseResult, config);
327
327
  }
328
328
 
329
329
  /**
@@ -16,7 +16,7 @@
16
16
  export const reactiveRuntime = `
17
17
  let __currentEffect = null;
18
18
  let __batchDepth = 0;
19
- const __pendingEffects = [];
19
+ const __pendingEffects = new Set();
20
20
 
21
21
  function __signal(initial) {
22
22
  let _value = initial;
@@ -30,9 +30,7 @@ function __signal(initial) {
30
30
  _value = args[0];
31
31
  if (old !== _value) {
32
32
  if (__batchDepth > 0) {
33
- for (const fn of _subs) {
34
- if (!__pendingEffects.includes(fn)) __pendingEffects.push(fn);
35
- }
33
+ for (const fn of _subs) __pendingEffects.add(fn);
36
34
  } else {
37
35
  for (const fn of [..._subs]) fn();
38
36
  }
@@ -46,9 +44,7 @@ function __computed(fn) {
46
44
  const recompute = () => {
47
45
  _dirty = true;
48
46
  if (__batchDepth > 0) {
49
- for (const fn of _subs) {
50
- if (!__pendingEffects.includes(fn)) __pendingEffects.push(fn);
51
- }
47
+ for (const fn of _subs) __pendingEffects.add(fn);
52
48
  } else {
53
49
  for (const fn of [..._subs]) fn();
54
50
  }
@@ -85,7 +81,8 @@ function __batch(fn) {
85
81
  } finally {
86
82
  __batchDepth--;
87
83
  if (__batchDepth === 0) {
88
- const pending = __pendingEffects.splice(0);
84
+ const pending = [...__pendingEffects];
85
+ __pendingEffects.clear();
89
86
  for (const f of pending) f();
90
87
  }
91
88
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprlab/wccompiler",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
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
  "bin": {