@zip.js/zip.js 2.12.0 → 2.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/deno.json +1 -1
  2. package/dist/zip-core-external.js +158 -41
  3. package/dist/zip-core-external.min.js +1 -1
  4. package/dist/zip-core.js +158 -41
  5. package/dist/zip-core.min.js +1 -1
  6. package/dist/zip-fs-core-external.js +159 -42
  7. package/dist/zip-fs-core-external.min.js +1 -1
  8. package/dist/zip-fs-core.js +159 -42
  9. package/dist/zip-fs-core.min.js +1 -1
  10. package/dist/zip-fs-external.js +159 -42
  11. package/dist/zip-fs-external.min.js +1 -1
  12. package/dist/zip-fs-native.js +161 -44
  13. package/dist/zip-fs-native.min.js +1 -1
  14. package/dist/zip-fs.js +160 -43
  15. package/dist/zip-fs.min.js +1 -1
  16. package/dist/zip-legacy.js +160 -43
  17. package/dist/zip-legacy.min.js +1 -1
  18. package/dist/zip-native.js +160 -43
  19. package/dist/zip-native.min.js +1 -1
  20. package/dist/zip-web-worker-native.js +1 -1
  21. package/dist/zip-web-worker.js +1 -1
  22. package/dist/zip.js +159 -42
  23. package/dist/zip.min.js +1 -1
  24. package/index-native.cjs +161 -44
  25. package/index-native.min.js +1 -1
  26. package/index.cjs +160 -43
  27. package/index.d.cts +19 -7
  28. package/index.d.ts +19 -7
  29. package/index.min.js +1 -1
  30. package/lib/core/codec-worker-web.js +96 -30
  31. package/lib/core/codec-worker.js +15 -3
  32. package/lib/core/util/error.js +35 -0
  33. package/lib/core/version.js +1 -1
  34. package/lib/core/web-worker-base.js +43 -7
  35. package/lib/core/web-worker-inline-native.js +1 -1
  36. package/lib/core/web-worker-inline-wasm.js +1 -1
  37. package/lib/core/zip-fs.js +2 -1
  38. package/lib/core/zip-reader.js +9 -4
  39. package/lib/core/zip-writer.js +8 -3
  40. package/package.json +1 -1
  41. package/worker-message-property-names.js +1 -1
@@ -489,6 +489,39 @@
489
489
  return new DataView(array.buffer, array.byteOffset, array.byteLength);
490
490
  }
491
491
 
