scratch-storage 5.0.10 → 6.0.0

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 (39) hide show
  1. package/.github/workflows/ci-cd.yml +10 -3
  2. package/.husky/commit-msg +0 -3
  3. package/dist/node/chunks/fetch-worker.7afe4ade866d6f6a3cb3.js +383 -0
  4. package/dist/node/chunks/fetch-worker.7afe4ade866d6f6a3cb3.js.map +1 -0
  5. package/dist/node/scratch-storage.js +376 -881
  6. package/dist/node/scratch-storage.js.map +1 -1
  7. package/dist/types/HostQueues.d.ts +20 -0
  8. package/dist/types/ScratchStorage.d.ts +2 -15
  9. package/dist/types/scratchFetch.d.ts +37 -15
  10. package/dist/web/chunks/fetch-worker.9fbe108071a9c5d6e70b.js +2 -0
  11. package/dist/web/chunks/{fetch-worker.4277f33a97fe995aa7dd.js.map → fetch-worker.9fbe108071a9c5d6e70b.js.map} +1 -1
  12. package/dist/web/chunks/fetch-worker.efebf27d479ab0f0d98c.js +394 -0
  13. package/dist/web/chunks/fetch-worker.efebf27d479ab0f0d98c.js.map +1 -0
  14. package/dist/web/scratch-storage.js +379 -884
  15. package/dist/web/scratch-storage.js.map +1 -1
  16. package/dist/web/scratch-storage.min.js +1 -1
  17. package/dist/web/scratch-storage.min.js.map +1 -1
  18. package/package.json +16 -14
  19. package/src/FetchTool.ts +3 -2
  20. package/src/FetchWorkerTool.worker.ts +94 -0
  21. package/src/HostQueues.ts +33 -0
  22. package/src/ScratchStorage.ts +1 -1
  23. package/src/{scratchFetch.js → scratchFetch.ts} +53 -34
  24. package/src/types.d.ts +4 -3
  25. package/test/build/api.test.js +60 -0
  26. package/test/build/scratchFetch.test.js +40 -0
  27. package/test/fixtures/known-assets.js +30 -2
  28. package/test/{__mocks__/cross-fetch.js → fixtures/mockFetch.js} +18 -17
  29. package/test/integration/download-known-assets.test.js +6 -3
  30. package/test/unit/fetch-tool.test.js +8 -7
  31. package/test/unit/metadata.test.js +9 -8
  32. package/tsconfig.json +0 -1
  33. package/tsconfig.test.json +1 -0
  34. package/dist/node/chunks/fetch-worker.56da39b0f4bad6747138.js +0 -809
  35. package/dist/node/chunks/fetch-worker.56da39b0f4bad6747138.js.map +0 -1
  36. package/dist/web/chunks/fetch-worker.4277f33a97fe995aa7dd.js +0 -2
  37. package/dist/web/chunks/fetch-worker.c813c32be403f91001ba.js +0 -820
  38. package/dist/web/chunks/fetch-worker.c813c32be403f91001ba.js.map +0 -1
  39. package/src/FetchWorkerTool.worker.js +0 -67
@@ -1,15 +1,15 @@
1
1
  /******/ (() => { // webpackBootstrap
2
2
  /******/ var __webpack_modules__ = ({
3
3
 
4
- /***/ 9:
5
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
4
+ /***/ 9
5
+ (module, __unused_webpack_exports, __webpack_require__) {
6
6
 
7
7
  module.exports = __webpack_require__(14)("iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAAAAADmVT4XAAADZElEQVR42u3a70vbQBgH8O/7vOibvsmbFUEEWUGGUhQ25nDuhSKIUFDxlYi0SAd94atRmFiHCH2x4W8iiNtwowXRgd1QipJYY3N/1F4kTQ6XLKS9yyHcvWyO8MnT5y53Tw5EcIMESIAESIAESIAESIAEPFVAq/6l8G4oAQCp4aniwbUVJ6BVzafwqKXy1VZMgNb+CHzbyK4ZB+Bi0nnk0VyhsDiSoAmvvnMHmGUVAF6UG+0ffsxRhsRHky/AyCsAUpumX0wAAIs6T4CxDADDtcdZsal6gjmdH8AsAEC6+s8Fa48SFExeAKusAEju+V367AmUCi9ANQ0AU3pwcOw2cMEH0FwAAKz5X228pRLR5AI4TgIAtIDL24oLUE94AB6W7LsH/cONN14Ilh44AOqD9s2LQR1KHiB9zgGgOSGeuA3ocPrME1Q4ANaceyePAzrcjHmAZYs9IBeW4/fzHiAwTCwAgTle9ACZK44ALDT9e6x7gL4aT0BQCHb4AqgA5/1TTOMLoJ7vZSMM0H/GHnCeDnu+CrU8vGYPcN5FADBYD0vCaYPDy+i0p337GSMsS1Z4vA3t9QgAZTt0IuIxFRPSKicAQHlvhk3FXF5GhBByMa8qo/sBO6BarwuYbYrYnFKDYEvE7phKgcxvEQBqnvhgiQCUOgoAO4C3JOS3L/hv23UXxVldBECfcueAqpAa0WGy/QeULREAY6aTXRFDgBuA13+ElOncAERMAGaA9hBQD4gQQHsIRE1AZoD2xrgQS5nOZyHgFKmWDSIG4GRAVidiAE4GRB6AzAB2AKIPQFaA5myHA5AV4ESNugZhC7BLR50lIBPAebrzBGQCKAFQNSIMcDvRTQIwAHxNApM3RBygGK0uyhxwOwGsPAgEnPWj5ycRCNiJtBHlAChGKQVwANzPY+CXSMDNWISiLA9AfRA5IhJQ68UnoQAt+AtOPIBKhJosF8B6UM0yLkAxQk2WCyDX9SiUh1gkQAIkoCuAvjGuquMbuijAtwG7MPL8yBICOHSPk3W8Ne8KcEUdmBi6FADYos+QleIH0N/ogOxd7AD6uAS6WRU8WcBdlgZMG/EnYUlwEpLLoQ4PjzGbiA5UsRMRsbQ+5ziDJmYqJuR6NaMomdXuFuZyPSABEiABEiABEiABEiAc8Bd6VyvCEKGqcQAAAABJRU5ErkJggg==")
8
8
 
9
- /***/ }),
9
+ /***/ },
10
10
 
11
- /***/ 14:
12
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
11
+ /***/ 14
12
+ (module, __unused_webpack_exports, __webpack_require__) {
13
13
 
14
14
  "use strict";
15
15
  /* provided dependency */ var Buffer = __webpack_require__(287)["hp"];
@@ -28,10 +28,10 @@ module.exports = function (base64Data) {
28
28
  }
29
29
 
30
30
 
31
- /***/ }),
31
+ /***/ },
32
32
 
33
- /***/ 15:
34
- /***/ ((module, exports, __webpack_require__) => {
33
+ /***/ 15
34
+ (module, exports, __webpack_require__) {
35
35
 
36
36
  var Transform = __webpack_require__(408),
37
37
  Filter = __webpack_require__(84);
@@ -80,10 +80,10 @@ exports.enable = function() {
80
80
 
81
81
 
82
82
 
83
- /***/ }),
83
+ /***/ },
84
84
 
85
- /***/ 84:
86
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
85
+ /***/ 84
86
+ (module, __unused_webpack_exports, __webpack_require__) {
87
87
 
88
88
  // default filter
89
89
  var Transform = __webpack_require__(408);
@@ -143,10 +143,10 @@ Filter.prototype.write = function(name, level, args) {
143
143
  module.exports = Filter;
144
144
 
145
145
 
146
- /***/ }),
146
+ /***/ },
147
147
 
148
- /***/ 113:
149
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
148
+ /***/ 113
149
+ (module, __unused_webpack_exports, __webpack_require__) {
150
150
 
151
151
  var Transform = __webpack_require__(408),
152
152
  cache = false;
@@ -164,10 +164,10 @@ logger.write = function(name, level, args) {
164
164
 
165
165
  module.exports = logger;
166
166
 
167
- /***/ }),
167
+ /***/ },
168
168
 
