From 05343f16ea5f7e34ca680f8fd5779a8667bd5fba Mon Sep 17 00:00:00 2001 From: lbb00 Date: Fri, 20 Mar 2026 21:32:26 +0800 Subject: [PATCH 1/4] feat: support custom global API namespace (e.g. qd.xxx) Add a mechanism for host apps to register custom API namespaces so that mini-programs can call qd.xxx() equivalently to wx.xxx(). - JS: env.js reads __diminaApiNamespaces and assigns globalApi to each name, with H5 fallback via Worker name - Android: DiminaConfig.addApiNamespace(), JsCore.evaluate(), MiniApp injects namespaces before service.js and exposes registerApi() - iOS: new DiminaConfig singleton, DMPApp injects namespaces in loadBundle() - HarmonyOS: new DiminaConfig singleton, DMPApp injects in startEngineService() - H5: jscore.js passes namespaces via Worker name property --- .../src/main/kotlin/com/didi/dimina/Dimina.kt | 9 +++++++++ .../src/main/kotlin/com/didi/dimina/core/JsCore.kt | 7 +++++++ .../main/kotlin/com/didi/dimina/core/MiniApp.kt | 12 ++++++++++++ fe/packages/container/src/core/jscore.js | 4 +++- fe/packages/service/src/core/env.js | 12 ++++++++++++ harmony/dimina/Index.ets | 3 ++- harmony/dimina/src/main/ets/DApp/DMPApp.ets | 7 +++++++ .../src/main/ets/DApp/config/DiminaConfig.ets | 10 ++++++++++ iOS/dimina/DiminaKit/App/DMPApp.swift | 6 ++++++ iOS/dimina/DiminaKit/App/DiminaConfig.swift | 14 ++++++++++++++ 10 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 harmony/dimina/src/main/ets/DApp/config/DiminaConfig.ets create mode 100644 iOS/dimina/DiminaKit/App/DiminaConfig.swift diff --git a/android/dimina/src/main/kotlin/com/didi/dimina/Dimina.kt b/android/dimina/src/main/kotlin/com/didi/dimina/Dimina.kt index cd4fe886..174f50da 100644 --- a/android/dimina/src/main/kotlin/com/didi/dimina/Dimina.kt +++ b/android/dimina/src/main/kotlin/com/didi/dimina/Dimina.kt @@ -43,15 +43,22 @@ class Dimina private constructor(context: Context) { // 配置类 class DiminaConfig private constructor(builder: Builder) { val debugMode: Boolean = builder.debugMode + val apiNamespaces: List = builder.apiNamespaces class Builder { var debugMode: Boolean = false + internal var apiNamespaces: MutableList = mutableListOf() fun setDebugMode(debugMode: Boolean): Builder { this.debugMode = debugMode return this } + fun addApiNamespace(name: String): Builder { + apiNamespaces.add(name) + return this + } + fun build(): DiminaConfig { return DiminaConfig(this) } @@ -66,6 +73,8 @@ class Dimina private constructor(context: Context) { return config.debugMode } + fun getApiNamespaces(): List = config.apiNamespaces + private val appContext: Context = context private lateinit var config: DiminaConfig diff --git a/android/dimina/src/main/kotlin/com/didi/dimina/core/JsCore.kt b/android/dimina/src/main/kotlin/com/didi/dimina/core/JsCore.kt index d5e5ca49..85582797 100644 --- a/android/dimina/src/main/kotlin/com/didi/dimina/core/JsCore.kt +++ b/android/dimina/src/main/kotlin/com/didi/dimina/core/JsCore.kt @@ -43,6 +43,13 @@ class JsCore { * @param scriptPath The JavaScript code to evaluate * @return The result of the evaluation */ + fun evaluate(script: String): JSValue { + if (!isInitialized()) { + return JSValue.createError("Engine not initialized") + } + return jsEngine.evaluate(script) + } + fun evaluateFromFile(scriptPath: String): JSValue { if (!isInitialized()) { return JSValue.createError("Engine not initialized") diff --git a/android/dimina/src/main/kotlin/com/didi/dimina/core/MiniApp.kt b/android/dimina/src/main/kotlin/com/didi/dimina/core/MiniApp.kt index 3b766883..201cca54 100644 --- a/android/dimina/src/main/kotlin/com/didi/dimina/core/MiniApp.kt +++ b/android/dimina/src/main/kotlin/com/didi/dimina/core/MiniApp.kt @@ -5,6 +5,7 @@ import android.content.Context import com.didi.dimina.Dimina import com.didi.dimina.api.ApiRegistry import com.didi.dimina.api.AsyncResult +import com.didi.dimina.api.BaseApiHandler import com.didi.dimina.api.SyncResult import com.didi.dimina.api.base.AppEventApi import com.didi.dimina.api.base.BaseAPI @@ -133,6 +134,13 @@ class MiniApp private constructor() { } else { LogUtils.d(tag, "Skipping JSSDK update check, last check was recent") } + // Inject custom API namespaces before loading service.js + val namespaces = Dimina.getInstance().getApiNamespaces() + if (namespaces.isNotEmpty()) { + val json = namespaces.joinToString(",") { "\"$it\"" } + evaluate("globalThis.__diminaApiNamespaces = [$json]") + } + evaluateFromFile( File( context.filesDir.absolutePath, @@ -352,6 +360,10 @@ class MiniApp private constructor() { LogUtils.d(tag, "Cleared all Bridge lists") } + fun registerApi(handler: BaseApiHandler) { + handler.registerWith(apiRegistry) + } + fun destroy() { // Clear API resources apiRegistry.clear() diff --git a/fe/packages/container/src/core/jscore.js b/fe/packages/container/src/core/jscore.js index 0d737d9c..d8b27c81 100644 --- a/fe/packages/container/src/core/jscore.js +++ b/fe/packages/container/src/core/jscore.js @@ -12,7 +12,9 @@ export class JSCore { // 使用 Web Worker 创建逻辑线程 // 使用下面的形式会使 hash 失效 // this.worker = new Worker(new URL('@dimina/service', import.meta.url)); - this.worker = new Worker(serviceURL, { type: 'classic' }) + const namespaces = this.parent.getApiNamespaces?.() || [] + const workerName = JSON.stringify({ apiNamespaces: namespaces }) + this.worker = new Worker(serviceURL, { type: 'classic', name: workerName }) // 监听逻辑线程的消息 this.worker.onmessage = (e) => { diff --git a/fe/packages/service/src/core/env.js b/fe/packages/service/src/core/env.js index 12274b8c..a9d55902 100644 --- a/fe/packages/service/src/core/env.js +++ b/fe/packages/service/src/core/env.js @@ -13,6 +13,18 @@ class Env { init() { globalThis.dd = globalThis.wx = globalApi + + // Register custom API namespaces + let apiNamespaces = globalThis.__diminaApiNamespaces || [] + if (apiNamespaces.length === 0 && typeof self !== 'undefined' && self.name) { + try { + const config = JSON.parse(self.name) + apiNamespaces = config.apiNamespaces || [] + } catch (e) {} + } + for (const name of apiNamespaces) { + globalThis[name] = globalApi + } globalThis.modRequire = modRequire globalThis.modDefine = modDefine globalThis.global = {} diff --git a/harmony/dimina/Index.ets b/harmony/dimina/Index.ets index 1d89fbfe..44ba4df0 100644 --- a/harmony/dimina/Index.ets +++ b/harmony/dimina/Index.ets @@ -5,4 +5,5 @@ export { DMPApp } from './src/main/ets/DApp/DMPApp'; export { DMPPhotoPreview } from './src/main/ets/Bridges/PhotoView/DMPPhotoPreview'; export { DMPAppManager } from './src/main/ets/DApp/DMPAppManager'; export { DMPLaunchConfig, DMPOpenType } from './src/main/ets/DApp/config/DMPLaunchConfig'; -export { DMPColorUtils } from './src/main/ets/Utils/DMPColorUtils'; \ No newline at end of file +export { DMPColorUtils } from './src/main/ets/Utils/DMPColorUtils'; +export { DiminaConfig } from './src/main/ets/DApp/config/DiminaConfig'; \ No newline at end of file diff --git a/harmony/dimina/src/main/ets/DApp/DMPApp.ets b/harmony/dimina/src/main/ets/DApp/DMPApp.ets index e5a023ba..0ac5896e 100644 --- a/harmony/dimina/src/main/ets/DApp/DMPApp.ets +++ b/harmony/dimina/src/main/ets/DApp/DMPApp.ets @@ -29,6 +29,7 @@ import { DMPNavigatorManager } from '../Navigator/DMPNavigatorManager' import { DRouter } from '../Navigator/DRouter' import { DMPAppLifecycle } from './DMPAppLifecycle' import { DMPDeviceUtil } from '../Utils/DMPDeviceUtils' +import { DiminaConfig } from './config/DiminaConfig' export type DMPBundleUpdateCallback = () => void; //小程序应用实例 @@ -354,6 +355,12 @@ export class DMPApp { private async startEngineService() { DMPLogger.d(Tags.LAUNCH, "startEngineService start"); + // Inject custom API namespaces before loading service.js + const namespaces = DiminaConfig.shared.apiNamespaces + if (namespaces.length > 0) { + const json = namespaces.map((n: string) => `"${n}"`).join(",") + this._service.executeScript(`globalThis.__diminaApiNamespaces = [${json}]`) + } const serviceJsPath = await this._bundleManager.requestServiceJsUri(); await this._service.loadFileUri(serviceJsPath); DMPLogger.i(Tags.LAUNCH, "startEngineService end"); diff --git a/harmony/dimina/src/main/ets/DApp/config/DiminaConfig.ets b/harmony/dimina/src/main/ets/DApp/config/DiminaConfig.ets new file mode 100644 index 00000000..66ae8241 --- /dev/null +++ b/harmony/dimina/src/main/ets/DApp/config/DiminaConfig.ets @@ -0,0 +1,10 @@ +export class DiminaConfig { + private static _instance: DiminaConfig = new DiminaConfig() + apiNamespaces: string[] = [] + + private constructor() {} + + static get shared(): DiminaConfig { + return DiminaConfig._instance + } +} diff --git a/iOS/dimina/DiminaKit/App/DMPApp.swift b/iOS/dimina/DiminaKit/App/DMPApp.swift index a8ae616d..18c7f729 100644 --- a/iOS/dimina/DiminaKit/App/DMPApp.swift +++ b/iOS/dimina/DiminaKit/App/DMPApp.swift @@ -107,6 +107,12 @@ public class DMPApp { public func loadBundle() async { print("loadBundle") + // Inject custom API namespaces before loading service.js + let namespaces = DiminaConfig.shared.apiNamespaces + if !namespaces.isEmpty { + let json = namespaces.map { "\"\($0)\"" }.joined(separator: ",") + await service?.evaluateScript("globalThis.__diminaApiNamespaces = [\(json)]") + } await service?.loadFile(path: DMPSandboxManager.sdkServicePath()) await service?.loadFile(path: DMPSandboxManager.appServicePath(appId: appId)) diff --git a/iOS/dimina/DiminaKit/App/DiminaConfig.swift b/iOS/dimina/DiminaKit/App/DiminaConfig.swift new file mode 100644 index 00000000..c400e97e --- /dev/null +++ b/iOS/dimina/DiminaKit/App/DiminaConfig.swift @@ -0,0 +1,14 @@ +// +// DiminaConfig.swift +// dimina +// + +import Foundation + +public class DiminaConfig { + public static let shared = DiminaConfig() + + public var apiNamespaces: [String] = [] + + private init() {} +} From e473279759606bf2f68a1e97912a507d8423bf0e Mon Sep 17 00:00:00 2001 From: lbb00 Date: Fri, 20 Mar 2026 21:48:08 +0800 Subject: [PATCH 2/4] test(service): add unit tests for env.js API namespace registration --- fe/packages/service/__tests__/env.spec.js | 87 +++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 fe/packages/service/__tests__/env.spec.js diff --git a/fe/packages/service/__tests__/env.spec.js b/fe/packages/service/__tests__/env.spec.js new file mode 100644 index 00000000..9e0b36b3 --- /dev/null +++ b/fe/packages/service/__tests__/env.spec.js @@ -0,0 +1,87 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' + +// Mock all heavy dependencies — we only care about the namespace logic +const mockGlobalApi = { __mock: true } + +vi.mock('@dimina/common', () => ({ + modDefine: vi.fn(), + modRequire: vi.fn(), +})) +vi.mock('../src/api', () => ({ default: mockGlobalApi })) +vi.mock('../src/instance/component/component-module', () => ({ ComponentModule: { type: 'component' } })) +vi.mock('../src/instance/page/page-module', () => ({ PageModule: { type: 'page' } })) +vi.mock('../src/core/loader', () => ({ default: { createAppModule: vi.fn(), createModule: vi.fn() } })) +vi.mock('../src/core/router', () => ({ default: { stack: vi.fn(() => []) } })) +vi.mock('../src/core/runtime', () => ({ default: { app: null } })) + +describe('env.js API namespace registration', () => { + beforeEach(() => { + // Clean up namespace-related globals before each test + delete globalThis.__diminaApiNamespaces + delete globalThis.qd + delete globalThis.myapp + delete globalThis.dd + delete globalThis.wx + // Simulate Worker's self (not available in Node) + globalThis.self = { name: '' } + }) + + afterEach(() => { + vi.resetModules() + }) + + it('should set dd and wx to globalApi', async () => { + await import('../src/core/env.js') + + expect(globalThis.dd).toBe(mockGlobalApi) + expect(globalThis.wx).toBe(mockGlobalApi) + }) + + it('should register namespaces from __diminaApiNamespaces', async () => { + globalThis.__diminaApiNamespaces = ['qd', 'myapp'] + + await import('../src/core/env.js') + + expect(globalThis.qd).toBe(mockGlobalApi) + expect(globalThis.myapp).toBe(mockGlobalApi) + // dd and wx should still work + expect(globalThis.dd).toBe(mockGlobalApi) + expect(globalThis.wx).toBe(mockGlobalApi) + }) + + it('should not create extra globals when __diminaApiNamespaces is empty', async () => { + globalThis.__diminaApiNamespaces = [] + + await import('../src/core/env.js') + + expect(globalThis.qd).toBeUndefined() + }) + + it('should fall back to self.name when __diminaApiNamespaces is not set', async () => { + self.name = JSON.stringify({ apiNamespaces: ['qd'] }) + + await import('../src/core/env.js') + + expect(globalThis.qd).toBe(mockGlobalApi) + }) + + it('should ignore invalid JSON in self.name', async () => { + self.name = 'not-json' + + await import('../src/core/env.js') + + expect(globalThis.qd).toBeUndefined() + // Core globals should still work + expect(globalThis.wx).toBe(mockGlobalApi) + }) + + it('should prefer __diminaApiNamespaces over self.name', async () => { + globalThis.__diminaApiNamespaces = ['qd'] + self.name = JSON.stringify({ apiNamespaces: ['myapp'] }) + + await import('../src/core/env.js') + + expect(globalThis.qd).toBe(mockGlobalApi) + expect(globalThis.myapp).toBeUndefined() + }) +}) From d173ccac211f81656b53f44e30c2e465446f82a0 Mon Sep 17 00:00:00 2001 From: lbb00 Date: Fri, 20 Mar 2026 22:01:21 +0800 Subject: [PATCH 3/4] refactor: remove standalone DiminaConfig, attach apiNamespaces to existing SDK entry points - iOS: add apiNamespaces to DMPAppManager with setup() method - HarmonyOS: add optional apiNamespaces param to DMPApp.init() - JS: merge dd/wx and custom namespace registration into one loop - Delete DiminaConfig.swift and DiminaConfig.ets --- fe/packages/service/src/core/env.js | 12 +++++------- harmony/dimina/Index.ets | 3 +-- harmony/dimina/src/main/ets/DApp/DMPApp.ets | 8 ++++---- .../src/main/ets/DApp/config/DiminaConfig.ets | 10 ---------- iOS/dimina/DiminaKit/App/DMPApp.swift | 2 +- iOS/dimina/DiminaKit/App/DMPAppManager.swift | 11 ++++++++--- iOS/dimina/DiminaKit/App/DiminaConfig.swift | 14 -------------- 7 files changed, 19 insertions(+), 41 deletions(-) delete mode 100644 harmony/dimina/src/main/ets/DApp/config/DiminaConfig.ets delete mode 100644 iOS/dimina/DiminaKit/App/DiminaConfig.swift diff --git a/fe/packages/service/src/core/env.js b/fe/packages/service/src/core/env.js index a9d55902..8e5e4f68 100644 --- a/fe/packages/service/src/core/env.js +++ b/fe/packages/service/src/core/env.js @@ -12,17 +12,15 @@ class Env { } init() { - globalThis.dd = globalThis.wx = globalApi - - // Register custom API namespaces - let apiNamespaces = globalThis.__diminaApiNamespaces || [] - if (apiNamespaces.length === 0 && typeof self !== 'undefined' && self.name) { + // Register API namespaces (dd, wx are built-in; custom ones from config) + let customNamespaces = globalThis.__diminaApiNamespaces || [] + if (customNamespaces.length === 0 && typeof self !== 'undefined' && self.name) { try { const config = JSON.parse(self.name) - apiNamespaces = config.apiNamespaces || [] + customNamespaces = config.apiNamespaces || [] } catch (e) {} } - for (const name of apiNamespaces) { + for (const name of ['dd', 'wx', ...customNamespaces]) { globalThis[name] = globalApi } globalThis.modRequire = modRequire diff --git a/harmony/dimina/Index.ets b/harmony/dimina/Index.ets index 44ba4df0..1d89fbfe 100644 --- a/harmony/dimina/Index.ets +++ b/harmony/dimina/Index.ets @@ -5,5 +5,4 @@ export { DMPApp } from './src/main/ets/DApp/DMPApp'; export { DMPPhotoPreview } from './src/main/ets/Bridges/PhotoView/DMPPhotoPreview'; export { DMPAppManager } from './src/main/ets/DApp/DMPAppManager'; export { DMPLaunchConfig, DMPOpenType } from './src/main/ets/DApp/config/DMPLaunchConfig'; -export { DMPColorUtils } from './src/main/ets/Utils/DMPColorUtils'; -export { DiminaConfig } from './src/main/ets/DApp/config/DiminaConfig'; \ No newline at end of file +export { DMPColorUtils } from './src/main/ets/Utils/DMPColorUtils'; \ No newline at end of file diff --git a/harmony/dimina/src/main/ets/DApp/DMPApp.ets b/harmony/dimina/src/main/ets/DApp/DMPApp.ets index 0ac5896e..f51305dd 100644 --- a/harmony/dimina/src/main/ets/DApp/DMPApp.ets +++ b/harmony/dimina/src/main/ets/DApp/DMPApp.ets @@ -29,8 +29,6 @@ import { DMPNavigatorManager } from '../Navigator/DMPNavigatorManager' import { DRouter } from '../Navigator/DRouter' import { DMPAppLifecycle } from './DMPAppLifecycle' import { DMPDeviceUtil } from '../Utils/DMPDeviceUtils' -import { DiminaConfig } from './config/DiminaConfig' - export type DMPBundleUpdateCallback = () => void; //小程序应用实例 export class DMPApp { @@ -40,6 +38,7 @@ export class DMPApp { private onUpdateResult?: DMPBundleUpdateCallback private _container: DMPContainer = new DMPContainer(this) private static _context: common.UIAbilityContext + private static _apiNamespaces: string[] = [] private _containerBridges: DMPBridges = new DMPBridges() private static _entryContext: DMPEntryContext private _appModuleManager: DMPAppModuleManager = new DMPAppModuleManager(this) @@ -123,9 +122,10 @@ export class DMPApp { return DMPApp._entryContext.getWindowStage(); } - static init(context: DMPEntryContext) { + static init(context: DMPEntryContext, options?: { apiNamespaces?: string[] }) { DMPApp._entryContext = context; DMPApp._context = DMPApp._entryContext.getContext(); + DMPApp._apiNamespaces = options?.apiNamespaces ?? []; ImageKnife.with(DMPApp._entryContext.getContext()) context.getWindowStage().on('windowStageEvent', DMPAppLifecycle.onWindowStageEvent); DMPDeviceUtil.prepareSafeAreaAndDisplayWH(DMPApp._entryContext.getContext()) @@ -356,7 +356,7 @@ export class DMPApp { private async startEngineService() { DMPLogger.d(Tags.LAUNCH, "startEngineService start"); // Inject custom API namespaces before loading service.js - const namespaces = DiminaConfig.shared.apiNamespaces + const namespaces = DMPApp._apiNamespaces if (namespaces.length > 0) { const json = namespaces.map((n: string) => `"${n}"`).join(",") this._service.executeScript(`globalThis.__diminaApiNamespaces = [${json}]`) diff --git a/harmony/dimina/src/main/ets/DApp/config/DiminaConfig.ets b/harmony/dimina/src/main/ets/DApp/config/DiminaConfig.ets deleted file mode 100644 index 66ae8241..00000000 --- a/harmony/dimina/src/main/ets/DApp/config/DiminaConfig.ets +++ /dev/null @@ -1,10 +0,0 @@ -export class DiminaConfig { - private static _instance: DiminaConfig = new DiminaConfig() - apiNamespaces: string[] = [] - - private constructor() {} - - static get shared(): DiminaConfig { - return DiminaConfig._instance - } -} diff --git a/iOS/dimina/DiminaKit/App/DMPApp.swift b/iOS/dimina/DiminaKit/App/DMPApp.swift index 18c7f729..0977dff9 100644 --- a/iOS/dimina/DiminaKit/App/DMPApp.swift +++ b/iOS/dimina/DiminaKit/App/DMPApp.swift @@ -108,7 +108,7 @@ public class DMPApp { public func loadBundle() async { print("loadBundle") // Inject custom API namespaces before loading service.js - let namespaces = DiminaConfig.shared.apiNamespaces + let namespaces = DMPAppManager.sharedInstance().apiNamespaces if !namespaces.isEmpty { let json = namespaces.map { "\"\($0)\"" }.joined(separator: ",") await service?.evaluateScript("globalThis.__diminaApiNamespaces = [\(json)]") diff --git a/iOS/dimina/DiminaKit/App/DMPAppManager.swift b/iOS/dimina/DiminaKit/App/DMPAppManager.swift index 7e58c143..479d04ae 100644 --- a/iOS/dimina/DiminaKit/App/DMPAppManager.swift +++ b/iOS/dimina/DiminaKit/App/DMPAppManager.swift @@ -7,15 +7,20 @@ public class DMPAppManager { private static let instance = DMPAppManager() - + private var appPools: [Int: DMPApp] = [:] private var appIndex: Int = 0 - + public private(set) var apiNamespaces: [String] = [] + private init() {} - + public static func sharedInstance() -> DMPAppManager { return instance } + + public func setup(apiNamespaces: [String] = []) { + self.apiNamespaces = apiNamespaces + } func getApp(appIndex: Int) -> DMPApp? { return appPools[appIndex] diff --git a/iOS/dimina/DiminaKit/App/DiminaConfig.swift b/iOS/dimina/DiminaKit/App/DiminaConfig.swift deleted file mode 100644 index c400e97e..00000000 --- a/iOS/dimina/DiminaKit/App/DiminaConfig.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// DiminaConfig.swift -// dimina -// - -import Foundation - -public class DiminaConfig { - public static let shared = DiminaConfig() - - public var apiNamespaces: [String] = [] - - private init() {} -} From ba83f5a23de070d01c1ac2e27c84be0dfe06489e Mon Sep 17 00:00:00 2001 From: lbb00 Date: Fri, 3 Apr 2026 21:26:14 +0800 Subject: [PATCH 4/4] fix(service): replace self with globalThis to pass oxlint --- fe/packages/service/__tests__/env.spec.js | 8 ++++---- fe/packages/service/src/core/env.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fe/packages/service/__tests__/env.spec.js b/fe/packages/service/__tests__/env.spec.js index 9e0b36b3..906460b1 100644 --- a/fe/packages/service/__tests__/env.spec.js +++ b/fe/packages/service/__tests__/env.spec.js @@ -58,15 +58,15 @@ describe('env.js API namespace registration', () => { }) it('should fall back to self.name when __diminaApiNamespaces is not set', async () => { - self.name = JSON.stringify({ apiNamespaces: ['qd'] }) + globalThis.name = JSON.stringify({ apiNamespaces: ['qd'] }) await import('../src/core/env.js') expect(globalThis.qd).toBe(mockGlobalApi) }) - it('should ignore invalid JSON in self.name', async () => { - self.name = 'not-json' + it('should ignore invalid JSON in globalThis.name', async () => { + globalThis.name = 'not-json' await import('../src/core/env.js') @@ -77,7 +77,7 @@ describe('env.js API namespace registration', () => { it('should prefer __diminaApiNamespaces over self.name', async () => { globalThis.__diminaApiNamespaces = ['qd'] - self.name = JSON.stringify({ apiNamespaces: ['myapp'] }) + globalThis.name = JSON.stringify({ apiNamespaces: ['myapp'] }) await import('../src/core/env.js') diff --git a/fe/packages/service/src/core/env.js b/fe/packages/service/src/core/env.js index 8e5e4f68..ccbff6f7 100644 --- a/fe/packages/service/src/core/env.js +++ b/fe/packages/service/src/core/env.js @@ -14,9 +14,9 @@ class Env { init() { // Register API namespaces (dd, wx are built-in; custom ones from config) let customNamespaces = globalThis.__diminaApiNamespaces || [] - if (customNamespaces.length === 0 && typeof self !== 'undefined' && self.name) { + if (customNamespaces.length === 0 && globalThis.name) { try { - const config = JSON.parse(self.name) + const config = JSON.parse(globalThis.name) customNamespaces = config.apiNamespaces || [] } catch (e) {} }