492
+ /*
493
+ Copyright (c) 2026 Gildas Lormeau. All rights reserved.
494
+
495
+ Redistribution and use in source and binary forms, with or without
496
+ modification, are permitted provided that the following conditions are met:
497
+
498
+ 1. Redistributions of source code must retain the above copyright notice,
499
+ this list of conditions and the following disclaimer.
500
+
501
+ 2. Redistributions in binary form must reproduce the above copyright
502
+ notice, this list of conditions and the following disclaimer in
503
+ the documentation and/or other materials provided with the distribution.
504
+
505
+ 3. The names of the authors may not be used to endorse or promote products
506
+ derived from this software without specific prior written permission.
507
+
508
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
509
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
510
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
511
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
512
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
513
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
514
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
515
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
516
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
517
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
518
+ */
519
+
520
+
521
+ function isErrorObject(error) {
522
+ return Boolean(error) && typeof error == "object";
523
+ }
524
+
492
525
  /*
493
526
  Copyright (c) 2022 Gildas Lormeau. All rights reserved.
494
527
 
@@ -2756,7 +2789,9 @@
2756
2789
 
2757
2790
  class CodecWorker {
2758
2791
 
2759
- constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI, createWorker }, onTaskFinished) {
2792
+ constructor(workerData, { readable, writable }, workerOptions, onTaskFinished) {
2793
+ const { options, config, streamOptions, useWebWorkers, transferStreams, workerURI } = workerOptions;
2794
+ let { createWorker } = workerOptions;
2760
2795
  const { signal } = streamOptions;
2761
2796
  if (createWorkerFailed) {
2762
2797
  createWorker = UNDEFINED_VALUE;
@@ -2769,6 +2804,7 @@
2769
2804
  .pipeThrough(new ProgressWatcherStream(streamOptions), { signal }),
2770
2805
  writable,
2771
2806
  options: Object.assign({}, options),
2807
+ workerOptions,
2772
2808
  workerURI,
2773
2809
  createWorker,
2774
2810
  transferStreams,
@@ -2850,7 +2886,7 @@
2850
2886
  };
2851
2887
  }
2852
2888
 
2853
- async function runWorker$1({ options, readable, writable, onTaskFinished }, config) {
2889
+ async function runWorker$1({ options, readable, writable, onTaskFinished, workerOptions }, config) {
2854
2890
  let codecStream, chunkStream;
2855
2891
  try {
2856
2892
  if (options.compressed && !options.format) {
@@ -2891,7 +2927,15 @@
2891
2927
  };
2892
2928
  } catch (error) {
2893
2929
  if (codecStream) {
2894
- error.outputSize = chunkStream ? chunkStream.outputSize : 0;
2930
+ const outputSize = chunkStream ? chunkStream.outputSize : 0;
2931
+ workerOptions.outputSize = outputSize;
2932
+ if (isErrorObject(error)) {
2933
+ try {
2934
+ error.outputSize = outputSize;
2935
+ } catch {
2936
+ // ignored
2937
+ }
2938
+ }
2895
2939
  }
2896
2940
  throw error;
2897
2941
  } finally {
@@ -3001,8 +3045,14 @@
3001
3045
  const result = new Promise((resolve, reject) => {
3002
3046
  resolveResult = resolve;
3003
3047
  rejectResult = error => {
3004
- if (error && error.outputSize === UNDEFINED_VALUE) {
3005
- error.outputSize = workerData.outputSize;
3048
+ const { outputSize, workerOptions } = workerData;
3049
+ workerOptions.outputSize = outputSize;
3050
+ if (isErrorObject(error)) {
3051
+ try {
3052
+ error.outputSize = outputSize;
3053
+ } catch {
3054
+ // ignored
3055
+ }
3006
3056
  }
3007
3057
  reject(error);
3008
3058
  };
@@ -3011,12 +3061,14 @@
3011
3061
  reader: null,
3012
3062
  writer: null,
3013
3063
  outputSize: 0,
3064
+ destinationFailed: false,
3065
+ destinationError: null,
3014
3066
  resolveResult,
3015
3067
  rejectResult,
3016
3068
  result
3017
3069
  });
3018
3070
  const { readable, options } = workerData;
3019
- const { writable, closed, abortPipe } = watchClosedStream(workerData.writable);
3071
+ const { writable, closed, abortPipe } = watchClosedStream(workerData.writable, workerData);
3020
3072
  let streamsTransferred;
3021
3073
  try {
3022
3074
  streamsTransferred = sendMessage({
@@ -3059,7 +3111,18 @@
3059
3111
  } catch {
3060
3112
  // ignored
3061
3113
  }
3062
- throw error;
3114
+ const { outputSize, workerOptions, destinationFailed, destinationError } = workerData;
3115
+ workerOptions.outputSize = outputSize;
3116
+ const workerFailed = isErrorObject(error) && (error.codecImportFailed || error.workerStartupFailed);
3117
+ const reportedError = destinationFailed && !workerFailed ? destinationError : error;
3118
+ if (isErrorObject(reportedError)) {
3119
+ try {
3120
+ reportedError.outputSize = outputSize;
3121
+ } catch {
3122
+ // ignored
3123
+ }
3124
+ }
3125
+ throw reportedError;
3063
3126
  }
3064
3127
 
3065
3128
  async function closeWritable() {
@@ -3073,12 +3136,27 @@
3073
3136
  }
3074
3137
  }
3075
3138
 
3076
- function watchClosedStream(writableSource) {
3139
+ function watchClosedStream(writableSource, workerData) {
3077
3140
  const abortController = new AbortController();
3078
- const { writable, readable } = new TransformStream();
3141
+ let aborting;
3142
+ const { writable, readable } = new TransformStream({
3143
+ transform(chunk, controller) {
3144
+ workerData.outputSize += chunk.length;
3145
+ controller.enqueue(chunk);
3146
+ }
3147
+ });
3079
3148
  const closed = readable.pipeTo(writableSource, { preventClose: true, preventAbort: true, signal: abortController.signal });
3080
- closed.catch(() => { });
3081
- return { writable, closed, abortPipe: () => abortController.abort() };
3149
+ closed.catch(error => {
3150
+ if (!aborting) {
3151
+ Object.assign(workerData, { destinationFailed: true, destinationError: error });
3152
+ }
3153
+ });
3154
+ return {
3155
+ writable, closed, abortPipe: () => {
3156
+ aborting = true;
3157
+ abortController.abort();
3158
+ }
3159
+ };
3082
3160
  }
3083
3161
 
3084
3162
  function releaseWorkerStreams(workerData) {
@@ -3271,21 +3349,12 @@
3271
3349
  }
3272
3350
 
3273
3351
  async function onMessage({ data }, workerData) {
3274
- const { type, value, messageId, result, error } = data;
3352
+ const { type, value, messageId, result, error, errorValue } = data;
3275
3353
  const { reader, writer, resolveResult, rejectResult, onTaskFinished, generation } = workerData;
3276
3354
  const stale = () => workerData.generation != generation;
3277
3355
  try {
3278
3356
  if (error) {
3279
- const { message, stack, code, name, outputSize, cause, codecImportFailed } = error;
3280
- const responseError = new Error(message);
3281
- Object.assign(responseError, { stack, code, name, outputSize });
3282
- if (cause) {
3283
- responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
3284
- }
3285
- if (codecImportFailed) {
3286
- responseError.codecImportFailed = true;
3287
- }
3288
- close(responseError);
3357
+ fail(getResponseError(error, errorValue));
3289
3358
  } else {
3290
3359
  if (type == MESSAGE_PULL) {
3291
3360
  const { value, done } = await reader.read();
@@ -3297,38 +3366,78 @@
3297
3366
  const chunk = new Uint8Array(value);
3298
3367
  await writer.ready;
3299
3368
  await writer.write(chunk);
3300
- workerData.outputSize += chunk.length;
3301
3369
  if (!stale()) {
3302
3370
  sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
3303
3371
  }
3304
3372
  }
3305
3373
  if (type == MESSAGE_CLOSE) {
3306
- close(null, result);
3374
+ succeed(result);
3307
3375
  }
3308
3376
  }
3309
3377
  } catch (error) {
3310
3378
  if (!stale()) {
3311
3379
  terminateWorker$1(workerData);
3312
- close(error);
3380
+ fail(error);
3313
3381
  }
3314
3382
  }
3315
3383
 
3316
- function close(error, result) {
3317
- if (stale()) {
3318
- return;
3319
- }
3320
- if (error) {
3384
+ function fail(error) {
3385
+ if (!stale()) {
3321
3386
  rejectResult(error);
3322
- } else {
3387
+ releaseWriter();
3388
+ if (!(isErrorObject(error) && error.codecImportFailed)) {
3389
+ onTaskFinished();
3390
+ }
3391
+ }
3392
+ }
3393
+
3394
+ function succeed(result) {
3395
+ if (!stale()) {
3323
3396
  resolveResult(result);
3397
+ releaseWriter();
3398
+ onTaskFinished();
3324
3399
  }
3400
+ }
3401
+
3402
+ function releaseWriter() {
3325
3403
  if (writer) {
3326
3404
  writer.releaseLock();
3327
3405
  }
3328
- if (!(error && error.codecImportFailed)) {
3329
- onTaskFinished();
3406
+ }
3407
+ }
3408
+
3409
+ function getResponseError(errorData, errorValue) {
3410
+ const { message, stack, code, name, outputSize, cause, codecImportFailed } = errorData;
3411
+ let responseError;
3412
+ if (errorValue) {
3413
+ responseError = errorValue.value;
3414
+ } else {
3415
+ responseError = Object.assign(new Error(message), { stack, code, name });
3416
+ if (cause) {
3417
+ responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
3418
+ }
3419
+ }
3420
+ if (isErrorObject(responseError)) {
3421
+ try {
3422
+ if (outputSize !== UNDEFINED_VALUE) {
3423
+ responseError.outputSize = outputSize;
3424
+ }
3425
+ if (codecImportFailed) {
3426
+ responseError.codecImportFailed = true;
3427
+ }
3428
+ if (errorValue) {
3429
+ if (responseError.name !== name) {
3430
+ responseError.name = name;
3431
+ }
3432
+ if (responseError.code !== code) {
3433
+ responseError.code = code;
3434
+ }
3435
+ }
3436
+ } catch {
3437
+ // ignored
3330
3438
  }
3331
3439
  }
3440
+ return responseError;
3332
3441
  }
3333
3442
 
3334
3443
  /*
@@ -5610,7 +5719,7 @@
5610
5719
  readRanges
5611
5720
  });
5612
5721
  }
5613
- let writable, abortError;
5722
+ let writable, abortError, aborted;
5614
5723
  try {
5615
5724
  if (!checkOverlappingEntryOnly) {
5616
5725
  if (checkPasswordOnly) {
@@ -5626,18 +5735,22 @@
5626
5735
  writer.size += writtenSize;
5627
5736
  }
5628
5737
  } catch (error) {
5629
- if (error.outputSize !== UNDEFINED_VALUE) {
5738
+ const { outputSize: failedOutputSize } = workerOptions;
5739
+ if (failedOutputSize !== UNDEFINED_VALUE) {
5740
+ writer.size += failedOutputSize;
5741
+ } else if (isErrorObject(error) && error.outputSize !== UNDEFINED_VALUE) {
5630
5742
  writer.size += error.outputSize;
5631
5743
  }
5632
- if (!checkPasswordOnly || error.message != ERR_ABORT_CHECK_PASSWORD) {
5744
+ if (!checkPasswordOnly || !isErrorObject(error) || error.message != ERR_ABORT_CHECK_PASSWORD) {
5633
5745
  abortError = error;
5746
+ aborted = true;
5634
5747
  throw error;
5635
5748
  }
5636
5749
  } finally {
5637
5750
  const preventClose = !ownsWritable(writer) && getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5638
5751
  if (!preventClose && writable && !writable.locked) {
5639
5752
  const writableWriter = writable.getWriter();
5640
- if (abortError) {
5753
+ if (aborted) {
5641
5754
  try {
5642
5755
  await writableWriter.abort(abortError);
5643
5756
  } catch {
@@ -6697,7 +6810,7 @@
6697
6810
  await Promise.allSettled(Array.from(pendingAddFileCalls));
6698
6811
  }
6699
6812
  await Promise.allSettled(zipWriter.pendingErrors.map(watcher => watcher.recorded));
6700
- const unobservedWatchers = zipWriter.pendingErrors.filter(watcher => watcher.error && !watcher.observed);
6813
+ const unobservedWatchers = zipWriter.pendingErrors.filter(watcher => watcher.failed && !watcher.observed);
6701
6814
  if (unobservedWatchers.length) {
6702
6815
  const unobservedErrors = unobservedWatchers.map(watcher => watcher.error);
6703
6816
  unobservedWatchers.forEach(watcher => watcher.observed = true);
@@ -6806,7 +6919,8 @@
6806
6919
  const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
6807
6920
  const watcher = {};
6808
6921
  watchedPromise.watcher = watcher;
6809
- watcher.recorded = Promise.prototype.then.call(watchedPromise, UNDEFINED_VALUE, error => watcher.error = error);
6922
+ watcher.recorded = Promise.prototype.then.call(watchedPromise, UNDEFINED_VALUE,
6923
+ error => Object.assign(watcher, { failed: true, error }));
6810
6924
  zipWriter.pendingErrors.push(watcher);
6811
6925
  return watchedPromise;
6812
6926
  }
@@ -7820,7 +7934,10 @@
7820
7934
  throw new Error(ERR_UNSUPPORTED_FORMAT);
7821
7935
  }
7822
7936
  } catch (error) {
7823
- if (error.outputSize !== UNDEFINED_VALUE) {
7937
+ const { outputSize: failedOutputSize } = workerOptions;
7938
+ if (failedOutputSize !== UNDEFINED_VALUE) {
7939
+ writer.size += failedOutputSize;
7940
+ } else if (isErrorObject(error) && error.outputSize !== UNDEFINED_VALUE) {
7824
7941
  writer.size += error.outputSize;
7825
7942
  }
7826
7943
  throw error;
@@ -8985,7 +9102,7 @@
8985
9102
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8986
9103
  */
8987
9104
 
8988
- const VERSION = "2.12.0";
9105
+ const VERSION = "2.13.1";
8989
9106
 
8990
9107
  /*
8991
9108
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -9610,7 +9727,7 @@
9610
9727
  }));
9611
9728
  return true;
9612
9729
  } catch (error) {
9613
- if (error.message == ERR_INVALID_PASSWORD) {
9730
+ if (isErrorObject(error) && error.message == ERR_INVALID_PASSWORD) {
9614
9731
  return false;
9615
9732
  } else {
9616
9733
  throw error;