Stop using Iterator helpers so core-js can be removed
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 15/100
- Issue type
- Refactor
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript, vite
- Domain
- build-system, frontend, tooling
Research direction
Start with prerequisite issue #2181, then inspect packages/graph-explorer/tsconfig.json, the listed TypeScript call sites, src/utils/createErrorDetails.ts, index.tsx, package.json, pnpm-lock.yaml, and vite.config.ts. Run pnpm check:types while narrowing the lib setting, then verify pnpm checks, pnpm test, and pnpm build. Done means no iterator helpers or core-js remain, the browser target is explicit, and the build contains no Iterator polyfill.
Written by the indexing model from the issue text.
Description
Iterator helpers (Iterator.prototype.map/filter/toArray, Iterator.from) are Baseline newly available as of March 2025, so they will not reach Baseline Widely Available until roughly September 2027. Vite's default build.target is baseline-widely-available, which in Vite 8 resolves to ['chrome111', 'edge111', 'firefox114', 'safari16.4', 'ios16.4'], and Vite only handles syntax transforms and does not cover polyfills. That is why packages/graph-explorer/src/index.tsx imports a core-js polyfill, and why core-js is a production dependency (#2130, #2167).
The usage does not earn that cost. Across 30 files (28 source, 2 test) only four helpers appear, and .toArray() accounts for the large majority. Every call site is drained eagerly, so nothing relies on laziness.
Work
Rewrite the call sites to natively supported equivalents:
m.values().toArray()becomesArray.from(m.values())m.values().map(f).toArray()becomesArray.from(m.values(), f), with no intermediate arraym.values().filter(p)becomes[...m.values()].filter(p)
The 7 sites that do not end in .toArray() are each immediately consumed by new Map(...), Promise.all(...), or a similar iterable consumer, so they rewrite the same way: connector/sparql/fetchNeighbors/index.ts:39 and :53, connector/sparql/neighborCounts.ts:268, core/StateProvider/neighbors.ts:157, modules/GraphViewer/GraphViewer.tsx:95 and :98.
Then remove the polyfill import from index.tsx and remove core-js from packages/graph-explorer/package.json and pnpm-lock.yaml.
Approach
Narrowing the TypeScript lib is the instrument. packages/graph-explorer/tsconfig.json currently sets lib: ["ESNext", "DOM", "DOM.Iterable"], which is the same class of mistake as the devDependencies entry was: it claims a runtime we do not ship to. Under ESNext a .take() call typechecks clean, so nothing catches a new helper today.
Measured by editing the lib value and running pnpm check:types:
lib |
Errors | Catches |
|---|---|---|
ESNext (today) |
0 | nothing |
ES2025 |
12 | Error.isError only; iterator helpers still allowed |
ES2024 |
185 | iterator helpers and Error.isError |
ES2023 |
187 | 2 more, from features we do not need to give up |
So the value is lib: ["ES2024", "DOM", "DOM.Iterable"]. It reports every call site by file and line from one command, in-editor, with no test run: 75 x TS2339 (Property 'toArray' does not exist on type 'MapIterator<Vertex>'), plus 45 x TS7006 and 21 x TS7031 where callbacks lose their inferred parameter types downstream.
- Land #2181 first. It is a separate bug and a hard prerequisite, not optional sequencing.
- Narrow
libtoES2024. Also decide onpackages/shared, which sets nolib, inheritstarget: "esnext"fromtsconfig.base.json, and runs in the browser through the@shared/*path mapping.graph-explorer-proxy-serveris Node-only and can keepESNext. - Run
pnpm check:typesand rewrite until green. - Remove the polyfill import from
index.tsxand removecore-jsfrompackages/graph-explorer/package.jsonandpnpm-lock.yaml. - Pin the build target in
packages/graph-explorer/vite.config.ts:build: { target: "baseline-widely-available" }. This matches Vite 8's current default, so nothing changes behaviourally. It belongs in this issue becauseimport "core-js/full/iterator"is what currently documents, implicitly, that we support browsers without native iterator helpers. Once that import is gone,build.targetis the only written record of the browser floor, and Vite fixes its Baseline snapshot per major release, so a Vite 9 upgrade would otherwise raise the floor silently.
Keep the narrowed lib afterwards. It is what stops a helper from being reintroduced, and it is the only tool that can: oxlint has no no-restricted-syntax, and no-restricted-properties only matches a static object name, so it would catch Iterator.from but not m.values().take(3). One caveat, no lib value means "Baseline Widely Available", so ES2024 closes the iterator-helper hole without making the config a precise statement of the browser floor.
Why #2181 blocks this
Narrowing lib turns Error.isError into a compile error. 15 of the 185 errors are that one call at src/utils/createErrorDetails.ts:52 and :66: 2 x TS2550 for the method plus 13 x TS18046 where error and cause stay unknown once the type guard stops narrowing. pnpm check:types cannot pass until #2181 lands, so start there.
Performance
The rewrite is faster, not slower. Benchmarked on Node 26, whole-loop times, lower is better:
| n | [...m.values()].filter() |
Array.from(...).filter() |
native iterator .filter().toArray() |
core-js .filter().toArray() |
|---|---|---|---|---|
| 10 | 3.0 ms | 3.6 ms | 3.1x slower | 30.5x slower |
| 100 | 4.1 ms | 1.6 ms | 1.7x | 17.0x |
| 1,000 | 3.5 ms | 1.6 ms | 1.8x | 19.9x |
| 20,000 | 3.8 ms | 2.1 ms | 1.8x | 17.4x |
Iterator helpers are slower than array methods even natively, because the iterator protocol costs a next() call and an object allocation per element while V8 heavily optimizes array methods. The comparison that matters is against the polyfill we actually ship, which is the 17-30x column.
Array.from beat spread at every size above 10, so prefer it over spread in the rewrites. That makes the one .filter() site at connector/sparql/fetchNeighbors/index.ts:53 a paren move:
// from
Array.from(verticesMap.values().filter(v => v.id !== req.resourceURI))
// to
Array.from(verticesMap.values()).filter(v => v.id !== req.resourceURI)
Acceptance
- No
Iterator.prototypehelper orIterator.fromcall remains inpackages/ core-jsappears nowhere inpackages/graph-explorer/package.jsonor the lockfile importerpnpm checksandpnpm testpasspnpm buildsucceeds anddistno longer contains the Iterator polyfill (about 22 KB gzipped today, 13 KB after the narrowing work)build.targetis set explicitly inpackages/graph-explorer/vite.config.tscore-jsis absent from the built image'snode_modules, removing the 1.3 MB / 3,728 files the--prodinstall currently keeps
Related Issues
- Blocked by #2181
- Related to #2130, #2157, #2167
[!IMPORTANT]
Internal only — this issue is maintained by the core team and is not accepting external contributions.
- Dominant language
- TypeScript
- Stars
- 481
- Forks
- 110
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 9
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from aws/graph-explorer
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
aws/graph-explorer#2199 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
aws/graph-explorer#2196 · 2 comments ·
-
help wanted needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
aws/graph-explorer#2060 ·
-
help wanted reliability usability
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
aws/graph-explorer#1977 · 2 comments ·
-
documentation usability
Difficulty 2/5 1-2 days Newbie friendliness 68/100
aws/graph-explorer#1719 ·
All issues in aws/graph-explorer
Similar issues
-
comp/dashboard P3 type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
NousResearch/hermes-agent#117722 ·
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 76/100
-
code-quality refactoring
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
github/gh-aw-firewall#8816 ·
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·