169
- /***/ 173:
170
- /***/ ((module) => {
169
+ /***/ 173
170
+ (module) {
171
171
 
172
172
  function M() { this._events = {}; }
173
173
  M.prototype = {
@@ -221,10 +221,10 @@ M.mixin = function(dest) {
221
221
  module.exports = M;
222
222
 
223
223
 
224
- /***/ }),
224
+ /***/ },
225
225
 
226
- /***/ 193:
227
- /***/ ((module) => {
226
+ /***/ 193
227
+ (module) {
228
228
 
229
229
  var hex = {
230
230
  black: '#000',
@@ -248,10 +248,10 @@ function color(fg, isInverse) {
248
248
  module.exports = color;
249
249
 
250
250
 
251
- /***/ }),
251
+ /***/ },
252
252
 
253
- /***/ 251:
254
- /***/ ((__unused_webpack_module, exports) => {
253
+ /***/ 251
254
+ (__unused_webpack_module, exports) {
255
255
 
256
256
  /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
257
257
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
@@ -340,10 +340,10 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
340
340
  }
341
341
 
342
342
 
343
- /***/ }),
343
+ /***/ },
344
344
 
345
- /***/ 260:
346
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
345
+ /***/ 260
346
+ (module, __unused_webpack_exports, __webpack_require__) {
347
347
 
348
348
  var Transform = __webpack_require__(408);
349
349
 
@@ -379,10 +379,10 @@ logger.minilog = __webpack_require__(658);
379
379
  module.exports = logger;
380
380
 
381
381
 
382
- /***/ }),
382
+ /***/ },
383
383
 
384
- /***/ 287:
385
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
384
+ /***/ 287
385
+ (__unused_webpack_module, exports, __webpack_require__) {
386
386
 
387
387
  "use strict";
388
388
  var __webpack_unused_export__;
@@ -2494,10 +2494,10 @@ function BufferBigIntNotDefined () {
2494
2494
  }
2495
2495
 
2496
2496
 
2497
- /***/ }),
2497
+ /***/ },
2498
2498
 
2499
- /***/ 408:
2500
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2499
+ /***/ 408
2500
+ (module, __unused_webpack_exports, __webpack_require__) {
2501
2501
 
2502
2502
  var microee = __webpack_require__(173);
2503
2503
 
@@ -2573,18 +2573,18 @@ Transform.mixin = function(dest) {
2573
2573
  module.exports = Transform;
2574
2574
 
2575
2575
 
2576
- /***/ }),
2576
+ /***/ },
2577
2577
 
2578
- /***/ 523:
2579
- /***/ ((module) => {
2578
+ /***/ 523
2579
+ (module) {
2580
2580
 
2581
2581
  "use strict";
2582
2582
  module.exports = require("base64-js");
2583
2583
 
2584
- /***/ }),
2584
+ /***/ },
2585
2585
 
2586
- /***/ 557:
2587
- /***/ ((module, exports, __webpack_require__) => {
2586
+ /***/ 557
2587
+ (module, exports, __webpack_require__) {
2588
2588
 
2589
2589
  var Minilog = __webpack_require__(15);
2590
2590
 
@@ -2630,10 +2630,10 @@ exports.backends = {
2630
2630
  };
2631
2631
 
2632
2632
 
2633
- /***/ }),
2633
+ /***/ },
2634
2634
 
2635
- /***/ 638:
2636
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2635
+ /***/ 638
2636
+ (module, __unused_webpack_exports, __webpack_require__) {
2637
2637
 
2638
2638
  var Transform = __webpack_require__(408),
2639
2639
  color = __webpack_require__(193);
@@ -2655,10 +2655,10 @@ logger.pipe = function() { };
2655
2655
  module.exports = logger;
2656
2656
 
2657
2657
 
2658
- /***/ }),
2658
+ /***/ },
2659
2659
 
2660
- /***/ 658:
2661
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2660
+ /***/ 658
2661
+ (module, __unused_webpack_exports, __webpack_require__) {
2662
2662
 
2663
2663
  var Transform = __webpack_require__(408),
2664
2664
  color = __webpack_require__(193),
@@ -2688,17 +2688,17 @@ logger.pipe = function() { };
2688
2688
  module.exports = logger;
2689
2689
 
2690
2690
 
2691
- /***/ }),
2691
+ /***/ },
2692
2692
 
2693
- /***/ 680:
2694
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2693
+ /***/ 680
2694
+ (module, __unused_webpack_exports, __webpack_require__) {
2695
2695
 
2696
2696
  module.exports = __webpack_require__(14)("UklGRiYAAABXQVZFZm10IBAAAAABAAEAIlYAAESsAAACABAAZGF0YQIAAAAAAA==")
2697
2697
 
2698
- /***/ }),
2698
+ /***/ },
2699
2699
 
2700
- /***/ 692:
2701
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2700
+ /***/ 692
2701
+ (module, __unused_webpack_exports, __webpack_require__) {
2702
2702
 
2703
2703
  var Transform = __webpack_require__(408),
2704
2704
  cache = [ ];
@@ -2716,10 +2716,10 @@ logger.empty = function() { cache = []; };
2716
2716
  module.exports = logger;
2717
2717
 
2718
2718
 
2719
- /***/ }),
2719
+ /***/ },
2720
2720
 
2721
- /***/ 740:
2722
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2721
+ /***/ 740
2722
+ (module, __unused_webpack_exports, __webpack_require__) {
2723
2723
 
2724
2724
  var Transform = __webpack_require__(408);
2725
2725
 
@@ -2797,10 +2797,10 @@ AjaxLogger.jQueryWait = function(onDone) {
2797
2797
  module.exports = AjaxLogger;
2798
2798
 
2799
2799
 
2800
- /***/ }),
2800
+ /***/ },
2801
2801
 
2802
- /***/ 767:
2803
- /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
2802
+ /***/ 767
2803
+ (__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
2804
2804
 
2805
2805
  "use strict";
2806
2806
  (function(r){function x(){}function y(){}var z=String.fromCharCode,v={}.toString,A=v.call(r.SharedArrayBuffer),B=v(),q=r.Uint8Array,t=q||Array,w=q?ArrayBuffer:t,C=w.isView||function(g){return g&&"length"in g},D=v.call(w.prototype);w=y.prototype;var E=r.TextEncoder,a=new (q?Uint16Array:t)(32);x.prototype.decode=function(g){if(!C(g)){var l=v.call(g);if(l!==D&&l!==A&&l!==B)throw TypeError("Failed to execute 'decode' on 'TextDecoder': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'");
@@ -2811,824 +2811,14 @@ f.subarray(0,c):f.slice(0,c)};E||(r.TextDecoder=x,r.TextEncoder=y)})(""+void 0==
2811
2811
  //# sourceMappingURL=https://cdn.jsdelivr.net/gh/AnonyCo/FastestSmallestTextEncoderDecoder/EncoderDecoderTogether.min.js.map
2812
2812
 
2813
2813
 
2814
- /***/ }),
2814
+ /***/ },
2815
2815
 
