supercov 4.24.7 → 4.25.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supercov",
3
- "version": "4.24.7",
3
+ "version": "4.25.0",
4
4
  "description": "Coverage, security and code quality for coding agents",
5
5
  "keywords": [
6
6
  "coverage",
@@ -123,14 +123,14 @@
123
123
  "test:windows-tls": "node scripts/windows-tls-test.mjs"
124
124
  },
125
125
  "optionalDependencies": {
126
- "@supercov/cli-darwin-arm64": "4.24.7",
127
- "@supercov/cli-darwin-x64": "4.24.7",
128
- "@supercov/cli-linux-arm64-gnu": "4.24.7",
129
- "@supercov/cli-linux-arm64-musl": "4.24.7",
130
- "@supercov/cli-linux-x64-gnu": "4.24.7",
131
- "@supercov/cli-linux-x64-musl": "4.24.7",
132
- "@supercov/cli-win32-arm64": "4.24.7",
133
- "@supercov/cli-win32-x64": "4.24.7"
126
+ "@supercov/cli-darwin-arm64": "4.25.0",
127
+ "@supercov/cli-darwin-x64": "4.25.0",
128
+ "@supercov/cli-linux-arm64-gnu": "4.25.0",
129
+ "@supercov/cli-linux-arm64-musl": "4.25.0",
130
+ "@supercov/cli-linux-x64-gnu": "4.25.0",
131
+ "@supercov/cli-linux-x64-musl": "4.25.0",
132
+ "@supercov/cli-win32-arm64": "4.25.0",
133
+ "@supercov/cli-win32-x64": "4.25.0"
134
134
  },
135
135
  "peerDependencies": {
136
136
  "@playwright/test": ">=1.55.0",
@@ -1,6 +1,8 @@
1
- import { appendFileSync, chmodSync, existsSync, mkdirSync, openSync, closeSync, fsyncSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
1
+ import fs, { appendFileSync, chmodSync, existsSync, mkdirSync, openSync, closeSync, fsyncSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
2
2
  import { randomUUID } from "node:crypto";
3
- import { dirname, resolve } from "node:path";
3
+ import { syncBuiltinESMExports } from "node:module";
4
+ import { threadId } from "node:worker_threads";
5
+ import { dirname, resolve, sep } from "node:path";
4
6
  import { Buffer } from "node:buffer";
5
7
 
6
8
  // In a container Supercov's `docker` launcher mounts the run's directory
@@ -146,3 +148,41 @@ export function appendEvidenceRecord(directory, prefix, payload) {
146
148
  append(journal.path, line);
147
149
  journal.size += Buffer.byteLength(line);
148
150
  }
151
+
152
+ // Playwright 1.59 writes each file it compiles into its cache in place and
153
+ // reads it back unchecked: a process that read one while another wrote it
154
+ // ran an empty module -- a config of no `default` failed at "Cannot add
155
+ // property metadata, object is not extensible", a test file at "does not
156
+ // provide an export named". The cache a run gives it starts empty and is
157
+ // shared by every Playwright of the run, the containers a sealed suite execs
158
+ // into among them, so every first compile raced; there each file is written
159
+ // whole, or is not there yet and is compiled again. A file written beside the
160
+ // cache's folders, not in one, is never taken for an old entry and removed.
161
+ //
162
+ // Playwright compiles in two threads: the config and CommonJS files in the
163
+ // process's own, ES modules in the thread its loader hooks run in, which has
164
+ // its own `fs` and does not run `--import`. Each calls this. The partial
165
+ // file's name is unique to the write: a process ID repeats across containers
166
+ // and both threads of one process count from zero.
167
+ let cacheWritesWhole = false;
168
+ export function writePlaywrightCacheWhole() {
169
+ const transformCache = process.env.PWTEST_CACHE_DIR;
170
+ if (!transformCache || cacheWritesWhole)
171
+ return;
172
+ cacheWritesWhole = true;
173
+ const cacheFolder = resolve(transformCache) + sep;
174
+ const writeFileSync = fs.writeFileSync;
175
+ fs.writeFileSync = function (file, ...rest) {
176
+ if (typeof file !== "string" || !resolve(file).startsWith(cacheFolder))
177
+ return writeFileSync.call(this, file, ...rest);
178
+ const partial = resolve(transformCache, `.writing-${process.pid}-${threadId}-${randomUUID()}`);
179
+ try {
180
+ writeFileSync.call(this, partial, ...rest);
181
+ fs.renameSync(partial, file);
182
+ }
183
+ finally {
184
+ fs.rmSync(partial, { force: true });
185
+ }
186
+ };
187
+ syncBuiltinESMExports();
188
+ }
@@ -628,6 +628,10 @@ function inspectExports(value, depth = 0) {
628
628
  exportedValues.add(object);
629
629
  if (typeof value === "function")
630
630
  patchBuilder(value);
631
+ // What sits below this depth is never inspected: listing it cost every
632
+ // process a descriptor read per key of every export's members.
633
+ if (depth === 2)
634
+ return;
631
635
  for (const key of Reflect.ownKeys(object).slice(0, 200)) {
632
636
  if (key === "prototype" || key === "caller" || key === "callee")
633
637
  continue;
@@ -719,6 +723,12 @@ function injectChildEnvironment(method, args) {
719
723
  // every task aborted with ERR_MODULE_NOT_FOUND. launchSupervisor.js is
720
724
  // generated into the same .supercov directory as register.mjs.
721
725
  environment.NODE_OPTIONS = appendNodeImport(existingEnvironment?.NODE_OPTIONS ?? process.env.NODE_OPTIONS, new URL("./register.mjs", import.meta.url).href);
726
+ // The Playwright runner marked its children as not test workers; a process
727
+ // it forks from its worker entry is one (see register.mjs).
728
+ if (method === "fork" &&
729
+ environment.SUPERCOV_PLAYWRIGHT_WORKER !== undefined &&
730
+ /\/worker\/(?:workerProcessEntry|workerMain)\.js$/.test(String(args[0]).replaceAll("\\", "/")))
731
+ environment.SUPERCOV_PLAYWRIGHT_WORKER = "1";
722
732
  next[index] = { ...options, env: environment };
723
733
  if (typeof original === "function")
724
734
  next.splice(index + 1, 0, original);