File: D:/HostingSpaces/SBogers10/base.komma.pro/node_modules/cypress/lib/exec/spawn.js
"use strict";
var _ = require('lodash');
var os = require('os');
var cp = require('child_process');
var path = require('path');
var Promise = require('bluebird');
var debug = require('debug')('cypress:cli');
var debugElectron = require('debug')('cypress:electron');
var util = require('../util');
var state = require('../tasks/state');
var xvfb = require('./xvfb');
var verify = require('../tasks/verify');
var errors = require('../errors');
var isXlibOrLibudevRe = /^(?:Xlib|libudev)/;
var isHighSierraWarningRe = /\*\*\* WARNING/;
var isRenderWorkerRe = /\.RenderWorker-/;
var GARBAGE_WARNINGS = [isXlibOrLibudevRe, isHighSierraWarningRe, isRenderWorkerRe];
var isGarbageLineWarning = function isGarbageLineWarning(str) {
return _.some(GARBAGE_WARNINGS, function (re) {
return re.test(str);
});
};
function isPlatform(platform) {
return os.platform() === platform;
}
function needsStderrPiped(needsXvfb) {
return _.some([isPlatform('darwin'), needsXvfb && isPlatform('linux'), util.isPossibleLinuxWithIncorrectDisplay()]);
}
function needsEverythingPipedDirectly() {
return isPlatform('win32');
}
function getStdio(needsXvfb) {
if (needsEverythingPipedDirectly()) {
return 'pipe';
} // https://github.com/cypress-io/cypress/issues/921
// https://github.com/cypress-io/cypress/issues/1143
// https://github.com/cypress-io/cypress/issues/1745
if (needsStderrPiped(needsXvfb)) {
// returning pipe here so we can massage stderr
// and remove garbage from Xlib and libuv
// due to starting the Xvfb process on linux
return ['inherit', 'inherit', 'pipe'];
}
return 'inherit';
}
module.exports = {
isGarbageLineWarning: isGarbageLineWarning,
start: function start(args) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var needsXvfb = xvfb.isNeeded();
var executable = state.getPathToExecutable(state.getBinaryDir());
if (util.getEnv('CYPRESS_RUN_BINARY')) {
executable = path.resolve(util.getEnv('CYPRESS_RUN_BINARY'));
}
debug('needs to start own Xvfb?', needsXvfb); // 1. Start arguments with "--" so Electron knows these are OUR
// arguments and does not try to sanitize them. Otherwise on Windows
// an url in one of the arguments crashes it :(
// https://github.com/cypress-io/cypress/issues/5466
// 2. Always push cwd into the args
// which additionally acts as a signal to the
// binary that it was invoked through the NPM module
args = ['--'].concat(args, '--cwd', process.cwd());
_.defaults(options, {
dev: false,
env: process.env,
detached: false,
stdio: getStdio(needsXvfb)
});
var spawn = function spawn() {
var overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return new Promise(function (resolve, reject) {
_.defaults(overrides, {
onStderrData: false,
electronLogging: false
});
if (options.dev) {
// if we're in dev then reset
// the launch cmd to be 'npm run dev'
executable = 'node';
args.unshift(path.resolve(__dirname, '..', '..', '..', 'scripts', 'start.js'));
debug('in dev mode the args became %o', args);
}
var onStderrData = overrides.onStderrData,
electronLogging = overrides.electronLogging;
var envOverrides = util.getEnvOverrides(options);
var electronArgs = _.clone(args);
var node11WindowsFix = isPlatform('win32');
if (!options.dev && verify.needsSandbox()) {
// this is one of the Electron's command line switches
// thus it needs to be before "--" separator
electronArgs.unshift('--no-sandbox');
} // strip dev out of child process options
var stdioOptions = _.pick(options, 'env', 'detached', 'stdio'); // figure out if we're going to be force enabling or disabling colors.
// also figure out whether we should force stdout and stderr into thinking
// it is a tty as opposed to a pipe.
stdioOptions.env = _.extend({}, stdioOptions.env, envOverrides);
if (node11WindowsFix) {
stdioOptions = _.extend({}, stdioOptions, {
windowsHide: false
});
}
if (electronLogging) {
stdioOptions.env.ELECTRON_ENABLE_LOGGING = true;
}
if (util.isPossibleLinuxWithIncorrectDisplay()) {
// make sure we use the latest DISPLAY variable if any
debug('passing DISPLAY', process.env.DISPLAY);
stdioOptions.env.DISPLAY = process.env.DISPLAY;
}
debug('spawning Cypress with executable: %s', executable);
debug('spawn args %o %o', electronArgs, _.omit(stdioOptions, 'env'));
var child = cp.spawn(executable, electronArgs, stdioOptions);
function resolveOn(event) {
return function (code, signal) {
debug('child event fired %o', {
event: event,
code: code,
signal: signal
});
if (code === null) {
var errorObject = errors.errors.childProcessKilled(event, signal);
return errors.getError(errorObject).then(reject);
}
resolve(code);
};
}
child.on('close', resolveOn('close'));
child.on('exit', resolveOn('exit'));
child.on('error', reject); // if stdio options is set to 'pipe', then
// we should set up pipes:
// process STDIN (read stream) => child STDIN (writeable)
// child STDOUT => process STDOUT
// child STDERR => process STDERR with additional filtering
if (child.stdin) {
debug('piping process STDIN into child STDIN');
process.stdin.pipe(child.stdin);
}
if (child.stdout) {
debug('piping child STDOUT to process STDOUT');
child.stdout.pipe(process.stdout);
} // if this is defined then we are manually piping for linux
// to filter out the garbage
if (child.stderr) {
debug('piping child STDERR to process STDERR');
child.stderr.on('data', function (data) {
var str = data.toString(); // bail if this is warning line garbage
if (isGarbageLineWarning(str)) {
return;
} // if we have a callback and this explictly returns
// false then bail
if (onStderrData && onStderrData(str) === false) {
return;
} // else pass it along!
process.stderr.write(data);
});
} // https://github.com/cypress-io/cypress/issues/1841
// https://github.com/cypress-io/cypress/issues/5241
// In some versions of node, it will throw on windows
// when you close the parent process after piping
// into the child process. unpiping does not seem
// to have any effect. so we're just catching the
// error here and not doing anything.
process.stdin.on('error', function (err) {
if (['EPIPE', 'ENOTCONN'].includes(err.code)) {
return;
}
throw err;
});
if (stdioOptions.detached) {
child.unref();
}
});
};
var spawnInXvfb = function spawnInXvfb() {
return xvfb.start().then(userFriendlySpawn)["finally"](xvfb.stop);
};
var userFriendlySpawn = function userFriendlySpawn(linuxWithDisplayEnv) {
debug('spawning, should retry on display problem?', Boolean(linuxWithDisplayEnv));
var brokenGtkDisplay;
var overrides = {};
if (linuxWithDisplayEnv) {
_.extend(overrides, {
electronLogging: true,
onStderrData: function onStderrData(str) {
// if we receive a broken pipe anywhere
// then we know that's why cypress exited early
if (util.isBrokenGtkDisplay(str)) {
brokenGtkDisplay = true;
} // we should attempt to always slurp up
// the stderr logs unless we've explicitly
// enabled the electron debug logging
if (!debugElectron.enabled) {
return false;
}
}
});
}
return spawn(overrides).then(function (code) {
if (code !== 0 && brokenGtkDisplay) {
util.logBrokenGtkDisplayWarning();
return spawnInXvfb();
}
return code;
}) // we can format and handle an error message from the code above
// prevent wrapping error again by using "known: undefined" filter
["catch"]({
known: undefined
}, errors.throwFormErrorText(errors.errors.unexpected));
};
if (needsXvfb) {
return spawnInXvfb();
} // if we are on linux and there's already a DISPLAY
// set, then we may need to rerun cypress after
// spawning our own Xvfb server
var linuxWithDisplayEnv = util.isPossibleLinuxWithIncorrectDisplay();
return userFriendlySpawn(linuxWithDisplayEnv);
}
};