@smthrs/plan 0.0.0-stage → 1.0.0-rc.13
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/CHANGELOG.md +189 -0
- package/LICENSE +21 -0
- package/README.md +230 -2
- package/THIRD_PARTY_NOTICES.md +48 -0
- package/dist/cjs/CachePolicy.d.ts +131 -0
- package/dist/cjs/CachePolicy.d.ts.map +1 -0
- package/dist/cjs/CachePolicy.js +50 -0
- package/dist/cjs/CachePolicy.js.map +7 -0
- package/dist/cjs/Effects.d.ts +258 -0
- package/dist/cjs/Effects.d.ts.map +1 -0
- package/dist/cjs/Effects.js +76 -0
- package/dist/cjs/Effects.js.map +7 -0
- package/dist/cjs/FileSet.d.ts +366 -0
- package/dist/cjs/FileSet.d.ts.map +1 -0
- package/dist/cjs/FileSet.js +196 -0
- package/dist/cjs/FileSet.js.map +7 -0
- package/dist/cjs/GraphBuildError.d.ts +120 -0
- package/dist/cjs/GraphBuildError.d.ts.map +1 -0
- package/dist/cjs/GraphBuildError.js +71 -0
- package/dist/cjs/GraphBuildError.js.map +7 -0
- package/dist/cjs/KeyMaterial.d.ts +107 -0
- package/dist/cjs/KeyMaterial.d.ts.map +1 -0
- package/dist/cjs/KeyMaterial.js +64 -0
- package/dist/cjs/KeyMaterial.js.map +7 -0
- package/dist/cjs/Node.d.ts +685 -0
- package/dist/cjs/Node.d.ts.map +1 -0
- package/dist/cjs/Node.js +230 -0
- package/dist/cjs/Node.js.map +7 -0
- package/dist/cjs/Placement.d.ts +117 -0
- package/dist/cjs/Placement.d.ts.map +1 -0
- package/dist/cjs/Placement.js +46 -0
- package/dist/cjs/Placement.js.map +7 -0
- package/dist/cjs/Plan.d.ts +489 -0
- package/dist/cjs/Plan.d.ts.map +1 -0
- package/dist/cjs/Plan.js +511 -0
- package/dist/cjs/Plan.js.map +7 -0
- package/dist/cjs/PlanDiff.d.ts +77 -0
- package/dist/cjs/PlanDiff.d.ts.map +1 -0
- package/dist/cjs/PlanDiff.js +149 -0
- package/dist/cjs/PlanDiff.js.map +7 -0
- package/dist/cjs/Planned.d.ts +121 -0
- package/dist/cjs/Planned.d.ts.map +1 -0
- package/dist/cjs/Planned.js +72 -0
- package/dist/cjs/Planned.js.map +7 -0
- package/dist/cjs/Repetition.d.ts +31 -0
- package/dist/cjs/Repetition.d.ts.map +1 -0
- package/dist/cjs/Repetition.js +36 -0
- package/dist/cjs/Repetition.js.map +7 -0
- package/dist/cjs/Scheduling.d.ts +89 -0
- package/dist/cjs/Scheduling.d.ts.map +1 -0
- package/dist/cjs/Scheduling.js +76 -0
- package/dist/cjs/Scheduling.js.map +7 -0
- package/dist/cjs/StepKey.d.ts +354 -0
- package/dist/cjs/StepKey.d.ts.map +1 -0
- package/dist/cjs/StepKey.js +313 -0
- package/dist/cjs/StepKey.js.map +7 -0
- package/dist/cjs/index.d.ts +91 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +59 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/ConflictAnnotation.d.ts +59 -0
- package/dist/cjs/internal/ConflictAnnotation.d.ts.map +1 -0
- package/dist/cjs/internal/ConflictAnnotation.js +247 -0
- package/dist/cjs/internal/ConflictAnnotation.js.map +7 -0
- package/dist/cjs/internal/EffectCandidates.d.ts +19 -0
- package/dist/cjs/internal/EffectCandidates.d.ts.map +1 -0
- package/dist/cjs/internal/EffectCandidates.js +92 -0
- package/dist/cjs/internal/EffectCandidates.js.map +7 -0
- package/dist/cjs/internal/JsonMirror.d.ts +34 -0
- package/dist/cjs/internal/JsonMirror.d.ts.map +1 -0
- package/dist/cjs/internal/JsonMirror.js +195 -0
- package/dist/cjs/internal/JsonMirror.js.map +7 -0
- package/dist/cjs/internal/SchemaIdentity.d.ts +140 -0
- package/dist/cjs/internal/SchemaIdentity.d.ts.map +1 -0
- package/dist/cjs/internal/SchemaIdentity.js +718 -0
- package/dist/cjs/internal/SchemaIdentity.js.map +7 -0
- package/dist/cjs/internal/effects.d.ts +245 -0
- package/dist/cjs/internal/effects.d.ts.map +1 -0
- package/dist/cjs/internal/effects.js +290 -0
- package/dist/cjs/internal/effects.js.map +7 -0
- package/dist/cjs/internal/node.d.ts +526 -0
- package/dist/cjs/internal/node.d.ts.map +1 -0
- package/dist/cjs/internal/node.js +313 -0
- package/dist/cjs/internal/node.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/test/PlanFixtures.d.ts +127 -0
- package/dist/cjs/test/PlanFixtures.d.ts.map +1 -0
- package/dist/cjs/test/PlanFixtures.js +59 -0
- package/dist/cjs/test/PlanFixtures.js.map +7 -0
- package/dist/esm/CachePolicy.d.ts +131 -0
- package/dist/esm/CachePolicy.d.ts.map +1 -0
- package/dist/esm/CachePolicy.js +117 -0
- package/dist/esm/CachePolicy.js.map +1 -0
- package/dist/esm/Effects.d.ts +258 -0
- package/dist/esm/Effects.d.ts.map +1 -0
- package/dist/esm/Effects.js +178 -0
- package/dist/esm/Effects.js.map +1 -0
- package/dist/esm/FileSet.d.ts +366 -0
- package/dist/esm/FileSet.d.ts.map +1 -0
- package/dist/esm/FileSet.js +398 -0
- package/dist/esm/FileSet.js.map +1 -0
- package/dist/esm/GraphBuildError.d.ts +120 -0
- package/dist/esm/GraphBuildError.d.ts.map +1 -0
- package/dist/esm/GraphBuildError.js +145 -0
- package/dist/esm/GraphBuildError.js.map +1 -0
- package/dist/esm/KeyMaterial.d.ts +107 -0
- package/dist/esm/KeyMaterial.d.ts.map +1 -0
- package/dist/esm/KeyMaterial.js +92 -0
- package/dist/esm/KeyMaterial.js.map +1 -0
- package/dist/esm/Node.d.ts +685 -0
- package/dist/esm/Node.d.ts.map +1 -0
- package/dist/esm/Node.js +591 -0
- package/dist/esm/Node.js.map +1 -0
- package/dist/esm/Placement.d.ts +117 -0
- package/dist/esm/Placement.d.ts.map +1 -0
- package/dist/esm/Placement.js +65 -0
- package/dist/esm/Placement.js.map +1 -0
- package/dist/esm/Plan.d.ts +489 -0
- package/dist/esm/Plan.d.ts.map +1 -0
- package/dist/esm/Plan.js +718 -0
- package/dist/esm/Plan.js.map +1 -0
- package/dist/esm/PlanDiff.d.ts +77 -0
- package/dist/esm/PlanDiff.d.ts.map +1 -0
- package/dist/esm/PlanDiff.js +205 -0
- package/dist/esm/PlanDiff.js.map +1 -0
- package/dist/esm/Planned.d.ts +121 -0
- package/dist/esm/Planned.d.ts.map +1 -0
- package/dist/esm/Planned.js +147 -0
- package/dist/esm/Planned.js.map +1 -0
- package/dist/esm/Repetition.d.ts +31 -0
- package/dist/esm/Repetition.d.ts.map +1 -0
- package/dist/esm/Repetition.js +24 -0
- package/dist/esm/Repetition.js.map +1 -0
- package/dist/esm/Scheduling.d.ts +89 -0
- package/dist/esm/Scheduling.d.ts.map +1 -0
- package/dist/esm/Scheduling.js +82 -0
- package/dist/esm/Scheduling.js.map +1 -0
- package/dist/esm/StepKey.d.ts +354 -0
- package/dist/esm/StepKey.d.ts.map +1 -0
- package/dist/esm/StepKey.js +503 -0
- package/dist/esm/StepKey.js.map +1 -0
- package/dist/esm/index.d.ts +91 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +91 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/ConflictAnnotation.d.ts +59 -0
- package/dist/esm/internal/ConflictAnnotation.d.ts.map +1 -0
- package/dist/esm/internal/ConflictAnnotation.js +332 -0
- package/dist/esm/internal/ConflictAnnotation.js.map +1 -0
- package/dist/esm/internal/EffectCandidates.d.ts +19 -0
- package/dist/esm/internal/EffectCandidates.d.ts.map +1 -0
- package/dist/esm/internal/EffectCandidates.js +86 -0
- package/dist/esm/internal/EffectCandidates.js.map +1 -0
- package/dist/esm/internal/JsonMirror.d.ts +34 -0
- package/dist/esm/internal/JsonMirror.d.ts.map +1 -0
- package/dist/esm/internal/JsonMirror.js +204 -0
- package/dist/esm/internal/JsonMirror.js.map +1 -0
- package/dist/esm/internal/SchemaIdentity.d.ts +140 -0
- package/dist/esm/internal/SchemaIdentity.d.ts.map +1 -0
- package/dist/esm/internal/SchemaIdentity.js +1002 -0
- package/dist/esm/internal/SchemaIdentity.js.map +1 -0
- package/dist/esm/internal/effects.d.ts +245 -0
- package/dist/esm/internal/effects.d.ts.map +1 -0
- package/dist/esm/internal/effects.js +459 -0
- package/dist/esm/internal/effects.js.map +1 -0
- package/dist/esm/internal/node.d.ts +526 -0
- package/dist/esm/internal/node.d.ts.map +1 -0
- package/dist/esm/internal/node.js +565 -0
- package/dist/esm/internal/node.js.map +1 -0
- package/dist/esm/test/PlanFixtures.d.ts +127 -0
- package/dist/esm/test/PlanFixtures.d.ts.map +1 -0
- package/dist/esm/test/PlanFixtures.js +60 -0
- package/dist/esm/test/PlanFixtures.js.map +1 -0
- package/docs/README.md +167 -0
- package/docs/api.md +1485 -0
- package/docs/concepts/authoring-ast.md +204 -0
- package/docs/concepts/effects-and-conflicts.md +135 -0
- package/docs/concepts/plan-value.md +168 -0
- package/docs/concepts/step-keys.md +179 -0
- package/docs/guides/author-a-node-graph.md +182 -0
- package/docs/guides/compile-a-plan.md +146 -0
- package/docs/guides/declare-file-effects.md +143 -0
- package/docs/guides/diff-two-plans.md +310 -0
- package/docs/installation.md +75 -0
- package/docs/quickstart.md +128 -0
- package/docs/testing.md +73 -0
- package/docs/troubleshooting.md +314 -0
- package/package.json +255 -3
- package/src/CachePolicy.ts +143 -0
- package/src/Effects.ts +302 -0
- package/src/FileSet.ts +493 -0
- package/src/GraphBuildError.ts +156 -0
- package/src/KeyMaterial.ts +111 -0
- package/src/Node.ts +974 -0
- package/src/Placement.ts +99 -0
- package/src/Plan.ts +911 -0
- package/src/PlanDiff.ts +244 -0
- package/src/Planned.ts +208 -0
- package/src/Repetition.ts +33 -0
- package/src/Scheduling.ts +154 -0
- package/src/StepKey.ts +736 -0
- package/src/index.ts +103 -0
- package/src/internal/ConflictAnnotation.ts +374 -0
- package/src/internal/EffectCandidates.ts +89 -0
- package/src/internal/JsonMirror.ts +255 -0
- package/src/internal/SchemaIdentity.ts +1096 -0
- package/src/internal/effects.ts +543 -0
- package/src/internal/node.ts +859 -0
- package/src/test/PlanFixtures.ts +76 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var ConflictAnnotation_exports = {};
|
|
30
|
+
__export(ConflictAnnotation_exports, {
|
|
31
|
+
annotate: () => annotate
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(ConflictAnnotation_exports);
|
|
34
|
+
var Effect = __toESM(require("effect/Effect"), 1);
|
|
35
|
+
var FileSet = __toESM(require("../FileSet.js"), 1);
|
|
36
|
+
var KeyMaterial = __toESM(require("../KeyMaterial.js"), 1);
|
|
37
|
+
var EffectCandidates = __toESM(require("./EffectCandidates.js"), 1);
|
|
38
|
+
const refuse = (code, message) => Effect.fail({ code, message });
|
|
39
|
+
const pairStrategy = (left, right) => left === "fail" || right === "fail" ? "fail" : left === "lane" || right === "lane" ? "lane" : "serialize";
|
|
40
|
+
const pairRuntime = (left, right) => left === "stop-merge" || right === "stop-merge" ? "stop-merge" : "delay-rebase";
|
|
41
|
+
const producedPaths = (effects) => [
|
|
42
|
+
...FileSet.expand(effects.writes),
|
|
43
|
+
...effects.removes ?? []
|
|
44
|
+
];
|
|
45
|
+
const describe = (entry) => typeof entry === "string" ? entry : entry._tag === "TreeArtifact" ? entry.path : entry.include.join(",");
|
|
46
|
+
const overlap = (left, right) => left.flatMap(
|
|
47
|
+
(leftEntry) => right.some((rightEntry) => FileSet.overlaps(leftEntry, rightEntry)) ? [describe(leftEntry)] : []
|
|
48
|
+
);
|
|
49
|
+
const readOverlap = (reads, produced) => reads.flatMap((entry) => produced.some((output) => FileSet.overlaps(entry, output)) ? [describe(entry)] : []);
|
|
50
|
+
const annotate = (nodes, frozen, replayGenerations) => Effect.gen(function* () {
|
|
51
|
+
const expanded = new Map(nodes.map((node) => [node.id, {
|
|
52
|
+
produced: producedPaths(node.effects),
|
|
53
|
+
reads: FileSet.expandReads(node.effects.reads)
|
|
54
|
+
}]));
|
|
55
|
+
const candidates = EffectCandidates.make(nodes.map((node) => expanded.get(node.id).produced));
|
|
56
|
+
const conflicts = /* @__PURE__ */ new Map();
|
|
57
|
+
const ordering = /* @__PURE__ */ new Map();
|
|
58
|
+
const edges = new Map(nodes.map((node) => [node.id, new Set(node.dependsOn)]));
|
|
59
|
+
const declaredEdges = new Map(nodes.map((node) => [node.id, KeyMaterial.dependencies(node.material)]));
|
|
60
|
+
const ordinals = new Map(nodes.map((node, index) => [node.id, index]));
|
|
61
|
+
const dependents = new Map(nodes.map((node) => [node.id, /* @__PURE__ */ new Set()]));
|
|
62
|
+
for (const node of nodes) {
|
|
63
|
+
for (const dependency of node.dependsOn) dependents.get(dependency).add(node.id);
|
|
64
|
+
}
|
|
65
|
+
const words = Math.ceil(nodes.length / 32);
|
|
66
|
+
const ancestors = /* @__PURE__ */ new Map();
|
|
67
|
+
let work = 0;
|
|
68
|
+
let pairs = 0;
|
|
69
|
+
let nextYield = 2048;
|
|
70
|
+
const checkpoint = Effect.gen(function* () {
|
|
71
|
+
if (work > 1e7 || pairs > 25e4) {
|
|
72
|
+
return yield* refuse(
|
|
73
|
+
"graph_too_large",
|
|
74
|
+
"Plan effect analysis exceeds its work budget (10000000 work units or 250000 candidate pairs)"
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
nextYield = Math.min(work + 2048, 10000001);
|
|
78
|
+
yield* Effect.yieldNow;
|
|
79
|
+
});
|
|
80
|
+
const closure = (id) => Effect.gen(function* () {
|
|
81
|
+
const cached = ancestors.get(id);
|
|
82
|
+
if (cached !== void 0) return cached;
|
|
83
|
+
const frame = (id2) => {
|
|
84
|
+
const bits = new Uint32Array(words);
|
|
85
|
+
const ordinal = ordinals.get(id2);
|
|
86
|
+
bits[ordinal >>> 5] |= 1 << (ordinal & 31);
|
|
87
|
+
return { id: id2, bits, dependencies: Array.from(edges.get(id2)), next: 0 };
|
|
88
|
+
};
|
|
89
|
+
const stack = [frame(id)];
|
|
90
|
+
while (stack.length > 0) {
|
|
91
|
+
const current = stack[stack.length - 1];
|
|
92
|
+
const dependency = current.dependencies[current.next];
|
|
93
|
+
if (dependency === void 0) {
|
|
94
|
+
ancestors.set(current.id, current.bits);
|
|
95
|
+
stack.pop();
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const bits = ancestors.get(dependency);
|
|
99
|
+
if (bits === void 0) {
|
|
100
|
+
stack.push(frame(dependency));
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
for (let word = 0; word < words; word++) {
|
|
104
|
+
current.bits[word] |= bits[word];
|
|
105
|
+
if (++work >= nextYield) yield* checkpoint;
|
|
106
|
+
}
|
|
107
|
+
current.next++;
|
|
108
|
+
}
|
|
109
|
+
return ancestors.get(id);
|
|
110
|
+
});
|
|
111
|
+
const reaches = (from, to) => Effect.gen(function* () {
|
|
112
|
+
const bits = yield* closure(from);
|
|
113
|
+
const ordinal = ordinals.get(to);
|
|
114
|
+
return (bits[ordinal >>> 5] & 1 << (ordinal & 31)) !== 0;
|
|
115
|
+
});
|
|
116
|
+
const addEdge = (from, to) => Effect.gen(function* () {
|
|
117
|
+
const source = yield* closure(from);
|
|
118
|
+
const target = yield* closure(to);
|
|
119
|
+
for (let word = 0; word < words; word++) {
|
|
120
|
+
source[word] |= target[word];
|
|
121
|
+
if (++work >= nextYield) yield* checkpoint;
|
|
122
|
+
}
|
|
123
|
+
const stack = [from];
|
|
124
|
+
while (stack.length > 0) {
|
|
125
|
+
for (const dependent of dependents.get(stack.pop())) {
|
|
126
|
+
if (++work >= nextYield) yield* checkpoint;
|
|
127
|
+
if (!ancestors.delete(dependent)) continue;
|
|
128
|
+
stack.push(dependent);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
edges.get(from).add(to);
|
|
132
|
+
dependents.get(to).add(from);
|
|
133
|
+
});
|
|
134
|
+
const route = (from, to, graph = edges) => Effect.gen(function* () {
|
|
135
|
+
const arrivedFrom = /* @__PURE__ */ new Map();
|
|
136
|
+
const seen = /* @__PURE__ */ new Set([from]);
|
|
137
|
+
const stack = [from];
|
|
138
|
+
while (stack.length > 0) {
|
|
139
|
+
const current = stack.pop();
|
|
140
|
+
if (current === to) {
|
|
141
|
+
const chain = [current];
|
|
142
|
+
for (let step = arrivedFrom.get(current); step !== void 0; step = arrivedFrom.get(step)) {
|
|
143
|
+
chain.push(step);
|
|
144
|
+
}
|
|
145
|
+
return chain.reverse();
|
|
146
|
+
}
|
|
147
|
+
for (const next of graph.get(current)) {
|
|
148
|
+
if (++work >= nextYield) yield* checkpoint;
|
|
149
|
+
if (seen.has(next)) continue;
|
|
150
|
+
seen.add(next);
|
|
151
|
+
arrivedFrom.set(next, current);
|
|
152
|
+
stack.push(next);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return void 0;
|
|
156
|
+
});
|
|
157
|
+
const ranges = [];
|
|
158
|
+
let start = frozen;
|
|
159
|
+
for (let end = start + 1; end <= nodes.length; end++) {
|
|
160
|
+
if (end === nodes.length || replayGenerations && nodes[end].generation !== nodes[start].generation) {
|
|
161
|
+
ranges.push({ start, end });
|
|
162
|
+
start = end;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
for (const { start: start2, end } of ranges) {
|
|
166
|
+
for (let index = start2; index < end; index++) {
|
|
167
|
+
const later = nodes[index];
|
|
168
|
+
const laterProduced = expanded.get(later.id).produced;
|
|
169
|
+
if (laterProduced.length === 0) continue;
|
|
170
|
+
const matches = candidates(laterProduced);
|
|
171
|
+
work += matches.length + laterProduced.length;
|
|
172
|
+
if (work >= nextYield) yield* checkpoint;
|
|
173
|
+
for (const before of matches) {
|
|
174
|
+
if (before >= index) break;
|
|
175
|
+
pairs++;
|
|
176
|
+
work += 32;
|
|
177
|
+
if (work >= nextYield || pairs > 25e4) yield* checkpoint;
|
|
178
|
+
const earlier = nodes[before];
|
|
179
|
+
const earlierProduced = expanded.get(earlier.id).produced;
|
|
180
|
+
work += earlierProduced.length * laterProduced.length;
|
|
181
|
+
if (work >= nextYield) yield* checkpoint;
|
|
182
|
+
const paths = overlap(earlierProduced, laterProduced);
|
|
183
|
+
if (paths.length === 0) continue;
|
|
184
|
+
if (yield* reaches(later.id, earlier.id)) continue;
|
|
185
|
+
const strategy = pairStrategy(earlier.strategy, later.strategy);
|
|
186
|
+
const runtime = pairRuntime(earlier.runtime, later.runtime);
|
|
187
|
+
if (strategy === "fail") {
|
|
188
|
+
return yield* refuse(
|
|
189
|
+
"overlap_forbidden",
|
|
190
|
+
`Nodes ${earlier.id} and ${later.id} both write ${paths.join(", ")}`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
const annotation = (other) => ({ with: other, paths, strategy, runtime });
|
|
194
|
+
if (before >= start2) {
|
|
195
|
+
const previous2 = conflicts.get(earlier.id) ?? [];
|
|
196
|
+
previous2.push(annotation(later.id));
|
|
197
|
+
conflicts.set(earlier.id, previous2);
|
|
198
|
+
}
|
|
199
|
+
const previous = conflicts.get(later.id) ?? [];
|
|
200
|
+
previous.push(annotation(earlier.id));
|
|
201
|
+
conflicts.set(later.id, previous);
|
|
202
|
+
if (strategy === "serialize") {
|
|
203
|
+
const added = ordering.get(later.id) ?? [];
|
|
204
|
+
added.push(earlier.id);
|
|
205
|
+
ordering.set(later.id, added);
|
|
206
|
+
yield* addEdge(later.id, earlier.id);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
for (let index = start2; index < end; index++) {
|
|
211
|
+
const reader = nodes[index];
|
|
212
|
+
const reads = expanded.get(reader.id).reads;
|
|
213
|
+
if (reads.length === 0) continue;
|
|
214
|
+
const matches = candidates(reads);
|
|
215
|
+
work += matches.length + reads.length;
|
|
216
|
+
if (work >= nextYield) yield* checkpoint;
|
|
217
|
+
for (const writerIndex of matches) {
|
|
218
|
+
if (writerIndex >= end) break;
|
|
219
|
+
pairs++;
|
|
220
|
+
work += 32;
|
|
221
|
+
if (work >= nextYield || pairs > 25e4) yield* checkpoint;
|
|
222
|
+
const writer = nodes[writerIndex];
|
|
223
|
+
if (writer.id === reader.id) continue;
|
|
224
|
+
const produced = expanded.get(writer.id).produced;
|
|
225
|
+
work += reads.length * produced.length;
|
|
226
|
+
if (work >= nextYield) yield* checkpoint;
|
|
227
|
+
const paths = readOverlap(reads, produced);
|
|
228
|
+
if (paths.length === 0) continue;
|
|
229
|
+
if (yield* reaches(reader.id, writer.id)) continue;
|
|
230
|
+
if (yield* reaches(writer.id, reader.id)) {
|
|
231
|
+
if ((yield* route(writer.id, reader.id, declaredEdges)) !== void 0) continue;
|
|
232
|
+
const contradiction = yield* route(writer.id, reader.id);
|
|
233
|
+
return yield* refuse(
|
|
234
|
+
"cycle",
|
|
235
|
+
`Plan cycle: node ${reader.id} reads ${paths.join(", ")}, which node ${writer.id} produces, so ${reader.id} must follow ${writer.id}, but ${writer.id} already depends on ${reader.id} through ${contradiction.join(" -> ")}`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
const added = ordering.get(reader.id) ?? [];
|
|
239
|
+
added.push(writer.id);
|
|
240
|
+
ordering.set(reader.id, added);
|
|
241
|
+
yield* addEdge(reader.id, writer.id);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return { conflicts, ordering };
|
|
246
|
+
});
|
|
247
|
+
//# sourceMappingURL=ConflictAnnotation.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/internal/ConflictAnnotation.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The compiler's effect analysis: which writers conflict, and which readers\n * must wait for a producer. Its vocabulary is pairs of declared effects; it\n * never re-keys a node, because ordering is not key material.\n *\n * @since 0.1.0\n * @private\n */\n\nimport * as Effect from \"effect/Effect\"\nimport * as FileSet from \"../FileSet.ts\"\nimport * as KeyMaterial from \"../KeyMaterial.ts\"\nimport type * as Plan from \"../Plan.ts\"\nimport * as EffectCandidates from \"./EffectCandidates.ts\"\n\n/**\n * What {@link annotate} found, by node id and in discovery order: the conflict\n * annotations a node carries and the ordering edges it gains. A frozen node\n * never appears, because its row is never rewritten.\n *\n * @private\n */\ninterface Annotations {\n readonly conflicts: ReadonlyMap<string, ReadonlyArray<Plan.ConflictAnnotation>>\n readonly ordering: ReadonlyMap<string, ReadonlyArray<string>>\n}\n\n/**\n * A graph the analysis refuses, in the fields a `PlanError` carries.\n *\n * @private\n */\ninterface Refusal {\n readonly code: \"cycle\" | \"graph_too_large\" | \"overlap_forbidden\"\n readonly message: string\n}\n\n/** @private */\nconst refuse = (code: Refusal[\"code\"], message: string) => Effect.fail<Refusal>({ code, message })\n\n/**\n * Resolves the pair's verdict. `fail` dominates \u2014 a flow that promised\n * disjointness must not be quietly serialized \u2014 then `lane`, because \"when\n * either writer requests `lane`, both receive lane annotations\"; `serialize`\n * is the default whenever an overlap is detected at all.\n *\n * @private\n */\nconst pairStrategy = (left: Plan.PairStrategy, right: Plan.PairStrategy): Plan.PairStrategy =>\n left === \"fail\" || right === \"fail\" ? \"fail\" : left === \"lane\" || right === \"lane\" ? \"lane\" : \"serialize\"\n\n/**\n * `stop-merge` dominates for the same reason `lane` does: it is the strategy a\n * declaration opts into, and a pair cannot half-merge.\n *\n * @private\n */\nconst pairRuntime = (left: Plan.RuntimeStrategy, right: Plan.RuntimeStrategy): Plan.RuntimeStrategy =>\n left === \"stop-merge\" || right === \"stop-merge\" ? \"stop-merge\" : \"delay-rebase\"\n\n/**\n * Every path a node mutates. A removal moves a path's content exactly as a\n * write does \u2014 a reader that runs before it sees different bytes than one that\n * runs after \u2014 so both passes below treat the two as one set.\n *\n * @private\n */\nconst producedPaths = (effects: Plan.NodeEffects): ReadonlyArray<FileSet.Entry> => [\n ...FileSet.expand(effects.writes),\n ...effects.removes ?? []\n]\n\n/**\n * How an annotation and a refusal name one declared entry.\n *\n * @private\n */\nconst describe = (entry: FileSet.Entry): string =>\n typeof entry === \"string\" ? entry : entry._tag === \"TreeArtifact\" ? entry.path : entry.include.join(\",\")\n\n/** @private */\nconst overlap = (\n left: ReadonlyArray<FileSet.Entry>,\n right: ReadonlyArray<FileSet.Entry>\n): ReadonlyArray<string> =>\n left.flatMap((leftEntry) =>\n right.some((rightEntry) => FileSet.overlaps(leftEntry, rightEntry)) ? [describe(leftEntry)] : []\n )\n\n/**\n * The read declarations of one node that a writer's produced set covers. The\n * conflict pass compares write sets against write sets, so this relation is\n * the one it cannot see. Rendered the way {@link overlap} renders a write,\n * because a refusal names them.\n *\n * @private\n */\nconst readOverlap = (\n reads: ReadonlyArray<FileSet.ReadEntry>,\n produced: ReadonlyArray<FileSet.Entry>\n): ReadonlyArray<string> =>\n reads.flatMap((entry) => produced.some((output) => FileSet.overlaps(entry, output)) ? [describe(entry)] : [])\n\n/**\n * Two passes over the graph.\n *\n * The first detects write overlaps and annotates the conflicting pair, adding\n * the ordering edge a `serialize` verdict implies. Nodes already ordered by a\n * dependency path are not conflicts.\n *\n * The second adds reader-after-writer edges: a node that reads a path another\n * node writes is ordered behind its producer. That pair is not a conflict,\n * because nothing needs annotating and no strategy applies. It is a missing\n * edge, so only `dependsOn` grows. When the graph already orders the producer\n * behind its reader by explicit material dependencies, the reader consumes\n * the earlier version. An opposing inferred ordering still fails with `cycle`.\n *\n * Nodes are visited in plan order, so a `serialize` edge always points from\n * the earlier declaration to the later one and can never close a cycle. The\n * first `frozen` nodes were recorded by an earlier generation: append-only\n * means their rows are never rewritten, so a pair discovered during\n * elaboration is annotated on the NEW node only \u2014 which is also the node the\n * ordering edge lands on, and the annotation names the other side either way.\n * `replayGenerations` re-derives a recorded plan one generation at a time\n * under that same rule.\n *\n * @since 0.1.0\n * @private\n */\nexport const annotate = (\n nodes: ReadonlyArray<Plan.PlanNode>,\n frozen: number,\n replayGenerations: boolean\n): Effect.Effect<Annotations, Refusal> =>\n Effect.gen(function*() {\n const expanded = new Map(nodes.map((node) => [node.id, {\n produced: producedPaths(node.effects),\n reads: FileSet.expandReads(node.effects.reads)\n }]))\n const candidates = EffectCandidates.make(nodes.map((node) => expanded.get(node.id)!.produced))\n const conflicts = new Map<string, Array<Plan.ConflictAnnotation>>()\n const ordering = new Map<string, Array<string>>()\n const edges = new Map(nodes.map((node) => [node.id, new Set(node.dependsOn)]))\n // Keep declaration sequencing separate from inferred ordering, including\n // for frozen generations whose `dependsOn` already contains inferred edges.\n const declaredEdges = new Map(nodes.map((node) => [node.id, KeyMaterial.dependencies(node.material)]))\n // One index and mutable graph serve every replayed generation. Future\n // producers are filtered at the generation boundary, never re-indexed.\n const ordinals = new Map(nodes.map((node, index) => [node.id, index]))\n const dependents = new Map(nodes.map((node) => [node.id, new Set<string>()]))\n for (const node of nodes) {\n for (const dependency of node.dependsOn) dependents.get(dependency)!.add(node.id)\n }\n const words = Math.ceil(nodes.length / 32)\n const ancestors = new Map<string, Uint32Array>()\n // Charge a pair for bookkeeping as well as its path comparisons. The\n // separate pair ceiling also bounds persisted annotations and edges.\n let work = 0\n let pairs = 0\n let nextYield = 2_048\n const checkpoint = Effect.gen(function*() {\n if (work > 10_000_000 || pairs > 250_000) {\n return yield* refuse(\n \"graph_too_large\",\n \"Plan effect analysis exceeds its work budget (10000000 work units or 250000 candidate pairs)\"\n )\n }\n nextYield = Math.min(work + 2_048, 10_000_001)\n yield* Effect.yieldNow\n })\n // Cache transitive ancestors as bitsets. Adding an edge updates its source\n // immediately and invalidates only cached dependents. In particular, dense\n // writers never walk the growing dependency DAG for each conflicting pair.\n const closure = (id: string): Effect.Effect<Uint32Array, Refusal> =>\n Effect.gen(function*() {\n const cached = ancestors.get(id)\n if (cached !== undefined) return cached\n const frame = (id: string) => {\n const bits = new Uint32Array(words)\n const ordinal = ordinals.get(id)!\n bits[ordinal >>> 5]! |= 1 << (ordinal & 31)\n return { id, bits, dependencies: Array.from(edges.get(id)!), next: 0 }\n }\n const stack = [frame(id)]\n while (stack.length > 0) {\n const current = stack[stack.length - 1]!\n const dependency = current.dependencies[current.next]\n if (dependency === undefined) {\n ancestors.set(current.id, current.bits)\n stack.pop()\n continue\n }\n const bits = ancestors.get(dependency)\n if (bits === undefined) {\n stack.push(frame(dependency))\n continue\n }\n for (let word = 0; word < words; word++) {\n current.bits[word]! |= bits[word]!\n if (++work >= nextYield) yield* checkpoint\n }\n current.next++\n }\n return ancestors.get(id)!\n })\n const reaches = (from: string, to: string) =>\n Effect.gen(function*() {\n const bits = yield* closure(from)\n const ordinal = ordinals.get(to)!\n return (bits[ordinal >>> 5]! & (1 << (ordinal & 31))) !== 0\n })\n const addEdge = (from: string, to: string) =>\n Effect.gen(function*() {\n const source = yield* closure(from)\n const target = yield* closure(to)\n for (let word = 0; word < words; word++) {\n source[word]! |= target[word]!\n if (++work >= nextYield) yield* checkpoint\n }\n const stack = [from]\n while (stack.length > 0) {\n for (const dependent of dependents.get(stack.pop()!)!) {\n if (++work >= nextYield) yield* checkpoint\n if (!ancestors.delete(dependent)) continue\n stack.push(dependent)\n }\n }\n edges.get(from)!.add(to)\n dependents.get(to)!.add(from)\n })\n // Routes are only needed for explicit version sequencing and a cycle's\n // diagnostic. Bound and yield these walks too.\n const route = (\n from: string,\n to: string,\n graph: ReadonlyMap<string, Iterable<string>> = edges\n ): Effect.Effect<ReadonlyArray<string> | undefined, Refusal> =>\n Effect.gen(function*() {\n const arrivedFrom = new Map<string, string>()\n const seen = new Set<string>([from])\n const stack = [from]\n while (stack.length > 0) {\n const current = stack.pop()!\n if (current === to) {\n const chain = [current]\n for (let step = arrivedFrom.get(current); step !== undefined; step = arrivedFrom.get(step)) {\n chain.push(step)\n }\n return chain.reverse()\n }\n for (const next of graph.get(current)!) {\n if (++work >= nextYield) yield* checkpoint\n if (seen.has(next)) continue\n seen.add(next)\n arrivedFrom.set(next, current)\n stack.push(next)\n }\n }\n return undefined\n })\n const ranges: Array<{ start: number; end: number }> = []\n let start = frozen\n for (let end = start + 1; end <= nodes.length; end++) {\n if (end === nodes.length || (replayGenerations && nodes[end]!.generation !== nodes[start]!.generation)) {\n ranges.push({ start, end })\n start = end\n }\n }\n for (const { start, end } of ranges) {\n for (let index = start; index < end; index++) {\n const later = nodes[index]!\n const laterProduced = expanded.get(later.id)!.produced\n if (laterProduced.length === 0) continue\n const matches = candidates(laterProduced)\n work += matches.length + laterProduced.length\n if (work >= nextYield) yield* checkpoint\n for (const before of matches) {\n if (before >= index) break\n pairs++\n work += 32\n if (work >= nextYield || pairs > 250_000) yield* checkpoint\n const earlier = nodes[before]!\n const earlierProduced = expanded.get(earlier.id)!.produced\n work += earlierProduced.length * laterProduced.length\n if (work >= nextYield) yield* checkpoint\n const paths = overlap(earlierProduced, laterProduced)\n if (paths.length === 0) continue\n if (yield* reaches(later.id, earlier.id)) continue\n const strategy = pairStrategy(earlier.strategy, later.strategy)\n const runtime = pairRuntime(earlier.runtime, later.runtime)\n if (strategy === \"fail\") {\n return yield* refuse(\n \"overlap_forbidden\",\n `Nodes ${earlier.id} and ${later.id} both write ${paths.join(\", \")}`\n )\n }\n const annotation = (other: string): Plan.ConflictAnnotation => ({ with: other, paths, strategy, runtime })\n if (before >= start) {\n const previous = conflicts.get(earlier.id) ?? []\n previous.push(annotation(later.id))\n conflicts.set(earlier.id, previous)\n }\n const previous = conflicts.get(later.id) ?? []\n previous.push(annotation(earlier.id))\n conflicts.set(later.id, previous)\n if (strategy === \"serialize\") {\n const added = ordering.get(later.id) ?? []\n added.push(earlier.id)\n ordering.set(later.id, added)\n yield* addEdge(later.id, earlier.id)\n }\n }\n }\n // Reader-after-writer. A node that READS a path another node WRITES was\n // ordered by nothing: the pass above compares write sets against write\n // sets, so reader and writer could be admitted in the same wavefront\n // round. The reader then measures pre-producer bytes and \u2014 because the\n // dispatch key honestly folds the digest it measured \u2014 caches that wrong\n // execution as a legitimate one. `PlanScheduler.measure` already assumes\n // \"their preceding producer has settled\"; this pass is what makes that\n // assumption true. Explicit read-before-write sequencing instead consumes\n // an earlier version: a source input, or another preceding writer's output.\n //\n // Ordering only, exactly like a `serialize` edge: it enters `dependsOn`\n // and never key material, because the reader computes the same result\n // either way and its content dependence is already keyed by the hermetic\n // boundary digests measured at dispatch.\n for (let index = start; index < end; index++) {\n const reader = nodes[index]!\n // Append-only: a frozen node's row is never rewritten, so the edge lands\n // on the new node only \u2014 the same rule the conflict pass follows.\n const reads = expanded.get(reader.id)!.reads\n if (reads.length === 0) continue\n const matches = candidates(reads)\n work += matches.length + reads.length\n if (work >= nextYield) yield* checkpoint\n for (const writerIndex of matches) {\n if (writerIndex >= end) break\n pairs++\n work += 32\n if (work >= nextYield || pairs > 250_000) yield* checkpoint\n const writer = nodes[writerIndex]!\n if (writer.id === reader.id) continue\n const produced = expanded.get(writer.id)!.produced\n work += reads.length * produced.length\n if (work >= nextYield) yield* checkpoint\n const paths = readOverlap(reads, produced)\n if (paths.length === 0) continue\n // Already ordered, by a material edge, a serialize edge, or a path\n // through either.\n if (yield* reaches(reader.id, writer.id)) continue\n // Explicit sequencing selects the version being read. Do not reverse\n // it just because a later node writes the same path. Only declared\n // Ref/Pending paths establish this intent; a serialize edge or an\n // earlier inferred producer edge cannot silently select old bytes.\n if (yield* reaches(writer.id, reader.id)) {\n if ((yield* route(writer.id, reader.id, declaredEdges)) !== undefined) continue\n const contradiction = (yield* route(writer.id, reader.id))!\n return yield* refuse(\n \"cycle\",\n `Plan cycle: node ${reader.id} reads ${paths.join(\", \")}, which node ${writer.id} produces, ` +\n `so ${reader.id} must follow ${writer.id}, but ${writer.id} already depends on ${reader.id} ` +\n `through ${contradiction.join(\" -> \")}`\n )\n }\n const added = ordering.get(reader.id) ?? []\n added.push(writer.id)\n ordering.set(reader.id, added)\n yield* addEdge(reader.id, writer.id)\n }\n }\n }\n return { conflicts, ordering }\n })\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["id", "start", "previous"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebuildable candidate index for the compiler's existing overlap predicate.
|
|
3
|
+
* Exact paths and tree prefixes share a trie keyed by case-folded segments, the
|
|
4
|
+
* form FileSet.overlaps compares. A plain string is a literal path there, even
|
|
5
|
+
* one holding `*`. Globs stay conservative: their exclusions and pair semantics
|
|
6
|
+
* are decided by FileSet.overlaps, never here.
|
|
7
|
+
* Nothing in this index becomes persisted plan or key material.
|
|
8
|
+
* @since 0.1.0
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
import * as FileSet from "../FileSet.ts";
|
|
12
|
+
/**
|
|
13
|
+
* Selects possible producers in declaration order; callers retain the final
|
|
14
|
+
* FileSet.overlaps check for every selected pair.
|
|
15
|
+
* @since 0.1.0
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
export declare const make: (produced: ReadonlyArray<ReadonlyArray<FileSet.Entry>>) => (entries: ReadonlyArray<FileSet.Entry>) => ReadonlyArray<number>;
|
|
19
|
+
//# sourceMappingURL=EffectCandidates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EffectCandidates.d.ts","sourceRoot":"","sources":["../../../src/internal/EffectCandidates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,OAAO,MAAM,eAAe,CAAA;AAgBxC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,UAAU,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MA0BhE,SAAS,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,KAAG,aAAa,CAAC,MAAM,CA6BrE,CAAA"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var EffectCandidates_exports = {};
|
|
30
|
+
__export(EffectCandidates_exports, {
|
|
31
|
+
make: () => make
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(EffectCandidates_exports);
|
|
34
|
+
var FileSet = __toESM(require("../FileSet.js"), 1);
|
|
35
|
+
const branch = () => ({ children: /* @__PURE__ */ new Map(), exact: /* @__PURE__ */ new Set(), trees: /* @__PURE__ */ new Set() });
|
|
36
|
+
const add = (target, values) => {
|
|
37
|
+
for (const value of values) target.add(value);
|
|
38
|
+
};
|
|
39
|
+
const patternLike = (entry) => typeof entry !== "string" && entry._tag === "Glob";
|
|
40
|
+
const ordered = (values) => Array.from(values).sort((left, right) => left - right);
|
|
41
|
+
const make = (produced) => {
|
|
42
|
+
const root = branch();
|
|
43
|
+
const all = /* @__PURE__ */ new Set();
|
|
44
|
+
const globs = /* @__PURE__ */ new Set();
|
|
45
|
+
for (let owner = 0; owner < produced.length; owner++) {
|
|
46
|
+
for (const entry of produced[owner]) {
|
|
47
|
+
all.add(owner);
|
|
48
|
+
if (patternLike(entry)) {
|
|
49
|
+
globs.add(owner);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const path = typeof entry === "string" ? entry : entry.path;
|
|
53
|
+
let current = root;
|
|
54
|
+
for (const segment of FileSet.folded(path).split("/")) {
|
|
55
|
+
let child = current.children.get(segment);
|
|
56
|
+
if (child === void 0) {
|
|
57
|
+
child = branch();
|
|
58
|
+
current.children.set(segment, child);
|
|
59
|
+
}
|
|
60
|
+
current = child;
|
|
61
|
+
}
|
|
62
|
+
const owners = typeof entry === "string" ? current.exact : current.trees;
|
|
63
|
+
owners.add(owner);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return (entries) => {
|
|
67
|
+
const found = /* @__PURE__ */ new Set();
|
|
68
|
+
for (const entry of entries) {
|
|
69
|
+
if (patternLike(entry)) return ordered(all);
|
|
70
|
+
add(found, globs);
|
|
71
|
+
const path = typeof entry === "string" ? entry : entry.path;
|
|
72
|
+
let current = root;
|
|
73
|
+
for (const segment of FileSet.folded(path).split("/")) {
|
|
74
|
+
current = current.children.get(segment);
|
|
75
|
+
if (current === void 0) break;
|
|
76
|
+
add(found, current.trees);
|
|
77
|
+
}
|
|
78
|
+
if (current === void 0) continue;
|
|
79
|
+
add(found, current.exact);
|
|
80
|
+
if (typeof entry === "string") continue;
|
|
81
|
+
const stack = Array.from(current.children.values());
|
|
82
|
+
while (stack.length > 0) {
|
|
83
|
+
const descendant = stack.pop();
|
|
84
|
+
add(found, descendant.exact);
|
|
85
|
+
add(found, descendant.trees);
|
|
86
|
+
for (const child of descendant.children.values()) stack.push(child);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return ordered(found);
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=EffectCandidates.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/internal/EffectCandidates.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Rebuildable candidate index for the compiler's existing overlap predicate.\n * Exact paths and tree prefixes share a trie keyed by case-folded segments, the\n * form FileSet.overlaps compares. A plain string is a literal path there, even\n * one holding `*`. Globs stay conservative: their exclusions and pair semantics\n * are decided by FileSet.overlaps, never here.\n * Nothing in this index becomes persisted plan or key material.\n * @since 0.1.0\n * @private\n */\n\nimport * as FileSet from \"../FileSet.ts\"\n\ninterface Branch {\n readonly children: Map<string, Branch>\n readonly exact: Set<number>\n readonly trees: Set<number>\n}\n\nconst branch = (): Branch => ({ children: new Map(), exact: new Set(), trees: new Set() })\nconst add = (target: Set<number>, values: ReadonlySet<number>): void => {\n for (const value of values) target.add(value)\n}\n/** A Glob has no single trie position, so it stays conservative. */\nconst patternLike = (entry: FileSet.Entry): entry is FileSet.Glob => typeof entry !== \"string\" && entry._tag === \"Glob\"\nconst ordered = (values: ReadonlySet<number>): Array<number> => Array.from(values).sort((left, right) => left - right)\n\n/**\n * Selects possible producers in declaration order; callers retain the final\n * FileSet.overlaps check for every selected pair.\n * @since 0.1.0\n * @private\n */\nexport const make = (produced: ReadonlyArray<ReadonlyArray<FileSet.Entry>>) => {\n const root = branch()\n const all = new Set<number>()\n const globs = new Set<number>()\n for (let owner = 0; owner < produced.length; owner++) {\n for (const entry of produced[owner]!) {\n all.add(owner)\n if (patternLike(entry)) {\n globs.add(owner)\n continue\n }\n const path = typeof entry === \"string\" ? entry : entry.path\n let current = root\n for (const segment of FileSet.folded(path).split(\"/\")) {\n let child = current.children.get(segment)\n if (child === undefined) {\n child = branch()\n current.children.set(segment, child)\n }\n current = child\n }\n const owners = typeof entry === \"string\" ? current.exact : current.trees\n owners.add(owner)\n }\n }\n\n return (entries: ReadonlyArray<FileSet.Entry>): ReadonlyArray<number> => {\n const found = new Set<number>()\n for (const entry of entries) {\n // A glob can overlap every other glob/tree; literal matches and\n // exclusions remain the final predicate's responsibility as well.\n if (patternLike(entry)) return ordered(all)\n add(found, globs)\n const path = typeof entry === \"string\" ? entry : entry.path\n let current: Branch | undefined = root\n for (const segment of FileSet.folded(path).split(\"/\")) {\n current = current.children.get(segment)\n if (current === undefined) break\n add(found, current.trees)\n }\n if (current === undefined) continue\n add(found, current.exact)\n if (typeof entry === \"string\") continue\n const stack = Array.from(current.children.values())\n while (stack.length > 0) {\n const descendant = stack.pop()!\n add(found, descendant.exact)\n add(found, descendant.trees)\n for (const child of descendant.children.values()) stack.push(child)\n }\n }\n // Original declaration order controls annotations, conflict precedence,\n // and cycle diagnostics, irrespective of trie or Set traversal order.\n return ordered(found)\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,cAAyB;AAQzB,MAAM,SAAS,OAAe,EAAE,UAAU,oBAAI,IAAI,GAAG,OAAO,oBAAI,IAAI,GAAG,OAAO,oBAAI,IAAI,EAAE;AACxF,MAAM,MAAM,CAAC,QAAqB,WAAsC;AACtE,aAAW,SAAS,OAAQ,QAAO,IAAI,KAAK;AAC9C;AAEA,MAAM,cAAc,CAAC,UAAgD,OAAO,UAAU,YAAY,MAAM,SAAS;AACjH,MAAM,UAAU,CAAC,WAA+C,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC,MAAM,UAAU,OAAO,KAAK;AAQ9G,MAAM,OAAO,CAAC,aAA0D;AAC7E,QAAM,OAAO,OAAO;AACpB,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,QAAQ,oBAAI,IAAY;AAC9B,WAAS,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS;AACpD,eAAW,SAAS,SAAS,KAAK,GAAI;AACpC,UAAI,IAAI,KAAK;AACb,UAAI,YAAY,KAAK,GAAG;AACtB,cAAM,IAAI,KAAK;AACf;AAAA,MACF;AACA,YAAM,OAAO,OAAO,UAAU,WAAW,QAAQ,MAAM;AACvD,UAAI,UAAU;AACd,iBAAW,WAAW,QAAQ,OAAO,IAAI,EAAE,MAAM,GAAG,GAAG;AACrD,YAAI,QAAQ,QAAQ,SAAS,IAAI,OAAO;AACxC,YAAI,UAAU,QAAW;AACvB,kBAAQ,OAAO;AACf,kBAAQ,SAAS,IAAI,SAAS,KAAK;AAAA,QACrC;AACA,kBAAU;AAAA,MACZ;AACA,YAAM,SAAS,OAAO,UAAU,WAAW,QAAQ,QAAQ,QAAQ;AACnE,aAAO,IAAI,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,CAAC,YAAiE;AACvE,UAAM,QAAQ,oBAAI,IAAY;AAC9B,eAAW,SAAS,SAAS;AAG3B,UAAI,YAAY,KAAK,EAAG,QAAO,QAAQ,GAAG;AAC1C,UAAI,OAAO,KAAK;AAChB,YAAM,OAAO,OAAO,UAAU,WAAW,QAAQ,MAAM;AACvD,UAAI,UAA8B;AAClC,iBAAW,WAAW,QAAQ,OAAO,IAAI,EAAE,MAAM,GAAG,GAAG;AACrD,kBAAU,QAAQ,SAAS,IAAI,OAAO;AACtC,YAAI,YAAY,OAAW;AAC3B,YAAI,OAAO,QAAQ,KAAK;AAAA,MAC1B;AACA,UAAI,YAAY,OAAW;AAC3B,UAAI,OAAO,QAAQ,KAAK;AACxB,UAAI,OAAO,UAAU,SAAU;AAC/B,YAAM,QAAQ,MAAM,KAAK,QAAQ,SAAS,OAAO,CAAC;AAClD,aAAO,MAAM,SAAS,GAAG;AACvB,cAAM,aAAa,MAAM,IAAI;AAC7B,YAAI,OAAO,WAAW,KAAK;AAC3B,YAAI,OAAO,WAAW,KAAK;AAC3B,mBAAW,SAAS,WAAW,SAAS,OAAO,EAAG,OAAM,KAAK,KAAK;AAAA,MACpE;AAAA,IACF;AAGA,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inert JSON mirror of a value: what `JSON.stringify` would see, as data.
|
|
3
|
+
*
|
|
4
|
+
* The AST stores payloads this way, the plan compiler stores key material this
|
|
5
|
+
* way, and a plan diff compares declarations this way, so all three share the
|
|
6
|
+
* one walk. A planned value is the only member with no JSON meaning of its
|
|
7
|
+
* own, and each caller decides what it becomes.
|
|
8
|
+
*
|
|
9
|
+
* @since 0.1.0
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
import * as Planned from "../Planned.ts";
|
|
13
|
+
/**
|
|
14
|
+
* Clones the JSON mirror of the input, so {@link module:StepKey.content} over
|
|
15
|
+
* the clone and the input produce the same key and the clone holds only inert
|
|
16
|
+
* JSON data. The walk uses an explicit stack, memoizes shared references and
|
|
17
|
+
* cycles, honors callable `toJSON`, omits object members without a JSON
|
|
18
|
+
* representation, and writes `null` for those values in arrays.
|
|
19
|
+
*
|
|
20
|
+
* `toJSON` receives the key canonical serialization passes it: the member
|
|
21
|
+
* name, the array index, or `""` at the root. Its replacement is therefore
|
|
22
|
+
* memoized per source and key, since one shared source may serialize
|
|
23
|
+
* differently at two positions. A source met again inside its own
|
|
24
|
+
* replacement reuses that replacement, so a cycle through `toJSON` clones as
|
|
25
|
+
* a cycle whatever key it recurs at.
|
|
26
|
+
*
|
|
27
|
+
* A planned value becomes whatever `plannedValue` returns for it. Refusals
|
|
28
|
+
* throw a {@link GraphBuildError} naming the member's path.
|
|
29
|
+
*
|
|
30
|
+
* @since 0.1.0
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
export declare const jsonMirror: (input: unknown, plannedValue: (value: unknown, reference: Planned.Reference) => unknown) => unknown;
|
|
34
|
+
//# sourceMappingURL=JsonMirror.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonMirror.d.ts","sourceRoot":"","sources":["../../../src/internal/JsonMirror.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,OAAO,MAAM,eAAe,CAAA;AAqFxC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,OAAO,EACd,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,KAAK,OAAO,KACtE,OAqIF,CAAA"}
|