diff --git a/packages/uni-app-harmony/dist/uni.runtime.esm.js b/packages/uni-app-harmony/dist/uni.runtime.esm.js
index d349707ae7810dde377d22ffcbbb1dc0148980f7..7d7f8cbd9402694ce600246b5560f103bfa385ab 100644
--- a/packages/uni-app-harmony/dist/uni.runtime.esm.js
+++ b/packages/uni-app-harmony/dist/uni.runtime.esm.js
@@ -1,6 +1,7 @@
import picker from '@ohos.file.picker';
import fs from '@ohos.file.fs';
import promptAction from '@ohos.promptAction';
+import { getCurrentInstance, onMounted, nextTick, onBeforeUnmount } from 'vue';
/**
* @vue/shared v3.4.21
@@ -39,7 +40,26 @@ const capitalize = cacheStringFunction((str) => {
});
const LINEFEED = '\n';
+const ON_READY = 'onReady';
+const ON_UNLOAD = 'onUnload';
+let lastLogTime = 0;
+function formatLog(module, ...args) {
+ const now = Date.now();
+ const diff = lastLogTime ? now - lastLogTime : 0;
+ lastLogTime = now;
+ return `[${now}][${diff}ms][${module}]:${args
+ .map((arg) => JSON.stringify(arg))
+ .join(' ')}`;
+}
+
+const invokeArrayFns = (fns, arg) => {
+ let ret;
+ for (let i = 0; i < fns.length; i++) {
+ ret = fns[i](arg);
+ }
+ return ret;
+};
function once(fn, ctx = null) {
let res;
return ((...args) => {
@@ -51,6 +71,86 @@ function once(fn, ctx = null) {
});
}
+class EventChannel {
+ id;
+ listener;
+ emitCache;
+ constructor(id, events) {
+ this.id = id;
+ this.listener = {};
+ this.emitCache = [];
+ if (events) {
+ Object.keys(events).forEach((name) => {
+ this.on(name, events[name]);
+ });
+ }
+ }
+ emit(eventName, ...args) {
+ const fns = this.listener[eventName];
+ if (!fns) {
+ return this.emitCache.push({
+ eventName,
+ args,
+ });
+ }
+ fns.forEach((opt) => {
+ opt.fn.apply(opt.fn, args);
+ });
+ this.listener[eventName] = fns.filter((opt) => opt.type !== 'once');
+ }
+ on(eventName, fn) {
+ this._addListener(eventName, 'on', fn);
+ this._clearCache(eventName);
+ }
+ once(eventName, fn) {
+ this._addListener(eventName, 'once', fn);
+ this._clearCache(eventName);
+ }
+ off(eventName, fn) {
+ const fns = this.listener[eventName];
+ if (!fns) {
+ return;
+ }
+ if (fn) {
+ for (let i = 0; i < fns.length;) {
+ if (fns[i].fn === fn) {
+ fns.splice(i, 1);
+ i--;
+ }
+ i++;
+ }
+ }
+ else {
+ delete this.listener[eventName];
+ }
+ }
+ _clearCache(eventName) {
+ for (let index = 0; index < this.emitCache.length; index++) {
+ const cache = this.emitCache[index];
+ const _name = eventName
+ ? cache.eventName === eventName
+ ? eventName
+ : null
+ : cache.eventName;
+ if (!_name)
+ continue;
+ const location = this.emit.apply(this, [_name, ...cache.args]);
+ if (typeof location === 'number') {
+ this.emitCache.pop();
+ continue;
+ }
+ this.emitCache.splice(index, 1);
+ index--;
+ }
+ }
+ _addListener(eventName, type, fn) {
+ (this.listener[eventName] || (this.listener[eventName] = [])).push({
+ fn,
+ type,
+ });
+ }
+}
+
const CHOOSE_SIZE_TYPES = ['original', 'compressed'];
const CHOOSE_SOURCE_TYPES = ['album', 'camera'];
function elemsInArray(strArr, optionalVal) {
@@ -878,6 +978,55 @@ const initI18nChooseImageMsgsOnce = /*#__PURE__*/ once(() => {
}
});
+function getCurrentPage() {
+ const pages = getCurrentPages();
+ const len = pages.length;
+ if (len) {
+ return pages[len - 1];
+ }
+}
+function getCurrentPageVm() {
+ const page = getCurrentPage();
+ if (page) {
+ return page.$vm;
+ }
+}
+
+function invokeHook(vm, name, args) {
+ if (isString(vm)) {
+ args = name;
+ name = vm;
+ vm = getCurrentPageVm();
+ }
+ else if (typeof vm === 'number') {
+ const page = getCurrentPages().find((page) => page.$page.id === vm);
+ if (page) {
+ vm = page.$vm;
+ }
+ else {
+ vm = getCurrentPageVm();
+ }
+ }
+ if (!vm) {
+ return;
+ }
+ const hooks = vm.$[name];
+ return hooks && invokeArrayFns(hooks, args);
+}
+
+function initPageVm(pageVm, page) {
+ pageVm.route = page.route;
+ pageVm.$vm = pageVm;
+ pageVm.$page = page;
+ pageVm.$mpType = 'page';
+ pageVm.$fontFamilySet = new Set();
+ if (page.meta.isTabBar) {
+ pageVm.$.__isTabBar = true;
+ // TODO preload? 初始化时,状态肯定是激活
+ pageVm.$.__isActive = true;
+ }
+}
+
const API_CHOOSE_IMAGE = 'chooseImage';
const ChooseImageOptions = {
formatArgs: {
@@ -1031,6 +1180,90 @@ var uni$1 = {
getSystemInfoSync: getSystemInfoSync
};
-globalThis.uni = uni$1;
+const pages = [];
+function addCurrentPage(page) {
+ const $page = page.$page;
+ if (!$page.meta.isNVue) {
+ return pages.push(page);
+ }
+ // 开发阶段热刷新需要移除旧的相同 id 的 page
+ const index = pages.findIndex((p) => p.$page.id === page.$page.id);
+ if (index > -1) {
+ pages.splice(index, 1, page);
+ }
+ else {
+ pages.push(page);
+ }
+}
+
+function setupPage(component) {
+ const oldSetup = component.setup;
+ component.inheritAttrs = false; // 禁止继承 __pageId 等属性,避免告警
+ component.setup = (_, ctx) => {
+ const { attrs: { __pageId, __pagePath, __pageQuery, __pageInstance }, } = ctx;
+ if (('production' !== 'production')) {
+ console.log(formatLog(__pagePath, 'setup'));
+ }
+ const instance = getCurrentInstance();
+ const pageVm = instance.proxy;
+ initPageVm(pageVm, __pageInstance);
+ addCurrentPage(initScope(__pageId, pageVm, __pageInstance));
+ {
+ onMounted(() => {
+ nextTick(() => {
+ // onShow被延迟,故onReady也同时延迟
+ invokeHook(pageVm, ON_READY);
+ });
+ // TODO preloadSubPackages
+ });
+ onBeforeUnmount(() => {
+ invokeHook(pageVm, ON_UNLOAD);
+ });
+ }
+ if (oldSetup) {
+ return oldSetup(__pageQuery, ctx);
+ }
+ };
+ return component;
+}
+function initScope(pageId, vm, pageInstance) {
+ {
+ const $getAppWebview = () => {
+ return plus.webview.getWebviewById(pageId + '');
+ };
+ vm.$getAppWebview = $getAppWebview;
+ vm.$.ctx.$scope = {
+ $getAppWebview,
+ };
+ }
+ vm.getOpenerEventChannel = () => {
+ if (!pageInstance.eventChannel) {
+ pageInstance.eventChannel = new EventChannel(pageId);
+ }
+ return pageInstance.eventChannel;
+ };
+ return vm;
+}
+
+function isVuePageAsyncComponent(component) {
+ return isFunction(component);
+}
+const pagesMap = new Map();
+function definePage(pagePath, asyncComponent) {
+ pagesMap.set(pagePath, once(createFactory(asyncComponent)));
+}
+function createFactory(component) {
+ return () => {
+ if (isVuePageAsyncComponent(component)) {
+ return component().then((component) => setupPage(component));
+ }
+ return setupPage(component);
+ };
+}
+
+var index = {
+ uni: uni$1,
+ __definePage: definePage,
+};
-export { uni$1 as uni };
+export { index as default };
diff --git a/packages/uni-app-uts/src/plugins/ios/plugin.ts b/packages/uni-app-uts/src/plugins/ios/plugin.ts
index f78d13a721ece6236af88adac5231bd40f4c4f8c..ea88fbceff82b6f0cf956a90d6622b834b5d12b3 100644
--- a/packages/uni-app-uts/src/plugins/ios/plugin.ts
+++ b/packages/uni-app-uts/src/plugins/ios/plugin.ts
@@ -72,11 +72,16 @@ export function uniAppIOSPlugin(): UniVitePlugin {
const appServiceMap = bundle[APP_SERVICE_FILENAME_MAP]
if (appServiceMap && appServiceMap.type === 'asset') {
fs.outputFileSync(
- path.resolve(
- process.env.UNI_OUTPUT_DIR,
- '../.sourcemap/app-ios',
- APP_SERVICE_FILENAME_MAP
- ),
+ process.env.UNI_APP_X_CACHE_DIR
+ ? path.resolve(
+ process.env.UNI_APP_X_CACHE_DIR,
+ APP_SERVICE_FILENAME_MAP
+ )
+ : path.resolve(
+ process.env.UNI_OUTPUT_DIR,
+ '../.sourcemap/app-ios',
+ APP_SERVICE_FILENAME_MAP
+ ),
appServiceMap.source
)
delete bundle[APP_SERVICE_FILENAME_MAP]
diff --git a/packages/uni-h5/dist-x/uni-h5.cjs.js b/packages/uni-h5/dist-x/uni-h5.cjs.js
index cc468f2d3c3da8e6f4396929ada10f460ccd644a..0fc3c9e8a2c1f6db9d61b5b3cd98f4a506965d58 100644
--- a/packages/uni-h5/dist-x/uni-h5.cjs.js
+++ b/packages/uni-h5/dist-x/uni-h5.cjs.js
@@ -13457,6 +13457,17 @@ function createRightWindowTsx(rightWindow, layoutState, windowState) {
}, windowState), null, 16)])], 12, ["data-show"]), [[vue.vShow, layoutState.showRightWindow || layoutState.apiShowRightWindow]]);
}
}
+function updateBackgroundColorContent(backgroundColorContent) {
+ {
+ return;
+ }
+}
+function useBackgroundColorContent(pageMeta) {
+ function update() {
+ updateBackgroundColorContent(pageMeta.backgroundColorContent || "");
+ }
+ vue.watchEffect(update);
+}
function usePageHeadTransparentBackgroundColor(backgroundColor) {
const { r, g: g2, b } = hexToRgba(backgroundColor);
return `rgba(${r},${g2},${b},0)`;
@@ -13915,10 +13926,10 @@ const index = defineSystemComponent({
const pageMeta = providePageMeta(getStateId());
const navigationBar = pageMeta.navigationBar;
const pageStyle = {};
- if (pageMeta.backgroundColorContent) {
- pageStyle.backgroundColor = pageMeta.backgroundColorContent;
- }
useDocumentTitle(pageMeta);
+ {
+ useBackgroundColorContent(pageMeta);
+ }
return () => vue.createVNode(
"uni-page",
{
diff --git a/packages/uni-h5/dist-x/uni-h5.es.js b/packages/uni-h5/dist-x/uni-h5.es.js
index 218d267aaca2213fb2ddec991e9375204dcc4a5c..0c56229c4562299b6dce33d0a2f812b0359e6e17 100644
--- a/packages/uni-h5/dist-x/uni-h5.es.js
+++ b/packages/uni-h5/dist-x/uni-h5.es.js
@@ -26691,6 +26691,23 @@ const UniServiceJSBridge$1 = /* @__PURE__ */ extend(ServiceJSBridge, {
UniViewJSBridge.subscribeHandler(event, args, pageId);
}
});
+function updateBackgroundColorContent(backgroundColorContent) {
+ if (backgroundColorContent) {
+ document.body.style.setProperty(
+ "--background-color-content",
+ backgroundColorContent
+ );
+ } else {
+ document.body.style.removeProperty("--background-color-content");
+ }
+}
+function useBackgroundColorContent(pageMeta) {
+ function update() {
+ updateBackgroundColorContent(pageMeta.backgroundColorContent || "");
+ }
+ watchEffect(update);
+ onActivated(update);
+}
function usePageHeadTransparentBackgroundColor(backgroundColor) {
const { r, g: g2, b } = hexToRgba(backgroundColor);
return `rgba(${r},${g2},${b},0)`;
@@ -27425,10 +27442,10 @@ const index = defineSystemComponent({
const pageMeta = providePageMeta(getStateId());
const navigationBar = pageMeta.navigationBar;
const pageStyle = {};
- if (pageMeta.backgroundColorContent) {
- pageStyle.backgroundColor = pageMeta.backgroundColorContent;
- }
useDocumentTitle(pageMeta);
+ {
+ useBackgroundColorContent(pageMeta);
+ }
return () => createVNode(
"uni-page",
{
diff --git a/packages/uni-uts-v1/__tests__/__snapshots__/stacktrace.runtime.spec.ts.snap b/packages/uni-uts-v1/__tests__/__snapshots__/stacktrace.runtime.spec.ts.snap
index bb45a2524159db3dd5b92abbaaa6a03a95a8138b..7f0e66be6cea7c3811c60dfbd3d7e5a5ed3765d5 100644
--- a/packages/uni-uts-v1/__tests__/__snapshots__/stacktrace.runtime.spec.ts.snap
+++ b/packages/uni-uts-v1/__tests__/__snapshots__/stacktrace.runtime.spec.ts.snap
@@ -1,5 +1,28 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`uts:stacktrace:runtime parseUTSJavaScriptRuntimeStacktrace 1`] = `
+"error: ReferenceError:Can't find variable: a
+at pages/index/index.uvue:3:8
+1 | ","\r\n\r\n","import App from './App.uvue'\r\n\r\nimport { createSSRApp } from 'vue'\n\r\nexport function createApp() {\r\n\tconst app = createSSRApp(App)\r\n\treturn {\r\n\t\tapp\r\n\t}\r\n}"],"names":["defineComponent","createSSRApp"],"mappings":";;;IACI,UAAU,CAAC,MAAA;QACP,GAAG,CAAC,OAAO,CAAC,KAAK,EAAC,6BAA6B,EAAC,CAAC,CAAA,CAAA;IACrD,CAAC,EAAE,IAAI,CAAA,CAAA;AACP,wBAAeA,mBAAA,CAAA;QACX,MAAM,GAAA;YACF,GAAG,CAAC,OAAO,CAAC,KAAK,EAAC,6BAA6B,EAAC,CAAC,CAAA,CAAA;SACrD;KACJ,CAAA;;;;;;;;;;;;;;ACNH,sBAAeA,mBAAA,CAAA;IACd,IAAA,QAAQ,EAAE,YAAA;YACT,GAAG,CAAC,OAAO,CAAC,KAAK,EAAC,eAAe,EAAC,YAAY,CAAA,CAAA;SAC9C;IACD,IAAA,MAAM,EAAE,YAAA;YACP,GAAG,CAAC,OAAO,CAAC,KAAK,EAAC,eAAe,EAAC,UAAU,CAAA,CAAA;SAC5C;IACD,IAAA,MAAM,EAAE,YAAA;YACP,GAAG,CAAC,OAAO,CAAC,KAAK,EAAC,gBAAgB,EAAC,UAAU,CAAA,CAAA;SAC7C;IAmBD,IAAA,MAAM,EAAE,YAAA;YACP,GAAG,CAAC,OAAO,CAAC,KAAK,EAAC,gBAAgB,EAAC,UAAU,CAAA,CAAA;SAC7C;KACF,CAAA;;;;;;IC9BS,MAAM,UAAU,GAAG,OAAO,UAAU,KAAK,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,GAAG,UAAU,CAAA;IAC7F,UAAU,CAAC,MAAM,GAAG,IAAI,CAAA;aAKlB,SAAS,GAAA;IACxB,IAAA,MAAM,GAAG,GAAGC,gBAAY,CAAC,GAAG,CAAC,CAAA;QAC7B,OAAO;YACN,GAAG;SACH,CAAA;IACF,CAAC;IACS,SAAS,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;;;;;;"}
\ No newline at end of file
diff --git a/packages/uni-uts-v1/__tests__/stacktrace.runtime.spec.ts b/packages/uni-uts-v1/__tests__/stacktrace.runtime.spec.ts
index d0eb95f7b6c697828bc30232154dc1b18eeea148..dead784f72eaabe956bb68a122d9a4db6a87e36d 100644
--- a/packages/uni-uts-v1/__tests__/stacktrace.runtime.spec.ts
+++ b/packages/uni-uts-v1/__tests__/stacktrace.runtime.spec.ts
@@ -1,12 +1,13 @@
import path from 'path'
import { parseUTSKotlinRuntimeStacktrace } from '../src/stacktrace/kotlin'
+import { parseUTSJavaScriptRuntimeStacktrace } from '../src/stacktrace/js'
describe('uts:stacktrace:runtime', () => {
test('parseUTSKotlinRuntimeStacktrace', async () => {
const cacheDir = path.resolve(
__dirname,
- 'examples/uni-app-x/unpackage/cache/.kotlin'
+ 'examples/uni-app-x/unpackage/cache/app-android'
)
expect(
parseUTSKotlinRuntimeStacktrace(
@@ -76,4 +77,31 @@ at uni.UNIXXXXXXX.IndexKt.test(index.kt:40)`,
)
).toMatchSnapshot()
})
+ test('parseUTSJavaScriptRuntimeStacktrace', async () => {
+ const cacheDir = path.resolve(
+ __dirname,
+ 'examples/uni-app-x/unpackage/cache/app-ios'
+ )
+ expect(
+ parseUTSJavaScriptRuntimeStacktrace(
+ `app-service.js(5:60) ReferenceError:Can't find variable: a @app-service.js:5:60`,
+ {
+ cacheDir,
+ }
+ )
+ ).toMatchSnapshot()
+ expect(
+ parseUTSJavaScriptRuntimeStacktrace(
+ `at
+Can't find variable: a
+onLoad@app-service.js:9:64
+callWithErrorHandling@uni-app-x-framework.js:2279:23
+callWithAsyncErrorHandling@uni-app-x-framework.js:2286:38
+@uni-app-x-framework.js:4763:45`,
+ {
+ cacheDir,
+ }
+ )
+ ).toMatchSnapshot()
+ })
})
diff --git a/packages/uni-uts-v1/src/stacktrace/js.ts b/packages/uni-uts-v1/src/stacktrace/js.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8b31b7c631ccb400a20d1fb7f8af4d4b8e6ea99a
--- /dev/null
+++ b/packages/uni-uts-v1/src/stacktrace/js.ts
@@ -0,0 +1,157 @@
+import { originalPositionForSync } from '../sourceMap'
+import {
+ COLORS,
+ type GenerateRuntimeCodeFrameOptions,
+ generateCodeFrame,
+ lineColumnToStartEnd,
+ resolveSourceMapDirByCacheDir,
+ resolveSourceMapFileBySourceFile,
+ splitRE,
+} from './utils'
+
+interface GenerateJavaScriptRuntimeCodeFrameOptions
+ extends GenerateRuntimeCodeFrameOptions {}
+const JS_ERROR_RE = /\(\d+:\d+\)\s(.*)\s@([^\s]+\.js)\:(\d+)\:(\d+)/
+const VUE_ERROR_RE = /@([^\s]+\.js)\:(\d+)\:(\d+)/
+
+// app-service.js(4:56) ReferenceError:Can't find variable: a @app-service.js:4:56
+export function parseUTSJavaScriptRuntimeStacktrace(
+ stacktrace: string,
+ options: GenerateJavaScriptRuntimeCodeFrameOptions
+) {
+ const res: string[] = []
+ const lines = stacktrace.split(splitRE)
+ const sourceMapDir = resolveSourceMapDirByCacheDir(options.cacheDir)
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i]
+ let codes = parseUTSJavaScriptRuntimeStacktraceJsErrorLine(
+ line,
+ sourceMapDir
+ )
+ if (codes.length) {
+ const color = options.logType
+ ? COLORS[options.logType as string] || ''
+ : ''
+ const [errorCode, ...other] = codes
+ let error = 'error: ' + errorCode
+ if (color) {
+ error = color + error + color
+ }
+ return [error, ...other].join('\n')
+ }
+ codes = parseUTSJavaScriptRuntimeStacktraceVueErrorLine(line, sourceMapDir)
+ if (codes.length && res.length) {
+ const color = options.logType
+ ? COLORS[options.logType as string] || ''
+ : ''
+ let error = 'error: ' + res[0]
+ if (color) {
+ error = color + error + color
+ }
+ const [, ...other] = res
+ const otherCodes = other.map((item) => {
+ if (color) {
+ return color + item + color
+ }
+ return item
+ })
+ return [error, ...otherCodes, ...codes].join('\n')
+ }
+
+ res.push(line)
+ }
+ return ''
+}
+
+// at
+// Can't find variable: a
+// onLoad@app-service.js:9:64
+// callWithErrorHandling@uni-app-x-framework.js:2279:23
+function parseUTSJavaScriptRuntimeStacktraceVueErrorLine(
+ lineStr: string,
+ sourceMapDir: string
+) {
+ const lines: string[] = []
+ const matches = lineStr.match(VUE_ERROR_RE)
+ if (!matches) {
+ return lines
+ }
+ const [, filename, line] = matches
+ const sourceMapFile = resolveSourceMapFileBySourceFile(filename, sourceMapDir)
+ if (!sourceMapFile) {
+ return lines
+ }
+
+ const originalPosition = originalPositionForSync({
+ sourceMapFile,
+ line: parseInt(line),
+ column: 0,
+ withSourceContent: true,
+ })
+ if (originalPosition.source && originalPosition.sourceContent) {
+ lines.push(
+ `at ${originalPosition.source.split('?')[0]}:${originalPosition.line}:${
+ originalPosition.column
+ }`
+ )
+ if (originalPosition.line !== null && originalPosition.column !== null) {
+ const { start, end } = lineColumnToStartEnd(
+ originalPosition.sourceContent,
+ originalPosition.line,
+ originalPosition.column
+ )
+ lines.push(
+ generateCodeFrame(originalPosition.sourceContent, start, end).replace(
+ /\t/g,
+ ' '
+ )
+ )
+ }
+ }
+ return lines
+}
+
+function parseUTSJavaScriptRuntimeStacktraceJsErrorLine(
+ lineStr: string,
+ sourceMapDir: string
+) {
+ const lines: string[] = []
+ const matches = lineStr.match(JS_ERROR_RE)
+ if (!matches) {
+ return lines
+ }
+ const [, error, filename, line] = matches
+ const sourceMapFile = resolveSourceMapFileBySourceFile(filename, sourceMapDir)
+ if (!sourceMapFile) {
+ return lines
+ }
+
+ const originalPosition = originalPositionForSync({
+ sourceMapFile,
+ line: parseInt(line),
+ column: 0,
+ withSourceContent: true,
+ })
+ if (originalPosition.source && originalPosition.sourceContent) {
+ lines.push(error)
+ lines.push(
+ `at ${originalPosition.source.split('?')[0]}:${originalPosition.line}:${
+ originalPosition.column
+ }`
+ )
+ if (originalPosition.line !== null && originalPosition.column !== null) {
+ const { start, end } = lineColumnToStartEnd(
+ originalPosition.sourceContent,
+ originalPosition.line,
+ originalPosition.column
+ )
+ lines.push(
+ generateCodeFrame(originalPosition.sourceContent, start, end).replace(
+ /\t/g,
+ ' '
+ )
+ )
+ }
+ }
+ return lines
+}
diff --git a/packages/uni-uts-v1/src/stacktrace/kotlin.ts b/packages/uni-uts-v1/src/stacktrace/kotlin.ts
index 363fd20d34ce4097300ecfb81f26946d9e7f2936..6800e72df9cff8ef4581879bb55da00b6283e223 100644
--- a/packages/uni-uts-v1/src/stacktrace/kotlin.ts
+++ b/packages/uni-uts-v1/src/stacktrace/kotlin.ts
@@ -2,7 +2,15 @@ import path from 'path'
import fs from 'fs-extra'
import { relative } from '../utils'
import { originalPositionFor, originalPositionForSync } from '../sourceMap'
-import { generateCodeFrame, lineColumnToStartEnd, splitRE } from './utils'
+import {
+ COLORS,
+ type GenerateRuntimeCodeFrameOptions,
+ generateCodeFrame,
+ lineColumnToStartEnd,
+ resolveSourceMapDirByCacheDir,
+ resolveSourceMapFileBySourceFile,
+ splitRE,
+} from './utils'
export interface MessageSourceLocation {
type: 'exception' | 'error' | 'warning' | 'info' | 'logging' | 'output'
@@ -175,31 +183,14 @@ function parseFilenameByClassName(className: string) {
return kotlinManifest.manifest[className.split('$')[0]] || 'index.kt'
}
-function resolveSourceMapFileByKtFile(file: string, sourceMapDir: string) {
- const sourceMapFile = path.resolve(sourceMapDir, file + '.map')
- if (fs.existsSync(sourceMapFile)) {
- return sourceMapFile
- }
-}
-
-const COLORS: Record = {
- warn: '\u200B',
- error: '\u200C',
-}
-
-interface GenerateRuntimeCodeFrameOptions {
+interface GenerateKotlinRuntimeCodeFrameOptions
+ extends GenerateRuntimeCodeFrameOptions {
appid: string
- cacheDir: string
- logType?: 'log' | 'info' | 'warn' | 'debug' | 'error'
-}
-
-function resolveSourceMapDirByCacheDir(cacheDir: string) {
- return path.resolve(cacheDir, 'sourceMap')
}
export function parseUTSKotlinRuntimeStacktrace(
stacktrace: string,
- options: GenerateRuntimeCodeFrameOptions
+ options: GenerateKotlinRuntimeCodeFrameOptions
) {
const appid = normalizeAppid(options.appid || DEFAULT_APPID)
if (!stacktrace.includes('uni.' + appid + '.')) {
@@ -209,13 +200,10 @@ export function parseUTSKotlinRuntimeStacktrace(
const re = createRegExp(appid)
const res: string[] = []
const lines = stacktrace.split(splitRE)
+ const sourceMapDir = resolveSourceMapDirByCacheDir(options.cacheDir)
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
- const codes = parseUTSKotlinRuntimeStacktraceLine(
- line,
- re,
- resolveSourceMapDirByCacheDir(options.cacheDir)
- )
+ const codes = parseUTSKotlinRuntimeStacktraceLine(line, re, sourceMapDir)
if (codes.length && res.length) {
const color = options.logType
? COLORS[options.logType as string] || ''
@@ -245,7 +233,7 @@ function parseUTSKotlinRuntimeStacktraceLine(
}
const [, className, line] = matches
- const sourceMapFile = resolveSourceMapFileByKtFile(
+ const sourceMapFile = resolveSourceMapFileBySourceFile(
parseFilenameByClassName(className),
sourceMapDir
)
diff --git a/packages/uni-uts-v1/src/stacktrace/utils.ts b/packages/uni-uts-v1/src/stacktrace/utils.ts
index 0d31e3ff4fbf4ccd53d82d687d3442d36380df3a..dec9803bcaa2e41f35459f8fa1633bba3a8e7d90 100644
--- a/packages/uni-uts-v1/src/stacktrace/utils.ts
+++ b/packages/uni-uts-v1/src/stacktrace/utils.ts
@@ -1,5 +1,32 @@
+import fs from 'fs'
+import path from 'path'
+
+export interface GenerateRuntimeCodeFrameOptions {
+ cacheDir: string
+ logType?: 'log' | 'info' | 'warn' | 'debug' | 'error'
+}
+
+export const COLORS: Record = {
+ warn: '\u200B',
+ error: '\u200C',
+}
+
export const splitRE = /\r?\n/
+export function resolveSourceMapDirByCacheDir(cacheDir: string) {
+ return path.resolve(cacheDir, 'sourcemap')
+}
+
+export function resolveSourceMapFileBySourceFile(
+ file: string,
+ sourceMapDir: string
+) {
+ const sourceMapFile = path.resolve(sourceMapDir, file + '.map')
+ if (fs.existsSync(sourceMapFile)) {
+ return sourceMapFile
+ }
+}
+
const range: number = 2
function posToNumber(