v8 stack 2/5: TurboModule spec and the JS surface - #24
Closed
dmurphy5 wants to merge 1 commit into
Closed
Conversation
Adds src/NativeRNFileUploader.ts, the codegen spec both platforms generate from. Six methods and five event emitters replace the hand-rolled NativeModules lookup and the DeviceEventEmitter string channels. Variant payloads (upload options, terminal events, snapshots) are typed as UnsafeObject in the spec because codegen cannot model Partial<>, intersections, or index signatures. The precise contracts live in src/types.ts and are applied at the public boundary in src/index.ts, so callers still get full types. Three new methods make terminal outcomes recoverable rather than fire-and- forget: getUnacknowledgedEvents/ackEvents read and drain the native journal, and getAllUploads enumerates what the OS still knows about. Terminal events carry eventId, type, timestamp, and — where the platform has them — responseCode, responseBody, and responseHeaders. Two behavior fixes on the JS side. A scoped addListener now drops events it cannot attribute instead of failing open and delivering another upload's event, and the iOS keep-alive hack that called native addListener on import is gone, since the codegen emitters need no such priming. Adds jest with the first test suite for the JS layer, and wires it into CI and the pre-commit hook. This PR lands the contract only. The Android and iOS implementations that back getUnacknowledgedEvents, ackEvents, getAllUploads, and the codegen emitters arrive in the next two PRs in this stack. BREAKING CHANGE: requires the New Architecture. `completed` now fires only for 2xx or a request's acceptStatus; other HTTP responses arrive as `error` with errorKind 'http' and the response attached. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The stack
Five PRs, each based on the one before it. This is 2/5.
ai.openspacerenamemaster#22 stays open and untouched as the single-diff view of the same change.
Its tree and this stack's tip are byte-identical (tree
f8404b0), so mergingeither one produces exactly the same
master. Review whichever is easier tofollow; merge one and close the other.
Defines the TurboModule spec and the v8 JS surface. This PR lands the contract
— the natives that back it arrive in the next two PRs in the stack.
What's in it
src/NativeRNFileUploader.tsis the codegen spec both platforms generate from.Six methods and five event emitters replace the hand-rolled
NativeModuleslookup and the
DeviceEventEmitterstring channels.Variant payloads (upload options, terminal events, snapshots) are typed as
UnsafeObjectin the spec because codegen can't modelPartial<>,intersections, or index signatures. The precise contracts live in
src/types.tsand are applied at the public boundary in
src/index.ts, so callers still getfull types — the looseness stops at the codegen layer.
Three new methods make terminal outcomes recoverable rather than
fire-and-forget:
getUnacknowledgedEvents/ackEventsread and drain the nativejournal, and
getAllUploadsenumerates what the OS still knows about. Terminalevents carry
eventId,type,timestamp, and — where the platform has them —responseCode,responseBody,responseHeaders.Two behavior fixes worth a look:
addListenernow drops events it can't attribute, instead of failingopen and delivering another upload's event to your handler.
addListeneron import is gone;the codegen emitters need no priming.
Adds jest and the first JS test suite, wired into CI and the pre-commit hook.
Reviewing this in the stack
The JS here calls
TurboModuleRegistry.getEnforcing, so the new methods have noimplementation until PRs 3 and 4 land. That's inherent to slicing this way —
codegen reads the spec, so the spec has to come before the natives that extend
it. The stack is runtime-complete at its tip.
Verified
yarn typecheck,yarn lint:ci, andyarn test(7/7) pass on this commit.Breaking
Requires the New Architecture.
completednow fires only for 2xx or a request'sacceptStatus; other HTTP responses arrive aserrorwitherrorKind: 'http'and the response attached.