@wevu/compiler 6.19.4 → 6.20.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/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
- import { WEAPP_VITE_RUNTIME_REACTIVITY_VIRTUAL_ID, WEAPP_VITE_RUNTIME_TEMPLATE_VIRTUAL_ID, WEAPP_VITE_RUNTIME_VIRTUAL_ID, WEVU_CLASS_STYLE_RUNTIME_FILE, WEVU_CLASS_STYLE_RUNTIME_MODULE, WEVU_EXPRESSION_ERROR_IDENTIFIER, WEVU_FUNCTION_PROP_PATHS_KEY, WEVU_INLINE_HANDLER, WEVU_INLINE_MAP_KEY, WEVU_IS_PAGE_KEY, WEVU_LAYOUT_HOSTS_KEY, WEVU_LAYOUT_HOST_ID_PREFIX, WEVU_LAYOUT_HOST_REF_PREFIX, WEVU_MODEL_HANDLER, WEVU_OWNER_HANDLER, WEVU_PROPS_ALIASES_KEY, WEVU_PROPS_DERIVED_KEYS_KEY, WEVU_PROPS_KEY, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_BASE, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_TAG_NAME, WEVU_SLOT_FUNCTION_TOKEN, WEVU_SLOT_NAMES_ATTR, WEVU_SLOT_NAMES_PROP, WEVU_SLOT_OWNER_ID_ATTR, WEVU_SLOT_OWNER_ID_KEY, WEVU_SLOT_OWNER_ID_PROP, WEVU_SLOT_OWNER_KEY, WEVU_SLOT_OWNER_PROXY_KEY, WEVU_SLOT_PROPS_ATTR, WEVU_SLOT_PROPS_DATA_KEY, WEVU_SLOT_PROPS_KEY, WEVU_SLOT_SCOPE_ATTR, WEVU_SLOT_SCOPE_KEY, WEVU_TEMPLATE_REFS_KEY, WEVU_TEMPLATE_REF_CLASS_PREFIX } from "@weapp-core/constants";
2
+ import { WEAPP_VITE_RUNTIME_REACTIVITY_VIRTUAL_ID, WEAPP_VITE_RUNTIME_TEMPLATE_VIRTUAL_ID, WEAPP_VITE_RUNTIME_VIRTUAL_ID, WEVU_CLASS_STYLE_RUNTIME_FILE, WEVU_CLASS_STYLE_RUNTIME_MODULE, WEVU_EXPRESSION_ERROR_IDENTIFIER, WEVU_FUNCTION_PROP_PATHS_KEY, WEVU_INLINE_HANDLER, WEVU_INLINE_MAP_KEY, WEVU_IS_PAGE_KEY, WEVU_JSX_ISLAND_DATA_KEY, WEVU_JSX_ISLAND_HANDLER, WEVU_JSX_ISLAND_TEMPLATE_NAME, WEVU_LAYOUT_HOSTS_KEY, WEVU_LAYOUT_HOST_ID_PREFIX, WEVU_LAYOUT_HOST_REF_PREFIX, WEVU_MODEL_HANDLER, WEVU_OWNER_HANDLER, WEVU_PROPS_ALIASES_KEY, WEVU_PROPS_DERIVED_KEYS_KEY, WEVU_PROPS_KEY, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_BASE, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_TAG_NAME, WEVU_SLOT_FUNCTION_TOKEN, WEVU_SLOT_NAMES_ATTR, WEVU_SLOT_NAMES_PROP, WEVU_SLOT_OWNER_ID_ATTR, WEVU_SLOT_OWNER_ID_KEY, WEVU_SLOT_OWNER_ID_PROP, WEVU_SLOT_OWNER_KEY, WEVU_SLOT_OWNER_PROXY_KEY, WEVU_SLOT_PROPS_ATTR, WEVU_SLOT_PROPS_DATA_KEY, WEVU_SLOT_PROPS_KEY, WEVU_SLOT_SCOPE_ATTR, WEVU_SLOT_SCOPE_KEY, WEVU_TEMPLATE_REFS_KEY, WEVU_TEMPLATE_REF_CLASS_PREFIX } from "@weapp-core/constants";
3
3
  import { getMiniProgramRuntimeGlobalKeys, getMiniProgramTemplatePreset, removeExtensionDeep } from "@weapp-core/shared";
4
4
  import path from "pathe";
5
5
  import { NodeTypes, baseParse } from "@vue/compiler-core";
@@ -10,11 +10,14 @@ import { recursive } from "merge";
10
10
  import { bundleRequire } from "rolldown-require";
11
11
  import { access, mkdir, readFile as readFile$1, rm, stat, writeFile } from "node:fs/promises";
12
12
  import { BABEL_TS_MODULE_PARSER_OPTIONS, BABEL_TS_MODULE_PLUGINS, generate, parse as parse$3, parseJsLike, traverse } from "@weapp-vite/ast/babel";
13
- import fs from "node:fs";
13
+ import path$1 from "node:path";
14
+ import fs, { readFileSync } from "node:fs";
14
15
  import os from "node:os";
15
16
  import process from "node:process";
16
17
  import { LRUCache } from "lru-cache";
17
- import { collectJsxImportedComponentsAndDefaultExportFromBabelAst, collectJsxTemplateTagsFromBabelExpression, getRenderPropertyFromComponentOptions, parseJsLikeWithEngine, resolveRenderExpressionFromComponentOptions, toStaticObjectKey, unwrapTypeScriptExpression } from "@weapp-vite/ast";
18
+ import { collectJsxImportedComponentsAndDefaultExportFromBabelAst, collectJsxTemplateTagsFromBabelExpression, getObjectPropertyByKey, getRenderPropertyFromComponentOptions, parseJsLikeWithEngine, resolveRenderExpressionFromComponentOptions, toStaticObjectKey, unwrapTypeScriptExpression } from "@weapp-vite/ast";
19
+ import vueJsxPlugin from "@vue/babel-plugin-jsx";
20
+ import { transformSync } from "@weapp-vite/ast/babelCore";
18
21
  import { compileScript, parse } from "vue/compiler-sfc";
19
22
  import { fileURLToPath } from "node:url";
20
23
  import postcss from "postcss";
@@ -895,7 +898,7 @@ function isStaticObjectKeyMatch$1(key, expected) {
895
898
  if (t.isStringLiteral(key)) return key.value === expected;
896
899
  return false;
897
900
  }
