@cplieger/deadset-ts 8.0.0-dev.1 → 8.0.0-dev.10

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 (276) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/mapper-connection.js +2 -1
  3. package/dist/bin/node-host.js +24 -5
  4. package/dist/src/analysis.js +181 -341
  5. package/dist/src/augmentations.js +106 -13
  6. package/dist/src/automatic-types.js +10 -29
  7. package/dist/src/build-scripts.js +425 -0
  8. package/dist/src/component-layer.js +4 -2
  9. package/dist/src/components.js +2 -3
  10. package/dist/src/config.js +6 -82
  11. package/dist/src/configuration-files.js +28 -176
  12. package/dist/src/configured-declarations.js +15 -20
  13. package/dist/src/conformance-record.js +1 -1
  14. package/dist/src/consumers.js +3 -30
  15. package/dist/src/contextual-uses.js +56 -9
  16. package/dist/src/contract/config.generated.js +558 -0
  17. package/dist/src/contract/contract.generated.js +1244 -0
  18. package/dist/src/contract/report.generated.js +862 -0
  19. package/dist/src/convention-rows.js +73 -3
  20. package/dist/src/conventions.js +36 -66
  21. package/dist/src/dependencies.js +103 -40
  22. package/dist/src/edges.js +38 -122
  23. package/dist/src/element-access.js +4 -6
  24. package/dist/src/entry-point-gaps.js +2 -8
  25. package/dist/src/entry-points.js +11 -27
  26. package/dist/src/enum-group.js +3 -10
  27. package/dist/src/erased-stores.js +4 -6
  28. package/dist/src/exempt-classes.js +1 -63
  29. package/dist/src/exempt.js +21 -40
  30. package/dist/src/failure.js +36 -0
  31. package/dist/src/file-facts.js +2 -25
  32. package/dist/src/findings/completion.js +139 -72
  33. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  34. package/dist/src/findings/emitters.js +5 -5
  35. package/dist/src/findings/interfaces.js +4 -5
  36. package/dist/src/findings/intra-function.js +13 -10
  37. package/dist/src/findings/non-code-artifacts.js +7 -8
  38. package/dist/src/findings/reads-and-writes.js +16 -13
  39. package/dist/src/findings/self-check.js +10 -12
  40. package/dist/src/findings/unused-declarations.js +41 -32
  41. package/dist/src/findings/visibility-narrowing.js +19 -16
  42. package/dist/src/findings-pass.js +8 -15
  43. package/dist/src/framework-lifecycle.js +7 -7
  44. package/dist/src/fs/document.js +52 -0
  45. package/dist/src/fs/manifest.js +72 -0
  46. package/dist/src/fs/tree.js +88 -0
  47. package/dist/src/generated-file.js +7 -4
  48. package/dist/src/git-ignore.js +39 -26
  49. package/dist/src/graph.js +5 -3
  50. package/dist/src/html-entries.js +6 -33
  51. package/dist/src/in-operands.js +2 -1
  52. package/dist/src/index.js +1 -1
  53. package/dist/src/injection-container.js +1 -1
  54. package/dist/src/intra-function-parts.js +63 -43
  55. package/dist/src/inventory.js +2 -21
  56. package/dist/src/javascript-file.js +33 -0
  57. package/dist/src/json-document.js +198 -67
  58. package/dist/src/keyof-comparisons.js +4 -6
  59. package/dist/src/kinds.js +3 -366
  60. package/dist/src/load/classify.js +270 -0
  61. package/dist/src/load/diagnostics.js +80 -0
  62. package/dist/src/load/discover.js +277 -0
  63. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  64. package/dist/src/load/expected-module.js +136 -0
  65. package/dist/src/load/load.js +27 -0
  66. package/dist/src/load/module-lookup.js +37 -0
  67. package/dist/src/load/plan.js +313 -0
  68. package/dist/src/load/specifiers.js +115 -0
  69. package/dist/src/load/synthesize.js +140 -0
  70. package/dist/src/load/test-globals.js +207 -0
  71. package/dist/src/load/test-joins.js +82 -0
  72. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  73. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  74. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +23 -65
  75. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  76. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  77. package/dist/src/manifest.js +49 -54
  78. package/dist/src/matrix.js +76 -4
  79. package/dist/src/mdx-entries.js +3 -26
  80. package/dist/src/outside-tests.js +1 -1
  81. package/dist/src/partial.js +2 -1
  82. package/dist/src/paths.js +26 -15
  83. package/dist/src/position.js +2 -1
  84. package/dist/src/print.js +11 -79
  85. package/dist/src/product.js +13 -0
  86. package/dist/src/query.js +1 -0
  87. package/dist/src/ref.js +1 -0
  88. package/dist/src/references.js +48 -30
  89. package/dist/src/report-schema.js +51 -0
  90. package/dist/src/report.js +57 -41
  91. package/dist/src/reporters/annotations.js +15 -8
  92. package/dist/src/reporters/sarif.js +16 -10
  93. package/dist/src/reporters/template.js +4 -19
  94. package/dist/src/resolve.js +245 -729
  95. package/dist/src/roots.js +273 -87
  96. package/dist/src/run.js +66 -77
  97. package/dist/src/schema.js +320 -343
  98. package/dist/src/scope.js +38 -115
  99. package/dist/src/serialization-contract.js +595 -21
  100. package/dist/src/session.js +34 -29
  101. package/dist/src/source-files.js +1 -1
  102. package/dist/src/suppress-file.js +25 -28
  103. package/dist/src/suppress-inline.js +3 -2
  104. package/dist/src/suppress.js +33 -51
  105. package/dist/src/sweep.js +7 -9
  106. package/dist/src/symbol-keys.js +3 -5
  107. package/dist/src/template-field.js +9 -19
  108. package/dist/src/test-support.js +8 -11
  109. package/dist/src/text/compare.js +26 -0
  110. package/dist/src/text/glob.js +194 -0
  111. package/dist/src/text/named-files.js +54 -0
  112. package/dist/src/text/shell.js +159 -0
  113. package/dist/src/text/yaml.js +393 -0
  114. package/dist/src/type-errors.js +11 -232
  115. package/dist/src/unseen-loads.js +100 -0
  116. package/dist/src/unwrap.js +23 -0
  117. package/dist/src/usage.js +10 -0
  118. package/dist/src/verbs/analyze.js +166 -126
  119. package/dist/src/verbs/describe.js +9 -16
  120. package/dist/src/verbs/explain.js +10 -7
  121. package/dist/src/verbs/print-config.js +2 -1
  122. package/dist/src/verbs/print-projects.js +6 -4
  123. package/dist/src/verbs/print-retained.js +4 -2
  124. package/dist/src/verbs/print-roots.js +4 -2
  125. package/dist/src/verbs/verb.js +1 -5
  126. package/dist/src/verbs/version.js +14 -3
  127. package/dist/src/workflow-steps.js +62 -64
  128. package/jsr.json +1 -1
  129. package/package.json +4 -3
  130. package/src/analysis.ts +245 -502
  131. package/src/augmentations.ts +135 -17
  132. package/src/automatic-types.ts +11 -29
  133. package/src/build-scripts.ts +543 -0
  134. package/src/component-layer.ts +4 -2
  135. package/src/components.ts +2 -4
  136. package/src/config.ts +31 -302
  137. package/src/configuration-files.ts +34 -179
  138. package/src/configured-declarations.ts +18 -23
  139. package/src/conformance-record.ts +1 -1
  140. package/src/consumers.ts +6 -57
  141. package/src/contextual-uses.ts +64 -12
  142. package/src/contract/config.generated.ts +818 -0
  143. package/src/contract/contract.generated.ts +1308 -0
  144. package/src/contract/report.generated.ts +1237 -0
  145. package/src/convention-rows.ts +85 -3
  146. package/src/conventions.ts +46 -84
  147. package/src/dependencies.ts +118 -46
  148. package/src/edges.ts +41 -140
  149. package/src/element-access.ts +4 -7
  150. package/src/entry-point-gaps.ts +3 -9
  151. package/src/entry-points.ts +12 -38
  152. package/src/enum-group.ts +2 -11
  153. package/src/erased-stores.ts +3 -7
  154. package/src/exempt-classes.ts +1 -75
  155. package/src/exempt.ts +36 -50
  156. package/src/failure.ts +63 -0
  157. package/src/file-facts.ts +9 -24
  158. package/src/finding.ts +14 -9
  159. package/src/findings/boundary.ts +2 -0
  160. package/src/findings/completion.ts +181 -84
  161. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  162. package/src/findings/emitter.ts +8 -9
  163. package/src/findings/emitters.ts +7 -7
  164. package/src/findings/interfaces.ts +4 -6
  165. package/src/findings/intra-function.ts +13 -11
  166. package/src/findings/non-code-artifacts.ts +9 -11
  167. package/src/findings/reads-and-writes.ts +20 -16
  168. package/src/findings/self-check.ts +11 -17
  169. package/src/findings/unused-declarations.ts +45 -32
  170. package/src/findings/visibility-narrowing.ts +20 -17
  171. package/src/findings-pass.ts +10 -19
  172. package/src/framework-lifecycle.ts +7 -7
  173. package/src/fs/document.ts +70 -0
  174. package/src/fs/manifest.ts +92 -0
  175. package/src/fs/tree.ts +110 -0
  176. package/src/generated-file.ts +7 -4
  177. package/src/git-ignore.ts +50 -26
  178. package/src/graph.ts +5 -3
  179. package/src/host.ts +12 -5
  180. package/src/html-entries.ts +6 -33
  181. package/src/in-operands.ts +2 -1
  182. package/src/index.ts +1 -1
  183. package/src/injection-container.ts +1 -1
  184. package/src/intra-function-parts.ts +73 -44
  185. package/src/inventory.ts +2 -20
  186. package/src/javascript-file.ts +37 -0
  187. package/src/json-document.ts +241 -76
  188. package/src/keyof-comparisons.ts +3 -7
  189. package/src/kinds.ts +5 -413
  190. package/src/load/classify.ts +397 -0
  191. package/src/load/diagnostics.ts +144 -0
  192. package/src/load/discover.ts +455 -0
  193. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  194. package/src/load/expected-module.ts +188 -0
  195. package/src/load/load.ts +73 -0
  196. package/src/load/module-lookup.ts +50 -0
  197. package/src/load/plan.ts +504 -0
  198. package/src/load/specifiers.ts +168 -0
  199. package/src/load/synthesize.ts +211 -0
  200. package/src/load/test-globals.ts +251 -0
  201. package/src/load/test-joins.ts +98 -0
  202. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  203. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  204. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +33 -76
  205. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  206. package/src/{workspace.ts → load/workspace.ts} +90 -134
  207. package/src/manifest.ts +81 -75
  208. package/src/matrix.ts +122 -4
  209. package/src/mdx-entries.ts +3 -26
  210. package/src/outside-tests.ts +1 -1
  211. package/src/partial.ts +3 -2
  212. package/src/paths.ts +27 -15
  213. package/src/position.ts +2 -1
  214. package/src/print.ts +12 -92
  215. package/src/product.ts +18 -0
  216. package/src/query.ts +11 -0
  217. package/src/ref.ts +1 -0
  218. package/src/references.ts +52 -31
  219. package/src/report-schema.ts +68 -0
  220. package/src/report.ts +101 -224
  221. package/src/reporters/annotations.ts +22 -11
  222. package/src/reporters/json.ts +1 -1
  223. package/src/reporters/reporter.ts +2 -4
  224. package/src/reporters/reporters.ts +1 -1
  225. package/src/reporters/sarif.ts +29 -16
  226. package/src/reporters/template.ts +4 -20
  227. package/src/reporters/text.ts +3 -3
  228. package/src/resolve.ts +283 -1114
  229. package/src/roots.ts +339 -104
  230. package/src/run.ts +75 -91
  231. package/src/schema.ts +391 -388
  232. package/src/scope.ts +46 -138
  233. package/src/serialization-contract.ts +763 -22
  234. package/src/session.ts +70 -54
  235. package/src/source-files.ts +1 -1
  236. package/src/suppress-file.ts +24 -33
  237. package/src/suppress-inline.ts +2 -2
  238. package/src/suppress.ts +43 -58
  239. package/src/sweep.ts +23 -9
  240. package/src/symbol-keys.ts +2 -5
  241. package/src/template-field.ts +15 -25
  242. package/src/test-support.ts +17 -13
  243. package/src/text/compare.ts +27 -0
  244. package/src/text/glob.ts +210 -0
  245. package/src/text/named-files.inputs.json +1522 -0
  246. package/src/text/named-files.ts +68 -0
  247. package/src/text/shell.ts +161 -0
  248. package/src/text/yaml.ts +423 -0
  249. package/src/type-errors.ts +18 -288
  250. package/src/unseen-loads.ts +134 -0
  251. package/src/unwrap.ts +34 -0
  252. package/src/usage.ts +10 -0
  253. package/src/verbs/analyze.ts +224 -162
  254. package/src/verbs/describe.ts +14 -15
  255. package/src/verbs/explain.ts +10 -11
  256. package/src/verbs/print-config.ts +2 -1
  257. package/src/verbs/print-projects.ts +6 -4
  258. package/src/verbs/print-retained.ts +4 -2
  259. package/src/verbs/print-roots.ts +4 -2
  260. package/src/verbs/verb.ts +2 -8
  261. package/src/verbs/version.ts +15 -3
  262. package/src/workflow-steps.ts +74 -64
  263. package/dist/src/base-url.js +0 -18
  264. package/dist/src/discover.js +0 -468
  265. package/dist/src/glob.js +0 -65
  266. package/dist/src/pnpm-workspace.js +0 -120
  267. package/dist/src/setup-failure.js +0 -23
  268. package/dist/src/test-joins.js +0 -101
  269. package/dist/src/version.js +0 -7
  270. package/src/base-url.ts +0 -24
  271. package/src/discover.ts +0 -653
  272. package/src/glob.ts +0 -67
  273. package/src/pnpm-workspace.ts +0 -135
  274. package/src/setup-failure.ts +0 -39
  275. package/src/test-joins.ts +0 -120
  276. package/src/version.ts +0 -7
