yarramate 1.15.0 → 1.15.1
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/compiler.js
CHANGED
|
@@ -362,9 +362,22 @@ function compileWorkspaceResolved(parsed) {
|
|
|
362
362
|
}
|
|
363
363
|
const alreadyDeclaresPolicy = pendingProfiles.some(({ identity }) => identity === shippedPolicyIdentity);
|
|
364
364
|
if (!alreadyDeclaresPolicy) {
|
|
365
|
+
// This probe runs BEFORE the document gate that rejects a source whose
|
|
366
|
+
// schema check failed, so it has to hold its own precondition: a source
|
|
367
|
+
// that composes to anything but a mapping - an empty file, a comment-only
|
|
368
|
+
// one, a bare scalar - selects no profile at all. It used to read
|
|
369
|
+
// `.profile` through an `as` cast, which is what hid the null from the
|
|
370
|
+
// typechecker, and an empty document crashed the whole compile with a
|
|
371
|
+
// `TypeError` instead of the `YM201 must be object` its schema already
|
|
372
|
+
// produces. Every other consumer of a parsed entry checks its diagnostics
|
|
373
|
+
// first (the profile walk above, the pattern walk below); this one could
|
|
374
|
+
// not, because it runs before that gate exists, so it narrows instead.
|
|
365
375
|
const selected = documentInputs.some(({ entry }) => {
|
|
366
376
|
const value = entry.value;
|
|
367
|
-
return value
|
|
377
|
+
return (typeof value === 'object' &&
|
|
378
|
+
value !== null &&
|
|
379
|
+
value.profile ===
|
|
380
|
+
shippedPolicyIdentity);
|
|
368
381
|
});
|
|
369
382
|
const extended = pendingProfiles.some(({ value }) => value.extends === shippedPolicyIdentity);
|
|
370
383
|
if (selected || extended) {
|
|
@@ -18,7 +18,13 @@ export type SubjectReferenceGroup = 'document' | 'projection' | 'evidence' | 'ad
|
|
|
18
18
|
export type SubjectReferenceForm = 'declaration' | 'reference' | 'qualified';
|
|
19
19
|
export interface SubjectReferencePosition {
|
|
20
20
|
readonly group: SubjectReferenceGroup;
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Key path from the document root; `*` matches every element of a
|
|
23
|
+
* collection, which is every index of a sequence and every value of a
|
|
24
|
+
* mapping whose keys are open. Both spell `*` because the schema, not the
|
|
25
|
+
* position, is what decides which one a path lands on: `items` and
|
|
26
|
+
* `patternProperties` are the same shape of "and now, each of these".
|
|
27
|
+
*/
|
|
22
28
|
readonly path: readonly string[];
|
|
23
29
|
readonly form: SubjectReferenceForm;
|
|
24
30
|
}
|
|
@@ -25,6 +25,15 @@ export const SUBJECT_REFERENCE_POSITIONS = [
|
|
|
25
25
|
path: ['concepts', '*', 'constraints', '*', 'ref'],
|
|
26
26
|
form: 'reference',
|
|
27
27
|
},
|
|
28
|
+
// The subjects bound into a pattern instance's slots (ADR 0123). Keyed by
|
|
29
|
+
// slot name rather than indexed, which is why it went missing: this is the
|
|
30
|
+
// only address in any of the four schemas that lives in a mapping, and the
|
|
31
|
+
// completeness walker below derived only sequences.
|
|
32
|
+
{
|
|
33
|
+
group: 'document',
|
|
34
|
+
path: ['concepts', '*', 'parts', '*'],
|
|
35
|
+
form: 'reference',
|
|
36
|
+
},
|
|
28
37
|
{
|
|
29
38
|
group: 'document',
|
|
30
39
|
path: ['concepts', '*', 'references', '*', 'ref'],
|
|
@@ -150,10 +159,22 @@ const collect = (node, path, pointer, form, documentId, source, hits, aliases) =
|
|
|
150
159
|
}
|
|
151
160
|
const [segment, ...rest] = path;
|
|
152
161
|
if (segment === '*') {
|
|
153
|
-
if (
|
|
162
|
+
if (isSeq(node)) {
|
|
163
|
+
for (const [index, item] of node.items.entries()) {
|
|
164
|
+
collect(item, rest, `${pointer}/${index}`, form, documentId, source, hits, aliases);
|
|
165
|
+
}
|
|
154
166
|
return;
|
|
155
|
-
|
|
156
|
-
|
|
167
|
+
}
|
|
168
|
+
// A mapping with open keys, which today is `parts` alone. The pointer
|
|
169
|
+
// segment is the authored key, so a diagnostic names the SLOT ("/parts/
|
|
170
|
+
// interface") rather than a position the reader would have to count out.
|
|
171
|
+
if (isMap(node)) {
|
|
172
|
+
for (const item of node.items) {
|
|
173
|
+
const key = isScalar(item.key) ? String(item.key.value) : undefined;
|
|
174
|
+
if (key === undefined)
|
|
175
|
+
continue;
|
|
176
|
+
collect(item.value, rest, `${pointer}/${key}`, form, documentId, source, hits, aliases);
|
|
177
|
+
}
|
|
157
178
|
}
|
|
158
179
|
return;
|
|
159
180
|
}
|