898
- function getObjectPropertyByKey$2(node, key) {
901
+ function getObjectPropertyByKey$3(node, key) {
899
902
  for (const prop of node.properties) {
900
903
  if (!t.isObjectProperty(prop) || prop.computed) continue;
901
904
  if (isStaticObjectKeyMatch$1(prop.key, key)) return prop;
@@ -979,7 +982,7 @@ function collectWevuPageFeatureFlags(ast) {
979
982
  function injectWevuPageFeatureFlagsIntoOptionsObject(optionsObject, enabled) {
980
983
  if (!enabled.size) return false;
981
984
  const expectedKeys = [...enabled];
982
- const existingFeaturesProp = getObjectPropertyByKey$2(optionsObject, "features");
985
+ const existingFeaturesProp = getObjectPropertyByKey$3(optionsObject, "features");
983
986
  let changed = false;
984
987
  if (!existingFeaturesProp) {
985
988
  const featuresObject = buildInjectedFeaturesObject(enabled);
@@ -991,7 +994,7 @@ function injectWevuPageFeatureFlagsIntoOptionsObject(optionsObject, enabled) {
991
994
  const featuresObject = existingFeaturesProp.value;
992
995
  const injectedProps = [];
993
996
  for (const key of expectedKeys) {
994
- if (getObjectPropertyByKey$2(featuresObject, key)) continue;
997
+ if (getObjectPropertyByKey$3(featuresObject, key)) continue;
995
998
  injectedProps.push(t.objectProperty(t.identifier(key), t.booleanLiteral(true)));
996
999
  }
997
1000
  if (injectedProps.length) {
@@ -2371,6 +2374,8 @@ const INTERNAL_RUNTIME_VALUE_EXPORTS = /* @__PURE__ */ new Set([
2371
2374
  "addMutationRecorder",
2372
2375
  "batch",
2373
2376
  "computed",
2377
+ "createTextVNode",
2378
+ "createVNode",
2374
2379
  "createApp",
2375
2380
  "createWevuComponent",
2376
2381
  "createWevuScopedSlotComponent",
@@ -2385,6 +2390,7 @@ const INTERNAL_RUNTIME_VALUE_EXPORTS = /* @__PURE__ */ new Set([
2385
2390
  "getCurrentScope",
2386
2391
  "getCurrentSetupContext",
2387
2392
  "getDeepWatchStrategy",
2393
+ "Fragment",
2388
2394
  "getNavigationBarMetrics",
2389
2395
  "getReactiveVersion",
2390
2396
  "hasInjectionContext",
@@ -2398,12 +2404,15 @@ const INTERNAL_RUNTIME_VALUE_EXPORTS = /* @__PURE__ */ new Set([
2398
2404
  "isRef",
2399
2405
  "isShallowReactive",
2400
2406
  "isShallowRef",
2407
+ "isVNode",
2401
2408
  "markNoSetData",
2402
2409
  "markRaw",
2403
2410
  "mergeModels",
2411
+ "mergeProps",
2404
2412
  "mountRuntimeInstance",
2405
2413
  "nextTick",
2406
2414
  "normalizeClass",
2415
+ "normalizeJsxIsland",
2407
2416
  "normalizeStyle",
2408
2417
  "onActivated",
2409
2418
  "onAddToFavorites",
@@ -2444,6 +2453,8 @@ const INTERNAL_RUNTIME_VALUE_EXPORTS = /* @__PURE__ */ new Set([
2444
2453
  "provide",
2445
2454
  "provideGlobal",
2446
2455
  "reactive",
2456
+ "resolveDirective",
2457
+ "resolveComponent",
2447
2458
  "readonly",
2448
2459
  "ref",
2449
2460
  "registerApp",
@@ -2474,6 +2485,7 @@ const INTERNAL_RUNTIME_VALUE_EXPORTS = /* @__PURE__ */ new Set([
2474
2485
  "toRef",
2475
2486
  "toRefs",
2476
2487
  "toValue",
2488
+ "transformOn",
2477
2489
  "touchReactive",
2478
2490
  "traverse",
2479
2491
  "triggerRef",
@@ -2503,6 +2515,12 @@ const INTERNAL_RUNTIME_VALUE_EXPORTS = /* @__PURE__ */ new Set([
2503
2515
  "useTemplateRef",
2504
2516
  "useUpdatePerformanceListener",
2505
2517
  "version",
2518
+ "vModelCheckbox",
2519
+ "vModelRadio",
2520
+ "vModelSelect",
2521
+ "vModelText",
2522
+ "vShow",
2523
+ "withDirectives",
2506
2524
  "waitForLayoutHost",
2507
2525
  "watch",
2508
2526
  "watchEffect",
@@ -2536,13 +2554,35 @@ function splitWevuNamedImportsToInternalRuntime(path, program, state) {
2536
2554
  }
2537
2555
  function createImportVisitors(program, state) {
2538
2556
  return { ImportDeclaration(path) {
2557
+ if (path.node.source.value === "@vue/babel-helper-vue-transform-on") {
2558
+ const defaultImport = path.node.specifiers.find((specifier) => t.isImportDefaultSpecifier(specifier));
2559
+ if (defaultImport) {
2560
+ ensureRuntimeImport(program, "transformOn", defaultImport.local.name);
2561
+ state.transformed = true;
2562
+ path.remove();
2563
+ return;
2564
+ }
2565
+ }
2539
2566
  if (path.node.source.value === "vue") {
2540
2567
  const movedVueRuntimeAPIs = /* @__PURE__ */ new Set([
2568
+ "createTextVNode",
2569
+ "createVNode",
2570
+ "Fragment",
2571
+ "isVNode",
2572
+ "mergeProps",
2573
+ "resolveComponent",
2574
+ "resolveDirective",
2541
2575
  "useAttrs",
2542
2576
  "useSlots",
2543
2577
  "useModel",
2544
2578
  "mergeModels",
2545
- "useTemplateRef"
2579
+ "useTemplateRef",
2580
+ "vModelCheckbox",
2581
+ "vModelRadio",
2582
+ "vModelSelect",
2583
+ "vModelText",
2584
+ "vShow",
2585
+ "withDirectives"
2546
2586
  ]);
2547
2587
  const movedSpecifiers = [];
2548
2588
  const remaining = path.node.specifiers.filter((specifier) => {
@@ -2615,7 +2655,7 @@ function isStaticObjectKeyMatch(key, expected) {
2615
2655
  if (t.isStringLiteral(key)) return key.value === expected;
2616
2656
  return false;
2617
2657
  }
2618
- function getObjectPropertyByKey$1(node, key) {
2658
+ function getObjectPropertyByKey$2(node, key) {
2619
2659
  for (const prop of node.properties) {
2620
2660
  if (!t.isObjectProperty(prop) || prop.computed) continue;
2621
2661
  if (isStaticObjectKeyMatch(prop.key, key)) return prop;
@@ -3077,7 +3117,7 @@ function injectClassStyleComputed(optionsObject, bindings, propsAliases, warn) {
3077
3117
  resolvePropValue: t.identifier("__wevuResolvePropValue")
3078
3118
  }, propsAliases);
3079
3119
  if (!entries.length) return false;
3080
- const computedProp = getObjectPropertyByKey$1(optionsObject, "computed");
3120
+ const computedProp = getObjectPropertyByKey$2(optionsObject, "computed");
3081
3121
  if (!computedProp) {
3082
3122
  optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey$1("computed"), t.objectExpression(entries)));
3083
3123
  return true;
@@ -3107,7 +3147,7 @@ function mergePlainDefaultsIntoObjectExpression(target, defaults) {
3107
3147
  let changed = false;
3108
3148
  const injectedProps = [];
3109
3149
  for (const [key, value] of entries) {
3110
- if (getObjectPropertyByKey$1(target, key)) continue;
3150
+ if (getObjectPropertyByKey$2(target, key)) continue;
3111
3151
  injectedProps.push(t.objectProperty(createStaticObjectKey$1(key), t.valueToNode(value)));
3112
3152
  }
3113
3153
  if (!injectedProps.length) return false;
@@ -3118,11 +3158,11 @@ function mergePlainDefaultsIntoObjectExpression(target, defaults) {
3118
3158
  function mergeNestedDefaults(optionsObject, key, defaultsValue) {
3119
3159
  if (!isPlainRecord(defaultsValue)) {
3120
3160
  if (defaultsValue === void 0) return false;
3121
- if (getObjectPropertyByKey$1(optionsObject, key)) return false;
3161
+ if (getObjectPropertyByKey$2(optionsObject, key)) return false;
3122
3162
  optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey$1(key), t.valueToNode(defaultsValue)));
3123
3163
  return true;
3124
3164
  }
3125
- const existing = getObjectPropertyByKey$1(optionsObject, key);
3165
+ const existing = getObjectPropertyByKey$2(optionsObject, key);
3126
3166
  if (!existing) {
3127
3167
  optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey$1(key), t.valueToNode(defaultsValue)));
3128
3168
  return true;
@@ -3145,21 +3185,21 @@ function applyWevuDefaultsToOptionsObject(optionsObject, defaults) {
3145
3185
  changed = mergeNestedDefaults(optionsObject, key, value) || changed;
3146
3186
  continue;
3147
3187
  }
3148
- if (value === void 0 || getObjectPropertyByKey$1(optionsObject, key)) continue;
3188
+ if (value === void 0 || getObjectPropertyByKey$2(optionsObject, key)) continue;
3149
3189
  optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey$1(key), t.valueToNode(value)));
3150
3190
  changed = true;
3151
3191
  }
3152
3192
  return changed;
3153
3193
  }
3154
3194
  function ensureNestedOptionValue(optionsObject, key, nestedKey, value) {
3155
- const existing = getObjectPropertyByKey$1(optionsObject, key);
3195
+ const existing = getObjectPropertyByKey$2(optionsObject, key);
3156
3196
  if (!existing) {
3157
3197
  const nested = t.objectExpression([t.objectProperty(createStaticObjectKey$1(nestedKey), t.valueToNode(value))]);
3158
3198
  optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey$1(key), nested));
3159
3199
  return true;
3160
3200
  }
3161
3201
  if (t.isObjectExpression(existing.value)) {
3162
- if (getObjectPropertyByKey$1(existing.value, nestedKey)) return false;
3202
+ if (getObjectPropertyByKey$2(existing.value, nestedKey)) return false;
3163
3203
  existing.value.properties.splice(0, 0, t.objectProperty(createStaticObjectKey$1(nestedKey), t.valueToNode(value)));
3164
3204
  return true;
3165
3205
  }
@@ -3374,7 +3414,7 @@ function buildMethodsMergeFromSpreadSources(componentExpr, inlineMapExpr) {
3374
3414
  function injectInlineExpressions(componentExpr, inlineExpressions) {
3375
3415
  if (!inlineExpressions.length) return false;
3376
3416
  const inlineMapExpr = buildInlineMapExpression(inlineExpressions);
3377
- const methodsProp = getObjectPropertyByKey$1(componentExpr, "methods");
3417
+ const methodsProp = getObjectPropertyByKey$2(componentExpr, "methods");
3378
3418
  if (!methodsProp) {
3379
3419
  const mergedMethods = buildMethodsMergeFromSpreadSources(componentExpr, inlineMapExpr);
3380
3420
  if (mergedMethods) {
@@ -3385,7 +3425,7 @@ function injectInlineExpressions(componentExpr, inlineExpressions) {
3385
3425
  return true;
3386
3426
  }
3387
3427
  if (!t.isObjectExpression(methodsProp.value)) return false;
3388
- const mapProp = getObjectPropertyByKey$1(methodsProp.value, WEVU_INLINE_MAP_KEY);
3428
+ const mapProp = getObjectPropertyByKey$2(methodsProp.value, WEVU_INLINE_MAP_KEY);
3389
3429
  if (!mapProp) {
3390
3430
  methodsProp.value.properties.push(t.objectProperty(createStaticObjectKey$1(WEVU_INLINE_MAP_KEY), inlineMapExpr));
3391
3431
  return true;
@@ -3411,7 +3451,7 @@ function injectLayoutHosts(optionsObject, bindings, warn) {
3411
3451
  const entries = bindings.map((binding) => buildLayoutHostEntry(binding));
3412
3452
  const hostsArray = t.arrayExpression(entries);
3413
3453
  const key = createStaticObjectKey$1(WEVU_LAYOUT_HOSTS_KEY);
3414
- const existing = getObjectPropertyByKey$1(optionsObject, WEVU_LAYOUT_HOSTS_KEY);
3454
+ const existing = getObjectPropertyByKey$2(optionsObject, WEVU_LAYOUT_HOSTS_KEY);
3415
3455
  if (!existing) {
3416
3456
  optionsObject.properties.push(t.objectProperty(key, hostsArray));
3417
3457
  return true;
@@ -3434,14 +3474,14 @@ function injectPropsAliases(optionsObject, propsAliases) {
3434
3474
  return t.objectProperty(createStaticObjectKey$1(alias), t.stringLiteral(propName));
3435
3475
  });
3436
3476
  if (!entries.length) return false;
3437
- if (getObjectPropertyByKey$1(optionsObject, WEVU_PROPS_ALIASES_KEY)) return false;
3477
+ if (getObjectPropertyByKey$2(optionsObject, WEVU_PROPS_ALIASES_KEY)) return false;
3438
3478
  optionsObject.properties.push(t.objectProperty(createStaticObjectKey$1(WEVU_PROPS_ALIASES_KEY), t.objectExpression(entries)));
3439
3479
  return true;
3440
3480
  }
3441
3481
  function injectPropsDerivedKeys(optionsObject, propsDerivedKeys) {
3442
3482
  const keys = [...new Set(propsDerivedKeys ?? [])].filter(Boolean);
3443
3483
  if (!keys.length) return false;
3444
- if (getObjectPropertyByKey$1(optionsObject, WEVU_PROPS_DERIVED_KEYS_KEY)) return false;
3484
+ if (getObjectPropertyByKey$2(optionsObject, WEVU_PROPS_DERIVED_KEYS_KEY)) return false;
3445
3485
  optionsObject.properties.push(t.objectProperty(createStaticObjectKey$1(WEVU_PROPS_DERIVED_KEYS_KEY), t.arrayExpression(keys.map((key) => t.stringLiteral(key)))));
3446
3486
  return true;
3447
3487
  }
@@ -3525,7 +3565,7 @@ function resolvePropertyName(node) {
3525
3565
  return null;
3526
3566
  }
3527
3567
  function injectSetupInitialData(componentOptionsObject) {
3528
- if (getObjectPropertyByKey$1(componentOptionsObject, "data")) return false;
3568
+ if (getObjectPropertyByKey$2(componentOptionsObject, "data")) return false;
3529
3569
  const setupFn = resolveSetupFunction(componentOptionsObject);
3530
3570
  if (!setupFn || !t.isBlockStatement(setupFn.body)) return false;
3531
3571
  const initializers = collectSetupInitializers(setupFn.body);
@@ -3567,7 +3607,7 @@ function injectTemplateRefs(optionsObject, bindings, warn) {
3567
3607
  const entries = bindings.map((binding) => buildTemplateRefEntry(binding));
3568
3608
  const refsArray = t.arrayExpression(entries);
3569
3609
  const key = createStaticObjectKey$1(WEVU_TEMPLATE_REFS_KEY);
3570
- const existing = getObjectPropertyByKey$1(optionsObject, WEVU_TEMPLATE_REFS_KEY);
3610
+ const existing = getObjectPropertyByKey$2(optionsObject, WEVU_TEMPLATE_REFS_KEY);
3571
3611
  if (!existing) {
3572
3612
  optionsObject.properties.push(t.objectProperty(key, refsArray));
3573
3613
  return true;
@@ -3612,7 +3652,7 @@ function createScopedSlotHostProperties() {
3612
3652
  ];
3613
3653
  }
3614
3654
  function injectScopedSlotHostProperties(componentOptionsObject) {
3615
- const propertiesProp = getObjectPropertyByKey$1(componentOptionsObject, "properties");
3655
+ const propertiesProp = getObjectPropertyByKey$2(componentOptionsObject, "properties");
3616
3656
  if (!propertiesProp) {
3617
3657
  componentOptionsObject.properties.splice(0, 0, t.objectProperty(t.identifier("properties"), t.objectExpression(createScopedSlotHostProperties())));
3618
3658
  return true;
@@ -3621,7 +3661,7 @@ function injectScopedSlotHostProperties(componentOptionsObject) {
3621
3661
  let changed = false;
3622
3662
  for (const prop of createScopedSlotHostProperties().reverse()) {
3623
3663
  const key = t.isIdentifier(prop.key) ? prop.key.name : void 0;
3624
- if (!key || getObjectPropertyByKey$1(propertiesProp.value, key)) continue;
3664
+ if (!key || getObjectPropertyByKey$2(propertiesProp.value, key)) continue;
3625
3665
  propertiesProp.value.properties.unshift(prop);
3626
3666
  changed = true;
3627
3667
  }
@@ -3645,7 +3685,7 @@ function shouldRelaxStructuredPropType(node) {
3645
3685
  });
3646
3686
  }
3647
3687
  function relaxStructuredTypeOnlyProps(componentOptionsObject) {
3648
- const propsProp = getObjectPropertyByKey$1(componentOptionsObject, "props");
3688
+ const propsProp = getObjectPropertyByKey$2(componentOptionsObject, "props");
3649
3689
  if (!propsProp || !t.isExpression(propsProp.value)) return false;
3650
3690
  const propsValue = unwrapTypeLikeExpression(propsProp.value);
3651
3691
  if (!t.isObjectExpression(propsValue)) return false;
@@ -3654,7 +3694,7 @@ function relaxStructuredTypeOnlyProps(componentOptionsObject) {
3654
3694
  if (!t.isObjectProperty(prop) || prop.computed || !t.isExpression(prop.value)) continue;
3655
3695
  const definition = unwrapTypeLikeExpression(prop.value);
3656
3696
  if (!t.isObjectExpression(definition)) continue;
3657
- const typeProp = getObjectPropertyByKey$1(definition, "type");
3697
+ const typeProp = getObjectPropertyByKey$2(definition, "type");
3658
3698
  if (!typeProp || !t.isExpression(typeProp.value)) continue;
3659
3699
  if (!shouldRelaxStructuredPropType(typeProp.value)) continue;
3660
3700
  typeProp.value = t.nullLiteral();
@@ -3954,7 +3994,8 @@ function rewriteVueSlotsExpression(ast) {
3954
3994
  function normalizeWxmlExpression(exp) {
3955
3995
  const hasTypeScriptSyntax = /\s(?:as|satisfies)\s/.test(exp) || /[\w$)\]]!(?=[.[\s,);:?]|$)/.test(exp) || /^\s*<[^>]+>/.test(exp);
3956
3996
  const needsVueSlotsRewrite = exp.includes("$slots");
3957
- if (!exp.includes("`") && !exp.includes("??") && !exp.includes("?.") && !hasTypeScriptSyntax && !needsVueSlotsRewrite) return exp;
3997
+ const needsThisRewrite = /\bthis\./.test(exp);
3998
+ if (!exp.includes("`") && !exp.includes("??") && !exp.includes("?.") && !hasTypeScriptSyntax && !needsVueSlotsRewrite && !needsThisRewrite) return exp;
3958
3999
  try {
3959
4000
  const ast = parse$3(`(${exp})`, {
3960
4001
  sourceType: "module",
@@ -3964,6 +4005,12 @@ function normalizeWxmlExpression(exp) {
3964
4005
  if (!stmt || !("expression" in stmt)) return exp;
3965
4006
  if (needsVueSlotsRewrite) rewriteVueSlotsExpression(ast);
3966
4007
  traverse(ast, {
4008
+ MemberExpression: { exit(path) {
4009
+ const node = path.node;
4010
+ if (!t.isThisExpression(node.object) || node.computed || !t.isIdentifier(node.property)) return;
4011
+ path.replaceWith(t.identifier(node.property.name));
4012
+ path.skip();
4013
+ } },
3967
4014
  TSAsExpression(path) {
3968
4015
  path.replaceWith(path.node.expression);
3969
4016
  },
@@ -4012,6 +4059,13 @@ function normalizeWxmlExpression(exp) {
4012
4059
  //#region src/plugins/jsx/compileJsx/ast.ts
4013
4060
  const ESCAPED_TEXT_RE = /[&<>]/g;
4014
4061
  const ESCAPED_ATTR_RE = /[&"<>]/g;
4062
+ const WXML_EXPRESSION_GENERATE_OPTIONS = {
4063
+ compact: true,
4064
+ jsescOption: {
4065
+ quotes: "single",
4066
+ minimal: true
4067
+ }
4068
+ };
4015
4069
  const ESCAPED_TEXT_MAP = {
4016
4070
  "&": "&amp;",
4017
4071
  "<": "&lt;",
@@ -4034,7 +4088,11 @@ function normalizeJsxText(value) {
4034
4088
  return value.replace(WHITESPACE_RE, " ");
4035
4089
  }
4036
4090
  function printExpression(exp) {
4037
- return generate(exp).code;
4091
+ const normalized = t.cloneNode(exp, true);
4092
+ t.traverseFast(normalized, (node) => {
4093
+ if (t.isStringLiteral(node)) node.extra = void 0;
4094
+ });
4095
+ return generate(normalized, WXML_EXPRESSION_GENERATE_OPTIONS).code;
4038
4096
  }
4039
4097
  function unwrapTsExpression$2(exp) {
4040
4098
  return unwrapTypeScriptExpression(exp);
@@ -4087,8 +4145,70 @@ function registerInlineExpression$1(exp, context) {
4087
4145
  function toJsxTagName(name, context) {
4088
4146
  if (t.isJSXIdentifier(name)) return name.name;
4089
4147
  if (t.isJSXNamespacedName(name)) return `${name.namespace.name}:${name.name.name}`;
4090
- context.warnings.push("暂不支持 JSX 成员标签(如 <Foo.Bar />),已回退为 <view />。");
4091
- return "view";
4148
+ context.warnings.push("JSX 成员标签(如 <Foo.Bar />)无法映射为小程序 WXML 组件标签,已生成 dynamic island。");
4149
+ return "block";
4150
+ }
4151
+ //#endregion
4152
+ //#region src/plugins/jsx/compileJsx/islandScript.ts
4153
+ function parseIslandExpression(expression) {
4154
+ const statement = parse$3(`const __wevuIsland = (${expression})`, BABEL_TS_MODULE_PARSER_OPTIONS).program.body[0];
4155
+ if (!t.isVariableDeclaration(statement)) return;
4156
+ const init = statement.declarations[0]?.init;
4157
+ return init && t.isExpression(init) ? init : void 0;
4158
+ }
4159
+ function injectIslandComputed(optionsObject, islands) {
4160
+ const entries = islands.flatMap((island) => {
4161
+ const expression = parseIslandExpression(island.expression);
4162
+ if (!expression) return [];
4163
+ const normalized = t.callExpression(t.memberExpression(t.identifier("__wevuNormalizeJsxIsland"), t.identifier("call")), [
4164
+ t.thisExpression(),
4165
+ expression,
4166
+ t.stringLiteral(island.id),
4167
+ t.objectExpression([t.objectProperty(t.identifier("normalizeClass"), t.identifier("__wevuNormalizeClass")), t.objectProperty(t.identifier("normalizeStyle"), t.identifier("__wevuNormalizeStyle"))])
4168
+ ]);
4169
+ return [t.objectProperty(t.stringLiteral(island.id), normalized)];
4170
+ });
4171
+ if (!entries.length) return false;
4172
+ const islandGetter = t.objectMethod("method", t.identifier(WEVU_JSX_ISLAND_DATA_KEY), [], t.blockStatement([t.returnStatement(t.objectExpression(entries))]));
4173
+ const computed = optionsObject.properties.find((property) => (t.isObjectProperty(property) || t.isObjectMethod(property)) && toStaticObjectKey(property.key) === "computed");
4174
+ if (computed && t.isObjectProperty(computed) && t.isObjectExpression(computed.value)) computed.value.properties.push(islandGetter);
4175
+ else optionsObject.properties.unshift(t.objectProperty(t.identifier("computed"), t.objectExpression([islandGetter])));
4176
+ return true;
4177
+ }
4178
+ function injectDynamicIslandRuntime(source, islands) {
4179
+ if (!islands?.length) return source;
4180
+ const ast = parse$3(source, BABEL_TS_MODULE_PARSER_OPTIONS);
4181
+ const defineComponentAliases = /* @__PURE__ */ new Set(["defineComponent", "_defineComponent"]);
4182
+ const declarations = /* @__PURE__ */ new Map();
4183
+ let injected = false;
4184
+ traverse(ast, {
4185
+ ImportDeclaration(path) {
4186
+ if (path.node.source.value !== "wevu" && path.node.source.value !== "vue") return;
4187
+ for (const specifier of path.node.specifiers) if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported, { name: "defineComponent" })) defineComponentAliases.add(specifier.local.name);
4188
+ },
4189
+ VariableDeclarator(path) {
4190
+ if (!t.isIdentifier(path.node.id) || !path.node.init) return;
4191
+ if (t.isObjectExpression(path.node.init)) declarations.set(path.node.id.name, path.node.init);
4192
+ if (t.isCallExpression(path.node.init) && t.isIdentifier(path.node.init.callee) && defineComponentAliases.has(path.node.init.callee.name)) {
4193
+ const first = path.node.init.arguments[0];
4194
+ if (t.isObjectExpression(first)) declarations.set(path.node.id.name, first);
4195
+ }
4196
+ },
4197
+ ExportDefaultDeclaration(path) {
4198
+ const declaration = path.node.declaration;
4199
+ let optionsObject;
4200
+ if (t.isObjectExpression(declaration)) optionsObject = declaration;
4201
+ else if (t.isCallExpression(declaration) && t.isIdentifier(declaration.callee) && defineComponentAliases.has(declaration.callee.name)) {
4202
+ const first = declaration.arguments[0];
4203
+ if (t.isObjectExpression(first)) optionsObject = first;
4204
+ } else if (t.isIdentifier(declaration)) optionsObject = declarations.get(declaration.name);
4205
+ if (optionsObject) injected = injectIslandComputed(optionsObject, islands) || injected;
4206
+ }
4207
+ });
4208
+ if (!injected) return source;
4209
+ ast.program.body.unshift(t.importDeclaration([t.importSpecifier(t.identifier("__wevuNormalizeJsxIsland"), t.identifier("normalizeJsxIsland"))], t.stringLiteral("wevu")));
4210
+ ast.program.body.unshift(t.importDeclaration([t.importSpecifier(t.identifier("__wevuNormalizeClass"), t.identifier("normalizeClass")), t.importSpecifier(t.identifier("__wevuNormalizeStyle"), t.identifier("normalizeStyle"))], t.stringLiteral("wevu/internal-template")));
4211
+ return generate(ast).code;
4092
4212
  }
4093
4213
  //#endregion
4094
4214
  //#region src/plugins/jsx/compileJsx/script.ts
@@ -4102,6 +4222,39 @@ function removeRenderOptionFromObjectExpression(node) {
4102
4222
  if (removed) node.properties = nextProps;
4103
4223
  return removed;
4104
4224
  }
4225
+ function resolveReturnedJsxClosureExpression(expression) {
4226
+ if (!t.isArrowFunctionExpression(expression) && !t.isFunctionExpression(expression)) return;
4227
+ if (t.isJSXElement(expression.body) || t.isJSXFragment(expression.body)) return expression.body;
4228
+ if (!t.isBlockStatement(expression.body)) return;
4229
+ const returned = expression.body.body.find((statement) => t.isReturnStatement(statement) && statement.argument);
4230
+ if (!returned || !t.isReturnStatement(returned)) return;
4231
+ return returned.argument && (t.isJSXElement(returned.argument) || t.isJSXFragment(returned.argument)) ? returned.argument : void 0;
4232
+ }
4233
+ function rewriteSetupRenderClosure(node) {
4234
+ const setup = node.properties.find((property) => {
4235
+ if (!t.isObjectMethod(property) && !t.isObjectProperty(property)) return false;
4236
+ return toStaticObjectKey(property.key) === "setup";
4237
+ });
4238
+ if (!setup || !t.isObjectMethod(setup)) return false;
4239
+ const localNames = /* @__PURE__ */ new Set();
4240
+ for (const param of setup.params) if (t.isIdentifier(param)) localNames.add(param.name);
4241
+ for (const statement of setup.body.body) if (t.isVariableDeclaration(statement)) {
4242
+ for (const declaration of statement.declarations) if (t.isIdentifier(declaration.id)) localNames.add(declaration.id.name);
4243
+ } else if (t.isFunctionDeclaration(statement) && statement.id) localNames.add(statement.id.name);
4244
+ for (const statement of setup.body.body) {
4245
+ if (!t.isReturnStatement(statement) || !statement.argument || !t.isExpression(statement.argument)) continue;
4246
+ const jsx = resolveReturnedJsxClosureExpression(statement.argument);
4247
+ if (!jsx) continue;
4248
+ const captures = /* @__PURE__ */ new Set();
4249
+ const file = t.file(t.program([t.expressionStatement(t.cloneNode(jsx, true))]));
4250
+ traverse(file, { ReferencedIdentifier(path) {
4251
+ if (localNames.has(path.node.name)) captures.add(path.node.name);
4252
+ } });
4253
+ statement.argument = t.objectExpression([...captures].map((name) => t.objectProperty(t.identifier(name), t.identifier(name), false, true)));
4254
+ return true;
4255
+ }
4256
+ return false;
4257
+ }
4105
4258
  function stripRenderOptionFromScript(source, filename, warn) {
4106
4259
  let ast;
4107
4260
  try {
@@ -4111,6 +4264,7 @@ function stripRenderOptionFromScript(source, filename, warn) {
4111
4264
  }
4112
4265
  const defineComponentAliases = /* @__PURE__ */ new Set(["defineComponent", "_defineComponent"]);
4113
4266
  const defineComponentDecls = /* @__PURE__ */ new Map();
4267
+ let hasDefaultExport = false;
4114
4268
  let removedRender = false;
4115
4269
  let removedJsonMacroImport = false;
4116
4270
  traverse(ast, {
@@ -4145,26 +4299,27 @@ function stripRenderOptionFromScript(source, filename, warn) {
4145
4299
  if (t.isObjectExpression(first)) defineComponentDecls.set(path.node.id.name, first);
4146
4300
  },
4147
4301
  ExportDefaultDeclaration(path) {
4302
+ hasDefaultExport = true;
4148
4303
  const declaration = path.node.declaration;
4149
4304
  if (t.isDeclaration(declaration)) return;
4150
4305
  if (t.isObjectExpression(declaration)) {
4151
- removedRender = removeRenderOptionFromObjectExpression(declaration) || removedRender;
4306
+ removedRender = removeRenderOptionFromObjectExpression(declaration) || rewriteSetupRenderClosure(declaration) || removedRender;
4152
4307
  return;
4153
4308
  }
4154
4309
  if (t.isCallExpression(declaration)) {
4155
4310
  const callee = declaration.callee;
4156
4311
  if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
4157
4312
  const first = declaration.arguments[0];
4158
- if (t.isObjectExpression(first)) removedRender = removeRenderOptionFromObjectExpression(first) || removedRender;
4313
+ if (t.isObjectExpression(first)) removedRender = removeRenderOptionFromObjectExpression(first) || rewriteSetupRenderClosure(first) || removedRender;
4159
4314
  return;
4160
4315
  }
4161
4316
  if (t.isIdentifier(declaration)) {
4162
4317
  const target = defineComponentDecls.get(declaration.name);
4163
- if (target) removedRender = removeRenderOptionFromObjectExpression(target) || removedRender;
4318
+ if (target) removedRender = removeRenderOptionFromObjectExpression(target) || rewriteSetupRenderClosure(target) || removedRender;
4164
4319
  }
4165
4320
  }
4166
4321
  });
4167
- if (!removedRender) warn?.(`[JSX 编译] 未在 ${filename} 中移除 render 选项,输出脚本可能包含 JSX。`);
4322
+ if (hasDefaultExport && !removedRender) warn?.(`[JSX 编译] 未在 ${filename} 中移除 render 选项,输出脚本可能包含 JSX。`);
4168
4323
  if (!removedRender && !removedJsonMacroImport) return source;
4169
4324
  return generate(ast).code;
4170
4325
  }
@@ -4662,15 +4817,26 @@ function resolveRenderExpression(componentExpr, context) {
4662
4817
  return null;
4663
4818
  }
4664
4819
  const renderExpression = resolveRenderExpressionFromComponentOptions(componentExpr);
4665
- if (!renderExpression) {
4666
- if (!getRenderPropertyFromComponentOptions(componentExpr)) {
4667
- context.warnings.push("未找到 render(),请在默认导出组件中声明 render 函数。");
4668
- return null;
4669
- }
4820
+ if (renderExpression) return renderExpression;
4821
+ if (getRenderPropertyFromComponentOptions(componentExpr)) {
4670
4822
  context.warnings.push("render 不是可执行函数。");
4671
4823
  return null;
4672
4824
  }
4673
- return renderExpression;
4825
+ const setup = getObjectPropertyByKey(componentExpr, "setup");
4826
+ if (setup && (t.isObjectMethod(setup) || t.isObjectProperty(setup))) {
4827
+ const body = t.isObjectMethod(setup) ? setup.body : setup.value;
4828
+ if (t.isBlockStatement(body)) for (const statement of body.body) {
4829
+ if (!t.isReturnStatement(statement) || !statement.argument) continue;
4830
+ if (t.isArrowFunctionExpression(statement.argument) || t.isFunctionExpression(statement.argument)) {
4831
+ const renderBody = statement.argument.body;
4832
+ if (t.isExpression(renderBody)) return renderBody;
4833
+ const returned = renderBody.body.find((item) => t.isReturnStatement(item) && item.argument);
4834
+ if (returned && t.isReturnStatement(returned) && returned.argument) return returned.argument;
4835
+ }
4836
+ }
4837
+ }
4838
+ context.warnings.push("未找到 render() 或 setup() 返回的 render closure。");
4839
+ return null;
4674
4840
  }
4675
4841
  function isCollectableJsxTemplateTag(tag) {
4676
4842
  if (!tag) return false;
@@ -4703,12 +4869,154 @@ function analyzeJsxAst(ast, context) {
4703
4869
  };
4704
4870
  }
4705
4871
  //#endregion
4872
+ //#region src/plugins/jsx/compileJsx/moduleResolver.ts
4873
+ const EXTENSIONS = [
4874
+ "",
4875
+ ".tsx",
4876
+ ".jsx",
4877
+ ".ts",
4878
+ ".js"
4879
+ ];
4880
+ function resolveFile(source, importer) {
4881
+ if (!source.startsWith(".")) return;
4882
+ const base = path$1.resolve(path$1.dirname(importer), source);
4883
+ for (const extension of EXTENSIONS) {
4884
+ const candidate = `${base}${extension}`;
4885
+ try {
4886
+ if (readFileSync(candidate, "utf8") !== void 0) return candidate;
4887
+ } catch {
4888
+ continue;
4889
+ }
4890
+ }
4891
+ for (const extension of EXTENSIONS) {
4892
+ const candidate = path$1.join(base, `index${extension}`);
4893
+ try {
4894
+ if (readFileSync(candidate, "utf8") !== void 0) return candidate;
4895
+ } catch {
4896
+ continue;
4897
+ }
4898
+ }
4899
+ }
4900
+ function expressionFromDeclaration(node) {
4901
+ if (!node) return;
4902
+ if (t.isJSXElement(node) || t.isJSXFragment(node)) return {
4903
+ expression: node,
4904
+ params: []
4905
+ };
4906
+ if (t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)) {
4907
+ let body;
4908
+ if (t.isBlockStatement(node.body)) {
4909
+ const returned = node.body.body.find((statement) => t.isReturnStatement(statement) && !!statement.argument);
4910
+ if (returned && t.isReturnStatement(returned) && returned.argument && t.isExpression(returned.argument)) body = returned.argument;
4911
+ } else body = node.body;
4912
+ if (body) return {
4913
+ expression: body,
4914
+ params: node.params.filter(t.isIdentifier).map((param) => param.name)
4915
+ };
4916
+ }
4917
+ if (t.isFunctionDeclaration(node)) {
4918
+ const body = node.body.body.find((statement) => t.isReturnStatement(statement) && !!statement.argument);
4919
+ if (body && t.isReturnStatement(body) && body.argument && t.isExpression(body.argument)) return {
4920
+ expression: body.argument,
4921
+ params: node.params.filter(t.isIdentifier).map((param) => param.name)
4922
+ };
4923
+ }
4924
+ }
4925
+ function collectExports(ast) {
4926
+ const locals = /* @__PURE__ */ new Map();
4927
+ const exports = /* @__PURE__ */ new Map();
4928
+ const reexports = /* @__PURE__ */ new Map();
4929
+ for (const statement of ast.program.body) {
4930
+ if (t.isVariableDeclaration(statement)) {
4931
+ for (const declaration of statement.declarations) if (t.isIdentifier(declaration.id) && declaration.init && t.isExpression(declaration.init)) locals.set(declaration.id.name, declaration.init);
4932
+ }
4933
+ if (t.isFunctionDeclaration(statement) && statement.id) locals.set(statement.id.name, statement);
4934
+ if (t.isExportNamedDeclaration(statement)) {
4935
+ if (statement.declaration) {
4936
+ if (t.isVariableDeclaration(statement.declaration)) {
4937
+ for (const declaration of statement.declaration.declarations) if (t.isIdentifier(declaration.id) && declaration.init && t.isExpression(declaration.init)) {
4938
+ locals.set(declaration.id.name, declaration.init);
4939
+ exports.set(declaration.id.name, declaration.id.name);
4940
+ }
4941
+ }
4942
+ if (t.isFunctionDeclaration(statement.declaration) && statement.declaration.id) {
4943
+ locals.set(statement.declaration.id.name, statement.declaration);
4944
+ exports.set(statement.declaration.id.name, statement.declaration.id.name);
4945
+ }
4946
+ }
4947
+ for (const specifier of statement.specifiers) if (t.isExportSpecifier(specifier) && t.isIdentifier(specifier.local) && t.isIdentifier(specifier.exported)) {
4948
+ exports.set(specifier.exported.name, specifier.local.name);
4949
+ if (statement.source) reexports.set(specifier.exported.name, {
4950
+ source: statement.source.value,
4951
+ importedName: specifier.local.name
4952
+ });
4953
+ }
4954
+ }
4955
+ if (t.isExportDefaultDeclaration(statement) && statement.declaration) {
4956
+ if (t.isFunctionDeclaration(statement.declaration) && statement.declaration.id) locals.set("default", statement.declaration);
4957
+ else if (t.isExpression(statement.declaration)) locals.set("default", statement.declaration);
4958
+ }
4959
+ }
4960
+ return {
4961
+ locals,
4962
+ exports,
4963
+ reexports
4964
+ };
4965
+ }
4966
+ function createJsxModuleResolver(warn) {
4967
+ const cache = /* @__PURE__ */ new Map();
4968
+ const active = /* @__PURE__ */ new Set();
4969
+ const dependencies = /* @__PURE__ */ new Set();
4970
+ function read(filename) {
4971
+ const code = readFileSync(filename, "utf8");
4972
+ const cached = cache.get(filename);
4973
+ if (cached?.code === code) return cached.exports;
4974
+ const collected = collectExports(parse$3(code, BABEL_TS_MODULE_PARSER_OPTIONS));
4975
+ cache.set(filename, {
4976
+ code,
4977
+ exports: collected
4978
+ });
4979
+ return collected;
4980
+ }
4981
+ function resolveExport(filename, localName) {
4982
+ if (active.has(filename)) {
4983
+ warn?.(`[JSX 编译] 检测到跨文件 JSX 循环引用:${filename}`);
4984
+ return;
4985
+ }
4986
+ active.add(filename);
4987
+ try {
4988
+ const { locals, reexports } = read(filename);
4989
+ const direct = expressionFromDeclaration(locals.get(localName) ?? null);
4990
+ if (direct) return direct;
4991
+ const forwarded = reexports.get(localName);
4992
+ if (!forwarded) return;
4993
+ const target = resolveFile(forwarded.source, filename);
4994
+ if (target) dependencies.add(target);
4995
+ return target ? resolveExport(target, forwarded.importedName) : void 0;
4996
+ } finally {
4997
+ active.delete(filename);
4998
+ }
4999
+ }
5000
+ function resolveImport(filename, source, importedName) {
5001
+ const target = resolveFile(source, filename);
5002
+ if (!target) return;
5003
+ dependencies.add(target);
5004
+ return resolveExport(target, importedName === "default" ? "default" : importedName);
5005
+ }
5006
+ return {
5007
+ getDependencies: () => [...dependencies],
5008
+ resolveExport,
5009
+ resolveImport
5010
+ };
5011
+ }
5012
+ //#endregion
4706
5013
  //#region src/plugins/jsx/compileJsx/attributes.ts
4707
5014
  const ON_EVENT_RE = /^on[A-Z]/;
4708
5015
  const CATCH_EVENT_RE = /^catch[A-Z]/;
4709
5016
  const CAPTURE_BIND_EVENT_RE = /^captureBind[A-Z]/;
4710
5017
  const CAPTURE_CATCH_EVENT_RE = /^captureCatch[A-Z]/;
4711
5018
  const MUT_BIND_EVENT_RE = /^mutBind[A-Z]/;
5019
+ const UPPERCASE_STYLE_RE = /[A-Z]/g;
4712
5020
  function isEventBinding(name) {
4713
5021
  return ON_EVENT_RE.test(name) || CATCH_EVENT_RE.test(name) || CAPTURE_BIND_EVENT_RE.test(name) || CAPTURE_CATCH_EVENT_RE.test(name) || MUT_BIND_EVENT_RE.test(name);
4714
5022
  }
@@ -4773,35 +5081,248 @@ function compileNormalAttribute(name, value, context) {
4773
5081
  if (!exp) return null;
4774
5082
  if (t.isStringLiteral(exp)) return `${normalizedName}="${escapeAttr(exp.value)}"`;
4775
5083
  if (t.isBooleanLiteral(exp)) return `${normalizedName}="${renderMustache$1(String(exp.value), context)}"`;
5084
+ if (normalizedName === "class") {
5085
+ const value = resolveStaticClass(exp);
5086
+ if (value != null) return `class="${escapeAttr(value)}"`;
5087
+ }
5088
+ if (normalizedName === "style") {
5089
+ const value = resolveStaticStyle(exp);
5090
+ if (value != null) return `style="${escapeAttr(value)}"`;
5091
+ }
4776
5092
  return `${normalizedName}="${renderMustache$1(normalizeInterpolationExpression(exp), context)}"`;
4777
5093
  }
5094
+ function compileNamedAttribute(name, value, context) {
5095
+ if (name === "key") return [];
5096
+ if (name === "v-html") {
5097
+ context.warnings.push("小程序不支持 JSX v-html,请使用 rich-text 组件替代。");
5098
+ return [];
5099
+ }
5100
+ if (name === "v-if" || name === "v-show" || name === "v-text" || name === "v-for") return [];
5101
+ if (name === "v-slots" || name === "v-model" || name === "v-models") {
5102
+ context.warnings.push(`JSX ${name} 需要 Wevu runtime 语义,已生成确定性诊断。`);
5103
+ return [];
5104
+ }
5105
+ if (name.startsWith("v-")) {
5106
+ context.warnings.push(`小程序不支持 JSX 自定义指令 ${name},已移除该指令。`);
5107
+ return [];
5108
+ }
5109
+ if (name === "innerHTML" || name.startsWith("domProps")) {
5110
+ context.warnings.push(`小程序不支持 JSX DOM property ${name},已移除该属性。`);
5111
+ return [];
5112
+ }
5113
+ if (isEventBinding(name)) return compileEventAttribute(name, value, context);
5114
+ const normalAttr = compileNormalAttribute(name, value, context);
5115
+ return normalAttr ? [normalAttr] : [];
5116
+ }
4778
5117
  function compileJsxAttributes(attributes, context) {
4779
5118
  const output = [];
4780
5119
  for (const attr of attributes) {
4781
5120
  if (t.isJSXSpreadAttribute(attr)) {
4782
- context.warnings.push("暂不支持 JSX spread attributes,已忽略。");
5121
+ const argument = unwrapTsExpression$2(attr.argument);
5122
+ if (t.isObjectExpression(argument)) for (const property of argument.properties) if (t.isObjectProperty(property) && !property.computed && (t.isIdentifier(property.key) || t.isStringLiteral(property.key))) {
5123
+ const value = property.value;
5124
+ if (t.isExpression(value)) {
5125
+ const name = t.isIdentifier(property.key) ? property.key.name : property.key.value;
5126
+ output.push(...compileNamedAttribute(name, t.jsxExpressionContainer(value), context));
5127
+ }
5128
+ } else context.warnings.push("JSX spread attributes 包含无法静态展开的属性,已保留为 dynamic island。");
5129
+ else context.warnings.push("动态 JSX spread attributes 无法映射为静态 WXML,已生成确定性诊断。");
4783
5130
  continue;
4784
5131
  }
4785
- if (!t.isJSXIdentifier(attr.name)) {
4786
- context.warnings.push("暂不支持 JSX 动态属性名,已忽略。");
5132
+ if (t.isJSXNamespacedName(attr.name)) {
5133
+ const namespace = attr.name.namespace.name;
5134
+ const name = attr.name.name.name;
5135
+ if (namespace.startsWith("v-")) context.warnings.push(`小程序不支持 JSX 自定义指令 ${namespace}:${name},已移除该指令。`);
5136
+ else context.warnings.push(`小程序不支持 JSX 命名属性 ${namespace}:${name},已移除该属性。`);
4787
5137
  continue;
4788
5138
  }
4789
- const name = attr.name.name;
4790
- if (name === "key") continue;
4791
- if (isEventBinding(name)) {
4792
- output.push(...compileEventAttribute(name, attr.value, context));
5139
+ if (!t.isJSXIdentifier(attr.name)) {
5140
+ context.warnings.push("小程序不支持 JSX 动态属性名,已移除该属性。");
4793
5141
  continue;
4794
5142
  }
4795
- const normalAttr = compileNormalAttribute(name, attr.value, context);
4796
- if (normalAttr) output.push(normalAttr);
5143
+ const name = attr.name.name;
5144
+ output.push(...compileNamedAttribute(name, attr.value, context));
4797
5145
  }
4798
5146
  return output;
4799
5147
  }
5148
+ function staticObjectKey(node) {
5149
+ if (t.isIdentifier(node)) return node.name;
5150
+ if (t.isStringLiteral(node)) return node.value;
5151
+ }
5152
+ function resolveStaticClass(exp) {
5153
+ if (t.isStringLiteral(exp) || t.isNumericLiteral(exp)) return String(exp.value);
5154
+ if (t.isArrayExpression(exp)) {
5155
+ const values = exp.elements.map((element) => {
5156
+ if (!element || !t.isExpression(element)) return "";
5157
+ return resolveStaticClass(element);
5158
+ });
5159
+ return values.some((value) => value == null) ? void 0 : values.filter(Boolean).join(" ");
5160
+ }
5161
+ if (t.isObjectExpression(exp)) {
5162
+ const values = [];
5163
+ for (const property of exp.properties) {
5164
+ if (!t.isObjectProperty(property) || property.computed || !t.isBooleanLiteral(property.value)) return;
5165
+ const key = staticObjectKey(property.key);
5166
+ if (key == null) return;
5167
+ if (property.value.value) values.push(key);
5168
+ }
5169
+ return values.join(" ");
5170
+ }
5171
+ }
5172
+ function resolveStaticStyle(exp) {
5173
+ if (t.isStringLiteral(exp)) return exp.value;
5174
+ if (t.isArrayExpression(exp)) {
5175
+ const values = exp.elements.map((element) => {
5176
+ if (!element || !t.isExpression(element)) return "";
5177
+ return resolveStaticStyle(element);
5178
+ });
5179
+ return values.some((value) => value == null) ? void 0 : values.filter(Boolean).join(";");
5180
+ }
5181
+ if (!t.isObjectExpression(exp)) return;
5182
+ const values = [];
5183
+ for (const property of exp.properties) {
5184
+ if (!t.isObjectProperty(property) || property.computed) return;
5185
+ const key = staticObjectKey(property.key)?.replace(UPPERCASE_STYLE_RE, (char) => `-${char.toLowerCase()}`);
5186
+ if (!key || !t.isStringLiteral(property.value) && !t.isNumericLiteral(property.value)) return;
5187
+ values.push(`${key}:${property.value.value}`);
5188
+ }
5189
+ return values.join(";");
5190
+ }
5191
+ function isStaticClassStyleExpression(exp) {
5192
+ return resolveStaticClass(exp) != null || resolveStaticStyle(exp) != null;
5193
+ }
4800
5194
  //#endregion
4801
5195
  //#region src/plugins/jsx/compileJsx/render.ts
5196
+ const DYNAMIC_ISLAND_TEMPLATE_DEPTH = 8;
5197
+ function resolveDynamicIslandTemplateName(depth) {
5198
+ return depth === 0 ? WEVU_JSX_ISLAND_TEMPLATE_NAME : `${WEVU_JSX_ISLAND_TEMPLATE_NAME}_${depth}`;
5199
+ }
4802
5200
  function compileListExpression(exp) {
4803
5201
  return normalizeInterpolationExpression(exp);
4804
5202
  }
5203
+ function registerDynamicIsland(exp, context, reason) {
5204
+ if (context.dynamicIslandMode === "static") {
5205
+ context.warnings.push(`[JSX 编译] static 模式不允许 dynamic island(${reason})。`);
5206
+ return "";
5207
+ }
5208
+ const id = `i${context.dynamicIslandSeed ?? 0}`;
5209
+ context.dynamicIslandSeed = (context.dynamicIslandSeed ?? 0) + 1;
5210
+ const expression = normalizeInterpolationExpression(exp);
5211
+ const captures = /* @__PURE__ */ new Set();
5212
+ const file = t.file(t.program([t.expressionStatement(t.cloneNode(exp, true))]));
5213
+ traverse(file, {
5214
+ ReferencedIdentifier(path) {
5215
+ if (path.scope.hasBinding(path.node.name)) return;
5216
+ if (context.importedBindings?.has(path.node.name)) return;
5217
+ captures.add(path.node.name);
5218
+ },
5219
+ ThisExpression() {
5220
+ captures.add("this");
5221
+ }
5222
+ });
5223
+ context.dynamicIslands?.push({
5224
+ id,
5225
+ expression,
5226
+ reason,
5227
+ captures: [...captures]
5228
+ });
5229
+ return `<template is="${WEVU_JSX_ISLAND_TEMPLATE_NAME}" data-wv-jsx-island="${id}" data="{{node:${WEVU_JSX_ISLAND_DATA_KEY}.${id},islandId:'${id}'}}" />`;
5230
+ }
5231
+ function renderDynamicIslandSupportTemplate(context) {
5232
+ const { directives } = context.platform;
5233
+ const bindTap = context.platform.eventBindingAttr("bind:tap");
5234
+ const bindInput = context.platform.eventBindingAttr("bind:input");
5235
+ const bindChange = context.platform.eventBindingAttr("bind:change");
5236
+ const attrs = `id="{{node.props.id}}" class="{{node.props.class}}" style="{{node.props.style}}" hidden="{{node.props.hidden}}"`;
5237
+ const tapAttrs = `${attrs} data-wv-jsx-handler="{{node.events.tap}}" ${bindTap}="${WEVU_JSX_ISLAND_HANDLER}"`;
5238
+ return Array.from({ length: DYNAMIC_ISLAND_TEMPLATE_DEPTH }, (_, depth) => {
5239
+ const templateName = resolveDynamicIslandTemplateName(depth);
5240
+ const childTemplateName = resolveDynamicIslandTemplateName(depth + 1);
5241
+ const childTemplate = depth + 1 < DYNAMIC_ISLAND_TEMPLATE_DEPTH ? `<block ${directives.forAttr}="{{node.children}}" ${directives.forItemAttr}="child" ${directives.keyAttr}="index"><template is="${childTemplateName}" data="{{node:child,islandId:islandId}}" /></block>` : "";
5242
+ return `<template name="${templateName}"><block ${directives.ifAttr}="{{node.kind=='text'}}">{{node.text}}</block><block ${directives.elifAttr}="{{node.kind=='fragment'}}">${childTemplate}</block><view ${directives.elifAttr}="{{node.tag=='view'}}" ${tapAttrs}>${childTemplate}</view><text ${directives.elifAttr}="{{node.tag=='text'}}" ${tapAttrs}>${childTemplate}</text><button ${directives.elifAttr}="{{node.tag=='button'}}" ${tapAttrs}>${childTemplate}</button><input ${directives.elifAttr}="{{node.tag=='input'}}" ${attrs} value="{{node.props.value}}" data-wv-jsx-handler="{{node.events.input||node.events.change}}" ${bindInput}="${WEVU_JSX_ISLAND_HANDLER}" ${bindChange}="${WEVU_JSX_ISLAND_HANDLER}" /><image ${directives.elifAttr}="{{node.tag=='image'}}" ${tapAttrs} src="{{node.props.src}}" /><block ${directives.elseAttr}>${childTemplate}</block></template>`;
5243
+ }).join("");
5244
+ }
5245
+ function resolveImportedExpression(node, context) {
5246
+ if (!context.filename || !context.moduleResolver) return;
5247
+ let localName;
5248
+ let importedName;
5249
+ if (t.isIdentifier(node)) localName = node.name;
5250
+ else if (t.isMemberExpression(node) && !node.computed && t.isIdentifier(node.object) && t.isIdentifier(node.property)) {
5251
+ localName = node.object.name;
5252
+ importedName = node.property.name;
5253
+ }
5254
+ if (!localName) return;
5255
+ const binding = context.importedBindings?.get(localName);
5256
+ if (!binding) return;
5257
+ if (binding.importedName !== "*" && importedName) return;
5258
+ const resolvedName = importedName ?? binding.importedName;
5259
+ const key = `${context.filename}:${localName}:${resolvedName}`;
5260
+ if (context.resolvingExports?.has(key)) {
5261
+ context.warnings.push(`[JSX 编译] 跨文件 JSX 导出循环引用:${localName}`);
5262
+ return;
5263
+ }
5264
+ context.resolvingExports?.add(key);
5265
+ try {
5266
+ return context.moduleResolver.resolveImport(context.filename, binding.source, resolvedName);
5267
+ } finally {
5268
+ context.resolvingExports?.delete(key);
5269
+ }
5270
+ }
5271
+ function compileImportedExpression(node, context) {
5272
+ const resolved = resolveImportedExpression(node, context);
5273
+ if (!resolved || resolved.params.length > 0) {
5274
+ const importedLocal = t.isIdentifier(node) ? node.name : t.isMemberExpression(node) && t.isIdentifier(node.object) ? node.object.name : "";
5275
+ if (context.importedBindings?.has(importedLocal)) {
5276
+ context.warnings.push(`[JSX 编译] 无法静态展开跨文件 JSX 导出,已生成 dynamic island:${importedLocal || "unknown"}`);
5277
+ return registerDynamicIsland(node, context, "unsupported-import");
5278
+ }
5279
+ return null;
5280
+ }
5281
+ return compileRenderableExpression(resolved.expression, context);
5282
+ }
5283
+ function compileImportedFactoryCall(node, context) {
5284
+ if (!t.isIdentifier(node.callee) || !context.filename || !context.moduleResolver) return null;
5285
+ const binding = context.importedBindings?.get(node.callee.name);
5286
+ if (!binding) return null;
5287
+ const resolved = context.moduleResolver.resolveImport(context.filename, binding.source, binding.importedName);
5288
+ if (!resolved || resolved.params.length === 0) {
5289
+ context.warnings.push(`[JSX 编译] 无法静态展开 JSX 工厂 ${node.callee.name},已生成 dynamic island。`);
5290
+ return registerDynamicIsland(node, context, "unsupported-call");
5291
+ }
5292
+ const replacements = /* @__PURE__ */ new Map();
5293
+ resolved.params.forEach((param, index) => {
5294
+ const argument = node.arguments[index];
5295
+ if (argument && t.isExpression(argument)) replacements.set(param, argument);
5296
+ });
5297
+ if (replacements.size !== resolved.params.length) {
5298
+ context.warnings.push(`[JSX 编译] JSX 工厂 ${node.callee.name} 调用参数不足,已保留运行时表达式。`);
5299
+ return null;
5300
+ }
5301
+ const expression = t.cloneNode(resolved.expression, true);
5302
+ const file = t.file(t.program([t.expressionStatement(expression)]));
5303
+ traverse(file, { ReferencedIdentifier(path) {
5304
+ const replacement = replacements.get(path.node.name);
5305
+ if (replacement) path.replaceWith(t.cloneNode(replacement, true));
5306
+ } });
5307
+ const output = file.program.body[0];
5308
+ if (!t.isExpressionStatement(output)) return null;
5309
+ let expanded = output.expression;
5310
+ if (t.isCallExpression(expanded) && expanded.arguments.length === 0) {
5311
+ const callee = expanded.callee;
5312
+ if (t.isArrowFunctionExpression(callee) || t.isFunctionExpression(callee)) {
5313
+ const body = callee.body;
5314
+ let capturesThis = false;
5315
+ if (t.isExpression(body)) {
5316
+ const file = t.file(t.program([t.expressionStatement(body)]));
5317
+ traverse(file, { ThisExpression() {
5318
+ capturesThis = true;
5319
+ } });
5320
+ if (!capturesThis) expanded = body;
5321
+ }
5322
+ }
5323
+ }
5324
+ return compileRenderableExpression(expanded, context);
5325
+ }
4805
5326
  function compileMapExpression(exp, context) {
4806
5327
  const callee = exp.callee;
4807
5328
  if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.property, { name: "map" })) return null;
@@ -4865,13 +5386,21 @@ function compileRenderableExpression(exp, context) {
4865
5386
  if (t.isConditionalExpression(node)) return compileConditionalExpression(node, context);
4866
5387
  if (t.isLogicalExpression(node)) return compileLogicalExpression(node, context);
4867
5388
  if (t.isCallExpression(node)) {
5389
+ const importedFactory = compileImportedFactoryCall(node, context);
5390
+ if (importedFactory != null) return importedFactory;
4868
5391
  const mapped = compileMapExpression(node, context);
4869
5392
  if (mapped != null) return mapped;
5393
+ context.warnings.push("无法证明 JSX 子节点函数调用返回静态文本,已生成 dynamic island。");
5394
+ return registerDynamicIsland(node, context, "unsupported-call");
4870
5395
  }
4871
5396
  if (t.isArrayExpression(node)) return node.elements.map((element) => {
4872
5397
  if (!element || !t.isExpression(element)) return "";
4873
5398
  return compileRenderableExpression(element, context);
4874
5399
  }).join("");
5400
+ if (t.isIdentifier(node) || t.isMemberExpression(node)) {
5401
+ const imported = compileImportedExpression(node, context);
5402
+ if (imported != null) return imported;
5403
+ }
4875
5404
  if (t.isNullLiteral(node) || t.isBooleanLiteral(node)) return "";
4876
5405
  return renderMustache$1(normalizeInterpolationExpression(node), context);
4877
5406
  }
@@ -4902,7 +5431,10 @@ function compileJsxChildren(children, context) {
4902
5431
  parts.push(compileJsxFragment(child, context));
4903
5432
  continue;
4904
5433
  }
4905
- if (t.isJSXSpreadChild(child)) context.warnings.push("暂不支持 JSX spread child,已忽略。");
5434
+ if (t.isJSXSpreadChild(child)) {
5435
+ parts.push(registerDynamicIsland(child.expression, context, "spread-child"));
5436
+ context.warnings.push("JSX spread child 无法映射为静态 WXML,已生成 dynamic island。");
5437
+ }
4906
5438
  }
4907
5439
  return parts.join("");
4908
5440
  }
@@ -4910,11 +5442,81 @@ function compileJsxFragment(node, context) {
4910
5442
  return compileJsxChildren(node.children, context);
4911
5443
  }
4912
5444
  function compileJsxElement(node, context) {
5445
+ if (t.isJSXMemberExpression(node.openingElement.name)) {
5446
+ context.warnings.push("JSX 成员标签(如 <Foo.Bar />)无法映射为小程序 WXML 组件标签,已生成 dynamic island。");
5447
+ return registerDynamicIsland(node, context, "dynamic-component");
5448
+ }
5449
+ const dynamicSpread = node.openingElement.attributes.find((attr) => {
5450
+ if (!t.isJSXSpreadAttribute(attr)) return false;
5451
+ const argument = unwrapTsExpression$2(attr.argument);
5452
+ return !t.isObjectExpression(argument) || argument.properties.some((property) => !t.isObjectProperty(property) || property.computed || !t.isIdentifier(property.key) && !t.isStringLiteral(property.key) || !t.isExpression(property.value));
5453
+ });
5454
+ if (dynamicSpread && t.isJSXSpreadAttribute(dynamicSpread)) {
5455
+ context.warnings.push("动态 JSX spread attributes 无法映射为静态 WXML,已生成 dynamic island。");
5456
+ return registerDynamicIsland(node, context, "dynamic-spread");
5457
+ }
4913
5458
  const tag = toJsxTagName(node.openingElement.name, context);
5459
+ if (tag === "component") {
5460
+ context.warnings.push("JSX 动态 component 无法映射为静态 WXML,已生成 dynamic island。");
5461
+ return registerDynamicIsland(node, context, "dynamic-component");
5462
+ }
5463
+ if (tag === "Teleport") {
5464
+ context.warnings.push("小程序不支持 JSX <Teleport>,已生成 dynamic island。");
5465
+ return registerDynamicIsland(node, context, "dynamic-component");
5466
+ }
5467
+ if (tag === "Transition") {
5468
+ context.warnings.push("JSX <Transition> 需要 Web 动画运行时,当前仅渲染子节点。");
5469
+ return compileJsxChildren(node.children, context);
5470
+ }
5471
+ if (tag === "KeepAlive") {
5472
+ context.warnings.push("JSX <KeepAlive> 需要运行时缓存管理,当前仅保留标记并渲染子节点。");
5473
+ return `<block data-keep-alive="true">${compileJsxChildren(node.children, context)}</block>`;
5474
+ }
5475
+ if (node.children.some((child) => {
5476
+ if (!t.isJSXExpressionContainer(child) || t.isJSXEmptyExpression(child.expression)) return false;
5477
+ const expression = unwrapTsExpression$2(child.expression);
5478
+ return t.isObjectExpression(expression) || t.isFunctionExpression(expression) || t.isArrowFunctionExpression(expression);
5479
+ })) {
5480
+ context.warnings.push("JSX slot 函数或对象 slots 无法映射为静态 WXML,已生成 dynamic island。");
5481
+ return registerDynamicIsland(node, context, "closure");
5482
+ }
5483
+ if (node.openingElement.attributes.some((attribute) => {
5484
+ if (!t.isJSXAttribute(attribute) || !t.isJSXIdentifier(attribute.name)) return false;
5485
+ if (attribute.name.name !== "class" && attribute.name.name !== "className" && attribute.name.name !== "style") return false;
5486
+ const expression = readJsxAttributeExpression(attribute.value);
5487
+ return !!expression && (t.isArrayExpression(expression) || t.isObjectExpression(expression)) && !isStaticClassStyleExpression(expression);
5488
+ })) {
5489
+ context.warnings.push("动态 JSX class/style 数组或对象需要运行时合并,已生成 dynamic island。");
5490
+ return registerDynamicIsland(node, context, "closure");
5491
+ }
5492
+ const directives = /* @__PURE__ */ new Map();
5493
+ for (const attribute of node.openingElement.attributes) {
5494
+ if (!t.isJSXAttribute(attribute)) continue;
5495
+ const name = t.isJSXIdentifier(attribute.name) ? attribute.name.name : t.isJSXNamespacedName(attribute.name) ? attribute.name.namespace.name : void 0;
5496
+ if (!name?.startsWith("v-")) continue;
5497
+ const expression = readJsxAttributeExpression(attribute.value);
5498
+ if (expression) directives.set(name, expression);
5499
+ }
5500
+ if (directives.has("v-for") || directives.has("v-slots") || directives.has("v-model") || directives.has("v-models")) {
5501
+ const directive = [
5502
+ "v-for",
5503
+ "v-slots",
5504
+ "v-model",
5505
+ "v-models"
5506
+ ].find((name) => directives.has(name));
5507
+ context.warnings.push(`JSX ${directive} 无法直接映射当前静态 WXML,已生成 dynamic island。`);
5508
+ return registerDynamicIsland(node, context, "closure");
5509
+ }
4914
5510
  const attrs = compileJsxAttributes(node.openingElement.attributes, context);
5511
+ const showExpression = directives.get("v-show");
5512
+ if (showExpression) attrs.push(`hidden="${renderMustache$1(`!(${normalizeInterpolationExpression(showExpression)})`, context)}"`);
4915
5513
  const attrsSegment = attrs.length ? ` ${attrs.join(" ")}` : "";
4916
- if (node.openingElement.selfClosing) return `<${tag}${attrsSegment} />`;
4917
- return `<${tag}${attrsSegment}>${compileJsxChildren(node.children, context)}</${tag}>`;
5514
+ const textExpression = directives.get("v-text");
5515
+ const content = textExpression ? renderMustache$1(normalizeInterpolationExpression(textExpression), context) : compileJsxChildren(node.children, context);
5516
+ const element = node.openingElement.selfClosing && !textExpression ? `<${tag}${attrsSegment} />` : `<${tag}${attrsSegment}>${content}</${tag}>`;
5517
+ const ifExpression = directives.get("v-if");
5518
+ if (ifExpression) return context.platform.wrapIf(normalizeInterpolationExpression(ifExpression), element, (expression) => renderMustache$1(expression, context));
5519
+ return element;
4918
5520
  }
4919
5521
  //#endregion
4920
5522
  //#region src/plugins/jsx/compileJsx/template.ts
@@ -4926,26 +5528,124 @@ function createJsxCompileContext(options) {
4926
5528
  warnings: [],
4927
5529
  inlineExpressions: [],
4928
5530
  inlineExpressionSeed: 0,
4929
- scopeStack: []
5531
+ scopeStack: [],
5532
+ moduleResolver: void 0,
5533
+ importedBindings: /* @__PURE__ */ new Map(),
5534
+ resolvingExports: /* @__PURE__ */ new Set(),
5535
+ dynamicIslands: [],
5536
+ dynamicIslandSeed: 0,
5537
+ dynamicIslandMode: "auto"
4930
5538
  };
4931
5539
  }
5540
+ function collectImportedBindings(ast, context) {
5541
+ for (const statement of ast.program.body) {
5542
+ if (!t.isImportDeclaration(statement)) continue;
5543
+ const source = statement.source.value;
5544
+ for (const specifier of statement.specifiers) if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.local)) {
5545
+ const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value;
5546
+ context.importedBindings?.set(specifier.local.name, {
5547
+ source,
5548
+ importedName
5549
+ });
5550
+ } else if (t.isImportDefaultSpecifier(specifier) && t.isIdentifier(specifier.local)) context.importedBindings?.set(specifier.local.name, {
5551
+ source,
5552
+ importedName: "default"
5553
+ });
5554
+ else if (t.isImportNamespaceSpecifier(specifier) && t.isIdentifier(specifier.local)) context.importedBindings?.set(specifier.local.name, {
5555
+ source,
5556
+ importedName: "*"
5557
+ });
5558
+ }
5559
+ }
4932
5560
  /**
4933
5561
  * 单次解析同时编译模板和收集自动组件上下文,避免重复 babelParse 和 traverse。
4934
5562
  */
4935
5563
  function compileJsxTemplateAndCollectComponents(source, filename, options) {
4936
5564
  const ast = parse$3(source, BABEL_TS_MODULE_PARSER_OPTIONS);
4937
5565
  const context = createJsxCompileContext(options);
5566
+ context.filename = filename;
5567
+ context.moduleResolver = createJsxModuleResolver(options?.warn);
5568
+ collectImportedBindings(ast, context);
4938
5569
  const { renderExpression, autoComponentContext } = analyzeJsxAst(ast, context);
4939
5570
  let template;
4940
5571
  if (renderExpression) {
4941
5572
  template = compileRenderableExpression(renderExpression, context);
5573
+ if (context.dynamicIslands?.length) template += renderDynamicIslandSupportTemplate(context);
4942
5574
  if (context.formatWxml) template = formatWxml(template);
4943
5575
  } else context.warnings = context.warnings.map((message) => message === "未识别到默认导出组件。" ? `未在 ${filename} 中识别到默认导出组件。` : message);
4944
5576
  return {
4945
5577
  template,
4946
5578
  warnings: context.warnings,
4947
5579
  inlineExpressions: context.inlineExpressions,
4948
- autoComponentContext
5580
+ autoComponentContext,
5581
+ dynamicIslands: context.dynamicIslands,
5582
+ dependencies: context.moduleResolver.getDependencies()
5583
+ };
5584
+ }
5585
+ //#endregion
5586
+ //#region src/plugins/jsx/vueJsxTransform.ts
5587
+ const DEFAULT_VUE_JSX_TRANSFORM_OPTIONS = {
5588
+ enableObjectSlots: true,
5589
+ mergeProps: true,
5590
+ optimize: true,
5591
+ resolveType: false,
5592
+ transformOn: true
5593
+ };
5594
+ function readDirectiveExpression(attribute) {
5595
+ if (!attribute.value) return t.booleanLiteral(true);
5596
+ if (!t.isJSXExpressionContainer(attribute.value) || t.isJSXEmptyExpression(attribute.value.expression)) return;
5597
+ return t.isExpression(attribute.value.expression) ? attribute.value.expression : void 0;
5598
+ }
5599
+ function createWevuJsxDirectiveCompatibilityPlugin() {
5600
+ return {
5601
+ name: "wevu-jsx-directive-compatibility",
5602
+ visitor: { JSXElement(path) {
5603
+ const attributes = path.node.openingElement.attributes;
5604
+ let ifExpression;
5605
+ let textExpression;
5606
+ path.node.openingElement.attributes = attributes.filter((attribute) => {
5607
+ if (!t.isJSXAttribute(attribute)) return true;
5608
+ const name = t.isJSXIdentifier(attribute.name) ? attribute.name.name : t.isJSXNamespacedName(attribute.name) ? attribute.name.namespace.name : void 0;
5609
+ if (name === "v-if") {
5610
+ ifExpression = readDirectiveExpression(attribute);
5611
+ return false;
5612
+ }
5613
+ if (name === "v-text") {
5614
+ textExpression = readDirectiveExpression(attribute);
5615
+ return false;
5616
+ }
5617
+ if (name?.startsWith("v-") && ![
5618
+ "v-html",
5619
+ "v-model",
5620
+ "v-models",
5621
+ "v-show",
5622
+ "v-slots"
5623
+ ].includes(name)) return false;
5624
+ return true;
5625
+ });
5626
+ if (textExpression) path.node.children = [t.jsxExpressionContainer(textExpression)];
5627
+ if (ifExpression) path.replaceWith(t.conditionalExpression(ifExpression, path.node, t.nullLiteral()));
5628
+ } }
5629
+ };
5630
+ }
5631
+ function transformVueJsxScript(source, filename, sourceMaps = true, options) {
5632
+ const result = transformSync(source, {
5633
+ filename,
5634
+ sourceType: "module",
5635
+ sourceMaps,
5636
+ plugins: [createWevuJsxDirectiveCompatibilityPlugin, [vueJsxPlugin, {
5637
+ ...DEFAULT_VUE_JSX_TRANSFORM_OPTIONS,
5638
+ ...options
5639
+ }]],
5640
+ parserOpts: { plugins: ["typescript", "jsx"] },
5641
+ generatorOpts: { retainLines: !sourceMaps }
5642
+ });
5643
+ return {
5644
+ code: result?.code ?? source,
5645
+ map: result?.map ? {
5646
+ ...result.map,
5647
+ file: result.map.file ?? void 0
5648
+ } : null
4949
5649
  };
4950
5650
  }
4951
5651
  //#endregion
@@ -4956,6 +5656,9 @@ function normalizeUsingComponentFrom(value) {
4956
5656
  if (!value) return;
4957
5657
  return typeof value === "string" ? value : value.from;
4958
5658
  }
5659
+ function toMiniProgramComponentTag(name) {
5660
+ return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase();
5661
+ }
4959
5662
  /**
4960
5663
  * 编译 JSX/TSX 文件,输出 wevu 脚本与 WXML 模板。
4961
5664
  */
@@ -4979,8 +5682,9 @@ async function compileJsxFile(source, filename, options) {
4979
5682
  const message = error instanceof Error ? error.message : String(error);
4980
5683
  throw new Error(`解析 ${filename} 失败:${message}`);
4981
5684
  }
4982
- const { template: compiledTemplateStr, warnings: templateWarnings, inlineExpressions, autoComponentContext } = compileJsxTemplateAndCollectComponents(source, filename, options);
5685
+ const { template: rawTemplate, warnings: templateWarnings, inlineExpressions, autoComponentContext, dynamicIslands, dependencies } = compileJsxTemplateAndCollectComponents(source, filename, options);
4983
5686
  const autoUsingComponentsMap = {};
5687
+ const localComponentAliases = /* @__PURE__ */ new Map();
4984
5688
  if (options?.autoUsingComponents?.resolveUsingComponentPath && autoComponentContext.templateTags.size > 0) for (const imported of autoComponentContext.importedComponents) {
4985
5689
  if (!autoComponentContext.templateTags.has(imported.localName)) continue;
4986
5690
  let resolved = normalizeUsingComponentFrom(await options.autoUsingComponents.resolveUsingComponentPath(imported.importSource, filename, {
@@ -4990,7 +5694,9 @@ async function compileJsxFile(source, filename, options) {
4990
5694
  }));
4991
5695
  if (!resolved && imported.importSource.startsWith("/")) resolved = removeExtensionDeep(imported.importSource);
4992
5696
  if (!resolved) continue;
4993
- autoUsingComponentsMap[imported.localName] = resolved;
5697
+ const componentName = imported.importSource.startsWith(".") || imported.importSource.startsWith("/") ? toMiniProgramComponentTag(imported.localName) : imported.localName;
5698
+ autoUsingComponentsMap[componentName] = resolved;
5699
+ if (componentName !== imported.localName) localComponentAliases.set(imported.localName, componentName);
4994
5700
  }
4995
5701
  const autoImportTagsMap = {};
4996
5702
  if (options?.autoImportTags?.resolveUsingComponent && autoComponentContext.templateTags.size > 0) for (const tag of autoComponentContext.templateTags) {
@@ -5002,10 +5708,12 @@ async function compileJsxFile(source, filename, options) {
5002
5708
  resolved = void 0;
5003
5709
  }
5004
5710
  if (!resolved?.from) continue;
5005
- autoImportTagsMap[resolved.name || tag] = resolved.from;
5711
+ const resolvedName = resolved.name || tag;
5712
+ autoImportTagsMap[localComponentAliases.get(resolvedName) ?? resolvedName] = resolved.from;
5006
5713
  }
5007
- const normalizedScriptSource = stripRenderOptionFromScript(scriptSource, filename, options?.warn);
5008
- const transformedScript = transformScript(normalizedScriptSource, {
5714
+ const normalizedScriptSource = injectDynamicIslandRuntime(stripRenderOptionFromScript(scriptSource, filename, options?.warn), dynamicIslands);
5715
+ const vueJsxTransformed = transformVueJsxScript(normalizedScriptSource, filename, options?.sourceMap !== false);
5716
+ const transformedScript = transformScript(vueJsxTransformed.code, {
5009
5717
  skipComponentTransform: options?.skipComponentTransform ?? options?.isApp,
5010
5718
  isApp: options?.isApp,
5011
5719
  isPage: options?.isPage,
@@ -5032,15 +5740,19 @@ async function compileJsxFile(source, filename, options) {
5032
5740
  }
5033
5741
  if (jsonDefaults && Object.keys(jsonDefaults).length > 0) configObj = mergeJson(configObj ?? {}, jsonDefaults, "defaults");
5034
5742
  if (scriptMacroConfig && Object.keys(scriptMacroConfig).length > 0) configObj = mergeJson(configObj ?? {}, scriptMacroConfig, "macro");
5743
+ let compiledTemplateStr = rawTemplate;
5744
+ for (const [from, to] of localComponentAliases) if (compiledTemplateStr) compiledTemplateStr = compiledTemplateStr.replaceAll(`<${from}`, `<${to}`).replaceAll(`</${from}>`, `</${to}>`);
5035
5745
  return {
5036
5746
  script: transformedScript.code,
5037
- scriptMap: transformedScript.map ?? null,
5747
+ scriptMap: transformedScript.map ?? vueJsxTransformed.map,
5038
5748
  template: compiledTemplateStr,
5039
5749
  config: configObj && Object.keys(configObj).length > 0 ? JSON.stringify(configObj, null, 2) : void 0,
5040
5750
  meta: {
5041
5751
  hasScriptSetup: false,
5042
5752
  hasSetupOption: SETUP_CALL_RE$1.test(normalizedScriptSource),
5043
- jsonMacroHash: scriptMacroHash
5753
+ jsonMacroHash: scriptMacroHash,
5754
+ jsxDynamicIslands: dynamicIslands,
5755
+ jsxDependencies: dependencies
5044
5756
  }
5045
5757
  };
5046
5758
  }
@@ -10477,7 +11189,18 @@ async function compileScriptPhase(descriptor, descriptorForCompile, filename, op
10477
11189
  if (!isAppFile && !descriptor.scriptSetup && !hasDefaultExport(scriptCode)) scriptCode += "\nexport default {}";
10478
11190
  } else scriptCode = "export default {}";
10479
11191
  if (scriptCode) {
10480
- const transformed = transformScript(scriptCode, {
11192
+ const scriptLang = descriptor.script?.lang ?? descriptor.scriptSetup?.lang;
11193
+ const isJsxScript = scriptLang === "jsx" || scriptLang === "tsx";
11194
+ let jsxTemplate;
11195
+ if (isJsxScript) {
11196
+ jsxTemplate = compileJsxTemplateAndCollectComponents(scriptCode, filename, options);
11197
+ scriptCode = injectDynamicIslandRuntime(stripRenderOptionFromScript(scriptCode, filename, descriptor.template ? void 0 : options?.warn), jsxTemplate.dynamicIslands);
11198
+ }
11199
+ const jsxTransformed = isJsxScript ? transformVueJsxScript(scriptCode, filename, options?.sourceMap !== false) : {
11200
+ code: scriptCode,
11201
+ map: null
11202
+ };
11203
+ const transformed = transformScript(jsxTransformed.code, {
10481
11204
  isTypeScript: descriptor.script?.lang === "ts" || descriptor.script?.lang === "tsx" || descriptor.scriptSetup?.lang === "ts" || descriptor.scriptSetup?.lang === "tsx",
10482
11205
  skipComponentTransform: options?.skipComponentTransform ?? isAppFile,
10483
11206
  isApp: isAppFile,
@@ -10500,7 +11223,9 @@ async function compileScriptPhase(descriptor, descriptorForCompile, filename, op
10500
11223
  });
10501
11224
  return {
10502
11225
  script: transformed.code,
10503
- scriptMap: composeSourceMaps(transformed.map ?? null, scriptMap),
11226
+ scriptMap: composeSourceMaps(transformed.map ?? jsxTransformed.map, scriptMap),
11227
+ template: jsxTemplate?.template,
11228
+ inlineExpressions: jsxTemplate?.inlineExpressions,
10504
11229
  autoUsingComponentsMap,
10505
11230
  autoComponentMeta
10506
11231
  };
@@ -10660,6 +11385,7 @@ async function compileVueFile(source, filename, options) {
10660
11385
  });
10661
11386
  result.script = scriptPhase.script;
10662
11387
  result.scriptMap = scriptPhase.scriptMap;
11388
+ if (scriptPhase.template) result.template = scriptPhase.template;
10663
11389
  compileStylePhase(parsed.descriptor, filename, result, options?.style);
10664
11390
  await compileConfigPhase({
10665
11391
  descriptor: parsed.descriptor,