Browse Source

Bugfixes and patches

101arrowz 3 years ago
parent
commit
77fe167fe0

+ 7 - 0
CHANGELOG.md

@@ -1,3 +1,10 @@
+## 0.7.3
+- Fix folder creation for certain operating system
+  - Create 0-length "files" for each directory specified with "object" syntax"
+  - Support empty folders
+  - Add options for folders
+- Fix minification in SWC
+  - Remove instanceof, no-whitespace assumptions in async functions
 ## 0.7.2
 ## 0.7.2
 - Fixed TypeScript typing for errors when using `strictNullChecks`
 - Fixed TypeScript typing for errors when using `strictNullChecks`
 - Fixed failure to compress files above 64kB with `{ level: 0 }`
 - Fixed failure to compress files above 64kB with `{ level: 0 }`

+ 20 - 9
README.md

@@ -243,26 +243,38 @@ const zipped = fflate.zipSync({
   'dir1': {
   'dir1': {
     'nested': {
     'nested': {
       // You can use Unicode in filenames
       // You can use Unicode in filenames
-      '你好.txt': strToU8('Hey there!')
+      '你好.txt': fflate.strToU8('Hey there!')
     },
     },
     // You can also manually write out a directory path
     // You can also manually write out a directory path
     'other/tmp.txt': new Uint8Array([97, 98, 99, 100])
     'other/tmp.txt': new Uint8Array([97, 98, 99, 100])
   },
   },
+
   // You can also provide compression options
   // You can also provide compression options
   'massiveImage.bmp': [aMassiveFile, {
   'massiveImage.bmp': [aMassiveFile, {
     level: 9,
     level: 9,
-    mem: 12,
-    // ZIP-specific: mtime works here too, defaults to current time
-    mtime: new Date('10/20/2020')
+    mem: 12
   }],
   }],
   // PNG is pre-compressed; no need to waste time
   // PNG is pre-compressed; no need to waste time
-  'superTinyFile.png': [aPNGFile, { level: 0 }]
+  'superTinyFile.png': [aPNGFile, { level: 0 }],
+
+  // Directories take options too
+  'exec': [{
+    'hello.sh': [fflate.strToU8('echo hello world'), {
+      // ZIP only: Set the operating system to Unix
+      os: 3,
+      // ZIP only: Make this file executable on Unix
+      attrs: 0o755 << 16
+    }]
+  }, {
+    // ZIP and GZIP support mtime (defaults to current time)
+    mtime: new Date('10/20/2020')
+  }]
 }, {
 }, {
   // These options are the defaults for all files, but file-specific
   // These options are the defaults for all files, but file-specific
   // options take precedence.
   // options take precedence.
   level: 1,
   level: 1,
-  // Obfuscate mtime by default
-  mtime: 0
+  // Obfuscate last modified time by default 
+  mtime: new Date('1/1/1980')
 });
 });
 
 
 // If you write the zipped data to myzip.zip and unzip, the folder
 // If you write the zipped data to myzip.zip and unzip, the folder
@@ -442,8 +454,7 @@ gzs.terminate();
 zip({ f1: aMassiveFile, 'f2.txt': anotherMassiveFile }, {
 zip({ f1: aMassiveFile, 'f2.txt': anotherMassiveFile }, {
   // The options object is still optional, you can still do just
   // The options object is still optional, you can still do just
   // zip(archive, callback)
   // zip(archive, callback)
-  level: 6,
-  mtime: 0
+  level: 6
 }, (err, data) => {
 }, (err, data) => {
   // Save the ZIP file
   // Save the ZIP file
 });
 });

+ 2 - 2
docs/README.md

@@ -113,7 +113,7 @@ ___
 
 
 ### AsyncZippableFile
 ### AsyncZippableFile
 
 
-Ƭ  **AsyncZippableFile**: Uint8Array \| []
+Ƭ  **AsyncZippableFile**: Uint8Array \| [AsyncZippable](interfaces/asynczippable.md) \| []
 
 
 A file that can be used to asynchronously create a ZIP archive
 A file that can be used to asynchronously create a ZIP archive
 
 
