@vitarx/plugin-vite 0.0.1-beta.6 → 0.0.1-beta.8

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/context.d.ts CHANGED
@@ -3,16 +3,9 @@
3
3
  * 定义编译转换过程中的上下文数据结构
4
4
  * @module context
5
5
  */
6
- import type { File } from '@babel/types';
7
- import type { CompileOptions } from './transform.js';
6
+ import type { CallExpression, File } from '@babel/types';
8
7
  import type { CompilerWarning } from './error.js';
9
- import { UI_API_NAMES } from './constants/index.js';
10
- /**
11
- * UI 相关的 API 名称列表
12
- * 这些 API 用于创建视图,在 HMR 时需要识别
13
- */
14
- export declare const UI_API_NAMES_CONST: readonly ["createView", "branch", "dynamic", "access", "withDirectives"];
15
- export type UIApiName = (typeof UI_API_NAMES)[number];
8
+ import type { CompileOptions } from './types.js';
16
9
  /**
17
10
  * 导入信息
18
11
  * 追踪需要注入的运行时 API
@@ -87,6 +80,12 @@ export interface TransformContext {
87
80
  refVariables: Set<string>;
88
81
  /** UI API 别名集合(用于 HMR 代码分离识别) */
89
82
  uiApiAliases: Set<string>;
83
+ /** builder 函数的本地别名(用于识别纯构建组件) */
84
+ builderAlias: string | null;
85
+ /** 已处理的 AST 节点追踪集合 */
86
+ processedNodes: WeakSet<any>;
87
+ /** 已添加 PURE 注释的节点追踪集合 */
88
+ pureCommentedNodes: WeakSet<CallExpression>;
90
89
  /** 编译警告列表 */
91
90
  warnings: CompilerWarning[];
92
91
  }
