sinwan-compiler 0.1.0 → 0.2.1
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/dist/{chunk-x75bhdr1.js → chunk-tvnem5mj.js} +57 -8
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/reactive-wrap.d.ts +5 -0
- package/package.json +6 -2
|
@@ -17,12 +17,32 @@ var traverse = typeof _traverse === "function" ? _traverse : _traverse.default ?
|
|
|
17
17
|
var REACTIVE_SOURCE_MODULES = {
|
|
18
18
|
"sinwan/store": new Set(["createMutable", "createStore"]),
|
|
19
19
|
"sinwan/reactivity": new Set(["signal", "computed"]),
|
|
20
|
+
"sinwan/react": new Set(["useState"]),
|
|
20
21
|
"sinwan/react-client": new Set(["useState"])
|
|
21
22
|
};
|
|
22
23
|
var COMPONENT_FACTORY_MODULES = {
|
|
23
24
|
sinwan: new Set(["cc"]),
|
|
24
25
|
"sinwan/component": new Set(["cc"])
|
|
25
26
|
};
|
|
27
|
+
var BUILTIN_REACTIVE_PROPS = new Map([
|
|
28
|
+
["For", { reactiveProps: new Set(["each"]) }],
|
|
29
|
+
["Show", { reactiveProps: new Set(["when"]) }],
|
|
30
|
+
["Switch", { reactiveProps: new Set(["when"]) }],
|
|
31
|
+
["Match", { reactiveProps: new Set(["when"]) }],
|
|
32
|
+
["Index", { reactiveProps: new Set(["each"]) }],
|
|
33
|
+
["Key", { reactiveProps: new Set(["when"]) }],
|
|
34
|
+
["Dynamic", { reactiveProps: new Set(["component"]) }],
|
|
35
|
+
["Visible", { reactiveProps: new Set(["when", "style"]) }],
|
|
36
|
+
["Portal", { reactiveProps: new Set(["mount"]) }],
|
|
37
|
+
["Virtual", { reactiveProps: new Set(["each"]) }],
|
|
38
|
+
["Activity", { reactiveProps: new Set(["mode"]) }]
|
|
39
|
+
]);
|
|
40
|
+
function isBuiltinReactiveProp(componentName, attrName) {
|
|
41
|
+
const entry = BUILTIN_REACTIVE_PROPS.get(componentName);
|
|
42
|
+
if (!entry)
|
|
43
|
+
return false;
|
|
44
|
+
return entry.reactiveProps.has(attrName);
|
|
45
|
+
}
|
|
26
46
|
function trackReactiveImports(ast) {
|
|
27
47
|
const names = {
|
|
28
48
|
createMutable: new Set,
|
|
@@ -370,23 +390,31 @@ function containsReactiveRead(expr, scope) {
|
|
|
370
390
|
visit(expr);
|
|
371
391
|
return found;
|
|
372
392
|
}
|
|
373
|
-
function
|
|
393
|
+
function getComponentExpressionInfo(exprPath) {
|
|
374
394
|
const parent = exprPath.parentPath;
|
|
375
|
-
if (!parent)
|
|
376
|
-
return false;
|
|
395
|
+
if (!parent) {
|
|
396
|
+
return { isComponent: false, componentName: null, attributeName: null };
|
|
397
|
+
}
|
|
377
398
|
let elementPath = null;
|
|
399
|
+
let attributeName = null;
|
|
378
400
|
if (parent.isJSXAttribute && parent.isJSXAttribute()) {
|
|
401
|
+
const attrName = parent.node.name;
|
|
402
|
+
if (t.isJSXIdentifier(attrName)) {
|
|
403
|
+
attributeName = attrName.name;
|
|
404
|
+
}
|
|
379
405
|
const openingElementPath = parent.parentPath;
|
|
380
406
|
elementPath = openingElementPath?.parentPath;
|
|
381
407
|
} else if (parent.isJSXElement && parent.isJSXElement()) {
|
|
382
408
|
elementPath = parent;
|
|
383
409
|
}
|
|
384
410
|
if (!elementPath || !elementPath.isJSXElement || !elementPath.isJSXElement()) {
|
|
385
|
-
return false;
|
|
411
|
+
return { isComponent: false, componentName: null, attributeName: null };
|
|
386
412
|
}
|
|
387
413
|
const name = elementPath.node.openingElement.name;
|
|
388
414
|
let firstChar = null;
|
|
415
|
+
let componentName = null;
|
|
389
416
|
if (t.isJSXIdentifier(name)) {
|
|
417
|
+
componentName = name.name;
|
|
390
418
|
firstChar = name.name?.[0] ?? null;
|
|
391
419
|
} else if (t.isJSXMemberExpression(name)) {
|
|
392
420
|
let current = name;
|
|
@@ -394,12 +422,29 @@ function isComponentExpression(exprPath) {
|
|
|
394
422
|
current = current.object;
|
|
395
423
|
}
|
|
396
424
|
if (t.isJSXIdentifier(current)) {
|
|
425
|
+
componentName = current.name;
|
|
397
426
|
firstChar = current.name?.[0] ?? null;
|
|
398
427
|
}
|
|
399
428
|
}
|
|
400
|
-
if (!firstChar)
|
|
429
|
+
if (!firstChar || firstChar !== firstChar.toUpperCase() || !/[A-Z]/.test(firstChar)) {
|
|
430
|
+
return { isComponent: false, componentName: null, attributeName: null };
|
|
431
|
+
}
|
|
432
|
+
return { isComponent: true, componentName, attributeName };
|
|
433
|
+
}
|
|
434
|
+
function isReactiveComponentProp(info, componentNames, reactiveProps) {
|
|
435
|
+
if (!info.isComponent || !info.componentName || !info.attributeName) {
|
|
401
436
|
return false;
|
|
402
|
-
|
|
437
|
+
}
|
|
438
|
+
if (isBuiltinReactiveProp(info.componentName, info.attributeName)) {
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
const componentFn = componentNames.get(info.componentName);
|
|
442
|
+
if (!componentFn)
|
|
443
|
+
return false;
|
|
444
|
+
const props = reactiveProps.get(componentFn);
|
|
445
|
+
if (!props)
|
|
446
|
+
return false;
|
|
447
|
+
return props.has(info.attributeName);
|
|
403
448
|
}
|
|
404
449
|
function shouldWrap(expr, scope) {
|
|
405
450
|
if (t.isArrowFunctionExpression(expr) || t.isFunctionExpression(expr))
|
|
@@ -720,8 +765,12 @@ function wrapReactiveExpressions(ast, options = {}) {
|
|
|
720
765
|
path2.traverse({
|
|
721
766
|
JSXExpressionContainer(exprPath) {
|
|
722
767
|
const expr = exprPath.node.expression;
|
|
723
|
-
|
|
724
|
-
|
|
768
|
+
const compInfo = getComponentExpressionInfo(exprPath);
|
|
769
|
+
if (compInfo.isComponent) {
|
|
770
|
+
if (!isReactiveComponentProp(compInfo, componentNames, reactiveProps)) {
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
725
774
|
if (shouldWrap(expr, scope)) {
|
|
726
775
|
exprPath.replaceWith(t.jsxExpressionContainer(createBindingDescriptor(expr, exprPath, options)));
|
|
727
776
|
}
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
export { transformJSX, type TransformOptions } from "./transform";
|
|
8
8
|
export { analyze, analyzeProject, analyzeModule, loadMetadata, AnalyzerCache, type AnalyzeOptions, type ModuleAnalysis, type ProjectAnalysis, type ImportedCallSite, type ImportInfo, type WorkspacesConfig, } from "./analyze";
|
|
9
9
|
export { runAnalyzeCli } from "./cli";
|
|
10
|
-
export { wrapReactiveExpressions, trackReactiveImports, collectComponentFunctions, computeLocalScopes, collectComponentCallGraph, propagateReactiveProps, buildFullScope, containsReactiveValue, getAllPropNames, isReactiveValue, type ReactiveScope, type Binding, type CallSite, type ImportNames, } from "./reactive-wrap";
|
|
10
|
+
export { wrapReactiveExpressions, trackReactiveImports, collectComponentFunctions, computeLocalScopes, collectComponentCallGraph, propagateReactiveProps, buildFullScope, containsReactiveValue, getAllPropNames, isReactiveValue, type ReactiveScope, type Binding, type CallSite, type ImportNames, type ComponentExpressionInfo, } from "./reactive-wrap";
|
package/dist/index.js
CHANGED
package/dist/reactive-wrap.d.ts
CHANGED
|
@@ -49,6 +49,11 @@ export interface ReactiveScope {
|
|
|
49
49
|
export declare function getAllPropNames(params: t.Node | undefined): Set<string>;
|
|
50
50
|
export declare function isReactiveValue(node: t.Identifier | t.MemberExpression, scope: ReactiveScope): boolean;
|
|
51
51
|
export declare function containsReactiveValue(expr: t.Expression, scope: ReactiveScope): boolean;
|
|
52
|
+
export interface ComponentExpressionInfo {
|
|
53
|
+
isComponent: boolean;
|
|
54
|
+
componentName: string | null;
|
|
55
|
+
attributeName: string | null;
|
|
56
|
+
}
|
|
52
57
|
export declare function collectComponentFunctions(ast: t.Node, ccNames: Set<string>): {
|
|
53
58
|
functions: Set<t.Function>;
|
|
54
59
|
names: Map<string, t.Function>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sinwan-compiler",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Shared compiler core for Sinwan plugins",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,7 +30,11 @@
|
|
|
30
30
|
"sinwan": "./dist/cli.js"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
|
-
"
|
|
33
|
+
"test": "bun test",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"build": "bun run build.ts",
|
|
36
|
+
"clean": "rm -rf dist",
|
|
37
|
+
"prepublishOnly": "bun run clean && bun run typecheck && bun run test && bun run build"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
36
40
|
"@types/babel__generator": "^7.27.0",
|