@@ -191,7 +191,7 @@ ___
 
 
 ### ZippableFile
 ### ZippableFile
 
 
-Ƭ  **ZippableFile**: Uint8Array \| []
+Ƭ  **ZippableFile**: Uint8Array \| [Zippable](interfaces/zippable.md) \| []
 
 
 A file that can be used to create a ZIP archive
 A file that can be used to create a ZIP archive
 
 

+ 4 - 2
docs/interfaces/asynczipoptions.md

@@ -47,7 +47,9 @@ rwx = user permissions, rwx = group permissions, rwx = other permissions
 
 
 A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
 A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
 
 
-If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0644 << 16
+If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0o644 << 16.
+Note that attributes usually only work in conjunction with the `os` setting: you must use
+`os` = 3 (Unix) if you want to set Unix permissions
 
 
 ___
 ___
 
 
@@ -145,4 +147,4 @@ ___
 
 
 The operating system of origin for this file. The value is defined
 The operating system of origin for this file. The value is defined
 by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
 by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
-is MS/DOS, 3 is UNIX, 19 is macOS.
+is MS/DOS, 3 is Unix, 19 is macOS.

+ 1 - 1
docs/interfaces/asynczippable.md

@@ -8,6 +8,6 @@ The complete directory structure of an asynchronously ZIPpable archive
 
 
 ## Indexable
 ## Indexable
 
 
-▪ [path: string]: [AsyncZippable](asynczippable.md) \| [AsyncZippableFile](../README.md#asynczippablefile)
+▪ [path: string]: [AsyncZippableFile](../README.md#asynczippablefile)
 
 
 The complete directory structure of an asynchronously ZIPpable archive
 The complete directory structure of an asynchronously ZIPpable archive

+ 4 - 2
docs/interfaces/zipattributes.md

@@ -44,7 +44,9 @@ rwx = user permissions, rwx = group permissions, rwx = other permissions
 
 
 A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
 A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
 
 
-If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0644 << 16
+If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0o644 << 16.
+Note that attributes usually only work in conjunction with the `os` setting: you must use
+`os` = 3 (Unix) if you want to set Unix permissions
 
 
 ___
 ___
 
 
@@ -85,4 +87,4 @@ ___
 
 
 The operating system of origin for this file. The value is defined
 The operating system of origin for this file. The value is defined
 by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
 by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
-is MS/DOS, 3 is UNIX, 19 is macOS.
+is MS/DOS, 3 is Unix, 19 is macOS.

+ 4 - 2
docs/interfaces/zipinputfile.md

@@ -55,7 +55,9 @@ rwx = user permissions, rwx = group permissions, rwx = other permissions
 
 
 A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
 A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
 
 
-If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0644 << 16
+If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0o644 << 16.
+Note that attributes usually only work in conjunction with the `os` setting: you must use
+`os` = 3 (Unix) if you want to set Unix permissions
 
 
 ___
 ___
 
 
@@ -166,7 +168,7 @@ ___
 
 
 The operating system of origin for this file. The value is defined
 The operating system of origin for this file. The value is defined
 by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
 by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
-is MS/DOS, 3 is UNIX, 19 is macOS.
+is MS/DOS, 3 is Unix, 19 is macOS.
 
 
 ___
 ___
 
 

+ 4 - 2
docs/interfaces/zipoptions.md

@@ -46,7 +46,9 @@ rwx = user permissions, rwx = group permissions, rwx = other permissions
 
 
 A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
 A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
 
 
-If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0644 << 16
+If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0o644 << 16.
+Note that attributes usually only work in conjunction with the `os` setting: you must use
+`os` = 3 (Unix) if you want to set Unix permissions
 
 
 ___
 ___
 
 
@@ -133,4 +135,4 @@ ___
 
 
 The operating system of origin for this file. The value is defined
 The operating system of origin for this file. The value is defined
 by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
 by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
-is MS/DOS, 3 is UNIX, 19 is macOS.
+is MS/DOS, 3 is Unix, 19 is macOS.

+ 1 - 1
docs/interfaces/zippable.md

@@ -8,6 +8,6 @@ The complete directory structure of a ZIPpable archive
 
 
 ## Indexable
 ## Indexable
 
 
-▪ [path: string]: [Zippable](zippable.md) \| [ZippableFile](../README.md#zippablefile)
+▪ [path: string]: [ZippableFile](../README.md#zippablefile)
 
 
 The complete directory structure of a ZIPpable archive
 The complete directory structure of a ZIPpable archive

+ 1 - 1
package.json

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

+ 22 - 15
src/index.ts

@@ -151,7 +151,7 @@ const slc = <T extends Uint8Array | Uint16Array | Uint32Array>(v: T, s: number,
   if (s == null || s < 0) s = 0;
   if (s == null || s < 0) s = 0;
   if (e == null || e > v.length) e = v.length;
   if (e == null || e > v.length) e = v.length;
   // can't use .constructor in case user-supplied
   // can't use .constructor in case user-supplied
-  const n = new (v instanceof u16 ? u16 : v instanceof u32 ? u32 : u8)(e - s) as T;
+  const n = new (v.BYTES_PER_ELEMENT == 2 ? u16 : v.BYTES_PER_ELEMENT == 4 ? u32 : u8)(e - s) as T;
   n.set(v.subarray(s, e));
   n.set(v.subarray(s, e));
   return n;
   return n;
 }
 }
@@ -930,7 +930,7 @@ const mrg = <A, B>(a: A, b: B) => {
 const wcln = (fn: () => unknown[], fnStr: string, td: Record<string, unknown>) => {
 const wcln = (fn: () => unknown[], fnStr: string, td: Record<string, unknown>) => {
   const dt = fn();
   const dt = fn();
   const st = fn.toString();
   const st = fn.toString();
-  const ks = st.slice(st.indexOf('[') + 1, st.lastIndexOf(']')).replace(/ /g, '').split(',');
+  const ks = st.slice(st.indexOf('[') + 1, st.lastIndexOf(']')).replace(/\s+/g, '').split(',');
   for (let i = 0; i < dt.length; ++i) {
   for (let i = 0; i < dt.length; ++i) {
     let v = dt[i], k = ks[i];
     let v = dt[i], k = ks[i];
     if (typeof v == 'function') {
     if (typeof v == 'function') {
@@ -958,7 +958,9 @@ const ch: CachedWorker[] = [];
 const cbfs = (v: Record<string, unknown>) => {
 const cbfs = (v: Record<string, unknown>) => {
   const tl: ArrayBuffer[] = [];
   const tl: ArrayBuffer[] = [];
   for (const k in v) {
   for (const k in v) {
-    if (v[k] instanceof u8 || v[k] instanceof u16 || v[k] instanceof u32) tl.push((v[k] = new (v[k].constructor as typeof u8)(v[k] as Uint8Array)).buffer);
+    if ((v[k] as Uint8Array).buffer) {
+      tl.push((v[k] = new (v[k].constructor as typeof u8)(v[k] as Uint8Array)).buffer);
+    }
   }
   }
   return tl;
   return tl;
 }
 }
@@ -977,7 +979,7 @@ const wrkr = <T, R>(fns: (() => unknown[])[], init: (ev: MessageEvent<T>) => voi
 
 
 // base async inflate fn
 // base async inflate fn
 const bInflt = () => [u8, u16, u32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, ec, hMap, max, bits, bits16, shft, slc, err, inflt, inflateSync, pbf, gu8];
 const bInflt = () => [u8, u16, u32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, ec, hMap, max, bits, bits16, shft, slc, err, inflt, inflateSync, pbf, gu8];
-const bDflt = () => [u8, u16, u32, fleb, fdeb, clim, revfl, revfd, flm, flt, fdm, fdt, rev, deo, et, hMap, wbits, wbits16, hTree, ln, lc, clen, wfblk, wblk, shft, slc, dflt, dopt, deflateSync, pbf]
+const bDflt = () => [u8, u16, u32, fleb, fdeb, clim, revfl, revfd, flm, flt, fdm, fdt, rev, deo, et, hMap, wbits, wbits16, hTree, ln, lc, clen, wfblk, wblk, shft, slc, dflt, dopt, deflateSync, pbf];
 
 
 // gzip extra
 // gzip extra
 const gze = () => [gzh, gzhl, wbytes, crc, crct];
 const gze = () => [gzh, gzhl, wbytes, crc, crct];
@@ -1967,7 +1969,7 @@ export interface ZipAttributes {
   /**
   /**
    * The operating system of origin for this file. The value is defined
    * The operating system of origin for this file. The value is defined
    * by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
    * by PKZIP's APPNOTE.txt, section 4.4.2.2. For example, 0 (the default)
-   * is MS/DOS, 3 is UNIX, 19 is macOS.
+   * is MS/DOS, 3 is Unix, 19 is macOS.
    */
    */
   os?: number;
   os?: number;
 
 
@@ -1988,7 +1990,9 @@ export interface ZipAttributes {
    * 
    * 
    * A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
    * A = archive, D = directory, V = volume label, S = system file, H = hidden, R = read-only
    * 
    * 
-   * If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0644 << 16
+   * If you want to set the Unix permissions, for instance, just bit shift by 16, e.g. 0o644 << 16.
+   * Note that attributes usually only work in conjunction with the `os` setting: you must use
+   * `os` = 3 (Unix) if you want to set Unix permissions
    */
    */
   attrs?: number;
   attrs?: number;
 
 
@@ -2043,25 +2047,25 @@ export interface AsyncUnzipOptions extends UnzipOptions {}
 /**
 /**
  * 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 | Zippable | [Uint8Array | Zippable, ZipOptions];
 
 
 /**
 /**
  * A file that can be used to asynchronously create 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 | AsyncZippable | [Uint8Array | AsyncZippable, AsyncZipOptions]
 
 
 /**
 /**
  * The complete directory structure of a ZIPpable archive
  * The complete directory structure of a ZIPpable archive
  */
  */
 export interface Zippable {
 export interface Zippable {
-  [path: string]: Zippable | ZippableFile;
+  [path: string]: ZippableFile;
 }
 }
 
 
 /**
 /**
  * The complete directory structure of an asynchronously ZIPpable archive
  * The complete directory structure of an asynchronously ZIPpable archive
  */
  */
 export interface AsyncZippable {
 export interface AsyncZippable {
-  [path: string]: AsyncZippable | AsyncZippableFile;
+  [path: string]: AsyncZippableFile;
 }
 }
 
 
 /**
 /**
@@ -2096,12 +2100,15 @@ export type UnzipFileHandler = (file: UnzipFile) => void;
 type FlatZippable<A extends boolean> = Record<string, [Uint8Array, (A extends true ? AsyncZipOptions : ZipOptions)]>;
 type FlatZippable<A extends boolean> = Record<string, [Uint8Array, (A extends true ? AsyncZipOptions : ZipOptions)]>;
 
 
 // flatten a directory structure
 // flatten a directory structure
-const fltn = <A extends boolean>(d: A extends true ? AsyncZippable : Zippable, p: string, t: FlatZippable<A>, o: ZipOptions) => {
+const fltn = <A extends boolean, D = A extends true ? AsyncZippable : Zippable>(d: D, p: string, t: FlatZippable<A>, o: ZipOptions) => {
   for (const k in d) {
   for (const k in d) {
-    const val = d[k], n = p + k;
-    if (val instanceof u8) t[n] = [val, o] as unknown as FlatZippable<A>[string];
-    else if (Array.isArray(val)) t[n] = [val[0], mrg(o, val[1])] as FlatZippable<A>[string];
-    else fltn(val as unknown as (A extends true ? AsyncZippable : Zippable), n + '/', t, o);
+    let val = d[k], n = p + k, op = o;
+    if (Array.isArray(val)) op = mrg(o, val[1]), val = val[0] as unknown as D[Extract<keyof D, string>];
+    if (val instanceof u8) t[n] = [val, op] as unknown as FlatZippable<A>[string];
+    else {
+      t[n += '/'] = [new u8(0), op] as unknown as FlatZippable<A>[string];
+      fltn(val as unknown as (A extends true ? AsyncZippable : Zippable), n, t, o);
+    }
   }
   }
 }
 }