Context
PR #49 fixes the immediate feature gap: Body did not expose a public byte-length property. That PR should stay scoped to the missing Body.size feature.
This issue tracks the follow-up refactor: improve the Body public surface, compatibility, and implementation shape by making Body inherit the conditionally imported platform Blob implementation while still behaving as a Stream<Uint8List>.
Target Shape
The intended direction is roughly:
class Body extends Blob with Stream<Uint8List> implements Stream<Uint8List> {
// Fetch body helpers and bodyUsed semantics live here.
}
Blob should come from the existing conditional import/export path so Body inherits the platform-specific Blob behavior on native, dart:io, and js targets instead of being hard-wired to only blob.native.dart.
Problem
Body currently maintains too much wrapper logic for standard body inputs that can be normalized by Blob directly. That overlaps with Blob/Block behavior and keeps the public API narrower than a Blob-like body value should be.
As a result, Body is less ergonomic and less compatible in user code that expects Blob-style byte container behavior, and it carries custom implementation paths that need to stay aligned with platform Blob behavior manually.
Proposal
Refactor Body so it:
- extends the conditionally imported platform
Blob implementation as the reusable byte-container base;
- implements
Stream<Uint8List> for direct stream compatibility;
- keeps Fetch-style helpers such as
bytes(), text(), json(), blob(), clone(), and bodyUsed on Body;
- lets Blob-derived properties such as
size, type, and slice() come from the inherited Blob surface where possible;
- keeps
factory Body([BodyInit? init]) minimal by routing ordinary Blob-compatible values through Blob initialization instead of duplicating per-type cases;
- keeps only Fetch-specific branches such as
Body, FormData, and arbitrary stream-backed bodies in Body itself;
- keeps arbitrary stream-backed bodies explicit if they cannot be represented as a known-size Blob without eager materialization.
Acceptance Criteria
Body extends the conditionally imported platform Blob implementation and implements Stream<Uint8List>.
Body exposes a more Blob-compatible public surface for direct user code.
- Existing
Request and Response body APIs continue to work across native, dart:io, and js paths.
- Fetch-style single-consume behavior and
bodyUsed semantics are preserved where applicable.
- Tests cover the inherited Blob surface, stream interface behavior, and any remaining stream-backed edge cases.
Follow-up to #49.
Context
PR #49 fixes the immediate feature gap:
Bodydid not expose a public byte-length property. That PR should stay scoped to the missingBody.sizefeature.This issue tracks the follow-up refactor: improve the
Bodypublic surface, compatibility, and implementation shape by makingBodyinherit the conditionally imported platformBlobimplementation while still behaving as aStream<Uint8List>.Target Shape
The intended direction is roughly:
Blobshould come from the existing conditional import/export path soBodyinherits the platform-specific Blob behavior on native,dart:io, and js targets instead of being hard-wired to onlyblob.native.dart.Problem
Bodycurrently maintains too much wrapper logic for standard body inputs that can be normalized byBlobdirectly. That overlaps withBlob/Blockbehavior and keeps the public API narrower than a Blob-like body value should be.As a result,
Bodyis less ergonomic and less compatible in user code that expects Blob-style byte container behavior, and it carries custom implementation paths that need to stay aligned with platformBlobbehavior manually.Proposal
Refactor
Bodyso it:Blobimplementation as the reusable byte-container base;Stream<Uint8List>for direct stream compatibility;bytes(),text(),json(),blob(),clone(), andbodyUsedonBody;size,type, andslice()come from the inherited Blob surface where possible;factory Body([BodyInit? init])minimal by routing ordinary Blob-compatible values through Blob initialization instead of duplicating per-type cases;Body,FormData, and arbitrary stream-backed bodies inBodyitself;Acceptance Criteria
Bodyextends the conditionally imported platformBlobimplementation and implementsStream<Uint8List>.Bodyexposes a more Blob-compatible public surface for direct user code.RequestandResponsebody APIs continue to work across native,dart:io, and js paths.bodyUsedsemantics are preserved where applicable.Follow-up to #49.