Skip to content

playwrightLoader: adapt to playwright-core 1.60 restructure#81

Merged
hynek-urban merged 9 commits into
devfrom
wz/playwright-core-1.60-compat
Jun 4, 2026
Merged

playwrightLoader: adapt to playwright-core 1.60 restructure#81
hynek-urban merged 9 commits into
devfrom
wz/playwright-core-1.60-compat

Conversation

@weishi-imbue
Copy link
Copy Markdown
Contributor

@weishi-imbue weishi-imbue commented Jun 3, 2026

playwright-core 1.60 dropped the internal subpaths we were importing in playwrightLoader.ts:

  • ./lib/server/registry/index (Registry instance)
  • ./lib/zipBundle (extract function)

Both files were removed AND not added to package.json#exports. Imports throw ERR_PACKAGE_PATH_NOT_EXPORTED, which our caller wraps as BrowserFeaturesUnavailableError — "Browser-based features are not available in the standalone latchkey binary". Misleading: latchkey isn't standalone, just incompatible with the new playwright-core.

This PR loads lib/coreBundle (which IS in the exports map) once and pulls the same symbols from the new locations:

  • coreBundle.default.registry.registry → Registry instance
  • coreBundle.default.utils.extractZip → extract function

The returned shape is unchanged so playwrightDownload.ts keeps working without changes.

Empirically verified locally that the new registry exposes findExecutable('chromium') and returns a real Executable. Diagnosed against the bundled playwright-core@1.60.0 shipping inside the minds.app, which is the version most users encounter.

Dependency bump (required)

lib/coreBundle only exists in playwright-core ≥ 1.60.0; 1.58.x/1.59.x still ship the old lib/zipBundle + lib/server/registry/index layout. latchkey declared playwright ^1.58.2 (lockfile pinned 1.58.2), so the new imports would throw ERR_PACKAGE_PATH_NOT_EXPORTED on the npm install -g latchkey path even though they resolve fine against the minds.app-bundled 1.60. This PR therefore bumps playwright and regenerates the lockfile so latchkey's own declared dependency matches the layout the code now requires.

The range is pinned with a tilde (~1.60.0), not a caret. We import playwright-core private internals, which carry no semver guarantee and were restructured in the 1.59→1.60 minor bump. A caret would let a fresh npm install -g latchkey resolve a future minor that moves them again, silently reintroducing this exact failure. Tilde allows only 1.60.x patches; minor playwright upgrades become deliberate, re-verified changes.

Typing

playwright-core ships no .d.ts for these internal subpaths, so src/playwright-core.d.ts carries an ambient declaration for lib/coreBundle (Executable, Registry, and the default export shape). playwrightLoader.ts derives its return types from that declaration — no inline casts or @ts-expect-error.

🤖 Generated with Claude Code

playwright-core 1.60 removed the internal subpaths we were importing:
  - ./lib/server/registry/index  (provided the Registry instance)
  - ./lib/zipBundle              (provided the extract function)

Those file paths no longer exist AND aren't in package.json's exports
map. Any import that names them throws ERR_PACKAGE_PATH_NOT_EXPORTED.
Our caller surfaces the throw as BrowserFeaturesUnavailableError so the
user sees 'Browser-based features are not available in the standalone
latchkey binary' — misleading, since playwright and playwright-core
both resolve fine, only the deep paths are gone.

The same symbols live inside ./lib/coreBundle (which IS in the exports
map):
  - coreBundle.default.registry.registry → the Registry instance
  - coreBundle.default.utils.extractZip  → the zip extract function

Load coreBundle once and adapt its namespace to the original
{ registry } / { extract } shape that playwrightDownload.ts
destructures. Empirically verified that registry.findExecutable('chromium')
returns a real Executable with executablePath/installType in
playwright-core 1.60.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vet found 1 issue.

