@dimina/compiler 1.0.14-beta.0 → 1.0.14

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.
@@ -1,18 +1,15 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_env = require("../env-M-7lpbHL.cjs");
3
+ const require_compatibility = require("../compatibility-DCnJNS-s.cjs");
3
4
  let node_path = require("node:path");
4
5
  node_path = require_env.__toESM(node_path, 1);
5
6
  let node_worker_threads = require("node:worker_threads");
6
7
  let node_fs = require("node:fs");
7
8
  node_fs = require_env.__toESM(node_fs, 1);
8
- let _babel_core = require("@babel/core");
9
- _babel_core = require_env.__toESM(_babel_core, 1);
10
- let _babel_traverse = require("@babel/traverse");
11
- _babel_traverse = require_env.__toESM(_babel_traverse, 1);
12
- let _babel_types = require("@babel/types");
13
- _babel_types = require_env.__toESM(_babel_types, 1);
14
- let _babel_generator = require("@babel/generator");
15
- _babel_generator = require_env.__toESM(_babel_generator, 1);
9
+ let oxc_parser = require("oxc-parser");
10
+ let oxc_walker = require("oxc-walker");
11
+ let magic_string = require("magic-string");
12
+ magic_string = require_env.__toESM(magic_string, 1);
16
13
  let _vue_compiler_sfc = require("@vue/compiler-sfc");
17
14
  let cheerio = require("cheerio");
18
15
  cheerio = require_env.__toESM(cheerio, 1);
@@ -21,9 +18,8 @@ let htmlparser2 = require("htmlparser2");
21
18
  htmlparser2 = require_env.__toESM(htmlparser2, 1);
22
19
  //#region src/common/expression-parser.js
23
20
  /**
24
- * 表达式解析器 - 使用 Babel AST 解析器提取依赖
21
+ * 表达式解析器 - 使用 Oxc AST 解析器提取依赖
25
22
  */
