Repository navigation
fix(shared): make await using work without a native Symbol.asyncDispose - #156
Conversation
…se fallback
On runtimes without a native Symbol.asyncDispose (Hermes/React Native,
older Safari or Node), AsyncIteratorClass registered its dispose method
under Symbol.for('asyncDispose'). esbuild's `__using`, Babel's `usingCtx`
and core-js all look it up under Symbol.for('Symbol.asyncDispose'), so
`await using` on an event-stream body threw "Object not disposable" and
its cleanup never ran.
Switch the fallback to the conventional key (still preferring the native
symbol), correct the JSDoc, and cover the fallback path with a test so the
v8 ignore markers can go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NRRM1bujEJiPEv7FbiLXDr
Take onTestFinished from the test context like the rest of the repo, drop a comment that repeats the one in iterator.ts, and call the dispose method directly instead of checking its type and invoking it via .call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NRRM1bujEJiPEv7FbiLXDr
await using work without a native Symbol.asyncDispose
@standard-server/aws-lambda
@standard-server/core
@standard-server/fastify
@standard-server/fetch
@standard-server/node
@standard-server/peer
@standard-server/shared
commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Merging this PR will not alter performance
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — initial review of PR #156 (8a8e59b against base 6c1cc3b).
- Fallback symbol key corrected (
packages/shared/src/iterator.ts) — the no-native-symbol fallback now usesSymbol.for('Symbol.asyncDispose')instead ofSymbol.for('asyncDispose'), matching the key esbuild's__knownSymbol('asyncDispose'), Babel'susingCtx, and core-js'swell-known-symbolpolyfill all use. - Comment/JSDoc updated — the stale "available in esnext" note is replaced with an accurate native-vs-fallback description; the two
/* v8 ignore */markers are dropped now that the fallback branch is exercised. - Regression test added (
packages/shared/src/iterator.test.ts) — stubs aSymbolproxy whoseasyncDisposeisundefined, re-imports the module, and asserts disposal dispatches underSymbol.for('Symbol.asyncDispose')with{ kind: 'cancelled' }.
Verified locally against head 8a8e59b: packages/shared/src/iterator.test.ts passes (22 tests), iterator.ts reports 100% line/branch/function coverage, and pnpm run check (sherif, oxlint, oxfmt, tsc) is clean. I confirmed the fallback key against the actual upstream sources — esbuild's __using uses __knownSymbol('asyncDispose') → Symbol.for('Symbol.asyncDispose'), Babel's usingCtx uses Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose"), and core-js resolves well-known symbols to Symbol.for('Symbol.' + name) without native support. This closes a real interop gap for await using on runtimes without a native Symbol.asyncDispose, while leaving the native path unchanged.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Summary
Updated the fallback symbol key for
asyncDisposeto useSymbol.for('Symbol.asyncDispose')instead ofSymbol.for('asyncDispose'), aligning with the standard used by esbuild, Babel, and core-js.Key Changes
Symbol.for('asyncDispose')toSymbol.for('Symbol.asyncDispose')to match ecosystem conventionsSymbol.asyncDisposeis not natively availableImplementation Details
The fallback symbol is now consistent with how other major JavaScript tooling and libraries handle the
asyncDisposesymbol on runtimes that don't have native support. The test uses a Proxy to simulate an environment whereSymbol.asyncDisposeis undefined, ensuring the fallback mechanism works correctly and calls cleanup with the expected{ kind: 'cancelled' }parameter.https://claude.ai/code/session_01NRRM1bujEJiPEv7FbiLXDr