From 80f5cb1cef1f2043c592adc4055802a27c40cc7b Mon Sep 17 00:00:00 2001 From: "Mark S. Miller" Date: Wed, 4 Sep 2024 22:31:56 -0700 Subject: [PATCH] refactor: Errors do not need `new` (#10030) Closes: #XXXX Refs: https://github.com/endojs/endo/pull/2445 ## Description Errors do not need `new` For all construction calls to a `*Error` constructor, the `new` is not needed. IOW, just calling the `*Error` constructor as a function has the same effect. ### Security Considerations none ### Scaling Considerations none ### Documentation Considerations none ### Testing Considerations none ### Compatibility Considerations none ### Upgrade Considerations none --- .../b:enable-orchestration/test-lib/wallet.js | 2 +- .../proposals/c:stake-bld/test-lib/wallet.js | 2 +- .../test/ica-channel-close.test.ts | 4 ++-- multichain-testing/tools/address.ts | 4 ++-- multichain-testing/tools/deploy.ts | 2 +- multichain-testing/tools/makeHttpClient.js | 2 +- multichain-testing/tools/marshalTables.js | 2 +- multichain-testing/tools/sleep.ts | 2 +- packages/SwingSet/README.md | 2 +- packages/agoric-cli/src/commands/auction.js | 2 ++ packages/agoric-cli/src/commands/gov.js | 6 +++++ packages/agoric-cli/src/commands/inter.js | 8 +++++++ .../agoric-cli/src/commands/test-upgrade.js | 2 ++ packages/agoric-cli/src/lib/bundles.js | 2 +- packages/agoric-cli/src/lib/wallet.js | 2 +- packages/agoric-cli/test/inter-cli.test.js | 2 ++ packages/casting/src/makeHttpClient.js | 2 +- packages/cosmic-proto/src/codegen/binary.ts | 12 +++++----- packages/cosmic-proto/src/codegen/helpers.ts | 22 ++++++++----------- packages/cosmic-proto/src/codegen/varint.ts | 4 ++-- packages/cosmic-proto/src/helpers.ts | 4 +--- packages/network/src/network.js | 2 +- packages/notifier/src/publish-kit.js | 2 +- .../smart-wallet/test/invitation1.test.js | 2 +- .../vats/src/proposals/localchain-test.js | 4 ++-- packages/vow/src/vow.js | 2 +- packages/vow/test/watch-utils.test.js | 2 +- packages/xsnap/src/build.js | 4 ++-- 28 files changed, 61 insertions(+), 47 deletions(-) diff --git a/a3p-integration/proposals/b:enable-orchestration/test-lib/wallet.js b/a3p-integration/proposals/b:enable-orchestration/test-lib/wallet.js index bb75e7b784d..5fbe9b70027 100644 --- a/a3p-integration/proposals/b:enable-orchestration/test-lib/wallet.js +++ b/a3p-integration/proposals/b:enable-orchestration/test-lib/wallet.js @@ -53,7 +53,7 @@ export const getCurrent = async (addr, { readLatestHead }) => { await readLatestHead(`published.wallet.${addr}.current`) ); if (current === undefined) { - throw new Error(`undefined current node for ${addr}`); + throw Error(`undefined current node for ${addr}`); } // Repair a type misunderstanding seen in the wild. diff --git a/a3p-integration/proposals/c:stake-bld/test-lib/wallet.js b/a3p-integration/proposals/c:stake-bld/test-lib/wallet.js index bb75e7b784d..5fbe9b70027 100644 --- a/a3p-integration/proposals/c:stake-bld/test-lib/wallet.js +++ b/a3p-integration/proposals/c:stake-bld/test-lib/wallet.js @@ -53,7 +53,7 @@ export const getCurrent = async (addr, { readLatestHead }) => { await readLatestHead(`published.wallet.${addr}.current`) ); if (current === undefined) { - throw new Error(`undefined current node for ${addr}`); + throw Error(`undefined current node for ${addr}`); } // Repair a type misunderstanding seen in the wild. diff --git a/multichain-testing/test/ica-channel-close.test.ts b/multichain-testing/test/ica-channel-close.test.ts index 3fa37d1498b..d7bf8305ea9 100644 --- a/multichain-testing/test/ica-channel-close.test.ts +++ b/multichain-testing/test/ica-channel-close.test.ts @@ -185,7 +185,7 @@ const intentionalCloseAccountScenario = test.macro({ ); const newChannel = findNewChannel(channels, { rPortID, lPortID }); t.log('New Channel after Reactivate', newChannel); - if (!newChannel) throw new Error('Channel not found'); + if (!newChannel) throw Error('Channel not found'); const newAddress = JSON.parse(newChannel.version).address; t.is(newAddress, address, `same chain address is returned - ${chainName}`); t.is( @@ -314,7 +314,7 @@ const channelCloseInitScenario = test.macro({ ).channels.find( x => x.port_id === 'transfer' && x.connection_hops[0] === rConnectionID, ); - if (!transferChannel) throw new Error('Transfer channel not found.'); + if (!transferChannel) throw Error('Transfer channel not found.'); const dstTransferChannel = { chainId: chainInfo['agoric'].chainId, diff --git a/multichain-testing/tools/address.ts b/multichain-testing/tools/address.ts index e81e3f94164..4a5def93d09 100644 --- a/multichain-testing/tools/address.ts +++ b/multichain-testing/tools/address.ts @@ -20,7 +20,7 @@ export const parseRemoteAddress = ( } => { const match = address.match(REMOTE_ADDR_RE); if (!match || !match.groups) { - throw new Error('Invalid remote address format'); + throw Error('Invalid remote address format'); } const { portID, version, channelID } = match.groups; @@ -42,7 +42,7 @@ export const parseLocalAddress = ( } => { const match = address.match(LOCAL_ADDR_RE); if (!match || !match.groups) { - throw new Error('Invalid local address format'); + throw Error('Invalid local address format'); } const { portID, version, channelID } = match.groups; diff --git a/multichain-testing/tools/deploy.ts b/multichain-testing/tools/deploy.ts index 01dc0d1270e..5cd3fba5e53 100755 --- a/multichain-testing/tools/deploy.ts +++ b/multichain-testing/tools/deploy.ts @@ -16,7 +16,7 @@ export const makeDeployBuilder = ( const { stdout } = await execa`agoric run ${builder}`; const match = stdout.match(/ (?[-\w]+)-permit.json/); if (!(match && match.groups)) { - throw new Error('no permit found'); + throw Error('no permit found'); } const plan = await readJSON(`./${match.groups.name}-plan.json`); console.log(plan); diff --git a/multichain-testing/tools/makeHttpClient.js b/multichain-testing/tools/makeHttpClient.js index e422f3f3c38..37344419946 100644 --- a/multichain-testing/tools/makeHttpClient.js +++ b/multichain-testing/tools/makeHttpClient.js @@ -7,7 +7,7 @@ const jsonType = { 'Content-Type': 'application/json' }; const filterBadStatus = res => { if (res.status >= 400) { - throw new Error(`Bad status on response: ${res.status}`); + throw Error(`Bad status on response: ${res.status}`); } return res; }; diff --git a/multichain-testing/tools/marshalTables.js b/multichain-testing/tools/marshalTables.js index 1eb50426883..827bd230cc3 100644 --- a/multichain-testing/tools/marshalTables.js +++ b/multichain-testing/tools/marshalTables.js @@ -75,7 +75,7 @@ const synthesizeRemotable = (slot, iface) => { */ export const makeClientMarshaller = valToSlot => { const noNewSlots = val => { - throw new Error(`unknown value: ${val}`); + throw Error(`unknown value: ${val}`); }; const { convertValToSlot, convertSlotToVal } = makeTranslationTable( valToSlot || noNewSlots, diff --git a/multichain-testing/tools/sleep.ts b/multichain-testing/tools/sleep.ts index 1c4d40bfdec..66251a87dca 100644 --- a/multichain-testing/tools/sleep.ts +++ b/multichain-testing/tools/sleep.ts @@ -56,7 +56,7 @@ const retryUntilCondition = async ( await sleep(retryIntervalMs, { log, setTimeout }); } - throw new Error(`${message} condition failed after ${maxRetries} retries.`); + throw Error(`${message} condition failed after ${maxRetries} retries.`); }; export const makeRetryUntilCondition = (defaultOptions: RetryOptions = {}) => { diff --git a/packages/SwingSet/README.md b/packages/SwingSet/README.md index 6c5d164e211..2409dc212e6 100644 --- a/packages/SwingSet/README.md +++ b/packages/SwingSet/README.md @@ -204,7 +204,7 @@ If wavy dot syntax is used on a Promise which rejects, the method is not invoked the return promise's `rejection` function is called instead: ```js -const badP = Promise.reject(new Error()); +const badP = Promise.reject(Error()); const p2 = badP~.foo(); p2.then(undefined, rej => console.log('rejected', rej)); // prints 'rejected' diff --git a/packages/agoric-cli/src/commands/auction.js b/packages/agoric-cli/src/commands/auction.js index 0b33b7507da..99ffd43355c 100644 --- a/packages/agoric-cli/src/commands/auction.js +++ b/packages/agoric-cli/src/commands/auction.js @@ -130,6 +130,8 @@ export const makeAuctionCommand = ( }; if (Object.keys(params).length === 0) { + // InvalidArgumentError is a class constructor, and so + // must be invoked with `new`. throw new InvalidArgumentError(`no parameters given`); } diff --git a/packages/agoric-cli/src/commands/gov.js b/packages/agoric-cli/src/commands/gov.js index 26a2f111927..8a4b46d49e5 100644 --- a/packages/agoric-cli/src/commands/gov.js +++ b/packages/agoric-cli/src/commands/gov.js @@ -73,6 +73,8 @@ export const makeGovCommand = (_logger, io = {}) => { const done = found.filter(it => it.instanceName === instanceName); if (done.length > 0) { console.warn(`invitation to ${instanceName} already accepted`, done); + // CommanderError is a class constructor, and so + // must be invoked with `new`. throw new CommanderError(1, 'EALREADY', `already accepted`); } }; @@ -330,6 +332,8 @@ export const makeGovCommand = (_logger, io = {}) => { const info = await readLatestHead( `published.committees.${opts.pathname}.latestQuestion`, ).catch(err => { + // CommanderError is a class constructor, and so + // must be invoked with `new`. throw new CommanderError(1, 'VSTORAGE_FAILURE', err.message); }); @@ -346,6 +350,8 @@ export const makeGovCommand = (_logger, io = {}) => { const votingRight = cont.find(it => it.instanceName === opts.instance); if (!votingRight) { console.debug('continuing ids', cont, 'for', current); + // CommanderError is a class constructor, and so + // must be invoked with `new`. throw new CommanderError( 1, 'NO_INVITATION', diff --git a/packages/agoric-cli/src/commands/inter.js b/packages/agoric-cli/src/commands/inter.js index f8353d41c8b..702b2ae0f48 100644 --- a/packages/agoric-cli/src/commands/inter.js +++ b/packages/agoric-cli/src/commands/inter.js @@ -218,6 +218,8 @@ export const makeInterCommand = ( try { return rawExec(file, args, ...opts); } catch (err) { + // InvalidArgumentError is a class constructor, and so + // must be invoked with `new`. throw new InvalidArgumentError( `${err.message}: is ${file} in your $PATH?`, ); @@ -239,6 +241,8 @@ export const makeInterCommand = ( const networkConfig = await getNetworkConfig(env); return makeWalletUtils({ fetch, execFileSync, delay }, networkConfig); } catch (err) { + // CommanderError is a class constructor, and so + // must be invoked with `new`. throw new CommanderError(1, 'RPC_FAIL', err.message); } }; @@ -431,6 +435,8 @@ inter auction status const parsePercent = v => { const p = Number(v); if (!(p >= -100 && p <= 100)) { + // InvalidArgumentError is a class constructor, and so + // must be invoked with `new`. throw new InvalidArgumentError('must be between -100 and 100'); } return p / 100; @@ -498,6 +504,8 @@ inter auction status const current = await getCurrent(from, { readLatestHead }); const liveIds = current.liveOffers.map(([i, _s]) => i); if (!liveIds.includes(id)) { + // InvalidArgumentError is a class constructor, and so + // must be invoked with `new`. throw new InvalidArgumentError( `${id} not in live offer ids: ${liveIds}`, ); diff --git a/packages/agoric-cli/src/commands/test-upgrade.js b/packages/agoric-cli/src/commands/test-upgrade.js index ca1aeda4a83..20223ee7bc5 100644 --- a/packages/agoric-cli/src/commands/test-upgrade.js +++ b/packages/agoric-cli/src/commands/test-upgrade.js @@ -41,6 +41,8 @@ export const makeTestCommand = ( const networkConfig = await getNetworkConfig(env); return makeWalletUtils({ fetch, execFileSync, delay }, networkConfig); } catch (err) { + // CommanderError is a class constructor, and so + // must be invoked with `new`. throw new CommanderError(1, 'RPC_FAIL', err.message); } }; diff --git a/packages/agoric-cli/src/lib/bundles.js b/packages/agoric-cli/src/lib/bundles.js index e41eb21ef02..d2feca36e72 100644 --- a/packages/agoric-cli/src/lib/bundles.js +++ b/packages/agoric-cli/src/lib/bundles.js @@ -28,7 +28,7 @@ export const PACKAGE_NAME_RE = /^(?:@[^/]+\/)?[^/]+/; /** @param {Bundle} bundleObj*/ export const extractBundleInfo = async bundleObj => { if (bundleObj.moduleFormat !== 'endoZipBase64') { - throw new Error('only endoZipBase64 is supported'); + throw Error('only endoZipBase64 is supported'); } const contents = Buffer.from(bundleObj.endoZipBase64, 'base64'); diff --git a/packages/agoric-cli/src/lib/wallet.js b/packages/agoric-cli/src/lib/wallet.js index c120db764e9..c8d3dc71e35 100644 --- a/packages/agoric-cli/src/lib/wallet.js +++ b/packages/agoric-cli/src/lib/wallet.js @@ -33,7 +33,7 @@ export const getCurrent = async (addr, { readLatestHead }) => { await readLatestHead(`published.wallet.${addr}.current`) ); if (current === undefined) { - throw new Error(`undefined current node for ${addr}`); + throw Error(`undefined current node for ${addr}`); } // Repair a type misunderstanding seen in the wild. diff --git a/packages/agoric-cli/test/inter-cli.test.js b/packages/agoric-cli/test/inter-cli.test.js index cddbe85fb07..5d7bb758626 100644 --- a/packages/agoric-cli/test/inter-cli.test.js +++ b/packages/agoric-cli/test/inter-cli.test.js @@ -366,6 +366,8 @@ const usageTest = (words, blurb = 'Command usage:') => { program.addCommand(cmd); for (const c of subCommands(program)) { c.exitOverride(() => { + // CommanderError is a class constructor, and so + // must be invoked with `new`. throw new CommanderError(1, 'usage', ''); }); } diff --git a/packages/casting/src/makeHttpClient.js b/packages/casting/src/makeHttpClient.js index 834c50c40e2..e6fe7c1ec7e 100644 --- a/packages/casting/src/makeHttpClient.js +++ b/packages/casting/src/makeHttpClient.js @@ -4,7 +4,7 @@ const { freeze } = Object; const filterBadStatus = res => { if (res.status >= 400) { - throw new Error(`Bad status on response: ${res.status}`); + throw Error(`Bad status on response: ${res.status}`); } return res; }; diff --git a/packages/cosmic-proto/src/codegen/binary.ts b/packages/cosmic-proto/src/codegen/binary.ts index 524eb36d273..33c34900cf4 100644 --- a/packages/cosmic-proto/src/codegen/binary.ts +++ b/packages/cosmic-proto/src/codegen/binary.ts @@ -100,7 +100,7 @@ export class BinaryReader implements IBinaryReader { len: number; assertBounds(): void { - if (this.pos > this.len) throw new RangeError('premature EOF'); + if (this.pos > this.len) throw RangeError('premature EOF'); } constructor(buf?: ArrayLike) { @@ -115,7 +115,7 @@ export class BinaryReader implements IBinaryReader { fieldNo = tag >>> 3, wireType = tag & 7; if (fieldNo <= 0 || wireType < 0 || wireType > 5) - throw new Error( + throw Error( 'illegal tag: field no ' + fieldNo + ' wire type ' + wireType, ); return [fieldNo, wireType, tag]; @@ -214,11 +214,11 @@ export class BinaryReader implements IBinaryReader { } float(): number { - throw new Error('float not supported'); + throw Error('float not supported'); } double(): number { - throw new Error('double not supported'); + throw Error('double not supported'); } bool(): boolean { @@ -466,11 +466,11 @@ export class BinaryWriter implements IBinaryWriter { sfixed32 = BinaryWriter.prototype.fixed32; float(value: number): BinaryWriter { - throw new Error('float not supported' + value); + throw Error('float not supported' + value); } double(value: number): BinaryWriter { - throw new Error('double not supported' + value); + throw Error('double not supported' + value); } bytes(value: Uint8Array): BinaryWriter { diff --git a/packages/cosmic-proto/src/codegen/helpers.ts b/packages/cosmic-proto/src/codegen/helpers.ts index ebdafe89353..a5547f7a637 100644 --- a/packages/cosmic-proto/src/codegen/helpers.ts +++ b/packages/cosmic-proto/src/codegen/helpers.ts @@ -35,7 +35,7 @@ export function omitDefault( return input === BigInt(0) ? undefined : input; } - throw new Error(`Got unsupported type ${typeof input}`); + throw Error(`Got unsupported type ${typeof input}`); } interface Duration { @@ -241,9 +241,7 @@ export class Decimal { const badCharacter = input.match(/[^0-9.]/); if (badCharacter) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - throw new Error( - `Invalid character at position ${badCharacter.index! + 1}`, - ); + throw Error(`Invalid character at position ${badCharacter.index! + 1}`); } let whole: string; @@ -261,21 +259,21 @@ export class Decimal { switch (parts.length) { case 0: case 1: - throw new Error( + throw Error( 'Fewer than two elements in split result. This must not happen here.', ); case 2: - if (!parts[1]) throw new Error('Fractional part missing'); + if (!parts[1]) throw Error('Fractional part missing'); whole = parts[0]; fractional = parts[1].replace(/0+$/, ''); break; default: - throw new Error('More than one separator found'); + throw Error('More than one separator found'); } } if (fractional.length > fractionalDigits) { - throw new Error('Got more fractional digits than supported'); + throw Error('Got more fractional digits than supported'); } const quantity = `${whole}${fractional.padEnd(fractionalDigits, '0')}`; @@ -293,13 +291,11 @@ export class Decimal { private static verifyFractionalDigits(fractionalDigits: number): void { if (!Number.isInteger(fractionalDigits)) - throw new Error('Fractional digits is not an integer'); + throw Error('Fractional digits is not an integer'); if (fractionalDigits < 0) - throw new Error('Fractional digits must not be negative'); + throw Error('Fractional digits must not be negative'); if (fractionalDigits > maxFractionalDigits) { - throw new Error( - `Fractional digits must not exceed ${maxFractionalDigits}`, - ); + throw Error(`Fractional digits must not exceed ${maxFractionalDigits}`); } } } diff --git a/packages/cosmic-proto/src/codegen/varint.ts b/packages/cosmic-proto/src/codegen/varint.ts index e379c6dcef1..4e82d8337ef 100644 --- a/packages/cosmic-proto/src/codegen/varint.ts +++ b/packages/cosmic-proto/src/codegen/varint.ts @@ -86,7 +86,7 @@ export function varint64read(this: ReaderLike): [number, number] { } } - throw new Error('invalid varint'); + throw Error('invalid varint'); } /** @@ -353,7 +353,7 @@ export function varint32read(this: ReaderLike): number { for (let readBytes = 5; (b & 0x80) !== 0 && readBytes < 10; readBytes++) b = this.buf[this.pos++]; - if ((b & 0x80) != 0) throw new Error('invalid varint'); + if ((b & 0x80) != 0) throw Error('invalid varint'); this.assertBounds(); diff --git a/packages/cosmic-proto/src/helpers.ts b/packages/cosmic-proto/src/helpers.ts index e1023dbd16d..5e2cb864cd6 100644 --- a/packages/cosmic-proto/src/helpers.ts +++ b/packages/cosmic-proto/src/helpers.ts @@ -97,9 +97,7 @@ const QUERY_REQ_TYPEURL_RE = export const typeUrlToGrpcPath = (typeUrl: Any['typeUrl']) => { const match = typeUrl.match(QUERY_REQ_TYPEURL_RE); if (!(match && match.groups)) { - throw new TypeError( - `Invalid typeUrl: ${typeUrl}. Must be a Query Request.`, - ); + throw TypeError(`Invalid typeUrl: ${typeUrl}. Must be a Query Request.`); } const { serviceName, methodName } = match.groups; return `/${serviceName}.Query/${methodName}`; diff --git a/packages/network/src/network.js b/packages/network/src/network.js index 029675c5324..4f31ef83b95 100644 --- a/packages/network/src/network.js +++ b/packages/network/src/network.js @@ -69,7 +69,7 @@ function throwIfInvalidPortName(specifiedName) { // Valid symbols: ., ,, _, +, -, #, [, ], <, > const portNameRegex = new RegExp('^[a-zA-Z0-9.,_+\\-#<>\\[\\]]{2,128}$'); if (!portNameRegex.test(specifiedName)) { - throw new Error(`Invalid IBC port name: ${specifiedName}`); + throw Error(`Invalid IBC port name: ${specifiedName}`); } } diff --git a/packages/notifier/src/publish-kit.js b/packages/notifier/src/publish-kit.js index 86a3d1f295f..e2403db1455 100644 --- a/packages/notifier/src/publish-kit.js +++ b/packages/notifier/src/publish-kit.js @@ -18,7 +18,7 @@ const makeQuietRejection = reason => { return rejection; }; const tooFarRejection = makeQuietRejection( - harden(new Error('Cannot read past end of iteration.')), + harden(Error('Cannot read past end of iteration.')), ); export const PublisherI = M.interface('Publisher', { diff --git a/packages/smart-wallet/test/invitation1.test.js b/packages/smart-wallet/test/invitation1.test.js index 5e9d2287779..b530f1727ad 100644 --- a/packages/smart-wallet/test/invitation1.test.js +++ b/packages/smart-wallet/test/invitation1.test.js @@ -193,7 +193,7 @@ test.serial('handle failure to create invitation', async t => { return slowWithdrawPurse; }, getAssetSubscription: () => { - throw new Error('TODO'); + throw Error('TODO'); }, }); diff --git a/packages/vats/src/proposals/localchain-test.js b/packages/vats/src/proposals/localchain-test.js index fcaf7751a56..201de2e38d2 100644 --- a/packages/vats/src/proposals/localchain-test.js +++ b/packages/vats/src/proposals/localchain-test.js @@ -20,7 +20,7 @@ export const testLocalChain = async ( let node = await chainStorage; if (!node) { console.error('testLocalChain no chainStorage'); - throw new Error('no chainStorage'); + throw Error('no chainStorage'); } let result; @@ -58,7 +58,7 @@ export const testLocalChain = async ( const emptyQuery = await E(localchain).queryMany([]); console.info('emptyQuery', emptyQuery); if (emptyQuery.length !== 0) { - throw new Error('emptyQuery results should be empty'); + throw Error('emptyQuery results should be empty'); } result = { success: true }; diff --git a/packages/vow/src/vow.js b/packages/vow/src/vow.js index 2b4013eb0cb..e2539baf06f 100644 --- a/packages/vow/src/vow.js +++ b/packages/vow/src/vow.js @@ -120,7 +120,7 @@ export const prepareVowKit = zone => { case 'pending': return provideCurrentKit(this.facets.resolver).promise; default: - throw new TypeError(`unexpected stepStatus ${stepStatus}`); + throw TypeError(`unexpected stepStatus ${stepStatus}`); } }, }, diff --git a/packages/vow/test/watch-utils.test.js b/packages/vow/test/watch-utils.test.js index 0a841e19327..13e5be07d5d 100644 --- a/packages/vow/test/watch-utils.test.js +++ b/packages/vow/test/watch-utils.test.js @@ -215,7 +215,7 @@ test('asPromise handles vow rejection', async t => { const zone = makeHeapZone(); const { watch, asPromise } = prepareBasicVowTools(zone); - const testPromiseP = Promise.reject(new Error('test error')); + const testPromiseP = Promise.reject(Error('test error')); const vow = watch(testPromiseP); await t.throwsAsync(asPromise(vow), { message: 'test error' }); diff --git a/packages/xsnap/src/build.js b/packages/xsnap/src/build.js index 23032349121..a2c7e7074fe 100644 --- a/packages/xsnap/src/build.js +++ b/packages/xsnap/src/build.js @@ -341,7 +341,7 @@ async function main(args, { env, stdout, spawn, fs, os }) { if (isWorkingCopy || showEnv) { if (showEnv && !isWorkingCopy) { - throw new Error('XSnap requires a working copy and git to --show-env'); + throw Error('XSnap requires a working copy and git to --show-env'); } await updateSubmodules(showEnv, { env, stdout, spawn, fs }); hasSource = true; @@ -362,7 +362,7 @@ async function main(args, { env, stdout, spawn, fs, os }) { } await makeXsnap({ spawn, fs, os }, { forceBuild }); } else if (!hasBin) { - throw new Error( + throw Error( 'XSnap has neither sources nor a pre-built binary. Docker? .dockerignore? npm files?', ); }