@gershy/clearing 0.0.2 → 0.0.4

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.
@@ -0,0 +1,605 @@
1
+ const applyClearing = (() => {
2
+ const global = globalThis;
3
+ // Prevent multiple installations...
4
+ const memSym = Symbol.for('clearing:mem');
5
+ if (global[memSym])
6
+ return;
7
+ global[memSym] = true;
8
+ const symNames = ['add', 'at', 'apart', 'assert', 'bind', 'bits', 'built', 'char', 'code', 'count', 'cut', 'dive', 'empty', 'fire', 'group', 'has', 'hasHead', 'hasTail', 'indent', 'isInt', 'limn', 'lower', 'mod', 'map', 'mapk', 'merge', 'padHead', 'padTail', 'rem', 'find', 'slash', 'slice', 'suppress', 'toArr', 'toNum', 'toObj', 'toStr', 'upper'];
9
+ const syms = Object.fromEntries(symNames.map(term => [term, Symbol(`clearing:${term}`)]));
10
+ const sovereign = v => v;
11
+ Object.assign(global, {
12
+ // Reference native constructors
13
+ AsyncFunction: (async () => { }).constructor,
14
+ GeneratorFunction: (function* () { })().constructor,
15
+ AsyncGeneratorFunction: (async function* () { })().constructor,
16
+ // Symbols
17
+ ...syms,
18
+ // Forms
19
+ getFormName: f => {
20
+ if (f === null)
21
+ return 'Null';
22
+ if (f === undefined)
23
+ return 'Undef';
24
+ if (f !== f)
25
+ return 'UndefNum';
26
+ return Object.getPrototypeOf(f)?.constructor.name ?? 'Prototypeless'; // e.g. `getFormName(Object.plain()) === 'Prototypeless'`
27
+ },
28
+ getForm: f => Object.getPrototypeOf(f)?.constructor ?? null,
29
+ isForm: (fact, Form) => {
30
+ // NaN only matches against the NaN primitive (not the Number Form)
31
+ if (fact !== fact)
32
+ return Form !== Form;
33
+ if (fact == null)
34
+ return false;
35
+ return Object.getPrototypeOf(fact).constructor === Form;
36
+ },
37
+ hasForm: (fact, Form) => fact instanceof Form,
38
+ // Utility
39
+ skip: undefined,
40
+ sovereign,
41
+ then: (val, rsv = Function.stub, rjc) => {
42
+ // Act on `val` regardless of whether it's a Promise or an immediate
43
+ // value; return `rsv(val)` either immediately or as a Promise;
44
+ // Promises are returned with `then`/`fail` handling
45
+ if (hasForm(val, Promise))
46
+ return val.then(rsv).catch(rjc);
47
+ // No `rjc` means no `try`/`catch` handling
48
+ if (!rjc)
49
+ return rsv(val);
50
+ try {
51
+ return rsv(val);
52
+ }
53
+ catch (err) {
54
+ return rjc(err);
55
+ }
56
+ },
57
+ safe: (val, acc = Function.stub, rjc) => {
58
+ try {
59
+ return then(val(), acc, rjc);
60
+ }
61
+ catch (err) {
62
+ if (!rjc)
63
+ throw err;
64
+ return rjc(err);
65
+ }
66
+ },
67
+ // Jsfn
68
+ jsfn: {
69
+ encode: sovereign((dec /* `val` is still not allowed to have cycles! */, opts) => {
70
+ const encodeFn = opts?.encodeFn ?? (fn => fn.toString());
71
+ const hoists = [];
72
+ const serializeObjKey = (key) => {
73
+ if (/^[$_a-zA-Z][$_a-zA-Z]+$/.test(key))
74
+ return key;
75
+ return `'${key.replaceAll(`'`, `\\'`)}'`;
76
+ };
77
+ const serialize = (val) => {
78
+ if (isForm(val, Object) && Object.keys(val).sort().join(',') === 'args,form,hoist' && hasForm(val.form, Function)) {
79
+ const { args, form, hoist } = val;
80
+ hoists.push(hoist);
81
+ return `new ${hoist.split('::').at(-1)}(${args.map(a => serialize(a)).join(', ')})`;
82
+ }
83
+ if (isForm(val, Array))
84
+ return '[' + val.map((v) => serialize(v)).join(',') + ']';
85
+ if (isForm(val, Object))
86
+ return '{' + val[toArr]((v, k) => `${serializeObjKey(k)}:${serialize(v)}`).join(',') + '}';
87
+ if (hasForm(val, Function))
88
+ return encodeFn(val);
89
+ return JSON.stringify(val);
90
+ };
91
+ return {
92
+ // Note `str` is stringified, but it isn't json - it's js, in string representation!!
93
+ // This representation is actually very simple - in order to run the js represented by
94
+ // `str`, all hoists need to be imported in the context
95
+ hoists,
96
+ str: serialize(dec)
97
+ };
98
+ })
99
+ },
100
+ });
101
+ const protoDefs = (Cls, def) => {
102
+ const protoVals = [];
103
+ const classVals = [];
104
+ for (const key of Reflect.ownKeys(def) /* includes symbols!! */) {
105
+ if (!isForm(key, String))
106
+ protoVals.push({ key, val: def[key] });
107
+ else if (key.startsWith('$'))
108
+ classVals.push({ key: key.slice(1), val: def[key] });
109
+ else if (key.endsWith('->'))
110
+ protoVals.push({ key: def[key], val: Cls.prototype[key.slice(0, -2)] });
111
+ }
112
+ // Assign class properties
113
+ Object.assign(Cls, Object.fromEntries(classVals.map(({ key, val }) => [key, val])));
114
+ // Avoid making more properties available on `global` - if a typo winds up referring to a
115
+ // global property, the bug which results can be highly unexpected!
116
+ // TODO: Note, we don't want to populate the global namespace, *but* we still populate all the
117
+ // symbols keyed by string name on `global` (note the *symbol* is keyed by its *string name* on
118
+ // `global` - i.e., `global['toArr']` results in `Symbol('clearing.toArr')`! This results in
119
+ // many dozens of keys being populated in global namespace... should probably move these
120
+ // symbols to a module import instead :(
121
+ if (Cls === global.constructor)
122
+ for (const entry of protoVals)
123
+ if (isForm(entry.key, String))
124
+ global[entry.key] = skip;
125
+ // Assign proto properties
126
+ Object.defineProperties(Cls.prototype, Object.fromEntries(protoVals
127
+ .map(({ key, val }) => [key, { enumerable: false, writable: true, value: val }])));
128
+ };
129
+ protoDefs(Object, {
130
+ $stub: Object.freeze({}),
131
+ $plain: obj => obj ? Object.assign(Object.create(null), obj) : Object.create(null),
132
+ 'hasOwnProperty->': has,
133
+ *[apart](dive = []) {
134
+ // Breaks apart a "structured" object into a flat list of dive keys paired with values; every
135
+ // value in the original object appears alongside the "dive" (chain of keys to recursively
136
+ // apply) required to dereference it
137
+ for (const [k, val] of this) {
138
+ if (isForm(val, Object))
139
+ yield* val[apart]([...dive, k]);
140
+ else
141
+ yield { dive: [...dive, k], val };
142
+ }
143
+ },
144
+ [at](cmps, def = skip) {
145
+ let ptr = this;
146
+ if (!isForm(cmps, Array))
147
+ cmps = [cmps];
148
+ for (const c of cmps) {
149
+ if (ptr[has](c))
150
+ ptr = ptr[c];
151
+ else
152
+ return def;
153
+ }
154
+ return ptr;
155
+ },
156
+ [built](diveFromKey = (key) => key.split('.')) {
157
+ // The reverse operation of `apart` - takes a flat list of (dive, value) pairs and produces a
158
+ // structured object
159
+ const result = {};
160
+ for (const [k, v] of this) {
161
+ const dive = diveFromKey(k);
162
+ const last = dive.pop();
163
+ let ptr = result;
164
+ for (const cmp of dive)
165
+ ptr = ptr[at](cmp) ?? (ptr[cmp] = {});
166
+ ptr[last] = isForm(v, Object) ? v[built]() : v;
167
+ }
168
+ return result;
169
+ },
170
+ [count]() { let c = 0; for (const k in this)
171
+ c++; return c; },
172
+ [dive](cmps, def = skip) { return this[at](cmps, def); },
173
+ [map](fn) {
174
+ const ret = Object.assign({}, this);
175
+ for (const k in ret) {
176
+ const v = fn(ret[k], k);
177
+ if (v !== skip)
178
+ ret[k] = v;
179
+ else
180
+ delete ret[k];
181
+ }
182
+ return ret;
183
+ },
184
+ [mapk](fn) {
185
+ const arr = [];
186
+ for (const k in this) {
187
+ const r = fn(this[k], k);
188
+ if (r !== skip)
189
+ arr.push(r);
190
+ }
191
+ return Object.fromEntries(arr);
192
+ },
193
+ [toArr](fn) {
194
+ const ret = [];
195
+ for (const k in this) {
196
+ const r = fn(this[k], k);
197
+ if (r !== skip)
198
+ ret.push(r);
199
+ }
200
+ return ret;
201
+ },
202
+ [slash](p) {
203
+ const obj = { ...this };
204
+ for (const k of p)
205
+ delete obj[k];
206
+ return obj;
207
+ },
208
+ [slice](p) {
209
+ // >> { a: 1, b: 2, c: 3, d: 4 }.slice([ 'b', 'd' ]);
210
+ // { b: 2, d: 4 }
211
+ return p[toObj](p => this[has](p) ? [p, this[p]] : skip);
212
+ },
213
+ [empty]() { for (const k in this)
214
+ return false; return true; },
215
+ [group](fn) {
216
+ // { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }.group(n => {
217
+ // if (n < 4) return 'small';
218
+ // if (n < 8) return 'medium';
219
+ // return 'big';
220
+ // });
221
+ // >> { small: { a: 1, b: 2, c: 3 }, medium: { d: 4, e: 5, f: 6, g: 7 }, big: { h: 8, i: 9, j: 10 } }
222
+ const ret = {};
223
+ for (const [k, v] of this) {
224
+ const t = fn(v, k);
225
+ if (!ret[has](t))
226
+ ret[t] = {};
227
+ ret[t][k] = v;
228
+ }
229
+ return ret;
230
+ },
231
+ [merge](o) {
232
+ for (const [k, v] of o) {
233
+ // `skip` can be passed to remove properties
234
+ if (v === skip) {
235
+ delete this[k];
236
+ continue;
237
+ }
238
+ // Incoming non-Object properties are simple
239
+ if (!isForm(v, Object)) {
240
+ this[k] = v;
241
+ continue;
242
+ }
243
+ // `v` is an Object; existing non-Object replaced with `{}`
244
+ if (!this[has](k) || !isForm(this[k], Object))
245
+ this[k] = {};
246
+ // And simply recurse!
247
+ this[k][merge](v);
248
+ }
249
+ return this;
250
+ },
251
+ *[Symbol.iterator]() { for (const k in this)
252
+ yield [k, this[k]]; }
253
+ });
254
+ protoDefs(Array, {
255
+ $stub: Object.freeze([]),
256
+ 'includes->': has,
257
+ [has](v) { return this.includes(v); },
258
+ [map](it) {
259
+ const ret = [];
260
+ const len = this.length;
261
+ for (let i = 0; i < len; i++) {
262
+ const r = it(this[i], i);
263
+ if (r !== skip)
264
+ ret.push(r);
265
+ }
266
+ return ret;
267
+ },
268
+ [toArr](it) { return this[map](it); },
269
+ [toObj](it) {
270
+ const ret = [];
271
+ const len = this.length;
272
+ for (let i = 0; i < len; i++) {
273
+ const r = it(this[i], i);
274
+ if (r !== skip)
275
+ ret.push(r);
276
+ }
277
+ return Object.fromEntries(ret);
278
+ },
279
+ [find](f) {
280
+ const n = this.length;
281
+ for (let i = 0; i < n; i++)
282
+ if (f(this[i], i))
283
+ return { found: true, val: this[i], ind: i };
284
+ return { found: false, val: null, ind: null };
285
+ },
286
+ [empty]() { return !this.length; },
287
+ [add](...args) { this.push(...args); return args[0]; },
288
+ [rem](val) { const ind = this.indexOf(val); if (ind > -1)
289
+ this.splice(ind, 1); },
290
+ [count]() { return this.length; },
291
+ [group](fn) {
292
+ // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ].group(n => {
293
+ // if (n < 4) return 'small';
294
+ // if (n < 8) return 'medium';
295
+ // return 'big';
296
+ // });
297
+ // >> { small: [ 1, 2, 3 ], medium: [ 4, 5, 6, 7 ], big: [ 8, 9, 10 ] }
298
+ const ret = {};
299
+ for (const elem of this) {
300
+ const t = fn(elem);
301
+ if (!ret[has](t))
302
+ ret[t] = [];
303
+ ret[t].push(elem);
304
+ }
305
+ return ret;
306
+ }
307
+ });
308
+ protoDefs(String, {
309
+ $baseline: (str, seq = '| ') => {
310
+ return str.split('\n')[map](ln => {
311
+ const ind = ln.indexOf(seq);
312
+ if (ind === -1)
313
+ return skip;
314
+ return ln.slice(ind + seq.length);
315
+ }).join('\n');
316
+ },
317
+ $charset: str => {
318
+ const cache = new Map();
319
+ return {
320
+ str,
321
+ size: BigInt(str.length),
322
+ charVal: (c) => {
323
+ if (!cache.has(c)) {
324
+ const ind = str.indexOf(c);
325
+ if (ind < 0)
326
+ throw Error('char outside charset')[mod]({ char: c });
327
+ cache.set(c, BigInt(ind));
328
+ }
329
+ return cache.get(c);
330
+ },
331
+ valChar: (n) => {
332
+ if (n < 0 || n >= str.length)
333
+ throw Error('val outside charset');
334
+ return str[n];
335
+ }
336
+ };
337
+ },
338
+ $base32: '0123456789abcdefghijklmnopqrstuv',
339
+ $base36: '0123456789abcdefghijklmnopqrstuvwxyz',
340
+ $base62: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
341
+ $base64: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_',
342
+ $base64Std: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/',
343
+ 'includes->': has,
344
+ 'startsWith->': hasHead,
345
+ 'endsWith->': hasTail,
346
+ 'padStart->': padHead,
347
+ 'padEnd->': padTail,
348
+ 'toUpperCase->': upper,
349
+ 'toLowerCase->': lower,
350
+ [cut](delim, cuts = 1) {
351
+ // `cuts` defines # of cuts (resulting array length is `num + 1`)
352
+ const split = this.split(delim, cuts < Infinity ? cuts : skip);
353
+ const numDelimsSplit = split.length - 1;
354
+ const lenConsumed = 0
355
+ + split.reduce((a, s) => a + s.length, 0)
356
+ + delim.length * numDelimsSplit;
357
+ return lenConsumed < this.length
358
+ ? [...split, this.slice(lenConsumed + delim.length)]
359
+ : split;
360
+ },
361
+ [code](ind = 0) { return this.charCodeAt(ind); },
362
+ [count]() { return this.length; },
363
+ [indent](...args /* amt=2, char=' ' | indentStr=' '.repeat(2) */) {
364
+ if (!this)
365
+ return this; // No-op on empty String (otherwise it would transform a 0-line string to a 1-line string)
366
+ let indentStr;
367
+ if (isForm(args[0], String)) {
368
+ indentStr = args[0];
369
+ }
370
+ else {
371
+ const [amt = 2, char = ' '] = args;
372
+ indentStr = char.repeat(amt);
373
+ }
374
+ return this.split('\n')[map](ln => `${indentStr}${ln}`).join('\n');
375
+ },
376
+ [toNum](charset = String.base62) {
377
+ if (isForm(charset, String))
378
+ charset = String.charset(charset);
379
+ const base = charset.size;
380
+ if (base === 1n)
381
+ return this.count();
382
+ let sum = 0n;
383
+ const n = this.length;
384
+ for (let ind = 0; ind < n; ind++)
385
+ // Earlier values of `i` represent higher places same as with written numbers further left
386
+ // digits are more significant
387
+ // The value of the place `i` is `ind - 1`
388
+ sum += (base ** BigInt(n - ind - 1)) * charset.charVal(this[ind]);
389
+ return sum;
390
+ }
391
+ });
392
+ protoDefs(Number, {
393
+ $int32: Math.pow(2, 32),
394
+ $int64: Math.pow(2, 64),
395
+ [char]() { return String.fromCharCode(this); },
396
+ [toArr](fn) { const arr = new Array(this || 0); for (let i = 0; i < this; i++)
397
+ arr[i] = fn(i); return arr; },
398
+ [toObj](fn) {
399
+ const ret = [];
400
+ for (let i = 0; i < this; i++) {
401
+ const r = fn(i);
402
+ if (r !== skip)
403
+ ret.push(r);
404
+ }
405
+ return Object.fromEntries(ret);
406
+ },
407
+ [toStr](charset, padLen = 0) {
408
+ // Note that base-1 requires 0 to map to the empty string. This also
409
+ // means that, for `n >= 1`:
410
+ // | (n).encodeStr(singleChr)
411
+ // is always equivalent to
412
+ // | singleChr.repeat(n - 1)
413
+ if (isForm(charset, String))
414
+ charset = String.charset(charset);
415
+ const base = charset.size;
416
+ if (base === 1n && padLen)
417
+ throw Error(`pad with base-1 encoding`);
418
+ if (this !== this)
419
+ return (base === 1n) ? '' : charset[0].repeat(Math.max(padLen, 1));
420
+ let num = this.constructor === BigInt ? this : BigInt(Math.floor(this));
421
+ const digits = [];
422
+ while (num) {
423
+ digits.push(charset.valChar(num % base));
424
+ num /= base;
425
+ }
426
+ return digits.reverse().join('')[padHead](padLen, charset.str[0]);
427
+ },
428
+ [isInt]() { return this === Math.round(this); }, // No bitwise shortcut - it disrupts Infinity
429
+ *[Symbol.iterator]() { Error.assert({ n: this }, args => args.n.isInteger()); for (let i = 0; i < this; i++)
430
+ yield i; },
431
+ *[bits]() { let n = this >= 0 ? this : -this; while (n) {
432
+ yield n & 1;
433
+ n = n >> 1;
434
+ } },
435
+ [map]: undefined // Prevent `Number(...).map`
436
+ });
437
+ protoDefs(BigInt, { [toStr]: Number.prototype[toStr] });
438
+ protoDefs(Function, {
439
+ $stub: v => v,
440
+ [bind](...args) { return this.bind(null, ...args); }
441
+ });
442
+ protoDefs(Error, {
443
+ $stackTraceLimit: 150,
444
+ $assert: (args, fn) => {
445
+ if (fn(args))
446
+ return;
447
+ throw Error('assert failed')[mod]({
448
+ fn: `false === (${fn.toString().replace(/[\s]+/, ' ')})(args)`,
449
+ args
450
+ });
451
+ },
452
+ [mod](props = {} /* { cause, msg, message, ...more } */) {
453
+ if (isForm(props, Function))
454
+ props = props(this.message, this);
455
+ if (isForm(props, String))
456
+ props = { message: props };
457
+ const { cause = null, msg = null, message = msg ?? this.message, ...moreProps } = props;
458
+ // - Assign `cause` to transfer props like fs "code" props, etc. - watch out, `cause` may be
459
+ // an Array or Object!
460
+ // - Assign `moreProps` to transfer any other properties
461
+ // - Add `message` prop
462
+ // - Only add `cause` prop if `cause` is non-null
463
+ return Object.assign(this, hasForm(cause, Error) ? cause : {}, moreProps, cause ? { message, cause } : { message });
464
+ },
465
+ [fire](props /* { cause, msg, message, ...more } */) { throw this[mod](props); },
466
+ [suppress]() {
467
+ this[Symbol.for('clearing.err.suppressed')] = true;
468
+ if (this.cause) {
469
+ const causes = hasForm(this.cause, Error) ? [this.cause] : this.cause;
470
+ for (const err of causes)
471
+ err[suppress]();
472
+ }
473
+ return this;
474
+ },
475
+ [limn](seen = new Map()) {
476
+ if (seen.has(this))
477
+ return seen.get(this);
478
+ seen.set(this, 'cycle(Error)');
479
+ const { message, stack, cause, ...props } = this;
480
+ return {
481
+ form: getFormName(this),
482
+ msg: message,
483
+ trace: stack?.split('\n').slice(1)[map](v => v.trim() ?? skip) ?? [],
484
+ ...props,
485
+ cause: !cause ? null : cause[limn](seen)
486
+ };
487
+ }
488
+ });
489
+ protoDefs(Promise, {
490
+ $resolve: Promise.resolve,
491
+ $reject: Promise.reject,
492
+ $all: Promise.all,
493
+ $allArr: Promise.all,
494
+ $later: (resolve, reject) => {
495
+ const p = new Promise((...a) => [resolve, reject] = a);
496
+ return Object.assign(p, { resolve, reject });
497
+ },
498
+ $allObj: (obj) => {
499
+ // Need to get `keys` here in case `obj` mutates before resolution
500
+ const keys = Object.keys(obj);
501
+ return Promise.allArr(Object.values(obj)).then(vals => {
502
+ const ret = {};
503
+ for (const [i, k] of keys.entries())
504
+ if (vals[i] !== skip)
505
+ ret[k] = vals[i];
506
+ return ret;
507
+ });
508
+ }
509
+ });
510
+ protoDefs(Set, {
511
+ $stub: { count: () => 0, add: Function.stub, rem: Function.stub, has: () => false, values: () => Array.stub },
512
+ 'delete->': rem,
513
+ [map](fn) {
514
+ const ret = [];
515
+ let ind = 0;
516
+ for (const item of this) {
517
+ const r = fn(item, ind++);
518
+ if (r !== skip)
519
+ ret.push(r);
520
+ }
521
+ return ret;
522
+ },
523
+ [find](fn) {
524
+ for (const val of this)
525
+ if (fn(val))
526
+ return { found: true, val };
527
+ return { found: false, val: null };
528
+ },
529
+ [count]() { return this.size; },
530
+ [empty]() { return !this.size; },
531
+ [toArr](fn) {
532
+ const ret = [];
533
+ let ind = 0;
534
+ for (const item of this) {
535
+ const r = fn(item, ind++);
536
+ if (r !== skip)
537
+ ret.push(r);
538
+ }
539
+ return ret;
540
+ },
541
+ [toObj](fn) {
542
+ const ret = [];
543
+ for (const item of this) {
544
+ const r = fn(item);
545
+ if (r !== skip)
546
+ ret.push(r);
547
+ }
548
+ return Object.fromEntries(ret);
549
+ }
550
+ });
551
+ protoDefs(Map, {
552
+ $stub: { count: () => 0, set: Function.stub, rem: Function.stub, has: () => false, values: () => Array.stub },
553
+ 'set->': add,
554
+ 'delete->': rem,
555
+ [map](fn) {
556
+ const ret = [];
557
+ for (const [k, v] of this) {
558
+ const r = fn(v, k);
559
+ if (r !== skip)
560
+ ret.push(r);
561
+ }
562
+ return Object.fromEntries(ret);
563
+ },
564
+ [find](fn) {
565
+ for (const [k, v] of this)
566
+ if (fn(v, k))
567
+ return { found: true, val: v, key: k };
568
+ return { found: false, val: null, key: null };
569
+ },
570
+ [count]() { return this.size; },
571
+ [empty]() { return !this.size; },
572
+ [toObj](fn) {
573
+ const ret = [];
574
+ for (const [k, v] of this) {
575
+ const r = fn(v, k);
576
+ if (r !== skip)
577
+ ret.push(r);
578
+ }
579
+ return Object.fromEntries(ret);
580
+ },
581
+ [toArr](fn) {
582
+ const ret = [];
583
+ for (const [k, v] of this) {
584
+ const r = fn(v, k);
585
+ if (r !== skip)
586
+ ret.push(r);
587
+ }
588
+ return ret;
589
+ }
590
+ });
591
+ protoDefs(GeneratorFunction, {
592
+ [toArr](fn) { return [...this][map](fn); },
593
+ [toObj](fn) {
594
+ const ret = {};
595
+ for (const v of this) {
596
+ const r = fn(v);
597
+ if (r !== skip)
598
+ ret[r[0]] = r[1];
599
+ }
600
+ return ret;
601
+ }
602
+ });
603
+ });
604
+ applyClearing();
605
+ export default applyClearing;