From 8820efd6bf592ea9e2fe050c8ce3e2344bbaf67e Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Thu, 3 Sep 2026 20:29:50 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(tests):=20=E8=A1=A5=E5=9B=9E=20add-plug?= =?UTF-8?q?in-modal.spec=20=E7=BC=BA=E5=A4=B1=E7=9A=84=20builtinTabPlugins?= =?UTF-8?q?=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #535(i18n catalog names)给 tests/add-plugin-modal.spec.tsx 新增 sentinelEntry 行时漏了 import;#535 自身 CI run 被 cancel,#536 带病 合入,main HEAD 7b5c7dd 的 typecheck/test 双红(本地 stash 复现一致: TS2304 / ReferenceError: builtinTabPlugins is not defined,CI run 33754439466 failure)。补上与 plugin-list.spec.ts 同源的 import。 与本 PR 主题无关,仅为本流验证门(typecheck/test 全绿)所需的最小 main 修复,独立成 commit 便于 review 剔除。 --- tests/add-plugin-modal.spec.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/add-plugin-modal.spec.tsx b/tests/add-plugin-modal.spec.tsx index c787950..06bdefd 100644 --- a/tests/add-plugin-modal.spec.tsx +++ b/tests/add-plugin-modal.spec.tsx @@ -19,6 +19,7 @@ import { createRoot } from 'react-dom/client' import { act } from 'react-dom/test-utils' import * as primitives from '@deepseek-ai/dsh-client-ui-primitives' import { type PluginEntry } from '../src/client/plugins-shared.ts' +import { builtinTabPlugins } from '../src/client/plugins-tabs.ts' import { builtinViewerPlugins } from '../src/client/plugins-viewers.ts' import { AddPluginModal, PluginListBody } from '../src/client/add-plugin-modal.tsx' import { createBetterSidebarService } from '../src/client/service.ts' From dc33087ce17b5a9f788cb143da0cf1307666ce40 Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Thu, 3 Sep 2026 20:29:59 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(client):=20=E5=88=A0=E9=99=A4=20rc.7?= =?UTF-8?q?=20=E5=AE=BF=E4=B8=BB=E7=9A=84=20=5F=5FDSH=5FMODULES=5F=5F=20?= =?UTF-8?q?=E5=9B=9E=E9=80=80=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit peer 基线已是 ^0.1.2-rc.1(全部 dsh-* peer),最后提供 window.__DSH_MODULES__ 页面全局的宿主是 0.1.0-rc.7,远低于下限, 装不上本插件——回退在受支持宿主上不可达。受支持宿主上 apply() 在 任何懒加载发生前调 setChunkModuleSystem(ctx.modules),moduleSystem() 前两跳(注入变量 + 插件全局 __dshSidebarModuleSystem__)必中。 回退的唯一活消费者是 vitest fixture:installModuleSystem() 原先经 rc.7 全局投递 fake 模块系统,现改为与生产同路径的 setChunkModuleSystem 注入;无任何专测回退分支的用例,全部断言保持不变。 - chunk-loader.ts: 删 moduleSystem() 第三跳,同步头注 / ChunkModuleSystem 接口注中的回退描述 - index.tsx: 删「falls back to the rc.7 global」注释 - README v0.14.0 changelog 与 docs/plans 设计文档中的提及属历史 存档(描述 PR #232 当时的迁移),保留不改 验证:lint / typecheck / build / vitest 119 文件 1243 用例全绿; 真机挂载 lane(钉版 @deepseek-ai/dsh@0.1.2-rc.1 CLI)mount.e2e 全内置 tab sweep(含终端 / editor 懒加载 chunk)通过;lib/*.js 产物中无 __DSH_MODULES__ 残留。 --- src/client/chunk-loader.ts | 11 +++++------ src/client/index.tsx | 7 +++---- tests/chunk-loader.spec.ts | 17 +++++------------ 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/client/chunk-loader.ts b/src/client/chunk-loader.ts index 0a9e87a..d89fdbf 100644 --- a/src/client/chunk-loader.ts +++ b/src/client/chunk-loader.ts @@ -23,8 +23,9 @@ * arbitrary file names, so the plugin's own host route serves the chunks), * 2. read the factory from the global registry, * 3. call it with a require that resolves the platform externals through - * `__DSH_MODULES__.import(spec)` — the seed-word branch, the one part of - * the module system that is stable across versions. + * the injected module system's `import(spec)` (the `ctx.modules` service) + * — the seed-word branch, the one part of the module system that is + * stable across versions. * * Caching contract (three layers, each with a failure path): * - In-memory: one in-flight promise per chunk, memoized until @@ -90,8 +91,7 @@ const CHUNK_REVALIDATE_TIMEOUT_MS = 5_000 * The client module system surface this loader needs to resolve externals. * DSH 0.1.0-rc.8 provides it as the `ctx.modules` service (no page global * anymore); the plugin injects it at activation via - * {@link setChunkModuleSystem}. The rc.7-era `window.__DSH_MODULES__` global - * remains as a fallback so older hosts and the test harness keep working. + * {@link setChunkModuleSystem}. */ export interface ChunkModuleSystem { import(specifier: string): Promise @@ -123,12 +123,11 @@ export function setChunkModuleSystem(system: ChunkModuleSystem | undefined): voi } /** Resolve the shell-installed module system (injected, then the plugin - * global shared with chunk-bundle copies, then the rc.7 page global). */ + * global shared with chunk-bundle copies). */ function moduleSystem(): ChunkModuleSystem | undefined { const g = globalThis as Record return injectedModuleSystem ?? g[MODULE_SYSTEM_GLOBAL] as ChunkModuleSystem | undefined - ?? (g as { __DSH_MODULES__?: ChunkModuleSystem }).__DSH_MODULES__ } /** The plugin-owned chunk factory registry the chunk scripts populate. */ diff --git a/src/client/index.tsx b/src/client/index.tsx index 3fdb559..aed2ee8 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -188,10 +188,9 @@ export function apply(ctx: Context): void { } } try { - // rc.8+ exposes the client module system as the `ctx.modules` service - // (no window.__DSH_MODULES__ page global anymore); the chunk loader needs - // it to resolve its externals, so inject it before anything can load a - // lazy chunk. The loader falls back to the rc.7 global when absent. + // rc.8+ exposes the client module system as the `ctx.modules` service; + // the chunk loader needs it to resolve its externals, so inject it + // before anything can load a lazy chunk. setChunkModuleSystem(ctx.modules) // Fresh chunk state for this activation: drop per-test fixtures and // revalidate loaded chunk scripts against the bundle route's ETags — diff --git a/tests/chunk-loader.spec.ts b/tests/chunk-loader.spec.ts index b94327b..86eb83d 100644 --- a/tests/chunk-loader.spec.ts +++ b/tests/chunk-loader.spec.ts @@ -8,9 +8,10 @@ * - externals resolve through the module system's seed branch (the stable, * version-independent part), once per page, * - resetChunks drops the cache and the externals memo (HMR). - * The production path runs against a fake `window.__DSH_MODULES__` and a - * stub script loader that simulates the executed chunk script by assigning - * the plugin-owned global factory registry. + * The production path runs against a fake module system injected via + * {@link setChunkModuleSystem} (mirroring the client half's `ctx.modules` + * injection) and a stub script loader that simulates the executed chunk + * script by assigning the plugin-owned global factory registry. */ import { beforeEach, describe, expect, it, vi } from 'vitest' import './browser-globals.ts' @@ -33,14 +34,10 @@ function installModuleSystem(): FakeModuleSystem { const fake: FakeModuleSystem = { import: vi.fn(async (specifier: string) => ({ seed: specifier })), } - ;(globalThis as Record).__DSH_MODULES__ = fake + setChunkModuleSystem(fake) return fake } -function removeModuleSystem(): void { - delete (globalThis as Record).__DSH_MODULES__ -} - /** Simulate a chunk script executing: it assigns its factory to the registry. */ function simulateScript(name: string, factory: (require: (spec: string) => unknown) => ChunkExports): void { const g = globalThis as { __dshChunks__?: Record } @@ -49,7 +46,6 @@ function simulateScript(name: string, factory: (require: (spec: string) => unkno } beforeEach(() => { - removeModuleSystem() setChunkModuleSystem(undefined) delete (globalThis as Record).__dshChunks__ resetChunks() @@ -89,9 +85,6 @@ describe('test-registry path (vitest / jsdom-less environments)', () => { describe('production path (script injection + global registry + externals require)', () => { it('resolves externals through an injected ctx.modules system (rc.8 — no page global)', async () => { const modules = installModuleSystem() - // rc.8 drops window.__DSH_MODULES__; the client half injects ctx.modules. - removeModuleSystem() - setChunkModuleSystem(modules) const loaded: string[] = [] setChunkScriptLoaderForTests(async (src) => { loaded.push(src)