26
- var traverse$1 = _babel_traverse.default.default ? _babel_traverse.default.default : _babel_traverse.default;
27
23
  var KEYWORDS = new Set([
28
24
  "true",
29
25
  "false",
@@ -57,7 +53,7 @@ var KEYWORDS = new Set([
57
53
  ]);
58
54
  /**
59
55
  * 提取表达式中的所有变量依赖路径
60
- * 使用 Babel AST 解析器进行精确分析
56
+ * 使用 Oxc AST 解析器进行精确分析
61
57
  * @param {string} expression - 表达式字符串,如 "count || defaultValue" 或 "item.name"
62
58
  * @returns {Array<string>} - 依赖的变量名数组,如 ["count", "defaultValue"] 或 ["item"]
63
59
  */
@@ -65,36 +61,42 @@ function extractDependencies(expression) {
65
61
  if (!expression || typeof expression !== "string") return [];
66
62
  const dependencies = /* @__PURE__ */ new Set();
67
63
  try {
68
- const code = `(${expression})`;
69
- traverse$1(_babel_core.default.parseSync(code, {
64
+ const ast = (0, oxc_parser.parseSync)("expression.js", `(${expression})`, {
70
65
  sourceType: "module",
71
- plugins: []
72
- }), {
73
- Identifier(path) {
74
- const name = path.node.name;
75
- if (KEYWORDS.has(name)) return;
76
- const parent = path.parent;
77
- if (parent.type === "MemberExpression" && parent.property === path.node && !parent.computed) return;
78
- if (parent.type === "CallExpression" && parent.callee === path.node) {
79
- dependencies.add(name);
80
- return;
81
- }
82
- if (parent.type === "ObjectProperty" && parent.key === path.node && !parent.computed) return;
83
- dependencies.add(name);
84
- },
85
- MemberExpression(path) {
86
- let root = path.node.object;
87
- while (root.type === "MemberExpression") root = root.object;
88
- if (root.type === "Identifier" && !KEYWORDS.has(root.name)) dependencies.add(root.name);
89
- path.skip();
90
- }
91
- });
66
+ lang: "js"
67
+ }).program;
68
+ visitExpressionAst(ast, null, dependencies);
92
69
  } catch (error) {
93
70
  console.warn("[expression-parser] AST 解析失败,表达式:", expression, "错误:", error.message);
94
71
  return [];
95
72
  }
96
73
  return Array.from(dependencies);
97
74
  }
75
+ function visitExpressionAst(node, parent, dependencies) {
76
+ if (!node || typeof node !== "object") return;
77
+ if (node.type === "Identifier") {
78
+ collectIdentifier(node, parent, dependencies);
79
+ return;
80
+ }
81
+ if (node.type === "MemberExpression") {
82
+ let root = node.object;
83
+ while (root?.type === "MemberExpression" || root?.type === "ChainExpression") root = root.type === "ChainExpression" ? root.expression : root.object;
84
+ if (root?.type === "Identifier" && !KEYWORDS.has(root.name)) dependencies.add(root.name);
85
+ return;
86
+ }
87
+ for (const [key, value] of Object.entries(node)) {
88
+ if (key === "type" || key === "start" || key === "end" || key === "loc") continue;
89
+ if (Array.isArray(value)) for (const child of value) visitExpressionAst(child, node, dependencies);
90
+ else visitExpressionAst(value, node, dependencies);
91
+ }
92
+ }
93
+ function collectIdentifier(node, parent, dependencies) {
94
+ const name = node.name;
95
+ if (KEYWORDS.has(name)) return;
96
+ if (parent?.type === "MemberExpression" && parent.property === node && !parent.computed) return;
97
+ if (parent?.type === "Property" && parent.key === node && !parent.computed && !parent.shorthand) return;
98
+ dependencies.add(name);
99
+ }
98
100
  /**
99
101
  * 解析表达式并生成依赖路径信息
100
102
  * @param {string} expression - 表达式字符串
@@ -127,20 +129,53 @@ function parseBindings(bindings) {
127
129
  }
128
130
  //#endregion
129
131
  //#region src/core/view-compiler.js
130
- var traverse = _babel_traverse.default.default ? _babel_traverse.default.default : _babel_traverse.default;
131
- var generateCode = _babel_generator.default.default ? _babel_generator.default.default : _babel_generator.default;
132
132
  var fileType = [".wxml", ".ddml"];
133
133
  /**
134
- * AST 生成代码,如果顶层是单个表达式语句,则只生成表达式部分
135
- * @param {*} ast - Babel AST
136
- * @returns {string} 生成的表达式代码
134
+ * 解析 JavaScript 代码
135
+ * @param {string} code
136
+ * @param {string} filename
137
+ * @param {'module'|'script'} sourceType
138
+ * @returns {*} Oxc Program AST
137
139
  */
138
- function generateCodeFromAst(ast) {
139
- if (ast.type === "File" && ast.program.body.length === 1) {
140
- const statement = ast.program.body[0];
141
- if (statement.type === "ExpressionStatement") return generateCode(statement.expression, { comments: false }).code;
142
- }
143
- return generateCode(ast, { comments: false }).code;
140
+ function parseJs(code, filename = "view-compiler.js", sourceType = "module") {
141
+ return (0, oxc_parser.parseSync)(filename, code, {
142
+ sourceType,
143
+ lang: "js"
144
+ }).program;
145
+ }
146
+ /**
147
+ * 如果顶层是单个表达式语句,则只返回表达式源码
148
+ * @param {string} code
149
+ * @param {*} ast - Oxc Program AST
150
+ * @returns {string} Program code or the source of the single top-level expression.
151
+ */
152
+ function getProgramCode(code, ast) {
153
+ const statement = ast.body?.[0];
154
+ if (ast.body?.length === 1 && statement?.type === "ExpressionStatement") return code.slice(statement.expression.start, statement.expression.end);
155
+ return code;
156
+ }
157
+ function isStringLiteral(node) {
158
+ return node?.type === "StringLiteral" || node?.type === "Literal" && typeof node.value === "string";
159
+ }
160
+ function getStringLiteralRawValue(node) {
161
+ if (!isStringLiteral(node)) return "";
162
+ if (typeof node.raw === "string") return node.raw.slice(1, -1);
163
+ return String(node.value);
164
+ }
165
+ function getSource(code, node) {
166
+ return code.slice(node.start, node.end);
167
+ }
168
+ function applyCodeReplacements(source, replacements) {
169
+ if (replacements.length === 0) return source;
170
+ const selected = [];
171
+ const byLargestRange = [...replacements].sort((a, b) => {
172
+ return b.end - b.start - (a.end - a.start) || b.start - a.start;
173
+ });
174
+ for (const replacement of byLargestRange) if (!selected.some((item) => replacement.start < item.end && item.start < replacement.end)) selected.push(replacement);
175
+ const s = new magic_string.default(source);
176
+ for (const replacement of selected.sort((a, b) => b.start - a.start)) if (replacement.type === "insert") s.appendLeft(replacement.start, replacement.value);
177
+ else s.overwrite(replacement.start, replacement.end, replacement.value);
178
+ return s.toString();
144
179
  }
145
180
  /**
146
181
  * 为模板表达式中的成员访问补充空值保护,避免生成的 render 函数直接访问 null/undefined 属性
@@ -151,12 +186,30 @@ function generateCodeFromAst(ast) {
151
186
  function addOptionalChaining(expression) {
152
187
  if (!expression || typeof expression !== "string") return expression;
153
188
  try {
154
- const ast = _babel_core.default.parseSync(`(${expression})`, { parserOpts: { plugins: ["optionalChaining", "nullishCoalescingOperator"] } });
155
- traverse(ast, { MemberExpression: { exit(astPath) {
156
- if (astPath.node.optional) return;
157
- astPath.replaceWith(_babel_types.default.optionalMemberExpression(astPath.node.object, astPath.node.property, astPath.node.computed, true));
158
- } } });
159
- return generateCodeFromAst(ast);
189
+ const code = `(${expression})`;
190
+ const ast = parseJs(code);
191
+ const insertions = [];
192
+ (0, oxc_walker.walk)(ast, { enter(node) {
193
+ if (node.type !== "MemberExpression" || node.optional) return;
194
+ if (node.computed) {
195
+ const bracketIndex = code.lastIndexOf("[", node.property.start);
196
+ if (bracketIndex >= 0) insertions.push({
197
+ type: "insert",
198
+ start: bracketIndex,
199
+ end: bracketIndex,
200
+ value: "?."
201
+ });
202
+ } else {
203
+ const dotIndex = code.lastIndexOf(".", node.property.start);
204
+ if (dotIndex >= 0) insertions.push({
205
+ type: "insert",
206
+ start: dotIndex,
207
+ end: dotIndex,
208
+ value: "?"
209
+ });
210
+ }
211
+ } });
212
+ return applyCodeReplacements(code, insertions).slice(1, -1);
160
213
  } catch (error) {
161
214
  return expression;
162
215
  }
@@ -394,15 +447,11 @@ function compileModule(module, isComponent, scriptRes, options = {}) {
394
447
  inline: true
395
448
  }
396
449
  });
397
- const ast = _babel_core.default.parseSync(code);
398
- insertWxsToRenderAst(ast, compileInstruction.scriptModule, scriptRes);
399
- code = generateCodeFromAst(ast);
450
+ code = insertWxsToRenderCode(code, compileInstruction.scriptModule, scriptRes, tm.path);
400
451
  tplComponents += `'${tm.path}':${code},`;
401
452
  }
402
453
  tplComponents += "}";
403
- const tplAst = _babel_core.default.parseSync(tplCode.code);
404
- insertWxsToRenderAst(tplAst, compileInstruction.scriptModule, scriptRes);
405
- const transCode = generateCodeFromAst(tplAst);
454
+ const transCode = insertWxsToRenderCode(tplCode.code, compileInstruction.scriptModule, scriptRes, module.path);
406
455
  const code = `Module({
407
456
  path: '${module.path}',
408
457
  id: '${module.id}',
@@ -439,44 +488,42 @@ function compileModule(module, isComponent, scriptRes, options = {}) {
439
488
  function processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, filePath) {
440
489
  let wxsAst;
441
490
  try {
442
- wxsAst = _babel_core.default.parseSync(wxsContent);
491
+ wxsAst = parseJs(wxsContent, wxsFilePath || "inline.wxs", "script");
443
492
  } catch (error) {
444
493
  console.error(`[view] 解析 wxs 文件失败: ${wxsFilePath}`, error.message);
445
494
  return wxsContent;
446
495
  }
447
- traverse(wxsAst, {
448
- CallExpression(astPath) {
449
- const calleeName = astPath.node.callee.name;
496
+ const replacements = [];
497
+ (0, oxc_walker.walk)(wxsAst, { enter(node) {
498
+ if (node.type === "CallExpression") {
499
+ const calleeName = node.callee?.name;
450
500
  if (calleeName === "getRegExp") {
451
- const args = astPath.node.arguments;
452
- if (args.length > 0) if (args[0].type === "StringLiteral" && (!args[1] || args[1].type === "StringLiteral")) {
453
- let pattern = "";
454
- let flags = "";
455
- const arg = args[0];
456
- if (arg.extra && arg.extra.raw) pattern = arg.extra.raw.slice(1, -1);
457
- else if (arg.value !== void 0) pattern = arg.value;
458
- else pattern = "";
459
- if (args.length > 1) {
460
- const flagArg = args[1];
461
- if (flagArg.extra && flagArg.extra.raw) flags = flagArg.extra.raw.slice(1, -1);
462
- else if (flagArg.value !== void 0) flags = flagArg.value;
463
- else flags = "";
464
- }
465
- const regexLiteral = _babel_types.default.regExpLiteral(pattern, flags);
466
- astPath.replaceWith(regexLiteral);
501
+ const args = node.arguments;
502
+ if (args.length > 0) if (isStringLiteral(args[0]) && (!args[1] || isStringLiteral(args[1]))) {
503
+ const pattern = getStringLiteralRawValue(args[0]);
504
+ const flags = args.length > 1 ? getStringLiteralRawValue(args[1]) : "";
505
+ replacements.push({
506
+ start: node.start,
507
+ end: node.end,
508
+ value: `/${pattern}/${flags}`
509
+ });
467
510
  } else {
468
- const newRegExpArgs = [args[0]];
469
- if (args.length > 1) newRegExpArgs.push(args[1]);
470
- const newRegExpCall = _babel_types.default.newExpression(_babel_types.default.identifier("RegExp"), newRegExpArgs);
471
- astPath.replaceWith(newRegExpCall);
511
+ const newRegExpArgs = args.map((arg) => getSource(wxsContent, arg)).join(", ");
512
+ replacements.push({
513
+ start: node.start,
514
+ end: node.end,
515
+ value: `new RegExp(${newRegExpArgs})`
516
+ });
472
517
  }
473
518
  } else if (calleeName === "getDate") {
474
- const args = [];
475
- for (let i = 0; i < astPath.node.arguments.length; i++) args.push(astPath.node.arguments[i]);
476
- const newExpr = _babel_types.default.newExpression(_babel_types.default.identifier("Date"), args);
477
- astPath.replaceWith(newExpr);
478
- } else if (calleeName === "require" && astPath.node.arguments.length > 0 && wxsFilePath) {
479
- const requirePath = astPath.node.arguments[0].value;
519
+ const args = node.arguments.map((arg) => getSource(wxsContent, arg)).join(", ");
520
+ replacements.push({
521
+ start: node.start,
522
+ end: node.end,
523
+ value: `new Date(${args})`
524
+ });
525
+ } else if (calleeName === "require" && node.arguments.length > 0 && wxsFilePath) {
526
+ const requirePath = node.arguments[0].value;
480
527
  if (requirePath && typeof requirePath === "string") {
481
528
  let resolvedWxsPath;
482
529
  if (filePath && filePath.includes("/miniprogram_npm/")) {
@@ -484,25 +531,37 @@ function processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, file
484
531
  resolvedWxsPath = node_path.default.resolve(currentWxsDir, requirePath);
485
532
  const moduleName = resolvedWxsPath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
486
533
  processWxsDependency(resolvedWxsPath, moduleName, scriptModule, workPath, filePath);
487
- astPath.node.arguments[0] = _babel_types.default.stringLiteral(moduleName);
534
+ replacements.push({
535
+ start: node.arguments[0].start,
536
+ end: node.arguments[0].end,
537
+ value: JSON.stringify(moduleName)
538
+ });
488
539
  } else {
489
540
  const currentWxsDir = node_path.default.dirname(wxsFilePath);
490
541
  resolvedWxsPath = node_path.default.resolve(currentWxsDir, requirePath);
491
542
  const depModuleName = resolvedWxsPath.replace(workPath, "").replace(/\.wxs$/, "").replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
492
543
  processWxsDependency(resolvedWxsPath, depModuleName, scriptModule, workPath, filePath);
493
- astPath.node.arguments[0] = _babel_types.default.stringLiteral(depModuleName);
544
+ replacements.push({
545
+ start: node.arguments[0].start,
546
+ end: node.arguments[0].end,
547
+ value: JSON.stringify(depModuleName)
548
+ });
494
549
  }
495
550
  }
496
551
  }
497
- },
498
- MemberExpression(astPath) {
499
- if (astPath.node.property.name === "constructor" && !astPath.node.computed) {
500
- const getTypeString = _babel_types.default.callExpression(_babel_types.default.memberExpression(_babel_types.default.callExpression(_babel_types.default.memberExpression(_babel_types.default.memberExpression(_babel_types.default.memberExpression(_babel_types.default.identifier("Object"), _babel_types.default.identifier("prototype")), _babel_types.default.identifier("toString")), _babel_types.default.identifier("call")), [astPath.node.object]), _babel_types.default.identifier("slice")), [_babel_types.default.numericLiteral(8), _babel_types.default.numericLiteral(-1)]);
501
- astPath.replaceWith(getTypeString);
552
+ }
553
+ if (node.type === "MemberExpression") {
554
+ if (node.property?.name === "constructor" && !node.computed) {
555
+ const objectCode = getSource(wxsContent, node.object);
556
+ replacements.push({
557
+ start: node.start,
558
+ end: node.end,
559
+ value: `Object.prototype.toString.call(${objectCode}).slice(8, -1)`
560
+ });
502
561
  }
503
562
  }
504
- });
505
- return generateCodeFromAst(wxsAst);
563
+ } });
564
+ return applyCodeReplacements(wxsContent, replacements);
506
565
  }
507
566
  /**
508
567
  * 通过代码内容判断是否为 wxs 模块
@@ -532,9 +591,9 @@ function processWxsDependency(wxsFilePath, moduleName, scriptModule, workPath, f
532
591
  }
533
592
  /**
534
593
  * 重新编译模块,包含所有收集到的 wxs 模块
535
- * @param {*} module
536
- * @param {*} scriptRes
537
- * @param {*} allScriptModules
594
+ * @param {*} module
595
+ * @param {*} scriptRes
596
+ * @param {*} allScriptModules
538
597
  */
539
598
  function compileModuleWithAllWxs(module, scriptRes, allScriptModules) {
540
599
  const { tpl, instruction } = toCompileTemplate(false, module.path, module.usingComponents, module.componentPlaceholder);
@@ -573,15 +632,11 @@ function compileModuleWithAllWxs(module, scriptRes, allScriptModules) {
573
632
  inline: true
574
633
  }
575
634
  });
576
- const ast = _babel_core.default.parseSync(code);
577
- insertWxsToRenderAst(ast, allScriptModules, scriptRes);
578
- code = generateCodeFromAst(ast);
635
+ code = insertWxsToRenderCode(code, allScriptModules, scriptRes, tm.path);
579
636
  tplComponents += `'${tm.path}':${code},`;
580
637
  }
581
638
  tplComponents += "}";
582
- const tplAst = _babel_core.default.parseSync(tplCode.code);
583
- insertWxsToRenderAst(tplAst, allScriptModules, scriptRes);
584
- const transCode = generateCodeFromAst(tplAst);
639
+ const transCode = insertWxsToRenderCode(tplCode.code, allScriptModules, scriptRes, module.path);
585
640
  const code = `Module({
586
641
  path: '${module.path}',
587
642
  id: '${module.id}',
@@ -668,13 +723,17 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
668
723
  const workPath = require_env.getWorkPath();
669
724
  const fullPath = getViewPath(workPath, path);
670
725
  if (!fullPath) return { tpl: void 0 };
726
+ const diagnosticSource = fullPath.startsWith(workPath) ? fullPath.slice(workPath.length) : path;
671
727
  let content = require_env.getContentByPath(fullPath).trim();
672
728
  if (!content) content = "<block></block>";
673
- else if (isComponent) content = `<wrapper name="${path}">${content}</wrapper>`;
674
- else if (cheerio.load(content, {
675
- xmlMode: true,
676
- decodeEntities: false
677
- }).root().children().toArray().filter((node) => node.type !== "comment").length > 1) content = `<view>${content}</view>`;
729
+ else {
730
+ require_compatibility.checkTemplateCompatibility(content, diagnosticSource, components);
731
+ if (isComponent) content = `<wrapper name="${path}">${content}</wrapper>`;
732
+ else if (cheerio.load(content, {
733
+ xmlMode: true,
734
+ decodeEntities: false
735
+ }).root().children().toArray().filter((node) => node.type !== "comment").length > 1) content = `<view>${content}</view>`;
736
+ }
678
737
  const templateModule = [];
679
738
  const scriptModule = [];
680
739
  const $ = cheerio.load(content, {
@@ -689,9 +748,11 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
689
748
  if (src) {
690
749
  const includeFullPath = require_env.getAbsolutePath(workPath, path, src);
691
750
  let includePath = includeFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
751
+ const includeDiagnosticSource = includeFullPath.startsWith(workPath) ? includeFullPath.slice(workPath.length) : includePath;
692
752
  if (!includePath.startsWith("/")) includePath = "/" + includePath;
693
753
  const includeContent = require_env.getContentByPath(includeFullPath).trim();
694
754
  if (includeContent) {
755
+ require_compatibility.checkTemplateCompatibility(includeContent, includeDiagnosticSource, components);
695
756
  const $includeContent = cheerio.load(includeContent, {
696
757
  xmlMode: true,
697
758
  decodeEntities: false
@@ -715,9 +776,11 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
715
776
  if (src) {
716
777
  const importFullPath = require_env.getAbsolutePath(workPath, path, src);
717
778
  let importPath = importFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
779
+ const importDiagnosticSource = importFullPath.startsWith(workPath) ? importFullPath.slice(workPath.length) : importPath;
718
780
  if (!importPath.startsWith("/")) importPath = "/" + importPath;
719
781
  const importContent = require_env.getContentByPath(importFullPath).trim();
720
782
  if (importContent) {
783
+ require_compatibility.checkTemplateCompatibility(importContent, importDiagnosticSource, components);
721
784
  const $$ = cheerio.load(importContent, {
722
785
  xmlMode: true,
723
786
  decodeEntities: false
@@ -835,7 +898,7 @@ function transTag(opts) {
835
898
  }
836
899
  /**
837
900
  * 处理动态slot指令生成,比如 slot="{{xxx}}"
838
- *
901
+ *
839
902
  * @param {string} slotValue - slot属性值
840
903
  * @returns {string} 生成的slot指令
841
904
  */
@@ -1250,28 +1313,43 @@ function extractWxsDependencies(moduleCode) {
1250
1313
  }
1251
1314
  return dependencies;
1252
1315
  }
1253
- function insertWxsToRenderAst(ast, scriptModule, scriptRes) {
1254
- const replacements = [];
1316
+ function insertWxsToRenderCode(code, scriptModule, scriptRes, filename = "render.js") {
1317
+ const wxsBindings = [];
1318
+ const codeReplacements = [];
1319
+ const ast = parseJs(code, filename);
1320
+ const statement = ast.body?.[0];
1321
+ const renderBody = (statement?.type === "ExpressionStatement" ? statement.expression : null)?.body;
1322
+ const declarations = [];
1255
1323
  for (const [index, sm] of scriptModule.entries()) {
1256
1324
  if (!scriptRes.has(sm.path)) scriptRes.set(sm.path, sm.code);
1257
1325
  const templatePropertyName = sm.originalName || sm.path;
1258
1326
  const requireModuleName = sm.path;
1259
1327
  const localIdentifier = `__wxs_${index}`;
1260
- replacements.push({
1328
+ wxsBindings.push({
1261
1329
  localIdentifier,
1262
1330
  templatePropertyName
1263
1331
  });
1264
- const variableDeclaration = _babel_types.default.variableDeclaration("const", [_babel_types.default.variableDeclarator(_babel_types.default.identifier(localIdentifier), _babel_types.default.callExpression(_babel_types.default.identifier("require"), [_babel_types.default.stringLiteral(requireModuleName)]))]);
1265
- ast.program.body[0].expression.body.body.unshift(variableDeclaration);
1332
+ declarations.push(`const ${localIdentifier} = require(${JSON.stringify(requireModuleName)});`);
1266
1333
  }
1267
- if (replacements.length === 0) return;
1268
- traverse(ast, { MemberExpression(astPath) {
1269
- const { node } = astPath;
1270
- if (node.object?.type === "Identifier" && node.object.name === "_ctx" && !node.computed && node.property?.type === "Identifier") {
1271
- const replacement = replacements.find((item) => item.templatePropertyName === node.property.name);
1272
- if (replacement) astPath.replaceWith(_babel_types.default.identifier(replacement.localIdentifier));
1334
+ if (wxsBindings.length === 0) return getProgramCode(code, ast);
1335
+ if (renderBody?.type === "BlockStatement") codeReplacements.push({
1336
+ type: "insert",
1337
+ start: renderBody.start + 1,
1338
+ end: renderBody.start + 1,
1339
+ value: `\n${declarations.join("\n")}`
1340
+ });
1341
+ (0, oxc_walker.walk)(ast, { enter(node) {
1342
+ if (node.type === "MemberExpression" && node.object?.type === "Identifier" && node.object.name === "_ctx" && !node.computed && node.property?.type === "Identifier") {
1343
+ const replacement = wxsBindings.find((item) => item.templatePropertyName === node.property.name);
1344
+ if (replacement) codeReplacements.push({
1345
+ start: node.start,
1346
+ end: node.end,
1347
+ value: replacement.localIdentifier
1348
+ });
1273
1349
  }
1274
1350
  } });
1351
+ const transformed = applyCodeReplacements(code, codeReplacements);
1352
+ return getProgramCode(transformed, parseJs(transformed, filename));
1275
1353
  }
1276
1354
  //#endregion
1277
1355
  exports.compileML = compileML;