supercov 4.11.0 → 4.12.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/docs/cli.md
CHANGED
|
@@ -349,6 +349,19 @@ same run:
|
|
|
349
349
|
|
|
350
350
|
## Export for other tools
|
|
351
351
|
|
|
352
|
+
Every obligation a run left uncovered, one JSON object per line:
|
|
353
|
+
|
|
354
|
+
```sh supercov-example
|
|
355
|
+
npx supercov runs latest gaps --format jsonl --metric mcdc --output gaps.jsonl
|
|
356
|
+
npx supercov runs latest gaps --format jsonl > gaps.jsonl
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Each line holds the file, the line, the source of that line and what `runs
|
|
360
|
+
<id> file` says of the obligation: for an MC/DC condition its decision, the
|
|
361
|
+
condition and the vectors observed. `--metric`, `--filter`, `--kind` and
|
|
362
|
+
`--runner` narrow it as they narrow `gaps`, and nothing is paged, so a tool or
|
|
363
|
+
an agent reads a run's every gap in one pass instead of a page at a time.
|
|
364
|
+
|
|
352
365
|
```sh supercov-example
|
|
353
366
|
npx supercov runs report --format lcov --output coverage/lcov.info
|
|
354
367
|
npx supercov runs report --format cobertura --output coverage/cobertura.xml
|
|
@@ -468,6 +481,20 @@ The same filters can focus a comparison:
|
|
|
468
481
|
npx supercov diff <older-run> <newer-run> --kind e2e
|
|
469
482
|
```
|
|
470
483
|
|
|
484
|
+
To see what a new test covered that the suite did not, measure it alone and
|
|
485
|
+
compare it with the suite's run, keeping only what it gained:
|
|
486
|
+
|
|
487
|
+
```sh supercov-example
|
|
488
|
+
npx supercov -- <the new test alone>
|
|
489
|
+
npx supercov diff <suite-run> latest --gained
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
A test run alone covers far less than the suite, so a plain `diff` of the two
|
|
493
|
+
lists nearly everything as lost. `--gained` lists only the lines, branches and
|
|
494
|
+
MC/DC conditions the newer run covers and the older does not, which is how to
|
|
495
|
+
check that a test reached the conditions it was written for without measuring
|
|
496
|
+
the whole suite. In `--json`, `gainedOnly` is `true` and `lost` is empty.
|
|
497
|
+
|
|
471
498
|
## Generate a portable HTML report
|
|
472
499
|
|
|
473
500
|
```sh
|
|
@@ -533,6 +560,16 @@ A source file
|
|
|
533
560
|
added since the run is outside every test's record; the working-tree check
|
|
534
561
|
says so, and the suite should run in full.
|
|
535
562
|
|
|
563
|
+
A server the suite starts is recorded too: a mock server `webServer` starts,
|
|
564
|
+
or the application's own. Each Node process of a Playwright run notes the
|
|
565
|
+
project files it loads and reads, and the tests it serves, by the test a
|
|
566
|
+
request names or, for one that names none (a webhook), the test running
|
|
567
|
+
then. A change to a file such a process loaded or read, a mock's code, a
|
|
568
|
+
helper it imports or the data it reads, affects the tests it served and no
|
|
569
|
+
others. A mock keeps its state between tests, so a mock's files count whole,
|
|
570
|
+
not route by route; a file the application's server loaded, a preload of its
|
|
571
|
+
own, affects every test it served.
|
|
572
|
+
|
|
536
573
|
### Which affected tests check the change
|
|
537
574
|
|
|
538
575
|
When the run has an [assertion assessment](assertions.md), `tests affected`
|
|
@@ -655,6 +692,19 @@ A run left out is named with the files and the functions that changed. The
|
|
|
655
692
|
merged run lists what differed and why it does not reach the earlier runs:
|
|
656
693
|
`merged across:` in `runs <id>`, and `mergedAcross` in JSON.
|
|
657
694
|
|
|
695
|
+
A changed file that a server the run's tests reached loaded or read (see
|
|
696
|
+
[Find the tests a change affects](#find-the-tests-a-change-affects)) takes
|
|
697
|
+
only those tests from the run: measure them again, and the merge keeps the
|
|
698
|
+
rest of the run and leaves their old records out:
|
|
699
|
+
|
|
700
|
+
```sh supercov-example
|
|
701
|
+
npx supercov runs <suite-run> tests affected --names # after changing a mock
|
|
702
|
+
npx supercov -- npx playwright test <those tests>
|
|
703
|
+
npx supercov merge
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
Until they are measured again, the merge refuses and names them.
|
|
707
|
+
|
|
658
708
|
When you know a change Supercov counts does not alter what the earlier tests
|
|
659
709
|
ran, say so:
|
|
660
710
|
|
|
@@ -666,6 +716,22 @@ The product code, the dependencies, and what is measured must still be the
|
|
|
666
716
|
same, and a run whose own test files changed is still left out. What was
|
|
667
717
|
accepted is listed in `merged across:` as accepted.
|
|
668
718
|
|
|
719
|
+
Runs measured on different machines merge the same way. Each machine
|
|
720
|
+
measures its part of the suite on the same commit and toolchain, and one job
|
|
721
|
+
merges them after copying each run's directory from `.supercov/runs/` into its
|
|
722
|
+
own:
|
|
723
|
+
|
|
724
|
+
```yaml
|
|
725
|
+
# Each of two jobs:
|
|
726
|
+
- run: npx supercov -- npx playwright test --shard=${{ matrix.shard }}/2
|
|
727
|
+
- uses: actions/upload-artifact@v4
|
|
728
|
+
with: { name: "supercov-${{ matrix.shard }}", path: .supercov/runs, include-hidden-files: true }
|
|
729
|
+
# Then one job:
|
|
730
|
+
- uses: actions/download-artifact@v4
|
|
731
|
+
with: { pattern: "supercov-*", path: .supercov/runs, merge-multiple: true }
|
|
732
|
+
- run: npx supercov merge
|
|
733
|
+
```
|
|
734
|
+
|
|
669
735
|
`assertions assess` assesses a merged run across every suite merged into it,
|
|
670
736
|
reusing the answers saved when its parts were assessed. `tests affected` of a
|
|
671
737
|
merged run is answered from the runs it was merged from, which hold the record
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.12.0",
|
|
4
4
|
"description": "Coverage, security and code quality for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"coverage",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"eval:skill": "claude plugin eval plugins/supercov --scaffold --trust-plugin --no-publish --model claude-sonnet-5 --judge-model claude-haiku-4-5 --threshold 0.66 --tag behavior trigger --allow-tools Bash Edit Write --max-cost-usd 15",
|
|
84
84
|
"eval:skill-triggers": "claude plugin eval plugins/supercov --scaffold --trust-plugin --no-publish --model claude-sonnet-5 --judge-model claude-haiku-4-5 --threshold 0.66 --tag trigger --ablation none --max-cost-usd 5",
|
|
85
85
|
"test:engine": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace && npm run test:runtime && npm run test:rust-assets && npm run test:engine-integrations",
|
|
86
|
-
"test:engine-integrations": "cargo build -p supercov && node scripts/html-report-integration.mjs && node scripts/rust-process-supervision.mjs && node scripts/rust-direct-node-integration.mjs && node scripts/rust-public-run-integration.mjs && node scripts/rust-embedded-runtime-integration.mjs && node scripts/rust-direct-vitest-integration.mjs && node scripts/rust-direct-jest-integration.mjs && node scripts/mocha-failure-output.mjs && node scripts/failure-output.mjs node ava tap && node scripts/side-by-side.mjs node && node scripts/merge-across.mjs && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/cross-origin-requests.mjs && node scripts/leaving-page.mjs && node scripts/background-by-time.mjs && node scripts/python-server-playwright.mjs && node scripts/ruby-server-playwright.mjs && node scripts/go-server-playwright.mjs && node scripts/jvm-server-playwright.mjs && node scripts/docker-server-playwright.mjs && node scripts/rust-classic-browser-integration.mjs && node scripts/rust-top-packages-integration.mjs && node scripts/rust-generic-esbuild-integration.mjs && node scripts/rust-generic-tsc-integration.mjs && node scripts/rust-generic-build-matrix.mjs && node scripts/rust-vite-playwright-integration.mjs",
|
|
86
|
+
"test:engine-integrations": "cargo build -p supercov && node scripts/html-report-integration.mjs && node scripts/rust-process-supervision.mjs && node scripts/rust-direct-node-integration.mjs && node scripts/rust-public-run-integration.mjs && node scripts/rust-embedded-runtime-integration.mjs && node scripts/rust-direct-vitest-integration.mjs && node scripts/rust-direct-jest-integration.mjs && node scripts/mocha-failure-output.mjs && node scripts/failure-output.mjs node ava tap && node scripts/side-by-side.mjs node && node scripts/merge-across.mjs && node scripts/mock-reach.mjs && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/cross-origin-requests.mjs && node scripts/leaving-page.mjs && node scripts/background-by-time.mjs && node scripts/python-server-playwright.mjs && node scripts/ruby-server-playwright.mjs && node scripts/go-server-playwright.mjs && node scripts/jvm-server-playwright.mjs && node scripts/docker-server-playwright.mjs && node scripts/rust-classic-browser-integration.mjs && node scripts/rust-top-packages-integration.mjs && node scripts/rust-generic-esbuild-integration.mjs && node scripts/rust-generic-tsc-integration.mjs && node scripts/rust-generic-build-matrix.mjs && node scripts/rust-vite-playwright-integration.mjs",
|
|
87
87
|
"test:platform": "cargo test --workspace && cargo build -p supercov && node scripts/rust-process-supervision.mjs && node scripts/workspace-crash-integration.mjs",
|
|
88
88
|
"test:native-package": "cargo build --release -p supercov && node scripts/native-package-integration.mjs && node scripts/native-release-set-integration.mjs",
|
|
89
89
|
"test:pypi-wheel": "node scripts/pypi-wheel-integration.mjs",
|
|
@@ -120,14 +120,14 @@
|
|
|
120
120
|
"test:windows-tls": "node scripts/windows-tls-test.mjs"
|
|
121
121
|
},
|
|
122
122
|
"optionalDependencies": {
|
|
123
|
-
"@supercov/cli-darwin-arm64": "4.
|
|
124
|
-
"@supercov/cli-darwin-x64": "4.
|
|
125
|
-
"@supercov/cli-linux-arm64-gnu": "4.
|
|
126
|
-
"@supercov/cli-linux-arm64-musl": "4.
|
|
127
|
-
"@supercov/cli-linux-x64-gnu": "4.
|
|
128
|
-
"@supercov/cli-linux-x64-musl": "4.
|
|
129
|
-
"@supercov/cli-win32-arm64": "4.
|
|
130
|
-
"@supercov/cli-win32-x64": "4.
|
|
123
|
+
"@supercov/cli-darwin-arm64": "4.12.0",
|
|
124
|
+
"@supercov/cli-darwin-x64": "4.12.0",
|
|
125
|
+
"@supercov/cli-linux-arm64-gnu": "4.12.0",
|
|
126
|
+
"@supercov/cli-linux-arm64-musl": "4.12.0",
|
|
127
|
+
"@supercov/cli-linux-x64-gnu": "4.12.0",
|
|
128
|
+
"@supercov/cli-linux-x64-musl": "4.12.0",
|
|
129
|
+
"@supercov/cli-win32-arm64": "4.12.0",
|
|
130
|
+
"@supercov/cli-win32-x64": "4.12.0"
|
|
131
131
|
},
|
|
132
132
|
"peerDependencies": {
|
|
133
133
|
"@playwright/test": ">=1.55.0",
|
|
@@ -719,6 +719,16 @@ class CoveragePhaseController {
|
|
|
719
719
|
ArrayBuffer.isView(result))
|
|
720
720
|
return result;
|
|
721
721
|
const candidate = result;
|
|
722
|
+
// A native dialog is Playwright's own object, returned as it is. Its
|
|
723
|
+
// `type()` was taken for a locator's action: it returned a promise
|
|
724
|
+
// where Playwright returns a string, and started a phase whose
|
|
725
|
+
// activation waits on the page, which runs nothing while the dialog
|
|
726
|
+
// is open, so the dialog could never be answered and the page never
|
|
727
|
+
// closed. Nothing a dialog's methods do is the application's work.
|
|
728
|
+
if (typeof candidate["accept"] === "function" &&
|
|
729
|
+
typeof candidate["dismiss"] === "function" &&
|
|
730
|
+
typeof candidate["defaultValue"] === "function")
|
|
731
|
+
return result;
|
|
722
732
|
if (typeof candidate["contexts"] === "function" &&
|
|
723
733
|
typeof candidate["newContext"] === "function")
|
|
724
734
|
trackBrowser(result);
|
|
@@ -847,8 +847,64 @@ function skipCoverageThresholds(tool) {
|
|
|
847
847
|
// instead, where such a file is read as an ES module and the hook never
|
|
848
848
|
// sees it; the loader is told so it can hand those files back.
|
|
849
849
|
const typescriptHandler = Module._extensions[".ts"];
|
|
850
|
+
// The tests a process serves reach the project files it loaded and read: a
|
|
851
|
+
// mock server a suite starts, the app server. Where SUPERCOV_SUPPORT_DIR is
|
|
852
|
+
// set this process notes them in a file of its own, which the loader adds
|
|
853
|
+
// its modules to and the runtime the tests the process served; a change to
|
|
854
|
+
// one of those files then affects those tests alone (`tests affected`,
|
|
855
|
+
// `merge`).
|
|
856
|
+
const supportDirectory = process.env.SUPERCOV_SUPPORT_DIR;
|
|
857
|
+
let supportFile;
|
|
858
|
+
if (supportDirectory) {
|
|
859
|
+
supportFile = path.join(supportDirectory, `${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.jsonl`);
|
|
860
|
+
// This process's own, not a parent's it inherited.
|
|
861
|
+
process.env.__SUPERCOV_SUPPORT_FILE = supportFile;
|
|
862
|
+
try {
|
|
863
|
+
fs.mkdirSync(supportDirectory, { recursive: true });
|
|
864
|
+
}
|
|
865
|
+
catch {
|
|
866
|
+
// Then nothing is noted, and every test counts as before.
|
|
867
|
+
}
|
|
868
|
+
const projectRoot = process.env.SUPERCOV_PROJECT_ROOT;
|
|
869
|
+
const read = new Set();
|
|
870
|
+
const noteRead = (target) => {
|
|
871
|
+
try {
|
|
872
|
+
const file = typeof target === "string"
|
|
873
|
+
? resolve(target)
|
|
874
|
+
: target instanceof URL && target.protocol === "file:"
|
|
875
|
+
? fileURLToPath(target)
|
|
876
|
+
: undefined;
|
|
877
|
+
// The copy lives under `.supercov/`: what is the project's is
|
|
878
|
+
// decided by the project root.
|
|
879
|
+
const inside = file && projectRoot && file.startsWith(projectRoot + sep) ? file.slice(projectRoot.length + 1) : undefined;
|
|
880
|
+
if (!inside || inside.startsWith(`.supercov${sep}`) || inside.split(sep).includes("node_modules") || read.has(file))
|
|
881
|
+
return;
|
|
882
|
+
read.add(file);
|
|
883
|
+
fs.appendFileSync(supportFile, `${JSON.stringify({ read: file })}\n`);
|
|
884
|
+
}
|
|
885
|
+
catch {
|
|
886
|
+
// A read not noted counts for every test, as before.
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
for (const name of ["readFileSync", "readFile"]) {
|
|
890
|
+
const original = fs[name];
|
|
891
|
+
fs[name] = function supercovNotedRead(target, ...rest) {
|
|
892
|
+
noteRead(target);
|
|
893
|
+
return original.call(this, target, ...rest);
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
const readPromised = fs.promises.readFile;
|
|
897
|
+
fs.promises.readFile = function supercovNotedRead(target, ...rest) {
|
|
898
|
+
noteRead(target);
|
|
899
|
+
return readPromised.call(this, target, ...rest);
|
|
900
|
+
};
|
|
901
|
+
syncBuiltinESMExports();
|
|
902
|
+
}
|
|
850
903
|
register(new URL("./resolve-loader.mjs", import.meta.url), {
|
|
851
|
-
data: {
|
|
904
|
+
data: {
|
|
905
|
+
typescriptRequireHook: typeof typescriptHandler === "function" && typescriptHandler.name !== "loadTS",
|
|
906
|
+
supportFile,
|
|
907
|
+
},
|
|
852
908
|
});
|
|
853
909
|
if (process.env.SUPERCOV_DEBUG === "1") {
|
|
854
910
|
console.error("[supercov] preload", { entrypoint });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { appendFileSync, readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, resolve as resolvePath } from "node:path";
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
4
|
const GENERATED_TARGET = "__SUPERCOV_PLAYWRIGHT_MODULE__";
|
|
@@ -27,8 +27,40 @@ function belongsToProject(parentURL) {
|
|
|
27
27
|
return (parentURL.startsWith(projectURL) && !parentURL.startsWith(generatedURL));
|
|
28
28
|
}
|
|
29
29
|
let typescriptRequireHook = false;
|
|
30
|
+
// Where this process notes the project modules it loads (`register.mjs`
|
|
31
|
+
// names it): a mock server a suite starts is reached by the tests it serves,
|
|
32
|
+
// and a change to a file it loaded is a change for them alone.
|
|
33
|
+
let supportFile;
|
|
34
|
+
const supportModules = new Set();
|
|
35
|
+
// A project file, not a dependency nor Supercov's own: the copy itself lives
|
|
36
|
+
// under `.supercov/`, so the project root decides.
|
|
37
|
+
function projectFile(file) {
|
|
38
|
+
if (!PROJECT_ROOT || !file.startsWith(PROJECT_ROOT))
|
|
39
|
+
return false;
|
|
40
|
+
const relative = file.slice(PROJECT_ROOT.length).replace(/^[\\/]/, "");
|
|
41
|
+
return relative !== "" && !/^\.supercov[\\/]/.test(relative) && !/(?:^|[\\/])node_modules[\\/]/.test(relative);
|
|
42
|
+
}
|
|
43
|
+
function noteLoaded(url) {
|
|
44
|
+
if (!supportFile || !url.startsWith("file:") || supportModules.has(url))
|
|
45
|
+
return;
|
|
46
|
+
supportModules.add(url);
|
|
47
|
+
try {
|
|
48
|
+
if (!projectFile(fileURLToPath(url)))
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
appendFileSync(supportFile, `${JSON.stringify({ loaded: url })}\n`);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Not recorded: the file counts for every test, as before.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
30
61
|
export function initialize(data) {
|
|
31
62
|
typescriptRequireHook = data?.typescriptRequireHook === true;
|
|
63
|
+
supportFile = typeof data?.supportFile === "string" ? data.supportFile : undefined;
|
|
32
64
|
}
|
|
33
65
|
const packageTypes = new Map();
|
|
34
66
|
function packageType(directory) {
|
|
@@ -144,6 +176,7 @@ function mapToCopy(source, filename) {
|
|
|
144
176
|
}
|
|
145
177
|
export async function load(url, context, nextLoad) {
|
|
146
178
|
const result = await nextLoad(url, context);
|
|
179
|
+
noteLoaded(url);
|
|
147
180
|
if (!NODE_COVERAGE_FILTERS || result.source == null || !url.startsWith("file:"))
|
|
148
181
|
return result;
|
|
149
182
|
const text = typeof result.source === "string" ? result.source : Buffer.from(result.source).toString("utf8");
|
|
@@ -1425,6 +1425,55 @@ emitterContextMaps.set(runtimeInstance, emitterCoverageContexts);
|
|
|
1425
1425
|
if (runtimeGlobal.__SUPERCOV_EMITTER_PATCHED_INSTANCES__ == null)
|
|
1426
1426
|
runtimeGlobal.__SUPERCOV_EMITTER_PATCHED_INSTANCES__ = new Set();
|
|
1427
1427
|
const patchedEmitterInstances = runtimeGlobal.__SUPERCOV_EMITTER_PATCHED_INSTANCES__;
|
|
1428
|
+
// Which tests this process served, and when it served a request that named
|
|
1429
|
+
// none, in the file `register.mjs` named for it: the project files it loaded
|
|
1430
|
+
// and read are reached by those tests, and a change to one is a change for
|
|
1431
|
+
// them alone (`tests affected`, `merge`). Its CommonJS modules are noted
|
|
1432
|
+
// here, once each, as requests come; the loader notes its ES modules.
|
|
1433
|
+
var supportNoted = { served: new Set(), modules: new Set(), lastUnscoped: 0 };
|
|
1434
|
+
function noteSupport(scope) {
|
|
1435
|
+
const file = typeof process !== "undefined" && process.env ? process.env.__SUPERCOV_SUPPORT_FILE : void 0;
|
|
1436
|
+
if (!file)
|
|
1437
|
+
return;
|
|
1438
|
+
const fs = getFs();
|
|
1439
|
+
if (!fs)
|
|
1440
|
+
return;
|
|
1441
|
+
const lines = [];
|
|
1442
|
+
if (scope) {
|
|
1443
|
+
if (!supportNoted.served.has(scope.testId)) {
|
|
1444
|
+
supportNoted.served.add(scope.testId);
|
|
1445
|
+
lines.push({ served: scope.testId });
|
|
1446
|
+
}
|
|
1447
|
+
} else {
|
|
1448
|
+
const now = Date.now();
|
|
1449
|
+
if (now - supportNoted.lastUnscoped >= 5) {
|
|
1450
|
+
supportNoted.lastUnscoped = now;
|
|
1451
|
+
lines.push({ unscoped: now });
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
try {
|
|
1455
|
+
const moduleBuiltin = typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("node:module") : void 0;
|
|
1456
|
+
const cache = moduleBuiltin && moduleBuiltin._cache;
|
|
1457
|
+
const root = process.env.SUPERCOV_PROJECT_ROOT;
|
|
1458
|
+
if (cache && root) {
|
|
1459
|
+
for (const name of Object.keys(cache)) {
|
|
1460
|
+
// The copy lives under `.supercov/`: the project root decides.
|
|
1461
|
+
const inside = name.indexOf(root) === 0 ? name.slice(root.length).replace(/^[\\/]/, "") : "";
|
|
1462
|
+
if (supportNoted.modules.has(name) || inside === "" || /^\.supercov[\\/]/.test(inside) || /(?:^|[\\/])node_modules[\\/]/.test(inside))
|
|
1463
|
+
continue;
|
|
1464
|
+
supportNoted.modules.add(name);
|
|
1465
|
+
lines.push({ loaded: name });
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
} catch (e) {
|
|
1469
|
+
}
|
|
1470
|
+
if (lines.length === 0)
|
|
1471
|
+
return;
|
|
1472
|
+
try {
|
|
1473
|
+
fs.appendFileSync(file, lines.map((line) => JSON.stringify(line)).join("\n") + "\n");
|
|
1474
|
+
} catch (e) {
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1428
1477
|
function installNodeRequestPropagation() {
|
|
1429
1478
|
if (isBrowser || patchedEmitterInstances.has(runtimeInstance) || typeof process === "undefined") return;
|
|
1430
1479
|
const builtin = (name) => typeof process.getBuiltinModule === "function" ? process.getBuiltinModule(name) : void 0;
|
|
@@ -1443,6 +1492,7 @@ function installNodeRequestPropagation() {
|
|
|
1443
1492
|
// HTTP headers establish ownership even when Express/SDK listeners and
|
|
1444
1493
|
// the server process were created by a shared before hook.
|
|
1445
1494
|
const incoming = requestCoverageContext(args[0]);
|
|
1495
|
+
noteSupport(incoming && incoming.scope);
|
|
1446
1496
|
if (incoming) context = incoming.scope ? incoming : context != null ? context : currentRequestContext();
|
|
1447
1497
|
if (incoming && incoming.scope)
|
|
1448
1498
|
noteServedAttempt(incoming.scope);
|