Skip to content

refactor(fetch): make Body extend platform Blob and implement Stream #50

Description

@medz

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions