cypress 15.15.0 → 15.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/cypress CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var cli = require('../cli-CQHngRhO.js');
5
- require('../xvfb-Csr_YzMk.js');
4
+ var cli = require('../cli-B97CK6L9.js');
5
+ require('../xvfb-SgoMy1_9.js');
6
6
  require('os');
7
7
  require('bluebird');
8
8
  require('@cypress/xvfb');
@@ -32,7 +32,7 @@ require('commander');
32
32
  require('cli-table3');
33
33
  require('dayjs');
34
34
  require('dayjs/plugin/relativeTime');
35
- require('../spawn-D9ARC26J.js');
35
+ require('../spawn-BZQfzolX.js');
36
36
  require('child_process');
37
37
  require('listr2');
38
38
  require('readline');
@@ -45,7 +45,7 @@ require('@cypress/request');
45
45
  require('request-progress');
46
46
  require('proxy-from-env');
47
47
  require('yauzl');
48
- require('extract-zip');
48
+ require('util');
49
49
  require('pretty-bytes');
50
50
 
51
51
  // declared here in order to avoid consumers who are looking for the binary to be available relative to the dist directory
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var xvfb = require('./xvfb-Csr_YzMk.js');
3
+ var xvfb = require('./xvfb-SgoMy1_9.js');
4
4
  var _ = require('lodash');
5
5
  var commander = require('commander');
6
6
  var commonTags = require('common-tags');
@@ -13,18 +13,20 @@ var dayjs = require('dayjs');
13
13
  var relativeTime = require('dayjs/plugin/relativeTime');
14
14
  var chalk = require('chalk');
15
15
  var Bluebird = require('bluebird');
16
- var spawn = require('./spawn-D9ARC26J.js');
16
+ var spawn = require('./spawn-BZQfzolX.js');
17
17
  var os = require('os');
18
18
  var listr2 = require('listr2');
19
19
  var timers = require('timers/promises');
20
- var promises = require('fs/promises');
20
+ var fsp = require('fs/promises');
21
21
  var assert = require('assert');
22
22
  var request = require('@cypress/request');
23
23
  var requestProgress = require('request-progress');
24
24
  var proxyFromEnv = require('proxy-from-env');
25
25
  var cp = require('child_process');
26
26
  var yauzl = require('yauzl');
27
- var extract = require('extract-zip');
27
+ var fs$1 = require('fs');
28
+ var util = require('util');
29
+ var require$$0 = require('stream');
28
30
  var readline = require('readline');
29
31
  var prettyBytes = require('pretty-bytes');
30
32
 
@@ -304,9 +306,154 @@ const downloadModule = {
304
306
  getCA,
305
307
  };
306
308
 
309
+ const pipelineAsync = util.promisify(require$$0.pipeline);
310
+ // Unix file mode masks for entries stored in zip's externalFileAttributes
311
+ // (the high 16 bits when the file was zipped on a Unix host).
312
+ const S_IFMT = 0o170000;
313
+ const S_IFDIR = 0o040000;
314
+ const S_IFLNK = 0o120000;
315
+ // PATH_MAX on Linux/macOS is 4096; symlink targets larger than this are not
316
+ // legal filesystem paths and almost certainly indicate a malformed or
317
+ // malicious archive. The cap also prevents reading an arbitrarily large
318
+ // "symlink" entry into memory.
319
+ const MAX_SYMLINK_TARGET_BYTES = 4096;
320
+ /**
321
+ * Extracts the contents of a zip archive into the given destination directory.
322
+ * Recreates directories, regular files, and symlinks while preserving Unix
323
+ * file modes encoded in each entry's external attributes. Calls `onEntry` once
324
+ * per archive entry processed. Refuses entries whose resolved path would
325
+ * escape the destination directory.
326
+ */
327
+ const extractWithYauzl = (zipFilePath, destDir, onEntry) => xvfb.__awaiter(void 0, void 0, void 0, function* () {
328
+ const resolvedDest = path.resolve(destDir);
329
+ yield new Promise((resolve, reject) => {
330
+ // autoClose: false — `finish` below owns closing the zipfile, so we don't
331
+ // want yauzl's internal end-listener closing it first and tripping a
332
+ // double-close (EBADF) when we do.
333
+ yauzl.open(zipFilePath, { lazyEntries: true, autoClose: false }, (err, zipFile) => {
334
+ if (err) {
335
+ return reject(err);
336
+ }
337
+ // `settled` guards against an in-flight `handleEntry` calling
338
+ // `zipFile.readEntry()` on a now-closed handle when extraction has
339
+ // already failed (e.g. yauzl emitted 'error' while we were writing
340
+ // an entry to disk).
341
+ let settled = false;
342
+ const finish = _.once((err) => {
343
+ var _a, _b;
344
+ settled = true;
345
+ (_a = zipFile.removeAllListeners) === null || _a === void 0 ? void 0 : _a.call(zipFile);
346
+ (_b = zipFile.close) === null || _b === void 0 ? void 0 : _b.call(zipFile);
347
+ if (err) {
348
+ return reject(err);
349
+ }
350
+ return resolve();
351
+ });
352
+ // Normalize any thrown / emitted value into a real Error so that a
353
+ // falsy rejection (e.g. `Promise.reject(undefined)`) doesn't get
354
+ // misread by `finish` as a successful completion.
355
+ const fail = (err) => {
356
+ finish(err instanceof Error ? err : new Error(typeof err === 'string' && err ? err : 'zip extraction failed'));
357
+ };
358
+ zipFile.on('error', fail);
359
+ zipFile.on('end', () => finish());
360
+ zipFile.on('entry', (entry) => {
361
+ handleEntry(zipFile, entry, resolvedDest)
362
+ .then(() => {
363
+ if (settled)
364
+ return;
365
+ onEntry();
366
+ zipFile.readEntry();
367
+ })
368
+ .catch(fail);
369
+ });
370
+ zipFile.readEntry();
371
+ });
372
+ });
373
+ });
374
+ const handleEntry = (zipFile, entry, resolvedDest) => xvfb.__awaiter(void 0, void 0, void 0, function* () {
375
+ const fileDest = path.resolve(resolvedDest, entry.fileName);
376
+ // refuse anything that would write outside the install dir
377
+ if (fileDest !== resolvedDest &&
378
+ !fileDest.startsWith(resolvedDest + path.sep)) {
379
+ throw new Error(`Refusing to extract entry outside of destination: ${entry.fileName}`);
380
+ }
381
+ const unixMode = (entry.externalFileAttributes >>> 16) & 0xffff;
382
+ // Some archivers mark directories by Unix mode bits instead of (or in
383
+ // addition to) a trailing slash; honor both so we don't extract a
384
+ // directory entry as a zero-byte file.
385
+ const isDir = /\/$/.test(entry.fileName) || (unixMode & S_IFMT) === S_IFDIR;
386
+ const isSymlink = (unixMode & S_IFMT) === S_IFLNK;
387
+ if (isDir) {
388
+ yield fsp.mkdir(fileDest, { recursive: true });
389
+ return;
390
+ }
391
+ yield fsp.mkdir(path.dirname(fileDest), { recursive: true });
392
+ if (isSymlink) {
393
+ if (entry.uncompressedSize > MAX_SYMLINK_TARGET_BYTES) {
394
+ throw new Error(`Refusing to extract symlink with target larger than ${MAX_SYMLINK_TARGET_BYTES} bytes: ${entry.fileName}`);
395
+ }
396
+ const linkTarget = yield readEntryAsString(zipFile, entry, MAX_SYMLINK_TARGET_BYTES);
397
+ const resolvedTarget = path.resolve(path.dirname(fileDest), linkTarget);
398
+ if (resolvedTarget !== resolvedDest &&
399
+ !resolvedTarget.startsWith(resolvedDest + path.sep)) {
400
+ throw new Error(`Refusing to extract symlink pointing outside of destination: ${entry.fileName} -> ${linkTarget}`);
401
+ }
402
+ yield fsp.rm(fileDest, { recursive: true, force: true });
403
+ yield fsp.symlink(linkTarget, fileDest);
404
+ return;
405
+ }
406
+ const readStream = yield new Promise((res, rej) => {
407
+ zipFile.openReadStream(entry, (err, rs) => {
408
+ if (err) {
409
+ return rej(err);
410
+ }
411
+ return res(rs);
412
+ });
413
+ });
414
+ // Preserve the Unix mode bits when present; otherwise fall back to a sane default.
415
+ const fileMode = (unixMode & 0o7777) || 0o644;
416
+ const writeStream = fs$1.createWriteStream(fileDest, { mode: fileMode });
417
+ yield pipelineAsync(readStream, writeStream);
418
+ });
419
+ const readEntryAsString = (zipFile, entry, maxBytes) => {
420
+ return new Promise((resolve, reject) => {
421
+ zipFile.openReadStream(entry, (err, rs) => {
422
+ if (err) {
423
+ return reject(err);
424
+ }
425
+ const chunks = [];
426
+ let received = 0;
427
+ let bailed = false;
428
+ const bail = (err) => {
429
+ var _a;
430
+ if (bailed)
431
+ return;
432
+ bailed = true;
433
+ (_a = rs.destroy) === null || _a === void 0 ? void 0 : _a.call(rs, err);
434
+ reject(err);
435
+ };
436
+ rs.on('data', (chunk) => {
437
+ received += chunk.length;
438
+ if (received > maxBytes) {
439
+ bail(new Error(`Refusing to read entry body larger than ${maxBytes} bytes: ${entry.fileName}`));
440
+ return;
441
+ }
442
+ chunks.push(chunk);
443
+ });
444
+ rs.on('end', () => {
445
+ if (bailed)
446
+ return;
447
+ resolve(Buffer.concat(chunks).toString('utf8'));
448
+ });
449
+ rs.on('error', bail);
450
+ });
451
+ });
452
+ };
453
+
307
454
  const debug$5 = Debug('cypress:cli:unzip');
