@shgysk8zer0/polyfills 0.2.8 → 0.3.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.
package/iterator.js CHANGED
@@ -1,197 +1,313 @@
1
- (function() {
2
- 'use strict';
3
-
4
- /**
5
- * @see https://github.com/tc39/proposal-iterator-helpers
6
- * @TODO implement `flat()`
7
- * @TODO implement `flatMap()`
8
- * @TODO implement `from()`
9
- */
10
- if (! ('Iterator' in globalThis)) {
11
- globalThis.Iterator = {
12
- 'prototype': Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())),
13
- };
14
- }
1
+ /**
2
+ * @see https://github.com/tc39/proposal-iterator-helpers
3
+ */
15
4
 
16
- const Iterator = globalThis.Iterator;
5
+ const supported = 'Iterator' in globalThis;
17
6
 
18
- if (! (Iterator.range instanceof Function)) {
19
- Iterator.range = function* range(start, end, option) {
20
- if (typeof option === 'number' || typeof option === 'bigint') {
21
- for (const n of Iterator.range(start, end, { step: option })) {
22
- yield n;
23
- }
24
- } else if (typeof option !== 'object' || Object.is(option, null)) {
25
- for (const n of Iterator.range(start, end, {})) {
26
- yield n;
7
+ const IteratorPrototype = supported
8
+ ? Object.getPrototypeOf(globalThis.Iterator)
9
+ : Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
10
+
11
+ const Iterator = supported
12
+ ? globalThis.Iterator
13
+ : (proto => {
14
+ class Iterator {
15
+ [Symbol.iterator]() {
16
+ return this;
17
+ }
18
+ }
19
+
20
+ Object.setPrototypeOf(Iterator, proto);
21
+
22
+ return Iterator;
23
+ })(IteratorPrototype);
24
+
25
+ if (! (Iterator.range instanceof Function)) {
26
+ Iterator.range = function range(start, end, option) {
27
+ if (typeof option === 'number' || typeof option === 'bigint') {
28
+ return Iterator.range(start, end, { step: option });
29
+ } else if (typeof option !== 'object' || Object.is(option, null)) {
30
+ return Iterator.range(start, end, {});
31
+ } else {
32
+ const {
33
+ // Default to +/-, Number/BigInt based on start & end
34
+ step = typeof start === 'number'
35
+ ? start < end ? 1 : -1
36
+ : start < end ? 1n : -1n,
37
+ inclusive = false,
38
+ } = option;
39
+
40
+ if (typeof start !== 'number' && typeof start !== 'bigint') {
41
+ throw new TypeError('Start must be a number');
42
+ } else if (Number.isNaN(start)) {
43
+ throw new RangeError('Invalid start');
44
+ } else if (typeof end !== 'number' && typeof end !== 'bigint') {
45
+ throw new TypeError('End must be a number');
46
+ } else if (Number.isNaN(end)) {
47
+ throw new RangeError('Invalid end');
48
+ } else if (typeof step !== 'number' && typeof step !== 'bigint') {
49
+ throw new TypeError('Step must be a number');
50
+ } else if (Number.isNaN(step)) {
51
+ throw new RangeError('Invalid step');
52
+ } else if (step === 0) {
53
+ throw new RangeError('Step must not be 0');
54
+ } else if ((step < 0 && start < end) || (step > 0 && start > end)) {
55
+ return;
56
+ } else if (inclusive) {
57
+ let n = start;
58
+ if (step > 0) {
59
+ return Iterator.from({
60
+ next() {
61
+ const ret = n <= end ? { value: n, done: false } : { done: true };
62
+ n+= step;
63
+ return ret;
64
+ }
65
+ });
66
+ } else {
67
+ return Iterator.from({
68
+ next() {
69
+ const ret = n >= end ? { value: n, done: false } : { done: true };
70
+ n+= step;
71
+ return ret;
72
+ }
73
+ });
27
74
  }
28
75
  } else {
29
- const {
30
- // Default to +/-, Number/BigInt based on start & end
31
- step = typeof start === 'number'
32
- ? start < end ? 1 : -1
33
- : start < end ? 1n : -1n,
34
- inclusive = false,
35
- } = option;
36
-
37
- if (typeof start !== 'number' && typeof start !== 'bigint') {
38
- throw new TypeError('Start must be a number');
39
- } else if (Number.isNaN(start)) {
40
- throw new RangeError('Invalid start');
41
- } else if (typeof end !== 'number' && typeof end !== 'bigint') {
42
- throw new TypeError('End must be a number');
43
- } else if (Number.isNaN(end)) {
44
- throw new RangeError('Invalid end');
45
- } else if (typeof step !== 'number' && typeof step !== 'bigint') {
46
- throw new TypeError('Step must be a number');
47
- } else if (Number.isNaN(step)) {
48
- throw new RangeError('Invalid step');
49
- } else if (step === 0) {
50
- throw new RangeError('Step must not be 0');
51
- } else if ((step < 0 && start < end) || (step > 0 && start > end)) {
52
- return;
53
- } else if (inclusive) {
54
- if (step > 0) {
55
- for (let n = start; n <= end; n+= step) {
56
- yield n;
57
- }
58
- } else {
59
- for (let n = start; n >= end; n+= step) {
60
- yield n;
76
+ let n = start;
77
+
78
+ if (step > 0) {
79
+ return Iterator.from({
80
+ next() {
81
+ const ret = n < end ? { value: n, done: false } : { done: true };
82
+ n+= step;
83
+ return ret;
61
84
  }
62
- }
85
+ });
63
86
  } else {
64
- if (step > 0) {
65
- for (let n = start; n < end; n+= step) {
66
- yield n;
67
- }
68
- } else {
69
- for (let n = start; n > end; n+= step) {
70
- yield n;
87
+ let n = start;
88
+
89
+ return Iterator.from({
90
+ next() {
91
+ const ret = n > end ? { value: n, done: false } : { done: true };
92
+ n+= step;
93
+ return ret;
71
94
  }
72
- }
95
+ });
73
96
  }
74
97
  }
75
- };
76
- }
98
+ }
99
+ };
100
+ }
77
101
 
78
- if (! (Iterator.prototype[Symbol.toStringTag])) {
79
- Iterator.prototype[Symbol.toStringTag] = 'Iterator';
80
- }
102
+ if (! (IteratorPrototype[Symbol.toStringTag])) {
103
+ IteratorPrototype[Symbol.toStringTag] = 'Iterator';
104
+ }
81
105
 
82
- if (! (Iterator.prototype.take instanceof Function)) {
83
- Iterator.prototype.take = function* take(limit) {
84
- let n = 0;
106
+ if (! (IteratorPrototype.take instanceof Function)) {
107
+ IteratorPrototype.take = function take(limit) {
108
+ let n = 0;
109
+ const iter = this;
85
110
 
86
- for (const item of this) {
87
- if (++n > limit) {
88
- break;
111
+ return Iterator.from({
112
+ next() {
113
+ if (n++ >= limit) {
114
+ return { done: true };
89
115
  } else {
90
- yield item;
116
+ return iter.next();
91
117
  }
92
118
  }
93
- };
94
- }
119
+ });
120
+ };
121
+ }
95
122
 
96
- if (! (Iterator.prototype.drop instanceof Function)) {
97
- Iterator.prototype.drop = function* drop(limit) {
98
- let n = 0;
99
- for (const item of this) {
100
- if (n++ >= limit) {
101
- yield item;
102
- }
123
+ if (! (IteratorPrototype.drop instanceof Function)) {
124
+ IteratorPrototype.drop = function drop(limit) {
125
+ for (let n = 0; n < limit; n++) {
126
+ const { done } = this.next();
127
+
128
+ if (done) {
129
+ break;
103
130
  }
104
- };
105
- }
131
+ }
106
132
 
107
- if (! (Iterator.prototype.toArray instanceof Function)) {
108
- Iterator.prototype.toArray = function toArray() {
109
- return Array.from(this);
110
- };
111
- }
133
+ return this;
134
+ };
135
+ }
112
136
 
113
- if (! (Iterator.prototype.forEach instanceof Function)) {
114
- Iterator.prototype.forEach = function forEach(callback) {
115
- for (const item of this) {
116
- callback(item);
117
- }
118
- };
119
- }
137
+ if (! (IteratorPrototype.toArray instanceof Function)) {
138
+ IteratorPrototype.toArray = function toArray() {
139
+ return Array.from(this);
140
+ };
141
+ }
120
142
 
121
- if (! (Iterator.prototype.map instanceof Function)) {
122
- Iterator.prototype.map = function* map(callback) {
123
- for (const item of this) {
124
- yield callback(item);
125
- }
143
+ if (! (IteratorPrototype.forEach instanceof Function)) {
144
+ IteratorPrototype.forEach = function forEach(callback) {
145
+ for (const item of this) {
146
+ callback.call(this, item);
147
+ }
148
+ };
149
+ }
150
+
151
+ if (! (IteratorPrototype.flatMap instanceof Function)) {
152
+ IteratorPrototype.flatMap = function flatMap(mapper) {
153
+ const iter = this;
154
+ let cur = this.next();
155
+
156
+ const getSubIter = ({ value, done = true } = {}) => {
157
+ return done
158
+ ? Iterator.from({
159
+ next() {
160
+ return { done: true };
161
+ }
162
+ })
163
+ : Iterator.from(mapper.call(iter, value));
126
164
  };
127
- }
128
165
 
129
- if (! (Iterator.prototype.reduce instanceof Function)) {
130
- Iterator.prototype.reduce = function reduce(callback, initialValue) {
131
- let current = typeof initialValue === 'undefined' ? this.next().value : initialValue;
166
+ let sub = getSubIter(cur);
132
167
 
133
- for (const item of this) {
134
- current = callback(current, item);
168
+ return Iterator.from({
169
+ next() {
170
+ const { value, done = true } = sub.next();
171
+
172
+ if (cur.done && done) {
173
+ return { done: true };
174
+ } else if (! done) {
175
+ return { value, done };
176
+ } else if (! cur.done) {
177
+ cur = iter.next();
178
+ sub = getSubIter(cur);
179
+ return sub.next();
180
+ } else {
181
+ return { done: true };
182
+ }
135
183
  }
184
+ });
136
185
 
137
- return current;
138
- };
139
- }
186
+ };
187
+ }
188
+
189
+ if (! (IteratorPrototype.map instanceof Function)) {
190
+ IteratorPrototype.map = function map(callback) {
191
+ const iter = this;
192
+
193
+ return Iterator.from({
194
+ next() {
195
+ const { done, value } = iter.next();
140
196
 
141
- if (! (Iterator.prototype.filter instanceof Function)) {
142
- Iterator.prototype.filter = function* filter(callback) {
143
- for (const item of this) {
144
- if (callback(item)) {
145
- yield item;
197
+ if (done) {
198
+ return { done };
199
+ } else {
200
+ return { value: callback.call(iter, value), done: false };
146
201
  }
147
202
  }
148
- };
149
- }
150
-
151
- if (! (Iterator.prototype.some instanceof Function)) {
152
- Iterator.prototype.some = function some(callback) {
153
- let retVal = false;
154
- for (const item of this) {
155
- if (callback(item)) {
156
- retVal = true;
157
- break;
203
+ });
204
+ };
205
+ }
206
+
207
+ if (! (IteratorPrototype.reduce instanceof Function)) {
208
+ IteratorPrototype.reduce = function reduce(callback, initialValue) {
209
+ let current = typeof initialValue === 'undefined' ? this.next().value : initialValue;
210
+
211
+ for (const item of this) {
212
+ current = callback.call(this, current, item);
213
+ }
214
+
215
+ return current;
216
+ };
217
+ }
218
+
219
+ if (! (IteratorPrototype.filter instanceof Function)) {
220
+ IteratorPrototype.filter = function filter(callback) {
221
+ const iter = this;
222
+ let done = false;
223
+ let value = undefined;
224
+
225
+ return Iterator.from({
226
+ next() {
227
+ while (! done) {
228
+ const cur = iter.next();
229
+ done = cur.done;
230
+
231
+ if (done) {
232
+ break;
233
+ } else if (callback.call(iter, cur.value)) {
234
+ value = cur.value;
235
+ break;
236
+ }
158
237
  }
238
+
239
+ return { done, value };
159
240
  }
241
+ });
242
+ };
243
+ }
160
244
 
161
- return retVal;
162
- };
163
- }
164
-
165
- if (! (Iterator.prototype.every instanceof Function)) {
166
- Iterator.prototype.every = function every(callback) {
167
- let retVal = true;
168
- for (const item of this) {
169
- if (! callback(item)) {
170
- retVal = false;
171
- break;
172
- }
245
+ if (! (IteratorPrototype.some instanceof Function)) {
246
+ IteratorPrototype.some = function some(callback) {
247
+ let retVal = false;
248
+ for (const item of this) {
249
+ if (callback.call(this, item)) {
250
+ retVal = true;
251
+ break;
173
252
  }
253
+ }
174
254
 
175
- return retVal;
176
- };
177
- }
255
+ return retVal;
256
+ };
257
+ }
178
258
 
179
- if (! (Iterator.prototype.find instanceof Function)) {
180
- Iterator.prototype.find = function find(callback) {
181
- for (const item of this) {
182
- if (callback(item)) {
183
- return item;
184
- }
259
+ if (! (IteratorPrototype.every instanceof Function)) {
260
+ IteratorPrototype.every = function every(callback) {
261
+ let retVal = true;
262
+ for (const item of this) {
263
+ if (! callback.call(this, item)) {
264
+ retVal = false;
265
+ break;
185
266
  }
186
- };
187
- }
267
+ }
268
+
269
+ return retVal;
270
+ };
271
+ }
188
272
 
189
- if (! (Iterator.prototype.indexed instanceof Function)) {
190
- Iterator.prototype.indexed = function* indexed() {
191
- let n = 0;
192
- for (const item of this) {
193
- yield [n++, item];
273
+ if (! (IteratorPrototype.find instanceof Function)) {
274
+ IteratorPrototype.find = function find(callback) {
275
+ for (const item of this) {
276
+ if (callback.call(this, item)) {
277
+ return item;
194
278
  }
195
- };
196
- }
197
- })();
279
+ }
280
+ };
281
+ }
282
+
283
+ if (! (IteratorPrototype.indexed instanceof Function)) {
284
+ IteratorPrototype.indexed = function indexed() {
285
+ let n = 0;
286
+ return this.map(item => [n++, item]);
287
+ };
288
+ }
289
+
290
+ if (! (Iterator.from instanceof Function)) {
291
+ Iterator.from = function from(obj) {
292
+ if (typeof obj !== 'object' || obj === null) {
293
+ throw new TypeError('Not an object.');
294
+ } else if (obj.next instanceof Function) {
295
+ const iter = Object.create(IteratorPrototype, {
296
+ 'next': {
297
+ enumerable: true,
298
+ configurable: false,
299
+ writable: false,
300
+ value: (...args) => obj.next(...args),
301
+ },
302
+ });
303
+
304
+ return iter;
305
+ } else if(obj[Symbol.iterator] instanceof Function) {
306
+ return Iterator.from(obj[Symbol.iterator]());
307
+ }
308
+ };
309
+ }
310
+
311
+ if (! supported) {
312
+ globalThis.Iterator = Iterator;
313
+ }
package/legacy/set.js ADDED
@@ -0,0 +1,72 @@
1
+ if (! ('Set' in globalThis)) {
2
+ globalThis.Set = class Set {
3
+ #items = [];
4
+
5
+ constructor(items) {
6
+ Array.from(items).forEach(item => this.add(item));
7
+ }
8
+
9
+ [Symbol.iterator]() {
10
+ return this.#items.values();
11
+ }
12
+
13
+ get [Symbol.toStringTag]() {
14
+ return 'Set';
15
+ }
16
+
17
+ get size() {
18
+ return this.#items.length;
19
+ }
20
+
21
+ add(item) {
22
+ if (! this.has(item)){
23
+ this.#items.push(item);
24
+ }
25
+
26
+ return this;
27
+ }
28
+
29
+ delete(item) {
30
+ const index = this.#items.indexOf(item);
31
+
32
+ if (index !== -1) {
33
+ this.#items = this.#items.slice(0, index).concat(this.#items.slice(index + 1));
34
+ return true;
35
+ } else {
36
+ return false;
37
+ }
38
+ }
39
+
40
+ has(item) {
41
+ return this.#items.includes(item);
42
+ }
43
+
44
+ clear() {
45
+ this.#items = [];
46
+ }
47
+
48
+ keys() {
49
+ return this[Symbol.iterator]();
50
+ }
51
+
52
+ values() {
53
+ return this[Symbol.iterator]();
54
+ }
55
+
56
+ entries() {
57
+ return this.keys().map(item => [item, item]);
58
+ }
59
+
60
+ forEach(callbackFn, thisArg) {
61
+ if (typeof thisArg === 'undefined') {
62
+ for (const value of this) {
63
+ callbackFn.call(this, value, value, this);
64
+ }
65
+ } else {
66
+ for (const value of this) {
67
+ callbackFn.call(thisArg, value, value, this);
68
+ }
69
+ }
70
+ }
71
+ };
72
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgysk8zer0/polyfills",
3
- "version": "0.2.8",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "A collection of JavaScript polyfills",