sinwan-compiler 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.
- package/dist/{chunk-x75bhdr1.js → chunk-ba0546ea.js} +56 -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
|
@@ -23,6 +23,25 @@ var COMPONENT_FACTORY_MODULES = {
|
|
|
23
23
|
sinwan: new Set(["cc"]),
|
|
24
24
|
"sinwan/component": new Set(["cc"])
|
|
25
25
|
};
|
|
26
|
+
var BUILTIN_REACTIVE_PROPS = new Map([
|
|
27
|
+
["For", { reactiveProps: new Set(["each"]) }],
|
|
28
|
+
["Show", { reactiveProps: new Set(["when"]) }],
|
|
29
|
+
["Switch", { reactiveProps: new Set(["when"]) }],
|
|
30
|
+
["Match", { reactiveProps: new Set(["when"]) }],
|
|
31
|
+
["Index", { reactiveProps: new Set(["each"]) }],
|
|
32
|
+
["Key", { reactiveProps: new Set(["when"]) }],
|
|
33
|
+
["Dynamic", { reactiveProps: new Set(["component"]) }],
|
|
34
|
+
["Visible", { reactiveProps: new Set(["when", "style"]) }],
|
|
35
|
+
["Portal", { reactiveProps: new Set(["mount"]) }],
|
|
36
|
+
["Virtual", { reactiveProps: new Set(["each"]) }],
|
|
37
|
+
["Activity", { reactiveProps: new Set(["mode"]) }]
|
|
38
|
+
]);
|
|
39
|
+
function isBuiltinReactiveProp(componentName, attrName) {
|
|
40
|
+
const entry = BUILTIN_REACTIVE_PROPS.get(componentName);
|
|
41
|
+
if (!entry)
|
|
42
|
+
return false;
|
|
43
|
+
return entry.reactiveProps.has(attrName);
|
|
44
|
+
}
|
|
26
45
|
function trackReactiveImports(ast) {
|
|
27
46
|
const names = {
|
|
28
47
|
createMutable: new Set,
|
|
@@ -370,23 +389,31 @@ function containsReactiveRead(expr, scope) {
|
|
|
370
389
|
visit(expr);
|
|
371
390
|
return found;
|
|
372
391
|
}
|
|
373
|
-
function
|
|
392
|
+
function getComponentExpressionInfo(exprPath) {
|
|
374
393
|
const parent = exprPath.parentPath;
|
|
375
|
-
if (!parent)
|
|
376
|
-
return false;
|
|
394
|
+
if (!parent) {
|
|
395
|
+
return { isComponent: false, componentName: null, attributeName: null };
|
|
396
|
+
}
|
|
377
397
|
let elementPath = null;
|
|
398
|
+
let attributeName = null;
|
|
378
399
|
if (parent.isJSXAttribute && parent.isJSXAttribute()) {
|
|
400
|
+
const attrName = parent.node.name;
|
|
401
|
+
if (t.isJSXIdentifier(attrName)) {
|
|
402
|
+
attributeName = attrName.name;
|
|
403
|
+
}
|
|
379
404
|
const openingElementPath = parent.parentPath;
|
|
380
405
|
elementPath = openingElementPath?.parentPath;
|
|
381
406
|
} else if (parent.isJSXElement && parent.isJSXElement()) {
|
|
382
407
|
elementPath = parent;
|
|
383
408
|
}
|
|
384
409
|
if (!elementPath || !elementPath.isJSXElement || !elementPath.isJSXElement()) {
|
|
385
|
-
return false;
|
|
410
|
+
return { isComponent: false, componentName: null, attributeName: null };
|
|
386
411
|
}
|
|
387
412
|
const name = elementPath.node.openingElement.name;
|
|
388
413
|
let firstChar = null;
|
|
414
|
+
let componentName = null;
|
|
389
415
|
if (t.isJSXIdentifier(name)) {
|
|
416
|
+
componentName = name.name;
|
|
390
417
|
firstChar = name.name?.[0] ?? null;
|
|
391
418
|
} else if (t.isJSXMemberExpression(name)) {
|
|
392
419
|
let current = name;
|
|
@@ -394,12 +421,29 @@ function isComponentExpression(exprPath) {
|
|
|
394
421
|
current = current.object;
|
|
395
422
|
}
|
|
396
423
|
if (t.isJSXIdentifier(current)) {
|
|
424
|
+
componentName = current.name;
|
|
397
425
|
firstChar = current.name?.[0] ?? null;
|
|
398
426
|
}
|
|
399
427
|
}
|
|
400
|
-
if (!firstChar)
|
|
428
|
+
if (!firstChar || firstChar !== firstChar.toUpperCase() || !/[A-Z]/.test(firstChar)) {
|
|
429
|
+
return { isComponent: false, componentName: null, attributeName: null };
|
|
430
|
+
}
|
|
431
|
+
return { isComponent: true, componentName, attributeName };
|
|
432
|
+
}
|
|
433
|
+
function isReactiveComponentProp(info, componentNames, reactiveProps) {
|
|
434
|
+
if (!info.isComponent || !info.componentName || !info.attributeName) {
|
|
401
435
|
return false;
|
|
402
|
-
|
|
436
|
+
}
|
|
437
|
+
if (isBuiltinReactiveProp(info.componentName, info.attributeName)) {
|
|
438
|
+
return true;
|
|
439
|
+
}
|
|
440
|
+
const componentFn = componentNames.get(info.componentName);
|
|
441
|
+
if (!componentFn)
|
|
442
|
+
return false;
|
|
443
|
+
const props = reactiveProps.get(componentFn);
|
|
444
|
+
if (!props)
|
|
445
|
+
return false;
|
|
446
|
+
return props.has(info.attributeName);
|
|
403
447
|
}
|
|
404
448
|
function shouldWrap(expr, scope) {
|
|
405
449
|
if (t.isArrowFunctionExpression(expr) || t.isFunctionExpression(expr))
|
|
@@ -720,8 +764,12 @@ function wrapReactiveExpressions(ast, options = {}) {
|
|
|
720
764
|
path2.traverse({
|
|
721
765
|
JSXExpressionContainer(exprPath) {
|
|
722
766
|
const expr = exprPath.node.expression;
|
|
723
|
-
|
|
724
|
-
|
|
767
|
+
const compInfo = getComponentExpressionInfo(exprPath);
|
|
768
|
+
if (compInfo.isComponent) {
|
|
769
|
+
if (!isReactiveComponentProp(compInfo, componentNames, reactiveProps)) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
725
773
|
if (shouldWrap(expr, scope)) {
|
|
726
774
|
exprPath.replaceWith(t.jsxExpressionContainer(createBindingDescriptor(expr, exprPath, options)));
|
|
727
775
|
}
|
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.
|
|
3
|
+
"version": "0.2.0",
|
|
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",
|