@ac-kit/core 0.1.0 → 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.
Files changed (176) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/dist/big-int/from-bytes-be.d.ts +14 -0
  3. package/dist/big-int/from-bytes-be.d.ts.map +1 -0
  4. package/dist/big-int/from-bytes-be.js +20 -0
  5. package/dist/big-int/from-bytes-be.js.map +1 -0
  6. package/dist/big-int/from-bytes-le.d.ts +15 -0
  7. package/dist/big-int/from-bytes-le.d.ts.map +1 -0
  8. package/dist/big-int/from-bytes-le.js +21 -0
  9. package/dist/big-int/from-bytes-le.js.map +1 -0
  10. package/dist/big-int/is-safe-number.d.ts +20 -0
  11. package/dist/big-int/is-safe-number.d.ts.map +1 -0
  12. package/dist/big-int/is-safe-number.js +24 -0
  13. package/dist/big-int/is-safe-number.js.map +1 -0
  14. package/dist/big-int/to-bytes-be.d.ts +19 -0
  15. package/dist/big-int/to-bytes-be.d.ts.map +1 -0
  16. package/dist/big-int/to-bytes-be.js +60 -0
  17. package/dist/big-int/to-bytes-be.js.map +1 -0
  18. package/dist/big-int/to-bytes-le.d.ts +19 -0
  19. package/dist/big-int/to-bytes-le.d.ts.map +1 -0
  20. package/dist/big-int/to-bytes-le.js +22 -0
  21. package/dist/big-int/to-bytes-le.js.map +1 -0
  22. package/dist/buffer/bytes-combine.d.ts +18 -0
  23. package/dist/buffer/bytes-combine.d.ts.map +1 -0
  24. package/dist/buffer/bytes-combine.js +25 -0
  25. package/dist/buffer/bytes-combine.js.map +1 -0
  26. package/dist/buffer/bytes-map.d.ts +14 -0
  27. package/dist/buffer/bytes-map.d.ts.map +1 -0
  28. package/dist/buffer/bytes-map.js +21 -0
  29. package/dist/buffer/bytes-map.js.map +1 -0
  30. package/dist/buffer/text/next-utf8-boundary.d.ts +17 -0
  31. package/dist/buffer/text/next-utf8-boundary.d.ts.map +1 -0
  32. package/dist/buffer/text/next-utf8-boundary.js +27 -0
  33. package/dist/buffer/text/next-utf8-boundary.js.map +1 -0
  34. package/dist/guards/has-object-prototype.d.ts +27 -0
  35. package/dist/guards/has-object-prototype.d.ts.map +1 -0
  36. package/dist/guards/has-object-prototype.js +30 -0
  37. package/dist/guards/has-object-prototype.js.map +1 -0
  38. package/dist/guards/is-object.d.ts +28 -2
  39. package/dist/guards/is-object.d.ts.map +1 -1
  40. package/dist/guards/is-object.js +28 -2
  41. package/dist/guards/is-object.js.map +1 -1
  42. package/dist/guards/is-pojo.d.ts +27 -2
  43. package/dist/guards/is-pojo.d.ts.map +1 -1
  44. package/dist/guards/is-pojo.js +27 -2
  45. package/dist/guards/is-pojo.js.map +1 -1
  46. package/dist/index.d.ts +22 -13
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +22 -13
  49. package/dist/index.js.map +1 -1
  50. package/dist/json/replacers/big-int.d.ts.map +1 -1
  51. package/dist/json/replacers/big-int.js +2 -5
  52. package/dist/json/replacers/big-int.js.map +1 -1
  53. package/dist/number/parse-number-or-big-int.d.ts +30 -0
  54. package/dist/number/parse-number-or-big-int.d.ts.map +1 -0
  55. package/dist/number/parse-number-or-big-int.js +44 -0
  56. package/dist/number/parse-number-or-big-int.js.map +1 -0
  57. package/dist/object/defaults.d.ts.map +1 -1
  58. package/dist/object/defaults.js +11 -4
  59. package/dist/object/defaults.js.map +1 -1
  60. package/dist/object/flatten-record.d.ts +67 -0
  61. package/dist/object/flatten-record.d.ts.map +1 -0
  62. package/dist/object/flatten-record.js +81 -0
  63. package/dist/object/flatten-record.js.map +1 -0
  64. package/dist/object/get-at-path.d.ts +5 -0
  65. package/dist/object/get-at-path.d.ts.map +1 -1
  66. package/dist/object/get-at-path.js +5 -0
  67. package/dist/object/get-at-path.js.map +1 -1
  68. package/dist/object/is-unsafe-record-key.d.ts +26 -0
  69. package/dist/object/is-unsafe-record-key.d.ts.map +1 -0
  70. package/dist/object/is-unsafe-record-key.js +28 -0
  71. package/dist/object/is-unsafe-record-key.js.map +1 -0
  72. package/dist/object/merge-inplace.d.ts.map +1 -1
  73. package/dist/object/merge-inplace.js +4 -2
  74. package/dist/object/merge-inplace.js.map +1 -1
  75. package/dist/object/merge.d.ts.map +1 -1
  76. package/dist/object/merge.js +4 -2
  77. package/dist/object/merge.js.map +1 -1
  78. package/dist/object/null-if-empty.d.ts +12 -0
  79. package/dist/object/null-if-empty.d.ts.map +1 -0
  80. package/dist/object/null-if-empty.js +17 -0
  81. package/dist/object/null-if-empty.js.map +1 -0
  82. package/dist/object/set-at-path.d.ts +5 -0
  83. package/dist/object/set-at-path.d.ts.map +1 -1
  84. package/dist/object/set-at-path.js +10 -3
  85. package/dist/object/set-at-path.js.map +1 -1
  86. package/dist/object/set-record-entry.d.ts +32 -0
  87. package/dist/object/set-record-entry.d.ts.map +1 -0
  88. package/dist/object/set-record-entry.js +43 -0
  89. package/dist/object/set-record-entry.js.map +1 -0
  90. package/dist/object/traverse.js +3 -3
  91. package/dist/object/traverse.js.map +1 -1
  92. package/dist/object/unflatten-record.d.ts +63 -0
  93. package/dist/object/unflatten-record.d.ts.map +1 -0
  94. package/dist/object/unflatten-record.js +71 -0
  95. package/dist/object/unflatten-record.js.map +1 -0
  96. package/dist/string/ascii/is-ascii-blank.d.ts +8 -0
  97. package/dist/string/ascii/is-ascii-blank.d.ts.map +1 -0
  98. package/dist/string/ascii/is-ascii-blank.js +11 -0
  99. package/dist/string/ascii/is-ascii-blank.js.map +1 -0
  100. package/dist/string/ascii/is-ascii-control.d.ts +6 -0
  101. package/dist/string/ascii/is-ascii-control.d.ts.map +1 -0
  102. package/dist/string/ascii/is-ascii-control.js +9 -0
  103. package/dist/string/ascii/is-ascii-control.js.map +1 -0
  104. package/dist/string/ascii/is-ascii-graphic.d.ts +7 -0
  105. package/dist/string/ascii/is-ascii-graphic.d.ts.map +1 -0
  106. package/dist/string/ascii/is-ascii-graphic.js +10 -0
  107. package/dist/string/ascii/is-ascii-graphic.js.map +1 -0
  108. package/dist/string/ascii/is-ascii-printable.d.ts +7 -0
  109. package/dist/string/ascii/is-ascii-printable.d.ts.map +1 -0
  110. package/dist/string/ascii/is-ascii-printable.js +10 -0
  111. package/dist/string/ascii/is-ascii-printable.js.map +1 -0
  112. package/dist/string/ascii/is-ascii-punctuation.d.ts +6 -0
  113. package/dist/string/ascii/is-ascii-punctuation.d.ts.map +1 -0
  114. package/dist/string/ascii/is-ascii-punctuation.js +10 -0
  115. package/dist/string/ascii/is-ascii-punctuation.js.map +1 -0
  116. package/dist/system/fs/escape-posix-path.d.ts.map +1 -0
  117. package/dist/system/fs/escape-posix-path.js.map +1 -0
  118. package/dist/system/fs/escape-win32-path.d.ts.map +1 -0
  119. package/dist/system/fs/escape-win32-path.js.map +1 -0
  120. package/package.json +2 -2
  121. package/dist/guards/is-plain-object.d.ts +0 -8
  122. package/dist/guards/is-plain-object.d.ts.map +0 -1
  123. package/dist/guards/is-plain-object.js +0 -11
  124. package/dist/guards/is-plain-object.js.map +0 -1
  125. package/dist/net/ephemeral-port.d.ts +0 -13
  126. package/dist/net/ephemeral-port.d.ts.map +0 -1
  127. package/dist/net/ephemeral-port.js +0 -19
  128. package/dist/net/ephemeral-port.js.map +0 -1
  129. package/dist/net/inet-address.d.ts +0 -20
  130. package/dist/net/inet-address.d.ts.map +0 -1
  131. package/dist/net/inet-address.js +0 -42
  132. package/dist/net/inet-address.js.map +0 -1
  133. package/dist/net/inet-endpoint.d.ts +0 -7
  134. package/dist/net/inet-endpoint.d.ts.map +0 -1
  135. package/dist/net/inet-endpoint.js +0 -2
  136. package/dist/net/inet-endpoint.js.map +0 -1
  137. package/dist/shell/fs/escape-posix-path.d.ts.map +0 -1
  138. package/dist/shell/fs/escape-posix-path.js.map +0 -1
  139. package/dist/shell/fs/escape-win32-path.d.ts.map +0 -1
  140. package/dist/shell/fs/escape-win32-path.js.map +0 -1
  141. package/dist/shell/process/parse-env-variable.d.ts +0 -43
  142. package/dist/shell/process/parse-env-variable.d.ts.map +0 -1
  143. package/dist/shell/process/parse-env-variable.js +0 -109
  144. package/dist/shell/process/parse-env-variable.js.map +0 -1
  145. package/dist/shell/process/stringify-env-variable.d.ts +0 -50
  146. package/dist/shell/process/stringify-env-variable.d.ts.map +0 -1
  147. package/dist/shell/process/stringify-env-variable.js +0 -86
  148. package/dist/shell/process/stringify-env-variable.js.map +0 -1
  149. package/dist/shell/process/types.d.ts +0 -7
  150. package/dist/shell/process/types.d.ts.map +0 -1
  151. package/dist/shell/process/types.js +0 -2
  152. package/dist/shell/process/types.js.map +0 -1
  153. package/dist/shell/shell/escape-posix-sh-command-arg.d.ts +0 -20
  154. package/dist/shell/shell/escape-posix-sh-command-arg.d.ts.map +0 -1
  155. package/dist/shell/shell/escape-posix-sh-command-arg.js +0 -26
  156. package/dist/shell/shell/escape-posix-sh-command-arg.js.map +0 -1
  157. package/dist/shell/shell/escape-posix-sh-command.d.ts +0 -19
  158. package/dist/shell/shell/escape-posix-sh-command.d.ts.map +0 -1
  159. package/dist/shell/shell/escape-posix-sh-command.js +0 -55
  160. package/dist/shell/shell/escape-posix-sh-command.js.map +0 -1
  161. package/dist/shell/shell/escape-posix-sh-sqe.d.ts +0 -13
  162. package/dist/shell/shell/escape-posix-sh-sqe.d.ts.map +0 -1
  163. package/dist/shell/shell/escape-posix-sh-sqe.js +0 -15
  164. package/dist/shell/shell/escape-posix-sh-sqe.js.map +0 -1
  165. package/dist/shell/shell/escape-win32-cmd-command-arg.d.ts +0 -20
  166. package/dist/shell/shell/escape-win32-cmd-command-arg.d.ts.map +0 -1
  167. package/dist/shell/shell/escape-win32-cmd-command-arg.js +0 -29
  168. package/dist/shell/shell/escape-win32-cmd-command-arg.js.map +0 -1
  169. package/dist/shell/shell/escape-win32-cmd-command.d.ts +0 -18
  170. package/dist/shell/shell/escape-win32-cmd-command.d.ts.map +0 -1
  171. package/dist/shell/shell/escape-win32-cmd-command.js +0 -20
  172. package/dist/shell/shell/escape-win32-cmd-command.js.map +0 -1
  173. /package/dist/{shell → system}/fs/escape-posix-path.d.ts +0 -0
  174. /package/dist/{shell → system}/fs/escape-posix-path.js +0 -0
  175. /package/dist/{shell → system}/fs/escape-win32-path.d.ts +0 -0
  176. /package/dist/{shell → system}/fs/escape-win32-path.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/object/defaults.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,QAAQ,CACvB,GAAG,IAAsC;IAEzC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,MAAa,EAAE,GAAG,EAAE,EAAE;QACzC,IAAI,GAAG,EAAE,CAAC;YACT,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;gBACvB,IACE,MAAwB,CAAC,GAAG,CAAC,KAAK,SAAS;oBAC3C,GAAqB,CAAC,GAAG,CAAC,KAAK,SAAS,EACxC,CAAC;oBACD,MAAwB,CAAC,GAAG,CAAC,GAAI,GAAqB,CAAC,GAAG,CAAC,CAAC;gBAC9D,CAAC;YACF,CAAC;QACF,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC,EAAE,EAAO,CAAM,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/object/defaults.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,QAAQ,CACvB,GAAG,IAAsC;IAEzC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,MAAa,EAAE,GAAG,EAAE,EAAE;QACzC,IAAI,GAAG,EAAE,CAAC;YACT,yEAAyE;YACzE,yEAAyE;YACzE,mCAAmC;YACnC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,KAAK,GAAI,GAAqB,CAAC,GAAG,CAAC,CAAC;gBAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;oBACzC,CAAC,CAAE,MAAwB,CAAC,GAAG,CAAC;oBAChC,CAAC,CAAC,SAAS,CAAC;gBAEb,IAAI,OAAO,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAClD,cAAc,CAAC,MAAuB,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;gBACrD,CAAC;YACF,CAAC;QACF,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC,EAAE,EAAO,CAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,67 @@