2816
- /***/ 914:
2817
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2816
+ /***/ 914
2817
+ (module, __unused_webpack_exports, __webpack_require__) {
2818
2818
 
2819
2819
  module.exports = __webpack_require__(14)("PD94bWwgdmVyc2lvbj0iMS4wIj8+Cjxzdmcgd2lkdGg9IjEyOCIgaGVpZ2h0PSIxMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiA8Zz4KICA8cmVjdCBmaWxsPSIjQ0NDIiBoZWlnaHQ9IjEyOCIgd2lkdGg9IjEyOCIvPgogIDx0ZXh0IGZpbGw9ImJsYWNrIiB5PSIxMDciIHg9IjM1LjUiIGZvbnQtc2l6ZT0iMTI4Ij4/PC90ZXh0PgogPC9nPgo8L3N2Zz4K")
2820
2820
 
2821
- /***/ }),
2822
-
2823
- /***/ 945:
2824
- /***/ ((module, exports, __webpack_require__) => {
2825
-
2826
- // Save global object in a variable
2827
- var __global__ =
2828
- (typeof globalThis !== 'undefined' && globalThis) ||
2829
- (typeof self !== 'undefined' && self) ||
2830
- (typeof __webpack_require__.g !== 'undefined' && __webpack_require__.g);
2831
- // Create an object that extends from __global__ without the fetch function
2832
- var __globalThis__ = (function () {
2833
- function F() {
2834
- this.fetch = false;
2835
- this.DOMException = __global__.DOMException
2836
- }
2837
- F.prototype = __global__; // Needed for feature detection on whatwg-fetch's code
2838
- return new F();
2839
- })();
2840
- // Wraps whatwg-fetch with a function scope to hijack the global object
2841
- // "globalThis" that's going to be patched
2842
- (function(globalThis) {
2843
-
2844
- var irrelevant = (function (exports) {
2845
-
2846
- /* eslint-disable no-prototype-builtins */
2847
- var g =
2848
- (typeof globalThis !== 'undefined' && globalThis) ||
2849
- (typeof self !== 'undefined' && self) ||
2850
- // eslint-disable-next-line no-undef
2851
- (typeof __webpack_require__.g !== 'undefined' && __webpack_require__.g) ||
2852
- {};
2853
-
2854
- var support = {
2855
- searchParams: 'URLSearchParams' in g,
2856
- iterable: 'Symbol' in g && 'iterator' in Symbol,
2857
- blob:
2858
- 'FileReader' in g &&
2859
- 'Blob' in g &&
2860
- (function() {
2861
- try {
2862
- new Blob();
2863
- return true
2864
- } catch (e) {
2865
- return false
2866
- }
2867
- })(),
2868
- formData: 'FormData' in g,
2869
- arrayBuffer: 'ArrayBuffer' in g
2870
- };
2871
-
2872
- function isDataView(obj) {
2873
- return obj && DataView.prototype.isPrototypeOf(obj)
2874
- }
2875
-
2876
- if (support.arrayBuffer) {
2877
- var viewClasses = [
2878
- '[object Int8Array]',
2879
- '[object Uint8Array]',
2880
- '[object Uint8ClampedArray]',
2881
- '[object Int16Array]',
2882
- '[object Uint16Array]',
2883
- '[object Int32Array]',
2884
- '[object Uint32Array]',
2885
- '[object Float32Array]',
2886
- '[object Float64Array]'
2887
- ];
2888
-
2889
- var isArrayBufferView =
2890
- ArrayBuffer.isView ||
2891
- function(obj) {
2892
- return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
2893
- };
2894
- }
2895
-
2896
- function normalizeName(name) {
2897
- if (typeof name !== 'string') {
2898
- name = String(name);
2899
- }
2900
- if (/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {
2901
- throw new TypeError('Invalid character in header field name: "' + name + '"')
2902
- }
2903
- return name.toLowerCase()
2904
- }
2905
-
2906
- function normalizeValue(value) {
2907
- if (typeof value !== 'string') {
2908
- value = String(value);
2909
- }
2910
- return value
2911
- }
2912
-
2913
- // Build a destructive iterator for the value list
2914
- function iteratorFor(items) {
2915
- var iterator = {
2916
- next: function() {
2917
- var value = items.shift();
2918
- return {done: value === undefined, value: value}
2919
- }
2920
- };
2921
-
2922
- if (support.iterable) {
2923
- iterator[Symbol.iterator] = function() {
2924
- return iterator
2925
- };
2926
- }
2927
-
2928
- return iterator
2929
- }
2930
-
2931
- function Headers(headers) {
2932
- this.map = {};
2933
-
2934
- if (headers instanceof Headers) {
2935
- headers.forEach(function(value, name) {
2936
- this.append(name, value);
2937
- }, this);
2938
- } else if (Array.isArray(headers)) {
2939
- headers.forEach(function(header) {
2940
- if (header.length != 2) {
2941
- throw new TypeError('Headers constructor: expected name/value pair to be length 2, found' + header.length)
2942
- }
2943
- this.append(header[0], header[1]);
2944
- }, this);
2945
- } else if (headers) {
2946
- Object.getOwnPropertyNames(headers).forEach(function(name) {
2947
- this.append(name, headers[name]);
2948
- }, this);
2949
- }
2950
- }
2951
-
2952
- Headers.prototype.append = function(name, value) {
2953
- name = normalizeName(name);
2954
- value = normalizeValue(value);
2955
- var oldValue = this.map[name];
2956
- this.map[name] = oldValue ? oldValue + ', ' + value : value;
2957
- };
2958
-
2959
- Headers.prototype['delete'] = function(name) {
2960
- delete this.map[normalizeName(name)];
2961
- };
2962
-
2963
- Headers.prototype.get = function(name) {
2964
- name = normalizeName(name);
2965
- return this.has(name) ? this.map[name] : null
2966
- };
2967
-
2968
- Headers.prototype.has = function(name) {
2969
- return this.map.hasOwnProperty(normalizeName(name))
2970
- };
2971
-
2972
- Headers.prototype.set = function(name, value) {
2973
- this.map[normalizeName(name)] = normalizeValue(value);
2974
- };
2975
-
2976
- Headers.prototype.forEach = function(callback, thisArg) {
2977
- for (var name in this.map) {
2978
- if (this.map.hasOwnProperty(name)) {
2979
- callback.call(thisArg, this.map[name], name, this);
2980
- }
2981
- }
2982
- };
2983
-
2984
- Headers.prototype.keys = function() {
2985
- var items = [];
2986
- this.forEach(function(value, name) {
2987
- items.push(name);
2988
- });
2989
- return iteratorFor(items)
2990
- };
2991
-
2992
- Headers.prototype.values = function() {
2993
- var items = [];
2994
- this.forEach(function(value) {
2995
- items.push(value);
2996
- });
2997
- return iteratorFor(items)
2998
- };
2999
-
3000
- Headers.prototype.entries = function() {
3001
- var items = [];
3002
- this.forEach(function(value, name) {
3003
- items.push([name, value]);
3004
- });
3005
- return iteratorFor(items)
3006
- };
3007
-
3008
- if (support.iterable) {
3009
- Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
3010
- }
3011
-
3012
- function consumed(body) {
3013
- if (body._noBody) return
3014
- if (body.bodyUsed) {
3015
- return Promise.reject(new TypeError('Already read'))
3016
- }
3017
- body.bodyUsed = true;
3018
- }
3019
-
3020
- function fileReaderReady(reader) {
3021
- return new Promise(function(resolve, reject) {
3022
- reader.onload = function() {
3023
- resolve(reader.result);
3024
- };
3025
- reader.onerror = function() {
3026
- reject(reader.error);
3027
- };
3028
- })
3029
- }
3030
-
3031
- function readBlobAsArrayBuffer(blob) {
3032
- var reader = new FileReader();
3033
- var promise = fileReaderReady(reader);
3034
- reader.readAsArrayBuffer(blob);
3035
- return promise
3036
- }
3037
-
3038
- function readBlobAsText(blob) {
3039
- var reader = new FileReader();
3040
- var promise = fileReaderReady(reader);
3041
- var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type);
3042
- var encoding = match ? match[1] : 'utf-8';
3043
- reader.readAsText(blob, encoding);
3044
- return promise
3045
- }
3046
-
3047
- function readArrayBufferAsText(buf) {
3048
- var view = new Uint8Array(buf);
3049
- var chars = new Array(view.length);
3050
-
3051
- for (var i = 0; i < view.length; i++) {
3052
- chars[i] = String.fromCharCode(view[i]);
3053
- }
3054
- return chars.join('')
3055
- }
3056
-
3057
- function bufferClone(buf) {
3058
- if (buf.slice) {
3059
- return buf.slice(0)
3060
- } else {
3061
- var view = new Uint8Array(buf.byteLength);
3062
- view.set(new Uint8Array(buf));
3063
- return view.buffer
3064
- }
3065
- }
3066
-
3067
- function Body() {
3068
- this.bodyUsed = false;
3069
-
3070
- this._initBody = function(body) {
3071
- /*
3072
- fetch-mock wraps the Response object in an ES6 Proxy to
3073
- provide useful test harness features such as flush. However, on
3074
- ES5 browsers without fetch or Proxy support pollyfills must be used;
3075
- the proxy-pollyfill is unable to proxy an attribute unless it exists
3076
- on the object before the Proxy is created. This change ensures
3077
- Response.bodyUsed exists on the instance, while maintaining the
3078
- semantic of setting Request.bodyUsed in the constructor before
3079
- _initBody is called.
3080
- */
3081
- // eslint-disable-next-line no-self-assign
3082
- this.bodyUsed = this.bodyUsed;
3083
- this._bodyInit = body;
3084
- if (!body) {
3085
- this._noBody = true;
3086
- this._bodyText = '';
3087
- } else if (typeof body === 'string') {
3088
- this._bodyText = body;
3089
- } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
3090
- this._bodyBlob = body;
3091
- } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
3092
- this._bodyFormData = body;
3093
- } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
3094
- this._bodyText = body.toString();
3095
- } else if (support.arrayBuffer && support.blob && isDataView(body)) {
3096
- this._bodyArrayBuffer = bufferClone(body.buffer);
3097
- // IE 10-11 can't handle a DataView body.
3098
- this._bodyInit = new Blob([this._bodyArrayBuffer]);
3099
- } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
3100
- this._bodyArrayBuffer = bufferClone(body);
3101
- } else {
3102
- this._bodyText = body = Object.prototype.toString.call(body);
3103
- }
3104
-
3105
- if (!this.headers.get('content-type')) {
3106
- if (typeof body === 'string') {
3107
- this.headers.set('content-type', 'text/plain;charset=UTF-8');
3108
- } else if (this._bodyBlob && this._bodyBlob.type) {
3109
- this.headers.set('content-type', this._bodyBlob.type);
3110
- } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
3111
- this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
3112
- }
3113
- }
3114
- };
3115
-
3116
- if (support.blob) {
3117
- this.blob = function() {
3118
- var rejected = consumed(this);
3119
- if (rejected) {
3120
- return rejected
3121
- }
3122
-
3123
- if (this._bodyBlob) {
3124
- return Promise.resolve(this._bodyBlob)
3125
- } else if (this._bodyArrayBuffer) {
3126
- return Promise.resolve(new Blob([this._bodyArrayBuffer]))
3127
- } else if (this._bodyFormData) {
3128
- throw new Error('could not read FormData body as blob')
3129
- } else {
3130
- return Promise.resolve(new Blob([this._bodyText]))
3131
- }
3132
- };
3133
- }
3134
-
3135
- this.arrayBuffer = function() {
3136
- if (this._bodyArrayBuffer) {
3137
- var isConsumed = consumed(this);
3138
- if (isConsumed) {
3139
- return isConsumed
3140
- } else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
3141
- return Promise.resolve(
3142
- this._bodyArrayBuffer.buffer.slice(
3143
- this._bodyArrayBuffer.byteOffset,
3144
- this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
3145
- )
3146
- )
3147
- } else {
3148
- return Promise.resolve(this._bodyArrayBuffer)
3149
- }
3150
- } else if (support.blob) {
3151
- return this.blob().then(readBlobAsArrayBuffer)
3152
- } else {
3153
- throw new Error('could not read as ArrayBuffer')
3154
- }
3155
- };
3156
-
3157
- this.text = function() {
3158
- var rejected = consumed(this);
3159
- if (rejected) {
3160
- return rejected
3161
- }
3162
-
3163
- if (this._bodyBlob) {
3164
- return readBlobAsText(this._bodyBlob)
3165
- } else if (this._bodyArrayBuffer) {
3166
- return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
3167
- } else if (this._bodyFormData) {
3168
- throw new Error('could not read FormData body as text')
3169
- } else {
3170
- return Promise.resolve(this._bodyText)
3171
- }
3172
- };
3173
-
3174
- if (support.formData) {
3175
- this.formData = function() {
3176
- return this.text().then(decode)
3177
- };
3178
- }
3179
-
3180
- this.json = function() {
3181
- return this.text().then(JSON.parse)
3182
- };
3183
-
3184
- return this
3185
- }
3186
-
3187
- // HTTP methods whose capitalization should be normalized
3188
- var methods = ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'TRACE'];
3189
-
3190
- function normalizeMethod(method) {
3191
- var upcased = method.toUpperCase();
3192
- return methods.indexOf(upcased) > -1 ? upcased : method
3193
- }
3194
-
3195
- function Request(input, options) {
3196
- if (!(this instanceof Request)) {
3197
- throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.')
3198
- }
3199
-
3200
- options = options || {};
3201
- var body = options.body;
3202
-
3203
- if (input instanceof Request) {
3204
- if (input.bodyUsed) {
3205
- throw new TypeError('Already read')
3206
- }
3207
- this.url = input.url;
3208
- this.credentials = input.credentials;
3209
- if (!options.headers) {
3210
- this.headers = new Headers(input.headers);
3211
- }
3212
- this.method = input.method;
3213
- this.mode = input.mode;
3214
- this.signal = input.signal;
3215
- if (!body && input._bodyInit != null) {
3216
- body = input._bodyInit;
3217
- input.bodyUsed = true;
3218
- }
3219
- } else {
3220
- this.url = String(input);
3221
- }
3222
-
3223
- this.credentials = options.credentials || this.credentials || 'same-origin';
3224
- if (options.headers || !this.headers) {
3225
- this.headers = new Headers(options.headers);
3226
- }
3227
- this.method = normalizeMethod(options.method || this.method || 'GET');
3228
- this.mode = options.mode || this.mode || null;
3229
- this.signal = options.signal || this.signal || (function () {
3230
- if ('AbortController' in g) {
3231
- var ctrl = new AbortController();
3232
- return ctrl.signal;
3233
- }
3234
- }());
3235
- this.referrer = null;
3236
-
3237
- if ((this.method === 'GET' || this.method === 'HEAD') && body) {
3238
- throw new TypeError('Body not allowed for GET or HEAD requests')
3239
- }
3240
- this._initBody(body);
3241
-
3242
- if (this.method === 'GET' || this.method === 'HEAD') {
3243
- if (options.cache === 'no-store' || options.cache === 'no-cache') {
3244
- // Search for a '_' parameter in the query string
3245
- var reParamSearch = /([?&])_=[^&]*/;
3246
- if (reParamSearch.test(this.url)) {
3247
- // If it already exists then set the value with the current time
3248
- this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime());
3249
- } else {
3250
- // Otherwise add a new '_' parameter to the end with the current time
3251
- var reQueryString = /\?/;
3252
- this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime();
3253
- }
3254
- }
3255
- }
3256
- }
3257
-
3258
- Request.prototype.clone = function() {
3259
- return new Request(this, {body: this._bodyInit})
3260
- };
3261
-
3262
- function decode(body) {
3263
- var form = new FormData();
3264
- body
3265
- .trim()
3266
- .split('&')
3267
- .forEach(function(bytes) {
3268
- if (bytes) {
3269
- var split = bytes.split('=');
3270
- var name = split.shift().replace(/\+/g, ' ');
3271
- var value = split.join('=').replace(/\+/g, ' ');
3272
- form.append(decodeURIComponent(name), decodeURIComponent(value));
3273
- }
3274
- });
3275
- return form
3276
- }
3277
-
3278
- function parseHeaders(rawHeaders) {
3279
- var headers = new Headers();
3280
- // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
3281
- // https://tools.ietf.org/html/rfc7230#section-3.2
3282
- var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ');
3283
- // Avoiding split via regex to work around a common IE11 bug with the core-js 3.6.0 regex polyfill
3284
- // https://github.com/github/fetch/issues/748
3285
- // https://github.com/zloirock/core-js/issues/751
3286
- preProcessedHeaders
3287
- .split('\r')
3288
- .map(function(header) {
3289
- return header.indexOf('\n') === 0 ? header.substr(1, header.length) : header
3290
- })
3291
- .forEach(function(line) {
3292
- var parts = line.split(':');
3293
- var key = parts.shift().trim();
3294
- if (key) {
3295
- var value = parts.join(':').trim();
3296
- try {
3297
- headers.append(key, value);
3298
- } catch (error) {
3299
- console.warn('Response ' + error.message);
3300
- }
3301
- }
3302
- });
3303
- return headers
3304
- }
3305
-
3306
- Body.call(Request.prototype);
3307
-
3308
- function Response(bodyInit, options) {
3309
- if (!(this instanceof Response)) {
3310
- throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.')
3311
- }
3312
- if (!options) {
3313
- options = {};
3314
- }
3315
-
3316
- this.type = 'default';
3317
- this.status = options.status === undefined ? 200 : options.status;
3318
- if (this.status < 200 || this.status > 599) {
3319
- throw new RangeError("Failed to construct 'Response': The status provided (0) is outside the range [200, 599].")
3320
- }
3321
- this.ok = this.status >= 200 && this.status < 300;
3322
- this.statusText = options.statusText === undefined ? '' : '' + options.statusText;
3323
- this.headers = new Headers(options.headers);
3324
- this.url = options.url || '';
3325
- this._initBody(bodyInit);
3326
- }
3327
-
3328
- Body.call(Response.prototype);
3329
-
3330
- Response.prototype.clone = function() {
3331
- return new Response(this._bodyInit, {
3332
- status: this.status,
3333
- statusText: this.statusText,
3334
- headers: new Headers(this.headers),
3335
- url: this.url
3336
- })
3337
- };
3338
-
3339
- Response.error = function() {
3340
- var response = new Response(null, {status: 200, statusText: ''});
3341
- response.ok = false;
3342
- response.status = 0;
3343
- response.type = 'error';
3344
- return response
3345
- };
3346
-
3347
- var redirectStatuses = [301, 302, 303, 307, 308];
3348
-
3349
- Response.redirect = function(url, status) {
3350
- if (redirectStatuses.indexOf(status) === -1) {
3351
- throw new RangeError('Invalid status code')
3352
- }
3353
-
3354
- return new Response(null, {status: status, headers: {location: url}})
3355
- };
3356
-
3357
- exports.DOMException = g.DOMException;
3358
- try {
3359
- new exports.DOMException();
3360
- } catch (err) {
3361
- exports.DOMException = function(message, name) {
3362
- this.message = message;
3363
- this.name = name;
3364
- var error = Error(message);
3365
- this.stack = error.stack;
3366
- };
3367
- exports.DOMException.prototype = Object.create(Error.prototype);
3368
- exports.DOMException.prototype.constructor = exports.DOMException;
3369
- }
3370
-
3371
- function fetch(input, init) {
3372
- return new Promise(function(resolve, reject) {
3373
- var request = new Request(input, init);
3374
-
3375
- if (request.signal && request.signal.aborted) {
3376
- return reject(new exports.DOMException('Aborted', 'AbortError'))
3377
- }
3378
-
3379
- var xhr = new XMLHttpRequest();
3380
-
3381
- function abortXhr() {
3382
- xhr.abort();
3383
- }
3384
-
3385
- xhr.onload = function() {
3386
- var options = {
3387
- statusText: xhr.statusText,
3388
- headers: parseHeaders(xhr.getAllResponseHeaders() || '')
3389
- };
3390
- // This check if specifically for when a user fetches a file locally from the file system
3391
- // Only if the status is out of a normal range
3392
- if (request.url.indexOf('file://') === 0 && (xhr.status < 200 || xhr.status > 599)) {
3393
- options.status = 200;
3394
- } else {
3395
- options.status = xhr.status;
3396
- }
3397
- options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
3398
- var body = 'response' in xhr ? xhr.response : xhr.responseText;
3399
- setTimeout(function() {
3400
- resolve(new Response(body, options));
3401
- }, 0);
3402
- };
3403
-
3404
- xhr.onerror = function() {
3405
- setTimeout(function() {
3406
- reject(new TypeError('Network request failed'));
3407
- }, 0);
3408
- };
3409
-
3410
- xhr.ontimeout = function() {
3411
- setTimeout(function() {
3412
- reject(new TypeError('Network request timed out'));
3413
- }, 0);
3414
- };
3415
-
3416
- xhr.onabort = function() {
3417
- setTimeout(function() {
3418
- reject(new exports.DOMException('Aborted', 'AbortError'));
3419
- }, 0);
3420
- };
3421
-
3422
- function fixUrl(url) {
3423
- try {
3424
- return url === '' && g.location.href ? g.location.href : url
3425
- } catch (e) {
3426
- return url
3427
- }
3428
- }
3429
-
3430
- xhr.open(request.method, fixUrl(request.url), true);
3431
-
3432
- if (request.credentials === 'include') {
3433
- xhr.withCredentials = true;
3434
- } else if (request.credentials === 'omit') {
3435
- xhr.withCredentials = false;
3436
- }
3437
-
3438
- if ('responseType' in xhr) {
3439
- if (support.blob) {
3440
- xhr.responseType = 'blob';
3441
- } else if (
3442
- support.arrayBuffer
3443
- ) {
3444
- xhr.responseType = 'arraybuffer';
3445
- }
3446
- }
3447
-
3448
- if (init && typeof init.headers === 'object' && !(init.headers instanceof Headers || (g.Headers && init.headers instanceof g.Headers))) {
3449
- var names = [];
3450
- Object.getOwnPropertyNames(init.headers).forEach(function(name) {
3451
- names.push(normalizeName(name));
3452
- xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
3453
- });
3454
- request.headers.forEach(function(value, name) {
3455
- if (names.indexOf(name) === -1) {
3456
- xhr.setRequestHeader(name, value);
3457
- }
3458
- });
3459
- } else {
3460
- request.headers.forEach(function(value, name) {
3461
- xhr.setRequestHeader(name, value);
3462
- });
3463
- }
3464
-
3465
- if (request.signal) {
3466
- request.signal.addEventListener('abort', abortXhr);
3467
-
3468
- xhr.onreadystatechange = function() {
3469
- // DONE (success or failure)
3470
- if (xhr.readyState === 4) {
3471
- request.signal.removeEventListener('abort', abortXhr);
3472
- }
3473
- };
3474
- }
3475
-
3476
- xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
3477
- })
3478
- }
3479
-
3480
- fetch.polyfill = true;
3481
-
3482
- if (!g.fetch) {
3483
- g.fetch = fetch;
3484
- g.Headers = Headers;
3485
- g.Request = Request;
3486
- g.Response = Response;
3487
- }
3488
-
3489
- exports.Headers = Headers;
3490
- exports.Request = Request;
3491
- exports.Response = Response;
3492
- exports.fetch = fetch;
3493
-
3494
- return exports;
3495
-
3496
- })({});
3497
- })(__globalThis__);
3498
- // This is a ponyfill, so...
3499
- __globalThis__.fetch.ponyfill = true;
3500
- delete __globalThis__.fetch.polyfill;
3501
- // Choose between native implementation (__global__) or custom implementation (__globalThis__)
3502
- var ctx = __global__.fetch ? __global__ : __globalThis__;
3503
- exports = ctx.fetch // To enable: import fetch from 'cross-fetch'
3504
- exports["default"] = ctx.fetch // For TypeScript consumers without esModuleInterop.
3505
- exports.fetch = ctx.fetch // To enable: import {fetch} from 'cross-fetch'
3506
- exports.Headers = ctx.Headers
3507
- exports.Request = ctx.Request
3508
- exports.Response = ctx.Response
3509
- module.exports = exports
3510
-
3511
-
3512
- /***/ }),
3513
-
3514
- /***/ 953:
3515
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
3516
-
3517
- const crossFetch = __webpack_require__(945);
3518
-
3519
- /**
3520
- * Metadata header names
3521
- * @enum {string} The enum value is the name of the associated header.
3522
- * @readonly
3523
- */
3524
- const RequestMetadata = {
3525
- /** The ID of the project associated with this request */
3526
- ProjectId: 'X-Project-ID',
3527
- /** The ID of the project run associated with this request */
3528
- RunId: 'X-Run-ID'
3529
- };
3530
-
3531
- /**
3532
- * Metadata headers for requests
3533
- * @type {Headers}
3534
- */
3535
- const metadata = new crossFetch.Headers();
3536
-
3537
- /**
3538
- * Check if there is any metadata to apply.
3539
- * @returns {boolean} true if `metadata` has contents, or false if it is empty.
3540
- */
3541
- const hasMetadata = () => {
3542
- /* global self */
3543
- const searchParams = typeof self !== 'undefined' && self && self.location && self.location.search && self.location.search.split(/[?&]/) || [];
3544
- if (!searchParams.includes('scratchMetadata=1')) {
3545
- // for now, disable this feature unless scratchMetadata=1
3546
- // TODO: remove this check once we're sure the feature works correctly in production
3547
- return false;
3548
- }
3549
- for (const _ of metadata) {
3550
- return true;
3551
- }
3552
- return false;
3553
- };
3554
-
3555
- /**
3556
- * Non-destructively merge any metadata state (if any) with the provided options object (if any).
3557
- * If there is metadata state but no options object is provided, make a new object.
3558
- * If there is no metadata state, return the provided options parameter without modification.
3559
- * If there is metadata and an options object is provided, modify a copy and return it.
3560
- * Headers in the provided options object may override headers generated from metadata state.
3561
- * @param {RequestInit} [options] The initial request options. May be null or undefined.
3562
- * @returns {RequestInit|undefined} the provided options parameter without modification, or a new options object.
3563
- */
3564
- const applyMetadata = options => {
3565
- if (hasMetadata()) {
3566
- const augmentedOptions = Object.assign({}, options);
3567
- augmentedOptions.headers = new crossFetch.Headers(metadata);
3568
- if (options && options.headers) {
3569
- // the Fetch spec says options.headers could be:
3570
- // "A Headers object, an object literal, or an array of two-item arrays to set request's headers."
3571
- // turn it into a Headers object to be sure of how to interact with it
3572
- const overrideHeaders = options.headers instanceof crossFetch.Headers ? options.headers : new crossFetch.Headers(options.headers);
3573
- for (const [name, value] of overrideHeaders.entries()) {
3574
- augmentedOptions.headers.set(name, value);
3575
- }
3576
- }
3577
- return augmentedOptions;
3578
- }
3579
- return options;
3580
- };
3581
-
3582
- /**
3583
- * Make a network request.
3584
- * This is a wrapper for the global fetch method, adding some Scratch-specific functionality.
3585
- * @param {RequestInfo|URL} resource The resource to fetch.
3586
- * @param {RequestInit} options Optional object containing custom settings for this request.
3587
- * @see {@link https://developer.mozilla.org/docs/Web/API/fetch} for more about the fetch API.
3588
- * @returns {Promise<Response>} A promise for the response to the request.
3589
- */
3590
- const scratchFetch = (resource, options) => {
3591
- const augmentedOptions = applyMetadata(options);
3592
- return crossFetch(resource, augmentedOptions);
3593
- };
3594
-
3595
- /**
3596
- * Set the value of a named request metadata item.
3597
- * Setting the value to `null` or `undefined` will NOT remove the item.
3598
- * Use `unsetMetadata` for that.
3599
- * @param {RequestMetadata} name The name of the metadata item to set.
3600
- * @param {any} value The value to set (will be converted to a string).
3601
- */
3602
- const setMetadata = (name, value) => {
3603
- metadata.set(name, value);
3604
- };
3605
-
3606
- /**
3607
- * Remove a named request metadata item.
3608
- * @param {RequestMetadata} name The name of the metadata item to remove.
3609
- */
3610
- const unsetMetadata = name => {
3611
- metadata.delete(name);
3612
- };
3613
-
3614
- /**
3615
- * Retrieve a named request metadata item.
3616
- * Only for use in tests. At the time of writing, used in scratch-vm tests.
3617
- * @param {RequestMetadata} name The name of the metadata item to retrieve.
3618
- * @returns {any} value The value of the metadata item, or `undefined` if it was not found.
3619
- */
3620
- const getMetadata = name => metadata.get(name);
3621
- module.exports = {
3622
- Headers: crossFetch.Headers,
3623
- RequestMetadata,
3624
- applyMetadata,
3625
- scratchFetch,
3626
- setMetadata,
3627
- unsetMetadata,
3628
- getMetadata
3629
- };
3630
-
3631
- /***/ })
2821
+ /***/ }
3632
2822
 
