supercov 0.0.42 → 0.0.44
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 +23 -3
- package/analyzers/typescript/README.md +59 -0
- package/analyzers/typescript/bin/compiler-identity.mjs +78 -0
- package/analyzers/typescript/bin/identity.mjs +71 -0
- package/analyzers/typescript/bin/query.mjs +29 -0
- package/analyzers/typescript/dist/analyze.js +5273 -0
- package/analyzers/typescript/dist/archive.js +337 -0
- package/analyzers/typescript/dist/awaited-observations.js +376 -0
- package/analyzers/typescript/dist/build-identity.json +1 -0
- package/analyzers/typescript/dist/compiler.js +32 -0
- package/analyzers/typescript/dist/frontend.js +75 -0
- package/analyzers/typescript/dist/mock-counts.js +2517 -0
- package/analyzers/typescript/dist/native-frontend.js +271 -0
- package/analyzers/typescript/dist/pragmas.js +186 -0
- package/analyzers/typescript/dist/types.js +1 -0
- package/analyzers/typescript/package.json +27 -0
- package/analyzers/typescript/src/analyze.ts +6180 -0
- package/analyzers/typescript/src/archive.ts +471 -0
- package/analyzers/typescript/src/awaited-observations.ts +561 -0
- package/analyzers/typescript/src/compiler.ts +49 -0
- package/analyzers/typescript/src/frontend.ts +136 -0
- package/analyzers/typescript/src/mock-counts.ts +3219 -0
- package/analyzers/typescript/src/native-frontend.ts +315 -0
- package/analyzers/typescript/src/pragmas.ts +284 -0
- package/analyzers/typescript/src/types.ts +45 -0
- package/analyzers/typescript/tsconfig.json +12 -0
- package/docs/agent-loop.md +129 -31
- package/docs/assertion-evidence.md +694 -0
- package/docs/cli.md +25 -15
- package/docs/code-verification.md +4 -0
- package/docs/coverage-model.md +6 -6
- package/docs/evidence.md +6 -6
- package/docs/getting-started.md +60 -72
- package/docs/performance.md +4 -4
- package/docs/supported-suites.md +40 -9
- package/docs/troubleshooting.md +8 -8
- package/docs/verification.md +14 -2
- package/docs/workspace-isolation.md +1 -1
- package/package.json +35 -15
- package/runtime/javascript/jest.cjs +134 -0
- package/runtime/javascript/jest.config.mjs +39 -0
- package/runtime/javascript/jestReporter.mjs +77 -0
- package/runtime/javascript/nodeAssertAdapter.mjs +32 -8
- package/runtime/javascript/nodeTest.mjs +13 -5
- package/runtime/javascript/register.mjs +22 -4
- package/runtime/javascript/runnerEvidence.mjs +33 -11
- package/runtime/javascript/runtime.mjs +73 -16
|
@@ -144,6 +144,12 @@ function createState() {
|
|
|
144
144
|
decisions: /* @__PURE__ */ new Map(),
|
|
145
145
|
hits: /* @__PURE__ */ new Set(),
|
|
146
146
|
events: [],
|
|
147
|
+
// Position of the test-file statement currently executing ("file:line:column"), set by the
|
|
148
|
+
// instrumented test module; production hits recorded meanwhile are attributed to it.
|
|
149
|
+
testStatement: void 0,
|
|
150
|
+
// Per value-position logical expression (`a && b`, `a || b`, `a ?? b`): the distinct
|
|
151
|
+
// (right operand evaluated?, result truthy?) pairs seen, keyed by branch id.
|
|
152
|
+
logicals: /* @__PURE__ */ new Map(),
|
|
147
153
|
eventKeys: /* @__PURE__ */ new Set(),
|
|
148
154
|
bufferedAttempts: /* @__PURE__ */ new Set(),
|
|
149
155
|
serverBuffers: /* @__PURE__ */ new Map(),
|
|
@@ -293,17 +299,26 @@ function decisionSnapshot() {
|
|
|
293
299
|
vectors: [...decision.vectors.values()]
|
|
294
300
|
}));
|
|
295
301
|
}
|
|
302
|
+
function logicalSnapshot() {
|
|
303
|
+
return [...state.logicals.entries()].map(([id, vectors]) => ({
|
|
304
|
+
id,
|
|
305
|
+
vectors: [...vectors.values()]
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
296
308
|
function coverageSnapshot() {
|
|
297
309
|
return {
|
|
298
310
|
decisions: decisionSnapshot(),
|
|
299
311
|
hits: [...state.hits],
|
|
300
|
-
events: state.events
|
|
312
|
+
events: state.events,
|
|
313
|
+
logicals: logicalSnapshot()
|
|
301
314
|
};
|
|
302
315
|
}
|
|
303
316
|
function resetCoverage(testId2) {
|
|
304
317
|
state.decisions.clear();
|
|
305
318
|
state.hits.clear();
|
|
306
319
|
state.events.length = 0;
|
|
320
|
+
state.testStatement = void 0;
|
|
321
|
+
state.logicals.clear();
|
|
307
322
|
state.eventKeys.clear();
|
|
308
323
|
state.probeV2ContextEpochs.clear();
|
|
309
324
|
activateProbeV2Key(`reset\0${state.probeV2NextEpoch}`, true);
|
|
@@ -604,21 +619,22 @@ function appendServer(record) {
|
|
|
604
619
|
var _a8, _b, _c, _d;
|
|
605
620
|
if (state.runtimeSnapshots) {
|
|
606
621
|
const timestampMs = (_a8 = record.timestampMs) != null ? _a8 : Date.now();
|
|
622
|
+
const statement = record.statementId ? { statementId: record.statementId } : {};
|
|
607
623
|
if (record.type === "decision") {
|
|
608
|
-
recordBrowserEvent(__spreadProps(__spreadValues({
|
|
624
|
+
recordBrowserEvent(__spreadProps(__spreadValues(__spreadValues({
|
|
609
625
|
type: "decision",
|
|
610
626
|
id: record.meta.id,
|
|
611
627
|
vector: record.vector,
|
|
612
628
|
timestampMs
|
|
613
|
-
}, record.phaseId ? { phaseId: record.phaseId } : {}), {
|
|
629
|
+
}, record.phaseId ? { phaseId: record.phaseId } : {}), statement), {
|
|
614
630
|
environment: "server"
|
|
615
631
|
}));
|
|
616
632
|
} else {
|
|
617
|
-
recordBrowserEvent(__spreadProps(__spreadValues({
|
|
633
|
+
recordBrowserEvent(__spreadProps(__spreadValues(__spreadValues({
|
|
618
634
|
type: "hit",
|
|
619
635
|
id: record.id,
|
|
620
636
|
timestampMs
|
|
621
|
-
}, record.phaseId ? { phaseId: record.phaseId } : {}), {
|
|
637
|
+
}, record.phaseId ? { phaseId: record.phaseId } : {}), statement), {
|
|
622
638
|
environment: "server"
|
|
623
639
|
}));
|
|
624
640
|
}
|
|
@@ -705,9 +721,11 @@ function withCoverageCarrier(carrier, callback) {
|
|
|
705
721
|
function assertionPhaseState(scope) {
|
|
706
722
|
const key = attemptKey(scope);
|
|
707
723
|
const existing = state.assertionPhases.get(key);
|
|
708
|
-
if (existing)
|
|
724
|
+
if (existing) {
|
|
725
|
+
existing.phaseIds ??= new Set(existing.phases.filter(phase => phase.kind === "assertion").map(phase => phase.id));
|
|
709
726
|
return existing;
|
|
710
|
-
|
|
727
|
+
}
|
|
728
|
+
const created = { counter: 0, phases: [], phaseIds: new Set() };
|
|
711
729
|
state.assertionPhases.set(key, created);
|
|
712
730
|
return created;
|
|
713
731
|
}
|
|
@@ -737,9 +755,13 @@ function withNodeAssertionPhase(operation, source, callback) {
|
|
|
737
755
|
const scope = context.scope;
|
|
738
756
|
if (!scope)
|
|
739
757
|
return callback();
|
|
740
|
-
const existing = context.phaseId
|
|
758
|
+
const existing = context.phaseId && assertionPhaseState(scope).phaseIds.has(context.phaseId);
|
|
741
759
|
if (existing)
|
|
742
760
|
return callback();
|
|
761
|
+
// The adapter's stack is only a fallback. Avoid formatting it when a lexical
|
|
762
|
+
// probe already supplied the active phase's exact original-source identity.
|
|
763
|
+
if (typeof source === "function")
|
|
764
|
+
source = source();
|
|
743
765
|
const bridged = (_a8 = runtimeGlobal.__SUPERCOV_ASSERTION_PHASE_BRIDGE__) == null ? void 0 : _a8.call(runtimeGlobal, operation, source, callback);
|
|
744
766
|
if (bridged == null ? void 0 : bridged.handled)
|
|
745
767
|
return bridged.value;
|
|
@@ -752,6 +774,7 @@ function withNodeAssertionPhase(operation, source, callback) {
|
|
|
752
774
|
startedAtMs: Date.now()
|
|
753
775
|
});
|
|
754
776
|
attempt.phases.push(phase);
|
|
777
|
+
attempt.phaseIds.add(phase.id);
|
|
755
778
|
try {
|
|
756
779
|
const result = withCoverageCarrier({ version: 1, scope, phaseId: phase.id }, callback);
|
|
757
780
|
if (result && typeof result.then === "function")
|
|
@@ -769,6 +792,16 @@ function withNodeAssertionPhase(operation, source, callback) {
|
|
|
769
792
|
throw cleanInstrumentationStack(error);
|
|
770
793
|
}
|
|
771
794
|
}
|
|
795
|
+
// Resolve the target exactly once, before argument evaluation, just like a
|
|
796
|
+
// native call reference. The closure carries only source identity and receiver;
|
|
797
|
+
// it never captures an assertion phase or mutable current-statement state across
|
|
798
|
+
// await. Rejected arguments therefore create no phase, and awaited producer work
|
|
799
|
+
// is not retroactively attributed to the assertion invocation.
|
|
800
|
+
function bindNodeAssertion(operation, source, receiver, method) {
|
|
801
|
+
const target = method === void 0 ? receiver : receiver[method];
|
|
802
|
+
const thisArgument = method === void 0 ? void 0 : receiver;
|
|
803
|
+
return (...args) => withNodeAssertionPhase(operation, source, () => Reflect.apply(target, thisArgument, args));
|
|
804
|
+
}
|
|
772
805
|
function takeNodeAssertionPhases(scope) {
|
|
773
806
|
var _a8, _b;
|
|
774
807
|
const key = attemptKey(scope);
|
|
@@ -962,25 +995,31 @@ function recordBrowserEvent(event) {
|
|
|
962
995
|
state.events.push(event);
|
|
963
996
|
return true;
|
|
964
997
|
}
|
|
998
|
+
function testStatement(source) {
|
|
999
|
+
state.testStatement = typeof source === "string" && source.length > 0 ? source : void 0;
|
|
1000
|
+
}
|
|
1001
|
+
function statementFields() {
|
|
1002
|
+
return state.testStatement ? { statementId: state.testStatement } : {};
|
|
1003
|
+
}
|
|
965
1004
|
function coverageHit(id) {
|
|
966
1005
|
state.hits.add(id);
|
|
967
1006
|
const timestampMs = Date.now();
|
|
968
1007
|
const phaseId = currentPhaseId();
|
|
969
1008
|
if (isBrowser) {
|
|
970
|
-
if (recordBrowserEvent(__spreadProps(__spreadValues({
|
|
1009
|
+
if (recordBrowserEvent(__spreadProps(__spreadValues(__spreadValues({
|
|
971
1010
|
type: "hit",
|
|
972
1011
|
id,
|
|
973
1012
|
timestampMs
|
|
974
|
-
}, phaseId ? { phaseId } : {}), {
|
|
1013
|
+
}, phaseId ? { phaseId } : {}), statementFields()), {
|
|
975
1014
|
environment: "browser"
|
|
976
1015
|
})))
|
|
977
1016
|
persistBrowser();
|
|
978
1017
|
} else {
|
|
979
|
-
appendServer(__spreadValues({
|
|
1018
|
+
appendServer(__spreadValues(__spreadValues({
|
|
980
1019
|
type: "hit",
|
|
981
1020
|
id,
|
|
982
1021
|
timestampMs
|
|
983
|
-
}, phaseId ? { phaseId } : {}));
|
|
1022
|
+
}, phaseId ? { phaseId } : {}), statementFields()));
|
|
984
1023
|
}
|
|
985
1024
|
}
|
|
986
1025
|
function registerProbeV2(definition) {
|
|
@@ -1113,6 +1152,20 @@ function selectionRight(frame, value, inferredName) {
|
|
|
1113
1152
|
}
|
|
1114
1153
|
function selectionEnd(frame, value) {
|
|
1115
1154
|
coverageHit(frame.rightEvaluated ? frame.rightId : frame.shortId);
|
|
1155
|
+
// Per-operand outcomes for the verifier: which side was selected and whether the result is
|
|
1156
|
+
// truthy. With the operator (known from the manifest) this gives each operand's outcome.
|
|
1157
|
+
const separator = frame.shortId.lastIndexOf(":");
|
|
1158
|
+
if (separator > 0) {
|
|
1159
|
+
const branchId = frame.shortId.slice(0, separator);
|
|
1160
|
+
const right = frame.rightEvaluated;
|
|
1161
|
+
const truthy = Boolean(value);
|
|
1162
|
+
let vectors = state.logicals.get(branchId);
|
|
1163
|
+
if (!vectors) {
|
|
1164
|
+
vectors = /* @__PURE__ */ new Map();
|
|
1165
|
+
state.logicals.set(branchId, vectors);
|
|
1166
|
+
}
|
|
1167
|
+
vectors.set(`${right ? "R" : "S"}${truthy ? "T" : "F"}`, { right, truthy });
|
|
1168
|
+
}
|
|
1116
1169
|
return value;
|
|
1117
1170
|
}
|
|
1118
1171
|
function optionalSelect(shortId, continuedId, value) {
|
|
@@ -1201,22 +1254,22 @@ function mcdcEnd(frame, value) {
|
|
|
1201
1254
|
const timestampMs = Date.now();
|
|
1202
1255
|
const phaseId = currentPhaseId();
|
|
1203
1256
|
if (isBrowser) {
|
|
1204
|
-
if (recordBrowserEvent(__spreadProps(__spreadValues({
|
|
1257
|
+
if (recordBrowserEvent(__spreadProps(__spreadValues(__spreadValues({
|
|
1205
1258
|
type: "decision",
|
|
1206
1259
|
id: decision.meta.id,
|
|
1207
1260
|
vector,
|
|
1208
1261
|
timestampMs
|
|
1209
|
-
}, phaseId ? { phaseId } : {}), {
|
|
1262
|
+
}, phaseId ? { phaseId } : {}), statementFields()), {
|
|
1210
1263
|
environment: "browser"
|
|
1211
1264
|
})))
|
|
1212
1265
|
persistBrowser();
|
|
1213
1266
|
} else {
|
|
1214
|
-
appendServer(__spreadValues({
|
|
1267
|
+
appendServer(__spreadValues(__spreadValues({
|
|
1215
1268
|
type: "decision",
|
|
1216
1269
|
meta: decision.meta,
|
|
1217
1270
|
vector,
|
|
1218
1271
|
timestampMs
|
|
1219
|
-
}, phaseId ? { phaseId } : {}));
|
|
1272
|
+
}, phaseId ? { phaseId } : {}), statementFields()));
|
|
1220
1273
|
}
|
|
1221
1274
|
return value;
|
|
1222
1275
|
}
|
|
@@ -1257,6 +1310,8 @@ const directRuntimeApi = {
|
|
|
1257
1310
|
selectionEnd,
|
|
1258
1311
|
selectionRight,
|
|
1259
1312
|
takeNodeAssertionPhases,
|
|
1313
|
+
bindNodeAssertion,
|
|
1314
|
+
testStatement,
|
|
1260
1315
|
tryBegin,
|
|
1261
1316
|
tryCatch,
|
|
1262
1317
|
tryEnd,
|
|
@@ -1306,6 +1361,8 @@ export {
|
|
|
1306
1361
|
selectionEnd,
|
|
1307
1362
|
selectionRight,
|
|
1308
1363
|
takeNodeAssertionPhases,
|
|
1364
|
+
bindNodeAssertion,
|
|
1365
|
+
testStatement,
|
|
1309
1366
|
tryBegin,
|
|
1310
1367
|
tryCatch,
|
|
1311
1368
|
tryEnd,
|