@weapp-vite/miniprogram-automator 1.3.0 → 1.4.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/README.md +74 -0
- package/dist/index.d.mts +41 -6
- package/dist/index.mjs +705 -77
- package/dist/{launch-anJvfi-6.mjs → launch-ElaGbFxh.mjs} +1387 -328
- package/package.json +2 -2
|
@@ -8,7 +8,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
8
8
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
9
9
|
var __getProtoOf = Object.getPrototypeOf;
|
|
10
10
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
-
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
11
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod, mod.exports), cb = null), mod.exports);
|
|
12
12
|
var __exportAll = (all, no_symbols) => {
|
|
13
13
|
let target = {};
|
|
14
14
|
for (var name in all) __defProp(target, name, {
|
|
@@ -163,11 +163,14 @@ function runPropertyObservers(definition, instance, changedKeys, previousPropert
|
|
|
163
163
|
const changedRoots = new Set(changedKeys.map((key) => parseDataPath$1(key)[0]));
|
|
164
164
|
for (const changedKey of Object.keys(propOptions)) {
|
|
165
165
|
if (!changedRoots.has(changedKey)) continue;
|
|
166
|
+
const value = instance.properties[changedKey];
|
|
167
|
+
if ((value === null || typeof value !== "object") && Object.hasOwn(previousProperties, changedKey) && Object.is(value, previousProperties[changedKey])) continue;
|
|
166
168
|
const option = propOptions[changedKey];
|
|
167
169
|
if (!option || typeof option !== "object" || Array.isArray(option)) continue;
|
|
168
170
|
const observer = typeof option.observer === "string" ? instance[option.observer] : option.observer;
|
|
169
171
|
if (typeof observer !== "function") continue;
|
|
170
|
-
|
|
172
|
+
const changedPath = parseDataPath$1(changedKeys.find((key) => parseDataPath$1(key)[0] === changedKey)).map((segment) => isArrayIndexSegment$1(segment) ? Number(segment) : segment);
|
|
173
|
+
observer.call(instance, value, previousProperties[changedKey], changedPath);
|
|
171
174
|
}
|
|
172
175
|
}
|
|
173
176
|
function normalizeObserverPattern(pattern) {
|
|
@@ -378,7 +381,6 @@ function resolveInitialProperties(definition, properties) {
|
|
|
378
381
|
if (option && typeof option === "object" && !Array.isArray(option) && "value" in option) resolved[key] = resolvePropertyDefaultValue(option, definition);
|
|
379
382
|
else resolved[key] = cloneValue$1(resolveDefaultValueByType(normalizePropertyType(option)));
|
|
380
383
|
}
|
|
381
|
-
for (const [key, value] of Object.entries(properties)) if (!(key in resolved)) resolved[key] = value;
|
|
382
384
|
return resolved;
|
|
383
385
|
}
|
|
384
386
|
//#endregion
|
|
@@ -778,7 +780,7 @@ const basename = function(p, extension) {
|
|
|
778
780
|
}
|
|
779
781
|
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
|
|
780
782
|
};
|
|
781
|
-
const parse$
|
|
783
|
+
const parse$3 = function(p) {
|
|
782
784
|
const root = _PATH_ROOT_RE.exec(p)?.[0]?.replace(/\\/g, "/") || "";
|
|
783
785
|
const base = basename(p);
|
|
784
786
|
const extension = extname(base);
|
|
@@ -804,7 +806,7 @@ const _path = {
|
|
|
804
806
|
matchesGlob,
|
|
805
807
|
normalize,
|
|
806
808
|
normalizeString,
|
|
807
|
-
parse: parse$
|
|
809
|
+
parse: parse$3,
|
|
808
810
|
relative,
|
|
809
811
|
resolve,
|
|
810
812
|
sep: "/",
|
|
@@ -839,11 +841,11 @@ const opposite = {
|
|
|
839
841
|
function definitions(instance) {
|
|
840
842
|
return Object.entries(instance.__definition__?.relations ?? {});
|
|
841
843
|
}
|
|
842
|
-
function includesBehavior(behaviors, target) {
|
|
843
|
-
return Array.isArray(behaviors) && behaviors.some((behavior) => behavior === target || behavior && typeof behavior === "object" && includesBehavior(behavior.behaviors, target));
|
|
844
|
+
function includesBehavior$1(behaviors, target) {
|
|
845
|
+
return Array.isArray(behaviors) && behaviors.some((behavior) => behavior === target || behavior && typeof behavior === "object" && includesBehavior$1(behavior.behaviors, target));
|
|
844
846
|
}
|
|
845
847
|
function matches(source, key, relation, target) {
|
|
846
|
-
if (relation.target) return includesBehavior(target.__definition__?.behaviors, relation.target);
|
|
848
|
+
if (relation.target) return includesBehavior$1(target.__definition__?.behaviors, relation.target);
|
|
847
849
|
const targetPath = key.startsWith("/") ? key.slice(1) : posix.join(posix.dirname(String(source.is)), key);
|
|
848
850
|
return posix.normalize(targetPath) === target.is;
|
|
849
851
|
}
|
|
@@ -917,29 +919,23 @@ function detachComponentRelations(instances) {
|
|
|
917
919
|
//#region ../../mpcore/packages/simulator/src/runtime/componentInstance/index.ts
|
|
918
920
|
function createComponentInstance(options) {
|
|
919
921
|
const definition = normalizeComponentDefinition(options.definition);
|
|
920
|
-
const inputProperties = resolveInitialProperties(definition, options.properties ?? {});
|
|
921
922
|
const data = {
|
|
922
923
|
...resolveInitialData$1(definition),
|
|
923
|
-
...
|
|
924
|
+
...resolveInitialProperties(definition, options.properties ?? {})
|
|
924
925
|
};
|
|
925
926
|
const instance = {
|
|
926
927
|
__definition__: definition,
|
|
927
928
|
data,
|
|
928
929
|
__propertySnapshots__: {},
|
|
929
|
-
properties:
|
|
930
|
-
...data,
|
|
931
|
-
...inputProperties
|
|
932
|
-
},
|
|
930
|
+
properties: data,
|
|
933
931
|
getRelationNodes(key) {
|
|
934
932
|
return getComponentRelationNodes(instance, key);
|
|
935
933
|
},
|
|
936
934
|
setData(patch, callback) {
|
|
937
935
|
const changedKeys = Object.keys(patch);
|
|
938
|
-
const
|
|
939
|
-
const propertyKeys = dataKeys.filter((key) => Object.hasOwn(definition.properties ?? {}, key));
|
|
936
|
+
const propertyKeys = [...new Set(changedKeys.map((key) => parseDataPath$1(key)[0]))].filter((key) => Object.hasOwn(definition.properties ?? {}, key));
|
|
940
937
|
const previousProperties = Object.fromEntries(propertyKeys.map((key) => [key, cloneValue$1(instance.properties[key])]));
|
|
941
938
|
for (const [key, value] of Object.entries(patch)) assignByPath$1(instance.data, key, value);
|
|
942
|
-
for (const key of dataKeys) instance.properties[key] = instance.data[key];
|
|
943
939
|
synchronizeAttachmentBindings(instance);
|
|
944
940
|
runComponentObservers(definition, instance, changedKeys, previousProperties);
|
|
945
941
|
if (options.requestRender) options.requestRender(callback);
|
|
@@ -1292,6 +1288,31 @@ function collectNodeDataset(node) {
|
|
|
1292
1288
|
//#endregion
|
|
1293
1289
|
//#region ../../mpcore/packages/simulator/src/view/componentEvent.ts
|
|
1294
1290
|
const eventNodes = /* @__PURE__ */ new WeakMap();
|
|
1291
|
+
/** 原生默认行为读取声明所有者与原始属性,避免组件根折叠覆盖宿主边界。 */
|
|
1292
|
+
function getNativeNodeOwner(node) {
|
|
1293
|
+
const entry = eventNodes.get(node);
|
|
1294
|
+
return entry ? {
|
|
1295
|
+
scopeId: entry.scope.getScopeId(),
|
|
1296
|
+
target: entry.target
|
|
1297
|
+
} : void 0;
|
|
1298
|
+
}
|
|
1299
|
+
/** 原生冒泡包含折叠的宿主绑定;catch 只截断其后的绑定和祖先。 */
|
|
1300
|
+
function visitNativeNodeEventBindings(node, eventName, visit) {
|
|
1301
|
+
const collect = (entry) => {
|
|
1302
|
+
const binding = entry.bindings ? entry.bindings.eventBindings?.get(eventName) : resolveEventBindingPhases(entry.target.attribs, eventName, false)?.bubble;
|
|
1303
|
+
if (binding) visit(entry.scope.getScopeId(), entry.target, binding);
|
|
1304
|
+
return binding?.stopAfter ?? false;
|
|
1305
|
+
};
|
|
1306
|
+
const entry = eventNodes.get(node);
|
|
1307
|
+
if (!entry) {
|
|
1308
|
+
const binding = resolveEventBindingPhases(node.attribs, eventName, false)?.bubble;
|
|
1309
|
+
if (binding) visit(node.attribs?.["data-sim-scope"] ?? null, node, binding);
|
|
1310
|
+
return binding?.stopAfter ?? false;
|
|
1311
|
+
}
|
|
1312
|
+
if (collect(entry)) return true;
|
|
1313
|
+
for (const host of entry.hosts ?? []) if (collect(eventNodes.get(host))) return true;
|
|
1314
|
+
return false;
|
|
1315
|
+
}
|
|
1295
1316
|
/** 在构造子树之前建立父链,created/observer 中的事件也能访问声明树。 */
|
|
1296
1317
|
function registerComponentEventNode(node, scope, parent) {
|
|
1297
1318
|
node.parent = parent ?? null;
|
|
@@ -13001,6 +13022,29 @@ var Parser$1 = class extends StatementParser {
|
|
|
13001
13022
|
return result;
|
|
13002
13023
|
}
|
|
13003
13024
|
};
|
|
13025
|
+
function parse$2(input, options) {
|
|
13026
|
+
if (options?.sourceType === "unambiguous") {
|
|
13027
|
+
options = { ...options };
|
|
13028
|
+
try {
|
|
13029
|
+
options.sourceType = "module";
|
|
13030
|
+
const parser = getParser(options, input);
|
|
13031
|
+
const ast = parser.parse();
|
|
13032
|
+
if (parser.sawUnambiguousESM) return ast;
|
|
13033
|
+
if (parser.ambiguousScriptDifferentAst) try {
|
|
13034
|
+
options.sourceType = "script";
|
|
13035
|
+
return getParser(options, input).parse();
|
|
13036
|
+
} catch {}
|
|
13037
|
+
else ast.program.sourceType = "script";
|
|
13038
|
+
return ast;
|
|
13039
|
+
} catch (moduleError) {
|
|
13040
|
+
try {
|
|
13041
|
+
options.sourceType = "script";
|
|
13042
|
+
return getParser(options, input).parse();
|
|
13043
|
+
} catch {}
|
|
13044
|
+
throw moduleError;
|
|
13045
|
+
}
|
|
13046
|
+
} else return getParser(options, input).parse();
|
|
13047
|
+
}
|
|
13004
13048
|
function parseExpression(input, options) {
|
|
13005
13049
|
const parser = getParser(options, input);
|
|
13006
13050
|
if (parser.options.strictMode) parser.state.strict = true;
|
|
@@ -13424,6 +13468,7 @@ function syncComponentProperties(instance, definition, nextProperties, bindingEx
|
|
|
13424
13468
|
const changedRootKeys = [];
|
|
13425
13469
|
const previousProperties = {};
|
|
13426
13470
|
for (const [key, value] of Object.entries(nextProperties)) {
|
|
13471
|
+
if (!Object.hasOwn(definition.properties ?? {}, key)) continue;
|
|
13427
13472
|
const nextValue = normalizeComponentPropertyValue(definition, key, value);
|
|
13428
13473
|
const bindingExpression = bindingExpressions[key];
|
|
13429
13474
|
const bindingAffected = freshPageChanges && !!bindingExpression && changedPageKeys.some((changedKey) => {
|
|
@@ -13434,7 +13479,6 @@ function syncComponentProperties(instance, definition, nextProperties, bindingEx
|
|
|
13434
13479
|
previousProperties[key] = instance.properties[key];
|
|
13435
13480
|
const deliveredValue = cloneValue$1(nextValue);
|
|
13436
13481
|
instance.properties[key] = deliveredValue;
|
|
13437
|
-
if (Object.hasOwn(definition.properties ?? {}, key)) instance.data[key] = deliveredValue;
|
|
13438
13482
|
changedRootKeys.push(key);
|
|
13439
13483
|
}
|
|
13440
13484
|
instance.__propertySnapshots ??= {};
|
|
@@ -13445,6 +13489,32 @@ function syncComponentProperties(instance, definition, nextProperties, bindingEx
|
|
|
13445
13489
|
runComponentObservers(definition, instance, changedRootKeys, previousProperties);
|
|
13446
13490
|
}
|
|
13447
13491
|
//#endregion
|
|
13492
|
+
//#region ../../mpcore/packages/simulator/src/runtime/componentInstance/reconcileRemoved.ts
|
|
13493
|
+
/** 用户卸载钩子失败也要完成关系与缓存收尾,避免下一次渲染重复卸载同一实例。 */
|
|
13494
|
+
function reconcileRemovedComponents(cache, scopes, activeScopeIds, pageScopeId) {
|
|
13495
|
+
const removed = [...cache].filter(([scopeId]) => scopeId.startsWith(`${pageScopeId}/`) && !activeScopeIds.has(scopeId));
|
|
13496
|
+
let failure;
|
|
13497
|
+
for (const [scopeId, instance] of removed) try {
|
|
13498
|
+
if (isComponentAttached(instance)) runComponentLifecycle(instance, "detached");
|
|
13499
|
+
else scheduleDiscardedComponentReady(cache, scopeId, instance);
|
|
13500
|
+
} catch (error) {
|
|
13501
|
+
failure ??= { error };
|
|
13502
|
+
}
|
|
13503
|
+
let relationsChanged = false;
|
|
13504
|
+
try {
|
|
13505
|
+
relationsChanged = syncComponentRelations(cache, activeScopeIds, pageScopeId);
|
|
13506
|
+
} catch (error) {
|
|
13507
|
+
failure ??= { error };
|
|
13508
|
+
} finally {
|
|
13509
|
+
for (const [scopeId] of removed) {
|
|
13510
|
+
cache.delete(scopeId);
|
|
13511
|
+
scopes.delete(scopeId);
|
|
13512
|
+
}
|
|
13513
|
+
}
|
|
13514
|
+
if (failure) throw failure.error;
|
|
13515
|
+
return relationsChanged;
|
|
13516
|
+
}
|
|
13517
|
+
//#endregion
|
|
13448
13518
|
//#region ../../mpcore/packages/simulator/src/runtime/pageLifecycle.ts
|
|
13449
13519
|
const loadingPages = /* @__PURE__ */ new WeakSet();
|
|
13450
13520
|
function isPageBeforeReady(page) {
|
|
@@ -13533,6 +13603,10 @@ function createPluginArtifactSource(fallback, miniprogramRootPath, plugins) {
|
|
|
13533
13603
|
readText: (filePath) => fallback.readText(resolvePhysicalPath(filePath))
|
|
13534
13604
|
};
|
|
13535
13605
|
}
|
|
13606
|
+
//#endregion
|
|
13607
|
+
//#region ../../@weapp-core/constants/dist/index.js
|
|
13608
|
+
/** 无头测试后端不支持所请求的自动化协议。 */
|
|
13609
|
+
const HEADLESS_PROTOCOL_UNSUPPORTED = "HEADLESS_PROTOCOL_UNSUPPORTED";
|
|
13536
13610
|
const WEVU_NATIVE_INSTANCE_KEY = "__wevuNativeInstance";
|
|
13537
13611
|
/** 宿主值为 1 时,实现带 routeEventId 的路由阶段契约;不代表微信 SDK 版本。 */
|
|
13538
13612
|
const WEVU_ROUTE_EVENT_CONTRACT_KEY = "__wevuRouteEventContract";
|
|
@@ -13646,66 +13720,155 @@ function resolveMiniProgramComponent(ownerFilePath, request, miniprogramRootPath
|
|
|
13646
13720
|
return npmPath ? relative(miniprogramRootPath, npmPath).slice(0, -3) : localPath;
|
|
13647
13721
|
}
|
|
13648
13722
|
//#endregion
|
|
13649
|
-
//#region ../../mpcore/packages/simulator/src/view/
|
|
13650
|
-
|
|
13651
|
-
|
|
13652
|
-
const
|
|
13653
|
-
|
|
13654
|
-
|
|
13655
|
-
|
|
13656
|
-
if (existing) return existing;
|
|
13657
|
-
const state = createTemplateRenderState(node);
|
|
13658
|
-
const wxsModules = Object.create(null);
|
|
13659
|
-
const ownDefinitions = new Map(state.definitions);
|
|
13660
|
-
const document = {
|
|
13661
|
-
state,
|
|
13662
|
-
exports: ownDefinitions
|
|
13663
|
-
};
|
|
13664
|
-
documents.set(owner, document);
|
|
13665
|
-
const visit = (child) => {
|
|
13666
|
-
if (child.name === "wxs" && loadWxs) {
|
|
13667
|
-
const name = child.attribs?.module;
|
|
13668
|
-
if (!name || !/^[a-z_$][\w$]*$/i.test(name) || [
|
|
13669
|
-
"__proto__",
|
|
13670
|
-
"constructor",
|
|
13671
|
-
"prototype"
|
|
13672
|
-
].includes(name)) throw new Error(`Invalid WXS module name in ${owner}: ${String(name)}`);
|
|
13673
|
-
if (Object.hasOwn(wxsModules, name)) throw new Error(`Duplicate WXS module in ${owner}: ${name}`);
|
|
13674
|
-
wxsModules[name] = loadWxs(owner, child);
|
|
13675
|
-
return;
|
|
13676
|
-
}
|
|
13677
|
-
if (child.name === "import" && child.attribs?.src) {
|
|
13678
|
-
const source = child.attribs.src;
|
|
13679
|
-
const imported = loadImport(owner, source.endsWith(".wxml") ? source : `${source}.wxml`);
|
|
13680
|
-
const importedDocument = collect(imported.root, imported.filePath);
|
|
13681
|
-
for (const [name, definition] of importedDocument.exports) state.definitions.set(name, definition);
|
|
13682
|
-
}
|
|
13683
|
-
for (const nested of child.children ?? []) visit(nested);
|
|
13684
|
-
};
|
|
13685
|
-
visit(node);
|
|
13686
|
-
if (Object.keys(wxsModules).length) state.wxsModules = wxsModules;
|
|
13687
|
-
for (const [name, definition] of ownDefinitions) {
|
|
13688
|
-
state.definitions.set(name, definition);
|
|
13689
|
-
definitionScopes.set(definition, state.definitions);
|
|
13690
|
-
if (state.wxsModules) definitionWxsScopes.set(definition, state.wxsModules);
|
|
13691
|
-
}
|
|
13692
|
-
state.definitionScopes = definitionScopes;
|
|
13693
|
-
state.definitionWxsScopes = definitionWxsScopes;
|
|
13694
|
-
return document;
|
|
13723
|
+
//#region ../../mpcore/packages/simulator/src/view/nodeEvents.ts
|
|
13724
|
+
/** 正确字段优先;复制触点,避免处理器修改调用者持有的数据。 */
|
|
13725
|
+
function readTouchEventPayload(event) {
|
|
13726
|
+
const changedTouches = event.changedTouches ?? event.changeTouches;
|
|
13727
|
+
return {
|
|
13728
|
+
...event.touches === void 0 ? {} : { touches: event.touches.map((touch) => ({ ...touch })) },
|
|
13729
|
+
...changedTouches === void 0 ? {} : { changedTouches: changedTouches.map((touch) => ({ ...touch })) }
|
|
13695
13730
|
};
|
|
13696
|
-
return collect(root, filePath).state;
|
|
13697
13731
|
}
|
|
13698
13732
|
//#endregion
|
|
13699
|
-
//#region ../../mpcore/packages/simulator/src/view/
|
|
13700
|
-
function
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13733
|
+
//#region ../../mpcore/packages/simulator/src/view/eventBinding.ts
|
|
13734
|
+
function resolveMiniProgramEventBinding(attributes, eventName) {
|
|
13735
|
+
return resolveEventBindingPhases(attributes, eventName, false)?.bubble ?? null;
|
|
13736
|
+
}
|
|
13737
|
+
/** 冒泡时保留原始 target,currentTarget 则属于当前执行绑定的节点。 */
|
|
13738
|
+
function createMiniProgramEventPayload(node, eventName, event, origin = node) {
|
|
13739
|
+
const dataset = collectNodeDataset(node);
|
|
13740
|
+
const nodeId = node.attribs?.id ?? "";
|
|
13741
|
+
const isOrigin = node === origin;
|
|
13742
|
+
return {
|
|
13743
|
+
...readTouchEventPayload(event),
|
|
13744
|
+
bubbles: false,
|
|
13745
|
+
capturePhase: false,
|
|
13746
|
+
composed: false,
|
|
13747
|
+
currentTarget: {
|
|
13748
|
+
dataset: isOrigin ? event.currentTarget?.dataset ?? event.dataset ?? dataset : dataset,
|
|
13749
|
+
id: isOrigin ? event.currentTarget?.id ?? event.id ?? nodeId : nodeId
|
|
13750
|
+
},
|
|
13751
|
+
detail: event.detail,
|
|
13752
|
+
mark: event.mark,
|
|
13753
|
+
target: {
|
|
13754
|
+
dataset: event.target?.dataset ?? event.dataset ?? (isOrigin ? dataset : collectNodeDataset(origin)),
|
|
13755
|
+
id: event.target?.id ?? event.id ?? origin.attribs?.id ?? ""
|
|
13756
|
+
},
|
|
13757
|
+
timeStamp: Date.now(),
|
|
13758
|
+
type: eventName
|
|
13759
|
+
};
|
|
13760
|
+
}
|
|
13761
|
+
//#endregion
|
|
13762
|
+
//#region ../../mpcore/packages/simulator/src/view/nativeForm.ts
|
|
13763
|
+
const pickerValues = /* @__PURE__ */ new WeakMap();
|
|
13764
|
+
/** 保存 picker 的原始数组属性,不能从渲染后的逗号字符串反推选项值。 */
|
|
13765
|
+
function setNativePickerValue(node, value) {
|
|
13766
|
+
if (node.name === "picker") pickerValues.set(node, value);
|
|
13767
|
+
}
|
|
13768
|
+
function includesBehavior(definition, name, visited = /* @__PURE__ */ new Set()) {
|
|
13769
|
+
if (visited.has(definition)) return false;
|
|
13770
|
+
visited.add(definition);
|
|
13771
|
+
return Array.isArray(definition.behaviors) && definition.behaviors.some((behavior) => behavior === name || behavior !== null && typeof behavior === "object" && includesBehavior(behavior, name, visited));
|
|
13772
|
+
}
|
|
13773
|
+
function nativeOwner(node) {
|
|
13774
|
+
return getNativeNodeOwner(node) ?? {
|
|
13775
|
+
scopeId: node.attribs?.["data-sim-scope"] ?? null,
|
|
13776
|
+
target: node
|
|
13777
|
+
};
|
|
13778
|
+
}
|
|
13779
|
+
function participatingScopes(formScope, pageScope, resolveComponent) {
|
|
13780
|
+
const scopes = /* @__PURE__ */ new Set([null, pageScope]);
|
|
13781
|
+
let current = formScope;
|
|
13782
|
+
while (current && !scopes.has(current)) {
|
|
13783
|
+
scopes.add(current);
|
|
13784
|
+
current = resolveComponent?.(current)?.ownerScopeId ?? null;
|
|
13707
13785
|
}
|
|
13708
|
-
return
|
|
13786
|
+
return scopes;
|
|
13787
|
+
}
|
|
13788
|
+
function participates(scopeId, formScopes, behavior, resolveComponent) {
|
|
13789
|
+
const visited = /* @__PURE__ */ new Set();
|
|
13790
|
+
while (!formScopes.has(scopeId)) {
|
|
13791
|
+
if (!scopeId || visited.has(scopeId)) return false;
|
|
13792
|
+
visited.add(scopeId);
|
|
13793
|
+
const component = resolveComponent?.(scopeId);
|
|
13794
|
+
if (!component || !includesBehavior(component.definition, behavior)) return false;
|
|
13795
|
+
scopeId = component.ownerScopeId;
|
|
13796
|
+
}
|
|
13797
|
+
return true;
|
|
13798
|
+
}
|
|
13799
|
+
function checked(attributes, name) {
|
|
13800
|
+
const value = attributes?.[name];
|
|
13801
|
+
return value !== void 0 && value !== "false" && value !== "0";
|
|
13802
|
+
}
|
|
13803
|
+
function choiceValues(group, pageScope, resolveComponent) {
|
|
13804
|
+
const values = [];
|
|
13805
|
+
const scopes = participatingScopes(nativeOwner(group).scopeId, pageScope, resolveComponent);
|
|
13806
|
+
const choice = group.name === "radio-group" ? "radio" : "checkbox";
|
|
13807
|
+
const visit = (node) => {
|
|
13808
|
+
if (node.name === "form" || node.name === "radio-group" || node.name === "checkbox-group") return;
|
|
13809
|
+
if (node.name === choice) {
|
|
13810
|
+
const owner = nativeOwner(node);
|
|
13811
|
+
if (checked(owner.target.attribs, "checked") && participates(owner.scopeId, scopes, "wx://form-field-group", resolveComponent)) values.push(owner.target.attribs?.value ?? "");
|
|
13812
|
+
}
|
|
13813
|
+
for (const child of node.children ?? []) visit(child);
|
|
13814
|
+
};
|
|
13815
|
+
for (const child of group.children ?? []) visit(child);
|
|
13816
|
+
return values;
|
|
13817
|
+
}
|
|
13818
|
+
function collectFormValues(form, scopes, pageScope, resolveComponent) {
|
|
13819
|
+
const values = Object.create(null);
|
|
13820
|
+
const visit = (node) => {
|
|
13821
|
+
if (node.name === "form") return;
|
|
13822
|
+
const owner = nativeOwner(node);
|
|
13823
|
+
const attributes = owner.target.attribs;
|
|
13824
|
+
const name = attributes?.name;
|
|
13825
|
+
if (attributes && name && participates(owner.scopeId, scopes, "wx://form-field-group", resolveComponent)) switch (node.name) {
|
|
13826
|
+
case "input":
|
|
13827
|
+
case "textarea":
|
|
13828
|
+
values[name] = attributes.value ?? "";
|
|
13829
|
+
break;
|
|
13830
|
+
case "switch":
|
|
13831
|
+
values[name] = checked(attributes, "checked");
|
|
13832
|
+
break;
|
|
13833
|
+
case "slider":
|
|
13834
|
+
values[name] = Number(attributes.value ?? 0);
|
|
13835
|
+
break;
|
|
13836
|
+
case "picker": {
|
|
13837
|
+
const mode = attributes.mode ?? "selector";
|
|
13838
|
+
if (mode === "multiSelector" || mode === "region") {
|
|
13839
|
+
const value = pickerValues.get(node);
|
|
13840
|
+
values[name] = Array.isArray(value) ? value.slice() : [];
|
|
13841
|
+
} else values[name] = mode === "selector" ? Number(attributes.value ?? 0) : attributes.value ?? "";
|
|
13842
|
+
break;
|
|
13843
|
+
}
|
|
13844
|
+
case "radio-group":
|
|
13845
|
+
values[name] = choiceValues(node, pageScope, resolveComponent)[0] ?? "";
|
|
13846
|
+
break;
|
|
13847
|
+
case "checkbox-group": values[name] = choiceValues(node, pageScope, resolveComponent);
|
|
13848
|
+
}
|
|
13849
|
+
for (const child of node.children ?? []) visit(child);
|
|
13850
|
+
};
|
|
13851
|
+
for (const child of form.children ?? []) visit(child);
|
|
13852
|
+
return values;
|
|
13853
|
+
}
|
|
13854
|
+
/** 先固定提交目标、字段值和方法所有者,再允许 tap 回调改变组件树。 */
|
|
13855
|
+
function prepareNativeFormSubmit(button, pageScope, event, resolveMethod, resolveComponent) {
|
|
13856
|
+
const owner = nativeOwner(button);
|
|
13857
|
+
if (owner.target.attribs?.["form-type"] !== "submit" || checked(owner.target.attribs, "disabled")) return;
|
|
13858
|
+
let form = button.parent;
|
|
13859
|
+
while (form && form.name !== "form") form = form.parent;
|
|
13860
|
+
if (!form) return;
|
|
13861
|
+
const formOwner = nativeOwner(form);
|
|
13862
|
+
const scopes = participatingScopes(formOwner.scopeId, pageScope, resolveComponent);
|
|
13863
|
+
if (!participates(owner.scopeId, scopes, "wx://form-field-button", resolveComponent)) return;
|
|
13864
|
+
const binding = resolveMiniProgramEventBinding(formOwner.target.attribs, "submit");
|
|
13865
|
+
return {
|
|
13866
|
+
call: binding?.method ? resolveMethod(formOwner.scopeId, binding.method) : void 0,
|
|
13867
|
+
event: createMiniProgramEventPayload(formOwner.target, "submit", {
|
|
13868
|
+
detail: { value: collectFormValues(form, scopes, pageScope, resolveComponent) },
|
|
13869
|
+
mark: event.mark
|
|
13870
|
+
})
|
|
13871
|
+
};
|
|
13709
13872
|
}
|
|
13710
13873
|
//#endregion
|
|
13711
13874
|
//#region ../../node_modules/.pnpm/entities@8.1.0/node_modules/entities/dist/decode-codepoint.js
|
|
@@ -16754,7 +16917,7 @@ const attributeEscapeRegex = /["&\u{A0}]/gu;
|
|
|
16754
16917
|
* following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
|
|
16755
16918
|
* @param data String to escape.
|
|
16756
16919
|
*/
|
|
16757
|
-
function escapeAttribute$
|
|
16920
|
+
function escapeAttribute$2(data) {
|
|
16758
16921
|
return escapeWithRegex(attributeEscapeRegex, data);
|
|
16759
16922
|
}
|
|
16760
16923
|
const textEscapeRegex = /[&<>\u{A0}]/gu;
|
|
@@ -16866,7 +17029,7 @@ function replaceQuotes(value) {
|
|
|
16866
17029
|
*/
|
|
16867
17030
|
function formatAttributes(attributes, options, xmlMode) {
|
|
16868
17031
|
if (!attributes) return "";
|
|
16869
|
-
const encode = (options.encodeEntities ?? options.decodeEntities) === false ? replaceQuotes : xmlMode || options.encodeEntities !== "utf8" ? encodeXML : escapeAttribute$
|
|
17032
|
+
const encode = (options.encodeEntities ?? options.decodeEntities) === false ? replaceQuotes : xmlMode || options.encodeEntities !== "utf8" ? encodeXML : escapeAttribute$2;
|
|
16870
17033
|
const isForeign = xmlMode === "foreign";
|
|
16871
17034
|
const showEmpty = !!(options.emptyAttrs ?? xmlMode);
|
|
16872
17035
|
let result = "";
|
|
@@ -17481,6 +17644,344 @@ function parseDocument(data, options) {
|
|
|
17481
17644
|
return handler.root;
|
|
17482
17645
|
}
|
|
17483
17646
|
//#endregion
|
|
17647
|
+
//#region ../../@weapp-core/shared/dist/rich-text.js
|
|
17648
|
+
const ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
17649
|
+
"a",
|
|
17650
|
+
"abbr",
|
|
17651
|
+
"address",
|
|
17652
|
+
"article",
|
|
17653
|
+
"aside",
|
|
17654
|
+
"b",
|
|
17655
|
+
"bdi",
|
|
17656
|
+
"bdo",
|
|
17657
|
+
"big",
|
|
17658
|
+
"blockquote",
|
|
17659
|
+
"br",
|
|
17660
|
+
"caption",
|
|
17661
|
+
"center",
|
|
17662
|
+
"cite",
|
|
17663
|
+
"code",
|
|
17664
|
+
"col",
|
|
17665
|
+
"colgroup",
|
|
17666
|
+
"dd",
|
|
17667
|
+
"del",
|
|
17668
|
+
"div",
|
|
17669
|
+
"dl",
|
|
17670
|
+
"dt",
|
|
17671
|
+
"em",
|
|
17672
|
+
"fieldset",
|
|
17673
|
+
"font",
|
|
17674
|
+
"h1",
|
|
17675
|
+
"h2",
|
|
17676
|
+
"h3",
|
|
17677
|
+
"h4",
|
|
17678
|
+
"h5",
|
|
17679
|
+
"h6",
|
|
17680
|
+
"header",
|
|
17681
|
+
"hr",
|
|
17682
|
+
"i",
|
|
17683
|
+
"img",
|
|
17684
|
+
"ins",
|
|
17685
|
+
"label",
|
|
17686
|
+
"legend",
|
|
17687
|
+
"li",
|
|
17688
|
+
"mark",
|
|
17689
|
+
"ol",
|
|
17690
|
+
"p",
|
|
17691
|
+
"pre",
|
|
17692
|
+
"q",
|
|
17693
|
+
"rt",
|
|
17694
|
+
"ruby",
|
|
17695
|
+
"s",
|
|
17696
|
+
"section",
|
|
17697
|
+
"small",
|
|
17698
|
+
"span",
|
|
17699
|
+
"strong",
|
|
17700
|
+
"sub",
|
|
17701
|
+
"sup",
|
|
17702
|
+
"table",
|
|
17703
|
+
"tbody",
|
|
17704
|
+
"td",
|
|
17705
|
+
"tfoot",
|
|
17706
|
+
"th",
|
|
17707
|
+
"thead",
|
|
17708
|
+
"tr",
|
|
17709
|
+
"tt",
|
|
17710
|
+
"u",
|
|
17711
|
+
"ul"
|
|
17712
|
+
]);
|
|
17713
|
+
const ALLOWED_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
17714
|
+
"abbr",
|
|
17715
|
+
"align",
|
|
17716
|
+
"alt",
|
|
17717
|
+
"axis",
|
|
17718
|
+
"bgcolor",
|
|
17719
|
+
"border",
|
|
17720
|
+
"cellpadding",
|
|
17721
|
+
"cellspacing",
|
|
17722
|
+
"class",
|
|
17723
|
+
"colspan",
|
|
17724
|
+
"dir",
|
|
17725
|
+
"height",
|
|
17726
|
+
"href",
|
|
17727
|
+
"id",
|
|
17728
|
+
"lang",
|
|
17729
|
+
"rowspan",
|
|
17730
|
+
"scope",
|
|
17731
|
+
"span",
|
|
17732
|
+
"start",
|
|
17733
|
+
"style",
|
|
17734
|
+
"summary",
|
|
17735
|
+
"target",
|
|
17736
|
+
"title",
|
|
17737
|
+
"type",
|
|
17738
|
+
"valign",
|
|
17739
|
+
"width"
|
|
17740
|
+
]);
|
|
17741
|
+
const URL_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "src"]);
|
|
17742
|
+
const ALLOWED_STYLE_PROPERTIES = /* @__PURE__ */ new Set([
|
|
17743
|
+
"background",
|
|
17744
|
+
"background-color",
|
|
17745
|
+
"border",
|
|
17746
|
+
"border-bottom",
|
|
17747
|
+
"border-color",
|
|
17748
|
+
"border-left",
|
|
17749
|
+
"border-radius",
|
|
17750
|
+
"border-right",
|
|
17751
|
+
"border-style",
|
|
17752
|
+
"border-top",
|
|
17753
|
+
"border-width",
|
|
17754
|
+
"color",
|
|
17755
|
+
"display",
|
|
17756
|
+
"font-family",
|
|
17757
|
+
"font-size",
|
|
17758
|
+
"font-style",
|
|
17759
|
+
"font-weight",
|
|
17760
|
+
"height",
|
|
17761
|
+
"letter-spacing",
|
|
17762
|
+
"line-height",
|
|
17763
|
+
"margin",
|
|
17764
|
+
"margin-bottom",
|
|
17765
|
+
"margin-left",
|
|
17766
|
+
"margin-right",
|
|
17767
|
+
"margin-top",
|
|
17768
|
+
"max-height",
|
|
17769
|
+
"max-width",
|
|
17770
|
+
"min-height",
|
|
17771
|
+
"min-width",
|
|
17772
|
+
"opacity",
|
|
17773
|
+
"overflow",
|
|
17774
|
+
"padding",
|
|
17775
|
+
"padding-bottom",
|
|
17776
|
+
"padding-left",
|
|
17777
|
+
"padding-right",
|
|
17778
|
+
"padding-top",
|
|
17779
|
+
"text-align",
|
|
17780
|
+
"text-decoration",
|
|
17781
|
+
"text-indent",
|
|
17782
|
+
"text-overflow",
|
|
17783
|
+
"text-transform",
|
|
17784
|
+
"vertical-align",
|
|
17785
|
+
"white-space",
|
|
17786
|
+
"width",
|
|
17787
|
+
"word-break",
|
|
17788
|
+
"word-wrap"
|
|
17789
|
+
]);
|
|
17790
|
+
function isRecord(value) {
|
|
17791
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
17792
|
+
}
|
|
17793
|
+
function isSafeUrl(value, attribute) {
|
|
17794
|
+
const normalized = Array.from(value).filter((character) => character.charCodeAt(0) > 32).join("").toLowerCase();
|
|
17795
|
+
if (!normalized || normalized.startsWith("#") || normalized.startsWith("/") || normalized.startsWith("./") || normalized.startsWith("../")) return true;
|
|
17796
|
+
if (/^(?:https?:|mailto:|tel:)/.test(normalized)) return true;
|
|
17797
|
+
return attribute === "src" && /^data:image\/(?:gif|jpe?g|png|webp);base64,/.test(normalized);
|
|
17798
|
+
}
|
|
17799
|
+
function isSafeStyleValue(value) {
|
|
17800
|
+
const normalized = value.toLowerCase().replace(/\s+/g, "");
|
|
17801
|
+
return !normalized.includes("url(") && !normalized.includes("expression(") && !normalized.includes("javascript:") && !normalized.includes("behavior:") && !normalized.includes("-moz-binding");
|
|
17802
|
+
}
|
|
17803
|
+
function sanitizeRichTextStyle(value) {
|
|
17804
|
+
const source = isRecord(value) ? Object.entries(value).map(([property, propertyValue]) => `${property}:${String(propertyValue)}`).join(";") : String(value ?? "");
|
|
17805
|
+
const declarations = [];
|
|
17806
|
+
for (const declaration of source.split(";")) {
|
|
17807
|
+
const separator = declaration.indexOf(":");
|
|
17808
|
+
if (separator <= 0) continue;
|
|
17809
|
+
const property = declaration.slice(0, separator).trim().toLowerCase();
|
|
17810
|
+
const propertyValue = declaration.slice(separator + 1).trim();
|
|
17811
|
+
if (ALLOWED_STYLE_PROPERTIES.has(property) && propertyValue && isSafeStyleValue(propertyValue)) declarations.push(`${property}: ${propertyValue}`);
|
|
17812
|
+
}
|
|
17813
|
+
return declarations.join("; ");
|
|
17814
|
+
}
|
|
17815
|
+
function sanitizeRichTextAttributes(value, tagName) {
|
|
17816
|
+
if (!isRecord(value)) return {};
|
|
17817
|
+
const attributes = {};
|
|
17818
|
+
for (const [rawName, rawValue] of Object.entries(value)) {
|
|
17819
|
+
const name = rawName.trim().toLowerCase();
|
|
17820
|
+
if (name.startsWith("on") || name === "srcdoc") continue;
|
|
17821
|
+
if (!ALLOWED_ATTRIBUTES.has(name) && name !== "src" && !name.startsWith("aria-") && !name.startsWith("data-")) continue;
|
|
17822
|
+
if (name === "src" && tagName !== "img") continue;
|
|
17823
|
+
const serialized = name === "style" ? sanitizeRichTextStyle(rawValue) : String(rawValue ?? "");
|
|
17824
|
+
if (!serialized || URL_ATTRIBUTES.has(name) && !isSafeUrl(serialized, name)) continue;
|
|
17825
|
+
attributes[name] = serialized;
|
|
17826
|
+
}
|
|
17827
|
+
if (tagName === "a") attributes.rel = "noopener noreferrer";
|
|
17828
|
+
return attributes;
|
|
17829
|
+
}
|
|
17830
|
+
function convertSourceNode(value) {
|
|
17831
|
+
if (!isRecord(value)) return [];
|
|
17832
|
+
if (value.type === "text" || !value.name && typeof value.text === "string") return [{
|
|
17833
|
+
type: "text",
|
|
17834
|
+
text: String(value.text ?? "")
|
|
17835
|
+
}];
|
|
17836
|
+
const children = Array.isArray(value.children) ? value.children.flatMap(convertSourceNode) : [];
|
|
17837
|
+
const name = String(value.name ?? "").toLowerCase();
|
|
17838
|
+
if (!ALLOWED_TAGS.has(name)) return children;
|
|
17839
|
+
return [{
|
|
17840
|
+
type: "element",
|
|
17841
|
+
name,
|
|
17842
|
+
attrs: sanitizeRichTextAttributes(value.attrs, name),
|
|
17843
|
+
children
|
|
17844
|
+
}];
|
|
17845
|
+
}
|
|
17846
|
+
function convertParsedNode(node) {
|
|
17847
|
+
if (node.type === "text") return [{
|
|
17848
|
+
type: "text",
|
|
17849
|
+
text: node.data
|
|
17850
|
+
}];
|
|
17851
|
+
if (node.type !== "tag") return [];
|
|
17852
|
+
const element = node;
|
|
17853
|
+
const children = element.children.flatMap(convertParsedNode);
|
|
17854
|
+
const name = element.name.toLowerCase();
|
|
17855
|
+
if (!ALLOWED_TAGS.has(name)) return children;
|
|
17856
|
+
return [{
|
|
17857
|
+
type: "element",
|
|
17858
|
+
name,
|
|
17859
|
+
attrs: sanitizeRichTextAttributes(element.attribs, name),
|
|
17860
|
+
children
|
|
17861
|
+
}];
|
|
17862
|
+
}
|
|
17863
|
+
function normalizeRichTextNodes(value) {
|
|
17864
|
+
if (typeof value === "string") return parseDocument(value, {
|
|
17865
|
+
decodeEntities: true,
|
|
17866
|
+
lowerCaseAttributeNames: true,
|
|
17867
|
+
lowerCaseTags: true
|
|
17868
|
+
}).children.flatMap(convertParsedNode);
|
|
17869
|
+
return (Array.isArray(value) ? value : [value]).flatMap(convertSourceNode);
|
|
17870
|
+
}
|
|
17871
|
+
//#endregion
|
|
17872
|
+
//#region ../../mpcore/packages/simulator/src/view/richText.ts
|
|
17873
|
+
function materializeNode(node) {
|
|
17874
|
+
if (node.type === "text") return {
|
|
17875
|
+
type: "text",
|
|
17876
|
+
data: node.text
|
|
17877
|
+
};
|
|
17878
|
+
for (const name of Object.keys(node.attrs)) if (name.startsWith("data-sim-")) delete node.attrs[name];
|
|
17879
|
+
return {
|
|
17880
|
+
type: "tag",
|
|
17881
|
+
name: node.name,
|
|
17882
|
+
attribs: node.attrs,
|
|
17883
|
+
children: node.children.map(materializeNode)
|
|
17884
|
+
};
|
|
17885
|
+
}
|
|
17886
|
+
/** 富文本直接成为已渲染节点,不能再进入 WXML 表达式或组件处理流程。 */
|
|
17887
|
+
function renderRichTextNodes(value) {
|
|
17888
|
+
return normalizeRichTextNodes(value).map(materializeNode);
|
|
17889
|
+
}
|
|
17890
|
+
//#endregion
|
|
17891
|
+
//#region ../../mpcore/packages/simulator/src/view/templateIncludes.ts
|
|
17892
|
+
/** 展开 include 的可渲染内容,并保留嵌套引用的来源文件。 */
|
|
17893
|
+
function expandTemplateIncludes(root, filePath, loadTemplate) {
|
|
17894
|
+
const owners = /* @__PURE__ */ new WeakMap();
|
|
17895
|
+
const expand = (node, owner, stack, included = false) => {
|
|
17896
|
+
if (included && (isTemplateDefinition(node) || node.name === "wxs")) return;
|
|
17897
|
+
owners.set(node, owner);
|
|
17898
|
+
if (node.name === "include" && node.attribs?.src) {
|
|
17899
|
+
const source = node.attribs.src;
|
|
17900
|
+
const loaded = loadTemplate(owner, source.endsWith(".wxml") ? source : `${source}.wxml`);
|
|
17901
|
+
if (stack.includes(loaded.filePath)) throw new Error("Circular WXML include is not supported");
|
|
17902
|
+
const { src: _src, ...attributes } = node.attribs;
|
|
17903
|
+
node.name = "block";
|
|
17904
|
+
node.attribs = attributes;
|
|
17905
|
+
node.children = (loaded.root.children ?? []).flatMap((child) => {
|
|
17906
|
+
const expanded = expand(child, loaded.filePath, [...stack, loaded.filePath], true);
|
|
17907
|
+
return expanded ? [expanded] : [];
|
|
17908
|
+
});
|
|
17909
|
+
return node;
|
|
17910
|
+
}
|
|
17911
|
+
node.children = node.children?.flatMap((child) => {
|
|
17912
|
+
const expanded = expand(child, owner, stack, included);
|
|
17913
|
+
return expanded ? [expanded] : [];
|
|
17914
|
+
});
|
|
17915
|
+
return node;
|
|
17916
|
+
};
|
|
17917
|
+
expand(root, filePath, [filePath]);
|
|
17918
|
+
return owners;
|
|
17919
|
+
}
|
|
17920
|
+
//#endregion
|
|
17921
|
+
//#region ../../mpcore/packages/simulator/src/view/templateImports.ts
|
|
17922
|
+
function createImportedTemplateState(root, filePath, loadImport, loadWxs) {
|
|
17923
|
+
const documents = /* @__PURE__ */ new Map();
|
|
17924
|
+
const definitionScopes = /* @__PURE__ */ new Map();
|
|
17925
|
+
const definitionWxsScopes = /* @__PURE__ */ new Map();
|
|
17926
|
+
const collect = (node, owner) => {
|
|
17927
|
+
const existing = documents.get(owner);
|
|
17928
|
+
if (existing) return existing;
|
|
17929
|
+
const owners = expandTemplateIncludes(node, owner, loadImport);
|
|
17930
|
+
const state = createTemplateRenderState(node);
|
|
17931
|
+
const wxsModules = Object.create(null);
|
|
17932
|
+
const ownDefinitions = new Map(state.definitions);
|
|
17933
|
+
const document = {
|
|
17934
|
+
state,
|
|
17935
|
+
exports: ownDefinitions
|
|
17936
|
+
};
|
|
17937
|
+
documents.set(owner, document);
|
|
17938
|
+
const visit = (child) => {
|
|
17939
|
+
const sourceOwner = owners.get(child) ?? owner;
|
|
17940
|
+
if (child.name === "wxs" && loadWxs) {
|
|
17941
|
+
const name = child.attribs?.module;
|
|
17942
|
+
if (!name || !/^[a-z_$][\w$]*$/i.test(name) || [
|
|
17943
|
+
"__proto__",
|
|
17944
|
+
"constructor",
|
|
17945
|
+
"prototype"
|
|
17946
|
+
].includes(name)) throw new Error(`Invalid WXS module name in ${owner}: ${String(name)}`);
|
|
17947
|
+
if (Object.hasOwn(wxsModules, name)) throw new Error(`Duplicate WXS module in ${owner}: ${name}`);
|
|
17948
|
+
wxsModules[name] = loadWxs(sourceOwner, child);
|
|
17949
|
+
return;
|
|
17950
|
+
}
|
|
17951
|
+
if (child.name === "import" && child.attribs?.src) {
|
|
17952
|
+
const source = child.attribs.src;
|
|
17953
|
+
const imported = loadImport(sourceOwner, source.endsWith(".wxml") ? source : `${source}.wxml`);
|
|
17954
|
+
const importedDocument = collect(imported.root, imported.filePath);
|
|
17955
|
+
for (const [name, definition] of importedDocument.exports) state.definitions.set(name, definition);
|
|
17956
|
+
}
|
|
17957
|
+
for (const nested of child.children ?? []) visit(nested);
|
|
17958
|
+
};
|
|
17959
|
+
visit(node);
|
|
17960
|
+
if (Object.keys(wxsModules).length) state.wxsModules = wxsModules;
|
|
17961
|
+
for (const [name, definition] of ownDefinitions) {
|
|
17962
|
+
state.definitions.set(name, definition);
|
|
17963
|
+
definitionScopes.set(definition, state.definitions);
|
|
17964
|
+
if (state.wxsModules) definitionWxsScopes.set(definition, state.wxsModules);
|
|
17965
|
+
}
|
|
17966
|
+
state.definitionScopes = definitionScopes;
|
|
17967
|
+
state.definitionWxsScopes = definitionWxsScopes;
|
|
17968
|
+
return document;
|
|
17969
|
+
};
|
|
17970
|
+
return collect(root, filePath).state;
|
|
17971
|
+
}
|
|
17972
|
+
//#endregion
|
|
17973
|
+
//#region ../../mpcore/packages/simulator/src/view/templateText.ts
|
|
17974
|
+
function interpolateTemplateText(input, data, emptyNull = false) {
|
|
17975
|
+
let output = "";
|
|
17976
|
+
let offset = 0;
|
|
17977
|
+
for (const range of templateInterpolations(input)) {
|
|
17978
|
+
const value = resolveTemplateExpression(data, range.expression);
|
|
17979
|
+
output += input.slice(offset, range.start) + (value === void 0 || emptyNull && value === null ? "" : String(value));
|
|
17980
|
+
offset = range.end;
|
|
17981
|
+
}
|
|
17982
|
+
return output + input.slice(offset);
|
|
17983
|
+
}
|
|
17984
|
+
//#endregion
|
|
17484
17985
|
//#region ../../mpcore/packages/simulator/src/view/templateAttributes.ts
|
|
17485
17986
|
function decodeAttribute(raw, quote) {
|
|
17486
17987
|
const source = raw.replaceAll(`\\${quote}`, quote);
|
|
@@ -17540,7 +18041,7 @@ function parseWxsTemplateDocument(templateSource) {
|
|
|
17540
18041
|
});
|
|
17541
18042
|
const masked = maskTemplateAttributes(source);
|
|
17542
18043
|
const document = parseDocument(`<page>${masked.source}</page>`, {
|
|
17543
|
-
xmlMode:
|
|
18044
|
+
xmlMode: true,
|
|
17544
18045
|
decodeEntities: false,
|
|
17545
18046
|
lowerCaseAttributeNames: false,
|
|
17546
18047
|
lowerCaseTags: false,
|
|
@@ -17598,7 +18099,7 @@ function collectDataset(node, source) {
|
|
|
17598
18099
|
function escapeText$2(text) {
|
|
17599
18100
|
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
17600
18101
|
}
|
|
17601
|
-
function escapeAttribute$
|
|
18102
|
+
function escapeAttribute$1(value) {
|
|
17602
18103
|
return escapeText$2(value).replaceAll("\"", """);
|
|
17603
18104
|
}
|
|
17604
18105
|
function cloneNode(node) {
|
|
@@ -17643,7 +18144,7 @@ function serializeDomNode$1(node) {
|
|
|
17643
18144
|
if (node.type === "root") return (node.children ?? []).map(serializeDomNode$1).join("");
|
|
17644
18145
|
const tagName = node.name ?? "";
|
|
17645
18146
|
if (!tagName) return (node.children ?? []).map(serializeDomNode$1).join("");
|
|
17646
|
-
return `<${tagName}${Object.entries(node.attribs ?? {}).map(([key, value]) => ` ${key}="${escapeAttribute$
|
|
18147
|
+
return `<${tagName}${Object.entries(node.attribs ?? {}).map(([key, value]) => ` ${key}="${escapeAttribute$1(value)}"`).join("")}>${(node.children ?? []).map(serializeDomNode$1).join("")}</${tagName}>`;
|
|
17647
18148
|
}
|
|
17648
18149
|
function isTagNode(node) {
|
|
17649
18150
|
return node.type === "tag" && typeof node.name === "string";
|
|
@@ -17662,7 +18163,7 @@ function resolveComponentAttributeValue(value, scope) {
|
|
|
17662
18163
|
}
|
|
17663
18164
|
return interpolateTemplate$1(value, wxsScopeData(scope));
|
|
17664
18165
|
}
|
|
17665
|
-
function applyNodeBindings(node, scope) {
|
|
18166
|
+
function applyNodeBindings(node, scope, richText = false) {
|
|
17666
18167
|
if (!isTagNode(node)) {
|
|
17667
18168
|
if (node.type === "text" && typeof node.data === "string") node.data = interpolateTemplateText(node.data, wxsScopeData(scope));
|
|
17668
18169
|
return;
|
|
@@ -17670,6 +18171,7 @@ function applyNodeBindings(node, scope) {
|
|
|
17670
18171
|
node.attribs ??= {};
|
|
17671
18172
|
node.attribs["data-sim-scope"] = scope.getScopeId();
|
|
17672
18173
|
for (const key of STRUCTURAL_ATTRS) delete node.attribs[key];
|
|
18174
|
+
if (richText) node.children = [];
|
|
17673
18175
|
let dataset;
|
|
17674
18176
|
for (const [key, value] of Object.entries({ ...node.attribs })) {
|
|
17675
18177
|
if (EVENT_BINDING_ATTRS.includes(key)) {
|
|
@@ -17677,6 +18179,8 @@ function applyNodeBindings(node, scope) {
|
|
|
17677
18179
|
continue;
|
|
17678
18180
|
}
|
|
17679
18181
|
const resolvedValue = typeof value === "string" ? resolveAttributeValue(value, scope) : value;
|
|
18182
|
+
if (key === "value") setNativePickerValue(node, resolvedValue);
|
|
18183
|
+
if (richText && key === "nodes") node.children = renderRichTextNodes(resolvedValue);
|
|
17680
18184
|
node.attribs[key] = String(resolvedValue ?? "");
|
|
17681
18185
|
if (isDatasetAttribute(key)) {
|
|
17682
18186
|
dataset ??= {};
|
|
@@ -17703,8 +18207,7 @@ function createLoopScope(scope, itemName, indexName, item, index) {
|
|
|
17703
18207
|
//#endregion
|
|
17704
18208
|
//#region ../../mpcore/packages/simulator/src/runtime/render/component.ts
|
|
17705
18209
|
function resolveComponentRegistryEntry(context, ownerJsonPath, ownerFilePath, alias, genericComponentBasePath) {
|
|
17706
|
-
const
|
|
17707
|
-
const componentBasePath = genericComponentBasePath ?? usingComponents.get(alias);
|
|
18210
|
+
const componentBasePath = genericComponentBasePath ?? resolveUsingComponent(context, ownerJsonPath, ownerFilePath, alias);
|
|
17708
18211
|
if (!componentBasePath) return null;
|
|
17709
18212
|
const filePath = `${componentBasePath}.js`;
|
|
17710
18213
|
const templatePath = `${componentBasePath}.wxml`;
|
|
@@ -17725,30 +18228,25 @@ function readComponentConfig(artifactSource, jsonPath) {
|
|
|
17725
18228
|
return {};
|
|
17726
18229
|
}
|
|
17727
18230
|
}
|
|
17728
|
-
function
|
|
18231
|
+
function resolveUsingComponent(context, ownerJsonPath, ownerFilePath, alias) {
|
|
17729
18232
|
try {
|
|
17730
18233
|
const usingComponents = readComponentConfig(context.artifactSource, ownerJsonPath).usingComponents;
|
|
17731
|
-
if (!usingComponents || typeof usingComponents !== "object" || Array.isArray(usingComponents)) return
|
|
17732
|
-
const
|
|
17733
|
-
|
|
17734
|
-
|
|
17735
|
-
const basePath = resolvePluginRequest(context.project.plugins, rawPath, "publicComponent")?.resourcePath ?? resolveMiniProgramComponent(ownerFilePath, rawPath, context.project.miniprogramRootPath, (candidate) => context.artifactSource.readText(candidate) !== void 0);
|
|
17736
|
-
resolved.set(alias, basePath.replace(LEADING_SLASH_RE$4, ""));
|
|
17737
|
-
}
|
|
17738
|
-
return resolved;
|
|
18234
|
+
if (!usingComponents || typeof usingComponents !== "object" || Array.isArray(usingComponents)) return;
|
|
18235
|
+
const rawPath = usingComponents[alias];
|
|
18236
|
+
if (typeof rawPath !== "string") return;
|
|
18237
|
+
return (resolvePluginRequest(context.project.plugins, rawPath, "publicComponent")?.resourcePath ?? resolveMiniProgramComponent(ownerFilePath, rawPath, context.project.miniprogramRootPath, (candidate) => context.artifactSource.has(candidate))).replace(LEADING_SLASH_RE$4, "");
|
|
17739
18238
|
} catch {
|
|
17740
|
-
return
|
|
18239
|
+
return;
|
|
17741
18240
|
}
|
|
17742
18241
|
}
|
|
17743
18242
|
function resolveComponentGenerics(context, hostNode, ownerJsonPath, ownerFilePath, componentFilePath, ownerGenerics) {
|
|
17744
18243
|
const componentJsonPath = path.resolve(context.project.miniprogramRootPath, `${componentFilePath.replace(JS_FILE_RE, "")}.json`);
|
|
17745
18244
|
const componentGenerics = readComponentConfig(context.artifactSource, componentJsonPath).componentGenerics;
|
|
17746
18245
|
if (!componentGenerics || typeof componentGenerics !== "object" || Array.isArray(componentGenerics)) return;
|
|
17747
|
-
const ownerComponents = resolveUsingComponents(context, ownerJsonPath, ownerFilePath);
|
|
17748
18246
|
const resolved = /* @__PURE__ */ new Map();
|
|
17749
18247
|
for (const [genericName, definition] of Object.entries(componentGenerics)) {
|
|
17750
18248
|
const selectedAlias = hostNode.attribs?.[`generic:${genericName}`];
|
|
17751
|
-
const selectedPath = selectedAlias ? ownerGenerics?.get(selectedAlias) ??
|
|
18249
|
+
const selectedPath = selectedAlias ? ownerGenerics?.get(selectedAlias) ?? resolveUsingComponent(context, ownerJsonPath, ownerFilePath, selectedAlias) : void 0;
|
|
17752
18250
|
if (selectedPath) {
|
|
17753
18251
|
resolved.set(genericName, selectedPath);
|
|
17754
18252
|
continue;
|
|
@@ -17799,7 +18297,6 @@ function resolveComponentProperties(clonedNode, scope, definition) {
|
|
|
17799
18297
|
};
|
|
17800
18298
|
}
|
|
17801
18299
|
function createRuntimeComponentInstance(componentScopeId, context, componentEntry, nextProperties, ownerScopeId, renderTemplate, bindEventsBeforeProperties = false) {
|
|
17802
|
-
const componentProperties = Object.keys(componentEntry.definition.methods ?? {}).some((key) => key.startsWith("__weapp_vite_")) || Object.hasOwn(componentEntry.definition.properties ?? {}, "__wvSlotOwnerId") ? Object.fromEntries(Object.keys(componentEntry.definition.properties ?? {}).filter((key) => Object.hasOwn(nextProperties, key)).map((key) => [key, nextProperties[key]])) : nextProperties;
|
|
17803
18300
|
const instanceOptions = {
|
|
17804
18301
|
definition: componentEntry.definition,
|
|
17805
18302
|
requestRender: (callback) => context.session.requestRender(callback)
|
|
@@ -17821,7 +18318,7 @@ function createRuntimeComponentInstance(componentScopeId, context, componentEntr
|
|
|
17821
18318
|
runComponentLifecycle(componentInstance, "created");
|
|
17822
18319
|
if (bindEventsBeforeProperties) instanceOptions.triggerEvent = buildComponentTrigger(componentScopeId, context);
|
|
17823
18320
|
componentInstance.__propertySnapshots = Object.fromEntries(Object.entries(componentInstance.properties).map(([key, propertyValue]) => [key, cloneValue$1(propertyValue)]));
|
|
17824
|
-
syncComponentProperties(componentInstance, componentInstance.__definition__ ?? componentEntry.definition,
|
|
18321
|
+
syncComponentProperties(componentInstance, componentInstance.__definition__ ?? componentEntry.definition, nextProperties, {}, [], renderTemplate);
|
|
17825
18322
|
if (!bindEventsBeforeProperties) instanceOptions.triggerEvent = buildComponentTrigger(componentScopeId, context);
|
|
17826
18323
|
return componentInstance;
|
|
17827
18324
|
} catch (error) {
|
|
@@ -18031,8 +18528,10 @@ function renderNodeTree(node, scope, context, ownerJsonPath, ownerFilePath, inst
|
|
|
18031
18528
|
renderPass.componentRoots.set(componentScopeId, renderedComponentRoot);
|
|
18032
18529
|
return renderedComponentRoot;
|
|
18033
18530
|
}
|
|
18034
|
-
|
|
18531
|
+
const richText = clonedNode.name === "rich-text";
|
|
18532
|
+
applyNodeBindings(clonedNode, scope, richText);
|
|
18035
18533
|
clonedNode.attribs["data-sim-node"] = instancePath;
|
|
18534
|
+
if (richText) return clonedNode;
|
|
18036
18535
|
clonedNode.children = renderChildren(clonedNode.children ?? [], scope, context, ownerJsonPath, ownerFilePath, `${instancePath}/${clonedNode.name}`, renderPass, templateRenderState, clonedNode);
|
|
18037
18536
|
return clonedNode;
|
|
18038
18537
|
}
|
|
@@ -18097,14 +18596,7 @@ function reconcileRuntimePageTree(context, page, bindingsOnly = false) {
|
|
|
18097
18596
|
}), scopeIds);
|
|
18098
18597
|
if (attached === "restart") continue;
|
|
18099
18598
|
const canFinalize = !pageAttaching && !hasPendingComponentAttachments(instances);
|
|
18100
|
-
const
|
|
18101
|
-
for (const [scopeId, instance] of removed) if (isComponentAttached(instance)) runComponentLifecycle(instance, "detached");
|
|
18102
|
-
else scheduleDiscardedComponentReady(context.componentCache, scopeId, instance);
|
|
18103
|
-
const relationsChanged = canFinalize && syncComponentRelations(context.componentCache, renderPass.seenComponentScopes, pageScopeId);
|
|
18104
|
-
for (const [scopeId] of removed) {
|
|
18105
|
-
context.componentCache.delete(scopeId);
|
|
18106
|
-
context.componentScopes.delete(scopeId);
|
|
18107
|
-
}
|
|
18599
|
+
const relationsChanged = canFinalize && reconcileRemovedComponents(context.componentCache, context.componentScopes, renderPass.seenComponentScopes, pageScopeId);
|
|
18108
18600
|
if (pageAttached || attached || relationsChanged) continue;
|
|
18109
18601
|
if (canFinalize && !isPageBeforeReady(page)) flushDiscardedComponentReady(context.componentCache, pageScopeId, (instance) => runComponentLifecycle(instance, "ready"));
|
|
18110
18602
|
if (canFinalize && !isPageBeforeReady(page) && flushComponentReady(instances, (instance) => {
|
|
@@ -18890,7 +19382,13 @@ function invokePreparedNavigationApi(prepare, option) {
|
|
|
18890
19382
|
//#region ../../mpcore/packages/simulator/src/kernel/artifactSource.ts
|
|
18891
19383
|
function createFileSystemArtifactSource() {
|
|
18892
19384
|
return {
|
|
18893
|
-
has
|
|
19385
|
+
has(filePath) {
|
|
19386
|
+
try {
|
|
19387
|
+
return fs.statSync(filePath).isFile();
|
|
19388
|
+
} catch {
|
|
19389
|
+
return false;
|
|
19390
|
+
}
|
|
19391
|
+
},
|
|
18894
19392
|
readText(filePath) {
|
|
18895
19393
|
try {
|
|
18896
19394
|
return fs.readFileSync(filePath, "utf8");
|
|
@@ -19035,6 +19533,62 @@ var RuntimeKernel = class {
|
|
|
19035
19533
|
}
|
|
19036
19534
|
};
|
|
19037
19535
|
//#endregion
|
|
19536
|
+
//#region ../../mpcore/packages/simulator/src/kernel/renderQueue.ts
|
|
19537
|
+
/** 两类宿主共享提交、错误诊断与等待回调边界,失败批次不自动重试。 */
|
|
19538
|
+
var RuntimeRenderQueue = class {
|
|
19539
|
+
options;
|
|
19540
|
+
closed = false;
|
|
19541
|
+
pending = false;
|
|
19542
|
+
running = false;
|
|
19543
|
+
callbacks = [];
|
|
19544
|
+
constructor(options) {
|
|
19545
|
+
this.options = options;
|
|
19546
|
+
}
|
|
19547
|
+
close() {
|
|
19548
|
+
this.closed = true;
|
|
19549
|
+
this.pending = false;
|
|
19550
|
+
this.callbacks.length = 0;
|
|
19551
|
+
}
|
|
19552
|
+
request(callback) {
|
|
19553
|
+
if (this.isClosed()) return;
|
|
19554
|
+
if (callback) this.callbacks.push(callback);
|
|
19555
|
+
if (this.pending) return;
|
|
19556
|
+
this.pending = true;
|
|
19557
|
+
if (this.running) return;
|
|
19558
|
+
Promise.resolve().then(async () => {
|
|
19559
|
+
if (this.isClosed()) return;
|
|
19560
|
+
this.pending = false;
|
|
19561
|
+
this.running = true;
|
|
19562
|
+
const callbacks = this.callbacks.splice(0);
|
|
19563
|
+
try {
|
|
19564
|
+
const rendered = this.options.render();
|
|
19565
|
+
if (rendered && typeof rendered.then === "function") await rendered;
|
|
19566
|
+
} catch (error) {
|
|
19567
|
+
this.options.onError(error);
|
|
19568
|
+
callbacks.push(...this.callbacks.splice(0));
|
|
19569
|
+
this.pending = false;
|
|
19570
|
+
} finally {
|
|
19571
|
+
for (const callback of callbacks) {
|
|
19572
|
+
if (this.isClosed()) break;
|
|
19573
|
+
try {
|
|
19574
|
+
callback();
|
|
19575
|
+
} catch (error) {
|
|
19576
|
+
this.options.onError(error);
|
|
19577
|
+
}
|
|
19578
|
+
}
|
|
19579
|
+
this.running = false;
|
|
19580
|
+
if (this.pending && !this.isClosed()) {
|
|
19581
|
+
this.pending = false;
|
|
19582
|
+
this.request();
|
|
19583
|
+
}
|
|
19584
|
+
}
|
|
19585
|
+
});
|
|
19586
|
+
}
|
|
19587
|
+
isClosed() {
|
|
19588
|
+
return this.closed || this.options.isClosed();
|
|
19589
|
+
}
|
|
19590
|
+
};
|
|
19591
|
+
//#endregion
|
|
19038
19592
|
//#region ../../mpcore/packages/simulator/src/project/resolveRoutes.ts
|
|
19039
19593
|
const LEADING_SLASH_RE$3 = /^\/+/;
|
|
19040
19594
|
const TRAILING_SLASH_RE$1 = /\/+$/;
|
|
@@ -19235,32 +19789,20 @@ function loadProject(projectPath) {
|
|
|
19235
19789
|
});
|
|
19236
19790
|
}
|
|
19237
19791
|
//#endregion
|
|
19238
|
-
//#region ../../mpcore/packages/simulator/src/view/
|
|
19239
|
-
function
|
|
19240
|
-
return
|
|
19792
|
+
//#region ../../mpcore/packages/simulator/src/view/nodeSerialization.ts
|
|
19793
|
+
function escapeText$1(text) {
|
|
19794
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
19241
19795
|
}
|
|
19242
|
-
|
|
19243
|
-
|
|
19244
|
-
|
|
19245
|
-
|
|
19246
|
-
const
|
|
19247
|
-
return {
|
|
19248
|
-
|
|
19249
|
-
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
dataset: isOrigin ? event.currentTarget?.dataset ?? event.dataset ?? dataset : dataset,
|
|
19253
|
-
id: isOrigin ? event.currentTarget?.id ?? event.id ?? nodeId : nodeId
|
|
19254
|
-
},
|
|
19255
|
-
detail: event.detail,
|
|
19256
|
-
mark: event.mark,
|
|
19257
|
-
target: {
|
|
19258
|
-
dataset: event.target?.dataset ?? event.dataset ?? (isOrigin ? dataset : collectNodeDataset(origin)),
|
|
19259
|
-
id: event.target?.id ?? event.id ?? origin.attribs?.id ?? ""
|
|
19260
|
-
},
|
|
19261
|
-
timeStamp: Date.now(),
|
|
19262
|
-
type: eventName
|
|
19263
|
-
};
|
|
19796
|
+
function serializeNode(node) {
|
|
19797
|
+
if (node.type === "text") return escapeText$1(node.data ?? "");
|
|
19798
|
+
if (node.type !== "tag") return (node.children ?? []).map(serializeNode).join("");
|
|
19799
|
+
if (node.name === "page") return (node.children ?? []).filter((child) => !(child.type === "tag" && (child.name === "import" || child.name === "wxs"))).map(serializeNode).join("");
|
|
19800
|
+
const attrs = Object.entries(node.attribs ?? {}).filter(([key]) => !key.startsWith("data-sim-")).map(([key, value]) => ` ${key}="${escapeText$1(value).replaceAll("\"", """)}"`).join("");
|
|
19801
|
+
return `<${node.name ?? ""}${attrs}>${(node.children ?? []).map(serializeNode).join("")}</${node.name ?? ""}>`;
|
|
19802
|
+
}
|
|
19803
|
+
function collectNodeText$1(node) {
|
|
19804
|
+
if (node.type === "text") return node.data ?? "";
|
|
19805
|
+
return (node.children ?? []).map(collectNodeText$1).join("");
|
|
19264
19806
|
}
|
|
19265
19807
|
//#endregion
|
|
19266
19808
|
//#region ../../node_modules/.pnpm/boolbase@2.0.0/node_modules/boolbase/dist/index.js
|
|
@@ -20753,10 +21295,10 @@ function queryInspectionSelectorAll(root, selector) {
|
|
|
20753
21295
|
}
|
|
20754
21296
|
//#endregion
|
|
20755
21297
|
//#region ../../node_modules/.pnpm/whynot@5.0.0/node_modules/whynot/dist/whynot.umd.cjs
|
|
20756
|
-
var require_whynot_umd = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
21298
|
+
var require_whynot_umd = /* @__PURE__ */ __commonJSMin(((exports, module, this$4) => {
|
|
20757
21299
|
(function(t, s) {
|
|
20758
21300
|
"object" == typeof exports && "undefined" != typeof module ? s(exports) : "function" == typeof define && define.amd ? define(["exports"], s) : s((t = "undefined" != typeof globalThis ? globalThis : t || self).whynot = {});
|
|
20759
|
-
})(
|
|
21301
|
+
})(this$4, (function(t) {
|
|
20760
21302
|
"use strict";
|
|
20761
21303
|
function s(t, s, i, r) {
|
|
20762
21304
|
const n = {
|
|
@@ -21104,10 +21646,10 @@ var require_whynot_umd = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
21104
21646
|
}));
|
|
21105
21647
|
//#endregion
|
|
21106
21648
|
//#region ../../node_modules/.pnpm/xspattern@3.1.0/node_modules/xspattern/dist/xspattern.umd.cjs
|
|
21107
|
-
var require_xspattern_umd = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
21649
|
+
var require_xspattern_umd = /* @__PURE__ */ __commonJSMin(((exports, module, this$3) => {
|
|
21108
21650
|
(function(A, B) {
|
|
21109
21651
|
"object" == typeof exports && "undefined" != typeof module ? B(exports, require_whynot_umd()) : "function" == typeof define && define.amd ? define(["exports", "whynot"], B) : B((A = "undefined" != typeof globalThis ? globalThis : A || self).xspattern = {}, A.whynot);
|
|
21110
|
-
})(
|
|
21652
|
+
})(this$3, (function(A, B) {
|
|
21111
21653
|
"use strict";
|
|
21112
21654
|
function a(A) {
|
|
21113
21655
|
return (B) => B === A;
|
|
@@ -22404,10 +22946,10 @@ var require_xspattern_umd = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
22404
22946
|
}));
|
|
22405
22947
|
//#endregion
|
|
22406
22948
|
//#region ../../node_modules/.pnpm/prsc@4.0.0/node_modules/prsc/dist/prsc.umd.cjs
|
|
22407
|
-
var require_prsc_umd = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
22949
|
+
var require_prsc_umd = /* @__PURE__ */ __commonJSMin(((exports, module, this$2) => {
|
|
22408
22950
|
(function(n, t) {
|
|
22409
22951
|
"object" == typeof exports && "undefined" != typeof module ? t(exports) : "function" == typeof define && define.amd ? define(["exports"], t) : t((n = "undefined" != typeof globalThis ? globalThis : n || self).prsc = {});
|
|
22410
|
-
})(
|
|
22952
|
+
})(this$2, (function(n) {
|
|
22411
22953
|
"use strict";
|
|
22412
22954
|
function t(n, t) {
|
|
22413
22955
|
return {
|
|
@@ -22650,12 +23192,12 @@ var require_prsc_umd = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
22650
23192
|
}));
|
|
22651
23193
|
//#endregion
|
|
22652
23194
|
//#region ../../mpcore/packages/simulator/src/view/xpath.ts
|
|
22653
|
-
var import_fontoxpath = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
23195
|
+
var import_fontoxpath = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module, this$1) => {
|
|
22654
23196
|
(function(root, factory) {
|
|
22655
23197
|
if (typeof define === "function" && define.amd) define(["xspattern", "prsc"], factory);
|
|
22656
23198
|
else if (typeof exports === "object") module.exports = factory(require_xspattern_umd(), require_prsc_umd());
|
|
22657
23199
|
else root.fontoxpath = factory(root.xspattern, root.prsc);
|
|
22658
|
-
})(
|
|
23200
|
+
})(this$1, function(xspattern, prsc) {
|
|
22659
23201
|
return (function(xspattern, prsc) {
|
|
22660
23202
|
const VERSION = "3.34.0";
|
|
22661
23203
|
const fontoxpathGlobal = {};
|
|
@@ -38560,30 +39102,12 @@ function queryInspectionXPathElements(root, expression) {
|
|
|
38560
39102
|
}
|
|
38561
39103
|
//#endregion
|
|
38562
39104
|
//#region ../../mpcore/packages/simulator/src/view/nodeHandle.ts
|
|
38563
|
-
function escapeText$1(text) {
|
|
38564
|
-
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
38565
|
-
}
|
|
38566
39105
|
function createValueEventDetail(value, detail) {
|
|
38567
39106
|
return {
|
|
38568
39107
|
value,
|
|
38569
39108
|
...detail ?? {}
|
|
38570
39109
|
};
|
|
38571
39110
|
}
|
|
38572
|
-
function escapeAttribute$1(value) {
|
|
38573
|
-
return escapeText$1(value).replaceAll("\"", """);
|
|
38574
|
-
}
|
|
38575
|
-
function serializeNode(node) {
|
|
38576
|
-
if (node.type === "text") return escapeText$1(node.data ?? "");
|
|
38577
|
-
if (node.type !== "tag") return (node.children ?? []).map(serializeNode).join("");
|
|
38578
|
-
if (node.name === "page") return (node.children ?? []).filter((child) => !(child.type === "tag" && (child.name === "import" || child.name === "wxs"))).map(serializeNode).join("");
|
|
38579
|
-
const attrs = Object.entries(node.attribs ?? {}).filter(([key]) => !key.startsWith("data-sim-")).map(([key, value]) => ` ${key}="${escapeAttribute$1(value)}"`).join("");
|
|
38580
|
-
const children = (node.children ?? []).map(serializeNode).join("");
|
|
38581
|
-
return `<${node.name ?? ""}${attrs}>${children}</${node.name ?? ""}>`;
|
|
38582
|
-
}
|
|
38583
|
-
function collectText(node) {
|
|
38584
|
-
if (node.type === "text") return node.data ?? "";
|
|
38585
|
-
return (node.children ?? []).map(collectText).join("");
|
|
38586
|
-
}
|
|
38587
39111
|
function resolvePageScopeId$1(scopeId) {
|
|
38588
39112
|
if (!scopeId) return null;
|
|
38589
39113
|
const pagePathIndex = scopeId.indexOf("/page/");
|
|
@@ -38661,7 +39185,7 @@ var HeadlessTestingNodeHandle = class HeadlessTestingNodeHandle {
|
|
|
38661
39185
|
}
|
|
38662
39186
|
async text() {
|
|
38663
39187
|
this.assertActive();
|
|
38664
|
-
return
|
|
39188
|
+
return collectNodeText$1(this.node);
|
|
38665
39189
|
}
|
|
38666
39190
|
async tagName() {
|
|
38667
39191
|
this.assertActive();
|
|
@@ -38673,10 +39197,23 @@ var HeadlessTestingNodeHandle = class HeadlessTestingNodeHandle {
|
|
|
38673
39197
|
const normalizedEventName = eventName.trim();
|
|
38674
39198
|
if (!normalizedEventName) throw new Error("Event name must be a non-empty string in headless testing runtime.");
|
|
38675
39199
|
let handlerResults;
|
|
38676
|
-
|
|
38677
|
-
|
|
38678
|
-
|
|
38679
|
-
|
|
39200
|
+
let nativeHandled;
|
|
39201
|
+
try {
|
|
39202
|
+
nativeHandled = this.interactions.dispatchNativeEvent?.(this.node, normalizedEventName, event, normalizedEventName === "tap" ? (result) => {
|
|
39203
|
+
handlerResults ??= [];
|
|
39204
|
+
handlerResults.push(result);
|
|
39205
|
+
} : void 0);
|
|
39206
|
+
} catch (error) {
|
|
39207
|
+
let failures;
|
|
39208
|
+
if (handlerResults) {
|
|
39209
|
+
for (const result of await Promise.allSettled(handlerResults)) if (result.status === "rejected") {
|
|
39210
|
+
failures ??= [error];
|
|
39211
|
+
failures.push(result.reason);
|
|
39212
|
+
}
|
|
39213
|
+
}
|
|
39214
|
+
if (failures) throw new AggregateError(failures, "Native interaction handlers failed", { cause: error });
|
|
39215
|
+
throw error;
|
|
39216
|
+
}
|
|
38680
39217
|
if (normalizedEventName === "tap" && nativeHandled) return handlerResults ? (await Promise.all(handlerResults))[0] : void 0;
|
|
38681
39218
|
const binding = resolveMiniProgramEventBinding(this.node.attribs, normalizedEventName);
|
|
38682
39219
|
if (!binding?.method) {
|
|
@@ -38688,6 +39225,20 @@ var HeadlessTestingNodeHandle = class HeadlessTestingNodeHandle {
|
|
|
38688
39225
|
async tap(event = {}) {
|
|
38689
39226
|
return await this.trigger("tap", event);
|
|
38690
39227
|
}
|
|
39228
|
+
async touchstart(event = {}) {
|
|
39229
|
+
return await this.trigger("touchstart", event);
|
|
39230
|
+
}
|
|
39231
|
+
async touchmove(event = {}) {
|
|
39232
|
+
return await this.trigger("touchmove", event);
|
|
39233
|
+
}
|
|
39234
|
+
async touchend(event = {}) {
|
|
39235
|
+
return await this.trigger("touchend", event);
|
|
39236
|
+
}
|
|
39237
|
+
async dispatchEvent({ eventName, $: selector, ...event }) {
|
|
39238
|
+
const target = selector ? await this.$(selector) : this;
|
|
39239
|
+
if (!target) throw new Error(`No node matching "${selector}" was found for dispatchEvent in headless testing runtime.`);
|
|
39240
|
+
return await target.trigger(eventName, event);
|
|
39241
|
+
}
|
|
38691
39242
|
async input(value, event = {}) {
|
|
38692
39243
|
return await this.trigger("input", {
|
|
38693
39244
|
...event,
|
|
@@ -38740,16 +39291,20 @@ function isMustacheOnly(value) {
|
|
|
38740
39291
|
return trimmed.startsWith("{{") && trimmed.endsWith("}}") && !trimmed.includes("{{", 2);
|
|
38741
39292
|
}
|
|
38742
39293
|
function visitDom(node, visitor) {
|
|
38743
|
-
visitor(node);
|
|
39294
|
+
if (visitor(node) === false) return;
|
|
38744
39295
|
for (const child of node.children ?? []) visitDom(child, visitor);
|
|
38745
39296
|
}
|
|
38746
39297
|
function interpolateDomTree(root, data) {
|
|
38747
39298
|
visitDom(root, (node) => {
|
|
39299
|
+
const richText = node.type === "tag" && node.name === "rich-text";
|
|
39300
|
+
if (richText) node.children = [];
|
|
38748
39301
|
if (typeof node.data === "string") node.data = interpolateTemplateText(node.data, data);
|
|
38749
39302
|
if (node.attribs) {
|
|
38750
39303
|
let dataset;
|
|
38751
39304
|
for (const [key, value] of Object.entries(node.attribs)) {
|
|
38752
39305
|
const resolvedValue = isMustacheOnly(value) ? resolveRawValueByPath(data, value.trim().slice(2, -2)) : interpolateTemplate(value, data);
|
|
39306
|
+
if (key === "value") setNativePickerValue(node, resolvedValue);
|
|
39307
|
+
if (richText && key === "nodes") node.children = renderRichTextNodes(resolvedValue);
|
|
38753
39308
|
node.attribs[key] = String(resolvedValue ?? "");
|
|
38754
39309
|
if (isDatasetAttribute(key)) {
|
|
38755
39310
|
dataset ??= {};
|
|
@@ -38758,6 +39313,7 @@ function interpolateDomTree(root, data) {
|
|
|
38758
39313
|
}
|
|
38759
39314
|
node.dataset = dataset;
|
|
38760
39315
|
}
|
|
39316
|
+
if (richText) return false;
|
|
38761
39317
|
});
|
|
38762
39318
|
}
|
|
38763
39319
|
function escapeText(text) {
|
|
@@ -38779,11 +39335,12 @@ function renderPageTree(project, page) {
|
|
|
38779
39335
|
const templateSource = project.artifactSource.readText(templatePath);
|
|
38780
39336
|
if (templateSource == null) throw new Error(`Missing template in headless runtime: ${templatePath}`);
|
|
38781
39337
|
const document = parseDocument(`<page>${templateSource}</page>`, {
|
|
38782
|
-
xmlMode:
|
|
39338
|
+
xmlMode: true,
|
|
38783
39339
|
decodeEntities: false,
|
|
38784
39340
|
recognizeSelfClosing: true
|
|
38785
39341
|
});
|
|
38786
39342
|
interpolateDomTree(document, page.data);
|
|
39343
|
+
linkRenderedParents(document);
|
|
38787
39344
|
return {
|
|
38788
39345
|
root: document,
|
|
38789
39346
|
wxml: serializeDomNode((document.children ?? [])[0] ?? document)
|
|
@@ -38954,7 +39511,7 @@ function getNativeScrollOffset(page, node) {
|
|
|
38954
39511
|
};
|
|
38955
39512
|
}
|
|
38956
39513
|
/** 原生交互更新宿主状态,导航仍交给统一 wx 路由入口。 */
|
|
38957
|
-
function dispatchNativeNodeEvent(page, node, eventName, event, wx, resolveMethod, onHandlerResult) {
|
|
39514
|
+
function dispatchNativeNodeEvent(page, node, eventName, event, wx, resolveMethod, onHandlerResult, resolveComponent) {
|
|
38958
39515
|
if (eventName === "scroll" && node.name === "scroll-view") {
|
|
38959
39516
|
const detail = event.detail;
|
|
38960
39517
|
const state = pageScrollViews.get(page)?.get(nodeKey(node));
|
|
@@ -38968,30 +39525,42 @@ function dispatchNativeNodeEvent(page, node, eventName, event, wx, resolveMethod
|
|
|
38968
39525
|
if (eventName !== "tap") return false;
|
|
38969
39526
|
let current = node;
|
|
38970
39527
|
let navigator;
|
|
39528
|
+
let button;
|
|
39529
|
+
const origin = getNativeNodeOwner(node)?.target ?? node;
|
|
38971
39530
|
let handlers;
|
|
38972
39531
|
let handled = false;
|
|
38973
|
-
|
|
38974
|
-
if (
|
|
38975
|
-
|
|
38976
|
-
if (binding?.method) {
|
|
38977
|
-
const call = resolveMethod(current.attribs?.["data-sim-scope"] ?? null, binding.method);
|
|
39532
|
+
const collectHandler = (scopeId, target, binding) => {
|
|
39533
|
+
if (binding.method) {
|
|
39534
|
+
const call = resolveMethod(scopeId, binding.method);
|
|
38978
39535
|
handlers ??= [];
|
|
38979
39536
|
handlers.push({
|
|
38980
|
-
|
|
39537
|
+
event: createMiniProgramEventPayload(target, "tap", event, origin),
|
|
38981
39538
|
call
|
|
38982
39539
|
});
|
|
38983
39540
|
handled = true;
|
|
38984
39541
|
}
|
|
38985
|
-
|
|
39542
|
+
};
|
|
39543
|
+
while (current) {
|
|
39544
|
+
if (!navigator && current.name === "navigator") navigator = current;
|
|
39545
|
+
if (!button && current.name === "button") button = current;
|
|
39546
|
+
if (visitNativeNodeEventBindings(current, "tap", collectHandler)) {
|
|
38986
39547
|
handled = true;
|
|
38987
39548
|
break;
|
|
38988
39549
|
}
|
|
38989
39550
|
current = current.parent;
|
|
38990
39551
|
}
|
|
39552
|
+
const submit = button ? prepareNativeFormSubmit(button, `page:${page.route}`, event, resolveMethod, resolveComponent) : void 0;
|
|
38991
39553
|
if (handlers) for (const handler of handlers) {
|
|
38992
|
-
const result = handler.call(
|
|
39554
|
+
const result = handler.call(handler.event);
|
|
38993
39555
|
onHandlerResult?.(result);
|
|
38994
39556
|
}
|
|
39557
|
+
if (submit) {
|
|
39558
|
+
handled = true;
|
|
39559
|
+
if (submit.call) {
|
|
39560
|
+
const result = submit.call(submit.event);
|
|
39561
|
+
onHandlerResult?.(result);
|
|
39562
|
+
}
|
|
39563
|
+
}
|
|
38995
39564
|
if (!navigator) return handled;
|
|
38996
39565
|
const openType = navigator.attribs?.["open-type"] ?? "navigate";
|
|
38997
39566
|
const url = navigator.attribs?.url ?? "";
|
|
@@ -39776,6 +40345,64 @@ function createHeadlessMediaQueryObserver(driver, onDisconnect) {
|
|
|
39776
40345
|
};
|
|
39777
40346
|
}
|
|
39778
40347
|
//#endregion
|
|
40348
|
+
//#region ../../mpcore/packages/simulator/src/view/templateRegistration.ts
|
|
40349
|
+
/** 编译模板及递归依赖共用全局注册图,图外原生模板继续实时读取。 */
|
|
40350
|
+
function createTemplateRegistration(source, projectRoot, compiledTemplatePaths = []) {
|
|
40351
|
+
const root = normalize(projectRoot);
|
|
40352
|
+
const normalizeTemplatePath = (filePath) => {
|
|
40353
|
+
const normalized = normalize(filePath);
|
|
40354
|
+
const local = relative(root, normalized);
|
|
40355
|
+
if (!normalized.endsWith(".wxml") || isAbsolute(local) || local === ".." || local.startsWith("../")) throw new TypeError("Compiled template paths must stay inside the mini-program root and end in .wxml.");
|
|
40356
|
+
return normalized;
|
|
40357
|
+
};
|
|
40358
|
+
const resolveRelativeTemplatePath = (filePath) => {
|
|
40359
|
+
const local = normalize(filePath);
|
|
40360
|
+
if (isAbsolute(local) || local === ".." || local.startsWith("../")) throw new TypeError("Compiled template paths must stay inside the mini-program root and end in .wxml.");
|
|
40361
|
+
return normalizeTemplatePath(join(root, local));
|
|
40362
|
+
};
|
|
40363
|
+
const entries = [...new Set(compiledTemplatePaths.map((filePath) => {
|
|
40364
|
+
if (typeof filePath !== "string" || !filePath || isAbsolute(filePath)) throw new TypeError("Compiled template paths must be project-relative WXML paths.");
|
|
40365
|
+
return resolveRelativeTemplatePath(filePath);
|
|
40366
|
+
}))];
|
|
40367
|
+
let registered = /* @__PURE__ */ new Map();
|
|
40368
|
+
function readSnapshot() {
|
|
40369
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
40370
|
+
const collect = (filePath) => {
|
|
40371
|
+
filePath = normalizeTemplatePath(filePath);
|
|
40372
|
+
if (snapshot.has(filePath)) return;
|
|
40373
|
+
const content = source.readText(filePath);
|
|
40374
|
+
if (content === void 0) throw new Error(`Missing compiled template during host registration: ${relative(root, filePath)}`);
|
|
40375
|
+
snapshot.set(filePath, content);
|
|
40376
|
+
const visit = (node) => {
|
|
40377
|
+
const request = node.attribs?.src;
|
|
40378
|
+
if ((node.name === "include" || node.name === "import") && request) {
|
|
40379
|
+
const target = (request.endsWith(".wxml") ? request : `${request}.wxml`).replaceAll("\\", "/");
|
|
40380
|
+
if (isAbsolute(target) && !target.startsWith("/")) throw new TypeError("Compiled template paths must stay inside the mini-program root and end in .wxml.");
|
|
40381
|
+
collect(resolveRelativeTemplatePath(target.startsWith("/") ? target.slice(1) : join(relative(root, dirname(filePath)), target)));
|
|
40382
|
+
}
|
|
40383
|
+
for (const child of node.children ?? []) visit(child);
|
|
40384
|
+
};
|
|
40385
|
+
visit(parseWxsTemplateDocument(content));
|
|
40386
|
+
};
|
|
40387
|
+
for (const filePath of entries) collect(filePath);
|
|
40388
|
+
return snapshot;
|
|
40389
|
+
}
|
|
40390
|
+
function reload() {
|
|
40391
|
+
const snapshot = readSnapshot();
|
|
40392
|
+
const changed = snapshot.size !== registered.size || [...snapshot].some(([filePath, content]) => registered.get(filePath) !== content);
|
|
40393
|
+
registered = snapshot;
|
|
40394
|
+
return changed;
|
|
40395
|
+
}
|
|
40396
|
+
reload();
|
|
40397
|
+
return {
|
|
40398
|
+
artifactSource: {
|
|
40399
|
+
has: (filePath) => registered.has(normalize(filePath)) || source.has(filePath),
|
|
40400
|
+
readText: (filePath) => registered.get(normalize(filePath)) ?? source.readText(filePath)
|
|
40401
|
+
},
|
|
40402
|
+
reload
|
|
40403
|
+
};
|
|
40404
|
+
}
|
|
40405
|
+
//#endregion
|
|
39779
40406
|
//#region ../../mpcore/packages/simulator/src/view/videoContext.ts
|
|
39780
40407
|
function createEventPayload(node, eventName, detail) {
|
|
39781
40408
|
const dataset = collectNodeDataset(node);
|
|
@@ -40034,6 +40661,360 @@ function createWorkerHost(options) {
|
|
|
40034
40661
|
};
|
|
40035
40662
|
}
|
|
40036
40663
|
//#endregion
|
|
40664
|
+
//#region ../../mpcore/packages/simulator/src/runtime/moduleSyntax/ast.ts
|
|
40665
|
+
function isSyntaxNode(value) {
|
|
40666
|
+
return value !== null && typeof value === "object" && "type" in value && typeof value.type === "string";
|
|
40667
|
+
}
|
|
40668
|
+
function childNodes(node) {
|
|
40669
|
+
const children = [];
|
|
40670
|
+
for (const [key, value] of Object.entries(node)) for (const child of Array.isArray(value) ? value : [value]) if (isSyntaxNode(child)) children.push({
|
|
40671
|
+
key,
|
|
40672
|
+
node: child
|
|
40673
|
+
});
|
|
40674
|
+
return children;
|
|
40675
|
+
}
|
|
40676
|
+
function patternIdentifiers(node) {
|
|
40677
|
+
if (node.type === "Identifier") return [node];
|
|
40678
|
+
const keys = node.type === "ObjectPattern" ? ["properties"] : node.type === "ObjectProperty" ? ["value"] : node.type === "AssignmentPattern" ? ["left"] : node.type === "RestElement" ? ["argument"] : ["elements"];
|
|
40679
|
+
return childNodes(node).filter((child) => keys.includes(child.key)).flatMap((child) => patternIdentifiers(child.node));
|
|
40680
|
+
}
|
|
40681
|
+
function createUniqueName(root) {
|
|
40682
|
+
const used = /* @__PURE__ */ new Set();
|
|
40683
|
+
const visit = (node) => {
|
|
40684
|
+
if (node.type === "Identifier" && typeof node.name === "string") used.add(node.name);
|
|
40685
|
+
childNodes(node).forEach((child) => visit(child.node));
|
|
40686
|
+
};
|
|
40687
|
+
visit(root);
|
|
40688
|
+
let index = 0;
|
|
40689
|
+
return () => {
|
|
40690
|
+
let name;
|
|
40691
|
+
do
|
|
40692
|
+
name = `__mpcoreEsm${index++}`;
|
|
40693
|
+
while (used.has(name));
|
|
40694
|
+
used.add(name);
|
|
40695
|
+
return name;
|
|
40696
|
+
};
|
|
40697
|
+
}
|
|
40698
|
+
function applySourceEdits(source, edits) {
|
|
40699
|
+
for (const edit of edits.toSorted((left, right) => right.start - left.start || right.end - left.end)) source = source.slice(0, edit.start) + edit.content + source.slice(edit.end);
|
|
40700
|
+
return source;
|
|
40701
|
+
}
|
|
40702
|
+
//#endregion
|
|
40703
|
+
//#region ../../mpcore/packages/simulator/src/runtime/moduleSyntax/bindings.ts
|
|
40704
|
+
const functionTypes = /* @__PURE__ */ new Set([
|
|
40705
|
+
"FunctionDeclaration",
|
|
40706
|
+
"FunctionExpression",
|
|
40707
|
+
"ArrowFunctionExpression",
|
|
40708
|
+
"ObjectMethod",
|
|
40709
|
+
"ClassMethod",
|
|
40710
|
+
"ClassPrivateMethod"
|
|
40711
|
+
]);
|
|
40712
|
+
const blockTypes = /* @__PURE__ */ new Set([
|
|
40713
|
+
"BlockStatement",
|
|
40714
|
+
"CatchClause",
|
|
40715
|
+
"ForStatement",
|
|
40716
|
+
"ForInStatement",
|
|
40717
|
+
"ForOfStatement",
|
|
40718
|
+
"SwitchStatement",
|
|
40719
|
+
"StaticBlock"
|
|
40720
|
+
]);
|
|
40721
|
+
/** 按词法作用域改写导入引用;声明、键名及同名局部变量保持原样。 */
|
|
40722
|
+
function rewriteImportReferences(root, imports, bindingName) {
|
|
40723
|
+
const scopes = /* @__PURE__ */ new WeakMap();
|
|
40724
|
+
const declarations = /* @__PURE__ */ new WeakSet();
|
|
40725
|
+
const moduleScope = {
|
|
40726
|
+
bindings: /* @__PURE__ */ new Set(),
|
|
40727
|
+
variable: true,
|
|
40728
|
+
functionDepth: 0
|
|
40729
|
+
};
|
|
40730
|
+
const declare = (pattern, scope) => {
|
|
40731
|
+
if (!isSyntaxNode(pattern)) return;
|
|
40732
|
+
for (const identifier of patternIdentifiers(pattern)) {
|
|
40733
|
+
scope.bindings.add(String(identifier.name));
|
|
40734
|
+
declarations.add(identifier);
|
|
40735
|
+
}
|
|
40736
|
+
};
|
|
40737
|
+
const visit = (node, inherited, parent, key) => {
|
|
40738
|
+
let scope = inherited;
|
|
40739
|
+
if (functionTypes.has(node.type)) {
|
|
40740
|
+
if (node.type === "FunctionDeclaration") declare(node.id, inherited);
|
|
40741
|
+
scope = {
|
|
40742
|
+
parent: inherited,
|
|
40743
|
+
bindings: /* @__PURE__ */ new Set(),
|
|
40744
|
+
variable: false,
|
|
40745
|
+
functionDepth: inherited.functionDepth + 1
|
|
40746
|
+
};
|
|
40747
|
+
declare(node.id, scope);
|
|
40748
|
+
if (Array.isArray(node.params)) node.params.forEach((parameter) => declare(parameter, scope));
|
|
40749
|
+
} else if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
|
|
40750
|
+
if (node.type === "ClassDeclaration") declare(node.id, inherited);
|
|
40751
|
+
scope = {
|
|
40752
|
+
parent: inherited,
|
|
40753
|
+
bindings: /* @__PURE__ */ new Set(),
|
|
40754
|
+
variable: false,
|
|
40755
|
+
functionDepth: inherited.functionDepth
|
|
40756
|
+
};
|
|
40757
|
+
declare(node.id, scope);
|
|
40758
|
+
} else if (blockTypes.has(node.type)) {
|
|
40759
|
+
scope = {
|
|
40760
|
+
parent: inherited,
|
|
40761
|
+
bindings: /* @__PURE__ */ new Set(),
|
|
40762
|
+
variable: node.type === "StaticBlock" || key === "body" && !!parent && functionTypes.has(parent.type),
|
|
40763
|
+
functionDepth: inherited.functionDepth
|
|
40764
|
+
};
|
|
40765
|
+
if (node.type === "CatchClause") declare(node.param, scope);
|
|
40766
|
+
}
|
|
40767
|
+
scopes.set(node, scope);
|
|
40768
|
+
if (node.type === "VariableDeclaration") {
|
|
40769
|
+
let owner = scope;
|
|
40770
|
+
while (node.kind === "var" && !owner.variable && owner.parent) owner = owner.parent;
|
|
40771
|
+
for (const child of childNodes(node)) declare(child.node.id, owner);
|
|
40772
|
+
}
|
|
40773
|
+
if (node.type === "ImportDeclaration") {
|
|
40774
|
+
for (const child of childNodes(node)) if (child.key === "specifiers") declare(child.node.local, moduleScope);
|
|
40775
|
+
return;
|
|
40776
|
+
}
|
|
40777
|
+
if (node.type === "ImportExpression" || node.type === "CallExpression" && isSyntaxNode(node.callee) && node.callee.type === "Import") throw new SyntaxError("Dynamic import is not supported by the synchronous mini-program module loader.");
|
|
40778
|
+
if (node.type === "MetaProperty" && isSyntaxNode(node.meta) && node.meta.name === "import") throw new SyntaxError("import.meta is not supported by the synchronous mini-program module loader.");
|
|
40779
|
+
if (scope.functionDepth === 0 && (node.type === "AwaitExpression" || node.type === "ForOfStatement" && node.await)) throw new SyntaxError("Top-level await is not supported by the synchronous mini-program module loader.");
|
|
40780
|
+
if (scope.functionDepth === 0 && node.type === "ReturnStatement") throw new SyntaxError("Top-level return is not valid in a mini-program ES module.");
|
|
40781
|
+
for (const child of childNodes(node)) {
|
|
40782
|
+
const computedMethodKey = functionTypes.has(node.type) && child.key === "key";
|
|
40783
|
+
const switchDiscriminant = node.type === "SwitchStatement" && child.key === "discriminant";
|
|
40784
|
+
visit(child.node, computedMethodKey || switchDiscriminant ? inherited : scope, node, child.key);
|
|
40785
|
+
}
|
|
40786
|
+
};
|
|
40787
|
+
visit(root, moduleScope);
|
|
40788
|
+
const edits = [];
|
|
40789
|
+
const rewrite = (node, parent, key) => {
|
|
40790
|
+
if (node.type === "ImportDeclaration" || node.type === "ExportAllDeclaration" || node.type === "ExportNamedDeclaration" && !node.declaration) return;
|
|
40791
|
+
if (node.type === "Identifier" && !declarations.has(node) && imports.has(String(node.name))) {
|
|
40792
|
+
const property = parent && key === "key" && !parent.computed && [
|
|
40793
|
+
"ObjectProperty",
|
|
40794
|
+
"ObjectMethod",
|
|
40795
|
+
"ClassMethod",
|
|
40796
|
+
"ClassPrivateMethod",
|
|
40797
|
+
"ClassProperty"
|
|
40798
|
+
].includes(parent.type);
|
|
40799
|
+
const member = parent && key === "property" && !parent.computed && ["MemberExpression", "OptionalMemberExpression"].includes(parent.type);
|
|
40800
|
+
const label = key === "label" || parent?.type === "PrivateName" || parent?.type === "MetaProperty";
|
|
40801
|
+
let owner = scopes.get(node);
|
|
40802
|
+
while (owner && !owner.bindings.has(String(node.name))) owner = owner.parent;
|
|
40803
|
+
if (!property && !member && !label && owner === moduleScope) {
|
|
40804
|
+
let content = `${bindingName}[${JSON.stringify(node.name)}]`;
|
|
40805
|
+
if (parent && (key === "callee" && ["CallExpression", "OptionalCallExpression"].includes(parent.type) || key === "tag" && parent.type === "TaggedTemplateExpression")) content = `(0, ${content})`;
|
|
40806
|
+
if (parent?.type === "ObjectProperty" && parent.shorthand && key === "value") content = `${node.name}: ${content}`;
|
|
40807
|
+
edits.push({
|
|
40808
|
+
start: node.start,
|
|
40809
|
+
end: node.end,
|
|
40810
|
+
content
|
|
40811
|
+
});
|
|
40812
|
+
}
|
|
40813
|
+
}
|
|
40814
|
+
childNodes(node).forEach((child) => rewrite(child.node, node, child.key));
|
|
40815
|
+
};
|
|
40816
|
+
rewrite(root);
|
|
40817
|
+
return edits;
|
|
40818
|
+
}
|
|
40819
|
+
//#endregion
|
|
40820
|
+
//#region ../../mpcore/packages/simulator/src/runtime/moduleSyntax/index.ts
|
|
40821
|
+
function position(node, edge) {
|
|
40822
|
+
const value = node[edge];
|
|
40823
|
+
if (typeof value !== "number") throw new SyntaxError("Missing source range in mini-program module syntax.");
|
|
40824
|
+
return value;
|
|
40825
|
+
}
|
|
40826
|
+
function identifierName(node) {
|
|
40827
|
+
return node.type === "Identifier" ? String(node.name) : String(node.value);
|
|
40828
|
+
}
|
|
40829
|
+
/** 同步转换静态 ESM;CJS 保留原字节,Node 与浏览器共享导入和导出语义。 */
|
|
40830
|
+
function transformMiniProgramModule(source) {
|
|
40831
|
+
if (!/\b(?:import|export)\b/.test(source)) return source;
|
|
40832
|
+
const ast = parse$2(source, {
|
|
40833
|
+
sourceType: "unambiguous",
|
|
40834
|
+
allowReturnOutsideFunction: true,
|
|
40835
|
+
tokens: true
|
|
40836
|
+
});
|
|
40837
|
+
const moduleNodes = ast.program.body.filter((node) => [
|
|
40838
|
+
"ImportDeclaration",
|
|
40839
|
+
"ExportNamedDeclaration",
|
|
40840
|
+
"ExportDefaultDeclaration",
|
|
40841
|
+
"ExportAllDeclaration"
|
|
40842
|
+
].includes(node.type));
|
|
40843
|
+
if (moduleNodes.length === 0) return source;
|
|
40844
|
+
const root = ast.program;
|
|
40845
|
+
const fresh = createUniqueName(root);
|
|
40846
|
+
const moduleName = fresh();
|
|
40847
|
+
const requireName = fresh();
|
|
40848
|
+
const objectName = fresh();
|
|
40849
|
+
const bindingsName = fresh();
|
|
40850
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
40851
|
+
const imports = /* @__PURE__ */ new Map();
|
|
40852
|
+
const exports = /* @__PURE__ */ new Map();
|
|
40853
|
+
const hoistedDefaultNames = [];
|
|
40854
|
+
const starExports = [];
|
|
40855
|
+
const edits = [];
|
|
40856
|
+
const dependency = (request) => {
|
|
40857
|
+
let name = dependencies.get(request);
|
|
40858
|
+
if (!name) {
|
|
40859
|
+
name = fresh();
|
|
40860
|
+
dependencies.set(request, name);
|
|
40861
|
+
}
|
|
40862
|
+
return name;
|
|
40863
|
+
};
|
|
40864
|
+
const remove = (node) => edits.push({
|
|
40865
|
+
start: position(node, "start"),
|
|
40866
|
+
end: position(node, "end"),
|
|
40867
|
+
content: ""
|
|
40868
|
+
});
|
|
40869
|
+
const own = (object, key) => `${objectName}.prototype.hasOwnProperty.call(${object}, ${key})`;
|
|
40870
|
+
for (const node of moduleNodes) {
|
|
40871
|
+
if ("attributes" in node && node.attributes?.length) throw new SyntaxError("Import attributes are not supported by the synchronous mini-program module loader.");
|
|
40872
|
+
if (node.type === "ImportDeclaration") {
|
|
40873
|
+
if (node.phase) throw new SyntaxError("Import phases are not supported by the synchronous mini-program module loader.");
|
|
40874
|
+
const namespace = dependency(node.source.value);
|
|
40875
|
+
for (const specifier of node.specifiers) {
|
|
40876
|
+
const binding = specifier.type === "ImportNamespaceSpecifier" ? namespace : specifier.type === "ImportDefaultSpecifier" ? `${namespace} != null && ${own(namespace, "\"default\"")} ? ${namespace}.default : ${namespace}` : `${namespace}[${JSON.stringify(identifierName(specifier.imported))}]`;
|
|
40877
|
+
imports.set(specifier.local.name, binding);
|
|
40878
|
+
}
|
|
40879
|
+
remove(node);
|
|
40880
|
+
} else if (node.type === "ExportNamedDeclaration") {
|
|
40881
|
+
if (node.declaration) {
|
|
40882
|
+
edits.push({
|
|
40883
|
+
start: position(node, "start"),
|
|
40884
|
+
end: position(node.declaration, "start"),
|
|
40885
|
+
content: ""
|
|
40886
|
+
});
|
|
40887
|
+
const patterns = node.declaration.type === "VariableDeclaration" ? node.declaration.declarations.map((declaration) => declaration.id) : "id" in node.declaration && node.declaration.id ? [node.declaration.id] : [];
|
|
40888
|
+
for (const pattern of patterns) for (const identifier of patternIdentifiers(pattern)) exports.set(String(identifier.name), String(identifier.name));
|
|
40889
|
+
} else {
|
|
40890
|
+
const namespace = node.source ? dependency(node.source.value) : void 0;
|
|
40891
|
+
for (const specifier of node.specifiers) {
|
|
40892
|
+
const exported = identifierName(specifier.exported);
|
|
40893
|
+
if (specifier.type === "ExportNamespaceSpecifier" && namespace) exports.set(exported, namespace);
|
|
40894
|
+
else if (specifier.type === "ExportSpecifier") {
|
|
40895
|
+
const local = identifierName(specifier.local);
|
|
40896
|
+
exports.set(exported, namespace ? `${namespace}[${JSON.stringify(local)}]` : local);
|
|
40897
|
+
} else throw new SyntaxError(`Unsupported mini-program export specifier: ${specifier.type}.`);
|
|
40898
|
+
}
|
|
40899
|
+
remove(node);
|
|
40900
|
+
}
|
|
40901
|
+
} else if (node.type === "ExportAllDeclaration") {
|
|
40902
|
+
starExports.push(dependency(node.source.value));
|
|
40903
|
+
remove(node);
|
|
40904
|
+
} else if (node.type === "ExportDefaultDeclaration") {
|
|
40905
|
+
const declaration = node.declaration;
|
|
40906
|
+
const defaultToken = ast.tokens?.find((token) => token.start > position(node, "start") && token.end <= position(declaration, "start") && token.type.label === "default");
|
|
40907
|
+
if (!defaultToken) throw new SyntaxError("Missing default export token in mini-program module syntax.");
|
|
40908
|
+
if (declaration.type === "FunctionDeclaration" && !declaration.id) {
|
|
40909
|
+
const name = fresh();
|
|
40910
|
+
const keyword = ast.tokens?.find((token) => token.start >= position(declaration, "start") && token.type.label === "function");
|
|
40911
|
+
const nameToken = declaration.generator ? ast.tokens?.find((token) => token.start >= (keyword?.end ?? position(declaration, "start")) && token.type.label === "*") : keyword;
|
|
40912
|
+
if (!nameToken) throw new SyntaxError("Missing default function token in mini-program module syntax.");
|
|
40913
|
+
exports.set("default", name);
|
|
40914
|
+
hoistedDefaultNames.push(name);
|
|
40915
|
+
edits.push({
|
|
40916
|
+
start: position(node, "start"),
|
|
40917
|
+
end: defaultToken.end,
|
|
40918
|
+
content: ""
|
|
40919
|
+
});
|
|
40920
|
+
edits.push({
|
|
40921
|
+
start: nameToken.end,
|
|
40922
|
+
end: nameToken.end,
|
|
40923
|
+
content: ` ${name}`
|
|
40924
|
+
});
|
|
40925
|
+
} else if ((declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") && declaration.id) {
|
|
40926
|
+
exports.set("default", declaration.id.name);
|
|
40927
|
+
edits.push({
|
|
40928
|
+
start: position(node, "start"),
|
|
40929
|
+
end: defaultToken.end,
|
|
40930
|
+
content: ""
|
|
40931
|
+
});
|
|
40932
|
+
} else {
|
|
40933
|
+
const name = fresh();
|
|
40934
|
+
exports.set("default", name);
|
|
40935
|
+
edits.push({
|
|
40936
|
+
start: position(node, "start"),
|
|
40937
|
+
end: defaultToken.end,
|
|
40938
|
+
content: `const ${name} = `
|
|
40939
|
+
});
|
|
40940
|
+
edits.push({
|
|
40941
|
+
start: position(node, "end"),
|
|
40942
|
+
end: position(node, "end"),
|
|
40943
|
+
content: ";"
|
|
40944
|
+
});
|
|
40945
|
+
}
|
|
40946
|
+
}
|
|
40947
|
+
}
|
|
40948
|
+
edits.push(...rewriteImportReferences(root, new Set(imports.keys()), bindingsName));
|
|
40949
|
+
const declarations = [
|
|
40950
|
+
dependencies.size ? `let ${[...dependencies.values()].join(", ")};` : "",
|
|
40951
|
+
`const ${bindingsName} = ${objectName}.create(null);`,
|
|
40952
|
+
...[...imports].map(([name, expression]) => `${objectName}.defineProperty(${bindingsName}, ${JSON.stringify(name)}, { get: () => (${expression}) });`),
|
|
40953
|
+
...[...exports].map(([name, expression]) => {
|
|
40954
|
+
const value = imports.has(expression) ? `${bindingsName}[${JSON.stringify(expression)}]` : expression;
|
|
40955
|
+
return `${objectName}.defineProperty(${moduleName}.exports, ${JSON.stringify(name)}, { enumerable: true, get: () => ${value} });`;
|
|
40956
|
+
}),
|
|
40957
|
+
...hoistedDefaultNames.map((name) => `${objectName}.defineProperty(${name}, 'name', { value: 'default', configurable: true });`),
|
|
40958
|
+
...[...dependencies].map(([request, namespace]) => `${namespace} = ${requireName}(${JSON.stringify(request)});`)
|
|
40959
|
+
];
|
|
40960
|
+
if (starExports.length) {
|
|
40961
|
+
const owners = fresh();
|
|
40962
|
+
const namespace = fresh();
|
|
40963
|
+
const key = fresh();
|
|
40964
|
+
declarations.push(`
|
|
40965
|
+
const ${owners} = ${objectName}.create(null);
|
|
40966
|
+
for (const ${namespace} of [${starExports.join(", ")}]) {
|
|
40967
|
+
for (const ${key} of ${objectName}.keys(${namespace})) {
|
|
40968
|
+
if (${key} === 'default' || ${own(`${moduleName}.exports`, key)}) continue;
|
|
40969
|
+
${owners}[${key}] = ${own(owners, key)} && ${owners}[${key}] !== ${namespace} ? null : ${namespace};
|
|
40970
|
+
}
|
|
40971
|
+
}
|
|
40972
|
+
for (const ${key} of ${objectName}.keys(${owners})) {
|
|
40973
|
+
if (${owners}[${key}] !== null) ${objectName}.defineProperty(${moduleName}.exports, ${key}, { enumerable: true, get: () => ${owners}[${key}][${key}] });
|
|
40974
|
+
}
|
|
40975
|
+
`);
|
|
40976
|
+
}
|
|
40977
|
+
return `(function(${moduleName}, ${requireName}, ${objectName}) {\n"use strict";\n${declarations.join("\n")}\n${applySourceEdits(source, edits)}\n${objectName}.preventExtensions(${moduleName}.exports);\n}).call(undefined, module, require, Object);`;
|
|
40978
|
+
}
|
|
40979
|
+
//#endregion
|
|
40980
|
+
//#region ../../mpcore/packages/simulator/src/runtime/pageDefinitionReload.ts
|
|
40981
|
+
/** 定义更新只解析已有路由,不触发普通导航的启动或 page-not-found 生命周期。 */
|
|
40982
|
+
function resolvePageDefinitionReloadRoute(project, route) {
|
|
40983
|
+
if (typeof route !== "string" || !route.trim() || /[?#]/.test(route)) throw new TypeError("Page definition reload requires a route path without query or hash.");
|
|
40984
|
+
const normalized = route.trim().replace(/^\/+/, "");
|
|
40985
|
+
const record = project.routes.find((record) => record.route === normalized);
|
|
40986
|
+
if (!record) throw new Error(`Unknown page definition reload route: ${route}`);
|
|
40987
|
+
return record;
|
|
40988
|
+
}
|
|
40989
|
+
function restoreMap(target, snapshot) {
|
|
40990
|
+
target.clear();
|
|
40991
|
+
for (const [key, value] of snapshot) target.set(key, value);
|
|
40992
|
+
}
|
|
40993
|
+
/** 仅替换目标 entry;失败恢复缓存和注册表,保留未变依赖的对象身份。 */
|
|
40994
|
+
function reloadPageModuleDefinition(options) {
|
|
40995
|
+
const { filePath, route, source, cache, registries } = options;
|
|
40996
|
+
const previous = cache.get(filePath);
|
|
40997
|
+
if (!previous || !registries.pages.has(route)) throw new Error(`Cannot reload a page definition before it is loaded: ${route}`);
|
|
40998
|
+
if (source === void 0) throw new Error(`Missing page script for definition reload: ${route}`);
|
|
40999
|
+
if (source === previous.source) return false;
|
|
41000
|
+
const modules = new Map(cache);
|
|
41001
|
+
const pages = new Map(registries.pages);
|
|
41002
|
+
const components = new Map(registries.components);
|
|
41003
|
+
const app = registries.appDefinition;
|
|
41004
|
+
cache.delete(filePath);
|
|
41005
|
+
registries.pages.delete(route);
|
|
41006
|
+
try {
|
|
41007
|
+
options.execute();
|
|
41008
|
+
return true;
|
|
41009
|
+
} catch (error) {
|
|
41010
|
+
restoreMap(cache, modules);
|
|
41011
|
+
restoreMap(registries.pages, pages);
|
|
41012
|
+
restoreMap(registries.components, components);
|
|
41013
|
+
registries.appDefinition = app;
|
|
41014
|
+
throw error;
|
|
41015
|
+
}
|
|
41016
|
+
}
|
|
41017
|
+
//#endregion
|
|
40037
41018
|
//#region ../../mpcore/packages/simulator/src/runtime/runtimeGlobals.ts
|
|
40038
41019
|
const MINI_PROGRAM_UNAVAILABLE_GLOBAL_NAMES = [
|
|
40039
41020
|
"window",
|
|
@@ -40077,102 +41058,6 @@ function createMiniProgramRuntimeGlobals(availableGlobals, overrides) {
|
|
|
40077
41058
|
}
|
|
40078
41059
|
//#endregion
|
|
40079
41060
|
//#region ../../mpcore/packages/simulator/src/runtime/moduleLoader.ts
|
|
40080
|
-
const ESM_IMPORT_LINE_RE = /^[ \t]*import[^\n]*$/gm;
|
|
40081
|
-
const ESM_EXPORT_LIST_RE = /^[ \t]*export[ \t]*\{([^}\n]+)\}[ \t]*;?$/gm;
|
|
40082
|
-
const ESM_EXPORT_DECLARATION_RE = /\bexport\s+(const|let|var|function|class)\s+([A-Za-z_$][\w$]*)/g;
|
|
40083
|
-
const ESM_EXPORT_DEFAULT_DECLARATION_RE = /\bexport\s+default\s+(function|class)\s+([A-Za-z_$][\w$]*)/g;
|
|
40084
|
-
function isImportWhitespace(value) {
|
|
40085
|
-
return value === " " || value === " ";
|
|
40086
|
-
}
|
|
40087
|
-
function parseEsmImportLine(line) {
|
|
40088
|
-
let statement = line.trim().slice(6).trim();
|
|
40089
|
-
if (statement.endsWith(";")) statement = statement.slice(0, -1).trimEnd();
|
|
40090
|
-
if (statement.startsWith("\"") || statement.startsWith("'")) {
|
|
40091
|
-
const quote = statement[0];
|
|
40092
|
-
if (statement.endsWith(quote) && statement.length > 1) return {
|
|
40093
|
-
request: statement.slice(1, -1),
|
|
40094
|
-
sideEffect: true
|
|
40095
|
-
};
|
|
40096
|
-
return;
|
|
40097
|
-
}
|
|
40098
|
-
let fromIndex = statement.indexOf("from");
|
|
40099
|
-
while (fromIndex >= 0) {
|
|
40100
|
-
if (isImportWhitespace(statement[fromIndex - 1]) && isImportWhitespace(statement[fromIndex + 4])) break;
|
|
40101
|
-
fromIndex = statement.indexOf("from", fromIndex + 4);
|
|
40102
|
-
}
|
|
40103
|
-
if (fromIndex < 0) return;
|
|
40104
|
-
const specifier = statement.slice(0, fromIndex).trim();
|
|
40105
|
-
const requestLiteral = statement.slice(fromIndex + 4).trim();
|
|
40106
|
-
const quote = requestLiteral[0];
|
|
40107
|
-
if (!specifier || quote !== "\"" && quote !== "'" || requestLiteral.length < 2 || !requestLiteral.endsWith(quote)) return;
|
|
40108
|
-
return {
|
|
40109
|
-
request: requestLiteral.slice(1, -1),
|
|
40110
|
-
sideEffect: false,
|
|
40111
|
-
specifier
|
|
40112
|
-
};
|
|
40113
|
-
}
|
|
40114
|
-
function createEsmImportBindings(specifier, request, index) {
|
|
40115
|
-
const namespaceName = `__headlessEsmImport${index}`;
|
|
40116
|
-
const statements = [`const ${namespaceName} = require(${JSON.stringify(request)});`];
|
|
40117
|
-
const normalizedSpecifier = specifier.trim();
|
|
40118
|
-
if (normalizedSpecifier.startsWith("{") && normalizedSpecifier.endsWith("}")) {
|
|
40119
|
-
const entries = normalizedSpecifier.slice(1, -1).split(",");
|
|
40120
|
-
for (const entry of entries) {
|
|
40121
|
-
const [importedName, localName] = entry.trim().split(/\s+as\s+/);
|
|
40122
|
-
if (!importedName) continue;
|
|
40123
|
-
const bindingName = localName || importedName;
|
|
40124
|
-
statements.push(`const ${bindingName} = ${namespaceName}[${JSON.stringify(importedName)}];`);
|
|
40125
|
-
}
|
|
40126
|
-
return statements.join("\n");
|
|
40127
|
-
}
|
|
40128
|
-
if (normalizedSpecifier.startsWith("* as ")) {
|
|
40129
|
-
const bindingName = normalizedSpecifier.slice(5).trim();
|
|
40130
|
-
statements.push(`const ${bindingName} = ${namespaceName};`);
|
|
40131
|
-
return statements.join("\n");
|
|
40132
|
-
}
|
|
40133
|
-
const [defaultName, namedPart] = normalizedSpecifier.split(/\s*,\s*/, 2);
|
|
40134
|
-
if (defaultName) statements.push(`const ${defaultName.trim()} = ${namespaceName}.default ?? ${namespaceName};`);
|
|
40135
|
-
if (namedPart?.startsWith("{") && namedPart.endsWith("}")) statements.push(createEsmImportBindings(namedPart, request, index).split("\n").slice(1).join("\n"));
|
|
40136
|
-
return statements.join("\n");
|
|
40137
|
-
}
|
|
40138
|
-
function transformEsmToCommonJs(source) {
|
|
40139
|
-
if (!/^\s*(?:import|export)\b/m.test(source)) return source;
|
|
40140
|
-
let importIndex = 0;
|
|
40141
|
-
const exportedNames = [];
|
|
40142
|
-
let transformed = source.replace(ESM_IMPORT_LINE_RE, (line) => {
|
|
40143
|
-
const parsed = parseEsmImportLine(line);
|
|
40144
|
-
if (!parsed) return line;
|
|
40145
|
-
if (parsed.sideEffect) return `require(${JSON.stringify(parsed.request)});`;
|
|
40146
|
-
return createEsmImportBindings(parsed.specifier, parsed.request, importIndex++);
|
|
40147
|
-
});
|
|
40148
|
-
transformed = transformed.replace(ESM_EXPORT_LIST_RE, (_match, entries) => {
|
|
40149
|
-
for (const entry of entries.split(",")) {
|
|
40150
|
-
const [local, exported] = entry.trim().split(/\s+as\s+/);
|
|
40151
|
-
if (local) exportedNames.push({
|
|
40152
|
-
exported: exported || local,
|
|
40153
|
-
local
|
|
40154
|
-
});
|
|
40155
|
-
}
|
|
40156
|
-
return "";
|
|
40157
|
-
});
|
|
40158
|
-
transformed = transformed.replace(ESM_EXPORT_DEFAULT_DECLARATION_RE, (_match, kind, local) => {
|
|
40159
|
-
exportedNames.push({
|
|
40160
|
-
exported: "default",
|
|
40161
|
-
local
|
|
40162
|
-
});
|
|
40163
|
-
return `${kind} ${local}`;
|
|
40164
|
-
});
|
|
40165
|
-
transformed = transformed.replace(ESM_EXPORT_DECLARATION_RE, (_match, kind, local) => {
|
|
40166
|
-
exportedNames.push({
|
|
40167
|
-
exported: local,
|
|
40168
|
-
local
|
|
40169
|
-
});
|
|
40170
|
-
return `${kind} ${local}`;
|
|
40171
|
-
});
|
|
40172
|
-
transformed = transformed.replace(/\bexport\s+default\s+/g, "module.exports.default = ");
|
|
40173
|
-
if (exportedNames.length > 0) transformed += `\n${exportedNames.map(({ exported, local }) => `module.exports[${JSON.stringify(exported)}] = ${local};`).join("\n")}`;
|
|
40174
|
-
return transformed;
|
|
40175
|
-
}
|
|
40176
41061
|
function createRequireNotFoundError(request, importer) {
|
|
40177
41062
|
return /* @__PURE__ */ new Error(`Cannot resolve require("${request}") from ${normalize(importer)} in headless runtime.`);
|
|
40178
41063
|
}
|
|
@@ -40232,6 +41117,7 @@ function createModuleLoader(registries, getCurrentPages, getApp, wxDriver, optio
|
|
|
40232
41117
|
const source = options.artifactSource.readText(resolvedPath);
|
|
40233
41118
|
if (source == null) throw new TypeError(`Missing module in headless runtime: ${normalize(resolvedPath)}`);
|
|
40234
41119
|
const module = {
|
|
41120
|
+
source,
|
|
40235
41121
|
componentDefinitions: [],
|
|
40236
41122
|
exports: {}
|
|
40237
41123
|
};
|
|
@@ -40241,7 +41127,7 @@ function createModuleLoader(registries, getCurrentPages, getApp, wxDriver, optio
|
|
|
40241
41127
|
const previousLoadContext = registries.currentLoadContext;
|
|
40242
41128
|
registries.currentLoadContext = loadContext;
|
|
40243
41129
|
const localRequire = ((request) => {
|
|
40244
|
-
const requiredPath = resolveMiniProgramModule(resolvedPath, request, options.miniprogramRootPath, (candidate) => options.artifactSource.
|
|
41130
|
+
const requiredPath = resolveMiniProgramModule(resolvedPath, request, options.miniprogramRootPath, (candidate) => options.artifactSource.has(candidate));
|
|
40245
41131
|
if (!requiredPath) throw createRequireNotFoundError(request, resolvedPath);
|
|
40246
41132
|
if (requiredPath.endsWith(".json")) {
|
|
40247
41133
|
const content = options.artifactSource.readText(requiredPath);
|
|
@@ -40254,7 +41140,7 @@ function createModuleLoader(registries, getCurrentPages, getApp, wxDriver, optio
|
|
|
40254
41140
|
});
|
|
40255
41141
|
localRequire.async = (request) => Promise.resolve().then(() => localRequire(request));
|
|
40256
41142
|
try {
|
|
40257
|
-
new vm.Script(`(function (exports, module, require, __filename, __dirname) { ${
|
|
41143
|
+
new vm.Script(`(function (exports, module, require, __filename, __dirname) { ${transformMiniProgramModule(source)}\n})`, { filename: resolvedPath }).runInNewContext(executionContext)(module.exports, module, localRequire, resolvedPath, path.dirname(resolvedPath));
|
|
40258
41144
|
const registeredDefinitions = [...registries.components.values()].filter((definition) => !registeredDefinitionsBefore.has(definition));
|
|
40259
41145
|
module.componentDefinitions = [.../* @__PURE__ */ new Set([
|
|
40260
41146
|
...requiredComponentDefinitions,
|
|
@@ -40301,6 +41187,17 @@ function createModuleLoader(registries, getCurrentPages, getApp, wxDriver, optio
|
|
|
40301
41187
|
if (!definition) throw new Error(`Page() was not registered for route "${route}" while executing ${normalize(filePath)}.`);
|
|
40302
41188
|
return definition;
|
|
40303
41189
|
},
|
|
41190
|
+
reloadPageModule(filePath, route) {
|
|
41191
|
+
const resolvedPath = path.resolve(filePath);
|
|
41192
|
+
return reloadPageModuleDefinition({
|
|
41193
|
+
filePath: resolvedPath,
|
|
41194
|
+
route,
|
|
41195
|
+
source: options.artifactSource.readText(resolvedPath),
|
|
41196
|
+
cache: moduleCache,
|
|
41197
|
+
registries,
|
|
41198
|
+
execute: () => loader.executePageModule(resolvedPath, route)
|
|
41199
|
+
});
|
|
41200
|
+
},
|
|
40304
41201
|
executeComponentModule(filePath, id) {
|
|
40305
41202
|
const loadedModule = executeModule(filePath, {
|
|
40306
41203
|
kind: "component",
|
|
@@ -40409,7 +41306,15 @@ var HeadlessRouteEvents = class {
|
|
|
40409
41306
|
const callbacks = state.callbacks;
|
|
40410
41307
|
state.callbacks = void 0;
|
|
40411
41308
|
try {
|
|
40412
|
-
|
|
41309
|
+
const event = state.event;
|
|
41310
|
+
this.bus.$emit("appRouteDone", {
|
|
41311
|
+
path: event.path,
|
|
41312
|
+
query: { ...event.query },
|
|
41313
|
+
openType: event.openType,
|
|
41314
|
+
webviewId: event.webviewId,
|
|
41315
|
+
routeEventId: event.routeEventId,
|
|
41316
|
+
timeStamp: event.timeStamp
|
|
41317
|
+
});
|
|
40413
41318
|
} finally {
|
|
40414
41319
|
this.settle(callbacks);
|
|
40415
41320
|
}
|
|
@@ -42293,6 +43198,7 @@ var HeadlessSession = class {
|
|
|
42293
43198
|
appInstance = null;
|
|
42294
43199
|
appLifecycle = new HeadlessAppLifecycle();
|
|
42295
43200
|
moduleLoader;
|
|
43201
|
+
templateRegistration;
|
|
42296
43202
|
routeEvents = new HeadlessRouteEvents((callback) => this.requestRender(callback), (page) => this.currentPageInstance === page && !this.kernel.isClosed);
|
|
42297
43203
|
eventListeners = /* @__PURE__ */ new Map();
|
|
42298
43204
|
registries;
|
|
@@ -42301,8 +43207,13 @@ var HeadlessSession = class {
|
|
|
42301
43207
|
componentCache = /* @__PURE__ */ new Map();
|
|
42302
43208
|
componentScopes = /* @__PURE__ */ new Map();
|
|
42303
43209
|
selectorQueryScopeSnapshots = /* @__PURE__ */ new WeakMap();
|
|
42304
|
-
|
|
42305
|
-
|
|
43210
|
+
renderQueue = new RuntimeRenderQueue({
|
|
43211
|
+
isClosed: () => this.kernel.isClosed,
|
|
43212
|
+
onError: (error) => this.kernel.diagnostics.record("exception", [error]),
|
|
43213
|
+
render: () => {
|
|
43214
|
+
if (this.currentPageInstance) this.renderCurrentPage();
|
|
43215
|
+
}
|
|
43216
|
+
});
|
|
42306
43217
|
tabBarRoutes;
|
|
42307
43218
|
tabPages = /* @__PURE__ */ new Map();
|
|
42308
43219
|
tabBarItems = /* @__PURE__ */ new Map();
|
|
@@ -42321,6 +43232,7 @@ var HeadlessSession = class {
|
|
|
42321
43232
|
constructor(options) {
|
|
42322
43233
|
if (!options.project && !options.projectPath) throw new Error("Headless runtime requires projectPath or project.");
|
|
42323
43234
|
this.project = options.project ?? loadProject(options.projectPath);
|
|
43235
|
+
this.templateRegistration = createTemplateRegistration(this.project.artifactSource, this.project.miniprogramRootPath, options.compiledTemplatePaths);
|
|
42324
43236
|
this.wxState = createHeadlessWxState(this.kernel.scheduler, {
|
|
42325
43237
|
strictMocks: options.strictHostMocks,
|
|
42326
43238
|
readPackageFile: createPackageAssetReader((relative) => this.project.artifactSource.readText(path.join(this.project.miniprogramRootPath, relative)))
|
|
@@ -42458,8 +43370,7 @@ var HeadlessSession = class {
|
|
|
42458
43370
|
failure = { error };
|
|
42459
43371
|
}
|
|
42460
43372
|
this.canvasContexts.clear();
|
|
42461
|
-
this.
|
|
42462
|
-
this.renderRequestPending = false;
|
|
43373
|
+
this.renderQueue.close();
|
|
42463
43374
|
this.appLifecycle.close();
|
|
42464
43375
|
this.routeEvents.close();
|
|
42465
43376
|
this.wxState.close();
|
|
@@ -42509,6 +43420,23 @@ var HeadlessSession = class {
|
|
|
42509
43420
|
this.assertActive();
|
|
42510
43421
|
return this.pages.slice();
|
|
42511
43422
|
}
|
|
43423
|
+
/** 显式重载已变更的页面 entry,保留 App 与依赖缓存;调用者随后自行导航。 */
|
|
43424
|
+
reloadPageDefinition(route) {
|
|
43425
|
+
this.assertActive();
|
|
43426
|
+
const record = resolvePageDefinitionReloadRoute(this.project, route);
|
|
43427
|
+
const filePath = path.resolve(this.project.miniprogramRootPath, `${record.resourcePath ?? record.route}.js`);
|
|
43428
|
+
return this.moduleLoader.reloadPageModule(filePath, record.route);
|
|
43429
|
+
}
|
|
43430
|
+
/** 显式提交编译模板及其 import/include 依赖;不重载脚本、不导航或替换实例。 */
|
|
43431
|
+
reloadTemplates() {
|
|
43432
|
+
this.assertActive();
|
|
43433
|
+
const changed = this.templateRegistration.reload();
|
|
43434
|
+
if (changed) {
|
|
43435
|
+
closeRuntimeWxsLoader(this.moduleLoader);
|
|
43436
|
+
this.requestRender();
|
|
43437
|
+
}
|
|
43438
|
+
return changed;
|
|
43439
|
+
}
|
|
42512
43440
|
getWx() {
|
|
42513
43441
|
this.assertActive();
|
|
42514
43442
|
return this.moduleLoader.wx;
|
|
@@ -42564,7 +43492,7 @@ var HeadlessSession = class {
|
|
|
42564
43492
|
const current = this.requireCurrentPage("renderCurrentPage()");
|
|
42565
43493
|
const rendered = renderRuntimePageTree({
|
|
42566
43494
|
changedPageKeys: current.__lastChangedKeys__ ?? [],
|
|
42567
|
-
artifactSource: this.
|
|
43495
|
+
artifactSource: this.templateRegistration.artifactSource,
|
|
42568
43496
|
componentCache: this.componentCache,
|
|
42569
43497
|
componentScopes: this.componentScopes,
|
|
42570
43498
|
moduleLoader: this.moduleLoader,
|
|
@@ -42594,20 +43522,18 @@ var HeadlessSession = class {
|
|
|
42594
43522
|
dispatchNativeNodeEvent(node, eventName, event, onHandlerResult) {
|
|
42595
43523
|
const current = this.requireCurrentPage("dispatchNativeNodeEvent()");
|
|
42596
43524
|
if (eventName === "tap") this.renderCurrentPage();
|
|
42597
|
-
return dispatchNativeNodeEvent(current, node, eventName, event, this.moduleLoader.wx, (scopeId, method) => this.resolveScopeMethod(current, scopeId, method), onHandlerResult)
|
|
43525
|
+
return dispatchNativeNodeEvent(current, node, eventName, event, this.moduleLoader.wx, (scopeId, method) => this.resolveScopeMethod(current, scopeId, method), onHandlerResult, (scopeId) => {
|
|
43526
|
+
const instance = this.componentCache.get(scopeId);
|
|
43527
|
+
const scope = this.componentScopes.get(scopeId);
|
|
43528
|
+
return instance?.__definition__ && scope ? {
|
|
43529
|
+
definition: instance.__definition__,
|
|
43530
|
+
ownerScopeId: scope.ownerScopeId ?? null
|
|
43531
|
+
} : void 0;
|
|
43532
|
+
});
|
|
42598
43533
|
}
|
|
42599
43534
|
requestRender(callback) {
|
|
42600
43535
|
this.assertActive();
|
|
42601
|
-
|
|
42602
|
-
if (this.renderRequestPending) return;
|
|
42603
|
-
this.renderRequestPending = true;
|
|
42604
|
-
Promise.resolve().then(() => {
|
|
42605
|
-
if (this.kernel.isClosed) return;
|
|
42606
|
-
this.renderRequestPending = false;
|
|
42607
|
-
const callbacks = this.renderRequestCallbacks.splice(0);
|
|
42608
|
-
if (this.currentPageInstance) this.renderCurrentPage();
|
|
42609
|
-
callbacks.forEach((cb) => cb());
|
|
42610
|
-
});
|
|
43536
|
+
this.renderQueue.request(callback);
|
|
42611
43537
|
}
|
|
42612
43538
|
getScopeSnapshot(scopeId) {
|
|
42613
43539
|
const scope = this.componentScopes.get(scopeId);
|
|
@@ -43832,6 +44758,133 @@ var HeadlessTestingPageHandle = class {
|
|
|
43832
44758
|
}
|
|
43833
44759
|
};
|
|
43834
44760
|
//#endregion
|
|
44761
|
+
//#region ../../mpcore/packages/simulator/src/testing/sessionHandle/protocol.ts
|
|
44762
|
+
/** 无头协议只公布已有运行时语义;不把宿主缺失能力伪装为调试器结果。 */
|
|
44763
|
+
var HeadlessTestingProtocolUnsupportedError = class extends Error {
|
|
44764
|
+
method;
|
|
44765
|
+
code = HEADLESS_PROTOCOL_UNSUPPORTED;
|
|
44766
|
+
constructor(method) {
|
|
44767
|
+
super(`Protocol method ${method} is not supported by the headless testing runtime.`);
|
|
44768
|
+
this.method = method;
|
|
44769
|
+
this.name = "HeadlessTestingProtocolUnsupportedError";
|
|
44770
|
+
}
|
|
44771
|
+
};
|
|
44772
|
+
function requireString(params, name) {
|
|
44773
|
+
const value = params[name];
|
|
44774
|
+
if (typeof value !== "string" || !value.trim()) throw new TypeError(`Protocol parameter ${name} must be a non-empty string.`);
|
|
44775
|
+
return value;
|
|
44776
|
+
}
|
|
44777
|
+
function readArgs(params) {
|
|
44778
|
+
if (params.args === void 0) return [];
|
|
44779
|
+
if (!Array.isArray(params.args)) throw new TypeError("Protocol parameter args must be an array.");
|
|
44780
|
+
return cloneProtocolValue(params.args);
|
|
44781
|
+
}
|
|
44782
|
+
function pageSnapshot(page) {
|
|
44783
|
+
return {
|
|
44784
|
+
pageId: page.pageId,
|
|
44785
|
+
path: page.path,
|
|
44786
|
+
query: page.query
|
|
44787
|
+
};
|
|
44788
|
+
}
|
|
44789
|
+
async function dispatch(target, method, params) {
|
|
44790
|
+
switch (method) {
|
|
44791
|
+
case "Tool.getInfo": return await target.toolInfo();
|
|
44792
|
+
case "App.getCurrentPage": {
|
|
44793
|
+
const page = await target.currentPage();
|
|
44794
|
+
return page ? pageSnapshot(page) : null;
|
|
44795
|
+
}
|
|
44796
|
+
case "App.getPageStack": return { pageStack: (await target.getCurrentPages()).map(pageSnapshot) };
|
|
44797
|
+
case "App.callFunction": return { result: cloneProtocolValue(await target.evaluateWithOptions(requireString(params, "functionDeclaration"), {}, ...readArgs(params))) };
|
|
44798
|
+
case "App.callWxMethod": return { result: cloneProtocolValue(await target.callWxMethodWithOptions(requireString(params, "method"), {}, ...readArgs(params))) };
|
|
44799
|
+
default: throw new HeadlessTestingProtocolUnsupportedError(method);
|
|
44800
|
+
}
|
|
44801
|
+
}
|
|
44802
|
+
async function sendHeadlessTestingProtocol(target, method, params, options) {
|
|
44803
|
+
let rejectClosed;
|
|
44804
|
+
const closed = new Promise((_resolve, reject) => {
|
|
44805
|
+
rejectClosed = reject;
|
|
44806
|
+
});
|
|
44807
|
+
const onClose = () => rejectClosed(/* @__PURE__ */ new Error(`The headless testing session closed before protocol method ${method} completed.`));
|
|
44808
|
+
target.on("close", onClose);
|
|
44809
|
+
try {
|
|
44810
|
+
return await runWithTimeout(() => Promise.race([dispatch(target, method, params), closed]), options.timeout, `Timed out executing protocol method ${method} in headless testing runtime.`);
|
|
44811
|
+
} finally {
|
|
44812
|
+
target.off("close", onClose);
|
|
44813
|
+
}
|
|
44814
|
+
}
|
|
44815
|
+
//#endregion
|
|
44816
|
+
//#region ../../mpcore/packages/simulator/src/testing/sessionHandle/cdp.ts
|
|
44817
|
+
/** 保留官方调用形状;当前后端的 enable 会明确报告不支持。 */
|
|
44818
|
+
function createHeadlessTestingCDP(target, assertActive) {
|
|
44819
|
+
let enabling;
|
|
44820
|
+
const enable = (options) => {
|
|
44821
|
+
enabling ??= target.send("App.CDPEnable", {}, options).catch((error) => {
|
|
44822
|
+
enabling = void 0;
|
|
44823
|
+
throw error;
|
|
44824
|
+
});
|
|
44825
|
+
return enabling;
|
|
44826
|
+
};
|
|
44827
|
+
return {
|
|
44828
|
+
enable,
|
|
44829
|
+
async sendCommand(domain, method, params = {}, options) {
|
|
44830
|
+
await enable(options);
|
|
44831
|
+
return await target.send("App.CDPCommand", {
|
|
44832
|
+
domain,
|
|
44833
|
+
method,
|
|
44834
|
+
params
|
|
44835
|
+
}, options);
|
|
44836
|
+
},
|
|
44837
|
+
async listProtocol(options) {
|
|
44838
|
+
await enable(options);
|
|
44839
|
+
return await target.send("App.CDPListProtocol", {}, options);
|
|
44840
|
+
},
|
|
44841
|
+
onEvent() {
|
|
44842
|
+
assertActive();
|
|
44843
|
+
throw new HeadlessTestingProtocolUnsupportedError("App.CDPEvent");
|
|
44844
|
+
}
|
|
44845
|
+
};
|
|
44846
|
+
}
|
|
44847
|
+
//#endregion
|
|
44848
|
+
//#region ../../mpcore/packages/simulator/src/testing/sessionHandle/navigation.ts
|
|
44849
|
+
/** 所有测试句柄通过同一个 wx 导航边界等待成功、失败或关闭通知。 */
|
|
44850
|
+
var HeadlessTestingNavigation = class {
|
|
44851
|
+
session;
|
|
44852
|
+
pending = /* @__PURE__ */ new Set();
|
|
44853
|
+
constructor(session) {
|
|
44854
|
+
this.session = session;
|
|
44855
|
+
session.on("close", () => {
|
|
44856
|
+
for (const reject of this.pending) reject(/* @__PURE__ */ new Error("The headless testing session closed before navigation completed."));
|
|
44857
|
+
this.pending.clear();
|
|
44858
|
+
});
|
|
44859
|
+
}
|
|
44860
|
+
invoke(methodName, options) {
|
|
44861
|
+
return new Promise((resolve, reject) => {
|
|
44862
|
+
const rejectNavigation = (error) => {
|
|
44863
|
+
this.pending.delete(rejectNavigation);
|
|
44864
|
+
reject(error);
|
|
44865
|
+
};
|
|
44866
|
+
this.pending.add(rejectNavigation);
|
|
44867
|
+
try {
|
|
44868
|
+
this.session.callWxMethod(methodName, {
|
|
44869
|
+
...options,
|
|
44870
|
+
success: () => {
|
|
44871
|
+
this.pending.delete(rejectNavigation);
|
|
44872
|
+
resolve();
|
|
44873
|
+
},
|
|
44874
|
+
fail: (error) => {
|
|
44875
|
+
const details = error && typeof error === "object" ? error : void 0;
|
|
44876
|
+
const reason = typeof details?.errMsg === "string" ? details.errMsg : typeof details?.message === "string" ? details.message : String(error);
|
|
44877
|
+
const target = options.url ? ` route "${options.url}"` : "";
|
|
44878
|
+
rejectNavigation(new Error(`Failed to ${methodName}${target} through the headless wx runtime: ${reason}`, { cause: error }));
|
|
44879
|
+
}
|
|
44880
|
+
});
|
|
44881
|
+
} catch (error) {
|
|
44882
|
+
rejectNavigation(error);
|
|
44883
|
+
}
|
|
44884
|
+
});
|
|
44885
|
+
}
|
|
44886
|
+
};
|
|
44887
|
+
//#endregion
|
|
43835
44888
|
//#region ../../mpcore/packages/simulator/src/testing/sessionHandle/scope.ts
|
|
43836
44889
|
var HeadlessTestingScopeHandle = class HeadlessTestingScopeHandle {
|
|
43837
44890
|
scopeId;
|
|
@@ -43893,20 +44946,41 @@ var HeadlessTestingScopeHandle = class HeadlessTestingScopeHandle {
|
|
|
43893
44946
|
var HeadlessTestingSessionHandle = class {
|
|
43894
44947
|
project;
|
|
43895
44948
|
session;
|
|
43896
|
-
|
|
44949
|
+
navigation;
|
|
44950
|
+
disconnection;
|
|
44951
|
+
cdp;
|
|
43897
44952
|
constructor(project, session) {
|
|
43898
44953
|
this.project = project;
|
|
43899
44954
|
this.session = session;
|
|
43900
|
-
this.
|
|
43901
|
-
for (const reject of this.pendingNavigations) reject(/* @__PURE__ */ new Error("The headless testing session closed before navigation completed."));
|
|
43902
|
-
});
|
|
44955
|
+
this.navigation = new HeadlessTestingNavigation(session);
|
|
43903
44956
|
}
|
|
43904
|
-
|
|
43905
|
-
this.disconnect();
|
|
44957
|
+
close() {
|
|
44958
|
+
return this.disconnect();
|
|
43906
44959
|
}
|
|
43907
|
-
/**
|
|
44960
|
+
/** 先保存共享结果,再同步开始关闭,覆盖关闭监听器内的重入调用。 */
|
|
43908
44961
|
disconnect() {
|
|
43909
|
-
this.
|
|
44962
|
+
if (!this.disconnection) {
|
|
44963
|
+
let resolve;
|
|
44964
|
+
let reject;
|
|
44965
|
+
this.disconnection = new Promise((accept, fail) => {
|
|
44966
|
+
resolve = accept;
|
|
44967
|
+
reject = fail;
|
|
44968
|
+
});
|
|
44969
|
+
try {
|
|
44970
|
+
this.session.close();
|
|
44971
|
+
resolve();
|
|
44972
|
+
} catch (error) {
|
|
44973
|
+
reject(error);
|
|
44974
|
+
}
|
|
44975
|
+
}
|
|
44976
|
+
return this.disconnection;
|
|
44977
|
+
}
|
|
44978
|
+
async send(method, params = {}, options = {}) {
|
|
44979
|
+
this.session.assertActive();
|
|
44980
|
+
return await sendHeadlessTestingProtocol(this, method, params, options);
|
|
44981
|
+
}
|
|
44982
|
+
CDP() {
|
|
44983
|
+
return this.cdp ??= createHeadlessTestingCDP(this, () => this.session.assertActive());
|
|
43910
44984
|
}
|
|
43911
44985
|
async toolInfo() {
|
|
43912
44986
|
return { version: "mpcore-simulator" };
|
|
@@ -43976,23 +45050,31 @@ var HeadlessTestingSessionHandle = class {
|
|
|
43976
45050
|
}, `Timed out waiting for ${normalizedCount} component(s) matching "${normalizedSelector}" in headless testing runtime.`, options);
|
|
43977
45051
|
}
|
|
43978
45052
|
async reLaunch(route) {
|
|
43979
|
-
await this.
|
|
45053
|
+
await this.navigation.invoke("reLaunch", { url: route });
|
|
43980
45054
|
return await this.requireCurrentPage("reLaunch", route);
|
|
43981
45055
|
}
|
|
45056
|
+
/** 只更新页面定义;不隐式导航,也不替换当前页面或应用实例。 */
|
|
45057
|
+
async reloadPageDefinition(route) {
|
|
45058
|
+
return this.session.reloadPageDefinition(route);
|
|
45059
|
+
}
|
|
45060
|
+
/** 显式提交宿主编译模板;不隐式重载脚本或导航。 */
|
|
45061
|
+
async reloadTemplates() {
|
|
45062
|
+
return this.session.reloadTemplates();
|
|
45063
|
+
}
|
|
43982
45064
|
async navigateTo(route) {
|
|
43983
|
-
await this.
|
|
45065
|
+
await this.navigation.invoke("navigateTo", { url: route });
|
|
43984
45066
|
return await this.requireCurrentPage("navigateTo", route);
|
|
43985
45067
|
}
|
|
43986
45068
|
async redirectTo(route) {
|
|
43987
|
-
await this.
|
|
45069
|
+
await this.navigation.invoke("redirectTo", { url: route });
|
|
43988
45070
|
return await this.requireCurrentPage("redirectTo", route);
|
|
43989
45071
|
}
|
|
43990
45072
|
async navigateBack(delta = 1) {
|
|
43991
|
-
await this.
|
|
45073
|
+
await this.navigation.invoke("navigateBack", { delta });
|
|
43992
45074
|
return await this.currentPage();
|
|
43993
45075
|
}
|
|
43994
45076
|
async switchTab(route) {
|
|
43995
|
-
await this.
|
|
45077
|
+
await this.navigation.invoke("switchTab", { url: route });
|
|
43996
45078
|
return await this.requireCurrentPage("switchTab", route);
|
|
43997
45079
|
}
|
|
43998
45080
|
async waitForCurrentPage(route, options = {}) {
|
|
@@ -44028,32 +45110,6 @@ var HeadlessTestingSessionHandle = class {
|
|
|
44028
45110
|
async triggerRouteDone(options) {
|
|
44029
45111
|
this.session.triggerRouteDone(options);
|
|
44030
45112
|
}
|
|
44031
|
-
invokeNavigation(methodName, options) {
|
|
44032
|
-
return new Promise((resolve, reject) => {
|
|
44033
|
-
const rejectNavigation = (error) => {
|
|
44034
|
-
this.pendingNavigations.delete(rejectNavigation);
|
|
44035
|
-
reject(error);
|
|
44036
|
-
};
|
|
44037
|
-
this.pendingNavigations.add(rejectNavigation);
|
|
44038
|
-
try {
|
|
44039
|
-
this.session.callWxMethod(methodName, {
|
|
44040
|
-
...options,
|
|
44041
|
-
success: () => {
|
|
44042
|
-
this.pendingNavigations.delete(rejectNavigation);
|
|
44043
|
-
resolve();
|
|
44044
|
-
},
|
|
44045
|
-
fail: (error) => {
|
|
44046
|
-
const details = error && typeof error === "object" ? error : void 0;
|
|
44047
|
-
const reason = typeof details?.errMsg === "string" ? details.errMsg : typeof details?.message === "string" ? details.message : String(error);
|
|
44048
|
-
const target = options.url ? ` route "${options.url}"` : "";
|
|
44049
|
-
rejectNavigation(new Error(`Failed to ${methodName}${target} through the headless wx runtime: ${reason}`, { cause: error }));
|
|
44050
|
-
}
|
|
44051
|
-
});
|
|
44052
|
-
} catch (error) {
|
|
44053
|
-
rejectNavigation(error);
|
|
44054
|
-
}
|
|
44055
|
-
});
|
|
44056
|
-
}
|
|
44057
45113
|
async requireCurrentPage(methodName, route) {
|
|
44058
45114
|
const page = await this.currentPage();
|
|
44059
45115
|
if (!page) throw new Error(`Failed to ${methodName} route "${route}" through the headless wx runtime.`);
|
|
@@ -44072,7 +45128,10 @@ function resolveInitialRoute(session) {
|
|
|
44072
45128
|
return session.project.routes[0]?.route ?? null;
|
|
44073
45129
|
}
|
|
44074
45130
|
async function launch(options) {
|
|
44075
|
-
const session = createHeadlessSession({
|
|
45131
|
+
const session = createHeadlessSession({
|
|
45132
|
+
compiledTemplatePaths: options.compiledTemplatePaths,
|
|
45133
|
+
projectPath: options.projectPath
|
|
45134
|
+
});
|
|
44076
45135
|
const handle = new HeadlessTestingSessionHandle(session.project, session);
|
|
44077
45136
|
try {
|
|
44078
45137
|
await options.onSessionCreated?.(handle);
|