3633
2823
  /******/ });
3634
2824
  /************************************************************************/
@@ -3686,7 +2876,7 @@ module.exports = {
3686
2876
  /******/ // This function allow to reference async chunks
3687
2877
  /******/ __webpack_require__.u = (chunkId) => {
3688
2878
  /******/ // return url for filenames based on template
3689
- /******/ return "chunks/" + "fetch-worker" + "." + "56da39b0f4bad6747138" + ".js";
2879
+ /******/ return "chunks/" + "fetch-worker" + "." + "7afe4ade866d6f6a3cb3" + ".js";
3690
2880
  /******/ };
3691
2881
  /******/ })();
3692
2882
  /******/
@@ -3745,6 +2935,20 @@ __webpack_require__.d(__webpack_exports__, {
3745
2935
  ScratchStorage: () => (/* reexport */ ScratchStorage)
3746
2936
  });
3747
2937
 
2938
+ // NAMESPACE OBJECT: ./src/scratchFetch.ts
2939
+ var scratchFetch_namespaceObject = {};
2940
+ __webpack_require__.r(scratchFetch_namespaceObject);
2941
+ __webpack_require__.d(scratchFetch_namespaceObject, {
2942
+ Headers: () => (Headers),
2943
+ RequestMetadata: () => (RequestMetadata),
2944
+ applyMetadata: () => (applyMetadata),
2945
+ getMetadata: () => (getMetadata),
2946
+ hasMetadata: () => (hasMetadata),
2947
+ scratchFetch: () => (scratchFetch),
2948
+ setMetadata: () => (setMetadata),
2949
+ unsetMetadata: () => (unsetMetadata)
2950
+ });
2951
+
3748
2952
  // EXTERNAL MODULE: ./node_modules/minilog/lib/web/index.js
