fix(windows): address native CI review findings
This commit is contained in:
@@ -6,7 +6,7 @@ import { Context } from 'cordis'
|
||||
import Hmr from '@cordisjs/plugin-hmr'
|
||||
import Loader from '@cordisjs/plugin-loader'
|
||||
import Timer from '@cordisjs/plugin-timer'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
async function bootHmr(dir: string, root: string[] = []): Promise<Context> {
|
||||
const ctx = new Context()
|
||||
@@ -33,7 +33,8 @@ describe('HMR exact config paths', () => {
|
||||
symlinkSync(target, alias, process.platform === 'win32' ? 'junction' : 'dir')
|
||||
writeFileSync(filename, 'export const generation = 0\n')
|
||||
const ctx = await bootHmr(alias, ['.'])
|
||||
const expected = pathToFileURL(filename).href
|
||||
const expected = pathToFileURL(join(realpathSync(target), 'module.ts')).href
|
||||
const cacheHas = vi.spyOn(ctx.loader.internal!.loadCache, 'has').mockReturnValue(false)
|
||||
const observed: string[] = []
|
||||
ctx.on('hmr/change', (url) => { observed.push(url) })
|
||||
try {
|
||||
@@ -43,6 +44,7 @@ describe('HMR exact config paths', () => {
|
||||
writeFileSync(filename, `export const generation = ${generation}\n`)
|
||||
await new Promise(resolve => setTimeout(resolve, 20))
|
||||
}
|
||||
expect(cacheHas).toHaveBeenCalledWith(expected)
|
||||
} finally {
|
||||
await ctx.fiber.dispose()
|
||||
rmSync(alias, { force: true })
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* @module @deepseek-ai/dsh-paths
|
||||
*/
|
||||
|
||||
import { realpath } from 'node:fs/promises'
|
||||
import { opendir, realpath } from 'node:fs/promises'
|
||||
import { homedir } from 'node:os'
|
||||
import { basename, dirname, join, resolve } from 'node:path'
|
||||
|
||||
@@ -20,19 +20,29 @@ export const DSH_HOME_ENV = 'DSH_HOME'
|
||||
/**
|
||||
* Give a native filesystem watcher one canonical spelling of a path, even
|
||||
* when its final components do not exist yet. The deepest existing ancestor
|
||||
* is resolved through {@link realpath}; the missing suffix is then restored.
|
||||
* This prevents Windows short-name aliases from being mixed with long paths
|
||||
* emitted by the native watcher backend.
|
||||
* is resolved through {@link realpath}; when a suffix is missing, that
|
||||
* ancestor is also proved to be an enumerable directory before the suffix is
|
||||
* restored. This prevents Windows from treating a regular-file ancestor as
|
||||
* ordinary absence, and prevents short-name aliases from being mixed with
|
||||
* long paths emitted by the native watcher backend.
|
||||
* @param path - Watch target or root, resolved against the current directory.
|
||||
* @returns the target with its existing ancestor canonicalized.
|
||||
* @throws when ancestor traversal encounters an error other than absence.
|
||||
* @throws when ancestor traversal encounters an error other than absence, or
|
||||
* the existing ancestor of a missing suffix is not an enumerable directory.
|
||||
*/
|
||||
export async function canonicalizeWatchPath(path: string): Promise<string> {
|
||||
let current = resolve(path)
|
||||
const missing: string[] = []
|
||||
while (true) {
|
||||
try {
|
||||
return join(await realpath(current), ...missing.reverse())
|
||||
const canonical = await realpath(current)
|
||||
if (missing.length > 0) {
|
||||
// A Windows file-as-parent probe reports ENOENT. Opening the resolved
|
||||
// ancestor preserves the cross-platform directory requirement.
|
||||
const directory = await opendir(canonical)
|
||||
await directory.close()
|
||||
}
|
||||
return join(canonical, ...missing.reverse())
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
|
||||
const parent = dirname(current)
|
||||
|
||||
Reference in New Issue
Block a user