1
+ export type FlattenRecordOptions = {
2
+ /**
3
+ * Separator joining the segments of an output key. Default `"."`.
4
+ *
5
+ * Must not be empty: `unflattenRecord` splits on it, and splitting on `""`
6
+ * would take every key apart character by character.
7
+ */
8
+ readonly delimiter?: string | null;
9
+ /**
10
+ * Descends into arrays, numbering their elements. Default `false`, which
11
+ * leaves an array whole as a leaf value.
12
+ *
13
+ * Off by default because an index is the one segment a flattened key cannot
14
+ * tell apart from an ordinary key spelled `"0"`, so numbering costs the round
15
+ * trip its only ambiguity-free case.
16
+ */
17
+ readonly flattenArrays?: boolean | null;
18
+ /**
19
+ * Greatest number of segments an output key may have. Default: unbounded.
20
+ *
21
+ * A value below that depth is copied across whole, still nested. `1` copies
22
+ * the record's own entries without flattening anything.
23
+ */
24
+ readonly maxDepth?: number | null;
25
+ };
26
+ /**
27
+ * Collapse a nested record into a one-level one, naming each leaf by the
28
+ * delimiter-joined path that reached it.
29
+ *
30
+ * A leaf is anything that is not a plain object — a `Date`, a `Map`, a class
31
+ * instance and, by default, an array are all copied across whole. So is an
32
+ * empty plain object, which has no entry to name and would otherwise vanish.
33
+ *
34
+ * **A key that contains the delimiter is not escaped.** `{ "a.b": 1 }` flattens
35
+ * to `{ "a.b": 1 }`, exactly as `{ a: { b: 1 } }` does, and
36
+ * {@link unflattenRecord} reads both back as `{ a: { b: 1 } }` — the delimiter
37
+ * always wins over a literal occurrence of it. Two inputs colliding onto one
38
+ * output key leave the last one written, in `Object.keys` order. Pick a
39
+ * delimiter the keys cannot contain when the round trip has to hold.
40
+ *
41
+ * Keys are written with `setRecordEntry`, so an input key named `__proto__`
42
+ * becomes an own entry of the result instead of reaching the prototype setter.
43
+ *
44
+ * Time is linear in the number of nodes visited, plus the cost of building the
45
+ * keys, which is the total length of the output's keys. Memory is the output
46
+ * record plus one stack frame per level of nesting, so a record nested deeper
47
+ * than the engine's stack overflows rather than degrading.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * flattenRecord({ key1: { keyA: "v" }, key2: { a: { b: 2 } } });
52
+ * // { "key1.keyA": "v", "key2.a.b": 2 }
53
+ *
54
+ * flattenRecord({ host: { tags: ["a", "b"] } });
55
+ * // { "host.tags": ["a", "b"] } — an array is a leaf
56
+ *
57
+ * flattenRecord({ a: { b: { c: 1 } } }, { delimiter: "/", maxDepth: 2 });
58
+ * // { "a/b": { c: 1 } }
59
+ * ```;
60
+ *
61
+ * @param source The record to flatten; it is not modified.
62
+ * @param options Delimiter, array handling and depth cap.
63
+ * @returns A new one-level record.
64
+ * @throws RangeError If the delimiter is empty or `maxDepth` is below 1.
65
+ */
66
+ export declare function flattenRecord(source: Readonly<Record<string, unknown>>, options?: FlattenRecordOptions): Record<string, unknown>;
67
+ //# sourceMappingURL=flatten-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flatten-record.d.ts","sourceRoot":"","sources":["../../src/object/flatten-record.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,oBAAoB,GAAG;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnC;;;;;;;OAOG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAExC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AA4CF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,aAAa,CAC5B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,OAAO,CAAC,EAAE,oBAAoB,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkBzB"}
@@ -0,0 +1,81 @@
1
+ import { isPojo } from "../guards/is-pojo.js";
2
+ import { setRecordEntry } from "./set-record-entry.js";
3
+ /** An empty container has no entry to name, so flattening it would lose the key. */
4
+ function isDescendable_(value, options) {
5
+ if (Array.isArray(value)) {
6
+ return options.flattenArrays && value.length > 0;
7
+ }
8
+ return isPojo(value) && Object.keys(value).length > 0;
9
+ }
10
+ function step_(source, prefix, depth, output, options) {
11
+ // Own keys only: `for...in` would walk a hostile source's prototype too.
12
+ for (const key of Object.keys(source)) {
13
+ const value = source[key];
14
+ // `null` rather than `""` for the root: a top-level key may itself be empty.
15
+ const outputKey = prefix === null ? key : prefix + options.delimiter + key;
16
+ if (depth < options.maxDepth && isDescendable_(value, options)) {
17
+ step_(value, outputKey, depth + 1, output, options);
18
+ }
19
+ else {
20
+ setRecordEntry(output, outputKey, value);
21
+ }
22
+ }
23
+ }
24
+ /**
25
+ * Collapse a nested record into a one-level one, naming each leaf by the
26
+ * delimiter-joined path that reached it.
27
+ *
28
+ * A leaf is anything that is not a plain object — a `Date`, a `Map`, a class
29
+ * instance and, by default, an array are all copied across whole. So is an
30
+ * empty plain object, which has no entry to name and would otherwise vanish.
31
+ *
32
+ * **A key that contains the delimiter is not escaped.** `{ "a.b": 1 }` flattens
33
+ * to `{ "a.b": 1 }`, exactly as `{ a: { b: 1 } }` does, and
34
+ * {@link unflattenRecord} reads both back as `{ a: { b: 1 } }` — the delimiter
35
+ * always wins over a literal occurrence of it. Two inputs colliding onto one
36
+ * output key leave the last one written, in `Object.keys` order. Pick a
37
+ * delimiter the keys cannot contain when the round trip has to hold.
38
+ *
39
+ * Keys are written with `setRecordEntry`, so an input key named `__proto__`
40
+ * becomes an own entry of the result instead of reaching the prototype setter.
41
+ *
42
+ * Time is linear in the number of nodes visited, plus the cost of building the
43
+ * keys, which is the total length of the output's keys. Memory is the output
44
+ * record plus one stack frame per level of nesting, so a record nested deeper
45
+ * than the engine's stack overflows rather than degrading.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * flattenRecord({ key1: { keyA: "v" }, key2: { a: { b: 2 } } });
50
+ * // { "key1.keyA": "v", "key2.a.b": 2 }
51
+ *
52
+ * flattenRecord({ host: { tags: ["a", "b"] } });
53
+ * // { "host.tags": ["a", "b"] } — an array is a leaf
54
+ *
55
+ * flattenRecord({ a: { b: { c: 1 } } }, { delimiter: "/", maxDepth: 2 });
56
+ * // { "a/b": { c: 1 } }
57
+ * ```;
58
+ *
59
+ * @param source The record to flatten; it is not modified.
60
+ * @param options Delimiter, array handling and depth cap.
61
+ * @returns A new one-level record.
62
+ * @throws RangeError If the delimiter is empty or `maxDepth` is below 1.
63
+ */
64
+ export function flattenRecord(source, options) {
65
+ const resolved = {
66
+ delimiter: options?.delimiter ?? ".",
67
+ flattenArrays: options?.flattenArrays ?? false,
68
+ maxDepth: options?.maxDepth ?? Number.POSITIVE_INFINITY,
69
+ };
70
+ if (resolved.delimiter.length === 0) {
71
+ throw new RangeError("flattenRecord: delimiter must not be empty");
72
+ }
73
+ // Negated so a `NaN` depth is rejected rather than silently flattening nothing.
74
+ if (!(resolved.maxDepth >= 1)) {
75
+ throw new RangeError("flattenRecord: maxDepth must be at least 1");
76
+ }
77
+ const output = {};
78
+ step_(source, null, 1, output, resolved);
79
+ return output;
80
+ }
81
+ //# sourceMappingURL=flatten-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flatten-record.js","sourceRoot":"","sources":["../../src/object/flatten-record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAoCvD,oFAAoF;AACpF,SAAS,cAAc,CAAC,KAAc,EAAE,OAAkB;IACzD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,KAAK,CACb,MAAyC,EACzC,MAAqB,EACrB,KAAa,EACb,MAA+B,EAC/B,OAAkB;IAElB,yEAAyE;IACzE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,6EAA6E;QAC7E,MAAM,SAAS,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,GAAG,CAAC;QAE3E,IAAI,KAAK,GAAG,OAAO,CAAC,QAAQ,IAAI,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;YAChE,KAAK,CACJ,KAA0C,EAC1C,SAAS,EACT,KAAK,GAAG,CAAC,EACT,MAAM,EACN,OAAO,CACP,CAAC;QACH,CAAC;aAAM,CAAC;YACP,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,UAAU,aAAa,CAC5B,MAAyC,EACzC,OAA8B;IAE9B,MAAM,QAAQ,GAAc;QAC3B,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,GAAG;QACpC,aAAa,EAAE,OAAO,EAAE,aAAa,IAAI,KAAK;QAC9C,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,MAAM,CAAC,iBAAiB;KACvD,CAAC;IAEF,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC,CAAC;IACpE,CAAC;IACD,gFAAgF;IAChF,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -6,6 +6,11 @@ export type PropertyPath = readonly (string | number)[];
6
6
  /**
7
7
  * Gets the value at `path` inside `root`.
8
8
  *
9
+ * Unlike `setAtPath`, this does not refuse a path through `__proto__`,
10
+ * `constructor` or `prototype`: reading one hands back a prototype the caller
11
+ * could already reach through any object it holds, so refusing it would cost an
12
+ * honest lookup and prevent nothing.
13
+ *
9
14
  * @param root The root object/array to traverse
10
15
  * @param path The path to traverse
11
16
  * @returns The value at the path, or `undefined` if the path does not exist.
@@ -1 +1 @@
1
- {"version":3,"file":"get-at-path.d.ts","sourceRoot":"","sources":["../../src/object/get-at-path.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAkBpE"}
1
+ {"version":3,"file":"get-at-path.d.ts","sourceRoot":"","sources":["../../src/object/get-at-path.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAkBpE"}
@@ -2,6 +2,11 @@ import { isObject } from "../guards/is-object.js";
2
2
  /**
3
3
  * Gets the value at `path` inside `root`.
4
4
  *
5
+ * Unlike `setAtPath`, this does not refuse a path through `__proto__`,
6
+ * `constructor` or `prototype`: reading one hands back a prototype the caller
7
+ * could already reach through any object it holds, so refusing it would cost an
8
+ * honest lookup and prevent nothing.
9
+ *
5
10
  * @param root The root object/array to traverse
6
11
  * @param path The path to traverse
7
12
  * @returns The value at the path, or `undefined` if the path does not exist.
@@ -1 +1 @@
1
- {"version":3,"file":"get-at-path.js","sourceRoot":"","sources":["../../src/object/get-at-path.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAQlD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,IAAa,EAAE,IAAkB;IAC1D,IAAI,OAAO,GAAG,IAAI,CAAC;IAEnB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC;YACnB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO;YACR,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,GAAI,OAAyB,CAAC,GAAG,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACP,OAAO;QACR,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"get-at-path.js","sourceRoot":"","sources":["../../src/object/get-at-path.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAQlD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,IAAa,EAAE,IAAkB;IAC1D,IAAI,OAAO,GAAG,IAAI,CAAC;IAEnB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC;YACnB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO;YACR,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,GAAI,OAAyB,CAAC,GAAG,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACP,OAAO;QACR,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Check whether a key may be followed while walking a record built from
3
+ * untrusted input.
4
+ *
5
+ * `__proto__` reaches the prototype setter when assigned to; `constructor`
6
+ * followed by `prototype` reaches `Object.prototype` when merely read, and a
7
+ * path-walking writer then mutates it. All three names are rejected together
8
+ * because a walk cannot tell which position it is in until the damage is done.
9
+ *
10
+ * Use this for a **path**. A single leaf assignment wants `setRecordEntry`
11
+ * instead, which stores such a key rather than refusing it — a record of
12
+ * environment variables or INI settings should still be able to hold one named
13
+ * `constructor`.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * isUnsafeRecordKey("__proto__"); // true
18
+ * isUnsafeRecordKey("constructor"); // true
19
+ * isUnsafeRecordKey("toString"); // false — shadowing is not pollution
20
+ * ```;
21
+ *
22
+ * @param key The key to check.
23
+ * @returns True if following the key can reach a shared prototype.
24
+ */
25
+ export declare function isUnsafeRecordKey(key: PropertyKey): boolean;
26
+ //# sourceMappingURL=is-unsafe-record-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-unsafe-record-key.d.ts","sourceRoot":"","sources":["../../src/object/is-unsafe-record-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAE3D"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Check whether a key may be followed while walking a record built from
3
+ * untrusted input.
4
+ *
5
+ * `__proto__` reaches the prototype setter when assigned to; `constructor`
6
+ * followed by `prototype` reaches `Object.prototype` when merely read, and a
7
+ * path-walking writer then mutates it. All three names are rejected together
8
+ * because a walk cannot tell which position it is in until the damage is done.
9
+ *
10
+ * Use this for a **path**. A single leaf assignment wants `setRecordEntry`
11
+ * instead, which stores such a key rather than refusing it — a record of
12
+ * environment variables or INI settings should still be able to hold one named
13
+ * `constructor`.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * isUnsafeRecordKey("__proto__"); // true
18
+ * isUnsafeRecordKey("constructor"); // true
19
+ * isUnsafeRecordKey("toString"); // false — shadowing is not pollution
20
+ * ```;
21
+ *
22
+ * @param key The key to check.
23
+ * @returns True if following the key can reach a shared prototype.
24
+ */
25
+ export function isUnsafeRecordKey(key) {
26
+ return key === "__proto__" || key === "constructor" || key === "prototype";
27
+ }
28
+ //# sourceMappingURL=is-unsafe-record-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-unsafe-record-key.js","sourceRoot":"","sources":["../../src/object/is-unsafe-record-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAgB;IACjD,OAAO,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,WAAW,CAAC;AAC5E,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"merge-inplace.d.ts","sourceRoot":"","sources":["../../src/object/merge-inplace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOlD,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,MAAM,oBAAoB,CAAC;AA4B5B;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EACvD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,YAAY,GAAG;IAAE,SAAS,CAAC,EAAE,KAAK,CAAA;CAAE,GAC5C,CAAC,CAAC;AACL,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3D,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,YAAY,GAAG;IAAE,SAAS,EAAE,IAAI,CAAA;CAAE,GACzC,CAAC,CAAC;AASL;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,QAAQ,SAAS,SAAS,OAAO,EAAE,EAC3E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CASnC"}
1
+ {"version":3,"file":"merge-inplace.d.ts","sourceRoot":"","sources":["../../src/object/merge-inplace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOlD,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,MAAM,oBAAoB,CAAC;AA6B5B;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EACvD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,YAAY,GAAG;IAAE,SAAS,CAAC,EAAE,KAAK,CAAA;CAAE,GAC5C,CAAC,CAAC;AACL,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAC3D,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,YAAY,GAAG;IAAE,SAAS,EAAE,IAAI,CAAA;CAAE,GACzC,CAAC,CAAC;AASL;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,QAAQ,SAAS,SAAS,OAAO,EAAE,EAC3E,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CASnC"}
@@ -4,6 +4,7 @@ import { isPojo } from "../guards/is-pojo.js";
4
4
  import { isSet } from "../guards/is-set.js";
5
5
  import { clone } from "./clone.js";
6
6
  import { MERGE_DEFAULT_OPTIONS, } from "./merge-options.js";
7
+ import { setRecordEntry } from "./set-record-entry.js";
7
8
  function resolve_(options) {
8
9
  return {
9
10
  recursive: options?.recursive ?? MERGE_DEFAULT_OPTIONS.recursive,
@@ -65,8 +66,9 @@ function mergeInplace_(target, source, options) {
65
66
  return fromSource_(source, options);
66
67
  }
67
68
  function mergePojoInplace_(target, source, options) {
68
- for (const key in source) {
69
- target[key] = nested_(target[key], source[key], options);
69
+ // Own keys only: `for...in` would walk a hostile source's prototype too.
70
+ for (const key of Object.keys(source)) {
71
+ setRecordEntry(target, key, nested_(target[key], source[key], options));
70
72
  }
71
73
  }
72
74
  function mergeSetInplace_(target, source, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"merge-inplace.js","sourceRoot":"","sources":["../../src/object/merge-inplace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"merge-inplace.js","sourceRoot":"","sources":["../../src/object/merge-inplace.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/object/merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOlD,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,MAAM,oBAAoB,CAAC;AA4B5B;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAChD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,YAAY,GAAG;IAAE,SAAS,CAAC,EAAE,KAAK,CAAA;CAAE,GAC5C,CAAC,CAAC;AACL,wBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EACpD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,YAAY,GAAG;IAAE,SAAS,EAAE,IAAI,CAAA;CAAE,GACzC,CAAC,CAAC;AASL;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,SAAS,SAAS,OAAO,EAAE,EAC3D,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,YAAY,GACpB,aAAa,CAAC,QAAQ,CAAC,CASzB"}
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/object/merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAOlD,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,MAAM,oBAAoB,CAAC;AA6B5B;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAChD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,YAAY,GAAG;IAAE,SAAS,CAAC,EAAE,KAAK,CAAA;CAAE,GAC5C,CAAC,CAAC;AACL,wBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EACpD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,YAAY,GAAG;IAAE,SAAS,EAAE,IAAI,CAAA;CAAE,GACzC,CAAC,CAAC;AASL;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,SAAS,SAAS,OAAO,EAAE,EAC3D,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,YAAY,GACpB,aAAa,CAAC,QAAQ,CAAC,CASzB"}
@@ -4,6 +4,7 @@ import { isPojo } from "../guards/is-pojo.js";
4
4
  import { isSet } from "../guards/is-set.js";
5
5
  import { clone } from "./clone.js";
6
6
  import { MERGE_DEFAULT_OPTIONS, } from "./merge-options.js";
7
+ import { setRecordEntry } from "./set-record-entry.js";
7
8
  function resolve_(options) {
8
9
  return {
9
10
  recursive: options?.recursive ?? MERGE_DEFAULT_OPTIONS.recursive,
@@ -60,8 +61,9 @@ function merge_(target, source, options) {
60
61
  }
61
62
  function mergePojo_(target, source, options) {
62
63
  const output = { ...target };
63
- for (const key in source) {
64
- output[key] = nested_(target[key], source[key], options);
64
+ // Own keys only: `for...in` would walk a hostile source's prototype too.
65
+ for (const key of Object.keys(source)) {
66
+ setRecordEntry(output, key, nested_(target[key], source[key], options));
65
67
  }
66
68
  return output;
67
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/object/merge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/object/merge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Normalizes an object with no own enumerable property to `null`.
3
+ *
4
+ * Useful against APIs that report "no value" as an empty object rather than as
5
+ * `null` or `undefined`, so that callers only have one absent form to test.
6
+ *
7
+ * @param value The object to normalize.
8
+ * @returns The object, or `null` when it is absent or has no own enumerable
9
+ * property.
10
+ */
11
+ export declare function nullIfEmpty<T extends object>(value: T | null | undefined): T | null;
12
+ //# sourceMappingURL=null-if-empty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"null-if-empty.d.ts","sourceRoot":"","sources":["../../src/object/null-if-empty.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC3C,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GACzB,CAAC,GAAG,IAAI,CAMV"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Normalizes an object with no own enumerable property to `null`.
3
+ *
4
+ * Useful against APIs that report "no value" as an empty object rather than as
5
+ * `null` or `undefined`, so that callers only have one absent form to test.
6
+ *
7
+ * @param value The object to normalize.
8
+ * @returns The object, or `null` when it is absent or has no own enumerable
9
+ * property.
10
+ */
11
+ export function nullIfEmpty(value) {
12
+ if (value === null || value === undefined) {
13
+ return null;
14
+ }
15
+ return Object.keys(value).length === 0 ? null : value;
16
+ }
17
+ //# sourceMappingURL=null-if-empty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"null-if-empty.js","sourceRoot":"","sources":["../../src/object/null-if-empty.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAC1B,KAA2B;IAE3B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACvD,CAAC"}
@@ -6,6 +6,11 @@ import { PropertyPath } from "./get-at-path.js";
6
6
  * the next key (`number` → array, `string` → object). Existing `null` or
7
7
  * `undefined` intermediates are replaced.
8
8
  *
9
+ * A path containing `__proto__`, `constructor` or `prototype` is refused
10
+ * outright and nothing is written, because walking one reaches a prototype
11
+ * shared with every other object. The refusal is silent, like the one for a
12
+ * non-numeric index into an array.
13
+ *
9
14
  * @param root The root object/array to mutate
10
15
  * @param path The path to traverse
11
16
  * @param value The value to set at the path
@@ -1 +1 @@
1
- {"version":3,"file":"set-at-path.d.ts","sourceRoot":"","sources":["../../src/object/set-at-path.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,EACzC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,OAAO,GACZ,IAAI,CAyCN"}
1
+ {"version":3,"file":"set-at-path.d.ts","sourceRoot":"","sources":["../../src/object/set-at-path.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAIhD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,EACzC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,OAAO,GACZ,IAAI,CAyCN"}
@@ -1,4 +1,6 @@
1
1
  import { isObject } from "../guards/is-object.js";
2
+ import { isUnsafeRecordKey } from "./is-unsafe-record-key.js";
3
+ import { setRecordEntry } from "./set-record-entry.js";
2
4
  /**
3
5
  * Mutates `root` by setting the value at `path`.
4
6
  *
@@ -6,12 +8,17 @@ import { isObject } from "../guards/is-object.js";
6
8
  * the next key (`number` → array, `string` → object). Existing `null` or
7
9
  * `undefined` intermediates are replaced.
8
10
  *
11
+ * A path containing `__proto__`, `constructor` or `prototype` is refused
12
+ * outright and nothing is written, because walking one reaches a prototype
13
+ * shared with every other object. The refusal is silent, like the one for a
14
+ * non-numeric index into an array.
15
+ *
9
16
  * @param root The root object/array to mutate
10
17
  * @param path The path to traverse
11
18
  * @param value The value to set at the path
12
19
  */
13
20
  export function setAtPath(root, path, value) {
14
- if (path.length === 0) {
21
+ if (path.length === 0 || path.some(isUnsafeRecordKey)) {
15
22
  return;
16
23
  }
17
24
  let current = root;
@@ -31,7 +38,7 @@ export function setAtPath(root, path, value) {
31
38
  else {
32
39
  const obj = current;
33
40
  if (!isObject(obj[key]) && !Array.isArray(obj[key])) {
34
- obj[key] = typeof nextKey === "number" ? [] : {};
41
+ setRecordEntry(obj, String(key), typeof nextKey === "number" ? [] : {});
35
42
  }
36
43
  current = obj[key];
37
44
  }
@@ -45,7 +52,7 @@ export function setAtPath(root, path, value) {
45
52
  current[lastIndex] = value;
46
53
  }
47
54
  else {
48
- current[lastKey] = value;
55
+ setRecordEntry(current, String(lastKey), value);
49
56
  }
50
57
  }
51
58
  //# sourceMappingURL=set-at-path.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"set-at-path.js","sourceRoot":"","sources":["../../src/object/set-at-path.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CACxB,IAAyC,EACzC,IAAkB,EAClB,KAAc;IAEd,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;IACR,CAAC;IAED,IAAI,OAAO,GAAY,IAAI,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QAE7B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC;YACnB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO;YACR,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjE,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACP,MAAM,GAAG,GAAG,OAAwB,CAAC;YAErC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,CAAC;YACD,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACF,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IACvC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC;QAC3B,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,OAAO;QACR,CAAC;QACD,OAAO,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAC5B,CAAC;SAAM,CAAC;QACN,OAAyB,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;IAC7C,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"set-at-path.js","sourceRoot":"","sources":["../../src/object/set-at-path.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,SAAS,CACxB,IAAyC,EACzC,IAAkB,EAClB,KAAc;IAEd,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACvD,OAAO;IACR,CAAC;IAED,IAAI,OAAO,GAAY,IAAI,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QAE7B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC;YACnB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO;YACR,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjE,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACP,MAAM,GAAG,GAAG,OAAwB,CAAC;YAErC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACrD,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzE,CAAC;YACD,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACF,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IACvC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC;QAC3B,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,OAAO;QACR,CAAC;QACD,OAAO,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAC5B,CAAC;SAAM,CAAC;QACP,cAAc,CAAC,OAAwB,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC;AACF,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Assign into a record whose keys come from untrusted input.
3
+ *
4
+ * `record[key] = value` runs the `__proto__` setter inherited from
5
+ * `Object.prototype`, so one key out of parsed text can replace the prototype
6
+ * of every object built afterwards. Defining the property instead stores an
7
+ * ordinary own `__proto__` entry and reaches no setter, leaving the record an
8
+ * otherwise normal object: same prototype, same spread, same `deepEqual`.
9
+ *
10
+ * Costs one string comparison over a plain assignment for every other key, so
11
+ * it is safe to call from a parser loop — `Object.defineProperty` is far slower
12
+ * and is taken only for the single key that needs it.
13
+ *
14
+ * This guards a **write**. A caller walking a path of untrusted keys must also
15
+ * guard its reads with `isUnsafeRecordKey`: stepping through `constructor` and
16
+ * then `prototype` pollutes without ever assigning to `__proto__`.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const parsed: Record<string, unknown> = {};
21
+ * setRecordEntry(parsed, "__proto__", { polluted: true });
22
+ *
23
+ * parsed["__proto__"]; // { polluted: true } — an own entry
24
+ * Object.getPrototypeOf(parsed) === Object.prototype; // true — untouched
25
+ * ```;
26
+ *
27
+ * @param record The record to assign into.
28
+ * @param key The key, which may come from untrusted input.
29
+ * @param value The value to store.
30
+ */
31
+ export declare function setRecordEntry<T>(record: Record<string, T>, key: string, value: NoInfer<T>): void;
32
+ //# sourceMappingURL=set-record-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-record-entry.d.ts","sourceRoot":"","sources":["../../src/object/set-record-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACzB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GACf,IAAI,CAYN"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Assign into a record whose keys come from untrusted input.
3
+ *
4
+ * `record[key] = value` runs the `__proto__` setter inherited from
5
+ * `Object.prototype`, so one key out of parsed text can replace the prototype
6
+ * of every object built afterwards. Defining the property instead stores an
7
+ * ordinary own `__proto__` entry and reaches no setter, leaving the record an
8
+ * otherwise normal object: same prototype, same spread, same `deepEqual`.
9
+ *
10
+ * Costs one string comparison over a plain assignment for every other key, so
11
+ * it is safe to call from a parser loop — `Object.defineProperty` is far slower
12
+ * and is taken only for the single key that needs it.
13
+ *
14
+ * This guards a **write**. A caller walking a path of untrusted keys must also
15
+ * guard its reads with `isUnsafeRecordKey`: stepping through `constructor` and
16
+ * then `prototype` pollutes without ever assigning to `__proto__`.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const parsed: Record<string, unknown> = {};
21
+ * setRecordEntry(parsed, "__proto__", { polluted: true });
22
+ *
23
+ * parsed["__proto__"]; // { polluted: true } — an own entry
24
+ * Object.getPrototypeOf(parsed) === Object.prototype; // true — untouched
25
+ * ```;
26
+ *
27
+ * @param record The record to assign into.
28
+ * @param key The key, which may come from untrusted input.
29
+ * @param value The value to store.
30
+ */
31
+ export function setRecordEntry(record, key, value) {
32
+ if (key === "__proto__") {
33
+ Object.defineProperty(record, key, {
34
+ value,
35
+ enumerable: true,
36
+ writable: true,
37
+ configurable: true,
38
+ });
39
+ return;
40
+ }
41
+ record[key] = value;
42
+ }
43
+ //# sourceMappingURL=set-record-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-record-entry.js","sourceRoot":"","sources":["../../src/object/set-record-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,cAAc,CAC7B,MAAyB,EACzB,GAAW,EACX,KAAiB;IAEjB,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;QACzB,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;YAClC,KAAK;YACL,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,IAAI;SAClB,CAAC,CAAC;QACH,OAAO;IACR,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AACrB,CAAC"}
@@ -1,5 +1,5 @@
1
+ import { hasObjectPrototype } from "../guards/has-object-prototype.js";
1
2
  import { isMap } from "../guards/is-map.js";
2
- import { isPlainObject } from "../guards/is-plain-object.js";
3
3
  import { isSet } from "../guards/is-set.js";
4
4
  import { defaults } from "./defaults.js";
5
5
  import { getObjectKeys, } from "./get-object-keys.js";
@@ -95,8 +95,8 @@ function traverseValue_(value, visitor, options, context) {
95
95
  return value;
96
96
  }
97
97
  // Check if we should traverse this object's properties
98
- const shouldTraverseObject = (isPlainObject(value) && options.traversePlainObjects) ||
99
- (!isPlainObject(value) &&
98
+ const shouldTraverseObject = (hasObjectPrototype(value) && options.traversePlainObjects) ||
99
+ (!hasObjectPrototype(value) &&
100
100
  shouldTraverseCustomObject(value, options.traverseCustomObjects));
101
101
  if (shouldTraverseObject) {
102
102
  return traverseObjectProperties_(value, visitor, options, parentPath);