308
455
  const unzipTools = {
309
- extract,
456
+ extractWithYauzl,
310
457
  };
311
458
  // expose this function for simple testing
312
459
  const unzip = (_a) => xvfb.__awaiter(void 0, [_a], void 0, function* ({ zipFilePath, installDir, progress }) {
@@ -319,7 +466,10 @@ const unzip = (_a) => xvfb.__awaiter(void 0, [_a], void 0, function* ({ zipFileP
319
466
  let yauzlDoneTime = 0;
320
467
  yield fs.ensureDir(installDir);
321
468
  yield new Promise((resolve, reject) => {
322
- return yauzl.open(zipFilePath, (err, zipFile) => {
469
+ // Open with lazyEntries so yauzl doesn't auto-emit entries (which would
470
+ // require the fd to stay open for the duration of the OS-tool extraction).
471
+ // We only need the entryCount here for the progress calculation.
472
+ return yauzl.open(zipFilePath, { lazyEntries: true }, (err, zipFile) => {
323
473
  yauzlDoneTime = Date.now();
324
474
  if (err) {
325
475
  debug$5('error using yauzl %s', err.message);
@@ -327,6 +477,8 @@ const unzip = (_a) => xvfb.__awaiter(void 0, [_a], void 0, function* ({ zipFileP
327
477
  }
328
478
  const total = zipFile.entryCount;
329
479
  debug$5('zipFile entries count', total);
480
+ // Close the count-only handle — the Node fallback re-opens the zip for extraction.
481
+ zipFile.close();
330
482
  const started = new Date();
331
483
  let percent = 0;
332
484
  let count = 0;
@@ -343,13 +495,8 @@ const unzip = (_a) => xvfb.__awaiter(void 0, [_a], void 0, function* ({ zipFileP
343
495
  };
344
496
  const unzipWithNode = () => xvfb.__awaiter(void 0, void 0, void 0, function* () {
345
497
  debug$5('unzipping with node.js (slow)');
346
- const opts = {
347
- dir: installDir,
348
- onEntry: tick,
349
- };
350
- debug$5('calling Node extract tool %s %o', zipFilePath, opts);
351
498
  try {
352
- yield unzipTools.extract(zipFilePath, opts);
499
+ yield unzipTools.extractWithYauzl(zipFilePath, installDir, tick);
353
500
  debug$5('node unzip finished');
354
501
  return resolve();
355
502
  }
@@ -569,7 +716,7 @@ const start$1 = (...args_1) => xvfb.__awaiter(void 0, [...args_1], void 0, funct
569
716
  if (!pkgPath) {
570
717
  return xvfb.throwFormErrorText('Could not find package.json for Cypress package to determine build information')();
571
718
  }
572
- const { buildInfo, version } = JSON.parse(yield promises.readFile(pkgPath, 'utf8'));
719
+ const { buildInfo, version } = JSON.parse(yield fsp.readFile(pkgPath, 'utf8'));
573
720
  _.defaults(options, {
574
721
  force: false,
575
722
  buildInfo,
@@ -673,9 +820,10 @@ const start$1 = (...args_1) => xvfb.__awaiter(void 0, [...args_1], void 0, funct
673
820
  // let the user know what version of cypress we're downloading!
674
821
  xvfb.loggerModule.log(`Installing Cypress ${chalk.gray(`(version: ${versionToInstall})`)}`);
675
822
  xvfb.loggerModule.log();
676
- const taskRunner = new listr2.Listr(tasks, {
677
- silentRendererCondition: () => xvfb.loggerModule.logLevel() === 'silent',
678
- });
823
+ const taskRunner = new listr2.Listr(tasks, Object.assign(Object.assign({
824
+ // In CI we want timestamped, line-per-event output. Locally,
825
+ // the default in-place spinner is the better experience.
826
+ renderer: xvfb.util.isCi() ? 'verbose' : 'default' }, (xvfb.util.isCi() && { rendererOptions: { timestamp: listr2.PRESET_TIMESTAMP } })), { silentRendererCondition: () => xvfb.loggerModule.logLevel() === 'silent' }));
679
827
  yield taskRunner.run();
680
828
  // delay 1 sec for UX, unless we are testing
681
829
  yield timers.setTimeout(1000);
@@ -1083,6 +1231,8 @@ function getSize(path$1) {
1083
1231
  }
1084
1232
 
1085
1233
  dayjs.extend(relativeTime);
1234
+ // Subdirs under the cache root that are not binary version dirs.
1235
+ const EXTERNAL_CACHE_ENTRIES = new Set(['bundles']);
1086
1236
  // output colors for the table
1087
1237
  const colors = {
1088
1238
  titles: chalk.white,
@@ -1104,6 +1254,8 @@ const prune = () => xvfb.__awaiter(void 0, void 0, void 0, function* () {
1104
1254
  try {
1105
1255
  const versions = yield fs.readdir(cacheDir);
1106
1256
  for (const version of versions) {
1257
+ if (EXTERNAL_CACHE_ENTRIES.has(version))
1258
+ continue;
1107
1259
  if (version !== checkedInBinaryVersion) {
1108
1260
  deletedBinary = true;
1109
1261
  const versionDir = path.join(cacheDir, version);
package/dist/cli.js CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- require('./xvfb-Csr_YzMk.js');
5
+ require('./xvfb-SgoMy1_9.js');
6
6
  require('lodash');
7
7
  require('commander');
8
8
  require('common-tags');
9
9
  require('log-symbols');
10
10
  require('debug');
11
- var cli = require('./cli-CQHngRhO.js');
12
- require('./spawn-D9ARC26J.js');
11
+ var cli = require('./cli-B97CK6L9.js');
12
+ require('./spawn-BZQfzolX.js');
13
13
  require('os');
14
14
  require('bluebird');
15
15
  require('@cypress/xvfb');
@@ -42,10 +42,10 @@ require('request-progress');
42
42
  require('proxy-from-env');
43
43
  require('child_process');
44
44
  require('yauzl');
45
- require('extract-zip');
45
+ require('util');
46
+ require('stream');
46
47
  require('readline');
47
48
  require('pretty-bytes');
48
- require('stream');
49
49
  require('string_decoder');
50
50
  require('node:string_decoder');
51
51
 
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var xvfb = require('./xvfb-Csr_YzMk.js');
3
+ var xvfb = require('./xvfb-SgoMy1_9.js');
4
4
  var tmp = require('tmp');
5
5
  var fs = require('fs-extra');
6
- var cli$1 = require('./cli-CQHngRhO.js');
6
+ var cli$1 = require('./cli-B97CK6L9.js');
7
7
 
8
8
  /**
9
9
  * Opens Cypress GUI
package/dist/cypress.js CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- require('./xvfb-Csr_YzMk.js');
3
+ require('./xvfb-SgoMy1_9.js');
4
4
  require('tmp');
5
5
  require('fs-extra');
6
- require('./cli-CQHngRhO.js');
7
- var cypress = require('./cypress-BMOTlyGc.js');
6
+ require('./cli-B97CK6L9.js');
7
+ var cypress = require('./cypress-DuMyFGfr.js');
8
8
  require('os');
9
9
  require('bluebird');
10
10
  require('@cypress/xvfb');
@@ -33,7 +33,7 @@ require('commander');
33
33
  require('cli-table3');
34
34
  require('dayjs');
35
35
  require('dayjs/plugin/relativeTime');
36
- require('./spawn-D9ARC26J.js');
36
+ require('./spawn-BZQfzolX.js');
37
37
  require('child_process');
38
38
  require('listr2');
39
39
  require('readline');
@@ -46,7 +46,7 @@ require('@cypress/request');
46
46
  require('request-progress');
47
47
  require('proxy-from-env');
48
48
  require('yauzl');
49
- require('extract-zip');
49
+ require('util');
50
50
  require('pretty-bytes');
51
51
 
52
52
 
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- require('../xvfb-Csr_YzMk.js');
3
+ require('../xvfb-SgoMy1_9.js');
4
4
  require('lodash');
5
5
  require('os');
6
6
  require('child_process');
7
7
  require('path');
8
8
  require('debug');
9
- var spawn = require('../spawn-D9ARC26J.js');
9
+ var spawn = require('../spawn-BZQfzolX.js');
10
10
  require('readline');
11
11
  require('process');
12
12
  require('stream');
package/dist/exec/xvfb.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var xvfb = require('../xvfb-Csr_YzMk.js');
5
+ var xvfb = require('../xvfb-SgoMy1_9.js');
6
6
  require('os');
7
7
  require('bluebird');
8
8
  require('@cypress/xvfb');
package/dist/index.js CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var xvfb = require('./xvfb-Csr_YzMk.js');
5
+ var xvfb = require('./xvfb-SgoMy1_9.js');
6
6
  var minimist = require('minimist');
7
7
  var Debug = require('debug');
8
- var cli$1 = require('./cli-CQHngRhO.js');
9
- var spawn = require('./spawn-D9ARC26J.js');
10
- var cypress = require('./cypress-BMOTlyGc.js');
8
+ var cli$1 = require('./cli-B97CK6L9.js');
9
+ var spawn = require('./spawn-BZQfzolX.js');
10
+ var cypress = require('./cypress-DuMyFGfr.js');
11
11
  require('os');
12
12
  require('bluebird');
13
13
  require('@cypress/xvfb');
@@ -44,10 +44,10 @@ require('request-progress');
44
44
  require('proxy-from-env');
45
45
  require('child_process');
46
46
  require('yauzl');
47
- require('extract-zip');
47
+ require('util');
48
+ require('stream');
48
49
  require('readline');
49
50
  require('pretty-bytes');
50
- require('stream');
51
51
  require('string_decoder');
52
52
  require('node:string_decoder');
53
53
  require('tmp');
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var xvfb = require('./xvfb-Csr_YzMk.js');
3
+ var xvfb = require('./xvfb-SgoMy1_9.js');
4
4
  var _ = require('lodash');
5
5
  var os = require('os');
6
6
  var cp = require('child_process');
@@ -171,9 +171,10 @@ function verifyBinary(installedVersion, binaryDir, options) {
171
171
  yield xvfb.stateModule.writeBinaryVerifiedAsync(true, binaryDir);
172
172
  task.title = xvfb.util.titleize(chalk.green('Verified Cypress!'), chalk.gray(binaryDir));
173
173
  }),
174
- }], {
175
- silentRendererCondition: () => xvfb.loggerModule.logLevel() === 'silent',
176
- });
174
+ }], Object.assign(Object.assign({
175
+ // In CI we want timestamped, line-per-event output. Locally,
176
+ // the default in-place spinner is the better experience.
177
+ renderer: xvfb.util.isCi() ? 'verbose' : 'default' }, (xvfb.util.isCi() && { rendererOptions: { timestamp: listr2.PRESET_TIMESTAMP } })), { silentRendererCondition: () => xvfb.loggerModule.logLevel() === 'silent' }));
177
178
  yield verifyTaskRunner.run();
178
179
  if (options.welcomeMessage) {
179
180
  xvfb.loggerModule.log();
@@ -1127,8 +1128,8 @@ function createSpawnFunction(executable, args, options) {
1127
1128
  }
1128
1129
  if (xvfb.util.isPossibleLinuxWithIncorrectDisplay()) {
1129
1130
  // make sure we use the latest DISPLAY variable if any
1130
- debug('passing DISPLAY', process.env.DISPLAY);
1131
- stdioOptions.env.DISPLAY = process.env.DISPLAY;
1131
+ debug('passing DISPLAY', process$1.env.DISPLAY);
1132
+ stdioOptions.env.DISPLAY = process$1.env.DISPLAY;
1132
1133
  }
1133
1134
  if (stdioOptions.env.ELECTRON_RUN_AS_NODE) {
1134
1135
  // Since we are running electron as node, we need to add an entry point file.
@@ -1144,8 +1145,8 @@ function createSpawnFunction(executable, args, options) {
1144
1145
  if (startScriptPath) {
1145
1146
  args.unshift(startScriptPath);
1146
1147
  }
1147
- if (process.env.CYPRESS_INTERNAL_DEV_DEBUG) {
1148
- args.unshift(process.env.CYPRESS_INTERNAL_DEV_DEBUG);
1148
+ if (process$1.env.CYPRESS_INTERNAL_DEV_DEBUG) {
1149
+ args.unshift(process$1.env.CYPRESS_INTERNAL_DEV_DEBUG);
1149
1150
  }
1150
1151
  debug('spawn args %o %o', args, _.omit(stdioOptions, 'env'));
1151
1152
  debug('spawning Cypress with executable: %s', executable);
@@ -1156,14 +1157,16 @@ function createSpawnFunction(executable, args, options) {
1156
1157
  function resolveOn(event) {
1157
1158
  return function (code, signal) {
1158
1159
  debug('child event fired %o', { event, code, signal });
1159
- if (code === null) {
1160
- const errorObject = xvfb.errors.childProcessKilled(event, signal);
1161
- errorObject.platform = platform;
1162
- const err = xvfb.getErrorSync(errorObject, platform);
1163
- reject(err);
1160
+ if (signal) {
1161
+ if (signal === 'SIGINT') {
1162
+ resolve(0);
1163
+ }
1164
+ else {
1165
+ resolve(128 + os.constants.signals[signal]);
1166
+ }
1164
1167
  return;
1165
1168
  }
1166
- resolve(code);
1169
+ resolve(code !== null && code !== void 0 ? code : 1);
1167
1170
  };
1168
1171
  }
1169
1172
  const child = cp.spawn(executable, args, stdioOptions);
@@ -1184,6 +1187,24 @@ function createSpawnFunction(executable, args, options) {
1184
1187
  });
1185
1188
  });
1186
1189
  }
1190
+ else {
1191
+ // Adding listeners here prevents immediate process.exit() for these signals.
1192
+ // Exiting when the child process exits instead will allow the child process
1193
+ // to log during the exit process.
1194
+ // Unlike in windows, we do not need to propagate these signals to the child process
1195
+ // tree.
1196
+ for (const signal of ['SIGINT', 'SIGTERM']) {
1197
+ debug('adding message for signal listener for %s', signal);
1198
+ process$1.once(signal, function () {
1199
+ return xvfb.__awaiter(this, void 0, void 0, function* () {
1200
+ console.log(`\n\n${signal} received; Attempting to exit gracefully. Force exit with ^C again if needed.\n\n`);
1201
+ if (process$1.stdin.isTTY) {
1202
+ process$1.stdin.setRawMode(false);
1203
+ }
1204
+ });
1205
+ });
1206
+ }
1207
+ }
1187
1208
  // if stdio options is set to 'pipe', then
1188
1209
  // we should set up pipes:
1189
1210
  // process STDIN (read stream) => child STDIN (writeable)
@@ -1214,9 +1235,9 @@ function createSpawnFunction(executable, args, options) {
1214
1235
  sourceStream.write(data);
1215
1236
  }
1216
1237
  });
1217
- if (((_a = process.env.ELECTRON_ENABLE_LOGGING) !== null && _a !== void 0 ? _a : '') === '1' ||
1238
+ if (((_a = process$1.env.ELECTRON_ENABLE_LOGGING) !== null && _a !== void 0 ? _a : '') === '1' ||
1218
1239
  debugElectron.enabled ||
1219
- ((_b = process.env.CYPRESS_INTERNAL_ENV) !== null && _b !== void 0 ? _b : '') === 'development') {
1240
+ ((_b = process$1.env.CYPRESS_INTERNAL_ENV) !== null && _b !== void 0 ? _b : '') === 'development') {
1220
1241
  sourceStream.pipe(process$1.stderr, { end: false });
1221
1242
  }
1222
1243
  else {
@@ -1231,6 +1252,7 @@ function createSpawnFunction(executable, args, options) {
1231
1252
  // to have any effect. so we're just catching the
1232
1253
  // error here and not doing anything.
1233
1254
  process$1.stdin.on('error', (err) => {
1255
+ debug('error on stdin', err);
1234
1256
  if (['EPIPE', 'ENOTCONN'].includes(err.code)) {
1235
1257
  return;
1236
1258
  }
@@ -1304,16 +1326,16 @@ function start(args_1) {
1304
1326
  // binary that it was invoked through the NPM module
1305
1327
  const baseArgs = args ? (typeof args === 'string' ? [args] : args) : [];
1306
1328
  const decoratedArgs = baseArgs.concat([
1307
- '--cwd', process.cwd(),
1308
- '--userNodePath', process.execPath,
1309
- '--userNodeVersion', process.versions.node,
1329
+ '--cwd', process$1.cwd(),
1330
+ '--userNodePath', process$1.execPath,
1331
+ '--userNodeVersion', process$1.versions.node,
1310
1332
  ]);
1311
1333
  const needsXvfb = xvfb.xvfb.isNeeded();
1312
1334
  debug('needs to start own Xvfb?', needsXvfb);
1313
1335
  const stdio = (_a = options.stdio) !== null && _a !== void 0 ? _a : getStdioStrategy(needsXvfb);
1314
1336
  const dev = (_b = options.dev) !== null && _b !== void 0 ? _b : false;
1315
1337
  const detached = (_c = options.detached) !== null && _c !== void 0 ? _c : false;
1316
- const env = (_d = options.env) !== null && _d !== void 0 ? _d : process.env;
1338
+ const env = (_d = options.env) !== null && _d !== void 0 ? _d : process$1.env;
1317
1339
  const spawn = createSpawnFunction(executable, decoratedArgs, { stdio, dev, detached, env });
1318
1340
  if (needsXvfb) {
1319
1341
  debug('starting xvfb');
@@ -593,8 +593,12 @@ const isInstallingFromPostinstallHook = () => {
593
593
  };
594
594
  const getCacheDir = () => {
595
595
  let cache_directory = util.getCacheDir();
596
- if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
597
- const envVarCacheDir = untildify(util.getEnv('CYPRESS_CACHE_FOLDER'));
596
+ // Pass trim=true so we strip surrounding double quotes and whitespace.
597
+ // Windows CMD's `set CYPRESS_CACHE_FOLDER="C:\path"` embeds literal quotes
598
+ // into the env value; without dequoting, the resolved cache directory ends
599
+ // up with quote chars in its name (see cypress-io/cypress#4506).
600
+ if (util.getEnv('CYPRESS_CACHE_FOLDER', true)) {
601
+ const envVarCacheDir = untildify(util.getEnv('CYPRESS_CACHE_FOLDER', true));
598
602
  debug$1('using environment variable CYPRESS_CACHE_FOLDER %s', envVarCacheDir);
599
603
  if (!path.isAbsolute(envVarCacheDir) && isInstallingFromPostinstallHook()) {
600
604
  const packageRootFolder = path.join('..', '..', envVarCacheDir);
@@ -925,12 +929,6 @@ const CYPRESS_RUN_BINARY = {
925
929
  };
926
930
  },
927
931
  };
928
- function getErrorSync(errorObject, platform) {
929
- const errorMessage = syncFormErrorText(Object.assign(Object.assign({}, errorObject), { platform }));
930
- const err = new Error(errorMessage);
931
- err.known = true;
932
- return err;
933
- }
934
932
  function formErrorText(info, msg, prevMessage) {
935
933
  return __awaiter(this, void 0, void 0, function* () {
936
934
  const platform = yield util.getPlatformInfo();
@@ -1154,7 +1152,6 @@ exports._xvfb = _xvfb;
1154
1152
  exports._xvfbOptions = _xvfbOptions;
1155
1153
  exports.errors = errors;
1156
1154
  exports.exitWithError = exitWithError;
1157
- exports.getErrorSync = getErrorSync;
1158
1155
  exports.isNeeded = isNeeded;
1159
1156
  exports.loggerModule = loggerModule;
1160
1157
  exports.relativeToRepoRoot = relativeToRepoRoot;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress",
3
- "version": "15.15.0",
3
+ "version": "15.16.0",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "postinstall": "node dist/index.js --exec install",
@@ -27,7 +27,6 @@
27
27
  "eventemitter2": "6.4.7",
28
28
  "execa": "4.1.0",
29
29
  "executable": "^4.1.1",
30
- "extract-zip": "2.0.1",
31
30
  "fs-extra": "^9.1.0",
32
31
  "hasha": "5.2.2",
33
32
  "is-installed-globally": "~0.4.0",
@@ -46,7 +45,7 @@
46
45
  "tslib": "1.14.1",
47
46
  "tree-kill": "1.2.2",
48
47
  "untildify": "^4.0.0",
49
- "yauzl": "^2.10.0"
48
+ "yauzl": "^3.3.1"
50
49
  },
51
50
  "files": [
52
51
  "bin",
@@ -139,8 +138,8 @@
139
138
  },
140
139
  "buildInfo": {
141
140
  "commitBranch": "develop",
142
- "commitSha": "914ad901d9d50e2c744769a445643702ceca774b",
143
- "commitDate": "2026-05-12T03:59:53.000Z",
141
+ "commitSha": "22aaf2371462ec13f138fd96c11e8f9f885ed575",
142
+ "commitDate": "2026-05-26T16:59:59.000Z",
144
143
  "stable": true
145
144
  },
146
145
  "description": "Cypress is a next generation front end testing tool built for the modern web",
@@ -12,7 +12,9 @@
12
12
  // Roey Berman <https://github.com/bergundy>
13
13
  // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
14
14
 
15
- import * as FakeTimers from '@sinonjs/fake-timers';
15
+ // Import via the @types name so TS resolves to the bundled
16
+ // @types/sinonjs__fake-timers (cypress-io/cypress#33829).
17
+ import * as FakeTimers from 'sinonjs__fake-timers';
16
18
 
17
19
  // sinon uses DOM dependencies which are absent in browser-less environment like node.js
18
20
  // to avoid compiler errors this monkey patch is used