@W-23618508 fix VS Code extension blocking others on empty workspace - #598
Merged
Conversation
The extension registers a TypeScript server plugin, so VS Code activates
it whenever any JS/TS file is opened — including empty (no-folder)
windows. On that path the config provider fell back to process.cwd()
(the extension host's arbitrary cwd, often the user's home directory),
and eager activation work then ran unbounded synchronous
globSync('**/.project') / detectWorkspaceType filesystem walks on the
shared extension-host thread, freezing every other extension.
Fix (all in packages/b2c-vs-extension):
- detectWorkingDirectory() returns '' when there are no workspace
folders instead of falling back to process.cwd(), so an empty window
does no filesystem discovery.
- Add isUnscannableRoot() (home dir, filesystem root, or empty path) and
guard config resolution + storefront-next detection with it, mirroring
the MCP server's existing home/root guard.
- Add findCartridgesSafe(): the single entry point all extension
cartridge discovery now uses. It refuses to scan an empty/home/root
directory (never falls back to cwd) and depth-bounds the scan
(WORKSPACE_DISCOVERY_MAX_DEPTH=5). Route every findCartridges() call
site through it.
- Add unit tests for isUnscannableRoot and findCartridgesSafe.
Gated on pnpm run typecheck:agent (all packages) and the extension test
suite (all vscode-test labels) passing.
This was referenced Jul 29, 2026
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.
Summary
Fixes W-23618508: the B2C Commerce VS Code extension was blocking other extensions when opened in an empty (no-folder) or non-B2C workspace. Clicking a B2C DX activity-bar icon in an empty window would spin forever, and other extensions (e.g. Claude Code) would also show a loading badge with an empty, un-activated panel.
Root cause
VS Code runs all extensions in a single shared extension-host process, so synchronous CPU work in one extension's activation stalls the event loop and makes every other extension appear stuck "activating" (the spinner + empty panels in the repro).
The extension can be activated in an empty window by several events — clicking a B2C DX view icon (
onView:*), or opening any JS/TS file (the extension contributes a TypeScript server plugin, which VS Code loads for all JS/TS files). Whatever the trigger,activate()→activateInner()then ran heavy synchronous, unbounded filesystem work:detectWorkingDirectory()fell back toprocess.cwd()when there were no workspace folders — the extension host's arbitrary cwd, often the user's home directory.globSync('**/.project')walks on the shared extension-host thread (viaregisterScriptTypes→CartridgeService.getCartridges()→findCartridges(cwd), andupdateStorefrontNextContext()→detectWorkspaceType(cwd)).Scanning the whole home tree synchronously freezes the extension host, blocking every other extension.
Fix (all in
packages/b2c-vs-extension)Do no filesystem discovery without a concrete workspace folder, and never let
findCartridgesscan out of home/root:workspace-discovery.ts: addedisUnscannableRoot(dir)(empty / home dir / filesystem root) andfindCartridgesSafe(dir, opts)— the single entry point all extension cartridge discovery now uses. It returns[]for unscannable roots (never falls back toprocess.cwd()) and depth-bounds every scan (WORKSPACE_DISCOVERY_MAX_DEPTH = 5). Mirrors the MCP server's existingregistry.tshome/root guard.config-provider.ts:detectWorkingDirectory()returns''(notprocess.cwd()) when there are no workspace folders;resolveAsyncskips resolution/discovery for home/root/missing dirs.extension.ts:updateStorefrontNextContext()skips detection for unscannable roots and depth-bounds the scan otherwise.findCartridgescall sites throughfindCartridgesSafe(cartridge-service, code-sync-manager, deploy-command, debugger, jobs-commands, jobs-tree-provider, scaffold-commands, onboardingPanel) so no path can recursively scan out of home.Manual testing
Reproduce the original report:
No workspace folders open; skipping filesystem discovery..projectscan.dw.jsonand cartridges) and confirm cartridge discovery, code sync, debugger, and Script API IntelliSense still work as before.