Skip to content

Commit 3ca7e78

Browse files
authored
fix(gzip): do not decompress gzip file if it already decompressed (#39)
1 parent 5d0e818 commit 3ca7e78

1 file changed

Lines changed: 30 additions & 36 deletions

File tree

src/core/gzipBundle.js

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import untar from "js-untar";
22
import { stripLeadingDotSlash } from "./stringOps.js";
3-
import { createFuture } from "./future.js";
43
import { MODULE_JS_FILE_EXTENSION, WASM_FILE_EXTENSION } from "./constants.js";
54

65
/**
@@ -17,23 +16,25 @@ export function isGzipBundle(url) {
1716
* @param {string} url
1817
* @returns {Promise<ArrayBuffer>} The decompressed tar archive contents from the gzip bundle.
1918
*/
20-
export function fetchGzipBundle(url) {
21-
const { promise, resolve, reject } = createFuture();
22-
fetch(url).then((response) => {
23-
if (response.ok) {
24-
const decompressedStream = response.body.pipeThrough(new DecompressionStream('gzip'));
25-
const decompressionResponse = new Response(decompressedStream);
26-
decompressionResponse
27-
.blob()
28-
.then((blob) => blob.arrayBuffer())
29-
.then(resolve)
30-
.catch(reject);
31-
}
32-
else {
33-
reject(new Error(`Could not fetch gzip bundle from ${url} - response status: ${response.status}`));
34-
}
35-
}).catch(reject);
36-
return promise;
19+
export async function fetchGzipBundle(url) {
20+
const response = await fetch(url);
21+
if (!response.ok) {
22+
throw new Error(`Could not fetch gzip bundle from ${url} - response status: ${response.status}`);
23+
}
24+
25+
const arrayBuffer = await response.arrayBuffer();
26+
const uint8View = new Uint8Array(arrayBuffer);
27+
28+
// Check if it's already decompressed by the browser/server.
29+
// Gzip magic number: 0x1F 0x8B.
30+
if (uint8View.length >= 2 && uint8View[0] === 0x1F && uint8View[1] === 0x8B) {
31+
// If it is gzipped, decompress it using DecompressionStream.
32+
const decompressedStream = new Response(arrayBuffer).body.pipeThrough(new DecompressionStream('gzip'));
33+
return await new Response(decompressedStream).arrayBuffer();
34+
}
35+
36+
// Not gzipped (already decompressed by server/browser).
37+
return arrayBuffer;
3738
}
3839

3940
/**
@@ -43,22 +44,15 @@ export function fetchGzipBundle(url) {
4344
* @param {string} wasmBaseName
4445
* @returns {Promise<{js: {name: string, buffer: ArrayBufferLike}, wasm: {name: string, buffer: ArrayBufferLike}}>}
4546
*/
46-
export function extractFilesFromGzipBundle(contents, config, wasmBaseName) {
47-
const { promise, resolve, reject } = createFuture();
48-
untar(contents)
49-
.then((files) => {
50-
const execModeSuffix = config?.exec === "async" ? "Async" : "";
51-
const jsFileMatch = `${wasmBaseName}WebAssembly${execModeSuffix}${MODULE_JS_FILE_EXTENSION}`;
52-
const wasmFileMatch = `${wasmBaseName}WebAssembly${execModeSuffix}${WASM_FILE_EXTENSION}`;
53-
const jsFile = files.find((file) => stripLeadingDotSlash(file.name) === jsFileMatch);
54-
const wasmFile = files.find((file) => stripLeadingDotSlash(file.name) === wasmFileMatch);
55-
if (jsFile === undefined || wasmFile === undefined) {
56-
reject(new Error(`Could not find expected files ${jsFileMatch} and ${wasmFileMatch} in the gzip bundle`));
57-
}
58-
else {
59-
resolve({ js: jsFile, wasm: wasmFile });
60-
}
61-
})
62-
.catch(reject);
63-
return promise;
47+
export async function extractFilesFromGzipBundle(contents, config, wasmBaseName) {
48+
const files = await untar(contents);
49+
const execModeSuffix = config?.exec === "async" ? "Async" : "";
50+
const jsFileMatch = `${wasmBaseName}WebAssembly${execModeSuffix}${MODULE_JS_FILE_EXTENSION}`;
51+
const wasmFileMatch = `${wasmBaseName}WebAssembly${execModeSuffix}${WASM_FILE_EXTENSION}`;
52+
const jsFile = files.find((file) => stripLeadingDotSlash(file.name) === jsFileMatch);
53+
const wasmFile = files.find((file) => stripLeadingDotSlash(file.name) === wasmFileMatch);
54+
if (jsFile === undefined || wasmFile === undefined) {
55+
throw new Error(`Could not find expected files ${jsFileMatch} and ${wasmFileMatch} in the gzip bundle`);
56+
}
57+
return { js: jsFile, wasm: wasmFile };
6458
}

0 commit comments

Comments
 (0)