@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 +13 -3
- package/lib/codegen.js +8 -3
- package/lib/compiler.js +1 -1
- package/lib/reactive-runtime.js +5 -8
- package/package.json +1 -1
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
|
-
|
|
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.
|
|
533
|
-
|
|
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
package/lib/reactive-runtime.js
CHANGED
|
@@ -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
|
|
84
|
+
const pending = [...__pendingEffects];
|
|
85
|
+
__pendingEffects.clear();
|
|
89
86
|
for (const f of pending) f();
|
|
90
87
|
}
|
|
91
88
|
}
|
package/package.json
CHANGED