Typed path prep bugfixes - #64544
Open
Jake Bailey (jakebailey) wants to merge 20 commits into
Open
Typed path prep bugfixes#64544Jake Bailey (jakebailey) wants to merge 20 commits into
Jake Bailey (jakebailey) wants to merge 20 commits into
Conversation
Copilot started reviewing on behalf of
Jake Bailey (jakebailey)
September 29, 2026 21:44
View session
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The auto-import fast path can corrupt sibling package paths, and the queue-close regression test is not reliably synchronized.
Review effort: Balanced
Findings: 2
Open (2)
What changed in this PR
Extracts typed-path preparation fixes covering path identity, module resolution, source maps, API lifecycle, and filesystem casing.
Changes:
- Preserves canonical and presentation paths across URIs, symlinks, watchers, and auto-imports.
- Fixes API snapshot lifecycle, cancellation, and project-relative lookups.
- Adds regression tests and refreshes source-map baselines.
| File | Description |
|---|---|
tsc/testdata/tests/cases/compiler/declarationEmitCommonJsModuleReferencedType.ts |
Tests nested package specifiers. |
tsc/testdata/baselines/reference/tsc/noEmitOnError/when-declarationMap-changes.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuildWatch/sample/should-not-trigger-recompilation-because-of-program-emit.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuildWatch/sample/non-local-change-does-not-start-build-of-referencing-projects-with-circular-references.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuildWatch/sample/change-builds-changes-and-reports-found-errors-message-with-circular-references.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuildWatch/sample/builds-when-new-file-is-added,-and-its-subsequent-updates-with-circular-references.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuild/solution/does-not-have-empty-files-diagnostic-when-files-is-empty-and-references-are-provided.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuild/sample/reports-error-if-input-file-is-missing.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuild/sample/reports-error-if-input-file-is-missing-with-force.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuild/sample/builds-correctly-when-project-is-not-composite-or-doesnt-have-any-references.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuild/sample/builds-correctly-when-declarationDir-is-specified.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuild/resolveJsonModule/sourcemap.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/tsbuild/resolveJsonModule/sourcemap-non-composite.js |
Updates source-map baseline. |
tsc/testdata/baselines/reference/fourslash/state/findAllRefsSolutionWithDisableReferencedProjectLoadReferencingDefaultProjectDirectly.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/findAllRefsSolutionReferencingDefaultProjectIndirectlyThroughDisableReferencedProjectLoadInOneButWithoutItInAnother.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/findAllRefsSolutionReferencingDefaultProjectIndirectlyThroughDisableReferencedProjectLoad.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/findAllRefsSolutionReferencingDefaultProjectIndirectly.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/findAllRefsSolutionReferencingDefaultProjectDirectly.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/findAllRefsRootOfReferencedProjectDeclarationMaps.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/findAllRefsProjectWithOwnFilesReferencingFileFromReferencedProject.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithSourceMapsNotSolutionEditEnd.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithSourceMapsNotSolutionEdit.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithSourceMapsNotSolution.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithSourceMapsEditEnd.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithSourceMapsEdit.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithSourceMaps.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithDisableSourceOfProjectReferenceRedirectEditEnd.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithDisableSourceOfProjectReferenceRedirectEdit.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithDisableSourceOfProjectReferenceRedirect.baseline |
Refreshes declaration-map output. |
tsc/testdata/baselines/reference/conformance/ES5For-of36(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/conformance/ES5For-of33(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/conformance/ES5For-of3(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/conformance/ES5For-of26(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/conformance/ES5For-of25(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/conformance/ES5For-of13(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/conformance/ES5For-of1(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/ternaryExpressionSourceMap.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/templateLiteralsSourceMap.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapWithCaseSensitiveFileNamesAndOutDir.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationVarInDownLevelGenerator(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationVariables.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationLambdaSpanningMultipleLines.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationLabeled.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationFunctionPropertyAssignment.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationExportAssignmentCommonjs.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationDestructuringVariableStatementObjectBindingPattern3.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationDestructuringVariableStatementObjectBindingPattern1.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationDestructuringVariableStatementArrayBindingPattern7.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationDestructuringVariableStatementArrayBindingPattern6.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationDestructuringVariableStatementArrayBindingPattern4.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapValidationDebugger.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapUnclosedBlock.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMapForFunctionWithCommentPrecedingStatement01.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMap-SkippedNode.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMap-SingleSpace1(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMap-SemiColon1(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMap-NewLine1(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMap-InterfacePrecedingVariableDeclaration1(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMap-EmptyFile1(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/sourceMap-Comment1(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/restParameterWithBindingPattern2.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/restParameterWithBindingPattern1.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/requireOfJsonFileWithSourceMap.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/properties(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/optionsSourcemapInlineSourcesMapRoot.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/optionsSourcemapInlineSources.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/optionsInlineSourceMapSourcemap.sourcemap.txt |
Updates inline-map baseline. |
tsc/testdata/baselines/reference/compiler/optionsInlineSourceMapSourcemap.js |
Updates inline-map output. |
tsc/testdata/baselines/reference/compiler/optionsInlineSourceMapMapRoot.sourcemap.txt |
Updates inline-map baseline. |
tsc/testdata/baselines/reference/compiler/optionsInlineSourceMapMapRoot.js |
Updates inline-map output. |
tsc/testdata/baselines/reference/compiler/noCatchBlock.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/jsFileCompilationWithMapFileAsJsWithOutDir.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.sourcemap.txt |
Updates inline-map baseline. |
tsc/testdata/baselines/reference/compiler/jsFileCompilationWithMapFileAsJsWithInlineSourceMap.js |
Updates inline-map output. |
tsc/testdata/baselines/reference/compiler/jsFileCompilationWithMapFileAsJs.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/isolatedModulesSourceMap.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/inlineSourceMap(target=es2015).sourcemap.txt |
Updates inline-map baseline. |
tsc/testdata/baselines/reference/compiler/inlineSourceMap(target=es2015).js |
Updates inline-map output. |
tsc/testdata/baselines/reference/compiler/emptyFile-souremap(target=es2015).js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/emitBOM.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/declarationMapWithInlineSourceMap.sourcemap.txt |
Updates inline declaration map. |
tsc/testdata/baselines/reference/compiler/declarationMapWithInlineSourceMap.js |
Updates inline declaration output. |
tsc/testdata/baselines/reference/compiler/declarationMapInlineSourcesContent.js.map |
Omits empty sourceRoot. |
tsc/testdata/baselines/reference/compiler/declarationEmitCommonJsModuleReferencedType.types |
Records nested-package types. |
tsc/testdata/baselines/reference/compiler/declarationEmitCommonJsModuleReferencedType.symbols |
Records nested-package symbols. |
tsc/testdata/baselines/reference/compiler/declarationEmitCommonJsModuleReferencedType.js |
Records test inputs and emit. |
tsc/testdata/baselines/reference/compiler/declarationEmitCommonJsModuleReferencedType.errors.txt |
Records test diagnostics. |
tsc/testdata/baselines/reference/compiler/contentMapperDeclarationEmitFailure.js.map |
Omits empty sourceRoot. |
tsc/internal/vfs/vfsmatch/vfsmatch.go |
Handles dynamic URI glob roots. |
tsc/internal/vfs/vfsmatch/vfsmatch_test.go |
Tests dynamic-root matching. |
tsc/internal/tspath/path.go |
Fixes dynamic and file-URL roots. |
tsc/internal/tspath/path_test.go |
Tests root and canonicalization behavior. |
tsc/internal/testutil/projecttestutil/projecttestutil.go |
Threads npm cancellation context. |
tsc/internal/testutil/projecttestutil/npmexecutormock_generated.go |
Regenerates context-aware npm mock. |
tsc/internal/symlinks/knownsymlinks.go |
Preserves symlink presentation paths. |
tsc/internal/symlinks/knownsymlinks_test.go |
Tests child spelling preservation. |
tsc/internal/sourcemap/generator.go |
Omits unset sourceRoot. |
tsc/internal/project/watch_test.go |
Tests watcher path spelling. |
tsc/internal/project/snapshotfs.go |
Tracks canonical and presented filenames. |
tsc/internal/project/session_test.go |
Updates watcher casing expectation. |
tsc/internal/project/refcountcache_test.go |
Tests rollback and final snapshot release. |
tsc/internal/project/projectcollectionbuilder.go |
Rolls back failed API state updates. |
tsc/internal/project/project.go |
Uses presentation-aware watch inputs. |
tsc/internal/project/background/queue.go |
Makes queue closure wait safely. |
tsc/internal/project/background/queue_test.go |
Tests close behavior. |
tsc/internal/modulespecifiers/specifiers.go |
Fixes nested package entrypoints. |
tsc/internal/module/util.go |
Splits file/directory package-root APIs. |
tsc/internal/lsp/server_completion_internal_test.go |
Tests invalid completion filenames. |
tsc/internal/lsp/replay_test.go |
Adapts npm executor context. |
tsc/internal/ls/rename.go |
Uses file-specific package roots. |
tsc/internal/ls/lsconv/converters.go |
Centralizes dynamic URI decoding. |
tsc/internal/ls/autoimport/util.go |
Fixes package realpath handling. |
tsc/internal/ls/autoimport/util_test.go |
Tests package realpath edge cases. |
tsc/internal/execute/watcher.go |
Canonicalizes mapper manifest events. |
tsc/internal/execute/tsctests/tsc_test.go |
Tests nested triple-slash redirects. |
tsc/internal/execute/tsctests/contentmapper_watch_test.go |
Tests case-insensitive mapper events. |
tsc/internal/execute/incremental/programtosnapshot.go |
Roots triple-slash references correctly. |
tsc/internal/compiler/projectreferencedtsfakinghost.go |
Preserves symlink child spelling. |
tsc/internal/api/session.go |
Fixes API path resolution and validation. |
tsc/internal/api/session_createsourcefile_test.go |
Tests empty filename rejection. |
tsc/cmd/tsc/lsp.go |
Cancels npm subprocesses through context. |
packages/typescript/test/sync/api.test.ts |
Regenerates synchronous API tests. |
packages/typescript/test/path.test.ts |
Tests VFS and URI path behavior. |
packages/typescript/test/async/api.test.ts |
Tests asynchronous API path behavior. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+268
to
+269
| if _, ok := strings.CutPrefix(fileName, packageDir); ok { | ||
| return replacePrefix(fileName, packageDir, realPackageDir) |
Comment on lines
+114
to
+119
| go func() { | ||
| q.Close() | ||
| close(closed) | ||
| }() | ||
|
|
||
| assert.Check(t, !channelClosed(closed), "Close returned before the active task completed") |
Jake Bailey (jakebailey)
force-pushed
the
typed-paths-prep
branch
from
September 29, 2026 23:11
2d9fb8d to
7153380
Compare
…A BUG) The new createSourceFile APIs treated an empty file name as the current working directory. A directory is not a valid source file name, and accepting it bypassed the rooted-path boundary. Reject empty names before resolving public string inputs into RootedFilePath values. Cover both in-memory and filesystem-backed source file creation.
…DA BUG) Main and the pre-port Strada behavior use canonical path strings as lookup keys, but some callers also reused those keys when constructing watcher globs or substituting a symlink target. On case-insensitive hosts that loses the spelling supplied by the filesystem or project configuration. Track the original filename alongside each canonical identity. Build watcher patterns from presentation paths, and retain the symlink spelling so child suffixes are taken from the original filename while lookup still uses canonical keys. This keeps identity comparisons canonical without leaking canonical casing into user-visible paths or filesystem watch registrations. Category: Typed-path-discovered; inherited Strada bug
…HS, STRADA BUG) Add focused coverage for the package realpath cache used during auto-import discovery. Exercise unscoped packages, scoped packages, and direct files under node_modules so file paths cannot silently become package-directory cache entries. The pre-fix expectations record the existing missing-separator result, which keeps this test commit independently green. The following fix updates the expectations to the path-preserving behavior. Category: Typed-path-discovered; inherited Strada bug
…S, STRADA BUG) Main and the pre-port Strada implementation use the same string path shape for both files and package directories while populating the auto-import realpath cache. A direct file under node_modules can therefore be interpreted as a package root, and replacing a cached prefix with string concatenation can produce paths such as node_modulesdep with no directory separator. Check whether each traversal candidate is actually a directory before caching a package realpath. Distinguish file and directory package-root parsing, and substitute cached prefixes with path-aware joining so exact roots and descendants preserve their separators. Cover bare scope directories, scoped package roots, unscoped packages, and direct files under node_modules. Category: Typed-path-discovered; inherited Strada bug
…DA BUG) Add coverage for deriving node_modules package roots from both file paths and directory paths. Include unscoped packages, scoped packages, bare scope directories, and direct files under node_modules. The test records the old directory parser's trailing-separator result so it remains independently green before the API is replaced. Category: Typed-path-discovered; inherited Strada bug
…DA BUG) Main and Strada route both files and directories through ParseNodeModuleFromPath with a Boolean path-kind argument. That makes it easy for callers to select the wrong boundary, especially for direct files under node_modules and scoped package directories. Replace the Boolean contract with explicit NodeModulePackageRootForFile and NodeModulePackageRootForDirectory helpers. Update module resolution, rename, auto-import realpaths, and project-reference source mapping to call the helper matching the path they hold. The explicit boundary prevents files from poisoning directory caches and keeps bare scopes distinct from scoped package roots. Category: Typed-path-discovered; inherited Strada bug
…A BUG) Add declaration-emit coverage for a type reached through node_modules/foo/other/index.d.ts. Exercise both a plain child directory and a child with its own package.json. Without nested metadata, the emitted specifier must retain the file path instead of treating foo/other as a package entrypoint. With nested metadata, the child package may still define that entrypoint. Category: Typed-path-discovered; inherited Strada bug
… BUG) The index-based node_modules path analysis inherited by main and Strada updates PackageRootIndex while probing nested package.json files. When a nested package.json is absent, that loses the original package boundary and incorrectly treats a child index.d.ts as the child directory's package entrypoint, shortening foo/other/index.d.ts to foo/other. Track the current candidate package root separately from the original package base. Use the original base when deciding whether a file without nested metadata is a package index, while still honoring actual nested package.json entrypoints. This keeps generated module specifiers stable for ordinary package subdirectories without disabling valid nested packages. Category: Typed-path-discovered; inherited Strada bug
… PARITY) Add a tsc incremental project-reference baseline for a nested source file with a triple-slash reference to referenced-project source. The baseline records the incorrect source dependency retained when redirect lookup roots the reference at the program working directory. Category: Typed-path-discovered; restores Strada behavior
…PARITY) Resolve triple-slash reference text from the containing source file directory before looking up project-reference redirects. This restores the output dependency intended by the original builder redirect change and removes the redundant referenced-project source from incremental build info. Category: Typed-path-discovered; restores Strada behavior
…ADA PARITY) The native API accepted project-relative file handles, but prepared auto-import snapshots by converting the unresolved handle against the session working directory. Strada and the TypeScript API instead operate on the source file selected from the project program, so the retry could prepare the wrong document and return no edit. Convert the resolved source filename back to a document URI before preparing auto imports. Apply the same rule to the completion retry added on current main, and cover both synchronous and asynchronous project-relative API calls. Category: Typed-path-discovered; restores Strada behavior
…IVE API) The JavaScript API accepts project-relative document identifiers, but its source-file cache canonicalized those identifiers against the API session's working directory. A project whose current directory differs from the session therefore fetched the same server source file under a second cache key and returned a new wrapper instead of preserving object identity. The native compiler and Strada resolve source files in their project context; the bug was confined to the newer JavaScript API cache boundary on main. Allow the API path converter to take an explicit base directory, and use the owning project's current directory for source- file and metadata cache keys. Keep the session directory as the default for project and snapshot keys. Cover both synchronous and asynchronous APIs, including metadata lookup and cache reuse across project-relative and absolute identifiers. Category: Typed-path-discovered; native API bug
…EW, STRADA BUG) Treat the file scheme and localhost authority case-insensitively when identifying local file URL volume roots. This matches URL semantics and prevents uppercase spellings from changing path normalization behavior. Category: Review-discovered; inherited Strada bug
Follow ECMA-426 when decoding source URLs. Preserve null source entries, resolve empty references with the specified sourceRoot semantics, retain duplicate source indices, and treat invalid source indices as unmapped positions rather than indexing invalid data. Omit sourceRoot from generated maps when it is not configured. The standard distinguishes an absent value from an explicit empty string, which denotes the root prefix "/"; historically TypeScript emitted an empty string while intending the absent-value behavior. Keep reverse mapping storage sparse-safe and reject malformed JSON values. Retain map-relative fallback for published TypeScript maps that used an explicit empty sourceRoot with nonempty relative sources. Category: Review-discovered; inherited Strada bug
Jake Bailey (jakebailey)
force-pushed
the
typed-paths-prep
branch
from
September 29, 2026 23:28
7153380 to
6da68a6
Compare
…DA BUG) Strada and main flattened non-file URIs into synthetic path strings. That representation normalized away dot segments and repeated separators, conflated reserved-looking names with encoded names, and could lose query, fragment, authority-only, and case-sensitive identity. The TypeScript API mirror had the same behavior. Introduce a reserved, reversible dynamic URI encoding in both Go and the TypeScript API. Treat the scheme and authority as the synthetic root, keep dynamic identities case-sensitive, and translate explicitly between logical URI segments and physical resolver paths. Carry that distinction through rootDirs, package.json fields, exports, generated entrypoints, CommonJS directory lookup, and VFS glob matching. Generic dynamic filenames outside the reserved codec root remain literal. Cover URI round trips, exceptional and reserved segments, dynamic package paths, rootDirs transitions, dotted directories, and generated module specifiers. Category: Review-discovered; inherited Strada bug
…NLY) API project and file opens are ref-counted in snapshot state. The project collection builder cloned that state for each snapshot, but then mutated the clone incrementally while processing closes and opens. If a later project update failed, the errored snapshot retained the earlier ref-count changes. The API session commits its own open-resource bookkeeping only after a successful update. Adopting the partially updated snapshot therefore left the two layers inconsistent, allowing a later close to release another session's reference or keep a resource loaded indefinitely. Clone the API state again at the request boundary and restore the pre-request state on error. This behavior is in the current native API on main; Strada did not have this shared, ref-counted API snapshot mechanism. Add a regression test that forces an update failure after closing a project and verifies that every API reference remains unchanged. Category: Review-discovered; native-only bug
A project session owns the initial reference to its current snapshot. Snapshot replacement releases the old session-owned reference, but Session.Close previously closed only the SnapshotHost and left the final current snapshot referenced. That retained the snapshot program, parse-cache entries, checker pools, and related project resources after the session itself had closed. Cancel and join background work, serialize closure against snapshot updates, then detach and dereference the current snapshot before closing its host. Thread the session context through automatic type acquisition and npm execution so shutdown can terminate external installs rather than waiting indefinitely. Make queue closure reject new work atomically with waiting for accepted work. LSP API sessions share the project snapshot and release their open-resource references through another update. Track their transports and connections so shutdown can stop and await all request handlers before closing each child session and finally the project session. This leak is present in the native project session on main. Strada managed project state through its server session lifecycle and did not have this reference-counted native snapshot ownership model. Add regression coverage that Close waits for queued work and that closing a project session releases both its parse-cache entry and program reference. Category: Review-discovered; native-only bug
…IVE ONLY) Content mapper manifest invalidation compared watch event paths with package manifest paths using their presentation strings. On a case-insensitive filesystem, equivalent paths with different casing therefore failed to trigger a mapper reload. Canonicalize both the changed paths and each configured mapper manifest using the watcher comparison policy before looking them up. Add a case-insensitive watch test whose symlink target and emitted event differ only in casing. This bug is present on main and is independent of typed paths. Category: Review-discovered; native-only bug
The JavaScript API virtual filesystem stored arbitrary path components in prototype-backed objects. Names such as toString and __proto__ could therefore collide with inherited properties instead of creating normal files and directories. Use null-prototype child maps and preserve entry spelling separately from canonical lookup keys. Accept an explicit CaseSensitivity so callers can model insensitive hosts without making sensitive hosts alias distinct files. Cover prototype-named components and case-insensitive lookup while preserving directory-entry casing. Category: Review; pre-existing native API bug
Jake Bailey (jakebailey)
force-pushed
the
typed-paths-prep
branch
from
September 30, 2026 00:07
6da68a6 to
190a3a5
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

This is just the fix stack pulled out of #64159 early for separate review and merge. See that PR for more info (and commit messages).