diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee index 2373385f75..5f690e9a8f 100644 --- a/atom/common/lib/asar.coffee +++ b/atom/common/lib/asar.coffee @@ -63,6 +63,15 @@ notFoundError = (asarPath, filePath, callback) -> throw error process.nextTick -> callback error +# Create a ENOTDIR error. +notDirError = (callback) -> + error = new Error('ENOTDIR, not a directory') + error.code = 'ENOTDIR' + error.errno = -20 + unless typeof callback is 'function' + throw error + process.nextTick -> callback error + # Create invalid archive error. invalidArchiveError = (asarPath, callback) -> error = new Error("Invalid package #{asarPath}") @@ -351,6 +360,24 @@ exports.wrapFsWithAsar = (fs) -> if stats.isDirectory then return 1 else return 0 + # Calling mkdir for directory inside asar archive should throw ENOTDIR + # error, but on Windows it throws ENOENT. + # This is to work around the recursive looping bug of mkdirp since it is + # widely used. + if process.platform is 'win32' + mkdir = fs.mkdir + fs.mkdir = (p, mode, callback) -> + callback = mode if typeof mode is 'function' + [isAsar, asarPath, filePath] = splitPath p + return notDirError callback if isAsar and filePath.length + mkdir p, mode, callback + + mkdirSync = fs.mkdirSync + fs.mkdirSync = (p, mode) -> + [isAsar, asarPath, filePath] = splitPath p + notDirError() if isAsar and filePath.length + mkdirSync p, mode + overrideAPI fs, 'open' overrideAPI child_process, 'execFile' overrideAPISync process, 'dlopen', 1 diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index 479443292b..7642283cea 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -374,6 +374,18 @@ describe 'asar package', -> assert.equal err.code, 'ENOENT' done() + describe 'fs.mkdir', -> + it 'throws error when calling inside asar archive', (done) -> + p = path.join fixtures, 'asar', 'a.asar', 'not-exist' + fs.mkdir p, (err) -> + assert.equal err.code, 'ENOTDIR' + done() + + describe 'fs.mkdirSync', -> + it 'throws error when calling inside asar archive', -> + p = path.join fixtures, 'asar', 'a.asar', 'not-exist' + assert.throws (-> fs.mkdirSync p), new RegExp('ENOTDIR') + describe 'child_process.fork', -> child_process = require 'child_process' @@ -547,6 +559,13 @@ describe 'asar package', -> it 'does not touch global fs object', -> assert.notEqual fs.readdir, gfs.readdir + describe 'mkdirp module', -> + mkdirp = require 'mkdirp' + + it 'throws error when calling inside asar archive', -> + p = path.join fixtures, 'asar', 'a.asar', 'not-exist' + assert.throws (-> mkdirp.sync p), new RegExp('ENOTDIR') + describe 'native-image', -> it 'reads image from asar archive', -> p = path.join fixtures, 'asar', 'logo.asar', 'logo.png' diff --git a/spec/package.json b/spec/package.json index 79e7d954eb..6d49f0da8b 100644 --- a/spec/package.json +++ b/spec/package.json @@ -7,6 +7,7 @@ "basic-auth": "^1.0.0", "graceful-fs": "3.0.5", "mocha": "2.1.0", + "mkdirp": "0.5.1", "multiparty": "4.1.2", "q": "0.9.7", "temp": "0.8.1", diff --git a/spec/webview-spec.coffee b/spec/webview-spec.coffee index 1dcf739ec0..4754ea4348 100644 --- a/spec/webview-spec.coffee +++ b/spec/webview-spec.coffee @@ -1,6 +1,7 @@ assert = require 'assert' path = require 'path' http = require 'http' +url = require 'url' describe '<webview> tag', -> @timeout 10000 @@ -261,12 +262,12 @@ describe '<webview> tag', -> it 'emits when favicon urls are received', (done) -> webview.addEventListener 'page-favicon-updated', (e) -> assert.equal e.favicons.length, 2 - url = + pageUrl = if process.platform is 'win32' 'file:///C:/favicon.png' else 'file:///favicon.png' - assert.equal e.favicons[0], url + assert.equal e.favicons[0], pageUrl done() webview.src = "file://#{fixtures}/pages/a.html" document.body.appendChild webview @@ -281,7 +282,9 @@ describe '<webview> tag', -> document.body.appendChild webview describe 'did-navigate event', -> - pageUrl = "file://#{fixtures}/pages/webview-will-navigate.html" + p = path.join fixtures, 'pages', 'webview-will-navigate.html' + p = p.replace /\\/g, '/' + pageUrl = url.format protocol: 'file', slashes: true, pathname: p it 'emits when a url that leads to outside of the page is clicked', (done) -> webview.addEventListener 'did-navigate', (e) -> @@ -293,7 +296,10 @@ describe '<webview> tag', -> describe 'did-navigate-in-page event', -> it 'emits when an anchor link is clicked', (done) -> - pageUrl = "file://#{fixtures}/pages/webview-did-navigate-in-page.html" + p = path.join fixtures, 'pages', 'webview-did-navigate-in-page.html' + p = p.replace /\\/g, '/' + pageUrl = url.format protocol: 'file', slashes: true, pathname: p + webview.addEventListener 'did-navigate-in-page', (e) -> assert.equal e.url, "#{pageUrl}#test_content" done() @@ -310,7 +316,10 @@ describe '<webview> tag', -> document.body.appendChild webview it 'emits when window.location.hash is changed', (done) -> - pageUrl = "file://#{fixtures}/pages/webview-did-navigate-in-page-with-hash.html" + p = path.join fixtures, 'pages', 'webview-did-navigate-in-page-with-hash.html' + p = p.replace /\\/g, '/' + pageUrl = url.format protocol: 'file', slashes: true, pathname: p + webview.addEventListener 'did-navigate-in-page', (e) -> assert.equal e.url, "#{pageUrl}#test" done()