Skip to content

fix(qwikloader): inline dynamic import under nonce CSP and fix WebKit mid-stream resume - #9208

Merged
Varixo merged 3 commits into
QwikDev:mainfrom
akasakariko:fix/8891-webkit-loader-csp
Oct 18, 2026
Merged

Varixo merged 3 commits into
QwikDev:mainfrom
akasakariko:fix/8891-webkit-loader-csp

Conversation

@akasakariko

Copy link
Copy Markdown
Contributor

Summary

Fixes #8891
Replaces #9182 and addresses maintainer review requesting multi-browser streaming coverage under enforced nonce CSP

  • Preserves modulepreload while replacing external async loader script with classic inline dynamic import via existing nonce-aware emitInlineScript helper
  • Resolves module import via new URL(serializedLoaderURL, document.baseURI).href
  • Escapes literal < as \u003C in serialized loader path to prevent premature script tag termination
  • Leaves inline and never loader modes untouched
  • Adds unit coverage for default and explicit module modes across nonce, relative path, CDN URL, and script termination scenarios
  • Re-enables WebKit mid-stream click queue and replay test, parameterizing test runs with and without CSP
  • Fixture onRequest attaches a fresh nonce and enforces script-src 'nonce-${nonce}' 'strict-dynamic' header with zero reported CSP violations
  • Gate fixture removes raw inline onclick attribute when nonce is present to respect strict browser CSP behavior in Firefox
  • Updates changed SSG snapshot loader tag and adds patch changeset for core
  • Scope note: addresses nonce-based strict-dynamic configurations without claiming universal compatibility across all CSP header permutations

Verification

Environment: macOS 26.4.1, Node 24.19.0, pnpm 11.22.0, Playwright 1.61.1 / WebKit 26.5 with PLAYWRIGHT_BROWSERS_PATH=/Volumes/P600/playwright-browsers

Pre-fix reproduction on latest main with WebKit skip removed:

pnpm exec playwright test --config e2e/qwik-e2e/playwright.config.ts error-handling.e2e.ts --grep 'mid-stream click' --browser=webkit --repeat-each=3 --workers=1 --retries=0

Result: 2 failures at loader-ready poll, 1 pass

Post-fix matrix across Chromium, Firefox, and WebKit (both with and without CSP):

GITHUB_ACTIONS=true pnpm exec playwright test --config e2e/qwik-e2e/playwright.config.ts error-handling.e2e.ts --grep 'mid-stream click' --browser=all --repeat-each=5 --workers=1 --retries=0

Result: 30 passed

Full error handling suite across all browsers:

GITHUB_ACTIONS=true pnpm exec playwright test --config e2e/qwik-e2e/playwright.config.ts error-handling.e2e.ts --browser=all --workers=1 --retries=0

Result: 126 passed, 6 existing skips

Mutation control:
Temporarily bypassed nonce on bootstrap script under enforced CSP; all 3 engines blocked execution with console violations; restoring nonce returned 30 passed

SSG snapshot tests:

pnpm exec playwright test --config e2e/qwik-e2e/playwright.config.ts ssg-snapshot.e2e.ts --browser=all --workers=1 --retries=0

Result: 6 passed, 12 intentional skips for non-Chromium browsers

Focused unit tests:

pnpm exec vitest run packages/qwik/src/core/tests/render-api.spec.tsx packages/qwik/src/server/ssr-container.spec.ts --maxWorkers=4
pnpm exec vitest run packages/qwik/src --maxWorkers=1

Result: 93 passed on render and container specs; 2629 passed, 18 skipped, 19 todo on core

Type and build verification:

  • pnpm build.core.dev passed
  • pnpm build --qwik --optimizer --qwikrouter --eslint passed
  • pnpm exec tsc -p packages/qwik/tsconfig.json --noEmit passed
  • pnpm lint.eslint passed
  • pnpm lint.prettier passed
  • git diff --check passed

Validation Limitations and Caveats

  • Concurrent worker run disclosure: one failure occurred during a 4-worker run concurrent with E2E, then the affected spec passed 34/34 and the entire core suite passed with one worker
  • Monorepo unit suite disclosure: pnpm exec vitest run packages --maxWorkers=4 yielded 4001 passed and 7 failures inside plugin.unit.ts due to missing local Rust wasm bindings (packages/qwik-vite/src/bindings/qwik.wasm.mjs); the same 7 failures reproduced after temporarily reverting ONLY packages/qwik/src/server/ssr-container.ts to base; other test changes remained, so do not claim clean base
  • Exploratory QWIK_OPTIMIZER=ts pnpm exec vitest run packages --maxWorkers=1 produced 4007 passed and 1 failure on the assertion verifying default Rust optimizer usage due to the environment variable override
  • Remote GitHub CI on this replacement PR has not run yet

@akasakariko
akasakariko requested a review from a team as a code owner October 13, 2026 15:34
@changeset-bot

changeset-bot Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2e43622

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 8 packages
Name Type
@qwik.dev/core Patch
@qwik.dev/devtools Patch
eslint-plugin-qwik Patch
@qwik.dev/mcp Patch
@qwik.dev/react Patch
@qwik.dev/router Patch
@qwik.dev/utils Patch
create-qwik Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@qwik.dev/core

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/core@9208

@qwik.dev/router

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/router@9208

@qwik.dev/utils

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/utils@9208

eslint-plugin-qwik

npm i https://pkg.pr.new/QwikDev/qwik/eslint-plugin-qwik@9208

create-qwik

npm i https://pkg.pr.new/QwikDev/qwik/create-qwik@9208

@qwik.dev/optimizer

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/optimizer@9208

@qwik.dev/devtools

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/devtools@9208

@qwik.dev/mcp

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/mcp@9208

commit: e042513

@Varixo Varixo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One more thing related to compatibility caveat remains: deployments using script-src "self" with a fixed set of hashes for existing inline scripts will need to add a hash for the new bootstrap. Could you mention this requirement in the changeset and documentation?

@Varixo

Varixo commented Oct 13, 2026

Copy link
Copy Markdown
Member

Also the other PR can be closed?

@akasakariko

Copy link
Copy Markdown
Contributor Author

@Varixo Thanks for the review

Good point on the hash-pinned script-src 'self' setups, I'll add a note about the extra hash for the new bootstrap to both the changeset and the docs

And yes, #9182 is superseded by this PR, so it can be closed

@Varixo Varixo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@Varixo
Varixo merged commit ef0be02 into QwikDev:main Oct 18, 2026
104 of 106 checks passed
akasakariko added a commit to akasakariko/akasakariko that referenced this pull request Oct 18, 2026
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.

qwikloader: WebKit may defer the async module loader while a stream is held, losing pre-resume clicks

2 participants