Skip to content

fix(extension): replace dynamic import() with static import in scanner#84

Merged
jserv merged 1 commit into
sysprog21:mainfrom
JackKuo-tw:fix/service-worker-dynamic-import
May 8, 2026
Merged

fix(extension): replace dynamic import() with static import in scanner#84
jserv merged 1 commit into
sysprog21:mainfrom
JackKuo-tw:fix/service-worker-dynamic-import

Conversation

@JackKuo-tw
Copy link
Copy Markdown
Contributor

@JackKuo-tw JackKuo-tw commented May 6, 2026

Problem

Clicking the extension icon fails with:

WASM scanner is not built. Run "sh extension/build-wasm.sh" before loading the extension.
import() is disallowed on ServiceWorkerGlobalScope by the HTML specification.

This happens even after a successful WASM build.

Root Cause

src/scanner.js loaded the WASM ES module via a dynamic import():

const wasmModule = await import("../dist/zhtw_mcp_wasm.js");

The HTML specification forbids dynamic import() inside a Service Worker global scope. Since background.js runs as an MV3 module service worker, this call fails at runtime.

Fix

Replace the runtime dynamic import() with a static top-level import, which is permitted in module service workers declared with "type": "module":

// Before — dynamic, forbidden in SW
const wasmModule = await import("../dist/zhtw_mcp_wasm.js");
await wasmModule.default(wasmUrl);
scanTextBinding = wasmModule.scan_text;

// After — static, allowed in module SW
import init, { scan_text } from "../dist/zhtw_mcp_wasm.js";
await init({ module_or_path: wasmUrl });

The scanTextBinding indirection is removed since scan_text is now a direct static import.

Closes #83

Dynamic import() is forbidden in ServiceWorkerGlobalScope by the HTML
spec. Since background.js runs as an MV3 service worker, the lazy
`await import("../dist/zhtw_mcp_wasm.js")` call in scanner.js caused
the WASM scanner to fail immediately with:

  import() is disallowed on ServiceWorkerGlobalScope by the HTML specification.

Replace it with a static top-level import (permitted in module service
workers declared with "type": "module") and pass the WASM URL directly
to the init function using the current object-parameter API.

Fixes: sysprog21#83

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="extension/src/scanner.js">

<violation number="1" location="extension/src/scanner.js:1">
P1: Static top-level import of WASM module bypasses graceful error handling — a missing or invalid WASM bundle now crashes the service worker at module load time instead of being caught and reported as a user-friendly error.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread extension/src/scanner.js
@@ -1,20 +1,18 @@
let wasmModulePromise;
let scanTextBinding;
import init, { scan_text } from "../dist/zhtw_mcp_wasm.js";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Static top-level import of WASM module bypasses graceful error handling — a missing or invalid WASM bundle now crashes the service worker at module load time instead of being caught and reported as a user-friendly error.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At extension/src/scanner.js, line 1:

<comment>Static top-level import of WASM module bypasses graceful error handling — a missing or invalid WASM bundle now crashes the service worker at module load time instead of being caught and reported as a user-friendly error.</comment>

<file context>
@@ -1,20 +1,18 @@
-let wasmModulePromise;
-let scanTextBinding;
+import init, { scan_text } from "../dist/zhtw_mcp_wasm.js";
+
+let initPromise;
</file context>

@JackKuo-tw
Copy link
Copy Markdown
Contributor Author

JackKuo-tw commented May 6, 2026

@doggy8088 could you help to verify this fix?

@JackKuo-tw JackKuo-tw force-pushed the fix/service-worker-dynamic-import branch from ebe1063 to 4ab5ad9 Compare May 6, 2026 23:36
@doggy8088
Copy link
Copy Markdown
Contributor

Thanks for the fix. I reviewed this PR and the direction looks correct.

Chrome Extension MV3 module service workers support top-level static import, but they do not support dynamic import(). Since background.js is registered as a module service worker via "type": "module", the previous await import("../dist/zhtw_mcp_wasm.js") path can fail in the service worker environment. Replacing it with a static import from ../dist/zhtw_mcp_wasm.js matches Chrome’s service worker loading model.

I also checked the review concern about error handling. It is true that if extension/dist/zhtw_mcp_wasm.js is missing, a static import fails during service worker module loading, so the old user-friendly scanText() error path cannot run. I do not think that should block this PR: an extension loaded without the generated WASM bundle is already not in a valid runnable state, and the extension packaging workflow builds WASM first and includes extension/dist/*.js and *.wasm in the package.

So I think this PR is the right fix for #83. If we want to improve the developer experience further, that can be handled separately by making the build/package step or README more explicit about requiring sh extension/build-wasm.sh before loading the unpacked extension.

LGTM.

@jserv jserv merged commit 97333ab into sysprog21:main May 8, 2026
5 of 9 checks passed
@jserv
Copy link
Copy Markdown
Contributor

jserv commented May 8, 2026

Thank @JackKuo-tw for contributing!

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.

fix: dynamic import() in service worker breaks WASM scanner

3 participants