Skip to content

decodeRemoteZip drops range-filtered entries due to path identity comparison #4109

Description

@chubes4

Description

decodeRemoteZip() emits zero files when a predicate selects entries from a range-capable ZIP larger than 1 MB.

The range path parses the central directory and local file headers into separate Uint8Array instances, then compares their paths by object identity:

requestedPaths.find((entry) => entry.path === file.path)

Equal byte sequences are distinct objects, so every requested file is discarded.

Reproduction

With @php-wasm/stream-compression@3.1.45:

import { decodeRemoteZip } from '@php-wasm/stream-compression';

const decoder = new TextDecoder();
const stream = await decodeRemoteZip(
	'https://wordpress.org/latest.zip',
	(entry) => /\.php$/.test(decoder.decode(entry.path))
);
const reader = stream.getReader();
let count = 0;

while (!(await reader.read()).done) count++;
console.log(count); // 0

The same archive contains thousands of PHP files. decodeZip() over the complete response emits them correctly.

Expected behavior

The range-backed stream compares path bytes by value and emits every selected entry. A deterministic unit test should exercise the range path with distinct but equal path arrays.

Impact

Callers cannot use range-filtered extraction to avoid downloading and inflating unrelated ZIP entries. This blocks memory- and CPU-bounded runtimes such as Cloudflare Workers from materializing only WordPress server files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions