fix(types): accept ArrayBufferView for byte-array struct inputs by PedroRosalba · Pull Request #7843 · cloudflare/workerd · GitHub
Skip to content

fix(types): accept ArrayBufferView for byte-array struct inputs - #7843

Open
PedroRosalba wants to merge 3 commits into
cloudflare:mainfrom
PedroRosalba:fix/bytes-input-arraybufferview
Open

PedroRosalba wants to merge 3 commits into
cloudflare:mainfrom
PedroRosalba:fix/bytes-input-arraybufferview

Conversation

@PedroRosalba

Copy link
Copy Markdown

Problem

Input struct fields of C++ type kj::Array<byte> are emitted by the type generator as plain ArrayBuffer (types/src/generator/type.ts), but JSG's unwrap for that type accepts any ArrayBuffer, ArrayBufferView or SharedArrayBuffer (src/workerd/jsg/value.h, tryUnwrap(kj::Array<byte>*)). Since TypeScript 5.7 a typed array is no longer assignable to ArrayBuffer, so code that the runtime accepts, and that the repo's own runtime tests already exercise, fails to compile:

  • WorkerLoaderModule.data: { data: new Uint8Array(...) } → TS2740 (its sibling wasm was already widened by hand in Accept WebAssembly.Module values in the dynamic worker loader #6997).
  • R2 ssecKey on R2GetOptions, R2PutOptions, R2MultipartOptions, R2UploadPartOptions: the 32-byte Uint8Array key that r2-test.js passes → TS2322. The checksum fields declared next to it already accept ArrayBuffer | ArrayBufferView.
  • AnalyticsEngineDataPoint.blobs / .indexes: writeDataPoint({ blobs: [new Uint8Array(...)] }) → TS2322.

Fix

One commit per API, each a hand-written JSG_STRUCT_TS_OVERRIDE widening the field to ArrayBuffer | ArrayBufferView (same shape as WorkerLoaderModule.wasm), the four regenerated snapshot files, and a type test. Types only; no runtime change.

Tests

  • bazel test //types:test/types/worker-loader //types:test/types/r2 //types:test/types/analytics-engine (new; each fails against the previous snapshot)
  • bazel test //src/workerd/api/tests:worker-loader-test@ //src/workerd/api/tests:r2-test@ //src/workerd/api/tests:analytics-engine-test@ (existing runtime coverage, unchanged)
  • just generate-types reproduces the snapshot edits byte for byte.
  • Also verified on the built binary that Uint8Array, DataView, a subarray() view and a SharedArrayBuffer all reach the mock backends as the expected bytes.

Tested on macOS (Apple Silicon) only.

`WorkerLoaderModule.data` is declared `jsg::Optional<kj::Array<const byte>>`,
and the JSG unwrap for that type takes any ArrayBuffer, ArrayBufferView or
SharedArrayBuffer (`src/workerd/jsg/value.h` `tryUnwrap(kj::Array<byte>*)`).
The type generator, however, emits a non-coerced struct field of
`kj::Array<byte>` as plain `ArrayBuffer` (`types/src/generator/type.ts`), so
the published type is `data?: ArrayBuffer`.

Since TypeScript 5.7 typed arrays are no longer structurally assignable to
`ArrayBuffer`, so `{ data: new Uint8Array(...) }`, which
`worker-loader-test.js` already passes at runtime, fails to compile:

  error TS2740: Type 'Uint8Array<ArrayBuffer>' is missing the following
  properties from type 'ArrayBuffer': maxByteLength, resizable, resize, ...

Widen `data` with the same hand-written override the sibling `wasm` field
received in 9cdf380 (cloudflare#6997) and add a type test.

Test: //types:test/types/worker-loader and //src/workerd/api/tests:worker-loader-test@
`ssecKey` on R2GetOptions, R2PutOptions, R2MultipartOptions and
R2UploadPartOptions is `jsg::Optional<kj::OneOf<kj::Array<byte>, kj::String>>`.
The JSG unwrap for `kj::Array<byte>` accepts any ArrayBuffer, ArrayBufferView
or SharedArrayBuffer, and `buildSsecKey()` only checks the byte length, but
the generator emits non-coerced `kj::Array<byte>` struct fields as plain
`ArrayBuffer`, so the published type is `ssecKey?: ArrayBuffer | string`.

Since TypeScript 5.7 a Uint8Array is not assignable to `ArrayBuffer`, so the
32-byte `Uint8Array` key that `r2-test.js` passes at runtime fails to
compile. The checksum fields declared next to `ssecKey` already accept
`ArrayBuffer | ArrayBufferView`; declare `ssecKey` the same way in the four
option structs and add a type test.

Test: //types:test/types/r2 and //src/workerd/api/tests:r2-test@
…and indexes

`AnalyticsEngineDataPoint.blobs` and `.indexes` are declared
`jsg::Optional<kj::Array<kj::Maybe<kj::OneOf<kj::Array<byte>, kj::String>>>>`.
The JSG unwrap for `kj::Array<byte>` accepts any ArrayBuffer, ArrayBufferView
or SharedArrayBuffer (`src/workerd/jsg/value.h` `tryUnwrap(kj::Array<byte>*)`),
and `setBlobs()` / `setIndexes()` copy whatever bytes they get, but the type
generator emits a non-coerced `kj::Array<byte>` struct field as plain
`ArrayBuffer` (`types/src/generator/type.ts`), so the published element type
is `(ArrayBuffer | string) | null`.

Since TypeScript 5.7 a typed array is not assignable to `ArrayBuffer`, so
`writeDataPoint({ blobs: [new Uint8Array(...)] })`, which the runtime accepts
and writes as the blob bytes, fails to compile:

  error TS2322: Type 'Uint8Array<ArrayBuffer>' is not assignable to type
  'string | ArrayBuffer | null'.

Widen both fields with a hand-written `JSG_STRUCT_TS_OVERRIDE`, the way
`WorkerLoaderModule.wasm` is declared, keep `doubles` generated, and add a
type test.

Test: //types:test/types/analytics-engine and //src/workerd/api/tests:analytics-engine-test@
@PedroRosalba
PedroRosalba requested review from a team as code owners October 20, 2026 10:52
@github-actions

Copy link
Copy Markdown

@clanky-the-clanker

Copy link
Copy Markdown

This pull request was not reviewed automatically because its author does not have write access to this repository. A maintainer with write access can start a review by commenting clanky review (or clanker review or @clanky-the-clanker review), optionally followed by instructions (e.g. clanky review focus on the retry logic).

@PedroRosalba

PedroRosalba commented Oct 20, 2026 •

Copy link
Copy Markdown
Author

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.

2 participants