Merge final CI coverage parent into manual compact
This commit is contained in:
@@ -59,23 +59,9 @@ describe('connection node half', () => {
|
||||
const ctx = new Context()
|
||||
ctx.provide('httpServer', fakeHttpServer(routes) as HttpServerService)
|
||||
ctx.provide('apiProxy', {} as unknown as ApiProxy)
|
||||
// The apply throw also escapes cordis as a late rejection — the shape the
|
||||
// boot's installFailLoud is contracted to catch. Capture it so the run
|
||||
// stays clean, same pattern as the webserver bind-failure test.
|
||||
const rejections: unknown[] = []
|
||||
const onUnhandled = (err: unknown): void => { rejections.push(err) }
|
||||
process.on('unhandledRejection', onUnhandled)
|
||||
try {
|
||||
const fiber = ctx.plugin({ inject: [...inject], apply }, { trustedHosts: ['harness.internal/path'] })
|
||||
await expect(fiber.await()).rejects.toThrow(/not a bare host\[:port\] authority/)
|
||||
expect(routes).toHaveLength(0)
|
||||
for (let i = 0; i < 100 && rejections.length === 0; i++) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
}
|
||||
expect(rejections.map(String).join('\n')).toContain('not a bare host[:port] authority')
|
||||
} finally {
|
||||
process.off('unhandledRejection', onUnhandled)
|
||||
}
|
||||
const fiber = ctx.plugin({ inject: [...inject], apply }, { trustedHosts: ['harness.internal/path'] })
|
||||
await expect(fiber).rejects.toThrow(/not a bare host\[:port\] authority/)
|
||||
expect(routes).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('registers the /api prefix route and removes it with the fiber', async () => {
|
||||
|
||||
@@ -41,8 +41,8 @@ interface Bench {
|
||||
|
||||
async function boot(): Promise<Bench> {
|
||||
const ctx = new Context()
|
||||
ctx.plugin(SlotsService)
|
||||
await ctx.fiber.await()
|
||||
const fiber = ctx.plugin(SlotsService)
|
||||
await fiber
|
||||
// Service accessor (ctx.get reads the reflect store, which Service-class
|
||||
// plugins do not write; the accessor is the product path).
|
||||
const svc = ctx.slots
|
||||
|
||||
@@ -131,6 +131,26 @@ interface FaceProgramHost {
|
||||
readonly files: Map<string, ts.SourceFile | undefined>
|
||||
}
|
||||
|
||||
/**
|
||||
* Process-wide parse cache for the bundled TypeScript default libraries.
|
||||
* `typescript/lib/lib.*.d.ts` content is immutable for the process lifetime,
|
||||
* so parses are shared across every {@link WorkspaceCaches} instance; the key
|
||||
* carries the parse-affecting settings, keeping reuse exact.
|
||||
*/
|
||||
const defaultLibraryParses = new Map<string, ts.SourceFile | undefined>()
|
||||
|
||||
function defaultLibraryKey(fileName: string, languageVersionOrOptions: ts.ScriptTarget | ts.CreateSourceFileOptions): string {
|
||||
const options = typeof languageVersionOrOptions === 'object'
|
||||
? languageVersionOrOptions
|
||||
: { languageVersion: languageVersionOrOptions }
|
||||
return [
|
||||
fileName,
|
||||
String(options.languageVersion),
|
||||
String(options.impliedNodeFormat ?? ''),
|
||||
String(options.jsDocParsingMode ?? ''),
|
||||
].join('\0')
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared memo over one immutable workspace snapshot. Passing one instance to
|
||||
* several analyzers (the batched and write-mode children reuse their parent's
|
||||
@@ -185,6 +205,13 @@ export class WorkspaceCaches {
|
||||
// only fires under oldProgram reuse, which these fresh programs never
|
||||
// request, and invalidate() is the one supported re-read path.
|
||||
host.getSourceFile = (fileName, languageVersionOrOptions, onError) => {
|
||||
if (isStandardLibraryFile(fileName)) {
|
||||
const key = defaultLibraryKey(fileName, languageVersionOrOptions)
|
||||
if (!defaultLibraryParses.has(key)) {
|
||||
defaultLibraryParses.set(key, base(fileName, languageVersionOrOptions, onError))
|
||||
}
|
||||
return defaultLibraryParses.get(key)
|
||||
}
|
||||
if (!files.has(fileName)) files.set(fileName, base(fileName, languageVersionOrOptions, onError))
|
||||
return files.get(fileName)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user