fix: some APIs modified for ASAR support cannot be util.promisify'ed (#13845)

This commit is contained in:
Milan Burda 2018-08-01 05:06:48 +02:00 committed by Samuel Attard
parent eb79ad4dab
commit c52b3d921e
2 changed files with 123 additions and 5 deletions

View file

@ -3,6 +3,7 @@
const {Buffer} = require('buffer') const {Buffer} = require('buffer')
const childProcess = require('child_process') const childProcess = require('child_process')
const path = require('path') const path = require('path')
const util = require('util')
const hasProp = {}.hasOwnProperty const hasProp = {}.hasOwnProperty
@ -217,6 +218,28 @@
arguments[arg] = newPath arguments[arg] = newPath
return old.apply(this, arguments) return old.apply(this, arguments)
} }
if (old[util.promisify.custom]) {
module[name][util.promisify.custom] = function () {
const p = arguments[arg]
const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) {
return old[util.promisify.custom].apply(this, arguments)
}
const archive = getOrCreateArchive(asarPath)
if (!archive) {
return new Promise(() => invalidArchiveError(asarPath))
}
const newPath = archive.copyFileOut(filePath)
if (!newPath) {
return new Promise(() => notFoundError(asarPath, filePath))
}
arguments[arg] = newPath
return old[util.promisify.custom].apply(this, arguments)
}
}
} }
// Override fs APIs. // Override fs APIs.
@ -373,6 +396,18 @@
}) })
} }
fs.exists[util.promisify.custom] = function (p) {
const [isAsar, asarPath, filePath] = splitPath(p)
if (!isAsar) {
return exists[util.promisify.custom](p)
}
const archive = getOrCreateArchive(asarPath)
if (!archive) {
return new Promise(() => invalidArchiveError(asarPath))
}
return Promise.resolve(archive.stat(filePath) !== false)
}
const {existsSync} = fs const {existsSync} = fs
fs.existsSync = function (p) { fs.existsSync = function (p) {
const [isAsar, asarPath, filePath] = splitPath(p) const [isAsar, asarPath, filePath] = splitPath(p)
@ -680,18 +715,22 @@
// called by `childProcess.{exec,execSync}`, causing // called by `childProcess.{exec,execSync}`, causing
// Electron to consider the full command as a single path // Electron to consider the full command as a single path
// to an archive. // to an archive.
['exec', 'execSync'].forEach(function (functionName) { const {exec, execSync} = childProcess
const old = childProcess[functionName] childProcess.exec = invokeWithNoAsar(exec)
childProcess[functionName] = function () { childProcess.exec[util.promisify.custom] = invokeWithNoAsar(exec[util.promisify.custom])
childProcess.execSync = invokeWithNoAsar(execSync)
function invokeWithNoAsar (func) {
return function () {
const processNoAsarOriginalValue = process.noAsar const processNoAsarOriginalValue = process.noAsar
process.noAsar = true process.noAsar = true
try { try {
return old.apply(this, arguments) return func.apply(this, arguments)
} finally { } finally {
process.noAsar = processNoAsarOriginalValue process.noAsar = processNoAsarOriginalValue
} }
} }
}) }
overrideAPI(fs, 'open') overrideAPI(fs, 'open')
overrideAPI(childProcess, 'execFile') overrideAPI(childProcess, 'execFile')

View file

@ -2,6 +2,7 @@ const assert = require('assert')
const ChildProcess = require('child_process') const ChildProcess = require('child_process')
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const util = require('util')
const {closeWindow} = require('./window-helpers') const {closeWindow} = require('./window-helpers')
const nativeImage = require('electron').nativeImage const nativeImage = require('electron').nativeImage
@ -549,6 +550,60 @@ describe('asar package', function () {
}) })
}) })
describe('fs.exists', function () {
it('handles an existing file', function (done) {
var p = path.join(fixtures, 'asar', 'a.asar', 'file1')
// eslint-disable-next-line
fs.exists(p, function (exists) {
assert.equal(exists, true)
done()
})
})
it('handles a non-existent file', function (done) {
var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
// eslint-disable-next-line
fs.exists(p, function (exists) {
assert.equal(exists, false)
done()
})
})
it('promisified version handles an existing file', (done) => {
var p = path.join(fixtures, 'asar', 'a.asar', 'file1')
// eslint-disable-next-line
util.promisify(fs.exists)(p).then(exists => {
assert.equal(exists, true)
done()
})
})
it('promisified version handles a non-existent file', function (done) {
var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
// eslint-disable-next-line
util.promisify(fs.exists)(p).then(exists => {
assert.equal(exists, false)
done()
})
})
})
describe('fs.existsSync', function () {
it('handles an existing file', function () {
var p = path.join(fixtures, 'asar', 'a.asar', 'file1')
assert.doesNotThrow(function () {
assert.equal(fs.existsSync(p), true)
})
})
it('handles a non-existent file', function () {
var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
assert.doesNotThrow(function () {
assert.equal(fs.existsSync(p), false)
})
})
})
describe('fs.access', function () { describe('fs.access', function () {
it('accesses a normal file', function (done) { it('accesses a normal file', function (done) {
var p = path.join(fixtures, 'asar', 'a.asar', 'file1') var p = path.join(fixtures, 'asar', 'a.asar', 'file1')
@ -644,6 +699,12 @@ describe('asar package', function () {
done() done()
}) })
}) })
it('can be promisified', () => {
return util.promisify(ChildProcess.exec)('echo ' + echo + ' foo bar').then(({ stdout }) => {
assert.equal(stdout.toString().replace(/\r/g, ''), echo + ' foo bar\n')
})
})
}) })
describe('child_process.execSync', function () { describe('child_process.execSync', function () {
@ -680,6 +741,12 @@ describe('asar package', function () {
var output = execFileSync(echo, ['test']) var output = execFileSync(echo, ['test'])
assert.equal(String(output), 'test\n') assert.equal(String(output), 'test\n')
}) })
it('can be promisified', () => {
return util.promisify(ChildProcess.execFile)(echo, ['test']).then(({ stdout }) => {
assert.equal(stdout, 'test\n')
})
})
}) })
describe('internalModuleReadJSON', function () { describe('internalModuleReadJSON', function () {
@ -700,6 +767,18 @@ describe('asar package', function () {
}) })
}) })
describe('util.promisify', function () {
it('can promisify all fs functions', function () {
const originalFs = require('original-fs')
for (const key in originalFs) {
if (originalFs[key][util.promisify.custom] && !fs[key][util.promisify.custom]) {
assert(false, `fs.${key}[util.promisify.custom] missing`)
}
}
})
})
describe('process.noAsar', function () { describe('process.noAsar', function () {
var errorName = process.platform === 'win32' ? 'ENOENT' : 'ENOTDIR' var errorName = process.platform === 'win32' ? 'ENOENT' : 'ENOTDIR'