@naturalcycles/js-lib 15.71.1 → 15.71.3
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/dist/datetime/localDate.js +1 -0
- package/dist/datetime/localTime.js +2 -0
- package/dist/intl/intl.js +1 -0
- package/dist/object/object.util.js +24 -0
- package/dist/string/slugify.js +0 -1
- package/package.json +2 -2
- package/src/datetime/localDate.ts +1 -0
- package/src/datetime/localTime.ts +2 -0
- package/src/intl/intl.ts +2 -0
- package/src/object/object.util.ts +26 -0
- package/src/string/slugify.ts +0 -1
|
@@ -647,6 +647,7 @@ export class LocalTime {
|
|
|
647
647
|
return this.unix;
|
|
648
648
|
}
|
|
649
649
|
format(fmt) {
|
|
650
|
+
// oxlint-disable-next-line no-restricted-globals
|
|
650
651
|
if (fmt instanceof Intl.DateTimeFormat) {
|
|
651
652
|
return fmt.format(this.$date);
|
|
652
653
|
}
|
|
@@ -862,6 +863,7 @@ class LocalTimeFactory {
|
|
|
862
863
|
isTimezoneValid(tz) {
|
|
863
864
|
if (tz === 'UTC')
|
|
864
865
|
return true; // we deliberately consider UTC a valid timezone, while it's mostly used in testing
|
|
866
|
+
// oxlint-disable-next-line no-restricted-globals
|
|
865
867
|
return Intl.supportedValuesOf('timeZone').includes(tz);
|
|
866
868
|
}
|
|
867
869
|
sort(items, dir = 'asc', opt = {}) {
|
package/dist/intl/intl.js
CHANGED
|
@@ -113,6 +113,8 @@ export function _filterObject(obj, predicate, opt = {}) {
|
|
|
113
113
|
}
|
|
114
114
|
return obj;
|
|
115
115
|
}
|
|
116
|
+
// Not vulnerable to prototype pollution: writes to a new {}, where __proto__
|
|
117
|
+
// assignment only changes the new object's prototype, not Object.prototype.
|
|
116
118
|
const r = {};
|
|
117
119
|
for (const [k, v] of _objectEntries(obj)) {
|
|
118
120
|
if (predicate(k, v, obj)) {
|
|
@@ -133,6 +135,8 @@ export function _filterObject(obj, predicate, opt = {}) {
|
|
|
133
135
|
* To skip some key-value pairs - use _mapObject instead.
|
|
134
136
|
*/
|
|
135
137
|
export function _mapValues(obj, mapper, opt = {}) {
|
|
138
|
+
// Not vulnerable to prototype pollution: writes to a new {} (or mutates the
|
|
139
|
+
// source in-place where own data properties shadow the __proto__ accessor).
|
|
136
140
|
const map = opt.mutate ? obj : {};
|
|
137
141
|
for (const [k, v] of Object.entries(obj)) {
|
|
138
142
|
map[k] = mapper(k, v, obj);
|
|
@@ -148,6 +152,8 @@ export function _mapValues(obj, mapper, opt = {}) {
|
|
|
148
152
|
* To skip some key-value pairs - use _mapObject instead.
|
|
149
153
|
*/
|
|
150
154
|
export function _mapKeys(obj, mapper) {
|
|
155
|
+
// Not vulnerable to prototype pollution: writes to a new {}, where __proto__
|
|
156
|
+
// assignment only changes the new object's prototype, not Object.prototype.
|
|
151
157
|
const map = {};
|
|
152
158
|
for (const [k, v] of Object.entries(obj)) {
|
|
153
159
|
map[mapper(k, v, obj)] = v;
|
|
@@ -171,6 +177,8 @@ export function _mapKeys(obj, mapper) {
|
|
|
171
177
|
* Non-string keys are passed via String(...)
|
|
172
178
|
*/
|
|
173
179
|
export function _mapObject(obj, mapper) {
|
|
180
|
+
// Not vulnerable to prototype pollution: writes to a new {}, where __proto__
|
|
181
|
+
// assignment only changes the new object's prototype, not Object.prototype.
|
|
174
182
|
const map = {};
|
|
175
183
|
for (const [k, v] of Object.entries(obj)) {
|
|
176
184
|
const r = mapper(k, v, obj);
|
|
@@ -204,6 +212,8 @@ export function _deepCopy(o, reviver) {
|
|
|
204
212
|
* otherwise it's not worth it (use normal object spread then).
|
|
205
213
|
*/
|
|
206
214
|
export function _mergeObjects(obj1, obj2) {
|
|
215
|
+
// Not vulnerable to prototype pollution: writes to a new {}, where __proto__
|
|
216
|
+
// assignment only changes the new object's prototype, not Object.prototype.
|
|
207
217
|
const map = {};
|
|
208
218
|
for (const k of Object.keys(obj1))
|
|
209
219
|
map[k] = obj1[k];
|
|
@@ -259,6 +269,8 @@ export function _merge(target, ...sources) {
|
|
|
259
269
|
if (!_isObject(source))
|
|
260
270
|
continue;
|
|
261
271
|
for (const key of Object.keys(source)) {
|
|
272
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype')
|
|
273
|
+
continue;
|
|
262
274
|
if (_isObject(source[key])) {
|
|
263
275
|
;
|
|
264
276
|
target[key] ||= {};
|
|
@@ -284,6 +296,9 @@ export function _deepTrim(o) {
|
|
|
284
296
|
return o.trim();
|
|
285
297
|
}
|
|
286
298
|
if (typeof o === 'object') {
|
|
299
|
+
// Not vulnerable to prototype pollution: mutates in-place on the same object.
|
|
300
|
+
// If __proto__ is an own data property (e.g. from JSON.parse), reads and writes
|
|
301
|
+
// go through the own property, not the Object.prototype accessor.
|
|
287
302
|
for (const k of Object.keys(o)) {
|
|
288
303
|
o[k] = _deepTrim(o[k]);
|
|
289
304
|
}
|
|
@@ -301,6 +316,9 @@ export function _unset(obj, prop) {
|
|
|
301
316
|
return;
|
|
302
317
|
}
|
|
303
318
|
const segs = prop.split('.');
|
|
319
|
+
// Prevent prototype pollution
|
|
320
|
+
if (segs.includes('__proto__') || segs.includes('constructor'))
|
|
321
|
+
return;
|
|
304
322
|
let last = segs.pop();
|
|
305
323
|
while (segs.length && segs[segs.length - 1].endsWith('\\')) {
|
|
306
324
|
last = segs.pop().slice(0, -1) + '.' + last;
|
|
@@ -363,6 +381,10 @@ export function _set(obj, path, value) {
|
|
|
363
381
|
else if (!path.length) {
|
|
364
382
|
return obj;
|
|
365
383
|
}
|
|
384
|
+
// Prevent prototype pollution
|
|
385
|
+
if (path.includes('__proto__') || path.includes('constructor')) {
|
|
386
|
+
return obj;
|
|
387
|
+
}
|
|
366
388
|
// oxlint-disable-next-line unicorn/no-array-reduce
|
|
367
389
|
;
|
|
368
390
|
path.slice(0, -1).reduce((a, c, i) => Object(a[c]) === a[c] // Does the key exist and is its value an object?
|
|
@@ -410,6 +432,8 @@ export function _has(obj, path) {
|
|
|
410
432
|
* Based on: https://github.com/substack/deep-freeze/blob/master/index.js
|
|
411
433
|
*/
|
|
412
434
|
export function _deepFreeze(o) {
|
|
435
|
+
// Not vulnerable to prototype pollution: read-only traversal, only calls
|
|
436
|
+
// Object.freeze — never assigns properties from one object to another.
|
|
413
437
|
Object.freeze(o);
|
|
414
438
|
Object.getOwnPropertyNames(o).forEach(prop => {
|
|
415
439
|
if (o.hasOwnProperty(prop) &&
|
package/dist/string/slugify.js
CHANGED
|
@@ -61,6 +61,5 @@ function decamelize(s) {
|
|
|
61
61
|
function escapeStringRegexp(s) {
|
|
62
62
|
// Escape characters with special meaning either inside or outside character sets.
|
|
63
63
|
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
|
|
64
|
-
// oxlint-disable-next-line unicorn/escape-case, unicorn/no-hex-escape
|
|
65
64
|
return s.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw `\$&`).replaceAll('-', String.raw `\x2d`);
|
|
66
65
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/js-lib",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "15.71.
|
|
4
|
+
"version": "15.71.3",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"tslib": "^2"
|
|
7
7
|
},
|
|
8
8
|
"peerDependencies": {
|
|
9
|
-
"undici": "^
|
|
9
|
+
"undici": "^8"
|
|
10
10
|
},
|
|
11
11
|
"peerDependenciesMeta": {
|
|
12
12
|
"undici": {
|
|
@@ -778,6 +778,7 @@ export class LocalTime {
|
|
|
778
778
|
}
|
|
779
779
|
|
|
780
780
|
format(fmt: Intl.DateTimeFormat | LocalTimeFormatter): string {
|
|
781
|
+
// oxlint-disable-next-line no-restricted-globals
|
|
781
782
|
if (fmt instanceof Intl.DateTimeFormat) {
|
|
782
783
|
return fmt.format(this.$date)
|
|
783
784
|
}
|
|
@@ -1009,6 +1010,7 @@ class LocalTimeFactory {
|
|
|
1009
1010
|
*/
|
|
1010
1011
|
isTimezoneValid(tz: string): boolean {
|
|
1011
1012
|
if (tz === 'UTC') return true // we deliberately consider UTC a valid timezone, while it's mostly used in testing
|
|
1013
|
+
// oxlint-disable-next-line no-restricted-globals
|
|
1012
1014
|
return Intl.supportedValuesOf('timeZone').includes(tz)
|
|
1013
1015
|
}
|
|
1014
1016
|
|
package/src/intl/intl.ts
CHANGED
|
@@ -153,6 +153,8 @@ export function _filterObject<T extends AnyObject>(
|
|
|
153
153
|
return obj
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
// Not vulnerable to prototype pollution: writes to a new {}, where __proto__
|
|
157
|
+
// assignment only changes the new object's prototype, not Object.prototype.
|
|
156
158
|
const r = {} as T
|
|
157
159
|
for (const [k, v] of _objectEntries(obj)) {
|
|
158
160
|
if (predicate(k, v, obj)) {
|
|
@@ -178,6 +180,8 @@ export function _mapValues<OUT = unknown, IN extends AnyObject = AnyObject>(
|
|
|
178
180
|
mapper: ObjectMapper<IN, any>,
|
|
179
181
|
opt: MutateOptions = {},
|
|
180
182
|
): OUT {
|
|
183
|
+
// Not vulnerable to prototype pollution: writes to a new {} (or mutates the
|
|
184
|
+
// source in-place where own data properties shadow the __proto__ accessor).
|
|
181
185
|
const map: any = opt.mutate ? obj : {}
|
|
182
186
|
for (const [k, v] of Object.entries(obj)) {
|
|
183
187
|
map[k] = mapper(k, v, obj)
|
|
@@ -194,6 +198,8 @@ export function _mapValues<OUT = unknown, IN extends AnyObject = AnyObject>(
|
|
|
194
198
|
* To skip some key-value pairs - use _mapObject instead.
|
|
195
199
|
*/
|
|
196
200
|
export function _mapKeys<T extends AnyObject>(obj: T, mapper: ObjectMapper<T, string>): T {
|
|
201
|
+
// Not vulnerable to prototype pollution: writes to a new {}, where __proto__
|
|
202
|
+
// assignment only changes the new object's prototype, not Object.prototype.
|
|
197
203
|
const map = {} as T
|
|
198
204
|
for (const [k, v] of Object.entries(obj)) {
|
|
199
205
|
map[mapper(k, v, obj) as keyof T] = v
|
|
@@ -221,6 +227,8 @@ export function _mapObject<OUT = unknown, IN extends AnyObject = AnyObject>(
|
|
|
221
227
|
obj: IN,
|
|
222
228
|
mapper: ObjectMapper<IN, KeyValueTuple<string, any> | typeof SKIP>,
|
|
223
229
|
): OUT {
|
|
230
|
+
// Not vulnerable to prototype pollution: writes to a new {}, where __proto__
|
|
231
|
+
// assignment only changes the new object's prototype, not Object.prototype.
|
|
224
232
|
const map: any = {}
|
|
225
233
|
for (const [k, v] of Object.entries(obj)) {
|
|
226
234
|
const r = mapper(k, v, obj)
|
|
@@ -260,6 +268,8 @@ export function _deepCopy<T>(o: T, reviver?: Reviver): T {
|
|
|
260
268
|
* otherwise it's not worth it (use normal object spread then).
|
|
261
269
|
*/
|
|
262
270
|
export function _mergeObjects<T>(obj1: StringMap<T>, obj2: StringMap<T>): StringMap<T> {
|
|
271
|
+
// Not vulnerable to prototype pollution: writes to a new {}, where __proto__
|
|
272
|
+
// assignment only changes the new object's prototype, not Object.prototype.
|
|
263
273
|
const map: StringMap<T> = {}
|
|
264
274
|
for (const k of Object.keys(obj1)) map[k] = obj1[k]
|
|
265
275
|
for (const k of Object.keys(obj2)) map[k] = obj2[k]
|
|
@@ -316,6 +326,8 @@ export function _merge<T extends AnyObject>(target: T, ...sources: any[]): T {
|
|
|
316
326
|
if (!_isObject(source)) continue
|
|
317
327
|
|
|
318
328
|
for (const key of Object.keys(source)) {
|
|
329
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue
|
|
330
|
+
|
|
319
331
|
if (_isObject(source[key])) {
|
|
320
332
|
;(target as any)[key] ||= {}
|
|
321
333
|
_merge(target[key], source[key])
|
|
@@ -340,6 +352,9 @@ export function _deepTrim<T extends AnyObject | string>(o: T): T {
|
|
|
340
352
|
return o.trim() as T
|
|
341
353
|
}
|
|
342
354
|
if (typeof o === 'object') {
|
|
355
|
+
// Not vulnerable to prototype pollution: mutates in-place on the same object.
|
|
356
|
+
// If __proto__ is an own data property (e.g. from JSON.parse), reads and writes
|
|
357
|
+
// go through the own property, not the Object.prototype accessor.
|
|
343
358
|
for (const k of Object.keys(o)) {
|
|
344
359
|
o[k] = _deepTrim(o[k])
|
|
345
360
|
}
|
|
@@ -361,6 +376,10 @@ export function _unset<T extends AnyObject>(obj: T, prop: string): void {
|
|
|
361
376
|
}
|
|
362
377
|
|
|
363
378
|
const segs = prop.split('.')
|
|
379
|
+
|
|
380
|
+
// Prevent prototype pollution
|
|
381
|
+
if (segs.includes('__proto__') || segs.includes('constructor')) return
|
|
382
|
+
|
|
364
383
|
let last = segs.pop()
|
|
365
384
|
while (segs.length && segs[segs.length - 1]!.endsWith('\\')) {
|
|
366
385
|
last = segs.pop()!.slice(0, -1) + '.' + last
|
|
@@ -431,6 +450,11 @@ export function _set<T extends AnyObject>(obj: T, path: PropertyPath, value: any
|
|
|
431
450
|
return obj as any
|
|
432
451
|
}
|
|
433
452
|
|
|
453
|
+
// Prevent prototype pollution
|
|
454
|
+
if ((path as any[]).includes('__proto__') || (path as any[]).includes('constructor')) {
|
|
455
|
+
return obj
|
|
456
|
+
}
|
|
457
|
+
|
|
434
458
|
// oxlint-disable-next-line unicorn/no-array-reduce
|
|
435
459
|
;(path as any[]).slice(0, -1).reduce(
|
|
436
460
|
(
|
|
@@ -487,6 +511,8 @@ export function _has<T extends AnyObject>(obj: T, path: string): boolean {
|
|
|
487
511
|
* Based on: https://github.com/substack/deep-freeze/blob/master/index.js
|
|
488
512
|
*/
|
|
489
513
|
export function _deepFreeze(o: any): void {
|
|
514
|
+
// Not vulnerable to prototype pollution: read-only traversal, only calls
|
|
515
|
+
// Object.freeze — never assigns properties from one object to another.
|
|
490
516
|
Object.freeze(o)
|
|
491
517
|
|
|
492
518
|
Object.getOwnPropertyNames(o).forEach(prop => {
|
package/src/string/slugify.ts
CHANGED
|
@@ -102,6 +102,5 @@ function decamelize(s: string): string {
|
|
|
102
102
|
function escapeStringRegexp(s: string): string {
|
|
103
103
|
// Escape characters with special meaning either inside or outside character sets.
|
|
104
104
|
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.
|
|
105
|
-
// oxlint-disable-next-line unicorn/escape-case, unicorn/no-hex-escape
|
|
106
105
|
return s.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw`\$&`).replaceAll('-', String.raw`\x2d`)
|
|
107
106
|
}
|