@shgysk8zer0/polyfills 0.3.0 → 0.3.2

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.
package/array.js CHANGED
@@ -1,267 +1,369 @@
1
- (function() {
2
- 'use strict';
3
-
4
- /**
5
- * @SEE https://github.com/tc39/proposal-relative-indexing-method#polyfill
6
- * @SEE https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
7
- */
8
-
9
- const SHIM_TARGETS = [Array, String, globalThis.Int8Array, globalThis.Uint8Array,
10
- globalThis.Uint8ClampedArray, globalThis.Int16Array, globalThis.Uint16Array,
11
- globalThis.Int32Array, globalThis.Uint32Array, globalThis.Float32Array,
12
- globalThis.Float64Array, globalThis.BigInt64Array, globalThis.BigUint64Array,
13
- ];
14
-
15
- if (! (Array.prototype.flat instanceof Function)) {
16
- Array.prototype.flat = function(depth = 1) {
17
- const result = [];
18
- depth = Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, depth));
19
-
20
- const flattenFn = (item, depth) => {
21
- if (Array.isArray(item) && depth >= 0) {
22
- item.forEach(i => flattenFn(i, depth - 1));
23
- } else {
24
- result.push(item);
25
- }
26
- };
1
+ /**
2
+ * @SEE https://github.com/tc39/proposal-relative-indexing-method#polyfill
3
+ * @SEE https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
4
+ */
27
5
 
28
- flattenFn(this, Number.isNaN(depth) ? 0 : depth);
29
- return result;
30
- };
31
- }
6
+ const SHIM_TARGETS = [Array, String, globalThis.Int8Array, globalThis.Uint8Array,
7
+ globalThis.Uint8ClampedArray, globalThis.Int16Array, globalThis.Uint16Array,
8
+ globalThis.Int32Array, globalThis.Uint32Array, globalThis.Float32Array,
9
+ globalThis.Float64Array, globalThis.BigInt64Array, globalThis.BigUint64Array,
10
+ ];
11
+
12
+ if (! (Array.prototype.flat instanceof Function)) {
13
+ Array.prototype.flat = function(depth = 1) {
14
+ const result = [];
15
+ depth = Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, depth));
32
16
 