@@ -1,4 +1,3 @@
1
- import { fails } from "../config.js";
2
1
  import { coalesced } from "../json-chunks.js";
3
2
  import { KINDS } from "../kinds.js";
4
3
  /** The escapes a workflow command's message needs, so a line break does not end the command. */
@@ -19,6 +18,12 @@ function escapeProperty(value) {
19
18
  function kindName(code) {
20
19
  return KINDS.get(code)?.name ?? code;
21
20
  }
21
+ /** The command each finding severity is annotated with, whatever the failing severity. */
22
+ const LEVELS = {
23
+ deny: "error",
24
+ warn: "warning",
25
+ allow: "notice",
26
+ };
22
27
  function command(level, at, endLine, title, message) {
23
28
  return `::${level} file=${escapeProperty(at.path)},line=${String(at.line)},col=${String(at.column)},endLine=${String(endLine)},title=${escapeProperty(title)}::${escapeData(message)}`;
24
29
  }
@@ -26,16 +31,15 @@ function command(level, at, endLine, title, message) {
26
31
  const SKIP_TITLE = "type error skipped";
27
32
  const SKIP_MESSAGE = "the analysis did not evaluate the function or statement holding this type error: ";
28
33
  /**
29
- * One workflow annotation per finding, then one per stale suppression, each naming its
30
- * file, line, column and last line, titled by its code and kind, then one warning per
31
- * type-error skip naming its file and line. A finding at or above the failing severity is
32
- * an error and one below it a warning; a stale suppression is an error, because its kind
33
- * is fixed on at the failing severity.
34
+ * The annotations `contract/grammar/annotations.md` states: one per finding, at the
35
+ * command its severity names, and one error per stale suppression, each naming its file,
36
+ * line, column and last line and titled by its code and kind; then one warning per
37
+ * type-error skip naming its file and line, and one per note naming its directory.
34
38
  */
35
- export function annotations(report, options) {
39
+ export function annotations(report) {
36
40
  return coalesced((function* lines() {
37
41
  for (const found of report.findings) {
38
- yield `${command(fails(found.severity, options.failOn) ? "error" : "warning", found.position, found.position.end_line, `${found.code} ${found.kind}`, found.message)}\n`;
42
+ yield `${command(LEVELS[found.severity], found.position, found.position.end_line, `${found.code} ${found.kind}`, found.message)}\n`;
39
43
  }
40
44
  for (const stale of report.stale_suppressions) {
41
45
  yield `${command("error", stale.position, stale.position.line, `${stale.code} ${kindName(stale.code)}`, stale.message)}\n`;
@@ -43,5 +47,8 @@ export function annotations(report, options) {
43
47
  for (const skip of report.type_error_skips) {
44
48
  yield `::warning file=${escapeProperty(skip.path)},line=${String(skip.line)},title=${escapeProperty(SKIP_TITLE)}::${escapeData(SKIP_MESSAGE + skip.message)}\n`;
45
49
  }
50
+ for (const note of report.notes) {
51
+ yield `::warning file=${escapeProperty(note.path)},title=${escapeProperty(note.kind)}::${escapeData(note.message)}\n`;
52
+ }
46
53
  })());
47
54
  }
@@ -5,6 +5,8 @@ import { lineHashes, symbolFingerprint } from "./fingerprint.js";
5
5
  import { RenderError } from "./reporter.js";
6
6
  import { utf8Bytes } from "./sha256.js";
7
7
  import { withheldLine } from "./text.js";
8
+ import { bytewise } from "../text/compare.js";
9
+ import { message } from "../product.js";
8
10
  const SCHEMA = "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json";
9
11
  const VERSION = "2.1.0";
10
12
  /** The unit a finding's column counts. */
@@ -101,7 +103,7 @@ function lineHashCache(read) {
101
103
  text = read(at.path);
102
104
  }
103
105
  catch (error) {
104
- throw new RenderError(`read ${at.path} for its line fingerprint: ${error instanceof Error ? error.message : String(error)}`);
106
+ throw new RenderError(`read ${at.path} for its line fingerprint: ${message(error)}`);
105
107
  }
106
108
  hashes = lineHashes(text);
107
109
  held.set(at.path, hashes);
@@ -114,7 +116,7 @@ function lineHashCache(read) {
114
116
  };
115
117
  }
116
118
  /** Every position a finding names beyond its own, in the mapping's order, the first hundred. */
117
- function relatedOf(found) {
119
+ function relatedOf(found, members) {
118
120
  const related = [];
119
121
  for (const one of found.details.implementations ?? []) {
120
122
  related.push({ label: "implementation", at: one.position, endLine: one.position.end_line });
@@ -126,7 +128,7 @@ function relatedOf(found) {
126
128
  const at = found.details.name_literal;
127
129
  related.push({ label: "name", at, endLine: at.end_line });
128
130
  }
129
- for (const one of found.component.members ?? []) {
131
+ for (const one of members(found.component.id)) {
130
132
  if (declarationKey(one.ref, one.position.path) !==
131
133
  declarationKey(found.symbol.ref, found.position.path)) {
132
134
  related.push({ label: "member", at: one.position, endLine: one.position.end_line });
@@ -143,7 +145,9 @@ function messageWithLinks(message, related) {
143
145
  return `${message} (see ${links.join(", ")})`;
144
146
  }
145
147
  /** Every member of the finding the mapping places nowhere else, under its schema name. */
146
- function propertiesOf(found) {
148
+ /** A result's member bag, its component holding the members the report lists for it once. */
149
+ function propertiesOf(found, members) {
150
+ const listed = members(found.component.id);
147
151
  return {
148
152
  language: found.language,
149
153
  symbol: found.symbol,
@@ -154,7 +158,7 @@ function propertiesOf(found) {
154
158
  : { liveness_relation: found.liveness_relation }),
155
159
  test_only: found.test_only,
156
160
  generated: found.generated,
157
- component: found.component,
161
+ component: listed.length === 0 ? found.component : { ...found.component, members: listed },
158
162
  retained_by: found.retained_by,
159
163
  configurations: found.configurations,
160
164
  consumers_loaded: found.consumers_loaded,
@@ -169,8 +173,8 @@ function ruleIndex(index, code) {
169
173
  }
170
174
  return at;
171
175
  }
172
- function findingResult(found, index, hashOf) {
173
- const related = relatedOf(found);
176
+ function findingResult(found, index, hashOf, members) {
177
+ const related = relatedOf(found, members);
174
178
  return {
175
179
  ruleId: found.code,
176
180
  ruleIndex: ruleIndex(index, found.code),
@@ -190,7 +194,7 @@ function findingResult(found, index, hashOf) {
190
194
  primaryLocationLineHash: hashOf(found.position),
191
195
  "deadsetSymbolRef/v1": symbolFingerprint(found.code, found.symbol.ref),
192
196
  },
193
- properties: propertiesOf(found),
197
+ properties: propertiesOf(found, members),
194
198
  };
195
199
  }
196
200
  /** A stale suppression at the failing level, at its own site; it is no finding, so it carries no member bag. */
@@ -218,11 +222,13 @@ export function sarif(report, options) {
218
222
  const ruleList = rules(kinds);
219
223
  const index = new Map(kinds.map((kind, at) => [kind.code, at]));
220
224
  const hashOf = lineHashCache(options.readSource);
225
+ const listed = new Map((report.components ?? []).map((one) => [one.id, one.members]));
226
+ const members = (id) => listed.get(id) ?? [];
221
227
  const results = [
222
- ...report.findings.map((found) => findingResult(found, index, hashOf)),
228
+ ...report.findings.map((found) => findingResult(found, index, hashOf, members)),
223
229
  ...report.stale_suppressions.map((stale) => staleResult(stale, index, hashOf)),
224
230
  ];
225
- const languages = [...report.analyzer.languages].sort().join("+");
231
+ const languages = [...report.analyzer.languages].sort(bytewise).join("+");
226
232
  const withheld = withheldLine(report.totals);
227
233
  const log = {
228
234
  $schema: SCHEMA,
@@ -9,6 +9,7 @@
9
9
  import { CHUNK_LENGTH } from "../json-chunks.js";
10
10
  import { RenderError } from "./reporter.js";
11
11
  import { utf8Bytes } from "./sha256.js";
12
+ import { bytewise } from "../text/compare.js";
12
13
  /** A template that does not parse, which refuses the invocation before any analysis. */
13
14
  export class TemplateError extends Error {
14
15
  constructor(message) {
@@ -513,7 +514,7 @@ function formatted(value, nested) {
513
514
  }
514
515
  const object = value;
515
516
  const entries = Object.keys(object)
516
- .sort()
517
+ .sort(bytewise)
517
518
  .map((key) => `${key}:${formatted(object[key] ?? null, true)}`);
518
519
  return `map[${entries.join(" ")}]`;
519
520
  }
@@ -538,26 +539,10 @@ function compareBasic(name, a, b) {
538
539
  return Number.NaN;
539
540
  }
540
541
  if (kind === "string") {
541
- return byCodePoints(a, b);
542
+ return bytewise(a, b);
542
543
  }
543
544
  return a < b ? -1 : 1;
544
545
  }
545
- /**
546
- * Two strings ordered by the bytes of their UTF-8 encodings, which is the order of their
547
- * code points: the order of their UTF-16 code units differs above U+FFFF.
548
- */
549
- function byCodePoints(a, b) {
550
- let at = 0;
551
- while (at < a.length && at < b.length) {
552
- const x = a.codePointAt(at) ?? 0;
553
- const y = b.codePointAt(at) ?? 0;
554
- if (x !== y) {
555
- return x < y ? -1 : 1;
556
- }
557
- at += x > 0xffff ? 2 : 1;
558
- }
559
- return a.length - b.length;
560
- }
561
546
  /** The escapes `%q` writes for the control characters that have one of their own. */
562
547
  const QUOTED_ESCAPES = {
563
548
  '"': '\\"',
@@ -903,7 +888,7 @@ class Execution {
903
888
  }
904
889
  else if (isObject(value)) {
905
890
  entries = Object.keys(value)
906
- .sort()
891
+ .sort(bytewise)
907
892
  .map((key) => [key, value[key] ?? null]);
908
893
  }
909
894
  else {