Comment thread src/playwrightLoader.ts Outdated
weishi-imbue and others added 7 commits June 3, 2026 10:57
Problem: src/playwrightLoader.ts ended with stray '</content>' and
'</invoke>' lines left over from a code-generation transcript, causing
TypeScript compile errors (TS1110, TS1161) that broke tsc for the whole
project.
Fix: Delete the two trailing artifact lines so the file ends cleanly
after loadPlaywrightZipBundle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: loadPlaywrightRegistry returned { registry: unknown }, so callers
in playwrightDownload.ts that use registry.findExecutable(...) and the
returned executable's directory/executablePath/downloadURLs/name failed to
typecheck (TS18046 'registry is of type unknown').
Fix: Add minimal PlaywrightExecutable and PlaywrightRegistry interfaces
reflecting the coreBundle registry shape (verified against playwright-core
1.60) and return { registry: PlaywrightRegistry }.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: playwright-core ships no type declarations for the internal
'lib/coreBundle' subpath, so tsc failed with TS2307 'Cannot find module'
on the dynamic import introduced by this change, breaking typecheck.
Fix: Add a @ts-expect-error directive on the import, mirroring the existing
pattern used for untyped dynamic imports in skillMd.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: playwrightLoader.ts imports playwright-core/lib/coreBundle, which
only exists in playwright-core >=1.60.0; 1.58.2/1.59.x still ship the old
lib/zipBundle and lib/server/registry/index layout. package.json declared
playwright ^1.58.2 and the lockfile pinned 1.58.2, so under the declared
floor the new code throws ERR_PACKAGE_PATH_NOT_EXPORTED at runtime and
vitest fails to load tests/playwrightDownload.test.ts ('Missing
./lib/coreBundle specifier in playwright-core').
Fix: Bump playwright to ^1.60.0 and update the lockfile to playwright-core
1.60.0. Also export the PlaywrightExecutable/PlaywrightRegistry interfaces
so getChromiumExecutable's inferred return type can be named across the
module boundary (TS4058).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: the playwright-core 1.60 refactor switched playwrightLoader.ts to
import 'playwright-core/lib/coreBundle' but left src/playwright-core.d.ts
declaring only the removed subpaths 'lib/server/registry/index' and
'lib/zipBundle' (dead code, nothing imports them). To compensate, the loader
typed the new import inline with an interface plus '@ts-expect-error' and an
'as unknown as' double cast, duplicating the Executable/Registry interfaces
already in the .d.ts and bypassing type checking of the dynamic import. The
file-level comment also narrated the migration history.

Fix: replace the stale declarations in src/playwright-core.d.ts with a single
ambient declaration for 'playwright-core/lib/coreBundle' (Executable, Registry,
and the default export shape). playwrightLoader.ts now derives its types from
that declaration, dropping the '@ts-expect-error', the unsafe cast, and the
duplicated inline interfaces. Trimmed the file comment to the load-bearing
exports-map fact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: The doc comment added to src/playwrightLoader.ts used RST-style
double-backtick code spans (``lib/coreBundle`` etc.), inconsistent with the
file header and every other comment code span in src/, which use single
backticks.

Fix: Converted the four double-backtick spans to single backticks to match the
dominant comment style. Comment-only change with no behavior impact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The doc comment narrated the full playwright-core 1.60 migration; that
history belongs in the PR description. Trim it to what the code does
(read registry/extract from lib/coreBundle) and the one load-bearing
fact (it is the only exports-mapped subpath that reaches them).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vet found 0 issues.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vet found 0 issues.

playwrightLoader.ts imports playwright-core private internals
(lib/coreBundle), which carry no semver guarantee and were restructured
in the 1.59->1.60 minor bump. A caret range lets a fresh
`npm install -g latchkey` resolve a future minor that moves them again,
silently reintroducing ERR_PACKAGE_PATH_NOT_EXPORTED. Tilde allows only
1.60.x patches; minor playwright upgrades become deliberate, re-verified
changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vet found 0 issues.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vet found 0 issues.

@weishi-imbue weishi-imbue requested a review from hynek-urban June 4, 2026 05:10
@hynek-urban
Copy link
Copy Markdown
Collaborator

Looks good to me. Thanks, @weishi-imbue !

@hynek-urban hynek-urban changed the base branch from main to dev June 4, 2026 09:48
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vet found 0 issues.

@hynek-urban hynek-urban merged commit e497e35 into dev Jun 4, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants