瀏覽代碼

Update docs

Arjun Barrett 4 年之前
父節點
當前提交
71f6fd034d
共有 8 個文件被更改,包括 78 次插入20 次删除
  1. 10 1
      README.md
  2. 3 1
      demo/App.tsx
  3. 1 1
      demo/components/file-picker/index.tsx
  4. 0 1
      demo/util/workers.ts
  5. 2 1
      docs/README.md
  6. 26 0
      docs/interfaces/asyncunzipoptions.md
  7. 1 1
      package.json
  8. 35 14
      src/index.ts

+ 10 - 1
README.md

@@ -222,7 +222,7 @@ As you may have guessed, there is an asynchronous version of every method as wel
 
 
 Note that there is a significant initial overhead to using workers of about 70ms, so it's best to avoid the asynchronous API unless necessary. However, if you're compressing multiple large files at once, or the synchronous API causes the main thread to hang for too long, the callback APIs are an order of magnitude better.
 Note that there is a significant initial overhead to using workers of about 70ms, so it's best to avoid the asynchronous API unless necessary. However, if you're compressing multiple large files at once, or the synchronous API causes the main thread to hang for too long, the callback APIs are an order of magnitude better.
 ```js
 ```js
-import { gzip, zlib, AsyncGzip, zip } from 'fflate';
+import { gzip, zlib, AsyncGzip, zip, strFromU8 } from 'fflate';
 
 
 // Workers will work in almost any browser (even IE11!)
 // Workers will work in almost any browser (even IE11!)
 // However, they fail below Node v12 without the --experimental-worker
 // However, they fail below Node v12 without the --experimental-worker
@@ -291,6 +291,15 @@ gzs.terminate();
 // significant for multiple large files; less so for many small ones.
 // significant for multiple large files; less so for many small ones.
 zip({ f1: aMassiveFile, 'f2.txt': anotherMassiveFile }, (err, data) => {
 zip({ f1: aMassiveFile, 'f2.txt': anotherMassiveFile }, (err, data) => {
   // Save the ZIP file
   // Save the ZIP file
+});
+
+// unzip is the only async function without support for consume option
+// Also parallelized, so unzip is also often much faster than unzipSync
+unzip(aMassiveZIPFile, (err, unzipped) => {
+  // If the archive has data.xml, log it here
+  console.log(unzipped['data.xml']);
+  // Conversion to string
+  console.log(strFromU8(unzipped['data.xml']))
 })
 })
 ```
 ```
 
 

+ 3 - 1
demo/App.tsx

@@ -3,6 +3,7 @@ import FilePicker from './components/file-picker';
 import CodeBox from './components/code-box';
 import CodeBox from './components/code-box';
 
 
 const App: FC = () => {
 const App: FC = () => {
+  const [err, setErr] = useState<string | Error | null>(null);
   const [files, setFiles] = useState<File[] | null>([]);
   const [files, setFiles] = useState<File[] | null>([]);
   const cbRef = useRef<HTMLDivElement>(null);
   const cbRef = useRef<HTMLDivElement>(null);
   useEffect(() => {
   useEffect(() => {
@@ -69,7 +70,8 @@ const App: FC = () => {
           flexDirection: 'column',
           flexDirection: 'column',
           marginBottom: '2vh'
           marginBottom: '2vh'
         }}>
         }}>
-          <FilePicker allowDirs onFiles={setFiles} onError={console.log} onDrag={() => {}}>
+          <FilePicker allowDirs onFiles={setFiles} onError={setErr} onDrag={() => {}}>
+            {err && <div style={{ color: 'red' }}>Error: {err}</div>}
             <div>{files ? ((files.length || 'No') + ' file' + (files.length == 1 ? '' : 's') + ' selected') : 'Loading...'}</div>
             <div>{files ? ((files.length || 'No') + ' file' + (files.length == 1 ? '' : 's') + ' selected') : 'Loading...'}</div>
             <br />
             <br />
           </FilePicker>
           </FilePicker>

+ 1 - 1
demo/components/file-picker/index.tsx

@@ -41,7 +41,7 @@ const FilePicker: FC<{
   onDrag(on: boolean): void;
   onDrag(on: boolean): void;
   onError(err: string | Error): void;
   onError(err: string | Error): void;
   allowDirs: boolean;
   allowDirs: boolean;
-} & HTMLAttributes<HTMLDivElement>
+} & Omit<HTMLAttributes<HTMLDivElement>, 'onError'>
 > = ({ onFiles, onDrag, onError, style, allowDirs, children, ...props }) => {
 > = ({ onFiles, onDrag, onError, style, allowDirs, children, ...props }) => {
   const inputRef = useRef<HTMLInputElement>(null);
   const inputRef = useRef<HTMLInputElement>(null);
   const dirInputRef = useRef<HTMLInputElement>(null);
   const dirInputRef = useRef<HTMLInputElement>(null);

+ 0 - 1
demo/util/workers.ts

@@ -106,7 +106,6 @@ onmessage = (ev: MessageEvent<[string, string]>) => {
         if (ev.data) {
         if (ev.data) {
           zip[ev.data[0]] = ev.data[1];
           zip[ev.data[0]] = ev.data[1];
         } else {
         } else {
-          console.log(zip);
           const buf = UZIP.encode(zip);
           const buf = UZIP.encode(zip);
           wk.postMessage([new Uint8Array(buf), true], [buf]);
           wk.postMessage([new Uint8Array(buf), true], [buf]);
         }
         }

+ 2 - 1
docs/README.md

@@ -26,6 +26,7 @@
 * [AsyncGzipOptions](interfaces/asyncgzipoptions.md)
 * [AsyncGzipOptions](interfaces/asyncgzipoptions.md)
 * [AsyncInflateOptions](interfaces/asyncinflateoptions.md)
 * [AsyncInflateOptions](interfaces/asyncinflateoptions.md)
 * [AsyncTerminable](interfaces/asyncterminable.md)
 * [AsyncTerminable](interfaces/asyncterminable.md)
+* [AsyncUnzipOptions](interfaces/asyncunzipoptions.md)
 * [AsyncUnzlibOptions](interfaces/asyncunzliboptions.md)
 * [AsyncUnzlibOptions](interfaces/asyncunzliboptions.md)
 * [AsyncZipOptions](interfaces/asynczipoptions.md)
 * [AsyncZipOptions](interfaces/asynczipoptions.md)
 * [AsyncZippable](interfaces/asynczippable.md)
 * [AsyncZippable](interfaces/asynczippable.md)
@@ -89,7 +90,7 @@ ___
 
 
 Ƭ  **AsyncZippableFile**: Uint8Array \| []
 Ƭ  **AsyncZippableFile**: Uint8Array \| []
 
 
-A file that can be used to asynchronously createa a ZIP archive
+A file that can be used to asynchronously create a ZIP archive
 
 
 ___
 ___
 
 

+ 26 - 0
docs/interfaces/asyncunzipoptions.md

@@ -0,0 +1,26 @@
+# Interface: AsyncUnzipOptions
+
+Options for asynchronously expanding a ZIP archive
+
+## Hierarchy
+
+* AsyncOptions
+
+  ↳ **AsyncUnzipOptions**
+
+## Index
+
+### Properties
+
+* [consume](asyncunzipoptions.md#consume)
+
+## Properties
+
+### consume
+
+• `Optional` **consume**: boolean
+
+*Inherited from [AsyncDeflateOptions](asyncdeflateoptions.md).[consume](asyncdeflateoptions.md#consume)*
+
+Whether or not to "consume" the source data. This will make the typed array/buffer you pass in
+unusable but will increase performance and reduce memory usage.

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "fflate",
   "name": "fflate",
-  "version": "0.3.10",
+  "version": "0.3.11",
   "description": "High performance (de)compression in an 8kB package",
   "description": "High performance (de)compression in an 8kB package",
   "main": "./lib/index.js",
   "main": "./lib/index.js",
   "module": "./esm/index.mjs",
   "module": "./esm/index.mjs",

+ 35 - 14
src/index.ts

@@ -320,7 +320,7 @@ const inflt = (dat: Uint8Array, buf?: Uint8Array, st?: InflateState) => {
   return bt == buf.length ? buf : slc(buf, 0, bt);
   return bt == buf.length ? buf : slc(buf, 0, bt);
 }
 }
 
 
-// starting at p, write the minimum number of bits that can hold v to ds
+// starting at p, write the minimum number of bits that can hold v to d
 const wbits = (d: Uint8Array, p: number, v: number) => {
 const wbits = (d: Uint8Array, p: number, v: number) => {
   v <<= p & 7;
   v <<= p & 7;
   const o = p >>> 3;
   const o = p >>> 3;
@@ -328,7 +328,7 @@ const wbits = (d: Uint8Array, p: number, v: number) => {
   d[o + 1] |= v >>> 8;
   d[o + 1] |= v >>> 8;
 }
 }
 
 
-// starting at p, write the minimum number of bits (>8) that can hold v to ds
+// starting at p, write the minimum number of bits (>8) that can hold v to d
 const wbits16 = (d: Uint8Array, p: number, v: number) => {
 const wbits16 = (d: Uint8Array, p: number, v: number) => {
   v <<= p & 7;
   v <<= p & 7;
   const o = p >>> 3;
   const o = p >>> 3;
@@ -1268,7 +1268,7 @@ export function inflate(data: Uint8Array, opts: AsyncInflateOptions, cb: FlateCa
 export function inflate(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function inflate(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function inflate(data: Uint8Array, opts: AsyncInflateOptions | FlateCallback, cb?: FlateCallback) {
 export function inflate(data: Uint8Array, opts: AsyncInflateOptions | FlateCallback, cb?: FlateCallback) {
   if (!cb) cb = opts as FlateCallback, opts = {};
   if (!cb) cb = opts as FlateCallback, opts = {};
-  if (!cb) throw 'no callback';
+  if (typeof cb != 'function') throw 'no callback';
   return cbify(data, opts as AsyncInflateOptions, [
   return cbify(data, opts as AsyncInflateOptions, [
     bInflt
     bInflt
   ], ev => pbf(inflateSync(ev.data[0], gu8(ev.data[1]))), 1, cb);
   ], ev => pbf(inflateSync(ev.data[0], gu8(ev.data[1]))), 1, cb);
@@ -1396,7 +1396,7 @@ export function gzip(data: Uint8Array, opts: AsyncGzipOptions, cb: FlateCallback
 export function gzip(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function gzip(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function gzip(data: Uint8Array, opts: AsyncGzipOptions | FlateCallback, cb?: FlateCallback) {
 export function gzip(data: Uint8Array, opts: AsyncGzipOptions | FlateCallback, cb?: FlateCallback) {
   if (!cb) cb = opts as FlateCallback, opts = {};
   if (!cb) cb = opts as FlateCallback, opts = {};
-  if (!cb) throw 'no callback';
+  if (typeof cb != 'function') throw 'no callback';
   return cbify(data, opts as AsyncGzipOptions, [
   return cbify(data, opts as AsyncGzipOptions, [
     bDflt,
     bDflt,
     gze,
     gze,
@@ -1513,7 +1513,7 @@ export function gunzip(data: Uint8Array, opts: AsyncGunzipOptions, cb: FlateCall
 export function gunzip(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function gunzip(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function gunzip(data: Uint8Array, opts: AsyncGunzipOptions | FlateCallback, cb?: FlateCallback) {
 export function gunzip(data: Uint8Array, opts: AsyncGunzipOptions | FlateCallback, cb?: FlateCallback) {
   if (!cb) cb = opts as FlateCallback, opts = {};
   if (!cb) cb = opts as FlateCallback, opts = {};
-  if (!cb) throw 'no callback';
+  if (typeof cb != 'function') throw 'no callback';
   return cbify(data, opts as AsyncGunzipOptions, [
   return cbify(data, opts as AsyncGunzipOptions, [
     bInflt,
     bInflt,
     guze,
     guze,
@@ -1638,7 +1638,7 @@ export function zlib(data: Uint8Array, opts: AsyncZlibOptions, cb: FlateCallback
 export function zlib(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function zlib(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function zlib(data: Uint8Array, opts: AsyncZlibOptions | FlateCallback, cb?: FlateCallback) {
 export function zlib(data: Uint8Array, opts: AsyncZlibOptions | FlateCallback, cb?: FlateCallback) {
   if (!cb) cb = opts as FlateCallback, opts = {};
   if (!cb) cb = opts as FlateCallback, opts = {};
-  if (!cb) throw 'no callback';
+  if (typeof cb != 'function') throw 'no callback';
   return cbify(data, opts as AsyncZlibOptions, [
   return cbify(data, opts as AsyncZlibOptions, [
     bDflt,
     bDflt,
     zle,
     zle,
@@ -1753,7 +1753,7 @@ export function unzlib(data: Uint8Array, opts: AsyncGunzipOptions, cb: FlateCall
 export function unzlib(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function unzlib(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function unzlib(data: Uint8Array, opts: AsyncGunzipOptions | FlateCallback, cb?: FlateCallback) {
 export function unzlib(data: Uint8Array, opts: AsyncGunzipOptions | FlateCallback, cb?: FlateCallback) {
   if (!cb) cb = opts as FlateCallback, opts = {};
   if (!cb) cb = opts as FlateCallback, opts = {};
-  if (!cb) throw 'no callback';
+  if (typeof cb != 'function') throw 'no callback';
   return cbify(data, opts as AsyncUnzlibOptions, [
   return cbify(data, opts as AsyncUnzlibOptions, [
     bInflt,
     bInflt,
     zule,
     zule,
@@ -1867,7 +1867,7 @@ export function decompress(data: Uint8Array, opts: AsyncInflateOptions, cb: Flat
 export function decompress(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function decompress(data: Uint8Array, cb: FlateCallback): AsyncTerminable;
 export function decompress(data: Uint8Array, opts: AsyncInflateOptions | FlateCallback, cb?: FlateCallback) {
 export function decompress(data: Uint8Array, opts: AsyncInflateOptions | FlateCallback, cb?: FlateCallback) {
   if (!cb) cb = opts as FlateCallback, opts = {};
   if (!cb) cb = opts as FlateCallback, opts = {};
-  if (!cb) throw 'no callback';
+  if (typeof cb != 'function') throw 'no callback';
   return (data[0] == 31 && data[1] == 139 && data[2] == 8)
   return (data[0] == 31 && data[1] == 139 && data[2] == 8)
     ? gunzip(data, opts as AsyncInflateOptions, cb)
     ? gunzip(data, opts as AsyncInflateOptions, cb)
     : ((data[0] & 15) != 8 || (data[0] >> 4) > 7 || ((data[0] << 8 | data[1]) % 31))
     : ((data[0] & 15) != 8 || (data[0] >> 4) > 7 || ((data[0] << 8 | data[1]) % 31))
@@ -1899,13 +1899,18 @@ export interface ZipOptions extends DeflateOptions, Pick<GzipOptions, 'mtime'> {
  */
  */
 export interface AsyncZipOptions extends AsyncDeflateOptions, Pick<AsyncGzipOptions, 'mtime'> {}
 export interface AsyncZipOptions extends AsyncDeflateOptions, Pick<AsyncGzipOptions, 'mtime'> {}
 
 
+/**
+ * Options for asynchronously expanding a ZIP archive
+ */
+export interface AsyncUnzipOptions extends AsyncOptions {}
+
 /**
 /**
  * A file that can be used to create a ZIP archive
  * A file that can be used to create a ZIP archive
  */
  */
 export type ZippableFile = Uint8Array | [Uint8Array, ZipOptions];
 export type ZippableFile = Uint8Array | [Uint8Array, ZipOptions];
 
 
 /**
 /**
- * A file that can be used to asynchronously createa a ZIP archive
+ * A file that can be used to asynchronously create a ZIP archive
  */
  */
 export type AsyncZippableFile = Uint8Array | [Uint8Array, AsyncZipOptions];
 export type AsyncZippableFile = Uint8Array | [Uint8Array, AsyncZipOptions];
 
 
@@ -2077,6 +2082,7 @@ export function zip(data: AsyncZippable, opts: AsyncZipOptions, cb: FlateCallbac
 export function zip(data: AsyncZippable, cb: FlateCallback): AsyncTerminable;
 export function zip(data: AsyncZippable, cb: FlateCallback): AsyncTerminable;
 export function zip(data: AsyncZippable, opts: AsyncZipOptions | FlateCallback, cb?: FlateCallback) {
 export function zip(data: AsyncZippable, opts: AsyncZipOptions | FlateCallback, cb?: FlateCallback) {
   if (!cb) cb = opts as FlateCallback, opts = {};
   if (!cb) cb = opts as FlateCallback, opts = {};
+  if (typeof cb != 'function') throw 'no callback';
   const r: FlatZippable<true> = {};
   const r: FlatZippable<true> = {};
   fltn(data, '', r, opts as AsyncZipOptions);
   fltn(data, '', r, opts as AsyncZipOptions);
   const k = Object.keys(r);
   const k = Object.keys(r);
@@ -2106,7 +2112,6 @@ export function zip(data: AsyncZippable, opts: AsyncZipOptions | FlateCallback,
     c.p(file);
     c.p(file);
     const n = strToU8(fn), s = n.length;
     const n = strToU8(fn), s = n.length;
     const t = p.level == 0 ? 0 : 8;
     const t = p.level == 0 ? 0 : 8;
-    if (n.length > 65535) throw 'filename too long';
     const cbl: FlateCallback = (e, d) => {
     const cbl: FlateCallback = (e, d) => {
       if (e) {
       if (e) {
         tAll();
         tAll();
@@ -2127,9 +2132,15 @@ export function zip(data: AsyncZippable, opts: AsyncZipOptions | FlateCallback,
         if (!--lft) cbf();
         if (!--lft) cbf();
       }
       }
     }
     }
+    if (n.length > 65535) cbl(new Error('filename too long'), null);
     if (!t) cbl(null, file);
     if (!t) cbl(null, file);
-    else if (m < 160000) cbl(null, deflateSync(file, opts as AsyncZipOptions));
-    else term.push(deflate(file, opts as AsyncZipOptions, cbl));
+    else if (m < 160000) {
+      try {
+        cbl(null, deflateSync(file, opts as AsyncZipOptions));
+      } catch(e) {
+        cbl(e, null);
+      }
+    } else term.push(deflate(file, opts as AsyncZipOptions, cbl));
   }
   }
   return tAll;
   return tAll;
 }
 }
@@ -2185,6 +2196,7 @@ export function zipSync(data: Zippable, opts: ZipOptions = {}) {
  * @returns A function that can be used to immediately terminate the unzipping
  * @returns A function that can be used to immediately terminate the unzipping
  */
  */
 export function unzip(data: Uint8Array, cb: UnzipCallback): AsyncTerminable {
 export function unzip(data: Uint8Array, cb: UnzipCallback): AsyncTerminable {
+  if (typeof cb != 'function') throw 'no callback';
   const term: AsyncTerminable[] = [];
   const term: AsyncTerminable[] = [];
   const tAll = () => {
   const tAll = () => {
     for (let i = 0; i < term.length; ++i) term[i]();
     for (let i = 0; i < term.length; ++i) term[i]();
@@ -2192,7 +2204,10 @@ export function unzip(data: Uint8Array, cb: UnzipCallback): AsyncTerminable {
   const files: Unzipped = {};
   const files: Unzipped = {};
   let e = data.length - 22;
   let e = data.length - 22;
   for (; b4(data, e) != 0x6054B50; --e) {
   for (; b4(data, e) != 0x6054B50; --e) {
-    if (!e || data.length - e > 65558) throw 'invalid zip file';
+    if (!e || data.length - e > 65558) {
+      cb(new Error('invalid zip file'), null);
+      return;
+    }
   };
   };
   let lft = b2(data, e + 8);
   let lft = b2(data, e + 8);
   if (!lft) cb(null, {});
   if (!lft) cb(null, {});
@@ -2214,7 +2229,13 @@ export function unzip(data: Uint8Array, cb: UnzipCallback): AsyncTerminable {
     if (!c) cbl(null, slc(data, b, b + sc))
     if (!c) cbl(null, slc(data, b, b + sc))
     else if (c == 8) {
     else if (c == 8) {
       const infl = data.subarray(b, sc ? b + sc : data.length);
       const infl = data.subarray(b, sc ? b + sc : data.length);
-      if (sc < 320000) cbl(null, inflateSync(infl, su != null && new u8(su)));
+      if (sc < 320000) {
+        try {
+          cbl(null, inflateSync(infl, su != null && new u8(su)));
+        } catch(e) {
+          cbl(e, null);
+        }
+      }
       else inflate(infl, { size: su }, cbl);
       else inflate(infl, { size: su }, cbl);
     } else throw 'unknown compression type ' + c;
     } else throw 'unknown compression type ' + c;
   }
   }