[PR #3797] [MERGED] fix(javascript): keep string Worker paths unresolved without a document base #5905

Closed
opened 2026-10-31 01:10:19 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3797
Author: @kaoru0822-kitauji
Created: 10/15/2026
Status: ✅ Merged
Merged: 10/15/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/3309-worker-document-base


📝 Commits (1)

  • 7d0cb7a fix(javascript): keep string Worker paths unresolved without a document base

📊 Changes

9 files changed (+119 additions, -51 deletions)

View changed files

📝 docs/javascript-artifact-reconstruction.md (+4 -1)
📝 src/domain/javascript/javascriptStaticAnalysisCalleeBoundary.test.ts (+3 -2)
📝 src/domain/javascript/javascriptStaticAnalysisCalls.ts (+12 -6)
📝 tests/acceptance/applications/applicationWorkflowCli.test.ts (+34 -20)
📝 tests/acceptance/applications/javascriptWorkerUrlCli.test.ts (+51 -9)
📝 tests/boundary/filesystem/javascript-applications/javascriptApplicationEmptyLiterals.test.ts (+3 -1)
📝 tests/boundary/filesystem/javascript-applications/javascriptApplicationTemplateLiterals.test.ts (+1 -1)
📝 tests/boundary/filesystem/javascriptSourceMapLocations.test.ts (+10 -10)
📝 tests/fixtures/javascriptRuntimeReconciliation.ts (+1 -1)

📄 Description

Fixes #3309

Root cause

inspectCall (javascriptStaticAnalysisCalls.ts) emitted the first string argument of a browser new Worker("./worker.js") and of navigator.serviceWorker.register("./sw.js") as the reference specifier. The graph then resolved it as a URL relative to the calling script. Neither loader uses that base:

  • A browser resolves both against the document base URL. In the issue's fixture, index.html loads scripts/main.js, and the browser fetched worker.js, not scripts/worker.js.
  • A Node worker_threads string resolves against process.cwd(). This producer already dropped the specifier for that case for the same reason.

So REA recorded a resolved, high-confidence mapping to the wrong file.

Change

Only new Worker(new URL(path, import.meta.url)) produces a specifier, and that one is genuinely module-relative. Every other worker or service-worker string reference keeps its exact call expression with specifier: null and stays unresolved, matching the existing worker_threads string handling. This is one representation for "base not established", not a second one. The docs worker bullet states the rule.

I considered keeping the declared string and marking its base as unknown. That needs a new field in the strict worker transfer schema and the graph contract, so I've left it out of this fix.

Validation

The issue's scenario, as a new public-CLI test, keeps string Worker paths unresolved because the document base is unknown. index.html loads scripts/main.js, and decoys exist at both worker.js and scripts/worker.js / scripts/sw.js. Both the worker and the service worker keep their expression, report resolved_path: null, and have no maps_to edge. The test fails on main; I checked by restoring main's producer and rebuilding.

Real applications: across Discord, Notion, Signal, Claude, Tabby and VS Code out/, all 21 worker and service-worker references are already unresolved (dynamic arguments, data: URLs, path.join). None used a plain string specifier, so nothing changes for them. Discord CLI output is identical: normalized JSON, 108,108,885 B both, 14.9 s vs 14.3 s. Output size is unchanged for these apps.

Tests that encoded script-relative string resolution, updated:

  • javascriptWorkerUrlCli.test.ts: the nested/literal.mjs string case moved out of the module-relative test. "", ?cache=1 and #worker Worker strings now assert the retained expression.
  • applicationWorkflowCli.test.ts: the percent-decoded worker case uses new URL("./worker%20file.js", import.meta.url), keeping its decoding coverage. The service worker is asserted unresolved.
  • javascriptSourceMapLocations.test.ts, javascriptRuntimeReconciliation fixture, javascriptApplicationTemplateLiterals.test.ts: the worker uses the module-relative form, so source-map, runtime-matching and template-literal identity coverage is kept.
  • javascriptApplicationEmptyLiterals.test.ts, javascriptStaticAnalysisCalleeBoundary.test.ts: assert the expression-keyed identity.

All 7 worker-related boundary/acceptance files pass (125 tests), as do 158 JavaScript/domain test files (2,966 tests), npm run check:fast and npm run docs:check.

Behavior change to note: apps that used plain string workers previously got a (wrong) resolved worker mapping. They now get an unresolved worker node with its expression.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/3797 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/15/2026 **Status:** ✅ Merged **Merged:** 10/15/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/3309-worker-document-base` --- ### 📝 Commits (1) - [`7d0cb7a`](https://github.com/morluto/rea/commit/7d0cb7a49ccc59ae3d8cf410fa7055acae5b0bd3) fix(javascript): keep string Worker paths unresolved without a document base ### 📊 Changes **9 files changed** (+119 additions, -51 deletions) <details> <summary>View changed files</summary> 📝 `docs/javascript-artifact-reconstruction.md` (+4 -1) 📝 `src/domain/javascript/javascriptStaticAnalysisCalleeBoundary.test.ts` (+3 -2) 📝 `src/domain/javascript/javascriptStaticAnalysisCalls.ts` (+12 -6) 📝 `tests/acceptance/applications/applicationWorkflowCli.test.ts` (+34 -20) 📝 `tests/acceptance/applications/javascriptWorkerUrlCli.test.ts` (+51 -9) 📝 `tests/boundary/filesystem/javascript-applications/javascriptApplicationEmptyLiterals.test.ts` (+3 -1) 📝 `tests/boundary/filesystem/javascript-applications/javascriptApplicationTemplateLiterals.test.ts` (+1 -1) 📝 `tests/boundary/filesystem/javascriptSourceMapLocations.test.ts` (+10 -10) 📝 `tests/fixtures/javascriptRuntimeReconciliation.ts` (+1 -1) </details> ### 📄 Description Fixes #3309 ## Root cause `inspectCall` (`javascriptStaticAnalysisCalls.ts`) emitted the first string argument of a browser `new Worker("./worker.js")` and of `navigator.serviceWorker.register("./sw.js")` as the reference specifier. The graph then resolved it as a URL relative to the **calling script**. Neither loader uses that base: - A browser resolves both against the **document** base URL. In the issue's fixture, `index.html` loads `scripts/main.js`, and the browser fetched `worker.js`, not `scripts/worker.js`. - A Node `worker_threads` string resolves against `process.cwd()`. This producer already dropped the specifier for that case for the same reason. So REA recorded a resolved, high-confidence mapping to the wrong file. ## Change Only `new Worker(new URL(path, import.meta.url))` produces a specifier, and that one is genuinely module-relative. Every other worker or service-worker string reference keeps its exact call expression with `specifier: null` and stays unresolved, matching the existing `worker_threads` string handling. This is one representation for "base not established", not a second one. The docs worker bullet states the rule. I considered keeping the declared string and marking its base as unknown. That needs a new field in the strict worker transfer schema and the graph contract, so I've left it out of this fix. ## Validation **The issue's scenario,** as a new public-CLI test, `keeps string Worker paths unresolved because the document base is unknown`. `index.html` loads `scripts/main.js`, and decoys exist at both `worker.js` and `scripts/worker.js` / `scripts/sw.js`. Both the worker and the service worker keep their expression, report `resolved_path: null`, and have no `maps_to` edge. The test **fails on `main`**; I checked by restoring main's producer and rebuilding. **Real applications:** across Discord, Notion, Signal, Claude, Tabby and VS Code `out/`, all 21 worker and service-worker references are already unresolved (dynamic arguments, `data:` URLs, `path.join`). None used a plain string specifier, so nothing changes for them. Discord CLI output is identical: normalized JSON, 108,108,885 B both, 14.9 s vs 14.3 s. Output size is unchanged for these apps. **Tests that encoded script-relative string resolution, updated:** - `javascriptWorkerUrlCli.test.ts`: the `nested/literal.mjs` string case moved out of the module-relative test. `""`, `?cache=1` and `#worker` Worker strings now assert the retained expression. - `applicationWorkflowCli.test.ts`: the percent-decoded worker case uses `new URL("./worker%20file.js", import.meta.url)`, keeping its decoding coverage. The service worker is asserted unresolved. - `javascriptSourceMapLocations.test.ts`, `javascriptRuntimeReconciliation` fixture, `javascriptApplicationTemplateLiterals.test.ts`: the worker uses the module-relative form, so source-map, runtime-matching and template-literal identity coverage is kept. - `javascriptApplicationEmptyLiterals.test.ts`, `javascriptStaticAnalysisCalleeBoundary.test.ts`: assert the expression-keyed identity. All 7 worker-related boundary/acceptance files pass (125 tests), as do 158 JavaScript/domain test files (2,966 tests), `npm run check:fast` and `npm run docs:check`. **Behavior change to note:** apps that used plain string workers previously got a (wrong) resolved worker mapping. They now get an unresolved worker node with its expression. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:10:19 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#5905
No description provided.