Skip to content

Conversation

@mikstime
Copy link
Contributor

@mikstime mikstime commented Feb 1, 2026

Proposal

Remove the ? or # part from dependencies in the metainfo.json file.

Description

@playwright/experimental-ct-core generates a metainfo.json file used for caching and other optimizations performed by Playwright under the hood.

The current implementation relies on a Vite plugin to generate this file. However, Vite prohibits the usage of # and ? in file names, meaning there is no reason to store them in the metainfo.json file.

Both # and ? are reserved for compatibility with browser URLs.

-- patak-dev

We experienced two major issues with the current behavior:

  • Our metainfo.json file exceeded 512MB, which is the hard limit for the JSON.parse() method, resulting in unexpected crashes

  • This data was serialized and deserialized each time tests ran, resulting in a 4x slowdown of tests in our project

80% performance improvement with proposed fix

Example

Metainfo.json file is reduced from 1.4M to 4.0K in provided example

1.4M    current/playwright/.cache/metainfo.json
4.0K    patched/playwright/.cache/metainfo.json

https://github.com/mikstime/playwright

@dgozman
Copy link
Contributor

dgozman commented Feb 3, 2026

@mikstime Thank you for the PR! Is there any way you can share a repro, or even better - turn that into a test? That would help us to review and prevent future regressions.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@mikstime
Copy link
Contributor Author

mikstime commented Feb 3, 2026

@mikstime Thank you for the PR! Is there any way you can share a repro, or even better - turn that into a test? That would help us to review and prevent future regressions.

Here is an example https://github.com/mikstime/playwright

@dgozman
Copy link
Contributor

dgozman commented Feb 4, 2026

@mikstime Thank you for the PR! Is there any way you can share a repro, or even better - turn that into a test? That would help us to review and prevent future regressions.

Here is an example https://github.com/mikstime/playwright

Wonderful! Could you please add a test to tests/playwright-test/playwright.ct-build.spec.ts that follows this example? You can run it with npm run ttest playwright.ct-build.spec:<line>.

@mikstime
Copy link
Contributor Author

mikstime commented Feb 4, 2026

@microsoft-github-policy-service agree

@mikstime
Copy link
Contributor Author

mikstime commented Feb 4, 2026

@mikstime Thank you for the PR! Is there any way you can share a repro, or even better - turn that into a test? That would help us to review and prevent future regressions.

Here is an example https://github.com/mikstime/playwright

Wonderful! Could you please add a test to tests/playwright-test/playwright.ct-build.spec.ts that follows this example? You can run it with npm run ttest playwright.ct-build.spec:<line>.

Sure. Thank you for the instructions.

Running 1 test using 1 worker

  ✓  1 [playwright-test] › tests/playwright-test/playwright.ct-build.spec.ts:740:5 › should remove ? or # from deps in metainfo.json (3.1s)

  1 passed (3.8s)

if (!path.isAbsolute(id))
return;
const normalizedId = path.normalize(id);
const normalizedId = path.normalize(id).split(/\?|#/)[0];
Copy link
Contributor

Choose a reason for hiding this comment

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

  • I think we should strip ? and # before the line 292, just in case there was something like /.. in the query params or hash.
  • It would be great to add a comment explaining/having an example of an import with a query param.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. I’ve stripped ? and # before line 292 and added a comment with an example of an import that includes query parameters.
For context: even without stripping, path.isAbsolute would still treat such paths as absolute. According to the Node.js documentation, paths like /baz/.. are considered absolute, and this also applies when query params or hashes are present, e.g.:

path.isAbsolute('C:/foo/..');   // true
path.isAbsolute('C:\\foo\\..'); // true
path.isAbsolute('/baz/..');    // true
path.isAbsolute('/baz/../..'); // true

This is also true:

> p.isAbsolute('/dir/file#x=../../b.png')
true
> p.isAbsolute('/dir/file?x=../../b.png')
true

That said, removing ? and # up front makes the intent clearer and avoids any edge cases involving traversal in query or hash parts.

expect(result.passed).toBe(1);
});

