@cplieger/deadset-ts 4.0.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/bin/component-mapper.js +5 -0
- package/dist/bin/mapper-connection.js +101 -0
- package/dist/bin/node-host.js +24 -2
- package/dist/src/analysis.js +229 -36
- package/dist/src/component-files.js +612 -0
- package/dist/src/component-layer.js +132 -0
- package/dist/src/config.js +9 -2
- package/dist/src/configuration-files.js +186 -0
- package/dist/src/conformance-record.js +2 -2
- package/dist/src/convention-rows.js +383 -0
- package/dist/src/conventions.js +456 -0
- package/dist/src/dependencies.js +30 -3
- package/dist/src/discover.js +10 -3
- package/dist/src/emit-map.js +72 -0
- package/dist/src/entry-point-gaps.js +81 -35
- package/dist/src/entry-points.js +47 -32
- package/dist/src/exempt.js +11 -3
- package/dist/src/findings/completion.js +19 -29
- package/dist/src/findings/emitters.js +22 -1
- package/dist/src/findings/unused-declarations.js +7 -2
- package/dist/src/graph.js +13 -5
- package/dist/src/inventory.js +4 -2
- package/dist/src/kinds.js +2 -2
- package/dist/src/manifest.js +37 -11
- package/dist/src/matrix.js +21 -13
- package/dist/src/partial.js +3 -1
- package/dist/src/pnpm-workspace.js +120 -0
- package/dist/src/position.js +17 -2
- package/dist/src/print.js +2 -0
- package/dist/src/references.js +209 -30
- package/dist/src/report.js +26 -6
- package/dist/src/reporters/annotations.js +10 -3
- package/dist/src/reporters/template.js +3 -0
- package/dist/src/resolve.js +31 -6
- package/dist/src/roots.js +37 -8
- package/dist/src/run.js +13 -3
- package/dist/src/schema.js +2 -0
- package/dist/src/session.js +141 -34
- package/dist/src/setup-failure.js +23 -0
- package/dist/src/source-files.js +4 -61
- package/dist/src/sweep.js +4 -2
- package/dist/src/template-field.js +38 -6
- package/dist/src/test-support.js +59 -0
- package/dist/src/type-errors.js +252 -0
- package/dist/src/type-query-alias.js +92 -0
- package/dist/src/verbs/analyze.js +24 -4
- package/dist/src/verbs/explain.js +4 -1
- package/dist/src/verbs/print-projects.js +17 -56
- package/dist/src/verbs/print-retained.js +7 -2
- package/dist/src/verbs/print-roots.js +7 -2
- package/dist/src/version-range.js +255 -0
- package/dist/src/version.js +1 -1
- package/dist/src/workspace-manifests.js +68 -0
- package/dist/src/workspace-programs.js +342 -0
- package/dist/src/workspace-resolution.js +307 -0
- package/dist/src/workspace-run.js +75 -0
- package/dist/src/workspace.js +358 -0
- package/jsr.json +1 -1
- package/package.json +2 -1
- package/src/analysis.ts +394 -70
- package/src/component-files.ts +718 -0
- package/src/component-layer.ts +160 -0
- package/src/config.ts +11 -2
- package/src/configuration-files.ts +235 -0
- package/src/conformance-record.ts +2 -2
- package/src/convention-rows.ts +440 -0
- package/src/conventions.ts +640 -0
- package/src/dependencies.ts +36 -2
- package/src/discover.ts +10 -6
- package/src/emit-map.ts +93 -0
- package/src/entry-point-gaps.ts +92 -38
- package/src/entry-points.ts +66 -36
- package/src/exempt.ts +21 -3
- package/src/findings/completion.ts +24 -33
- package/src/findings/emitters.ts +32 -1
- package/src/findings/unused-declarations.ts +9 -2
- package/src/graph.ts +15 -4
- package/src/host.ts +23 -0
- package/src/index.ts +1 -1
- package/src/inventory.ts +13 -2
- package/src/kinds.ts +2 -2
- package/src/manifest.ts +47 -14
- package/src/matrix.ts +43 -15
- package/src/partial.ts +6 -1
- package/src/pnpm-workspace.ts +135 -0
- package/src/position.ts +23 -2
- package/src/print.ts +2 -0
- package/src/references.ts +227 -28
- package/src/report.ts +56 -6
- package/src/reporters/annotations.ts +12 -3
- package/src/reporters/template.ts +3 -0
- package/src/resolve.ts +59 -6
- package/src/roots.ts +60 -9
- package/src/run.ts +15 -5
- package/src/schema.ts +2 -0
- package/src/session.ts +218 -37
- package/src/setup-failure.ts +39 -0
- package/src/source-files.ts +4 -66
- package/src/sweep.ts +9 -2
- package/src/template-field.ts +42 -7
- package/src/test-support.ts +77 -0
- package/src/type-errors.ts +340 -0
- package/src/type-query-alias.ts +133 -0
- package/src/verbs/analyze.ts +38 -4
- package/src/verbs/explain.ts +4 -1
- package/src/verbs/print-projects.ts +17 -69
- package/src/verbs/print-retained.ts +7 -2
- package/src/verbs/print-roots.ts +7 -2
- package/src/verbs/verb.ts +6 -3
- package/src/version-range.ts +309 -0
- package/src/version.ts +1 -1
- package/src/workspace-manifests.ts +100 -0
- package/src/workspace-programs.ts +486 -0
- package/src/workspace-resolution.ts +393 -0
- package/src/workspace-run.ts +148 -0
- package/src/workspace.ts +463 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a snapshot reads component files: a file-system layer that never reaches the disk gives
|
|
3
|
+
* every configuration the snapshot opens a `contentMappers` member naming this analyzer's own
|
|
4
|
+
* mapper, or none, in place of any the configuration declares, because a configuration's own
|
|
5
|
+
* member wins over one it extends. The mapper resolves as a package linked into the
|
|
6
|
+
* `node_modules` beside each configuration, to a directory holding only its manifest.
|
|
7
|
+
*/
|
|
8
|
+
import { dirnamePath, joinPath } from "./paths.js";
|
|
9
|
+
/** The name the mapper's manifest declares and every configuration's entry names. */
|
|
10
|
+
export const MAPPER_PACKAGE = "deadset-ts-component-files";
|
|
11
|
+
/** The manifest of the mapper's package, which runs `command`. */
|
|
12
|
+
export function mapperManifest(command) {
|
|
13
|
+
return `${JSON.stringify({
|
|
14
|
+
name: MAPPER_PACKAGE,
|
|
15
|
+
version: "0.0.0",
|
|
16
|
+
private: true,
|
|
17
|
+
typescript: { contentMapper: { exec: command } },
|
|
18
|
+
}, null, 2)}\n`;
|
|
19
|
+
}
|
|
20
|
+
/** The offset past the white space and comments from `at`. */
|
|
21
|
+
function pastTrivia(text, from) {
|
|
22
|
+
let at = from;
|
|
23
|
+
for (;;) {
|
|
24
|
+
if (/\s/u.test(text[at] ?? "x")) {
|
|
25
|
+
at += 1;
|
|
26
|
+
}
|
|
27
|
+
else if (text.startsWith("//", at)) {
|
|
28
|
+
const end = text.slice(at).search(/[\n\r]/u);
|
|
29
|
+
at = end < 0 ? text.length : at + end;
|
|
30
|
+
}
|
|
31
|
+
else if (text.startsWith("/*", at)) {
|
|
32
|
+
const end = text.indexOf("*/", at + 2);
|
|
33
|
+
at = end < 0 ? text.length : end + 2;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return at;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** The offset past the string opening at `from`. */
|
|
41
|
+
function pastString(text, from) {
|
|
42
|
+
let at = from + 1;
|
|
43
|
+
while (at < text.length && text[at] !== '"') {
|
|
44
|
+
at += text[at] === "\\" ? 2 : 1;
|
|
45
|
+
}
|
|
46
|
+
return at + 1;
|
|
47
|
+
}
|
|
48
|
+
/** The offset past the value starting at `from`: a string, a bracketed value, or a bare word. */
|
|
49
|
+
function pastValue(text, from) {
|
|
50
|
+
const first = text[from];
|
|
51
|
+
if (first === '"') {
|
|
52
|
+
return pastString(text, from);
|
|
53
|
+
}
|
|
54
|
+
if (first !== "{" && first !== "[") {
|
|
55
|
+
let at = from;
|
|
56
|
+
while (at < text.length && /[^\s,}\]/]/u.test(text[at] ?? "")) {
|
|
57
|
+
at += 1;
|
|
58
|
+
}
|
|
59
|
+
return at;
|
|
60
|
+
}
|
|
61
|
+
let depth = 0;
|
|
62
|
+
let at = from;
|
|
63
|
+
while (at < text.length) {
|
|
64
|
+
at = pastTrivia(text, at);
|
|
65
|
+
const char = text[at];
|
|
66
|
+
if (char === '"') {
|
|
67
|
+
at = pastString(text, at);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (char === "{" || char === "[") {
|
|
71
|
+
depth += 1;
|
|
72
|
+
}
|
|
73
|
+
else if (char === "}" || char === "]") {
|
|
74
|
+
depth -= 1;
|
|
75
|
+
if (depth === 0) {
|
|
76
|
+
return at + 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
at += 1;
|
|
80
|
+
}
|
|
81
|
+
return at;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* One configuration's text with its top-level `contentMappers` member set to `mappers`,
|
|
85
|
+
* the member's own value replaced where it has one and the member written first
|
|
86
|
+
* otherwise. Every line keeps its number. Text that holds no object is returned as is,
|
|
87
|
+
* for the compiler to refuse.
|
|
88
|
+
*/
|
|
89
|
+
export function withContentMappers(text, mappers) {
|
|
90
|
+
const value = JSON.stringify(mappers);
|
|
91
|
+
const open = pastTrivia(text, 0);
|
|
92
|
+
if (text[open] !== "{") {
|
|
93
|
+
return text;
|
|
94
|
+
}
|
|
95
|
+
let at = pastTrivia(text, open + 1);
|
|
96
|
+
const empty = text[at] === "}";
|
|
97
|
+
while (at < text.length && text[at] === '"') {
|
|
98
|
+
const keyEnd = pastString(text, at);
|
|
99
|
+
const key = text.slice(at, keyEnd);
|
|
100
|
+
const valueStart = pastTrivia(text, pastTrivia(text, keyEnd) + 1);
|
|
101
|
+
const valueEnd = pastValue(text, valueStart);
|
|
102
|
+
if (key === '"contentMappers"') {
|
|
103
|
+
return text.slice(0, valueStart) + value + text.slice(valueEnd);
|
|
104
|
+
}
|
|
105
|
+
at = pastTrivia(text, valueEnd);
|
|
106
|
+
if (text[at] !== ",") {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
at = pastTrivia(text, at + 1);
|
|
110
|
+
}
|
|
111
|
+
return `${text.slice(0, open + 1)}"contentMappers":${value}${empty ? "" : ","}${text.slice(open + 1)}`;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The layer one snapshot is created with: every configuration named carrying `mapper`, its
|
|
115
|
+
* package linked beside it, or no mapper at all where `mapper` is absent. A configuration
|
|
116
|
+
* `written` holds is that text, which exists nowhere else; any other is read through the host.
|
|
117
|
+
*/
|
|
118
|
+
export function componentLayer(host, configFiles, mapper, written = new Map()) {
|
|
119
|
+
const mappers = mapper === undefined ? [] : [{ package: MAPPER_PACKAGE, extensions: [...mapper.extensions] }];
|
|
120
|
+
const files = {};
|
|
121
|
+
const symlinks = {};
|
|
122
|
+
for (const configFile of configFiles) {
|
|
123
|
+
files[configFile] = withContentMappers(written.get(configFile) ?? host.readFile(configFile), mappers);
|
|
124
|
+
if (mapper !== undefined) {
|
|
125
|
+
symlinks[joinPath(dirnamePath(configFile), "node_modules", MAPPER_PACKAGE)] = {
|
|
126
|
+
target: mapper.packageDirectory,
|
|
127
|
+
host: true,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { kind: "layer", files, symlinks };
|
|
132
|
+
}
|
package/dist/src/config.js
CHANGED
|
@@ -21,7 +21,7 @@ export function defaultConfig() {
|
|
|
21
21
|
targetKind: "",
|
|
22
22
|
analysis: {
|
|
23
23
|
languages: [],
|
|
24
|
-
minConfidence: "
|
|
24
|
+
minConfidence: "probable",
|
|
25
25
|
generatedFiles: "exclude",
|
|
26
26
|
consumerTests: "test",
|
|
27
27
|
configurations: [],
|
|
@@ -47,8 +47,15 @@ export function defaultConfig() {
|
|
|
47
47
|
],
|
|
48
48
|
},
|
|
49
49
|
ts: {
|
|
50
|
-
testFiles: [
|
|
50
|
+
testFiles: [
|
|
51
|
+
"**/*.test.{ts,tsx,mts,cts}",
|
|
52
|
+
"**/*.spec.*",
|
|
53
|
+
"**/__tests__/**",
|
|
54
|
+
"**/__mocks__/**",
|
|
55
|
+
],
|
|
51
56
|
entryFiles: [],
|
|
57
|
+
componentExtensions: [".vue", ".svelte", ".astro"],
|
|
58
|
+
disabledConventions: [],
|
|
52
59
|
injectionRegistrations: [],
|
|
53
60
|
lifecycleContracts: [],
|
|
54
61
|
serializers: [],
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The configuration files a tool loads by name, and the strings they hold. A file in a
|
|
3
|
+
* directory that holds a `package.json` is a configuration module when its name is
|
|
4
|
+
* `<stem>.config.<ext>`, `<stem>.<qualifier>.config.<ext>` or `.<stem>rc.<ext>`, and a
|
|
5
|
+
* JSON configuration file when its name is the JSON form of one of them. A tool reads
|
|
6
|
+
* every string either holds as it likes, so each one that spells a declared dependency
|
|
7
|
+
* uses it and each relative one that names a source file of the program roots the file.
|
|
8
|
+
*/
|
|
9
|
+
import { isNoSubstitutionTemplateLiteral, isStringLiteral, } from "@typescript/native/unstable/ast";
|
|
10
|
+
import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.js";
|
|
11
|
+
const MANIFEST = "package.json";
|
|
12
|
+
/** A configuration module's name, each form with the spelling a root reports it by. */
|
|
13
|
+
const MODULE_FORMS = [
|
|
14
|
+
{ name: /^[\w-]+\.config\.(?:js|mjs|cjs|ts|mts|cts)$/u, form: "<stem>.config.<ext>" },
|
|
15
|
+
{
|
|
16
|
+
name: /^[\w-]+\.[\w-]+\.config\.(?:js|mjs|cjs|ts|mts|cts)$/u,
|
|
17
|
+
form: "<stem>.<qualifier>.config.<ext>",
|
|
18
|
+
},
|
|
19
|
+
{ name: /^\.[\w-]+rc\.(?:js|mjs|cjs)$/u, form: ".<stem>rc.<ext>" },
|
|
20
|
+
];
|
|
21
|
+
/** A JSON configuration file's name. */
|
|
22
|
+
const DOCUMENT_NAME = /^(?:[\w-]+(?:\.[\w-]+)?\.config\.json|\.[\w-]+rc(?:\.json)?)$/u;
|
|
23
|
+
/** The manifest members a dependency is declared in. */
|
|
24
|
+
const DEPENDENCY_MEMBERS = [
|
|
25
|
+
"dependencies",
|
|
26
|
+
"devDependencies",
|
|
27
|
+
"peerDependencies",
|
|
28
|
+
"optionalDependencies",
|
|
29
|
+
];
|
|
30
|
+
/** The prefixes a string names a file with, relative to the file that writes it. */
|
|
31
|
+
const RELATIVE_PREFIXES = ["./", "../"];
|
|
32
|
+
/** The extensions the program's module resolution appends to a specifier written without one. */
|
|
33
|
+
const RESOLVED_EXTENSIONS = [
|
|
34
|
+
".ts",
|
|
35
|
+
".tsx",
|
|
36
|
+
".d.ts",
|
|
37
|
+
".mts",
|
|
38
|
+
".cts",
|
|
39
|
+
".js",
|
|
40
|
+
".jsx",
|
|
41
|
+
".mjs",
|
|
42
|
+
".cjs",
|
|
43
|
+
];
|
|
44
|
+
/** The file's name, the last segment of its path. */
|
|
45
|
+
function basename(path) {
|
|
46
|
+
return path.slice(path.lastIndexOf("/") + 1);
|
|
47
|
+
}
|
|
48
|
+
function isRecord(value) {
|
|
49
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
50
|
+
}
|
|
51
|
+
/** The form one file name is as a configuration module, or undefined where it is none. */
|
|
52
|
+
export function configurationModuleForm(name) {
|
|
53
|
+
return MODULE_FORMS.find((one) => one.name.test(name))?.form;
|
|
54
|
+
}
|
|
55
|
+
/** Whether one file name is a JSON configuration file's. */
|
|
56
|
+
export function isConfigurationDocumentName(name) {
|
|
57
|
+
return DOCUMENT_NAME.test(name);
|
|
58
|
+
}
|
|
59
|
+
/** Every string value one decoded JSON value holds at any depth. */
|
|
60
|
+
export function documentStrings(value) {
|
|
61
|
+
if (typeof value === "string") {
|
|
62
|
+
return [value];
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
return value.flatMap(documentStrings);
|
|
66
|
+
}
|
|
67
|
+
return isRecord(value) ? Object.values(value).flatMap(documentStrings) : [];
|
|
68
|
+
}
|
|
69
|
+
/** Every string literal and every template literal with no substitution one file writes. */
|
|
70
|
+
export function moduleStrings(file) {
|
|
71
|
+
const found = [];
|
|
72
|
+
const visit = (node) => {
|
|
73
|
+
if (isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node)) {
|
|
74
|
+
found.push({ node, text: node.text });
|
|
75
|
+
}
|
|
76
|
+
node.forEachChild(visit);
|
|
77
|
+
};
|
|
78
|
+
file.forEachChild(visit);
|
|
79
|
+
return found;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The configuration files of one project's own files below the target root. A module
|
|
83
|
+
* is an own file; a JSON configuration file is read from each directory below the
|
|
84
|
+
* target root, the root included, that holds an own file or is above one. Either sits
|
|
85
|
+
* in a directory that holds a manifest. A document that cannot be read or parsed as
|
|
86
|
+
* JSON holds no string.
|
|
87
|
+
*/
|
|
88
|
+
export function configurationFiles(host, targetRoot, files) {
|
|
89
|
+
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
90
|
+
const manifests = new Map();
|
|
91
|
+
const holdsManifest = (dir) => {
|
|
92
|
+
let held = manifests.get(dir);
|
|
93
|
+
if (held === undefined) {
|
|
94
|
+
held = host.kindOf(joinPath(dir, MANIFEST)) === "file";
|
|
95
|
+
manifests.set(dir, held);
|
|
96
|
+
}
|
|
97
|
+
return held;
|
|
98
|
+
};
|
|
99
|
+
const modules = [];
|
|
100
|
+
const dirs = new Set([root]);
|
|
101
|
+
for (const file of files.byPath.values()) {
|
|
102
|
+
const form = configurationModuleForm(basename(file.fileName));
|
|
103
|
+
if (form !== undefined && holdsManifest(dirnamePath(file.fileName))) {
|
|
104
|
+
modules.push({ file, form });
|
|
105
|
+
}
|
|
106
|
+
for (let dir = dirnamePath(file.fileName); relativePath(root, dir) !== undefined && !dirs.has(dir); dir = dirnamePath(dir)) {
|
|
107
|
+
dirs.add(dir);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const documents = [];
|
|
111
|
+
for (const dir of [...dirs].sort()) {
|
|
112
|
+
if (!holdsManifest(dir)) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
let names;
|
|
116
|
+
try {
|
|
117
|
+
names = host
|
|
118
|
+
.readDirectory(dir)
|
|
119
|
+
.filter((entry) => !entry.directory && isConfigurationDocumentName(entry.name))
|
|
120
|
+
.map((entry) => entry.name)
|
|
121
|
+
.sort();
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
for (const name of names) {
|
|
127
|
+
const path = joinPath(dir, name);
|
|
128
|
+
let value;
|
|
129
|
+
try {
|
|
130
|
+
value = JSON.parse(host.readFile(path));
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
documents.push({ path, strings: documentStrings(value) });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { modules, documents };
|
|
139
|
+
}
|
|
140
|
+
/** Every dependency the manifest in one directory declares, or none where it holds none to read. */
|
|
141
|
+
export function declaredIn(host, dir) {
|
|
142
|
+
let value;
|
|
143
|
+
try {
|
|
144
|
+
value = JSON.parse(host.readFile(joinPath(dir, MANIFEST)));
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
if (!isRecord(value)) {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
const names = new Set();
|
|
153
|
+
for (const member of DEPENDENCY_MEMBERS) {
|
|
154
|
+
const section = value[member];
|
|
155
|
+
if (isRecord(section)) {
|
|
156
|
+
Object.keys(section).forEach((name) => names.add(name));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return [...names];
|
|
160
|
+
}
|
|
161
|
+
/** The dependencies one string uses: each it equals, or is followed by `/` and a subpath in. */
|
|
162
|
+
export function dependenciesNamed(text, declared) {
|
|
163
|
+
return declared.filter((name) => text === name || text.startsWith(`${name}/`));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* The own files one string names read against a directory: none unless it starts with
|
|
167
|
+
* `./` or `../`, else the file it names directly or through the emit mapping, or the
|
|
168
|
+
* file it names with an extension the module resolution appends.
|
|
169
|
+
*/
|
|
170
|
+
export function filesNamedBy(files, dir, text) {
|
|
171
|
+
if (!RELATIVE_PREFIXES.some((prefix) => text.startsWith(prefix)) || text.includes("*")) {
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
const path = resolvePath(dir, text);
|
|
175
|
+
const direct = files.named(path);
|
|
176
|
+
if (direct.length > 0) {
|
|
177
|
+
return direct;
|
|
178
|
+
}
|
|
179
|
+
for (const extension of RESOLVED_EXTENSIONS) {
|
|
180
|
+
const held = files.byName.get(path + extension);
|
|
181
|
+
if (held !== undefined) {
|
|
182
|
+
return [held];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return [];
|
|
186
|
+
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Regenerate it with `UPDATE_GOLDEN=1 npx vitest --run src/conformance.corpus.test.ts`.
|
|
3
3
|
export const RECORD = {
|
|
4
4
|
conformance: {
|
|
5
|
-
corpusVersion: "2.
|
|
5
|
+
corpusVersion: "2.1.1",
|
|
6
6
|
result: "pass",
|
|
7
|
-
digest: "sha256:
|
|
7
|
+
digest: "sha256:e5e456bf3a706f1fa9f906ae71e10ea98a78da52d7d99a5ed59dca8a72bbe927",
|
|
8
8
|
},
|
|
9
9
|
gaps: [
|
|
10
10
|
{
|