diff --git a/lib/fs.js b/lib/fs.js index fae2857e3fc759..27e1a2e79cd135 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -16,11 +16,9 @@ const EventEmitter = require('events'); const FSReqWrap = binding.FSReqWrap; const FSEvent = process.binding('fs_event_wrap').FSEvent; const internalFS = require('internal/fs'); -const internalURL = require('internal/url'); const assertEncoding = internalFS.assertEncoding; const stringToFlags = internalFS.stringToFlags; const SyncWriteStream = internalFS.SyncWriteStream; -const getPathFromURL = internalURL.getPathFromURL; Object.defineProperty(exports, 'constants', { configurable: false, @@ -204,16 +202,6 @@ fs.Stats.prototype.isSocket = function() { }); }); -function handleError(val, callback) { - if (val instanceof Error) { - if (typeof callback === 'function') { - process.nextTick(callback, val); - return true; - } else throw val; - } - return false; -} - fs.access = function(path, mode, callback) { if (typeof mode === 'function') { callback = mode; @@ -222,9 +210,6 @@ fs.access = function(path, mode, callback) { throw new TypeError('"callback" argument must be a function'); } - if (handleError((path = getPathFromURL(path)), callback)) - return; - if (!nullCheck(path, callback)) return; @@ -235,7 +220,6 @@ fs.access = function(path, mode, callback) { }; fs.accessSync = function(path, mode) { - handleError((path = getPathFromURL(path))); nullCheck(path); if (mode === undefined) @@ -247,8 +231,6 @@ fs.accessSync = function(path, mode) { }; fs.exists = function(path, callback) { - if (handleError((path = getPathFromURL(path)), cb)) - return; if (!nullCheck(path, cb)) return; var req = new FSReqWrap(); req.oncomplete = cb; @@ -260,7 +242,6 @@ fs.exists = function(path, callback) { fs.existsSync = function(path) { try { - handleError((path = getPathFromURL(path))); nullCheck(path); binding.stat(pathModule._makeLong(path)); return true; @@ -273,8 +254,6 @@ fs.readFile = function(path, options, callback) { callback = maybeCallback(arguments[arguments.length - 1]); options = getOptions(options, { flag: 'r' }); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; @@ -558,8 +537,6 @@ fs.open = function(path, flags, mode, callback_) { var callback = makeCallback(arguments[arguments.length - 1]); mode = modeNum(mode, 0o666); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); @@ -573,7 +550,6 @@ fs.open = function(path, flags, mode, callback_) { fs.openSync = function(path, flags, mode) { mode = modeNum(mode, 0o666); - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode); }; @@ -669,12 +645,6 @@ fs.writeSync = function(fd, buffer, offset, length, position) { fs.rename = function(oldPath, newPath, callback) { callback = makeCallback(callback); - if (handleError((oldPath = getPathFromURL(oldPath)), callback)) - return; - - if (handleError((newPath = getPathFromURL(newPath)), callback)) - return; - if (!nullCheck(oldPath, callback)) return; if (!nullCheck(newPath, callback)) return; var req = new FSReqWrap(); @@ -685,8 +655,6 @@ fs.rename = function(oldPath, newPath, callback) { }; fs.renameSync = function(oldPath, newPath) { - handleError((oldPath = getPathFromURL(oldPath))); - handleError((newPath = getPathFromURL(newPath))); nullCheck(oldPath); nullCheck(newPath); return binding.rename(pathModule._makeLong(oldPath), @@ -758,8 +726,6 @@ fs.ftruncateSync = function(fd, len) { fs.rmdir = function(path, callback) { callback = maybeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -767,7 +733,6 @@ fs.rmdir = function(path, callback) { }; fs.rmdirSync = function(path) { - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.rmdir(pathModule._makeLong(path)); }; @@ -795,8 +760,6 @@ fs.fsyncSync = function(fd) { fs.mkdir = function(path, mode, callback) { if (typeof mode === 'function') callback = mode; callback = makeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -806,7 +769,6 @@ fs.mkdir = function(path, mode, callback) { }; fs.mkdirSync = function(path, mode) { - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.mkdir(pathModule._makeLong(path), modeNum(mode, 0o777)); @@ -815,8 +777,6 @@ fs.mkdirSync = function(path, mode) { fs.readdir = function(path, options, callback) { callback = makeCallback(typeof options === 'function' ? options : callback); options = getOptions(options, {}); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -825,7 +785,6 @@ fs.readdir = function(path, options, callback) { fs.readdirSync = function(path, options) { options = getOptions(options, {}); - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.readdir(pathModule._makeLong(path), options.encoding); }; @@ -838,8 +797,6 @@ fs.fstat = function(fd, callback) { fs.lstat = function(path, callback) { callback = makeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -848,8 +805,6 @@ fs.lstat = function(path, callback) { fs.stat = function(path, callback) { callback = makeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -861,13 +816,11 @@ fs.fstatSync = function(fd) { }; fs.lstatSync = function(path) { - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.lstat(pathModule._makeLong(path)); }; fs.statSync = function(path) { - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.stat(pathModule._makeLong(path)); }; @@ -875,8 +828,6 @@ fs.statSync = function(path) { fs.readlink = function(path, options, callback) { callback = makeCallback(typeof options === 'function' ? options : callback); options = getOptions(options, {}); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -885,7 +836,6 @@ fs.readlink = function(path, options, callback) { fs.readlinkSync = function(path, options) { options = getOptions(options, {}); - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.readlink(pathModule._makeLong(path), options.encoding); }; @@ -909,12 +859,6 @@ fs.symlink = function(target, path, type_, callback_) { var type = (typeof type_ === 'string' ? type_ : null); var callback = makeCallback(arguments[arguments.length - 1]); - if (handleError((target = getPathFromURL(target)), callback)) - return; - - if (handleError((path = getPathFromURL(path)), callback)) - return; - if (!nullCheck(target, callback)) return; if (!nullCheck(path, callback)) return; @@ -929,8 +873,7 @@ fs.symlink = function(target, path, type_, callback_) { fs.symlinkSync = function(target, path, type) { type = (typeof type === 'string' ? type : null); - handleError((target = getPathFromURL(target))); - handleError((path = getPathFromURL(path))); + nullCheck(target); nullCheck(path); @@ -941,13 +884,6 @@ fs.symlinkSync = function(target, path, type) { fs.link = function(existingPath, newPath, callback) { callback = makeCallback(callback); - - if (handleError((existingPath = getPathFromURL(existingPath)), callback)) - return; - - if (handleError((newPath = getPathFromURL(newPath)), callback)) - return; - if (!nullCheck(existingPath, callback)) return; if (!nullCheck(newPath, callback)) return; @@ -960,8 +896,6 @@ fs.link = function(existingPath, newPath, callback) { }; fs.linkSync = function(existingPath, newPath) { - handleError((existingPath = getPathFromURL(existingPath))); - handleError((newPath = getPathFromURL(newPath))); nullCheck(existingPath); nullCheck(newPath); return binding.link(pathModule._makeLong(existingPath), @@ -970,8 +904,6 @@ fs.linkSync = function(existingPath, newPath) { fs.unlink = function(path, callback) { callback = makeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -979,7 +911,6 @@ fs.unlink = function(path, callback) { }; fs.unlinkSync = function(path) { - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.unlink(pathModule._makeLong(path)); }; @@ -1036,8 +967,6 @@ if (constants.hasOwnProperty('O_SYMLINK')) { fs.chmod = function(path, mode, callback) { callback = makeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -1047,7 +976,6 @@ fs.chmod = function(path, mode, callback) { }; fs.chmodSync = function(path, mode) { - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.chmod(pathModule._makeLong(path), modeNum(mode)); }; @@ -1082,8 +1010,6 @@ fs.fchownSync = function(fd, uid, gid) { fs.chown = function(path, uid, gid, callback) { callback = makeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -1091,7 +1017,6 @@ fs.chown = function(path, uid, gid, callback) { }; fs.chownSync = function(path, uid, gid) { - handleError((path = getPathFromURL(path))); nullCheck(path); return binding.chown(pathModule._makeLong(path), uid, gid); }; @@ -1119,8 +1044,6 @@ fs._toUnixTimestamp = toUnixTimestamp; fs.utimes = function(path, atime, mtime, callback) { callback = makeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; @@ -1131,7 +1054,6 @@ fs.utimes = function(path, atime, mtime, callback) { }; fs.utimesSync = function(path, atime, mtime) { - handleError((path = getPathFromURL(path))); nullCheck(path); atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); @@ -1292,7 +1214,6 @@ FSWatcher.prototype.start = function(filename, persistent, recursive, encoding) { - handleError((filename = getPathFromURL(filename))); nullCheck(filename); var err = this._handle.start(pathModule._makeLong(filename), persistent, @@ -1311,7 +1232,6 @@ FSWatcher.prototype.close = function() { }; fs.watch = function(filename, options, listener) { - handleError((filename = getPathFromURL(filename))); nullCheck(filename); if (typeof options === 'function') { @@ -1372,7 +1292,6 @@ util.inherits(StatWatcher, EventEmitter); StatWatcher.prototype.start = function(filename, persistent, interval) { - handleError((filename = getPathFromURL(filename))); nullCheck(filename); this._handle.start(pathModule._makeLong(filename), persistent, interval); }; @@ -1386,7 +1305,6 @@ StatWatcher.prototype.stop = function() { const statWatchers = new Map(); fs.watchFile = function(filename, options, listener) { - handleError((filename = getPathFromURL(filename))); nullCheck(filename); filename = pathModule.resolve(filename); var stat; @@ -1423,7 +1341,6 @@ fs.watchFile = function(filename, options, listener) { }; fs.unwatchFile = function(filename, listener) { - handleError((filename = getPathFromURL(filename))); nullCheck(filename); filename = pathModule.resolve(filename); var stat = statWatchers.get(filename); @@ -1467,7 +1384,6 @@ function encodeRealpathResult(result, options) { fs.realpathSync = function realpathSync(p, options) { options = getOptions(options, {}); - handleError((p = getPathFromURL(p))); nullCheck(p); p = p.toString('utf8'); @@ -1571,8 +1487,6 @@ fs.realpathSync = function realpathSync(p, options) { fs.realpath = function realpath(p, options, callback) { callback = maybeCallback(typeof options === 'function' ? options : callback); options = getOptions(options, {}); - if (handleError((p = getPathFromURL(p)), callback)) - return; if (!nullCheck(p, callback)) return; @@ -1731,7 +1645,7 @@ function ReadStream(path, options) { Readable.call(this, options); - handleError((this.path = getPathFromURL(path))); + this.path = path; this.fd = options.fd === undefined ? null : options.fd; this.flags = options.flags === undefined ? 'r' : options.flags; this.mode = options.mode === undefined ? 0o666 : options.mode; @@ -1894,7 +1808,7 @@ function WriteStream(path, options) { Writable.call(this, options); - handleError((this.path = getPathFromURL(path))); + this.path = path; this.fd = options.fd === undefined ? null : options.fd; this.flags = options.flags === undefined ? 'w' : options.flags; this.mode = options.mode === undefined ? 0o666 : options.mode; diff --git a/lib/internal/url.js b/lib/internal/url.js index 49444880d1f491..3fe6e106d5b1fa 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -7,9 +7,6 @@ const cannotBeBase = Symbol('cannot-be-base'); const special = Symbol('special'); const searchParams = Symbol('query'); const querystring = require('querystring'); -const os = require('os'); - -const isWindows = process.platform === 'win32'; const kScheme = Symbol('scheme'); const kHost = Symbol('host'); @@ -1115,66 +1112,6 @@ function urlToOptions(url) { return options; } -function getPathFromURLWin32(url) { - var hostname = url.hostname; - var pathname = url.pathname; - for (var n = 0; n < pathname.length; n++) { - if (pathname[n] === '%') { - var third = pathname.codePointAt(n + 2) | 0x20; - if ((pathname[n + 1] === '2' && third === 102) || // 2f 2F / - (pathname[n + 1] === '5' && third === 99)) { // 5c 5C \ - return new Error('Path must not include encoded \\ or / characters'); - } - } - } - pathname = decodeURIComponent(pathname); - if (hostname !== '') { - // If hostname is set, then we have a UNC path - // Pass the hostname through domainToUnicode just in case - // it is an IDN using punycode encoding. We do not need to worry - // about percent encoding because the URL parser will have - // already taken care of that for us. Note that this only - // causes IDNs with an appropriate `xn--` prefix to be decoded. - return `//${domainToUnicode(hostname)}${pathname}`; - } else { - // Otherwise, it's a local path that requires a drive letter - var letter = pathname.codePointAt(1) | 0x20; - var sep = pathname[2]; - if (letter < 97 || letter > 122 || // a..z A..Z - (sep !== ':')) { - return new Error('File URLs must specify absolute paths'); - } - return pathname.slice(1); - } -} - -function getPathFromURLPosix(url) { - if (url.hostname !== '') { - return new Error( - `File URLs on ${os.platform()} must use hostname 'localhost'` + - ' or not specify any hostname'); - } - var pathname = url.pathname; - for (var n = 0; n < pathname.length; n++) { - if (pathname[n] === '%') { - var third = pathname.codePointAt(n + 2) | 0x20; - if (pathname[n + 1] === '2' && third === 102) { - return new Error('Path must not include encoded / characters'); - } - } - } - return decodeURIComponent(pathname); -} - -function getPathFromURL(path) { - if (!(path instanceof URL)) - return path; - if (path.protocol !== 'file:') - return new Error('Only `file:` URLs are supported'); - return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path); -} - -exports.getPathFromURL = getPathFromURL; exports.URL = URL; exports.URLSearchParams = URLSearchParams; exports.domainToASCII = domainToASCII; diff --git a/test/parallel/test-fs-null-bytes.js b/test/parallel/test-fs-null-bytes.js index 39768489fbee6d..fa29e64c9b2382 100644 --- a/test/parallel/test-fs-null-bytes.js +++ b/test/parallel/test-fs-null-bytes.js @@ -2,7 +2,6 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); -const URL = require('url').URL; function check(async, sync) { const expected = /Path must be a string without null bytes/; @@ -49,62 +48,6 @@ check(null, fs.watch, 'foo\u0000bar', common.fail); check(null, fs.watchFile, 'foo\u0000bar', common.fail); check(fs.writeFile, fs.writeFileSync, 'foo\u0000bar'); -check(fs.access, fs.accessSync, new URL('file:///foo\u0000bar')); -check(fs.access, fs.accessSync, new URL('file:///foo\u0000bar'), fs.F_OK); -check(fs.appendFile, fs.appendFileSync, new URL('file:///foo\u0000bar')); -check(fs.chmod, fs.chmodSync, new URL('file:///foo\u0000bar'), '0644'); -check(fs.chown, fs.chownSync, new URL('file:///foo\u0000bar'), 12, 34); -check(fs.link, fs.linkSync, new URL('file:///foo\u0000bar'), 'foobar'); -check(fs.link, fs.linkSync, 'foobar', new URL('file:///foo\u0000bar')); -check(fs.lstat, fs.lstatSync, new URL('file:///foo\u0000bar')); -check(fs.mkdir, fs.mkdirSync, new URL('file:///foo\u0000bar'), '0755'); -check(fs.open, fs.openSync, new URL('file:///foo\u0000bar'), 'r'); -check(fs.readFile, fs.readFileSync, new URL('file:///foo\u0000bar')); -check(fs.readdir, fs.readdirSync, new URL('file:///foo\u0000bar')); -check(fs.readlink, fs.readlinkSync, new URL('file:///foo\u0000bar')); -check(fs.realpath, fs.realpathSync, new URL('file:///foo\u0000bar')); -check(fs.rename, fs.renameSync, new URL('file:///foo\u0000bar'), 'foobar'); -check(fs.rename, fs.renameSync, 'foobar', new URL('file:///foo\u0000bar')); -check(fs.rmdir, fs.rmdirSync, new URL('file:///foo\u0000bar')); -check(fs.stat, fs.statSync, new URL('file:///foo\u0000bar')); -check(fs.symlink, fs.symlinkSync, new URL('file:///foo\u0000bar'), 'foobar'); -check(fs.symlink, fs.symlinkSync, 'foobar', new URL('file:///foo\u0000bar')); -check(fs.truncate, fs.truncateSync, new URL('file:///foo\u0000bar')); -check(fs.unlink, fs.unlinkSync, new URL('file:///foo\u0000bar')); -check(null, fs.unwatchFile, new URL('file:///foo\u0000bar'), common.fail); -check(fs.utimes, fs.utimesSync, new URL('file:///foo\u0000bar'), 0, 0); -check(null, fs.watch, new URL('file:///foo\u0000bar'), common.fail); -check(null, fs.watchFile, new URL('file:///foo\u0000bar'), common.fail); -check(fs.writeFile, fs.writeFileSync, new URL('file:///foo\u0000bar')); - -check(fs.access, fs.accessSync, new URL('file:///foo%00bar')); -check(fs.access, fs.accessSync, new URL('file:///foo%00bar'), fs.F_OK); -check(fs.appendFile, fs.appendFileSync, new URL('file:///foo%00bar')); -check(fs.chmod, fs.chmodSync, new URL('file:///foo%00bar'), '0644'); -check(fs.chown, fs.chownSync, new URL('file:///foo%00bar'), 12, 34); -check(fs.link, fs.linkSync, new URL('file:///foo%00bar'), 'foobar'); -check(fs.link, fs.linkSync, 'foobar', new URL('file:///foo%00bar')); -check(fs.lstat, fs.lstatSync, new URL('file:///foo%00bar')); -check(fs.mkdir, fs.mkdirSync, new URL('file:///foo%00bar'), '0755'); -check(fs.open, fs.openSync, new URL('file:///foo%00bar'), 'r'); -check(fs.readFile, fs.readFileSync, new URL('file:///foo%00bar')); -check(fs.readdir, fs.readdirSync, new URL('file:///foo%00bar')); -check(fs.readlink, fs.readlinkSync, new URL('file:///foo%00bar')); -check(fs.realpath, fs.realpathSync, new URL('file:///foo%00bar')); -check(fs.rename, fs.renameSync, new URL('file:///foo%00bar'), 'foobar'); -check(fs.rename, fs.renameSync, 'foobar', new URL('file:///foo%00bar')); -check(fs.rmdir, fs.rmdirSync, new URL('file:///foo%00bar')); -check(fs.stat, fs.statSync, new URL('file:///foo%00bar')); -check(fs.symlink, fs.symlinkSync, new URL('file:///foo%00bar'), 'foobar'); -check(fs.symlink, fs.symlinkSync, 'foobar', new URL('file:///foo%00bar')); -check(fs.truncate, fs.truncateSync, new URL('file:///foo%00bar')); -check(fs.unlink, fs.unlinkSync, new URL('file:///foo%00bar')); -check(null, fs.unwatchFile, new URL('file:///foo%00bar'), common.fail); -check(fs.utimes, fs.utimesSync, new URL('file:///foo%00bar'), 0, 0); -check(null, fs.watch, new URL('file:///foo%00bar'), common.fail); -check(null, fs.watchFile, new URL('file:///foo%00bar'), common.fail); -check(fs.writeFile, fs.writeFileSync, new URL('file:///foo%00bar')); - // an 'error' for exists means that it doesn't exist. // one of many reasons why this file is the absolute worst. fs.exists('foo\u0000bar', common.mustCall((exists) => { diff --git a/test/parallel/test-fs-whatwg-url.js b/test/parallel/test-fs-whatwg-url.js deleted file mode 100644 index 7a94fd68d7e4fa..00000000000000 --- a/test/parallel/test-fs-whatwg-url.js +++ /dev/null @@ -1,70 +0,0 @@ -'use strict'; - -const common = require('../common'); -const assert = require('assert'); -const path = require('path'); -const fs = require('fs'); -const os = require('os'); -const URL = require('url').URL; -const Buffer = require('buffer').Buffer; - -function pathToFileURL(p) { - if (!path.isAbsolute(p)) - throw new Error('Path must be absolute'); - if (common.isWindows && p.startsWith('\\\\')) - p = p.slice(2); - return new URL(`file://${p}`); -} - -const p = path.resolve(common.fixturesDir, 'a.js'); -const url = pathToFileURL(p); - -assert(url instanceof URL); - -// Check that we can pass in a URL object successfully -fs.readFile(url, common.mustCall((err, data) => { - assert.ifError(err); - assert(Buffer.isBuffer(data)); -})); - -// Check that using a non file:// URL reports an error -const httpUrl = new URL('http://example.org'); -fs.readFile(httpUrl, common.mustCall((err) => { - assert(err); - assert.strictEqual(err.message, - 'Only `file:` URLs are supported'); -})); - -// pct-encoded characters in the path will be decoded and checked -fs.readFile(new URL('file:///c:/tmp/%00test'), common.mustCall((err) => { - assert(err); - assert.strictEqual(err.message, - 'Path must be a string without null bytes'); -})); - -if (common.isWindows) { - // encoded back and forward slashes are not permitted on windows - ['%2f', '%2F', '%5c', '%5C'].forEach((i) => { - fs.readFile(new URL(`file:///c:/tmp/${i}`), common.mustCall((err) => { - assert(err); - assert.strictEqual(err.message, - 'Path must not include encoded \\ or / characters'); - })); - }); -} else { - // encoded forward slashes are not permitted on other platforms - ['%2f', '%2F'].forEach((i) => { - fs.readFile(new URL(`file:///c:/tmp/${i}`), common.mustCall((err) => { - assert(err); - assert.strictEqual(err.message, - 'Path must not include encoded / characters'); - })); - }); - - fs.readFile(new URL('file://hostname/a/b/c'), common.mustCall((err) => { - assert(err); - assert.strictEqual(err.message, - `File URLs on ${os.platform()} must use ` + - 'hostname \'localhost\' or not specify any hostname'); - })); -}