3749
2953
  var web = __webpack_require__(557);
3750
2954
  var web_default = /*#__PURE__*/__webpack_require__.n(web);
@@ -4135,9 +3339,295 @@ class BuiltinHelper extends Helper {
4135
3339
  return Promise.resolve(this.get(assetId));
4136
3340
  }
4137
3341
  }
4138
- // EXTERNAL MODULE: ./src/scratchFetch.js
4139
- var scratchFetch = __webpack_require__(953);
4140
- var scratchFetch_default = /*#__PURE__*/__webpack_require__.n(scratchFetch);
3342
+ ;// ./node_modules/@scratch/task-herder/dist/task-herder.js
3343
+ const CancelReason = {
3344
+ QueueCostLimitExceeded: "Queue cost limit exceeded",
3345
+ Aborted: "Task aborted",
3346
+ Cancel: "Task cancelled",
3347
+ TaskTooExpensive: "Task cost exceeds maximum bucket size"
3348
+ };
3349
+ function PromiseWithResolvers() {
3350
+ let e, t;
3351
+ return {
3352
+ promise: new Promise((n, r) => {
3353
+ e = n, t = r;
3354
+ }),
3355
+ resolve: e,
3356
+ reject: t
3357
+ };
3358
+ }
3359
+ var TaskRecord = class {
3360
+ cost;
3361
+ promise;
3362
+ run;
3363
+ cancel;
3364
+ constructor(e, n = {}) {
3365
+ this.cost = n.cost ?? 1;
3366
+ let { promise: r, resolve: i, reject: a } = PromiseWithResolvers();
3367
+ this.promise = r, this.cancel = (e) => {
3368
+ a(e);
3369
+ }, this.run = async () => {
3370
+ try {
3371
+ i(await e());
3372
+ } catch (e) {
3373
+ a(e);
3374
+ }
3375
+ };
3376
+ }
3377
+ }, TaskQueue = class {
3378
+ burstLimit;
3379
+ sustainRate;
3380
+ queueCostLimit;
3381
+ concurrencyLimit;
3382
+ tokenCount;
3383
+ runningTasks = 0;
3384
+ pendingTaskRecords = [];
3385
+ lastRefillTime = Date.now();
3386
+ onTaskAdded = PromiseWithResolvers().resolve;
3387
+ onTaskFinished = PromiseWithResolvers().resolve;
3388
+ constructor(e) {
3389
+ this.burstLimit = e.burstLimit, this.sustainRate = e.sustainRate, this.tokenCount = e.startingTokens ?? e.burstLimit, this.queueCostLimit = e.queueCostLimit ?? Infinity, this.concurrencyLimit = e.concurrency ?? 1, this.runTasks();
3390
+ }
3391
+ get length() {
3392
+ return this.pendingTaskRecords.length;
3393
+ }
3394
+ get options() {
3395
+ return {
3396
+ burstLimit: this.burstLimit,
3397
+ sustainRate: this.sustainRate,
3398
+ startingTokens: this.tokenCount,
3399
+ queueCostLimit: this.queueCostLimit,
3400
+ concurrency: this.concurrencyLimit
3401
+ };
3402
+ }
3403
+ do(t, r = {}) {
3404
+ let i = new TaskRecord(t, r);
3405
+ return i.cost > this.burstLimit ? Promise.reject(Error(CancelReason.TaskTooExpensive)) : this.queueCostLimit < Infinity && this.pendingTaskRecords.reduce((e, t) => e + t.cost, i.cost) > this.queueCostLimit ? Promise.reject(Error(CancelReason.QueueCostLimitExceeded)) : (this.pendingTaskRecords.push(i), r.signal?.addEventListener("abort", () => {
3406
+ this.cancel(i.promise, Error(CancelReason.Aborted));
3407
+ }), this.onTaskAdded(), i.promise);
3408
+ }
3409
+ cancel(t, n) {
3410
+ let r = this.pendingTaskRecords.findIndex((e) => e.promise === t);
3411
+ if (r !== -1) {
3412
+ let [t] = this.pendingTaskRecords.splice(r, 1);
3413
+ return t.cancel(n ?? Error(CancelReason.Cancel)), !0;
3414
+ }
3415
+ return !1;
3416
+ }
3417
+ cancelAll(t) {
3418
+ let n = this.pendingTaskRecords;
3419
+ return this.pendingTaskRecords = [], t ??= Error(CancelReason.Cancel), n.forEach((e) => {
3420
+ e.cancel(t);
3421
+ }), n.length;
3422
+ }
3423
+ refillAndSpend(e) {
3424
+ return this.refill(), this.spend(e);
3425
+ }
3426
+ refill() {
3427
+ let e = Date.now(), t = e - this.lastRefillTime;
3428
+ if (t <= 0) return;
3429
+ this.lastRefillTime = e;
3430
+ let n = t / 1e3 * this.sustainRate;
3431
+ this.tokenCount = Math.min(this.burstLimit, this.tokenCount + n);
3432
+ }
3433
+ spend(e) {
3434
+ return this.tokenCount >= e ? (this.tokenCount -= e, !0) : !1;
3435
+ }
3436
+ async runTasks() {
3437
+ for (;;) {
3438
+ let n = this.pendingTaskRecords.shift();
3439
+ if (!n) {
3440
+ let { promise: e, resolve: n } = PromiseWithResolvers();
3441
+ this.onTaskAdded = n, await e;
3442
+ continue;
3443
+ }
3444
+ if (n.cost > this.burstLimit) {
3445
+ n.cancel(Error(CancelReason.TaskTooExpensive));
3446
+ continue;
3447
+ }
3448
+ if (this.refillAndSpend(n.cost)) {
3449
+ if (this.runningTasks >= this.concurrencyLimit) {
3450
+ let { promise: e, resolve: n } = PromiseWithResolvers();
3451
+ this.onTaskFinished = n, await e;
3452
+ }
3453
+ this.runTask(n);
3454
+ } else {
3455
+ this.pendingTaskRecords.unshift(n);
3456
+ let e = Math.max(n.cost - this.tokenCount, 0), t = Math.ceil(1e3 * e / this.sustainRate);
3457
+ await new Promise((e) => setTimeout(e, t));
3458
+ }
3459
+ }
3460
+ }
3461
+ async runTask(e) {
3462
+ this.runningTasks++;
3463
+ try {
3464
+ await e.run();
3465
+ } finally {
3466
+ this.runningTasks--, this.onTaskFinished();
3467
+ }
3468
+ }
3469
+ }, QueueManager = class {
3470
+ queues;
3471
+ defaultOptions;
3472
+ constructor(e, t) {
3473
+ this.queues = new Map(t), this.defaultOptions = e;
3474
+ }
3475
+ create(e, t = {}) {
3476
+ let n = new TaskQueue({
3477
+ ...this.defaultOptions,
3478
+ ...t
3479
+ });
3480
+ return this.queues.set(e, n), n;
3481
+ }
3482
+ get(e) {
3483
+ return this.queues.get(e);
3484
+ }
3485
+ getOrCreate(e, t = {}) {
3486
+ return this.get(e) ?? this.create(e, t);
3487
+ }
3488
+ options() {
3489
+ return { ...this.defaultOptions };
3490
+ }
3491
+ };
3492
+
3493
+
3494
+ ;// ./src/HostQueues.ts
3495
+
3496
+ /**
3497
+ * @summary A set of generous limits, for things like downloading assets from CDN.
3498
+ * @description
3499
+ * In practice, these limits seem to lead to slightly better performance than no limits at all, mostly due to the
3500
+ * concurrency limit. For example, on my development computer & my relatively fast residential connection, a
3501
+ * concurrency limit of 4 loads a particular test project in 21 seconds, as opposed to 25 seconds when I bypass the
3502
+ * queue and call `fetch` directly. In that test, my setup downloads about 50 assets per second, so this set of options
3503
+ * only affects concurrency and doesn't actually throttle the downloads. Limiting concurrency also fixes the issue
3504
+ * where very large projects (thousands of assets) can lead to browser failures like `net::ERR_INSUFFICIENT_RESOURCES`.
3505
+ * The exact concurrency limit doesn't seem to matter much since the browser limits parallel connections itself. It
3506
+ * just needs to be high enough to avoid bubbles in the download pipeline and low enough to avoid resource exhaustion.
3507
+ * @see {@link https://github.com/scratchfoundation/scratch-gui/issues/7111}
3508
+ */
3509
+ const AssetQueueOptions = {
3510
+ burstLimit: 64,
3511
+ sustainRate: 64,
3512
+ // WARNING: asset download concurrency >=5 can lead to corrupted buffers on Chrome (December 2025, Chrome 142.0)
3513
+ // when using Scratch's bitmap load pipeline. Marking the canvas context as `{willReadFrequently: true}` seems to
3514
+ // eliminate that issue, so maybe the problem is related to hardware acceleration.
3515
+ concurrency: 64
3516
+ };
3517
+ /**
3518
+ * Central registry of per-host queues.
3519
+ * Uses strict limits by default. Override these strict limits as needed for specific hosts.
3520
+ */
3521
+ const hostQueueManager = new QueueManager({
3522
+ burstLimit: 5,
3523
+ sustainRate: 1,
3524
+ concurrency: 1
3525
+ });
3526
+ ;// ./src/scratchFetch.ts
3527
+
3528
+ const Headers = globalThis.Headers;
3529
+ /**
3530
+ * Metadata header names.
3531
+ * The enum value is the name of the associated header.
3532
+ */
3533
+ var RequestMetadata;
3534
+ (function (RequestMetadata) {
3535
+ /** The ID of the project associated with this request */
3536
+ RequestMetadata["ProjectId"] = "X-Project-ID";
3537
+ /** The ID of the project run associated with this request */
3538
+ RequestMetadata["RunId"] = "X-Run-ID";
3539
+ })(RequestMetadata || (RequestMetadata = {}));
3540
+ /**
3541
+ * Metadata headers for requests.
3542
+ */
3543
+ const metadata = new Headers();
3544
+ /**
3545
+ * Check if there is any metadata to apply.
3546
+ * @returns {boolean} true if `metadata` has contents, or false if it is empty.
3547
+ */
3548
+ const hasMetadata = () => {
3549
+ const searchParams = typeof self !== 'undefined' && self && self.location && self.location.search && self.location.search.split(/[?&]/) || [];
3550
+ if (!searchParams.includes('scratchMetadata=1')) {
3551
+ // for now, disable this feature unless scratchMetadata=1
3552
+ // TODO: remove this check once we're sure the feature works correctly in production
3553
+ return false;
3554
+ }
3555
+ for (const _ of metadata) {
3556
+ return true;
3557
+ }
3558
+ return false;
3559
+ };
3560
+ /**
3561
+ * Non-destructively merge any metadata state (if any) with the provided options object (if any).
3562
+ * If there is metadata state but no options object is provided, make a new object.
3563
+ * If there is no metadata state, return the provided options parameter without modification.
3564
+ * If there is metadata and an options object is provided, modify a copy and return it.
3565
+ * Headers in the provided options object may override headers generated from metadata state.
3566
+ * @param {RequestInit} [options] The initial request options. May be null or undefined.
3567
+ * @returns {RequestInit|undefined} the provided options parameter without modification, or a new options object.
3568
+ */
3569
+ const applyMetadata = options => {
3570
+ if (hasMetadata()) {
3571
+ const augmentedOptions = Object.assign({}, options);
3572
+ augmentedOptions.headers = new Headers(metadata);
3573
+ if (options && options.headers) {
3574
+ // the Fetch spec says options.headers could be:
3575
+ // "A Headers object, an object literal, or an array of two-item arrays to set request's headers."
3576
+ // turn it into a Headers object to be sure of how to interact with it
3577
+ const overrideHeaders = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
3578
+ for (const [name, value] of overrideHeaders.entries()) {
3579
+ augmentedOptions.headers.set(name, value);
3580
+ }
3581
+ }
3582
+ return augmentedOptions;
3583
+ }
3584
+ return options;
3585
+ };
3586
+ /**
3587
+ * Make a network request.
3588
+ * This is a wrapper for the global fetch method, adding some Scratch-specific functionality.
3589
+ * @param {RequestInfo|URL} resource The resource to fetch.
3590
+ * @param {RequestInit} [requestOptions] Optional object containing custom settings for this request.
3591
+ * @param {ScratchFetchOptions} [scratchOptions] Optional Scratch-specific settings for this request.
3592
+ * @see {@link https://developer.mozilla.org/docs/Web/API/fetch} for more about the fetch API.
3593
+ * @returns {Promise<Response>} A promise for the response to the request.
3594
+ */
3595
+ const scratchFetch = (resource, requestOptions, scratchOptions) => {
3596
+ requestOptions = applyMetadata(requestOptions);
3597
+ let queueName = scratchOptions === null || scratchOptions === void 0 ? void 0 : scratchOptions.queueName;
3598
+ if (!queueName) {
3599
+ // Normalize resource to a Request object. The `fetch` call will do this anyway, so it's not much extra work,
3600
+ // but it guarantees availability of the URL for queue naming.
3601
+ resource = new Request(resource, requestOptions);
3602
+ queueName = new URL(resource.url).hostname;
3603
+ }
3604
+ const queue = hostQueueManager.getOrCreate(queueName, scratchOptions === null || scratchOptions === void 0 ? void 0 : scratchOptions.queueOptions);
3605
+ return queue.do(() => fetch(resource, requestOptions));
3606
+ };
3607
+ /**
3608
+ * Set the value of a named request metadata item.
3609
+ * Setting the value to `null` or `undefined` will NOT remove the item.
3610
+ * Use `unsetMetadata` for that.
3611
+ * @param {RequestMetadata} name The name of the metadata item to set.
3612
+ * @param {any} value The value to set (will be converted to a string).
3613
+ */
3614
+ const setMetadata = (name, value) => {
3615
+ metadata.set(name, value);
3616
+ };
3617
+ /**
3618
+ * Remove a named request metadata item.
3619
+ * @param {RequestMetadata} name The name of the metadata item to remove.
3620
+ */
3621
+ const unsetMetadata = name => {
3622
+ metadata.delete(name);
3623
+ };
3624
+ /**
3625
+ * Retrieve a named request metadata item.
3626
+ * Only for use in tests. At the time of writing, used in scratch-vm tests.
3627
+ * @param {RequestMetadata} name The name of the metadata item to retrieve.
3628
+ * @returns {string|null} The value of the metadata item, or `null` if it was not found.
3629
+ */
3630
+ const getMetadata = name => metadata.get(name);
4141
3631
  ;// ./src/FetchWorkerTool.ts
