@vitarx/plugin-vite 0.0.1-alpha.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.
Files changed (42) hide show
  1. package/LICENSE +27 -0
  2. package/README.md +298 -0
  3. package/dist/components.js +1 -0
  4. package/dist/constants/index.js +59 -0
  5. package/dist/context.js +78 -0
  6. package/dist/error.js +156 -0
  7. package/dist/hmr-client/index.js +143 -0
  8. package/dist/hmr-client/update.js +53 -0
  9. package/dist/hmr-client/utils.js +125 -0
  10. package/dist/index.js +65 -0
  11. package/dist/passes/components/ifBlock.js +42 -0
  12. package/dist/passes/components/index.js +24 -0
  13. package/dist/passes/components/switch.js +102 -0
  14. package/dist/passes/directives/index.js +6 -0
  15. package/dist/passes/directives/processDirectives.js +46 -0
  16. package/dist/passes/directives/vIf.js +64 -0
  17. package/dist/passes/hmr/index.js +5 -0
  18. package/dist/passes/hmr/inject.js +189 -0
  19. package/dist/passes/imports/collectImports.js +56 -0
  20. package/dist/passes/imports/collectRefVariables.js +95 -0
  21. package/dist/passes/imports/index.js +7 -0
  22. package/dist/passes/imports/injectImports.js +96 -0
  23. package/dist/passes/index.js +16 -0
  24. package/dist/passes/jsx/index.js +7 -0
  25. package/dist/passes/jsx/processChildren.js +114 -0
  26. package/dist/passes/jsx/processJSXElement.js +173 -0
  27. package/dist/passes/jsx/processJSXFragment.js +37 -0
  28. package/dist/passes/props/attribute.js +165 -0
  29. package/dist/passes/props/index.js +94 -0
  30. package/dist/passes/props/types.js +1 -0
  31. package/dist/passes/props/vmodel.js +115 -0
  32. package/dist/transform.js +144 -0
  33. package/dist/utils/ast-builders.js +142 -0
  34. package/dist/utils/ast-guards.js +16 -0
  35. package/dist/utils/branch-factory.js +107 -0
  36. package/dist/utils/component-collect.js +233 -0
  37. package/dist/utils/generate.js +11 -0
  38. package/dist/utils/index.js +16 -0
  39. package/dist/utils/jsx-helpers.js +168 -0
  40. package/dist/utils/pattern-helpers.js +47 -0
  41. package/dist/utils/vif-helpers.js +127 -0
  42. package/package.json +63 -0