@@ -105,12 +104,6 @@ export declare function createContext(code: string, id: string, options: Compile
105
104
  * @param name - 导入名称
106
105
  */
107
106
  export declare function markImport(ctx: TransformContext, name: keyof ImportInfo): void;
108
- /**
109
- * 记录 UI API 别名
110
- * @param ctx - 转换上下文
111
- * @param alias - API 别名
112
- */
113
- export declare function markUiApiAlias(ctx: TransformContext, alias: string): void;
114
107
  /**
115
108
  * 添加编译警告
116
109
  * @param ctx - 转换上下文
package/dist/context.js CHANGED
@@ -1,9 +1,3 @@
1
- import { UI_API_NAMES } from './constants/index.js';
2
- /**
3
- * UI 相关的 API 名称列表
4
- * 这些 API 用于创建视图,在 HMR 时需要识别
5
- */
6
- export const UI_API_NAMES_CONST = UI_API_NAMES;
7
1
  /**
8
2
  * 创建转换上下文
9
3
  * @param code - 源代码
@@ -50,6 +44,9 @@ export function createContext(code, id, options, ast) {
50
44
  },
51
45
  refVariables: new Set(),
52
46
  uiApiAliases: new Set(),
47
+ builderAlias: null,
48
+ processedNodes: new WeakSet(),
49
+ pureCommentedNodes: new WeakSet(),
53
50
  warnings: []
54
51
  };
55
52
  }
@@ -61,14 +58,6 @@ export function createContext(code, id, options, ast) {
61
58
  export function markImport(ctx, name) {
62
59
  ctx.imports[name] = true;
63
60
  }
64
- /**
65
- * 记录 UI API 别名
66
- * @param ctx - 转换上下文
67
- * @param alias - API 别名
68
- */
69
- export function markUiApiAlias(ctx, alias) {
70
- ctx.uiApiAliases.add(alias);
71
- }
72
61
  /**
73
62
  * 添加编译警告
74
63
  * @param ctx - 转换上下文
@@ -45,8 +45,9 @@ export default class HMRManager {
45
45
  * 注册节点
46
46
  *
47
47
  * @param view - 组件视图节点
48
+ * @param component - 组件构造函数
48
49
  */
49
- register(view: ComponentView): void;
50
+ register(view: ComponentView, component?: Component): void;
50
51
  /**
51
52
  * 获取模块id
52
53
  *
@@ -80,11 +80,12 @@ class HMRManager {
80
80
  * 注册节点
81
81
  *
82
82
  * @param view - 组件视图节点
83
+ * @param component - 组件构造函数
83
84
  */
84
- register(view) {
85
+ register(view, component) {
85
86
  if (!view)
86
87
  return;
87
- const component = view.component;
88
+ component ?? (component = view.component);
88
89
  const id = this.getId(component);
89
90
  if (__classPrivateFieldGet(this, _HMRManager_idMapToView, "f").has(id)) {
90
91
  __classPrivateFieldGet(this, _HMRManager_idMapToView, "f").get(id).add(view);
@@ -124,7 +125,7 @@ class HMRManager {
124
125
  if (id)
125
126
  __classPrivateFieldGet(this, _HMRManager_idMapToComponent, "f").set(id, newComponent);
126
127
  // 更新节点视图
127
- if (node.active && node.isMounted) {
128
+ if ((node.isActive || node.active) && node.isMounted) {
128
129
  processUpdate(node, newComponent);
129
130
  }
130
131
  }
@@ -10,7 +10,7 @@ import { UI_API_NAMES } from '../constants/index.js';
10
10
  * UI 相关的运行时 API 名称
11
11
  * 这些 API 调用代表 UI 描述代码
12
12
  */
13
- const UI_APIS = new Set([...UI_API_NAMES, 'jsxDEV']);
13
+ const UI_APIS = new Set([...UI_API_NAMES, 'jsxDEV', 'h']);
14
14
  /**
15
15
  * 判断标识符名称是否为 UI API
16
16
  * 支持原始名称和带后缀的名称(如 jsxDEV$1)
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { version } from 'vite';
4
- import { transform } from './transform.js';
4
+ import { shouldTransform, transform } from './transform.js';
5
5
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
6
  const IS_V8 = version.startsWith('8');
7
7
  let viteTransform;
@@ -32,7 +32,6 @@ export default function vitarx(options) {
32
32
  let viteConfig;
33
33
  return {
34
34
  name: 'vite-plugin-vitarx',
35
- enforce: 'pre',
36
35
  config(config, env) {
37
36
  isDEV = env.command === 'serve' && !env.isPreview;
38
37
  const configSSR = !!config.build?.ssr;
@@ -59,15 +58,17 @@ export default function vitarx(options) {
59
58
  ssr: isSSR,
60
59
  hmr: isDEV && !isSSR,
61
60
  runtimeModule: 'vitarx',
62
- sourceMap: false,
61
+ sourceMap: true,
63
62
  transformClassNameToClass: options?.transformClassNameToClass ?? false
64
63
  };
65
64
  },
66
65
  async transform(code, id) {
66
+ if (!shouldTransform(id))
67
+ return null;
67
68
  const result = await transform(code, id, compileOptions);
68
69
  if (!result)
69
70
  return null;
70
- return await viteTransform(result.code, id, undefined, this.getCombinedSourcemap(), viteConfig);
71
+ return viteTransform(result.code, id, undefined, result.map || undefined, viteConfig);
71
72
  }
72
73
  };
73
74
  }
@@ -27,7 +27,7 @@ export function processDirectives(viewCall, directives, ctx) {
27
27
  }
28
28
  markImport(ctx, 'withDirectives');
29
29
  const withDirectivesAlias = getAlias(ctx.vitarxAliases, 'withDirectives');
30
- return addPureComment(createWithDirectivesCall(viewCall, directiveArray, withDirectivesAlias));
30
+ return addPureComment(createWithDirectivesCall(viewCall, directiveArray, withDirectivesAlias), ctx);
31
31
  }
32
32
  /**
33
33
  * 构建指令值对象
@@ -0,0 +1,19 @@
1
+ /**
2
+ * HMR 导入注入模块
3
+ * 负责注入 HMR 所需的导入语句
4
+ * @module passes/hmr/inject-imports
5
+ */
6
+ import * as t from '@babel/types';
7
+ /** getComponentView 的内部别名,避免与用户代码冲突 */
8
+ export declare const GET_COMPONENT_VIEW_ALIAS = "__$VITARX_GET_COMPONENT_VIEW$__";
9
+ /**
10
+ * 注入 HMR 客户端导入
11
+ * @param program - AST Program 节点
12
+ */
13
+ export declare function injectHMRImport(program: t.Program): void;
14
+ /**
15
+ * 注入 getComponentView 导入
16
+ * 使用唯一的别名避免与用户代码冲突
17
+ * @param program - AST Program 节点
18
+ */
19
+ export declare function injectGetComponentViewImport(program: t.Program): void;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * HMR 导入注入模块
3
+ * 负责注入 HMR 所需的导入语句
4
+ * @module passes/hmr/inject-imports
5
+ */
6
+ import * as t from '@babel/types';
7
+ import { HMR } from '../../constants/index.js';
8
+ /** getComponentView 的内部别名,避免与用户代码冲突 */
9
+ export const GET_COMPONENT_VIEW_ALIAS = '__$VITARX_GET_COMPONENT_VIEW$__';
10
+ /**
11
+ * 注入 HMR 客户端导入
12
+ * @param program - AST Program 节点
13
+ */
14
+ export function injectHMRImport(program) {
15
+ const importDecl = t.importDeclaration([t.importDefaultSpecifier(t.identifier(HMR.manager))], t.stringLiteral('@vitarx/vite-plugin/hmr-client'));
16
+ program.body.unshift(importDecl);
17
+ }
18
+ /**
19
+ * 注入 getComponentView 导入
20
+ * 使用唯一的别名避免与用户代码冲突
21
+ * @param program - AST Program 节点
22
+ */
23
+ export function injectGetComponentViewImport(program) {
24
+ const importDecl = t.importDeclaration([t.importSpecifier(t.identifier(GET_COMPONENT_VIEW_ALIAS), t.identifier('getComponentView'))], t.stringLiteral('vitarx'));
25
+ program.body.unshift(importDecl);
26
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * HMR 状态恢复模块
3
+ * 负责为组件函数注入状态保存和恢复代码
4
+ * @module passes/hmr/inject-state
5
+ */
6
+ import * as t from '@babel/types';
7
+ /**
8
+ * 创建组件函数体内的 HMR 注册代码
9
+ * @param variableNames - 需要追踪的变量名列表
10
+ * @returns HMR 注册语句数组
11
+ */
12
+ export declare function createHMRRegistrationStatements(variableNames: string[]): t.Statement[];
13
+ /**
14
+ * 创建包装组件的 HMR 注册代码
15
+ * 只注册节点,不保存状态,传入组件函数自身作为第二个参数
16
+ * @param componentName - 组件函数名称
17
+ * @returns HMR 注册语句数组
18
+ */
19
+ export declare function createWrappedComponentHMRStatements(componentName: string): t.Statement[];
20
+ /**
21
+ * 从函数体中收集局部变量名
22
+ * @param functionBody - 函数体语句块
23
+ * @returns 变量名数组
24
+ */
25
+ export declare function collectLocalVariableNames(functionBody: t.BlockStatement): string[];
26
+ /**
27
+ * 为函数体内的变量声明注入状态恢复代码
28
+ */
29
+ export declare function injectStatePreservation(functionBody: t.BlockStatement): void;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * HMR 状态恢复模块
3
+ * 负责为组件函数注入状态保存和恢复代码
4
+ * @module passes/hmr/inject-state
5
+ */
6
+ import * as t from '@babel/types';
7
+ import { HMR } from '../../constants/index.js';
8
+ import { collectPatternBindings } from '../../utils/index.js';
9
+ import { GET_COMPONENT_VIEW_ALIAS } from './inject-imports.js';
10
+ /**
11
+ * 创建组件函数体内的 HMR 注册代码
12
+ * @param variableNames - 需要追踪的变量名列表
13
+ * @returns HMR 注册语句数组
14
+ */
15
+ export function createHMRRegistrationStatements(variableNames) {
16
+ const statements = [];
17
+ statements.push(t.variableDeclaration('const', [
18
+ t.variableDeclarator(t.identifier(HMR.view), t.callExpression(t.identifier(GET_COMPONENT_VIEW_ALIAS), []))
19
+ ]));
20
+ statements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier(HMR.manager), t.identifier('instance')), t.identifier('register')), [t.identifier(HMR.view)])));
21
+ const stateProperties = variableNames.map(name => t.objectMethod('get', t.identifier(name), [], t.blockStatement([t.returnStatement(t.identifier(name))])));
22
+ 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')), [
23
+ t.arrowFunctionExpression([], t.blockStatement([
24
+ t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(HMR.view), t.identifier(HMR.state)), t.objectExpression(stateProperties)))
25
+ ]))
26
+ ]))));
27
+ return statements;
28
+ }
29
+ /**
30
+ * 创建包装组件的 HMR 注册代码
31
+ * 只注册节点,不保存状态,传入组件函数自身作为第二个参数
32
+ * @param componentName - 组件函数名称
33
+ * @returns HMR 注册语句数组
34
+ */
35
+ export function createWrappedComponentHMRStatements(componentName) {
36
+ const statements = [];
37
+ statements.push(t.variableDeclaration('const', [
38
+ t.variableDeclarator(t.identifier(HMR.view), t.callExpression(t.identifier(GET_COMPONENT_VIEW_ALIAS), []))
39
+ ]));
40
+ statements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier(HMR.manager), t.identifier('instance')), t.identifier('register')), [t.identifier(HMR.view), t.identifier(componentName)])));
41
+ return statements;
42
+ }
43
+ /**
44
+ * 从函数体中收集局部变量名
45
+ * @param functionBody - 函数体语句块
46
+ * @returns 变量名数组
47
+ */
48
+ export function collectLocalVariableNames(functionBody) {
49
+ const variableNames = new Set();
50
+ for (const stmt of functionBody.body) {
51
+ if (stmt.type === 'VariableDeclaration') {
52
+ for (const decl of stmt.declarations) {
53
+ if (decl.id.type !== 'VoidPattern') {
54
+ collectPatternBindings(decl.id, variableNames);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ return Array.from(variableNames);
60
+ }
61
+ /**
62
+ * 判断表达式是否为函数类型
63
+ */
64
+ function isFunctionExpression(expr) {
65
+ if (!expr)
66
+ return false;
67
+ return (expr.type === 'ArrowFunctionExpression' ||
68
+ expr.type === 'FunctionExpression' ||
69
+ expr.type === 'ClassExpression');
70
+ }
71
+ /**
72
+ * 创建状态恢复表达式
73
+ * 格式:__$VITARX_HMR$__.instance.memo(__$VITARX_HMR_VIEW_NODE$__, '变量名') ?? 原始初始值
74
+ */
75
+ function createMemoExpression(variableName, originalInit) {
76
+ 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);
77
+ }
78
+ /**
79
+ * 为单个变量声明注入状态恢复代码
80
+ */
81
+ function injectStatePreservationForDeclaration(decl) {
82
+ if (decl.id.type !== 'Identifier')
83
+ return;
84
+ if (!decl.init)
85
+ return;
86
+ if (isFunctionExpression(decl.init))
87
+ return;
88
+ decl.init = createMemoExpression(decl.id.name, decl.init);
89
+ }
90
+ /**
91
+ * 为函数体内的变量声明注入状态恢复代码
92
+ */
93
+ export function injectStatePreservation(functionBody) {
94
+ for (const stmt of functionBody.body) {
95
+ if (stmt.type === 'VariableDeclaration') {
96
+ for (const decl of stmt.declarations) {
97
+ injectStatePreservationForDeclaration(decl);
98
+ }
99
+ }
100
+ }
101
+ }
@@ -4,7 +4,7 @@
4
4
  * @module passes/hmr
5
5
  */
6
6
  import * as t from '@babel/types';
7
- import { type ComponentInfo } from '../../utils/index.js';
7
+ import type { ComponentInfo } from '../../utils/index.js';
8
8
  /**
9
9
  * 注入 HMR 支持
10
10
  * 主入口函数,为所有组件注入完整的 HMR 支持
@@ -5,133 +5,28 @@
5
5
  */
6
6
  import * as t from '@babel/types';
7
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
- }
8
+ import { injectHMRImport, injectGetComponentViewImport } from './inject-imports.js';
9
+ import { createHMRRegistrationStatements, createWrappedComponentHMRStatements, collectLocalVariableNames, injectStatePreservation } from './inject-state.js';
117
10
  /**
118
11
  * 为组件函数注入 HMR 注册代码
119
12
  * @param func - 函数声明/表达式/箭头函数
120
13
  * @param variableNames - 需要追踪的变量名列表
14
+ * @param isWrapped - 是否为包装组件
15
+ * @param componentName - 组件名称(包装组件需要)
121
16
  */
122
- function injectHMRIntoFunction(func, variableNames) {
123
- // 处理箭头函数没有函数体的情况(表达式体)
17
+ function injectHMRIntoFunction(func, variableNames, isWrapped = false, componentName) {
124
18
  if (func.type === 'ArrowFunctionExpression' && func.body.type !== 'BlockStatement') {
125
- // 将表达式体转换为块语句
126
19
  const returnStmt = t.returnStatement(func.body);
127
20
  func.body = t.blockStatement([returnStmt]);
128
21
  }
129
22
  if (!func.body || func.body.type !== 'BlockStatement')
130
23
  return;
131
- // 注入状态恢复代码
132
- injectStatePreservation(func.body);
133
- // 注入 HMR 注册代码
134
- const statements = createHMRRegistrationStatements(variableNames);
24
+ if (!isWrapped) {
25
+ injectStatePreservation(func.body);
26
+ }
27
+ const statements = isWrapped
28
+ ? createWrappedComponentHMRStatements(componentName)
29
+ : createHMRRegistrationStatements(variableNames);
135
30
  func.body.body.unshift(...statements);
136
31
  }
137
32
  /**
@@ -171,19 +66,14 @@ function generateComponentId(filename, componentName) {
171
66
  export function injectHMRSupport(program, components, filename) {
172
67
  if (components.length === 0)
173
68
  return;
174
- // 注入必要的导入
175
69
  injectHMRImport(program);
176
70
  injectGetComponentViewImport(program);
177
- // 为每个组件函数注入 HMR 代码
178
- for (const { node } of components) {
179
- // 收集局部变量名(如果有函数体)
71
+ for (const { node, isWrapped, name } of components) {
180
72
  const variableNames = node.body?.type === 'BlockStatement' ? collectLocalVariableNames(node.body) : [];
181
- injectHMRIntoFunction(node, variableNames);
73
+ injectHMRIntoFunction(node, variableNames, isWrapped, name);
182
74
  }
183
- // 为每个组件绑定 ID
184
75
  for (const { name } of components) {
185
76
  program.body.push(createBindIdStatement(name, generateComponentId(filename, name)));
186
77
  }
187
- // 注入 import.meta.hot.accept
188
78
  program.body.push(createHotAcceptStatement());
189
79
  }
@@ -22,7 +22,7 @@ function handleLogicalExpression(expr, ctx, loc) {
22
22
  markImport(ctx, 'dynamic');
23
23
  const dynamicAlias = getAlias(ctx.vitarxAliases, 'dynamic');
24
24
  const locInfo = loc ? getDevLocInfo(ctx, { loc }) : null;
25
- return addPureComment(createDynamicCall(expr, dynamicAlias, locInfo));
25
+ return addPureComment(createDynamicCall(expr, dynamicAlias, locInfo), ctx);
26
26
  }
27
27
  /**
28
28
  * 处理子节点数组
@@ -87,7 +87,7 @@ export function transformJSXElement(node, ctx, handleVIf = false) {
87
87
  viewCall = processDirectives(viewCall, directives, ctx);
88
88
  }
89
89
  else {
90
- viewCall = addPureComment(viewCall);
90
+ viewCall = addPureComment(viewCall, ctx);
91
91
  }
92
92
  if (node.loc) {
93
93
  viewCall.loc = node.loc;
@@ -1,5 +1,5 @@
1
1
  import * as t from '@babel/types';
2
- import { addPureComment, createCreateViewCall, filterWhitespaceChildren, getAlias, getDevLocInfo, validateMatchInSwitch } from '../../utils/index.js';
2
+ import { addPureComment, createCreateViewCall, filterWhitespaceChildren, getAlias, getDevLocInfo, validateNoDirectMatchChild } from '../../utils/index.js';
3
3
  import { processChildren } from './processChildren.js';
4
4
  /**
5
5
  * 处理 JSX Fragment
@@ -11,7 +11,7 @@ export function processJSXFragment(path, ctx) {
11
11
  // 过滤空白子节点
12
12
  const children = filterWhitespaceChildren(node.children);
13
13
  // 校验 Match 组件
14
- validateMatchInSwitch(children);
14
+ validateNoDirectMatchChild(children);
15
15
  // 标记需要的导入
16
16
  ctx.imports.Fragment = true;
17
17
  ctx.imports.createView = true;
@@ -20,7 +20,7 @@ export function processJSXFragment(path, ctx) {
20
20
  const locInfo = getDevLocInfo(ctx, node);
21
21
  // 无子元素
22
22
  if (children.length === 0) {
23
- const viewCall = addPureComment(createCreateViewCall(t.identifier(fragmentAlias), null, locInfo, createViewAlias));
23
+ const viewCall = addPureComment(createCreateViewCall(t.identifier(fragmentAlias), null, locInfo, createViewAlias), ctx);
24
24
  if (node.loc)
25
25
  viewCall.loc = node.loc;
26
26
  path.replaceWith(viewCall);
@@ -30,7 +30,7 @@ export function processJSXFragment(path, ctx) {
30
30
  const processedChildren = processChildren(children, ctx);
31
31
  const childrenValue = processedChildren.length === 1 ? processedChildren[0] : t.arrayExpression(processedChildren);
32
32
  const props = t.objectExpression([t.objectProperty(t.identifier('children'), childrenValue)]);
33
- const viewCall = addPureComment(createCreateViewCall(t.identifier(fragmentAlias), props, locInfo, createViewAlias));
33
+ const viewCall = addPureComment(createCreateViewCall(t.identifier(fragmentAlias), props, locInfo, createViewAlias), ctx);
34
34
  if (node.loc)
35
35
  viewCall.loc = node.loc;
36
36
  path.replaceWith(viewCall);
@@ -5,16 +5,9 @@
5
5
  */
6
6
  import * as t from '@babel/types';
7
7
  import { createError } from '../../error.js';
8
- import { isNativeElement } from '../../utils/index.js';
8
+ import { getJSXElementName, isNativeElement } from '../../utils/index.js';
9
9
  import { createProperty, getAttributeValue, processAttribute, processSpreadAttribute } from './attribute.js';
10
10
  import { createVModelProps, extractVModelState } from './vmodel.js';
11
- /**
12
- * 获取 JSX 元素的名称
13
- */
14
- function getJSXElementName(node) {
15
- const nameNode = node.openingElement.name;
16
- return nameNode.type === 'JSXIdentifier' ? nameNode.name : null;
17
- }
18
11
  /**
19
12
  * 校验 class 和 className 不能同时存在
20
13
  */
@@ -1,15 +1,16 @@
1
- export interface TransformResult {
2
- code: string;
3
- map: any;
4
- }
5
- export interface CompileOptions {
6
- hmr: boolean;
7
- dev: boolean;
8
- ssr: boolean;
9
- runtimeModule: string;
10
- sourceMap: boolean | 'inline' | 'both';
11
- transformClassNameToClass: boolean;
1
+ /**
2
+ * 主转换模块
3
+ * 负责解析 JSX/TSX 代码并转换为 createView 调用
4
+ * @module transform
5
+ */
6
+ import { type GeneratorResult } from '@babel/generator';
7
+ import type { CompileOptions } from './types.js';
8
+ export interface TransformResult extends GeneratorResult {
12
9
  }
10
+ /**
11
+ * 检查文件是否需要转换
12
+ */
13
+ export declare function shouldTransform(id: string): boolean;
13
14
  /**
14
15
  * 转换 JSX/TSX 代码
15
16
  */