@weapp-vite/miniprogram-automator 1.2.13 → 1.2.15
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 +19 -0
- package/dist/index.d.mts +9 -3
- package/dist/index.mjs +465 -42
- package/dist/{launch-yIGimB0F.mjs → launch-Dqnd-Lqe.mjs} +350 -42
- package/package.json +1 -1
|
@@ -12036,6 +12036,42 @@ function resolveTemplateData(node, source) {
|
|
|
12036
12036
|
return resolved && typeof resolved === "object" ? resolved : {};
|
|
12037
12037
|
}
|
|
12038
12038
|
//#endregion
|
|
12039
|
+
//#region ../../mpcore/packages/simulator/src/project/plugins.ts
|
|
12040
|
+
const HEADLESS_PLUGIN_VIRTUAL_ROOT = "__plugins__";
|
|
12041
|
+
const PLUGIN_URL_RE = /^plugin:\/\/([^/]+)\/(.+)$/;
|
|
12042
|
+
function createPluginVirtualRoot(alias) {
|
|
12043
|
+
return `${HEADLESS_PLUGIN_VIRTUAL_ROOT}/${alias}`;
|
|
12044
|
+
}
|
|
12045
|
+
function resolvePluginRequest(plugins, request, kind) {
|
|
12046
|
+
const match = PLUGIN_URL_RE.exec(request);
|
|
12047
|
+
if (!match) return;
|
|
12048
|
+
const [, alias, publicName] = match;
|
|
12049
|
+
const plugin = plugins.find((item) => item.alias === alias);
|
|
12050
|
+
const registry = kind === "page" ? plugin?.config.pages : plugin?.config.publicComponents;
|
|
12051
|
+
const resourcePath = registry && typeof registry === "object" && !Array.isArray(registry) ? registry[publicName] : void 0;
|
|
12052
|
+
if (!plugin || typeof resourcePath !== "string" || !resourcePath) return;
|
|
12053
|
+
return {
|
|
12054
|
+
plugin,
|
|
12055
|
+
publicName,
|
|
12056
|
+
resourcePath: `${plugin.virtualRoot}/${resourcePath}`
|
|
12057
|
+
};
|
|
12058
|
+
}
|
|
12059
|
+
function createPluginArtifactSource(fallback, miniprogramRootPath, plugins) {
|
|
12060
|
+
function resolvePhysicalPath(filePath) {
|
|
12061
|
+
const normalizedPath = path.resolve(filePath);
|
|
12062
|
+
for (const plugin of plugins) {
|
|
12063
|
+
const virtualRootPath = path.resolve(miniprogramRootPath, plugin.virtualRoot);
|
|
12064
|
+
const relativePath = path.relative(virtualRootPath, normalizedPath);
|
|
12065
|
+
if (!relativePath.startsWith("..") && !path.isAbsolute(relativePath)) return path.resolve(plugin.rootPath, relativePath);
|
|
12066
|
+
}
|
|
12067
|
+
return normalizedPath;
|
|
12068
|
+
}
|
|
12069
|
+
return {
|
|
12070
|
+
has: (filePath) => fallback.has(resolvePhysicalPath(filePath)),
|
|
12071
|
+
readText: (filePath) => fallback.readText(resolvePhysicalPath(filePath))
|
|
12072
|
+
};
|
|
12073
|
+
}
|
|
12074
|
+
//#endregion
|
|
12039
12075
|
//#region ../../mpcore/packages/simulator/src/view/eventBinding.ts
|
|
12040
12076
|
const LEGACY_EVENT_NAME_RE = /^\w+$/;
|
|
12041
12077
|
const EVENT_BINDING_PREFIXES = [
|
|
@@ -14583,11 +14619,12 @@ function isMustacheOnly(value) {
|
|
|
14583
14619
|
function toDatasetKey$3(attributeName) {
|
|
14584
14620
|
return attributeName.slice(5).replace(DATASET_NAME_RE$3, (_match, char) => char.toUpperCase());
|
|
14585
14621
|
}
|
|
14586
|
-
function collectDataset$3(node) {
|
|
14622
|
+
function collectDataset$3(node, source) {
|
|
14587
14623
|
const dataset = {};
|
|
14588
14624
|
for (const [key, value] of Object.entries(node.attribs ?? {})) {
|
|
14589
14625
|
if (!key.startsWith("data-") || key === "data-sim-scope" || key === "data-sim-tap" || key === "data-sim-component") continue;
|
|
14590
|
-
|
|
14626
|
+
const resolvedValue = source && isMustacheOnly(value) ? resolveTemplateExpression(source, value) : value;
|
|
14627
|
+
dataset[toDatasetKey$3(key)] = String(resolvedValue ?? "");
|
|
14591
14628
|
}
|
|
14592
14629
|
return dataset;
|
|
14593
14630
|
}
|
|
@@ -14698,7 +14735,7 @@ function createLoopScope(scope, itemName, indexName, item, index) {
|
|
|
14698
14735
|
//#endregion
|
|
14699
14736
|
//#region ../../mpcore/packages/simulator/src/runtime/render/component.ts
|
|
14700
14737
|
function resolveComponentRegistryEntry(context, ownerJsonPath, ownerFilePath, alias, genericComponentBasePath) {
|
|
14701
|
-
const usingComponents = resolveUsingComponents(context
|
|
14738
|
+
const usingComponents = resolveUsingComponents(context, ownerJsonPath, ownerFilePath);
|
|
14702
14739
|
const componentBasePath = genericComponentBasePath ?? usingComponents.get(alias);
|
|
14703
14740
|
if (!componentBasePath) return null;
|
|
14704
14741
|
const filePath = `${componentBasePath}.js`;
|
|
@@ -14720,14 +14757,14 @@ function readComponentConfig(artifactSource, jsonPath) {
|
|
|
14720
14757
|
return {};
|
|
14721
14758
|
}
|
|
14722
14759
|
}
|
|
14723
|
-
function resolveUsingComponents(
|
|
14760
|
+
function resolveUsingComponents(context, ownerJsonPath, ownerFilePath) {
|
|
14724
14761
|
try {
|
|
14725
|
-
const usingComponents = readComponentConfig(artifactSource, ownerJsonPath).usingComponents;
|
|
14762
|
+
const usingComponents = readComponentConfig(context.artifactSource, ownerJsonPath).usingComponents;
|
|
14726
14763
|
if (!usingComponents || typeof usingComponents !== "object" || Array.isArray(usingComponents)) return /* @__PURE__ */ new Map();
|
|
14727
14764
|
const resolved = /* @__PURE__ */ new Map();
|
|
14728
14765
|
for (const [alias, rawPath] of Object.entries(usingComponents)) {
|
|
14729
14766
|
if (typeof rawPath !== "string") continue;
|
|
14730
|
-
const basePath = rawPath.startsWith("/") ? rawPath.replace(LEADING_SLASH_RE$4, "") : path.posix.normalize(path.posix.join(path.posix.dirname(ownerFilePath), rawPath));
|
|
14767
|
+
const basePath = resolvePluginRequest(context.project.plugins, rawPath, "publicComponent")?.resourcePath ?? (rawPath.startsWith("/") ? rawPath.replace(LEADING_SLASH_RE$4, "") : path.posix.normalize(path.posix.join(path.posix.dirname(ownerFilePath), rawPath)));
|
|
14731
14768
|
resolved.set(alias, basePath.replace(LEADING_SLASH_RE$4, ""));
|
|
14732
14769
|
}
|
|
14733
14770
|
return resolved;
|
|
@@ -14739,7 +14776,7 @@ function resolveComponentGenerics(context, hostNode, ownerJsonPath, ownerFilePat
|
|
|
14739
14776
|
const componentJsonPath = path.resolve(context.project.miniprogramRootPath, `${componentFilePath.replace(JS_FILE_RE, "")}.json`);
|
|
14740
14777
|
const componentGenerics = readComponentConfig(context.artifactSource, componentJsonPath).componentGenerics;
|
|
14741
14778
|
if (!componentGenerics || typeof componentGenerics !== "object" || Array.isArray(componentGenerics)) return;
|
|
14742
|
-
const ownerComponents = resolveUsingComponents(context
|
|
14779
|
+
const ownerComponents = resolveUsingComponents(context, ownerJsonPath, ownerFilePath);
|
|
14743
14780
|
const resolved = /* @__PURE__ */ new Map();
|
|
14744
14781
|
for (const [genericName, definition] of Object.entries(componentGenerics)) {
|
|
14745
14782
|
const selectedAlias = hostNode.attribs?.[`generic:${genericName}`];
|
|
@@ -14764,9 +14801,10 @@ function buildComponentTrigger(componentScopeId, context, hostNode) {
|
|
|
14764
14801
|
return (instance, eventName, detail, triggerOptions) => {
|
|
14765
14802
|
const interactionTarget = instance.__lastInteractionEvent__?.target;
|
|
14766
14803
|
const interactionCurrentTarget = instance.__lastInteractionEvent__?.currentTarget;
|
|
14804
|
+
const componentDataset = context.componentScopes.get(componentScopeId)?.dataset ?? hostDataset;
|
|
14767
14805
|
const interactionMark = instance.__lastInteractionEvent__?.mark;
|
|
14768
14806
|
const target = {
|
|
14769
|
-
dataset: interactionTarget?.dataset ??
|
|
14807
|
+
dataset: interactionTarget?.dataset ?? componentDataset,
|
|
14770
14808
|
id: interactionTarget?.id ?? hostId
|
|
14771
14809
|
};
|
|
14772
14810
|
let currentScopeId = componentScopeId;
|
|
@@ -14822,7 +14860,7 @@ function createComponentScope(clonedNode, scope, componentScopeId, componentInst
|
|
|
14822
14860
|
alias: clonedNode.name,
|
|
14823
14861
|
classList: String(clonedNode.attribs?.class ?? "").split(CLASS_SPLIT_RE).map((item) => item.trim()).filter(Boolean),
|
|
14824
14862
|
data: createMergedScopeData(scope.data, componentInstance.properties, componentInstance.data),
|
|
14825
|
-
dataset: collectDataset$3(clonedNode),
|
|
14863
|
+
dataset: collectDataset$3(clonedNode, scope.data),
|
|
14826
14864
|
eventBindings: collectComponentEventBindings(clonedNode),
|
|
14827
14865
|
getMethod: (methodName) => {
|
|
14828
14866
|
const method = componentInstance?.[methodName];
|
|
@@ -14854,9 +14892,10 @@ function resolveComponentProperties(clonedNode, scope, definition) {
|
|
|
14854
14892
|
};
|
|
14855
14893
|
}
|
|
14856
14894
|
function createRuntimeComponentInstance(componentScopeId, context, clonedNode, componentEntry, nextProperties, ownerScopeId) {
|
|
14895
|
+
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;
|
|
14857
14896
|
const componentInstance = createComponentInstance({
|
|
14858
14897
|
definition: componentEntry.definition,
|
|
14859
|
-
properties:
|
|
14898
|
+
properties: componentProperties,
|
|
14860
14899
|
requestRender: (callback) => context.session.requestRender(callback),
|
|
14861
14900
|
triggerEvent: buildComponentTrigger(componentScopeId, context, clonedNode)
|
|
14862
14901
|
});
|
|
@@ -14869,7 +14908,7 @@ function createRuntimeComponentInstance(componentScopeId, context, clonedNode, c
|
|
|
14869
14908
|
componentInstance.selectOwnerComponent = () => ownerScopeId ? context.componentCache.get(ownerScopeId) ?? null : null;
|
|
14870
14909
|
context.componentCache.set(componentScopeId, componentInstance);
|
|
14871
14910
|
runComponentLifecycle(componentInstance, "created");
|
|
14872
|
-
runComponentObservers(componentInstance.__definition__ ?? componentEntry.definition, componentInstance, Object.keys(
|
|
14911
|
+
runComponentObservers(componentInstance.__definition__ ?? componentEntry.definition, componentInstance, Object.keys(componentProperties), {});
|
|
14873
14912
|
componentInstance.__propertySnapshots = Object.fromEntries(Object.entries(componentInstance.properties).map(([key, propertyValue]) => [key, cloneValue$1(propertyValue)]));
|
|
14874
14913
|
runComponentLifecycle(componentInstance, "attached");
|
|
14875
14914
|
return componentInstance;
|
|
@@ -15050,7 +15089,8 @@ function renderNodeTree(node, scope, context, ownerJsonPath, ownerFilePath, inst
|
|
|
15050
15089
|
}
|
|
15051
15090
|
function renderRuntimePageTree(context, page) {
|
|
15052
15091
|
const route = page.route.replace(LEADING_SLASH_RE$4, "");
|
|
15053
|
-
const
|
|
15092
|
+
const resourcePath = context.project.routes.find((item) => item.route === route)?.resourcePath ?? route;
|
|
15093
|
+
const templatePath = path.resolve(context.project.miniprogramRootPath, `${resourcePath}.wxml`);
|
|
15054
15094
|
const document = parseTemplateDocument(readTemplateSource(context.artifactSource, templatePath));
|
|
15055
15095
|
const pageScopeId = `page:${route}`;
|
|
15056
15096
|
const pageScope = {
|
|
@@ -15067,7 +15107,7 @@ function renderRuntimePageTree(context, page) {
|
|
|
15067
15107
|
const seenComponentScopes = /* @__PURE__ */ new Set();
|
|
15068
15108
|
const root = (document.children ?? [])[0] ?? document;
|
|
15069
15109
|
const templateRenderState = createTemplateRenderState(root);
|
|
15070
|
-
const renderedRoot = renderNodeTree(root, pageScope, context, path.resolve(context.project.miniprogramRootPath, `${
|
|
15110
|
+
const renderedRoot = renderNodeTree(root, pageScope, context, path.resolve(context.project.miniprogramRootPath, `${resourcePath}.json`), `${resourcePath}.js`, pageScopeId, seenComponentScopes, templateRenderState);
|
|
15071
15111
|
for (const [scopeId, instance] of [...context.componentCache.entries()]) if (!seenComponentScopes.has(scopeId)) {
|
|
15072
15112
|
runComponentLifecycle(instance, "detached");
|
|
15073
15113
|
context.componentCache.delete(scopeId);
|
|
@@ -15138,15 +15178,21 @@ function registerAppDefinition(registries, definition) {
|
|
|
15138
15178
|
registries.appDefinition = definition;
|
|
15139
15179
|
return definition;
|
|
15140
15180
|
}
|
|
15141
|
-
function registerPageDefinition(registries, definition) {
|
|
15142
|
-
const route = registries.currentLoadContext?.route;
|
|
15181
|
+
function registerPageDefinition(registries, definition, explicitRoute) {
|
|
15182
|
+
const route = explicitRoute ?? registries.currentLoadContext?.route;
|
|
15143
15183
|
if (!route) throw new Error("Cannot register Page() without an active page load context in headless runtime.");
|
|
15144
15184
|
if (registries.pages.has(route)) throw createDuplicateRegistrationError("page", route);
|
|
15145
15185
|
registries.pages.set(route, definition);
|
|
15146
15186
|
return definition;
|
|
15147
15187
|
}
|
|
15148
15188
|
function registerComponentDefinition(registries, definition) {
|
|
15149
|
-
if (registries.currentLoadContext?.kind === "page")
|
|
15189
|
+
if (registries.currentLoadContext?.kind === "page") {
|
|
15190
|
+
if (registries.currentLoadContext.componentDefinitions) {
|
|
15191
|
+
registries.currentLoadContext.componentDefinitions.push(definition);
|
|
15192
|
+
return definition;
|
|
15193
|
+
}
|
|
15194
|
+
return registerPageDefinition(registries, normalizeComponentPageDefinition(definition));
|
|
15195
|
+
}
|
|
15150
15196
|
const id = registries.currentLoadContext?.route ?? `anonymous:${registries.components.size}`;
|
|
15151
15197
|
if (registries.components.has(id)) throw createDuplicateRegistrationError("component", id);
|
|
15152
15198
|
registries.components.set(id, definition);
|
|
@@ -15694,15 +15740,24 @@ var RuntimeDiagnostics = class {
|
|
|
15694
15740
|
timestamp: Date.now()
|
|
15695
15741
|
});
|
|
15696
15742
|
}
|
|
15697
|
-
createConsole(baseConsole = console) {
|
|
15743
|
+
createConsole(baseConsole = console, onConsole) {
|
|
15698
15744
|
const runtimeConsole = Object.create(baseConsole);
|
|
15745
|
+
const wrap = (level, method) => (...args) => {
|
|
15746
|
+
if (level === "error" || level === "warn") this.record(level, args);
|
|
15747
|
+
onConsole?.({
|
|
15748
|
+
args: [...args],
|
|
15749
|
+
level
|
|
15750
|
+
});
|
|
15751
|
+
method(...args);
|
|
15752
|
+
};
|
|
15753
|
+
runtimeConsole.debug = wrap("debug", baseConsole.debug.bind(baseConsole));
|
|
15754
|
+
runtimeConsole.info = wrap("info", baseConsole.info.bind(baseConsole));
|
|
15755
|
+
runtimeConsole.log = wrap("log", baseConsole.log.bind(baseConsole));
|
|
15699
15756
|
runtimeConsole.error = (...args) => {
|
|
15700
|
-
|
|
15701
|
-
baseConsole.error(...args);
|
|
15757
|
+
wrap("error", baseConsole.error.bind(baseConsole))(...args);
|
|
15702
15758
|
};
|
|
15703
15759
|
runtimeConsole.warn = (...args) => {
|
|
15704
|
-
|
|
15705
|
-
baseConsole.warn(...args);
|
|
15760
|
+
wrap("warn", baseConsole.warn.bind(baseConsole))(...args);
|
|
15706
15761
|
};
|
|
15707
15762
|
return runtimeConsole;
|
|
15708
15763
|
}
|
|
@@ -15803,7 +15858,7 @@ function pushRoute(records, seen, record) {
|
|
|
15803
15858
|
seen.add(record.route);
|
|
15804
15859
|
records.push(record);
|
|
15805
15860
|
}
|
|
15806
|
-
function resolveRoutesFromAppConfig(config) {
|
|
15861
|
+
function resolveRoutesFromAppConfig(config, plugins = []) {
|
|
15807
15862
|
const records = [];
|
|
15808
15863
|
const seen = /* @__PURE__ */ new Set();
|
|
15809
15864
|
if (Array.isArray(config.pages)) for (const page of config.pages) {
|
|
@@ -15833,6 +15888,19 @@ function resolveRoutesFromAppConfig(config) {
|
|
|
15833
15888
|
});
|
|
15834
15889
|
}
|
|
15835
15890
|
}
|
|
15891
|
+
for (const plugin of plugins) {
|
|
15892
|
+
const pages = plugin.config.pages;
|
|
15893
|
+
if (!pages || typeof pages !== "object" || Array.isArray(pages)) continue;
|
|
15894
|
+
for (const resourcePath of Object.values(pages)) {
|
|
15895
|
+
if (typeof resourcePath !== "string" || !resourcePath) continue;
|
|
15896
|
+
pushRoute(records, seen, {
|
|
15897
|
+
kind: "page",
|
|
15898
|
+
resourcePath: `${plugin.virtualRoot}/${resourcePath}`,
|
|
15899
|
+
route: `plugin-private://${plugin.provider}/${resourcePath}`,
|
|
15900
|
+
source: "plugin"
|
|
15901
|
+
});
|
|
15902
|
+
}
|
|
15903
|
+
}
|
|
15836
15904
|
return records;
|
|
15837
15905
|
}
|
|
15838
15906
|
//#endregion
|
|
@@ -15844,9 +15912,10 @@ function createProjectDescriptor(options) {
|
|
|
15844
15912
|
appConfigPath: options.appConfigPath,
|
|
15845
15913
|
miniprogramRoot: options.miniprogramRoot,
|
|
15846
15914
|
miniprogramRootPath: options.miniprogramRootPath,
|
|
15915
|
+
plugins: options.plugins ?? [],
|
|
15847
15916
|
projectPath: options.projectPath,
|
|
15848
15917
|
projectConfigFiles: options.projectConfigFiles ?? [],
|
|
15849
|
-
routes: resolveRoutesFromAppConfig(options.appConfig)
|
|
15918
|
+
routes: resolveRoutesFromAppConfig(options.appConfig, options.plugins ?? [])
|
|
15850
15919
|
};
|
|
15851
15920
|
}
|
|
15852
15921
|
//#endregion
|
|
@@ -15963,6 +16032,36 @@ function resolveMiniprogramRoot(projectPath, configFiles) {
|
|
|
15963
16032
|
}
|
|
15964
16033
|
throw new Error(`Failed to resolve miniprogramRoot for headless runtime project: ${projectPath}. Expected project.config.json or project.private.config.json to define miniprogramRoot.`);
|
|
15965
16034
|
}
|
|
16035
|
+
function resolveConfiguredRoot(configFiles, key) {
|
|
16036
|
+
for (const configFile of [...configFiles].reverse()) {
|
|
16037
|
+
const value = configFile.value[key];
|
|
16038
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
16039
|
+
}
|
|
16040
|
+
}
|
|
16041
|
+
function resolveLocalPlugins(projectPath, projectConfigFiles, appConfig) {
|
|
16042
|
+
const pluginRoot = resolveConfiguredRoot(projectConfigFiles, "pluginRoot");
|
|
16043
|
+
const configuredPlugins = appConfig.plugins;
|
|
16044
|
+
if (!pluginRoot || !configuredPlugins || typeof configuredPlugins !== "object" || Array.isArray(configuredPlugins)) return [];
|
|
16045
|
+
const rootPath = path.resolve(projectPath, pluginRoot);
|
|
16046
|
+
const pluginConfig = readJsonObject$1(path.resolve(rootPath, "plugin.json"));
|
|
16047
|
+
if (!pluginConfig) return [];
|
|
16048
|
+
const plugins = [];
|
|
16049
|
+
const projectAppId = resolveConfiguredRoot(projectConfigFiles, "appid");
|
|
16050
|
+
for (const [alias, definition] of Object.entries(configuredPlugins)) {
|
|
16051
|
+
if (!definition || typeof definition !== "object" || Array.isArray(definition)) continue;
|
|
16052
|
+
const provider = definition.provider;
|
|
16053
|
+
const isLocalPlugin = definition.version === "dev" || projectAppId && provider === projectAppId;
|
|
16054
|
+
if (typeof provider !== "string" || !provider || !isLocalPlugin) continue;
|
|
16055
|
+
plugins.push({
|
|
16056
|
+
alias,
|
|
16057
|
+
config: pluginConfig,
|
|
16058
|
+
provider,
|
|
16059
|
+
rootPath,
|
|
16060
|
+
virtualRoot: createPluginVirtualRoot(alias)
|
|
16061
|
+
});
|
|
16062
|
+
}
|
|
16063
|
+
return plugins;
|
|
16064
|
+
}
|
|
15966
16065
|
function ensureFileExists(filePath, label) {
|
|
15967
16066
|
if (fs.existsSync(filePath)) return;
|
|
15968
16067
|
throw new Error(`Missing ${label} for headless runtime project: ${normalize(filePath)}`);
|
|
@@ -15981,11 +16080,15 @@ function loadProject(projectPath) {
|
|
|
15981
16080
|
ensureFileExists(miniprogramRootPath, "miniprogramRoot directory");
|
|
15982
16081
|
const appConfigPath = path.resolve(miniprogramRootPath, "app.json");
|
|
15983
16082
|
ensureFileExists(appConfigPath, "built app.json");
|
|
16083
|
+
const appConfig = loadAppConfig(appConfigPath);
|
|
16084
|
+
const plugins = resolveLocalPlugins(normalizedProjectPath, projectConfigFiles, appConfig);
|
|
15984
16085
|
return createProjectDescriptor({
|
|
15985
|
-
appConfig
|
|
16086
|
+
appConfig,
|
|
15986
16087
|
appConfigPath,
|
|
16088
|
+
artifactSource: createPluginArtifactSource(createFileSystemArtifactSource(), miniprogramRootPath, plugins),
|
|
15987
16089
|
miniprogramRoot,
|
|
15988
16090
|
miniprogramRootPath,
|
|
16091
|
+
plugins,
|
|
15989
16092
|
projectPath: normalizedProjectPath,
|
|
15990
16093
|
projectConfigFiles
|
|
15991
16094
|
});
|
|
@@ -16321,12 +16424,15 @@ function parseNumericLikeValue$1(value) {
|
|
|
16321
16424
|
const match = value.match(NUMERIC_LIKE_VALUE_RE$1);
|
|
16322
16425
|
return match ? Number(match[0]) : 0;
|
|
16323
16426
|
}
|
|
16324
|
-
function resolveRect$1(node) {
|
|
16427
|
+
function resolveRect$1(node, windowInfo) {
|
|
16325
16428
|
const style = parseStyleDeclarations$1(node.attribs?.style);
|
|
16326
16429
|
const left = parseNumericLikeValue$1(node.attribs?.["data-sim-left"] ?? style.left);
|
|
16327
16430
|
const top = parseNumericLikeValue$1(node.attribs?.["data-sim-top"] ?? style.top);
|
|
16328
|
-
const
|
|
16329
|
-
const
|
|
16431
|
+
const rawWidth = node.attribs?.["data-sim-width"] ?? style.width;
|
|
16432
|
+
const rawHeight = node.attribs?.["data-sim-height"] ?? style.height;
|
|
16433
|
+
const isTopLevelView = node.name === "view" && node.parent?.name === "page" && windowInfo?.windowWidth != null;
|
|
16434
|
+
const width = rawWidth != null ? parseNumericLikeValue$1(rawWidth) : isTopLevelView && windowInfo ? windowInfo.windowWidth : 0;
|
|
16435
|
+
const height = rawHeight != null ? parseNumericLikeValue$1(rawHeight) : isTopLevelView && windowInfo ? windowInfo.windowHeight : 0;
|
|
16330
16436
|
return {
|
|
16331
16437
|
bottom: top + height,
|
|
16332
16438
|
height,
|
|
@@ -16373,7 +16479,7 @@ function resolveFieldsResult(node, fields, options) {
|
|
|
16373
16479
|
if (fields.dataset) result.dataset = collectDataset$1(node);
|
|
16374
16480
|
if (fields.mark) result.mark = collectMark(node);
|
|
16375
16481
|
if (fields.rect || fields.size) {
|
|
16376
|
-
const rect = resolveRect$1(node);
|
|
16482
|
+
const rect = resolveRect$1(node, options.root.name === "page" ? options.windowInfo : void 0);
|
|
16377
16483
|
if (fields.rect) Object.assign(result, rect);
|
|
16378
16484
|
if (fields.size) {
|
|
16379
16485
|
result.width = rect.width;
|
|
@@ -17161,6 +17267,102 @@ function createHeadlessVideoContext(driver, videoId, scope) {
|
|
|
17161
17267
|
}
|
|
17162
17268
|
//#endregion
|
|
17163
17269
|
//#region ../../mpcore/packages/simulator/src/runtime/moduleLoader.ts
|
|
17270
|
+
const ESM_IMPORT_LINE_RE = /^[ \t]*import[^\n]*$/gm;
|
|
17271
|
+
const ESM_EXPORT_LIST_RE = /^[ \t]*export[ \t]*\{([^}\n]+)\}[ \t]*;?$/gm;
|
|
17272
|
+
const ESM_EXPORT_DECLARATION_RE = /\bexport\s+(const|let|var|function|class)\s+([A-Za-z_$][\w$]*)/g;
|
|
17273
|
+
const ESM_EXPORT_DEFAULT_DECLARATION_RE = /\bexport\s+default\s+(function|class)\s+([A-Za-z_$][\w$]*)/g;
|
|
17274
|
+
function isImportWhitespace(value) {
|
|
17275
|
+
return value === " " || value === " ";
|
|
17276
|
+
}
|
|
17277
|
+
function parseEsmImportLine(line) {
|
|
17278
|
+
let statement = line.trim().slice(6).trim();
|
|
17279
|
+
if (statement.endsWith(";")) statement = statement.slice(0, -1).trimEnd();
|
|
17280
|
+
if (statement.startsWith("\"") || statement.startsWith("'")) {
|
|
17281
|
+
const quote = statement[0];
|
|
17282
|
+
if (statement.endsWith(quote) && statement.length > 1) return {
|
|
17283
|
+
request: statement.slice(1, -1),
|
|
17284
|
+
sideEffect: true
|
|
17285
|
+
};
|
|
17286
|
+
return;
|
|
17287
|
+
}
|
|
17288
|
+
let fromIndex = statement.indexOf("from");
|
|
17289
|
+
while (fromIndex >= 0) {
|
|
17290
|
+
if (isImportWhitespace(statement[fromIndex - 1]) && isImportWhitespace(statement[fromIndex + 4])) break;
|
|
17291
|
+
fromIndex = statement.indexOf("from", fromIndex + 4);
|
|
17292
|
+
}
|
|
17293
|
+
if (fromIndex < 0) return;
|
|
17294
|
+
const specifier = statement.slice(0, fromIndex).trim();
|
|
17295
|
+
const requestLiteral = statement.slice(fromIndex + 4).trim();
|
|
17296
|
+
const quote = requestLiteral[0];
|
|
17297
|
+
if (!specifier || quote !== "\"" && quote !== "'" || requestLiteral.length < 2 || !requestLiteral.endsWith(quote)) return;
|
|
17298
|
+
return {
|
|
17299
|
+
request: requestLiteral.slice(1, -1),
|
|
17300
|
+
sideEffect: false,
|
|
17301
|
+
specifier
|
|
17302
|
+
};
|
|
17303
|
+
}
|
|
17304
|
+
function createEsmImportBindings(specifier, request, index) {
|
|
17305
|
+
const namespaceName = `__headlessEsmImport${index}`;
|
|
17306
|
+
const statements = [`const ${namespaceName} = require(${JSON.stringify(request)});`];
|
|
17307
|
+
const normalizedSpecifier = specifier.trim();
|
|
17308
|
+
if (normalizedSpecifier.startsWith("{") && normalizedSpecifier.endsWith("}")) {
|
|
17309
|
+
const entries = normalizedSpecifier.slice(1, -1).split(",");
|
|
17310
|
+
for (const entry of entries) {
|
|
17311
|
+
const [importedName, localName] = entry.trim().split(/\s+as\s+/);
|
|
17312
|
+
if (!importedName) continue;
|
|
17313
|
+
const bindingName = localName || importedName;
|
|
17314
|
+
statements.push(`const ${bindingName} = ${namespaceName}[${JSON.stringify(importedName)}];`);
|
|
17315
|
+
}
|
|
17316
|
+
return statements.join("\n");
|
|
17317
|
+
}
|
|
17318
|
+
if (normalizedSpecifier.startsWith("* as ")) {
|
|
17319
|
+
const bindingName = normalizedSpecifier.slice(5).trim();
|
|
17320
|
+
statements.push(`const ${bindingName} = ${namespaceName};`);
|
|
17321
|
+
return statements.join("\n");
|
|
17322
|
+
}
|
|
17323
|
+
const [defaultName, namedPart] = normalizedSpecifier.split(/\s*,\s*/, 2);
|
|
17324
|
+
if (defaultName) statements.push(`const ${defaultName.trim()} = ${namespaceName}.default ?? ${namespaceName};`);
|
|
17325
|
+
if (namedPart?.startsWith("{") && namedPart.endsWith("}")) statements.push(createEsmImportBindings(namedPart, request, index).split("\n").slice(1).join("\n"));
|
|
17326
|
+
return statements.join("\n");
|
|
17327
|
+
}
|
|
17328
|
+
function transformEsmToCommonJs(source) {
|
|
17329
|
+
if (!/^\s*(?:import|export)\b/m.test(source)) return source;
|
|
17330
|
+
let importIndex = 0;
|
|
17331
|
+
const exportedNames = [];
|
|
17332
|
+
let transformed = source.replace(ESM_IMPORT_LINE_RE, (line) => {
|
|
17333
|
+
const parsed = parseEsmImportLine(line);
|
|
17334
|
+
if (!parsed) return line;
|
|
17335
|
+
if (parsed.sideEffect) return `require(${JSON.stringify(parsed.request)});`;
|
|
17336
|
+
return createEsmImportBindings(parsed.specifier, parsed.request, importIndex++);
|
|
17337
|
+
});
|
|
17338
|
+
transformed = transformed.replace(ESM_EXPORT_LIST_RE, (_match, entries) => {
|
|
17339
|
+
for (const entry of entries.split(",")) {
|
|
17340
|
+
const [local, exported] = entry.trim().split(/\s+as\s+/);
|
|
17341
|
+
if (local) exportedNames.push({
|
|
17342
|
+
exported: exported || local,
|
|
17343
|
+
local
|
|
17344
|
+
});
|
|
17345
|
+
}
|
|
17346
|
+
return "";
|
|
17347
|
+
});
|
|
17348
|
+
transformed = transformed.replace(ESM_EXPORT_DEFAULT_DECLARATION_RE, (_match, kind, local) => {
|
|
17349
|
+
exportedNames.push({
|
|
17350
|
+
exported: "default",
|
|
17351
|
+
local
|
|
17352
|
+
});
|
|
17353
|
+
return `${kind} ${local}`;
|
|
17354
|
+
});
|
|
17355
|
+
transformed = transformed.replace(ESM_EXPORT_DECLARATION_RE, (_match, kind, local) => {
|
|
17356
|
+
exportedNames.push({
|
|
17357
|
+
exported: local,
|
|
17358
|
+
local
|
|
17359
|
+
});
|
|
17360
|
+
return `${kind} ${local}`;
|
|
17361
|
+
});
|
|
17362
|
+
transformed = transformed.replace(/\bexport\s+default\s+/g, "module.exports.default = ");
|
|
17363
|
+
if (exportedNames.length > 0) transformed += `\n${exportedNames.map(({ exported, local }) => `module.exports[${JSON.stringify(exported)}] = ${local};`).join("\n")}`;
|
|
17364
|
+
return transformed;
|
|
17365
|
+
}
|
|
17164
17366
|
function createRequireNotFoundError(request, importer) {
|
|
17165
17367
|
return /* @__PURE__ */ new Error(`Cannot resolve require("${request}") from ${normalize(importer)} in headless runtime.`);
|
|
17166
17368
|
}
|
|
@@ -17176,7 +17378,7 @@ function resolveRequiredModulePath(artifactSource, importer, request) {
|
|
|
17176
17378
|
for (const candidate of candidates) if (artifactSource.has(candidate)) return candidate;
|
|
17177
17379
|
throw createRequireNotFoundError(request, importer);
|
|
17178
17380
|
}
|
|
17179
|
-
function createExecutionContext(registries, getCurrentPages, getApp, wxDriver, kernel, globals) {
|
|
17381
|
+
function createExecutionContext(registries, getCurrentPages, getApp, wxDriver, kernel, globals, onConsole) {
|
|
17180
17382
|
const wx = createHeadlessWx(wxDriver);
|
|
17181
17383
|
return {
|
|
17182
17384
|
App(definition) {
|
|
@@ -17194,7 +17396,7 @@ function createExecutionContext(registries, getCurrentPages, getApp, wxDriver, k
|
|
|
17194
17396
|
Page(definition) {
|
|
17195
17397
|
return registerPageDefinition(registries, definition);
|
|
17196
17398
|
},
|
|
17197
|
-
console: kernel.diagnostics.createConsole(),
|
|
17399
|
+
console: kernel.diagnostics.createConsole(console, onConsole),
|
|
17198
17400
|
clearInterval: (handle) => kernel.scheduler.clearInterval(handle),
|
|
17199
17401
|
clearTimeout: (handle) => kernel.scheduler.clearTimeout(handle),
|
|
17200
17402
|
getApp,
|
|
@@ -17204,13 +17406,17 @@ function createExecutionContext(registries, getCurrentPages, getApp, wxDriver, k
|
|
|
17204
17406
|
require: void 0,
|
|
17205
17407
|
setInterval: kernel.scheduler.setInterval.bind(kernel.scheduler),
|
|
17206
17408
|
setTimeout: kernel.scheduler.setTimeout.bind(kernel.scheduler),
|
|
17409
|
+
TextDecoder: globalThis.TextDecoder,
|
|
17410
|
+
TextEncoder: globalThis.TextEncoder,
|
|
17411
|
+
URL: globalThis.URL,
|
|
17412
|
+
URLSearchParams: globalThis.URLSearchParams,
|
|
17207
17413
|
wx,
|
|
17208
17414
|
...globals
|
|
17209
17415
|
};
|
|
17210
17416
|
}
|
|
17211
17417
|
function createModuleLoader(registries, getCurrentPages, getApp, wxDriver, options) {
|
|
17212
17418
|
const moduleCache = /* @__PURE__ */ new Map();
|
|
17213
|
-
const executionContext = createExecutionContext(registries, getCurrentPages, getApp, wxDriver, options.kernel, options.globals ?? {});
|
|
17419
|
+
const executionContext = createExecutionContext(registries, getCurrentPages, getApp, wxDriver, options.kernel, options.globals ?? {}, options.onConsole);
|
|
17214
17420
|
executionContext.globalThis = executionContext;
|
|
17215
17421
|
function executeModule(filePath, loadContext) {
|
|
17216
17422
|
const resolvedPath = path.resolve(filePath);
|
|
@@ -17240,14 +17446,24 @@ function createModuleLoader(registries, getCurrentPages, getApp, wxDriver, optio
|
|
|
17240
17446
|
});
|
|
17241
17447
|
localRequire.async = (request) => Promise.resolve().then(() => localRequire(request));
|
|
17242
17448
|
try {
|
|
17243
|
-
new vm.Script(`(function (exports, module, require, __filename, __dirname) { ${source}\n})`, { filename: resolvedPath }).runInNewContext(executionContext)(module.exports, module, localRequire, resolvedPath, path.dirname(resolvedPath));
|
|
17449
|
+
new vm.Script(`(function (exports, module, require, __filename, __dirname) { ${transformEsmToCommonJs(source)}\n})`, { filename: resolvedPath }).runInNewContext(executionContext)(module.exports, module, localRequire, resolvedPath, path.dirname(resolvedPath));
|
|
17244
17450
|
const registeredDefinitions = [...registries.components.values()].filter((definition) => !registeredDefinitionsBefore.has(definition));
|
|
17245
|
-
module.componentDefinitions = [.../* @__PURE__ */ new Set([
|
|
17451
|
+
module.componentDefinitions = [.../* @__PURE__ */ new Set([
|
|
17452
|
+
...requiredComponentDefinitions,
|
|
17453
|
+
...loadContext?.componentDefinitions ?? [],
|
|
17454
|
+
...registeredDefinitions
|
|
17455
|
+
])];
|
|
17246
17456
|
return module;
|
|
17247
17457
|
} finally {
|
|
17248
17458
|
registries.currentLoadContext = previousLoadContext;
|
|
17249
17459
|
}
|
|
17250
17460
|
}
|
|
17461
|
+
executionContext.requirePlugin = (alias) => {
|
|
17462
|
+
const plugin = options.plugins.find((item) => item.alias === alias);
|
|
17463
|
+
if (!plugin) throw new Error(`Unknown local plugin "${alias}" in headless runtime.`);
|
|
17464
|
+
const main = typeof plugin.config.main === "string" && plugin.config.main ? plugin.config.main : "index.js";
|
|
17465
|
+
return executeModule(path.resolve(options.miniprogramRootPath, plugin.virtualRoot, main), null).exports;
|
|
17466
|
+
};
|
|
17251
17467
|
return {
|
|
17252
17468
|
close() {
|
|
17253
17469
|
moduleCache.clear();
|
|
@@ -17258,11 +17474,13 @@ function createModuleLoader(registries, getCurrentPages, getApp, wxDriver, optio
|
|
|
17258
17474
|
return registries.appDefinition;
|
|
17259
17475
|
},
|
|
17260
17476
|
executePageModule(filePath, route) {
|
|
17261
|
-
executeModule(filePath, {
|
|
17477
|
+
const fallbackDefinition = executeModule(filePath, {
|
|
17262
17478
|
kind: "page",
|
|
17263
|
-
route
|
|
17264
|
-
|
|
17265
|
-
|
|
17479
|
+
route,
|
|
17480
|
+
componentDefinitions: []
|
|
17481
|
+
}).componentDefinitions.at(-1);
|
|
17482
|
+
const definition = registries.pages.get(route) ?? (fallbackDefinition ? normalizeComponentPageDefinition(fallbackDefinition) : void 0);
|
|
17483
|
+
if (!registries.pages.has(route) && definition) registerPageDefinition(registries, definition, route);
|
|
17266
17484
|
if (!definition) throw new Error(`Page() was not registered for route "${route}" while executing ${normalize(filePath)}.`);
|
|
17267
17485
|
return definition;
|
|
17268
17486
|
},
|
|
@@ -19015,6 +19233,7 @@ var HeadlessSession = class {
|
|
|
19015
19233
|
appDefinition = null;
|
|
19016
19234
|
appInstance = null;
|
|
19017
19235
|
moduleLoader;
|
|
19236
|
+
eventListeners = /* @__PURE__ */ new Map();
|
|
19018
19237
|
registries;
|
|
19019
19238
|
currentPageInstance = null;
|
|
19020
19239
|
pages = [];
|
|
@@ -19156,7 +19375,10 @@ var HeadlessSession = class {
|
|
|
19156
19375
|
}, {
|
|
19157
19376
|
artifactSource: this.project.artifactSource,
|
|
19158
19377
|
globals: options.globals,
|
|
19159
|
-
kernel: this.kernel
|
|
19378
|
+
kernel: this.kernel,
|
|
19379
|
+
miniprogramRootPath: this.project.miniprogramRootPath,
|
|
19380
|
+
onConsole: (entry) => this.emit("console", entry),
|
|
19381
|
+
plugins: this.project.plugins
|
|
19160
19382
|
});
|
|
19161
19383
|
}
|
|
19162
19384
|
assertActive() {
|
|
@@ -19170,11 +19392,26 @@ var HeadlessSession = class {
|
|
|
19170
19392
|
this.renderRequestPending = false;
|
|
19171
19393
|
this.wxState.close();
|
|
19172
19394
|
this.moduleLoader.close();
|
|
19395
|
+
this.eventListeners.clear();
|
|
19173
19396
|
this.kernel.close();
|
|
19174
19397
|
}
|
|
19175
19398
|
getDiagnostics() {
|
|
19176
19399
|
return this.kernel.diagnostics.getEntries();
|
|
19177
19400
|
}
|
|
19401
|
+
on(eventName, handler) {
|
|
19402
|
+
if (!eventName || typeof handler !== "function") return;
|
|
19403
|
+
const listeners = this.eventListeners.get(eventName) ?? /* @__PURE__ */ new Set();
|
|
19404
|
+
listeners.add(handler);
|
|
19405
|
+
this.eventListeners.set(eventName, listeners);
|
|
19406
|
+
}
|
|
19407
|
+
removeListener(eventName, handler) {
|
|
19408
|
+
const listeners = this.eventListeners.get(eventName);
|
|
19409
|
+
listeners?.delete(handler);
|
|
19410
|
+
if (listeners?.size === 0) this.eventListeners.delete(eventName);
|
|
19411
|
+
}
|
|
19412
|
+
emit(eventName, ...args) {
|
|
19413
|
+
for (const handler of [...this.eventListeners.get(eventName) ?? []]) handler(...args);
|
|
19414
|
+
}
|
|
19178
19415
|
get isClosed() {
|
|
19179
19416
|
return this.kernel.isClosed;
|
|
19180
19417
|
}
|
|
@@ -19186,6 +19423,10 @@ var HeadlessSession = class {
|
|
|
19186
19423
|
this.assertActive();
|
|
19187
19424
|
return this.pages.slice();
|
|
19188
19425
|
}
|
|
19426
|
+
getWx() {
|
|
19427
|
+
this.assertActive();
|
|
19428
|
+
return this.moduleLoader.wx;
|
|
19429
|
+
}
|
|
19189
19430
|
callWxMethod(methodName, ...args) {
|
|
19190
19431
|
this.assertActive();
|
|
19191
19432
|
const method = this.moduleLoader.wx[methodName];
|
|
@@ -19581,9 +19822,19 @@ var HeadlessSession = class {
|
|
|
19581
19822
|
this.appDefinition = this.moduleLoader.executeAppModule(appModulePath);
|
|
19582
19823
|
this.appInstance = createAppInstance(this.appDefinition);
|
|
19583
19824
|
this.appInstance.onLaunch?.(launchOptions);
|
|
19825
|
+
this.syncRuntimeAppState();
|
|
19584
19826
|
this.appInstance.onShow?.(launchOptions);
|
|
19585
19827
|
return this.appInstance;
|
|
19586
19828
|
}
|
|
19829
|
+
syncRuntimeAppState() {
|
|
19830
|
+
const runtimeApp = this.appInstance?.__wevuRuntimeApp;
|
|
19831
|
+
if (!runtimeApp || typeof runtimeApp !== "object" || !this.appInstance) return;
|
|
19832
|
+
if (runtimeApp.globalData && typeof runtimeApp.globalData === "object") this.appInstance.globalData = {
|
|
19833
|
+
...this.appInstance.globalData,
|
|
19834
|
+
...runtimeApp.globalData
|
|
19835
|
+
};
|
|
19836
|
+
if (Object.hasOwn(runtimeApp, "routes")) this.appInstance.routes = runtimeApp.routes;
|
|
19837
|
+
}
|
|
19587
19838
|
reLaunch(url) {
|
|
19588
19839
|
const target = this.resolveNavigationTarget(url);
|
|
19589
19840
|
this.bootstrap(createAppLaunchOptions(target.normalizedRoute, target.query));
|
|
@@ -19746,8 +19997,9 @@ var HeadlessSession = class {
|
|
|
19746
19997
|
});
|
|
19747
19998
|
}
|
|
19748
19999
|
createFreshPage(target) {
|
|
19749
|
-
const
|
|
19750
|
-
const
|
|
20000
|
+
const resourcePath = target.routeRecord.resourcePath ?? target.routeRecord.route;
|
|
20001
|
+
const pageModulePath = path.resolve(this.project.miniprogramRootPath, `${resourcePath}.js`);
|
|
20002
|
+
const pageConfigPath = path.resolve(this.project.miniprogramRootPath, `${resourcePath}.json`);
|
|
19751
20003
|
const pageDefinition = this.moduleLoader.executePageModule(pageModulePath, target.routeRecord.route);
|
|
19752
20004
|
const pageConfig = readJsonObject(this.project, pageConfigPath);
|
|
19753
20005
|
const pageInstance = createPageInstance(`/${target.routeRecord.route}`, pageDefinition, target.query, {
|
|
@@ -19782,7 +20034,9 @@ var HeadlessSession = class {
|
|
|
19782
20034
|
}
|
|
19783
20035
|
resolveNavigationTarget(url) {
|
|
19784
20036
|
const { pathname, query } = parseNavigationUrl(url);
|
|
19785
|
-
const
|
|
20037
|
+
const baseRoute = this.currentPageInstance ? stripLeadingSlash(this.currentPageInstance.route) : void 0;
|
|
20038
|
+
const pluginRequest = resolvePluginRequest(this.project.plugins, pathname, "page");
|
|
20039
|
+
const normalizedRoute = pluginRequest ? `plugin-private://${pluginRequest.plugin.provider}/${pluginRequest.resourcePath.slice(pluginRequest.plugin.virtualRoot.length + 1)}` : resolveNavigationPath(pathname, baseRoute);
|
|
19786
20040
|
const routeRecord = this.project.routes.find((item) => item.route === normalizedRoute);
|
|
19787
20041
|
if (!routeRecord) {
|
|
19788
20042
|
this.bootstrap(createAppLaunchOptions(normalizedRoute, query));
|
|
@@ -20231,7 +20485,10 @@ var HeadlessTestingPageHandle = class {
|
|
|
20231
20485
|
return await runWithTimeout(async () => {
|
|
20232
20486
|
this.session?.renderCurrentPage();
|
|
20233
20487
|
const method = this.page[normalizedMethodName];
|
|
20234
|
-
if (typeof method !== "function")
|
|
20488
|
+
if (typeof method !== "function") {
|
|
20489
|
+
if (options.routeOnly) return;
|
|
20490
|
+
throw new TypeError(`Method "${normalizedMethodName}" does not exist on headless page ${this.page.route}.`);
|
|
20491
|
+
}
|
|
20235
20492
|
return cloneProtocolValue(await method.apply(this.page, args));
|
|
20236
20493
|
}, options.timeout, `Timed out calling page method "${normalizedMethodName}" in headless testing runtime.`);
|
|
20237
20494
|
}
|
|
@@ -20406,6 +20663,24 @@ var HeadlessTestingSessionHandle = class {
|
|
|
20406
20663
|
async close() {
|
|
20407
20664
|
this.session.close();
|
|
20408
20665
|
}
|
|
20666
|
+
on(eventName, handler) {
|
|
20667
|
+
this.session.on(eventName, handler);
|
|
20668
|
+
return this;
|
|
20669
|
+
}
|
|
20670
|
+
removeListener(eventName, handler) {
|
|
20671
|
+
this.session.removeListener(eventName, handler);
|
|
20672
|
+
return this;
|
|
20673
|
+
}
|
|
20674
|
+
off(eventName, handler) {
|
|
20675
|
+
return this.removeListener(eventName, handler);
|
|
20676
|
+
}
|
|
20677
|
+
async evaluate(evaluator, ...args) {
|
|
20678
|
+
return await this.evaluateWithOptions(evaluator, {}, ...args);
|
|
20679
|
+
}
|
|
20680
|
+
async evaluateWithOptions(evaluator, options = {}, ...args) {
|
|
20681
|
+
this.session.assertActive();
|
|
20682
|
+
return await runWithTimeout(() => this.evaluateInRuntime(evaluator, args), options.timeout, "Timed out evaluating code in headless testing runtime.");
|
|
20683
|
+
}
|
|
20409
20684
|
async currentPage() {
|
|
20410
20685
|
this.session.assertActive();
|
|
20411
20686
|
const current = this.session.getCurrentPages().at(-1);
|
|
@@ -20502,12 +20777,45 @@ var HeadlessTestingSessionHandle = class {
|
|
|
20502
20777
|
if (!page) throw new Error(`Failed to ${methodName} route "${route}" through the headless wx runtime.`);
|
|
20503
20778
|
return page;
|
|
20504
20779
|
}
|
|
20780
|
+
async evaluateInRuntime(evaluator, args) {
|
|
20781
|
+
const runtimeGlobals = {
|
|
20782
|
+
getApp: () => this.session.getApp(),
|
|
20783
|
+
getCurrentPages: () => this.session.getCurrentPages(),
|
|
20784
|
+
wx: this.session.getWx()
|
|
20785
|
+
};
|
|
20786
|
+
const host = globalThis;
|
|
20787
|
+
const previous = /* @__PURE__ */ new Map();
|
|
20788
|
+
for (const [name, value] of Object.entries(runtimeGlobals)) {
|
|
20789
|
+
previous.set(name, Object.getOwnPropertyDescriptor(host, name));
|
|
20790
|
+
Object.defineProperty(host, name, {
|
|
20791
|
+
configurable: true,
|
|
20792
|
+
enumerable: false,
|
|
20793
|
+
value,
|
|
20794
|
+
writable: true
|
|
20795
|
+
});
|
|
20796
|
+
}
|
|
20797
|
+
try {
|
|
20798
|
+
const fn = typeof evaluator === "string" ? new vm.Script(`(${evaluator})`).runInThisContext() : evaluator;
|
|
20799
|
+
if (typeof fn !== "function") throw new TypeError("Headless evaluator must be a function or function source string.");
|
|
20800
|
+
return await fn(...args);
|
|
20801
|
+
} finally {
|
|
20802
|
+
for (const [name, descriptor] of previous) if (descriptor) Object.defineProperty(host, name, descriptor);
|
|
20803
|
+
else delete host[name];
|
|
20804
|
+
}
|
|
20805
|
+
}
|
|
20505
20806
|
};
|
|
20506
20807
|
//#endregion
|
|
20507
20808
|
//#region ../../mpcore/packages/simulator/src/testing/launch.ts
|
|
20809
|
+
function resolveInitialRoute(session) {
|
|
20810
|
+
const entryPagePath = typeof session.project.appConfig.entryPagePath === "string" ? session.project.appConfig.entryPagePath.trim().replace(/^\/+/, "") : "";
|
|
20811
|
+
if (entryPagePath && session.project.routes.some((route) => route.route === entryPagePath)) return entryPagePath;
|
|
20812
|
+
return session.project.routes[0]?.route ?? null;
|
|
20813
|
+
}
|
|
20508
20814
|
async function launch(options) {
|
|
20509
20815
|
const session = createHeadlessSession({ projectPath: options.projectPath });
|
|
20510
20816
|
session.bootstrap();
|
|
20817
|
+
const initialRoute = resolveInitialRoute(session);
|
|
20818
|
+
if (initialRoute) session.reLaunch(`/${initialRoute}`);
|
|
20511
20819
|
return new HeadlessTestingSessionHandle(session.project, session);
|
|
20512
20820
|
}
|
|
20513
20821
|
//#endregion
|