@@ -0,0 +1,189 @@
1
+ /**
2
+ * HMR 代码注入模块
3
+ * 在 HMR 模式下为组件函数注入热更新支持代码
4
+ * @module passes/hmr
5
+ */
6
+ import * as t from '@babel/types';
7
+ import { HMR } from '../../constants/index.js';
8
+ import { collectPatternBindings } from '../../utils/index.js';
9
+ /** getComponentView 的内部别名,避免与用户代码冲突 */
10
+ const GET_COMPONENT_VIEW_ALIAS = '__$VITARX_GET_COMPONENT_VIEW$__';
11
+ /**
12
+ * 注入 HMR 客户端导入
13
+ * @param program - AST Program 节点
14
+ */
15
+ function injectHMRImport(program) {
16
+ const importDecl = t.importDeclaration([t.importDefaultSpecifier(t.identifier(HMR.manager))], t.stringLiteral('@vitarx/vite-plugin/hmr-client'));
17
+ program.body.unshift(importDecl);
18
+ }
19
+ /**
20
+ * 注入 getComponentView 导入
21
+ * 使用唯一的别名避免与用户代码冲突
22
+ * @param program - AST Program 节点
23
+ */
24
+ function injectGetComponentViewImport(program) {
25
+ // 创建独立的 import 语句,使用不会冲突的别名
26
+ const importDecl = t.importDeclaration([t.importSpecifier(t.identifier(GET_COMPONENT_VIEW_ALIAS), t.identifier('getComponentView'))], t.stringLiteral('vitarx'));
27
+ program.body.unshift(importDecl);
28
+ }
29
+ /**
30
+ * 创建组件函数体内的 HMR 注册代码
31
+ * @param variableNames - 需要追踪的变量名列表
32
+ * @returns HMR 注册语句数组
33
+ */
34
+ function createHMRRegistrationStatements(variableNames) {
35
+ const statements = [];
36
+ // 声明并获取当前视图实例
37
+ statements.push(t.variableDeclaration('const', [
38
+ t.variableDeclarator(t.identifier(HMR.view), t.callExpression(t.identifier(GET_COMPONENT_VIEW_ALIAS), []))
39
+ ]));
40
+ // 注册到 HMR 管理器
41
+ statements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier(HMR.manager), t.identifier('instance')), t.identifier('register')), [t.identifier(HMR.view)])));
42
+ // 创建状态追踪对象
43
+ const stateProperties = variableNames.map(name => t.objectMethod('get', t.identifier(name), [], t.blockStatement([t.returnStatement(t.identifier(name))])));
44
+ // 异步设置状态
45
+ statements.push(t.expressionStatement(t.logicalExpression('&&', t.identifier(HMR.view), t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.identifier('Promise'), t.identifier('resolve')), []), t.identifier('then')), [
46
+ t.arrowFunctionExpression([], t.blockStatement([
47
+ t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(HMR.view), t.identifier(HMR.state)), t.objectExpression(stateProperties)))
48
+ ]))
49
+ ]))));
50
+ return statements;
51
+ }
52
+ /**
53
+ * 从函数体中收集局部变量名
54
+ * @param functionBody - 函数体语句块
55
+ * @returns 变量名数组
56
+ */
57
+ function collectLocalVariableNames(functionBody) {
58
+ const variableNames = new Set();
59
+ for (const stmt of functionBody.body) {
60
+ if (stmt.type === 'VariableDeclaration') {
61
+ for (const decl of stmt.declarations) {
62
+ if (decl.id.type !== 'VoidPattern') {
63
+ collectPatternBindings(decl.id, variableNames);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ return Array.from(variableNames);
69
+ }
70
+ /**
71
+ * 判断表达式是否为函数类型
72
+ * 包括:箭头函数、函数表达式、类表达式
73
+ */
74
+ function isFunctionExpression(expr) {
75
+ if (!expr)
76
+ return false;
77
+ return (expr.type === 'ArrowFunctionExpression' ||
78
+ expr.type === 'FunctionExpression' ||
79
+ expr.type === 'ClassExpression');
80
+ }
81
+ /**
82
+ * 创建状态恢复表达式
83
+ * 格式:__$VITARX_HMR$__.instance.memo(__$VITARX_HMR_VIEW_NODE$__, '变量名') ?? 原始初始值
84
+ */
85
+ function createMemoExpression(variableName, originalInit) {
86
+ return t.logicalExpression('??', t.callExpression(t.memberExpression(t.memberExpression(t.identifier(HMR.manager), t.identifier('instance')), t.identifier('memo')), [t.identifier(HMR.view), t.stringLiteral(variableName)]), originalInit);
87
+ }
88
+ /**
89
+ * 为单个变量声明注入状态恢复代码
90
+ * 仅处理标识符类型的变量声明,且初始值不是函数
91
+ */
92
+ function injectStatePreservationForDeclaration(decl) {
93
+ // 只处理标识符类型的变量声明
94
+ if (decl.id.type !== 'Identifier')
95
+ return;
96
+ // 没有初始值,不需要处理
97
+ if (!decl.init)
98
+ return;
99
+ // 初始值是函数,不需要状态恢复
100
+ if (isFunctionExpression(decl.init))
101
+ return;
102
+ // 注入状态恢复代码
103
+ decl.init = createMemoExpression(decl.id.name, decl.init);
104
+ }
105
+ /**
106
+ * 为函数体内的变量声明注入状态恢复代码
107
+ */
108
+ function injectStatePreservation(functionBody) {
109
+ for (const stmt of functionBody.body) {
110
+ if (stmt.type === 'VariableDeclaration') {
111
+ for (const decl of stmt.declarations) {
112
+ injectStatePreservationForDeclaration(decl);
113
+ }
114
+ }
115
+ }
116
+ }
117
+ /**
118
+ * 为组件函数注入 HMR 注册代码
119
+ * @param func - 函数声明/表达式/箭头函数
120
+ * @param variableNames - 需要追踪的变量名列表
121
+ */
122
+ function injectHMRIntoFunction(func, variableNames) {
123
+ // 处理箭头函数没有函数体的情况(表达式体)
124
+ if (func.type === 'ArrowFunctionExpression' && func.body.type !== 'BlockStatement') {
125
+ // 将表达式体转换为块语句
126
+ const returnStmt = t.returnStatement(func.body);
127
+ func.body = t.blockStatement([returnStmt]);
128
+ }
129
+ if (!func.body || func.body.type !== 'BlockStatement')
130
+ return;
131
+ // 注入状态恢复代码
132
+ injectStatePreservation(func.body);
133
+ // 注入 HMR 注册代码
134
+ const statements = createHMRRegistrationStatements(variableNames);
135
+ func.body.body.unshift(...statements);
136
+ }
137
+ /**
138
+ * 创建 bindId 语句
139
+ */
140
+ function createBindIdStatement(componentName, componentId) {
141
+ return t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier(HMR.manager), t.identifier('instance')), t.identifier('bindId')), [t.identifier(componentName), t.stringLiteral(componentId)]));
142
+ }
143
+ /**
144
+ * 创建 import.meta.hot.accept 语句
145
+ */
146
+ function createHotAcceptStatement() {
147
+ return t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.identifier('import'), t.identifier('meta')), t.identifier('hot')), t.identifier('accept')), [
148
+ t.arrowFunctionExpression([t.identifier('mod')], t.blockStatement([
149
+ t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier(HMR.manager), t.identifier('instance')), t.identifier('update')), [t.identifier('mod')]))
150
+ ]))
151
+ ]));
152
+ }
153
+ /**
154
+ * 生成组件唯一 ID(文件路径 + 组件名称)
155
+ */
156
+ function generateComponentId(filename, componentName) {
157
+ const combined = `${filename}:${componentName}`;
158
+ let hash = 0;
159
+ for (let i = 0; i < combined.length; i++) {
160
+ hash = ((hash << 5) - hash + combined.charCodeAt(i)) | 0;
161
+ }
162
+ return Math.abs(hash).toString(16);
163
+ }
164
+ /**
165
+ * 注入 HMR 支持
166
+ * 主入口函数,为所有组件注入完整的 HMR 支持
167
+ * @param program - AST Program 节点
168
+ * @param components - 组件信息列表
169
+ * @param filename - 文件名
170
+ */
171
+ export function injectHMRSupport(program, components, filename) {
172
+ if (components.length === 0)
173
+ return;
174
+ // 注入必要的导入
175
+ injectHMRImport(program);
176
+ injectGetComponentViewImport(program);
177
+ // 为每个组件函数注入 HMR 代码
178
+ for (const { node } of components) {
179
+ // 收集局部变量名(如果有函数体)
180
+ const variableNames = node.body?.type === 'BlockStatement' ? collectLocalVariableNames(node.body) : [];
181
+ injectHMRIntoFunction(node, variableNames);
182
+ }
183
+ // 为每个组件绑定 ID
184
+ for (const { name } of components) {
185
+ program.body.push(createBindIdStatement(name, generateComponentId(filename, name)));
186
+ }
187
+ // 注入 import.meta.hot.accept
188
+ program.body.push(createHotAcceptStatement());
189
+ }
@@ -0,0 +1,56 @@
1
+ import { VITARX_MODULE } from '../../constants/index.js';
2
+ import { collectPatternBindings } from '../../utils/index.js';
3
+ /**
4
+ * 收集现有导入信息
5
+ * @param program - AST Program 节点
6
+ * @returns 本地变量名集合和 vitarx 导入映射
7
+ */
8
+ export function collectExistingImports(program) {
9
+ const localNames = new Set();
10
+ const vitarxImports = new Map();
11
+ for (const node of program.body) {
12
+ if (node.type !== 'ImportDeclaration')
13
+ continue;
14
+ const source = node.source.value;
15
+ for (const specifier of node.specifiers) {
16
+ localNames.add(specifier.local.name);
17
+ if (source === VITARX_MODULE && specifier.type === 'ImportSpecifier') {
18
+ const importedName = specifier.imported.type === 'Identifier'
19
+ ? specifier.imported.name
20
+ : specifier.imported.value;
21
+ vitarxImports.set(importedName, specifier.local.name);
22
+ }
23
+ }
24
+ }
25
+ return { localNames, vitarxImports };
26
+ }
27
+ /**
28
+ * 收集本地变量绑定
29
+ * 包括导入绑定、变量声明、函数声明、类声明
30
+ * @param program - AST Program 节点
31
+ * @returns 本地变量名集合
32
+ */
33
+ export function collectLocalBindings(program) {
34
+ const bindings = new Set();
35
+ for (const node of program.body) {
36
+ if (node.type === 'ImportDeclaration') {
37
+ for (const specifier of node.specifiers) {
38
+ bindings.add(specifier.local.name);
39
+ }
40
+ }
41
+ if (node.type === 'VariableDeclaration') {
42
+ for (const decl of node.declarations) {
43
+ if (decl.id.type !== 'VoidPattern') {
44
+ collectPatternBindings(decl.id, bindings);
45
+ }
46
+ }
47
+ }
48
+ if (node.type === 'FunctionDeclaration' && node.id) {
49
+ bindings.add(node.id.name);
50
+ }
51
+ if (node.type === 'ClassDeclaration' && node.id) {
52
+ bindings.add(node.id.name);
53
+ }
54
+ }
55
+ return bindings;
56
+ }
@@ -0,0 +1,95 @@
1
+ import { REF_APIS, RESPONSIVE_MODULES } from '../../constants/index.js';
2
+ import { collectPatternBindings, collectObjectPatternBindings } from '../../utils/index.js';
3
+ /**
4
+ * 收集 ref API 的别名
5
+ * 识别从 vitarx 或 @vitarx/responsive 导入的 ref/toRef/toRefs/shallowRef/computed
6
+ * @param program - AST Program 节点
7
+ * @returns ref API 别名映射
8
+ */
9
+ export function collectRefApiAliases(program) {
10
+ const aliases = {
11
+ ref: null,
12
+ toRef: null,
13
+ toRefs: null,
14
+ shallowRef: null,
15
+ computed: null
16
+ };
17
+ for (const node of program.body) {
18
+ if (node.type !== 'ImportDeclaration')
19
+ continue;
20
+ const source = node.source.value;
21
+ if (!RESPONSIVE_MODULES.includes(source))
22
+ continue;
23
+ for (const specifier of node.specifiers) {
24
+ if (specifier.type !== 'ImportSpecifier')
25
+ continue;
26
+ const importedName = specifier.imported.type === 'Identifier'
27
+ ? specifier.imported.name
28
+ : specifier.imported.value;
29
+ if (Object.values(REF_APIS).includes(importedName)) {
30
+ aliases[importedName] = specifier.local.name;
31
+ }
32
+ }
33
+ }
34
+ return aliases;
35
+ }
36
+ /**
37
+ * 收集通过 ref API 定义的变量
38
+ * 包括直接赋值和 toRefs 解构
39
+ * @param program - AST Program 节点
40
+ * @param refApiAliases - ref API 别名映射
41
+ * @returns ref 变量名集合
42
+ */
43
+ export function collectRefVariables(program, refApiAliases) {
44
+ const refVariables = new Set();
45
+ const { refApiLocalNames, toRefsLocalNames } = buildApiNameSets(refApiAliases);
46
+ for (const node of program.body) {
47
+ if (node.type !== 'VariableDeclaration')
48
+ continue;
49
+ for (const decl of node.declarations) {
50
+ if (!decl.init)
51
+ continue;
52
+ if (decl.id.type === 'VoidPattern')
53
+ continue;
54
+ const init = decl.init;
55
+ if (init.type !== 'CallExpression' || init.callee.type !== 'Identifier') {
56
+ continue;
57
+ }
58
+ const calleeName = init.callee.name;
59
+ if (toRefsLocalNames.has(calleeName) && decl.id.type === 'ObjectPattern') {
60
+ collectObjectPatternBindings(decl.id, refVariables);
61
+ }
62
+ else if (refApiLocalNames.has(calleeName)) {
63
+ collectPatternBindings(decl.id, refVariables);
64
+ }
65
+ }
66
+ }
67
+ return refVariables;
68
+ }
69
+ /**
70
+ * 构建 API 名称集合
71
+ */
72
+ function buildApiNameSets(refApiAliases) {
73
+ const refApiLocalNames = new Set();
74
+ const toRefsLocalNames = new Set();
75
+ for (const key of Object.keys(refApiAliases)) {
76
+ const alias = refApiAliases[key];
77
+ if (alias) {
78
+ if (key === 'toRefs') {
79
+ toRefsLocalNames.add(alias);
80
+ }
81
+ else {
82
+ refApiLocalNames.add(alias);
83
+ }
84
+ }
85
+ else {
86
+ if (key === 'toRefs') {
87
+ toRefsLocalNames.add(key);
88
+ }
89
+ else {
90
+ refApiLocalNames.add(key);
91
+ }
92
+ }
93
+ }
94
+ return { refApiLocalNames, toRefsLocalNames };
95
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 导入处理模块
3
+ * @module passes/imports
4
+ */
5
+ export { collectExistingImports, collectLocalBindings } from './collectImports.js';
6
+ export { collectRefApiAliases, collectRefVariables } from './collectRefVariables.js';
7
+ export { injectImports } from './injectImports.js';
@@ -0,0 +1,96 @@
1
+ /**
2
+ * 导入注入模块
3
+ * 负责动态注入 vitarx 导入语句
4
+ * @module passes/imports/injectImports
5
+ */
6
+ import * as t from '@babel/types';
7
+ import { VITARX_MODULE } from '../../constants/index.js';
8
+ /**
9
+ * API 导入配置
10
+ * 定义需要注入的 API 及其与 ImportInfo 的映射关系
11
+ */
12
+ const API_IMPORT_CONFIG = [
13
+ { name: 'createView', importKey: 'createView' },
14
+ { name: 'Fragment', importKey: 'Fragment' },
15
+ { name: 'branch', importKey: 'branch' },
16
+ { name: 'dynamic', importKey: 'dynamic' },
17
+ { name: 'access', importKey: 'access' },
18
+ { name: 'withDirectives', importKey: 'withDirectives' },
19
+ { name: 'unref', importKey: 'unref' },
20
+ { name: 'isRef', importKey: 'isRef' }
21
+ ];
22
+ /**
23
+ * 注入 vitarx 导入
24
+ * 根据已使用的 API 动态生成导入语句
25
+ * @param program - AST Program 节点
26
+ * @param ctx - 转换上下文
27
+ */
28
+ export function injectImports(program, ctx) {
29
+ if (!needsInject(ctx))
30
+ return;
31
+ const existingVitarxImport = findExistingVitarxImport(program);
32
+ if (existingVitarxImport) {
33
+ appendImportSpecifiers(existingVitarxImport, ctx);
34
+ }
35
+ else {
36
+ const specifiers = buildImportSpecifiers(ctx);
37
+ if (specifiers.length === 0)
38
+ return;
39
+ const importDecl = t.importDeclaration(specifiers, t.stringLiteral(VITARX_MODULE));
40
+ program.body.unshift(importDecl);
41
+ }
42
+ }
43
+ /**
44
+ * 查找已存在的 vitarx 导入语句
45
+ */
46
+ function findExistingVitarxImport(program) {
47
+ for (const node of program.body) {
48
+ if (node.type === 'ImportDeclaration' && node.source.value === VITARX_MODULE) {
49
+ return node;
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+ /**
55
+ * 向已存在的导入语句追加说明符
56
+ */
57
+ function appendImportSpecifiers(importDecl, ctx) {
58
+ const existingLocals = new Set();
59
+ for (const spec of importDecl.specifiers) {
60
+ if (spec.type === 'ImportSpecifier') {
61
+ existingLocals.add(spec.local.name);
62
+ }
63
+ }
64
+ for (const { name, importKey } of API_IMPORT_CONFIG) {
65
+ if (!ctx.imports[importKey])
66
+ continue;
67
+ const alias = ctx.vitarxAliases[name];
68
+ const localName = alias || name;
69
+ if (existingLocals.has(localName))
70
+ continue;
71
+ const imported = t.identifier(name);
72
+ const local = t.identifier(localName);
73
+ importDecl.specifiers.push(t.importSpecifier(local, imported));
74
+ }
75
+ }
76
+ /**
77
+ * 检查是否需要注入导入
78
+ */
79
+ function needsInject(ctx) {
80
+ return Object.values(ctx.imports).some(Boolean);
81
+ }
82
+ /**
83
+ * 构建导入说明符列表
84
+ */
85
+ function buildImportSpecifiers(ctx) {
86
+ const specifiers = [];
87
+ for (const { name, importKey } of API_IMPORT_CONFIG) {
88
+ if (ctx.imports[importKey]) {
89
+ const alias = ctx.vitarxAliases[name];
90
+ const imported = t.identifier(name);
91
+ const local = alias ? t.identifier(alias) : imported;
92
+ specifiers.push(t.importSpecifier(local, imported));
93
+ }
94
+ }
95
+ return specifiers;
96
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 编译转换处理模块
3
+ * @module passes
4
+ */
5
+ // 导入处理
6
+ export { collectExistingImports, collectLocalBindings, collectRefApiAliases, collectRefVariables, injectImports } from './imports/index.js';
7
+ // 编译宏组件
8
+ export { processPureCompileComponent, processSwitch, processIfBlock } from './components/index.js';
9
+ // 指令处理
10
+ export { processVIfChain, processDirectives } from './directives/index.js';
11
+ // JSX 处理
12
+ export { processChildren, processJSXElement, transformJSXElement, processJSXFragment } from './jsx/index.js';
13
+ // Props 处理
14
+ export { processProps } from './props/index.js';
15
+ // HMR 注入
16
+ export { injectHMRSupport } from './hmr/index.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * JSX 处理模块
3
+ * @module passes/jsx
4
+ */
5
+ export { processChildren } from './processChildren.js';
6
+ export { processJSXElement, transformJSXElement } from './processJSXElement.js';
7
+ export { processJSXFragment } from './processJSXFragment.js';
@@ -0,0 +1,114 @@
1
+ /**
2
+ * 子元素处理模块
3
+ * 处理 JSX 元素的子节点
4
+ * @module passes/jsx/processChildren
5
+ */
6
+ import * as t from '@babel/types';
7
+ import { isBooleanLiteral, isConditionalExpression, isIdentifier, isJSXElement, isJSXExpressionContainer, isJSXFragment, isJSXText, isLogicalExpression, isMemberExpression, isNumericLiteral, isStringLiteral } from '@babel/types';
8
+ import { markImport } from '../../context.js';
9
+ import { addPureComment, createAccessCall, createBinaryBranch, createDynamicCall, getAlias } from '../../utils/index.js';
10
+ /**
11
+ * 处理子节点数组
12
+ * @param children - 子节点数组
13
+ * @param ctx - 转换上下文
14
+ * @returns 处理后的表达式数组
15
+ */
16
+ export function processChildren(children, ctx) {
17
+ const result = [];
18
+ for (const child of children) {
19
+ const processed = processChildNode(child, ctx);
20
+ if (processed !== null) {
21
+ result.push(processed);
22
+ }
23
+ }
24
+ return result;
25
+ }
26
+ /**
27
+ * 处理单个子节点
28
+ */
29
+ function processChildNode(node, ctx) {
30
+ // JSX 文本
31
+ if (isJSXText(node)) {
32
+ const trimmed = node.value.trim();
33
+ if (!trimmed)
34
+ return null;
35
+ return t.stringLiteral(trimmed);
36
+ }
37
+ // JSX 表达式容器
38
+ if (isJSXExpressionContainer(node)) {
39
+ if (node.expression.type === 'JSXEmptyExpression')
40
+ return null;
41
+ return processChildExpression(node.expression, ctx);
42
+ }
43
+ // JSX 展开子元素
44
+ if (node.type === 'JSXSpreadChild') {
45
+ return processChildExpression(node.expression, ctx);
46
+ }
47
+ // JSX 元素或片段
48
+ if (isJSXElement(node) || isJSXFragment(node)) {
49
+ return node;
50
+ }
51
+ // 字面量
52
+ if (isStringLiteral(node) || isNumericLiteral(node) || isBooleanLiteral(node)) {
53
+ return node;
54
+ }
55
+ // 标识符
56
+ if (isIdentifier(node)) {
57
+ return node;
58
+ }
59
+ // 成员表达式
60
+ if (isMemberExpression(node)) {
61
+ markImport(ctx, 'access');
62
+ const accessAlias = getAlias(ctx.vitarxAliases, 'access');
63
+ return createAccessCall(node.object, node.property, accessAlias);
64
+ }
65
+ // 条件表达式
66
+ if (isConditionalExpression(node)) {
67
+ return processConditionalExpression(node, ctx);
68
+ }
69
+ // 逻辑表达式
70
+ if (isLogicalExpression(node)) {
71
+ markImport(ctx, 'dynamic');
72
+ const dynamicAlias = getAlias(ctx.vitarxAliases, 'dynamic');
73
+ return addPureComment(createDynamicCall(node, dynamicAlias));
74
+ }
75
+ // 调用表达式
76
+ if (node.type === 'CallExpression') {
77
+ return node;
78
+ }
79
+ return node;
80
+ }
81
+ /**
82
+ * 处理子表达式
83
+ */
84
+ function processChildExpression(expr, ctx) {
85
+ if (isIdentifier(expr)) {
86
+ return expr;
87
+ }
88
+ if (isMemberExpression(expr)) {
89
+ markImport(ctx, 'access');
90
+ const accessAlias = getAlias(ctx.vitarxAliases, 'access');
91
+ return createAccessCall(expr.object, expr.property, accessAlias);
92
+ }
93
+ if (isConditionalExpression(expr)) {
94
+ return processConditionalExpression(expr, ctx);
95
+ }
96
+ if (isLogicalExpression(expr)) {
97
+ markImport(ctx, 'dynamic');
98
+ const dynamicAlias = getAlias(ctx.vitarxAliases, 'dynamic');
99
+ return addPureComment(createDynamicCall(expr, dynamicAlias));
100
+ }
101
+ return expr;
102
+ }
103
+ /**
104
+ * 处理条件表达式
105
+ * 转换为 branch 调用
106
+ */
107
+ function processConditionalExpression(node, ctx) {
108
+ const { test, consequent, alternate } = node;
109
+ // 处理分支
110
+ const processedConsequent = processChildNode(consequent, ctx) || t.nullLiteral();
111
+ const processedAlternate = processChildNode(alternate, ctx) || t.nullLiteral();
112
+ // 使用公共的 createBinaryBranch
113
+ return createBinaryBranch(test, processedConsequent, processedAlternate, ctx);
114
+ }