"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // packages/utils/third_party/yauzl/pend.js var require_pend = __commonJS({ "packages/utils/third_party/yauzl/pend.js"(exports2, module2) { "use strict"; module2.exports = Pend; function Pend() { this.pending = 0; this.max = Infinity; this.listeners = []; this.waiting = []; this.error = null; } Pend.prototype.go = function(fn) { if (this.pending < this.max) { pendGo(this, fn); } else { this.waiting.push(fn); } }; Pend.prototype.wait = function(cb) { if (this.pending === 0) { cb(this.error); } else { this.listeners.push(cb); } }; Pend.prototype.hold = function() { return pendHold(this); }; function pendHold(self) { self.pending += 1; var called = false; return onCb; function onCb(err) { if (called) throw new Error("callback called twice"); called = true; self.error = self.error || err; self.pending -= 1; if (self.waiting.length > 0 && self.pending < self.max) { pendGo(self, self.waiting.shift()); } else if (self.pending === 0) { var listeners = self.listeners; self.listeners = []; listeners.forEach(cbListener); } } function cbListener(listener) { listener(self.error); } } function pendGo(self, fn) { fn(pendHold(self)); } } }); // packages/utils/third_party/yauzl/fd-slicer.js var require_fd_slicer = __commonJS({ "packages/utils/third_party/yauzl/fd-slicer.js"(exports2) { "use strict"; var fs4 = require("fs"); var util2 = require("util"); var stream = require("stream"); var Readable = stream.Readable; var Writable = stream.Writable; var PassThrough = stream.PassThrough; var Pend = require_pend(); var EventEmitter = require("events").EventEmitter; exports2.createFromBuffer = createFromBuffer; exports2.createFromFd = createFromFd; exports2.BufferSlicer = BufferSlicer; exports2.FdSlicer = FdSlicer; util2.inherits(FdSlicer, EventEmitter); function FdSlicer(fd, options2) { options2 = options2 || {}; EventEmitter.call(this); this.fd = fd; this.pend = new Pend(); this.pend.max = 1; this.refCount = 0; this.autoClose = !!options2.autoClose; } FdSlicer.prototype.read = function(buffer, offset, length, position, callback) { var self = this; self.pend.go(function(cb) { fs4.read(self.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) { cb(); callback(err, bytesRead, buffer2); }); }); }; FdSlicer.prototype.write = function(buffer, offset, length, position, callback) { var self = this; self.pend.go(function(cb) { fs4.write(self.fd, buffer, offset, length, position, function(err, written, buffer2) { cb(); callback(err, written, buffer2); }); }); }; FdSlicer.prototype.createReadStream = function(options2) { return new ReadStream(this, options2); }; FdSlicer.prototype.createWriteStream = function(options2) { return new WriteStream(this, options2); }; FdSlicer.prototype.ref = function() { this.refCount += 1; }; FdSlicer.prototype.unref = function() { var self = this; self.refCount -= 1; if (self.refCount > 0) return; if (self.refCount < 0) throw new Error("invalid unref"); if (self.autoClose) { fs4.close(self.fd, onCloseDone); } function onCloseDone(err) { if (err) { self.emit("error", err); } else { self.emit("close"); } } }; util2.inherits(ReadStream, Readable); function ReadStream(context, options2) { options2 = options2 || {}; Readable.call(this, options2); this.context = context; this.context.ref(); this.start = options2.start || 0; this.endOffset = options2.end; this.pos = this.start; this._destroyed = false; } ReadStream.prototype._read = function(n) { var self = this; if (self._destroyed) return; var toRead = Math.min(self._readableState.highWaterMark, n); if (self.endOffset != null) { toRead = Math.min(toRead, self.endOffset - self.pos); } if (toRead <= 0) { self._destroyed = true; self.push(null); self.context.unref(); return; } self.context.pend.go(function(cb) { if (self._destroyed) return cb(); var buffer = Buffer.allocUnsafe(toRead); fs4.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) { if (self._destroyed) return cb(); if (err) { self.destroy(err); } else if (bytesRead === 0) { self._destroyed = true; self.push(null); self.context.unref(); } else { self.pos += bytesRead; self.push(buffer.slice(0, bytesRead)); } cb(); }); }); }; ReadStream.prototype.destroy = function(err) { if (err == null && !this.readableEnded) { err = new Error("stream destroyed"); } return Readable.prototype.destroy.call(this, err); }; ReadStream.prototype._destroy = function(err, cb) { if (!this._destroyed) { this._destroyed = true; this.context.unref(); } cb(err); }; util2.inherits(WriteStream, Writable); function WriteStream(context, options2) { options2 = options2 || {}; Writable.call(this, options2); this.context = context; this.context.ref(); this.start = options2.start || 0; this.endOffset = options2.end == null ? Infinity : +options2.end; this.bytesWritten = 0; this.pos = this.start; this._destroyed = false; this.on("finish", this.destroy.bind(this)); } WriteStream.prototype._write = function(buffer, encoding, callback) { var self = this; if (self._destroyed) return; if (self.pos + buffer.length > self.endOffset) { var err = new Error("maximum file length exceeded"); err.code = "ETOOBIG"; self.destroy(); callback(err); return; } self.context.pend.go(function(cb) { if (self._destroyed) return cb(); fs4.write(self.context.fd, buffer, 0, buffer.length, self.pos, function(err2, bytes) { if (err2) { self.destroy(); cb(); callback(err2); } else { self.bytesWritten += bytes; self.pos += bytes; self.emit("progress"); cb(); callback(); } }); }); }; WriteStream.prototype._destroy = function(err, cb) { if (!this._destroyed) { this._destroyed = true; this.context.unref(); } cb(err); }; util2.inherits(BufferSlicer, EventEmitter); function BufferSlicer(buffer, options2) { EventEmitter.call(this); options2 = options2 || {}; this.refCount = 0; this.buffer = buffer; this.maxChunkSize = options2.maxChunkSize || Number.MAX_SAFE_INTEGER; } BufferSlicer.prototype.read = function(buffer, offset, length, position, callback) { if (!(0 <= offset && offset <= buffer.length)) throw new RangeError("offset outside buffer: 0 <= " + offset + " <= " + buffer.length); if (position < 0) throw new RangeError("position is negative: " + position); if (offset + length > buffer.length) { length = buffer.length - offset; } if (position + length > this.buffer.length) { length = this.buffer.length - position; } if (length <= 0) { setImmediate(function() { callback(null, 0); }); return; } this.buffer.copy(buffer, offset, position, position + length); setImmediate(function() { callback(null, length); }); }; BufferSlicer.prototype.write = function(buffer, offset, length, position, callback) { buffer.copy(this.buffer, position, offset, offset + length); setImmediate(function() { callback(null, length, buffer); }); }; BufferSlicer.prototype.createReadStream = function(options2) { options2 = options2 || {}; var readStream = new PassThrough(options2); readStream._destroyed = false; readStream.start = options2.start || 0; readStream.endOffset = options2.end; readStream.pos = readStream.endOffset || this.buffer.length; var entireSlice = this.buffer.slice(readStream.start, readStream.pos); var offset = 0; while (true) { var nextOffset = offset + this.maxChunkSize; if (nextOffset >= entireSlice.length) { if (offset < entireSlice.length) { readStream.write(entireSlice.slice(offset, entireSlice.length)); } break; } readStream.write(entireSlice.slice(offset, nextOffset)); offset = nextOffset; } readStream.end(); readStream._destroy = function(err, cb) { readStream._destroyed = true; PassThrough.prototype._destroy.call(readStream, err, cb); }; return readStream; }; BufferSlicer.prototype.createWriteStream = function(options2) { var bufferSlicer = this; options2 = options2 || {}; var writeStream = new Writable(options2); writeStream.start = options2.start || 0; writeStream.endOffset = options2.end == null ? this.buffer.length : +options2.end; writeStream.bytesWritten = 0; writeStream.pos = writeStream.start; writeStream._destroyed = false; writeStream._write = function(buffer, encoding, callback) { if (writeStream._destroyed) return; var end = writeStream.pos + buffer.length; if (end > writeStream.endOffset) { var err = new Error("maximum file length exceeded"); err.code = "ETOOBIG"; writeStream._destroyed = true; callback(err); return; } buffer.copy(bufferSlicer.buffer, writeStream.pos, 0, buffer.length); writeStream.bytesWritten += buffer.length; writeStream.pos = end; writeStream.emit("progress"); callback(); }; writeStream._destroy = function(err, cb) { writeStream._destroyed = true; cb(err); }; return writeStream; }; BufferSlicer.prototype.ref = function() { this.refCount += 1; }; BufferSlicer.prototype.unref = function() { this.refCount -= 1; if (this.refCount < 0) { throw new Error("invalid unref"); } }; function createFromBuffer(buffer, options2) { return new BufferSlicer(buffer, options2); } function createFromFd(fd, options2) { return new FdSlicer(fd, options2); } } }); // packages/utils/third_party/yauzl/buffer-crc32.js var require_buffer_crc32 = __commonJS({ "packages/utils/third_party/yauzl/buffer-crc32.js"(exports2, module2) { "use strict"; var Buffer2 = require("buffer").Buffer; var CRC_TABLE = [ 0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989, 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918e3, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117 ]; if (typeof Int32Array !== "undefined") { CRC_TABLE = new Int32Array(CRC_TABLE); } function ensureBuffer(input) { if (Buffer2.isBuffer(input)) { return input; } var hasNewBufferAPI = typeof Buffer2.alloc === "function" && typeof Buffer2.from === "function"; if (typeof input === "number") { return hasNewBufferAPI ? Buffer2.alloc(input) : new Buffer2(input); } else if (typeof input === "string") { return hasNewBufferAPI ? Buffer2.from(input) : new Buffer2(input); } else { throw new Error("input must be buffer, number, or string, received " + typeof input); } } function bufferizeInt(num) { var tmp = ensureBuffer(4); tmp.writeInt32BE(num, 0); return tmp; } function _crc32(buf, previous) { buf = ensureBuffer(buf); if (Buffer2.isBuffer(previous)) { previous = previous.readUInt32BE(0); } var crc = ~~previous ^ -1; for (var n = 0; n < buf.length; n++) { crc = CRC_TABLE[(crc ^ buf[n]) & 255] ^ crc >>> 8; } return crc ^ -1; } function crc32() { return bufferizeInt(_crc32.apply(null, arguments)); } crc32.signed = function() { return _crc32.apply(null, arguments); }; crc32.unsigned = function() { return _crc32.apply(null, arguments) >>> 0; }; module2.exports = crc32; } }); // packages/utils/third_party/yauzl/index.js var require_yauzl = __commonJS({ "packages/utils/third_party/yauzl/index.js"(exports2) { "use strict"; var fs4 = require("fs"); var zlib = require("zlib"); var fd_slicer = require_fd_slicer(); var crc32 = require_buffer_crc32(); var util2 = require("util"); var EventEmitter = require("events").EventEmitter; var Transform = require("stream").Transform; var PassThrough = require("stream").PassThrough; var Writable = require("stream").Writable; exports2.open = open2; exports2.fromFd = fromFd; exports2.fromBuffer = fromBuffer; exports2.fromRandomAccessReader = fromRandomAccessReader; exports2.dosDateTimeToDate = dosDateTimeToDate; exports2.getFileNameLowLevel = getFileNameLowLevel; exports2.validateFileName = validateFileName; exports2.parseExtraFields = parseExtraFields; exports2.ZipFile = ZipFile; exports2.Entry = Entry; exports2.LocalFileHeader = LocalFileHeader; exports2.RandomAccessReader = RandomAccessReader; function open2(path4, options2, callback) { if (typeof options2 === "function") { callback = options2; options2 = null; } if (options2 == null) options2 = {}; if (options2.autoClose == null) options2.autoClose = true; if (options2.lazyEntries == null) options2.lazyEntries = false; if (options2.decodeStrings == null) options2.decodeStrings = true; if (options2.validateEntrySizes == null) options2.validateEntrySizes = true; if (options2.strictFileNames == null) options2.strictFileNames = false; if (callback == null) callback = defaultCallback; fs4.open(path4, "r", function(err, fd) { if (err) return callback(err); fromFd(fd, options2, function(err2, zipfile) { if (err2) fs4.close(fd, defaultCallback); callback(err2, zipfile); }); }); } function fromFd(fd, options2, callback) { if (typeof options2 === "function") { callback = options2; options2 = null; } if (options2 == null) options2 = {}; if (options2.autoClose == null) options2.autoClose = false; if (options2.lazyEntries == null) options2.lazyEntries = false; if (options2.decodeStrings == null) options2.decodeStrings = true; if (options2.validateEntrySizes == null) options2.validateEntrySizes = true; if (options2.strictFileNames == null) options2.strictFileNames = false; if (callback == null) callback = defaultCallback; fs4.fstat(fd, function(err, stats) { if (err) return callback(err); var reader = fd_slicer.createFromFd(fd, { autoClose: true }); fromRandomAccessReader(reader, stats.size, options2, callback); }); } function fromBuffer(buffer, options2, callback) { if (typeof options2 === "function") { callback = options2; options2 = null; } if (options2 == null) options2 = {}; options2.autoClose = false; if (options2.lazyEntries == null) options2.lazyEntries = false; if (options2.decodeStrings == null) options2.decodeStrings = true; if (options2.validateEntrySizes == null) options2.validateEntrySizes = true; if (options2.strictFileNames == null) options2.strictFileNames = false; var reader = fd_slicer.createFromBuffer(buffer, { maxChunkSize: 65536 }); fromRandomAccessReader(reader, buffer.length, options2, callback); } function fromRandomAccessReader(reader, totalSize, options2, callback) { if (typeof options2 === "function") { callback = options2; options2 = null; } if (options2 == null) options2 = {}; if (options2.autoClose == null) options2.autoClose = true; if (options2.lazyEntries == null) options2.lazyEntries = false; if (options2.decodeStrings == null) options2.decodeStrings = true; var decodeStrings = !!options2.decodeStrings; if (options2.validateEntrySizes == null) options2.validateEntrySizes = true; if (options2.strictFileNames == null) options2.strictFileNames = false; if (callback == null) callback = defaultCallback; if (typeof totalSize !== "number") throw new Error("expected totalSize parameter to be a number"); if (totalSize > Number.MAX_SAFE_INTEGER) { throw new Error("zip file too large. only file sizes up to 2^52 are supported due to JavaScript's Number type being an IEEE 754 double."); } reader.ref(); var eocdrWithoutCommentSize = 22; var zip64EocdlSize = 20; var maxCommentSize = 65535; var bufferSize = Math.min(zip64EocdlSize + eocdrWithoutCommentSize + maxCommentSize, totalSize); var buffer = newBuffer(bufferSize); var bufferReadStart = totalSize - buffer.length; readAndAssertNoEof(reader, buffer, 0, bufferSize, bufferReadStart, function(err) { if (err) return callback(err); for (var i = bufferSize - eocdrWithoutCommentSize; i >= 0; i -= 1) { if (buffer.readUInt32LE(i) !== 101010256) continue; var eocdrBuffer = buffer.subarray(i); var diskNumber = eocdrBuffer.readUInt16LE(4); var entryCount = eocdrBuffer.readUInt16LE(10); var centralDirectoryOffset = eocdrBuffer.readUInt32LE(16); var commentLength = eocdrBuffer.readUInt16LE(20); var expectedCommentLength = eocdrBuffer.length - eocdrWithoutCommentSize; if (commentLength !== expectedCommentLength) { return callback(new Error("Invalid comment length. Expected: " + expectedCommentLength + ". Found: " + commentLength + ". Are there extra bytes at the end of the file? Or is the end of central dir signature `PK\u263A\u263B` in the comment?")); } var comment = decodeStrings ? decodeBuffer(eocdrBuffer.subarray(22), false) : eocdrBuffer.subarray(22); if (i - zip64EocdlSize >= 0 && buffer.readUInt32LE(i - zip64EocdlSize) === 117853008) { var zip64EocdlBuffer = buffer.subarray(i - zip64EocdlSize, i - zip64EocdlSize + zip64EocdlSize); var zip64EocdrOffset = readUInt64LE(zip64EocdlBuffer, 8); var zip64EocdrBuffer = newBuffer(56); return readAndAssertNoEof(reader, zip64EocdrBuffer, 0, zip64EocdrBuffer.length, zip64EocdrOffset, function(err2) { if (err2) return callback(err2); if (zip64EocdrBuffer.readUInt32LE(0) !== 101075792) { return callback(new Error("invalid zip64 end of central directory record signature")); } diskNumber = zip64EocdrBuffer.readUInt32LE(16); if (diskNumber !== 0) { return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber)); } entryCount = readUInt64LE(zip64EocdrBuffer, 32); centralDirectoryOffset = readUInt64LE(zip64EocdrBuffer, 48); return callback(null, new ZipFile(reader, centralDirectoryOffset, totalSize, entryCount, comment, options2.autoClose, options2.lazyEntries, decodeStrings, options2.validateEntrySizes, options2.strictFileNames)); }); } if (diskNumber !== 0) { return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber)); } return callback(null, new ZipFile(reader, centralDirectoryOffset, totalSize, entryCount, comment, options2.autoClose, options2.lazyEntries, decodeStrings, options2.validateEntrySizes, options2.strictFileNames)); } callback(new Error("End of central directory record signature not found. Either not a zip file, or file is truncated.")); }); } util2.inherits(ZipFile, EventEmitter); function ZipFile(reader, centralDirectoryOffset, fileSize, entryCount, comment, autoClose, lazyEntries, decodeStrings, validateEntrySizes, strictFileNames) { var self = this; EventEmitter.call(self); self.reader = reader; self.reader.on("error", function(err) { emitError(self, err); }); self.reader.once("close", function() { self.emit("close"); }); self.readEntryCursor = centralDirectoryOffset; self.fileSize = fileSize; self.entryCount = entryCount; self.comment = comment; self.entriesRead = 0; self.autoClose = !!autoClose; self.lazyEntries = !!lazyEntries; self.decodeStrings = !!decodeStrings; self.validateEntrySizes = !!validateEntrySizes; self.strictFileNames = !!strictFileNames; self.isOpen = true; self.emittedError = false; if (!self.lazyEntries) self._readEntry(); } ZipFile.prototype.close = function() { if (!this.isOpen) return; this.isOpen = false; this.reader.unref(); }; function emitErrorAndAutoClose(self, err) { if (self.autoClose) self.close(); emitError(self, err); } function emitError(self, err) { if (self.emittedError) return; self.emittedError = true; self.emit("error", err); } ZipFile.prototype.readEntry = function() { if (!this.lazyEntries) throw new Error("readEntry() called without lazyEntries:true"); this._readEntry(); }; ZipFile.prototype._readEntry = function() { var self = this; if (self.entryCount === self.entriesRead) { setImmediate(function() { if (self.autoClose) self.close(); if (self.emittedError) return; self.emit("end"); }); return; } if (self.emittedError) return; var buffer = newBuffer(46); readAndAssertNoEof(self.reader, buffer, 0, buffer.length, self.readEntryCursor, function(err) { if (err) return emitErrorAndAutoClose(self, err); if (self.emittedError) return; var entry = new Entry(); var signature = buffer.readUInt32LE(0); if (signature !== 33639248) return emitErrorAndAutoClose(self, new Error("invalid central directory file header signature: 0x" + signature.toString(16))); entry.versionMadeBy = buffer.readUInt16LE(4); entry.versionNeededToExtract = buffer.readUInt16LE(6); entry.generalPurposeBitFlag = buffer.readUInt16LE(8); entry.compressionMethod = buffer.readUInt16LE(10); entry.lastModFileTime = buffer.readUInt16LE(12); entry.lastModFileDate = buffer.readUInt16LE(14); entry.crc32 = buffer.readUInt32LE(16); entry.compressedSize = buffer.readUInt32LE(20); entry.uncompressedSize = buffer.readUInt32LE(24); entry.fileNameLength = buffer.readUInt16LE(28); entry.extraFieldLength = buffer.readUInt16LE(30); entry.fileCommentLength = buffer.readUInt16LE(32); entry.internalFileAttributes = buffer.readUInt16LE(36); entry.externalFileAttributes = buffer.readUInt32LE(38); entry.relativeOffsetOfLocalHeader = buffer.readUInt32LE(42); if (entry.generalPurposeBitFlag & 64) return emitErrorAndAutoClose(self, new Error("strong encryption is not supported")); self.readEntryCursor += 46; buffer = newBuffer(entry.fileNameLength + entry.extraFieldLength + entry.fileCommentLength); readAndAssertNoEof(self.reader, buffer, 0, buffer.length, self.readEntryCursor, function(err2) { if (err2) return emitErrorAndAutoClose(self, err2); if (self.emittedError) return; entry.fileNameRaw = buffer.subarray(0, entry.fileNameLength); var fileCommentStart = entry.fileNameLength + entry.extraFieldLength; entry.extraFieldRaw = buffer.subarray(entry.fileNameLength, fileCommentStart); entry.fileCommentRaw = buffer.subarray(fileCommentStart, fileCommentStart + entry.fileCommentLength); try { entry.extraFields = parseExtraFields(entry.extraFieldRaw); } catch (err3) { return emitErrorAndAutoClose(self, err3); } if (self.decodeStrings) { var isUtf8 = (entry.generalPurposeBitFlag & 2048) !== 0; entry.fileComment = decodeBuffer(entry.fileCommentRaw, isUtf8); entry.fileName = getFileNameLowLevel(entry.generalPurposeBitFlag, entry.fileNameRaw, entry.extraFields, self.strictFileNames); var errorMessage = validateFileName(entry.fileName); if (errorMessage != null) return emitErrorAndAutoClose(self, new Error(errorMessage)); } else { entry.fileComment = entry.fileCommentRaw; entry.fileName = entry.fileNameRaw; } entry.comment = entry.fileComment; self.readEntryCursor += buffer.length; self.entriesRead += 1; for (var i = 0; i < entry.extraFields.length; i++) { var extraField = entry.extraFields[i]; if (extraField.id !== 1) continue; var zip64EiefBuffer = extraField.data; var index = 0; if (entry.uncompressedSize === 4294967295) { if (index + 8 > zip64EiefBuffer.length) { return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include uncompressed size")); } entry.uncompressedSize = readUInt64LE(zip64EiefBuffer, index); index += 8; } if (entry.compressedSize === 4294967295) { if (index + 8 > zip64EiefBuffer.length) { return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include compressed size")); } entry.compressedSize = readUInt64LE(zip64EiefBuffer, index); index += 8; } if (entry.relativeOffsetOfLocalHeader === 4294967295) { if (index + 8 > zip64EiefBuffer.length) { return emitErrorAndAutoClose(self, new Error("zip64 extended information extra field does not include relative header offset")); } entry.relativeOffsetOfLocalHeader = readUInt64LE(zip64EiefBuffer, index); index += 8; } break; } if (self.validateEntrySizes && entry.compressionMethod === 0) { var expectedCompressedSize = entry.uncompressedSize; if (entry.isEncrypted()) { expectedCompressedSize += 12; } if (entry.compressedSize !== expectedCompressedSize) { var msg = "compressed/uncompressed size mismatch for stored file: " + entry.compressedSize + " != " + entry.uncompressedSize; return emitErrorAndAutoClose(self, new Error(msg)); } } self.emit("entry", entry); if (!self.lazyEntries) self._readEntry(); }); }); }; ZipFile.prototype.openReadStream = function(entry, options2, callback) { var self = this; var relativeStart = 0; var relativeEnd = entry.compressedSize; if (callback == null) { callback = options2; options2 = null; } if (options2 == null) { options2 = {}; } else { if (options2.decrypt != null) { if (!entry.isEncrypted()) { throw new Error("options.decrypt can only be specified for encrypted entries"); } if (options2.decrypt !== false) throw new Error("invalid options.decrypt value: " + options2.decrypt); if (entry.isCompressed()) { if (options2.decompress !== false) throw new Error("entry is encrypted and compressed, and options.decompress !== false"); } } if (options2.decompress != null) { if (!entry.isCompressed()) { throw new Error("options.decompress can only be specified for compressed entries"); } if (!(options2.decompress === false || options2.decompress === true)) { throw new Error("invalid options.decompress value: " + options2.decompress); } } if (options2.start != null || options2.end != null) { if (entry.isCompressed() && options2.decompress !== false) { throw new Error("start/end range not allowed for compressed entry without options.decompress === false"); } if (entry.isEncrypted() && options2.decrypt !== false) { throw new Error("start/end range not allowed for encrypted entry without options.decrypt === false"); } } if (options2.start != null) { relativeStart = options2.start; if (relativeStart < 0) throw new Error("options.start < 0"); if (relativeStart > entry.compressedSize) throw new Error("options.start > entry.compressedSize"); } if (options2.end != null) { relativeEnd = options2.end; if (relativeEnd < 0) throw new Error("options.end < 0"); if (relativeEnd > entry.compressedSize) throw new Error("options.end > entry.compressedSize"); if (relativeEnd < relativeStart) throw new Error("options.end < options.start"); } } if (!self.isOpen) return callback(new Error("closed")); if (entry.isEncrypted()) { if (options2.decrypt !== false) return callback(new Error("entry is encrypted, and options.decrypt !== false")); } var decompress; if (entry.compressionMethod === 0) { decompress = false; } else if (entry.compressionMethod === 8) { decompress = options2.decompress != null ? options2.decompress : true; } else { return callback(new Error("unsupported compression method: " + entry.compressionMethod)); } self.readLocalFileHeader(entry, { minimal: true }, function(err, localFileHeader) { if (err) return callback(err); self.openReadStreamLowLevel( localFileHeader.fileDataStart, entry.compressedSize, relativeStart, relativeEnd, decompress, entry.uncompressedSize, callback ); }); }; ZipFile.prototype.openReadStreamLowLevel = function(fileDataStart, compressedSize, relativeStart, relativeEnd, decompress, uncompressedSize, callback) { var self = this; var fileDataEnd = fileDataStart + compressedSize; var readStream = self.reader.createReadStream({ start: fileDataStart + relativeStart, end: fileDataStart + relativeEnd }); var endpointStream = readStream; if (decompress) { var destroyed = false; var inflateFilter = zlib.createInflateRaw(); readStream.on("error", function(err) { setImmediate(function() { if (!destroyed) inflateFilter.emit("error", err); }); }); readStream.pipe(inflateFilter); if (self.validateEntrySizes) { endpointStream = new AssertByteCountStream(uncompressedSize); inflateFilter.on("error", function(err) { setImmediate(function() { if (!destroyed) endpointStream.emit("error", err); }); }); inflateFilter.pipe(endpointStream); } else { endpointStream = inflateFilter; } installDestroyFn(endpointStream, function() { destroyed = true; if (inflateFilter !== endpointStream) inflateFilter.unpipe(endpointStream); readStream.unpipe(inflateFilter); readStream.destroy(); }); } callback(null, endpointStream); }; ZipFile.prototype.readLocalFileHeader = function(entry, options2, callback) { var self = this; if (callback == null) { callback = options2; options2 = null; } if (options2 == null) options2 = {}; self.reader.ref(); var buffer = newBuffer(30); readAndAssertNoEof(self.reader, buffer, 0, buffer.length, entry.relativeOffsetOfLocalHeader, function(err) { try { if (err) return callback(err); var signature = buffer.readUInt32LE(0); if (signature !== 67324752) { return callback(new Error("invalid local file header signature: 0x" + signature.toString(16))); } var fileNameLength = buffer.readUInt16LE(26); var extraFieldLength = buffer.readUInt16LE(28); var fileDataStart = entry.relativeOffsetOfLocalHeader + 30 + fileNameLength + extraFieldLength; if (fileDataStart + entry.compressedSize > self.fileSize) { return callback(new Error("file data overflows file bounds: " + fileDataStart + " + " + entry.compressedSize + " > " + self.fileSize)); } if (options2.minimal) { return callback(null, { fileDataStart }); } var localFileHeader = new LocalFileHeader(); localFileHeader.fileDataStart = fileDataStart; localFileHeader.versionNeededToExtract = buffer.readUInt16LE(4); localFileHeader.generalPurposeBitFlag = buffer.readUInt16LE(6); localFileHeader.compressionMethod = buffer.readUInt16LE(8); localFileHeader.lastModFileTime = buffer.readUInt16LE(10); localFileHeader.lastModFileDate = buffer.readUInt16LE(12); localFileHeader.crc32 = buffer.readUInt32LE(14); localFileHeader.compressedSize = buffer.readUInt32LE(18); localFileHeader.uncompressedSize = buffer.readUInt32LE(22); localFileHeader.fileNameLength = fileNameLength; localFileHeader.extraFieldLength = extraFieldLength; buffer = newBuffer(fileNameLength + extraFieldLength); self.reader.ref(); readAndAssertNoEof(self.reader, buffer, 0, buffer.length, entry.relativeOffsetOfLocalHeader + 30, function(err2) { try { if (err2) return callback(err2); localFileHeader.fileName = buffer.subarray(0, fileNameLength); localFileHeader.extraField = buffer.subarray(fileNameLength); return callback(null, localFileHeader); } finally { self.reader.unref(); } }); } finally { self.reader.unref(); } }); }; function Entry() { } Entry.prototype.getLastModDate = function(options2) { if (options2 == null) options2 = {}; if (!options2.forceDosFormat) { for (var i = 0; i < this.extraFields.length; i++) { var extraField = this.extraFields[i]; if (extraField.id === 21589) { var data = extraField.data; if (data.length < 5) continue; var flags = data[0]; var HAS_MTIME = 1; if (!(flags & HAS_MTIME)) continue; var posixTimestamp = data.readInt32LE(1); return new Date(posixTimestamp * 1e3); } else if (extraField.id === 10) { var data = extraField.data; if (data.length !== 32) continue; if (data.readUInt16LE(4) !== 1) continue; if (data.readUInt16LE(6) !== 24) continue; var hundredNanoSecondsSince1601 = data.readUInt32LE(8) + 4294967296 * data.readInt32LE(12); var millisecondsSince1970 = hundredNanoSecondsSince1601 / 1e4 - 116444736e5; return new Date(millisecondsSince1970); } } } return dosDateTimeToDate(this.lastModFileDate, this.lastModFileTime, options2.timezone); }; Entry.prototype.isEncrypted = function() { return (this.generalPurposeBitFlag & 1) !== 0; }; Entry.prototype.isCompressed = function() { return this.compressionMethod === 8; }; function LocalFileHeader() { } function dosDateTimeToDate(date, time, timezone) { var day = date & 31; var month = (date >> 5 & 15) - 1; var year = (date >> 9 & 127) + 1980; var millisecond = 0; var second = (time & 31) * 2; var minute = time >> 5 & 63; var hour = time >> 11 & 31; if (timezone == null || timezone === "local") { return new Date(year, month, day, hour, minute, second, millisecond); } else if (timezone === "UTC") { return new Date(Date.UTC(year, month, day, hour, minute, second, millisecond)); } else { throw new Error("unrecognized options.timezone: " + options.timezone); } } function getFileNameLowLevel(generalPurposeBitFlag, fileNameBuffer, extraFields, strictFileNames) { var fileName = null; for (var i = 0; i < extraFields.length; i++) { var extraField = extraFields[i]; if (extraField.id === 28789) { if (extraField.data.length < 6) { continue; } if (extraField.data.readUInt8(0) !== 1) { continue; } var oldNameCrc32 = extraField.data.readUInt32LE(1); if (crc32.unsigned(fileNameBuffer) !== oldNameCrc32) { continue; } fileName = decodeBuffer(extraField.data.subarray(5), true); break; } } if (fileName == null) { var isUtf8 = (generalPurposeBitFlag & 2048) !== 0; fileName = decodeBuffer(fileNameBuffer, isUtf8); } if (!strictFileNames) { fileName = fileName.replace(/\\/g, "/"); } return fileName; } function validateFileName(fileName) { if (fileName.indexOf("\\") !== -1) { return "invalid characters in fileName: " + fileName; } if (/^[a-zA-Z]:/.test(fileName) || /^\//.test(fileName)) { return "absolute path: " + fileName; } if (fileName.split("/").indexOf("..") !== -1) { return "invalid relative path: " + fileName; } return null; } function parseExtraFields(extraFieldBuffer) { var extraFields = []; var i = 0; while (i < extraFieldBuffer.length - 3) { var headerId = extraFieldBuffer.readUInt16LE(i + 0); var dataSize = extraFieldBuffer.readUInt16LE(i + 2); var dataStart = i + 4; var dataEnd = dataStart + dataSize; if (dataEnd > extraFieldBuffer.length) throw new Error("extra field length exceeds extra field buffer size"); var dataBuffer = extraFieldBuffer.subarray(dataStart, dataEnd); extraFields.push({ id: headerId, data: dataBuffer }); i = dataEnd; } return extraFields; } function readAndAssertNoEof(reader, buffer, offset, length, position, callback) { if (length === 0) { return setImmediate(function() { callback(null, newBuffer(0)); }); } reader.read(buffer, offset, length, position, function(err, bytesRead) { if (err) return callback(err); if (bytesRead < length) { return callback(new Error("unexpected EOF")); } callback(); }); } util2.inherits(AssertByteCountStream, Transform); function AssertByteCountStream(byteCount) { Transform.call(this); this.actualByteCount = 0; this.expectedByteCount = byteCount; } AssertByteCountStream.prototype._transform = function(chunk, encoding, cb) { this.actualByteCount += chunk.length; if (this.actualByteCount > this.expectedByteCount) { var msg = "too many bytes in the stream. expected " + this.expectedByteCount + ". got at least " + this.actualByteCount; return cb(new Error(msg)); } cb(null, chunk); }; AssertByteCountStream.prototype._flush = function(cb) { if (this.actualByteCount < this.expectedByteCount) { var msg = "not enough bytes in the stream. expected " + this.expectedByteCount + ". got only " + this.actualByteCount; return cb(new Error(msg)); } cb(); }; util2.inherits(RandomAccessReader, EventEmitter); function RandomAccessReader() { EventEmitter.call(this); this.refCount = 0; } RandomAccessReader.prototype.ref = function() { this.refCount += 1; }; RandomAccessReader.prototype.unref = function() { var self = this; self.refCount -= 1; if (self.refCount > 0) return; if (self.refCount < 0) throw new Error("invalid unref"); self.close(onCloseDone); function onCloseDone(err) { if (err) return self.emit("error", err); self.emit("close"); } }; RandomAccessReader.prototype.createReadStream = function(options2) { if (options2 == null) options2 = {}; var start = options2.start; var end = options2.end; if (start === end) { var emptyStream = new PassThrough(); setImmediate(function() { emptyStream.end(); }); return emptyStream; } var stream = this._readStreamForRange(start, end); var destroyed = false; var refUnrefFilter = new RefUnrefFilter(this); stream.on("error", function(err) { setImmediate(function() { if (!destroyed) refUnrefFilter.emit("error", err); }); }); installDestroyFn(refUnrefFilter, function() { stream.unpipe(refUnrefFilter); refUnrefFilter.unref(); stream.destroy(); }); var byteCounter = new AssertByteCountStream(end - start); refUnrefFilter.on("error", function(err) { setImmediate(function() { if (!destroyed) byteCounter.emit("error", err); }); }); installDestroyFn(byteCounter, function() { destroyed = true; refUnrefFilter.unpipe(byteCounter); refUnrefFilter.destroy(); }); return stream.pipe(refUnrefFilter).pipe(byteCounter); }; RandomAccessReader.prototype._readStreamForRange = function(start, end) { throw new Error("not implemented"); }; RandomAccessReader.prototype.read = function(buffer, offset, length, position, callback) { var readStream = this.createReadStream({ start: position, end: position + length }); var writeStream = new Writable(); var written = 0; writeStream._write = function(chunk, encoding, cb) { chunk.copy(buffer, offset + written, 0, chunk.length); written += chunk.length; cb(); }; writeStream.on("finish", callback); readStream.on("error", function(error) { callback(error); }); readStream.pipe(writeStream); }; RandomAccessReader.prototype.close = function(callback) { setImmediate(callback); }; util2.inherits(RefUnrefFilter, PassThrough); function RefUnrefFilter(context) { PassThrough.call(this); this.context = context; this.context.ref(); this.unreffedYet = false; } RefUnrefFilter.prototype._flush = function(cb) { this.unref(); cb(); }; RefUnrefFilter.prototype.unref = function(cb) { if (this.unreffedYet) return; this.unreffedYet = true; this.context.unref(); }; var cp437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\xB6\xA7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0"; function decodeBuffer(buffer, isUtf8) { if (isUtf8) { return buffer.toString("utf8"); } else { var result = ""; for (var i = 0; i < buffer.length; i++) { result += cp437[buffer[i]]; } return result; } } function readUInt64LE(buffer, offset) { var lower32 = buffer.readUInt32LE(offset); var upper32 = buffer.readUInt32LE(offset + 4); return upper32 * 4294967296 + lower32; } var newBuffer; if (typeof Buffer.allocUnsafe === "function") { newBuffer = function(len) { return Buffer.allocUnsafe(len); }; } else { newBuffer = function(len) { return new Buffer(len); }; } function installDestroyFn(stream, fn) { if (typeof stream.destroy === "function") { stream._destroy = function(err, cb) { fn(); if (cb != null) cb(err); }; } else { stream.destroy = fn; } } function defaultCallback(err) { if (err) throw err; } } }); // packages/playwright/src/worker/workerProcessEntry.ts var import_common4 = require("../common"); // packages/playwright/src/worker/workerMain.ts var import_common3 = require("../common"); var globals = __toESM(require("../globals")); var import_expect = require("../matchers/expect"); // packages/playwright/src/util.ts var import_fs = __toESM(require("fs")); var import_path = __toESM(require("path")); var import_util = __toESM(require("util")); var debug = require("playwright-core/lib/utilsBundle").debug; var mime = require("playwright-core/lib/utilsBundle").mime; var minimatch = require("playwright-core/lib/utilsBundle").minimatch; var { calculateSha1 } = require("playwright-core/lib/coreBundle").utils; var { sanitizeForFilePath } = require("playwright-core/lib/coreBundle").utils; var { isRegExp } = require("playwright-core/lib/coreBundle").iso; var { parseStackFrame, stringifyStackFrames } = require("playwright-core/lib/coreBundle").iso; var { ansiRegex, isString, stripAnsiEscapes } = require("playwright-core/lib/coreBundle").iso; var PLAYWRIGHT_TEST_PATH = import_path.default.join(__dirname, ".."); var PLAYWRIGHT_CORE_PATH = import_path.default.dirname(require.resolve("playwright-core/package.json")); function filterStackTrace(e) { const name = e.name ? e.name + ": " : ""; const cause = e.cause instanceof Error ? filterStackTrace(e.cause) : void 0; if (process.env.PWDEBUGIMPL) return { message: name + e.message, stack: e.stack || "", cause }; const stackLines = stringifyStackFrames(filteredStackTrace(e.stack?.split("\n") || [])); return { message: name + e.message, stack: `${name}${e.message}${stackLines.map((line) => "\n" + line).join("")}`, cause }; } function filterStackFile(file) { if (process.env.PWDEBUGIMPL) return true; if (file.startsWith(PLAYWRIGHT_TEST_PATH)) return false; if (file.startsWith(PLAYWRIGHT_CORE_PATH)) return false; return true; } function filteredStackTrace(rawStack) { const frames = []; for (const line of rawStack) { const frame = parseStackFrame(line, import_path.default.sep, !!process.env.PWDEBUGIMPL); if (!frame || !frame.file) continue; if (!filterStackFile(frame.file)) continue; frames.push(frame); } return frames; } function serializeError(error) { if (error instanceof Error) return filterStackTrace(error); return { value: import_util.default.inspect(error) }; } function relativeFilePath(file) { if (!import_path.default.isAbsolute(file)) return file; return import_path.default.relative(process.cwd(), file); } function formatLocation(location) { return relativeFilePath(location.file) + ":" + location.line + ":" + location.column; } var windowsFilesystemFriendlyLength = 60; function trimLongString(s, length = 100) { if (s.length <= length) return s; const hash = calculateSha1(s); const middle = `-${hash.substring(0, 5)}-`; const start = Math.floor((length - middle.length) / 2); const end = length - middle.length - start; return s.substring(0, start) + middle + s.slice(-end); } function addSuffixToFilePath(filePath, suffix) { const ext = import_path.default.extname(filePath); const base = filePath.substring(0, filePath.length - ext.length); return base + suffix + ext; } function sanitizeFilePathBeforeExtension(filePath, ext) { ext ??= import_path.default.extname(filePath); const base = filePath.substring(0, filePath.length - ext.length); return sanitizeForFilePath(base) + ext; } function getContainedPath(parentPath, subPath = "") { const resolvedPath = import_path.default.resolve(parentPath, subPath); if (resolvedPath === parentPath || resolvedPath.startsWith(parentPath + import_path.default.sep)) return resolvedPath; return null; } var debugTest = debug("pw:test"); async function normalizeAndSaveAttachment(outputPath, name, options2 = {}) { if (options2.path === void 0 && options2.body === void 0) return { name, contentType: "text/plain" }; if ((options2.path !== void 0 ? 1 : 0) + (options2.body !== void 0 ? 1 : 0) !== 1) throw new Error(`Exactly one of "path" and "body" must be specified`); if (options2.path !== void 0) { const hash = calculateSha1(options2.path); if (!isString(name)) throw new Error('"name" should be string.'); const sanitizedNamePrefix = sanitizeForFilePath(name) + "-"; const dest = import_path.default.join(outputPath, "attachments", sanitizedNamePrefix + hash + import_path.default.extname(options2.path)); await import_fs.default.promises.mkdir(import_path.default.dirname(dest), { recursive: true }); await import_fs.default.promises.copyFile(options2.path, dest); const contentType = options2.contentType ?? (mime.getType(import_path.default.basename(options2.path)) || "application/octet-stream"); return { name, contentType, path: dest }; } else { const contentType = options2.contentType ?? (typeof options2.body === "string" ? "text/plain" : "application/octet-stream"); return { name, contentType, body: typeof options2.body === "string" ? Buffer.from(options2.body) : options2.body }; } } // packages/playwright/src/worker/fixtureRunner.ts var import_common = require("../common"); var { ManualPromise } = require("playwright-core/lib/coreBundle").iso; var { escapeWithQuotes } = require("playwright-core/lib/coreBundle").iso; var Fixture = class { constructor(runner, registration) { this.failed = false; this._deps = /* @__PURE__ */ new Set(); this._usages = /* @__PURE__ */ new Set(); this.runner = runner; this.registration = registration; this.value = null; const isUserFixture = this.registration.location && filterStackFile(this.registration.location.file); const title = this.registration.customTitle || this.registration.name; const location = isUserFixture ? this.registration.location : void 0; this._stepInfo = { title: `Fixture ${escapeWithQuotes(title, '"')}`, category: "fixture", location }; if (this.registration.box === "self") this._stepInfo = void 0; else if (this.registration.box) this._stepInfo.group = isUserFixture ? "configuration" : "internal"; this._setupDescription = { title, phase: "setup", location, slot: this.registration.timeout !== void 0 ? { timeout: this.registration.timeout, elapsed: 0 } : this.registration.scope === "worker" ? { timeout: this.runner.workerFixtureTimeout, elapsed: 0 } : void 0 }; this._teardownDescription = { ...this._setupDescription, phase: "teardown" }; } async setup(testInfo, runnable) { this.runner.instanceForId.set(this.registration.id, this); if (typeof this.registration.fn !== "function") { this.value = this.registration.fn; return; } const run = () => testInfo._runWithTimeout({ ...runnable, fixture: this._setupDescription }, () => this._setupInternal(testInfo)); if (this._stepInfo) await testInfo._runAsStep(this._stepInfo, run); else await run(); } async _setupInternal(testInfo) { const params = {}; for (const name of this.registration.deps) { const registration = this.runner.pool.resolve(name, this.registration); const dep = this.runner.instanceForId.get(registration.id); if (!dep) { this.failed = true; return; } dep._usages.add(this); this._deps.add(dep); params[name] = dep.value; if (dep.failed) { this.failed = true; return; } } let called = false; const useFuncStarted = new ManualPromise(); const useFunc = async (value) => { if (called) throw new Error(`Cannot provide fixture value for the second time`); called = true; this.value = value; this._useFuncFinished = new ManualPromise(); useFuncStarted.resolve(); await this._useFuncFinished; }; const workerInfo = { config: testInfo.config, parallelIndex: testInfo.parallelIndex, workerIndex: testInfo.workerIndex, project: testInfo.project }; const info = this.registration.scope === "worker" ? workerInfo : testInfo; this._selfTeardownComplete = (async () => { try { await this.registration.fn(params, useFunc, info); if (!useFuncStarted.isDone()) throw new Error(`use() was not called in fixture "${this.registration.name}"`); } catch (error) { this.failed = true; if (!useFuncStarted.isDone()) useFuncStarted.reject(error); else throw error; } })(); await useFuncStarted; } async teardown(testInfo, runnable) { try { const fixtureRunnable = { ...runnable, fixture: this._teardownDescription }; if (!testInfo._timeoutManager.isTimeExhaustedFor(fixtureRunnable)) { const run = () => testInfo._runWithTimeout(fixtureRunnable, () => this._teardownInternal()); if (this._stepInfo) await testInfo._runAsStep(this._stepInfo, run); else await run(); } } finally { for (const dep of this._deps) dep._usages.delete(this); this.runner.instanceForId.delete(this.registration.id); } } async _teardownInternal() { if (typeof this.registration.fn !== "function") return; if (this._usages.size !== 0) { console.error("Internal error: fixture integrity at", this._teardownDescription.title); this._usages.clear(); } if (this._useFuncFinished) { this._useFuncFinished.resolve(); this._useFuncFinished = void 0; await this._selfTeardownComplete; } } _collectFixturesInTeardownOrder(scope, collector) { if (this.registration.scope !== scope) return; for (const fixture of this._usages) fixture._collectFixturesInTeardownOrder(scope, collector); collector.add(this); } }; var FixtureRunner = class { constructor() { this.testScopeClean = true; this.instanceForId = /* @__PURE__ */ new Map(); this.workerFixtureTimeout = 0; } setPool(pool) { if (!this.testScopeClean) throw new Error("Did not teardown test scope"); if (this.pool && pool.digest !== this.pool.digest) { throw new Error([ `Playwright detected inconsistent test.use() options.`, `Most common mistakes that lead to this issue:`, ` - Calling test.use() outside of the test file, for example in a common helper.`, ` - One test file imports from another test file.` ].join("\n")); } this.pool = pool; } _collectFixturesInSetupOrder(registration, collector) { if (collector.has(registration)) return; for (const name of registration.deps) { const dep = this.pool.resolve(name, registration); this._collectFixturesInSetupOrder(dep, collector); } collector.add(registration); } async teardownScope(scope, testInfo, runnable) { const allFixtures = Array.from(this.instanceForId.values()).reverse(); const collector = /* @__PURE__ */ new Set(); for (const fixture of allFixtures) fixture._collectFixturesInTeardownOrder(scope, collector); let firstError; for (const fixture of collector) { try { await fixture.teardown(testInfo, runnable); } catch (error) { firstError = firstError ?? error; } } if (scope === "test") this.testScopeClean = true; if (firstError) throw firstError; } async resolveParametersForFunction(fn, testInfo, autoFixtures, runnable) { const collector = /* @__PURE__ */ new Set(); const auto = []; for (const registration of this.pool.autoFixtures()) { let shouldRun = true; if (autoFixtures === "all-hooks-only") shouldRun = registration.scope === "worker" || registration.auto === "all-hooks-included"; else if (autoFixtures === "worker") shouldRun = registration.scope === "worker"; if (shouldRun) auto.push(registration); } auto.sort((r1, r2) => (r1.scope === "worker" ? 0 : 1) - (r2.scope === "worker" ? 0 : 1)); for (const registration of auto) this._collectFixturesInSetupOrder(registration, collector); const names = getRequiredFixtureNames(fn); for (const name of names) this._collectFixturesInSetupOrder(this.pool.resolve(name), collector); for (const registration of collector) await this._setupFixtureForRegistration(registration, testInfo, runnable); const params = {}; for (const name of names) { const registration = this.pool.resolve(name); const fixture = this.instanceForId.get(registration.id); if (!fixture || fixture.failed) return null; params[name] = fixture.value; } return { result: params }; } async resolveParametersAndRunFunction(fn, testInfo, autoFixtures, runnable) { const params = await this.resolveParametersForFunction(fn, testInfo, autoFixtures, runnable); if (params === null) { return null; } await testInfo._runWithTimeout(runnable, () => fn(params.result, testInfo)); } async _setupFixtureForRegistration(registration, testInfo, runnable) { if (registration.scope === "test") this.testScopeClean = false; let fixture = this.instanceForId.get(registration.id); if (fixture) return fixture; fixture = new Fixture(this, registration); await fixture.setup(testInfo, runnable); return fixture; } dependsOnWorkerFixturesOnly(fn, location) { const names = getRequiredFixtureNames(fn, location); for (const name of names) { const registration = this.pool.resolve(name); if (registration.scope !== "worker") return false; } return true; } }; function getRequiredFixtureNames(fn, location) { return import_common.fixtures.fixtureParameterNames(fn, location ?? { file: "", line: 1, column: 1 }, (e) => { throw new Error(`${formatLocation(e.location)}: ${e.message}`); }); } // packages/playwright/src/worker/testInfo.ts var import_fs3 = __toESM(require("fs")); var import_path3 = __toESM(require("path")); // packages/playwright/src/worker/timeoutManager.ts var colors = require("playwright-core/lib/utilsBundle").colors; var { ManualPromise: ManualPromise2 } = require("playwright-core/lib/coreBundle").iso; var { monotonicTime } = require("playwright-core/lib/coreBundle").iso; var kMaxDeadline = 2147483647; var TimeoutManager = class { constructor(timeout) { this._ignoreTimeouts = false; this._slow = false; this._defaultSlot = { timeout, elapsed: 0 }; } setIgnoreTimeouts(ignoreTimeouts) { if (this._ignoreTimeouts === ignoreTimeouts) return; this._ignoreTimeouts = ignoreTimeouts; if (this._running) { if (ignoreTimeouts) this._running.slot.elapsed += monotonicTime() - this._running.start; else this._running.start = monotonicTime(); this._updateTimeout(this._running); } } interrupt() { if (this._running) this._running.timeoutPromise.reject(this._createTimeoutError(this._running)); } isTimeExhaustedFor(runnable) { const slot = runnable.fixture?.slot || runnable.slot || this._defaultSlot; return slot.timeout > 0 && slot.elapsed >= slot.timeout - 1; } async withRunnable(runnable, cb) { if (this._running) throw new Error(`Internal error: duplicate runnable`); const running = this._running = { runnable, slot: runnable.fixture?.slot || runnable.slot || this._defaultSlot, start: monotonicTime(), deadline: kMaxDeadline, timer: void 0, timeoutPromise: new ManualPromise2() }; let debugTitle = ""; try { if (debugTest.enabled) { debugTitle = runnable.fixture ? `${runnable.fixture.phase} "${runnable.fixture.title}"` : runnable.type; const location = runnable.location ? ` at "${formatLocation(runnable.location)}"` : ``; debugTest(`started ${debugTitle}${location}`); } this._updateTimeout(running); return await Promise.race([ cb(), running.timeoutPromise ]); } finally { if (running.timer) clearTimeout(running.timer); running.timer = void 0; running.slot.elapsed += monotonicTime() - running.start; this._running = void 0; if (debugTest.enabled) debugTest(`finished ${debugTitle}`); } } _updateTimeout(running) { if (running.timer) clearTimeout(running.timer); running.timer = void 0; if (this._ignoreTimeouts || !running.slot.timeout) { running.deadline = kMaxDeadline; return; } running.deadline = running.start + (running.slot.timeout - running.slot.elapsed); const timeout = running.deadline - monotonicTime() + 1; if (timeout <= 0) running.timeoutPromise.reject(this._createTimeoutError(running)); else running.timer = setTimeout(() => running.timeoutPromise.reject(this._createTimeoutError(running)), timeout); } defaultSlot() { return this._defaultSlot; } slow() { if (this._slow) return; this._slow = true; const slot = this._running ? this._running.slot : this._defaultSlot; slot.timeout = slot.timeout * 3; if (this._running) this._updateTimeout(this._running); } setTimeout(timeout) { const slot = this._running ? this._running.slot : this._defaultSlot; slot.timeout = timeout; if (this._running) this._updateTimeout(this._running); } currentSlotDeadline() { return this._running ? this._running.deadline : kMaxDeadline; } currentSlotType() { return this._running ? this._running.runnable.type : "test"; } _createTimeoutError(running) { let message = ""; const timeout = running.slot.timeout; const runnable = running.runnable; switch (runnable.type) { case "test": { if (runnable.fixture) { if (runnable.fixture.phase === "setup") message = `Test timeout of ${timeout}ms exceeded while setting up "${runnable.fixture.title}".`; else message = `Tearing down "${runnable.fixture.title}" exceeded the test timeout of ${timeout}ms.`; } else { message = `Test timeout of ${timeout}ms exceeded.`; } break; } case "afterEach": case "beforeEach": message = `Test timeout of ${timeout}ms exceeded while running "${runnable.type}" hook.`; break; case "beforeAll": case "afterAll": message = `"${runnable.type}" hook timeout of ${timeout}ms exceeded.`; break; case "teardown": { if (runnable.fixture) message = `Worker teardown timeout of ${timeout}ms exceeded while ${runnable.fixture.phase === "setup" ? "setting up" : "tearing down"} "${runnable.fixture.title}".`; else message = `Worker teardown timeout of ${timeout}ms exceeded.`; break; } case "skip": case "slow": case "fixme": case "fail": message = `"${runnable.type}" modifier timeout of ${timeout}ms exceeded.`; break; } const fixtureWithSlot = runnable.fixture?.slot ? runnable.fixture : void 0; if (fixtureWithSlot) message = `Fixture "${fixtureWithSlot.title}" timeout of ${timeout}ms exceeded during ${fixtureWithSlot.phase}.`; message = colors.red(message); const location = (fixtureWithSlot || runnable).location; const error = new TimeoutManagerError(message); error.name = ""; error.stack = message + (location ? ` at ${location.file}:${location.line}:${location.column}` : ""); return error; } }; var TimeoutManagerError = class extends Error { }; // packages/playwright/src/worker/testTracing.ts var import_fs2 = __toESM(require("fs")); var import_path2 = __toESM(require("path")); var yauzl = __toESM(require_yauzl()); var import_coreBundle = require("playwright-core/lib/coreBundle"); var yazl = require("playwright-core/lib/utilsBundle").yazl; var { ManualPromise: ManualPromise3 } = require("playwright-core/lib/coreBundle").iso; var { monotonicTime: monotonicTime2 } = require("playwright-core/lib/coreBundle").iso; var { calculateSha1: calculateSha12, createGuid } = require("playwright-core/lib/coreBundle").utils; var { SerializedFS } = require("playwright-core/lib/coreBundle").utils; var testTraceEntryName = "test.trace"; var version = 8; var traceOrdinal = 0; var TestTracing = class { constructor(testInfo, artifactsDir) { this._traceEvents = []; this._temporaryTraceFiles = []; this._didFinishTestFunctionAndAfterEachHooks = false; this._testInfo = testInfo; this._artifactsDir = artifactsDir; this._tracesDir = import_path2.default.join(this._artifactsDir, "traces"); this._contextCreatedEvent = { version, type: "context-options", origin: "testRunner", browserName: "", playwrightVersion: (0, import_coreBundle.getPlaywrightVersion)(), options: {}, platform: process.platform, wallTime: Date.now(), monotonicTime: monotonicTime2(), sdkLanguage: "javascript" }; this._appendTraceEvent(this._contextCreatedEvent); } _shouldCaptureTrace() { if (this._options?.mode === "on") return true; if (this._options?.mode === "retain-on-failure") return true; if (this._options?.mode === "on-first-retry" && this._testInfo.retry === 1) return true; if (this._options?.mode === "on-all-retries" && this._testInfo.retry > 0) return true; if (this._options?.mode === "retain-on-first-failure" && this._testInfo.retry === 0) return true; if (this._options?.mode === "retain-on-failure-and-retries") return true; return false; } async startIfNeeded(value) { const defaultTraceOptions = { screenshots: true, snapshots: true, sources: true, attachments: true, live: false, mode: "off" }; if (!value) { this._options = defaultTraceOptions; } else if (typeof value === "string") { this._options = { ...defaultTraceOptions, mode: value === "retry-with-trace" ? "on-first-retry" : value }; } else { const mode = value.mode || "off"; this._options = { ...defaultTraceOptions, ...value, mode: mode === "retry-with-trace" ? "on-first-retry" : mode }; } if (!this._shouldCaptureTrace()) { this._options = void 0; return; } if (!this._liveTraceFile && this._options.live) { this._liveTraceFile = { file: import_path2.default.join(this._tracesDir, `${this._testInfo.testId}-test.trace`), fs: new SerializedFS() }; this._liveTraceFile.fs.mkdir(import_path2.default.dirname(this._liveTraceFile.file)); const data = this._traceEvents.map((e) => JSON.stringify(e)).join("\n") + "\n"; this._liveTraceFile.fs.writeFile(this._liveTraceFile.file, data); } } didFinishTestFunctionAndAfterEachHooks() { this._didFinishTestFunctionAndAfterEachHooks = true; } artifactsDir() { return this._artifactsDir; } tracesDir() { return this._tracesDir; } traceTitle() { return [import_path2.default.relative(this._testInfo.project.testDir, this._testInfo.file) + ":" + this._testInfo.line, ...this._testInfo.titlePath.slice(1)].join(" \u203A "); } generateNextTraceRecordingName() { const ordinalSuffix = traceOrdinal ? `-recording${traceOrdinal}` : ""; ++traceOrdinal; const retrySuffix = this._testInfo.retry ? `-retry${this._testInfo.retry}` : ""; return `${this._testInfo.testId}${retrySuffix}${ordinalSuffix}`; } _generateNextTraceRecordingPath() { const file = import_path2.default.join(this._artifactsDir, createGuid() + ".zip"); this._temporaryTraceFiles.push(file); return file; } traceOptions() { return this._options; } maybeGenerateNextTraceRecordingPath() { if (this._didFinishTestFunctionAndAfterEachHooks && this._shouldAbandonTrace()) return; return this._generateNextTraceRecordingPath(); } _shouldAbandonTrace() { if (!this._options) return true; const testFailed = this._testInfo.status !== this._testInfo.expectedStatus; if (this._options.mode === "retain-on-failure-and-retries") return !testFailed && this._testInfo.retry === 0; return !testFailed && (this._options.mode === "retain-on-failure" || this._options.mode === "retain-on-first-failure"); } async stopIfNeeded() { this._contextCreatedEvent.testTimeout = this._testInfo.timeout; if (!this._options) return; const error = await this._liveTraceFile?.fs.syncAndGetError(); if (error) throw error; if (this._shouldAbandonTrace()) { for (const file of this._temporaryTraceFiles) await import_fs2.default.promises.unlink(file).catch(() => { }); return; } const zipFile = new yazl.ZipFile(); if (!this._options?.attachments) { for (const event of this._traceEvents) { if (event.type === "after") delete event.attachments; } } if (this._options?.sources) { const sourceFiles = /* @__PURE__ */ new Set(); for (const event of this._traceEvents) { if (event.type === "before") { for (const frame of event.stack || []) sourceFiles.add(frame.file); } } for (const sourceFile of sourceFiles) { await import_fs2.default.promises.readFile(sourceFile, "utf8").then((source) => { zipFile.addBuffer(Buffer.from(source), "resources/src@" + calculateSha12(sourceFile) + ".txt"); }).catch(() => { }); } } const sha1s = /* @__PURE__ */ new Set(); for (const event of this._traceEvents.filter((e) => e.type === "after")) { for (const attachment of event.attachments || []) { let contentPromise; if (attachment.path) contentPromise = import_fs2.default.promises.readFile(attachment.path).catch(() => void 0); else if (attachment.base64) contentPromise = Promise.resolve(Buffer.from(attachment.base64, "base64")); const content = await contentPromise; if (content === void 0) continue; const sha1 = calculateSha12(content); attachment.sha1 = sha1; delete attachment.path; delete attachment.base64; if (sha1s.has(sha1)) continue; sha1s.add(sha1); zipFile.addBuffer(content, "resources/" + sha1); } } const traceContent = Buffer.from(this._traceEvents.map((e) => JSON.stringify(e)).join("\n")); zipFile.addBuffer(traceContent, testTraceEntryName); await new Promise((f) => { zipFile.end(void 0, () => { zipFile.outputStream.pipe(import_fs2.default.createWriteStream(this._generateNextTraceRecordingPath())).on("close", f); }); }); const tracePath = this._testInfo.outputPath("trace.zip"); await mergeTraceFiles(tracePath, this._temporaryTraceFiles); this._testInfo.attachments.push({ name: "trace", path: tracePath, contentType: "application/zip" }); } appendForError(error) { const rawStack = error.stack?.split("\n") || []; const stack = rawStack ? filteredStackTrace(rawStack) : []; this._appendTraceEvent({ type: "error", message: this._formatError(error), stack }); } _formatError(error) { const parts = [error.message || String(error.value)]; if (error.cause) parts.push("[cause]: " + this._formatError(error.cause)); return parts.join("\n"); } appendStdioToTrace(type, chunk) { this._appendTraceEvent({ type, timestamp: monotonicTime2(), text: typeof chunk === "string" ? chunk : void 0, base64: typeof chunk === "string" ? void 0 : chunk.toString("base64") }); } appendBeforeActionForStep(options2) { this._appendTraceEvent({ type: "before", callId: options2.stepId, stepId: options2.stepId, parentId: options2.parentId, startTime: monotonicTime2(), class: "Test", method: options2.category, title: options2.title, params: Object.fromEntries(Object.entries(options2.params || {}).map(([name, value]) => [name, generatePreview(value)])), stack: options2.stack, group: options2.group }); } appendAfterActionForStep(callId, error, attachments = [], annotations) { this._appendTraceEvent({ type: "after", callId, endTime: monotonicTime2(), attachments: serializeAttachments(attachments), annotations, error }); } _appendTraceEvent(event) { this._traceEvents.push(event); if (this._liveTraceFile) this._liveTraceFile.fs.appendFile(this._liveTraceFile.file, JSON.stringify(event) + "\n", true); } }; function serializeAttachments(attachments) { if (attachments.length === 0) return void 0; return attachments.filter((a) => a.name !== "trace").map((a) => { return { name: a.name, contentType: a.contentType, path: a.path, base64: a.body?.toString("base64") }; }); } function generatePreview(value, visited = /* @__PURE__ */ new Set()) { if (visited.has(value)) return ""; visited.add(value); if (typeof value === "string") return value; if (typeof value === "number") return value.toString(); if (typeof value === "boolean") return value.toString(); if (value === null) return "null"; if (value === void 0) return "undefined"; if (Array.isArray(value)) return "[" + value.map((v) => generatePreview(v, visited)).join(", ") + "]"; if (typeof value === "object") return "Object"; return String(value); } async function mergeTraceFiles(fileName, temporaryTraceFiles) { temporaryTraceFiles = temporaryTraceFiles.filter((file) => import_fs2.default.existsSync(file)); if (temporaryTraceFiles.length === 1) { await import_fs2.default.promises.rename(temporaryTraceFiles[0], fileName); return; } const mergePromise = new ManualPromise3(); const zipFile = new yazl.ZipFile(); const entryNames = /* @__PURE__ */ new Set(); zipFile.on("error", (error) => mergePromise.reject(error)); for (let i = temporaryTraceFiles.length - 1; i >= 0; --i) { const tempFile = temporaryTraceFiles[i]; const promise = new ManualPromise3(); yauzl.open(tempFile, (err, inZipFile) => { if (err) { promise.reject(err); return; } let pendingEntries = inZipFile.entryCount; inZipFile.on("entry", (entry) => { let entryName = entry.fileName; if (entry.fileName === testTraceEntryName) { } else if (entry.fileName.match(/trace\.[a-z]*$/)) { entryName = i + "-" + entry.fileName; } if (entryNames.has(entryName)) { if (--pendingEntries === 0) promise.resolve(); return; } entryNames.add(entryName); inZipFile.openReadStream(entry, (err2, readStream) => { if (err2) { promise.reject(err2); return; } zipFile.addReadStream(readStream, entryName); if (--pendingEntries === 0) promise.resolve(); }); }); }); await promise; } zipFile.end(void 0, () => { zipFile.outputStream.pipe(import_fs2.default.createWriteStream(fileName)).on("close", () => { void Promise.all(temporaryTraceFiles.map((tempFile) => import_fs2.default.promises.unlink(tempFile))).then(() => { mergePromise.resolve(); }).catch((error) => mergePromise.reject(error)); }).on("error", (error) => mergePromise.reject(error)); }); await mergePromise; } // packages/playwright/src/worker/util.ts function testInfoError(error) { const result = serializeError(error); const matcherResult = error instanceof Error ? error.matcherResult : void 0; if (matcherResult?.ariaSnapshot !== void 0) result.errorContext = matcherResult.ariaSnapshot; return result; } // packages/playwright/src/worker/testInfo.ts var import_common2 = require("../common"); var { ManualPromise: ManualPromise4 } = require("playwright-core/lib/coreBundle").iso; var { captureRawStack, stringifyStackFrames: stringifyStackFrames2 } = require("playwright-core/lib/coreBundle").iso; var { escapeWithQuotes: escapeWithQuotes2 } = require("playwright-core/lib/coreBundle").iso; var { monotonicTime: monotonicTime3 } = require("playwright-core/lib/coreBundle").iso; var { createGuid: createGuid2 } = require("playwright-core/lib/coreBundle").utils; var { sanitizeForFilePath: sanitizeForFilePath2 } = require("playwright-core/lib/coreBundle").utils; var { currentZone } = require("playwright-core/lib/coreBundle").utils; var emtpyTestInfoCallbacks = { onStepBegin: () => { }, onStepEnd: () => { }, onAttach: () => { }, onTestPaused: () => Promise.reject(new Error("TestInfoImpl not initialized")) }; var TestInfoImpl = class { constructor(configInternal, projectInternal, workerParams, test, retry, callbacks) { this._snapshotNames = { lastAnonymousSnapshotIndex: 0, lastNamedSnapshotIndex: {} }; this._ariaSnapshotNames = { lastAnonymousSnapshotIndex: 0, lastNamedSnapshotIndex: {} }; this._interruptedPromise = new ManualPromise4(); this._lastStepId = 0; this._steps = []; this._stepMap = /* @__PURE__ */ new Map(); this._onDidFinishTestFunctionCallbacks = /* @__PURE__ */ new Set(); this._hasNonRetriableError = false; this._hasUnhandledError = false; this._allowSkips = false; this.duration = 0; this.annotations = []; this.attachments = []; this.status = "passed"; this.snapshotSuffix = ""; this.errors = []; this._ignoreTimeoutsCounter = 0; this.testId = test?.id ?? ""; this._callbacks = callbacks; this._startTime = monotonicTime3(); this._startWallTime = Date.now(); this._requireFile = test?._requireFile ?? ""; this._uniqueSymbol = Symbol("testInfoUniqueSymbol"); this._workerParams = workerParams; this.repeatEachIndex = workerParams.repeatEachIndex; this.retry = retry; this.workerIndex = workerParams.workerIndex; this.parallelIndex = workerParams.parallelIndex; this._projectInternal = projectInternal; this.project = projectInternal.project; this._configInternal = configInternal; this.config = configInternal.config; this.title = test?.title ?? ""; this.titlePath = test?.titlePath() ?? []; this.file = test?.location.file ?? ""; this.line = test?.location.line ?? 0; this.column = test?.location.column ?? 0; this.tags = test?.tags ?? []; this.fn = test?.fn ?? (() => { }); this.expectedStatus = test?.expectedStatus ?? "skipped"; this._timeoutManager = new TimeoutManager(this.project.timeout); if (configInternal.configCLIOverrides.debug === "inspector") this._setIgnoreTimeouts(true); this.outputDir = (() => { const relativeTestFilePath = import_path3.default.relative(this.project.testDir, this._requireFile.replace(/\.(spec|test)\.(js|ts|jsx|tsx|mjs|mts|cjs|cts)$/, "")); const sanitizedRelativePath = relativeTestFilePath.replace(process.platform === "win32" ? new RegExp("\\\\", "g") : new RegExp("/", "g"), "-"); const fullTitleWithoutSpec = this.titlePath.slice(1).join(" "); let testOutputDir = trimLongString(sanitizedRelativePath + "-" + sanitizeForFilePath2(fullTitleWithoutSpec), windowsFilesystemFriendlyLength); if (projectInternal.id) testOutputDir += "-" + sanitizeForFilePath2(projectInternal.id); if (this.retry) testOutputDir += "-retry" + this.retry; if (this.repeatEachIndex) testOutputDir += "-repeat" + this.repeatEachIndex; return import_path3.default.join(this.project.outputDir, testOutputDir); })(); this.snapshotDir = (() => { const relativeTestFilePath = import_path3.default.relative(this.project.testDir, this._requireFile); return import_path3.default.join(this.project.snapshotDir, relativeTestFilePath + "-snapshots"); })(); this._attachmentsPush = this.attachments.push.bind(this.attachments); const attachmentsPush = (...attachments) => { for (const a of attachments) this._attach(a, this._parentStep()?.stepId); return this.attachments.length; }; Object.defineProperty(this.attachments, "push", { value: attachmentsPush, writable: true, enumerable: false, configurable: true }); this._tracing = new TestTracing(this, workerParams.artifactsDir); this.skip = import_common2.transform.wrapFunctionWithLocation((location, ...args) => this._modifier("skip", location, args)); this.fixme = import_common2.transform.wrapFunctionWithLocation((location, ...args) => this._modifier("fixme", location, args)); this.fail = import_common2.transform.wrapFunctionWithLocation((location, ...args) => this._modifier("fail", location, args)); this.slow = import_common2.transform.wrapFunctionWithLocation((location, ...args) => this._modifier("slow", location, args)); } get error() { return this.errors[0]; } set error(e) { if (e === void 0) throw new Error("Cannot assign testInfo.error undefined value!"); this.errors[0] = e; } get timeout() { return this._timeoutManager.defaultSlot().timeout; } set timeout(timeout) { } _deadline() { return { deadline: this._timeoutManager.currentSlotDeadline(), timeout: this.timeout }; } _modifier(type, location, modifierArgs) { if (typeof modifierArgs[1] === "function") { throw new Error([ "It looks like you are calling test.skip() inside the test and pass a callback.", "Pass a condition instead and optional description instead:", `test('my test', async ({ page, isMobile }) => {`, ` test.skip(isMobile, 'This test is not applicable on mobile');`, `});` ].join("\n")); } if (modifierArgs.length >= 1 && !modifierArgs[0]) return; const description = modifierArgs[1]; this.annotations.push({ type, description, location }); if (type === "slow") { this._timeoutManager.slow(); } else if (type === "skip" || type === "fixme") { this.expectedStatus = "skipped"; throw new TestSkipError("Test is skipped: " + (description || "")); } else if (type === "fail") { if (this.expectedStatus !== "skipped") this.expectedStatus = "failed"; } } _findLastPredefinedStep(steps) { for (let i = steps.length - 1; i >= 0; i--) { const child = this._findLastPredefinedStep(steps[i].steps); if (child) return child; if ((steps[i].category === "hook" || steps[i].category === "fixture") && !steps[i].endWallTime) return steps[i]; } } _parentStep() { return currentZone().data("stepZone") ?? this._findLastPredefinedStep(this._steps); } _addStep(data, parentStep) { const stepId = `${data.category}@${++this._lastStepId}`; if (data.category === "hook" || data.category === "fixture") { parentStep = this._findLastPredefinedStep(this._steps); } else { if (!parentStep) parentStep = this._parentStep(); } const filteredStack = filteredStackTrace(captureRawStack()); let boxedStack = parentStep?.boxedStack; let location = data.location; if (!boxedStack && data.box) { boxedStack = filteredStack.slice(1); location = location || boxedStack[0]; } location = location || filteredStack[0]; const step = { ...data, stepId, group: parentStep?.group ?? data.group, boxedStack, location, steps: [], attachmentIndices: [], info: new TestStepInfoImpl(this, stepId, data.title, parentStep?.info), complete: (result) => { if (step.endWallTime) return; step.endWallTime = Date.now(); if (result.attachments) { for (const attachment of result.attachments) this._attach(attachment, stepId); } if (result.error) { if (typeof result.error === "object" && !result.error?.[stepSymbol]) result.error[stepSymbol] = step; const error = testInfoError(result.error); if (step.boxedStack) error.stack = `${error.message} ${stringifyStackFrames2(step.boxedStack).join("\n")}`; step.error = error; } if (result.softError) { step.infectParentStepsWithError = true; this._failWithError(result.softError); } if (result.shouldNotRetryTest) this._hasNonRetriableError = true; if (!step.error) { for (const childStep of step.steps) { if (childStep.error && childStep.infectParentStepsWithError) { step.error = childStep.error; step.infectParentStepsWithError = true; break; } } } if (!step.group) { const payload = { testId: this.testId, stepId, wallTime: step.endWallTime, error: step.error ? import_common2.ipc.toTestInfoErrorPayload(step.error) : void 0, suggestedRebaseline: result.suggestedRebaseline, annotations: step.info.annotations }; this._callbacks.onStepEnd(payload); } if (step.group !== "internal") { const errorForTrace = step.error ? { name: "", message: step.error.message || "", stack: step.error.stack } : void 0; const attachments = step.attachmentIndices.map((i) => this.attachments[i]); this._tracing.appendAfterActionForStep(stepId, errorForTrace, attachments, step.info.annotations); } } }; const parentStepList = parentStep ? parentStep.steps : this._steps; parentStepList.push(step); this._stepMap.set(stepId, step); if (!step.group) { const payload = { testId: this.testId, stepId, parentStepId: parentStep ? parentStep.stepId : void 0, title: step.title, category: step.category, wallTime: Date.now(), location: step.location }; this._callbacks.onStepBegin(payload); } if (step.group !== "internal") { this._tracing.appendBeforeActionForStep({ stepId, parentId: parentStep?.stepId, title: step.shortTitle ?? step.title, category: step.category, params: step.params, stack: step.location ? [step.location] : [], group: step.group }); } return step; } _abort(location, message) { this.annotations.push({ type: "abort", description: message, location }); throw new TestAbortError("Test aborted" + (message ? ": " + message : "")); } _interrupt() { this._interruptedPromise.resolve(); this._timeoutManager.interrupt(); if (this.status === "passed") this.status = "interrupted"; } _failWithError(error) { if (this.status === "passed" || this.status === "skipped") this.status = error instanceof TimeoutManagerError ? "timedOut" : "failed"; const serialized = testInfoError(error); const step = typeof error === "object" ? error?.[stepSymbol] : void 0; if (step && step.boxedStack) serialized.stack = `${error.name}: ${error.message} ${stringifyStackFrames2(step.boxedStack).join("\n")}`; this.errors.push(serialized); this._tracing.appendForError(serialized); } async _runAsStep(stepInfo, cb) { const step = this._addStep(stepInfo); try { await cb(); step.complete({}); } catch (error) { step.complete({ error }); throw error; } } async _runWithTimeout(runnable, cb) { try { await this._timeoutManager.withRunnable(runnable, async () => { try { await cb(); } catch (e) { if (this._allowSkips && e instanceof TestSkipError) { if (this.status === "passed") this.status = "skipped"; } else { this._failWithError(e); } throw e; } }); } catch (error) { if (!this._interruptedPromise.isDone() && error instanceof TimeoutManagerError) this._failWithError(error); throw error; } } _isFailure() { return this.status !== "skipped" && this.status !== this.expectedStatus; } _currentHookType() { const type = this._timeoutManager.currentSlotType(); return ["beforeAll", "afterAll", "beforeEach", "afterEach"].includes(type) ? type : void 0; } _setIgnoreTimeouts(ignoreTimeouts) { this._ignoreTimeoutsCounter += ignoreTimeouts ? 1 : -1; this._timeoutManager.setIgnoreTimeouts(this._ignoreTimeoutsCounter > 0); } async _didFinishTestFunction() { const shouldPause = this._workerParams.pauseAtEnd && !this._isFailure() || this._workerParams.pauseOnError && this._isFailure(); if (shouldPause) { await Promise.race([ this._callbacks.onTestPaused({ testId: this.testId, errors: this._isFailure() ? this.errors.map(import_common2.ipc.toTestInfoErrorPayload) : [], status: this.status }), this._interruptedPromise ]); } for (const cb of this._onDidFinishTestFunctionCallbacks) await cb(); } // ------------ TestInfo methods ------------ async attach(name, options2 = {}) { const step = this._addStep({ title: `Attach ${escapeWithQuotes2(name, '"')}`, category: "test.attach" }); this._attach( await normalizeAndSaveAttachment(this.outputPath(), name, options2), step.stepId ); step.complete({}); } _attach(attachment, stepId) { const index = this._attachmentsPush(attachment) - 1; let step = stepId ? this._stepMap.get(stepId) : void 0; if (!!step?.group) step = void 0; if (step) { step.attachmentIndices.push(index); } else { const stepId2 = `attach@${createGuid2()}`; this._tracing.appendBeforeActionForStep({ stepId: stepId2, title: `Attach ${escapeWithQuotes2(attachment.name, '"')}`, category: "test.attach", stack: [] }); this._tracing.appendAfterActionForStep(stepId2, void 0, [attachment]); } this._callbacks.onAttach({ testId: this.testId, name: attachment.name, contentType: attachment.contentType, path: attachment.path, body: attachment.body?.toString("base64"), stepId: step?.stepId }); } outputPath(...pathSegments) { const outputPath = this._getOutputPath(...pathSegments); import_fs3.default.mkdirSync(this.outputDir, { recursive: true }); return outputPath; } _getOutputPath(...pathSegments) { const joinedPath = import_path3.default.join(...pathSegments); const outputPath = getContainedPath(this.outputDir, joinedPath); if (outputPath) return outputPath; throw new Error(`The outputPath is not allowed outside of the parent directory. Please fix the defined path. outputPath: ${joinedPath}`); } _fsSanitizedTestName() { const fullTitleWithoutSpec = this.titlePath.slice(1).join(" "); return sanitizeForFilePath2(trimLongString(fullTitleWithoutSpec)); } _resolveSnapshotPaths(kind, name, updateSnapshotIndex, anonymousExtension) { const snapshotNames = kind === "aria" ? this._ariaSnapshotNames : this._snapshotNames; const defaultExtensions = { "aria": ".aria.yml", "screenshot": ".png", "snapshot": ".txt" }; const ariaAwareExtname = (filePath) => kind === "aria" && filePath.endsWith(".aria.yml") ? ".aria.yml" : import_path3.default.extname(filePath); let subPath; let ext; let relativeOutputPath; if (!name) { const index = snapshotNames.lastAnonymousSnapshotIndex + 1; if (updateSnapshotIndex === "updateSnapshotIndex") snapshotNames.lastAnonymousSnapshotIndex = index; const fullTitleWithoutSpec = [...this.titlePath.slice(1), index].join(" "); ext = anonymousExtension ?? defaultExtensions[kind]; subPath = sanitizeFilePathBeforeExtension(trimLongString(fullTitleWithoutSpec) + ext, ext); relativeOutputPath = sanitizeFilePathBeforeExtension(trimLongString(fullTitleWithoutSpec, windowsFilesystemFriendlyLength) + ext, ext); } else { if (Array.isArray(name)) { subPath = import_path3.default.join(...name); relativeOutputPath = import_path3.default.join(...name); ext = ariaAwareExtname(subPath); } else { ext = ariaAwareExtname(name); subPath = sanitizeFilePathBeforeExtension(name, ext); relativeOutputPath = sanitizeFilePathBeforeExtension(trimLongString(name, windowsFilesystemFriendlyLength), ext); } const index = (snapshotNames.lastNamedSnapshotIndex[relativeOutputPath] || 0) + 1; if (updateSnapshotIndex === "updateSnapshotIndex") snapshotNames.lastNamedSnapshotIndex[relativeOutputPath] = index; if (index > 1) relativeOutputPath = addSuffixToFilePath(relativeOutputPath, `-${index - 1}`); } const legacyTemplate = "{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{-projectName}{-snapshotSuffix}{ext}"; let template; if (kind === "screenshot") { template = this._projectInternal.expect?.toHaveScreenshot?.pathTemplate || this._projectInternal.snapshotPathTemplate || legacyTemplate; } else if (kind === "aria") { const ariaDefaultTemplate = "{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{ext}"; template = this._projectInternal.expect?.toMatchAriaSnapshot?.pathTemplate || this._projectInternal.snapshotPathTemplate || ariaDefaultTemplate; } else { template = this._projectInternal.snapshotPathTemplate || legacyTemplate; } const nameArgument = import_path3.default.join(import_path3.default.dirname(subPath), import_path3.default.basename(subPath, ext)); const absoluteSnapshotPath = this._applyPathTemplate(template, nameArgument, ext); return { absoluteSnapshotPath, relativeOutputPath }; } _applyPathTemplate(template, nameArgument, ext) { const relativeTestFilePath = import_path3.default.relative(this.project.testDir, this._requireFile); const parsedRelativeTestFilePath = import_path3.default.parse(relativeTestFilePath); const projectNamePathSegment = sanitizeForFilePath2(this.project.name); const snapshotPath = template.replace(/\{(.)?testDir\}/g, "$1" + this.project.testDir).replace(/\{(.)?snapshotDir\}/g, "$1" + this.project.snapshotDir).replace(/\{(.)?snapshotSuffix\}/g, this.snapshotSuffix ? "$1" + this.snapshotSuffix : "").replace(/\{(.)?testFileDir\}/g, "$1" + parsedRelativeTestFilePath.dir).replace(/\{(.)?platform\}/g, "$1" + process.platform).replace(/\{(.)?projectName\}/g, projectNamePathSegment ? "$1" + projectNamePathSegment : "").replace(/\{(.)?testName\}/g, "$1" + this._fsSanitizedTestName()).replace(/\{(.)?testFileBaseName\}/g, "$1" + parsedRelativeTestFilePath.name).replace(/\{(.)?testFileName\}/g, "$1" + parsedRelativeTestFilePath.base).replace(/\{(.)?testFilePath\}/g, "$1" + relativeTestFilePath).replace(/\{(.)?arg\}/g, "$1" + nameArgument).replace(/\{(.)?ext\}/g, ext ? "$1" + ext : ""); return import_path3.default.normalize(import_path3.default.resolve(this._configInternal.configDir, snapshotPath)); } snapshotPath(...args) { let name = args; let kind = "snapshot"; const options2 = args[args.length - 1]; if (options2 && typeof options2 === "object") { kind = options2.kind ?? kind; name = args.slice(0, -1); } if (!["snapshot", "screenshot", "aria"].includes(kind)) throw new Error(`testInfo.snapshotPath: unknown kind "${kind}", must be one of "snapshot", "screenshot" or "aria"`); return this._resolveSnapshotPaths(kind, name.length <= 1 ? name[0] : name, "dontUpdateSnapshotIndex").absoluteSnapshotPath; } setTimeout(timeout) { this._timeoutManager.setTimeout(timeout); } artifactsDir() { return this._workerParams.artifactsDir; } }; var TestStepInfoImpl = class { constructor(testInfo, stepId, title, parentStep) { this.annotations = []; this._testInfo = testInfo; this._stepId = stepId; this._title = title; this._parentStep = parentStep; this.skip = import_common2.transform.wrapFunctionWithLocation((location, ...args) => { if (args.length > 0 && !args[0]) return; const description = args[1]; this.annotations.push({ type: "skip", description, location }); throw new StepSkipError(description); }); } async _runStepBody(skip, body, location) { if (skip) { this.annotations.push({ type: "skip", location }); return void 0; } try { return await body(this); } catch (e) { if (e instanceof StepSkipError) return void 0; throw e; } } async attach(name, options2) { this._testInfo._attach(await normalizeAndSaveAttachment(this._testInfo.outputPath(), name, options2), this._stepId); } get titlePath() { const parent = this._parentStep ?? this._testInfo; return [...parent.titlePath, this._title]; } }; var TestSkipError = class extends Error { }; var TestAbortError = class extends Error { }; var StepSkipError = class extends Error { }; var stepSymbol = Symbol("step"); // packages/playwright/src/worker/workerMain.ts var colors2 = require("playwright-core/lib/utilsBundle").colors; var { ManualPromise: ManualPromise5 } = require("playwright-core/lib/coreBundle").iso; var { removeFolders } = require("playwright-core/lib/coreBundle").utils; var { gracefullyCloseAll } = require("playwright-core/lib/coreBundle").utils; var WorkerMain = class extends import_common3.ProcessRunner { constructor(params) { super(); // Accumulated fatal errors that cannot be attributed to a test. this._fatalErrors = []; // The stage of the full cleanup. Once "finished", we can safely stop running anything. this._didRunFullCleanup = false; // Whether the worker was stopped due to an unhandled error in a test marked with test.fail(). // This should force dispatcher to use a new worker instead. this._stoppedDueToUnhandledErrorInTestFail = false; // Whether the worker was requested to stop. this._isStopped = false; // This promise resolves once the single "run test group" call finishes. this._runFinished = new ManualPromise5(); this._currentTest = null; this._lastRunningTests = []; this._totalRunningTests = 0; // Suites that had their beforeAll hooks, but not afterAll hooks executed. // These suites still need afterAll hooks to be executed for the proper cleanup. // Contains dynamic annotations originated by modifiers with a callback, e.g. `test.skip(() => true)`. this._activeSuites = /* @__PURE__ */ new Map(); process.env.TEST_WORKER_INDEX = String(params.workerIndex); process.env.TEST_PARALLEL_INDEX = String(params.parallelIndex); globals.setIsWorkerProcess(); this._params = params; this._fixtureRunner = new FixtureRunner(); this._runFinished.resolve(); process.on("unhandledRejection", (reason) => this.unhandledError(reason)); process.on("uncaughtException", (error) => this.unhandledError(error)); process.stdout.write = (chunk, cb) => { this.dispatchEvent("stdOut", import_common3.ipc.stdioChunkToParams(chunk)); this._currentTest?._tracing.appendStdioToTrace("stdout", chunk); if (typeof cb === "function") process.nextTick(cb); return true; }; if (!process.env.PW_RUNNER_DEBUG) { process.stderr.write = (chunk, cb) => { this.dispatchEvent("stdErr", import_common3.ipc.stdioChunkToParams(chunk)); this._currentTest?._tracing.appendStdioToTrace("stderr", chunk); if (typeof cb === "function") process.nextTick(cb); return true; }; } } _stop() { if (!this._isStopped) { this._isStopped = true; this._currentTest?._interrupt(); } return this._runFinished; } async gracefullyClose() { try { await this._stop(); if (!this._config) { return; } const fakeTestInfo = new TestInfoImpl(this._config, this._project, this._params, void 0, 0, emtpyTestInfoCallbacks); const runnable = { type: "teardown" }; await fakeTestInfo._runWithTimeout(runnable, () => this._loadIfNeeded()).catch(() => { }); await this._fixtureRunner.teardownScope("test", fakeTestInfo, runnable).catch(() => { }); await this._fixtureRunner.teardownScope("worker", fakeTestInfo, runnable).catch(() => { }); await fakeTestInfo._runWithTimeout(runnable, () => gracefullyCloseAll()).catch(() => { }); this._fatalErrors.push(...fakeTestInfo.errors); } catch (e) { this._fatalErrors.push(testInfoError(e)); } if (this._fatalErrors.length) { this._appendProcessTeardownDiagnostics(this._fatalErrors[this._fatalErrors.length - 1]); const payload = { fatalErrors: this._fatalErrors.map(import_common3.ipc.toTestInfoErrorPayload) }; this.dispatchEvent("teardownErrors", payload); } } _appendProcessTeardownDiagnostics(error) { if (!this._lastRunningTests.length) return; const count = this._totalRunningTests === 1 ? "1 test" : `${this._totalRunningTests} tests`; let lastMessage = ""; if (this._lastRunningTests.length < this._totalRunningTests) lastMessage = `, last ${this._lastRunningTests.length} tests were`; const message = [ "", "", colors2.red(`Failed worker ran ${count}${lastMessage}:`), ...this._lastRunningTests.map((test) => formatTestTitle(test, this._project.project.name)) ].join("\n"); if (error.message) { if (error.stack) { let index = error.stack.indexOf(error.message); if (index !== -1) { index += error.message.length; error.stack = error.stack.substring(0, index) + message + error.stack.substring(index); } } error.message += message; } else if (error.value) { error.value += message; } } unhandledError(error) { if (!this._currentTest) { if (!this._fatalErrors.length) this._fatalErrors.push(testInfoError(error)); void this._stop(); return; } if (!this._currentTest._hasUnhandledError) { this._currentTest._hasUnhandledError = true; this._currentTest._failWithError(error); } const isExpectError = error instanceof Error && !!error.matcherResult; const shouldContinueInThisWorker = this._currentTest.expectedStatus === "failed" && isExpectError; if (!shouldContinueInThisWorker) { this._stoppedDueToUnhandledErrorInTestFail = true; void this._stop(); } } async _loadIfNeeded() { if (this._config) return; const config = await import_common3.configLoader.deserializeConfig(this._params.config); const project = config.projects.find((p) => p.id === this._params.projectId); if (!project) throw new Error(`Project "${this._params.projectId}" not found in the worker process. Make sure project name does not change.`); this._config = config; this._project = project; this._poolBuilder = import_common3.poolBuilder.PoolBuilder.createForWorker(this._project); this._fixtureRunner.workerFixtureTimeout = this._project.project.timeout; } async runTestGroup(runPayload) { this._runFinished = new ManualPromise5(); const entries = new Map(runPayload.entries.map((e) => [e.testId, e])); let fatalUnknownTestIds; try { await this._loadIfNeeded(); const fileSuite = await import_common3.testLoader.loadTestFile(runPayload.file, this._config); const suite = import_common3.suiteUtils.bindFileSuiteToProject(this._project, fileSuite); if (this._params.repeatEachIndex) import_common3.suiteUtils.applyRepeatEachIndex(this._project, suite, this._params.repeatEachIndex); import_common3.suiteUtils.filterTestsRemoveEmptySuites(suite, (test) => entries.has(test.id)); const tests = suite.allTests(); const unknownTestIds = new Set(entries.keys()); for (const test of tests) unknownTestIds.delete(test.id); if (unknownTestIds.size) { fatalUnknownTestIds = [...unknownTestIds]; void this._stop(); return; } this._poolBuilder.buildPools(suite); this._activeSuites = /* @__PURE__ */ new Map(); this._didRunFullCleanup = false; for (let i = 0; i < tests.length; i++) { if (this._isStopped && this._didRunFullCleanup) break; const entry = entries.get(tests[i].id); entries.delete(tests[i].id); debugTest(`test started "${tests[i].title}"`); await this._runTest(tests[i], entry.retry, tests[i + 1]); debugTest(`test finished "${tests[i].title}"`); } } catch (e) { this._fatalErrors.push(testInfoError(e)); void this._stop(); } finally { const donePayload = { fatalErrors: this._fatalErrors.map(import_common3.ipc.toTestInfoErrorPayload), skipTestsDueToSetupFailure: [], fatalUnknownTestIds, stoppedDueToUnhandledErrorInTestFail: this._stoppedDueToUnhandledErrorInTestFail }; for (const test of this._skipRemainingTestsInSuite?.allTests() || []) { if (entries.has(test.id)) donePayload.skipTestsDueToSetupFailure.push(test.id); } this.dispatchEvent("done", donePayload); this._fatalErrors = []; this._skipRemainingTestsInSuite = void 0; this._runFinished.resolve(); } } async customMessage(payload) { try { if (this._currentTest?.testId !== payload.testId) throw new Error("Test has already stopped"); const response = await this._currentTest._onCustomMessageCallback?.(payload.request); return { response }; } catch (error) { return { response: {}, error: import_common3.ipc.toTestInfoErrorPayload(testInfoError(error)) }; } } resume(payload) { this._resumePromise?.resolve(payload); } async _runTest(test, retry, nextTest) { const testInfo = new TestInfoImpl(this._config, this._project, this._params, test, retry, { onStepBegin: (payload) => this.dispatchEvent("stepBegin", payload), onStepEnd: (payload) => this.dispatchEvent("stepEnd", payload), onAttach: (payload) => this.dispatchEvent("attach", payload), onTestPaused: (payload) => { this._resumePromise = new ManualPromise5(); this.dispatchEvent("testPaused", payload); return this._resumePromise; } }); const processAnnotation = (annotation) => { testInfo.annotations.push(annotation); switch (annotation.type) { case "fixme": case "skip": testInfo.expectedStatus = "skipped"; break; case "fail": if (testInfo.expectedStatus !== "skipped") testInfo.expectedStatus = "failed"; break; case "slow": testInfo._timeoutManager.slow(); break; } }; if (!this._isStopped) this._fixtureRunner.setPool(test._pool); const suites = getSuites(test); const reversedSuites = suites.slice().reverse(); const nextSuites = new Set(getSuites(nextTest)); testInfo._timeoutManager.setTimeout(test.timeout); for (const annotation of test.annotations) processAnnotation(annotation); for (const suite of suites) { const extraAnnotations = this._activeSuites.get(suite) || []; for (const annotation of extraAnnotations) processAnnotation(annotation); } this._currentTest = testInfo; globals.setCurrentTestInfo(testInfo); (0, import_expect.setExpectConfig)({ testInfo, filteredStackTrace, ignoreSnapshots: testInfo._projectInternal.project.ignoreSnapshots, updateSnapshots: testInfo.config.updateSnapshots, timeout: testInfo._projectInternal.expect?.timeout, toHaveScreenshot: testInfo._projectInternal.expect?.toHaveScreenshot, toMatchSnapshot: testInfo._projectInternal.expect?.toMatchSnapshot, toMatchAriaSnapshot: testInfo._projectInternal.expect?.toMatchAriaSnapshot, toPass: testInfo._projectInternal.expect?.toPass }); this.dispatchEvent("testBegin", buildTestBeginPayload(testInfo)); const isSkipped = testInfo.expectedStatus === "skipped"; const hasAfterAllToRunBeforeNextTest = reversedSuites.some((suite) => { return this._activeSuites.has(suite) && !nextSuites.has(suite) && suite._hooks.some((hook) => hook.type === "afterAll"); }); if (isSkipped && nextTest && !hasAfterAllToRunBeforeNextTest) { testInfo.status = "skipped"; this.dispatchEvent("testEnd", buildTestEndPayload(testInfo)); return; } this._totalRunningTests++; this._lastRunningTests.push(test); if (this._lastRunningTests.length > 10) this._lastRunningTests.shift(); let shouldRunAfterEachHooks = false; testInfo._allowSkips = true; await (async () => { await testInfo._runWithTimeout({ type: "test" }, async () => { const traceFixtureRegistration = test._pool.resolve("trace"); if (!traceFixtureRegistration) return; if (typeof traceFixtureRegistration.fn === "function") throw new Error(`"trace" option cannot be a function`); await testInfo._tracing.startIfNeeded(traceFixtureRegistration.fn); }); if (this._isStopped || isSkipped) { testInfo.status = "skipped"; return; } await removeFolders([testInfo.outputDir]); let testFunctionParams = null; await testInfo._runAsStep({ title: "Before Hooks", category: "hook" }, async () => { for (const suite of suites) await this._runBeforeAllHooksForSuite(suite, testInfo); shouldRunAfterEachHooks = true; await this._runEachHooksForSuites(suites, "beforeEach", testInfo); const params = await this._fixtureRunner.resolveParametersForFunction(test.fn, testInfo, "test", { type: "test" }); if (params !== null) testFunctionParams = params.result; }); if (testFunctionParams === null) { return; } await testInfo._runWithTimeout({ type: "test" }, async () => { const fn = test.fn; await fn(testFunctionParams, testInfo); }); })().catch(() => { }); testInfo.duration = testInfo._timeoutManager.defaultSlot().elapsed | 0; testInfo._allowSkips = true; const afterHooksTimeout = calculateMaxTimeout(this._project.project.timeout, testInfo.timeout); const afterHooksSlot = { timeout: afterHooksTimeout, elapsed: 0 }; await testInfo._runAsStep({ title: "After Hooks", category: "hook" }, async () => { let firstAfterHooksError; try { await testInfo._runWithTimeout({ type: "test", slot: afterHooksSlot }, () => testInfo._didFinishTestFunction()); } catch (error) { firstAfterHooksError = firstAfterHooksError ?? error; } try { if (shouldRunAfterEachHooks) await this._runEachHooksForSuites(reversedSuites, "afterEach", testInfo, afterHooksSlot); } catch (error) { firstAfterHooksError = firstAfterHooksError ?? error; } testInfo._tracing.didFinishTestFunctionAndAfterEachHooks(); try { await this._fixtureRunner.teardownScope("test", testInfo, { type: "test", slot: afterHooksSlot }); } catch (error) { firstAfterHooksError = firstAfterHooksError ?? error; } for (const suite of reversedSuites) { if (!nextSuites.has(suite) || testInfo._isFailure()) { try { await this._runAfterAllHooksForSuite(suite, testInfo); } catch (error) { firstAfterHooksError = firstAfterHooksError ?? error; } } } if (firstAfterHooksError) throw firstAfterHooksError; }).catch(() => { }); if (testInfo._isFailure()) this._isStopped = true; if (this._isStopped) { this._didRunFullCleanup = true; await testInfo._runAsStep({ title: "Worker Cleanup", category: "hook" }, async () => { let firstWorkerCleanupError; const teardownSlot = { timeout: this._project.project.timeout, elapsed: 0 }; try { await this._fixtureRunner.teardownScope("test", testInfo, { type: "test", slot: teardownSlot }); } catch (error) { firstWorkerCleanupError = firstWorkerCleanupError ?? error; } for (const suite of reversedSuites) { try { await this._runAfterAllHooksForSuite(suite, testInfo); } catch (error) { firstWorkerCleanupError = firstWorkerCleanupError ?? error; } } try { await this._fixtureRunner.teardownScope("worker", testInfo, { type: "teardown", slot: teardownSlot }); } catch (error) { firstWorkerCleanupError = firstWorkerCleanupError ?? error; } if (firstWorkerCleanupError) throw firstWorkerCleanupError; }).catch(() => { }); } const tracingSlot = { timeout: this._project.project.timeout, elapsed: 0 }; await testInfo._runWithTimeout({ type: "test", slot: tracingSlot }, async () => { await testInfo._tracing.stopIfNeeded(); }).catch(() => { }); testInfo.duration = testInfo._timeoutManager.defaultSlot().elapsed + afterHooksSlot.elapsed | 0; this._currentTest = null; globals.setCurrentTestInfo(null); (0, import_expect.setExpectConfig)({ testInfo: null, filteredStackTrace, ignoreSnapshots: false, updateSnapshots: "missing" }); this.dispatchEvent("testEnd", buildTestEndPayload(testInfo)); const preserveOutput = this._config.config.preserveOutput === "always" || this._config.config.preserveOutput === "failures-only" && testInfo._isFailure(); if (!preserveOutput) await removeFolders([testInfo.outputDir]); } _collectHooksAndModifiers(suite, type, testInfo) { const runnables = []; for (const modifier of suite._modifiers) { const modifierType = this._fixtureRunner.dependsOnWorkerFixturesOnly(modifier.fn, modifier.location) ? "beforeAll" : "beforeEach"; if (modifierType !== type) continue; const fn = async (fixtures3) => { const result = await modifier.fn(fixtures3); testInfo._modifier(modifier.type, modifier.location, [!!result, modifier.description]); }; import_common3.fixtures.inheritFixtureNames(modifier.fn, fn); runnables.push({ title: `${modifier.type} modifier`, location: modifier.location, type: modifier.type, fn }); } runnables.push(...suite._hooks.filter((hook) => hook.type === type)); return runnables; } async _runBeforeAllHooksForSuite(suite, testInfo) { if (this._activeSuites.has(suite)) return; const extraAnnotations = []; this._activeSuites.set(suite, extraAnnotations); await this._runAllHooksForSuite(suite, testInfo, "beforeAll", extraAnnotations); } async _runAllHooksForSuite(suite, testInfo, type, extraAnnotations) { let firstError; for (const hook of this._collectHooksAndModifiers(suite, type, testInfo)) { try { await testInfo._runAsStep({ title: hook.title, category: "hook", location: hook.location }, async () => { const timeSlot = { timeout: this._project.project.timeout, elapsed: 0 }; const runnable = { type: hook.type, slot: timeSlot, location: hook.location }; const existingAnnotations = new Set(testInfo.annotations); try { await this._fixtureRunner.resolveParametersAndRunFunction(hook.fn, testInfo, "all-hooks-only", runnable); } finally { if (extraAnnotations) { const newAnnotations = testInfo.annotations.filter((a) => !existingAnnotations.has(a)); extraAnnotations.push(...newAnnotations); } await this._fixtureRunner.teardownScope("test", testInfo, runnable); } }); } catch (error) { firstError = firstError ?? error; if (type === "beforeAll" && error instanceof TestSkipError) break; if (type === "beforeAll" && !this._skipRemainingTestsInSuite) { this._skipRemainingTestsInSuite = suite; } } } if (firstError) throw firstError; } async _runAfterAllHooksForSuite(suite, testInfo) { if (!this._activeSuites.has(suite)) return; this._activeSuites.delete(suite); await this._runAllHooksForSuite(suite, testInfo, "afterAll"); } async _runEachHooksForSuites(suites, type, testInfo, slot) { let firstError; const hooks = suites.map((suite) => this._collectHooksAndModifiers(suite, type, testInfo)).flat(); for (const hook of hooks) { const runnable = { type: hook.type, location: hook.location, slot }; if (testInfo._timeoutManager.isTimeExhaustedFor(runnable)) { continue; } try { await testInfo._runAsStep({ title: hook.title, category: "hook", location: hook.location }, async () => { await this._fixtureRunner.resolveParametersAndRunFunction(hook.fn, testInfo, "test", runnable); }); } catch (error) { firstError = firstError ?? error; if (error instanceof TestSkipError) break; } } if (firstError) throw firstError; } }; function buildTestBeginPayload(testInfo) { return { testId: testInfo.testId, startWallTime: testInfo._startWallTime }; } function buildTestEndPayload(testInfo) { return { testId: testInfo.testId, duration: testInfo.duration, status: testInfo.status, errors: testInfo.errors.map(import_common3.ipc.toTestInfoErrorPayload), hasNonRetriableError: testInfo._hasNonRetriableError, expectedStatus: testInfo.expectedStatus, annotations: testInfo.annotations, timeout: testInfo.timeout }; } function getSuites(test) { const suites = []; for (let suite = test?.parent; suite; suite = suite.parent) suites.push(suite); suites.reverse(); return suites; } function formatTestTitle(test, projectName) { const [, ...titles] = test.titlePath(); const location = `${relativeFilePath(test.location.file)}:${test.location.line}:${test.location.column}`; const projectTitle = projectName ? `[${projectName}] \u203A ` : ""; return `${projectTitle}${location} \u203A ${titles.join(" \u203A ")}`; } function calculateMaxTimeout(t1, t2) { return !t1 || !t2 ? 0 : Math.max(t1, t2); } var create = (params) => new WorkerMain(params); // packages/playwright/src/worker/workerProcessEntry.ts (0, import_common4.startProcessRunner)(create);