33
- if (! (Array.prototype.flatMap instanceof Function)) {
34
- Array.prototype.flatMap = function(cb, thisArg) {
35
- return this.map(cb, thisArg).flat(1);
17
+ const flattenFn = (item, depth) => {
18
+ if (Array.isArray(item) && depth >= 0) {
19
+ item.forEach(i => flattenFn(i, depth - 1));
20
+ } else {
21
+ result.push(item);
22
+ }
36
23
  };
37
- }
38
24
 
39
- if (! (Array.prototype.findLast instanceof Function)) {
40
- Array.prototype.findLast = function(callback, thisArg) {
41
- let found = undefined;
25
+ flattenFn(this, Number.isNaN(depth) ? 0 : depth);
26
+ return result;
27
+ };
28
+ }
42
29
 
43
- this.forEach((item, index, arr) => {
44
- if (callback.call(thisArg, item, index, arr)) {
45
- found = item;
46
- }
47
- }, thisArg);
30
+ if (! (Array.prototype.flatMap instanceof Function)) {
31
+ Array.prototype.flatMap = function(cb, thisArg) {
32
+ return this.map(cb, thisArg).flat(1);
33
+ };
34
+ }
48
35
 
49
- return found;
50
- };
51
- }
36
+ if (! (Array.prototype.findLast instanceof Function)) {
37
+ Array.prototype.findLast = function(callback, thisArg) {
38
+ let found = undefined;
52
39
 
53
- if(! ('lastIndex' in Array.prototype)) {
54
- Object.defineProperty(Array.prototype, 'lastIndex', {
55
- enumerable: false,
56
- configurable: false,
57
- get: function() {
58
- return Math.max(0, this.length - 1);
40
+ this.forEach((item, index, arr) => {
41
+ if (callback.call(thisArg, item, index, arr)) {
42
+ found = item;
59
43
  }
60
- });
61
- }
44
+ }, thisArg);
62
45
 
63
- if(! ('lastItem' in Array.prototype)) {
64
- Object.defineProperty(Array.prototype, 'lastItem', {
65
- enumerable: false,
66
- configurable: false,
67
- get: function() {
68
- return this[this.lastIndex];
69
- },
70
- set: function(val) {
71
- this[this.lastIndex] = val;
72
- }
73
- });
74
- }
46
+ return found;
47
+ };
48
+ }
75
49
 
76
- if (! (Array.prototype.findLastIndex instanceof Function)) {
77
- Array.prototype.findLastIndex = function(callback, thisArg) {
78
- let found = -1;
79
-
80
- this.forEach((item, index, arr) => {
81
- if (callback.call(thisArg, item, index, arr)) {
82
- found = index;
83
- }
84
- }, thisArg);
50
+ if(! ('lastIndex' in Array.prototype)) {
51
+ Object.defineProperty(Array.prototype, 'lastIndex', {
52
+ enumerable: false,
53
+ configurable: false,
54
+ get: function() {
55
+ return Math.max(0, this.length - 1);
56
+ }
57
+ });
58
+ }
85
59
 
86
- return found;
87
- };
88
- }
60
+ if(! ('lastItem' in Array.prototype)) {
61
+ Object.defineProperty(Array.prototype, 'lastItem', {
62
+ enumerable: false,
63
+ configurable: false,
64
+ get: function() {
65
+ return this[this.lastIndex];
66
+ },
67
+ set: function(val) {
68
+ this[this.lastIndex] = val;
69
+ }
70
+ });
71
+ }
89
72
 
90
- if (! (Array.prototype.at instanceof Function)) {
91
- const at = function at(n) {
92
- n = Math.trunc(n) || 0;
93
- if (n < 0) n += this.length;
94
- if (n < 0 || n >= this.length) return undefined;
95
- return this[n];
96
- };
73
+ if (! (Array.prototype.findLastIndex instanceof Function)) {
74
+ Array.prototype.findLastIndex = function(callback, thisArg) {
75
+ let found = -1;
97
76
 
98
- for (const C of SHIM_TARGETS) {
99
- if (typeof C !== 'undefined') {
100
- Object.defineProperty(C.prototype, 'at', {
101
- value: at,
102
- writable: true,
103
- enumerable: false,
104
- configurable: true
105
- });
77
+ this.forEach((item, index, arr) => {
78
+ if (callback.call(thisArg, item, index, arr)) {
79
+ found = index;
106
80
  }
81
+ }, thisArg);
82
+
83
+ return found;
84
+ };
85
+ }
86
+
87
+ if (! (Array.prototype.at instanceof Function)) {
88
+ const at = function at(n) {
89
+ n = Math.trunc(n) || 0;
90
+ if (n < 0) n += this.length;
91
+ if (n < 0 || n >= this.length) return undefined;
92
+ return this[n];
93
+ };
94
+
95
+ for (const C of SHIM_TARGETS) {
96
+ if (typeof C !== 'undefined') {
97
+ Object.defineProperty(C.prototype, 'at', {
98
+ value: at,
99
+ writable: true,
100
+ enumerable: false,
101
+ configurable: true
102
+ });
107
103
  }
108
104
  }
105
+ }
109
106
 
110
- /**
111
- * @deprecated [moved to `Object.groupBy()`]
112
- * @see https://github.com/tc39/proposal-array-grouping
113
- */
114
- if (! (Array.prototype.group instanceof Function) && Object.groupBy instanceof Function) {
115
- Array.prototype.group = function group(callback) {
116
- console.warn('`Array.group()` is deprecated. Please use `Object.groupBy()` instead.');
117
- return Object.groupBy(this, callback);
118
- };
119
- }
107
+ /**
108
+ * @deprecated [moved to `Object.groupBy()`]
109
+ * @see https://github.com/tc39/proposal-array-grouping
110
+ */
111
+ if (! (Array.prototype.group instanceof Function) && Object.groupBy instanceof Function) {
112
+ Array.prototype.group = function group(callback) {
113
+ console.warn('`Array.group()` is deprecated. Please use `Object.groupBy()` instead.');
114
+ return Object.groupBy(this, callback);
115
+ };
116
+ }
120
117
 
121
- /**
122
- * @deprecated [moved to `Object.groupBy()`]
123
- */
124
- if (! (Array.prototype.groupBy instanceof Function) && Object.groupBy instanceof Function) {
125
- Array.prototype.groupBy = function groupBy(callback) {
126
- console.warn('`Array.goupBy()` is deprecated. Please use `Object.groupBy()` instead.');
127
- return Object.groupBy(this, callback);
128
- };
129
- }
118
+ /**
119
+ * @deprecated [moved to `Object.groupBy()`]
120
+ */
121
+ if (! (Array.prototype.groupBy instanceof Function) && Object.groupBy instanceof Function) {
122
+ Array.prototype.groupBy = function groupBy(callback) {
123
+ console.warn('`Array.goupBy()` is deprecated. Please use `Object.groupBy()` instead.');
124
+ return Object.groupBy(this, callback);
125
+ };
126
+ }
130
127
 
131
- /**
132
- * @see https://github.com/tc39/proposal-array-grouping
133
- * @deprecated [moved to `Map.groupBy()`]
134
- * @requires `Map.prototype.emplace`
135
- */
136
- if (! (Array.prototype.groupToMap instanceof Function) && (Map.groupBy instanceof Function)) {
137
- Array.prototype.groupToMap = function groupToMap(callback) {
138
- console.warn('`Array.groupToMap()` is deprecated. Please use `Map.groupBy()` instead.');
139
- return Map.groupBy(this, callback);
140
- };
141
- }
128
+ /**
129
+ * @see https://github.com/tc39/proposal-array-grouping
130
+ * @deprecated [moved to `Map.groupBy()`]
131
+ * @requires `Map.prototype.emplace`
132
+ */
133
+ if (! (Array.prototype.groupToMap instanceof Function) && (Map.groupBy instanceof Function)) {
134
+ Array.prototype.groupToMap = function groupToMap(callback) {
135
+ console.warn('`Array.groupToMap()` is deprecated. Please use `Map.groupBy()` instead.');
136
+ return Map.groupBy(this, callback);
137
+ };
138
+ }
142
139
 
143
- /**
144
- * @deprecated [moved to `Map.groupBy()`]
145
- */
146
- if (Map.groupBy instanceof Function) {
147
- Array.prototype.groupByToMap = function groupByToMap(callback) {
148
- console.warn('`Array.groupByToMap()` is deprecated. Please use `Map.groupBy()` instead.');
149
- return Map.groupBy(this, callback);
150
- };
151
- }
140
+ /**
141
+ * @deprecated [moved to `Map.groupBy()`]
142
+ */
143
+ if (Map.groupBy instanceof Function) {
144
+ Array.prototype.groupByToMap = function groupByToMap(callback) {
145
+ console.warn('`Array.groupByToMap()` is deprecated. Please use `Map.groupBy()` instead.');
146
+ return Map.groupBy(this, callback);
147
+ };
148
+ }
152
149
 
153
- /**
154
- * @see https://github.com/tc39/proposal-array-from-async
155
- */
156
- if (! (Array.fromAsync instanceof Function)) {
157
- Array.fromAsync = async function fromAsync(items, mapFn, thisArg = globalThis) {
158
- let arr = [];
150
+ /**
151
+ * @see https://github.com/tc39/proposal-array-from-async
152
+ */
153
+ if (! (Array.fromAsync instanceof Function)) {
154
+ Array.fromAsync = async function fromAsync(items, mapFn, thisArg = globalThis) {
155
+ let arr = [];
159
156
 
160
- for await (const item of items) {
161
- arr.push(await item);
162
- }
157
+ for await (const item of items) {
158
+ arr.push(await item);
159
+ }
163
160
 
164
- return Array.from(arr, mapFn, thisArg);
165
- };
166
- }
161
+ return Array.from(arr, mapFn, thisArg);
162
+ };
163
+ }
167
164
 
168
- /**
169
- * @see https://github.com/tc39/proposal-array-equality/
170
- */
171
- if (! (Array.prototype.equals instanceof Function)) {
172
- Array.prototype.equals = function equals(arr) {
173
- if (this === arr) {
174
- return true;
175
- } else if (! Array.isArray(arr)) {
176
- return false;
177
- } else if (this.length !== arr.length) {
178
- return false;
179
- } else {
180
- return this.every((item, i) => {
181
- const val = arr[i];
182
- if (Array.isArray(item)) {
183
- return Array.isArray(val) && item.equals(val);
184
- } else {
185
- return Object.is(item, val);
186
- }
187
- });
188
- }
189
- };
190
- }
191
- /**
192
- * @see https://github.com/tc39/proposal-array-unique
193
- */
194
- if (! (Array.prototype.uniqueBy instanceof Function)) {
195
- Array.prototype.uniqueBy = function uniqueBy(arg) {
196
- if (typeof arg === 'undefined') {
197
- return [...new Set(this)];
198
- } else if (typeof arg === 'string') {
199
- const found = [];
200
-
201
- return this.filter(obj => {
202
- const key = obj[arg];
203
- if (found.includes(key)) {
165
+ /**
166
+ * @see https://github.com/tc39/proposal-array-equality/
167
+ */
168
+ if (! (Array.prototype.equals instanceof Function)) {
169
+ Array.prototype.equals = function equals(arr) {
170
+ if (this === arr) {
171
+ return true;
172
+ } else if (! Array.isArray(arr)) {
173
+ return false;
174
+ } else if (this.length !== arr.length) {
175
+ return false;
176
+ } else {
177
+ return this.every((item, i) => {
178
+ const val = arr[i];
179
+ if (Array.isArray(item)) {
180
+ return Array.isArray(val) && item.equals(val);
181
+ } else {
182
+ return Object.is(item, val);
183
+ }
184
+ });
185
+ }
186
+ };
187
+ }
188
+ /**
189
+ * @see https://github.com/tc39/proposal-array-unique
190
+ */
191
+ if (! (Array.prototype.uniqueBy instanceof Function)) {
192
+ Array.prototype.uniqueBy = function uniqueBy(arg) {
193
+ if (typeof arg === 'undefined') {
194
+ return [...new Set(this)];
195
+ } else if (typeof arg === 'string') {
196
+ const found = [];
197
+
198
+ return this.filter(obj => {
199
+ const key = obj[arg];
200
+ if (found.includes(key)) {
201
+ return false;
202
+ } else {
203
+ found.push(key);
204
+ return true;
205
+ }
206
+ });
207
+ } else if (arg instanceof Function) {
208
+ const found = [];
209
+
210
+ return this.filter((...args) => {
211
+ try {
212
+ const key = arg.apply(this, args);
213
+
214
+ if (typeof key !== 'string') {
215
+ return false;
216
+ } else if (found.includes(key)) {
204
217
  return false;
205
218
  } else {
206
219
  found.push(key);
207
220
  return true;
208
221
  }
209
- });
210
- } else if (arg instanceof Function) {
211
- const found = [];
212
-
213
- return this.filter((...args) => {
214
- try {
215
- const key = arg.apply(this, args);
216
-
217
- if (typeof key !== 'string') {
218
- return false;
219
- } else if (found.includes(key)) {
220
- return false;
221
- } else {
222
- found.push(key);
223
- return true;
224
- }
225
- } catch(err) {
226
- return false;
227
- }
228
- });
229
- } else {
230
- throw new TypeError('Not a valid argument for uniqueBy');
231
- }
232
- };
233
- }
222
+ } catch(err) {
223
+ return false;
224
+ }
225
+ });
226
+ } else {
227
+ throw new TypeError('Not a valid argument for uniqueBy');
228
+ }
229
+ };
230
+ }
234
231
 
235
- /**
236
- * Change Array by copy proposal
237
- * @Note: Not clear if should use `structedClone` or `[...this]` for copies
238
- * @see https://github.com/tc39/proposal-change-array-by-copy
239
- */
240
- if (! (Array.prototype.toReversed instanceof Function)) {
241
- Array.prototype.toReversed = function toReversed() {
242
- return [...this].reverse();
243
- };
244
- }
232
+ /**
233
+ * Change Array by copy proposal
234
+ * @Note: Not clear if should use `structedClone` or `[...this]` for copies
235
+ * @see https://github.com/tc39/proposal-change-array-by-copy
236
+ */
237
+ if (! (Array.prototype.toReversed instanceof Function)) {
238
+ Array.prototype.toReversed = function toReversed() {
239
+ return [...this].reverse();
240
+ };
241
+ }
245
242
 
246
- if (! (Array.prototype.toSorted instanceof Function)) {
247
- Array.prototype.toSorted = function toSorted(cmpFn) {
248
- return [...this].sort(cmpFn);
249
- };
250
- }
243
+ if (! (Array.prototype.toSorted instanceof Function)) {
244
+ Array.prototype.toSorted = function toSorted(cmpFn) {
245
+ return [...this].sort(cmpFn);
246
+ };
247
+ }
251
248
 
252
- if (! (Array.prototype.toSpliced instanceof Function)) {
253
- Array.prototype.toSpliced = function toSpliced(start, deleteCount, ...items) {
254
- const cpy = [...this];
255
- cpy.splice(start, deleteCount, ...items);
256
- return cpy;
257
- };
258
- }
249
+ if (! (Array.prototype.toSpliced instanceof Function)) {
250
+ Array.prototype.toSpliced = function toSpliced(start, deleteCount, ...items) {
251
+ const cpy = [...this];
252
+ cpy.splice(start, deleteCount, ...items);
253
+ return cpy;
254
+ };
255
+ }
259
256
 
260
- if (! (Array.prototype.with instanceof Function)) {
261
- Array.prototype.with = function (index, value) {
262
- const cpy = [...this];
263
- cpy[index] = value;
264
- return cpy;
265
- };
266
- }
267
- })();
257
+ if (! (Array.prototype.with instanceof Function)) {
258
+ Array.prototype.with = function (index, value) {
259
+ const cpy = [...this];
260
+ cpy[index] = value;
261
+ return cpy;
262
+ };
263
+ }
264
+
265
+ if (! (Array.isTemplateObject instanceof Function)) {
266
+ Array.isTemplateObject = function(target) {
267
+ if (! (
268
+ Array.isArray(target) && Array.isArray(target.raw)
269
+ && Object.isFrozen(target) && Object.isFrozen(target.raw)
270
+ )) {
271
+ return false;
272
+ } else {
273
+ return target.length !== 0 && target.length === target.raw.length;
274
+ }
275
+ };
276
+ }
277
+
278
+ /**
279
+ * @see https://github.com/tc39/proposal-arraybuffer-base64
280
+ */
281
+ if (! (Uint8Array.prototype.toHex instanceof Function)) {
282
+ Uint8Array.prototype.toHex = function toHex() {
283
+ return Array.from(this).map(n => n.toString(16).padStart('0', 2)).join('');
284
+ };
285
+ }
286
+
287
+ if (! (Uint8Array.prototype.toBase64 instanceof Function)) {
288
+ Uint8Array.prototype.toBase64 = function toBase64({ alphabet = 'base64' } = {}) {
289
+ if (alphabet === 'base64') {
290
+ // @todo Figure out encoding specifics
291
+ return btoa(String.fromCodePoint(...this));
292
+ // return btoa(new TextDecoder().decode(this));
293
+ } else if (alphabet === 'base64url') {
294
+ return this.toBase64({ alphabet: 'base64' }).replaceAll('+', '-').replaceAll('/', '_');
295
+ } else {
296
+ throw new TypeError('expected alphabet to be either "base64" or "base64url');
297
+ }
298
+ };
299
+ }
300
+
301
+ if (! (Uint8Array.fromHex instanceof Function)) {
302
+ Uint8Array.fromHex = function fromHex(str) {
303
+ if (typeof str !== 'string') {
304
+ throw new TypeError('expected input to be a string');
305
+ } else if (! (str.length & 1) === 0) {
306
+ throw new SyntaxError('string should be an even number of characters');
307
+ } else {
308
+ return Uint8Array.from(
309
+ globalThis.Iterator.range(0, str.length, { step: 2 }),
310
+ i => parseInt(str.substring(i, i + 2), 16)
311
+ );
312
+ }
313
+ };
314
+ }
315
+
316
+ if (! (Uint8Array.fromBase64 instanceof Function)) {
317
+ Uint8Array.fromBase64 = function fromBase64(str, {
318
+ alphabet = 'base64',
319
+ lastChunkHandling = 'loose',
320
+ } = {}) {
321
+ if (typeof str !== 'string') {
322
+ throw new TypeError('expected input to be a string');
323
+ } else if (! ['base64', 'base64url'].includes(alphabet)) {
324
+ throw new TypeError('expected alphabet to be either "base64" or "base64url');
325
+ } else if (! ['loose', 'strict', 'stop-before-partial'].includes(lastChunkHandling)) {
326
+ throw new TypeError(`Invalid \`lastChunkHandling\`: "${lastChunkHandling}".`);
327
+ } else if (alphabet === 'base64') {
328
+ const lastChunkLength = str.length % 4;
329
+
330
+ if (lastChunkLength === 1) {
331
+ throw new TypeError('Invalid string length.');
332
+ } else if (lastChunkLength !== 0) {
333
+ switch(lastChunkHandling) {
334
+ case 'strict':
335
+ throw new SyntaxError('Missing padding.');
336
+
337
+ case 'loose':
338
+ return Uint8Array.fromBase64(str.padEnd(str.length + (4 - lastChunkLength), '='), {
339
+ alphabet: 'base64',
340
+ lastChunkHandling: 'strict',
341
+ });
342
+
343
+ case 'stop-before-partial':
344
+ return Uint8Array.fromBase64(str.slice(0, str.length - lastChunkLength), {
345
+ alphabet: 'base64',
346
+ lastChunkHandling: 'strict',
347
+ });
348
+
349
+ // Already checked for valid `lastChunkHandling`
350
+ }
351
+ } else {
352
+ return new TextEncoder().encode(atob(str));
353
+ }
354
+ } else {
355
+ return Uint8Array.fromBase64(
356
+ str.replaceAll('-', '+').replaceAll('_', '/'),
357
+ { alphabet: 'base64', }
358
+ );
359
+ }
360
+ };
361
+ }
362
+
363
+ // @todo Implement Uint8Array.fromBase64Into & Uint8Array.fromHexInto
364
+ // if (! (Uint8Array.fromBase64Into instanceof Function)) {
365
+ // Uint8Array.fromBase64Into = function fromBase64Into(str, target) {
366
+ // const { read, written } = new TextEncoder().encodeInto(atob(str), target);
367
+ // return { read, written, target };
368
+ // };
369
+ // }