4142
3632
  const _excluded = ["url"];
4143
3633
  function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
@@ -4238,14 +3728,14 @@ class PrivateFetchWorkerTool {
4238
3728
  return new Promise((resolve, reject) => {
4239
3729
  // TODO: Use a Scratch standard ID generator ...
4240
3730
  const id = Math.random().toString(16).substring(2);
4241
- const augmentedOptions = (0,scratchFetch.applyMetadata)(Object.assign({
3731
+ const augmentedOptions = applyMetadata(Object.assign({
4242
3732
  method: 'GET'
4243
3733
  }, options));
4244
3734
  // the Fetch spec says options.headers could be:
4245
3735
  // "A Headers object, an object literal, or an array of two-item arrays to set request's headers."
4246
3736
  // structured clone (postMessage) doesn't support Headers objects
4247
3737
  // so turn it into an array of two-item arrays to make it to the worker intact
4248
- if (augmentedOptions && augmentedOptions.headers instanceof scratchFetch.Headers) {
3738
+ if (augmentedOptions && augmentedOptions.headers instanceof Headers) {
4249
3739
  augmentedOptions.headers = Array.from(augmentedOptions.headers.entries());
4250
3740
  }
4251
3741
  worker.postMessage({
@@ -4337,6 +3827,7 @@ const FetchTool_excluded = ["url"],
4337
3827
  function FetchTool_objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = FetchTool_objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
4338
3828
  function FetchTool_objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
4339
3829
 
3830
+
4340
3831
  /**
4341
3832
  * @typedef {Request & {withCredentials: boolean}} ScratchSendRequest
4342
3833
  */
@@ -4362,9 +3853,11 @@ class FetchTool {
4362
3853
  url
4363
3854
  } = _ref,
4364
3855
  options = FetchTool_objectWithoutProperties(_ref, FetchTool_excluded);
4365
- return (0,scratchFetch.scratchFetch)(url, Object.assign({
3856
+ return scratchFetch(url, Object.assign({
4366
3857
  method: 'GET'
4367
- }, options)).then(result => {
3858
+ }, options), {
3859
+ queueOptions: AssetQueueOptions
3860
+ }).then(result => {
4368
3861
  if (result.ok) return result.arrayBuffer().then(b => new Uint8Array(b));
4369
3862
  if (result.status === 404) return null;
4370
3863
  return Promise.reject(result.status); // TODO: we should throw a proper error
@@ -4389,9 +3882,11 @@ class FetchTool {
4389
3882
  withCredentials = false
4390
3883
  } = _ref2,
4391
3884
  options = FetchTool_objectWithoutProperties(_ref2, _excluded2);
4392
- return (0,scratchFetch.scratchFetch)(url, Object.assign({
3885
+ return scratchFetch(url, Object.assign({
4393
3886
  credentials: withCredentials ? 'include' : 'omit'
4394
- }, options)).then(response => {
3887
+ }, options), {
3888
+ queueOptions: AssetQueueOptions
3889
+ }).then(response => {
4395
3890
  if (response.ok) return response.text();
4396
3891
  return Promise.reject(response.status);
4397
3892
  });
@@ -4713,7 +4208,7 @@ class ScratchStorage {
4713
4208
  * @returns {module} the scratchFetch module, with properties for `scratchFetch`, `setMetadata`, etc.
4714
4209
  */
4715
4210
  get scratchFetch() {
4716
- return (scratchFetch_default());
4211
+ return scratchFetch_namespaceObject;
4717
4212
  }
4718
4213
  /**
4719
4214
  * @deprecated Please use the `Asset` member of a storage instance instead.