test('should remove ? or # from deps in metainfo.json', async ({ runInlineTest }, testInfo) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for the test, this really helped!

Just to understand the scenario better, do you have a custom loader/plugin/something else that handles query params? What's the actual usecase of yours, not the toy example we have here?

Can we have a test that resembles real life? IIUC, this should manifest in watch not triggering when you change a styles file that was imported as './style.css?inline'. At least, that's the impression I get from reading vite docs. If so, we can add a simple test next to should watch component when editing util.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to understand the scenario better, do you have a custom loader/plugin/something else that handles query params? What's the actual usecase of yours, not the toy example we have here?

We use a Vite plugin that transforms source code and appends query parameters to module imports. These query params are used to alter compilation behavior based on the user agent.

If so, we can add a simple test next to should watch component when editing util.

Sure. I’ve added two tests:

  • One that directly covers the query-param import case (e.g. style.css?inline), matching the real-world scenario described above.
  • Another that exercises the same behavior through a story file, since playwright compiles these cases differently.

Copy link
Contributor

@dgozman dgozman left a comment

Choose a reason for hiding this comment

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

This looks great, thank you for following through!

@github-actions

This comment has been minimized.

@dgozman
Copy link
Contributor

dgozman commented Feb 11, 2026

@mikstime It seems like this broke our component tests. Could you please take a look? You can run npm run ct for all component tests, or cd tests/components/ct-svelte && npm install && npx playwright test to see what's going on with specific tests. Please let me know if you stumble upon any issue.

@github-actions

This comment has been minimized.

@mikstime
Copy link
Contributor Author

@mikstime It seems like this broke our component tests. Could you please take a look? You can run npm run ct for all component tests, or cd tests/components/ct-svelte && npm install && npx playwright test to see what's going on with specific tests. Please let me know if you stumble upon any issue.

Sorry about that — looks like I dropped a small but important guard during the rebase:

  if (deps.has(normalizedId))
    return;

Must be working now. npm run ct is passing now (18 passed (4.3m))

@github-actions
Copy link
Contributor

Test results for "tests 1"

4 failed
❌ [playwright-test] › reporter-html.spec.ts:304 › merged › should not include image diff with non-images @macos-latest-node20
❌ [playwright-test] › ui-mode-test-network-tab.spec.ts:371 › should not preserve selection across test runs @macos-latest-node20
❌ [playwright-test] › update-aria-snapshot.spec.ts:299 › should update missing snapshots in tsx @macos-latest-node20
❌ [playwright-test] › update-aria-snapshot.spec.ts:669 › update-source-method › should overwrite source when specified in the config @macos-latest-node20

5 flaky ⚠️ [chromium-library] › library/popup.spec.ts:258 › should not throw when click closes popup `@chromium-ubuntu-22.04-arm-node20`
⚠️ [firefox-library] › library/inspector/cli-codegen-1.spec.ts:1082 › cli codegen › should not throw csp directive violation errors `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-page] › page/page-wait-for-function.spec.ts:104 › should work with strict CSP policy `@firefox-ubuntu-22.04-node20`
⚠️ [playwright-test] › ui-mode-trace.spec.ts:384 › should reveal errors in the sourcetab `@macos-latest-node20`
⚠️ [playwright-test] › ui-mode-trace.spec.ts:812 › should update state on subsequent run `@macos-latest-node20`

38565 passed, 843 skipped


Merge workflow run.

@mikstime
Copy link
Contributor Author

Test results for "tests 1"

4 failed ❌ [playwright-test] › reporter-html.spec.ts:304 › merged › should not include image diff with non-images @macos-latest-node20 ❌ [playwright-test] › ui-mode-test-network-tab.spec.ts:371 › should not preserve selection across test runs @macos-latest-node20 ❌ [playwright-test] › update-aria-snapshot.spec.ts:299 › should update missing snapshots in tsx @macos-latest-node20 ❌ [playwright-test] › update-aria-snapshot.spec.ts:669 › update-source-method › should overwrite source when specified in the config @macos-latest-node20

5 flaky
38565 passed, 843 skipped

Merge workflow run.

Can't reproduce locally on macOS + node 20. Can it be a fluke?

Tests passing locally
mikstime@mikstime-osx playwright-1 % node -v
v20.13.1
mikstime@mikstime-osx playwright-1 % npm run ttest update-aria-snapshot.spec.ts:299
mikstime@mikstime-osx playwright-1 % npm run ttest update-aria-snapshot.spec.ts:299

> playwright-internal@1.59.0-next ttest
> node ./tests/playwright-test/stable-test-runner/node_modules/@playwright/test/cli test --config=tests/playwright-test/playwright.config.ts update-aria-snapshot.spec.ts:299


Running 1 test using 1 worker

  ✓  1 [playwright-test] › tests/playwright-test/update-aria-snapshot.spec.ts:299:5 › should update missing snapshots in tsx (10.3s)

  1 passed (11.0s)
mikstime@mikstime-osx playwright-1 % npm run ttest update-aria-snapshot.spec.ts:669

> playwright-internal@1.59.0-next ttest
> node ./tests/playwright-test/stable-test-runner/node_modules/@playwright/test/cli test --config=tests/playwright-test/playwright.config.ts update-aria-snapshot.spec.ts:669


Running 1 test using 1 worker

  ✓  1 [playwright-test] › tests/playwright-test/update-aria-snapshot.spec.ts:669:7 › update-source-method › should overwrite source when specified in the config (8.9s)

  1 passed (9.6s)
mikstime@mikstime-osx playwright-1 % npm run ttest reporter-html.spec.ts:304       

> playwright-internal@1.59.0-next ttest
> node ./tests/playwright-test/stable-test-runner/node_modules/@playwright/test/cli test --config=tests/playwright-test/playwright.config.ts reporter-html.spec.ts:304


Running 2 tests using 2 workers

  ✓  1 [playwright-test] › tests/playwright-test/reporter-html.spec.ts:304:5 › created › should not include image diff with non-images (2.7s)
  ✓  2 [playwright-test] › tests/playwright-test/reporter-html.spec.ts:304:5 › merged › should not include image diff with non-images (3.1s)

  2 passed (5.7s)
mikstime@mikstime-osx playwright-1 % npm run ttest ui-mode-test-network-tab.spec.ts:371

> playwright-internal@1.59.0-next ttest
> node ./tests/playwright-test/stable-test-runner/node_modules/@playwright/test/cli test --config=tests/playwright-test/playwright.config.ts ui-mode-test-network-tab.spec.ts:371


Running 1 test using 1 worker

  ✓  1 [playwright-test] › tests/playwright-test/ui-mode-test-network-tab.spec.ts:371:5 › should not preserve selection across test runs (7.4s)

  1 passed (8.2s)

@github-actions
Copy link
Contributor

Test results for "MCP"

10 failed
❌ [chrome] › mcp/autowait.spec.ts:19 › racy navigation destroys context @mcp-windows-latest
❌ [chromium] › mcp/roots.spec.ts:47 › check that trace is saved in workspace @mcp-windows-latest
❌ [firefox] › mcp/cli-cookies.spec.ts:59 › cookie-delete removes cookie @mcp-windows-latest
❌ [firefox] › mcp/cli-parsing.spec.ts:54 › wrong argument type @mcp-windows-latest
❌ [firefox] › mcp/cli-route.spec.ts:85 › unroute removes all routes @mcp-windows-latest
❌ [chrome] › mcp/cli-parsing.spec.ts:63 › should preserve leading zeros in string arguments @mcp-macos-15
❌ [chrome] › mcp/cli-save-as.spec.ts:19 › screenshot @mcp-macos-15
❌ [chrome] › mcp/cli-save-as.spec.ts:26 › screenshot @mcp-macos-15
❌ [chrome] › mcp/test-debug.spec.ts:234 › test_debug / evaluate x 2 @mcp-macos-15
❌ [chromium] › mcp/launch.spec.ts:21 › test reopen browser @mcp-macos-15

4769 passed, 135 skipped


Merge workflow run.

Copy link
Contributor

@dgozman dgozman left a comment

Choose a reason for hiding this comment

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

All the related tests are passing, merging in. Thank you for the fix!

@dgozman dgozman merged commit a7bcfe3 into microsoft:main Feb 11, 2026
30 of 33 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