From d52997e975b9da6e0cea3d9b99873e9ddc768679 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Fri, 27 Oct 2023 16:40:36 -0700 Subject: [PATCH] feat: convert internal classes from util.inherits to classes BREAKING CHANGE: the `Gyp` class exported is now created using ECMAScript classes and therefore might have small differences to classes that were previously created with `util.inherits`. --- lib/configure.js | 4 +- lib/find-python.js | 83 +++++---- lib/find-visualstudio.js | 86 +++++---- lib/node-gyp.js | 311 ++++++++++++++++----------------- test/common.js | 14 ++ test/test-find-python.js | 59 +++---- test/test-find-visualstudio.js | 86 ++++----- 7 files changed, 303 insertions(+), 340 deletions(-) diff --git a/lib/configure.js b/lib/configure.js index 8ccfc3fad5..8d59e33497 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -9,8 +9,8 @@ const win = process.platform === 'win32' const findNodeDirectory = require('./find-node-directory') const createConfigGypi = require('./create-config-gypi') const { format: msgFormat } = require('util') -const findPython = require('./find-python') -const findVisualStudio = win ? require('./find-visualstudio') : null +const { findPython } = require('./find-python') +const { findVisualStudio } = win ? require('./find-visualstudio') : {} async function configure (gyp, argv) { const buildDir = path.resolve('build') diff --git a/lib/find-python.js b/lib/find-python.js index f01d1dd454..615da57bb8 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -2,10 +2,15 @@ const log = require('./log') const semver = require('semver') -const { _extend: extend } = require('util') // eslint-disable-line n/no-deprecated-api const { execFile } = require('./util') const win = process.platform === 'win32' +function getOsUserInfo () { + try { + return require('os').userInfo().username + } catch {} +} + const systemDrive = process.env.SystemDrive || 'C:' const username = process.env.USERNAME || process.env.USER || getOsUserInfo() const localAppData = process.env.LOCALAPPDATA || `${systemDrive}\\${username}\\AppData\\Local` @@ -32,40 +37,36 @@ for (const majorMinor of ['311', '310', '39', '38']) { } } -function getOsUserInfo () { - try { - return require('os').userInfo().username - } catch (e) {} -} - -function PythonFinder (configPython) { - this.configPython = configPython - this.errorLog = [] -} +class PythonFinder { + static findPython = (...args) => new PythonFinder(...args).findPython() -PythonFinder.prototype = { - log: log.withPrefix('find Python'), - argsExecutable: ['-c', 'import sys; print(sys.executable);'], - argsVersion: ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'], - semverRange: '>=3.6.0', + log = log.withPrefix('find Python') + argsExecutable = ['-c', 'import sys; print(sys.executable);'] + argsVersion = ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'] + semverRange = '>=3.6.0' // These can be overridden for testing: - execFile, - env: process.env, - win, - pyLauncher: 'py.exe', - winDefaultLocations: winDefaultLocationsArray, + execFile = execFile + env = process.env + win = win + pyLauncher = 'py.exe' + winDefaultLocations = winDefaultLocationsArray + + constructor (configPython) { + this.configPython = configPython + this.errorLog = [] + } // Logs a message at verbose level, but also saves it to be displayed later // at error level if an error occurs. This should help diagnose the problem. - addLog: function addLog (message) { + addLog (message) { this.log.verbose(message) this.errorLog.push(message) - }, + } // Find Python by trying a sequence of possibilities. // Ignore errors, keep trying until Python is found. - findPython: async function findPython () { + async findPython () { const SKIP = 0 const FAIL = 1 const toCheck = (() => { @@ -161,12 +162,12 @@ PythonFinder.prototype = { } return this.fail() - }, + } // Check if command is a valid Python to use. // Will exit the Python finder on success. // If on Windows, run in a CMD shell to support BAT/CMD launchers. - checkCommand: async function checkCommand (command) { + async checkCommand (command) { let exec = command let args = this.argsExecutable let shell = false @@ -190,7 +191,7 @@ PythonFinder.prototype = { this.addLog(`- "${command}" is not in PATH or produced an error`) throw err } - }, + } // Check if the py launcher can find a valid Python to use. // Will exit the Python finder on success. @@ -202,7 +203,7 @@ PythonFinder.prototype = { // the first command line argument. Since "py.exe -3" would be an invalid // executable for "execFile", we have to use the launcher to figure out // where the actual "python.exe" executable is located. - checkPyLauncher: async function checkPyLauncher () { + async checkPyLauncher () { this.log.verbose(`- executing "${this.pyLauncher}" to get Python 3 executable path`) // Possible outcomes: same as checkCommand try { @@ -213,11 +214,11 @@ PythonFinder.prototype = { this.addLog(`- "${this.pyLauncher}" is not in PATH or produced an error`) throw err } - }, + } // Check if a Python executable is the correct version to use. // Will exit the Python finder on success. - checkExecPath: async function checkExecPath (execPath) { + async checkExecPath (execPath) { this.log.verbose(`- executing "${execPath}" to get version`) // Possible outcomes: // - Error: executable can not be run (likely meaning the command wasn't @@ -249,11 +250,11 @@ PythonFinder.prototype = { this.addLog(`- "${execPath}" could not be run`) throw err } - }, + } // Run an executable or shell command, trimming the output. - run: async function run (exec, args, shell) { - const env = extend({}, this.env) + async run (exec, args, shell) { + const env = Object.assign({}, this.env) env.TERM = 'dumb' const opts = { env, shell } @@ -270,14 +271,14 @@ PythonFinder.prototype = { this.log.silly('execFile: threw:\n%s', err.stack) throw err } - }, + } - succeed: function succeed (execPath, version) { + succeed (execPath, version) { this.log.info(`using Python version ${version} found at "${execPath}"`) return execPath - }, + } - fail: function fail () { + fail () { const errorLog = this.errorLog.join('\n') const pathExample = this.win @@ -306,10 +307,4 @@ PythonFinder.prototype = { } } -const findPython = async (configPython) => new PythonFinder(configPython).findPython() - -module.exports = findPython -module.exports.test = { - PythonFinder, - findPython -} +module.exports = PythonFinder diff --git a/lib/find-visualstudio.js b/lib/find-visualstudio.js index 7df976a2db..b57770259a 100644 --- a/lib/find-visualstudio.js +++ b/lib/find-visualstudio.js @@ -5,26 +5,28 @@ const { existsSync } = require('fs') const { win32: path } = require('path') const { regSearchKeys, execFile } = require('./util') -function VisualStudioFinder (nodeSemver, configMsvsVersion) { - this.nodeSemver = nodeSemver - this.configMsvsVersion = configMsvsVersion - this.errorLog = [] - this.validVersions = [] -} +class VisualStudioFinder { + static findVisualStudio = (...args) => new VisualStudioFinder(...args).findVisualStudio() + + log = log.withPrefix('find VS') -VisualStudioFinder.prototype = { - log: log.withPrefix('find VS'), + regSearchKeys = regSearchKeys - regSearchKeys, + constructor (nodeSemver, configMsvsVersion) { + this.nodeSemver = nodeSemver + this.configMsvsVersion = configMsvsVersion + this.errorLog = [] + this.validVersions = [] + } // Logs a message at verbose level, but also saves it to be displayed later // at error level if an error occurs. This should help diagnose the problem. - addLog: function addLog (message) { + addLog (message) { this.log.verbose(message) this.errorLog.push(message) - }, + } - findVisualStudio: async function findVisualStudio () { + async findVisualStudio () { this.configVersionYear = null this.configPath = null if (this.configMsvsVersion) { @@ -65,16 +67,16 @@ VisualStudioFinder.prototype = { } return this.fail() - }, + } - succeed: function succeed (info) { + succeed (info) { this.log.info(`using VS${info.versionYear} (${info.version}) found at:` + `\n"${info.path}"` + '\nrun with --verbose for detailed information') return info - }, + } - fail: function fail () { + fail () { if (this.configMsvsVersion && this.envVcInstallDir) { this.errorLog.push( 'msvs_version does not match this VS Command Prompt or the', @@ -109,11 +111,11 @@ VisualStudioFinder.prototype = { this.log.error(`\n${errorLog}\n\n${infoLog}\n`) throw new Error('Could not find any Visual Studio installation to use') - }, + } // Invoke the PowerShell script to get information about Visual Studio 2017 // or newer installations - findVisualStudio2017OrNewer: async function findVisualStudio2017OrNewer () { + async findVisualStudio2017OrNewer () { const ps = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe') const csFile = path.join(__dirname, 'Find-VisualStudio.cs') @@ -128,11 +130,11 @@ VisualStudioFinder.prototype = { this.log.silly('Running', ps, psArgs) const [err, stdout, stderr] = await execFile(ps, psArgs, { encoding: 'utf8' }) return this.parseData(err, stdout, stderr) - }, + } // Parse the output of the PowerShell script and look for an installation // of Visual Studio 2017 or newer to use - parseData: function parseData (err, stdout, stderr) { + parseData (err, stdout, stderr) { this.log.silly('PS stderr = %j', stderr) const failPowershell = () => { @@ -220,10 +222,10 @@ VisualStudioFinder.prototype = { this.addLog( 'could not find a version of Visual Studio 2017 or newer to use') return null - }, + } // Helper - process version information - getVersionInfo: function getVersionInfo (info) { + getVersionInfo (info) { const match = /^(\d+)\.(\d+)\..*/.exec(info.version) if (!match) { this.log.silly('- failed to parse version:', info.version) @@ -249,14 +251,14 @@ VisualStudioFinder.prototype = { } this.log.silly('- unsupported version:', ret.versionMajor) return {} - }, + } - msBuildPathExists: function msBuildPathExists (path) { + msBuildPathExists (path) { return existsSync(path) - }, + } // Helper - process MSBuild information - getMSBuild: function getMSBuild (info, versionYear) { + getMSBuild (info, versionYear) { const pkg = 'Microsoft.VisualStudio.VC.MSBuild.Base' const msbuildPath = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'MSBuild.exe') const msbuildPathArm64 = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'arm64', 'MSBuild.exe') @@ -280,10 +282,10 @@ VisualStudioFinder.prototype = { return msbuildPath } return null - }, + } // Helper - process toolset information - getToolset: function getToolset (info, versionYear) { + getToolset (info, versionYear) { const pkg = 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64' const express = 'Microsoft.VisualStudio.WDExpress' @@ -304,10 +306,10 @@ VisualStudioFinder.prototype = { } this.log.silly('- invalid versionYear:', versionYear) return null - }, + } // Helper - process Windows SDK information - getSDK: function getSDK (info) { + getSDK (info) { const win8SDK = 'Microsoft.VisualStudio.Component.Windows81SDK' const win10SDKPrefix = 'Microsoft.VisualStudio.Component.Windows10SDK.' const win11SDKPrefix = 'Microsoft.VisualStudio.Component.Windows11SDK.' @@ -339,10 +341,10 @@ VisualStudioFinder.prototype = { return '8.1' } return null - }, + } // Find an installation of Visual Studio 2015 to use - findVisualStudio2015: async function findVisualStudio2015 () { + async findVisualStudio2015 () { if (this.nodeSemver.major >= 19) { this.addLog( 'not looking for VS2015 as it is only supported up to Node.js 18') @@ -355,10 +357,10 @@ VisualStudioFinder.prototype = { versionYear: 2015, toolset: 'v140' }) - }, + } // Find an installation of Visual Studio 2013 to use - findVisualStudio2013: async function findVisualStudio2013 () { + async findVisualStudio2013 () { if (this.nodeSemver.major >= 9) { this.addLog( 'not looking for VS2013 as it is only supported up to Node.js 8') @@ -371,10 +373,10 @@ VisualStudioFinder.prototype = { versionYear: 2013, toolset: 'v120' }) - }, + } // Helper - common code for VS2013 and VS2015 - findOldVS: async function findOldVS (info) { + async findOldVS (info) { const regVC7 = ['HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7', 'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7'] const regMSBuild = 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions' @@ -408,14 +410,14 @@ VisualStudioFinder.prototype = { this.addLog('- not found') return null } - }, + } // After finding a usable version of Visual Studio: // - add it to validVersions to be displayed at the end if a specific // version was requested and not found; // - check if this is the version that was requested. // - check if this matches the Visual Studio Command Prompt - checkConfigVersion: function checkConfigVersion (versionYear, vsPath) { + checkConfigVersion (versionYear, vsPath) { this.validVersions.push(versionYear) this.validVersions.push(vsPath) @@ -438,10 +440,4 @@ VisualStudioFinder.prototype = { } } -const findVisualStudio = async (nodeSemver, configMsvsVersion) => new VisualStudioFinder(nodeSemver, configMsvsVersion).findVisualStudio() - -module.exports = findVisualStudio -module.exports.test = { - VisualStudioFinder, - findVisualStudio -} +module.exports = VisualStudioFinder diff --git a/lib/node-gyp.js b/lib/node-gyp.js index c2ce69051f..5e25bf996f 100644 --- a/lib/node-gyp.js +++ b/lib/node-gyp.js @@ -4,8 +4,8 @@ const path = require('path') const nopt = require('nopt') const log = require('./log') const childProcess = require('child_process') -const EE = require('events').EventEmitter -const { inherits } = require('util') +const { EventEmitter } = require('events') + const commands = [ // Module build commands 'build', @@ -17,191 +17,172 @@ const commands = [ 'list', 'remove' ] -const aliases = { - ls: 'list', - rm: 'remove' -} -function gyp () { - return new Gyp() -} +class Gyp extends EventEmitter { + /** + * Export the contents of the package.json. + */ + package = require('../package.json') + + /** + * nopt configuration definitions + */ + configDefs = { + help: Boolean, // everywhere + arch: String, // 'configure' + cafile: String, // 'install' + debug: Boolean, // 'build' + directory: String, // bin + make: String, // 'build' + 'msvs-version': String, // 'configure' + ensure: Boolean, // 'install' + solution: String, // 'build' (windows only) + proxy: String, // 'install' + noproxy: String, // 'install' + devdir: String, // everywhere + nodedir: String, // 'configure' + loglevel: String, // everywhere + python: String, // 'configure' + 'dist-url': String, // 'install' + tarball: String, // 'install' + jobs: String, // 'build' + thin: String, // 'configure' + 'force-process-config': Boolean // 'configure' + } -function Gyp () { - this.devDir = '' + /** + * nopt shorthands + */ + shorthands = { + release: '--no-debug', + C: '--directory', + debug: '--debug', + j: '--jobs', + silly: '--loglevel=silly', + verbose: '--loglevel=verbose', + silent: '--loglevel=silent' + } - this.commands = commands.reduce((acc, command) => { - acc[command] = (argv) => require('./' + command)(this, argv) - return acc - }, {}) -} -inherits(Gyp, EE) -exports.Gyp = Gyp -const proto = Gyp.prototype - -/** - * Export the contents of the package.json. - */ - -proto.package = require('../package.json') - -/** - * nopt configuration definitions - */ - -proto.configDefs = { - help: Boolean, // everywhere - arch: String, // 'configure' - cafile: String, // 'install' - debug: Boolean, // 'build' - directory: String, // bin - make: String, // 'build' - 'msvs-version': String, // 'configure' - ensure: Boolean, // 'install' - solution: String, // 'build' (windows only) - proxy: String, // 'install' - noproxy: String, // 'install' - devdir: String, // everywhere - nodedir: String, // 'configure' - loglevel: String, // everywhere - python: String, // 'configure' - 'dist-url': String, // 'install' - tarball: String, // 'install' - jobs: String, // 'build' - thin: String, // 'configure' - 'force-process-config': Boolean // 'configure' -} + /** + * expose the command aliases for the bin file to use. + */ + aliases = { + ls: 'list', + rm: 'remove' + } -/** - * nopt shorthands - */ - -proto.shorthands = { - release: '--no-debug', - C: '--directory', - debug: '--debug', - j: '--jobs', - silly: '--loglevel=silly', - verbose: '--loglevel=verbose', - silent: '--loglevel=silent' -} + constructor (...args) { + super(...args) -/** - * expose the command aliases for the bin file to use. - */ + this.devDir = '' -proto.aliases = aliases + this.commands = commands.reduce((acc, command) => { + acc[command] = (argv) => require('./' + command)(this, argv) + return acc + }, {}) -/** - * Parses the given argv array and sets the 'opts', - * 'argv' and 'command' properties. - */ + Object.defineProperty(this, 'version', { + enumerable: true, + get: function () { return this.package.version } + }) + } -proto.parseArgv = function parseOpts (argv) { - this.opts = nopt(this.configDefs, this.shorthands, argv) - this.argv = this.opts.argv.remain.slice() + /** + * Parses the given argv array and sets the 'opts', + * 'argv' and 'command' properties. + */ + parseArgv (argv) { + this.opts = nopt(this.configDefs, this.shorthands, argv) + this.argv = this.opts.argv.remain.slice() - const commands = this.todo = [] + const commands = this.todo = [] - // create a copy of the argv array with aliases mapped - argv = this.argv.map(function (arg) { + // create a copy of the argv array with aliases mapped + argv = this.argv.map((arg) => { // is this an alias? - if (arg in this.aliases) { - arg = this.aliases[arg] - } - return arg - }, this) - - // process the mapped args into "command" objects ("name" and "args" props) - argv.slice().forEach(function (arg) { - if (arg in this.commands) { - const args = argv.splice(0, argv.indexOf(arg)) - argv.shift() - if (commands.length > 0) { - commands[commands.length - 1].args = args + if (arg in this.aliases) { + arg = this.aliases[arg] } - commands.push({ name: arg, args: [] }) + return arg + }) + + // process the mapped args into "command" objects ("name" and "args" props) + argv.slice().forEach((arg) => { + if (arg in this.commands) { + const args = argv.splice(0, argv.indexOf(arg)) + argv.shift() + if (commands.length > 0) { + commands[commands.length - 1].args = args + } + commands.push({ name: arg, args: [] }) + } + }) + if (commands.length > 0) { + commands[commands.length - 1].args = argv.splice(0) } - }, this) - if (commands.length > 0) { - commands[commands.length - 1].args = argv.splice(0) - } - // support for inheriting config env variables from npm - const npmConfigPrefix = 'npm_config_' - Object.keys(process.env).forEach(function (name) { - if (name.indexOf(npmConfigPrefix) !== 0) { - return - } - const val = process.env[name] - if (name === npmConfigPrefix + 'loglevel') { - log.logger.level = val - } else { + // support for inheriting config env variables from npm + const npmConfigPrefix = 'npm_config_' + Object.keys(process.env).forEach((name) => { + if (name.indexOf(npmConfigPrefix) !== 0) { + return + } + const val = process.env[name] + if (name === npmConfigPrefix + 'loglevel') { + log.logger.level = val + } else { // add the user-defined options to the config - name = name.substring(npmConfigPrefix.length) - // gyp@741b7f1 enters an infinite loop when it encounters - // zero-length options so ensure those don't get through. - if (name) { + name = name.substring(npmConfigPrefix.length) + // gyp@741b7f1 enters an infinite loop when it encounters + // zero-length options so ensure those don't get through. + if (name) { // convert names like force_process_config to force-process-config - if (name.includes('_')) { - name = name.replace(/_/g, '-') + if (name.includes('_')) { + name = name.replace(/_/g, '-') + } + this.opts[name] = val } - this.opts[name] = val } - } - }, this) + }) - if (this.opts.loglevel) { - log.logger.level = this.opts.loglevel + if (this.opts.loglevel) { + log.logger.level = this.opts.loglevel + } + log.resume() } - log.resume() -} - -/** - * Spawns a child process and emits a 'spawn' event. - */ -proto.spawn = function spawn (command, args, opts) { - if (!opts) { - opts = {} - } - if (!opts.silent && !opts.stdio) { - opts.stdio = [0, 1, 2] + /** + * Spawns a child process and emits a 'spawn' event. + */ + spawn (command, args, opts) { + if (!opts) { + opts = {} + } + if (!opts.silent && !opts.stdio) { + opts.stdio = [0, 1, 2] + } + const cp = childProcess.spawn(command, args, opts) + log.info('spawn', command) + log.info('spawn args', args) + return cp } - const cp = childProcess.spawn(command, args, opts) - log.info('spawn', command) - log.info('spawn args', args) - return cp -} -/** - * Returns the usage instructions for node-gyp. - */ - -proto.usage = function usage () { - const str = [ - '', - ' Usage: node-gyp [options]', - '', - ' where is one of:', - commands.map(function (c) { - return ' - ' + c + ' - ' + require('./' + c).usage - }).join('\n'), - '', - 'node-gyp@' + this.version + ' ' + path.resolve(__dirname, '..'), - 'node@' + process.versions.node - ].join('\n') - return str + /** + * Returns the usage instructions for node-gyp. + */ + usage () { + return [ + '', + ' Usage: node-gyp [options]', + '', + ' where is one of:', + commands.map((c) => ' - ' + c + ' - ' + require('./' + c).usage).join('\n'), + '', + 'node-gyp@' + this.version + ' ' + path.resolve(__dirname, '..'), + 'node@' + process.versions.node + ].join('\n') + } } -/** - * Version number getter. - */ - -Object.defineProperty(proto, 'version', { - get: function () { - return this.package.version - }, - enumerable: true -}) - -module.exports = exports = gyp +module.exports = () => new Gyp() +module.exports.Gyp = Gyp diff --git a/test/common.js b/test/common.js index b714ee2902..f7e2e2a34c 100644 --- a/test/common.js +++ b/test/common.js @@ -1,3 +1,17 @@ const envPaths = require('env-paths') module.exports.devDir = () => envPaths('node-gyp', { suffix: '' }).cache + +module.exports.poison = (object, property) => { + function fail () { + console.error(Error(`Property ${property} should not have been accessed.`)) + process.abort() + } + const descriptor = { + configurable: false, + enumerable: false, + get: fail, + set: fail + } + Object.defineProperty(object, property, descriptor) +} diff --git a/test/test-find-python.js b/test/test-find-python.js index a00ae94057..c5fa35d4bc 100644 --- a/test/test-find-python.js +++ b/test/test-find-python.js @@ -4,42 +4,33 @@ delete process.env.PYTHON const { describe, it } = require('mocha') const assert = require('assert') -const { test: { PythonFinder, findPython: testFindPython } } = require('../lib/find-python') +const PythonFinder = require('../lib/find-python') const { execFile } = require('../lib/util') +const { poison } = require('./common') -describe('find-python', function () { - it('find python', async function () { - const found = await testFindPython(null) - const [err, stdout, stderr] = await execFile(found, ['-V'], { encoding: 'utf-8' }) - assert.strictEqual(err, null) - assert.ok(/Python 3/.test(stdout)) - assert.strictEqual(stderr, '') - }) - - function poison (object, property) { - function fail () { - console.error(Error(`Property ${property} should not have been accessed.`)) - process.abort() - } - const descriptor = { - configurable: false, - enumerable: false, - get: fail, - set: fail - } - Object.defineProperty(object, property, descriptor) +class TestPythonFinder extends PythonFinder { + constructor (...args) { + super(...args) + delete this.env.NODE_GYP_FORCE_PYTHON } - function TestPythonFinder () { PythonFinder.apply(this, arguments) } - TestPythonFinder.prototype = Object.create(PythonFinder.prototype) - delete TestPythonFinder.prototype.env.NODE_GYP_FORCE_PYTHON - const findPython = async (f) => { + async findPython () { try { - return { err: null, python: await f.findPython() } + return { err: null, python: await super.findPython() } } catch (err) { return { err, python: null } } } +} + +describe('find-python', function () { + it('find python', async function () { + const found = await PythonFinder.findPython(null) + const [err, stdout, stderr] = await execFile(found, ['-V'], { encoding: 'utf-8' }) + assert.strictEqual(err, null) + assert.ok(/Python 3/.test(stdout)) + assert.strictEqual(stderr, '') + }) it('find python - python', async function () { const f = new TestPythonFinder('python') @@ -55,7 +46,7 @@ describe('find-python', function () { return [null, '/path/python'] } - const { err, python } = await findPython(f) + const { err, python } = await f.findPython() assert.strictEqual(err, null) assert.strictEqual(python, '/path/python') }) @@ -72,7 +63,7 @@ describe('find-python', function () { } } - const { err } = await findPython(f) + const { err } = await f.findPython() assert.ok(/Could not find any Python/.test(err)) assert.ok(/not supported/i.test(f.errorLog)) }) @@ -89,7 +80,7 @@ describe('find-python', function () { } } - const { err } = await findPython(f) + const { err } = await f.findPython() assert.ok(/Could not find any Python/.test(err)) assert.ok(/not in PATH/.test(f.errorLog)) }) @@ -107,7 +98,7 @@ describe('find-python', function () { } } - const { err } = await findPython(f) + const { err } = await f.findPython() assert.ok(/Could not find any Python/.test(err)) assert.ok(/not in PATH/.test(f.errorLog)) }) @@ -136,7 +127,7 @@ describe('find-python', function () { assert.fail() } } - const { err, python } = await findPython(f) + const { err, python } = await f.findPython() assert.strictEqual(err, null) assert.strictEqual(python, 'Z:\\snake.exe') }) @@ -159,7 +150,7 @@ describe('find-python', function () { assert.fail() } } - const { err, python } = await findPython(f) + const { err, python } = await f.findPython() assert.strictEqual(err, null) assert.ok(python === expectedProgram) }) @@ -177,7 +168,7 @@ describe('find-python', function () { assert.fail() } } - const { err } = await findPython(f) + const { err } = await f.findPython() assert.ok(/Could not find any Python/.test(err)) assert.ok(/not in PATH/.test(f.errorLog)) }) diff --git a/test/test-find-visualstudio.js b/test/test-find-visualstudio.js index cb065e52cf..08e9438c45 100644 --- a/test/test-find-visualstudio.js +++ b/test/test-find-visualstudio.js @@ -4,34 +4,20 @@ const { describe, it } = require('mocha') const assert = require('assert') const fs = require('fs') const path = require('path') -const { test: { VisualStudioFinder } } = require('../lib/find-visualstudio') +const VisualStudioFinder = require('../lib/find-visualstudio') +const { poison } = require('./common') const semverV1 = { major: 1, minor: 0, patch: 0 } delete process.env.VCINSTALLDIR -function poison (object, property) { - function fail () { - console.error(Error(`Property ${property} should not have been accessed.`)) - process.abort() - } - const descriptor = { - configurable: false, - enumerable: false, - get: fail, - set: fail - } - Object.defineProperty(object, property, descriptor) -} - -function TestVisualStudioFinder () { VisualStudioFinder.apply(this, arguments) } -TestVisualStudioFinder.prototype = Object.create(VisualStudioFinder.prototype) - -const findVisualStudio = async (finder) => { - try { - return { err: null, info: await finder.findVisualStudio() } - } catch (err) { - return { err, info: null } +class TestVisualStudioFinder extends VisualStudioFinder { + async findVisualStudio () { + try { + return { err: null, info: await super.findVisualStudio() } + } catch (err) { + return { err, info: null } + } } } @@ -62,7 +48,7 @@ describe('find-visualstudio', function () { throw new Error() } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: 'C:\\MSBuild12\\MSBuild.exe', @@ -102,7 +88,7 @@ describe('find-visualstudio', function () { throw new Error() } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.ok(/find .* Visual Studio/i.test(err), 'expect error') assert.ok(!info, 'no data') }) @@ -129,7 +115,7 @@ describe('find-visualstudio', function () { } throw new Error() } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: 'C:\\MSBuild14\\MSBuild.exe', @@ -228,7 +214,7 @@ describe('find-visualstudio', function () { const data = fs.readFileSync(file) return finder.parseData(null, data, '') } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\' + @@ -254,7 +240,7 @@ describe('find-visualstudio', function () { const data = fs.readFileSync(file) return finder.parseData(null, data, '') } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\' + @@ -279,7 +265,7 @@ describe('find-visualstudio', function () { const data = fs.readFileSync(file) return finder.parseData(null, data, '') } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\' + @@ -305,7 +291,7 @@ describe('find-visualstudio', function () { const data = fs.readFileSync(file) return finder.parseData(null, data, '') } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\' + @@ -331,7 +317,7 @@ describe('find-visualstudio', function () { const data = fs.readFileSync(file) return finder.parseData(null, data, '') } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\' + @@ -357,7 +343,7 @@ describe('find-visualstudio', function () { const data = fs.readFileSync(file) return finder.parseData(null, data, '') } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\' + @@ -392,7 +378,7 @@ describe('find-visualstudio', function () { const data = fs.readFileSync(file) return finder.parseData(null, data, '') } - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info, { msBuild: msBuildPath, @@ -456,7 +442,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, 'AABB') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.ok(/find .* Visual Studio/i.test(err), 'expect error') assert.ok(!info, 'no data') }) @@ -465,7 +451,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, '2013') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.versionYear, 2013) }) @@ -474,7 +460,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, 'C:\\VS2013') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.path, 'C:\\VS2013') }) @@ -483,7 +469,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, '2015') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.versionYear, 2015) }) @@ -492,7 +478,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, 'C:\\VS2015') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.path, 'C:\\VS2015') }) @@ -501,7 +487,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, '2017') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.versionYear, 2017) }) @@ -511,7 +497,7 @@ describe('find-visualstudio', function () { 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.path, 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community') @@ -521,7 +507,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, '2019') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.versionYear, 2019) }) @@ -531,7 +517,7 @@ describe('find-visualstudio', function () { 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.path, 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools') @@ -545,7 +531,7 @@ describe('find-visualstudio', function () { } allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.versionYear, 2022) }) @@ -555,7 +541,7 @@ describe('find-visualstudio', function () { 'c:\\program files (x86)\\microsoft visual studio\\2019\\BUILDTOOLS') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.path, 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools') @@ -569,7 +555,7 @@ describe('find-visualstudio', function () { } allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.versionYear, 2022) }) @@ -582,7 +568,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.path, 'C:\\VS2015') }) @@ -594,7 +580,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.path, 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools') @@ -607,7 +593,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, null) allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.ok(/find .* Visual Studio/i.test(err), 'expect error') assert.ok(!info, 'no data') }) @@ -618,7 +604,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, 'C:\\VS2015') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.strictEqual(err, null) assert.deepStrictEqual(info.path, 'C:\\VS2015') }) @@ -630,7 +616,7 @@ describe('find-visualstudio', function () { const finder = new TestVisualStudioFinder(semverV1, 'C:\\VS2015') allVsVersions(finder) - const { err, info } = await findVisualStudio(finder) + const { err, info } = await finder.findVisualStudio() assert.ok(/find .* Visual Studio/i.test(err), 'expect error') assert.ok(!info, 'no data') })