@intentius/tsad-reference 1.4.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/CAVEATS.md +95 -0
- package/README.md +42 -0
- package/dist/adapter.d.ts +5 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +50 -0
- package/dist/adapter.js.map +1 -0
- package/dist/fnbody.d.ts +11 -0
- package/dist/fnbody.d.ts.map +1 -0
- package/dist/fnbody.js +68 -0
- package/dist/fnbody.js.map +1 -0
- package/dist/fold.d.ts +86 -0
- package/dist/fold.d.ts.map +1 -0
- package/dist/fold.js +558 -0
- package/dist/fold.js.map +1 -0
- package/dist/foldable-helpers.d.ts +23 -0
- package/dist/foldable-helpers.d.ts.map +1 -0
- package/dist/foldable-helpers.js +25 -0
- package/dist/foldable-helpers.js.map +1 -0
- package/dist/host.d.ts +45 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +5 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/module.d.ts +20 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +74 -0
- package/dist/module.js.map +1 -0
- package/dist/project.d.ts +22 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +481 -0
- package/dist/project.js.map +1 -0
- package/dist/revive.d.ts +16 -0
- package/dist/revive.d.ts.map +1 -0
- package/dist/revive.js +109 -0
- package/dist/revive.js.map +1 -0
- package/dist/subset.d.ts +42 -0
- package/dist/subset.d.ts.map +1 -0
- package/dist/subset.js +214 -0
- package/dist/subset.js.map +1 -0
- package/package.json +37 -0
- package/src/adapter.ts +48 -0
- package/src/fnbody.ts +61 -0
- package/src/fold.ts +581 -0
- package/src/foldable-helpers.ts +38 -0
- package/src/host.ts +38 -0
- package/src/index.ts +8 -0
- package/src/module.ts +52 -0
- package/src/no-own-execution.test.ts +86 -0
- package/src/prebuild.test.ts +68 -0
- package/src/project.ts +495 -0
- package/src/revive.ts +120 -0
- package/src/subset.ts +224 -0
package/dist/project.js
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* J2, the per-file verdict, and J3, the identity-taint fixpoint.
|
|
3
|
+
*
|
|
4
|
+
* Written from `spec/judgments.md` (#21, #22), not derived from any
|
|
5
|
+
* implementation. A project here is a map of path to source; there is no
|
|
6
|
+
* filesystem and no real module system, which is enough for the judgments
|
|
7
|
+
* because both are defined over a finite set of files and the edges between
|
|
8
|
+
* them.
|
|
9
|
+
*
|
|
10
|
+
* Revival (`F-Val-Fate`, #61) runs through the host the caller supplies: a
|
|
11
|
+
* `{__resource}` envelope becomes a real instance of the class the folding
|
|
12
|
+
* file imported, and with `EMPTY_HOST` it stays an envelope, which is an
|
|
13
|
+
* object either way as far as F-Capture's identity test is concerned. What
|
|
14
|
+
* this file does not do is in `CAVEATS.md`.
|
|
15
|
+
*/
|
|
16
|
+
import { posix } from "node:path";
|
|
17
|
+
import * as ts from "typescript";
|
|
18
|
+
import { EMPTY_HOST } from "./host.js";
|
|
19
|
+
import { foldExpr, collectConsts, collectLocalFunctions, FoldRejection, isFoldableFunction } from "./fold.js";
|
|
20
|
+
import { registerHelpers, registerHostSpecifiers, isHostOwnedSpecifier } from "./foldable-helpers.js";
|
|
21
|
+
import { revive } from "./revive.js";
|
|
22
|
+
const parse = (path, source) => ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true);
|
|
23
|
+
const isProjectSpecifier = (s) => s.startsWith(".") || s.startsWith("/");
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a relative specifier against the project's own key set: the
|
|
26
|
+
* specifier joined to the importer's directory and normalised, then the three
|
|
27
|
+
* obvious candidates. `..` segments are resolved; the corpus found a version
|
|
28
|
+
* of this that left `../../config` unjoined, which dropped the import edge and
|
|
29
|
+
* with it the forward taint, so a file chant ran folded here (#96).
|
|
30
|
+
*/
|
|
31
|
+
function resolveKey(from, spec, files) {
|
|
32
|
+
const base = from.includes("/") ? from.slice(0, from.lastIndexOf("/") + 1) : "";
|
|
33
|
+
const joined = posix.normalize(base + spec).replace(/^\.\//, "");
|
|
34
|
+
for (const cand of [joined, `${joined}.ts`, `${joined}/index.ts`])
|
|
35
|
+
if (files.has(cand))
|
|
36
|
+
return cand;
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
function scanExports(sf, admitDefault) {
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const st of sf.statements) {
|
|
42
|
+
if (ts.isExportAssignment(st)) {
|
|
43
|
+
// S-ExportDefault (spec 1.2, #94): in data-host, `export default ⟨Expr⟩`
|
|
44
|
+
// is the declarator named `default`; in full it stays S-Disqualify until
|
|
45
|
+
// chant admits it. `export = …` disqualifies in both.
|
|
46
|
+
if (st.isExportEquals || !admitDefault)
|
|
47
|
+
return { declarators: out, disqualified: "`export default` is not foldable" };
|
|
48
|
+
out.push({ kind: "default", expr: st.expression });
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (ts.isExportDeclaration(st)) {
|
|
52
|
+
if (st.isTypeOnly)
|
|
53
|
+
continue;
|
|
54
|
+
if (!st.exportClause || !ts.isNamedExports(st.exportClause)) {
|
|
55
|
+
return { declarators: out, disqualified: "`export * from` is not foldable" };
|
|
56
|
+
}
|
|
57
|
+
const elements = st.exportClause.elements
|
|
58
|
+
.filter((e) => !e.isTypeOnly)
|
|
59
|
+
.map((e) => ({ imported: (e.propertyName ?? e.name).text, local: (e.propertyName ?? e.name).text, as: e.name.text }));
|
|
60
|
+
if (st.moduleSpecifier && ts.isStringLiteral(st.moduleSpecifier)) {
|
|
61
|
+
out.push({ kind: "re-export", specifier: st.moduleSpecifier.text, elements });
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
out.push({ kind: "named-export", elements: elements.map(({ local, as }) => ({ local, as })) });
|
|
65
|
+
}
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const exported = st.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
|
|
69
|
+
if (ts.isFunctionDeclaration(st) && exported) {
|
|
70
|
+
if (st.modifiers?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword) || !st.name) {
|
|
71
|
+
return { declarators: out, disqualified: "`export default function` is not foldable" };
|
|
72
|
+
}
|
|
73
|
+
if (st.body)
|
|
74
|
+
out.push({ kind: "function", name: st.name.text, fn: st });
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (ts.isClassDeclaration(st) && exported)
|
|
78
|
+
return { declarators: out, disqualified: "an exported class is not foldable" };
|
|
79
|
+
if (!ts.isVariableStatement(st) || !exported)
|
|
80
|
+
continue;
|
|
81
|
+
if ((st.declarationList.flags & ts.NodeFlags.Const) === 0) {
|
|
82
|
+
return { declarators: out, disqualified: "an exported `let`/`var` is not foldable" };
|
|
83
|
+
}
|
|
84
|
+
for (const d of st.declarationList.declarations) {
|
|
85
|
+
if (!d.initializer)
|
|
86
|
+
return { declarators: out, disqualified: "an exported uninitialized declaration is not foldable" };
|
|
87
|
+
if (ts.isIdentifier(d.name)) {
|
|
88
|
+
out.push({ kind: ts.isNewExpression(d.initializer) ? "resource" : "single", name: d.name.text, expr: d.initializer });
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (ts.isObjectBindingPattern(d.name)) {
|
|
92
|
+
const elements = [];
|
|
93
|
+
for (const el of d.name.elements) {
|
|
94
|
+
if (el.dotDotDotToken || el.initializer || !ts.isIdentifier(el.name)) {
|
|
95
|
+
return { declarators: out, disqualified: "an exported destructured declaration with a rest, default, or nested element is not foldable" };
|
|
96
|
+
}
|
|
97
|
+
elements.push({ key: (el.propertyName ?? el.name).text, as: el.name.text });
|
|
98
|
+
}
|
|
99
|
+
out.push({ kind: "destructure", expr: d.initializer, elements });
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
return { declarators: out, disqualified: "an exported array-destructured declaration is not foldable" };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return { declarators: out };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Index every non-primitive `f` produced, so a later file's capture of one is
|
|
109
|
+
* attributable. "Non-primitive" is F-Identity's reference test, the broad one
|
|
110
|
+
* F-Import uses: a plain object counts, and the walk does not ask whether
|
|
111
|
+
* anything inside it is live.
|
|
112
|
+
*/
|
|
113
|
+
function indexOwned(value, file, session, seen = new Set()) {
|
|
114
|
+
if (value === null || typeof value !== "object")
|
|
115
|
+
return;
|
|
116
|
+
if (seen.has(value))
|
|
117
|
+
return;
|
|
118
|
+
seen.add(value);
|
|
119
|
+
if (!session.owner.has(value))
|
|
120
|
+
session.owner.set(value, file);
|
|
121
|
+
// Recurse through plain structure only: an entity's interior belongs to the
|
|
122
|
+
// entity, and reaching into it would attribute its fields to the wrong file.
|
|
123
|
+
const proto = Object.getPrototypeOf(value);
|
|
124
|
+
if (proto !== Object.prototype && proto !== Array.prototype && proto !== null)
|
|
125
|
+
return;
|
|
126
|
+
for (const inner of Object.values(value))
|
|
127
|
+
indexOwned(inner, file, session, seen);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* F-Capture, decided over the produced namespace: which other files' objects
|
|
131
|
+
* are in `X(f)`.
|
|
132
|
+
*
|
|
133
|
+
* The walk descends through an entity's own properties as well as through
|
|
134
|
+
* plain structure, which is where `indexOwned` above stops. F-Capture asks
|
|
135
|
+
* whether some value in `X(f)` came from `X(g)`, and an object handed to a
|
|
136
|
+
* constructor is still in `X(f)` after the constructor kept it. Stopping at
|
|
137
|
+
* the entity lost the edge entirely for the ordinary case, a shared plain
|
|
138
|
+
* object passed as a resource's `labels`, and the loss was invisible until
|
|
139
|
+
* the corpus ran against a real host (#25): with no host the entity never
|
|
140
|
+
* becomes an instance, so the walk stayed inside plain objects and found the
|
|
141
|
+
* object anyway.
|
|
142
|
+
*/
|
|
143
|
+
function capturesIn(value, self, session, out, seen = new Set()) {
|
|
144
|
+
if (value === null || typeof value !== "object")
|
|
145
|
+
return;
|
|
146
|
+
if (seen.has(value))
|
|
147
|
+
return;
|
|
148
|
+
seen.add(value);
|
|
149
|
+
const from = session.owner.get(value);
|
|
150
|
+
if (from !== undefined && from !== self)
|
|
151
|
+
out.add(from);
|
|
152
|
+
for (const inner of ownData(value))
|
|
153
|
+
capturesIn(inner, self, session, out, seen);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* An object's own data properties, enumerable or not, accessors skipped.
|
|
157
|
+
*
|
|
158
|
+
* A host's entity class is free to keep what it was handed wherever it likes,
|
|
159
|
+
* and chant's keeps it on a non-enumerable `props`. `Object.values` cannot see
|
|
160
|
+
* that, so a capture walk built on it reports no capture for the ordinary case
|
|
161
|
+
* of a shared object passed to a constructor. Accessors are skipped rather
|
|
162
|
+
* than invoked: reading one can throw (chant's `AttrRef.toJSON` does, for a
|
|
163
|
+
* reference whose logical name is not yet assigned), and an accessor computes
|
|
164
|
+
* a value rather than holding one.
|
|
165
|
+
*/
|
|
166
|
+
function ownData(value) {
|
|
167
|
+
// An object held weakly is still held: an attribute reference keeps its
|
|
168
|
+
// entity behind a `WeakRef`, and the file holding the reference holds the
|
|
169
|
+
// entity for F-Capture's purposes, the same as if it held it directly.
|
|
170
|
+
if (value instanceof WeakRef) {
|
|
171
|
+
const target = value.deref();
|
|
172
|
+
return target === undefined ? [] : [target];
|
|
173
|
+
}
|
|
174
|
+
const out = [];
|
|
175
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
176
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
177
|
+
if (descriptor && "value" in descriptor)
|
|
178
|
+
out.push(descriptor.value);
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
/** Every value binding a non-type-only import clause introduces. */
|
|
183
|
+
function bindingNames(clause) {
|
|
184
|
+
const out = [];
|
|
185
|
+
if (clause.name)
|
|
186
|
+
out.push(clause.name.text);
|
|
187
|
+
const nb = clause.namedBindings;
|
|
188
|
+
if (nb && ts.isNamespaceImport(nb))
|
|
189
|
+
out.push(nb.name.text);
|
|
190
|
+
if (nb && ts.isNamedImports(nb))
|
|
191
|
+
for (const el of nb.elements)
|
|
192
|
+
if (!el.isTypeOnly)
|
|
193
|
+
out.push(el.name.text);
|
|
194
|
+
return out;
|
|
195
|
+
}
|
|
196
|
+
function verdictOf(path, session) {
|
|
197
|
+
const memo = session.memo.get(path);
|
|
198
|
+
if (memo)
|
|
199
|
+
return memo;
|
|
200
|
+
if (session.stack.includes(path)) {
|
|
201
|
+
// F-Cycle: a located error naming the cycle, not an infinite regress.
|
|
202
|
+
return { kind: "run", rule: "F-Cycle", reason: `import cycle: ${[...session.stack, path].join(" -> ")}` };
|
|
203
|
+
}
|
|
204
|
+
session.stack.push(path);
|
|
205
|
+
const v = foldFile(path, session);
|
|
206
|
+
session.stack.pop();
|
|
207
|
+
session.memo.set(path, v);
|
|
208
|
+
return v;
|
|
209
|
+
}
|
|
210
|
+
function foldFile(path, session) {
|
|
211
|
+
const source = session.files.get(path);
|
|
212
|
+
if (source === undefined)
|
|
213
|
+
return { kind: "run", rule: "F-NotProject", reason: `${path} is not project source` };
|
|
214
|
+
const sf = parse(path, source);
|
|
215
|
+
// F-Scan
|
|
216
|
+
const scan = scanExports(sf, session.host.profile === "data-host");
|
|
217
|
+
if (scan.disqualified)
|
|
218
|
+
return { kind: "run", rule: "F-Scan", reason: scan.disqualified };
|
|
219
|
+
// F-NoExports
|
|
220
|
+
if (scan.declarators.length === 0)
|
|
221
|
+
return { kind: "run", rule: "F-NoExports", reason: "no foldable resource exports" };
|
|
222
|
+
// F-Bind
|
|
223
|
+
const consts = collectConsts(sf);
|
|
224
|
+
const externals = new Map();
|
|
225
|
+
const captures = new Set();
|
|
226
|
+
const mine = [];
|
|
227
|
+
session.locals.set(path, mine);
|
|
228
|
+
/** F-Import: why a binding was left unresolved, "for diagnostics only". */
|
|
229
|
+
const unresolved = new Map();
|
|
230
|
+
// F-Import
|
|
231
|
+
for (const st of sf.statements) {
|
|
232
|
+
if (!ts.isImportDeclaration(st) || !ts.isStringLiteral(st.moduleSpecifier))
|
|
233
|
+
continue;
|
|
234
|
+
const spec = st.moduleSpecifier.text;
|
|
235
|
+
const clause = st.importClause;
|
|
236
|
+
if (!clause || clause.isTypeOnly)
|
|
237
|
+
continue;
|
|
238
|
+
if (!isProjectSpecifier(spec)) {
|
|
239
|
+
// F-Import, bare specifier: a package is never a member of F. A host-owned
|
|
240
|
+
// one still binds its REAL exports (F-Host-Trust arm 1), which is what lets
|
|
241
|
+
// revival construct anything at all (F-Val-Fate).
|
|
242
|
+
const supplied = session.host.values.get(spec);
|
|
243
|
+
if (supplied && isHostOwnedSpecifier(spec) && clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
|
|
244
|
+
for (const el of clause.namedBindings.elements) {
|
|
245
|
+
if (el.isTypeOnly)
|
|
246
|
+
continue;
|
|
247
|
+
const imported = (el.propertyName ?? el.name).text;
|
|
248
|
+
if (supplied.has(imported))
|
|
249
|
+
externals.set(el.name.text, supplied.get(imported));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
const target = resolveKey(path, spec, session.files);
|
|
255
|
+
if (!target)
|
|
256
|
+
continue;
|
|
257
|
+
const tv = verdictOf(target, session);
|
|
258
|
+
if (tv.kind !== "fold") {
|
|
259
|
+
// F-Import: the binding is not resolved, and the cause is kept for F-Reason.
|
|
260
|
+
for (const n of bindingNames(clause))
|
|
261
|
+
unresolved.set(n, { rule: tv.rule, reason: tv.reason });
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (clause.name && tv.exports.has("default")) {
|
|
265
|
+
// `import n from "./g"` binds the target's default export (S-ExportDefault, spec 1.2).
|
|
266
|
+
const value = tv.exports.get("default");
|
|
267
|
+
externals.set(clause.name.text, value);
|
|
268
|
+
if (value !== null && typeof value === "object" && !isFoldableFunction(value))
|
|
269
|
+
captures.add(target);
|
|
270
|
+
}
|
|
271
|
+
if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) {
|
|
272
|
+
// F-Namespace: a synthetic plain object of the target's entries.
|
|
273
|
+
const ns = Object.fromEntries(tv.exports);
|
|
274
|
+
externals.set(clause.namedBindings.name.text, ns);
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
|
|
278
|
+
for (const el of clause.namedBindings.elements) {
|
|
279
|
+
if (el.isTypeOnly)
|
|
280
|
+
continue;
|
|
281
|
+
const imported = (el.propertyName ?? el.name).text;
|
|
282
|
+
if (!tv.exports.has(imported))
|
|
283
|
+
continue;
|
|
284
|
+
const value = tv.exports.get(imported);
|
|
285
|
+
externals.set(el.name.text, value);
|
|
286
|
+
// F-Import: an imported value with identity is a capture at the
|
|
287
|
+
// import, by F-Identity's reference test, whether or not it reaches
|
|
288
|
+
// X(f). A project-local function is a callable, not a value, and
|
|
289
|
+
// F-CallLeak decides its edge at the call instead. The corpus found
|
|
290
|
+
// the walk over X(f) below is not enough on its own: a file that
|
|
291
|
+
// reads only primitives out of an imported object holds no object in
|
|
292
|
+
// its namespace, and chant taints it anyway, as the text says (#96).
|
|
293
|
+
if (value !== null && typeof value === "object" && !isFoldableFunction(value))
|
|
294
|
+
captures.add(target);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// F-Declarator, into X
|
|
299
|
+
const scope = { consts, externals, depth: 0, captures };
|
|
300
|
+
const evalHost = { intrinsics: session.host.intrinsics };
|
|
301
|
+
const exports = new Map();
|
|
302
|
+
/** F-Val-Fate: what the declarator produced, revived through this file's own imports. */
|
|
303
|
+
const live = (v, node, what) => {
|
|
304
|
+
const { line, character } = sf.getLineAndCharacterOfPosition(node.getStart());
|
|
305
|
+
return revive(v, externals, { line: line + 1, column: character + 1, what });
|
|
306
|
+
};
|
|
307
|
+
// F-Bind, S-LocalFunction: the file's own functions, exported or not, bound
|
|
308
|
+
// before anything can call them. The exported ones are also declarators
|
|
309
|
+
// below, and reuse the same marker so F-CallLeak's flag is one object.
|
|
310
|
+
for (const fn of collectLocalFunctions(sf, path, consts, externals)) {
|
|
311
|
+
mine.push(fn);
|
|
312
|
+
externals.set(fn.name, fn);
|
|
313
|
+
}
|
|
314
|
+
// F-Prebuild: every same-file `const n = new T(…)`, exported or not, built
|
|
315
|
+
// once in source order before any declarator reads it, and bound in
|
|
316
|
+
// `externals` where F-Eval-Ident step 1 looks. A construction that fails is
|
|
317
|
+
// skipped rather than failing the file here: the name stays unbound, a
|
|
318
|
+
// reference to it rejects under step 1, and an exported one reproduces the
|
|
319
|
+
// failure below with its own located reason. `collectConsts` yields source
|
|
320
|
+
// order, so a later construction sees an earlier one (#68).
|
|
321
|
+
const prebuilt = new Map();
|
|
322
|
+
for (const [name, init] of consts) {
|
|
323
|
+
if (!ts.isNewExpression(init))
|
|
324
|
+
continue;
|
|
325
|
+
try {
|
|
326
|
+
const instance = live(foldExpr(init, scope, evalHost), init, name);
|
|
327
|
+
prebuilt.set(init, instance);
|
|
328
|
+
externals.set(name, instance);
|
|
329
|
+
}
|
|
330
|
+
catch (e) {
|
|
331
|
+
if (!(e instanceof FoldRejection))
|
|
332
|
+
throw e;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
for (const d of scan.declarators) {
|
|
336
|
+
try {
|
|
337
|
+
if (d.kind === "resource") {
|
|
338
|
+
// F-Count: the instance F-Prebuild built for this initializer is the
|
|
339
|
+
// one exported; a second construction would be a second entity.
|
|
340
|
+
exports.set(d.name, prebuilt.has(d.expr) ? prebuilt.get(d.expr) : live(foldExpr(d.expr, scope, evalHost), d.expr, d.name));
|
|
341
|
+
}
|
|
342
|
+
else if (d.kind === "single") {
|
|
343
|
+
exports.set(d.name, live(foldExpr(d.expr, scope, evalHost), d.expr, d.name));
|
|
344
|
+
}
|
|
345
|
+
else if (d.kind === "destructure") {
|
|
346
|
+
const base = live(foldExpr(d.expr, scope, evalHost), d.expr, "a destructured declaration");
|
|
347
|
+
if (base === null || typeof base !== "object") {
|
|
348
|
+
return { kind: "run", rule: "F-Declarator", reason: "destructured source is not an object" };
|
|
349
|
+
}
|
|
350
|
+
for (const el of d.elements)
|
|
351
|
+
exports.set(el.as, base[el.key]);
|
|
352
|
+
}
|
|
353
|
+
else if (d.kind === "named-export") {
|
|
354
|
+
for (const el of d.elements) {
|
|
355
|
+
const init = consts.get(el.local);
|
|
356
|
+
// Through F-Eval-Ident, never by re-folding the initializer: a name
|
|
357
|
+
// bound to a same-file `new` reads F-Prebuild's instance, and a
|
|
358
|
+
// failed one reproduces step 1's rejection rather than building a
|
|
359
|
+
// second entity here.
|
|
360
|
+
const v = init && ts.isNewExpression(init)
|
|
361
|
+
? prebuilt.has(init)
|
|
362
|
+
? prebuilt.get(init)
|
|
363
|
+
: live(foldExpr(init, scope, evalHost), init, el.as)
|
|
364
|
+
: init
|
|
365
|
+
? live(foldExpr(init, scope, evalHost), init, el.as)
|
|
366
|
+
: externals.get(el.local);
|
|
367
|
+
if (v === undefined && !consts.has(el.local) && !externals.has(el.local)) {
|
|
368
|
+
return { kind: "run", rule: "F-Reference", reason: `unresolved identifier: ${el.local}` };
|
|
369
|
+
}
|
|
370
|
+
exports.set(el.as, v);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else if (d.kind === "re-export") {
|
|
374
|
+
const target = resolveKey(path, d.specifier, session.files);
|
|
375
|
+
if (!target)
|
|
376
|
+
return { kind: "run", rule: "F-Import", reason: `cannot resolve re-export from ${d.specifier}` };
|
|
377
|
+
const tv = verdictOf(target, session);
|
|
378
|
+
if (tv.kind !== "fold")
|
|
379
|
+
return { kind: "run", rule: "F-Import", reason: `re-export source ${target} falls back to run` };
|
|
380
|
+
// A re-export is a capture, and the owner index below records it as one.
|
|
381
|
+
for (const el of d.elements)
|
|
382
|
+
exports.set(el.as, tv.exports.get(el.imported));
|
|
383
|
+
}
|
|
384
|
+
else if (d.kind === "function") {
|
|
385
|
+
exports.set(d.name, externals.get(d.name));
|
|
386
|
+
}
|
|
387
|
+
else if (d.kind === "default") {
|
|
388
|
+
exports.set("default", live(foldExpr(d.expr, scope, evalHost), d.expr, "default"));
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
catch (e) {
|
|
392
|
+
// F-Total: one failed declarator is a failure of the whole file. F-Reason.
|
|
393
|
+
if (e instanceof FoldRejection) {
|
|
394
|
+
// F-Reason: an unresolved identifier that came from an unresolved import
|
|
395
|
+
// reports the import's own cause, not just the bare name.
|
|
396
|
+
const name = /unresolved identifier: (\w+)$/.exec(e.message)?.[1];
|
|
397
|
+
const cause = name ? unresolved.get(name) : undefined;
|
|
398
|
+
if (cause) {
|
|
399
|
+
const rule = cause.rule === "F-Cycle" ? "F-Cycle" : "F-Import";
|
|
400
|
+
return { kind: "run", rule, reason: `${e.message} (its module falls back to run: ${cause.reason})` };
|
|
401
|
+
}
|
|
402
|
+
return { kind: "run", rule: e.rule, reason: e.message };
|
|
403
|
+
}
|
|
404
|
+
throw e;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// F-Capture over X(f). F-CallLeak has already put its own edges in `captures`.
|
|
408
|
+
for (const v of exports.values())
|
|
409
|
+
capturesIn(v, path, session, captures);
|
|
410
|
+
for (const v of exports.values())
|
|
411
|
+
indexOwned(v, path, session);
|
|
412
|
+
return { kind: "fold", exports, captures };
|
|
413
|
+
}
|
|
414
|
+
export function foldProject(files, host = EMPTY_HOST) {
|
|
415
|
+
registerHelpers(host.helpers);
|
|
416
|
+
registerHostSpecifiers(host.ownedSpecifierPrefixes);
|
|
417
|
+
const session = { files, host, memo: new Map(), stack: [], locals: new Map(), owner: new Map() };
|
|
418
|
+
const tentative = new Map();
|
|
419
|
+
for (const path of files.keys())
|
|
420
|
+
tentative.set(path, verdictOf(path, session));
|
|
421
|
+
// Edges. Forward: f imports g. Backward: c captured from f.
|
|
422
|
+
const imports = new Map();
|
|
423
|
+
for (const [path, source] of files) {
|
|
424
|
+
const set = new Set();
|
|
425
|
+
for (const st of parse(path, source).statements) {
|
|
426
|
+
const spec = (ts.isImportDeclaration(st) || ts.isExportDeclaration(st)) && st.moduleSpecifier && ts.isStringLiteral(st.moduleSpecifier)
|
|
427
|
+
? st.moduleSpecifier.text
|
|
428
|
+
: undefined;
|
|
429
|
+
if (!spec || !isProjectSpecifier(spec))
|
|
430
|
+
continue;
|
|
431
|
+
const target = resolveKey(path, spec, files);
|
|
432
|
+
if (target)
|
|
433
|
+
set.add(target);
|
|
434
|
+
}
|
|
435
|
+
imports.set(path, set);
|
|
436
|
+
}
|
|
437
|
+
// F-Succ. Both directions from one tainted file.
|
|
438
|
+
const succ = new Map();
|
|
439
|
+
const add = (from, to) => {
|
|
440
|
+
if (!succ.has(from))
|
|
441
|
+
succ.set(from, new Set());
|
|
442
|
+
succ.get(from).add(to);
|
|
443
|
+
};
|
|
444
|
+
for (const [f, gs] of imports)
|
|
445
|
+
for (const g of gs)
|
|
446
|
+
add(f, g); // forward: f taints what it imports
|
|
447
|
+
for (const [c, v] of tentative) {
|
|
448
|
+
if (v.kind !== "fold")
|
|
449
|
+
continue;
|
|
450
|
+
for (const source of v.captures)
|
|
451
|
+
add(source, c); // backward: the captured source taints the capturer
|
|
452
|
+
}
|
|
453
|
+
// F-Seed, F-Taint, F-Fix: least fixpoint by worklist over a finite set.
|
|
454
|
+
const tainted = new Set([...tentative].filter(([, v]) => v.kind !== "fold").map(([p]) => p));
|
|
455
|
+
const reason = new Map();
|
|
456
|
+
const source = new Map();
|
|
457
|
+
const queue = [...tainted];
|
|
458
|
+
while (queue.length > 0) {
|
|
459
|
+
const current = queue.shift();
|
|
460
|
+
for (const next of succ.get(current) ?? []) {
|
|
461
|
+
if (tainted.has(next))
|
|
462
|
+
continue;
|
|
463
|
+
tainted.add(next);
|
|
464
|
+
source.set(next, current);
|
|
465
|
+
// F-Reason for a taint: name the edge that fired. The forward edge is the
|
|
466
|
+
// one a reader can see in the file's own imports; the backward edge is the
|
|
467
|
+
// one nothing in the file predicts, so it has to be spelled out.
|
|
468
|
+
reason.set(next, imports.get(current)?.has(next)
|
|
469
|
+
? `would fold in isolation, but ${current}, which imports it, falls back to run`
|
|
470
|
+
: `would fold in isolation, but it captured objects from ${current}, which falls back to run`);
|
|
471
|
+
queue.push(next);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// F-Verdict
|
|
475
|
+
const verdicts = new Map();
|
|
476
|
+
for (const [path, v] of tentative) {
|
|
477
|
+
verdicts.set(path, tainted.has(path) && v.kind === "fold" ? { kind: "run", rule: "F-Taint", reason: reason.get(path) ?? "tainted" } : v);
|
|
478
|
+
}
|
|
479
|
+
return { verdicts, tentative, taintReason: reason, taintSource: source };
|
|
480
|
+
}
|
|
481
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
|
package/dist/revive.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Where a revival happened, for the located rejection F-Reason wants. */
|
|
2
|
+
export interface RevivalSite {
|
|
3
|
+
readonly line: number;
|
|
4
|
+
readonly column: number;
|
|
5
|
+
/** The declarator or call this tree came from, for the message. */
|
|
6
|
+
readonly what: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* @param bindings the folding file's resolved names, `externals`. A host-owned
|
|
10
|
+
* import puts the real value here (F-Import, F-Host-Trust arm 1), which is
|
|
11
|
+
* what makes revival possible at all.
|
|
12
|
+
* @param inHostArgs true inside an intrinsic's or helper's arguments, where
|
|
13
|
+
* F-Val-Position rejects an `{__attrRef}` instead of passing it through.
|
|
14
|
+
*/
|
|
15
|
+
export declare function revive(value: unknown, bindings: ReadonlyMap<string, unknown>, site: RevivalSite, inHostArgs?: boolean): unknown;
|
|
16
|
+
//# sourceMappingURL=revive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revive.d.ts","sourceRoot":"","sources":["../src/revive.ts"],"names":[],"mappings":"AAiBA,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAMD;;;;;;GAMG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,IAAI,EAAE,WAAW,EACjB,UAAU,UAAQ,GACjB,OAAO,CAsBT"}
|
package/dist/revive.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F-Val-Fate: revival. A folded tree holds envelopes, values that *denote*
|
|
3
|
+
* something not yet constructed; revival walks the tree and replaces each one
|
|
4
|
+
* by resolving its name through the folding file's own imports and invoking
|
|
5
|
+
* the real constructor or function the host supplies (#61).
|
|
6
|
+
*
|
|
7
|
+
* Written from `spec/values.md`. Five of the six envelope kinds are here.
|
|
8
|
+
* `__compositeStep` is not: its fate is "resolve the composite (J2 F-Call),
|
|
9
|
+
* then read `.step` off the real result", and this implementation has no
|
|
10
|
+
* composite factory form, so it rejects rather than guessing. See CAVEATS.md.
|
|
11
|
+
*
|
|
12
|
+
* Revival is J2's step, not J1's. `foldExpr` yields envelopes and that is the
|
|
13
|
+
* answer the expression fixtures compare; `F-Declarator` revives what the
|
|
14
|
+
* declarator produced.
|
|
15
|
+
*/
|
|
16
|
+
import { FoldRejection, isEnvelope, isLiveObject } from "./fold.js";
|
|
17
|
+
const DOTTED = /^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/;
|
|
18
|
+
/**
|
|
19
|
+
* @param bindings the folding file's resolved names, `externals`. A host-owned
|
|
20
|
+
* import puts the real value here (F-Import, F-Host-Trust arm 1), which is
|
|
21
|
+
* what makes revival possible at all.
|
|
22
|
+
* @param inHostArgs true inside an intrinsic's or helper's arguments, where
|
|
23
|
+
* F-Val-Position rejects an `{__attrRef}` instead of passing it through.
|
|
24
|
+
*/
|
|
25
|
+
export function revive(value, bindings, site, inHostArgs = false) {
|
|
26
|
+
if (value === null || typeof value !== "object")
|
|
27
|
+
return value;
|
|
28
|
+
// F-Val-Live: a live object passes through unchanged, never rebuilt.
|
|
29
|
+
if (isLiveObject(value))
|
|
30
|
+
return value;
|
|
31
|
+
// A structure with no envelope anywhere inside is already final, and is
|
|
32
|
+
// returned AS IS rather than rebuilt. F-Memo requires every reference to
|
|
33
|
+
// X(g) to be the same object; a rebuilt copy would make F-Capture record an
|
|
34
|
+
// edge to a copy and the judgment vacuous.
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
const next = value.map((v) => revive(v, bindings, site, inHostArgs));
|
|
37
|
+
return next.every((v, i) => v === value[i]) ? value : next;
|
|
38
|
+
}
|
|
39
|
+
if (!isEnvelope(value)) {
|
|
40
|
+
const out = {};
|
|
41
|
+
let changed = false;
|
|
42
|
+
for (const [k, v] of Object.entries(value)) {
|
|
43
|
+
out[k] = revive(v, bindings, site, inHostArgs);
|
|
44
|
+
if (out[k] !== v)
|
|
45
|
+
changed = true;
|
|
46
|
+
}
|
|
47
|
+
return changed ? out : value;
|
|
48
|
+
}
|
|
49
|
+
return reviveEnvelope(value, bindings, site, inHostArgs);
|
|
50
|
+
}
|
|
51
|
+
function fail(site, message) {
|
|
52
|
+
throw new FoldRejection("F-Val-Fate", site.line, site.column, `${site.what}: ${message}`);
|
|
53
|
+
}
|
|
54
|
+
function resolve(name, bindings, site) {
|
|
55
|
+
if (!bindings.has(name))
|
|
56
|
+
fail(site, `revival cannot resolve ${name}; the folding file does not import it from the host`);
|
|
57
|
+
return bindings.get(name);
|
|
58
|
+
}
|
|
59
|
+
function callable(name, bindings, site) {
|
|
60
|
+
const v = resolve(name, bindings, site);
|
|
61
|
+
if (typeof v !== "function")
|
|
62
|
+
fail(site, `${name} resolves to ${typeof v}, which revival cannot invoke`);
|
|
63
|
+
return v;
|
|
64
|
+
}
|
|
65
|
+
function reviveEnvelope(e, bindings, site, inHostArgs) {
|
|
66
|
+
// `__attrRef` is the one envelope that survives, except inside host arguments.
|
|
67
|
+
if ("__attrRef" in e) {
|
|
68
|
+
if (inHostArgs) {
|
|
69
|
+
const { entity, attribute } = e.__attrRef;
|
|
70
|
+
fail(site, `an attribute reference (${entity}.${attribute}) inside a host call's arguments is rejected, not revived (F-Val-Position)`);
|
|
71
|
+
}
|
|
72
|
+
return e;
|
|
73
|
+
}
|
|
74
|
+
const args = (a) => a.map((x) => revive(x, bindings, site, true));
|
|
75
|
+
if ("__resource" in e) {
|
|
76
|
+
const name = e.__resource;
|
|
77
|
+
const C = callable(name, bindings, site);
|
|
78
|
+
// F-Val-Arity: spread `args` when present, otherwise props and optional attributes.
|
|
79
|
+
if (Array.isArray(e.args))
|
|
80
|
+
return new C(...e.args.map((x) => revive(x, bindings, site, false)));
|
|
81
|
+
const props = revive(e.props, bindings, site, false);
|
|
82
|
+
return "attributes" in e ? new C(props, revive(e.attributes, bindings, site, false)) : new C(props);
|
|
83
|
+
}
|
|
84
|
+
if ("__intrinsic" in e) {
|
|
85
|
+
const fn = callable(e.__intrinsic, bindings, site);
|
|
86
|
+
// The tag form keeps its cooked strings; the call form is a plain call.
|
|
87
|
+
if (Array.isArray(e.strings))
|
|
88
|
+
return fn(e.strings, ...args(e.values));
|
|
89
|
+
return fn(...args(e.args));
|
|
90
|
+
}
|
|
91
|
+
if ("__helper" in e)
|
|
92
|
+
return callable(e.__helper, bindings, site)(...args(e.args));
|
|
93
|
+
if ("__symbol" in e) {
|
|
94
|
+
const text = e.__symbol;
|
|
95
|
+
if (!DOTTED.test(text))
|
|
96
|
+
fail(site, `a symbolic reference revives only through a simple dotted chain, and "${text}" is not one`);
|
|
97
|
+
const [root, ...rest] = text.split(".");
|
|
98
|
+
let current = resolve(root, bindings, site);
|
|
99
|
+
for (const step of rest) {
|
|
100
|
+
if (current === null || current === undefined)
|
|
101
|
+
fail(site, `revival of "${text}" read "${step}" on ${String(current)}`);
|
|
102
|
+
current = current[step];
|
|
103
|
+
}
|
|
104
|
+
return current;
|
|
105
|
+
}
|
|
106
|
+
// __compositeStep
|
|
107
|
+
fail(site, "a composite step envelope needs a composite factory form, which this implementation does not have");
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=revive.js.map
|