From 610cac26f0f0d98df2541bdc4251c624cca52702 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Tue, 6 Feb 2018 22:34:50 +0100 Subject: [PATCH 001/193] doc: add missing "changes" key in YAML comment PR-URL: https://github.com/nodejs/node/pull/18605 Reviewed-By: Anna Henningsen Reviewed-By: Anatoli Papirovski --- doc/api/http.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/http.md b/doc/api/http.md index 5659bb2edab393..341a08c5aeb89c 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -1666,6 +1666,7 @@ Found'`. ## http.createServer([options][, requestListener]) -* `file` {string|Buffer|URL|[FileHandle][]} filename or `FileHandle` +* `file` {string|Buffer|URL|FileHandle} filename or `FileHandle` * `data` {string|Buffer} * `options` {Object|string} * `encoding` {string|null} **Default:** `'utf8'` @@ -3640,7 +3640,7 @@ fs.promises.copyFile('source.txt', 'destination.txt', COPYFILE_EXCL) added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * `mode` {integer} * Returns: {Promise} @@ -3652,7 +3652,7 @@ success. added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * `uid` {integer} * `gid` {integer} * Returns: {Promise} @@ -3665,7 +3665,7 @@ the `Promise` with no arguments upon success. added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * Returns: {Promise} Asynchronous fdatasync(2). The `Promise` is resolved with no arguments upon @@ -3676,7 +3676,7 @@ success. added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * Returns: {Promise} Retrieves the [`fs.Stats`][] for the given `filehandle`. @@ -3686,7 +3686,7 @@ Retrieves the [`fs.Stats`][] for the given `filehandle`. added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * Returns: {Promise} Asynchronous fsync(2). The `Promise` is resolved with no arguments upon @@ -3697,7 +3697,7 @@ success. added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * `len` {integer} **Default:** `0` * Returns: {Promise} @@ -3746,7 +3746,7 @@ The last three bytes are null bytes ('\0'), to compensate the over-truncation. added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * `atime` {number|string|Date} * `mtime` {number|string|Date}` * Returns: {Promise} @@ -3934,7 +3934,7 @@ files can be opened for writing with the `r+` flag. A call to added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * `buffer` {Buffer|Uint8Array} * `offset` {integer} * `length` {integer} @@ -3981,7 +3981,7 @@ will be passed as `Buffer` objects. added: REPLACEME --> -* `path` {string|Buffer|URL|[FileHandle][]} filename or `FileHandle` +* `path` {string|Buffer|URL|FileHandle} filename or `FileHandle` * `options` {Object|string} * `encoding` {string|null} **Default:** `null` * `flag` {string} **Default:** `'r'` @@ -4147,7 +4147,7 @@ The `atime` and `mtime` arguments follow these rules: added: REPLACEME --> -* `filehandle` {[FileHandle][]} +* `filehandle` {FileHandle} * `buffer` {Buffer|Uint8Array} * `offset` {integer} * `length` {integer} @@ -4180,7 +4180,7 @@ the end of the file. added: REPLACEME --> -* `file` {string|Buffer|URL|[FileHandle][]} filename or `FileHandle` +* `file` {string|Buffer|URL|FileHandle} filename or `FileHandle` * `data` {string|Buffer|Uint8Array} * `options` {Object|string} * `encoding` {string|null} **Default:** `'utf8'` @@ -4469,7 +4469,6 @@ The following constants are meant for use with the [`fs.Stats`][] object's [`util.promisify()`]: util.html#util_util_promisify_original [Caveats]: #fs_caveats [Common System Errors]: errors.html#errors_common_system_errors -[FileHandle]: #fs_class_filehandle [FS Constants]: #fs_fs_constants_1 [MDN-Date]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date [MDN-Number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js index 0ab73162dd59e0..1a7698ad6a3c5d 100644 --- a/tools/doc/type-parser.js +++ b/tools/doc/type-parser.js @@ -45,6 +45,7 @@ const typeMap = { 'EventEmitter': 'events.html#events_class_eventemitter', + 'FileHandle': 'fs.html#fs_class_filehandle', 'fs.Stats': 'fs.html#fs_class_fs_stats', 'http.Agent': 'http.html#http_class_http_agent', From 12ae33476a69a3b13477ffd60a7497088e769870 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 3 Feb 2018 17:30:48 +0800 Subject: [PATCH 005/193] util: skip type checks in internal getSystemErrorName PR-URL: https://github.com/nodejs/node/pull/18546 Reviewed-By: James M Snell --- lib/internal/util.js | 8 -------- lib/util.js | 13 ++++++++++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/internal/util.js b/lib/internal/util.js index 1e48eedfd59b48..3de8090cfa2618 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -221,14 +221,6 @@ function getConstructorOf(obj) { } function getSystemErrorName(err) { - if (typeof err !== 'number') { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'err', 'number', err); - } - if (err >= 0 || !Number.isSafeInteger(err)) { - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'err', - 'a negative integer', err); - } - const entry = errmap.get(err); return entry ? entry[0] : `Unknown system error ${err}`; } diff --git a/lib/util.js b/lib/util.js index 4525792b2ec4c4..14c99bd454c8b0 100644 --- a/lib/util.js +++ b/lib/util.js @@ -55,7 +55,7 @@ const { const { customInspectSymbol, deprecate, - getSystemErrorName, + getSystemErrorName: internalErrorName, getIdentificationOf, isError, promisify, @@ -1139,6 +1139,17 @@ function callbackify(original) { return callbackified; } +function getSystemErrorName(err) { + if (typeof err !== 'number') { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'err', 'number', err); + } + if (err >= 0 || !Number.isSafeInteger(err)) { + throw new errors.RangeError('ERR_OUT_OF_RANGE', 'err', + 'a negative integer', err); + } + return internalErrorName(err); +} + // Keep the `exports =` so that various functions can still be monkeypatched module.exports = exports = { _errnoException, From 030384833f95ee9f61fc194cdcab4075df083926 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 3 Feb 2018 17:35:04 +0800 Subject: [PATCH 006/193] fs: do not call new when creating uvException We cannot make uvException a proper class due to compatibility reasons for now, so there is no need to call new since it only returns a newly-created Error. PR-URL: https://github.com/nodejs/node/pull/18546 Reviewed-By: James M Snell --- lib/fs.js | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 7087a5f03c5f9e..7136911e60eb23 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -407,7 +407,7 @@ fs.accessSync = function(path, mode) { binding.access(pathModule.toNamespacedPath(path), mode, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } }; @@ -638,7 +638,7 @@ function tryStatSync(fd, isUserFd) { binding.fstat(fd, undefined, ctx); if (ctx.errno !== undefined && !isUserFd) { fs.closeSync(fd); - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } } @@ -736,7 +736,7 @@ fs.closeSync = function(fd) { const ctx = {}; binding.close(fd, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } }; @@ -929,7 +929,7 @@ fs.renameSync = function(oldPath, newPath) { binding.rename(pathModule.toNamespacedPath(oldPath), pathModule.toNamespacedPath(newPath), undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } }; @@ -999,7 +999,7 @@ fs.ftruncateSync = function(fd, len = 0) { const ctx = {}; binding.ftruncate(fd, len, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } }; @@ -1033,7 +1033,7 @@ fs.fdatasyncSync = function(fd) { const ctx = {}; binding.fdatasync(fd, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } }; @@ -1049,7 +1049,7 @@ fs.fsyncSync = function(fd) { const ctx = {}; binding.fsync(fd, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } }; @@ -1134,7 +1134,7 @@ fs.fstatSync = function(fd) { const ctx = { fd }; binding.fstat(fd, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } return statsFromValues(); }; @@ -1146,7 +1146,7 @@ fs.lstatSync = function(path) { const ctx = { path }; binding.lstat(pathModule.toNamespacedPath(path), undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } return statsFromValues(); }; @@ -1158,7 +1158,7 @@ fs.statSync = function(path) { const ctx = { path }; binding.stat(pathModule.toNamespacedPath(path), undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } return statsFromValues(); }; @@ -1184,7 +1184,7 @@ fs.readlinkSync = function(path, options) { const result = binding.readlink(pathModule.toNamespacedPath(path), options.encoding, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } return result; }; @@ -1264,7 +1264,7 @@ fs.symlinkSync = function(target, path, type) { pathModule.toNamespacedPath(path), flags, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } else if (ctx.error) { // TODO(joyeecheung): this is an encoding error usually caused by memory // problems. We need to figure out proper error code(s) for this. @@ -1309,7 +1309,7 @@ fs.linkSync = function(existingPath, newPath) { pathModule.toNamespacedPath(newPath), undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } return result; }; @@ -1332,7 +1332,7 @@ fs.unlinkSync = function(path) { const ctx = { path }; binding.unlink(pathModule.toNamespacedPath(path), undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } }; @@ -1939,7 +1939,7 @@ fs.realpathSync = function realpathSync(p, options) { const ctx = { path: base }; binding.lstat(pathModule.toNamespacedPath(base), undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } knownHard[base] = true; } @@ -1983,7 +1983,7 @@ fs.realpathSync = function realpathSync(p, options) { const ctx = { path: base }; binding.lstat(baseLong, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } if ((statValues[1/*mode*/] & S_IFMT) !== S_IFLNK) { @@ -2008,11 +2008,11 @@ fs.realpathSync = function realpathSync(p, options) { const ctx = { path: base }; binding.stat(baseLong, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } linkTarget = binding.readlink(baseLong, undefined, undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } } resolvedLink = pathModule.resolve(previous, linkTarget); @@ -2033,7 +2033,7 @@ fs.realpathSync = function realpathSync(p, options) { const ctx = { path: base }; binding.lstat(pathModule.toNamespacedPath(base), undefined, ctx); if (ctx.errno !== undefined) { - throw new errors.uvException(ctx); + throw errors.uvException(ctx); } knownHard[base] = true; } From c0762c2f54f80b92f2f5e0f9af51f4c048c53e4f Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 3 Feb 2018 17:09:15 +0800 Subject: [PATCH 007/193] errors: move error creation helpers to errors.js This commit moves error creation helpers scattered around under lib/ into lib/internal/errors.js in the hope of being clearer about the differences of errors that we throw into the user land. - Move util._errnoException and util._exceptionWithHostPort into internal/errors.js and simplify their logic so it's clearer what the properties these helpers create. - Move the errnoException helper in dns.js to internal/errors.js into internal/errors.js and rename it to dnsException. Simplify it's logic so it no longer calls errnoException and skips the unnecessary argument checks. PR-URL: https://github.com/nodejs/node/pull/18546 Reviewed-By: James M Snell --- lib/dgram.js | 4 +- lib/dns.js | 47 +++--------- lib/fs.js | 2 +- lib/internal/child_process.js | 2 +- lib/internal/errors.js | 131 ++++++++++++++++++++++++++++++++-- lib/internal/http2/core.js | 4 +- lib/internal/process.js | 4 +- lib/net.js | 4 +- lib/tty.js | 4 +- lib/util.js | 38 +--------- 10 files changed, 148 insertions(+), 92 deletions(-) diff --git a/lib/dgram.js b/lib/dgram.js index 0c4990cac5d315..bed6129b47be11 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -45,8 +45,8 @@ const SEND_BUFFER = false; // Lazily loaded var cluster = null; -const errnoException = util._errnoException; -const exceptionWithHostPort = util._exceptionWithHostPort; +const errnoException = errors.errnoException; +const exceptionWithHostPort = errors.exceptionWithHostPort; function lookup4(lookup, address, callback) { diff --git a/lib/dns.js b/lib/dns.js index 979d724c3e4aa5..51c144f4e394eb 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -21,17 +21,10 @@ 'use strict'; -const util = require('util'); - const cares = process.binding('cares_wrap'); const { isIP, isIPv4, isLegalPort } = require('internal/net'); const { customPromisifyArgs } = require('internal/util'); const errors = require('internal/errors'); -const { - UV_EAI_MEMORY, - UV_EAI_NODATA, - UV_EAI_NONAME -} = process.binding('uv'); const { GetAddrInfoReqWrap, @@ -40,36 +33,12 @@ const { ChannelWrap, } = cares; -function errnoException(err, syscall, hostname) { - // FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass - // the true error to the user. ENOTFOUND is not even a proper POSIX error! - if (err === UV_EAI_MEMORY || - err === UV_EAI_NODATA || - err === UV_EAI_NONAME) { - err = 'ENOTFOUND'; - } - var ex = null; - if (typeof err === 'string') { // c-ares error code. - const errHost = hostname ? ` ${hostname}` : ''; - ex = new Error(`${syscall} ${err}${errHost}`); - ex.code = err; - ex.errno = err; - ex.syscall = syscall; - } else { - ex = util._errnoException(err, syscall); - } - if (hostname) { - ex.hostname = hostname; - } - return ex; -} - const IANA_DNS_PORT = 53; - +const dnsException = errors.dnsException; function onlookup(err, addresses) { if (err) { - return this.callback(errnoException(err, 'getaddrinfo', this.hostname)); + return this.callback(dnsException(err, 'getaddrinfo', this.hostname)); } if (this.family) { this.callback(null, addresses[0], this.family); @@ -81,7 +50,7 @@ function onlookup(err, addresses) { function onlookupall(err, addresses) { if (err) { - return this.callback(errnoException(err, 'getaddrinfo', this.hostname)); + return this.callback(dnsException(err, 'getaddrinfo', this.hostname)); } var family = this.family; @@ -161,7 +130,7 @@ function lookup(hostname, options, callback) { var err = cares.getaddrinfo(req, hostname, family, hints, verbatim); if (err) { - process.nextTick(callback, errnoException(err, 'getaddrinfo', hostname)); + process.nextTick(callback, dnsException(err, 'getaddrinfo', hostname)); return {}; } return req; @@ -173,7 +142,7 @@ Object.defineProperty(lookup, customPromisifyArgs, function onlookupservice(err, host, service) { if (err) - return this.callback(errnoException(err, 'getnameinfo', this.host)); + return this.callback(dnsException(err, 'getnameinfo', this.host)); this.callback(null, host, service); } @@ -202,7 +171,7 @@ function lookupService(host, port, callback) { req.oncomplete = onlookupservice; var err = cares.getnameinfo(req, host, port); - if (err) throw errnoException(err, 'getnameinfo', host); + if (err) throw dnsException(err, 'getnameinfo', host); return req; } @@ -215,7 +184,7 @@ function onresolve(err, result, ttls) { result = result.map((address, index) => ({ address, ttl: ttls[index] })); if (err) - this.callback(errnoException(err, this.bindingName, this.hostname)); + this.callback(dnsException(err, this.bindingName, this.hostname)); else this.callback(null, result); } @@ -253,7 +222,7 @@ function resolver(bindingName) { req.oncomplete = onresolve; req.ttl = !!(options && options.ttl); var err = this._handle[bindingName](req, name); - if (err) throw errnoException(err, bindingName); + if (err) throw dnsException(err, bindingName); return req; } Object.defineProperty(query, 'name', { value: bindingName }); diff --git a/lib/fs.js b/lib/fs.js index 7136911e60eb23..04d3d0a5bd4357 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -62,7 +62,7 @@ const { kMaxLength } = require('buffer'); const isWindows = process.platform === 'win32'; const DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); -const errnoException = util._errnoException; +const errnoException = errors.errnoException; let truncateWarn = true; diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 2bade01f95f209..ac2b75f24575b8 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -29,7 +29,7 @@ const { UV_ESRCH } = process.binding('uv'); -const errnoException = util._errnoException; +const errnoException = errors.errnoException; const { SocketListSend, SocketListReceive } = SocketList; const MAX_HANDLE_RETRANSMISSIONS = 3; diff --git a/lib/internal/errors.js b/lib/internal/errors.js index a41df135407341..c07920ae5d01ed 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -18,7 +18,12 @@ var green = ''; var red = ''; var white = ''; -const { errmap } = process.binding('uv'); +const { + errmap, + UV_EAI_MEMORY, + UV_EAI_NODATA, + UV_EAI_NONAME +} = process.binding('uv'); const { kMaxLength } = process.binding('buffer'); const { defineProperty } = Object; @@ -33,6 +38,14 @@ function lazyUtil() { return util_; } +var internalUtil = null; +function lazyInternalUtil() { + if (!internalUtil) { + internalUtil = require('internal/util'); + } + return internalUtil; +} + function makeNodeError(Base) { return class NodeError extends Base { constructor(key, ...args) { @@ -356,10 +369,15 @@ function E(sym, val) { messages.set(sym, typeof val === 'function' ? val : String(val)); } -// This creates an error compatible with errors produced in UVException -// using the context collected in CollectUVExceptionInfo -// The goal is to migrate them to ERR_* errors later when -// compatibility is not a concern +/** + * This creates an error compatible with errors produced in the C++ + * function UVException using a context object with data assembled in C++. + * The goal is to migrate them to ERR_* errors later when compatibility is + * not a concern. + * + * @param {Object} ctx + * @returns {Error} + */ function uvException(ctx) { const err = new Error(); @@ -389,7 +407,110 @@ function uvException(ctx) { return err; } +/** + * This used to be util._errnoException(). + * + * @param {number} err - A libuv error number + * @param {string} syscall + * @param {string} [original] + * @returns {Error} + */ +function errnoException(err, syscall, original) { + // TODO(joyeecheung): We have to use the type-checked + // getSystemErrorName(err) to guard against invalid arguments from users. + // This can be replaced with [ code ] = errmap.get(err) when this method + // is no longer exposed to user land. + const code = lazyUtil().getSystemErrorName(err); + const message = original ? + `${syscall} ${code} ${original}` : `${syscall} ${code}`; + + const ex = new Error(message); + // TODO(joyeecheung): errno is supposed to err, like in uvException + ex.code = ex.errno = code; + ex.syscall = syscall; + + Error.captureStackTrace(ex, errnoException); + return ex; +} + +/** + * This used to be util._exceptionWithHostPort(). + * + * @param {number} err - A libuv error number + * @param {string} syscall + * @param {string} address + * @param {number} [port] + * @param {string} [additional] + * @returns {Error} + */ +function exceptionWithHostPort(err, syscall, address, port, additional) { + // TODO(joyeecheung): We have to use the type-checked + // getSystemErrorName(err) to guard against invalid arguments from users. + // This can be replaced with [ code ] = errmap.get(err) when this method + // is no longer exposed to user land. + const code = lazyUtil().getSystemErrorName(err); + let details = ''; + if (port && port > 0) { + details = ` ${address}:${port}`; + } else if (address) { + details = ` ${address}`; + } + if (additional) { + details += ` - Local (${additional})`; + } + + const ex = new Error(`${syscall} ${code}${details}`); + // TODO(joyeecheung): errno is supposed to err, like in uvException + ex.code = ex.errno = code; + ex.syscall = syscall; + ex.address = address; + if (port) { + ex.port = port; + } + + Error.captureStackTrace(ex, exceptionWithHostPort); + return ex; +} + +/** + * @param {number|string} err - A libuv error number or a c-ares error code + * @param {string} syscall + * @param {string} [hostname] + * @returns {Error} + */ +function dnsException(err, syscall, hostname) { + const ex = new Error(); + // FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass + // the true error to the user. ENOTFOUND is not even a proper POSIX error! + if (err === UV_EAI_MEMORY || + err === UV_EAI_NODATA || + err === UV_EAI_NONAME) { + err = 'ENOTFOUND'; // Fabricated error name. + } + if (typeof err === 'string') { // c-ares error code. + const errHost = hostname ? ` ${hostname}` : ''; + ex.message = `${syscall} ${err}${errHost}`; + // TODO(joyeecheung): errno is supposed to be a number, like in uvException + ex.code = ex.errno = err; + ex.syscall = syscall; + } else { // libuv error number + const code = lazyInternalUtil().getSystemErrorName(err); + ex.message = `${syscall} ${code}`; + // TODO(joyeecheung): errno is supposed to be err, like in uvException + ex.code = ex.errno = code; + ex.syscall = syscall; + } + if (hostname) { + ex.hostname = hostname; + } + Error.captureStackTrace(ex, dnsException); + return ex; +} + module.exports = exports = { + dnsException, + errnoException, + exceptionWithHostPort, uvException, message, Error: makeNodeError(Error), diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index f735e2fcc92f62..5f811ca8af403a 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -1631,7 +1631,7 @@ class Http2Stream extends Duplex { req.async = false; const err = createWriteReq(req, handle, data, encoding); if (err) - throw util._errnoException(err, 'write', req.error); + throw errors.errnoException(err, 'write', req.error); trackWriteState(this, req.bytes); } @@ -1674,7 +1674,7 @@ class Http2Stream extends Duplex { } const err = handle.writev(req, chunks); if (err) - throw util._errnoException(err, 'write', req.error); + throw errors.errnoException(err, 'write', req.error); trackWriteState(this, req.bytes); } diff --git a/lib/internal/process.js b/lib/internal/process.js index 757c8de8e685f1..776129a140fe68 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -170,7 +170,7 @@ function setupKillAndExit() { } if (err) - throw util._errnoException(err, 'kill'); + throw errors.errnoException(err, 'kill'); return true; }; @@ -200,7 +200,7 @@ function setupSignalHandlers() { const err = wrap.start(signum); if (err) { wrap.close(); - throw util._errnoException(err, 'uv_signal_start'); + throw errors.errnoException(err, 'uv_signal_start'); } signalWraps[type] = wrap; diff --git a/lib/net.js b/lib/net.js index 0ba7457b7f8026..5d99b00662d49d 100644 --- a/lib/net.js +++ b/lib/net.js @@ -59,8 +59,8 @@ const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); // reasons it's lazy loaded. var cluster = null; -const errnoException = util._errnoException; -const exceptionWithHostPort = util._exceptionWithHostPort; +const errnoException = errors.errnoException; +const exceptionWithHostPort = errors.exceptionWithHostPort; const { kTimeout, diff --git a/lib/tty.js b/lib/tty.js index 584ff9d87093c4..79e61e981b5a07 100644 --- a/lib/tty.js +++ b/lib/tty.js @@ -21,7 +21,7 @@ 'use strict'; -const { inherits, _errnoException, _extend } = require('util'); +const { inherits, _extend } = require('util'); const net = require('net'); const { TTY, isTTY } = process.binding('tty_wrap'); const errors = require('internal/errors'); @@ -178,7 +178,7 @@ WriteStream.prototype._refreshSize = function() { const winSize = new Array(2); const err = this._handle.getWindowSize(winSize); if (err) { - this.emit('error', _errnoException(err, 'getWindowSize')); + this.emit('error', errors.errnoException(err, 'getWindowSize')); return; } const [newCols, newRows] = winSize; diff --git a/lib/util.js b/lib/util.js index 14c99bd454c8b0..e13f5b8b80009e 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1058,40 +1058,6 @@ function error(...args) { } } -function _errnoException(err, syscall, original) { - const name = getSystemErrorName(err); - var message = `${syscall} ${name}`; - if (original) - message += ` ${original}`; - const e = new Error(message); - e.code = e.errno = name; - e.syscall = syscall; - return e; -} - -function _exceptionWithHostPort(err, - syscall, - address, - port, - additional) { - var details; - if (port && port > 0) { - details = `${address}:${port}`; - } else { - details = address; - } - - if (additional) { - details += ` - Local (${additional})`; - } - var ex = exports._errnoException(err, syscall, details); - ex.address = address; - if (port) { - ex.port = port; - } - return ex; -} - function callbackifyOnRejected(reason, cb) { // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M). // Because `null` is a special error value in callbacks which means "no error @@ -1152,8 +1118,8 @@ function getSystemErrorName(err) { // Keep the `exports =` so that various functions can still be monkeypatched module.exports = exports = { - _errnoException, - _exceptionWithHostPort, + _errnoException: errors.errnoException, + _exceptionWithHostPort: errors.exceptionWithHostPort, _extend, callbackify, debuglog, From d797775fb82caae5f721140625dfb0f984ce929e Mon Sep 17 00:00:00 2001 From: Shobhit Chittora Date: Wed, 1 Nov 2017 01:31:02 +0530 Subject: [PATCH 008/193] tools: add fixer for prefer-assert-iferror.js PR-URL: https://github.com/nodejs/node/pull/16648 Refs: https://github.com/nodejs/node/issues/16636 Reviewed-By: Anatoli Papirovski Reviewed-By: Gibson Fahnestock Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- .../test-eslint-prefer-assert-iferror.js | 14 +++++++---- tools/eslint-rules/prefer-assert-iferror.js | 23 +++++++++++++++++-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/test/parallel/test-eslint-prefer-assert-iferror.js b/test/parallel/test-eslint-prefer-assert-iferror.js index 6e577b1fc35ace..8a9723f4b21f6a 100644 --- a/test/parallel/test-eslint-prefer-assert-iferror.js +++ b/test/parallel/test-eslint-prefer-assert-iferror.js @@ -14,12 +14,18 @@ new RuleTester().run('prefer-assert-iferror', rule, { ], invalid: [ { - code: 'if (err) throw err;', - errors: [{ message: 'Use assert.ifError(err) instead.' }] + code: 'require("assert");\n' + + 'if (err) throw err;', + errors: [{ message: 'Use assert.ifError(err) instead.' }], + output: 'require("assert");\n' + + 'assert.ifError(err);' }, { - code: 'if (error) { throw error; }', - errors: [{ message: 'Use assert.ifError(error) instead.' }] + code: 'require("assert");\n' + + 'if (error) { throw error; }', + errors: [{ message: 'Use assert.ifError(error) instead.' }], + output: 'require("assert");\n' + + 'assert.ifError(error);' } ] }); diff --git a/tools/eslint-rules/prefer-assert-iferror.js b/tools/eslint-rules/prefer-assert-iferror.js index e15287417693e0..399ee7403a6c88 100644 --- a/tools/eslint-rules/prefer-assert-iferror.js +++ b/tools/eslint-rules/prefer-assert-iferror.js @@ -5,9 +5,12 @@ 'use strict'; +const utils = require('./rules-utils.js'); + module.exports = { create(context) { const sourceCode = context.getSourceCode(); + var assertImported = false; function hasSameTokens(nodeA, nodeB) { const aTokens = sourceCode.getTokens(nodeA); @@ -20,8 +23,15 @@ module.exports = { }); } + function checkAssertNode(node) { + if (utils.isRequired(node, ['assert'])) { + assertImported = true; + } + } + return { - IfStatement(node) { + 'CallExpression': (node) => checkAssertNode(node), + 'IfStatement': (node) => { const firstStatement = node.consequent.type === 'BlockStatement' ? node.consequent.body[0] : node.consequent; @@ -30,10 +40,19 @@ module.exports = { firstStatement.type === 'ThrowStatement' && hasSameTokens(node.test, firstStatement.argument) ) { + const argument = sourceCode.getText(node.test); context.report({ node: firstStatement, message: 'Use assert.ifError({{argument}}) instead.', - data: { argument: sourceCode.getText(node.test) } + data: { argument }, + fix: (fixer) => { + if (assertImported) { + return fixer.replaceText( + node, + `assert.ifError(${argument});` + ); + } + } }); } } From e5429204679cab10cd4ee28d5dfec9026a91a6d1 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 3 Feb 2018 18:27:21 +0800 Subject: [PATCH 009/193] test: do not check TXT content in test-dns-any google.com added another TXT record which broke this test. This removes the check on the content of the TXT record since that depends on an external state subject to change. PR-URL: https://github.com/nodejs/node/pull/18547 Reviewed-By: Khaidi Chu Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Jon Moss Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- test/internet/test-dns-any.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/internet/test-dns-any.js b/test/internet/test-dns-any.js index dd80e48bf44e91..a83040801f38f4 100644 --- a/test/internet/test-dns-any.js +++ b/test/internet/test-dns-any.js @@ -59,9 +59,6 @@ const checkers = { checkTXT(r) { assert.ok(Array.isArray(r.entries)); assert.ok(r.entries.length > 0); - r.entries.forEach((txt) => { - assert(txt.startsWith('v=spf1')); - }); assert.strictEqual(r.type, 'TXT'); }, checkSOA(r) { From b8f7f84fc233a5876b1d275fed63775bdbb7932f Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 5 Feb 2018 15:55:15 -0500 Subject: [PATCH 010/193] test: fix flaky test-http2-session-unref This test should exit naturally or will timeout on its own, a separate unrefed timer is not necessary. PR-URL: https://github.com/nodejs/node/pull/18589 Fixes: https://github.com/nodejs/node/issues/18587 Reviewed-By: Michael Dawson Reviewed-By: James M Snell Reviewed-By: Yuta Hiroto Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig --- test/parallel/test-http2-session-unref.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/parallel/test-http2-session-unref.js b/test/parallel/test-http2-session-unref.js index e765352cdc615d..e63cd0d208e32b 100644 --- a/test/parallel/test-http2-session-unref.js +++ b/test/parallel/test-http2-session-unref.js @@ -49,5 +49,3 @@ server.listen(0, common.mustCall(() => { })); server.emit('connection', serverSide); server.unref(); - -setTimeout(common.mustNotCall(() => {}), 1000).unref(); From 93df1169ea451983f09611c0acc9d3c98760dd28 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Tue, 6 Feb 2018 11:19:04 +0200 Subject: [PATCH 011/193] lib,doc: revert format name to cjs over commonjs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18596 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Myles Borins Reviewed-By: Ruben Bridgewater --- doc/api/esm.md | 2 +- lib/internal/loader/DefaultResolve.js | 2 +- lib/internal/loader/Translators.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api/esm.md b/doc/api/esm.md index 10f20958593b59..2cfa5a9f29c753 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -137,7 +137,7 @@ module. This can be one of the following: | `format` | Description | | --- | --- | | `"esm"` | Load a standard JavaScript module | -| `"commonjs"` | Load a node-style CommonJS module | +| `"cjs"` | Load a node-style CommonJS module | | `"builtin"` | Load a node builtin CommonJS module | | `"json"` | Load a JSON file | | `"addon"` | Load a [C++ Addon][addons] | diff --git a/lib/internal/loader/DefaultResolve.js b/lib/internal/loader/DefaultResolve.js index faadf0bc99ef95..69dd9537c18c2d 100644 --- a/lib/internal/loader/DefaultResolve.js +++ b/lib/internal/loader/DefaultResolve.js @@ -44,7 +44,7 @@ const extensionFormatMap = { '.mjs': 'esm', '.json': 'json', '.node': 'addon', - '.js': 'commonjs' + '.js': 'cjs' }; function resolve(specifier, parentURL) { diff --git a/lib/internal/loader/Translators.js b/lib/internal/loader/Translators.js index f1db8334dd5eea..d2f28774177fd6 100644 --- a/lib/internal/loader/Translators.js +++ b/lib/internal/loader/Translators.js @@ -32,7 +32,7 @@ translators.set('esm', async (url) => { // Strategy for loading a node-style CommonJS module const isWindows = process.platform === 'win32'; const winSepRegEx = /\//g; -translators.set('commonjs', async (url) => { +translators.set('cjs', async (url) => { debug(`Translating CJSModule ${url}`); const pathname = internalURLModule.getPathFromURL(new URL(url)); const module = CJSModule._cache[ From 4ac7be94f004811a57545c5a191381156af23e43 Mon Sep 17 00:00:00 2001 From: "Tim O. Peters" Date: Thu, 4 Jan 2018 11:17:01 +0100 Subject: [PATCH 012/193] doc: be more explicit in the sypnosis Assuming less knowledge on the part of the reader, making it easier to get start using Node.js. PR-URL: https://github.com/nodejs/node/pull/17977 Fixes: https://github.com/nodejs/node/issues/17970, Reviewed-By: Vse Mozhet Byt Reviewed-By: Gireesh Punathil Reviewed-By: Ruben Bridgewater Reviewed-By: Jeremiah Senkpiel --- doc/api/synopsis.md | 76 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/doc/api/synopsis.md b/doc/api/synopsis.md index ada2437387b7e2..508dde1ff483f8 100644 --- a/doc/api/synopsis.md +++ b/doc/api/synopsis.md @@ -9,9 +9,58 @@ Please see the [Command Line Options][] document for information about different options and ways to run scripts with Node.js. ## Example - An example of a [web server][] written with Node.js which responds with -`'Hello World'`: +`'Hello World!'`: + +Commands displayed in this document are shown starting with `$` or `>` +to replicate how they would appear in a user's terminal. +Do not include the `$` and `>` character they are there to +indicate the start of each command. + +There are many tutorials and examples that follow this +convention: `$` or `>` for commands run as a regular user, and `#` +for commands that should be executed as an administrator. + +Lines that don’t start with `$` or `>` character are typically showing +the output of the previous command. + +Firstly, make sure to have downloaded and installed Node.js. +See [this guide][] for further install information. + +Now, create an empty project folder called `projects`, navigate into it: +Project folder can be named base on user's current project title but +this example will use `projects` as the project folder. + +Linux and Mac: + +```console +$ mkdir ~/projects +$ cd ~/projects +``` + +Windows CMD: + +```console +> mkdir %USERPROFILE%\projects +> cd %USERPROFILE%\projects +``` + +Windows PowerShell: + +```console +> mkdir $env:USERPROFILE\projects +> cd $env:USERPROFILE\projects +``` + +Next, create a new source file in the `projects` + folder and call it `hello-world.js`. + +In Node.js it is considered good style to use +hyphens (`-`) or underscores (`_`) to separate + multiple words in filenames. + +Open `hello-world.js` in any preferred text editor and +paste in the following content. ```js const http = require('http'); @@ -22,7 +71,7 @@ const port = 3000; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); - res.end('Hello World\n'); + res.end('Hello World!\n'); }); server.listen(port, hostname, () => { @@ -30,15 +79,26 @@ server.listen(port, hostname, () => { }); ``` -To run the server, put the code into a file called `example.js` and execute -it with Node.js: +Save the file, go back to the terminal window enter the following command: -```txt -$ node example.js -Server running at http://127.0.0.1:3000/ +```console +$ node hello-world.js ``` +An output like this should appear in the terminal to indicate Node.js +server is running: + + ```console + Server running at http://127.0.0.1:3000/ + ```` + +Now, open any preferred web browser and visit `http://127.0.0.1:3000`. + +If the browser displays the string `Hello, world!`, that indicates +the server is working. + Many of the examples in the documentation can be run similarly. [Command Line Options]: cli.html#cli_command_line_options [web server]: http.html +[this guide]: https://nodejs.org/en/download/package-manager/ From 5ecd2e15b8725f67219b746a6291992dbef62f06 Mon Sep 17 00:00:00 2001 From: Bhavani Shankar Date: Thu, 1 Feb 2018 15:32:41 +0530 Subject: [PATCH 013/193] test: improve error message output PR-URL: https://github.com/nodejs/node/pull/18498 Reviewed-By: Ruben Bridgewater Reviewed-By: Anatoli Papirovski Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Gireesh Punathil Reviewed-By: Michael Dawson --- test/addons-napi/test_general/test.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test/addons-napi/test_general/test.js b/test/addons-napi/test_general/test.js index c89d718ca18575..bcaa13d894bedc 100644 --- a/test/addons-napi/test_general/test.js +++ b/test/addons-napi/test_general/test.js @@ -63,22 +63,25 @@ let w = {}; test_general.wrap(w); w = null; global.gc(); -assert.strictEqual(test_general.derefItemWasCalled(), true, +const derefItemWasCalled = test_general.derefItemWasCalled(); +assert.strictEqual(derefItemWasCalled, true, 'deref_item() was called upon garbage collecting a ' + - 'wrapped object'); + 'wrapped object. test_general.derefItemWasCalled() ' + + `returned ${derefItemWasCalled}`); + // Assert that wrapping twice fails. const x = {}; test_general.wrap(x); -assert.throws(() => test_general.wrap(x), Error); +common.expectsError(() => test_general.wrap(x), + { type: Error, message: 'Invalid argument' }); // Ensure that wrapping, removing the wrap, and then wrapping again works. const y = {}; test_general.wrap(y); test_general.removeWrap(y); -assert.doesNotThrow(() => test_general.wrap(y), Error, - 'Wrapping twice succeeds if a remove_wrap()' + - ' separates the instances'); +// Wrapping twice succeeds if a remove_wrap() separates the instances +assert.doesNotThrow(() => test_general.wrap(y)); // Ensure that removing a wrap and garbage collecting does not fire the // finalize callback. @@ -87,8 +90,11 @@ test_general.testFinalizeWrap(z); test_general.removeWrap(z); z = null; global.gc(); -assert.strictEqual(test_general.finalizeWasCalled(), false, - 'finalize callback was not called upon garbage collection'); +const finalizeWasCalled = test_general.finalizeWasCalled(); +assert.strictEqual(finalizeWasCalled, false, + 'finalize callback was not called upon garbage collection.' + + ' test_general.finalizeWasCalled() ' + + `returned ${finalizeWasCalled}`); // test napi_adjust_external_memory const adjustedValue = test_general.testAdjustExternalMemory(); From af5632e4f40b2462139ae1534bc5ef99ce39ebbb Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Sun, 4 Feb 2018 13:43:21 -0500 Subject: [PATCH 014/193] readline: use Date.now() and move test to parallel The readline module wants a truthy time while using Timer.now() doesn't necessarily guarantee that early on in the process' life. It also doesn't actually resolve the timing issues experienced in an earlier issue. Instead, this PR fixes the related tests and moves them back to parallel. Refs: https://github.com/nodejs/node/issues/14674 PR-URL: https://github.com/nodejs/node/pull/18563 Reviewed-By: Anna Henningsen Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater --- lib/readline.js | 10 +- test/parallel/test-readline-interface.js | 77 +++++++++++++++ test/sequential/test-readline-interface.js | 108 --------------------- 3 files changed, 81 insertions(+), 114 deletions(-) delete mode 100644 test/sequential/test-readline-interface.js diff --git a/lib/readline.js b/lib/readline.js index bca9c25ab2348b..5f28f4c43f17d5 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -48,8 +48,6 @@ const { kClearScreenDown } = CSI; -const { now } = process.binding('timer_wrap').Timer; - const kHistorySize = 30; const kMincrlfDelay = 100; // \r\n, \n, or \r followed by something other than \n @@ -411,7 +409,7 @@ Interface.prototype._normalWrite = function(b) { } var string = this._decoder.write(b); if (this._sawReturnAt && - now() - this._sawReturnAt <= this.crlfDelay) { + Date.now() - this._sawReturnAt <= this.crlfDelay) { string = string.replace(/^\n/, ''); this._sawReturnAt = 0; } @@ -424,7 +422,7 @@ Interface.prototype._normalWrite = function(b) { this._line_buffer = null; } if (newPartContainsEnding) { - this._sawReturnAt = string.endsWith('\r') ? now() : 0; + this._sawReturnAt = string.endsWith('\r') ? Date.now() : 0; // got one or more newlines; process into "line" events var lines = string.split(lineEnding); @@ -917,14 +915,14 @@ Interface.prototype._ttyWrite = function(s, key) { switch (key.name) { case 'return': // carriage return, i.e. \r - this._sawReturnAt = now(); + this._sawReturnAt = Date.now(); this._line(); break; case 'enter': // When key interval > crlfDelay if (this._sawReturnAt === 0 || - now() - this._sawReturnAt > this.crlfDelay) { + Date.now() - this._sawReturnAt > this.crlfDelay) { this._line(); } this._sawReturnAt = 0; diff --git a/test/parallel/test-readline-interface.js b/test/parallel/test-readline-interface.js index 69c0f113ff103b..fe33e244cebd20 100644 --- a/test/parallel/test-readline-interface.js +++ b/test/parallel/test-readline-interface.js @@ -869,3 +869,80 @@ function isWarned(emitter) { assert.strictEqual(rl._prompt, '$ '); } }); + +// For the purposes of the following tests, we do not care about the exact +// value of crlfDelay, only that the behaviour conforms to what's expected. +// Setting it to Infinity allows the test to succeed even under extreme +// CPU stress. +const crlfDelay = Infinity; + +[ true, false ].forEach(function(terminal) { + // sending multiple newlines at once that does not end with a new line + // and a `end` event(last line is) + + // \r\n should emit one line event, not two + { + const fi = new FakeInput(); + const rli = new readline.Interface( + { + input: fi, + output: fi, + terminal: terminal, + crlfDelay + } + ); + const expectedLines = ['foo', 'bar', 'baz', 'bat']; + let callCount = 0; + rli.on('line', function(line) { + assert.strictEqual(line, expectedLines[callCount]); + callCount++; + }); + fi.emit('data', expectedLines.join('\r\n')); + assert.strictEqual(callCount, expectedLines.length - 1); + rli.close(); + } + + // \r\n should emit one line event when split across multiple writes. + { + const fi = new FakeInput(); + const rli = new readline.Interface({ + input: fi, + output: fi, + terminal: terminal, + crlfDelay + }); + const expectedLines = ['foo', 'bar', 'baz', 'bat']; + let callCount = 0; + rli.on('line', function(line) { + assert.strictEqual(line, expectedLines[callCount]); + callCount++; + }); + expectedLines.forEach(function(line) { + fi.emit('data', `${line}\r`); + fi.emit('data', '\n'); + }); + assert.strictEqual(callCount, expectedLines.length); + rli.close(); + } + + // Emit one line event when the delay between \r and \n is + // over the default crlfDelay but within the setting value. + { + const fi = new FakeInput(); + const delay = 125; + const rli = new readline.Interface({ + input: fi, + output: fi, + terminal: terminal, + crlfDelay + }); + let callCount = 0; + rli.on('line', () => callCount++); + fi.emit('data', '\r'); + setTimeout(common.mustCall(() => { + fi.emit('data', '\n'); + assert.strictEqual(callCount, 1); + rli.close(); + }), delay); + } +}); diff --git a/test/sequential/test-readline-interface.js b/test/sequential/test-readline-interface.js deleted file mode 100644 index 488dd8338da761..00000000000000 --- a/test/sequential/test-readline-interface.js +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Flags: --expose_internals -'use strict'; -const common = require('../common'); - -// These test cases are in `sequential` rather than the analogous test file in -// `parallel` because they become unreliable under load. The unreliability under -// load was determined empirically when the test cases were in `parallel` by -// running: -// tools/test.py -j 96 --repeat 192 test/parallel/test-readline-interface.js - -const assert = require('assert'); -const readline = require('readline'); -const EventEmitter = require('events').EventEmitter; -const inherits = require('util').inherits; - -function FakeInput() { - EventEmitter.call(this); -} -inherits(FakeInput, EventEmitter); -FakeInput.prototype.resume = () => {}; -FakeInput.prototype.pause = () => {}; -FakeInput.prototype.write = () => {}; -FakeInput.prototype.end = () => {}; - -[ true, false ].forEach(function(terminal) { - // sending multiple newlines at once that does not end with a new line - // and a `end` event(last line is) - - // \r\n should emit one line event, not two - { - const fi = new FakeInput(); - const rli = new readline.Interface( - { input: fi, output: fi, terminal: terminal } - ); - const expectedLines = ['foo', 'bar', 'baz', 'bat']; - let callCount = 0; - rli.on('line', function(line) { - assert.strictEqual(line, expectedLines[callCount]); - callCount++; - }); - fi.emit('data', expectedLines.join('\r\n')); - assert.strictEqual(callCount, expectedLines.length - 1); - rli.close(); - } - - // \r\n should emit one line event when split across multiple writes. - { - const fi = new FakeInput(); - const rli = new readline.Interface( - { input: fi, output: fi, terminal: terminal } - ); - const expectedLines = ['foo', 'bar', 'baz', 'bat']; - let callCount = 0; - rli.on('line', function(line) { - assert.strictEqual(line, expectedLines[callCount]); - callCount++; - }); - expectedLines.forEach(function(line) { - fi.emit('data', `${line}\r`); - fi.emit('data', '\n'); - }); - assert.strictEqual(callCount, expectedLines.length); - rli.close(); - } - - // Emit one line event when the delay between \r and \n is - // over the default crlfDelay but within the setting value. - { - const fi = new FakeInput(); - const delay = 125; - const crlfDelay = common.platformTimeout(1000); - const rli = new readline.Interface({ - input: fi, - output: fi, - terminal: terminal, - crlfDelay - }); - let callCount = 0; - rli.on('line', () => callCount++); - fi.emit('data', '\r'); - setTimeout(common.mustCall(() => { - fi.emit('data', '\n'); - assert.strictEqual(callCount, 1); - rli.close(); - }), delay); - } -}); From d0e4d4e0a1ffd665f24ecd2ae91445adbc2b011d Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Mon, 5 Feb 2018 11:17:07 -0500 Subject: [PATCH 015/193] deps: patch V8 to 6.4.388.42 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18578 Refs: https://github.com/v8/v8/compare/6.4.388.41...6.4.388.42 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/frames.cc | 9 ++++ deps/v8/src/frames.h | 1 + .../v8/src/profiler/sampling-heap-profiler.cc | 23 +++++++-- deps/v8/test/cctest/test-heap-profiler.cc | 48 ++++++++++++++++++- 5 files changed, 77 insertions(+), 6 deletions(-) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index dafa83627b224a..8c4bc0237702ed 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 4 #define V8_BUILD_NUMBER 388 -#define V8_PATCH_LEVEL 41 +#define V8_PATCH_LEVEL 42 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/frames.cc b/deps/v8/src/frames.cc index bd1abda4de8650..23713197f59d66 100644 --- a/deps/v8/src/frames.cc +++ b/deps/v8/src/frames.cc @@ -1013,6 +1013,15 @@ JSFunction* JavaScriptFrame::function() const { return JSFunction::cast(function_slot_object()); } +Object* JavaScriptFrame::unchecked_function() const { + // During deoptimization of an optimized function, we may have yet to + // materialize some closures on the stack. The arguments marker object + // marks this case. + DCHECK(function_slot_object()->IsJSFunction() || + isolate()->heap()->arguments_marker() == function_slot_object()); + return function_slot_object(); +} + Object* JavaScriptFrame::receiver() const { return GetParameter(-1); } Object* JavaScriptFrame::context() const { diff --git a/deps/v8/src/frames.h b/deps/v8/src/frames.h index a72832af06dbc0..e21d62764b30c3 100644 --- a/deps/v8/src/frames.h +++ b/deps/v8/src/frames.h @@ -684,6 +684,7 @@ class JavaScriptFrame : public StandardFrame { // Accessors. virtual JSFunction* function() const; + Object* unchecked_function() const; Object* receiver() const override; Object* context() const override; Script* script() const override; diff --git a/deps/v8/src/profiler/sampling-heap-profiler.cc b/deps/v8/src/profiler/sampling-heap-profiler.cc index 0aa0525633ca2c..51fe8866fa1c19 100644 --- a/deps/v8/src/profiler/sampling-heap-profiler.cc +++ b/deps/v8/src/profiler/sampling-heap-profiler.cc @@ -157,12 +157,21 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() { std::vector stack; JavaScriptFrameIterator it(isolate_); int frames_captured = 0; + bool found_arguments_marker_frames = false; while (!it.done() && frames_captured < stack_depth_) { JavaScriptFrame* frame = it.frame(); - SharedFunctionInfo* shared = frame->function()->shared(); - stack.push_back(shared); - - frames_captured++; + // If we are materializing objects during deoptimization, inlined + // closures may not yet be materialized, and this includes the + // closure on the stack. Skip over any such frames (they'll be + // in the top frames of the stack). The allocations made in this + // sensitive moment belong to the formerly optimized frame anyway. + if (frame->unchecked_function()->IsJSFunction()) { + SharedFunctionInfo* shared = frame->function()->shared(); + stack.push_back(shared); + frames_captured++; + } else { + found_arguments_marker_frames = true; + } it.Advance(); } @@ -209,6 +218,12 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() { } node = node->FindOrAddChildNode(name, script_id, shared->start_position()); } + + if (found_arguments_marker_frames) { + node = + node->FindOrAddChildNode("(deopt)", v8::UnboundScript::kNoScriptId, 0); + } + return node; } diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index ce015777e5d6e9..a0796ccd56c158 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -3083,7 +3083,7 @@ TEST(SamplingHeapProfilerPretenuredInlineAllocations) { // Suppress randomness to avoid flakiness in tests. v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true; - // Grow new space unitl maximum capacity reached. + // Grow new space until maximum capacity reached. while (!CcTest::heap()->new_space()->IsAtMaximumCapacity()) { CcTest::heap()->new_space()->Grow(); } @@ -3138,3 +3138,49 @@ TEST(SamplingHeapProfilerPretenuredInlineAllocations) { CHECK_GE(count, 8000); } + +TEST(SamplingHeapProfilerSampleDuringDeopt) { + i::FLAG_allow_natives_syntax = true; + + v8::HandleScope scope(v8::Isolate::GetCurrent()); + LocalContext env; + v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); + + // Suppress randomness to avoid flakiness in tests. + v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true; + + // Small sample interval to force each object to be sampled. + heap_profiler->StartSamplingHeapProfiler(i::kPointerSize); + + // Lazy deopt from runtime call from inlined callback function. + const char* source = + "var b = " + " [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];" + "(function f() {" + " var result = 0;" + " var lazyDeopt = function(deopt) {" + " var callback = function(v,i,o) {" + " result += i;" + " if (i == 13 && deopt) {" + " %DeoptimizeNow();" + " }" + " return v;" + " };" + " b.map(callback);" + " };" + " lazyDeopt();" + " lazyDeopt();" + " %OptimizeFunctionOnNextCall(lazyDeopt);" + " lazyDeopt();" + " lazyDeopt(true);" + " lazyDeopt();" + "})();"; + + CompileRun(source); + // Should not crash. + + std::unique_ptr profile( + heap_profiler->GetAllocationProfile()); + CHECK(profile); + heap_profiler->StopSamplingHeapProfiler(); +} From 1573e4563a0d3f6c08a1dd3ab3d161bece532db5 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Sun, 4 Feb 2018 11:48:21 -0500 Subject: [PATCH 016/193] src: move GetNow to Environment PR-URL: https://github.com/nodejs/node/pull/18562 Reviewed-By: Ben Noordhuis Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- src/env.cc | 15 +++++++++++++++ src/env.h | 2 ++ src/timer_wrap.cc | 16 ++-------------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/env.cc b/src/env.cc index 1b3323eb26c2e7..07e37498c898bb 100644 --- a/src/env.cc +++ b/src/env.cc @@ -11,13 +11,16 @@ namespace node { using v8::Context; using v8::FunctionTemplate; using v8::HandleScope; +using v8::Integer; using v8::Isolate; using v8::Local; using v8::Message; +using v8::Number; using v8::Private; using v8::StackFrame; using v8::StackTrace; using v8::String; +using v8::Value; IsolateData::IsolateData(Isolate* isolate, uv_loop_t* event_loop, @@ -362,6 +365,18 @@ void Environment::ToggleImmediateRef(bool ref) { } +Local Environment::GetNow() { + uv_update_time(event_loop()); + uint64_t now = uv_now(event_loop()); + CHECK_GE(now, timer_base()); + now -= timer_base(); + if (now <= 0xffffffff) + return Integer::New(isolate(), static_cast(now)); + else + return Number::New(isolate(), static_cast(now)); +} + + void CollectExceptionInfo(Environment* env, v8::Local obj, int errorno, diff --git a/src/env.h b/src/env.h index 4701b58e8a99c6..b621a54e3780cd 100644 --- a/src/env.h +++ b/src/env.h @@ -735,6 +735,8 @@ class Environment { static inline Environment* ForAsyncHooks(AsyncHooks* hooks); + v8::Local GetNow(); + private: inline void CreateImmediate(native_immediate_callback cb, void* data, diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc index f1b423d3669ed5..441974ae77b5db 100644 --- a/src/timer_wrap.cc +++ b/src/timer_wrap.cc @@ -37,7 +37,6 @@ using v8::FunctionTemplate; using v8::HandleScope; using v8::Integer; using v8::Local; -using v8::Number; using v8::Object; using v8::String; using v8::Value; @@ -142,7 +141,7 @@ class TimerWrap : public HandleWrap { Local ret; Local args[1]; do { - args[0] = GetNow(env); + args[0] = env->GetNow(); ret = wrap->MakeCallback(kOnTimeout, 1, args).ToLocalChecked(); } while (ret->IsUndefined() && !env->tick_info()->has_thrown() && @@ -153,18 +152,7 @@ class TimerWrap : public HandleWrap { static void Now(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - args.GetReturnValue().Set(GetNow(env)); - } - - static Local GetNow(Environment* env) { - uv_update_time(env->event_loop()); - uint64_t now = uv_now(env->event_loop()); - CHECK(now >= env->timer_base()); - now -= env->timer_base(); - if (now <= 0xfffffff) - return Integer::New(env->isolate(), static_cast(now)); - else - return Number::New(env->isolate(), static_cast(now)); + args.GetReturnValue().Set(env->GetNow()); } uv_timer_t handle_; From 92ba624fa1da61c4061aa554877bfa3c94c83324 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Sun, 4 Feb 2018 11:51:18 -0500 Subject: [PATCH 017/193] tls: provide now value from C++ Instead of separately calling into C++ from JS to retrieve the Timer.now() value, pass it in as an argument. PR-URL: https://github.com/nodejs/node/pull/18562 Reviewed-By: Ben Noordhuis Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- lib/_tls_wrap.js | 8 +++----- src/tls_wrap.cc | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 16d8b24c2979d4..fcd447bb5901fe 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -32,7 +32,6 @@ const common = require('_tls_common'); const { StreamWrap } = require('_stream_wrap'); const { Buffer } = require('buffer'); const debug = util.debuglog('tls'); -const { Timer } = process.binding('timer_wrap'); const tls_wrap = process.binding('tls_wrap'); const { TCP, constants: TCPConstants } = process.binding('tcp_wrap'); const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap'); @@ -49,14 +48,13 @@ const kSNICallback = Symbol('snicallback'); const noop = () => {}; -function onhandshakestart() { +function onhandshakestart(now) { debug('onhandshakestart'); - const owner = this.owner; - const now = Timer.now(); - assert(now >= this.lastHandshakeTime); + const owner = this.owner; + if ((now - this.lastHandshakeTime) >= tls.CLIENT_RENEG_WINDOW * 1000) { this.handshakes = 0; } diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 971dbb857f77f5..0cba1898fbaaad 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -230,7 +230,8 @@ void TLSWrap::SSLInfoCallback(const SSL* ssl_, int where, int ret) { if (where & SSL_CB_HANDSHAKE_START) { Local callback = object->Get(env->onhandshakestart_string()); if (callback->IsFunction()) { - c->MakeCallback(callback.As(), 0, nullptr); + Local argv[] = { env->GetNow() }; + c->MakeCallback(callback.As(), arraysize(argv), argv); } } From ffb385bff5f52b8729895eae51b28d417c736602 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 1 Feb 2018 10:33:27 -0500 Subject: [PATCH 018/193] test: refactor test-http-abort-before-end This test was added over six years ago, and the behavior seems to have changed since then. When the test was originally written, common.mustCall() did not exist. The only assertion in this test was not actually executing. Instead of an 'error' event being emitted as expected, an 'abort' event was emitted. PR-URL: https://github.com/nodejs/node/pull/18508 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/parallel/test-http-abort-before-end.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/test/parallel/test-http-abort-before-end.js b/test/parallel/test-http-abort-before-end.js index 37d1291b074127..5577f256ca2ec9 100644 --- a/test/parallel/test-http-abort-before-end.js +++ b/test/parallel/test-http-abort-before-end.js @@ -22,25 +22,22 @@ 'use strict'; const common = require('../common'); const http = require('http'); -const assert = require('assert'); const server = http.createServer(common.mustNotCall()); -server.listen(0, function() { +server.listen(0, common.mustCall(() => { const req = http.request({ method: 'GET', host: '127.0.0.1', - port: this.address().port + port: server.address().port }); - req.on('error', function(ex) { - // https://github.com/joyent/node/issues/1399#issuecomment-2597359 - // abort() should emit an Error, not the net.Socket object - assert(ex instanceof Error); - }); + req.on('abort', common.mustCall(() => { + server.close(); + })); + + req.on('error', common.mustNotCall()); req.abort(); req.end(); - - server.close(); -}); +})); From f783d61ad3c753eb297abe6a76e199a049ee9c66 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Wed, 7 Feb 2018 23:31:51 +0200 Subject: [PATCH 019/193] doc: fix link in https.md PR-URL: https://github.com/nodejs/node/pull/18630 Reviewed-By: Jon Moss Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater --- doc/api/https.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/https.md b/doc/api/https.md index c1daf77dbf4617..2cc7502012d63d 100644 --- a/doc/api/https.md +++ b/doc/api/https.md @@ -257,7 +257,7 @@ const req = https.request(options, (res) => { [`http.Server#setTimeout()`]: http.html#http_server_settimeout_msecs_callback [`http.Server#timeout`]: http.html#http_server_timeout [`http.Server`]: http.html#http_class_http_server -[`http.createServer()`]: http.html#httpcreateserveroptions-requestlistener +[`http.createServer()`]: http.html#http_http_createserver_options_requestlistener [`http.close()`]: http.html#http_server_close_callback [`http.get()`]: http.html#http_http_get_options_callback [`http.request()`]: http.html#http_http_request_options_callback From 259f62a8e8d4eac2f067b205abc9264b946d6738 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Wed, 7 Feb 2018 23:55:37 +0200 Subject: [PATCH 020/193] doc: fix MDN links to avoid redirections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit developer.mozilla.org/en/... -> developer.mozilla.org/en-US/... PR-URL: https://github.com/nodejs/node/pull/18631 Reviewed-By: Ruben Bridgewater Reviewed-By: Tobias Nießen --- doc/api/assert.md | 10 +++++----- doc/api/fs.md | 2 +- doc/api/intl.md | 14 +++++++------- doc/api/url.md | 2 +- doc/api/util.md | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index 0e5f444205635b..77b173067a3039 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -950,14 +950,14 @@ second argument. This might lead to difficult-to-spot errors. [`Error.captureStackTrace`]: errors.html#errors_error_capturestacktrace_targetobject_constructoropt [`Error`]: errors.html#errors_class_error -[`Map`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map +[`Map`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map [`Object.is()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is [`RegExp`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions -[`Set`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Set -[`Symbol`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Symbol +[`Set`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set +[`Symbol`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol [`TypeError`]: errors.html#errors_class_typeerror -[`WeakMap`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/WeakMap -[`WeakSet`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/WeakSet +[`WeakMap`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap +[`WeakSet`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet [`assert.deepEqual()`]: #assert_assert_deepequal_actual_expected_message [`assert.deepStrictEqual()`]: #assert_assert_deepstrictequal_actual_expected_message [`assert.notDeepStrictEqual()`]: #assert_assert_notdeepstrictequal_actual_expected_message diff --git a/doc/api/fs.md b/doc/api/fs.md index 064ecbd561c17d..3aa0f86378464e 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4470,7 +4470,7 @@ The following constants are meant for use with the [`fs.Stats`][] object's [Caveats]: #fs_caveats [Common System Errors]: errors.html#errors_common_system_errors [FS Constants]: #fs_fs_constants_1 -[MDN-Date]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date +[MDN-Date]: https://developer.mozilla.org/en-US/JavaScript/Reference/Global_Objects/Date [MDN-Number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type [MSDN-Rel-Path]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#fully_qualified_vs._relative_paths [Readable Streams]: stream.html#stream_class_stream_readable diff --git a/doc/api/intl.md b/doc/api/intl.md index 224c00a62fe888..83a9947dc21238 100644 --- a/doc/api/intl.md +++ b/doc/api/intl.md @@ -190,17 +190,17 @@ to be helpful: ["ICU Data"]: http://userguide.icu-project.org/icudata [`--icu-data-dir`]: cli.html#cli_icu_data_dir_file -[`Date.prototype.toLocaleString()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString -[`Intl`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl +[`Date.prototype.toLocaleString()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString +[`Intl`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl [`Intl.DateTimeFormat`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat [`NODE_ICU_DATA`]: cli.html#cli_node_icu_data_file -[`Number.prototype.toLocaleString()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString +[`Number.prototype.toLocaleString()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString [`require('buffer').transcode()`]: buffer.html#buffer_buffer_transcode_source_fromenc_toenc [`require('util').TextDecoder`]: util.html#util_class_util_textdecoder -[`String.prototype.localeCompare()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare -[`String.prototype.normalize()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/normalize -[`String.prototype.toLowerCase()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase -[`String.prototype.toUpperCase()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase +[`String.prototype.localeCompare()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare +[`String.prototype.normalize()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize +[`String.prototype.toLowerCase()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase +[`String.prototype.toUpperCase()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase [BUILDING.md]: https://github.com/nodejs/node/blob/master/BUILDING.md [BUILDING.md#full-icu]: https://github.com/nodejs/node/blob/master/BUILDING.md#build-with-full-icu-support-all-locales-supported-by-icu [ECMA-262]: https://tc39.github.io/ecma262/ diff --git a/doc/api/url.md b/doc/api/url.md index 3f75de06026306..42137b4ddd3637 100644 --- a/doc/api/url.md +++ b/doc/api/url.md @@ -1120,7 +1120,7 @@ console.log(myURL.origin); ``` [`Error`]: errors.html#errors_class_error -[`JSON.stringify()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify +[`JSON.stringify()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify [`Map`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map [`TypeError`]: errors.html#errors_class_typeerror [`URLSearchParams`]: #url_class_urlsearchparams diff --git a/doc/api/util.md b/doc/api/util.md index fdf6ed69bc95e0..00100c9d5e4054 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -1370,7 +1370,7 @@ Deprecated predecessor of `console.log`. [`Array.isArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray [`Buffer.isBuffer()`]: buffer.html#buffer_class_method_buffer_isbuffer_obj [`Error`]: errors.html#errors_class_error -[`Object.assign()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign +[`Object.assign()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign [`assert.deepStrictEqual()`]: assert.html#assert_assert_deepstrictequal_actual_expected_message [`console.error()`]: console.html#console_console_error_data_args [`console.log()`]: console.html#console_console_log_data_args @@ -1382,6 +1382,6 @@ Deprecated predecessor of `console.log`. [Internationalization]: intl.html [WHATWG Encoding Standard]: https://encoding.spec.whatwg.org/ [Common System Errors]: errors.html#errors_common_system_errors -[constructor]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor +[constructor]: https://developer.mozilla.org/en-US/JavaScript/Reference/Global_Objects/Object/constructor [list of deprecated APIS]: deprecations.html#deprecations_list_of_deprecated_apis [semantically incompatible]: https://github.com/nodejs/node/issues/4179 From 8ccd320549efdbab3608ddcbefca62bd69f8b879 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 20 Jan 2018 15:11:03 +0100 Subject: [PATCH 021/193] src: don't abort when package.json is a directory PR-URL: https://github.com/nodejs/node/pull/18270 Fixes: https://github.com/nodejs/node/issues/8307 Reviewed-By: Richard Lau Reviewed-By: Bradley Farias Reviewed-By: Anna Henningsen Reviewed-By: Guy Bedford Reviewed-By: Matteo Collina --- src/node_file.cc | 14 +++++++++----- .../packages/is-dir/package.json/.placeholder | 0 test/parallel/test-module-loading-error.js | 7 +++++++ 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 test/fixtures/packages/is-dir/package.json/.placeholder diff --git a/src/node_file.cc b/src/node_file.cc index 8f016ccf02695b..a77dc0a986765b 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -673,6 +673,12 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo& args) { return; } + std::shared_ptr defer_close(nullptr, [fd, loop] (...) { + uv_fs_t close_req; + CHECK_EQ(0, uv_fs_close(loop, &close_req, fd, nullptr)); + uv_fs_req_cleanup(&close_req); + }); + const size_t kBlockSize = 32 << 10; std::vector chars; int64_t offset = 0; @@ -689,14 +695,12 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo& args) { numchars = uv_fs_read(loop, &read_req, fd, &buf, 1, offset, nullptr); uv_fs_req_cleanup(&read_req); - CHECK_GE(numchars, 0); + if (numchars < 0) + return; + offset += numchars; } while (static_cast(numchars) == kBlockSize); - uv_fs_t close_req; - CHECK_EQ(0, uv_fs_close(loop, &close_req, fd, nullptr)); - uv_fs_req_cleanup(&close_req); - size_t start = 0; if (offset >= 3 && 0 == memcmp(&chars[0], "\xEF\xBB\xBF", 3)) { start = 3; // Skip UTF-8 BOM. diff --git a/test/fixtures/packages/is-dir/package.json/.placeholder b/test/fixtures/packages/is-dir/package.json/.placeholder new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/test/parallel/test-module-loading-error.js b/test/parallel/test-module-loading-error.js index 818a35eb582211..811d7d5ded8576 100644 --- a/test/parallel/test-module-loading-error.js +++ b/test/parallel/test-module-loading-error.js @@ -78,3 +78,10 @@ common.expectsError( code: 'ERR_INVALID_ARG_VALUE', message: 'The argument \'id\' must be a non-empty string. Received \'\'' }); + +common.expectsError( + () => { require('../fixtures/packages/is-dir'); }, + { + code: 'MODULE_NOT_FOUND', + message: 'Cannot find module \'../fixtures/packages/is-dir\'' + }); From b50571602afdbed72d3cb9e412c0e4ef5d1bae80 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 1 Feb 2018 22:39:51 +0800 Subject: [PATCH 022/193] build: do not suppress output in make doc-only This helps to show the cause of errors in the CI. PR-URL: https://github.com/nodejs/node/pull/18507 Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock Reviewed-By: Daniel Bevenius Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fbe19b961bd4a7..547890111bed73 100644 --- a/Makefile +++ b/Makefile @@ -619,7 +619,7 @@ doc-only: $(apidoc_dirs) $(apiassets) ## Builds the docs with the local or the if [ ! -d doc/api/assets ]; then \ $(MAKE) tools/doc/node_modules/js-yaml/package.json; \ fi; - @$(MAKE) -s $(apidocs_html) $(apidocs_json) + @$(MAKE) $(apidocs_html) $(apidocs_json) .PHONY: doc doc: $(NODE_EXE) doc-only From d8f73385e220d54de9f9c53da8d8693813e6d774 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 23 Jan 2018 10:23:46 +0800 Subject: [PATCH 023/193] fs: throw errors on invalid paths synchronously - Throw getPathFromURL() and nullCheck() errors synchronously instead of deferring them to the next tick, since we already throw validatePath() errors synchronously. - Merge nullCheck() into validatePath() - Never throws in `fs.exists()`, instead, invoke the callback with false, or emit a warning when the callback is not a function. This is to bring it inline with fs.existsSync(), which never throws. - Updates the comment of rethrow() - Throw ERR_INVALID_ARG_VALUE for null checks PR-URL: https://github.com/nodejs/node/pull/18308 Reviewed-By: Gireesh Punathil Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- lib/fs.js | 404 +++++++----------- lib/internal/url.js | 14 +- test/parallel/test-fs-copyfile.js | 20 - test/parallel/test-fs-exists.js | 25 +- test/parallel/test-fs-null-bytes.js | 28 +- test/parallel/test-fs-whatwg-url.js | 93 ++-- test/parallel/test-repl-persistent-history.js | 2 +- 7 files changed, 252 insertions(+), 334 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 04d3d0a5bd4357..56acc657912bbe 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -108,8 +108,9 @@ function copyObject(source) { return target; } +// TODO(joyeecheung): explore how the deprecation could be solved via linting +// rules. See https://github.com/nodejs/node/pull/12976 function rethrow() { - // TODO(thefourtheye) Throw error instead of warning in major version > 7 process.emitWarning( 'Calling an asynchronous function without callback is deprecated.', 'DeprecationWarning', 'DEP0013', rethrow @@ -207,6 +208,34 @@ function validateOffsetLengthWrite(offset, length, byteLength) { } } +// Check if the path contains null types if it is a string nor Uint8Array, +// otherwise return silently. +function nullCheck(path, propName, throwError = true) { + const pathIsString = typeof path === 'string'; + const pathIsUint8Array = isUint8Array(path); + + // We can only perform meaningful checks on strings and Uint8Arrays. + if (!pathIsString && !pathIsUint8Array) { + return; + } + + if (pathIsString && path.indexOf('\u0000') === -1) { + return; + } else if (pathIsUint8Array && path.indexOf(0) === -1) { + return; + } + + const err = new errors.Error( + 'ERR_INVALID_ARG_VALUE', propName, path, + 'must be a string or Uint8Array without null bytes'); + + if (throwError) { + Error.captureStackTrace(err, nullCheck); + throw err; + } + return err; +} + function validatePath(path, propName) { let err; @@ -217,6 +246,8 @@ function validatePath(path, propName) { if (typeof path !== 'string' && !isUint8Array(path)) { err = new errors.TypeError('ERR_INVALID_ARG_TYPE', propName, ['string', 'Buffer', 'URL']); + } else { + err = nullCheck(path, propName, false); } if (err !== undefined) { @@ -255,21 +286,6 @@ function makeStatsCallback(cb) { }; } -function nullCheck(path, callback) { - if (('' + path).indexOf('\u0000') !== -1) { - const er = new errors.Error('ERR_INVALID_ARG_TYPE', - 'path', - 'string without null bytes', - path); - - if (typeof callback !== 'function') - throw er; - process.nextTick(callback, er); - return false; - } - return true; -} - function isFd(path) { return (path >>> 0) === path; } @@ -361,16 +377,6 @@ Object.defineProperties(fs, { X_OK: { enumerable: true, value: constants.X_OK || 0 }, }); -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; @@ -379,14 +385,9 @@ fs.access = function(path, mode, callback) { throw new errors.TypeError('ERR_INVALID_CALLBACK'); } - if (handleError((path = getPathFromURL(path)), callback)) - return; - + path = getPathFromURL(path); validatePath(path); - if (!nullCheck(path, callback)) - return; - mode = mode | 0; var req = new FSReqWrap(); req.oncomplete = makeCallback(callback); @@ -394,9 +395,8 @@ fs.access = function(path, mode, callback) { }; fs.accessSync = function(path, mode) { - handleError((path = getPathFromURL(path))); + path = getPathFromURL(path); validatePath(path); - nullCheck(path); if (mode === undefined) mode = fs.F_OK; @@ -411,17 +411,30 @@ fs.accessSync = function(path, mode) { } }; +// fs.exists never throws even when the arguments are invalid - if there is +// a callback it would invoke it with false, otherwise it emits a warning +// (see the comments of rethrow()). +// This is to bring it inline with fs.existsSync, which never throws. +// TODO(joyeecheung): deprecate the never-throw-on-invalid-arguments behavior fs.exists = function(path, callback) { - if (handleError((path = getPathFromURL(path)), cb)) + if (typeof callback !== 'function') { + rethrow(); return; - validatePath(path); - if (!nullCheck(path, cb)) return; + } + + function suppressedCallback(err) { + callback(err ? false : true); + } + + try { + path = getPathFromURL(path); + validatePath(path); + } catch (err) { + return callback(false); + } var req = new FSReqWrap(); - req.oncomplete = cb; + req.oncomplete = suppressedCallback; binding.stat(pathModule.toNamespacedPath(path), req); - function cb(err) { - if (callback) callback(err ? false : true); - } }; Object.defineProperty(fs.exists, internalUtil.promisify.custom, { @@ -432,16 +445,16 @@ Object.defineProperty(fs.exists, internalUtil.promisify.custom, { } }); - +// fs.existsSync never throws, it only returns true or false. +// Since fs.existsSync never throws, users have established +// the expectation that passing invalid arguments to it, even like +// fs.existsSync(), would only get a false in return, so we cannot signal +// validation errors to users properly out of compatibility concerns. +// TODO(joyeecheung): deprecate the never-throw-on-invalid-arguments behavior fs.existsSync = function(path) { try { - handleError((path = getPathFromURL(path))); - try { - validatePath(path); - } catch (e) { - return false; - } - nullCheck(path); + path = getPathFromURL(path); + validatePath(path); const ctx = { path }; binding.stat(pathModule.toNamespacedPath(path), undefined, ctx); if (ctx.errno !== undefined) { @@ -456,12 +469,6 @@ fs.existsSync = function(path) { fs.readFile = function(path, options, callback) { callback = maybeCallback(callback || options); options = getOptions(options, { flag: 'r' }); - - if (handleError((path = getPathFromURL(path)), callback)) - return; - if (!nullCheck(path, callback)) - return; - var context = new ReadFileContext(callback, options.encoding); context.isUserFd = isFd(path); // file descriptor ownership var req = new FSReqWrap(); @@ -475,8 +482,8 @@ fs.readFile = function(path, options, callback) { return; } + path = getPathFromURL(path); validatePath(path); - binding.open(pathModule.toNamespacedPath(path), stringToFlags(options.flag || 'r'), 0o666, @@ -754,9 +761,7 @@ 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; + path = getPathFromURL(path); validatePath(path); validateUint32(mode, 'mode'); @@ -771,8 +776,7 @@ fs.open = function(path, flags, mode, callback_) { fs.openSync = function(path, flags, mode) { mode = modeNum(mode, 0o666); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); validateUint32(mode, 'mode'); @@ -901,15 +905,9 @@ 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; + oldPath = getPathFromURL(oldPath); validatePath(oldPath, 'oldPath'); + newPath = getPathFromURL(newPath); validatePath(newPath, 'newPath'); const req = new FSReqWrap(); req.oncomplete = callback; @@ -919,11 +917,9 @@ fs.rename = function(oldPath, newPath, callback) { }; fs.renameSync = function(oldPath, newPath) { - handleError((oldPath = getPathFromURL(oldPath))); - handleError((newPath = getPathFromURL(newPath))); - nullCheck(oldPath); - nullCheck(newPath); + oldPath = getPathFromURL(oldPath); validatePath(oldPath, 'oldPath'); + newPath = getPathFromURL(newPath); validatePath(newPath, 'newPath'); const ctx = { path: oldPath, dest: newPath }; binding.rename(pathModule.toNamespacedPath(oldPath), @@ -1005,9 +1001,7 @@ fs.ftruncateSync = function(fd, len = 0) { fs.rmdir = function(path, callback) { callback = maybeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; - if (!nullCheck(path, callback)) return; + path = getPathFromURL(path); validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; @@ -1015,8 +1009,7 @@ fs.rmdir = function(path, callback) { }; fs.rmdirSync = function(path) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return binding.rmdir(pathModule.toNamespacedPath(path)); }; @@ -1056,10 +1049,7 @@ 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; - + path = getPathFromURL(path); validatePath(path); mode = modeNum(mode, 0o777); validateUint32(mode, 'mode'); @@ -1070,8 +1060,7 @@ fs.mkdir = function(path, mode, callback) { }; fs.mkdirSync = function(path, mode) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); mode = modeNum(mode, 0o777); validateUint32(mode, 'mode'); @@ -1081,10 +1070,7 @@ 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; - + path = getPathFromURL(path); validatePath(path); const req = new FSReqWrap(); @@ -1094,8 +1080,7 @@ fs.readdir = function(path, options, callback) { fs.readdirSync = function(path, options) { options = getOptions(options, {}); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return binding.readdir(pathModule.toNamespacedPath(path), options.encoding); }; @@ -1109,9 +1094,7 @@ fs.fstat = function(fd, callback) { fs.lstat = function(path, callback) { callback = makeStatsCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; - if (!nullCheck(path, callback)) return; + path = getPathFromURL(path); validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; @@ -1120,9 +1103,7 @@ fs.lstat = function(path, callback) { fs.stat = function(path, callback) { callback = makeStatsCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; - if (!nullCheck(path, callback)) return; + path = getPathFromURL(path); validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; @@ -1140,8 +1121,7 @@ fs.fstatSync = function(fd) { }; fs.lstatSync = function(path) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); const ctx = { path }; binding.lstat(pathModule.toNamespacedPath(path), undefined, ctx); @@ -1152,8 +1132,7 @@ fs.lstatSync = function(path) { }; fs.statSync = function(path) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); const ctx = { path }; binding.stat(pathModule.toNamespacedPath(path), undefined, ctx); @@ -1166,9 +1145,7 @@ 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; + path = getPathFromURL(path); validatePath(path, 'oldPath'); const req = new FSReqWrap(); req.oncomplete = callback; @@ -1177,8 +1154,7 @@ fs.readlink = function(path, options, callback) { fs.readlinkSync = function(path, options) { options = getOptions(options, {}); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path, 'oldPath'); const ctx = { path }; const result = binding.readlink(pathModule.toNamespacedPath(path), @@ -1229,14 +1205,8 @@ 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; + target = getPathFromURL(target); + path = getPathFromURL(path); validatePath(target, 'target'); validatePath(path); @@ -1250,11 +1220,8 @@ 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); - + target = getPathFromURL(target); + path = getPathFromURL(path); validatePath(target, 'target'); validatePath(path); const flags = stringToSymlinkType(type); @@ -1276,15 +1243,8 @@ 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; - + existingPath = getPathFromURL(existingPath); + newPath = getPathFromURL(newPath); validatePath(existingPath, 'existingPath'); validatePath(newPath, 'newPath'); @@ -1297,10 +1257,8 @@ fs.link = function(existingPath, newPath, callback) { }; fs.linkSync = function(existingPath, newPath) { - handleError((existingPath = getPathFromURL(existingPath))); - handleError((newPath = getPathFromURL(newPath))); - nullCheck(existingPath); - nullCheck(newPath); + existingPath = getPathFromURL(existingPath); + newPath = getPathFromURL(newPath); validatePath(existingPath, 'existingPath'); validatePath(newPath, 'newPath'); @@ -1316,9 +1274,7 @@ 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; + path = getPathFromURL(path); validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; @@ -1326,8 +1282,7 @@ fs.unlink = function(path, callback) { }; fs.unlinkSync = function(path) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); const ctx = { path }; binding.unlink(pathModule.toNamespacedPath(path), undefined, ctx); @@ -1394,10 +1349,7 @@ if (constants.O_SYMLINK !== undefined) { fs.chmod = function(path, mode, callback) { callback = makeCallback(callback); - if (handleError((path = getPathFromURL(path)), callback)) - return; - if (!nullCheck(path, callback)) return; - + path = getPathFromURL(path); validatePath(path); mode = modeNum(mode); validateUint32(mode, 'mode'); @@ -1408,8 +1360,7 @@ fs.chmod = function(path, mode, callback) { }; fs.chmodSync = function(path, mode) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); mode = modeNum(mode); validateUint32(mode, 'mode'); @@ -1466,10 +1417,7 @@ 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; - + path = getPathFromURL(path); validatePath(path); validateUint32(uid, 'uid'); validateUint32(gid, 'gid'); @@ -1480,8 +1428,7 @@ fs.chown = function(path, uid, gid, callback) { }; fs.chownSync = function(path, uid, gid) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); validateUint32(uid, 'uid'); validateUint32(gid, 'gid'); @@ -1515,10 +1462,7 @@ 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; - + path = getPathFromURL(path); validatePath(path); const req = new FSReqWrap(); @@ -1530,8 +1474,7 @@ fs.utimes = function(path, atime, mtime, callback) { }; fs.utimesSync = function(path, atime, mtime) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); binding.utimes(pathModule.toNamespacedPath(path), toUnixTimestamp(atime), @@ -1685,12 +1628,17 @@ function FSWatcher() { } util.inherits(FSWatcher, EventEmitter); +// FIXME(joyeecheung): this method is not documented. +// At the moment if filename is undefined, we +// 1. Throw an Error from C++ land if it's the first time .start() is called +// 2. Return silently from C++ land if .start() has already been called +// on a valid filename and the wrap has been initialized FSWatcher.prototype.start = function(filename, persistent, recursive, encoding) { - handleError((filename = getPathFromURL(filename))); - nullCheck(filename); + filename = getPathFromURL(filename); + nullCheck(filename, 'filename'); var err = this._handle.start(pathModule.toNamespacedPath(filename), persistent, recursive, @@ -1708,9 +1656,6 @@ FSWatcher.prototype.close = function() { }; fs.watch = function(filename, options, listener) { - handleError((filename = getPathFromURL(filename))); - nullCheck(filename); - if (typeof options === 'function') { listener = options; } @@ -1777,9 +1722,14 @@ function StatWatcher() { util.inherits(StatWatcher, EventEmitter); +// FIXME(joyeecheung): this method is not documented. +// At the moment if filename is undefined, we +// 1. Throw an Error from C++ land if it's the first time .start() is called +// 2. Return silently from C++ land if .start() has already been called +// on a valid filename and the wrap has been initialized StatWatcher.prototype.start = function(filename, persistent, interval) { - handleError((filename = getPathFromURL(filename))); - nullCheck(filename); + filename = getPathFromURL(filename); + nullCheck(filename, 'filename'); this._handle.start(pathModule.toNamespacedPath(filename), persistent, interval); }; @@ -1793,8 +1743,8 @@ StatWatcher.prototype.stop = function() { const statWatchers = new Map(); fs.watchFile = function(filename, options, listener) { - handleError((filename = getPathFromURL(filename))); - nullCheck(filename); + filename = getPathFromURL(filename); + validatePath(filename); filename = pathModule.resolve(filename); var stat; @@ -1833,8 +1783,8 @@ fs.watchFile = function(filename, options, listener) { }; fs.unwatchFile = function(filename, listener) { - handleError((filename = getPathFromURL(filename))); - nullCheck(filename); + filename = getPathFromURL(filename); + validatePath(filename); filename = pathModule.resolve(filename); var stat = statWatchers.get(filename); @@ -1903,12 +1853,11 @@ fs.realpathSync = function realpathSync(p, options) { options = emptyObj; else options = getOptions(options, emptyObj); + p = getPathFromURL(p); if (typeof p !== 'string') { - handleError((p = getPathFromURL(p))); - if (typeof p !== 'string') - p += ''; + p += ''; } - nullCheck(p); + validatePath(p); p = pathModule.resolve(p); const cache = options[internalFS.realpathCacheKey]; @@ -2046,8 +1995,8 @@ fs.realpathSync = function realpathSync(p, options) { fs.realpathSync.native = function(path, options) { options = getOptions(options, {}); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); + validatePath(path); return binding.realpath(path, options.encoding); }; @@ -2058,14 +2007,11 @@ fs.realpath = function realpath(p, options, callback) { options = emptyObj; else options = getOptions(options, emptyObj); + p = getPathFromURL(p); if (typeof p !== 'string') { - if (handleError((p = getPathFromURL(p)), callback)) - return; - if (typeof p !== 'string') - p += ''; + p += ''; } - if (!nullCheck(p, callback)) - return; + validatePath(p); p = pathModule.resolve(p); const seenLinks = Object.create(null); @@ -2192,14 +2138,13 @@ fs.realpath = function realpath(p, options, callback) { fs.realpath.native = function(path, options, callback) { callback = maybeCallback(callback || options); options = getOptions(options, {}); - if (handleError((path = getPathFromURL(path)), callback)) return; - if (!nullCheck(path, callback)) return; + path = getPathFromURL(path); + validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; return binding.realpath(path, options.encoding, req); }; - fs.mkdtemp = function(prefix, options, callback) { callback = makeCallback(typeof options === 'function' ? options : callback); options = getOptions(options, {}); @@ -2209,26 +2154,22 @@ fs.mkdtemp = function(prefix, options, callback) { 'string', prefix); } - if (!nullCheck(prefix, callback)) { - return; - } - + nullCheck(prefix, 'prefix'); var req = new FSReqWrap(); req.oncomplete = callback; - binding.mkdtemp(`${prefix}XXXXXX`, options.encoding, req); }; fs.mkdtempSync = function(prefix, options) { + options = getOptions(options, {}); if (!prefix || typeof prefix !== 'string') { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'prefix', 'string', prefix); } - options = getOptions(options, {}); - nullCheck(prefix); + nullCheck(prefix, 'prefix'); return binding.mkdtemp(`${prefix}XXXXXX`, options.encoding); }; @@ -2248,21 +2189,7 @@ fs.copyFile = function(src, dest, flags, callback) { } src = getPathFromURL(src); - - if (handleError(src, callback)) - return; - - if (!nullCheck(src, callback)) - return; - dest = getPathFromURL(dest); - - if (handleError(dest, callback)) - return; - - if (!nullCheck(dest, callback)) - return; - validatePath(src, 'src'); validatePath(dest, 'dest'); @@ -2277,13 +2204,7 @@ fs.copyFile = function(src, dest, flags, callback) { fs.copyFileSync = function(src, dest, flags) { src = getPathFromURL(src); - handleError(src); - nullCheck(src); - dest = getPathFromURL(dest); - handleError(dest); - nullCheck(dest); - validatePath(src, 'src'); validatePath(dest, 'dest'); @@ -2320,7 +2241,8 @@ function ReadStream(path, options) { Readable.call(this, options); - handleError((this.path = getPathFromURL(path))); + // path will be ignored when fd is specified, so it can be falsy + this.path = getPathFromURL(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; @@ -2483,7 +2405,8 @@ function WriteStream(path, options) { Writable.call(this, options); - handleError((this.path = getPathFromURL(path))); + // path will be ignored when fd is specified, so it can be falsy + this.path = getPathFromURL(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; @@ -2783,8 +2706,7 @@ async function readFileHandle(filehandle, options) { // thrown synchronously const promises = { async access(path, mode = fs.F_OK) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); mode = mode | 0; @@ -2793,10 +2715,8 @@ const promises = { }, async copyFile(src, dest, flags) { - handleError((src = getPathFromURL(src))); - handleError((dest = getPathFromURL(dest))); - nullCheck(src); - nullCheck(dest); + src = getPathFromURL(src); + dest = getPathFromURL(dest); validatePath(src, 'src'); validatePath(dest, 'dest'); flags = flags | 0; @@ -2809,8 +2729,7 @@ const promises = { // promises.open() uses the fs.FileHandle class. async open(path, flags, mode) { mode = modeNum(mode, 0o666); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); validateUint32(mode, 'mode'); return new FileHandle( @@ -2877,10 +2796,8 @@ const promises = { }, async rename(oldPath, newPath) { - handleError((oldPath = getPathFromURL(oldPath))); - handleError((newPath = getPathFromURL(newPath))); - nullCheck(oldPath); - nullCheck(newPath); + oldPath = getPathFromURL(oldPath); + newPath = getPathFromURL(newPath); validatePath(oldPath, 'oldPath'); validatePath(newPath, 'newPath'); return binding.rename(pathModule.toNamespacedPath(oldPath), @@ -2900,8 +2817,7 @@ const promises = { }, async rmdir(path) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return binding.rmdir(pathModule.toNamespacedPath(path), kUsePromises); }, @@ -2918,8 +2834,7 @@ const promises = { async mkdir(path, mode) { mode = modeNum(mode, 0o777); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); validateUint32(mode, 'mode'); return binding.mkdir(pathModule.toNamespacedPath(path), mode, kUsePromises); @@ -2927,8 +2842,7 @@ const promises = { async readdir(path, options) { options = getOptions(options, {}); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return binding.readdir(pathModule.toNamespacedPath(path), options.encoding, kUsePromises); @@ -2936,8 +2850,7 @@ const promises = { async readlink(path, options) { options = getOptions(options, {}); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path, 'oldPath'); return binding.readlink(pathModule.toNamespacedPath(path), options.encoding, kUsePromises); @@ -2945,10 +2858,8 @@ const promises = { async symlink(target, path, type_) { const type = (typeof type_ === 'string' ? type_ : null); - handleError((target = getPathFromURL(target))); - handleError((path = getPathFromURL(path))); - nullCheck(target); - nullCheck(path); + target = getPathFromURL(target); + path = getPathFromURL(path); validatePath(target, 'target'); validatePath(path); return binding.symlink(preprocessSymlinkDestination(target, type, path), @@ -2963,26 +2874,22 @@ const promises = { }, async lstat(path) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return statsFromValues( await binding.lstat(pathModule.toNamespacedPath(path), kUsePromises)); }, async stat(path) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return statsFromValues( await binding.stat(pathModule.toNamespacedPath(path), kUsePromises)); }, async link(existingPath, newPath) { - handleError((existingPath = getPathFromURL(existingPath))); - handleError((newPath = getPathFromURL(newPath))); - nullCheck(existingPath); - nullCheck(newPath); + existingPath = getPathFromURL(existingPath); + newPath = getPathFromURL(newPath); validatePath(existingPath, 'existingPath'); validatePath(newPath, 'newPath'); return binding.link(pathModule.toNamespacedPath(existingPath), @@ -2991,8 +2898,7 @@ const promises = { }, async unlink(path) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return binding.unlink(pathModule.toNamespacedPath(path), kUsePromises); }, @@ -3007,8 +2913,7 @@ const promises = { }, async chmod(path, mode) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); mode = modeNum(mode); validateUint32(mode, 'mode'); @@ -3041,8 +2946,7 @@ const promises = { }, async chown(path, uid, gid) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); validateUint32(uid, 'uid'); validateUint32(gid, 'gid'); @@ -3051,8 +2955,7 @@ const promises = { }, async utimes(path, atime, mtime) { - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return binding.utimes(pathModule.toNamespacedPath(path), toUnixTimestamp(atime), @@ -3069,8 +2972,7 @@ const promises = { async realpath(path, options) { options = getOptions(options, {}); - handleError((path = getPathFromURL(path))); - nullCheck(path); + path = getPathFromURL(path); validatePath(path); return binding.realpath(path, options.encoding, kUsePromises); }, diff --git a/lib/internal/url.js b/lib/internal/url.js index b395e77b046f10..7055667718beed 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -1321,7 +1321,7 @@ function getPathFromURLWin32(url) { 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 errors.TypeError( + throw new errors.TypeError( 'ERR_INVALID_FILE_URL_PATH', 'must not include encoded \\ or / characters'); } @@ -1342,8 +1342,8 @@ function getPathFromURLWin32(url) { var sep = pathname[2]; if (letter < 97 || letter > 122 || // a..z A..Z (sep !== ':')) { - return new errors.TypeError('ERR_INVALID_FILE_URL_PATH', - 'must be absolute'); + throw new errors.TypeError('ERR_INVALID_FILE_URL_PATH', + 'must be absolute'); } return pathname.slice(1); } @@ -1351,15 +1351,15 @@ function getPathFromURLWin32(url) { function getPathFromURLPosix(url) { if (url.hostname !== '') { - return new errors.TypeError('ERR_INVALID_FILE_URL_HOST', platform); + throw new errors.TypeError('ERR_INVALID_FILE_URL_HOST', platform); } 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 errors.TypeError('ERR_INVALID_FILE_URL_PATH', - 'must not include encoded / characters'); + throw new errors.TypeError('ERR_INVALID_FILE_URL_PATH', + 'must not include encoded / characters'); } } } @@ -1372,7 +1372,7 @@ function getPathFromURL(path) { return path; } if (path.protocol !== 'file:') - return new errors.TypeError('ERR_INVALID_URL_SCHEME', 'file'); + throw new errors.TypeError('ERR_INVALID_URL_SCHEME', 'file'); return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path); } diff --git a/test/parallel/test-fs-copyfile.js b/test/parallel/test-fs-copyfile.js index a335065bf43cb7..8b910ba046ec48 100644 --- a/test/parallel/test-fs-copyfile.js +++ b/test/parallel/test-fs-copyfile.js @@ -102,26 +102,6 @@ common.expectsError(() => { ); }); -// Throws if the source path is an invalid path. -common.expectsError(() => { - fs.copyFileSync('\u0000', dest); -}, { - code: 'ERR_INVALID_ARG_TYPE', - type: Error, - message: 'The "path" argument must be of type string without null bytes.' + - ' Received type string' -}); - -// Throws if the destination path is an invalid path. -common.expectsError(() => { - fs.copyFileSync(src, '\u0000'); -}, { - code: 'ERR_INVALID_ARG_TYPE', - type: Error, - message: 'The "path" argument must be of type string without null bytes.' + - ' Received type string' -}); - // Errors if invalid flags are provided. assert.throws(() => { fs.copyFileSync(src, dest, -1); diff --git a/test/parallel/test-fs-exists.js b/test/parallel/test-fs-exists.js index a526373c6a876d..c52679764b4558 100644 --- a/test/parallel/test-fs-exists.js +++ b/test/parallel/test-fs-exists.js @@ -26,30 +26,33 @@ const fs = require('fs'); const { URL } = require('url'); const f = __filename; +// Only warnings are emitted when the callback is invalid +assert.doesNotThrow(() => fs.exists(f)); +assert.doesNotThrow(() => fs.exists()); +assert.doesNotThrow(() => fs.exists(f, {})); + fs.exists(f, common.mustCall(function(y) { assert.strictEqual(y, true); })); -assert.doesNotThrow(() => fs.exists(f)); - fs.exists(`${f}-NO`, common.mustCall(function(y) { assert.strictEqual(y, false); })); +// If the path is invalid, fs.exists will still invoke the callback with false +// instead of throwing errors fs.exists(new URL('https://foo'), common.mustCall(function(y) { assert.strictEqual(y, false); })); +fs.exists({}, common.mustCall(function(y) { + assert.strictEqual(y, false); +})); + assert(fs.existsSync(f)); assert(!fs.existsSync(`${f}-NO`)); -common.expectsError( - () => { fs.exists(() => {}); }, - { - code: 'ERR_INVALID_ARG_TYPE', - message: 'The "path" argument must be one of type string, Buffer, or URL', - type: TypeError - } -); - +// fs.existsSync() never throws assert(!fs.existsSync()); +assert(!fs.existsSync({})); +assert(!fs.existsSync(new URL('https://foo'))); diff --git a/test/parallel/test-fs-null-bytes.js b/test/parallel/test-fs-null-bytes.js index 44defc782ee139..6ffaef571ac8d6 100644 --- a/test/parallel/test-fs-null-bytes.js +++ b/test/parallel/test-fs-null-bytes.js @@ -27,16 +27,7 @@ const URL = require('url').URL; function check(async, sync) { const argsSync = Array.prototype.slice.call(arguments, 2); - const argsAsync = argsSync.concat((er) => { - common.expectsError( - () => { - throw er; - }, - { - code: 'ERR_INVALID_ARG_TYPE', - type: Error - }); - }); + const argsAsync = argsSync.concat(common.mustNotCall()); if (sync) { common.expectsError( @@ -44,13 +35,20 @@ function check(async, sync) { sync.apply(null, argsSync); }, { - code: 'ERR_INVALID_ARG_TYPE', + code: 'ERR_INVALID_ARG_VALUE', type: Error, }); } if (async) { - async.apply(null, argsAsync); + common.expectsError( + () => { + async.apply(null, argsAsync); + }, + { + code: 'ERR_INVALID_ARG_VALUE', + type: Error + }); } } @@ -59,6 +57,8 @@ check(fs.access, fs.accessSync, 'foo\u0000bar', fs.F_OK); check(fs.appendFile, fs.appendFileSync, 'foo\u0000bar', 'abc'); check(fs.chmod, fs.chmodSync, 'foo\u0000bar', '0644'); check(fs.chown, fs.chownSync, 'foo\u0000bar', 12, 34); +check(fs.copyFile, fs.copyFileSync, 'foo\u0000bar', 'abc'); +check(fs.copyFile, fs.copyFileSync, 'abc', 'foo\u0000bar'); check(fs.link, fs.linkSync, 'foo\u0000bar', 'foobar'); check(fs.link, fs.linkSync, 'foobar', 'foo\u0000bar'); check(fs.lstat, fs.lstatSync, 'foo\u0000bar'); @@ -90,6 +90,8 @@ check(fs.access, fs.accessSync, fileUrl, fs.F_OK); check(fs.appendFile, fs.appendFileSync, fileUrl, 'abc'); check(fs.chmod, fs.chmodSync, fileUrl, '0644'); check(fs.chown, fs.chownSync, fileUrl, 12, 34); +check(fs.copyFile, fs.copyFileSync, fileUrl, 'abc'); +check(fs.copyFile, fs.copyFileSync, 'abc', fileUrl); check(fs.link, fs.linkSync, fileUrl, 'foobar'); check(fs.link, fs.linkSync, 'foobar', fileUrl); check(fs.lstat, fs.lstatSync, fileUrl); @@ -118,6 +120,8 @@ check(fs.access, fs.accessSync, fileUrl2, fs.F_OK); check(fs.appendFile, fs.appendFileSync, fileUrl2, 'abc'); check(fs.chmod, fs.chmodSync, fileUrl2, '0644'); check(fs.chown, fs.chownSync, fileUrl2, 12, 34); +check(fs.copyFile, fs.copyFileSync, fileUrl2, 'abc'); +check(fs.copyFile, fs.copyFileSync, 'abc', fileUrl2); check(fs.link, fs.linkSync, fileUrl2, 'foobar'); check(fs.link, fs.linkSync, 'foobar', fileUrl2); check(fs.lstat, fs.lstatSync, fileUrl2); diff --git a/test/parallel/test-fs-whatwg-url.js b/test/parallel/test-fs-whatwg-url.js index 21eb82700aeb13..cfdfbe0dde01b8 100644 --- a/test/parallel/test-fs-whatwg-url.js +++ b/test/parallel/test-fs-whatwg-url.js @@ -29,46 +29,75 @@ fs.readFile(url, common.mustCall((err, data) => { // Check that using a non file:// URL reports an error const httpUrl = new URL('http://example.org'); -fs.readFile(httpUrl, common.expectsError({ - code: 'ERR_INVALID_URL_SCHEME', - type: TypeError, - message: 'The URL must be of scheme file' -})); -// pct-encoded characters in the path will be decoded and checked -fs.readFile(new URL('file:///c:/tmp/%00test'), common.mustCall((err) => { - common.expectsError( - () => { - throw err; - }, - { - code: 'ERR_INVALID_ARG_TYPE', - type: Error - }); -})); +common.expectsError( + () => { + fs.readFile(httpUrl, common.mustNotCall()); + }, + { + code: 'ERR_INVALID_URL_SCHEME', + type: TypeError, + message: 'The URL must be of scheme file' + }); +// pct-encoded characters in the path will be decoded and checked 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.expectsError({ - code: 'ERR_INVALID_FILE_URL_PATH', - type: TypeError, - message: 'File URL path must not include encoded \\ or / characters' - })); + common.expectsError( + () => { + fs.readFile(new URL(`file:///c:/tmp/${i}`), common.mustNotCall()); + }, + { + code: 'ERR_INVALID_FILE_URL_PATH', + type: TypeError, + message: 'File URL path must not include encoded \\ or / characters' + } + ); }); + common.expectsError( + () => { + fs.readFile(new URL('file:///c:/tmp/%00test'), common.mustNotCall()); + }, + { + code: 'ERR_INVALID_ARG_VALUE', + type: Error, + message: 'The argument \'path\' must be a string or Uint8Array without ' + + 'null bytes. Received \'c:/tmp/\\u0000test\'' + } + ); } else { // encoded forward slashes are not permitted on other platforms ['%2f', '%2F'].forEach((i) => { - fs.readFile(new URL(`file:///c:/tmp/${i}`), common.expectsError({ - code: 'ERR_INVALID_FILE_URL_PATH', - type: TypeError, - message: 'File URL path must not include encoded / characters' - })); + common.expectsError( + () => { + fs.readFile(new URL(`file:///c:/tmp/${i}`), common.mustNotCall()); + }, + { + code: 'ERR_INVALID_FILE_URL_PATH', + type: TypeError, + message: 'File URL path must not include encoded / characters' + }); }); - - fs.readFile(new URL('file://hostname/a/b/c'), common.expectsError({ - code: 'ERR_INVALID_FILE_URL_HOST', - type: TypeError, - message: `File URL host must be "localhost" or empty on ${os.platform()}` - })); + common.expectsError( + () => { + fs.readFile(new URL('file://hostname/a/b/c'), common.mustNotCall()); + }, + { + code: 'ERR_INVALID_FILE_URL_HOST', + type: TypeError, + message: `File URL host must be "localhost" or empty on ${os.platform()}` + } + ); + common.expectsError( + () => { + fs.readFile(new URL('file:///tmp/%00test'), common.mustNotCall()); + }, + { + code: 'ERR_INVALID_ARG_VALUE', + type: Error, + message: 'The argument \'path\' must be a string or Uint8Array without ' + + 'null bytes. Received \'/tmp/\\u0000test\'' + } + ); } diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js index 396203d949f4ba..43c868f8326f3f 100644 --- a/test/parallel/test-repl-persistent-history.js +++ b/test/parallel/test-repl-persistent-history.js @@ -57,7 +57,7 @@ const CLEAR = { ctrl: true, name: 'u' }; // File paths const historyFixturePath = fixtures.path('.node_repl_history'); const historyPath = path.join(tmpdir.path, '.fixture_copy_repl_history'); -const historyPathFail = path.join(tmpdir.path, '.node_repl\u0000_history'); +const historyPathFail = fixtures.path('nonexistent_folder', 'filename'); const oldHistoryPathObj = fixtures.path('old-repl-history-file-obj.json'); const oldHistoryPathFaulty = fixtures.path('old-repl-history-file-faulty.json'); const oldHistoryPath = fixtures.path('old-repl-history-file.json'); From 87b9bceacb6877e62148ea0f96f89a03f9b76a47 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Wed, 7 Feb 2018 10:52:04 +0100 Subject: [PATCH 024/193] stream: always defer readable in EOF when sync Fix a regression introduced by https://github.com/nodejs/node/pull/18515 that broke the dicer module tests. See: https://github.com/nodejs/node/pull/18515 PR-URL: https://github.com/nodejs/node/pull/18615 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum --- lib/_stream_readable.js | 6 +++--- .../test-stream-readable-object-multi-push-async.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index c7b356ed4421b0..46afe5f33dee91 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -488,9 +488,9 @@ function onEofChunk(stream, state) { } state.ended = true; - if (state.sync && state.length) { - // if we are sync and have data in the buffer, wait until next tick - // to emit the data. otherwise we risk emitting data in the flow() + if (state.sync) { + // if we are sync, wait until next tick to emit the data. + // Otherwise we risk emitting data in the flow() // the readable code triggers during a read() call emitReadable(stream); } else { diff --git a/test/parallel/test-stream-readable-object-multi-push-async.js b/test/parallel/test-stream-readable-object-multi-push-async.js index 4babfd12a27084..17c84c7310e053 100644 --- a/test/parallel/test-stream-readable-object-multi-push-async.js +++ b/test/parallel/test-stream-readable-object-multi-push-async.js @@ -160,7 +160,7 @@ const BATCH = 10; }); readable.on('end', common.mustCall(() => { - assert.strictEqual(nextTickPassed, false); + assert.strictEqual(nextTickPassed, true); })); } From e9b5b4fae3592f4d4992e0e4195fec8d65f57bf4 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Tue, 6 Feb 2018 21:29:26 +0100 Subject: [PATCH 025/193] stream: fix misleading error message The method to implement is `_write` not `_transform`. PR-URL: https://github.com/nodejs/node/pull/18604 Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig Reviewed-By: Matteo Collina --- lib/_stream_writable.js | 2 +- .../test-stream-writable-constructor-set-methods.js | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 396ccfb00bc68c..3796bbc04e115d 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -541,7 +541,7 @@ function clearBuffer(stream, state) { } Writable.prototype._write = function(chunk, encoding, cb) { - cb(new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_transform')); + cb(new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_write')); }; Writable.prototype._writev = null; diff --git a/test/parallel/test-stream-writable-constructor-set-methods.js b/test/parallel/test-stream-writable-constructor-set-methods.js index a12112d1ecc266..441e8ee75b337d 100644 --- a/test/parallel/test-stream-writable-constructor-set-methods.js +++ b/test/parallel/test-stream-writable-constructor-set-methods.js @@ -1,5 +1,5 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const Writable = require('stream').Writable; @@ -26,6 +26,16 @@ w2.write(Buffer.from('blerg')); w2.write(Buffer.from('blerg')); w2.end(); +const w3 = new Writable(); + +w3.on('error', common.expectsError({ + type: Error, + code: 'ERR_METHOD_NOT_IMPLEMENTED', + message: 'The _write method is not implemented' +})); + +w3.end(Buffer.from('blerg')); + process.on('exit', function() { assert.strictEqual(w._write, _write); assert(_writeCalled); From b1c6ecb2c674f43290ad772bc464568aa42ef5d0 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 3 Feb 2018 21:58:22 +0800 Subject: [PATCH 026/193] fs: fix misplaced errors in fs.symlinkSync The ctx.error is supposed to be handled in fs.readlinkSync, but was handled in fs.symlinkSync by mistake. Also fix the error number check in readlink to be consistent with SYNC_CALL. PR-URL: https://github.com/nodejs/node/pull/18548 Refs: https://github.com/nodejs/node/pull/18348 Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- lib/fs.js | 10 +++++----- src/node_file.cc | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 56acc657912bbe..da718f3f334413 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1161,6 +1161,11 @@ fs.readlinkSync = function(path, options) { options.encoding, undefined, ctx); if (ctx.errno !== undefined) { throw errors.uvException(ctx); + } else if (ctx.error) { + // TODO(joyeecheung): this is an encoding error usually caused by memory + // problems. We need to figure out proper error code(s) for this. + Error.captureStackTrace(ctx.error); + throw ctx.error; } return result; }; @@ -1232,11 +1237,6 @@ fs.symlinkSync = function(target, path, type) { if (ctx.errno !== undefined) { throw errors.uvException(ctx); - } else if (ctx.error) { - // TODO(joyeecheung): this is an encoding error usually caused by memory - // problems. We need to figure out proper error code(s) for this. - Error.captureStackTrace(ctx.error); - throw ctx.error; } }; diff --git a/src/node_file.cc b/src/node_file.cc index a77dc0a986765b..62dd5fe80cf8b2 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -886,7 +886,7 @@ static void ReadLink(const FunctionCallbackInfo& args) { fs_req_wrap req; int err = SyncCall(env, args[3], &req, "readlink", uv_fs_readlink, *path); - if (err) { + if (err < 0) { return; // syscall failed, no need to continue, error info is in ctx } const char* link_path = static_cast(req.req.ptr); From 1b05d7bc86d30d47d021cc37476fb0131490a74b Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 5 Feb 2018 09:47:01 -0500 Subject: [PATCH 027/193] timers: remove unused variable A recent commit removed the usage of the second argument of tryOnTimeout but left the definition in place. Remove it. PR-URL: https://github.com/nodejs/node/pull/18579 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater --- lib/timers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/timers.js b/lib/timers.js index b4c27fbeb9bf89..7b7fb4e04f52dc 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -260,7 +260,7 @@ TimerWrap.prototype[kOnTimeout] = function listOnTimeout(now) { continue; } - tryOnTimeout(timer, list); + tryOnTimeout(timer); } // If `L.peek(list)` returned nothing, the list was either empty or we have @@ -289,7 +289,7 @@ TimerWrap.prototype[kOnTimeout] = function listOnTimeout(now) { // An optimization so that the try/finally only de-optimizes (since at least v8 // 4.7) what is in this smaller function. -function tryOnTimeout(timer, list) { +function tryOnTimeout(timer) { timer._called = true; const timerAsyncId = (typeof timer[async_id_symbol] === 'number') ? timer[async_id_symbol] : null; From 568b6a5c9e9893fbb6ab811cfa76841fb3c80a0a Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 5 Feb 2018 09:50:18 -0500 Subject: [PATCH 028/193] timers: be more defensive with intervals It's possible for user-code to flip an existing timeout to be an interval during its execution, in which case the current code would crash due to start being undefined. Fix this by providing a default start value within rearm. PR-URL: https://github.com/nodejs/node/pull/18579 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater --- lib/timers.js | 3 +-- test/parallel/test-timers-timeout-to-interval.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-timers-timeout-to-interval.js diff --git a/lib/timers.js b/lib/timers.js index 7b7fb4e04f52dc..4d41b5dc8a4e3e 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -442,8 +442,7 @@ function ontimeout(timer, start) { rearm(timer, start); } - -function rearm(timer, start) { +function rearm(timer, start = TimerWrap.now()) { // // Do not re-arm unenroll'd or closed timers. if (timer._idleTimeout === -1) return; diff --git a/test/parallel/test-timers-timeout-to-interval.js b/test/parallel/test-timers-timeout-to-interval.js new file mode 100644 index 00000000000000..6952f2231a7e18 --- /dev/null +++ b/test/parallel/test-timers-timeout-to-interval.js @@ -0,0 +1,12 @@ +'use strict'; +const common = require('../common'); + +// This isn't officially supported but nonetheless is something that is +// currently possible and as such it shouldn't cause the process to crash + +const t = setTimeout(common.mustCall(() => { + if (t._repeat) { + clearInterval(t); + } + t._repeat = true; +}, 2), 1); From c11cb038a116f1097e4f800b6e4471dafce8a46f Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 5 Feb 2018 11:19:11 -0500 Subject: [PATCH 029/193] timers: async track unref timers When async hooks integration for Timers was introduced, it was not included in the code for unref'd or subsequently ref'd timers which means those timers only have Timerwrap hooks. PR-URL: https://github.com/nodejs/node/pull/18579 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater --- lib/timers.js | 6 +-- test/async-hooks/test-timers.setTimeout.js | 61 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 test/async-hooks/test-timers.setTimeout.js diff --git a/lib/timers.js b/lib/timers.js index 4d41b5dc8a4e3e..954c73f6026402 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -289,7 +289,7 @@ TimerWrap.prototype[kOnTimeout] = function listOnTimeout(now) { // An optimization so that the try/finally only de-optimizes (since at least v8 // 4.7) what is in this smaller function. -function tryOnTimeout(timer) { +function tryOnTimeout(timer, start) { timer._called = true; const timerAsyncId = (typeof timer[async_id_symbol] === 'number') ? timer[async_id_symbol] : null; @@ -297,7 +297,7 @@ function tryOnTimeout(timer) { if (timerAsyncId !== null) emitBefore(timerAsyncId, timer[trigger_async_id_symbol]); try { - ontimeout(timer); + ontimeout(timer, start); threw = false; } finally { if (timerAsyncId !== null) { @@ -520,7 +520,7 @@ function unrefdHandle(now) { try { // Don't attempt to call the callback if it is not a function. if (typeof this.owner._onTimeout === 'function') { - ontimeout(this.owner, now); + tryOnTimeout(this.owner, now); } } finally { // Make sure we clean up if the callback is no longer a function diff --git a/test/async-hooks/test-timers.setTimeout.js b/test/async-hooks/test-timers.setTimeout.js new file mode 100644 index 00000000000000..8f1d3222ddf662 --- /dev/null +++ b/test/async-hooks/test-timers.setTimeout.js @@ -0,0 +1,61 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const tick = require('./tick'); +const initHooks = require('./init-hooks'); +const { checkInvocations } = require('./hook-checks'); +const TIMEOUT = common.platformTimeout(100); + +const hooks = initHooks(); +hooks.enable(); + +// install first timeout +setTimeout(common.mustCall(ontimeout), TIMEOUT); +const as = hooks.activitiesOfTypes('Timeout'); +assert.strictEqual(as.length, 1); +const t1 = as[0]; +assert.strictEqual(t1.type, 'Timeout'); +assert.strictEqual(typeof t1.uid, 'number'); +assert.strictEqual(typeof t1.triggerAsyncId, 'number'); +checkInvocations(t1, { init: 1 }, 't1: when first timer installed'); + +let timer; +let t2; +function ontimeout() { + checkInvocations(t1, { init: 1, before: 1 }, 't1: when first timer fired'); + + setTimeout(onSecondTimeout, TIMEOUT).unref(); + const as = hooks.activitiesOfTypes('Timeout'); + t2 = as[1]; + assert.strictEqual(as.length, 2); + checkInvocations(t1, { init: 1, before: 1 }, + 't1: when second timer installed'); + checkInvocations(t2, { init: 1 }, + 't2: when second timer installed'); + + timer = setTimeout(common.mustNotCall(), 2 ** 31 - 1); +} + +function onSecondTimeout() { + const as = hooks.activitiesOfTypes('Timeout'); + assert.strictEqual(as.length, 3); + checkInvocations(t1, { init: 1, before: 1, after: 1 }, + 't1: when second timer fired'); + checkInvocations(t2, { init: 1, before: 1 }, + 't2: when second timer fired'); + clearTimeout(timer); + tick(2); +} + +process.on('exit', onexit); + +function onexit() { + hooks.disable(); + hooks.sanityCheck('Timeout'); + + checkInvocations(t1, { init: 1, before: 1, after: 1, destroy: 1 }, + 't1: when process exits'); + checkInvocations(t2, { init: 1, before: 1, after: 1, destroy: 1 }, + 't2: when process exits'); +} From 8204b0f9c6dbbdba1ca4120698a7f87ca1c9d91c Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 5 Feb 2018 13:09:08 -0500 Subject: [PATCH 030/193] timers: simplify clearTimeout & clearInterval Remove unnecessary condition from timeout & interval clearing. PR-URL: https://github.com/nodejs/node/pull/18579 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater --- lib/timers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/timers.js b/lib/timers.js index 954c73f6026402..39a22454ac906b 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -465,8 +465,8 @@ function rearm(timer, start = TimerWrap.now()) { const clearTimeout = exports.clearTimeout = function(timer) { - if (timer && (timer[kOnTimeout] || timer._onTimeout)) { - timer[kOnTimeout] = timer._onTimeout = null; + if (timer && timer._onTimeout) { + timer._onTimeout = null; if (timer instanceof Timeout) { timer.close(); // for after === 0 } else { From 86c659ba61dd923439335b240d81b38cab407acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=88=9A?= Date: Mon, 5 Feb 2018 16:33:42 +0800 Subject: [PATCH 031/193] stream: add a test case for the underlying cause. The original test case hides the underlying cause by using `PassThrough`. This change adds a test case for the underlying cause. This makes it clearer and easier to be understood. Refs: https://github.com/nodejs/node/pull/18372 PR-URL: https://github.com/nodejs/node/pull/18575 Reviewed-By: Matteo Collina --- ...st-stream-readable-no-unneeded-readable.js | 81 ++++++++++++------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/test/parallel/test-stream-readable-no-unneeded-readable.js b/test/parallel/test-stream-readable-no-unneeded-readable.js index bd3e06e5f7d55c..13ee2b498c4b96 100644 --- a/test/parallel/test-stream-readable-no-unneeded-readable.js +++ b/test/parallel/test-stream-readable-no-unneeded-readable.js @@ -2,38 +2,61 @@ const common = require('../common'); const { Readable, PassThrough } = require('stream'); -const source = new Readable({ - read: () => {} -}); +function test(r) { + const wrapper = new Readable({ + read: () => { + let data = r.read(); -source.push('foo'); -source.push('bar'); -source.push(null); - -const pt = source.pipe(new PassThrough()); - -const wrapper = new Readable({ - read: () => { - let data = pt.read(); - - if (data) { - wrapper.push(data); - return; - } - - pt.once('readable', function() { - data = pt.read(); if (data) { wrapper.push(data); + return; } - // else the end event should fire - }); - } -}); -pt.once('end', function() { - wrapper.push(null); -}); + r.once('readable', function() { + data = r.read(); + if (data) { + wrapper.push(data); + } + // else the end event should fire + }); + }, + }); + + r.once('end', function() { + wrapper.push(null); + }); + + wrapper.resume(); + wrapper.once('end', common.mustCall()); +} + +{ + const source = new Readable({ + read: () => {} + }); + source.push('foo'); + source.push('bar'); + source.push(null); + + const pt = source.pipe(new PassThrough()); + test(pt); +} + +{ + // This is the underlying cause of the above test case. + const pushChunks = ['foo', 'bar']; + const r = new Readable({ + read: () => { + const chunk = pushChunks.shift(); + if (chunk) { + // synchronous call + r.push(chunk); + } else { + // asynchronous call + process.nextTick(() => r.push(null)); + } + }, + }); -wrapper.resume(); -wrapper.once('end', common.mustCall()); + test(r); +} From 809af1fe8a0a096be4f0a3020f8e60ee1c827cbc Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 5 Feb 2018 19:49:50 +0100 Subject: [PATCH 032/193] benchmark: improve compare output The current output uses JSON.stringify to escape the config values. This switches to util.inspect to have a better readable output. PR-URL: https://github.com/nodejs/node/pull/18597 Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski Reviewed-By: Andreas Madsen Reviewed-By: Luigi Pinca --- benchmark/compare.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/benchmark/compare.js b/benchmark/compare.js index 6b51a70eb9a41b..e7866b60e36418 100644 --- a/benchmark/compare.js +++ b/benchmark/compare.js @@ -1,6 +1,7 @@ 'use strict'; -const fork = require('child_process').fork; +const { fork } = require('child_process'); +const { inspect } = require('util'); const path = require('path'); const CLI = require('./_cli.js'); const BenchmarkProgress = require('./_benchmark_progress.js'); @@ -76,7 +77,7 @@ if (showProgress) { // Construct configuration string, " A=a, B=b, ..." let conf = ''; for (const key of Object.keys(data.conf)) { - conf += ` ${key}=${JSON.stringify(data.conf[key])}`; + conf += ` ${key}=${inspect(data.conf[key])}`; } conf = conf.slice(1); // Escape quotes (") for correct csv formatting From d3569b623ccd593c9ef62fcaf0aba2711dc7fbfa Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 5 Feb 2018 21:55:16 -0800 Subject: [PATCH 033/193] doc: remove **Note:** tags Remove the various **Note:** prefixes throughout the docs. PR-URL: https://github.com/nodejs/node/pull/18592 Reviewed-By: Rich Trott Reviewed-By: Daniel Bevenius Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater Reviewed-By: Michael Dawson --- doc/api/addons.md | 2 +- doc/api/async_hooks.md | 12 ++-- doc/api/buffer.md | 18 ++--- doc/api/child_process.md | 68 +++++++++---------- doc/api/cli.md | 40 +++++------ doc/api/cluster.md | 6 +- doc/api/console.md | 9 ++- doc/api/crypto.md | 22 +++--- doc/api/deprecations.md | 26 +++---- doc/api/documentation.md | 6 +- doc/api/errors.md | 2 +- doc/api/fs.md | 107 ++++++++++++++--------------- doc/api/http.md | 16 ++--- doc/api/http2.md | 97 ++++++++++++-------------- doc/api/intl.md | 4 +- doc/api/modules.md | 20 +++--- doc/api/n-api.md | 46 ++++++------- doc/api/net.md | 21 +++--- doc/api/os.md | 18 ++--- doc/api/path.md | 6 +- doc/api/process.md | 127 +++++++++++++++++----------------- doc/api/punycode.md | 2 +- doc/api/querystring.md | 2 +- doc/api/readline.md | 22 +++--- doc/api/stream.md | 143 +++++++++++++++++++-------------------- doc/api/timers.md | 20 +++--- doc/api/tls.md | 84 +++++++++++------------ doc/api/url.md | 18 ++--- doc/api/util.md | 12 ++-- doc/api/v8.md | 4 +- doc/api/vm.md | 18 ++--- doc/api/zlib.md | 17 +++-- 32 files changed, 493 insertions(+), 522 deletions(-) diff --git a/doc/api/addons.md b/doc/api/addons.md index c6802530f6dc67..385f64d955266e 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -115,7 +115,7 @@ specifically to compile Node.js Addons. } ``` -*Note*: A version of the `node-gyp` utility is bundled and distributed with +A version of the `node-gyp` utility is bundled and distributed with Node.js as part of `npm`. This version is not made directly available for developers to use and is intended only to support the ability to use the `npm install` command to compile and install Addons. Developers who wish to diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index e0922fcd1134f5..d854d737dcec20 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -306,8 +306,8 @@ set to the `asyncId` of a parent Promise, if there is one, and `undefined` otherwise. For example, in the case of `b = a.then(handler)`, `a` is considered a parent Promise of `b`. -*Note*: In some cases the resource object is reused for performance reasons, -it is thus not safe to use it as a key in a `WeakMap` or add properties to it. +In some cases the resource object is reused for performance reasons, it is +thus not safe to use it as a key in a `WeakMap` or add properties to it. ###### Asynchronous context example @@ -377,9 +377,9 @@ destroy: 9 destroy: 5 ``` -*Note*: As illustrated in the example, `executionAsyncId()` and `execution` -each specify the value of the current execution context; which is delineated by -calls to `before` and `after`. +As illustrated in the example, `executionAsyncId()` and `execution` each specify +the value of the current execution context; which is delineated by calls to +`before` and `after`. Only using `execution` to graph resource allocation results in the following: @@ -599,7 +599,7 @@ own resources. The `init` hook will trigger when an `AsyncResource` is instantiated. -*Note*: `before` and `after` calls must be unwound in the same order that they +The `before` and `after` calls must be unwound in the same order that they are called. Otherwise, an unrecoverable exception will occur and the process will abort. diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 5e72e3bd969b4f..ec2c409ba59c6e 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -195,10 +195,10 @@ The character encodings currently supported by Node.js include: * `'hex'` - Encode each byte as two hexadecimal characters. -*Note*: Today's browsers follow the [WHATWG Encoding Standard][] which aliases -both 'latin1' and ISO-8859-1 to win-1252. This means that while doing something -like `http.get()`, if the returned charset is one of those listed in the WHATWG -specification it is possible that the server actually returned +Modern Web browsers follow the [WHATWG Encoding Standard][] which aliases +both `'latin1'` and `'ISO-8859-1'` to `'win-1252'`. This means that while doing +something like `http.get()`, if the returned charset is one of those listed in +the WHATWG specification it is possible that the server actually returned win-1252-encoded data, and using `'latin1'` encoding may incorrectly decode the characters. @@ -702,9 +702,9 @@ Returns the actual byte length of a string. This is not the same as [`String.prototype.length`] since that returns the number of *characters* in a string. -*Note*: For `'base64'` and `'hex'`, this function assumes valid input. For -strings that contain non-Base64/Hex-encoded data (e.g. whitespace), the return -value might be greater than the length of a `Buffer` created from the string. +For `'base64'` and `'hex'`, this function assumes valid input. For strings that +contain non-Base64/Hex-encoded data (e.g. whitespace), the return value might be +greater than the length of a `Buffer` created from the string. Example: @@ -1948,8 +1948,8 @@ offset and cropped by the `start` and `end` indices. Specifying `end` greater than [`buf.length`] will return the same result as that of `end` equal to [`buf.length`]. -*Note*: Modifying the new `Buffer` slice will modify the memory in the -original `Buffer` because the allocated memory of the two objects overlap. +Modifying the new `Buffer` slice will modify the memory in the original `Buffer` +because the allocated memory of the two objects overlap. Example: Create a `Buffer` with the ASCII alphabet, take a slice, and then modify one byte from the original `Buffer` diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 715eb9d269c38d..768eb91a83de77 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -170,9 +170,8 @@ exec('echo "The \\$HOME variable is $HOME"'); //The $HOME variable is escaped in the first instance, but not in the second ``` -*Note*: Never pass unsanitized user input to this function. Any input -containing shell metacharacters may be used to trigger arbitrary command -execution. +**Never pass unsanitized user input to this function. Any input containing shell +metacharacters may be used to trigger arbitrary command execution.** ```js const { exec } = require('child_process'); @@ -218,8 +217,8 @@ If `timeout` is greater than `0`, the parent will send the signal identified by the `killSignal` property (the default is `'SIGTERM'`) if the child runs longer than `timeout` milliseconds. -*Note*: Unlike the exec(3) POSIX system call, `child_process.exec()` does not -replace the existing process and uses a shell to execute the command. +Unlike the exec(3) POSIX system call, `child_process.exec()` does not replace +the existing process and uses a shell to execute the command. If this method is invoked as its [`util.promisify()`][]ed version, it returns a Promise for an object with `stdout` and `stderr` properties. In case of an @@ -316,9 +315,9 @@ async function getVersion() { getVersion(); ``` -*Note*: If the `shell` option is enabled, do not pass unsanitized user input -to this function. Any input containing shell metacharacters may be used to -trigger arbitrary command execution. +**If the `shell` option is enabled, do not pass unsanitized user input to this +function. Any input containing shell metacharacters may be used to trigger +arbitrary command execution.** ### child_process.fork(modulePath[, args][, options]) -*Note*: Usage of `util.inherits()` is discouraged. Please use the ES6 `class` -and `extends` keywords to get language level inheritance support. Also note +Usage of `util.inherits()` is discouraged. Please use the ES6 `class` and +`extends` keywords to get language level inheritance support. Also note that the two styles are [semantically incompatible][]. * `constructor` {Function} @@ -812,7 +810,7 @@ with ICU and using the full ICU data (see [Internationalization][]). | `'shift_jis'` | `'csshiftjis'`, `'ms932'`, `'ms_kanji'`, `'shift-jis'`, `'sjis'`, `'windows-31j'`, `'x-sjis'` | | `'euc-kr'` | `'cseuckr'`, `'csksc56011987'`, `'iso-ir-149'`, `'korean'`, `'ks_c_5601-1987'`, `'ks_c_5601-1989'`, `'ksc5601'`, `'ksc_5601'`, `'windows-949'` | -*Note*: The `'iso-8859-16'` encoding listed in the [WHATWG Encoding Standard][] +The `'iso-8859-16'` encoding listed in the [WHATWG Encoding Standard][] is not supported. ### new TextDecoder([encoding[, options]]) diff --git a/doc/api/v8.md b/doc/api/v8.md index c9d2512fddff2f..e4e3de78ced495 100644 --- a/doc/api/v8.md +++ b/doc/api/v8.md @@ -9,7 +9,7 @@ built into the Node.js binary. It can be accessed using: const v8 = require('v8'); ``` -*Note*: The APIs and implementation are subject to change at any time. +The APIs and implementation are subject to change at any time. ## v8.cachedDataVersionTag() - `algorithm` {string} - `key` {string | Buffer | TypedArray | DataView} - `iv` {string | Buffer | TypedArray | DataView} From 240f9a20b7ff7edad339fbfae7ff50633a300741 Mon Sep 17 00:00:00 2001 From: Mathias Buus Date: Tue, 6 Feb 2018 14:58:10 +0100 Subject: [PATCH 039/193] process: use linked reusable queue for ticks PR-URL: https://github.com/nodejs/node/pull/18617 Reviewed-By: Anna Henningsen Reviewed-By: Benjamin Gruenbaum Reviewed-By: Ruben Bridgewater Reviewed-By: Anatoli Papirovski Reviewed-By: Benedikt Meurer Reviewed-By: Matteo Collina Reviewed-By: Luigi Pinca Reviewed-By: Tiancheng "Timothy" Gu --- lib/internal/process/next_tick.js | 76 ++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js index e7fad84397c427..84a7402117c5c2 100644 --- a/lib/internal/process/next_tick.js +++ b/lib/internal/process/next_tick.js @@ -32,32 +32,55 @@ function setupNextTick() { const kHasScheduled = 0; const kHasPromiseRejections = 1; - const nextTickQueue = { - head: null, - tail: null, + // Queue size for each tick array. Must be a factor of two. + const kQueueSize = 2048; + const kQueueMask = kQueueSize - 1; + + class FixedQueue { + constructor() { + this.bottom = 0; + this.top = 0; + this.list = new Array(kQueueSize); + this.next = null; + } + push(data) { - const entry = { data, next: null }; - if (this.tail !== null) { - this.tail.next = entry; - } else { - this.head = entry; - tickInfo[kHasScheduled] = 1; - } - this.tail = entry; - }, + this.list[this.top] = data; + this.top = (this.top + 1) & kQueueMask; + } + shift() { - if (this.head === null) - return; - const ret = this.head.data; - if (this.head === this.tail) { - this.head = this.tail = null; + const next = this.list[this.bottom]; + if (next === undefined) return null; + this.list[this.bottom] = undefined; + this.bottom = (this.bottom + 1) & kQueueMask; + return next; + } + } + + var head = new FixedQueue(); + var tail = head; + + function push(data) { + if (head.bottom === head.top) { + if (head.list[head.top] !== undefined) + head = head.next = new FixedQueue(); + else + tickInfo[kHasScheduled] = 1; + } + head.push(data); + } + + function shift() { + const next = tail.shift(); + if (tail.top === tail.bottom) { + if (tail.next) + tail = tail.next; + else tickInfo[kHasScheduled] = 0; - } else { - this.head = this.head.next; - } - return ret; } - }; + return next; + } process.nextTick = nextTick; // Needs to be accessible from beyond this scope. @@ -69,7 +92,7 @@ function setupNextTick() { function _tickCallback() { let tock; do { - while (tock = nextTickQueue.shift()) { + while (tock = shift()) { const asyncId = tock[async_id_symbol]; emitBefore(asyncId, tock[trigger_async_id_symbol]); // emitDestroy() places the async_id_symbol into an asynchronous queue @@ -93,7 +116,7 @@ function setupNextTick() { emitAfter(asyncId); } runMicrotasks(); - } while (nextTickQueue.head !== null || emitPromiseRejectionWarnings()); + } while (head.top !== head.bottom || emitPromiseRejectionWarnings()); tickInfo[kHasPromiseRejections] = 0; } @@ -139,8 +162,7 @@ function setupNextTick() { args[i - 1] = arguments[i]; } - nextTickQueue.push(new TickObject(callback, args, - getDefaultTriggerAsyncId())); + push(new TickObject(callback, args, getDefaultTriggerAsyncId())); } // `internalNextTick()` will not enqueue any callback when the process is @@ -168,6 +190,6 @@ function setupNextTick() { if (triggerAsyncId === null) triggerAsyncId = getDefaultTriggerAsyncId(); - nextTickQueue.push(new TickObject(callback, args, triggerAsyncId)); + push(new TickObject(callback, args, triggerAsyncId)); } } From da97a47c4406d2c4bc867349dd039d6cc7cdff72 Mon Sep 17 00:00:00 2001 From: Mathias Buus Date: Tue, 6 Feb 2018 22:48:54 +0100 Subject: [PATCH 040/193] benchmark: add stream.pipe benchmarks PR-URL: https://github.com/nodejs/node/pull/18617 Reviewed-By: Anna Henningsen Reviewed-By: Benjamin Gruenbaum Reviewed-By: Ruben Bridgewater Reviewed-By: Anatoli Papirovski Reviewed-By: Benedikt Meurer Reviewed-By: Matteo Collina Reviewed-By: Luigi Pinca Reviewed-By: Tiancheng "Timothy" Gu --- benchmark/streams/pipe-object-mode.js | 24 ++++++++++++++++++++++++ benchmark/streams/pipe.js | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 benchmark/streams/pipe-object-mode.js create mode 100644 benchmark/streams/pipe.js diff --git a/benchmark/streams/pipe-object-mode.js b/benchmark/streams/pipe-object-mode.js new file mode 100644 index 00000000000000..d52b2238780ccb --- /dev/null +++ b/benchmark/streams/pipe-object-mode.js @@ -0,0 +1,24 @@ +'use strict'; + +const common = require('../common'); +const { Readable, Writable } = require('stream'); + +const bench = common.createBenchmark(main, { + n: [5e6] +}); + +function main({ n }) { + const b = {}; + const r = new Readable({ objectMode: true }); + const w = new Writable({ objectMode: true }); + + var i = 0; + + r._read = () => r.push(i++ === n ? null : b); + w._write = (data, enc, cb) => cb(); + + bench.start(); + + r.pipe(w); + w.on('finish', () => bench.end(n)); +} diff --git a/benchmark/streams/pipe.js b/benchmark/streams/pipe.js new file mode 100644 index 00000000000000..a7d67b7d6908c8 --- /dev/null +++ b/benchmark/streams/pipe.js @@ -0,0 +1,24 @@ +'use strict'; + +const common = require('../common'); +const { Readable, Writable } = require('stream'); + +const bench = common.createBenchmark(main, { + n: [5e6] +}); + +function main({ n }) { + const b = new Buffer(1024); + const r = new Readable(); + const w = new Writable(); + + var i = 0; + + r._read = () => r.push(i++ === n ? null : b); + w._write = (data, enc, cb) => cb(); + + bench.start(); + + r.pipe(w); + w.on('finish', () => bench.end(n)); +} From 14bc3e22f3b2c34616091183fd431f39af6c2b65 Mon Sep 17 00:00:00 2001 From: Andreas Madsen Date: Wed, 7 Feb 2018 20:05:45 +0100 Subject: [PATCH 041/193] domain: runtime deprecate MakeCallback Users of MakeCallback that adds the domain property to carry context, should start using the async_context variant of MakeCallback or the AsyncResource class. PR-URL: https://github.com/nodejs/node/pull/17417 Reviewed-By: Anatoli Papirovski Reviewed-By: Ruben Bridgewater --- doc/api/deprecations.md | 9 +++++ lib/domain.js | 16 +++++++++ .../make-callback-domain-warning/binding.cc | 31 ++++++++++++++++ .../make-callback-domain-warning/binding.gyp | 9 +++++ .../make-callback-domain-warning/test.js | 35 +++++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 test/addons/make-callback-domain-warning/binding.cc create mode 100644 test/addons/make-callback-domain-warning/binding.gyp create mode 100644 test/addons/make-callback-domain-warning/test.js diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index a5386f7bf015af..1f5809624afe95 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -871,6 +871,15 @@ Type: Runtime `timers.unenroll()` is deprecated. Please use the publicly documented [`clearTimeout()`][] or [`clearInterval()`][] instead. + +### DEP0097: MakeCallback with domain property + +Type: Runtime + +Users of `MakeCallback` that add the `domain` property to carry context, +should start using the `async_context` variant of `MakeCallback` or +`CallbackScope`, or the the high-level `AsyncResource` class. + [`--pending-deprecation`]: cli.html#cli_pending_deprecation [`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size [`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array diff --git a/lib/domain.js b/lib/domain.js index 08fbd207f171d3..be109c9ce056bd 100644 --- a/lib/domain.js +++ b/lib/domain.js @@ -94,13 +94,29 @@ process.setUncaughtExceptionCaptureCallback = function(fn) { throw err; }; + +let sendMakeCallbackDeprecation = false; +function emitMakeCallbackDeprecation() { + if (!sendMakeCallbackDeprecation) { + process.emitWarning( + 'Using a domain property in MakeCallback is deprecated. Use the ' + + 'async_context variant of MakeCallback or the AsyncResource class ' + + 'instead.', 'DeprecationWarning', 'DEP0097'); + sendMakeCallbackDeprecation = true; + } +} + function topLevelDomainCallback(cb, ...args) { const domain = this.domain; + if (exports.active && domain) + emitMakeCallbackDeprecation(); + if (domain) domain.enter(); const ret = Reflect.apply(cb, this, args); if (domain) domain.exit(); + return ret; } diff --git a/test/addons/make-callback-domain-warning/binding.cc b/test/addons/make-callback-domain-warning/binding.cc new file mode 100644 index 00000000000000..c42166c7455277 --- /dev/null +++ b/test/addons/make-callback-domain-warning/binding.cc @@ -0,0 +1,31 @@ +#include "node.h" +#include "v8.h" + +#include + +using v8::Function; +using v8::FunctionCallbackInfo; +using v8::Isolate; +using v8::Local; +using v8::Object; +using v8::Value; + +namespace { + +void MakeCallback(const FunctionCallbackInfo& args) { + assert(args[0]->IsObject()); + assert(args[1]->IsFunction()); + Isolate* isolate = args.GetIsolate(); + Local recv = args[0].As(); + Local method = args[1].As(); + + node::MakeCallback(isolate, recv, method, 0, nullptr); +} + +void Initialize(Local exports) { + NODE_SET_METHOD(exports, "makeCallback", MakeCallback); +} + +} // namespace + +NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) diff --git a/test/addons/make-callback-domain-warning/binding.gyp b/test/addons/make-callback-domain-warning/binding.gyp new file mode 100644 index 00000000000000..7ede63d94a0d77 --- /dev/null +++ b/test/addons/make-callback-domain-warning/binding.gyp @@ -0,0 +1,9 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'defines': [ 'V8_DEPRECATION_WARNINGS=1' ], + 'sources': [ 'binding.cc' ] + } + ] +} diff --git a/test/addons/make-callback-domain-warning/test.js b/test/addons/make-callback-domain-warning/test.js new file mode 100644 index 00000000000000..2ea3c3f3d14b2b --- /dev/null +++ b/test/addons/make-callback-domain-warning/test.js @@ -0,0 +1,35 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const domain = require('domain'); +const binding = require(`./build/${common.buildType}/binding`); + +function makeCallback(object, cb) { + binding.makeCallback(object, () => setImmediate(cb)); +} + +let latestWarning = null; +process.on('warning', function(warning) { + latestWarning = warning; +}); + +const d = domain.create(); + +// When domain is disabled, no warning will be emitted +makeCallback({ domain: d }, common.mustCall(function() { + assert.strictEqual(latestWarning, null); + + d.run(common.mustCall(function() { + // No warning will be emitted when no domain property is applied + makeCallback({}, common.mustCall(function() { + assert.strictEqual(latestWarning, null); + + // Warning is emitted when domain property is used and domain is enabled + makeCallback({ domain: d }, common.mustCall(function() { + assert.strictEqual(latestWarning.name, 'DeprecationWarning'); + assert.strictEqual(latestWarning.code, 'DEP0097'); + })); + })); + })); +})); From cccddc59e5058008464b359cb1fdceb98597a55a Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 6 Feb 2018 11:08:23 +0100 Subject: [PATCH 042/193] assert: fix throws trace The current stack trace thrown in case `assert.throws(fn, object)` is used did not filter the stack trace. This fixes it. PR-URL: https://github.com/nodejs/node/pull/18595 Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski --- lib/assert.js | 34 ++++++++++++---------------- test/message/assert_throws_stack.js | 6 +++++ test/message/assert_throws_stack.out | 14 ++++++++++++ 3 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 test/message/assert_throws_stack.js create mode 100644 test/message/assert_throws_stack.out diff --git a/lib/assert.js b/lib/assert.js index ce4cee28d103ab..67c658d9e68bb3 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -361,11 +361,17 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) { } }; -function createMsg(msg, key, actual, expected) { - if (msg) - return msg; - return `${key}: expected ${inspect(expected[key])}, ` + - `not ${inspect(actual[key])}`; +function compareExceptionKey(actual, expected, key, msg) { + if (!isDeepStrictEqual(actual[key], expected[key])) { + innerFail({ + actual: actual[key], + expected: expected[key], + message: msg || `${key}: expected ${inspect(expected[key])}, ` + + `not ${inspect(actual[key])}`, + operator: 'throws', + stackStartFn: assert.throws + }); + } } function expectedException(actual, expected, msg) { @@ -380,23 +386,13 @@ function expectedException(actual, expected, msg) { // The name and message could be non enumerable. Therefore test them // explicitly. if ('name' in expected) { - assert.strictEqual( - actual.name, - expected.name, - createMsg(msg, 'name', actual, expected)); + compareExceptionKey(actual, expected, 'name', msg); } if ('message' in expected) { - assert.strictEqual( - actual.message, - expected.message, - createMsg(msg, 'message', actual, expected)); + compareExceptionKey(actual, expected, 'message', msg); } - const keys = Object.keys(expected); - for (const key of keys) { - assert.deepStrictEqual( - actual[key], - expected[key], - createMsg(msg, key, actual, expected)); + for (const key of Object.keys(expected)) { + compareExceptionKey(actual, expected, key, msg); } return true; } diff --git a/test/message/assert_throws_stack.js b/test/message/assert_throws_stack.js new file mode 100644 index 00000000000000..36bc5734cae37f --- /dev/null +++ b/test/message/assert_throws_stack.js @@ -0,0 +1,6 @@ +'use strict'; + +require('../common'); +const assert = require('assert').strict; + +assert.throws(() => { throw new Error('foo'); }, { bar: true }); diff --git a/test/message/assert_throws_stack.out b/test/message/assert_throws_stack.out new file mode 100644 index 00000000000000..d34bdd24798190 --- /dev/null +++ b/test/message/assert_throws_stack.out @@ -0,0 +1,14 @@ +assert.js:* + throw new AssertionError(obj); + ^ + +AssertionError [ERR_ASSERTION]: bar: expected true, not undefined + at Object. (*assert_throws_stack.js:*:*) + at * + at * + at * + at * + at * + at * + at * + at * From 8e70811cc88d93f8fa931d69eef51af750d9c1ff Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Fri, 9 Feb 2018 04:08:30 +0200 Subject: [PATCH 043/193] doc: fix links in YAML metadata of assert.md PR-URL: https://github.com/nodejs/node/pull/18670 Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca --- doc/api/assert.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index 77b173067a3039..ca414e1c7cba47 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -208,7 +208,9 @@ changes: description: Enumerable symbol properties are now compared. - version: v9.0.0 pr-url: https://github.com/nodejs/node/pull/15036 - description: NaN is now compared using the [SameValueZero][] comparison. + description: NaN is now compared using the + [SameValueZero](https://tc39.github.io/ecma262/#sec-samevaluezero) + comparison. - version: v8.5.0 pr-url: https://github.com/nodejs/node/pull/15001 description: Error names and messages are now properly compared @@ -615,7 +617,9 @@ changes: description: -0 and +0 are not considered equal anymore. - version: v9.0.0 pr-url: https://github.com/nodejs/node/pull/15036 - description: NaN is now compared using the [SameValueZero][] comparison. + description: NaN is now compared using the + [SameValueZero](https://tc39.github.io/ecma262/#sec-samevaluezero) + comparison. - version: v9.0.0 pr-url: https://github.com/nodejs/node/pull/15001 description: Error names and messages are now properly compared From eacc88c3a6ef68a88a3a4b819b375c698c05fd9a Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 9 Feb 2018 09:00:00 -0600 Subject: [PATCH 044/193] doc: add devsnek to collaborators PR-URL: https://github.com/nodejs/node/pull/18679 Fixes: https://github.com/nodejs/node/issues/18544 Reviewed-By: Joyee Cheung Reviewed-By: Anatoli Papirovski Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Vse Mozhet Byt --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9767b71d0919c0..714fde2c143cf7 100644 --- a/README.md +++ b/README.md @@ -340,6 +340,8 @@ For more information about the governance of the Node.js project, see **Daniel Bevenius** <daniel.bevenius@gmail.com> * [DavidCai1993](https://github.com/DavidCai1993) - **David Cai** <davidcai1993@yahoo.com> (he/him) +* [devsnek](https://github.com/devsnek) - +**Gus Caplan** <me@gus.host> (he/him) * [edsadr](https://github.com/edsadr) - **Adrian Estrada** <edsadr@gmail.com> (he/him) * [eljefedelrodeodeljefe](https://github.com/eljefedelrodeodeljefe) - From dbd1d1d43f30df17a7bb216e0898afb398f6604f Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Fri, 9 Feb 2018 08:58:59 -0500 Subject: [PATCH 045/193] doc: fix arg definition in fs Currently doc building doesn't support ES-style default params in function definitions which causes an error. PR-URL: https://github.com/nodejs/node/pull/18678 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Evan Lucas Reviewed-By: Gus Caplan --- doc/api/fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 4c801fe358cd6a..a83d4031e7a856 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -3388,7 +3388,7 @@ added: REPLACEME Asynchronous fsync(2). The `Promise` is resolved with no arguments upon success. -#### filehandle.truncate(len = 0) +#### filehandle.truncate(len) From e5f101fe7beba032089ae3b3fb425c0ee15df258 Mon Sep 17 00:00:00 2001 From: Peter Marton Date: Thu, 5 Oct 2017 14:24:12 +0200 Subject: [PATCH 046/193] http2: add req and res options to server creation Add optional Http2ServerRequest and Http2ServerResponse options to createServer and createSecureServer. Allows custom req & res classes that extend the default ones to be used without overriding the prototype. PR-URL: https://github.com/nodejs/node/pull/15560 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Anatoli Papirovski Reviewed-By: Anna Henningsen --- doc/api/http2.md | 8 ++++ lib/internal/http2/compat.js | 8 ++-- lib/internal/http2/core.js | 10 ++++- .../test-http2-options-server-request.js | 40 +++++++++++++++++++ .../test-http2-options-server-response.js | 34 ++++++++++++++++ 5 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 test/parallel/test-http2-options-server-request.js create mode 100644 test/parallel/test-http2-options-server-response.js diff --git a/doc/api/http2.md b/doc/api/http2.md index 083a491cca3214..8b428484c00d96 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1707,6 +1707,14 @@ changes: * `Http1ServerResponse` {http.ServerResponse} Specifies the ServerResponse class to used for HTTP/1 fallback. Useful for extending the original `http.ServerResponse`. **Default:** `http.ServerResponse` + * `Http2ServerRequest` {http2.Http2ServerRequest} Specifies the + Http2ServerRequest class to use. + Useful for extending the original `Http2ServerRequest`. + **Default:** `Http2ServerRequest` + * `Http2ServerResponse` {htt2.Http2ServerResponse} Specifies the + Http2ServerResponse class to use. + Useful for extending the original `Http2ServerResponse`. + **Default:** `Http2ServerResponse` * `onRequestHandler` {Function} See [Compatibility API][] * Returns: {Http2Server} diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index b5dd81c80f4038..5e6c51377e94ba 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -661,11 +661,11 @@ class Http2ServerResponse extends Stream { } } -function onServerStream(stream, headers, flags, rawHeaders) { +function onServerStream(ServerRequest, ServerResponse, + stream, headers, flags, rawHeaders) { const server = this; - const request = new Http2ServerRequest(stream, headers, undefined, - rawHeaders); - const response = new Http2ServerResponse(stream); + const request = new ServerRequest(stream, headers, undefined, rawHeaders); + const response = new ServerResponse(stream); // Check for the CONNECT method const method = headers[HTTP2_HEADER_METHOD]; diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 5f811ca8af403a..307ca98db8da22 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -2498,6 +2498,10 @@ function initializeOptions(options) { options.Http1ServerResponse = options.Http1ServerResponse || http.ServerResponse; + options.Http2ServerRequest = options.Http2ServerRequest || + Http2ServerRequest; + options.Http2ServerResponse = options.Http2ServerResponse || + Http2ServerResponse; return options; } @@ -2563,7 +2567,11 @@ class Http2Server extends NETServer { function setupCompat(ev) { if (ev === 'request') { this.removeListener('newListener', setupCompat); - this.on('stream', onServerStream); + this.on('stream', onServerStream.bind( + this, + this[kOptions].Http2ServerRequest, + this[kOptions].Http2ServerResponse) + ); } } diff --git a/test/parallel/test-http2-options-server-request.js b/test/parallel/test-http2-options-server-request.js new file mode 100644 index 00000000000000..2143d379823d51 --- /dev/null +++ b/test/parallel/test-http2-options-server-request.js @@ -0,0 +1,40 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const h2 = require('http2'); + +class MyServerRequest extends h2.Http2ServerRequest { + getUserAgent() { + return this.headers['user-agent'] || 'unknown'; + } +} + +const server = h2.createServer({ + Http2ServerRequest: MyServerRequest +}, (req, res) => { + assert.strictEqual(req.getUserAgent(), 'node-test'); + + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end(); +}); +server.listen(0); + +server.on('listening', common.mustCall(() => { + + const client = h2.connect(`http://localhost:${server.address().port}`); + const req = client.request({ + ':path': '/', + 'User-Agent': 'node-test' + }); + + req.on('response', common.mustCall()); + + req.resume(); + req.on('end', common.mustCall(() => { + server.close(); + client.destroy(); + })); +})); diff --git a/test/parallel/test-http2-options-server-response.js b/test/parallel/test-http2-options-server-response.js new file mode 100644 index 00000000000000..6f1ae1881d22d8 --- /dev/null +++ b/test/parallel/test-http2-options-server-response.js @@ -0,0 +1,34 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const h2 = require('http2'); + +class MyServerResponse extends h2.Http2ServerResponse { + status(code) { + return this.writeHead(code, { 'Content-Type': 'text/plain' }); + } +} + +const server = h2.createServer({ + Http2ServerResponse: MyServerResponse +}, (req, res) => { + res.status(200); + res.end(); +}); +server.listen(0); + +server.on('listening', common.mustCall(() => { + + const client = h2.connect(`http://localhost:${server.address().port}`); + const req = client.request({ ':path': '/' }); + + req.on('response', common.mustCall()); + + req.resume(); + req.on('end', common.mustCall(() => { + server.close(); + client.destroy(); + })); +})); From 0f9efef05deb11dbbdf5adf96460839f5b332207 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 5 Feb 2018 14:29:32 -0500 Subject: [PATCH 047/193] timers: refactor timer list processing Instead of using kOnTimeout index to track a special list processing function, just pass in a function to C++ at startup that executes all handles and determines which function to call. This change improves the performance of unpooled timeouts by roughly 20%, as well as makes the unref/ref processing easier to follow. PR-URL: https://github.com/nodejs/node/pull/18582 Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina Reviewed-By: Vladimir de Turckheim Reviewed-By: Evan Lucas --- benchmark/timers/timers-timeout-unpooled.js | 36 +++++++++++++++++++ lib/timers.js | 38 ++++++++++----------- src/env.h | 1 + src/timer_wrap.cc | 17 ++++----- test/message/timeout_throw.out | 3 +- 5 files changed, 67 insertions(+), 28 deletions(-) create mode 100644 benchmark/timers/timers-timeout-unpooled.js diff --git a/benchmark/timers/timers-timeout-unpooled.js b/benchmark/timers/timers-timeout-unpooled.js new file mode 100644 index 00000000000000..19f0f6a4af4d0d --- /dev/null +++ b/benchmark/timers/timers-timeout-unpooled.js @@ -0,0 +1,36 @@ +'use strict'; +const common = require('../common.js'); + +// The following benchmark sets up n * 1e6 unpooled timeouts, +// then measures their execution on the next uv tick + +const bench = common.createBenchmark(main, { + n: [1e6], +}); + +function main({ n }) { + let count = 0; + + // Function tracking on the hidden class in V8 can cause misleading + // results in this benchmark if only a single function is used — + // alternate between two functions for a fairer benchmark + + function cb() { + count++; + if (count === n) + bench.end(n); + } + function cb2() { + count++; + if (count === n) + bench.end(n); + } + + for (var i = 0; i < n; i++) { + // unref().ref() will cause each of these timers to + // allocate their own handle + setTimeout(i % 2 ? cb : cb2, 1).unref().ref(); + } + + bench.start(); +} diff --git a/lib/timers.js b/lib/timers.js index 39a22454ac906b..8e914d751a93d8 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -24,7 +24,7 @@ const async_wrap = process.binding('async_wrap'); const { Timer: TimerWrap, - setImmediateCallback, + setupTimers, } = process.binding('timer_wrap'); const L = require('internal/linkedlist'); const timerInternals = require('internal/timers'); @@ -34,7 +34,6 @@ const assert = require('assert'); const util = require('util'); const errors = require('internal/errors'); const debug = util.debuglog('timer'); -const kOnTimeout = TimerWrap.kOnTimeout | 0; // Two arrays that share state between C++ and JS. const { async_hook_fields, async_id_fields } = async_wrap; const { @@ -57,7 +56,7 @@ const kRefCount = 1; const kHasOutstanding = 2; const [immediateInfo, toggleImmediateRef] = - setImmediateCallback(processImmediate); + setupTimers(processImmediate, processTimers); const kRefed = Symbol('refed'); @@ -221,10 +220,14 @@ function TimersList(msecs, unrefed) { timer.start(msecs); } -// adds listOnTimeout to the C++ object prototype, as -// V8 would not inline it otherwise. -TimerWrap.prototype[kOnTimeout] = function listOnTimeout(now) { - const list = this._list; +function processTimers(now) { + if (this.owner) + return unrefdHandle(this.owner, now); + return listOnTimeout(this, now); +} + +function listOnTimeout(handle, now) { + const list = handle._list; const msecs = list.msecs; debug('timeout callback %d', msecs); @@ -241,7 +244,7 @@ TimerWrap.prototype[kOnTimeout] = function listOnTimeout(now) { if (timeRemaining <= 0) { timeRemaining = 1; } - this.start(timeRemaining); + handle.start(timeRemaining); debug('%d list wait because diff is %d', msecs, diff); return true; } @@ -280,11 +283,11 @@ TimerWrap.prototype[kOnTimeout] = function listOnTimeout(now) { // Do not close the underlying handle if its ownership has changed // (e.g it was unrefed in its callback). - if (!this.owner) - this.close(); + if (!handle.owner) + handle.close(); return true; -}; +} // An optimization so that the try/finally only de-optimizes (since at least v8 @@ -516,18 +519,17 @@ exports.clearInterval = function(timer) { }; -function unrefdHandle(now) { +function unrefdHandle(timer, now) { try { // Don't attempt to call the callback if it is not a function. - if (typeof this.owner._onTimeout === 'function') { - tryOnTimeout(this.owner, now); + if (typeof timer._onTimeout === 'function') { + tryOnTimeout(timer, now); } } finally { // Make sure we clean up if the callback is no longer a function // even if the timer is an interval. - if (!this.owner._repeat || - typeof this.owner._onTimeout !== 'function') { - this.owner.close(); + if (!timer._repeat || typeof timer._onTimeout !== 'function') { + timer.close(); } } @@ -557,7 +559,6 @@ Timeout.prototype.unref = function() { this._handle = handle || new TimerWrap(); this._handle.owner = this; - this._handle[kOnTimeout] = unrefdHandle; this._handle.start(delay); this._handle.unref(); } @@ -581,7 +582,6 @@ Timeout.prototype.close = function() { } this._idleTimeout = -1; - this._handle[kOnTimeout] = null; this._handle.close(); } else { unenroll(this); diff --git a/src/env.h b/src/env.h index b621a54e3780cd..95548c0900ea13 100644 --- a/src/env.h +++ b/src/env.h @@ -308,6 +308,7 @@ class ModuleWrap; V(secure_context_constructor_template, v8::FunctionTemplate) \ V(tcp_constructor_template, v8::FunctionTemplate) \ V(tick_callback_function, v8::Function) \ + V(timers_callback_function, v8::Function) \ V(tls_wrap_constructor_function, v8::Function) \ V(tty_constructor_template, v8::FunctionTemplate) \ V(udp_constructor_function, v8::Function) \ diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc index 441974ae77b5db..02c0b8166981ab 100644 --- a/src/timer_wrap.cc +++ b/src/timer_wrap.cc @@ -41,8 +41,6 @@ using v8::Object; using v8::String; using v8::Value; -const uint32_t kOnTimeout = 0; - class TimerWrap : public HandleWrap { public: static void Initialize(Local target, @@ -53,8 +51,6 @@ class TimerWrap : public HandleWrap { Local timerString = FIXED_ONE_BYTE_STRING(env->isolate(), "Timer"); constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->SetClassName(timerString); - constructor->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "kOnTimeout"), - Integer::New(env->isolate(), kOnTimeout)); env->SetTemplateMethod(constructor, "now", Now); @@ -71,18 +67,22 @@ class TimerWrap : public HandleWrap { target->Set(timerString, constructor->GetFunction()); target->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "setImmediateCallback"), - env->NewFunctionTemplate(SetImmediateCallback) + FIXED_ONE_BYTE_STRING(env->isolate(), "setupTimers"), + env->NewFunctionTemplate(SetupTimers) ->GetFunction(env->context()).ToLocalChecked()).FromJust(); } size_t self_size() const override { return sizeof(*this); } private: - static void SetImmediateCallback(const FunctionCallbackInfo& args) { + static void SetupTimers(const FunctionCallbackInfo& args) { CHECK(args[0]->IsFunction()); + CHECK(args[1]->IsFunction()); auto env = Environment::GetCurrent(args); + env->set_immediate_callback_function(args[0].As()); + env->set_timers_callback_function(args[1].As()); + auto toggle_ref_cb = [] (const FunctionCallbackInfo& args) { Environment::GetCurrent(args)->ToggleImmediateRef(args[0]->IsTrue()); }; @@ -142,7 +142,8 @@ class TimerWrap : public HandleWrap { Local args[1]; do { args[0] = env->GetNow(); - ret = wrap->MakeCallback(kOnTimeout, 1, args).ToLocalChecked(); + ret = wrap->MakeCallback(env->timers_callback_function(), 1, args) + .ToLocalChecked(); } while (ret->IsUndefined() && !env->tick_info()->has_thrown() && wrap->object()->Get(env->context(), diff --git a/test/message/timeout_throw.out b/test/message/timeout_throw.out index 9ef4f63e3d8b97..382cf5a054942c 100644 --- a/test/message/timeout_throw.out +++ b/test/message/timeout_throw.out @@ -5,4 +5,5 @@ ReferenceError: undefined_reference_error_maker is not defined at Timeout._onTimeout (*test*message*timeout_throw.js:*:*) at ontimeout (timers.js:*:*) at tryOnTimeout (timers.js:*:*) - at Timer.listOnTimeout (timers.js:*:*) + at listOnTimeout (timers.js:*:*) + at Timer.processTimers (timers.js:*:*) From 523a1550a3d07ecc3d13e071cb0f1c732bae3bad Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Thu, 1 Feb 2018 15:25:41 -0800 Subject: [PATCH 048/193] async_hooks: deprecate unsafe emit{Before,After} The emit{Before,After} APIs in AsyncResource are problematic. * emit{Before,After} are named to suggest that the only thing they do is emit the before and after hooks. However, they in fact, mutate the current execution context. * They must be properly nested. Failure to do so by user code leads to catastrophic (unrecoverable) exceptions. It is very easy for the users to forget that they must be using a try/finally block around the code that must be surrounded by these operations. Even the example provided in the official docs makes this mistake. Failing to use a finally can lead to a catastrophic crash if the callback ends up throwing. This change provides a safer `runInAsyncScope` API as an alternative and deprecates emit{Before,After}. PR-URL: https://github.com/nodejs/node/pull/18513 Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Andreas Madsen --- doc/api/async_hooks.md | 64 +++++++++++++++---- doc/api/deprecations.md | 13 ++++ lib/async_hooks.js | 24 +++++++ ...dder.api.async-resource.runInAsyncScope.js | 11 ++++ ...c-hooks-recursive-stack-runInAsyncScope.js | 20 ++++++ ...fter-uncaught-exception-runInAsyncScope.js | 40 ++++++++++++ 6 files changed, 160 insertions(+), 12 deletions(-) create mode 100644 test/async-hooks/test-embedder.api.async-resource.runInAsyncScope.js create mode 100644 test/parallel/test-async-hooks-recursive-stack-runInAsyncScope.js create mode 100644 test/parallel/test-emit-after-uncaught-exception-runInAsyncScope.js diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index d854d737dcec20..4813169bfd8179 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -599,10 +599,6 @@ own resources. The `init` hook will trigger when an `AsyncResource` is instantiated. -The `before` and `after` calls must be unwound in the same order that they -are called. Otherwise, an unrecoverable exception will occur and the process -will abort. - The following is an overview of the `AsyncResource` API. ```js @@ -615,11 +611,13 @@ const asyncResource = new AsyncResource( type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false } ); -// Call AsyncHooks before callbacks. -asyncResource.emitBefore(); - -// Call AsyncHooks after callbacks. -asyncResource.emitAfter(); +// Run a function in the execution context of the resource. This will +// * establish the context of the resource +// * trigger the AsyncHooks before callbacks +// * call the provided function `fn` with the supplied arguments +// * trigger the AsyncHooks after callbacks +// * restore the original execution context +asyncResource.runInAsyncScope(fn, thisArg, ...args); // Call AsyncHooks destroy callbacks. asyncResource.emitDestroy(); @@ -629,6 +627,14 @@ asyncResource.asyncId(); // Return the trigger ID for the AsyncResource instance. asyncResource.triggerAsyncId(); + +// Call AsyncHooks before callbacks. +// Deprecated: Use asyncResource.runInAsyncScope instead. +asyncResource.emitBefore(); + +// Call AsyncHooks after callbacks. +// Deprecated: Use asyncResource.runInAsyncScope instead. +asyncResource.emitAfter(); ``` #### `AsyncResource(type[, options])` @@ -654,9 +660,7 @@ class DBQuery extends AsyncResource { getInfo(query, callback) { this.db.get(query, (err, data) => { - this.emitBefore(); - callback(err, data); - this.emitAfter(); + this.runInAsyncScope(callback, null, err, data); }); } @@ -667,7 +671,26 @@ class DBQuery extends AsyncResource { } ``` +#### `asyncResource.runInAsyncScope(fn[, thisArg, ...args])` + + +* `fn` {Function} The function to call in the execution context of this async + resource. +* `thisArg` {any} The receiver to be used for the function call. +* `...args` {any} Optional arguments to pass to the function. + +Call the provided function with the provided arguments in the execution context +of the async resource. This will establish the context, trigger the AsyncHooks +before callbacks, call the function, trigger the AsyncHooks after callbacks, and +then restore the original execution context. + #### `asyncResource.emitBefore()` + +> Stability: 0 - Deprecated: Use [`asyncResource.runInAsyncScope()`][] instead. * Returns: {undefined} @@ -675,7 +698,17 @@ Call all `before` callbacks to notify that a new asynchronous execution context is being entered. If nested calls to `emitBefore()` are made, the stack of `asyncId`s will be tracked and properly unwound. +`before` and `after` calls must be unwound in the same order that they +are called. Otherwise, an unrecoverable exception will occur and the process +will abort. For this reason, the `emitBefore` and `emitAfter` APIs are +considered deprecated. Please use `runInAsyncScope`, as it provides a much safer +alternative. + #### `asyncResource.emitAfter()` + +> Stability: 0 - Deprecated: Use [`asyncResource.runInAsyncScope()`][] instead. * Returns: {undefined} @@ -686,6 +719,12 @@ If the user's callback throws an exception, `emitAfter()` will automatically be called for all `asyncId`s on the stack if the error is handled by a domain or `'uncaughtException'` handler. +`before` and `after` calls must be unwound in the same order that they +are called. Otherwise, an unrecoverable exception will occur and the process +will abort. For this reason, the `emitBefore` and `emitAfter` APIs are +considered deprecated. Please use `runInAsyncScope`, as it provides a much safer +alternative. + #### `asyncResource.emitDestroy()` * Returns: {undefined} @@ -705,6 +744,7 @@ never be called. constructor. [`after` callback]: #async_hooks_after_asyncid +[`asyncResource.runInAsyncScope()`]: #async_hooks_asyncresource_runinasyncscope_fn_thisarg_args [`before` callback]: #async_hooks_before_asyncid [`destroy` callback]: #async_hooks_destroy_asyncid [`init` callback]: #async_hooks_init_asyncid_type_triggerasyncid_resource diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 1f5809624afe95..c18c9d58e0b521 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -880,6 +880,18 @@ Users of `MakeCallback` that add the `domain` property to carry context, should start using the `async_context` variant of `MakeCallback` or `CallbackScope`, or the the high-level `AsyncResource` class. + +### DEP0098: AsyncHooks Embedder AsyncResource.emit{Before,After} APIs + +Type: Runtime + +The embedded API provided by AsyncHooks exposes emit{Before,After} methods +which are very easy to use incorrectly which can lead to unrecoverable errors. + +Use [`asyncResource.runInAsyncScope()`][] API instead which provides a much +safer, and more convenient, alternative. See +https://github.com/nodejs/node/pull/18513 for more details. + [`--pending-deprecation`]: cli.html#cli_pending_deprecation [`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size [`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array @@ -892,6 +904,7 @@ should start using the `async_context` variant of `MakeCallback` or [`Server.getConnections()`]: net.html#net_server_getconnections_callback [`Server.listen({fd: })`]: net.html#net_server_listen_handle_backlog_callback [`SlowBuffer`]: buffer.html#buffer_class_slowbuffer +[`asyncResource.runInAsyncScope()`]: async_hooks.html#async_hooks_asyncresource_runinasyncscope_fn_thisarg_args [`child_process`]: child_process.html [`console.error()`]: console.html#console_console_error_data_args [`console.log()`]: console.html#console_console_log_data_args diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 55a16a569e908b..e7450f29acc05f 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -139,6 +139,17 @@ function triggerAsyncId() { const destroyedSymbol = Symbol('destroyed'); +let emitBeforeAfterWarning = true; +function showEmitBeforeAfterWarning() { + if (emitBeforeAfterWarning) { + process.emitWarning( + 'asyncResource.emitBefore and emitAfter are deprecated. Please use ' + + 'asyncResource.runInAsyncScope instead', + 'DeprecationWarning', 'DEP00XX'); + emitBeforeAfterWarning = false; + } +} + class AsyncResource { constructor(type, opts = {}) { if (typeof type !== 'string') @@ -174,15 +185,28 @@ class AsyncResource { } emitBefore() { + showEmitBeforeAfterWarning(); emitBefore(this[async_id_symbol], this[trigger_async_id_symbol]); return this; } emitAfter() { + showEmitBeforeAfterWarning(); emitAfter(this[async_id_symbol]); return this; } + runInAsyncScope(fn, thisArg, ...args) { + emitBefore(this[async_id_symbol], this[trigger_async_id_symbol]); + let ret; + try { + ret = Reflect.apply(fn, thisArg, args); + } finally { + emitAfter(this[async_id_symbol]); + } + return ret; + } + emitDestroy() { this[destroyedSymbol].destroyed = true; emitDestroy(this[async_id_symbol]); diff --git a/test/async-hooks/test-embedder.api.async-resource.runInAsyncScope.js b/test/async-hooks/test-embedder.api.async-resource.runInAsyncScope.js new file mode 100644 index 00000000000000..627880b4d98b07 --- /dev/null +++ b/test/async-hooks/test-embedder.api.async-resource.runInAsyncScope.js @@ -0,0 +1,11 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const async_hooks = require('async_hooks'); + +// Ensure that asyncResource.makeCallback returns the callback return value. +const a = new async_hooks.AsyncResource('foobar'); +const ret = a.runInAsyncScope(() => { + return 1729; +}); +assert.strictEqual(ret, 1729); diff --git a/test/parallel/test-async-hooks-recursive-stack-runInAsyncScope.js b/test/parallel/test-async-hooks-recursive-stack-runInAsyncScope.js new file mode 100644 index 00000000000000..bc4ac86e7f1ca1 --- /dev/null +++ b/test/parallel/test-async-hooks-recursive-stack-runInAsyncScope.js @@ -0,0 +1,20 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const async_hooks = require('async_hooks'); + +// This test verifies that the async ID stack can grow indefinitely. + +function recurse(n) { + const a = new async_hooks.AsyncResource('foobar'); + a.runInAsyncScope(() => { + assert.strictEqual(a.asyncId(), async_hooks.executionAsyncId()); + assert.strictEqual(a.triggerAsyncId(), async_hooks.triggerAsyncId()); + if (n >= 0) + recurse(n - 1); + assert.strictEqual(a.asyncId(), async_hooks.executionAsyncId()); + assert.strictEqual(a.triggerAsyncId(), async_hooks.triggerAsyncId()); + }); +} + +recurse(1000); diff --git a/test/parallel/test-emit-after-uncaught-exception-runInAsyncScope.js b/test/parallel/test-emit-after-uncaught-exception-runInAsyncScope.js new file mode 100644 index 00000000000000..5003972e9984aa --- /dev/null +++ b/test/parallel/test-emit-after-uncaught-exception-runInAsyncScope.js @@ -0,0 +1,40 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const async_hooks = require('async_hooks'); + +const id_obj = {}; +let collect = true; + +const hook = async_hooks.createHook({ + before(id) { if (collect) id_obj[id] = true; }, + after(id) { delete id_obj[id]; }, +}).enable(); + +process.once('uncaughtException', common.mustCall((er) => { + assert.strictEqual(er.message, 'bye'); + collect = false; +})); + +setImmediate(common.mustCall(() => { + process.nextTick(common.mustCall(() => { + assert.strictEqual(Object.keys(id_obj).length, 0); + hook.disable(); + })); + + // Create a stack of async ids that will need to be emitted in the case of + // an uncaught exception. + const ar1 = new async_hooks.AsyncResource('Mine'); + ar1.runInAsyncScope(() => { + const ar2 = new async_hooks.AsyncResource('Mine'); + ar2.runInAsyncScope(() => { + throw new Error('bye'); + }); + }); + + // TODO(trevnorris): This test shows that the after() hooks are always called + // correctly, but it doesn't solve where the emitDestroy() is missed because + // of the uncaught exception. Simple solution is to always call emitDestroy() + // before the emitAfter(), but how to codify this? +})); From edffad075e1dac0ebea7e70b05e4e49528fc59d2 Mon Sep 17 00:00:00 2001 From: JiaHerr Tee Date: Thu, 8 Feb 2018 18:38:38 -0500 Subject: [PATCH 049/193] test: add url type check in Module options The code coverage in `root/internal/vm/Module.js` lacked test coverage for the url options paramter. The test adds a check to ensure error is thrown. PR-URL: https://github.com/nodejs/node/pull/18664 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Gus Caplan Reviewed-By: Yuta Hiroto Reviewed-By: James M Snell --- test/parallel/test-vm-module-errors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-vm-module-errors.js b/test/parallel/test-vm-module-errors.js index 1c7e01cf30e51b..424d35e8aaf67a 100644 --- a/test/parallel/test-vm-module-errors.js +++ b/test/parallel/test-vm-module-errors.js @@ -44,7 +44,7 @@ async function checkArgType() { }); for (const invalidOptions of [ - 0, 1, null, true, 'str', () => {}, Symbol.iterator + 0, 1, null, true, 'str', () => {}, { url: 0 }, Symbol.iterator ]) { common.expectsError(() => { new Module('', invalidOptions); From 37c88f080de987d6adf9e2b4f7fe65cca1f5ecc2 Mon Sep 17 00:00:00 2001 From: Justin Lee Date: Fri, 9 Feb 2018 09:02:50 -0800 Subject: [PATCH 050/193] doc: fix links to Style Guide and CPP Style Guide PR-URL: https://github.com/nodejs/node/pull/18683 Reviewed-By: Vse Mozhet Byt Reviewed-By: Joyee Cheung Reviewed-By: Ruben Bridgewater Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig --- doc/guides/contributing/pull-requests.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/guides/contributing/pull-requests.md b/doc/guides/contributing/pull-requests.md index 5812c8c54645e2..3d7c548bbd3022 100644 --- a/doc/guides/contributing/pull-requests.md +++ b/doc/guides/contributing/pull-requests.md @@ -109,12 +109,12 @@ If you are modifying code, please be sure to run `make lint` from time to time to ensure that the changes follow the Node.js code style guide. Any documentation you write (including code comments and API documentation) -should follow the [Style Guide](doc/STYLE_GUIDE.md). Code samples included +should follow the [Style Guide](../../STYLE_GUIDE.md). Code samples included in the API docs will also be checked when running `make lint` (or `vcbuild.bat lint` on Windows). For contributing C++ code, you may want to look at the -[C++ Style Guide](CPP_STYLE_GUIDE.md). +[C++ Style Guide](../../../CPP_STYLE_GUIDE.md). ### Step 4: Commit From 9b4aa78f720284b5ad43850bbef90400ca010845 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 7 Feb 2018 00:07:08 +0100 Subject: [PATCH 051/193] test: refactor assert test This adds puctiations to the comments, uses a capital letters for the first character, removes a few obsolete comments and switches to assert.ok when suitable. It also moves all `assert.deepEqual()` and `assert.deepStrictEqual()` tests to the appropriate file. PR-URL: https://github.com/nodejs/node/pull/18610 Reviewed-By: Joyee Cheung --- test/parallel/test-assert-deep.js | 299 +++++++++++++++++++- test/parallel/test-assert.js | 436 ++++-------------------------- 2 files changed, 349 insertions(+), 386 deletions(-) diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js index 8f08d571383a77..1fad9f40517bd5 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -1,7 +1,9 @@ 'use strict'; + const common = require('../common'); const assert = require('assert'); const util = require('util'); +const { AssertionError } = assert; // Template tag function turning an error message into a RegExp // for assert.throws() @@ -25,7 +27,7 @@ function re(literals, ...values) { // That is why we discourage using deepEqual in our own tests. // Turn off no-restricted-properties because we are testing deepEqual! -/* eslint-disable no-restricted-properties */ +/* eslint-disable no-restricted-properties, prefer-common-expectserror */ const arr = new Uint8Array([120, 121, 122, 10]); const buf = Buffer.from(arr); @@ -545,4 +547,299 @@ assertDeepAndStrictEqual(-0, -0); assertDeepAndStrictEqual(a, b); } +assert.doesNotThrow( + () => assert.deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), + 'deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))'); + +assert.throws(() => assert.deepEqual(new Date(), new Date(2000, 3, 14)), + AssertionError, + 'deepEqual(new Date(), new Date(2000, 3, 14))'); + +assert.throws( + () => assert.notDeepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), + AssertionError, + 'notDeepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' +); + +assert.doesNotThrow( + () => assert.notDeepEqual(new Date(), new Date(2000, 3, 14)), + 'notDeepEqual(new Date(), new Date(2000, 3, 14))' +); + +assert.doesNotThrow(() => assert.deepEqual(/a/, /a/)); +assert.doesNotThrow(() => assert.deepEqual(/a/g, /a/g)); +assert.doesNotThrow(() => assert.deepEqual(/a/i, /a/i)); +assert.doesNotThrow(() => assert.deepEqual(/a/m, /a/m)); +assert.doesNotThrow(() => assert.deepEqual(/a/igm, /a/igm)); +assert.throws(() => assert.deepEqual(/ab/, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/ab/ deepEqual /a/' + }); +assert.throws(() => assert.deepEqual(/a/g, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/g deepEqual /a/' + }); +assert.throws(() => assert.deepEqual(/a/i, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/i deepEqual /a/' + }); +assert.throws(() => assert.deepEqual(/a/m, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/m deepEqual /a/' + }); +assert.throws(() => assert.deepEqual(/a/igm, /a/im), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/gim deepEqual /a/im' + }); + +{ + const re1 = /a/g; + re1.lastIndex = 3; + assert.doesNotThrow(() => assert.deepEqual(re1, /a/g)); +} + +assert.doesNotThrow(() => assert.deepEqual(4, '4'), 'deepEqual(4, \'4\')'); +assert.doesNotThrow(() => assert.deepEqual(true, 1), 'deepEqual(true, 1)'); +assert.throws(() => assert.deepEqual(4, '5'), + AssertionError, + 'deepEqual( 4, \'5\')'); + +// Having the same number of owned properties && the same set of keys. +assert.doesNotThrow(() => assert.deepEqual({ a: 4 }, { a: 4 })); +assert.doesNotThrow(() => assert.deepEqual({ a: 4, b: '2' }, { a: 4, b: '2' })); +assert.doesNotThrow(() => assert.deepEqual([4], ['4'])); +assert.throws( + () => assert.deepEqual({ a: 4 }, { a: 4, b: true }), AssertionError); +assert.doesNotThrow(() => assert.deepEqual(['a'], { 0: 'a' })); +assert.doesNotThrow(() => assert.deepEqual({ a: 4, b: '1' }, { b: '1', a: 4 })); +const a1 = [1, 2, 3]; +const a2 = [1, 2, 3]; +a1.a = 'test'; +a1.b = true; +a2.b = true; +a2.a = 'test'; +assert.throws(() => assert.deepEqual(Object.keys(a1), Object.keys(a2)), + AssertionError); +assert.doesNotThrow(() => assert.deepEqual(a1, a2)); + +// Having an identical prototype property. +const nbRoot = { + toString() { return `${this.first} ${this.last}`; } +}; + +function nameBuilder(first, last) { + this.first = first; + this.last = last; + return this; +} +nameBuilder.prototype = nbRoot; + +function nameBuilder2(first, last) { + this.first = first; + this.last = last; + return this; +} +nameBuilder2.prototype = nbRoot; + +const nb1 = new nameBuilder('Ryan', 'Dahl'); +let nb2 = new nameBuilder2('Ryan', 'Dahl'); + +assert.doesNotThrow(() => assert.deepEqual(nb1, nb2)); + +nameBuilder2.prototype = Object; +nb2 = new nameBuilder2('Ryan', 'Dahl'); +assert.doesNotThrow(() => assert.deepEqual(nb1, nb2)); + +// Primitives and object. +assert.throws(() => assert.deepEqual(null, {}), AssertionError); +assert.throws(() => assert.deepEqual(undefined, {}), AssertionError); +assert.throws(() => assert.deepEqual('a', ['a']), AssertionError); +assert.throws(() => assert.deepEqual('a', { 0: 'a' }), AssertionError); +assert.throws(() => assert.deepEqual(1, {}), AssertionError); +assert.throws(() => assert.deepEqual(true, {}), AssertionError); +assert.throws(() => assert.deepEqual(Symbol(), {}), AssertionError); + +// Primitive wrappers and object. +assert.doesNotThrow(() => assert.deepEqual(new String('a'), ['a']), + AssertionError); +assert.doesNotThrow(() => assert.deepEqual(new String('a'), { 0: 'a' }), + AssertionError); +assert.doesNotThrow(() => assert.deepEqual(new Number(1), {}), AssertionError); +assert.doesNotThrow(() => assert.deepEqual(new Boolean(true), {}), + AssertionError); + +// Same number of keys but different key names. +assert.throws(() => assert.deepEqual({ a: 1 }, { b: 1 }), AssertionError); + +assert.doesNotThrow( + () => assert.deepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), + 'deepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' +); + +assert.throws( + () => assert.deepStrictEqual(new Date(), new Date(2000, 3, 14)), + AssertionError, + 'deepStrictEqual(new Date(), new Date(2000, 3, 14))' +); + +assert.throws( + () => assert.notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), + AssertionError, + 'notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' +); + +assert.doesNotThrow( + () => assert.notDeepStrictEqual(new Date(), new Date(2000, 3, 14)), + 'notDeepStrictEqual(new Date(), new Date(2000, 3, 14))' +); + +assert.doesNotThrow(() => assert.deepStrictEqual(/a/, /a/)); +assert.doesNotThrow(() => assert.deepStrictEqual(/a/g, /a/g)); +assert.doesNotThrow(() => assert.deepStrictEqual(/a/i, /a/i)); +assert.doesNotThrow(() => assert.deepStrictEqual(/a/m, /a/m)); +assert.doesNotThrow(() => assert.deepStrictEqual(/a/igm, /a/igm)); +assert.throws( + () => assert.deepStrictEqual(/ab/, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/ab/ deepStrictEqual /a/' + }); +assert.throws( + () => assert.deepStrictEqual(/a/g, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/g deepStrictEqual /a/' + }); +assert.throws( + () => assert.deepStrictEqual(/a/i, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/i deepStrictEqual /a/' + }); +assert.throws( + () => assert.deepStrictEqual(/a/m, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/m deepStrictEqual /a/' + }); +assert.throws( + () => assert.deepStrictEqual(/a/igm, /a/im), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/gim deepStrictEqual /a/im' + }); + +{ + const re1 = /a/; + re1.lastIndex = 3; + assert.doesNotThrow(() => assert.deepStrictEqual(re1, /a/)); +} + +assert.throws(() => assert.deepStrictEqual(4, '4'), + AssertionError, + 'deepStrictEqual(4, \'4\')'); + +assert.throws(() => assert.deepStrictEqual(true, 1), + AssertionError, + 'deepStrictEqual(true, 1)'); + +assert.throws(() => assert.deepStrictEqual(4, '5'), + AssertionError, + 'deepStrictEqual(4, \'5\')'); + +// Having the same number of owned properties && the same set of keys. +assert.doesNotThrow(() => assert.deepStrictEqual({ a: 4 }, { a: 4 })); +assert.doesNotThrow( + () => assert.deepStrictEqual({ a: 4, b: '2' }, { a: 4, b: '2' })); +assert.throws(() => assert.deepStrictEqual([4], ['4']), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: "[ 4 ] deepStrictEqual [ '4' ]" + }); +assert.throws(() => assert.deepStrictEqual({ a: 4 }, { a: 4, b: true }), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '{ a: 4 } deepStrictEqual { a: 4, b: true }' + }); +assert.throws(() => assert.deepStrictEqual(['a'], { 0: 'a' }), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: "[ 'a' ] deepStrictEqual { '0': 'a' }" + }); + /* eslint-enable */ + +assert.doesNotThrow( + () => assert.deepStrictEqual({ a: 4, b: '1' }, { b: '1', a: 4 })); + +assert.throws( + () => assert.deepStrictEqual([0, 1, 2, 'a', 'b'], [0, 1, 2, 'b', 'a']), + AssertionError); + +assert.doesNotThrow(() => assert.deepStrictEqual(a1, a2)); + +// Prototype check. +function Constructor1(first, last) { + this.first = first; + this.last = last; +} + +function Constructor2(first, last) { + this.first = first; + this.last = last; +} + +const obj1 = new Constructor1('Ryan', 'Dahl'); +let obj2 = new Constructor2('Ryan', 'Dahl'); + +assert.throws(() => assert.deepStrictEqual(obj1, obj2), AssertionError); + +Constructor2.prototype = Constructor1.prototype; +obj2 = new Constructor2('Ryan', 'Dahl'); + +assert.doesNotThrow(() => assert.deepStrictEqual(obj1, obj2)); + +// primitives +assert.throws(() => assert.deepStrictEqual(4, '4'), AssertionError); +assert.throws(() => assert.deepStrictEqual(true, 1), AssertionError); +assert.throws(() => assert.deepStrictEqual(Symbol(), Symbol()), + AssertionError); + +const s = Symbol(); +assert.doesNotThrow(() => assert.deepStrictEqual(s, s)); + +// Primitives and object. +assert.throws(() => assert.deepStrictEqual(null, {}), AssertionError); +assert.throws(() => assert.deepStrictEqual(undefined, {}), AssertionError); +assert.throws(() => assert.deepStrictEqual('a', ['a']), AssertionError); +assert.throws(() => assert.deepStrictEqual('a', { 0: 'a' }), AssertionError); +assert.throws(() => assert.deepStrictEqual(1, {}), AssertionError); +assert.throws(() => assert.deepStrictEqual(true, {}), AssertionError); +assert.throws(() => assert.deepStrictEqual(Symbol(), {}), AssertionError); + +// Primitive wrappers and object. +assert.throws(() => assert.deepStrictEqual(new String('a'), ['a']), + AssertionError); +assert.throws(() => assert.deepStrictEqual(new String('a'), { 0: 'a' }), + AssertionError); +assert.throws(() => assert.deepStrictEqual(new Number(1), {}), AssertionError); +assert.throws(() => assert.deepStrictEqual(new Boolean(true), {}), + AssertionError); diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index e422acbbfbcddd..869011908c30a6 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -33,432 +33,104 @@ const { errorCache } = require('internal/errors'); const { writeFileSync, unlinkSync } = require('fs'); const a = assert; -function makeBlock(f) { - const args = Array.prototype.slice.call(arguments, 1); - return () => { - return f.apply(null, args); - }; -} - assert.ok(a.AssertionError.prototype instanceof Error, 'a.AssertionError instanceof Error'); -assert.throws(makeBlock(a, false), a.AssertionError, 'ok(false)'); +assert.throws(() => a(false), a.AssertionError, 'ok(false)'); -assert.doesNotThrow(makeBlock(a, true), a.AssertionError, 'ok(true)'); +assert.doesNotThrow(() => a(true), a.AssertionError, 'ok(true)'); -assert.doesNotThrow(makeBlock(a, 'test', 'ok(\'test\')')); +assert.doesNotThrow(() => a('test', 'ok(\'test\')')); -assert.throws(makeBlock(a.ok, false), - a.AssertionError, 'ok(false)'); +assert.throws(() => a.ok(false), a.AssertionError, 'ok(false)'); -assert.doesNotThrow(makeBlock(a.ok, true), - a.AssertionError, 'ok(true)'); +assert.doesNotThrow(() => a.ok(true), a.AssertionError, 'ok(true)'); -assert.doesNotThrow(makeBlock(a.ok, 'test'), 'ok(\'test\')'); +assert.doesNotThrow(() => a.ok('test'), 'ok(\'test\')'); -assert.throws(makeBlock(a.equal, true, false), +assert.throws(() => a.equal(true, false), a.AssertionError, 'equal(true, false)'); -assert.doesNotThrow(makeBlock(a.equal, null, null), - 'equal(null, null)'); +assert.doesNotThrow(() => a.equal(null, null), 'equal(null, null)'); -assert.doesNotThrow(makeBlock(a.equal, undefined, undefined), +assert.doesNotThrow(() => a.equal(undefined, undefined), 'equal(undefined, undefined)'); -assert.doesNotThrow(makeBlock(a.equal, null, undefined), - 'equal(null, undefined)'); +assert.doesNotThrow(() => a.equal(null, undefined), 'equal(null, undefined)'); -assert.doesNotThrow(makeBlock(a.equal, true, true), 'equal(true, true)'); +assert.doesNotThrow(() => a.equal(true, true), 'equal(true, true)'); -assert.doesNotThrow(makeBlock(a.equal, 2, '2'), 'equal(2, \'2\')'); +assert.doesNotThrow(() => a.equal(2, '2'), 'equal(2, \'2\')'); -assert.doesNotThrow(makeBlock(a.notEqual, true, false), - 'notEqual(true, false)'); +assert.doesNotThrow(() => a.notEqual(true, false), 'notEqual(true, false)'); -assert.throws(makeBlock(a.notEqual, true, true), +assert.throws(() => a.notEqual(true, true), a.AssertionError, 'notEqual(true, true)'); -assert.throws(makeBlock(a.strictEqual, 2, '2'), +assert.throws(() => a.strictEqual(2, '2'), a.AssertionError, 'strictEqual(2, \'2\')'); -assert.throws(makeBlock(a.strictEqual, null, undefined), +assert.throws(() => a.strictEqual(null, undefined), a.AssertionError, 'strictEqual(null, undefined)'); -assert.throws(makeBlock(a.notStrictEqual, 2, 2), +assert.throws(() => a.notStrictEqual(2, 2), a.AssertionError, 'notStrictEqual(2, 2)'); -assert.doesNotThrow(makeBlock(a.notStrictEqual, 2, '2'), - 'notStrictEqual(2, \'2\')'); - -// deepEqual joy! -assert.doesNotThrow(makeBlock(a.deepEqual, new Date(2000, 3, 14), - new Date(2000, 3, 14)), - 'deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))'); - -assert.throws(makeBlock(a.deepEqual, new Date(), new Date(2000, 3, 14)), - a.AssertionError, - 'deepEqual(new Date(), new Date(2000, 3, 14))'); - -assert.throws( - makeBlock(a.notDeepEqual, new Date(2000, 3, 14), new Date(2000, 3, 14)), - a.AssertionError, - 'notDeepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' -); - -assert.doesNotThrow(makeBlock( - a.notDeepEqual, - new Date(), - new Date(2000, 3, 14)), - 'notDeepEqual(new Date(), new Date(2000, 3, 14))' -); - -assert.doesNotThrow(makeBlock(a.deepEqual, /a/, /a/)); -assert.doesNotThrow(makeBlock(a.deepEqual, /a/g, /a/g)); -assert.doesNotThrow(makeBlock(a.deepEqual, /a/i, /a/i)); -assert.doesNotThrow(makeBlock(a.deepEqual, /a/m, /a/m)); -assert.doesNotThrow(makeBlock(a.deepEqual, /a/igm, /a/igm)); -assert.throws(makeBlock(a.deepEqual, /ab/, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/ab\/ deepEqual \/a\/$/ - })); -assert.throws(makeBlock(a.deepEqual, /a/g, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/g deepEqual \/a\/$/ - })); -assert.throws(makeBlock(a.deepEqual, /a/i, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/i deepEqual \/a\/$/ - })); -assert.throws(makeBlock(a.deepEqual, /a/m, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/m deepEqual \/a\/$/ - })); -assert.throws(makeBlock(a.deepEqual, /a/igm, /a/im), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/gim deepEqual \/a\/im$/ - })); - -{ - const re1 = /a/g; - re1.lastIndex = 3; - assert.doesNotThrow(makeBlock(a.deepEqual, re1, /a/g)); -} - -assert.doesNotThrow(makeBlock(a.deepEqual, 4, '4'), 'deepEqual(4, \'4\')'); -assert.doesNotThrow(makeBlock(a.deepEqual, true, 1), 'deepEqual(true, 1)'); -assert.throws(makeBlock(a.deepEqual, 4, '5'), - a.AssertionError, - 'deepEqual( 4, \'5\')'); - -// having the same number of owned properties && the same set of keys -assert.doesNotThrow(makeBlock(a.deepEqual, { a: 4 }, { a: 4 })); -assert.doesNotThrow(makeBlock(a.deepEqual, { a: 4, b: '2' }, { a: 4, b: '2' })); -assert.doesNotThrow(makeBlock(a.deepEqual, [4], ['4'])); -assert.throws(makeBlock(a.deepEqual, { a: 4 }, { a: 4, b: true }), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, ['a'], { 0: 'a' })); -//(although not necessarily the same order), -assert.doesNotThrow(makeBlock(a.deepEqual, { a: 4, b: '1' }, { b: '1', a: 4 })); -const a1 = [1, 2, 3]; -const a2 = [1, 2, 3]; -a1.a = 'test'; -a1.b = true; -a2.b = true; -a2.a = 'test'; -assert.throws(makeBlock(a.deepEqual, Object.keys(a1), Object.keys(a2)), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, a1, a2)); - -// having an identical prototype property -const nbRoot = { - toString() { return `${this.first} ${this.last}`; } -}; - -function nameBuilder(first, last) { - this.first = first; - this.last = last; - return this; -} -nameBuilder.prototype = nbRoot; - -function nameBuilder2(first, last) { - this.first = first; - this.last = last; - return this; -} -nameBuilder2.prototype = nbRoot; - -const nb1 = new nameBuilder('Ryan', 'Dahl'); -let nb2 = new nameBuilder2('Ryan', 'Dahl'); - -assert.doesNotThrow(makeBlock(a.deepEqual, nb1, nb2)); - -nameBuilder2.prototype = Object; -nb2 = new nameBuilder2('Ryan', 'Dahl'); -assert.doesNotThrow(makeBlock(a.deepEqual, nb1, nb2)); - -// primitives and object -assert.throws(makeBlock(a.deepEqual, null, {}), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, undefined, {}), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, 'a', ['a']), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, 'a', { 0: 'a' }), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, 1, {}), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, true, {}), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, Symbol(), {}), a.AssertionError); - -// primitive wrappers and object -assert.doesNotThrow(makeBlock(a.deepEqual, new String('a'), ['a']), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, new String('a'), { 0: 'a' }), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, new Number(1), {}), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, new Boolean(true), {}), - a.AssertionError); - -// same number of keys but different key names -assert.throws(makeBlock(a.deepEqual, { a: 1 }, { b: 1 }), a.AssertionError); - -//deepStrictEqual -assert.doesNotThrow( - makeBlock(a.deepStrictEqual, new Date(2000, 3, 14), new Date(2000, 3, 14)), - 'deepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' -); - -assert.throws( - makeBlock(a.deepStrictEqual, new Date(), new Date(2000, 3, 14)), - a.AssertionError, - 'deepStrictEqual(new Date(), new Date(2000, 3, 14))' -); - -assert.throws( - makeBlock(a.notDeepStrictEqual, new Date(2000, 3, 14), new Date(2000, 3, 14)), - a.AssertionError, - 'notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' -); - -assert.doesNotThrow( - makeBlock(a.notDeepStrictEqual, new Date(), new Date(2000, 3, 14)), - 'notDeepStrictEqual(new Date(), new Date(2000, 3, 14))' -); - -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/, /a/)); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/g, /a/g)); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/i, /a/i)); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/m, /a/m)); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/igm, /a/igm)); -assert.throws( - makeBlock(a.deepStrictEqual, /ab/, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/ab\/ deepStrictEqual \/a\/$/ - })); -assert.throws( - makeBlock(a.deepStrictEqual, /a/g, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/g deepStrictEqual \/a\/$/ - })); -assert.throws( - makeBlock(a.deepStrictEqual, /a/i, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/i deepStrictEqual \/a\/$/ - })); -assert.throws( - makeBlock(a.deepStrictEqual, /a/m, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/m deepStrictEqual \/a\/$/ - })); -assert.throws( - makeBlock(a.deepStrictEqual, /a/igm, /a/im), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/gim deepStrictEqual \/a\/im$/ - })); - -{ - const re1 = /a/; - re1.lastIndex = 3; - assert.doesNotThrow(makeBlock(a.deepStrictEqual, re1, /a/)); -} - -assert.throws(makeBlock(a.deepStrictEqual, 4, '4'), - a.AssertionError, - 'deepStrictEqual(4, \'4\')'); - -assert.throws(makeBlock(a.deepStrictEqual, true, 1), - a.AssertionError, - 'deepStrictEqual(true, 1)'); - -assert.throws(makeBlock(a.deepStrictEqual, 4, '5'), - a.AssertionError, - 'deepStrictEqual(4, \'5\')'); - -// having the same number of owned properties && the same set of keys -assert.doesNotThrow(makeBlock(a.deepStrictEqual, { a: 4 }, { a: 4 })); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, - { a: 4, b: '2' }, - { a: 4, b: '2' })); -assert.throws(makeBlock(a.deepStrictEqual, [4], ['4']), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\[ 4 ] deepStrictEqual \[ '4' ]$/ - })); -assert.throws(makeBlock(a.deepStrictEqual, { a: 4 }, { a: 4, b: true }), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^{ a: 4 } deepStrictEqual { a: 4, b: true }$/ - })); -assert.throws(makeBlock(a.deepStrictEqual, ['a'], { 0: 'a' }), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\[ 'a' ] deepStrictEqual { '0': 'a' }$/ - })); -//(although not necessarily the same order), -assert.doesNotThrow(makeBlock(a.deepStrictEqual, - { a: 4, b: '1' }, - { b: '1', a: 4 })); - -assert.throws(makeBlock(a.deepStrictEqual, - [0, 1, 2, 'a', 'b'], - [0, 1, 2, 'b', 'a']), - a.AssertionError); - -assert.doesNotThrow(makeBlock(a.deepStrictEqual, a1, a2)); - -// Prototype check -function Constructor1(first, last) { - this.first = first; - this.last = last; -} - -function Constructor2(first, last) { - this.first = first; - this.last = last; -} - -const obj1 = new Constructor1('Ryan', 'Dahl'); -let obj2 = new Constructor2('Ryan', 'Dahl'); - -assert.throws(makeBlock(a.deepStrictEqual, obj1, obj2), a.AssertionError); - -Constructor2.prototype = Constructor1.prototype; -obj2 = new Constructor2('Ryan', 'Dahl'); - -assert.doesNotThrow(makeBlock(a.deepStrictEqual, obj1, obj2)); - -// primitives -assert.throws(makeBlock(assert.deepStrictEqual, 4, '4'), - a.AssertionError); -assert.throws(makeBlock(assert.deepStrictEqual, true, 1), - a.AssertionError); -assert.throws(makeBlock(assert.deepStrictEqual, Symbol(), Symbol()), - a.AssertionError); - -const s = Symbol(); -assert.doesNotThrow(makeBlock(assert.deepStrictEqual, s, s)); - +assert.doesNotThrow(() => a.notStrictEqual(2, '2'), 'notStrictEqual(2, \'2\')'); -// primitives and object -assert.throws(makeBlock(a.deepStrictEqual, null, {}), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, undefined, {}), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, 'a', ['a']), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, 'a', { 0: 'a' }), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, 1, {}), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, true, {}), a.AssertionError); -assert.throws(makeBlock(assert.deepStrictEqual, Symbol(), {}), - a.AssertionError); - - -// primitive wrappers and object -assert.throws(makeBlock(a.deepStrictEqual, new String('a'), ['a']), - a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, new String('a'), { 0: 'a' }), - a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, new Number(1), {}), - a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, new Boolean(true), {}), - a.AssertionError); - - -// Testing the throwing +// Testing the throwing. function thrower(errorConstructor) { throw new errorConstructor({}); } -// the basic calls work -assert.throws(makeBlock(thrower, a.AssertionError), - a.AssertionError, 'message'); -assert.throws(makeBlock(thrower, a.AssertionError), a.AssertionError); +// The basic calls work. +assert.throws(() => thrower(a.AssertionError), a.AssertionError, 'message'); +assert.throws(() => thrower(a.AssertionError), a.AssertionError); // eslint-disable-next-line no-restricted-syntax -assert.throws(makeBlock(thrower, a.AssertionError)); +assert.throws(() => thrower(a.AssertionError)); -// if not passing an error, catch all. +// If not passing an error, catch all. // eslint-disable-next-line no-restricted-syntax -assert.throws(makeBlock(thrower, TypeError)); +assert.throws(() => thrower(TypeError)); -// when passing a type, only catch errors of the appropriate type +// When passing a type, only catch errors of the appropriate type. { let threw = false; try { - a.throws(makeBlock(thrower, TypeError), a.AssertionError); + a.throws(() => thrower(TypeError), a.AssertionError); } catch (e) { threw = true; assert.ok(e instanceof TypeError, 'type'); } - assert.strictEqual(true, threw, - 'a.throws with an explicit error is eating extra errors'); + assert.ok(threw, 'a.throws with an explicit error is eating extra errors'); } -// doesNotThrow should pass through all errors +// doesNotThrow should pass through all errors. { let threw = false; try { - a.doesNotThrow(makeBlock(thrower, TypeError), a.AssertionError); + a.doesNotThrow(() => thrower(TypeError), a.AssertionError); } catch (e) { threw = true; assert.ok(e instanceof TypeError); } - assert.strictEqual(true, threw, 'a.doesNotThrow with an explicit error is ' + - 'eating extra errors'); + assert(threw, 'a.doesNotThrow with an explicit error is eating extra errors'); } -// key difference is that throwing our correct error makes an assertion error +// Key difference is that throwing our correct error makes an assertion error. { let threw = false; try { - a.doesNotThrow(makeBlock(thrower, TypeError), TypeError); + a.doesNotThrow(() => thrower(TypeError), TypeError); } catch (e) { threw = true; assert.ok(e instanceof a.AssertionError); } - assert.strictEqual(true, threw, - 'a.doesNotThrow is not catching type matching errors'); + assert.ok(threw, 'a.doesNotThrow is not catching type matching errors'); } common.expectsError( - () => assert.doesNotThrow(makeBlock(thrower, Error), 'user message'), + () => assert.doesNotThrow(() => thrower(Error), 'user message'), { type: a.AssertionError, code: 'ERR_ASSERTION', @@ -468,7 +140,7 @@ common.expectsError( ); common.expectsError( - () => assert.doesNotThrow(makeBlock(thrower, Error), 'user message'), + () => assert.doesNotThrow(() => thrower(Error), 'user message'), { code: 'ERR_ASSERTION', message: /Got unwanted exception: user message\n\[object Object\]/ @@ -476,14 +148,14 @@ common.expectsError( ); common.expectsError( - () => assert.doesNotThrow(makeBlock(thrower, Error)), + () => assert.doesNotThrow(() => thrower(Error)), { code: 'ERR_ASSERTION', message: /Got unwanted exception\.\n\[object Object\]/ } ); -// make sure that validating using constructor really works +// Make sure that validating using constructor really works. { let threw = false; try { @@ -499,11 +171,11 @@ common.expectsError( assert.ok(threw, 'wrong constructor validation'); } -// use a RegExp to validate error message -a.throws(makeBlock(thrower, TypeError), /\[object Object\]/); +// Use a RegExp to validate the error message. +a.throws(() => thrower(TypeError), /\[object Object\]/); -// use a fn to validate error object -a.throws(makeBlock(thrower, TypeError), (err) => { +// Use a fn to validate the error object. +a.throws(() => thrower(TypeError), (err) => { if ((err instanceof TypeError) && /\[object Object\]/.test(err)) { return true; } @@ -512,18 +184,12 @@ a.throws(makeBlock(thrower, TypeError), (err) => { // https://github.com/nodejs/node/issues/3188 { let threw = false; - let AnotherErrorType; try { const ES6Error = class extends Error {}; - AnotherErrorType = class extends Error {}; - const functionThatThrows = () => { - throw new AnotherErrorType('foo'); - }; - - assert.throws(functionThatThrows, ES6Error); + assert.throws(() => { throw new AnotherErrorType('foo'); }, ES6Error); } catch (e) { threw = true; assert(e instanceof AnotherErrorType, @@ -533,7 +199,7 @@ a.throws(makeBlock(thrower, TypeError), (err) => { assert.ok(threw); } -// check messages from assert.throws() +// Check messages from assert.throws(). { const noop = () => {}; assert.throws( @@ -622,7 +288,7 @@ try { let threw = false; const rangeError = new RangeError('my range'); - // verify custom errors + // Verify custom errors. try { assert.strictEqual(1, 2, rangeError); } catch (e) { @@ -633,7 +299,7 @@ try { assert.ok(threw); threw = false; - // verify AssertionError is the result from doesNotThrow with custom Error + // Verify AssertionError is the result from doesNotThrow with custom Error. try { assert.doesNotThrow(() => { throw new TypeError('wrong type'); @@ -648,7 +314,7 @@ try { } { - // Verify that throws() and doesNotThrow() throw on non-function block + // Verify that throws() and doesNotThrow() throw on non-function block. function typeName(value) { return value === null ? 'null' : typeof value; } @@ -699,7 +365,7 @@ assert.throws(() => { })); { - // bad args to AssertionError constructor should throw TypeError + // Bad args to AssertionError constructor should throw TypeError. const args = [1, true, false, '', null, Infinity, Symbol('test'), undefined]; const re = /^The "options" argument must be of type Object$/; args.forEach((input) => { @@ -722,7 +388,7 @@ common.expectsError( } ); -// Test strict assert +// Test strict assert. { const a = require('assert'); const assert = require('assert').strict; @@ -771,7 +437,7 @@ common.expectsError( ); Error.stackTraceLimit = tmpLimit; - // Test error diffs + // Test error diffs. const colors = process.stdout.isTTY && process.stdout.getColorDepth() > 1; const start = 'Input A expected to deepStrictEqual input B:'; const actExp = colors ? @@ -936,7 +602,7 @@ common.expectsError( ); { - // Test caching + // Test caching. const fs = process.binding('fs'); const tmp = fs.close; fs.close = common.mustCall(tmp, 1); From b8f47b27571f8d763f811f017be3fb37d466c4fc Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Wed, 7 Feb 2018 16:42:21 -0800 Subject: [PATCH 052/193] src: add "icu::" prefix before ICU symbols In ICU 61.x, icu4c will no longer put its declarations in the global namespace. Everything will be in the "icu::" namespace (or icu_60:: in the linker). Prepare for this. https://ssl.icu-project.org/trac/ticket/13460 --- src/inspector_io.cc | 9 +++++---- src/node_i18n.cc | 2 +- tools/icu/iculslocs.cc | 14 +++++++------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/inspector_io.cc b/src/inspector_io.cc index 9af4458c6b20f1..01ddc296b08693 100644 --- a/src/inspector_io.cc +++ b/src/inspector_io.cc @@ -74,11 +74,11 @@ std::string StringViewToUtf8(const StringView& view) { size_t result_length = view.length() * sizeof(*source); std::string result(result_length, '\0'); - UnicodeString utf16(unicodeSource, view.length()); + icu::UnicodeString utf16(unicodeSource, view.length()); // ICU components for std::string compatibility are not enabled in build... bool done = false; while (!done) { - CheckedArrayByteSink sink(&result[0], result_length); + icu::CheckedArrayByteSink sink(&result[0], result_length); utf16.toUTF8(sink); result_length = sink.NumberOfBytesAppended(); result.resize(result_length); @@ -111,8 +111,9 @@ void ReleasePairOnAsyncClose(uv_handle_t* async) { } // namespace std::unique_ptr Utf8ToStringView(const std::string& message) { - UnicodeString utf16 = - UnicodeString::fromUTF8(StringPiece(message.data(), message.length())); + icu::UnicodeString utf16 = + icu::UnicodeString::fromUTF8(icu::StringPiece(message.data(), + message.length())); StringView view(reinterpret_cast(utf16.getBuffer()), utf16.length()); return StringBuffer::create(view); diff --git a/src/node_i18n.cc b/src/node_i18n.cc index 71ae6a000336e2..d65fc55ed1fee5 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -523,7 +523,7 @@ const char* GetVersion(const char* type, } else if (!strcmp(type, TYPE_UNICODE)) { return U_UNICODE_VERSION; } else if (!strcmp(type, TYPE_TZ)) { - return TimeZone::getTZDataVersion(*status); + return icu::TimeZone::getTZDataVersion(*status); } else if (!strcmp(type, TYPE_CLDR)) { UVersionInfo versionArray; ulocdata_getCLDRVersion(versionArray, status); diff --git a/tools/icu/iculslocs.cc b/tools/icu/iculslocs.cc index ca312b783565c4..3ceb8d2a4d81d0 100644 --- a/tools/icu/iculslocs.cc +++ b/tools/icu/iculslocs.cc @@ -64,7 +64,7 @@ int VERBOSE = 0; #define RES_INDEX "res_index" #define INSTALLEDLOCALES "InstalledLocales" -CharString packageName; +icu::CharString packageName; const char* locale = RES_INDEX; // locale referring to our index void usage() { @@ -147,7 +147,7 @@ int localeExists(const char* loc, UBool* exists) { if (VERBOSE > 1) { printf("Trying to open %s:%s\n", packageName.data(), loc); } - LocalUResourceBundlePointer aResource( + icu::LocalUResourceBundlePointer aResource( ures_openDirect(packageName.data(), loc, &status)); *exists = FALSE; if (U_SUCCESS(status)) { @@ -189,11 +189,11 @@ void printIndent(FILE* bf, int indent) { * @return 0 for OK, 1 for err */ int dumpAllButInstalledLocales(int lev, - LocalUResourceBundlePointer* bund, + icu::LocalUResourceBundlePointer* bund, FILE* bf, UErrorCode* status) { ures_resetIterator(bund->getAlias()); - LocalUResourceBundlePointer t; + icu::LocalUResourceBundlePointer t; while (U_SUCCESS(*status) && ures_hasNext(bund->getAlias())) { t.adoptInstead(ures_getNextResource(bund->getAlias(), t.orphan(), status)); ASSERT_SUCCESS(status, "while processing table"); @@ -254,10 +254,10 @@ int list(const char* toBundle) { printf("\"locale\": %s\n", locale); } - LocalUResourceBundlePointer bund( + icu::LocalUResourceBundlePointer bund( ures_openDirect(packageName.data(), locale, &status)); ASSERT_SUCCESS(&status, "while opening the bundle"); - LocalUResourceBundlePointer installedLocales( + icu::LocalUResourceBundlePointer installedLocales( // NOLINTNEXTLINE (readability/null_usage) ures_getByKey(bund.getAlias(), INSTALLEDLOCALES, NULL, &status)); ASSERT_SUCCESS(&status, "while fetching installed locales"); @@ -295,7 +295,7 @@ int list(const char* toBundle) { } // OK, now list them. - LocalUResourceBundlePointer subkey; + icu::LocalUResourceBundlePointer subkey; int validCount = 0; for (int32_t i = 0; i < count; i++) { From 6007a9cc0e361d428123e4c0f74024c6cd7815f4 Mon Sep 17 00:00:00 2001 From: Jeff Principe Date: Mon, 16 Oct 2017 21:23:29 -0700 Subject: [PATCH 053/193] https: add extra options to Agent#getName() Adds the remaining options from tls.createSecureContext() to the string generated by Agent#getName(). This allows https.request() to accept the options and generate unique sockets appropriately. PR-URL: https://github.com/nodejs/node/pull/16402 Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- doc/api/https.md | 11 +-- lib/https.js | 24 +++++ .../test-https-agent-additional-options.js | 87 +++++++++++++++++++ test/parallel/test-https-agent-getname.js | 12 ++- .../test-https-agent-secure-protocol.js | 57 ------------ 5 files changed, 127 insertions(+), 64 deletions(-) create mode 100644 test/parallel/test-https-agent-additional-options.js delete mode 100644 test/parallel/test-https-agent-secure-protocol.js diff --git a/doc/api/https.md b/doc/api/https.md index 2cc7502012d63d..58e62ccced4728 100644 --- a/doc/api/https.md +++ b/doc/api/https.md @@ -12,7 +12,7 @@ separate module. added: v0.4.5 --> -An Agent object for HTTPS similar to [`http.Agent`][]. See [`https.request()`][] +An [`Agent`][] object for HTTPS similar to [`http.Agent`][]. See [`https.request()`][] for more information. ## Class: https.Server @@ -168,9 +168,10 @@ changes: Makes a request to a secure web server. -The following additional `options` from [`tls.connect()`][] are also accepted -when using a custom [`Agent`][]: `ca`, `cert`, `ciphers`, `clientCertEngine`, -`key`, `passphrase`, `pfx`, `rejectUnauthorized`, `secureProtocol`, `servername` +The following additional `options` from [`tls.connect()`][] are also accepted: +`ca`, `cert`, `ciphers`, `clientCertEngine`, `crl`, `dhparam`, `ecdhCurve`, +`honorCipherOrder`, `key`, `passphrase`, `pfx`, `rejectUnauthorized`, +`secureOptions`, `secureProtocol`, `servername`, `sessionIdContext` `options` can be an object, a string, or a [`URL`][] object. If `options` is a string, it is automatically parsed with [`url.parse()`][]. If it is a [`URL`][] @@ -220,7 +221,7 @@ const req = https.request(options, (res) => { }); ``` -Alternatively, opt out of connection pooling by not using an `Agent`. +Alternatively, opt out of connection pooling by not using an [`Agent`][]. Example: diff --git a/lib/https.js b/lib/https.js index 741ce84d2f8820..84ddeb5036a900 100644 --- a/lib/https.js +++ b/lib/https.js @@ -194,6 +194,30 @@ Agent.prototype.getName = function getName(options) { if (options.secureProtocol) name += options.secureProtocol; + name += ':'; + if (options.crl) + name += options.crl; + + name += ':'; + if (options.honorCipherOrder !== undefined) + name += options.honorCipherOrder; + + name += ':'; + if (options.ecdhCurve) + name += options.ecdhCurve; + + name += ':'; + if (options.dhparam) + name += options.dhparam; + + name += ':'; + if (options.secureOptions !== undefined) + name += options.secureOptions; + + name += ':'; + if (options.sessionIdContext) + name += options.sessionIdContext; + return name; }; diff --git a/test/parallel/test-https-agent-additional-options.js b/test/parallel/test-https-agent-additional-options.js new file mode 100644 index 00000000000000..8d10524d902ca7 --- /dev/null +++ b/test/parallel/test-https-agent-additional-options.js @@ -0,0 +1,87 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const crypto = require('crypto'); +const https = require('https'); +const fixtures = require('../common/fixtures'); + +const options = { + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem'), + ca: fixtures.readKey('ca1-cert.pem') +}; + +const server = https.Server(options, function(req, res) { + res.writeHead(200); + res.end('hello world\n'); +}); + +function getBaseOptions(port) { + return { + path: '/', + port: port, + ca: options.ca, + rejectUnautorized: true, + servername: 'agent1', + }; +} + +const updatedValues = new Map([ + ['dhparam', fixtures.readKey('dh2048.pem')], + ['ecdhCurve', 'secp384r1'], + ['honorCipherOrder', true], + ['secureOptions', crypto.constants.SSL_OP_CIPHER_SERVER_PREFERENCE], + ['secureProtocol', 'TLSv1_method'], + ['sessionIdContext', 'sessionIdContext'], +]); + +function variations(iter, port, cb) { + const { done, value } = iter.next(); + if (done) { + return common.mustCall(cb); + } else { + const [key, val] = value; + return common.mustCall(function(res) { + res.resume(); + https.globalAgent.once('free', common.mustCall(function() { + https.get( + Object.assign({}, getBaseOptions(port), { [key]: val }), + variations(iter, port, cb) + ); + })); + }); + } +} + +server.listen(0, common.mustCall(function() { + const port = this.address().port; + const globalAgent = https.globalAgent; + globalAgent.keepAlive = true; + https.get(getBaseOptions(port), variations( + updatedValues.entries(), + port, + common.mustCall(function(res) { + res.resume(); + globalAgent.once('free', common.mustCall(function() { + // Verify that different keep-alived connections are created + // for the base call and each variation + const keys = Object.keys(globalAgent.freeSockets); + assert.strictEqual(keys.length, 1 + updatedValues.size); + let i = 1; + for (const [, value] of updatedValues) { + assert.ok( + keys[i].startsWith(value.toString() + ':') || + keys[i].endsWith(':' + value.toString()) || + keys[i].includes(':' + value.toString() + ':') + ); + i++; + } + globalAgent.destroy(); + server.close(); + })); + }) + )); +})); diff --git a/test/parallel/test-https-agent-getname.js b/test/parallel/test-https-agent-getname.js index 0cdc9568d84470..c29e09731df0b2 100644 --- a/test/parallel/test-https-agent-getname.js +++ b/test/parallel/test-https-agent-getname.js @@ -12,7 +12,7 @@ const agent = new https.Agent(); // empty options assert.strictEqual( agent.getName({}), - 'localhost:::::::::::' + 'localhost:::::::::::::::::' ); // pass all options arguments @@ -23,13 +23,21 @@ const options = { ca: 'ca', cert: 'cert', ciphers: 'ciphers', + crl: [Buffer.from('c'), Buffer.from('r'), Buffer.from('l')], + dhparam: 'dhparam', + ecdhCurve: 'ecdhCurve', + honorCipherOrder: false, key: 'key', pfx: 'pfx', rejectUnauthorized: false, + secureOptions: 0, + secureProtocol: 'secureProtocol', servername: 'localhost', + sessionIdContext: 'sessionIdContext' }; assert.strictEqual( agent.getName(options), - '0.0.0.0:443:192.168.1.1:ca:cert::ciphers:key:pfx:false:localhost:' + '0.0.0.0:443:192.168.1.1:ca:cert::ciphers:key:pfx:false:localhost:' + + 'secureProtocol:c,r,l:false:ecdhCurve:dhparam:0:sessionIdContext' ); diff --git a/test/parallel/test-https-agent-secure-protocol.js b/test/parallel/test-https-agent-secure-protocol.js deleted file mode 100644 index 82554952e8446b..00000000000000 --- a/test/parallel/test-https-agent-secure-protocol.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -const common = require('../common'); -if (!common.hasCrypto) - common.skip('missing crypto'); - -const assert = require('assert'); -const https = require('https'); -const fixtures = require('../common/fixtures'); - -const options = { - key: fixtures.readKey('agent1-key.pem'), - cert: fixtures.readKey('agent1-cert.pem'), - ca: fixtures.readKey('ca1-cert.pem') -}; - -const server = https.Server(options, function(req, res) { - res.writeHead(200); - res.end('hello world\n'); -}); - -server.listen(0, common.mustCall(function() { - const port = this.address().port; - const globalAgent = https.globalAgent; - globalAgent.keepAlive = true; - https.get({ - path: '/', - port: port, - ca: options.ca, - rejectUnauthorized: true, - servername: 'agent1', - secureProtocol: 'SSLv23_method' - }, common.mustCall(function(res) { - res.resume(); - globalAgent.once('free', common.mustCall(function() { - https.get({ - path: '/', - port: port, - ca: options.ca, - rejectUnauthorized: true, - servername: 'agent1', - secureProtocol: 'TLSv1_method' - }, common.mustCall(function(res) { - res.resume(); - globalAgent.once('free', common.mustCall(function() { - // Verify that two keep-alive connections are created - // due to the different secureProtocol settings: - const keys = Object.keys(globalAgent.freeSockets); - assert.strictEqual(keys.length, 2); - assert.ok(keys[0].includes(':SSLv23_method')); - assert.ok(keys[1].includes(':TLSv1_method')); - globalAgent.destroy(); - server.close(); - })); - })); - })); - })); -})); From de848ac1e0483327a2ce8716c3f8567eaeacb660 Mon Sep 17 00:00:00 2001 From: Bradley Farias Date: Fri, 22 Dec 2017 11:19:50 -0600 Subject: [PATCH 054/193] repl: refactor tests to not rely on timing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests relying on synchronous timing have been migrated to use events. PR-URL: https://github.com/nodejs/node/pull/17828 Reviewed-By: James M Snell Reviewed-By: Michaël Zasso --- lib/internal/repl.js | 4 +- lib/repl.js | 79 +++++------ test/parallel/test-repl-autolibs.js | 27 +++- test/parallel/test-repl-context.js | 67 ++++++---- test/parallel/test-repl-end-emits-exit.js | 18 +-- test/parallel/test-repl-eval-scope.js | 38 +++--- test/parallel/test-repl-eval.js | 50 +++---- ...test-repl-function-definition-edge-case.js | 71 ++++++---- test/parallel/test-repl-load-multiline.js | 4 +- test/parallel/test-repl-mode.js | 53 ++++++-- test/parallel/test-repl-null-thrown.js | 7 +- test/parallel/test-repl-null.js | 21 ++- .../parallel/test-repl-pretty-custom-stack.js | 4 +- test/parallel/test-repl-pretty-stack.js | 4 +- test/parallel/test-repl-recoverable.js | 8 +- .../test-repl-throw-null-or-undefined.js | 20 +-- test/parallel/test-repl-underscore.js | 124 ++++++++++-------- test/parallel/test-repl-use-global.js | 65 ++++----- 18 files changed, 391 insertions(+), 273 deletions(-) diff --git a/lib/internal/repl.js b/lib/internal/repl.js index 812af56ed2e046..76412c3b118a8c 100644 --- a/lib/internal/repl.js +++ b/lib/internal/repl.js @@ -8,7 +8,7 @@ const os = require('os'); const util = require('util'); const debug = util.debuglog('repl'); module.exports = Object.create(REPL); -module.exports.createInternalRepl = createRepl; +module.exports.createInternalRepl = createInternalRepl; // XXX(chrisdickinson): The 15ms debounce value is somewhat arbitrary. // The debounce is to guard against code pasted into the REPL. @@ -19,7 +19,7 @@ function _writeToOutput(repl, message) { repl._refreshLine(); } -function createRepl(env, opts, cb) { +function createInternalRepl(env, opts, cb) { if (typeof opts === 'function') { cb = opts; opts = null; diff --git a/lib/repl.js b/lib/repl.js index 84682b1b63e6cc..2227953fa86468 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -109,6 +109,11 @@ writer.options = Object.assign({}, exports._builtinLibs = internalModule.builtinLibs; +const sep = '\u0000\u0000\u0000'; +const regExMatcher = new RegExp(`^${sep}(.*)${sep}(.*)${sep}(.*)${sep}(.*)` + + `${sep}(.*)${sep}(.*)${sep}(.*)${sep}(.*)` + + `${sep}(.*)$`); + function REPLServer(prompt, stream, eval_, @@ -149,6 +154,7 @@ function REPLServer(prompt, } var self = this; + replMap.set(self, self); self._domain = dom || domain.create(); self.useGlobal = !!useGlobal; @@ -165,41 +171,6 @@ function REPLServer(prompt, self.rli = this; const savedRegExMatches = ['', '', '', '', '', '', '', '', '', '']; - const sep = '\u0000\u0000\u0000'; - const regExMatcher = new RegExp(`^${sep}(.*)${sep}(.*)${sep}(.*)${sep}(.*)` + - `${sep}(.*)${sep}(.*)${sep}(.*)${sep}(.*)` + - `${sep}(.*)$`); - - eval_ = eval_ || defaultEval; - - // Pause taking in new input, and store the keys in a buffer. - const pausedBuffer = []; - let paused = false; - function pause() { - paused = true; - } - function unpause() { - if (!paused) return; - paused = false; - let entry; - while (entry = pausedBuffer.shift()) { - const [type, payload] = entry; - switch (type) { - case 'key': { - const [d, key] = payload; - self._ttyWrite(d, key); - break; - } - case 'close': - self.emit('exit'); - break; - } - if (paused) { - break; - } - } - } - function defaultEval(code, context, file, cb) { var err, result, script, wrappedErr; var wrappedCmd = false; @@ -331,7 +302,6 @@ function REPLServer(prompt, if (awaitPromise && !err) { let sigintListener; - pause(); let promise = result; if (self.breakEvalOnSigint) { const interrupt = new Promise((resolve, reject) => { @@ -350,7 +320,6 @@ function REPLServer(prompt, prioritizedSigintQueue.delete(sigintListener); finishExecution(undefined, result); - unpause(); }, (err) => { // Remove prioritized SIGINT listener if it was not called. prioritizedSigintQueue.delete(sigintListener); @@ -360,7 +329,6 @@ function REPLServer(prompt, Object.defineProperty(err, 'stack', { value: '' }); } - unpause(); if (err && process.domain) { debug('not recoverable, send to domain'); process.domain.emit('error', err); @@ -377,6 +345,36 @@ function REPLServer(prompt, } } + eval_ = eval_ || defaultEval; + + // Pause taking in new input, and store the keys in a buffer. + const pausedBuffer = []; + let paused = false; + function pause() { + paused = true; + } + function unpause() { + if (!paused) return; + paused = false; + let entry; + while (entry = pausedBuffer.shift()) { + const [type, payload] = entry; + switch (type) { + case 'key': { + const [d, key] = payload; + self._ttyWrite(d, key); + break; + } + case 'close': + self.emit('exit'); + break; + } + if (paused) { + break; + } + } + } + self.eval = self._domain.bind(eval_); self._domain.on('error', function debugDomainError(e) { @@ -405,6 +403,7 @@ function REPLServer(prompt, top.clearBufferedCommand(); top.lines.level = []; top.displayPrompt(); + unpause(); }); if (!input && !output) { @@ -593,6 +592,7 @@ function REPLServer(prompt, const evalCmd = self[kBufferedCommandSymbol] + cmd + '\n'; debug('eval %j', evalCmd); + pause(); self.eval(evalCmd, self.context, 'repl', finish); function finish(e, ret) { @@ -605,6 +605,7 @@ function REPLServer(prompt, '(Press Control-D to exit.)\n'); self.clearBufferedCommand(); self.displayPrompt(); + unpause(); return; } @@ -642,6 +643,7 @@ function REPLServer(prompt, // Display prompt again self.displayPrompt(); + unpause(); } }); @@ -724,7 +726,6 @@ exports.start = function(prompt, ignoreUndefined, replMode); if (!exports.repl) exports.repl = repl; - replMap.set(repl, repl); return repl; }; diff --git a/test/parallel/test-repl-autolibs.js b/test/parallel/test-repl-autolibs.js index 52234deb5e732e..68f8402ddbfdaa 100644 --- a/test/parallel/test-repl-autolibs.js +++ b/test/parallel/test-repl-autolibs.js @@ -29,7 +29,22 @@ const repl = require('repl'); common.globalCheck = false; const putIn = new common.ArrayStream(); -repl.start('', putIn, null, true); + + +const replserver = repl.start('', putIn, null, true); +const callbacks = []; +const $eval = replserver.eval; +replserver.eval = function(code, context, file, cb) { + const expected = callbacks.shift(); + return $eval.call(this, code, context, file, (...args) => { + try { + expected(cb, ...args); + } catch (e) { + console.error(e); + process.exit(1); + } + }); +}; test1(); @@ -48,6 +63,11 @@ function test1() { } }; assert(!gotWrite); + callbacks.push(common.mustCall((cb, err, result) => { + assert.ifError(err); + assert.strictEqual(result, require('fs')); + cb(err, result); + })); putIn.run(['fs']); assert(gotWrite); } @@ -66,6 +86,11 @@ function test2() { const val = {}; global.url = val; assert(!gotWrite); + callbacks.push(common.mustCall((cb, err, result) => { + assert.ifError(err); + assert.strictEqual(result, val); + cb(err, result); + })); putIn.run(['url']); assert(gotWrite); } diff --git a/test/parallel/test-repl-context.js b/test/parallel/test-repl-context.js index 9d18067bc2aca4..90364cee694bb5 100644 --- a/test/parallel/test-repl-context.js +++ b/test/parallel/test-repl-context.js @@ -27,40 +27,57 @@ function testContext(repl) { repl.close(); } -testContextSideEffects(repl.start({ input: stream, output: stream })); +const replserver = repl.start({ input: stream, output: stream }); +const callbacks = []; +const $eval = replserver.eval; +replserver.eval = function(code, context, file, cb) { + const expected = callbacks.shift(); + return $eval.call(this, code, context, file, (...args) => { + try { + expected(cb, ...args); + } catch (e) { + console.error(e); + process.exit(1); + } + }); +}; +testContextSideEffects(replserver); function testContextSideEffects(server) { assert.ok(!server.underscoreAssigned); assert.strictEqual(server.lines.length, 0); // an assignment to '_' in the repl server - server.write('_ = 500;\n'); - assert.ok(server.underscoreAssigned); - assert.strictEqual(server.lines.length, 1); - assert.strictEqual(server.lines[0], '_ = 500;'); - assert.strictEqual(server.last, 500); + callbacks.push(common.mustCall((cb, ...args) => { + assert.ok(server.underscoreAssigned); + assert.strictEqual(server.last, 500); + cb(...args); + assert.strictEqual(server.lines.length, 1); + assert.strictEqual(server.lines[0], '_ = 500;'); - // use the server to create a new context - const context = server.createContext(); + // use the server to create a new context + const context = server.createContext(); - // ensure that creating a new context does not - // have side effects on the server - assert.ok(server.underscoreAssigned); - assert.strictEqual(server.lines.length, 1); - assert.strictEqual(server.lines[0], '_ = 500;'); - assert.strictEqual(server.last, 500); + // ensure that creating a new context does not + // have side effects on the server + assert.ok(server.underscoreAssigned); + assert.strictEqual(server.lines.length, 1); + assert.strictEqual(server.lines[0], '_ = 500;'); + assert.strictEqual(server.last, 500); - // reset the server context - server.resetContext(); - assert.ok(!server.underscoreAssigned); - assert.strictEqual(server.lines.length, 0); + // reset the server context + server.resetContext(); + assert.ok(!server.underscoreAssigned); + assert.strictEqual(server.lines.length, 0); - // ensure that assigning to '_' in the new context - // does not change the value in our server. - assert.ok(!server.underscoreAssigned); - vm.runInContext('_ = 1000;\n', context); + // ensure that assigning to '_' in the new context + // does not change the value in our server. + assert.ok(!server.underscoreAssigned); + vm.runInContext('_ = 1000;\n', context); - assert.ok(!server.underscoreAssigned); - assert.strictEqual(server.lines.length, 0); - server.close(); + assert.ok(!server.underscoreAssigned); + assert.strictEqual(server.lines.length, 0); + server.close(); + })); + server.write('_ = 500;\n'); } diff --git a/test/parallel/test-repl-end-emits-exit.js b/test/parallel/test-repl-end-emits-exit.js index 67f667eeb3d8db..dd9ad5c1eb0e56 100644 --- a/test/parallel/test-repl-end-emits-exit.js +++ b/test/parallel/test-repl-end-emits-exit.js @@ -21,10 +21,7 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const repl = require('repl'); -let terminalExit = 0; -let regularExit = 0; // Create a dummy stream that does nothing const stream = new common.ArrayStream(); @@ -41,11 +38,10 @@ function testTerminalMode() { stream.emit('data', '\u0004'); }); - r1.on('exit', function() { + r1.on('exit', common.mustCall(function() { // should be fired from the simulated ^D keypress - terminalExit++; testRegularMode(); - }); + })); } function testRegularMode() { @@ -59,17 +55,11 @@ function testRegularMode() { stream.emit('end'); }); - r2.on('exit', function() { + r2.on('exit', common.mustCall(function() { // should be fired from the simulated 'end' event - regularExit++; - }); + })); } -process.on('exit', function() { - assert.strictEqual(terminalExit, 1); - assert.strictEqual(regularExit, 1); -}); - // start testTerminalMode(); diff --git a/test/parallel/test-repl-eval-scope.js b/test/parallel/test-repl-eval-scope.js index 00b577cba73f76..83311fd92cd67b 100644 --- a/test/parallel/test-repl-eval-scope.js +++ b/test/parallel/test-repl-eval-scope.js @@ -3,21 +3,27 @@ const common = require('../common'); const assert = require('assert'); const repl = require('repl'); -{ - const stream = new common.ArrayStream(); - const options = { - eval: common.mustCall((cmd, context) => { - assert.strictEqual(cmd, '.scope\n'); - assert.deepStrictEqual(context, { animal: 'Sterrance' }); - }), - input: stream, - output: stream, - terminal: true - }; +const exitTests = []; +process.on('exit', () => { + for (const test of exitTests) test(); +}); +const CONTEXT = { animal: 'Sterrance' }; +const stream = new common.ArrayStream(); +const options = { + eval: common.mustCall((cmd, context) => { + // need to escape the domain + exitTests.push(common.mustCall(() => { + assert.strictEqual(cmd, '.scope'); + assert.ok(context === CONTEXT); + })); + }), + input: stream, + output: stream, + terminal: true +}; - const r = repl.start(options); - r.context = { animal: 'Sterrance' }; +const r = repl.start(options); +r.context = CONTEXT; - stream.emit('data', '\t'); - stream.emit('.exit\n'); -} +stream.emit('data', '\t'); +stream.emit('.exit\n'); diff --git a/test/parallel/test-repl-eval.js b/test/parallel/test-repl-eval.js index d775423fb74a52..d7290a1583da58 100644 --- a/test/parallel/test-repl-eval.js +++ b/test/parallel/test-repl-eval.js @@ -3,31 +3,31 @@ const common = require('../common'); const assert = require('assert'); const repl = require('repl'); -{ - let evalCalledWithExpectedArgs = false; +const exitTests = []; +process.on('exit', () => { + for (const test of exitTests) test(); +}); +const options = { + eval: common.mustCall((cmd, context) => { + // Assertions here will not cause the test to exit with an error code + // so set a boolean that is checked later instead. + exitTests.push(common.mustCall(() => { + assert.strictEqual(cmd, 'function f() {}\n'); + assert.strictEqual(context.foo, 'bar'); + })); + }) +}; - const options = { - eval: common.mustCall((cmd, context) => { - // Assertions here will not cause the test to exit with an error code - // so set a boolean that is checked later instead. - evalCalledWithExpectedArgs = (cmd === 'function f() {}\n' && - context.foo === 'bar'); - }) - }; +const r = repl.start(options); +r.context = { foo: 'bar' }; - const r = repl.start(options); - r.context = { foo: 'bar' }; - - try { - // Default preprocessor transforms - // function f() {} to - // var f = function f() {} - // Test to ensure that original input is preserved. - // Reference: https://github.com/nodejs/node/issues/9743 - r.write('function f() {}\n'); - } finally { - r.write('.exit\n'); - } - - assert(evalCalledWithExpectedArgs); +try { + // Default preprocessor transforms + // function f() {} to + // var f = function f() {} + // Test to ensure that original input is preserved. + // Reference: https://github.com/nodejs/node/issues/9743 + r.write('function f() {}\n'); +} finally { + r.write('.exit\n'); } diff --git a/test/parallel/test-repl-function-definition-edge-case.js b/test/parallel/test-repl-function-definition-edge-case.js index 1e3063e3db53ff..bda40594a8876a 100644 --- a/test/parallel/test-repl-function-definition-edge-case.js +++ b/test/parallel/test-repl-function-definition-edge-case.js @@ -7,32 +7,47 @@ const stream = require('stream'); common.globalCheck = false; -const r = initRepl(); - -r.input.emit('data', 'function a() { return 42; } (1)\n'); -r.input.emit('data', 'a\n'); -r.input.emit('data', '.exit'); - -const expected = '1\n[Function: a]\n'; -const got = r.output.accumulator.join(''); -assert.strictEqual(got, expected); - -function initRepl() { - const input = new stream(); - input.write = input.pause = input.resume = () => {}; - input.readable = true; - - const output = new stream(); - output.writable = true; - output.accumulator = []; - - output.write = (data) => output.accumulator.push(data); - - return repl.start({ - input, - output, - useColors: false, - terminal: false, - prompt: '' +const input = new stream(); +input.write = input.pause = input.resume = () => {}; +input.readable = true; + +const output = new stream(); +output.writable = true; +output.accumulator = []; + +output.write = (data) => output.accumulator.push(data); + +const replserver = repl.start({ + input, + output, + useColors: false, + terminal: false, + prompt: '' +}); +const callbacks = []; +const $eval = replserver.eval; +replserver.eval = function(code, context, file, cb) { + const expected = callbacks.shift(); + return $eval.call(this, code, context, file, (...args) => { + try { + expected(...args); + } catch (e) { + console.error(e); + process.exit(1); + } + cb(...args); }); -} +}; + +callbacks.push(common.mustCall((err, result) => { + assert.ifError(err); + assert.strictEqual(result, 1); +})); +replserver.input.emit('data', 'function a() { return 42; } (1)\n'); +callbacks.push(common.mustCall((err, result) => { + assert.ifError(err); + assert.strictEqual(typeof result, 'function'); + assert.strictEqual(result.toString(), 'function a() { return 42; }'); +})); +replserver.input.emit('data', 'a\n'); +replserver.input.emit('data', '.exit'); diff --git a/test/parallel/test-repl-load-multiline.js b/test/parallel/test-repl-load-multiline.js index 8ab878ae768ddd..922aef3d493901 100644 --- a/test/parallel/test-repl-load-multiline.js +++ b/test/parallel/test-repl-load-multiline.js @@ -36,5 +36,7 @@ const r = repl.start({ }); r.write(`${command}\n`); -assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected); +r.on('exit', common.mustCall(() => { + assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected); +})); r.close(); diff --git a/test/parallel/test-repl-mode.js b/test/parallel/test-repl-mode.js index 60b430d8c7ee31..39d7ff88cce905 100644 --- a/test/parallel/test-repl-mode.js +++ b/test/parallel/test-repl-mode.js @@ -19,35 +19,49 @@ tests.forEach(function(test) { function testSloppyMode() { const cli = initRepl(repl.REPL_MODE_SLOPPY); + cli.callbacks.push(common.mustCall((err, result) => { + assert.ifError(err); + assert.strictEqual(result, 3); + })); cli.input.emit('data', 'x = 3\n'); - assert.strictEqual(cli.output.accumulator.join(''), '> 3\n> '); - cli.output.accumulator.length = 0; + cli.callbacks.push(common.mustCall((err, result) => { + assert.ifError(err); + assert.strictEqual(result, undefined); + })); cli.input.emit('data', 'let y = 3\n'); - assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> '); } function testStrictMode() { const cli = initRepl(repl.REPL_MODE_STRICT); + cli._domain.once('error', common.mustCall((err) => { + assert.ok(err); + assert.ok(/ReferenceError: x is not defined/.test(err.message)); + })); cli.input.emit('data', 'x = 3\n'); - assert.ok(/ReferenceError: x is not defined/.test( - cli.output.accumulator.join(''))); - cli.output.accumulator.length = 0; + cli.callbacks.push(common.mustCall((err, result) => { + assert.ifError(err); + assert.strictEqual(result, undefined); + })); cli.input.emit('data', 'let y = 3\n'); - assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> '); } function testAutoMode() { const cli = initRepl(repl.REPL_MODE_MAGIC); + cli.callbacks.push(common.mustCall((err, result) => { + assert.ifError(err); + assert.strictEqual(result, 3); + })); cli.input.emit('data', 'x = 3\n'); - assert.strictEqual(cli.output.accumulator.join(''), '> 3\n> '); - cli.output.accumulator.length = 0; + cli.callbacks.push(common.mustCall((err, result) => { + assert.ifError(err); + assert.strictEqual(result, undefined); + })); cli.input.emit('data', 'let y = 3\n'); - assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> '); } function initRepl(mode) { @@ -62,11 +76,28 @@ function initRepl(mode) { output.accumulator = []; output.writable = true; - return repl.start({ + const replserver = repl.start({ input: input, output: output, useColors: false, terminal: false, replMode: mode }); + const callbacks = []; + const $eval = replserver.eval; + replserver.eval = function(code, context, file, cb) { + const expected = callbacks.shift(); + return $eval.call(this, code, context, file, (...args) => { + console.log('EVAL RET', args); + try { + expected(...args); + } catch (e) { + console.error(e); + process.exit(1); + } + cb(...args); + }); + }; + replserver.callbacks = callbacks; + return replserver; } diff --git a/test/parallel/test-repl-null-thrown.js b/test/parallel/test-repl-null-thrown.js index 1fe5d30396d534..9b78b0b1dc4d6d 100644 --- a/test/parallel/test-repl-null-thrown.js +++ b/test/parallel/test-repl-null-thrown.js @@ -1,5 +1,5 @@ 'use strict'; -require('../common'); +const common = require('../common'); const repl = require('repl'); const assert = require('assert'); const Stream = require('stream'); @@ -18,7 +18,6 @@ const replserver = repl.start({ replserver.emit('line', 'process.nextTick(() => { throw null; })'); replserver.emit('line', '.exit'); -setTimeout(() => { - console.log(text); +replserver.on('exit', common.mustCall(() => { assert(text.includes('Thrown: null')); -}, 0); +})); diff --git a/test/parallel/test-repl-null.js b/test/parallel/test-repl-null.js index 66d09b28f28b84..2748cfa780ee16 100644 --- a/test/parallel/test-repl-null.js +++ b/test/parallel/test-repl-null.js @@ -1,9 +1,28 @@ 'use strict'; -require('../common'); +const common = require('../common'); const repl = require('repl'); const assert = require('assert'); +const callbacks = [ + common.mustCall((err, value) => { + assert.ifError(err); + assert.strictEqual(value, undefined); + }) +]; const replserver = new repl.REPLServer(); +const $eval = replserver.eval; +replserver.eval = function(code, context, file, cb) { + const expected = callbacks.shift(); + return $eval.call(this, code, context, file, (...args) => { + try { + expected(...args); + } catch (e) { + console.error(e); + process.exit(1); + } + cb(...args); + }); +}; replserver._inTemplateLiteral = true; diff --git a/test/parallel/test-repl-pretty-custom-stack.js b/test/parallel/test-repl-pretty-custom-stack.js index be102c1d677a9c..0ca4039a5f8e36 100644 --- a/test/parallel/test-repl-pretty-custom-stack.js +++ b/test/parallel/test-repl-pretty-custom-stack.js @@ -22,7 +22,9 @@ function run({ command, expected }) { }); r.write(`${command}\n`); - assert.strictEqual(accum, expected); + r.on('exit', common.mustCall(() => { + assert.strictEqual(accum, expected); + })); r.close(); } diff --git a/test/parallel/test-repl-pretty-stack.js b/test/parallel/test-repl-pretty-stack.js index 0fc6b3ada04c79..55f37e1703e52d 100644 --- a/test/parallel/test-repl-pretty-stack.js +++ b/test/parallel/test-repl-pretty-stack.js @@ -22,7 +22,9 @@ function run({ command, expected }) { }); r.write(`${command}\n`); - assert.strictEqual(accum, expected); + r.on('exit', common.mustCall(() => { + assert.strictEqual(accum, expected); + })); r.close(); } diff --git a/test/parallel/test-repl-recoverable.js b/test/parallel/test-repl-recoverable.js index 6788d84595066c..c1767bbc4db03b 100644 --- a/test/parallel/test-repl-recoverable.js +++ b/test/parallel/test-repl-recoverable.js @@ -4,14 +4,11 @@ const common = require('../common'); const assert = require('assert'); const repl = require('repl'); -let evalCount = 0; let recovered = false; let rendered = false; function customEval(code, context, file, cb) { - evalCount++; - - return cb(evalCount === 1 ? new repl.Recoverable() : null, true); + return cb(!recovered ? new repl.Recoverable() : null, true); } const putIn = new common.ArrayStream(); @@ -26,7 +23,7 @@ putIn.write = function(msg) { } }; -repl.start('', putIn, customEval); +repl.start('', putIn, common.mustCall(customEval, 2)); // https://github.com/nodejs/node/issues/2939 // Expose recoverable errors to the consumer. @@ -36,5 +33,4 @@ putIn.emit('data', '2\n'); process.on('exit', function() { assert(recovered, 'REPL never recovered'); assert(rendered, 'REPL never rendered the result'); - assert.strictEqual(evalCount, 2); }); diff --git a/test/parallel/test-repl-throw-null-or-undefined.js b/test/parallel/test-repl-throw-null-or-undefined.js index fd2fd202b5bcb6..ef25dbe015de88 100644 --- a/test/parallel/test-repl-throw-null-or-undefined.js +++ b/test/parallel/test-repl-throw-null-or-undefined.js @@ -1,18 +1,20 @@ 'use strict'; -require('../common'); +const common = require('../common'); // This test ensures that the repl does not // crash or emit error when throwing `null|undefined` // ie `throw null` or `throw undefined` -const assert = require('assert'); const repl = require('repl'); -const r = repl.start(); +const replserver = repl.start(); +const $eval = replserver.eval; +replserver.eval = function(code, context, file, cb) { + return $eval.call(this, code, context, file, + common.mustNotCall( + 'repl crashes/throw error on `throw null|undefined`')); +}; +replserver.write('throw null\n'); +replserver.write('throw undefined\n'); -assert.doesNotThrow(() => { - r.write('throw null\n'); - r.write('throw undefined\n'); -}, TypeError, 'repl crashes/throw error on `throw null|undefined`'); - -r.write('.exit\n'); +replserver.write('.exit\n'); diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js index 91f32223e180b9..1b22dcc7221a7f 100644 --- a/test/parallel/test-repl-underscore.js +++ b/test/parallel/test-repl-underscore.js @@ -28,20 +28,22 @@ function testSloppyMode() { _; // remains 30 from user input `); - assertOutput(r.output, [ - 'undefined', - 'undefined', - 'undefined', - '10', - '10', - 'Expression assignment to _ now disabled.', - '20', - '20', - '30', - '30', - '40', - '30' - ]); + r.on('exit', () => { + assertOutput(r.output, [ + 'undefined', + 'undefined', + 'undefined', + '10', + '10', + 'Expression assignment to _ now disabled.', + '20', + '20', + '30', + '30', + '40', + '30' + ]); + }); } function testStrictMode() { @@ -61,20 +63,22 @@ function testStrictMode() { _; // remains 30 from user input `); - assertOutput(r.output, [ - 'undefined', - 'undefined', - 'undefined', - 'undefined', - '20', - '30', - '30', - 'undefined', - '30', - 'undefined', - 'undefined', - '30' - ]); + r.on('exit', () => { + assertOutput(r.output, [ + 'undefined', + 'undefined', + 'undefined', + 'undefined', + '20', + '30', + '30', + 'undefined', + '30', + 'undefined', + 'undefined', + '30' + ]); + }); } function testMagicMode() { @@ -94,20 +98,22 @@ function testMagicMode() { _; // remains 30 from user input `); - assertOutput(r.output, [ - 'undefined', - '10', - '10', - 'undefined', - '20', - '30', - '30', - 'undefined', - '30', - 'undefined', - '50', - '30' - ]); + r.on('exit', () => { + assertOutput(r.output, [ + 'undefined', + '10', + '10', + 'undefined', + '20', + '30', + '30', + 'undefined', + '30', + 'undefined', + '50', + '30' + ]); + }); } function testResetContext() { @@ -121,15 +127,17 @@ function testResetContext() { _; // expect 20 `); - assertOutput(r.output, [ - 'Expression assignment to _ now disabled.', - '10', - '10', - 'Clearing context...', - '10', - '20', - '20' - ]); + r.on('exit', () => { + assertOutput(r.output, [ + 'Expression assignment to _ now disabled.', + '10', + '10', + 'Clearing context...', + '10', + '20', + '20' + ]); + }); } function testResetContextGlobal() { @@ -141,12 +149,14 @@ function testResetContextGlobal() { _; // remains 10 `); - assertOutput(r.output, [ - 'Expression assignment to _ now disabled.', - '10', - '10', - '10', - ]); + r.on('exit', () => { + assertOutput(r.output, [ + 'Expression assignment to _ now disabled.', + '10', + '10', + '10', + ]); + }); // delete globals leaked by REPL when `useGlobal` is `true` delete global.module; diff --git a/test/parallel/test-repl-use-global.js b/test/parallel/test-repl-use-global.js index c76505272b2682..75646a9c00aae7 100644 --- a/test/parallel/test-repl-use-global.js +++ b/test/parallel/test-repl-use-global.js @@ -7,13 +7,6 @@ const stream = require('stream'); const repl = require('internal/repl'); const assert = require('assert'); -// Array of [useGlobal, expectedResult] pairs -const globalTestCases = [ - [false, 'undefined'], - [true, '\'tacos\''], - [undefined, 'undefined'] -]; - const globalTest = (useGlobal, cb, output) => (err, repl) => { if (err) return cb(err); @@ -26,26 +19,12 @@ const globalTest = (useGlobal, cb, output) => (err, repl) => { global.lunch = 'tacos'; repl.write('global.lunch;\n'); repl.close(); - delete global.lunch; - cb(null, str.trim()); -}; - -// Test how the global object behaves in each state for useGlobal -for (const [option, expected] of globalTestCases) { - runRepl(option, globalTest, common.mustCall((err, output) => { - assert.ifError(err); - assert.strictEqual(output, expected); + repl.on('exit', common.mustCall(() => { + delete global.lunch; + cb(null, str.trim()); })); -} +}; -// Test how shadowing the process object via `let` -// behaves in each useGlobal state. Note: we can't -// actually test the state when useGlobal is true, -// because the exception that's generated is caught -// (see below), but errors are printed, and the test -// suite is aware of it, causing a failure to be flagged. -// -const processTestCases = [false, undefined]; const processTest = (useGlobal, cb, output) => (err, repl) => { if (err) return cb(err); @@ -57,15 +36,37 @@ const processTest = (useGlobal, cb, output) => (err, repl) => { repl.write('let process;\n'); repl.write('21 * 2;\n'); repl.close(); - cb(null, str.trim()); -}; - -for (const option of processTestCases) { - runRepl(option, processTest, common.mustCall((err, output) => { + repl.on('exit', common.mustCall((err) => { assert.ifError(err); - assert.strictEqual(output, 'undefined\n42'); + cb(null, str.trim()); })); -} +}; + +// Array of [useGlobal, expectedResult, fn] pairs +const testCases = [ + // Test how the global object behaves in each state for useGlobal + [false, 'undefined', globalTest], + [true, '\'tacos\'', globalTest], + [undefined, 'undefined', globalTest], + // Test how shadowing the process object via `let` + // behaves in each useGlobal state. Note: we can't + // actually test the state when useGlobal is true, + // because the exception that's generated is caught + // (see below), but errors are printed, and the test + // suite is aware of it, causing a failure to be flagged. + [false, 'undefined\n42', processTest] +]; + +const next = common.mustCall(() => { + if (testCases.length) { + const [option, expected, runner] = testCases.shift(); + runRepl(option, runner, common.mustCall((err, output) => { + assert.strictEqual(output, expected); + next(); + })); + } +}, testCases.length + 1); +next(); function runRepl(useGlobal, testFunc, cb) { const inputStream = new stream.PassThrough(); From 180af17b522f531eb15b917f4fde9570b6aa95ae Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 1 Feb 2018 02:28:39 +0100 Subject: [PATCH 055/193] string_decoder: reimplement in C++ Implement string decoder in C++. The perks are a decent speed boost (for decoding, whereas creation show some performance degradation), that this can now be used more easily to add native decoding support to C++ streams and (arguably) more readable variable names. PR-URL: https://github.com/nodejs/node/pull/18537 Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis --- lib/string_decoder.js | 285 ++++------------------- node.gyp | 4 + src/node_internals.h | 1 + src/string_decoder-inl.h | 38 +++ src/string_decoder.cc | 334 +++++++++++++++++++++++++++ src/string_decoder.h | 50 ++++ test/parallel/test-string-decoder.js | 4 + 7 files changed, 478 insertions(+), 238 deletions(-) create mode 100644 src/string_decoder-inl.h create mode 100644 src/string_decoder.cc create mode 100644 src/string_decoder.h diff --git a/lib/string_decoder.js b/lib/string_decoder.js index 1e569ba6b26a4c..d955a663307de9 100644 --- a/lib/string_decoder.js +++ b/lib/string_decoder.js @@ -22,10 +22,23 @@ 'use strict'; const { Buffer } = require('buffer'); +const { + kIncompleteCharactersStart, + kIncompleteCharactersEnd, + kMissingBytes, + kBufferedBytes, + kEncodingField, + kSize, + decode, + flush, + encodings +} = internalBinding('string_decoder'); const internalUtil = require('internal/util'); const errors = require('internal/errors'); const isEncoding = Buffer[internalUtil.kIsEncodingSymbol]; +const kNativeDecoder = Symbol('kNativeDecoder'); + // Do not cache `Buffer.isEncoding` when checking encoding names as some // modules monkey-patch it to support additional encodings function normalizeEncoding(enc) { @@ -36,258 +49,54 @@ function normalizeEncoding(enc) { return nenc || enc; } +const encodingsMap = {}; +for (var i = 0; i < encodings.length; ++i) + encodingsMap[encodings[i]] = i; + // StringDecoder provides an interface for efficiently splitting a series of // buffers into a series of JS strings without breaking apart multi-byte // characters. -exports.StringDecoder = StringDecoder; -function StringDecoder(encoding) { - this.encoding = normalizeEncoding(encoding); - var nb; - switch (this.encoding) { - case 'utf16le': - this.text = utf16Text; - this.end = utf16End; - nb = 4; - break; - case 'utf8': - this.fillLast = utf8FillLast; - nb = 4; - break; - case 'base64': - this.text = base64Text; - this.end = base64End; - nb = 3; - break; - default: - this.write = simpleWrite; - this.end = simpleEnd; - return; - } - this.lastNeed = 0; - this.lastTotal = 0; - this.lastChar = Buffer.allocUnsafe(nb); -} - -StringDecoder.prototype.write = function(buf) { - if (buf.length === 0) - return ''; - var r; - var i; - if (this.lastNeed) { - r = this.fillLast(buf); - if (r === undefined) - return ''; - i = this.lastNeed; - this.lastNeed = 0; - } else { - i = 0; - } - if (i < buf.length) - return (r ? r + this.text(buf, i) : this.text(buf, i)); - return r || ''; -}; - -StringDecoder.prototype.end = utf8End; - -// Returns only complete characters in a Buffer -StringDecoder.prototype.text = utf8Text; - -// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer -StringDecoder.prototype.fillLast = function(buf) { - if (this.lastNeed <= buf.length) { - buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); - return this.lastChar.toString(this.encoding, 0, this.lastTotal); - } - buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); - this.lastNeed -= buf.length; -}; - -// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a -// continuation byte. If an invalid byte is detected, -2 is returned. -function utf8CheckByte(byte) { - if (byte <= 0x7F) - return 0; - else if (byte >> 5 === 0x06) - return 2; - else if (byte >> 4 === 0x0E) - return 3; - else if (byte >> 3 === 0x1E) - return 4; - return (byte >> 6 === 0x02 ? -1 : -2); -} - -// Checks at most 3 bytes at the end of a Buffer in order to detect an -// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) -// needed to complete the UTF-8 character (if applicable) are returned. -function utf8CheckIncomplete(self, buf, i) { - var j = buf.length - 1; - if (j < i) - return 0; - var nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) - self.lastNeed = nb - 1; - return nb; - } - if (--j < i || nb === -2) - return 0; - nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) - self.lastNeed = nb - 2; - return nb; - } - if (--j < i || nb === -2) - return 0; - nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) { - if (nb === 2) - nb = 0; - else - self.lastNeed = nb - 3; - } - return nb; - } - return 0; -} - -// Validates as many continuation bytes for a multi-byte UTF-8 character as -// needed or are available. If we see a non-continuation byte where we expect -// one, we "replace" the validated continuation bytes we've seen so far with -// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding -// behavior. The continuation byte check is included three times in the case -// where all of the continuation bytes for a character exist in the same buffer. -// It is also done this way as a slight performance increase instead of using a -// loop. -function utf8CheckExtraBytes(self, buf, p) { - if ((buf[0] & 0xC0) !== 0x80) { - self.lastNeed = 0; - return '\ufffd'; - } - if (self.lastNeed > 1 && buf.length > 1) { - if ((buf[1] & 0xC0) !== 0x80) { - self.lastNeed = 1; - return '\ufffd'; - } - if (self.lastNeed > 2 && buf.length > 2) { - if ((buf[2] & 0xC0) !== 0x80) { - self.lastNeed = 2; - return '\ufffd'; - } - } +class StringDecoder { + constructor(encoding) { + this.encoding = normalizeEncoding(encoding); + this[kNativeDecoder] = Buffer.alloc(kSize); + this[kNativeDecoder][kEncodingField] = encodingsMap[this.encoding]; } -} -// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. -function utf8FillLast(buf) { - const p = this.lastTotal - this.lastNeed; - var r = utf8CheckExtraBytes(this, buf, p); - if (r !== undefined) - return r; - if (this.lastNeed <= buf.length) { - buf.copy(this.lastChar, p, 0, this.lastNeed); - return this.lastChar.toString(this.encoding, 0, this.lastTotal); + write(buf) { + if (typeof buf === 'string') + return buf; + if (!ArrayBuffer.isView(buf)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buf', + ['Buffer', 'Uint8Array', 'ArrayBufferView']); + return decode(this[kNativeDecoder], buf); } - buf.copy(this.lastChar, p, 0, buf.length); - this.lastNeed -= buf.length; -} -// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a -// partial character, the character's bytes are buffered until the required -// number of bytes are available. -function utf8Text(buf, i) { - const total = utf8CheckIncomplete(this, buf, i); - if (!this.lastNeed) - return buf.toString('utf8', i); - this.lastTotal = total; - const end = buf.length - (total - this.lastNeed); - buf.copy(this.lastChar, 0, end); - return buf.toString('utf8', i, end); -} - -// For UTF-8, a replacement character is added when ending on a partial -// character. -function utf8End(buf) { - const r = (buf && buf.length ? this.write(buf) : ''); - if (this.lastNeed) { - this.lastNeed = 0; - this.lastTotal = 0; - return r + '\ufffd'; + end(buf) { + let ret = ''; + if (buf !== undefined) + ret = this.write(buf); + if (this[kNativeDecoder][kBufferedBytes] > 0) + ret += flush(this[kNativeDecoder]); + return ret; } - return r; -} -// UTF-16LE typically needs two bytes per character, but even if we have an even -// number of bytes available, we need to check if we end on a leading/high -// surrogate. In that case, we need to wait for the next two bytes in order to -// decode the last character properly. -function utf16Text(buf, i) { - if ((buf.length - i) % 2 === 0) { - const r = buf.toString('utf16le', i); - if (r) { - const c = r.charCodeAt(r.length - 1); - if (c >= 0xD800 && c <= 0xDBFF) { - this.lastNeed = 2; - this.lastTotal = 4; - this.lastChar[0] = buf[buf.length - 2]; - this.lastChar[1] = buf[buf.length - 1]; - return r.slice(0, -1); - } - } - return r; - } - this.lastNeed = 1; - this.lastTotal = 2; - this.lastChar[0] = buf[buf.length - 1]; - return buf.toString('utf16le', i, buf.length - 1); -} + /* Everything below this line is undocumented legacy stuff. */ -// For UTF-16LE we do not explicitly append special replacement characters if we -// end on a partial character, we simply let v8 handle that. -function utf16End(buf) { - const r = (buf && buf.length ? this.write(buf) : ''); - if (this.lastNeed) { - const end = this.lastTotal - this.lastNeed; - this.lastNeed = 0; - this.lastTotal = 0; - return r + this.lastChar.toString('utf16le', 0, end); + text(buf, offset) { + this[kNativeDecoder][kMissingBytes] = 0; + this[kNativeDecoder][kBufferedBytes] = 0; + return this.write(buf.slice(offset)); } - return r; -} -function base64Text(buf, i) { - const n = (buf.length - i) % 3; - if (n === 0) - return buf.toString('base64', i); - this.lastNeed = 3 - n; - this.lastTotal = 3; - if (n === 1) { - this.lastChar[0] = buf[buf.length - 1]; - } else { - this.lastChar[0] = buf[buf.length - 2]; - this.lastChar[1] = buf[buf.length - 1]; + get lastTotal() { + return this[kNativeDecoder][kBufferedBytes] + this.lastNeed; } - return buf.toString('base64', i, buf.length - n); -} - -function base64End(buf) { - const r = (buf && buf.length ? this.write(buf) : ''); - if (this.lastNeed) { - const end = 3 - this.lastNeed; - this.lastNeed = 0; - this.lastTotal = 0; - return r + this.lastChar.toString('base64', 0, end); + get lastChar() { + return this[kNativeDecoder].subarray(kIncompleteCharactersStart, + kIncompleteCharactersEnd); } - return r; } -// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) -function simpleWrite(buf) { - return buf.toString(this.encoding); -} - -function simpleEnd(buf) { - return (buf && buf.length ? this.write(buf) : ''); -} +exports.StringDecoder = StringDecoder; diff --git a/node.gyp b/node.gyp index 9c398284939b50..e2b17cd2b5fae6 100644 --- a/node.gyp +++ b/node.gyp @@ -326,6 +326,7 @@ 'src/signal_wrap.cc', 'src/spawn_sync.cc', 'src/string_bytes.cc', + 'src/string_decoder.cc', 'src/string_search.cc', 'src/stream_base.cc', 'src/stream_wrap.cc', @@ -379,6 +380,8 @@ 'src/req_wrap.h', 'src/req_wrap-inl.h', 'src/string_bytes.h', + 'src/string_decoder.h', + 'src/string_decoder-inl.h', 'src/stream_base.h', 'src/stream_base-inl.h', 'src/stream_wrap.h', @@ -989,6 +992,7 @@ '<(obj_path)<(obj_separator)node_url.<(obj_suffix)', '<(obj_path)<(obj_separator)util.<(obj_suffix)', '<(obj_path)<(obj_separator)string_bytes.<(obj_suffix)', + '<(obj_path)<(obj_separator)string_decoder.<(obj_suffix)', '<(obj_path)<(obj_separator)string_search.<(obj_suffix)', '<(obj_path)<(obj_separator)stream_base.<(obj_suffix)', '<(obj_path)<(obj_separator)node_constants.<(obj_suffix)', diff --git a/src/node_internals.h b/src/node_internals.h index b3e1f5cd9f270c..094fcc2d839d5f 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -120,6 +120,7 @@ struct sockaddr; V(signal_wrap) \ V(spawn_sync) \ V(stream_wrap) \ + V(string_decoder) \ V(tcp_wrap) \ V(timer_wrap) \ V(trace_events) \ diff --git a/src/string_decoder-inl.h b/src/string_decoder-inl.h new file mode 100644 index 00000000000000..8a04211906f759 --- /dev/null +++ b/src/string_decoder-inl.h @@ -0,0 +1,38 @@ +#ifndef SRC_STRING_DECODER_INL_H_ +#define SRC_STRING_DECODER_INL_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "string_decoder.h" +#include "util.h" + +namespace node { + +void StringDecoder::SetEncoding(enum encoding encoding) { + state_[kBufferedBytes] = 0; + state_[kMissingBytes] = 0; + state_[kEncodingField] = encoding; +} + +enum encoding StringDecoder::Encoding() const { + return static_cast(state_[kEncodingField]); +} + +unsigned StringDecoder::BufferedBytes() const { + return state_[kBufferedBytes]; +} + +unsigned StringDecoder::MissingBytes() const { + return state_[kMissingBytes]; +} + +char* StringDecoder::IncompleteCharacterBuffer() { + return reinterpret_cast(state_ + kIncompleteCharactersStart); +} + + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_STRING_DECODER_INL_H_ diff --git a/src/string_decoder.cc b/src/string_decoder.cc new file mode 100644 index 00000000000000..ad1bace918c678 --- /dev/null +++ b/src/string_decoder.cc @@ -0,0 +1,334 @@ +#include "string_decoder-inl.h" +#include "string_bytes.h" +#include "node_internals.h" +#include "node_buffer.h" + +using v8::Array; +using v8::Context; +using v8::FunctionCallbackInfo; +using v8::Integer; +using v8::Isolate; +using v8::Local; +using v8::MaybeLocal; +using v8::Object; +using v8::String; +using v8::Value; + +namespace node { + +namespace { + +MaybeLocal MakeString(Isolate* isolate, + const char* data, + size_t length, + enum encoding encoding) { + Local error; + MaybeLocal ret; + if (encoding == UTF8) { + return String::NewFromUtf8( + isolate, + data, + v8::NewStringType::kNormal, + length); + } else if (encoding == UCS2) { +#ifdef DEBUG + CHECK_EQ(reinterpret_cast(data) % 2, 0); + CHECK_EQ(length % 2, 0); +#endif + ret = StringBytes::Encode( + isolate, + reinterpret_cast(data), + length / 2, + &error); + } else { + ret = StringBytes::Encode( + isolate, + data, + length, + encoding, + &error); + } + + if (ret.IsEmpty()) { + CHECK(!error.IsEmpty()); + isolate->ThrowException(error); + } + +#ifdef DEBUG + CHECK(ret.IsEmpty() || ret.ToLocalChecked()->IsString()); +#endif + return ret.FromMaybe(Local()).As(); +} + +} // anonymous namespace + + +MaybeLocal StringDecoder::DecodeData(Isolate* isolate, + const char* data, + size_t* nread_ptr) { + Local prepend, body; + + size_t nread = *nread_ptr; + + if (Encoding() == UTF8 || Encoding() == UCS2 || Encoding() == BASE64) { + // See if we want bytes to finish a character from the previous + // chunk; if so, copy the new bytes to the missing bytes buffer + // and create a small string from it that is to be prepended to the + // main body. + if (MissingBytes() > 0) { + // There are never more bytes missing than the pre-calculated maximum. + CHECK_LE(MissingBytes() + BufferedBytes(), + kIncompleteCharactersEnd); + if (Encoding() == UTF8) { + // For UTF-8, we need special treatment to align with the V8 decoder: + // If an incomplete character is found at a chunk boundary, we turn + // that character into a single invalid one. + for (size_t i = 0; i < nread && i < MissingBytes(); ++i) { + if ((data[i] & 0xC0) != 0x80) { + // This byte is not a continuation byte even though it should have + // been one. + // Act as if there was a 1-byte incomplete character, which does + // not make sense but works here because we know it's invalid. + state_[kMissingBytes] = 0; + state_[kBufferedBytes] = 1; + data += i; + nread -= i; + break; + } + } + } + + size_t found_bytes = + std::min(nread, static_cast(MissingBytes())); + memcpy(IncompleteCharacterBuffer() + BufferedBytes(), + data, + found_bytes); + // Adjust the two buffers. + data += found_bytes; + nread -= found_bytes; + + state_[kMissingBytes] -= found_bytes; + state_[kBufferedBytes] += found_bytes; + + if (LIKELY(MissingBytes() == 0)) { + // If no more bytes are missing, create a small string that we + // will later prepend. + if (!MakeString(isolate, + IncompleteCharacterBuffer(), + BufferedBytes(), + Encoding()).ToLocal(&prepend)) { + return MaybeLocal(); + } + + *nread_ptr += BufferedBytes(); + // No more buffered bytes. + state_[kBufferedBytes] = 0; + } + } + + // It could be that trying to finish the previous chunk already + // consumed all data that we received in this chunk. + if (UNLIKELY(nread == 0)) { + body = !prepend.IsEmpty() ? prepend : String::Empty(isolate); + prepend = Local(); + } else { +#ifdef DEBUG + // If not, that means is no character left to finish at this point. + CHECK_EQ(MissingBytes(), 0); + CHECK_EQ(BufferedBytes(), 0); +#endif + + // See whether there is a character that we may have to cut off and + // finish when receiving the next chunk. + if (Encoding() == UTF8 && data[nread - 1] & 0x80) { + // This is UTF-8 encoded data and we ended on a non-ASCII UTF-8 byte. + // This means we'll need to figure out where the character to which + // the byte belongs begins. + for (size_t i = nread - 1; ; --i) { +#ifdef DEBUG + CHECK_LT(i, nread); +#endif + state_[kBufferedBytes]++; + if ((data[i] & 0xC0) == 0x80) { + // This byte does not start a character (a "trailing" byte). + if (state_[kBufferedBytes] >= 4 || i == 0) { + // We either have more then 4 trailing bytes (which means + // the current character would not be inside the range for + // valid Unicode, and in particular cannot be represented + // through JavaScript's UTF-16-based approach to strings), or the + // current buffer does not contain the start of an UTF-8 character + // at all. Either way, this is invalid UTF8 and we can just + // let the engine's decoder handle it. + state_[kBufferedBytes] = 0; + break; + } + } else { + // Found the first byte of a UTF-8 character. By looking at the + // upper bits we can tell how long the character *should* be. + if ((data[i] & 0xE0) == 0xC0) { + state_[kMissingBytes] = 2; + } else if ((data[i] & 0xF0) == 0xE0) { + state_[kMissingBytes] = 3; + } else if ((data[i] & 0xF8) == 0xF0) { + state_[kMissingBytes] = 4; + } else { + // This lead byte would indicate a character outside of the + // representable range. + state_[kBufferedBytes] = 0; + break; + } + + if (BufferedBytes() >= MissingBytes()) { + // Received more or exactly as many trailing bytes than the lead + // character would indicate. In the "==" case, we have valid + // data and don't need to slice anything off; + // in the ">" case, this is invalid UTF-8 anyway. + state_[kMissingBytes] = 0; + state_[kBufferedBytes] = 0; + } + + state_[kMissingBytes] -= state_[kBufferedBytes]; + break; + } + } + } else if (Encoding() == UCS2) { + if ((nread % 2) == 1) { + // We got half a codepoint, and need the second byte of it. + state_[kBufferedBytes] = 1; + state_[kMissingBytes] = 1; + } else if ((data[nread - 1] & 0xFC) == 0xD8) { + // Half a split UTF-16 character. + state_[kBufferedBytes] = 2; + state_[kMissingBytes] = 2; + } + } else if (Encoding() == BASE64) { + state_[kBufferedBytes] = nread % 3; + if (state_[kBufferedBytes] > 0) + state_[kMissingBytes] = 3 - BufferedBytes(); + } + + if (BufferedBytes() > 0) { + // Copy the requested number of buffered bytes from the end of the + // input into the incomplete character buffer. + nread -= BufferedBytes(); + *nread_ptr -= BufferedBytes(); + memcpy(IncompleteCharacterBuffer(), data + nread, BufferedBytes()); + } + + if (nread > 0) { + if (!MakeString(isolate, data, nread, Encoding()).ToLocal(&body)) + return MaybeLocal(); + } else { + body = String::Empty(isolate); + } + } + + if (prepend.IsEmpty()) { + return body; + } else { + return String::Concat(prepend, body); + } + } else { + CHECK(Encoding() == ASCII || Encoding() == HEX || Encoding() == LATIN1); + return MakeString(isolate, data, nread, Encoding()); + } +} + +MaybeLocal StringDecoder::FlushData(Isolate* isolate) { + if (Encoding() == ASCII || Encoding() == HEX || Encoding() == LATIN1) { + CHECK_EQ(MissingBytes(), 0); + CHECK_EQ(BufferedBytes(), 0); + } + + if (Encoding() == UCS2 && BufferedBytes() % 2 == 1) { + // Ignore a single trailing byte, like the JS decoder does. + state_[kMissingBytes]--; + state_[kBufferedBytes]--; + } + + if (BufferedBytes() == 0) + return String::Empty(isolate); + + MaybeLocal ret = + MakeString(isolate, + IncompleteCharacterBuffer(), + BufferedBytes(), + Encoding()); + + state_[kMissingBytes] = 0; + state_[kBufferedBytes] = 0; + + return ret; +} + +namespace { + +void DecodeData(const FunctionCallbackInfo& args) { + StringDecoder* decoder = + reinterpret_cast(Buffer::Data(args[0])); + CHECK_NE(decoder, nullptr); + size_t nread = Buffer::Length(args[1]); + MaybeLocal ret = + decoder->DecodeData(args.GetIsolate(), Buffer::Data(args[1]), &nread); + if (!ret.IsEmpty()) + args.GetReturnValue().Set(ret.ToLocalChecked()); +} + +void FlushData(const FunctionCallbackInfo& args) { + StringDecoder* decoder = + reinterpret_cast(Buffer::Data(args[0])); + CHECK_NE(decoder, nullptr); + MaybeLocal ret = decoder->FlushData(args.GetIsolate()); + if (!ret.IsEmpty()) + args.GetReturnValue().Set(ret.ToLocalChecked()); +} + +void InitializeStringDecoder(Local target, + Local unused, + Local context) { + Environment* env = Environment::GetCurrent(context); + Isolate* isolate = env->isolate(); + +#define SET_DECODER_CONSTANT(name) \ + target->Set(context, \ + FIXED_ONE_BYTE_STRING(isolate, #name), \ + Integer::New(isolate, StringDecoder::name)).FromJust() + + SET_DECODER_CONSTANT(kIncompleteCharactersStart); + SET_DECODER_CONSTANT(kIncompleteCharactersEnd); + SET_DECODER_CONSTANT(kMissingBytes); + SET_DECODER_CONSTANT(kBufferedBytes); + SET_DECODER_CONSTANT(kEncodingField); + SET_DECODER_CONSTANT(kNumFields); + + Local encodings = Array::New(isolate); +#define ADD_TO_ENCODINGS_ARRAY(cname, jsname) \ + encodings->Set(context, \ + static_cast(cname), \ + FIXED_ONE_BYTE_STRING(isolate, jsname)).FromJust() + ADD_TO_ENCODINGS_ARRAY(ASCII, "ascii"); + ADD_TO_ENCODINGS_ARRAY(UTF8, "utf8"); + ADD_TO_ENCODINGS_ARRAY(BASE64, "base64"); + ADD_TO_ENCODINGS_ARRAY(UCS2, "utf16le"); + ADD_TO_ENCODINGS_ARRAY(HEX, "hex"); + ADD_TO_ENCODINGS_ARRAY(BUFFER, "buffer"); + ADD_TO_ENCODINGS_ARRAY(LATIN1, "latin1"); + + target->Set(context, + FIXED_ONE_BYTE_STRING(isolate, "encodings"), + encodings).FromJust(); + + target->Set(context, + FIXED_ONE_BYTE_STRING(isolate, "kSize"), + Integer::New(isolate, sizeof(StringDecoder))).FromJust(); + + env->SetMethod(target, "decode", DecodeData); + env->SetMethod(target, "flush", FlushData); +} + +} // anonymous namespace + +} // namespace node + +NODE_MODULE_CONTEXT_AWARE_INTERNAL(string_decoder, + node::InitializeStringDecoder) diff --git a/src/string_decoder.h b/src/string_decoder.h new file mode 100644 index 00000000000000..9059eeaa9d2eb7 --- /dev/null +++ b/src/string_decoder.h @@ -0,0 +1,50 @@ +#ifndef SRC_STRING_DECODER_H_ +#define SRC_STRING_DECODER_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "node.h" + +namespace node { + +class StringDecoder { + public: + StringDecoder() { state_[kEncodingField] = BUFFER; } + inline void SetEncoding(enum encoding encoding); + inline enum encoding Encoding() const; + + inline char* IncompleteCharacterBuffer(); + inline unsigned MissingBytes() const; + inline unsigned BufferedBytes() const; + + // Decode a string from the specified encoding. + // The value pointed to by `nread` will be modified to reflect that + // less data may have been read because it ended on an incomplete character + // and more data may have been read because a previously incomplete character + // was finished. + v8::MaybeLocal DecodeData(v8::Isolate* isolate, + const char* data, + size_t* nread); + // Flush an incomplete character. For character encodings like UTF8 this + // means printing replacement characters, buf for e.g. Base64 the returned + // string contains more data. + v8::MaybeLocal FlushData(v8::Isolate* isolate); + + enum Fields { + kIncompleteCharactersStart = 0, + kIncompleteCharactersEnd = 4, + kMissingBytes = 4, + kBufferedBytes = 5, + kEncodingField = 6, + kNumFields = 7 + }; + + private: + uint8_t state_[kNumFields] = {}; +}; + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_STRING_DECODER_H_ diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js index 9d1fe69a25df73..21a0b6c3e38539 100644 --- a/test/parallel/test-string-decoder.js +++ b/test/parallel/test-string-decoder.js @@ -128,6 +128,10 @@ assert.strictEqual(decoder.write(Buffer.from('3DD8', 'hex')), ''); assert.strictEqual(decoder.write(Buffer.from('4D', 'hex')), ''); assert.strictEqual(decoder.end(), '\ud83d'); +decoder = new StringDecoder('utf16le'); +assert.strictEqual(decoder.write(Buffer.from('3DD84D', 'hex')), '\ud83d'); +assert.strictEqual(decoder.end(), ''); + common.expectsError( () => new StringDecoder(1), { From 93bbe4e3ee034d22657e263a2fc6972589e6723f Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 4 Feb 2018 19:32:26 +0100 Subject: [PATCH 056/193] deps,src: align ssize_t ABI between Node & nghttp2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, we performed casts that are considered undefined behavior. Instead, just define `ssize_t` for nghttp2 the same way we define it for the rest of Node. Also, remove a TODO comment that would probably also be *technically* correct but shouldn’t matter as long as nobody is complaining. PR-URL: https://github.com/nodejs/node/pull/18565 Reviewed-By: Matteo Collina Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- deps/nghttp2/lib/includes/config.h | 14 ++++++++++++-- src/node.h | 1 - src/node_http2.cc | 13 ++----------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/deps/nghttp2/lib/includes/config.h b/deps/nghttp2/lib/includes/config.h index 0346e0614fdb8d..242bbcfb62ff7a 100644 --- a/deps/nghttp2/lib/includes/config.h +++ b/deps/nghttp2/lib/includes/config.h @@ -1,8 +1,18 @@ /* Hint to the compiler that a function never returns */ #define NGHTTP2_NORETURN -/* Define to `int' if does not define. */ -#define ssize_t int +/* Edited to match src/node.h. */ +#include + +#ifdef _WIN32 +#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) +typedef intptr_t ssize_t; +# define _SSIZE_T_ +# define _SSIZE_T_DEFINED +#endif +#else // !_WIN32 +# include // size_t, ssize_t +#endif // _WIN32 /* Define to 1 if you have the `std::map::emplace`. */ #define HAVE_STD_MAP_EMPLACE 1 diff --git a/src/node.h b/src/node.h index e6f47aa30075c4..89dbdfc727b0c5 100644 --- a/src/node.h +++ b/src/node.h @@ -184,7 +184,6 @@ NODE_EXTERN v8::Local MakeCallback( #endif #ifdef _WIN32 -// TODO(tjfontaine) consider changing the usage of ssize_t to ptrdiff_t #if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) typedef intptr_t ssize_t; # define _SSIZE_T_ diff --git a/src/node_http2.cc b/src/node_http2.cc index bd2e93a13c208b..2f688a4b352a15 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -764,13 +764,7 @@ inline ssize_t Http2Session::Write(const uv_buf_t* bufs, size_t nbufs) { bufs[n].len); CHECK_NE(ret, NGHTTP2_ERR_NOMEM); - // If there is an error calling any of the callbacks, ret will be a - // negative number identifying the error code. This can happen, for - // instance, if the session is destroyed during any of the JS callbacks - // Note: if ssize_t is not defined (e.g. on Win32), nghttp2 will typedef - // ssize_t to int. Cast here so that the < 0 check actually works on - // Windows. - if (static_cast(ret) < 0) + if (ret < 0) return ret; total += ret; @@ -1709,10 +1703,7 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf) { statistics_.data_received += nread; ssize_t ret = Write(&stream_buf_, 1); - // Note: if ssize_t is not defined (e.g. on Win32), nghttp2 will typedef - // ssize_t to int. Cast here so that the < 0 check actually works on - // Windows. - if (static_cast(ret) < 0) { + if (ret < 0) { DEBUG_HTTP2SESSION2(this, "fatal error receiving data: %d", ret); Local argv[] = { From 1729af2ce907bd1c97b501fb2dce3d94ccc2174c Mon Sep 17 00:00:00 2001 From: Jack Horton Date: Mon, 5 Feb 2018 11:00:33 -0800 Subject: [PATCH 057/193] test: convert new tests to use error types PR-URL: https://github.com/nodejs/node/pull/18581 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- test/addons-napi/test_typedarray/test.js | 4 ++-- test/parallel/test-console-assign-undefined.js | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/addons-napi/test_typedarray/test.js b/test/addons-napi/test_typedarray/test.js index ed37f3c5d4da1b..41915b380be8e8 100644 --- a/test/addons-napi/test_typedarray/test.js +++ b/test/addons-napi/test_typedarray/test.js @@ -60,7 +60,7 @@ arrayTypes.forEach((currentType) => { const template = Reflect.construct(currentType, buffer); assert.throws(() => { test_typedarray.CreateTypedArray(template, buffer, 0, 136); - }, /Invalid typed array length/); + }, RangeError); }); const nonByteArrayTypes = [ Int16Array, Uint16Array, Int32Array, Uint32Array, @@ -71,5 +71,5 @@ nonByteArrayTypes.forEach((currentType) => { test_typedarray.CreateTypedArray(template, buffer, currentType.BYTES_PER_ELEMENT + 1, 1); console.log(`start of offset ${currentType}`); - }, /start offset of/); + }, RangeError); }); diff --git a/test/parallel/test-console-assign-undefined.js b/test/parallel/test-console-assign-undefined.js index 76007ce41e2a0a..1c47b3bda784bb 100644 --- a/test/parallel/test-console-assign-undefined.js +++ b/test/parallel/test-console-assign-undefined.js @@ -17,8 +17,7 @@ assert.strictEqual(global.console, 42); common.expectsError( () => console.log('foo'), { - type: TypeError, - message: 'console.log is not a function' + type: TypeError } ); From 28708677d941f51ebdcee2640b8b95f36110ad39 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Wed, 7 Feb 2018 14:51:10 -0500 Subject: [PATCH 058/193] src: resolve issues reported by coverity The specific issues raised by Coverity are: ** CID 182716: Control flow issues (DEADCODE) /src/node_file.cc: 1192 >>> CID 182716: Control flow issues (DEADCODE) >>> Execution cannot reach this statement: "args->GetReturnValue().Set(...". ** CID 182715: Uninitialized members (UNINIT_CTOR) /src/node_file.h: 29 >>> CID 182715: Uninitialized members (UNINIT_CTOR) >>> Non-static class member "syscall_" is not initialized in this constructor nor in any functions that it calls. PR-URL: https://github.com/nodejs/node/pull/18629 Reviewed-By: Ben Noordhuis Reviewed-By: Anna Henningsen Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- src/node_file.cc | 10 +++------- src/node_file.h | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/node_file.cc b/src/node_file.cc index 62dd5fe80cf8b2..7991cdd35044f0 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1192,13 +1192,9 @@ static void OpenFileHandle(const FunctionCallbackInfo& args) { req_wrap->SetReturnValue(args); } else { SYNC_CALL(open, *path, *path, flags, mode) - if (SYNC_RESULT < 0) { - args.GetReturnValue().Set(SYNC_RESULT); - } else { - HandleScope scope(env->isolate()); - FileHandle* fd = new FileHandle(env, SYNC_RESULT); - args.GetReturnValue().Set(fd->object()); - } + HandleScope scope(env->isolate()); + FileHandle* fd = new FileHandle(env, SYNC_RESULT); + args.GetReturnValue().Set(fd->object()); } } diff --git a/src/node_file.h b/src/node_file.h index d49807f5294e01..b76caa1467b3e2 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -62,7 +62,7 @@ class FSReqBase : public ReqWrap { private: enum encoding encoding_ = UTF8; - const char* syscall_; + const char* syscall_ = nullptr; const char* data_ = nullptr; MaybeStackBuffer buffer_; From df2f4ad22b27bc4cf26e1c5552d037327850bef4 Mon Sep 17 00:00:00 2001 From: alejandro estrada Date: Thu, 8 Feb 2018 13:01:33 -0500 Subject: [PATCH 059/193] src: replace var for let / const. Replace var for let or const. PR-URL: https://github.com/nodejs/node/pull/18649 Reviewed-By: Ruben Bridgewater Reviewed-By: Julian Duque Reviewed-By: James M Snell --- lib/internal/async_hooks.js | 4 ++-- lib/internal/bootstrap_node.js | 8 ++++---- lib/internal/readline.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 92cd9ba1e42b74..d1310ad2cac005 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -262,7 +262,7 @@ function getOrSetAsyncId(object) { // the user to safeguard this call and make sure it's zero'd out when the // constructor is complete. function getDefaultTriggerAsyncId() { - var defaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; + let defaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; // If defaultTriggerAsyncId isn't set, use the executionAsyncId if (defaultTriggerAsyncId < 0) defaultTriggerAsyncId = async_id_fields[kExecutionAsyncId]; @@ -276,7 +276,7 @@ function defaultTriggerAsyncIdScope(triggerAsyncId, block, ...args) { const oldDefaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; async_id_fields[kDefaultTriggerAsyncId] = triggerAsyncId; - var ret; + let ret; try { ret = Reflect.apply(block, null, args); } finally { diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index 33de5ae4be2f0d..0c2109fab36cc0 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -176,7 +176,7 @@ const fs = NativeModule.require('fs'); // read the source const filename = Module._resolveFilename(process.argv[1]); - var source = fs.readFileSync(filename, 'utf-8'); + const source = fs.readFileSync(filename, 'utf-8'); checkScriptSyntax(source, filename); process.exit(0); } @@ -222,7 +222,7 @@ // Read all of stdin - execute it. process.stdin.setEncoding('utf8'); - var code = ''; + let code = ''; process.stdin.on('data', function(d) { code += d; }); @@ -495,7 +495,7 @@ const versionTypes = icu.getVersion().split(','); for (var n = 0; n < versionTypes.length; n++) { - var name = versionTypes[n]; + const name = versionTypes[n]; const version = icu.getVersion(name); Object.defineProperty(process.versions, name, { writable: false, @@ -670,7 +670,7 @@ ]; NativeModule.prototype.compile = function() { - var source = NativeModule.getSource(this.id); + let source = NativeModule.getSource(this.id); source = NativeModule.wrap(source); this.loading = true; diff --git a/lib/internal/readline.js b/lib/internal/readline.js index b15ed4972ef7f2..e3d3007a75c645 100644 --- a/lib/internal/readline.js +++ b/lib/internal/readline.js @@ -9,8 +9,8 @@ const ansi = const kEscape = '\x1b'; -var getStringWidth; -var isFullWidthCodePoint; +let getStringWidth; +let isFullWidthCodePoint; function CSI(strings, ...args) { let ret = `${kEscape}[`; From c5c9515c1b8abea2fd98cdd1319176ea1c367764 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 9 Feb 2018 01:22:37 +0800 Subject: [PATCH 060/193] fs: fix stack overflow in fs.readdirSync Previously, fs.readdirSync calls the function returned by env->push_values_to_array_function() in batch and check the returned Maybe right away in C++, which can lead to assertions if the call stack already reaches the maximum size. This patch fixes that by returning early the call fails so the stack overflow error will be properly thrown into JS land. PR-URL: https://github.com/nodejs/node/pull/18647 Fixes: https://github.com/nodejs/node/issues/18645 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- src/node_file.cc | 12 +++++++++--- .../parallel/test-fs-readdir-stack-overflow.js | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 test/parallel/test-fs-readdir-stack-overflow.js diff --git a/src/node_file.cc b/src/node_file.cc index 7991cdd35044f0..9f9c7044f91167 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1132,14 +1132,20 @@ static void ReadDir(const FunctionCallbackInfo& args) { name_v[name_idx++] = filename.ToLocalChecked(); if (name_idx >= arraysize(name_v)) { - fn->Call(env->context(), names, name_idx, name_v) - .ToLocalChecked(); + MaybeLocal ret = fn->Call(env->context(), names, name_idx, + name_v); + if (ret.IsEmpty()) { + return; + } name_idx = 0; } } if (name_idx > 0) { - fn->Call(env->context(), names, name_idx, name_v).ToLocalChecked(); + MaybeLocal ret = fn->Call(env->context(), names, name_idx, name_v); + if (ret.IsEmpty()) { + return; + } } args.GetReturnValue().Set(names); diff --git a/test/parallel/test-fs-readdir-stack-overflow.js b/test/parallel/test-fs-readdir-stack-overflow.js new file mode 100644 index 00000000000000..b7dea52cc37ec5 --- /dev/null +++ b/test/parallel/test-fs-readdir-stack-overflow.js @@ -0,0 +1,18 @@ +'use strict'; + +const common = require('../common'); + +const fs = require('fs'); + +function recurse() { + fs.readdirSync('.'); + recurse(); +} + +common.expectsError( + () => recurse(), + { + type: RangeError, + message: 'Maximum call stack size exceeded' + } +); From cf52ab19dc9632e59b38744ebd0614b4d8ac151b Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Thu, 8 Feb 2018 10:07:57 +0100 Subject: [PATCH 061/193] test: remove unused using declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18637 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Jon Moss Reviewed-By: Tobias Nießen --- test/cctest/test_environment.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/cctest/test_environment.cc b/test/cctest/test_environment.cc index 4575d3b65ae318..c559a21fda1530 100644 --- a/test/cctest/test_environment.cc +++ b/test/cctest/test_environment.cc @@ -5,12 +5,6 @@ #include "gtest/gtest.h" #include "node_test_fixture.h" -using node::Environment; -using node::IsolateData; -using node::CreateIsolateData; -using node::FreeIsolateData; -using node::CreateEnvironment; -using node::FreeEnvironment; using node::AtExit; using node::RunAtExit; From 38bac4266a4f7adcfdd9832934aa57c564da1179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Wed, 7 Feb 2018 16:20:21 +0100 Subject: [PATCH 062/193] crypto: allow passing null as IV unless required PR-URL: https://github.com/nodejs/node/pull/18644 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- doc/api/crypto.md | 16 +++++++-- lib/internal/crypto/cipher.js | 4 +-- src/node_crypto.cc | 34 ++++++++++++++----- .../test-crypto-cipheriv-decipheriv.js | 12 +++++-- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 3eb4519d9f9503..9adc9082fc2fc2 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1286,6 +1286,11 @@ Adversaries][] for details. ### crypto.createCipheriv(algorithm, key, iv[, options]) - `algorithm` {string} - `key` {string | Buffer | TypedArray | DataView} @@ -1301,7 +1306,8 @@ available cipher algorithms. The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector][]. Both arguments must be `'utf8'` encoded strings, -[Buffers][`Buffer`], `TypedArray`, or `DataView`s. +[Buffers][`Buffer`], `TypedArray`, or `DataView`s. If the cipher does not need +an initialization vector, `iv` may be `null`. ### crypto.createCredentials(details) - `algorithm` {string} - `key` {string | Buffer | TypedArray | DataView} @@ -1363,7 +1374,8 @@ available cipher algorithms. The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector][]. Both arguments must be `'utf8'` encoded strings, -[Buffers][`Buffer`], `TypedArray`, or `DataView`s. +[Buffers][`Buffer`], `TypedArray`, or `DataView`s. If the cipher does not need +an initialization vector, `iv` may be `null`. ### crypto.createDiffieHellman(prime[, primeEncoding][, generator][, generatorEncoding]) * `urlString` {string} The URL string to parse. From 2bead4ba9e1f92f1cf07fdaaa32197fff7600172 Mon Sep 17 00:00:00 2001 From: Aonghus O Nia Date: Thu, 8 Feb 2018 17:01:23 -0500 Subject: [PATCH 064/193] doc: fix exporting a function example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missing the length argument in napi_create_function. PR-URL: https://github.com/nodejs/node/pull/18661 Reviewed-By: Michael Dawson Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- doc/api/n-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 3a954bd0d5815e..050f8a18925398 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -918,7 +918,7 @@ For example, to set a function to be returned by the `require()` for the addon: napi_value Init(napi_env env, napi_value exports) { napi_value method; napi_status status; - status = napi_create_function(env, "exports", Method, NULL, &method); + status = napi_create_function(env, "exports", NAPI_AUTO_LENGTH, Method, NULL, &method); if (status != napi_ok) return NULL; return method; } From d1e80e7cf1aa70fc2a22aea887063f4fa87fc4a9 Mon Sep 17 00:00:00 2001 From: Mihail Bodrov Date: Fri, 9 Feb 2018 02:42:23 +0300 Subject: [PATCH 065/193] buffer: simplify check size in assertSize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18665 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso Reviewed-By: Joyee Cheung Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- lib/buffer.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 4b800039fe6f80..edebf901aa8425 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -238,9 +238,7 @@ function assertSize(size) { if (typeof size !== 'number') { err = new errors.TypeError('ERR_INVALID_ARG_TYPE', 'size', 'number', size); - } else if (size < 0) { - err = new errors.RangeError('ERR_INVALID_OPT_VALUE', 'size', size); - } else if (size > kMaxLength) { + } else if (size < 0 || size > kMaxLength) { err = new errors.RangeError('ERR_INVALID_OPT_VALUE', 'size', size); } From 4a1a4bfc7edf4ce209b5ed29ce7ff440e1457ed1 Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Fri, 9 Feb 2018 14:23:42 +0100 Subject: [PATCH 066/193] build: no longer have v8-debug.h as dependency. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref: https://github.com/nodejs/node/issues/18643 PR-URL: https://github.com/nodejs/node/pull/18677 Refs: https://github.com/nodejs/node/issues/18643 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- node.gyp | 1 - 1 file changed, 1 deletion(-) diff --git a/node.gyp b/node.gyp index e2b17cd2b5fae6..268119454418ef 100644 --- a/node.gyp +++ b/node.gyp @@ -393,7 +393,6 @@ 'src/util-inl.h', 'deps/http_parser/http_parser.h', 'deps/v8/include/v8.h', - 'deps/v8/include/v8-debug.h', # javascript files to make for an even more pleasant IDE experience '<@(library_files)', # node.gyp is added to the project by default. From 540cbf84afddfbdd2e88ecbb92c28b7dcc582498 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Fri, 9 Feb 2018 10:20:20 -0600 Subject: [PATCH 067/193] doc: add error check to fs example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the err passed to the callback of fs.open() was not checked. PR-URL: https://github.com/nodejs/node/pull/18681 Reviewed-By: Anatoli Papirovski Reviewed-By: Vse Mozhet Byt Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- doc/api/fs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/fs.md b/doc/api/fs.md index a83d4031e7a856..2a0ce3f8a22e54 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1397,6 +1397,7 @@ fs.open('myfile', 'wx', (err, fd) => { fs.exists('myfile', (exists) => { if (exists) { fs.open('myfile', 'r', (err, fd) => { + if (err) throw err; readMyData(fd); }); } else { From 01d049165c7d3ef9d102c85f0218044cb45f4787 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Sat, 10 Feb 2018 09:32:49 +0100 Subject: [PATCH 068/193] test: fix flaky repl-timeout-throw Don't disconnect the child until all exceptions are thrown. Fixes: https://github.com/nodejs/node/issues/18659 PR-URL: https://github.com/nodejs/node/pull/18692 Fixes: https://github.com/nodejs/node/issues/18659 Reviewed-By: Ben Noordhuis Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig --- test/sequential/test-repl-timeout-throw.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/sequential/test-repl-timeout-throw.js b/test/sequential/test-repl-timeout-throw.js index aa933394b42ae7..3636b93ddfc2b2 100644 --- a/test/sequential/test-repl-timeout-throw.js +++ b/test/sequential/test-repl-timeout-throw.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const spawn = require('child_process').spawn; @@ -13,6 +13,8 @@ child.stdout.setEncoding('utf8'); child.stdout.on('data', function(c) { process.stdout.write(c); stdout += c; + if (stdout.includes('> THROW 2')) + child.stdin.end(); }); child.stdin.write = function(original) { @@ -46,8 +48,6 @@ child.stdout.once('data', function() { ' });\n' + ' });\n' + '});"";\n'); - - setTimeout(child.stdin.end.bind(child.stdin), common.platformTimeout(200)); } }); From 3e8af961b384445564babfb1f0edd3cdefd19466 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 10 Feb 2018 09:36:55 -0600 Subject: [PATCH 069/193] test: formalize exposure of internal bindings moves exposed internalBindings to a single location with short guidelines on how to expose them and a warning for users should they come across it PR-URL: https://github.com/nodejs/node/pull/18698 Reviewed-By: Joyee Cheung Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Ruben Bridgewater --- lib/internal/loader/ModuleWrap.js | 5 ----- lib/internal/test/binding.js | 13 +++++++++++++ node.gyp | 2 +- test/parallel/test-internal-module-wrap.js | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) delete mode 100644 lib/internal/loader/ModuleWrap.js create mode 100644 lib/internal/test/binding.js diff --git a/lib/internal/loader/ModuleWrap.js b/lib/internal/loader/ModuleWrap.js deleted file mode 100644 index b2b11daead7dde..00000000000000 --- a/lib/internal/loader/ModuleWrap.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -// exposes ModuleWrap for testing - -module.exports = internalBinding('module_wrap').ModuleWrap; diff --git a/lib/internal/test/binding.js b/lib/internal/test/binding.js new file mode 100644 index 00000000000000..7b9e1a089d2c36 --- /dev/null +++ b/lib/internal/test/binding.js @@ -0,0 +1,13 @@ +'use strict'; + +process.emitWarning( + 'These APIs are exposed only for testing and are not ' + + 'tracked by any versioning system or deprecation process.', + 'internal/test/binding'); + +// These exports should be scoped as specifically as possible +// to avoid exposing APIs because even with that warning and +// this file being internal people will still try to abuse it. +module.exports = { + ModuleWrap: internalBinding('module_wrap').ModuleWrap, +}; diff --git a/node.gyp b/node.gyp index 268119454418ef..d5bfad90fd7842 100644 --- a/node.gyp +++ b/node.gyp @@ -107,7 +107,6 @@ 'lib/internal/loader/DefaultResolve.js', 'lib/internal/loader/ModuleJob.js', 'lib/internal/loader/ModuleMap.js', - 'lib/internal/loader/ModuleWrap.js', 'lib/internal/loader/Translators.js', 'lib/internal/safe_globals.js', 'lib/internal/net.js', @@ -125,6 +124,7 @@ 'lib/internal/repl.js', 'lib/internal/repl/await.js', 'lib/internal/socket_list.js', + 'lib/internal/test/binding.js', 'lib/internal/test/unicode.js', 'lib/internal/timers.js', 'lib/internal/tls.js', diff --git a/test/parallel/test-internal-module-wrap.js b/test/parallel/test-internal-module-wrap.js index 634d1ebc6f678e..66a17a0f344701 100644 --- a/test/parallel/test-internal-module-wrap.js +++ b/test/parallel/test-internal-module-wrap.js @@ -6,7 +6,7 @@ const common = require('../common'); common.crashOnUnhandledRejection(); const assert = require('assert'); -const ModuleWrap = require('internal/loader/ModuleWrap'); +const { ModuleWrap } = require('internal/test/binding'); const { getPromiseDetails, isPromise } = process.binding('util'); const setTimeoutAsync = require('util').promisify(setTimeout); From a1bab826c49e880c3771146dd916076b8a223431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Sat, 10 Feb 2018 16:32:01 +0100 Subject: [PATCH 070/193] doc: mark NAPI_AUTO_LENGTH as code PR-URL: https://github.com/nodejs/node/pull/18697 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Jeremiah Senkpiel Reviewed-By: Luigi Pinca --- doc/api/n-api.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 050f8a18925398..5ad6debfbe14ca 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -554,10 +554,10 @@ NAPI_NO_RETURN void napi_fatal_error(const char* location, - `[in] location`: Optional location at which the error occurred. - `[in] location_len`: The length of the location in bytes, or -NAPI_AUTO_LENGTH if it is null-terminated. +`NAPI_AUTO_LENGTH` if it is null-terminated. - `[in] message`: The message associated with the error. - `[in] message_len`: The length of the message in bytes, or -NAPI_AUTO_LENGTH if it is +`NAPI_AUTO_LENGTH` if it is null-terminated. The function call does not return, the process will be terminated. @@ -1255,7 +1255,7 @@ napi_status napi_create_function(napi_env env, - `[in] utf8name`: A string representing the name of the function encoded as UTF8. - `[in] length`: The length of the utf8name in bytes, or -NAPI_AUTO_LENGTH if it is null-terminated. +`NAPI_AUTO_LENGTH` if it is null-terminated. - `[in] cb`: A function pointer to the native function to be invoked when the created function is invoked from JavaScript. - `[in] data`: Optional arbitrary context data to be passed into the native @@ -1483,7 +1483,7 @@ napi_status napi_create_string_latin1(napi_env env, - `[in] env`: The environment that the API is invoked under. - `[in] str`: Character buffer representing a ISO-8859-1-encoded string. - `[in] length`: The length of the string in bytes, or -NAPI_AUTO_LENGTH if it is null-terminated. +`NAPI_AUTO_LENGTH` if it is null-terminated. - `[out] result`: A `napi_value` representing a JavaScript String. Returns `napi_ok` if the API succeeded. @@ -1507,7 +1507,7 @@ napi_status napi_create_string_utf16(napi_env env, - `[in] env`: The environment that the API is invoked under. - `[in] str`: Character buffer representing a UTF16-LE-encoded string. - `[in] length`: The length of the string in two-byte code units, or -NAPI_AUTO_LENGTH if it is null-terminated. +`NAPI_AUTO_LENGTH` if it is null-terminated. - `[out] result`: A `napi_value` representing a JavaScript String. Returns `napi_ok` if the API succeeded. @@ -1530,7 +1530,7 @@ napi_status napi_create_string_utf8(napi_env env, - `[in] env`: The environment that the API is invoked under. - `[in] str`: Character buffer representing a UTF8-encoded string. -- `[in] length`: The length of the string in bytes, or NAPI_AUTO_LENGTH +- `[in] length`: The length of the string in bytes, or `NAPI_AUTO_LENGTH` if it is null-terminated. - `[out] result`: A `napi_value` representing a JavaScript String. @@ -3052,7 +3052,7 @@ napi_status napi_define_class(napi_env env, - `[in] utf8name`: Name of the JavaScript constructor function; this is not required to be the same as the C++ class name, though it is recommended for clarity. - - `[in] length`: The length of the utf8name in bytes, or NAPI_AUTO_LENGTH + - `[in] length`: The length of the utf8name in bytes, or `NAPI_AUTO_LENGTH` if it is null-terminated. - `[in] constructor`: Callback function that handles constructing instances of the class. (This should be a static method on the class, not an actual From 316846b8decf7158dd73d0ee23999686eee863bd Mon Sep 17 00:00:00 2001 From: Mihail Bodrov Date: Sat, 10 Feb 2018 19:38:45 +0300 Subject: [PATCH 071/193] url: simplify constructor URLSearchParams. Remove needless check null PR-URL: https://github.com/nodejs/node/pull/18700 Reviewed-By: Ruben Bridgewater Reviewed-By: Gus Caplan Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- lib/internal/url.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/internal/url.js b/lib/internal/url.js index 7055667718beed..0bdfc4783e65f3 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -98,8 +98,7 @@ class URLSearchParams { constructor(init = undefined) { if (init === null || init === undefined) { this[searchParams] = []; - } else if ((typeof init === 'object' && init !== null) || - typeof init === 'function') { + } else if (typeof init === 'object' || typeof init === 'function') { const method = init[Symbol.iterator]; if (method === this[Symbol.iterator]) { // While the spec does not have this branch, we can use it as a From 2aa3e3b00ff97e50f87a3345a33bcac9f424d0d7 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Sat, 10 Feb 2018 16:13:46 -0500 Subject: [PATCH 072/193] timers: fix enroll deprecation wording MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18704 Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Colin Ihrig Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Jon Moss Reviewed-By: Jeremiah Senkpiel Reviewed-By: Luigi Pinca --- lib/timers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/timers.js b/lib/timers.js index 8e914d751a93d8..08ddf16785685d 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -379,7 +379,7 @@ function enroll(item, msecs) { exports.enroll = util.deprecate(enroll, 'timers.enroll() is deprecated. ' + - 'Please use clearTimeout instead.', + 'Please use setTimeout instead.', 'DEP0095'); From bd4773a0431da9c846c3b4a2f6459db1f151c115 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 5 Feb 2018 21:59:38 -0800 Subject: [PATCH 073/193] module: use undefined if no main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the package.json file does not have a "main" entry, return undefined rather than an empty string. This is to make more consistent behavior. For example, when package.json is a directory, "main" is undefined rather than an empty string. PR-URL: https://github.com/nodejs/node/pull/18593 Reviewed-By: Bradley Farias Reviewed-By: Michaël Zasso Reviewed-By: Benjamin Gruenbaum Reviewed-By: Vladimir de Turckheim Reviewed-By: Yuta Hiroto Reviewed-By: Benedikt Meurer Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Matteo Collina --- src/node_file.cc | 7 +++---- test/parallel/test-module-binding.js | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/node_file.cc b/src/node_file.cc index 9f9c7044f91167..ccb9c65cfaf63c 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -652,9 +652,8 @@ void Close(const FunctionCallbackInfo& args) { // Used to speed up module loading. Returns the contents of the file as -// a string or undefined when the file cannot be opened. Returns an empty -// string when the file does not contain the substring '"main"' because that -// is the property we care about. +// a string or undefined when the file cannot be opened or "main" is not found +// in the file. static void InternalModuleReadJSON(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); uv_loop_t* loop = env->event_loop(); @@ -708,7 +707,7 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo& args) { const size_t size = offset - start; if (size == 0 || size == SearchString(&chars[start], size, "\"main\"")) { - args.GetReturnValue().SetEmptyString(); + return; } else { Local chars_string = String::NewFromUtf8(env->isolate(), diff --git a/test/parallel/test-module-binding.js b/test/parallel/test-module-binding.js index bea0c91f0c5bca..a3ebaf9e7266d2 100644 --- a/test/parallel/test-module-binding.js +++ b/test/parallel/test-module-binding.js @@ -6,8 +6,9 @@ const { readFileSync } = require('fs'); const { strictEqual } = require('assert'); strictEqual(internalModuleReadJSON('nosuchfile'), undefined); -strictEqual(internalModuleReadJSON(fixtures.path('empty.txt')), ''); -strictEqual(internalModuleReadJSON(fixtures.path('empty-with-bom.txt')), ''); +strictEqual(internalModuleReadJSON(fixtures.path('empty.txt')), undefined); +strictEqual(internalModuleReadJSON(fixtures.path('empty-with-bom.txt')), + undefined); { const filename = fixtures.path('require-bin/package.json'); strictEqual(internalModuleReadJSON(filename), readFileSync(filename, 'utf8')); From 9f6a56590129370f8b17c133f15a63e3832fa3cc Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Wed, 7 Feb 2018 17:46:49 -0800 Subject: [PATCH 074/193] async_hooks: rename PromiseWrap.parentId Rename the `parentId` property on the PromiseWrap object to a `isChainedPromise` property. The former wasn't quite useful as it was always defined to be the same value as the trigger id available in the init hook. Instead rename the property to be closer to the information it communicates: whether the promise is a chained promise or not. PR-URL: https://github.com/nodejs/node/pull/18633 Fixes: https://github.com/nodejs/node/issues/18470 Reviewed-By: Andreas Madsen Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu --- doc/api/async_hooks.md | 6 +++--- src/async_wrap.cc | 25 +++++++++++------------ test/parallel/test-async-hooks-promise.js | 4 ++-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index 4813169bfd8179..a96fd042930081 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -301,10 +301,10 @@ and document their own resource objects. For example, such a resource object could contain the SQL query being executed. In the case of Promises, the `resource` object will have `promise` property -that refers to the Promise that is being initialized, and a `parentId` property -set to the `asyncId` of a parent Promise, if there is one, and `undefined` +that refers to the Promise that is being initialized, and a `isChainedPromise` +property, set to `true` if the promise has a parent promise, and `false` otherwise. For example, in the case of `b = a.then(handler)`, `a` is considered -a parent Promise of `b`. +a parent Promise of `b`. Here, `b` is considered a chained promise. In some cases the resource object is reused for performance reasons, it is thus not safe to use it as a key in a `WeakMap` or add properties to it. diff --git a/src/async_wrap.cc b/src/async_wrap.cc index 706cd879901fba..387f3012480c63 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -245,7 +245,7 @@ class PromiseWrap : public AsyncWrap { size_t self_size() const override { return sizeof(*this); } static constexpr int kPromiseField = 1; - static constexpr int kParentAsyncIdField = 2; + static constexpr int kIsChainedPromiseField = 2; static constexpr int kInternalFieldCount = 3; static PromiseWrap* New(Environment* env, @@ -254,8 +254,8 @@ class PromiseWrap : public AsyncWrap { bool silent); static void GetPromise(Local property, const PropertyCallbackInfo& info); - static void getParentAsyncId(Local property, - const PropertyCallbackInfo& info); + static void getIsChainedPromise(Local property, + const PropertyCallbackInfo& info); }; PromiseWrap* PromiseWrap::New(Environment* env, @@ -265,11 +265,10 @@ PromiseWrap* PromiseWrap::New(Environment* env, Local object = env->promise_wrap_template() ->NewInstance(env->context()).ToLocalChecked(); object->SetInternalField(PromiseWrap::kPromiseField, promise); - if (parent_wrap != nullptr) { - object->SetInternalField(PromiseWrap::kParentAsyncIdField, - Number::New(env->isolate(), - parent_wrap->get_async_id())); - } + object->SetInternalField(PromiseWrap::kIsChainedPromiseField, + parent_wrap != nullptr ? + v8::True(env->isolate()) : + v8::False(env->isolate())); CHECK_EQ(promise->GetAlignedPointerFromInternalField(0), nullptr); promise->SetInternalField(0, object); return new PromiseWrap(env, object, silent); @@ -280,10 +279,10 @@ void PromiseWrap::GetPromise(Local property, info.GetReturnValue().Set(info.Holder()->GetInternalField(kPromiseField)); } -void PromiseWrap::getParentAsyncId(Local property, - const PropertyCallbackInfo& info) { +void PromiseWrap::getIsChainedPromise(Local property, + const PropertyCallbackInfo& info) { info.GetReturnValue().Set( - info.Holder()->GetInternalField(kParentAsyncIdField)); + info.Holder()->GetInternalField(kIsChainedPromiseField)); } static void PromiseHook(PromiseHookType type, Local promise, @@ -383,8 +382,8 @@ static void SetupHooks(const FunctionCallbackInfo& args) { FIXED_ONE_BYTE_STRING(env->isolate(), "promise"), PromiseWrap::GetPromise); promise_wrap_template->SetAccessor( - FIXED_ONE_BYTE_STRING(env->isolate(), "parentId"), - PromiseWrap::getParentAsyncId); + FIXED_ONE_BYTE_STRING(env->isolate(), "isChainedPromise"), + PromiseWrap::getIsChainedPromise); env->set_promise_wrap_template(promise_wrap_template); } } diff --git a/test/parallel/test-async-hooks-promise.js b/test/parallel/test-async-hooks-promise.js index d712fd616c647b..4b36f6026b36c6 100644 --- a/test/parallel/test-async-hooks-promise.js +++ b/test/parallel/test-async-hooks-promise.js @@ -21,8 +21,8 @@ const a = Promise.resolve(42); const b = a.then(common.mustCall()); assert.strictEqual(initCalls[0].triggerId, 1); -assert.strictEqual(initCalls[0].resource.parentId, undefined); +assert.strictEqual(initCalls[0].resource.isChainedPromise, false); assert.strictEqual(initCalls[0].resource.promise, a); assert.strictEqual(initCalls[1].triggerId, initCalls[0].id); -assert.strictEqual(initCalls[1].resource.parentId, initCalls[0].id); +assert.strictEqual(initCalls[1].resource.isChainedPromise, true); assert.strictEqual(initCalls[1].resource.promise, b); From ba944b16972c4b248e946d4bacb2141e5ef7eba9 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 10 Feb 2018 15:44:21 +0100 Subject: [PATCH 075/193] lib: provide proper deprecation code Refs: https://github.com/nodejs/node/pull/18513 PR-URL: https://github.com/nodejs/node/pull/18694 Refs: https://github.com/nodejs/node/pull/18513 Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Colin Ihrig Reviewed-By: Jeremiah Senkpiel Reviewed-By: Luigi Pinca --- lib/async_hooks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/async_hooks.js b/lib/async_hooks.js index e7450f29acc05f..cc9e893885a9ec 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -145,7 +145,7 @@ function showEmitBeforeAfterWarning() { process.emitWarning( 'asyncResource.emitBefore and emitAfter are deprecated. Please use ' + 'asyncResource.runInAsyncScope instead', - 'DeprecationWarning', 'DEP00XX'); + 'DeprecationWarning', 'DEP0098'); emitBeforeAfterWarning = false; } } From 1a5f6705c611bc9376e8cd49ff2b03b08c3b97b0 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 12 Feb 2018 12:31:23 +0100 Subject: [PATCH 076/193] tools: fix eslint isRequired Currently the call can lead to a TypeError with the message: `Cannot read property 'value' of undefined`. This fixes it by first checking that the first argument is truthy. PR-URL: https://github.com/nodejs/node/pull/18729 Reviewed-By: Anatoli Papirovski Reviewed-By: Benjamin Gruenbaum --- tools/eslint-rules/rules-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/eslint-rules/rules-utils.js b/tools/eslint-rules/rules-utils.js index 2bfab1c6399ee8..0fda705fb290b7 100644 --- a/tools/eslint-rules/rules-utils.js +++ b/tools/eslint-rules/rules-utils.js @@ -8,7 +8,7 @@ * require calls. */ module.exports.isRequired = function(node, modules) { - return node.callee.name === 'require' && + return node.callee.name === 'require' && node.arguments.length !== 0 && modules.includes(node.arguments[0].value); }; From 60c9ad797994e544af21ce991dce2c3360ae1801 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Thu, 22 Jun 2017 18:47:44 +0200 Subject: [PATCH 077/193] repl: remove deprecated NODE_REPL_HISTORY_FILE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/13876 Reviewed-By: Matteo Collina Reviewed-By: Michaël Zasso Reviewed-By: Gibson Fahnestock Reviewed-By: Colin Ihrig --- doc/api/deprecations.md | 5 +- doc/api/repl.md | 16 ---- lib/internal/repl.js | 58 ++----------- test/fixtures/old-repl-history-file.json | 4 - test/parallel/test-repl-persistent-history.js | 82 +------------------ 5 files changed, 14 insertions(+), 151 deletions(-) delete mode 100644 test/fixtures/old-repl-history-file.json diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index c18c9d58e0b521..c0778aebadbd36 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -378,9 +378,10 @@ instead. ### DEP0041: NODE\_REPL\_HISTORY\_FILE environment variable -Type: Documentation-only +Type: End-of-life -The `NODE_REPL_HISTORY_FILE` environment variable has been deprecated. +The `NODE_REPL_HISTORY_FILE` environment variable was removed. Please use +`NODE_REPL_HISTORY` instead. ### DEP0042: tls.CryptoStream diff --git a/doc/api/repl.md b/doc/api/repl.md index 506f54a4b8a2a8..182c0434c0340a 100644 --- a/doc/api/repl.md +++ b/doc/api/repl.md @@ -506,22 +506,6 @@ by saving inputs to a `.node_repl_history` file located in the user's home directory. This can be disabled by setting the environment variable `NODE_REPL_HISTORY=""`. -#### NODE_REPL_HISTORY_FILE - - -> Stability: 0 - Deprecated: Use `NODE_REPL_HISTORY` instead. - -Previously in Node.js/io.js v2.x, REPL history was controlled by using a -`NODE_REPL_HISTORY_FILE` environment variable, and the history was saved in JSON -format. This variable has now been deprecated, and the old JSON REPL history -file will be automatically converted to a simplified plain text format. This new -file will be saved to either the user's home directory, or a directory defined -by the `NODE_REPL_HISTORY` variable, as documented in the -[Environment Variable Options](#repl_environment_variable_options). - ### Using the Node.js REPL with advanced line-editors For advanced line-editors, start Node.js with the environment variable diff --git a/lib/internal/repl.js b/lib/internal/repl.js index 76412c3b118a8c..a852f87bc889bf 100644 --- a/lib/internal/repl.js +++ b/lib/internal/repl.js @@ -34,7 +34,7 @@ function createInternalRepl(env, opts, cb) { if (parseInt(env.NODE_NO_READLINE)) { opts.terminal = false; } - // the "dumb" special terminal, as defined by terminfo, doesn't support + // The "dumb" special terminal, as defined by terminfo, doesn't support // ANSI color control codes. // see http://invisible-island.net/ncurses/terminfo.ti.html#toc-_Specials if (parseInt(env.NODE_DISABLE_COLORS) || env.TERM === 'dumb') { @@ -61,17 +61,15 @@ function createInternalRepl(env, opts, cb) { const repl = REPL.start(opts); if (opts.terminal) { - return setupHistory(repl, env.NODE_REPL_HISTORY, - env.NODE_REPL_HISTORY_FILE, cb); + return setupHistory(repl, env.NODE_REPL_HISTORY, cb); } repl._historyPrev = _replHistoryMessage; cb(null, repl); } -function setupHistory(repl, historyPath, oldHistoryPath, ready) { - // Empty string disables persistent history. - +function setupHistory(repl, historyPath, ready) { + // Empty string disables persistent history if (typeof historyPath === 'string') historyPath = historyPath.trim(); @@ -131,50 +129,8 @@ function setupHistory(repl, historyPath, oldHistoryPath, ready) { if (data) { repl.history = data.split(/[\n\r]+/, repl.historySize); - } else if (oldHistoryPath === historyPath) { - // If pre-v3.0, the user had set NODE_REPL_HISTORY_FILE to - // ~/.node_repl_history, warn the user about it and proceed. - _writeToOutput( - repl, - '\nThe old repl history file has the same name and location as ' + - `the new one i.e., ${historyPath} and is empty.\nUsing it as is.\n`); - - } else if (oldHistoryPath) { - let threw = false; - try { - // Pre-v3.0, repl history was stored as JSON. - // Try and convert it to line separated history. - const oldReplJSONHistory = fs.readFileSync(oldHistoryPath, 'utf8'); - - // Only attempt to use the history if there was any. - if (oldReplJSONHistory) repl.history = JSON.parse(oldReplJSONHistory); - - if (Array.isArray(repl.history)) { - repl.history = repl.history.slice(0, repl.historySize); - } else { - threw = true; - _writeToOutput( - repl, - '\nError: The old history file data has to be an Array.\n' + - 'REPL session history will not be persisted.\n'); - } - } catch (err) { - // Cannot open or parse history file. - // Don't crash, just don't persist history. - threw = true; - const type = err instanceof SyntaxError ? 'parse' : 'open'; - _writeToOutput(repl, `\nError: Could not ${type} old history file.\n` + - 'REPL session history will not be persisted.\n'); - } - if (!threw) { - // Grab data from the older pre-v3.0 JSON NODE_REPL_HISTORY_FILE format. - _writeToOutput( - repl, - '\nConverted old JSON repl history to line-separated history.\n' + - `The new repl history file can be found at ${historyPath}.\n`); - } else { - repl.history = []; - } + } else { + repl.history = []; } fs.open(historyPath, 'r+', onhandle); @@ -188,7 +144,7 @@ function setupHistory(repl, historyPath, oldHistoryPath, ready) { repl._historyHandle = hnd; repl.on('line', online); - // reading the file data out erases it + // Reading the file data out erases it repl.once('flushHistory', function() { repl.resume(); ready(null, repl); diff --git a/test/fixtures/old-repl-history-file.json b/test/fixtures/old-repl-history-file.json deleted file mode 100644 index 963d93ddf379c0..00000000000000 --- a/test/fixtures/old-repl-history-file.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - "'=^.^='", - "'hello world'" -] diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js index 43c868f8326f3f..4d0330272ab3c6 100644 --- a/test/parallel/test-repl-persistent-history.js +++ b/test/parallel/test-repl-persistent-history.js @@ -58,11 +58,6 @@ const CLEAR = { ctrl: true, name: 'u' }; const historyFixturePath = fixtures.path('.node_repl_history'); const historyPath = path.join(tmpdir.path, '.fixture_copy_repl_history'); const historyPathFail = fixtures.path('nonexistent_folder', 'filename'); -const oldHistoryPathObj = fixtures.path('old-repl-history-file-obj.json'); -const oldHistoryPathFaulty = fixtures.path('old-repl-history-file-faulty.json'); -const oldHistoryPath = fixtures.path('old-repl-history-file.json'); -const enoentHistoryPath = fixtures.path('enoent-repl-history-file.json'); -const emptyHistoryPath = fixtures.path('.empty-repl-history-file'); const defaultHistoryPath = path.join(tmpdir.path, '.node_repl_history'); const emptyHiddenHistoryPath = fixtures.path('.empty-hidden-repl-history-file'); const devNullHistoryPath = path.join(tmpdir.path, @@ -72,23 +67,10 @@ const prompt = '> '; const replDisabled = '\nPersistent history support disabled. Set the ' + 'NODE_REPL_HISTORY environment\nvariable to a valid, ' + 'user-writable path to enable.\n'; -const convertMsg = '\nConverted old JSON repl history to line-separated ' + - 'history.\nThe new repl history file can be found at ' + - `${defaultHistoryPath}.\n`; const homedirErr = '\nError: Could not get the home directory.\n' + 'REPL session history will not be persisted.\n'; const replFailedRead = '\nError: Could not open history file.\n' + 'REPL session history will not be persisted.\n'; -const oldHistoryFailedOpen = '\nError: Could not open old history file.\n' + - 'REPL session history will not be persisted.\n'; -const oldHistoryFailedParse = '\nError: Could not parse old history file.\n' + - 'REPL session history will not be persisted.\n'; -const oldHistoryObj = '\nError: The old history file data has to be an Array' + - '.\nREPL session history will not be persisted.\n'; -const sameHistoryFilePaths = '\nThe old repl history file has the same name ' + - 'and location as the new one i.e., ' + - `${defaultHistoryPath}` + - ' and is empty.\nUsing it as is.\n'; const tests = [ { @@ -101,71 +83,21 @@ const tests = [ test: [UP], expected: [prompt, replDisabled, prompt] }, - { - env: { NODE_REPL_HISTORY_FILE: enoentHistoryPath }, - test: [UP], - expected: [prompt, oldHistoryFailedOpen, prompt] - }, - { - env: { NODE_REPL_HISTORY_FILE: oldHistoryPathObj }, - test: [UP], - expected: [prompt, oldHistoryObj, prompt] - }, - { - env: { NODE_REPL_HISTORY_FILE: oldHistoryPathFaulty }, - test: [UP], - expected: [prompt, oldHistoryFailedParse, prompt] - }, - { - env: { NODE_REPL_HISTORY: '', - NODE_REPL_HISTORY_FILE: oldHistoryPath }, - test: [UP], - expected: [prompt, replDisabled, prompt] - }, - { - env: { NODE_REPL_HISTORY_FILE: emptyHistoryPath }, - test: [UP], - expected: [prompt, convertMsg, prompt] - }, - { - env: { NODE_REPL_HISTORY_FILE: defaultHistoryPath }, - test: [UP], - expected: [prompt, sameHistoryFilePaths, prompt] - }, { env: { NODE_REPL_HISTORY: historyPath }, test: [UP, CLEAR], expected: [prompt, `${prompt}'you look fabulous today'`, prompt] }, - { - env: { NODE_REPL_HISTORY: historyPath, - NODE_REPL_HISTORY_FILE: oldHistoryPath }, - test: [UP, CLEAR], - expected: [prompt, `${prompt}'you look fabulous today'`, prompt] - }, - { - env: { NODE_REPL_HISTORY: historyPath, - NODE_REPL_HISTORY_FILE: '' }, - test: [UP, CLEAR], - expected: [prompt, `${prompt}'you look fabulous today'`, prompt] - }, { env: {}, - test: [UP], - expected: [prompt] - }, - { - env: { NODE_REPL_HISTORY_FILE: oldHistoryPath }, - test: [UP, CLEAR, '\'42\'', ENTER], - expected: [prompt, convertMsg, prompt, `${prompt}'=^.^='`, prompt, '\'', - '4', '2', '\'', '\'42\'\n', prompt, prompt], + test: [UP, '\'42\'', ENTER], + expected: [prompt, '\'', '4', '2', '\'', '\'42\'\n', prompt, prompt], clean: false }, - { // Requires the above testcase + { // Requires the above test case env: {}, test: [UP, UP, ENTER], - expected: [prompt, `${prompt}'42'`, `${prompt}'=^.^='`, '\'=^.^=\'\n', - prompt] + expected: [prompt, `${prompt}'42'`, '\'42\'\n', prompt] }, { env: { NODE_REPL_HISTORY: historyPath, @@ -173,12 +105,6 @@ const tests = [ test: [UP, UP, CLEAR], expected: [prompt, `${prompt}'you look fabulous today'`, prompt] }, - { - env: { NODE_REPL_HISTORY_FILE: oldHistoryPath, - NODE_REPL_HISTORY_SIZE: 1 }, - test: [UP, UP, UP, CLEAR], - expected: [prompt, convertMsg, prompt, `${prompt}'=^.^='`, prompt] - }, { env: { NODE_REPL_HISTORY: historyPathFail, NODE_REPL_HISTORY_SIZE: 1 }, From 1fc373bdf6758dcf045db21e4a075e4099ca7c19 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sun, 11 Feb 2018 19:17:03 +0100 Subject: [PATCH 078/193] Revert "repl: refactor tests to not rely on timing" This reverts commit de848ac1e0483327a2ce8716c3f8567eaeacb660. The commit broke multiline repl. PR-URL: https://github.com/nodejs/node/pull/18715 Refs: https://github.com/nodejs/node/pull/17828 Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Colin Ihrig --- lib/internal/repl.js | 4 +- lib/repl.js | 79 ++++++----- test/parallel/test-repl-autolibs.js | 27 +--- test/parallel/test-repl-context.js | 67 ++++------ test/parallel/test-repl-end-emits-exit.js | 18 ++- test/parallel/test-repl-eval-scope.js | 38 +++--- test/parallel/test-repl-eval.js | 50 +++---- ...test-repl-function-definition-edge-case.js | 71 ++++------ test/parallel/test-repl-load-multiline.js | 4 +- test/parallel/test-repl-mode.js | 53 ++------ test/parallel/test-repl-null-thrown.js | 7 +- test/parallel/test-repl-null.js | 21 +-- .../parallel/test-repl-pretty-custom-stack.js | 4 +- test/parallel/test-repl-pretty-stack.js | 4 +- test/parallel/test-repl-recoverable.js | 8 +- .../test-repl-throw-null-or-undefined.js | 20 ++- test/parallel/test-repl-underscore.js | 124 ++++++++---------- test/parallel/test-repl-use-global.js | 65 +++++---- 18 files changed, 273 insertions(+), 391 deletions(-) diff --git a/lib/internal/repl.js b/lib/internal/repl.js index a852f87bc889bf..adbb80b0af7e60 100644 --- a/lib/internal/repl.js +++ b/lib/internal/repl.js @@ -8,7 +8,7 @@ const os = require('os'); const util = require('util'); const debug = util.debuglog('repl'); module.exports = Object.create(REPL); -module.exports.createInternalRepl = createInternalRepl; +module.exports.createInternalRepl = createRepl; // XXX(chrisdickinson): The 15ms debounce value is somewhat arbitrary. // The debounce is to guard against code pasted into the REPL. @@ -19,7 +19,7 @@ function _writeToOutput(repl, message) { repl._refreshLine(); } -function createInternalRepl(env, opts, cb) { +function createRepl(env, opts, cb) { if (typeof opts === 'function') { cb = opts; opts = null; diff --git a/lib/repl.js b/lib/repl.js index 2227953fa86468..84682b1b63e6cc 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -109,11 +109,6 @@ writer.options = Object.assign({}, exports._builtinLibs = internalModule.builtinLibs; -const sep = '\u0000\u0000\u0000'; -const regExMatcher = new RegExp(`^${sep}(.*)${sep}(.*)${sep}(.*)${sep}(.*)` + - `${sep}(.*)${sep}(.*)${sep}(.*)${sep}(.*)` + - `${sep}(.*)$`); - function REPLServer(prompt, stream, eval_, @@ -154,7 +149,6 @@ function REPLServer(prompt, } var self = this; - replMap.set(self, self); self._domain = dom || domain.create(); self.useGlobal = !!useGlobal; @@ -171,6 +165,41 @@ function REPLServer(prompt, self.rli = this; const savedRegExMatches = ['', '', '', '', '', '', '', '', '', '']; + const sep = '\u0000\u0000\u0000'; + const regExMatcher = new RegExp(`^${sep}(.*)${sep}(.*)${sep}(.*)${sep}(.*)` + + `${sep}(.*)${sep}(.*)${sep}(.*)${sep}(.*)` + + `${sep}(.*)$`); + + eval_ = eval_ || defaultEval; + + // Pause taking in new input, and store the keys in a buffer. + const pausedBuffer = []; + let paused = false; + function pause() { + paused = true; + } + function unpause() { + if (!paused) return; + paused = false; + let entry; + while (entry = pausedBuffer.shift()) { + const [type, payload] = entry; + switch (type) { + case 'key': { + const [d, key] = payload; + self._ttyWrite(d, key); + break; + } + case 'close': + self.emit('exit'); + break; + } + if (paused) { + break; + } + } + } + function defaultEval(code, context, file, cb) { var err, result, script, wrappedErr; var wrappedCmd = false; @@ -302,6 +331,7 @@ function REPLServer(prompt, if (awaitPromise && !err) { let sigintListener; + pause(); let promise = result; if (self.breakEvalOnSigint) { const interrupt = new Promise((resolve, reject) => { @@ -320,6 +350,7 @@ function REPLServer(prompt, prioritizedSigintQueue.delete(sigintListener); finishExecution(undefined, result); + unpause(); }, (err) => { // Remove prioritized SIGINT listener if it was not called. prioritizedSigintQueue.delete(sigintListener); @@ -329,6 +360,7 @@ function REPLServer(prompt, Object.defineProperty(err, 'stack', { value: '' }); } + unpause(); if (err && process.domain) { debug('not recoverable, send to domain'); process.domain.emit('error', err); @@ -345,36 +377,6 @@ function REPLServer(prompt, } } - eval_ = eval_ || defaultEval; - - // Pause taking in new input, and store the keys in a buffer. - const pausedBuffer = []; - let paused = false; - function pause() { - paused = true; - } - function unpause() { - if (!paused) return; - paused = false; - let entry; - while (entry = pausedBuffer.shift()) { - const [type, payload] = entry; - switch (type) { - case 'key': { - const [d, key] = payload; - self._ttyWrite(d, key); - break; - } - case 'close': - self.emit('exit'); - break; - } - if (paused) { - break; - } - } - } - self.eval = self._domain.bind(eval_); self._domain.on('error', function debugDomainError(e) { @@ -403,7 +405,6 @@ function REPLServer(prompt, top.clearBufferedCommand(); top.lines.level = []; top.displayPrompt(); - unpause(); }); if (!input && !output) { @@ -592,7 +593,6 @@ function REPLServer(prompt, const evalCmd = self[kBufferedCommandSymbol] + cmd + '\n'; debug('eval %j', evalCmd); - pause(); self.eval(evalCmd, self.context, 'repl', finish); function finish(e, ret) { @@ -605,7 +605,6 @@ function REPLServer(prompt, '(Press Control-D to exit.)\n'); self.clearBufferedCommand(); self.displayPrompt(); - unpause(); return; } @@ -643,7 +642,6 @@ function REPLServer(prompt, // Display prompt again self.displayPrompt(); - unpause(); } }); @@ -726,6 +724,7 @@ exports.start = function(prompt, ignoreUndefined, replMode); if (!exports.repl) exports.repl = repl; + replMap.set(repl, repl); return repl; }; diff --git a/test/parallel/test-repl-autolibs.js b/test/parallel/test-repl-autolibs.js index 68f8402ddbfdaa..52234deb5e732e 100644 --- a/test/parallel/test-repl-autolibs.js +++ b/test/parallel/test-repl-autolibs.js @@ -29,22 +29,7 @@ const repl = require('repl'); common.globalCheck = false; const putIn = new common.ArrayStream(); - - -const replserver = repl.start('', putIn, null, true); -const callbacks = []; -const $eval = replserver.eval; -replserver.eval = function(code, context, file, cb) { - const expected = callbacks.shift(); - return $eval.call(this, code, context, file, (...args) => { - try { - expected(cb, ...args); - } catch (e) { - console.error(e); - process.exit(1); - } - }); -}; +repl.start('', putIn, null, true); test1(); @@ -63,11 +48,6 @@ function test1() { } }; assert(!gotWrite); - callbacks.push(common.mustCall((cb, err, result) => { - assert.ifError(err); - assert.strictEqual(result, require('fs')); - cb(err, result); - })); putIn.run(['fs']); assert(gotWrite); } @@ -86,11 +66,6 @@ function test2() { const val = {}; global.url = val; assert(!gotWrite); - callbacks.push(common.mustCall((cb, err, result) => { - assert.ifError(err); - assert.strictEqual(result, val); - cb(err, result); - })); putIn.run(['url']); assert(gotWrite); } diff --git a/test/parallel/test-repl-context.js b/test/parallel/test-repl-context.js index 90364cee694bb5..9d18067bc2aca4 100644 --- a/test/parallel/test-repl-context.js +++ b/test/parallel/test-repl-context.js @@ -27,57 +27,40 @@ function testContext(repl) { repl.close(); } -const replserver = repl.start({ input: stream, output: stream }); -const callbacks = []; -const $eval = replserver.eval; -replserver.eval = function(code, context, file, cb) { - const expected = callbacks.shift(); - return $eval.call(this, code, context, file, (...args) => { - try { - expected(cb, ...args); - } catch (e) { - console.error(e); - process.exit(1); - } - }); -}; -testContextSideEffects(replserver); +testContextSideEffects(repl.start({ input: stream, output: stream })); function testContextSideEffects(server) { assert.ok(!server.underscoreAssigned); assert.strictEqual(server.lines.length, 0); // an assignment to '_' in the repl server - callbacks.push(common.mustCall((cb, ...args) => { - assert.ok(server.underscoreAssigned); - assert.strictEqual(server.last, 500); - cb(...args); - assert.strictEqual(server.lines.length, 1); - assert.strictEqual(server.lines[0], '_ = 500;'); + server.write('_ = 500;\n'); + assert.ok(server.underscoreAssigned); + assert.strictEqual(server.lines.length, 1); + assert.strictEqual(server.lines[0], '_ = 500;'); + assert.strictEqual(server.last, 500); - // use the server to create a new context - const context = server.createContext(); + // use the server to create a new context + const context = server.createContext(); - // ensure that creating a new context does not - // have side effects on the server - assert.ok(server.underscoreAssigned); - assert.strictEqual(server.lines.length, 1); - assert.strictEqual(server.lines[0], '_ = 500;'); - assert.strictEqual(server.last, 500); + // ensure that creating a new context does not + // have side effects on the server + assert.ok(server.underscoreAssigned); + assert.strictEqual(server.lines.length, 1); + assert.strictEqual(server.lines[0], '_ = 500;'); + assert.strictEqual(server.last, 500); - // reset the server context - server.resetContext(); - assert.ok(!server.underscoreAssigned); - assert.strictEqual(server.lines.length, 0); + // reset the server context + server.resetContext(); + assert.ok(!server.underscoreAssigned); + assert.strictEqual(server.lines.length, 0); - // ensure that assigning to '_' in the new context - // does not change the value in our server. - assert.ok(!server.underscoreAssigned); - vm.runInContext('_ = 1000;\n', context); + // ensure that assigning to '_' in the new context + // does not change the value in our server. + assert.ok(!server.underscoreAssigned); + vm.runInContext('_ = 1000;\n', context); - assert.ok(!server.underscoreAssigned); - assert.strictEqual(server.lines.length, 0); - server.close(); - })); - server.write('_ = 500;\n'); + assert.ok(!server.underscoreAssigned); + assert.strictEqual(server.lines.length, 0); + server.close(); } diff --git a/test/parallel/test-repl-end-emits-exit.js b/test/parallel/test-repl-end-emits-exit.js index dd9ad5c1eb0e56..67f667eeb3d8db 100644 --- a/test/parallel/test-repl-end-emits-exit.js +++ b/test/parallel/test-repl-end-emits-exit.js @@ -21,7 +21,10 @@ 'use strict'; const common = require('../common'); +const assert = require('assert'); const repl = require('repl'); +let terminalExit = 0; +let regularExit = 0; // Create a dummy stream that does nothing const stream = new common.ArrayStream(); @@ -38,10 +41,11 @@ function testTerminalMode() { stream.emit('data', '\u0004'); }); - r1.on('exit', common.mustCall(function() { + r1.on('exit', function() { // should be fired from the simulated ^D keypress + terminalExit++; testRegularMode(); - })); + }); } function testRegularMode() { @@ -55,11 +59,17 @@ function testRegularMode() { stream.emit('end'); }); - r2.on('exit', common.mustCall(function() { + r2.on('exit', function() { // should be fired from the simulated 'end' event - })); + regularExit++; + }); } +process.on('exit', function() { + assert.strictEqual(terminalExit, 1); + assert.strictEqual(regularExit, 1); +}); + // start testTerminalMode(); diff --git a/test/parallel/test-repl-eval-scope.js b/test/parallel/test-repl-eval-scope.js index 83311fd92cd67b..00b577cba73f76 100644 --- a/test/parallel/test-repl-eval-scope.js +++ b/test/parallel/test-repl-eval-scope.js @@ -3,27 +3,21 @@ const common = require('../common'); const assert = require('assert'); const repl = require('repl'); -const exitTests = []; -process.on('exit', () => { - for (const test of exitTests) test(); -}); -const CONTEXT = { animal: 'Sterrance' }; -const stream = new common.ArrayStream(); -const options = { - eval: common.mustCall((cmd, context) => { - // need to escape the domain - exitTests.push(common.mustCall(() => { - assert.strictEqual(cmd, '.scope'); - assert.ok(context === CONTEXT); - })); - }), - input: stream, - output: stream, - terminal: true -}; +{ + const stream = new common.ArrayStream(); + const options = { + eval: common.mustCall((cmd, context) => { + assert.strictEqual(cmd, '.scope\n'); + assert.deepStrictEqual(context, { animal: 'Sterrance' }); + }), + input: stream, + output: stream, + terminal: true + }; -const r = repl.start(options); -r.context = CONTEXT; + const r = repl.start(options); + r.context = { animal: 'Sterrance' }; -stream.emit('data', '\t'); -stream.emit('.exit\n'); + stream.emit('data', '\t'); + stream.emit('.exit\n'); +} diff --git a/test/parallel/test-repl-eval.js b/test/parallel/test-repl-eval.js index d7290a1583da58..d775423fb74a52 100644 --- a/test/parallel/test-repl-eval.js +++ b/test/parallel/test-repl-eval.js @@ -3,31 +3,31 @@ const common = require('../common'); const assert = require('assert'); const repl = require('repl'); -const exitTests = []; -process.on('exit', () => { - for (const test of exitTests) test(); -}); -const options = { - eval: common.mustCall((cmd, context) => { - // Assertions here will not cause the test to exit with an error code - // so set a boolean that is checked later instead. - exitTests.push(common.mustCall(() => { - assert.strictEqual(cmd, 'function f() {}\n'); - assert.strictEqual(context.foo, 'bar'); - })); - }) -}; +{ + let evalCalledWithExpectedArgs = false; -const r = repl.start(options); -r.context = { foo: 'bar' }; + const options = { + eval: common.mustCall((cmd, context) => { + // Assertions here will not cause the test to exit with an error code + // so set a boolean that is checked later instead. + evalCalledWithExpectedArgs = (cmd === 'function f() {}\n' && + context.foo === 'bar'); + }) + }; -try { - // Default preprocessor transforms - // function f() {} to - // var f = function f() {} - // Test to ensure that original input is preserved. - // Reference: https://github.com/nodejs/node/issues/9743 - r.write('function f() {}\n'); -} finally { - r.write('.exit\n'); + const r = repl.start(options); + r.context = { foo: 'bar' }; + + try { + // Default preprocessor transforms + // function f() {} to + // var f = function f() {} + // Test to ensure that original input is preserved. + // Reference: https://github.com/nodejs/node/issues/9743 + r.write('function f() {}\n'); + } finally { + r.write('.exit\n'); + } + + assert(evalCalledWithExpectedArgs); } diff --git a/test/parallel/test-repl-function-definition-edge-case.js b/test/parallel/test-repl-function-definition-edge-case.js index bda40594a8876a..1e3063e3db53ff 100644 --- a/test/parallel/test-repl-function-definition-edge-case.js +++ b/test/parallel/test-repl-function-definition-edge-case.js @@ -7,47 +7,32 @@ const stream = require('stream'); common.globalCheck = false; -const input = new stream(); -input.write = input.pause = input.resume = () => {}; -input.readable = true; - -const output = new stream(); -output.writable = true; -output.accumulator = []; - -output.write = (data) => output.accumulator.push(data); - -const replserver = repl.start({ - input, - output, - useColors: false, - terminal: false, - prompt: '' -}); -const callbacks = []; -const $eval = replserver.eval; -replserver.eval = function(code, context, file, cb) { - const expected = callbacks.shift(); - return $eval.call(this, code, context, file, (...args) => { - try { - expected(...args); - } catch (e) { - console.error(e); - process.exit(1); - } - cb(...args); +const r = initRepl(); + +r.input.emit('data', 'function a() { return 42; } (1)\n'); +r.input.emit('data', 'a\n'); +r.input.emit('data', '.exit'); + +const expected = '1\n[Function: a]\n'; +const got = r.output.accumulator.join(''); +assert.strictEqual(got, expected); + +function initRepl() { + const input = new stream(); + input.write = input.pause = input.resume = () => {}; + input.readable = true; + + const output = new stream(); + output.writable = true; + output.accumulator = []; + + output.write = (data) => output.accumulator.push(data); + + return repl.start({ + input, + output, + useColors: false, + terminal: false, + prompt: '' }); -}; - -callbacks.push(common.mustCall((err, result) => { - assert.ifError(err); - assert.strictEqual(result, 1); -})); -replserver.input.emit('data', 'function a() { return 42; } (1)\n'); -callbacks.push(common.mustCall((err, result) => { - assert.ifError(err); - assert.strictEqual(typeof result, 'function'); - assert.strictEqual(result.toString(), 'function a() { return 42; }'); -})); -replserver.input.emit('data', 'a\n'); -replserver.input.emit('data', '.exit'); +} diff --git a/test/parallel/test-repl-load-multiline.js b/test/parallel/test-repl-load-multiline.js index 922aef3d493901..8ab878ae768ddd 100644 --- a/test/parallel/test-repl-load-multiline.js +++ b/test/parallel/test-repl-load-multiline.js @@ -36,7 +36,5 @@ const r = repl.start({ }); r.write(`${command}\n`); -r.on('exit', common.mustCall(() => { - assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected); -})); +assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected); r.close(); diff --git a/test/parallel/test-repl-mode.js b/test/parallel/test-repl-mode.js index 39d7ff88cce905..60b430d8c7ee31 100644 --- a/test/parallel/test-repl-mode.js +++ b/test/parallel/test-repl-mode.js @@ -19,49 +19,35 @@ tests.forEach(function(test) { function testSloppyMode() { const cli = initRepl(repl.REPL_MODE_SLOPPY); - cli.callbacks.push(common.mustCall((err, result) => { - assert.ifError(err); - assert.strictEqual(result, 3); - })); cli.input.emit('data', 'x = 3\n'); + assert.strictEqual(cli.output.accumulator.join(''), '> 3\n> '); + cli.output.accumulator.length = 0; - cli.callbacks.push(common.mustCall((err, result) => { - assert.ifError(err); - assert.strictEqual(result, undefined); - })); cli.input.emit('data', 'let y = 3\n'); + assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> '); } function testStrictMode() { const cli = initRepl(repl.REPL_MODE_STRICT); - cli._domain.once('error', common.mustCall((err) => { - assert.ok(err); - assert.ok(/ReferenceError: x is not defined/.test(err.message)); - })); cli.input.emit('data', 'x = 3\n'); + assert.ok(/ReferenceError: x is not defined/.test( + cli.output.accumulator.join(''))); + cli.output.accumulator.length = 0; - cli.callbacks.push(common.mustCall((err, result) => { - assert.ifError(err); - assert.strictEqual(result, undefined); - })); cli.input.emit('data', 'let y = 3\n'); + assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> '); } function testAutoMode() { const cli = initRepl(repl.REPL_MODE_MAGIC); - cli.callbacks.push(common.mustCall((err, result) => { - assert.ifError(err); - assert.strictEqual(result, 3); - })); cli.input.emit('data', 'x = 3\n'); + assert.strictEqual(cli.output.accumulator.join(''), '> 3\n> '); + cli.output.accumulator.length = 0; - cli.callbacks.push(common.mustCall((err, result) => { - assert.ifError(err); - assert.strictEqual(result, undefined); - })); cli.input.emit('data', 'let y = 3\n'); + assert.strictEqual(cli.output.accumulator.join(''), 'undefined\n> '); } function initRepl(mode) { @@ -76,28 +62,11 @@ function initRepl(mode) { output.accumulator = []; output.writable = true; - const replserver = repl.start({ + return repl.start({ input: input, output: output, useColors: false, terminal: false, replMode: mode }); - const callbacks = []; - const $eval = replserver.eval; - replserver.eval = function(code, context, file, cb) { - const expected = callbacks.shift(); - return $eval.call(this, code, context, file, (...args) => { - console.log('EVAL RET', args); - try { - expected(...args); - } catch (e) { - console.error(e); - process.exit(1); - } - cb(...args); - }); - }; - replserver.callbacks = callbacks; - return replserver; } diff --git a/test/parallel/test-repl-null-thrown.js b/test/parallel/test-repl-null-thrown.js index 9b78b0b1dc4d6d..1fe5d30396d534 100644 --- a/test/parallel/test-repl-null-thrown.js +++ b/test/parallel/test-repl-null-thrown.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const repl = require('repl'); const assert = require('assert'); const Stream = require('stream'); @@ -18,6 +18,7 @@ const replserver = repl.start({ replserver.emit('line', 'process.nextTick(() => { throw null; })'); replserver.emit('line', '.exit'); -replserver.on('exit', common.mustCall(() => { +setTimeout(() => { + console.log(text); assert(text.includes('Thrown: null')); -})); +}, 0); diff --git a/test/parallel/test-repl-null.js b/test/parallel/test-repl-null.js index 2748cfa780ee16..66d09b28f28b84 100644 --- a/test/parallel/test-repl-null.js +++ b/test/parallel/test-repl-null.js @@ -1,28 +1,9 @@ 'use strict'; -const common = require('../common'); +require('../common'); const repl = require('repl'); const assert = require('assert'); -const callbacks = [ - common.mustCall((err, value) => { - assert.ifError(err); - assert.strictEqual(value, undefined); - }) -]; const replserver = new repl.REPLServer(); -const $eval = replserver.eval; -replserver.eval = function(code, context, file, cb) { - const expected = callbacks.shift(); - return $eval.call(this, code, context, file, (...args) => { - try { - expected(...args); - } catch (e) { - console.error(e); - process.exit(1); - } - cb(...args); - }); -}; replserver._inTemplateLiteral = true; diff --git a/test/parallel/test-repl-pretty-custom-stack.js b/test/parallel/test-repl-pretty-custom-stack.js index 0ca4039a5f8e36..be102c1d677a9c 100644 --- a/test/parallel/test-repl-pretty-custom-stack.js +++ b/test/parallel/test-repl-pretty-custom-stack.js @@ -22,9 +22,7 @@ function run({ command, expected }) { }); r.write(`${command}\n`); - r.on('exit', common.mustCall(() => { - assert.strictEqual(accum, expected); - })); + assert.strictEqual(accum, expected); r.close(); } diff --git a/test/parallel/test-repl-pretty-stack.js b/test/parallel/test-repl-pretty-stack.js index 55f37e1703e52d..0fc6b3ada04c79 100644 --- a/test/parallel/test-repl-pretty-stack.js +++ b/test/parallel/test-repl-pretty-stack.js @@ -22,9 +22,7 @@ function run({ command, expected }) { }); r.write(`${command}\n`); - r.on('exit', common.mustCall(() => { - assert.strictEqual(accum, expected); - })); + assert.strictEqual(accum, expected); r.close(); } diff --git a/test/parallel/test-repl-recoverable.js b/test/parallel/test-repl-recoverable.js index c1767bbc4db03b..6788d84595066c 100644 --- a/test/parallel/test-repl-recoverable.js +++ b/test/parallel/test-repl-recoverable.js @@ -4,11 +4,14 @@ const common = require('../common'); const assert = require('assert'); const repl = require('repl'); +let evalCount = 0; let recovered = false; let rendered = false; function customEval(code, context, file, cb) { - return cb(!recovered ? new repl.Recoverable() : null, true); + evalCount++; + + return cb(evalCount === 1 ? new repl.Recoverable() : null, true); } const putIn = new common.ArrayStream(); @@ -23,7 +26,7 @@ putIn.write = function(msg) { } }; -repl.start('', putIn, common.mustCall(customEval, 2)); +repl.start('', putIn, customEval); // https://github.com/nodejs/node/issues/2939 // Expose recoverable errors to the consumer. @@ -33,4 +36,5 @@ putIn.emit('data', '2\n'); process.on('exit', function() { assert(recovered, 'REPL never recovered'); assert(rendered, 'REPL never rendered the result'); + assert.strictEqual(evalCount, 2); }); diff --git a/test/parallel/test-repl-throw-null-or-undefined.js b/test/parallel/test-repl-throw-null-or-undefined.js index ef25dbe015de88..fd2fd202b5bcb6 100644 --- a/test/parallel/test-repl-throw-null-or-undefined.js +++ b/test/parallel/test-repl-throw-null-or-undefined.js @@ -1,20 +1,18 @@ 'use strict'; -const common = require('../common'); +require('../common'); // This test ensures that the repl does not // crash or emit error when throwing `null|undefined` // ie `throw null` or `throw undefined` +const assert = require('assert'); const repl = require('repl'); -const replserver = repl.start(); -const $eval = replserver.eval; -replserver.eval = function(code, context, file, cb) { - return $eval.call(this, code, context, file, - common.mustNotCall( - 'repl crashes/throw error on `throw null|undefined`')); -}; -replserver.write('throw null\n'); -replserver.write('throw undefined\n'); +const r = repl.start(); -replserver.write('.exit\n'); +assert.doesNotThrow(() => { + r.write('throw null\n'); + r.write('throw undefined\n'); +}, TypeError, 'repl crashes/throw error on `throw null|undefined`'); + +r.write('.exit\n'); diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js index 1b22dcc7221a7f..91f32223e180b9 100644 --- a/test/parallel/test-repl-underscore.js +++ b/test/parallel/test-repl-underscore.js @@ -28,22 +28,20 @@ function testSloppyMode() { _; // remains 30 from user input `); - r.on('exit', () => { - assertOutput(r.output, [ - 'undefined', - 'undefined', - 'undefined', - '10', - '10', - 'Expression assignment to _ now disabled.', - '20', - '20', - '30', - '30', - '40', - '30' - ]); - }); + assertOutput(r.output, [ + 'undefined', + 'undefined', + 'undefined', + '10', + '10', + 'Expression assignment to _ now disabled.', + '20', + '20', + '30', + '30', + '40', + '30' + ]); } function testStrictMode() { @@ -63,22 +61,20 @@ function testStrictMode() { _; // remains 30 from user input `); - r.on('exit', () => { - assertOutput(r.output, [ - 'undefined', - 'undefined', - 'undefined', - 'undefined', - '20', - '30', - '30', - 'undefined', - '30', - 'undefined', - 'undefined', - '30' - ]); - }); + assertOutput(r.output, [ + 'undefined', + 'undefined', + 'undefined', + 'undefined', + '20', + '30', + '30', + 'undefined', + '30', + 'undefined', + 'undefined', + '30' + ]); } function testMagicMode() { @@ -98,22 +94,20 @@ function testMagicMode() { _; // remains 30 from user input `); - r.on('exit', () => { - assertOutput(r.output, [ - 'undefined', - '10', - '10', - 'undefined', - '20', - '30', - '30', - 'undefined', - '30', - 'undefined', - '50', - '30' - ]); - }); + assertOutput(r.output, [ + 'undefined', + '10', + '10', + 'undefined', + '20', + '30', + '30', + 'undefined', + '30', + 'undefined', + '50', + '30' + ]); } function testResetContext() { @@ -127,17 +121,15 @@ function testResetContext() { _; // expect 20 `); - r.on('exit', () => { - assertOutput(r.output, [ - 'Expression assignment to _ now disabled.', - '10', - '10', - 'Clearing context...', - '10', - '20', - '20' - ]); - }); + assertOutput(r.output, [ + 'Expression assignment to _ now disabled.', + '10', + '10', + 'Clearing context...', + '10', + '20', + '20' + ]); } function testResetContextGlobal() { @@ -149,14 +141,12 @@ function testResetContextGlobal() { _; // remains 10 `); - r.on('exit', () => { - assertOutput(r.output, [ - 'Expression assignment to _ now disabled.', - '10', - '10', - '10', - ]); - }); + assertOutput(r.output, [ + 'Expression assignment to _ now disabled.', + '10', + '10', + '10', + ]); // delete globals leaked by REPL when `useGlobal` is `true` delete global.module; diff --git a/test/parallel/test-repl-use-global.js b/test/parallel/test-repl-use-global.js index 75646a9c00aae7..c76505272b2682 100644 --- a/test/parallel/test-repl-use-global.js +++ b/test/parallel/test-repl-use-global.js @@ -7,6 +7,13 @@ const stream = require('stream'); const repl = require('internal/repl'); const assert = require('assert'); +// Array of [useGlobal, expectedResult] pairs +const globalTestCases = [ + [false, 'undefined'], + [true, '\'tacos\''], + [undefined, 'undefined'] +]; + const globalTest = (useGlobal, cb, output) => (err, repl) => { if (err) return cb(err); @@ -19,12 +26,26 @@ const globalTest = (useGlobal, cb, output) => (err, repl) => { global.lunch = 'tacos'; repl.write('global.lunch;\n'); repl.close(); - repl.on('exit', common.mustCall(() => { - delete global.lunch; - cb(null, str.trim()); - })); + delete global.lunch; + cb(null, str.trim()); }; +// Test how the global object behaves in each state for useGlobal +for (const [option, expected] of globalTestCases) { + runRepl(option, globalTest, common.mustCall((err, output) => { + assert.ifError(err); + assert.strictEqual(output, expected); + })); +} + +// Test how shadowing the process object via `let` +// behaves in each useGlobal state. Note: we can't +// actually test the state when useGlobal is true, +// because the exception that's generated is caught +// (see below), but errors are printed, and the test +// suite is aware of it, causing a failure to be flagged. +// +const processTestCases = [false, undefined]; const processTest = (useGlobal, cb, output) => (err, repl) => { if (err) return cb(err); @@ -36,37 +57,15 @@ const processTest = (useGlobal, cb, output) => (err, repl) => { repl.write('let process;\n'); repl.write('21 * 2;\n'); repl.close(); - repl.on('exit', common.mustCall((err) => { - assert.ifError(err); - cb(null, str.trim()); - })); + cb(null, str.trim()); }; -// Array of [useGlobal, expectedResult, fn] pairs -const testCases = [ - // Test how the global object behaves in each state for useGlobal - [false, 'undefined', globalTest], - [true, '\'tacos\'', globalTest], - [undefined, 'undefined', globalTest], - // Test how shadowing the process object via `let` - // behaves in each useGlobal state. Note: we can't - // actually test the state when useGlobal is true, - // because the exception that's generated is caught - // (see below), but errors are printed, and the test - // suite is aware of it, causing a failure to be flagged. - [false, 'undefined\n42', processTest] -]; - -const next = common.mustCall(() => { - if (testCases.length) { - const [option, expected, runner] = testCases.shift(); - runRepl(option, runner, common.mustCall((err, output) => { - assert.strictEqual(output, expected); - next(); - })); - } -}, testCases.length + 1); -next(); +for (const option of processTestCases) { + runRepl(option, processTest, common.mustCall((err, output) => { + assert.ifError(err); + assert.strictEqual(output, 'undefined\n42'); + })); +} function runRepl(useGlobal, testFunc, cb) { const inputStream = new stream.PassThrough(); From 656a5d042d30c8c5dbb49a9a9b38ea0df81ec1ca Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 7 Feb 2018 02:15:23 +0100 Subject: [PATCH 079/193] assert: fix infinite loop In rare cirumstances it is possible to get a identical error diff. In such a case the advances diffing runs into a infinite loop. This fixes it by properly checking for extra entries. PR-URL: https://github.com/nodejs/node/pull/18611 Reviewed-By: Joyee Cheung Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen --- lib/internal/errors.js | 2 ++ test/parallel/test-assert.js | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index c07920ae5d01ed..6d3b0557803563 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -184,6 +184,8 @@ function createErrDiff(actual, expected, operator) { } actualLines.pop(); expectedLines.pop(); + if (actualLines.length === 0 || expectedLines.length === 0) + break; a = actualLines[actualLines.length - 1]; b = expectedLines[expectedLines.length - 1]; } diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 869011908c30a6..f3f0012f84251e 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -31,6 +31,7 @@ const { EOL } = require('os'); const EventEmitter = require('events'); const { errorCache } = require('internal/errors'); const { writeFileSync, unlinkSync } = require('fs'); +const { inspect } = require('util'); const a = assert; assert.ok(a.AssertionError.prototype instanceof Error, @@ -565,6 +566,17 @@ common.expectsError( () => assert.deepEqual(Array(12).fill(1), Array(12).fill(2)), { message }); + const obj1 = {}; + const obj2 = { loop: 'forever' }; + obj2[inspect.custom] = () => '{}'; + // No infinite loop and no custom inspect. + assert.throws(() => assert.deepEqual(obj1, obj2), { + message: `${start}\n` + + `${actExp}\n` + + '\n' + + ' {}' + }); + // notDeepEqual tests message = 'Identical input passed to notDeepStrictEqual:\n[\n 1\n]'; assert.throws( From 0cdc87778e9c871e8bbbb081f4dc52fb17248e58 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 7 Feb 2018 02:23:40 +0100 Subject: [PATCH 080/193] assert: show proper differences Right now it is possible to get an AssertionError from input that has the customInspect function set to always return the same value. That way the error message is actually misleading because the output is going to look the same. This fixes it by deactivating the custom inspect function. PR-URL: https://github.com/nodejs/node/pull/18611 Reviewed-By: Joyee Cheung Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen --- lib/internal/errors.js | 10 ++++++---- test/parallel/test-assert.js | 6 +++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 6d3b0557803563..fb4f5e84822d7f 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -164,9 +164,9 @@ function createErrDiff(actual, expected, operator) { var skipped = false; const util = lazyUtil(); const actualLines = util - .inspect(actual, { compact: false }).split('\n'); + .inspect(actual, { compact: false, customInspect: false }).split('\n'); const expectedLines = util - .inspect(expected, { compact: false }).split('\n'); + .inspect(expected, { compact: false, customInspect: false }).split('\n'); const msg = `Input A expected to ${operator} input B:\n` + `${green}+ expected${white} ${red}- actual${white}`; const skippedMsg = ' ... Lines skipped'; @@ -310,8 +310,10 @@ class AssertionError extends Error { } else if (errorDiff === 1) { // In case the objects are equal but the operator requires unequal, show // the first object and say A equals B - const res = util - .inspect(actual, { compact: false }).split('\n'); + const res = util.inspect( + actual, + { compact: false, customInspect: false } + ).split('\n'); if (res.length > 20) { res[19] = '...'; diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index f3f0012f84251e..c120f47302a4bc 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -574,7 +574,11 @@ common.expectsError( message: `${start}\n` + `${actExp}\n` + '\n' + - ' {}' + `${minus} {}\n` + + `${plus} {\n` + + `${plus} loop: 'forever',\n` + + `${plus} [Symbol(util.inspect.custom)]: [Function]\n` + + `${plus} }` }); // notDeepEqual tests From 377cfd6fccd9e0ab455a50dada3b3cb37805479d Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 7 Feb 2018 01:38:45 +0100 Subject: [PATCH 081/193] http2: use `_final` instead of `on('finish')` PR-URL: https://github.com/nodejs/node/pull/18609 Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski --- lib/internal/http2/core.js | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 307ca98db8da22..2fdcb8d6388180 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -1415,18 +1415,6 @@ function afterDoStreamWrite(status, handle, req) { req.handle = undefined; } -function onHandleFinish() { - const handle = this[kHandle]; - if (this[kID] === undefined) { - this.once('ready', onHandleFinish); - } else if (handle !== undefined) { - const req = new ShutdownWrap(); - req.oncomplete = () => {}; - req.handle = handle; - handle.shutdown(req); - } -} - function streamOnResume() { if (!this.destroyed && !this.pending) this[kHandle].readStart(); @@ -1447,6 +1435,13 @@ function abort(stream) { } } +function afterShutdown() { + this.callback(); + const stream = this.handle[kOwner]; + if (stream) + stream[kMaybeDestroy](); +} + // An Http2Stream is a Duplex stream that is backed by a // node::http2::Http2Stream handle implementing StreamBase. class Http2Stream extends Duplex { @@ -1471,7 +1466,6 @@ class Http2Stream extends Duplex { writeQueueSize: 0 }; - this.once('finish', onHandleFinish); this.on('resume', streamOnResume); this.on('pause', streamOnPause); } @@ -1678,6 +1672,23 @@ class Http2Stream extends Duplex { trackWriteState(this, req.bytes); } + _final(cb) { + const handle = this[kHandle]; + if (this[kID] === undefined) { + this.once('ready', () => this._final(cb)); + } else if (handle !== undefined) { + debug(`Http2Stream ${this[kID]} [Http2Session ` + + `${sessionName(this[kSession][kType])}]: _final shutting down`); + const req = new ShutdownWrap(); + req.oncomplete = afterShutdown; + req.callback = cb; + req.handle = handle; + handle.shutdown(req); + } else { + cb(); + } + } + _read(nread) { if (this.destroyed) { this.push(null); From 2287deab94cb409ee808d0c6338bc5b08a0c6c80 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 5 Feb 2018 20:40:53 -0800 Subject: [PATCH 082/193] fs: make URL paths no longer experimental PR-URL: https://github.com/nodejs/node/pull/18591 Reviewed-By: Weijia Wang Reviewed-By: Evan Lucas Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca --- doc/api/fs.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 2a0ce3f8a22e54..2210d7ecb3b96f 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -164,9 +164,6 @@ example `fs.readdirSync('c:\\')` can potentially return a different result than - -> Stability: 1 - Experimental - For most `fs` module functions, the `path` or `filename` argument may be passed as a WHATWG [`URL`][] object. Only [`URL`][] objects using the `file:` protocol are supported. From c3ff89920e43a246324842c915d33893a7456568 Mon Sep 17 00:00:00 2001 From: Chin Huang Date: Fri, 2 Feb 2018 15:03:07 -0800 Subject: [PATCH 083/193] test: add useful info to error msg and refactor Add useful info about process.domain to error meesages in the uncaughtException event listener and the beforeExit event listener. Refactor code such as using template literals, and also make sure uncaughtException listner is detached after firing once to avoid endless loop in case of exception throw in the beforeExit event listner. PR-URL: https://github.com/nodejs/node/pull/18541 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- ...domain-stack-empty-in-process-uncaughtexception.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/parallel/test-domain-stack-empty-in-process-uncaughtexception.js b/test/parallel/test-domain-stack-empty-in-process-uncaughtexception.js index 79ded2dd9d1424..e9e8ab12d59d2c 100644 --- a/test/parallel/test-domain-stack-empty-in-process-uncaughtexception.js +++ b/test/parallel/test-domain-stack-empty-in-process-uncaughtexception.js @@ -6,15 +6,18 @@ const assert = require('assert'); const d = domain.create(); -process.on('uncaughtException', common.mustCall(function onUncaught() { +process.once('uncaughtException', common.mustCall(function onUncaught() { assert.strictEqual( process.domain, null, - 'domains stack should be empty in uncaughtException handler'); + 'Domains stack should be empty in uncaughtException handler ' + + `but the value of process.domain is ${JSON.stringify(process.domain)}`); })); process.on('beforeExit', common.mustCall(function onBeforeExit() { - assert.strictEqual(process.domain, null, - 'domains stack should be empty in beforeExit handler'); + assert.strictEqual( + process.domain, null, + 'Domains stack should be empty in beforeExit handler ' + + `but the value of process.domain is ${JSON.stringify(process.domain)}`); })); d.run(function() { From 18e728474031911650992fee9cd113be0d00d67e Mon Sep 17 00:00:00 2001 From: Kevin Caulfield Date: Thu, 1 Feb 2018 18:57:37 -0500 Subject: [PATCH 084/193] test: fix and improve error message Add unexpected value to dgram socket type assertion and fix the size entry. PR-URL: https://github.com/nodejs/node/pull/18449 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater --- test/parallel/test-dgram-createSocket-type.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-dgram-createSocket-type.js b/test/parallel/test-dgram-createSocket-type.js index 54f3aaa0603621..19f4dad9208212 100644 --- a/test/parallel/test-dgram-createSocket-type.js +++ b/test/parallel/test-dgram-createSocket-type.js @@ -52,10 +52,12 @@ validTypes.forEach((validType) => { // note: linux will double the buffer size assert.ok(socket.getRecvBufferSize() === 10000 || socket.getRecvBufferSize() === 20000, - 'SO_RCVBUF not 1300 or 2600'); + 'SO_RCVBUF not 10000 or 20000, ' + + `was ${socket.getRecvBufferSize()}`); assert.ok(socket.getSendBufferSize() === 15000 || socket.getSendBufferSize() === 30000, - 'SO_SNDBUF not 1800 or 3600'); + 'SO_SNDBUF not 15000 or 30000, ' + + `was ${socket.getRecvBufferSize()}`); socket.close(); })); } From a27e443df3ae17e9110df043ca2a54d4bd8686f0 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 12 Feb 2018 09:20:59 -0500 Subject: [PATCH 085/193] test: fix missing param in benchmark-timers PR-URL: https://github.com/nodejs/node/pull/18734 Fixes: https://github.com/nodejs/node/issues/18730 Reviewed-By: Ruben Bridgewater Reviewed-By: Benjamin Gruenbaum --- test/parallel/test-benchmark-timers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/parallel/test-benchmark-timers.js b/test/parallel/test-benchmark-timers.js index cca9ede3a01c41..4cbcb1f11b9327 100644 --- a/test/parallel/test-benchmark-timers.js +++ b/test/parallel/test-benchmark-timers.js @@ -7,6 +7,7 @@ const runBenchmark = require('../common/benchmark'); runBenchmark('timers', [ 'type=depth', + 'n=1', 'millions=0.000001', 'thousands=0.001' ], From 3d53848d751eac4bb642ef8c50339d51cf9155bc Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Mon, 12 Feb 2018 12:43:11 -0500 Subject: [PATCH 086/193] doc: add mmarchini to collaborators PR-URL: https://github.com/nodejs/node/pull/18740 Reviewed-By: Joyee Cheung Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater Reviewed-By: Richard Lau --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 714fde2c143cf7..364047f25ff387 100644 --- a/README.md +++ b/README.md @@ -426,6 +426,8 @@ For more information about the governance of the Node.js project, see **Mikeal Rogers** <mikeal.rogers@gmail.com> * [misterdjules](https://github.com/misterdjules) - **Julien Gilli** <jgilli@nodejs.org> +* [mmarchini](https://github.com/mmarchini) - +**Matheus Marchini** <matheus@sthima.com> * [mscdex](https://github.com/mscdex) - **Brian White** <mscdex@mscdex.net> * [MylesBorins](https://github.com/MylesBorins) - From 6abce37f3469878d18ce3700b4aad2fcf5836eea Mon Sep 17 00:00:00 2001 From: Sergey Golovin Date: Thu, 8 Feb 2018 20:14:41 +0300 Subject: [PATCH 087/193] path: replace "magic" numbers by readable constants PR-URL: https://github.com/nodejs/node/pull/18654 Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell Reviewed-By: Kyle Farnung Reviewed-By: Jeremiah Senkpiel --- lib/internal/constants.js | 16 +++ lib/path.js | 238 ++++++++++++++++++++------------------ node.gyp | 1 + 3 files changed, 144 insertions(+), 111 deletions(-) create mode 100644 lib/internal/constants.js diff --git a/lib/internal/constants.js b/lib/internal/constants.js new file mode 100644 index 00000000000000..f0ffec7a447529 --- /dev/null +++ b/lib/internal/constants.js @@ -0,0 +1,16 @@ +'use strict'; + +module.exports = { + // Alphabet chars. + CHAR_UPPERCASE_A: 65, /*A*/ + CHAR_LOWERCASE_A: 97, /*a*/ + CHAR_UPPERCASE_Z: 90, /*Z*/ + CHAR_LOWERCASE_Z: 122, /*z*/ + + // Non-alphabetic chars. + CHAR_DOT: 46, /*.*/ + CHAR_FORWARD_SLASH: 47, /*/*/ + CHAR_BACKWARD_SLASH: 92, /*\*/ + CHAR_COLON: 58, /*:*/ + CHAR_QUESTION_MARK: 63, /*?*/ +}; diff --git a/lib/path.js b/lib/path.js index eca4fcb9d21718..248809b2e2f70b 100644 --- a/lib/path.js +++ b/lib/path.js @@ -22,6 +22,17 @@ 'use strict'; const errors = require('internal/errors'); +const { + CHAR_UPPERCASE_A, + CHAR_LOWERCASE_A, + CHAR_UPPERCASE_Z, + CHAR_LOWERCASE_Z, + CHAR_DOT, + CHAR_FORWARD_SLASH, + CHAR_BACKWARD_SLASH, + CHAR_COLON, + CHAR_QUESTION_MARK, +} = require('internal/constants'); function assertPath(path) { if (typeof path !== 'string') { @@ -39,17 +50,17 @@ function normalizeStringWin32(path, allowAboveRoot) { for (var i = 0; i <= path.length; ++i) { if (i < path.length) code = path.charCodeAt(i); - else if (code === 47/*/*/ || code === 92/*\*/) + else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) break; else - code = 47/*/*/; - if (code === 47/*/*/ || code === 92/*\*/) { + code = CHAR_FORWARD_SLASH; + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { if (lastSlash === i - 1 || dots === 1) { // NOOP } else if (lastSlash !== i - 1 && dots === 2) { if (res.length < 2 || lastSegmentLength !== 2 || - res.charCodeAt(res.length - 1) !== 46/*.*/ || - res.charCodeAt(res.length - 2) !== 46/*.*/) { + res.charCodeAt(res.length - 1) !== CHAR_DOT || + res.charCodeAt(res.length - 2) !== CHAR_DOT) { if (res.length > 2) { const lastSlashIndex = res.lastIndexOf('\\'); if (lastSlashIndex !== res.length - 1) { @@ -88,7 +99,7 @@ function normalizeStringWin32(path, allowAboveRoot) { } lastSlash = i; dots = 0; - } else if (code === 46/*.*/ && dots !== -1) { + } else if (code === CHAR_DOT && dots !== -1) { ++dots; } else { dots = -1; @@ -107,17 +118,17 @@ function normalizeStringPosix(path, allowAboveRoot) { for (var i = 0; i <= path.length; ++i) { if (i < path.length) code = path.charCodeAt(i); - else if (code === 47/*/*/) + else if (code === CHAR_FORWARD_SLASH) break; else - code = 47/*/*/; - if (code === 47/*/*/) { + code = CHAR_FORWARD_SLASH; + if (code === CHAR_FORWARD_SLASH) { if (lastSlash === i - 1 || dots === 1) { // NOOP } else if (lastSlash !== i - 1 && dots === 2) { if (res.length < 2 || lastSegmentLength !== 2 || - res.charCodeAt(res.length - 1) !== 46/*.*/ || - res.charCodeAt(res.length - 2) !== 46/*.*/) { + res.charCodeAt(res.length - 1) !== CHAR_DOT || + res.charCodeAt(res.length - 2) !== CHAR_DOT) { if (res.length > 2) { const lastSlashIndex = res.lastIndexOf('/'); if (lastSlashIndex !== res.length - 1) { @@ -156,7 +167,7 @@ function normalizeStringPosix(path, allowAboveRoot) { } lastSlash = i; dots = 0; - } else if (code === 46/*.*/ && dots !== -1) { + } else if (code === CHAR_DOT && dots !== -1) { ++dots; } else { dots = -1; @@ -223,7 +234,7 @@ const win32 = { // Try to match a root if (len > 1) { - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Possible UNC root // If we started with a separator, we know we at least have an @@ -231,14 +242,14 @@ const win32 = { isAbsolute = true; code = path.charCodeAt(1); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Matched double path separator at beginning var j = 2; var last = j; // Match 1 or more non-path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) break; } if (j < len && j !== last) { @@ -248,7 +259,7 @@ const win32 = { // Match 1 or more path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code !== 47/*/*/ && code !== 92/*\*/) + if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) break; } if (j < len && j !== last) { @@ -257,7 +268,10 @@ const win32 = { // Match 1 or more non-path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) + const isPathSeparator = + code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; + + if (isPathSeparator) break; } if (j === len) { @@ -276,16 +290,16 @@ const win32 = { } else { rootEnd = 1; } - } else if ((code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 97/*a*/ && code <= 122/*z*/)) { + } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || + (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { // Possible device root - if (path.charCodeAt(1) === 58/*:*/) { + if (path.charCodeAt(1) === CHAR_COLON) { device = path.slice(0, 2); rootEnd = 2; if (len > 2) { code = path.charCodeAt(2); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Treat separator following drive name as an absolute path // indicator isAbsolute = true; @@ -294,7 +308,7 @@ const win32 = { } } } - } else if (code === 47/*/*/ || code === 92/*\*/) { + } else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // `path` contains just a path separator rootEnd = 1; isAbsolute = true; @@ -343,7 +357,7 @@ const win32 = { // Try to match a root if (len > 1) { - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Possible UNC root // If we started with a separator, we know we at least have an absolute @@ -351,14 +365,14 @@ const win32 = { isAbsolute = true; code = path.charCodeAt(1); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Matched double path separator at beginning var j = 2; var last = j; // Match 1 or more non-path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) break; } if (j < len && j !== last) { @@ -368,7 +382,7 @@ const win32 = { // Match 1 or more path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code !== 47/*/*/ && code !== 92/*\*/) + if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) break; } if (j < len && j !== last) { @@ -377,7 +391,7 @@ const win32 = { // Match 1 or more non-path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) break; } if (j === len) { @@ -397,16 +411,16 @@ const win32 = { } else { rootEnd = 1; } - } else if ((code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 97/*a*/ && code <= 122/*z*/)) { + } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || + (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { // Possible device root - if (path.charCodeAt(1) === 58/*:*/) { + if (path.charCodeAt(1) === CHAR_COLON) { device = path.slice(0, 2); rootEnd = 2; if (len > 2) { code = path.charCodeAt(2); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Treat separator following drive name as an absolute path // indicator isAbsolute = true; @@ -415,14 +429,15 @@ const win32 = { } } } - } else if (code === 47/*/*/ || code === 92/*\*/) { + } else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // `path` contains just a path separator, exit early to avoid unnecessary // work return '\\'; } code = path.charCodeAt(len - 1); - var trailingSeparator = (code === 47/*/*/ || code === 92/*\*/); + var trailingSeparator = + (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH); var tail; if (rootEnd < len) tail = normalizeStringWin32(path.slice(rootEnd), !isAbsolute); @@ -462,15 +477,15 @@ const win32 = { if (len === 0) return false; var code = path.charCodeAt(0); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { return true; - } else if ((code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 97/*a*/ && code <= 122/*z*/)) { + } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || + (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { // Possible device root - if (len > 2 && path.charCodeAt(1) === 58/*:*/) { + if (len > 2 && path.charCodeAt(1) === CHAR_COLON) { code = path.charCodeAt(2); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) return true; } } @@ -514,16 +529,16 @@ const win32 = { var needsReplace = true; var slashCount = 0; var code = firstPart.charCodeAt(0); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { ++slashCount; const firstLen = firstPart.length; if (firstLen > 1) { code = firstPart.charCodeAt(1); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { ++slashCount; if (firstLen > 2) { code = firstPart.charCodeAt(2); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) ++slashCount; else { // We matched a UNC path in the first part @@ -537,7 +552,7 @@ const win32 = { // Find any more consecutive slashes we need to replace for (; slashCount < joined.length; ++slashCount) { code = joined.charCodeAt(slashCount); - if (code !== 47/*/*/ && code !== 92/*\*/) + if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) break; } @@ -576,13 +591,13 @@ const win32 = { // Trim any leading backslashes var fromStart = 0; for (; fromStart < from.length; ++fromStart) { - if (from.charCodeAt(fromStart) !== 92/*\*/) + if (from.charCodeAt(fromStart) !== CHAR_BACKWARD_SLASH) break; } // Trim trailing backslashes (applicable to UNC paths only) var fromEnd = from.length; for (; fromEnd - 1 > fromStart; --fromEnd) { - if (from.charCodeAt(fromEnd - 1) !== 92/*\*/) + if (from.charCodeAt(fromEnd - 1) !== CHAR_BACKWARD_SLASH) break; } var fromLen = (fromEnd - fromStart); @@ -590,13 +605,13 @@ const win32 = { // Trim any leading backslashes var toStart = 0; for (; toStart < to.length; ++toStart) { - if (to.charCodeAt(toStart) !== 92/*\*/) + if (to.charCodeAt(toStart) !== CHAR_BACKWARD_SLASH) break; } // Trim trailing backslashes (applicable to UNC paths only) var toEnd = to.length; for (; toEnd - 1 > toStart; --toEnd) { - if (to.charCodeAt(toEnd - 1) !== 92/*\*/) + if (to.charCodeAt(toEnd - 1) !== CHAR_BACKWARD_SLASH) break; } var toLen = (toEnd - toStart); @@ -608,7 +623,7 @@ const win32 = { for (; i <= length; ++i) { if (i === length) { if (toLen > length) { - if (to.charCodeAt(toStart + i) === 92/*\*/) { + if (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) { // We get here if `from` is the exact base path for `to`. // For example: from='C:\\foo\\bar'; to='C:\\foo\\bar\\baz' return toOrig.slice(toStart + i + 1); @@ -619,7 +634,7 @@ const win32 = { } } if (fromLen > length) { - if (from.charCodeAt(fromStart + i) === 92/*\*/) { + if (from.charCodeAt(fromStart + i) === CHAR_BACKWARD_SLASH) { // We get here if `to` is the exact base path for `from`. // For example: from='C:\\foo\\bar'; to='C:\\foo' lastCommonSep = i; @@ -635,7 +650,7 @@ const win32 = { var toCode = to.charCodeAt(toStart + i); if (fromCode !== toCode) break; - else if (fromCode === 92/*\*/) + else if (fromCode === CHAR_BACKWARD_SLASH) lastCommonSep = i; } @@ -651,7 +666,7 @@ const win32 = { // Generate the relative path based on the path difference between `to` and // `from` for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { - if (i === fromEnd || from.charCodeAt(i) === 92/*\*/) { + if (i === fromEnd || from.charCodeAt(i) === CHAR_BACKWARD_SLASH) { if (out.length === 0) out += '..'; else @@ -665,7 +680,7 @@ const win32 = { return out + toOrig.slice(toStart + lastCommonSep, toEnd); else { toStart += lastCommonSep; - if (toOrig.charCodeAt(toStart) === 92/*\*/) + if (toOrig.charCodeAt(toStart) === CHAR_BACKWARD_SLASH) ++toStart; return toOrig.slice(toStart, toEnd); } @@ -685,22 +700,22 @@ const win32 = { if (resolvedPath.length >= 3) { var code = resolvedPath.charCodeAt(0); - if (code === 92/*\*/) { + if (code === CHAR_BACKWARD_SLASH) { // Possible UNC root - if (resolvedPath.charCodeAt(1) === 92/*\*/) { + if (resolvedPath.charCodeAt(1) === CHAR_BACKWARD_SLASH) { code = resolvedPath.charCodeAt(2); - if (code !== 63/*?*/ && code !== 46/*.*/) { + if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) { // Matched non-long UNC root, convert the path to a long UNC path return '\\\\?\\UNC\\' + resolvedPath.slice(2); } } - } else if ((code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 97/*a*/ && code <= 122/*z*/)) { + } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || + (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { // Possible device root - if (resolvedPath.charCodeAt(1) === 58/*:*/ && - resolvedPath.charCodeAt(2) === 92/*\*/) { + if (resolvedPath.charCodeAt(1) === CHAR_COLON && + resolvedPath.charCodeAt(2) === CHAR_BACKWARD_SLASH) { // Matched device root, convert the path to a long UNC path return '\\\\?\\' + resolvedPath; } @@ -723,20 +738,20 @@ const win32 = { // Try to match a root if (len > 1) { - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Possible UNC root rootEnd = offset = 1; code = path.charCodeAt(1); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Matched double path separator at beginning var j = 2; var last = j; // Match 1 or more non-path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) break; } if (j < len && j !== last) { @@ -745,7 +760,7 @@ const win32 = { // Match 1 or more path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code !== 47/*/*/ && code !== 92/*\*/) + if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) break; } if (j < len && j !== last) { @@ -754,7 +769,7 @@ const win32 = { // Match 1 or more non-path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) break; } if (j === len) { @@ -771,20 +786,20 @@ const win32 = { } } } - } else if ((code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 97/*a*/ && code <= 122/*z*/)) { + } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || + (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { // Possible device root - if (path.charCodeAt(1) === 58/*:*/) { + if (path.charCodeAt(1) === CHAR_COLON) { rootEnd = offset = 2; if (len > 2) { code = path.charCodeAt(2); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) rootEnd = offset = 3; } } } - } else if (code === 47/*/*/ || code === 92/*\*/) { + } else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // `path` contains just a path separator, exit early to avoid // unnecessary work return path; @@ -792,7 +807,7 @@ const win32 = { for (var i = len - 1; i >= offset; --i) { code = path.charCodeAt(i); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { if (!matchedSlash) { end = i; break; @@ -827,9 +842,9 @@ const win32 = { // disregarded if (path.length >= 2) { const drive = path.charCodeAt(0); - if ((drive >= 65/*A*/ && drive <= 90/*Z*/) || - (drive >= 97/*a*/ && drive <= 122/*z*/)) { - if (path.charCodeAt(1) === 58/*:*/) + if ((drive >= CHAR_UPPERCASE_A && drive <= CHAR_UPPERCASE_Z) || + (drive >= CHAR_LOWERCASE_A && drive <= CHAR_LOWERCASE_Z)) { + if (path.charCodeAt(1) === CHAR_COLON) start = 2; } } @@ -841,7 +856,7 @@ const win32 = { var firstNonSlashEnd = -1; for (i = path.length - 1; i >= start; --i) { const code = path.charCodeAt(i); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -881,7 +896,7 @@ const win32 = { } else { for (i = path.length - 1; i >= start; --i) { const code = path.charCodeAt(i); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -919,16 +934,16 @@ const win32 = { // disregarded if (path.length >= 2) { const code = path.charCodeAt(0); - if (path.charCodeAt(1) === 58/*:*/ && - ((code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 97/*a*/ && code <= 122/*z*/))) { + if (path.charCodeAt(1) === CHAR_COLON && + ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || + (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z))) { start = startPart = 2; } } for (var i = path.length - 1; i >= start; --i) { const code = path.charCodeAt(i); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -943,7 +958,7 @@ const win32 = { matchedSlash = false; end = i + 1; } - if (code === 46/*.*/) { + if (code === CHAR_DOT) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; @@ -992,19 +1007,19 @@ const win32 = { // Try to match a root if (len > 1) { - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Possible UNC root code = path.charCodeAt(1); rootEnd = 1; - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // Matched double path separator at beginning var j = 2; var last = j; // Match 1 or more non-path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) break; } if (j < len && j !== last) { @@ -1013,7 +1028,7 @@ const win32 = { // Match 1 or more path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code !== 47/*/*/ && code !== 92/*\*/) + if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) break; } if (j < len && j !== last) { @@ -1022,7 +1037,7 @@ const win32 = { // Match 1 or more non-path separators for (; j < len; ++j) { code = path.charCodeAt(j); - if (code === 47/*/*/ || code === 92/*\*/) + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) break; } if (j === len) { @@ -1037,15 +1052,15 @@ const win32 = { } } } - } else if ((code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 97/*a*/ && code <= 122/*z*/)) { + } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || + (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { // Possible device root - if (path.charCodeAt(1) === 58/*:*/) { + if (path.charCodeAt(1) === CHAR_COLON) { rootEnd = 2; if (len > 2) { code = path.charCodeAt(2); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { if (len === 3) { // `path` contains just a drive root, exit early to avoid // unnecessary work @@ -1062,7 +1077,7 @@ const win32 = { } } } - } else if (code === 47/*/*/ || code === 92/*\*/) { + } else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // `path` contains just a path separator, exit early to avoid // unnecessary work ret.root = ret.dir = path; @@ -1085,7 +1100,7 @@ const win32 = { // Get non-dir info for (; i >= rootEnd; --i) { code = path.charCodeAt(i); - if (code === 47/*/*/ || code === 92/*\*/) { + if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -1100,7 +1115,7 @@ const win32 = { matchedSlash = false; end = i + 1; } - if (code === 46/*.*/) { + if (code === CHAR_DOT) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; @@ -1174,7 +1189,7 @@ const posix = { } resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charCodeAt(0) === 47/*/*/; + resolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; } // At this point the path should be resolved to a full absolute path, but @@ -1202,8 +1217,9 @@ const posix = { if (path.length === 0) return '.'; - const isAbsolute = path.charCodeAt(0) === 47/*/*/; - const trailingSeparator = path.charCodeAt(path.length - 1) === 47/*/*/; + const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; + const trailingSeparator = + path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH; // Normalize the path path = normalizeStringPosix(path, !isAbsolute); @@ -1221,7 +1237,7 @@ const posix = { isAbsolute: function isAbsolute(path) { assertPath(path); - return path.length > 0 && path.charCodeAt(0) === 47/*/*/; + return path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH; }, @@ -1261,7 +1277,7 @@ const posix = { // Trim any leading backslashes var fromStart = 1; for (; fromStart < from.length; ++fromStart) { - if (from.charCodeAt(fromStart) !== 47/*/*/) + if (from.charCodeAt(fromStart) !== CHAR_FORWARD_SLASH) break; } var fromEnd = from.length; @@ -1270,7 +1286,7 @@ const posix = { // Trim any leading backslashes var toStart = 1; for (; toStart < to.length; ++toStart) { - if (to.charCodeAt(toStart) !== 47/*/*/) + if (to.charCodeAt(toStart) !== CHAR_FORWARD_SLASH) break; } var toEnd = to.length; @@ -1283,7 +1299,7 @@ const posix = { for (; i <= length; ++i) { if (i === length) { if (toLen > length) { - if (to.charCodeAt(toStart + i) === 47/*/*/) { + if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) { // We get here if `from` is the exact base path for `to`. // For example: from='/foo/bar'; to='/foo/bar/baz' return to.slice(toStart + i + 1); @@ -1293,7 +1309,7 @@ const posix = { return to.slice(toStart + i); } } else if (fromLen > length) { - if (from.charCodeAt(fromStart + i) === 47/*/*/) { + if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) { // We get here if `to` is the exact base path for `from`. // For example: from='/foo/bar/baz'; to='/foo/bar' lastCommonSep = i; @@ -1309,7 +1325,7 @@ const posix = { var toCode = to.charCodeAt(toStart + i); if (fromCode !== toCode) break; - else if (fromCode === 47/*/*/) + else if (fromCode === CHAR_FORWARD_SLASH) lastCommonSep = i; } @@ -1317,7 +1333,7 @@ const posix = { // Generate the relative path based on the path difference between `to` // and `from` for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { - if (i === fromEnd || from.charCodeAt(i) === 47/*/*/) { + if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) { if (out.length === 0) out += '..'; else @@ -1331,7 +1347,7 @@ const posix = { return out + to.slice(toStart + lastCommonSep); else { toStart += lastCommonSep; - if (to.charCodeAt(toStart) === 47/*/*/) + if (to.charCodeAt(toStart) === CHAR_FORWARD_SLASH) ++toStart; return to.slice(toStart); } @@ -1348,12 +1364,12 @@ const posix = { if (path.length === 0) return '.'; var code = path.charCodeAt(0); - var hasRoot = (code === 47/*/*/); + var hasRoot = (code === CHAR_FORWARD_SLASH); var end = -1; var matchedSlash = true; for (var i = path.length - 1; i >= 1; --i) { code = path.charCodeAt(i); - if (code === 47/*/*/) { + if (code === CHAR_FORWARD_SLASH) { if (!matchedSlash) { end = i; break; @@ -1389,7 +1405,7 @@ const posix = { var firstNonSlashEnd = -1; for (i = path.length - 1; i >= 0; --i) { const code = path.charCodeAt(i); - if (code === 47/*/*/) { + if (code === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -1428,7 +1444,7 @@ const posix = { return path.slice(start, end); } else { for (i = path.length - 1; i >= 0; --i) { - if (path.charCodeAt(i) === 47/*/*/) { + if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -1461,7 +1477,7 @@ const posix = { var preDotState = 0; for (var i = path.length - 1; i >= 0; --i) { const code = path.charCodeAt(i); - if (code === 47/*/*/) { + if (code === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -1476,7 +1492,7 @@ const posix = { matchedSlash = false; end = i + 1; } - if (code === 46/*.*/) { + if (code === CHAR_DOT) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; @@ -1519,7 +1535,7 @@ const posix = { if (path.length === 0) return ret; var code = path.charCodeAt(0); - var isAbsolute = (code === 47/*/*/); + var isAbsolute = (code === CHAR_FORWARD_SLASH); var start; if (isAbsolute) { ret.root = '/'; @@ -1540,7 +1556,7 @@ const posix = { // Get non-dir info for (; i >= start; --i) { code = path.charCodeAt(i); - if (code === 47/*/*/) { + if (code === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -1555,7 +1571,7 @@ const posix = { matchedSlash = false; end = i + 1; } - if (code === 46/*.*/) { + if (code === CHAR_DOT) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; diff --git a/node.gyp b/node.gyp index d5bfad90fd7842..826543a9d17ce1 100644 --- a/node.gyp +++ b/node.gyp @@ -95,6 +95,7 @@ 'lib/internal/crypto/random.js', 'lib/internal/crypto/sig.js', 'lib/internal/crypto/util.js', + 'lib/internal/constants.js', 'lib/internal/encoding.js', 'lib/internal/errors.js', 'lib/internal/freelist.js', From b6000d828525f991341bd69fc4550e1316d4c81c Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Fri, 9 Feb 2018 18:30:22 -0500 Subject: [PATCH 088/193] deps: patch V8 to 6.4.388.44 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18687 Refs: https://github.com/v8/v8/compare/6.4.388.42...6.4.388.44 Reviewed-By: Ruben Bridgewater Reviewed-By: Michaël Zasso Reviewed-By: Franziska Hinkelmann --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/objects-inl.h | 49 +++++++++---------- deps/v8/src/objects.cc | 27 +++++++--- deps/v8/src/objects.h | 2 +- .../src/profiler/heap-snapshot-generator.cc | 2 - deps/v8/test/cctest/test-heap-profiler.cc | 11 +++++ .../mjsunit/regress/regress-crbug-806388.js | 20 ++++++++ 7 files changed, 77 insertions(+), 36 deletions(-) create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-806388.js diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 8c4bc0237702ed..c3bd1dfe2dd281 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 4 #define V8_BUILD_NUMBER 388 -#define V8_PATCH_LEVEL 42 +#define V8_PATCH_LEVEL 44 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index 77ad0872686c96..1cbb2990574292 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -2231,7 +2231,8 @@ int Map::NumberOfOwnDescriptors() const { void Map::SetNumberOfOwnDescriptors(int number) { - DCHECK(number <= instance_descriptors()->number_of_descriptors()); + CHECK_LE(static_cast(number), + static_cast(kMaxNumberOfDescriptors)); set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number)); } @@ -2239,8 +2240,9 @@ int Map::EnumLength() const { return EnumLengthBits::decode(bit_field3()); } void Map::SetEnumLength(int length) { if (length != kInvalidEnumCacheSentinel) { - DCHECK_GE(length, 0); - DCHECK(length <= NumberOfOwnDescriptors()); + DCHECK_LE(length, NumberOfOwnDescriptors()); + CHECK_LE(static_cast(length), + static_cast(kMaxNumberOfDescriptors)); } set_bit_field3(EnumLengthBits::update(bit_field3(), length)); } @@ -3002,9 +3004,9 @@ int Map::instance_size() const { } void Map::set_instance_size(int value) { - DCHECK_EQ(0, value & (kPointerSize - 1)); + CHECK_EQ(0, value & (kPointerSize - 1)); value >>= kPointerSizeLog2; - DCHECK(0 <= value && value < 256); + CHECK_LT(static_cast(value), 256); set_instance_size_in_words(value); } @@ -3015,8 +3017,7 @@ int Map::inobject_properties_start_or_constructor_function_index() const { void Map::set_inobject_properties_start_or_constructor_function_index( int value) { - DCHECK_LE(0, value); - DCHECK_LT(value, 256); + CHECK_LT(static_cast(value), 256); RELAXED_WRITE_BYTE_FIELD( this, kInObjectPropertiesStartOrConstructorFunctionIndexOffset, static_cast(value)); @@ -3028,7 +3029,7 @@ int Map::GetInObjectPropertiesStartInWords() const { } void Map::SetInObjectPropertiesStartInWords(int value) { - DCHECK(IsJSObjectMap()); + CHECK(IsJSObjectMap()); set_inobject_properties_start_or_constructor_function_index(value); } @@ -3044,7 +3045,7 @@ int Map::GetConstructorFunctionIndex() const { void Map::SetConstructorFunctionIndex(int value) { - DCHECK(IsPrimitiveMap()); + CHECK(IsPrimitiveMap()); set_inobject_properties_start_or_constructor_function_index(value); } @@ -3153,8 +3154,7 @@ int Map::used_or_unused_instance_size_in_words() const { } void Map::set_used_or_unused_instance_size_in_words(int value) { - DCHECK_LE(0, value); - DCHECK_LE(value, 255); + CHECK_LE(static_cast(value), 255); WRITE_BYTE_FIELD(this, kUsedOrUnusedInstanceSizeInWordsOffset, static_cast(value)); } @@ -3172,12 +3172,12 @@ int Map::UsedInstanceSize() const { void Map::SetInObjectUnusedPropertyFields(int value) { STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kPointerSize); if (!IsJSObjectMap()) { - DCHECK_EQ(0, value); + CHECK_EQ(0, value); set_used_or_unused_instance_size_in_words(0); DCHECK_EQ(0, UnusedPropertyFields()); return; } - DCHECK_LE(0, value); + CHECK_LE(0, value); DCHECK_LE(value, GetInObjectProperties()); int used_inobject_properties = GetInObjectProperties() - value; set_used_or_unused_instance_size_in_words( @@ -3187,8 +3187,7 @@ void Map::SetInObjectUnusedPropertyFields(int value) { void Map::SetOutOfObjectUnusedPropertyFields(int value) { STATIC_ASSERT(JSObject::kFieldsAdded == JSObject::kHeaderSize / kPointerSize); - DCHECK_LE(0, value); - DCHECK_LT(value, JSObject::kFieldsAdded); + CHECK_LT(static_cast(value), JSObject::kFieldsAdded); // For out of object properties "used_instance_size_in_words" byte encodes // the slack in the property array. set_used_or_unused_instance_size_in_words(value); @@ -3227,8 +3226,8 @@ void Map::AccountAddedOutOfObjectPropertyField(int unused_in_property_array) { if (unused_in_property_array < 0) { unused_in_property_array += JSObject::kFieldsAdded; } - DCHECK_GE(unused_in_property_array, 0); - DCHECK_LT(unused_in_property_array, JSObject::kFieldsAdded); + CHECK_LT(static_cast(unused_in_property_array), + JSObject::kFieldsAdded); set_used_or_unused_instance_size_in_words(unused_in_property_array); DCHECK_EQ(unused_in_property_array, UnusedPropertyFields()); } @@ -3358,7 +3357,7 @@ bool Map::should_be_fast_prototype_map() const { } void Map::set_elements_kind(ElementsKind elements_kind) { - DCHECK_LT(static_cast(elements_kind), kElementsKindCount); + CHECK_LT(static_cast(elements_kind), kElementsKindCount); DCHECK_LE(kElementsKindCount, 1 << Map::ElementsKindBits::kSize); set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind)); DCHECK(this->elements_kind() == elements_kind); @@ -3700,7 +3699,7 @@ Object* Map::prototype_info() const { void Map::set_prototype_info(Object* value, WriteBarrierMode mode) { - DCHECK(is_prototype_map()); + CHECK(is_prototype_map()); WRITE_FIELD(this, Map::kTransitionsOrPrototypeInfoOffset, value); CONDITIONAL_WRITE_BARRIER( GetHeap(), this, Map::kTransitionsOrPrototypeInfoOffset, value, mode); @@ -3708,11 +3707,11 @@ void Map::set_prototype_info(Object* value, WriteBarrierMode mode) { void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { - DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); - DCHECK(value->IsMap()); - DCHECK(GetBackPointer()->IsUndefined(GetIsolate())); - DCHECK(!value->IsMap() || - Map::cast(value)->GetConstructor() == constructor_or_backpointer()); + CHECK_GE(instance_type(), FIRST_JS_RECEIVER_TYPE); + CHECK(value->IsMap()); + CHECK(GetBackPointer()->IsUndefined(GetIsolate())); + CHECK_IMPLIES(value->IsMap(), Map::cast(value)->GetConstructor() == + constructor_or_backpointer()); set_constructor_or_backpointer(value, mode); } @@ -3743,7 +3742,7 @@ FunctionTemplateInfo* Map::GetFunctionTemplateInfo() const { void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { // Never overwrite a back pointer with a constructor. - DCHECK(!constructor_or_backpointer()->IsMap()); + CHECK(!constructor_or_backpointer()->IsMap()); set_constructor_or_backpointer(constructor, mode); } diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 7b3c632a447a68..bd876e67d7b650 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -13014,14 +13014,19 @@ MaybeHandle JSFunction::GetDerivedMap(Isolate* isolate, constructor_initial_map->UnusedPropertyFields(); int instance_size; int in_object_properties; - CalculateInstanceSizeForDerivedClass(function, instance_type, - embedder_fields, &instance_size, - &in_object_properties); + bool success = CalculateInstanceSizeForDerivedClass( + function, instance_type, embedder_fields, &instance_size, + &in_object_properties); int unused_property_fields = in_object_properties - pre_allocated; - Handle map = - Map::CopyInitialMap(constructor_initial_map, instance_size, - in_object_properties, unused_property_fields); + + Handle map; + if (success) { + map = Map::CopyInitialMap(constructor_initial_map, instance_size, + in_object_properties, unused_property_fields); + } else { + map = Map::CopyInitialMap(constructor_initial_map); + } map->set_new_target_is_base(false); JSFunction::SetInitialMap(function, map, prototype); @@ -13726,12 +13731,14 @@ void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type, requested_embedder_fields; } -void JSFunction::CalculateInstanceSizeForDerivedClass( +// static +bool JSFunction::CalculateInstanceSizeForDerivedClass( Handle function, InstanceType instance_type, int requested_embedder_fields, int* instance_size, int* in_object_properties) { Isolate* isolate = function->GetIsolate(); int expected_nof_properties = 0; + bool result = true; for (PrototypeIterator iter(isolate, function, kStartAtReceiver); !iter.IsAtEnd(); iter.Advance()) { Handle current = @@ -13745,6 +13752,11 @@ void JSFunction::CalculateInstanceSizeForDerivedClass( Compiler::Compile(func, Compiler::CLEAR_EXCEPTION)) { DCHECK(shared->is_compiled()); expected_nof_properties += shared->expected_nof_properties(); + } else if (!shared->is_compiled()) { + // In case there was a compilation error for the constructor we will + // throw an error during instantiation. Hence we directly return 0; + result = false; + break; } if (!IsDerivedConstructor(shared->kind())) { break; @@ -13753,6 +13765,7 @@ void JSFunction::CalculateInstanceSizeForDerivedClass( CalculateInstanceSizeHelper(instance_type, true, requested_embedder_fields, expected_nof_properties, instance_size, in_object_properties); + return result; } diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index a9be023ec83a20..521c0e6554932d 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -4082,7 +4082,7 @@ class JSFunction: public JSObject { DECL_CAST(JSFunction) // Calculate the instance size and in-object properties count. - static void CalculateInstanceSizeForDerivedClass( + static bool CalculateInstanceSizeForDerivedClass( Handle function, InstanceType instance_type, int requested_embedder_fields, int* instance_size, int* in_object_properties); diff --git a/deps/v8/src/profiler/heap-snapshot-generator.cc b/deps/v8/src/profiler/heap-snapshot-generator.cc index 1f6459c904fbb8..6f3a952d1f740a 100644 --- a/deps/v8/src/profiler/heap-snapshot-generator.cc +++ b/deps/v8/src/profiler/heap-snapshot-generator.cc @@ -1113,8 +1113,6 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { constructor_or_backpointer, Map::kConstructorOrBackPointerOffset); } else { - DCHECK(constructor_or_backpointer->IsJSFunction() || - constructor_or_backpointer->IsNull(map->GetIsolate())); SetInternalReference(map, entry, "constructor", constructor_or_backpointer, Map::kConstructorOrBackPointerOffset); } diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index a0796ccd56c158..5a94708ba8ec4e 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -3184,3 +3184,14 @@ TEST(SamplingHeapProfilerSampleDuringDeopt) { CHECK(profile); heap_profiler->StopSamplingHeapProfiler(); } + +TEST(HeapSnapshotPrototypeNotJSReceiver) { + LocalContext env; + v8::HandleScope scope(env->GetIsolate()); + v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); + CompileRun( + "function object() {}" + "object.prototype = 42;"); + const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); + CHECK(ValidateSnapshot(snapshot)); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-806388.js b/deps/v8/test/mjsunit/regress/regress-crbug-806388.js new file mode 100644 index 00000000000000..b55b50107ec977 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-806388.js @@ -0,0 +1,20 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --enable-slow-asserts --expose-gc + +class Derived extends Array { + constructor(a) { + // Syntax Error. + const a = 1; + } +} + +// Derived is not a subclass of RegExp +let o = Reflect.construct(RegExp, [], Derived); +o.lastIndex = 0x1234; +%HeapObjectVerify(o); + +gc(); +%HeapObjectVerify(o); From e782715d0a1c33f98212bdc064b4b4eea198e605 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 12 Feb 2018 01:21:19 -0500 Subject: [PATCH 089/193] string_decoder: fix regressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are libraries which invoke StringDecoder using .call and .inherits, which directly conflicts with making StringDecoder be a class which can only be invoked with the new keyword. Revert to declaring it as a function. StringDecoder#lastNeed was not defined, redefine it using the new interface and fix StringDecoder#lastTotal. PR-URL: https://github.com/nodejs/node/pull/18723 Refs: https://github.com/nodejs/node/pull/18537 Reviewed-By: Michaël Zasso Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Evan Lucas Reviewed-By: Luigi Pinca Reviewed-By: Tiancheng "Timothy" Gu --- lib/string_decoder.js | 88 ++++++++++++++++------------ test/parallel/test-string-decoder.js | 10 ++++ 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/lib/string_decoder.js b/lib/string_decoder.js index d955a663307de9..04d31b2607c63e 100644 --- a/lib/string_decoder.js +++ b/lib/string_decoder.js @@ -56,47 +56,61 @@ for (var i = 0; i < encodings.length; ++i) // StringDecoder provides an interface for efficiently splitting a series of // buffers into a series of JS strings without breaking apart multi-byte // characters. -class StringDecoder { - constructor(encoding) { - this.encoding = normalizeEncoding(encoding); - this[kNativeDecoder] = Buffer.alloc(kSize); - this[kNativeDecoder][kEncodingField] = encodingsMap[this.encoding]; - } - - write(buf) { - if (typeof buf === 'string') - return buf; - if (!ArrayBuffer.isView(buf)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buf', - ['Buffer', 'Uint8Array', 'ArrayBufferView']); - return decode(this[kNativeDecoder], buf); - } - - end(buf) { - let ret = ''; - if (buf !== undefined) - ret = this.write(buf); - if (this[kNativeDecoder][kBufferedBytes] > 0) - ret += flush(this[kNativeDecoder]); - return ret; - } +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + this[kNativeDecoder] = Buffer.alloc(kSize); + this[kNativeDecoder][kEncodingField] = encodingsMap[this.encoding]; +} - /* Everything below this line is undocumented legacy stuff. */ +StringDecoder.prototype.write = function write(buf) { + if (typeof buf === 'string') + return buf; + if (!ArrayBuffer.isView(buf)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buf', + ['Buffer', 'Uint8Array', 'ArrayBufferView']); + return decode(this[kNativeDecoder], buf); +}; - text(buf, offset) { - this[kNativeDecoder][kMissingBytes] = 0; - this[kNativeDecoder][kBufferedBytes] = 0; - return this.write(buf.slice(offset)); - } +StringDecoder.prototype.end = function end(buf) { + let ret = ''; + if (buf !== undefined) + ret = this.write(buf); + if (this[kNativeDecoder][kBufferedBytes] > 0) + ret += flush(this[kNativeDecoder]); + return ret; +}; - get lastTotal() { - return this[kNativeDecoder][kBufferedBytes] + this.lastNeed; - } +/* Everything below this line is undocumented legacy stuff. */ +StringDecoder.prototype.text = function text(buf, offset) { + this[kNativeDecoder][kMissingBytes] = 0; + this[kNativeDecoder][kBufferedBytes] = 0; + return this.write(buf.slice(offset)); +}; - get lastChar() { - return this[kNativeDecoder].subarray(kIncompleteCharactersStart, - kIncompleteCharactersEnd); +Object.defineProperties(StringDecoder.prototype, { + lastChar: { + configurable: true, + enumerable: true, + get() { + return this[kNativeDecoder].subarray(kIncompleteCharactersStart, + kIncompleteCharactersEnd); + } + }, + lastNeed: { + configurable: true, + enumerable: true, + get() { + return this[kNativeDecoder][kMissingBytes]; + } + }, + lastTotal: { + configurable: true, + enumerable: true, + get() { + return this[kNativeDecoder][kBufferedBytes] + + this[kNativeDecoder][kMissingBytes]; + } } -} +}); exports.StringDecoder = StringDecoder; diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js index 21a0b6c3e38539..0e7ea8ffdd56a6 100644 --- a/test/parallel/test-string-decoder.js +++ b/test/parallel/test-string-decoder.js @@ -29,6 +29,11 @@ const StringDecoder = require('string_decoder').StringDecoder; let decoder = new StringDecoder(); assert.strictEqual(decoder.encoding, 'utf8'); +// Should work without 'new' keyword +const decoder2 = {}; +StringDecoder.call(decoder2); +assert.strictEqual(decoder2.encoding, 'utf8'); + // UTF-8 test('utf-8', Buffer.from('$', 'utf-8'), '$'); test('utf-8', Buffer.from('¢', 'utf-8'), '¢'); @@ -84,6 +89,11 @@ test('utf16le', Buffer.from('3DD84DDC', 'hex'), '\ud83d\udc4d'); // thumbs up // Additional UTF-8 tests decoder = new StringDecoder('utf8'); assert.strictEqual(decoder.write(Buffer.from('E1', 'hex')), ''); + +// A quick test for lastNeed & lastTotal which are undocumented. +assert.strictEqual(decoder.lastNeed, 2); +assert.strictEqual(decoder.lastTotal, 3); + assert.strictEqual(decoder.end(), '\ufffd'); decoder = new StringDecoder('utf8'); From 60e612d0b0e3adbeb15d9b0b5a437726d1071cda Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 24 Jan 2018 01:39:46 -0800 Subject: [PATCH 090/193] 2018-01-13, Version 6.13.0 'Boron' (LTS) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This LTS release comes with 112 commits, 17 of which are considered Semver-Minor. This includes 32 which are doc related, 30 which are test related, 8 which are build / tool related and 1 commit which updates a dependency. Notable Changes: * console: - added console.count() and console.clear() (James M Snell) https://github.com/nodejs/node/pull/12678 * crypto: - expose ECDH class (Bryan English) https://github.com/nodejs/node/pull/8188 - added cypto.randomFill() and crypto.randomFillSync() (Evan Lucas) https://github.com/nodejs/node/pull/10209 - warn on invalid authentication tag length (Tobias Nießen) https://github.com/nodejs/node/pull/17566 * deps: - upgrade libuv to 1.16.1 (cjihrig) https://github.com/nodejs/node/pull/16835 * dgram: - added socket.setMulticastInterface() (Will Young) https://github.com/nodejs/node/pull/7855 * http: - add agent.keepSocketAlive and agent.reuseSocket as to allow overridable keep-alive behavior of `Agent` (Fedor Indutny) https://github.com/nodejs/node/pull/13005 * lib: - return this from net.Socket.end() (Sam Roberts) https://github.com/nodejs/node/pull/13481 * module: - add builtinModules api that provides list of all builtin modules in Node (Jon Moss) https://github.com/nodejs/node/pull/16386 * net: - return this from getConnections() (Sam Roberts) https://github.com/nodejs/node/pull/13553 * promises: - more robust stringification for unhandled rejections (Timothy Gu) https://github.com/nodejs/node/pull/13784 * repl: - improve require() autocompletion (Alexey Orlenko) https://github.com/nodejs/node/pull/14409 * src: - add openssl-system-ca-path configure option (Daniel Bevenius) https://github.com/nodejs/node/pull/16790 - add --use-bundled-ca --use-openssl-ca check (Daniel Bevenius) https://github.com/nodejs/node/pull/12087 - add process.ppid (cjihrig) https://github.com/nodejs/node/pull/16839 * tls: - accept `lookup` option for `tls.connect()` (Fedor Indutny) https://github.com/nodejs/node/pull/12839 * tools, build: - a new macOS installer! (JP Wesselink) https://github.com/nodejs/node/pull/15179 * url: - WHATWG URL api support (James M Snell) https://github.com/nodejs/node/pull/7448 * util: - add %i and %f formatting specifiers (Roman Reiss) https://github.com/nodejs/node/pull/10308 PR-URL: https://github.com/nodejs/node/pull/18342 --- CHANGELOG.md | 3 +- doc/changelogs/CHANGELOG_V6.md | 159 +++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2787fbc8bae41..97b162993d511d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,7 +60,8 @@ release. 8.0.0
-6.12.3
+6.13.0
+6.12.3
6.12.2
6.12.1
6.12.0
diff --git a/doc/changelogs/CHANGELOG_V6.md b/doc/changelogs/CHANGELOG_V6.md index 228bcbc37d144a..8f9f993bebe6b0 100644 --- a/doc/changelogs/CHANGELOG_V6.md +++ b/doc/changelogs/CHANGELOG_V6.md @@ -9,6 +9,7 @@ +6.13.0
6.12.3
6.12.2
6.12.1
@@ -63,6 +64,164 @@ [Node.js Long Term Support Plan](https://github.com/nodejs/LTS) and will be supported actively until April 2018 and maintained until April 2019. + +## 2018-02-13, Version 6.13.0 'Boron' (LTS), @MylesBorins + +This LTS release comes with 112 commits, 17 of which are considered Semver-Minor. This includes 32 which are doc related, +31 which are test related, 8 which are build / tool related and 1 commit which updates a dependency. + +### Notable Changes + +* **console**: + - added console.count() and console.clear() (James M Snell) [#12678](https://github.com/nodejs/node/pull/12678) +* **crypto**: + - expose ECDH class (Bryan English) [#8188](https://github.com/nodejs/node/pull/8188) + - added cypto.randomFill() and crypto.randomFillSync() (Evan Lucas) [#10209](https://github.com/nodejs/node/pull/10209) + - warn on invalid authentication tag length (Tobias Nießen) [#17566](https://github.com/nodejs/node/pull/17566) +* **deps**: + - upgrade libuv to 1.16.1 (cjihrig) [#16835](https://github.com/nodejs/node/pull/16835) +* **dgram**: + - added socket.setMulticastInterface() (Will Young) [#7855](https://github.com/nodejs/node/pull/7855) +* **http**: + - add agent.keepSocketAlive and agent.reuseSocket as to allow overridable keep-alive behavior of `Agent` (Fedor Indutny) [#13005](https://github.com/nodejs/node/pull/13005) +* **lib**: + - return this from net.Socket.end() (Sam Roberts) [#13481](https://github.com/nodejs/node/pull/13481) +* **module**: + - add builtinModules api that provides list of all builtin modules in Node (Jon Moss) [#16386](https://github.com/nodejs/node/pull/16386) +* **net**: + - return this from getConnections() (Sam Roberts) [#13553](https://github.com/nodejs/node/pull/13553) +* **promises**: + - more robust stringification for unhandled rejections (Timothy Gu) [#13784](https://github.com/nodejs/node/pull/13784) +* **repl**: + - improve require() autocompletion (Alexey Orlenko) [#14409](https://github.com/nodejs/node/pull/14409) +* **src**: + - add openssl-system-ca-path configure option (Daniel Bevenius) [#16790](https://github.com/nodejs/node/pull/16790) + - add --use-bundled-ca --use-openssl-ca check (Daniel Bevenius) [#12087](https://github.com/nodejs/node/pull/12087) + - add process.ppid (cjihrig) [#16839](https://github.com/nodejs/node/pull/16839) +* **tls**: + - accept `lookup` option for `tls.connect()` (Fedor Indutny) [#12839](https://github.com/nodejs/node/pull/12839) +* **tools, build**: + - a new macOS installer! (JP Wesselink) [#15179](https://github.com/nodejs/node/pull/15179) +* **url**: + - WHATWG URL api support (James M Snell) [#7448](https://github.com/nodejs/node/pull/7448) +* **util**: + - add %i and %f formatting specifiers (Roman Reiss) [#10308](https://github.com/nodejs/node/pull/10308) + +### Commits + +* [[`6f33953d90`](https://github.com/nodejs/node/commit/6f33953d90)] - **benchmark**: fix timeout in write-stream-throughput (Anatoli Papirovski) [#17958](https://github.com/nodejs/node/pull/17958) +* [[`ce136392fb`](https://github.com/nodejs/node/commit/ce136392fb)] - **(SEMVER-MINOR)** **console**: add console.count() and console.clear() (James M Snell) [#12678](https://github.com/nodejs/node/pull/12678) +* [[`691cd5a3d1`](https://github.com/nodejs/node/commit/691cd5a3d1)] - **crypto**: warn on invalid authentication tag length (Tobias Nießen) [#17566](https://github.com/nodejs/node/pull/17566) +* [[`4b4e4db1c1`](https://github.com/nodejs/node/commit/4b4e4db1c1)] - **crypto**: add ocsp_request ClientHelloParser::Reset (Daniel Bevenius) [#17753](https://github.com/nodejs/node/pull/17753) +* [[`c377d2299a`](https://github.com/nodejs/node/commit/c377d2299a)] - **crypto**: remove unused header in clienthello.h (Daniel Bevenius) [#17752](https://github.com/nodejs/node/pull/17752) +* [[`ddd9d85681`](https://github.com/nodejs/node/commit/ddd9d85681)] - **crypto**: remove BIO_set_shutdown (Daniel Bevenius) [#17542](https://github.com/nodejs/node/pull/17542) +* [[`f3b3437e48`](https://github.com/nodejs/node/commit/f3b3437e48)] - **(SEMVER-MINOR)** **crypto**: expose ECDH class (Bryan English) [#8188](https://github.com/nodejs/node/pull/8188) +* [[`6f62f83468`](https://github.com/nodejs/node/commit/6f62f83468)] - **(SEMVER-MINOR)** **crypto**: add randomFill and randomFillSync (Evan Lucas) [#10209](https://github.com/nodejs/node/pull/10209) +* [[`a1d7469aef`](https://github.com/nodejs/node/commit/a1d7469aef)] - **(SEMVER-MINOR)** **deps**: upgrade libuv to 1.16.1 (cjihrig) [#16835](https://github.com/nodejs/node/pull/16835) +* [[`8f2e52abd7`](https://github.com/nodejs/node/commit/8f2e52abd7)] - **(SEMVER-MINOR)** **dgram**: added setMulticastInterface() (Will Young) [#7855](https://github.com/nodejs/node/pull/7855) +* [[`1b689863ee`](https://github.com/nodejs/node/commit/1b689863ee)] - **doc**: remove x86 from os.arch() options (Gibson Fahnestock) [#17899](https://github.com/nodejs/node/pull/17899) +* [[`8f80548b7f`](https://github.com/nodejs/node/commit/8f80548b7f)] - **doc**: move matthewloring to emeriti (Rich Trott) [#17998](https://github.com/nodejs/node/pull/17998) +* [[`15d0ed5f33`](https://github.com/nodejs/node/commit/15d0ed5f33)] - **doc**: move joshgav to TSC emeriti list (Rich Trott) [#17953](https://github.com/nodejs/node/pull/17953) +* [[`12db4d97b2`](https://github.com/nodejs/node/commit/12db4d97b2)] - **doc**: improve security section of README.md (Rich Trott) [#17929](https://github.com/nodejs/node/pull/17929) +* [[`b79189b9b6`](https://github.com/nodejs/node/commit/b79189b9b6)] - **doc**: copy-edit COLLABORATOR_GUIDE.md (Rich Trott) [#17922](https://github.com/nodejs/node/pull/17922) +* [[`7628640db6`](https://github.com/nodejs/node/commit/7628640db6)] - **doc**: improve alt text (Rich Trott) [#17922](https://github.com/nodejs/node/pull/17922) +* [[`bb022dbb96`](https://github.com/nodejs/node/commit/bb022dbb96)] - **doc**: fix spelling of contributors (Rich Trott) [#17922](https://github.com/nodejs/node/pull/17922) +* [[`21c5d820bb`](https://github.com/nodejs/node/commit/21c5d820bb)] - **doc**: add references to PR communication articles (Salame William) [#17902](https://github.com/nodejs/node/pull/17902) +* [[`3c3a631643`](https://github.com/nodejs/node/commit/3c3a631643)] - **doc**: fix typo (Tobias Nießen) [#17900](https://github.com/nodejs/node/pull/17900) +* [[`5b00ee31ee`](https://github.com/nodejs/node/commit/5b00ee31ee)] - **doc**: use my legal name in README (Timothy Gu) [#17894](https://github.com/nodejs/node/pull/17894) +* [[`0ce48f9094`](https://github.com/nodejs/node/commit/0ce48f9094)] - **doc**: use dashes instead of asterisks (Ruben Bridgewater) [#17722](https://github.com/nodejs/node/pull/17722) +* [[`f6b4aa62bc`](https://github.com/nodejs/node/commit/f6b4aa62bc)] - **doc**: update AUTHORS list (Ruben Bridgewater) [#17805](https://github.com/nodejs/node/pull/17805) +* [[`653c026578`](https://github.com/nodejs/node/commit/653c026578)] - **doc**: add starkwang to collaborators (Weijia Wang) [#17847](https://github.com/nodejs/node/pull/17847) +* [[`68164145de`](https://github.com/nodejs/node/commit/68164145de)] - **doc**: improve fs api descriptions (Evan Lucas) [#17679](https://github.com/nodejs/node/pull/17679) +* [[`722640f562`](https://github.com/nodejs/node/commit/722640f562)] - **doc**: instructions on how to make membership public (Michael Dawson) [#17688](https://github.com/nodejs/node/pull/17688) +* [[`1553c7326c`](https://github.com/nodejs/node/commit/1553c7326c)] - **doc**: removed extra explanation in api/buffer.md (Waleed Ashraf) [#17796](https://github.com/nodejs/node/pull/17796) +* [[`22607951b8`](https://github.com/nodejs/node/commit/22607951b8)] - **doc**: use american spelling as per style guide (sreepurnajasti) [#17818](https://github.com/nodejs/node/pull/17818) +* [[`d85840dd8f`](https://github.com/nodejs/node/commit/d85840dd8f)] - **doc**: require CI status indicator in PRs (Nikolai Vavilov) [#17151](https://github.com/nodejs/node/pull/17151) +* [[`5cc6dd6295`](https://github.com/nodejs/node/commit/5cc6dd6295)] - **doc**: remove duplicate the from onboarding.md (sreepurnajasti) [#17733](https://github.com/nodejs/node/pull/17733) +* [[`a6f7ba4f09`](https://github.com/nodejs/node/commit/a6f7ba4f09)] - **doc**: fix typo in README.md (Weijia Wang) [#17729](https://github.com/nodejs/node/pull/17729) +* [[`df48a5ded8`](https://github.com/nodejs/node/commit/df48a5ded8)] - **doc**: fix typo in child_process.md (Rich Trott) [#17727](https://github.com/nodejs/node/pull/17727) +* [[`4cba4324ff`](https://github.com/nodejs/node/commit/4cba4324ff)] - **doc**: improve release guide (Evan Lucas) [#17677](https://github.com/nodejs/node/pull/17677) +* [[`423ef3ddbf`](https://github.com/nodejs/node/commit/423ef3ddbf)] - **doc**: not all example code can be run without 1:1 (Jeremiah Senkpiel) [#17702](https://github.com/nodejs/node/pull/17702) +* [[`c683efbf6d`](https://github.com/nodejs/node/commit/c683efbf6d)] - **doc**: adjust TTY wording & add inter-doc links (Jeremiah Senkpiel) [#17702](https://github.com/nodejs/node/pull/17702) +* [[`14ffddd989`](https://github.com/nodejs/node/commit/14ffddd989)] - **doc**: add isTTY property documentation (SonaySevik) [#16828](https://github.com/nodejs/node/pull/16828) +* [[`9c8d0366b3`](https://github.com/nodejs/node/commit/9c8d0366b3)] - **doc**: fix fs.existsSync description (Jeremiah Senkpiel) [#17702](https://github.com/nodejs/node/pull/17702) +* [[`6abd4599af`](https://github.com/nodejs/node/commit/6abd4599af)] - **doc**: improve documentation.md (Jeremiah Senkpiel) [#17702](https://github.com/nodejs/node/pull/17702) +* [[`d0b89a12ec`](https://github.com/nodejs/node/commit/d0b89a12ec)] - **doc**: add countdown module to writing tests guide (Bamieh) [#17201](https://github.com/nodejs/node/pull/17201) +* [[`1eac4055f0`](https://github.com/nodejs/node/commit/1eac4055f0)] - **doc**: include Daniel Bevenius as a TSC member (Rich Trott) [#17652](https://github.com/nodejs/node/pull/17652) +* [[`83fe79c558`](https://github.com/nodejs/node/commit/83fe79c558)] - **doc**: correct pbkdf2 salt length recommendation (Will Clark) [#17524](https://github.com/nodejs/node/pull/17524) +* [[`43a2bc040f`](https://github.com/nodejs/node/commit/43a2bc040f)] - **doc**: improve randomfill and fix broken link (Sakthipriyan Vairamani (thefourtheye)) [#12541](https://github.com/nodejs/node/pull/12541) +* [[`ef0213c0b8`](https://github.com/nodejs/node/commit/ef0213c0b8)] - **doc**: move Code of Conduct to admin repo (Myles Borins) [#17301](https://github.com/nodejs/node/pull/17301) +* [[`e16d01fc94`](https://github.com/nodejs/node/commit/e16d01fc94)] - **gitignore**: ignore *.VC.db files (Tobias Nießen) [#17898](https://github.com/nodejs/node/pull/17898) +* [[`1390c280bc`](https://github.com/nodejs/node/commit/1390c280bc)] - **(SEMVER-MINOR)** **http**: overridable keep-alive behavior of `Agent` (Fedor Indutny) [#13005](https://github.com/nodejs/node/pull/13005) +* [[`063c4fa345`](https://github.com/nodejs/node/commit/063c4fa345)] - **(SEMVER-MINOR)** **lib**: return this from net.Socket.end() (Sam Roberts) [#13481](https://github.com/nodejs/node/pull/13481) +* [[`cdf4a9c394`](https://github.com/nodejs/node/commit/cdf4a9c394)] - **(SEMVER-MINOR)** **module**: add builtinModules (Jon Moss) [#16386](https://github.com/nodejs/node/pull/16386) +* [[`ffc1444117`](https://github.com/nodejs/node/commit/ffc1444117)] - **net**: remove ADDRCONFIG DNS hint on Windows (Bartosz Sosnowski) [#17662](https://github.com/nodejs/node/pull/17662) +* [[`6a27774882`](https://github.com/nodejs/node/commit/6a27774882)] - **(SEMVER-MINOR)** **net**: return this from getConnections() (Sam Roberts) [#13553](https://github.com/nodejs/node/pull/13553) +* [[`a09e2fd43b`](https://github.com/nodejs/node/commit/a09e2fd43b)] - **net**: fix timeout with null handle (Anatoli Papirovski) [#16489](https://github.com/nodejs/node/pull/16489) +* [[`a301c1a0e0`](https://github.com/nodejs/node/commit/a301c1a0e0)] - **net**: fix timeouts during long writes (Anatoli Papirovski) [#15791](https://github.com/nodejs/node/pull/15791) +* [[`c64a73ba6c`](https://github.com/nodejs/node/commit/c64a73ba6c)] - **promises**: more robust stringification (Timothy Gu) [#13784](https://github.com/nodejs/node/pull/13784) +* [[`3b9fea0782`](https://github.com/nodejs/node/commit/3b9fea0782)] - **(SEMVER-MINOR)** **repl**: improve require() autocompletion (Alexey Orlenko) [#14409](https://github.com/nodejs/node/pull/14409) +* [[`9181fbb699`](https://github.com/nodejs/node/commit/9181fbb699)] - **src**: dumb down code by removing std::move (Anna Henningsen) [#18324](https://github.com/nodejs/node/pull/18324) +* [[`57865a9213`](https://github.com/nodejs/node/commit/57865a9213)] - **src**: use correct OOB check for IPv6 parsing (Anna Henningsen) [#17470](https://github.com/nodejs/node/pull/17470) +* [[`f306d3eb7a`](https://github.com/nodejs/node/commit/f306d3eb7a)] - **src**: make url host a proper C++ class (Anna Henningsen) [#17470](https://github.com/nodejs/node/pull/17470) +* [[`1976c7c7a5`](https://github.com/nodejs/node/commit/1976c7c7a5)] - **src**: move url internals into anonymous namespace (Anna Henningsen) [#17470](https://github.com/nodejs/node/pull/17470) +* [[`d66f469931`](https://github.com/nodejs/node/commit/d66f469931)] - **src**: minor cleanups to node_url.cc (Anna Henningsen) [#17470](https://github.com/nodejs/node/pull/17470) +* [[`979af518c1`](https://github.com/nodejs/node/commit/979af518c1)] - **src**: remove nonexistent method from header file (Anna Henningsen) [#17748](https://github.com/nodejs/node/pull/17748) +* [[`2268d00e38`](https://github.com/nodejs/node/commit/2268d00e38)] - **(SEMVER-MINOR)** **src**: add openssl-system-ca-path configure option (Daniel Bevenius) [#16790](https://github.com/nodejs/node/pull/16790) +* [[`a6d2384c9a`](https://github.com/nodejs/node/commit/a6d2384c9a)] - **src**: clean up MaybeStackBuffer (Timothy Gu) [#11464](https://github.com/nodejs/node/pull/11464) +* [[`9f3b4ad5bd`](https://github.com/nodejs/node/commit/9f3b4ad5bd)] - **src**: fix incorrect macro comment (Daniel Bevenius) [#12688](https://github.com/nodejs/node/pull/12688) +* [[`2b29cea1b4`](https://github.com/nodejs/node/commit/2b29cea1b4)] - **src**: guard bundled_ca/openssl_ca with HAVE_OPENSSL (Daniel Bevenius) [#12302](https://github.com/nodejs/node/pull/12302) +* [[`758dc81e8d`](https://github.com/nodejs/node/commit/758dc81e8d)] - **(SEMVER-MAJOR)** **src**: add --use-bundled-ca --use-openssl-ca check (Daniel Bevenius) [#12087](https://github.com/nodejs/node/pull/12087) +* [[`2d4fca2c41`](https://github.com/nodejs/node/commit/2d4fca2c41)] - **(SEMVER-MINOR)** **src**: add process.ppid (cjihrig) [#16839](https://github.com/nodejs/node/pull/16839) +* [[`b6ce918e0a`](https://github.com/nodejs/node/commit/b6ce918e0a)] - **stream**: fix disparity between buffer and the count (jlvivero) [#15661](https://github.com/nodejs/node/pull/15661) +* [[`f82065fbe1`](https://github.com/nodejs/node/commit/f82065fbe1)] - **test**: make test-cli-syntax engine agnostic (Rich Trott) [#16272](https://github.com/nodejs/node/pull/16272) +* [[`a4e2ced73b`](https://github.com/nodejs/node/commit/a4e2ced73b)] - **test**: decrease duration of test-cli-syntax (Evan Lucas) [#14187](https://github.com/nodejs/node/pull/14187) +* [[`734ce678f4`](https://github.com/nodejs/node/commit/734ce678f4)] - **test**: use valid authentication tag length (Tobias Nießen) [#17566](https://github.com/nodejs/node/pull/17566) +* [[`694828df0e`](https://github.com/nodejs/node/commit/694828df0e)] - **test**: mark test-inspector-stop-profile-after-done flaky (Myles Borins) [#18491](https://github.com/nodejs/node/pull/18491) +* [[`5668403ddb`](https://github.com/nodejs/node/commit/5668403ddb)] - **test**: improve flaky test-listen-fd-ebadf.js (Rich Trott) [#17797](https://github.com/nodejs/node/pull/17797) +* [[`fce10f722d`](https://github.com/nodejs/node/commit/fce10f722d)] - **test**: fix test-tls-server-verify.js on Windows CI (Rich Trott) [#18382](https://github.com/nodejs/node/pull/18382) +* [[`4473c6c807`](https://github.com/nodejs/node/commit/4473c6c807)] - **test**: fix flaky test-http-pipeline-flood (Anatoli Papirovski) [#17955](https://github.com/nodejs/node/pull/17955) +* [[`001b67296e`](https://github.com/nodejs/node/commit/001b67296e)] - **test**: rename regression tests (Tobias Nießen) [#17948](https://github.com/nodejs/node/pull/17948) +* [[`0c3f23ef59`](https://github.com/nodejs/node/commit/0c3f23ef59)] - **test**: fix flaky test-pipe-unref (Anatoli Papirovski) [#17950](https://github.com/nodejs/node/pull/17950) +* [[`9e760285de`](https://github.com/nodejs/node/commit/9e760285de)] - **test**: fix crypto test case to use correct encoding (Tobias Nießen) [#17956](https://github.com/nodejs/node/pull/17956) +* [[`1c4aa61388`](https://github.com/nodejs/node/commit/1c4aa61388)] - **test**: simplify test-buffer-slice.js (Weijia Wang) [#17962](https://github.com/nodejs/node/pull/17962) +* [[`2c554a9d2b`](https://github.com/nodejs/node/commit/2c554a9d2b)] - **test**: improve to use template string (sreepurnajasti) [#17895](https://github.com/nodejs/node/pull/17895) +* [[`8c1f41fc11`](https://github.com/nodejs/node/commit/8c1f41fc11)] - **test**: make test-tls-invoke-queued use public API (Anna Henningsen) [#17864](https://github.com/nodejs/node/pull/17864) +* [[`b3e625d67a`](https://github.com/nodejs/node/commit/b3e625d67a)] - **test**: refactor test-tls-securepair-fiftharg (Anna Henningsen) [#17836](https://github.com/nodejs/node/pull/17836) +* [[`038e52627f`](https://github.com/nodejs/node/commit/038e52627f)] - **test**: remove undefined function (Rich Trott) [#17845](https://github.com/nodejs/node/pull/17845) +* [[`5314754685`](https://github.com/nodejs/node/commit/5314754685)] - **test**: use common module API in test-child-process-exec-stdout-stderr-data-string (sreepurnajasti) [#17751](https://github.com/nodejs/node/pull/17751) +* [[`f291bc1d98`](https://github.com/nodejs/node/commit/f291bc1d98)] - **test**: refactor test-repl-definecommand (Rich Trott) [#17795](https://github.com/nodejs/node/pull/17795) +* [[`cb7854354f`](https://github.com/nodejs/node/commit/cb7854354f)] - **test**: change callback function to arrow function (rt33) [#17734](https://github.com/nodejs/node/pull/17734) +* [[`bdb535c731`](https://github.com/nodejs/node/commit/bdb535c731)] - **test**: Use countdown in test file (sreepurnajasti) [#17646](https://github.com/nodejs/node/pull/17646) +* [[`31c5db6c03`](https://github.com/nodejs/node/commit/31c5db6c03)] - **test**: update test-http-content-length to use countdown (Bamieh) [#17201](https://github.com/nodejs/node/pull/17201) +* [[`cc03470b82`](https://github.com/nodejs/node/commit/cc03470b82)] - **test**: change callback function to arrow function (routerman) [#17697](https://github.com/nodejs/node/pull/17697) +* [[`81e6569990`](https://github.com/nodejs/node/commit/81e6569990)] - **test**: change callback function to arrow function (you12724) [#17698](https://github.com/nodejs/node/pull/17698) +* [[`2d77241f33`](https://github.com/nodejs/node/commit/2d77241f33)] - **test**: change callback function to arrow function (Shinya Kanamaru) [#17699](https://github.com/nodejs/node/pull/17699) +* [[`af3e074249`](https://github.com/nodejs/node/commit/af3e074249)] - **(SEMVER-MINOR)** **test**: add `makeDuplexPair()` helper (Anna Henningsen) [#16269](https://github.com/nodejs/node/pull/16269) +* [[`fb0bd8a584`](https://github.com/nodejs/node/commit/fb0bd8a584)] - **test**: fix flaky test-child-process-pass-fd (Rich Trott) [#17598](https://github.com/nodejs/node/pull/17598) +* [[`b3b245665e`](https://github.com/nodejs/node/commit/b3b245665e)] - **test**: add test description to fs.readFile tests (Jamie Davis) [#17610](https://github.com/nodejs/node/pull/17610) +* [[`5f7944842a`](https://github.com/nodejs/node/commit/5f7944842a)] - **test**: fix truncation of argv (Daniel Bevenius) [#12110](https://github.com/nodejs/node/pull/12110) +* [[`699c6638c3`](https://github.com/nodejs/node/commit/699c6638c3)] - **test**: add common.hasIntl (James M Snell) [#9246](https://github.com/nodejs/node/pull/9246) +* [[`365dba2195`](https://github.com/nodejs/node/commit/365dba2195)] - **test**: fix flaky test-crypto-classes.js (Bryan English) [#15662](https://github.com/nodejs/node/pull/15662) +* [[`d29a6202e7`](https://github.com/nodejs/node/commit/d29a6202e7)] - **(SEMVER-MINOR)** **test**: crypto createClass instanceof Class (Bryan English) [#8188](https://github.com/nodejs/node/pull/8188) +* [[`7b801b5f83`](https://github.com/nodejs/node/commit/7b801b5f83)] - **test**: don't skip when common.mustCall() is pending (cjihrig) [#15421](https://github.com/nodejs/node/pull/15421) +* [[`4f6dd9649f`](https://github.com/nodejs/node/commit/4f6dd9649f)] - **test,doc**: do not indicate that non-functions "return" values (Rich Trott) [#17267](https://github.com/nodejs/node/pull/17267) +* [[`a08925dcbd`](https://github.com/nodejs/node/commit/a08925dcbd)] - **tls**: comment about old-style errors (xortiz) [#17759](https://github.com/nodejs/node/pull/17759) +* [[`56e1586608`](https://github.com/nodejs/node/commit/56e1586608)] - **tls**: unconsume stream on destroy (Anna Henningsen) [#17478](https://github.com/nodejs/node/pull/17478) +* [[`00b279087e`](https://github.com/nodejs/node/commit/00b279087e)] - **(SEMVER-MINOR)** **tls**: accept `lookup` option for `tls.connect()` (Fedor Indutny) [#12839](https://github.com/nodejs/node/pull/12839) +* [[`521dc2511f`](https://github.com/nodejs/node/commit/521dc2511f)] - **tls**: properly track writeQueueSize during writes (Anatoli Papirovski) [#15791](https://github.com/nodejs/node/pull/15791) +* [[`51bfd32922`](https://github.com/nodejs/node/commit/51bfd32922)] - **tools**: do not override V8's gitignore (Yang Guo) [#18010](https://github.com/nodejs/node/pull/18010) +* [[`32f528a92e`](https://github.com/nodejs/node/commit/32f528a92e)] - **tools**: fix AttributeError: __exit__ on Python 2.6 (Dmitriy Kasyanov) [#17663](https://github.com/nodejs/node/pull/17663) +* [[`6187aec242`](https://github.com/nodejs/node/commit/6187aec242)] - **tools**: autofixer for lowercase-name-for-primitive (Shobhit Chittora) [#17715](https://github.com/nodejs/node/pull/17715) +* [[`928b7c87cd`](https://github.com/nodejs/node/commit/928b7c87cd)] - **tools**: simplify lowercase-name-for-primitive rule (cjihrig) [#17653](https://github.com/nodejs/node/pull/17653) +* [[`7821a4c899`](https://github.com/nodejs/node/commit/7821a4c899)] - **tools**: add lowercase-name-for-primitive eslint rule (Weijia Wang) [#17568](https://github.com/nodejs/node/pull/17568) +* [[`1d706026a7`](https://github.com/nodejs/node/commit/1d706026a7)] - **tools**: make doc tool a bit more readable (Tobias Nießen) [#17125](https://github.com/nodejs/node/pull/17125) +* [[`b8a5d6dbbc`](https://github.com/nodejs/node/commit/b8a5d6dbbc)] - **tools**: remove useless function declaration (Tobias Nießen) [#17125](https://github.com/nodejs/node/pull/17125) +* [[`18803bc409`](https://github.com/nodejs/node/commit/18803bc409)] - **(SEMVER-MINOR)** **tools, build**: refactor macOS installer (JP Wesselink) [#15179](https://github.com/nodejs/node/pull/15179) +* [[`24def19417`](https://github.com/nodejs/node/commit/24def19417)] - **(SEMVER-MINOR)** **url**: adding WHATWG URL support (James M Snell) [#7448](https://github.com/nodejs/node/pull/7448) +* [[`60b10f0896`](https://github.com/nodejs/node/commit/60b10f0896)] - **url**: update IDNA handling (Timothy Gu) [#13362](https://github.com/nodejs/node/pull/13362) +* [[`7af1ad0ec1`](https://github.com/nodejs/node/commit/7af1ad0ec1)] - **(SEMVER-MINOR)** **util**: add %i and %f formatting specifiers (Roman Reiss) [#10308](https://github.com/nodejs/node/pull/10308) + ## 2018-01-02, Version 6.12.3 'Boron' (LTS), @MylesBorins From 80ac941407235e9ce950c5db97494898ec10f360 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 14 Feb 2018 00:28:19 +0100 Subject: [PATCH 091/193] doc: make linter happy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was not caught by the linter because the release commit for 6.13.0 came from a different branch, where we don’t apply it like we do on the main branch. Example failure: https://ci.nodejs.org/job/node-test-linter/16132/console PR-URL: https://github.com/nodejs/node/pull/18769 Reviewed-By: Matheus Marchini --- doc/changelogs/CHANGELOG_V6.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/changelogs/CHANGELOG_V6.md b/doc/changelogs/CHANGELOG_V6.md index 8f9f993bebe6b0..0c9343bcadaa85 100644 --- a/doc/changelogs/CHANGELOG_V6.md +++ b/doc/changelogs/CHANGELOG_V6.md @@ -94,13 +94,13 @@ This LTS release comes with 112 commits, 17 of which are considered Semver-Minor - more robust stringification for unhandled rejections (Timothy Gu) [#13784](https://github.com/nodejs/node/pull/13784) * **repl**: - improve require() autocompletion (Alexey Orlenko) [#14409](https://github.com/nodejs/node/pull/14409) -* **src**: +* **src**: - add openssl-system-ca-path configure option (Daniel Bevenius) [#16790](https://github.com/nodejs/node/pull/16790) - add --use-bundled-ca --use-openssl-ca check (Daniel Bevenius) [#12087](https://github.com/nodejs/node/pull/12087) - add process.ppid (cjihrig) [#16839](https://github.com/nodejs/node/pull/16839) * **tls**: - accept `lookup` option for `tls.connect()` (Fedor Indutny) [#12839](https://github.com/nodejs/node/pull/12839) -* **tools, build**: +* **tools, build**: - a new macOS installer! (JP Wesselink) [#15179](https://github.com/nodejs/node/pull/15179) * **url**: - WHATWG URL api support (James M Snell) [#7448](https://github.com/nodejs/node/pull/7448) @@ -211,7 +211,7 @@ This LTS release comes with 112 commits, 17 of which are considered Semver-Minor * [[`00b279087e`](https://github.com/nodejs/node/commit/00b279087e)] - **(SEMVER-MINOR)** **tls**: accept `lookup` option for `tls.connect()` (Fedor Indutny) [#12839](https://github.com/nodejs/node/pull/12839) * [[`521dc2511f`](https://github.com/nodejs/node/commit/521dc2511f)] - **tls**: properly track writeQueueSize during writes (Anatoli Papirovski) [#15791](https://github.com/nodejs/node/pull/15791) * [[`51bfd32922`](https://github.com/nodejs/node/commit/51bfd32922)] - **tools**: do not override V8's gitignore (Yang Guo) [#18010](https://github.com/nodejs/node/pull/18010) -* [[`32f528a92e`](https://github.com/nodejs/node/commit/32f528a92e)] - **tools**: fix AttributeError: __exit__ on Python 2.6 (Dmitriy Kasyanov) [#17663](https://github.com/nodejs/node/pull/17663) +* [[`32f528a92e`](https://github.com/nodejs/node/commit/32f528a92e)] - **tools**: fix AttributeError: `__exit__` on Python 2.6 (Dmitriy Kasyanov) [#17663](https://github.com/nodejs/node/pull/17663) * [[`6187aec242`](https://github.com/nodejs/node/commit/6187aec242)] - **tools**: autofixer for lowercase-name-for-primitive (Shobhit Chittora) [#17715](https://github.com/nodejs/node/pull/17715) * [[`928b7c87cd`](https://github.com/nodejs/node/commit/928b7c87cd)] - **tools**: simplify lowercase-name-for-primitive rule (cjihrig) [#17653](https://github.com/nodejs/node/pull/17653) * [[`7821a4c899`](https://github.com/nodejs/node/commit/7821a4c899)] - **tools**: add lowercase-name-for-primitive eslint rule (Weijia Wang) [#17568](https://github.com/nodejs/node/pull/17568) @@ -574,7 +574,7 @@ This LTS release comes with 263 commits. This includes 173 which are test relate * [[`4c98e07702`](https://github.com/nodejs/node/commit/4c98e07702)] - **test**: fixtures in test-net-pipe-connect-errors (Eric Freiberg) [#15922](https://github.com/nodejs/node/pull/15922) * [[`244bfb398d`](https://github.com/nodejs/node/commit/244bfb398d)] - **test**: fixtures in test-process-redirect-warnings-env (Kat Rosario) [#15930](https://github.com/nodejs/node/pull/15930) * [[`18479d3cff`](https://github.com/nodejs/node/commit/18479d3cff)] - **test**: fix ordering of strictEqual actual/expected (Chad Zezula) [#16008](https://github.com/nodejs/node/pull/16008) -* [[`66fd6a1409`](https://github.com/nodejs/node/commit/66fd6a1409)] - **test**: use fixtures.readSync (szhang351) +* [[`66fd6a1409`](https://github.com/nodejs/node/commit/66fd6a1409)] - **test**: use fixtures.readSync (szhang351) * [[`6d33564b1a`](https://github.com/nodejs/node/commit/6d33564b1a)] - **test**: replaced fixturesDir with common.fixtures (Dolapo Toki) [#15836](https://github.com/nodejs/node/pull/15836) * [[`a6f04bec9e`](https://github.com/nodejs/node/commit/a6f04bec9e)] - **test**: use fixtures.fixturesDir (Gene Wu) [#15822](https://github.com/nodejs/node/pull/15822) * [[`2103453977`](https://github.com/nodejs/node/commit/2103453977)] - **test**: replaces fixturesDir with fixtures methods (Christian Murphy) [#15817](https://github.com/nodejs/node/pull/15817) @@ -684,7 +684,7 @@ This release includes a security update to openssl that has been deemed low seve * **process**: - add --redirect-warnings command line argument (James M Snell) [#10116](https://github.com/nodejs/node/pull/10116) * **src**: - - allow CLI args in env with NODE_OPTIONS (Sam Roberts) [#12028](https://github.com/nodejs/node/pull/12028) + - allow CLI args in env with NODE_OPTIONS (Sam Roberts) [#12028](https://github.com/nodejs/node/pull/12028) - --abort-on-uncaught-exception in NODE_OPTIONS (Sam Roberts) [#13932](https://github.com/nodejs/node/pull/13932) - allow --tls-cipher-list in NODE_OPTIONS (Sam Roberts) [#13172](https://github.com/nodejs/node/pull/13172) - use SafeGetenv() for NODE_REDIRECT_WARNINGS (Sam Roberts) [#12677](https://github.com/nodejs/node/pull/12677) @@ -770,7 +770,7 @@ This release includes a security update to openssl that has been deemed low seve * [[`b166837551`](https://github.com/nodejs/node/commit/b166837551)] - **src,etw**: fix event 9 on 64 bit Windows (João Reis) [#15563](https://github.com/nodejs/node/pull/15563) * [[`18987794bd`](https://github.com/nodejs/node/commit/18987794bd)] - **test**: move test-cluster-debug-port to sequential (Oleksandr Kushchak) [#16292](https://github.com/nodejs/node/pull/16292) * [[`1fdbaed2f2`](https://github.com/nodejs/node/commit/1fdbaed2f2)] - **test**: begin normalizing fixtures use (James M Snell) [#14332](https://github.com/nodejs/node/pull/14332) -* [[`3ad6a9dfc4`](https://github.com/nodejs/node/commit/3ad6a9dfc4)] - **test**: remove assert message (Joe Henry) +* [[`3ad6a9dfc4`](https://github.com/nodejs/node/commit/3ad6a9dfc4)] - **test**: remove assert message (Joe Henry) * [[`58509ec471`](https://github.com/nodejs/node/commit/58509ec471)] - **test**: clarify assert messages in crypto tests (cpandrews8) [#16019](https://github.com/nodejs/node/pull/16019) * [[`ab7f43aa41`](https://github.com/nodejs/node/commit/ab7f43aa41)] - **test**: include expected result in error messages (Chowdhurian) [#16039](https://github.com/nodejs/node/pull/16039) * [[`342ac9f0c6`](https://github.com/nodejs/node/commit/342ac9f0c6)] - **test**: cleanup test-buffer-sharedarraybuffer (Rafal Leszczynski) [#15896](https://github.com/nodejs/node/pull/15896) From e9ba0cfd46d75d21e9e2359e40710c3ee46a296a Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Mon, 12 Feb 2018 07:28:41 +0100 Subject: [PATCH 092/193] test: add crypto check to test-benchmark-tls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently when building --without-ssl a 'ERR_NO_CRYPTO' error is reported. This is not currently being picked up by the crypto-check lint rule as it does not actually require any crypto modules directly, but instead this is done by common/benchmark. PR-URL: https://github.com/nodejs/node/pull/18724 Reviewed-By: Ruben Bridgewater Reviewed-By: Benjamin Gruenbaum Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Tobias Nießen Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/sequential/test-benchmark-tls.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/sequential/test-benchmark-tls.js b/test/sequential/test-benchmark-tls.js index 7c87aa3cbcd89e..3545955e3ab5b0 100644 --- a/test/sequential/test-benchmark-tls.js +++ b/test/sequential/test-benchmark-tls.js @@ -2,6 +2,9 @@ const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + if (!common.enoughTestMem) common.skip('Insufficient memory for TLS benchmark test'); From 18d23aa36e7f91bbc8dc6eb5972d2663a3a3df35 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 9 Feb 2018 03:34:50 +0800 Subject: [PATCH 093/193] src: do not redefine private for GenDebugSymbols Redefining private breaks any private inheritance in the included files. We can simply declare GenDebugSymbols() as friends in related classes to gain the access that we need. PR-URL: https://github.com/nodejs/node/pull/18653 Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- src/base_object.h | 1 + src/env.h | 1 + src/handle_wrap.h | 2 ++ src/node_postmortem_metadata.cc | 54 --------------------------------- src/req_wrap.h | 1 + src/util.h | 2 ++ 6 files changed, 7 insertions(+), 54 deletions(-) diff --git a/src/base_object.h b/src/base_object.h index 5852f764066fbc..965683d029e43e 100644 --- a/src/base_object.h +++ b/src/base_object.h @@ -70,6 +70,7 @@ class BaseObject { // offsets and generate debug symbols for BaseObject, which assumes that the // position of members in memory are predictable. For more information please // refer to `doc/guides/node-postmortem-support.md` + friend int GenDebugSymbols(); v8::Persistent persistent_handle_; Environment* env_; }; diff --git a/src/env.h b/src/env.h index 95548c0900ea13..0c3cfe2cedcf2a 100644 --- a/src/env.h +++ b/src/env.h @@ -782,6 +782,7 @@ class Environment { // symbols for Environment, which assumes that the position of members in // memory are predictable. For more information please refer to // `doc/guides/node-postmortem-support.md` + friend int GenDebugSymbols(); HandleWrapQueue handle_wrap_queue_; ReqWrapQueue req_wrap_queue_; ListHead&); static void OnClose(uv_handle_t* handle); + // handle_wrap_queue_ needs to be at a fixed offset from the start of the // class because it is used by src/node_postmortem_metadata.cc to calculate // offsets and generate debug symbols for HandleWrap, which assumes that the // position of members in memory are predictable. For more information please // refer to `doc/guides/node-postmortem-support.md` + friend int GenDebugSymbols(); ListNode handle_wrap_queue_; enum { kInitialized, kClosing, kClosingWithCallback, kClosed } state_; uv_handle_t* const handle_; diff --git a/src/node_postmortem_metadata.cc b/src/node_postmortem_metadata.cc index 4a463958f54509..b335e7fbf818c6 100644 --- a/src/node_postmortem_metadata.cc +++ b/src/node_postmortem_metadata.cc @@ -1,57 +1,3 @@ -// Need to import standard headers before redefining private, otherwise it -// won't compile. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace node { -// Forward declaration needed before redefining private. -int GenDebugSymbols(); -} // namespace node - - -#define private friend int GenDebugSymbols(); private - #include "env.h" #include "base_object-inl.h" #include "handle_wrap.h" diff --git a/src/req_wrap.h b/src/req_wrap.h index 05bc558570abf1..ddd0840aad2ab6 100644 --- a/src/req_wrap.h +++ b/src/req_wrap.h @@ -22,6 +22,7 @@ class ReqWrap : public AsyncWrap { private: friend class Environment; + friend int GenDebugSymbols(); ListNode req_wrap_queue_; protected: diff --git a/src/util.h b/src/util.h index 47bdf27c307109..21c566a4ca6cd6 100644 --- a/src/util.h +++ b/src/util.h @@ -159,6 +159,7 @@ class ListNode { private: template (U::*M)> friend class ListHead; + friend int GenDebugSymbols(); ListNode* prev_; ListNode* next_; DISALLOW_COPY_AND_ASSIGN(ListNode); @@ -189,6 +190,7 @@ class ListHead { inline Iterator end() const; private: + friend int GenDebugSymbols(); ListNode head_; DISALLOW_COPY_AND_ASSIGN(ListHead); }; From b2e20b002bcc36cc027f7121b99cb0376a6f9af7 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 8 Feb 2018 22:24:08 +0800 Subject: [PATCH 094/193] fs: extract binding error handling into a helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18642 Reviewed-By: Jon Moss Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- lib/fs.js | 92 +++++++++++++++++++------------------------------------ 1 file changed, 32 insertions(+), 60 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index da718f3f334413..6129e3c3ef35a0 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -108,6 +108,20 @@ function copyObject(source) { return target; } +function handleErrorFromBinding(ctx) { + if (ctx.errno !== undefined) { // libuv error numbers + const err = errors.uvException(ctx); + Error.captureStackTrace(err, handleErrorFromBinding); + throw err; + } else if (ctx.error !== undefined) { // errors created in C++ land. + // TODO(joyeecheung): currently, ctx.error are encoding errors + // usually caused by memory problems. We need to figure out proper error + // code(s) for this. + Error.captureStackTrace(ctx.error, handleErrorFromBinding); + throw ctx.error; + } +} + // TODO(joyeecheung): explore how the deprecation could be solved via linting // rules. See https://github.com/nodejs/node/pull/12976 function rethrow() { @@ -405,10 +419,7 @@ fs.accessSync = function(path, mode) { const ctx = { path }; binding.access(pathModule.toNamespacedPath(path), mode, undefined, ctx); - - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); }; // fs.exists never throws even when the arguments are invalid - if there is @@ -742,9 +753,7 @@ fs.closeSync = function(fd) { const ctx = {}; binding.close(fd, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); }; function modeNum(m, def) { @@ -924,9 +933,7 @@ fs.renameSync = function(oldPath, newPath) { const ctx = { path: oldPath, dest: newPath }; binding.rename(pathModule.toNamespacedPath(oldPath), pathModule.toNamespacedPath(newPath), undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); }; fs.truncate = function(path, len, callback) { @@ -994,9 +1001,7 @@ fs.ftruncateSync = function(fd, len = 0) { len = Math.max(0, len); const ctx = {}; binding.ftruncate(fd, len, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); }; fs.rmdir = function(path, callback) { @@ -1025,9 +1030,7 @@ fs.fdatasyncSync = function(fd) { validateUint32(fd, 'fd'); const ctx = {}; binding.fdatasync(fd, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); }; fs.fsync = function(fd, callback) { @@ -1041,9 +1044,7 @@ fs.fsyncSync = function(fd) { validateUint32(fd, 'fd'); const ctx = {}; binding.fsync(fd, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); }; fs.mkdir = function(path, mode, callback) { @@ -1114,9 +1115,7 @@ fs.fstatSync = function(fd) { validateUint32(fd, 'fd'); const ctx = { fd }; binding.fstat(fd, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); return statsFromValues(); }; @@ -1125,9 +1124,7 @@ fs.lstatSync = function(path) { validatePath(path); const ctx = { path }; binding.lstat(pathModule.toNamespacedPath(path), undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); return statsFromValues(); }; @@ -1136,9 +1133,7 @@ fs.statSync = function(path) { validatePath(path); const ctx = { path }; binding.stat(pathModule.toNamespacedPath(path), undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); return statsFromValues(); }; @@ -1159,14 +1154,7 @@ fs.readlinkSync = function(path, options) { const ctx = { path }; const result = binding.readlink(pathModule.toNamespacedPath(path), options.encoding, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } else if (ctx.error) { - // TODO(joyeecheung): this is an encoding error usually caused by memory - // problems. We need to figure out proper error code(s) for this. - Error.captureStackTrace(ctx.error); - throw ctx.error; - } + handleErrorFromBinding(ctx); return result; }; @@ -1235,9 +1223,7 @@ fs.symlinkSync = function(target, path, type) { binding.symlink(preprocessSymlinkDestination(target, type, path), pathModule.toNamespacedPath(path), flags, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); }; fs.link = function(existingPath, newPath, callback) { @@ -1266,9 +1252,7 @@ fs.linkSync = function(existingPath, newPath) { const result = binding.link(pathModule.toNamespacedPath(existingPath), pathModule.toNamespacedPath(newPath), undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); return result; }; @@ -1286,9 +1270,7 @@ fs.unlinkSync = function(path) { validatePath(path); const ctx = { path }; binding.unlink(pathModule.toNamespacedPath(path), undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); }; fs.fchmod = function(fd, mode, callback) { @@ -1887,9 +1869,7 @@ fs.realpathSync = function realpathSync(p, options) { if (isWindows && !knownHard[base]) { const ctx = { path: base }; binding.lstat(pathModule.toNamespacedPath(base), undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); knownHard[base] = true; } @@ -1931,9 +1911,7 @@ fs.realpathSync = function realpathSync(p, options) { var baseLong = pathModule.toNamespacedPath(base); const ctx = { path: base }; binding.lstat(baseLong, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); if ((statValues[1/*mode*/] & S_IFMT) !== S_IFLNK) { knownHard[base] = true; @@ -1956,13 +1934,9 @@ fs.realpathSync = function realpathSync(p, options) { if (linkTarget === null) { const ctx = { path: base }; binding.stat(baseLong, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); linkTarget = binding.readlink(baseLong, undefined, undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); } resolvedLink = pathModule.resolve(previous, linkTarget); @@ -1981,9 +1955,7 @@ fs.realpathSync = function realpathSync(p, options) { if (isWindows && !knownHard[base]) { const ctx = { path: base }; binding.lstat(pathModule.toNamespacedPath(base), undefined, ctx); - if (ctx.errno !== undefined) { - throw errors.uvException(ctx); - } + handleErrorFromBinding(ctx); knownHard[base] = true; } } From 82c43aed16cf9b69e2fd44f2e9797a8c56f6fb6d Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 28 Jan 2018 17:26:08 +0100 Subject: [PATCH 095/193] tls_wrap: use DoTryWrite() Use `DoTryWrite()` to write data to the underlying socket. This does probably not make any difference in performance because the callback is still deferred (for now), but brings TLSWrap in line with other things that write to streams. PR-URL: https://github.com/nodejs/node/pull/18676 Reviewed-By: Ben Noordhuis Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- src/tls_wrap.cc | 26 ++++++++++++----- test/async-hooks/test-writewrap.js | 47 +++++++++++++++--------------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 0cba1898fbaaad..ee6e120ca0bf73 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -280,6 +280,22 @@ void TLSWrap::EncOut() { &count); CHECK(write_size_ != 0 && count != 0); + uv_buf_t buf[arraysize(data)]; + uv_buf_t* bufs = buf; + for (size_t i = 0; i < count; i++) + buf[i] = uv_buf_init(data[i], size[i]); + + int err = stream_->DoTryWrite(&bufs, &count); + if (err != 0) { + InvokeQueued(err); + } else if (count == 0) { + env()->SetImmediate([](Environment* env, void* data) { + NODE_COUNT_NET_BYTES_SENT(write_size_); + static_cast(data)->OnStreamAfterWrite(nullptr, 0); + }, this, object()); + return; + } + Local req_wrap_obj = env()->write_wrap_constructor_function() ->NewInstance(env()->context()).ToLocalChecked(); @@ -287,10 +303,7 @@ void TLSWrap::EncOut() { req_wrap_obj, static_cast(stream_)); - uv_buf_t buf[arraysize(data)]; - for (size_t i = 0; i < count; i++) - buf[i] = uv_buf_init(data[i], size[i]); - int err = stream_->DoWrite(write_req, buf, count, nullptr); + err = stream_->DoWrite(write_req, buf, count, nullptr); // Ignore errors, this should be already handled in js if (err) { @@ -303,9 +316,8 @@ void TLSWrap::EncOut() { void TLSWrap::OnStreamAfterWrite(WriteWrap* req_wrap, int status) { - // We should not be getting here after `DestroySSL`, because all queued writes - // must be invoked with UV_ECANCELED - CHECK_NE(ssl_, nullptr); + if (ssl_ == nullptr) + status = UV_ECANCELED; // Handle error if (status) { diff --git a/test/async-hooks/test-writewrap.js b/test/async-hooks/test-writewrap.js index d349f635665ddd..ed17887684c9c2 100644 --- a/test/async-hooks/test-writewrap.js +++ b/test/async-hooks/test-writewrap.js @@ -1,14 +1,10 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) - common.skip('missing crypto'); - const assert = require('assert'); const initHooks = require('./init-hooks'); -const fixtures = require('../common/fixtures'); const { checkInvocations } = require('./hook-checks'); -const tls = require('tls'); +const net = require('net'); const hooks = initHooks(); hooks.enable(); @@ -16,13 +12,9 @@ hooks.enable(); // // Creating server and listening on port // -const server = tls - .createServer({ - cert: fixtures.readSync('test_cert.pem'), - key: fixtures.readSync('test_key.pem') - }) +const server = net.createServer() .on('listening', common.mustCall(onlistening)) - .on('secureConnection', common.mustCall(onsecureConnection)) + .on('connection', common.mustCall(onconnection)) .listen(0); assert.strictEqual(hooks.activitiesOfTypes('WRITEWRAP').length, 0); @@ -32,16 +24,17 @@ function onlistening() { // // Creating client and connecting it to server // - tls - .connect(server.address().port, { rejectUnauthorized: false }) - .on('secureConnect', common.mustCall(onsecureConnect)); + net + .connect(server.address().port) + .on('connect', common.mustCall(onconnect)); assert.strictEqual(hooks.activitiesOfTypes('WRITEWRAP').length, 0); } function checkDestroyedWriteWraps(n, stage) { const as = hooks.activitiesOfTypes('WRITEWRAP'); - assert.strictEqual(as.length, n, `${n} WRITEWRAPs when ${stage}`); + assert.strictEqual(as.length, n, + `${as.length} out of ${n} WRITEWRAPs when ${stage}`); function checkValidWriteWrap(w) { assert.strictEqual(w.type, 'WRITEWRAP'); @@ -53,35 +46,41 @@ function checkDestroyedWriteWraps(n, stage) { as.forEach(checkValidWriteWrap); } -function onsecureConnection() { +function onconnection(conn) { + conn.resume(); // // Server received client connection // - checkDestroyedWriteWraps(3, 'server got secure connection'); + checkDestroyedWriteWraps(0, 'server got connection'); } -function onsecureConnect() { +function onconnect() { // // Client connected to server // - checkDestroyedWriteWraps(4, 'client connected'); + checkDestroyedWriteWraps(0, 'client connected'); // // Destroying client socket // - this.destroy(); + this.write('f'.repeat(128000), () => onafterwrite(this)); +} + +function onafterwrite(self) { + checkDestroyedWriteWraps(1, 'client destroyed'); + self.destroy(); - checkDestroyedWriteWraps(4, 'client destroyed'); + checkDestroyedWriteWraps(1, 'client destroyed'); // // Closing server // server.close(common.mustCall(onserverClosed)); - checkDestroyedWriteWraps(4, 'server closing'); + checkDestroyedWriteWraps(1, 'server closing'); } function onserverClosed() { - checkDestroyedWriteWraps(4, 'server closed'); + checkDestroyedWriteWraps(1, 'server closed'); } process.on('exit', onexit); @@ -89,5 +88,5 @@ process.on('exit', onexit); function onexit() { hooks.disable(); hooks.sanityCheck('WRITEWRAP'); - checkDestroyedWriteWraps(4, 'process exits'); + checkDestroyedWriteWraps(1, 'process exits'); } From e1271c07c32232b2ec721e7a7e516196868fc7d9 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 8 Feb 2018 18:32:32 +0100 Subject: [PATCH 096/193] src: only set JSStreamWrap write req after `write()` Otherwise `this[kCurrentWriteRequest]` is set to a value even if one of the `write` calls throws. This is needed in order not to break tests in a later commit. PR-URL: https://github.com/nodejs/node/pull/18676 Reviewed-By: Ben Noordhuis Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- lib/internal/wrap_js_stream.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/internal/wrap_js_stream.js b/lib/internal/wrap_js_stream.js index 1c494e57e1f9dd..aed26ed8c6976a 100644 --- a/lib/internal/wrap_js_stream.js +++ b/lib/internal/wrap_js_stream.js @@ -137,7 +137,6 @@ class JSStreamWrap extends Socket { doWrite(req, bufs) { assert.strictEqual(this[kCurrentWriteRequest], null); assert.strictEqual(this[kCurrentShutdownRequest], null); - this[kCurrentWriteRequest] = req; const handle = this._handle; const self = this; @@ -149,6 +148,9 @@ class JSStreamWrap extends Socket { this.stream.write(bufs[i], done); this.stream.uncork(); + // Only set the request here, because the `write()` calls could throw. + this[kCurrentWriteRequest] = req; + function done(err) { if (!err && --pending !== 0) return; From 0ed9ea861b847579478457b7f5aab430fb6d77cb Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 8 Feb 2018 21:29:30 +0100 Subject: [PATCH 097/193] test: make sure WriteWrap tests are actually async PR-URL: https://github.com/nodejs/node/pull/18676 Reviewed-By: Ben Noordhuis Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- test/async-hooks/test-writewrap.js | 27 ++++++++++++++++--- test/sequential/test-async-wrap-getasyncid.js | 26 ++++++++++-------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/test/async-hooks/test-writewrap.js b/test/async-hooks/test-writewrap.js index ed17887684c9c2..4f3455480ba849 100644 --- a/test/async-hooks/test-writewrap.js +++ b/test/async-hooks/test-writewrap.js @@ -47,6 +47,7 @@ function checkDestroyedWriteWraps(n, stage) { } function onconnection(conn) { + conn.write('hi'); // Let the client know we're ready. conn.resume(); // // Server received client connection @@ -60,15 +61,35 @@ function onconnect() { // checkDestroyedWriteWraps(0, 'client connected'); + this.once('data', common.mustCall(ondata)); +} + +function ondata() { // - // Destroying client socket + // Writing data to client socket // - this.write('f'.repeat(128000), () => onafterwrite(this)); + const write = () => { + let writeFinished = false; + this.write('f'.repeat(1280000), () => { + writeFinished = true; + }); + process.nextTick(() => { + if (writeFinished) { + // Synchronous finish, write more data immediately. + writeFinished = false; + write(); + } else { + // Asynchronous write; this is what we are here for. + onafterwrite(this); + } + }); + }; + write(); } function onafterwrite(self) { checkDestroyedWriteWraps(1, 'client destroyed'); - self.destroy(); + self.end(); checkDestroyedWriteWraps(1, 'client destroyed'); diff --git a/test/sequential/test-async-wrap-getasyncid.js b/test/sequential/test-async-wrap-getasyncid.js index fb11f2d9e46305..2db6ba9db661cf 100644 --- a/test/sequential/test-async-wrap-getasyncid.js +++ b/test/sequential/test-async-wrap-getasyncid.js @@ -197,7 +197,6 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check const handle = new tcp_wrap.TCP(tcp_wrap.constants.SOCKET); const req = new tcp_wrap.TCPConnectWrap(); const sreq = new stream_wrap.ShutdownWrap(); - const wreq = new stream_wrap.WriteWrap(); testInitialized(handle, 'TCP'); testUninitialized(req, 'TCPConnectWrap'); testUninitialized(sreq, 'ShutdownWrap'); @@ -206,20 +205,25 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check handle.close(); }); - wreq.handle = handle; - wreq.oncomplete = common.mustCall(() => { - handle.shutdown(sreq); - testInitialized(sreq, 'ShutdownWrap'); - }); - wreq.async = true; - - req.oncomplete = common.mustCall(() => { - // Use a long string to make sure the write happens asynchronously. + req.oncomplete = common.mustCall(writeData); + function writeData() { + const wreq = new stream_wrap.WriteWrap(); + wreq.handle = handle; + wreq.oncomplete = () => { + handle.shutdown(sreq); + testInitialized(sreq, 'ShutdownWrap'); + }; const err = handle.writeLatin1String(wreq, 'hi'.repeat(100000)); if (err) throw new Error(`write failed: ${getSystemErrorName(err)}`); + if (!wreq.async) { + testUninitialized(wreq, 'WriteWrap'); + // Synchronous finish. Write more data until we hit an + // asynchronous write. + return writeData(); + } testInitialized(wreq, 'WriteWrap'); - }); + } req.address = common.localhostIPv4; req.port = server.address().port; const err = handle.connect(req, req.address, req.port); From 0e7b61229aa602e55c5fb034a63d7da97eecff3b Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 8 Feb 2018 04:59:10 +0100 Subject: [PATCH 098/193] src: refactor WriteWrap and ShutdownWraps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Encapsulate stream requests more: - `WriteWrap` and `ShutdownWrap` classes are now tailored to the streams on which they are used. In particular, for most streams these are now plain `AsyncWrap`s and do not carry the overhead of unused libuv request data. - Provide generic `Write()` and `Shutdown()` methods that wrap around the actual implementations, and make *usage* of streams easier, rather than implementing; for example, wrap objects don’t need to be provided by callers anymore. - Use `EmitAfterWrite()` and `EmitAfterShutdown()` handlers to call the corresponding JS handlers, rather than always trying to call them. This makes usage of streams by other C++ code easier and leaner. Also fix up some tests that were previously not actually testing asynchronicity when the comments indicated that they would. PR-URL: https://github.com/nodejs/node/pull/18676 Reviewed-By: Ben Noordhuis Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- benchmark/net/tcp-raw-c2s.js | 2 +- benchmark/net/tcp-raw-pipe.js | 4 +- benchmark/net/tcp-raw-s2c.js | 8 +- lib/internal/http2/core.js | 9 +- lib/internal/wrap_js_stream.js | 6 +- lib/net.js | 14 +- src/env.h | 1 + src/js_stream.cc | 7 +- src/node_http2.cc | 44 +--- src/node_http2.h | 9 +- src/req_wrap-inl.h | 5 + src/req_wrap.h | 2 + src/stream_base-inl.h | 216 ++++++++++++++++-- src/stream_base.cc | 300 ++++++++----------------- src/stream_base.h | 246 ++++++++++++-------- src/stream_wrap.cc | 36 ++- src/stream_wrap.h | 3 + src/tls_wrap.cc | 61 ++--- src/tls_wrap.h | 6 + test/parallel/test-tcp-wrap-connect.js | 4 +- 20 files changed, 556 insertions(+), 427 deletions(-) diff --git a/benchmark/net/tcp-raw-c2s.js b/benchmark/net/tcp-raw-c2s.js index 2be3bb3b538ffd..4b6dd9c3f2b145 100644 --- a/benchmark/net/tcp-raw-c2s.js +++ b/benchmark/net/tcp-raw-c2s.js @@ -118,7 +118,7 @@ function client(type, len) { fail(err, 'write'); } - function afterWrite(err, handle, req) { + function afterWrite(err, handle) { if (err) fail(err, 'write'); diff --git a/benchmark/net/tcp-raw-pipe.js b/benchmark/net/tcp-raw-pipe.js index 2fc03f08cd4a90..dfde3d40b50b55 100644 --- a/benchmark/net/tcp-raw-pipe.js +++ b/benchmark/net/tcp-raw-pipe.js @@ -51,7 +51,7 @@ function main({ dur, len, type }) { if (err) fail(err, 'write'); - writeReq.oncomplete = function(status, handle, req, err) { + writeReq.oncomplete = function(status, handle, err) { if (err) fail(err, 'write'); }; @@ -130,7 +130,7 @@ function main({ dur, len, type }) { fail(err, 'write'); } - function afterWrite(err, handle, req) { + function afterWrite(err, handle) { if (err) fail(err, 'write'); diff --git a/benchmark/net/tcp-raw-s2c.js b/benchmark/net/tcp-raw-s2c.js index 339f5e393d9254..fe0bffd8127ec7 100644 --- a/benchmark/net/tcp-raw-s2c.js +++ b/benchmark/net/tcp-raw-s2c.js @@ -74,14 +74,14 @@ function main({ dur, len, type }) { fail(err, 'write'); } else if (!writeReq.async) { process.nextTick(function() { - afterWrite(null, clientHandle, writeReq); + afterWrite(0, clientHandle); }); } } - function afterWrite(status, handle, req, err) { - if (err) - fail(err, 'write'); + function afterWrite(status, handle) { + if (status) + fail(status, 'write'); while (clientHandle.writeQueueSize === 0) write(); diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 2fdcb8d6388180..dc01fb14e6e263 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -1399,20 +1399,19 @@ function trackWriteState(stream, bytes) { session[kHandle].chunksSentSinceLastWrite = 0; } -function afterDoStreamWrite(status, handle, req) { +function afterDoStreamWrite(status, handle) { const stream = handle[kOwner]; const session = stream[kSession]; stream[kUpdateTimer](); - const { bytes } = req; + const { bytes } = this; stream[kState].writeQueueSize -= bytes; if (session !== undefined) session[kState].writeQueueSize -= bytes; - if (typeof req.callback === 'function') - req.callback(null); - req.handle = undefined; + if (typeof this.callback === 'function') + this.callback(null); } function streamOnResume() { diff --git a/lib/internal/wrap_js_stream.js b/lib/internal/wrap_js_stream.js index aed26ed8c6976a..feacab267bea4d 100644 --- a/lib/internal/wrap_js_stream.js +++ b/lib/internal/wrap_js_stream.js @@ -115,9 +115,9 @@ class JSStreamWrap extends Socket { const handle = this._handle; - this.stream.end(() => { - // Ensure that write was dispatched - setImmediate(() => { + setImmediate(() => { + // Ensure that write is dispatched asynchronously. + this.stream.end(() => { this.finishShutdown(handle, 0); }); }); diff --git a/lib/net.js b/lib/net.js index 48dd690e89dc7d..1bc28e856df5bd 100644 --- a/lib/net.js +++ b/lib/net.js @@ -335,7 +335,7 @@ function onSocketFinish() { } -function afterShutdown(status, handle, req) { +function afterShutdown(status, handle) { var self = handle.owner; debug('afterShutdown destroyed=%j', self.destroyed, @@ -869,12 +869,12 @@ protoGetter('bytesWritten', function bytesWritten() { }); -function afterWrite(status, handle, req, err) { +function afterWrite(status, handle, err) { var self = handle.owner; if (self !== process.stderr && self !== process.stdout) debug('afterWrite', status); - if (req.async) + if (this.async) self[kLastWriteQueueSize] = 0; // callback may come after call to destroy. @@ -884,9 +884,9 @@ function afterWrite(status, handle, req, err) { } if (status < 0) { - var ex = errnoException(status, 'write', req.error); + var ex = errnoException(status, 'write', this.error); debug('write failure', ex); - self.destroy(ex, req.cb); + self.destroy(ex, this.cb); return; } @@ -895,8 +895,8 @@ function afterWrite(status, handle, req, err) { if (self !== process.stderr && self !== process.stdout) debug('afterWrite call cb'); - if (req.cb) - req.cb.call(undefined); + if (this.cb) + this.cb.call(undefined); } diff --git a/src/env.h b/src/env.h index 0c3cfe2cedcf2a..68b674f4fdbf91 100644 --- a/src/env.h +++ b/src/env.h @@ -306,6 +306,7 @@ class ModuleWrap; V(script_context_constructor_template, v8::FunctionTemplate) \ V(script_data_constructor_function, v8::Function) \ V(secure_context_constructor_template, v8::FunctionTemplate) \ + V(shutdown_wrap_constructor_function, v8::Function) \ V(tcp_constructor_template, v8::FunctionTemplate) \ V(tick_callback_function, v8::Function) \ V(timers_callback_function, v8::Function) \ diff --git a/src/js_stream.cc b/src/js_stream.cc index 9e67a2094ded89..3ba6a254cfc03e 100644 --- a/src/js_stream.cc +++ b/src/js_stream.cc @@ -91,8 +91,6 @@ int JSStream::DoShutdown(ShutdownWrap* req_wrap) { req_wrap->object() }; - req_wrap->Dispatched(); - TryCatch try_catch(env()->isolate()); Local value; int value_int = UV_EPROTO; @@ -127,8 +125,6 @@ int JSStream::DoWrite(WriteWrap* w, bufs_arr }; - w->Dispatched(); - TryCatch try_catch(env()->isolate()); Local value; int value_int = UV_EPROTO; @@ -154,9 +150,8 @@ void JSStream::New(const FunctionCallbackInfo& args) { template void JSStream::Finish(const FunctionCallbackInfo& args) { - Wrap* w; CHECK(args[0]->IsObject()); - ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As()); + Wrap* w = static_cast(StreamReq::FromObject(args[0].As())); w->Done(args[1]->Int32Value()); } diff --git a/src/node_http2.cc b/src/node_http2.cc index 2f688a4b352a15..6f59c119e53a6b 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -1552,18 +1552,9 @@ void Http2Session::SendPendingData() { chunks_sent_since_last_write_++; - // DoTryWrite may modify both the buffer list start itself and the - // base pointers/length of the individual buffers. - uv_buf_t* writebufs = *bufs; - if (stream_->DoTryWrite(&writebufs, &count) != 0 || count == 0) { - // All writes finished synchronously, nothing more to do here. - ClearOutgoing(0); - return; - } - - WriteWrap* req = AllocateSend(); - if (stream_->DoWrite(req, writebufs, count, nullptr) != 0) { - req->Dispose(); + StreamWriteResult res = underlying_stream()->Write(*bufs, count); + if (!res.async) { + ClearOutgoing(res.err); } DEBUG_HTTP2SESSION2(this, "wants data in return? %d", @@ -1649,15 +1640,6 @@ inline void Http2Session::SetChunksSinceLastWrite(size_t n) { chunks_sent_since_last_write_ = n; } -// Allocates the data buffer used to pass outbound data to the i/o stream. -WriteWrap* Http2Session::AllocateSend() { - HandleScope scope(env()->isolate()); - Local obj = - env()->write_wrap_constructor_function() - ->NewInstance(env()->context()).ToLocalChecked(); - return WriteWrap::New(env(), obj, static_cast(stream_)); -} - // Callback used to receive inbound data from the i/o stream void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf) { Http2Scope h2scope(this); @@ -1833,20 +1815,15 @@ inline void Http2Stream::Close(int32_t code) { DEBUG_HTTP2STREAM2(this, "closed with code %d", code); } - -inline void Http2Stream::Shutdown() { - CHECK(!this->IsDestroyed()); - Http2Scope h2scope(this); - flags_ |= NGHTTP2_STREAM_FLAG_SHUT; - CHECK_NE(nghttp2_session_resume_data(session_->session(), id_), - NGHTTP2_ERR_NOMEM); - DEBUG_HTTP2STREAM(this, "writable side shutdown"); -} - int Http2Stream::DoShutdown(ShutdownWrap* req_wrap) { CHECK(!this->IsDestroyed()); - req_wrap->Dispatched(); - Shutdown(); + { + Http2Scope h2scope(this); + flags_ |= NGHTTP2_STREAM_FLAG_SHUT; + CHECK_NE(nghttp2_session_resume_data(session_->session(), id_), + NGHTTP2_ERR_NOMEM); + DEBUG_HTTP2STREAM(this, "writable side shutdown"); + } req_wrap->Done(0); return 0; } @@ -2038,7 +2015,6 @@ inline int Http2Stream::DoWrite(WriteWrap* req_wrap, CHECK_EQ(send_handle, nullptr); Http2Scope h2scope(this); session_->SetChunksSinceLastWrite(); - req_wrap->Dispatched(); if (!IsWritable()) { req_wrap->Done(UV_EOF); return 0; diff --git a/src/node_http2.h b/src/node_http2.h index bf41d74ed49ad9..0e81eaac6ca7fe 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -601,9 +601,6 @@ class Http2Stream : public AsyncWrap, inline void Close(int32_t code); - // Shutdown the writable side of the stream - inline void Shutdown(); - // Destroy this stream instance and free all held memory. inline void Destroy(); @@ -818,6 +815,10 @@ class Http2Session : public AsyncWrap, public StreamListener { inline void EmitStatistics(); + inline StreamBase* underlying_stream() { + return static_cast(stream_); + } + void Start(); void Stop(); void Close(uint32_t code = NGHTTP2_NO_ERROR, @@ -907,8 +908,6 @@ class Http2Session : public AsyncWrap, public StreamListener { template static void GetSettings(const FunctionCallbackInfo& args); - WriteWrap* AllocateSend(); - uv_loop_t* event_loop() const { return env()->event_loop(); } diff --git a/src/req_wrap-inl.h b/src/req_wrap-inl.h index 6d0c57cd81d367..4a7984e649c733 100644 --- a/src/req_wrap-inl.h +++ b/src/req_wrap-inl.h @@ -33,6 +33,11 @@ void ReqWrap::Dispatched() { req_.data = this; } +template +ReqWrap* ReqWrap::from_req(T* req) { + return ContainerOf(&ReqWrap::req_, req); +} + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/req_wrap.h b/src/req_wrap.h index ddd0840aad2ab6..656be38dcea943 100644 --- a/src/req_wrap.h +++ b/src/req_wrap.h @@ -20,6 +20,8 @@ class ReqWrap : public AsyncWrap { inline void Dispatched(); // Call this after the req has been dispatched. T* req() { return &req_; } + static ReqWrap* from_req(T* req); + private: friend class Environment; friend int GenDebugSymbols(); diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index 76922c1d8af77d..b479e04bae4c8a 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -25,6 +25,25 @@ using v8::Value; using AsyncHooks = Environment::AsyncHooks; +inline void StreamReq::AttachToObject(v8::Local req_wrap_obj) { + CHECK_EQ(req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField), + nullptr); + req_wrap_obj->SetAlignedPointerInInternalField(kStreamReqField, this); +} + +inline StreamReq* StreamReq::FromObject(v8::Local req_wrap_obj) { + return static_cast( + req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField)); +} + +inline void StreamReq::Dispose() { + object()->SetAlignedPointerInInternalField(kStreamReqField, nullptr); + delete this; +} + +inline v8::Local StreamReq::object() { + return GetAsyncWrap()->object(); +} inline StreamListener::~StreamListener() { if (stream_ != nullptr) @@ -36,6 +55,15 @@ inline void StreamListener::PassReadErrorToPreviousListener(ssize_t nread) { previous_listener_->OnStreamRead(nread, uv_buf_init(nullptr, 0)); } +inline void StreamListener::OnStreamAfterShutdown(ShutdownWrap* w, int status) { + CHECK_NE(previous_listener_, nullptr); + previous_listener_->OnStreamAfterShutdown(w, status); +} + +inline void StreamListener::OnStreamAfterWrite(WriteWrap* w, int status) { + CHECK_NE(previous_listener_, nullptr); + previous_listener_->OnStreamAfterWrite(w, status); +} inline StreamResource::~StreamResource() { while (listener_ != nullptr) { @@ -93,6 +121,9 @@ inline void StreamResource::EmitAfterWrite(WriteWrap* w, int status) { listener_->OnStreamAfterWrite(w, status); } +inline void StreamResource::EmitAfterShutdown(ShutdownWrap* w, int status) { + listener_->OnStreamAfterShutdown(w, status); +} inline StreamBase::StreamBase(Environment* env) : env_(env) { PushStreamListener(&default_listener_); @@ -102,6 +133,150 @@ inline Environment* StreamBase::stream_env() const { return env_; } +inline void StreamBase::AfterWrite(WriteWrap* req_wrap, int status) { + AfterRequest(req_wrap, [&]() { + EmitAfterWrite(req_wrap, status); + }); +} + +inline void StreamBase::AfterShutdown(ShutdownWrap* req_wrap, int status) { + AfterRequest(req_wrap, [&]() { + EmitAfterShutdown(req_wrap, status); + }); +} + +template +inline void StreamBase::AfterRequest(Wrap* req_wrap, EmitEvent emit) { + Environment* env = stream_env(); + + v8::HandleScope handle_scope(env->isolate()); + v8::Context::Scope context_scope(env->context()); + + emit(); + req_wrap->Dispose(); +} + +inline int StreamBase::Shutdown(v8::Local req_wrap_obj) { + Environment* env = stream_env(); + if (req_wrap_obj.IsEmpty()) { + req_wrap_obj = + env->shutdown_wrap_constructor_function() + ->NewInstance(env->context()).ToLocalChecked(); + } + + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + env, GetAsyncWrap()->get_async_id()); + ShutdownWrap* req_wrap = CreateShutdownWrap(req_wrap_obj); + int err = DoShutdown(req_wrap); + + if (err != 0) { + req_wrap->Dispose(); + } + + const char* msg = Error(); + if (msg != nullptr) { + req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); + ClearError(); + } + + return err; +} + +inline StreamWriteResult StreamBase::Write( + uv_buf_t* bufs, + size_t count, + uv_stream_t* send_handle, + v8::Local req_wrap_obj) { + Environment* env = stream_env(); + int err; + if (send_handle == nullptr) { + err = DoTryWrite(&bufs, &count); + if (err != 0 || count == 0) { + return StreamWriteResult { false, err, nullptr }; + } + } + + if (req_wrap_obj.IsEmpty()) { + req_wrap_obj = + env->write_wrap_constructor_function() + ->NewInstance(env->context()).ToLocalChecked(); + } + + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + env, GetAsyncWrap()->get_async_id()); + WriteWrap* req_wrap = CreateWriteWrap(req_wrap_obj); + + err = DoWrite(req_wrap, bufs, count, send_handle); + bool async = err == 0; + + if (!async) { + req_wrap->Dispose(); + req_wrap = nullptr; + } + + const char* msg = Error(); + if (msg != nullptr) { + req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); + ClearError(); + } + + req_wrap_obj->Set(env->async(), v8::Boolean::New(env->isolate(), async)); + + return StreamWriteResult { async, err, req_wrap }; +} + +template +SimpleShutdownWrap::SimpleShutdownWrap( + StreamBase* stream, + v8::Local req_wrap_obj) + : ShutdownWrap(stream, req_wrap_obj), + OtherBase(stream->stream_env(), + req_wrap_obj, + AsyncWrap::PROVIDER_SHUTDOWNWRAP) { + Wrap(req_wrap_obj, static_cast(this)); +} + +template +SimpleShutdownWrap::~SimpleShutdownWrap() { + ClearWrap(static_cast(this)->object()); + if (kResetPersistent) { + auto& persistent = static_cast(this)->persistent(); + CHECK_EQ(persistent.IsEmpty(), false); + persistent.Reset(); + } +} + +inline ShutdownWrap* StreamBase::CreateShutdownWrap( + v8::Local object) { + return new SimpleShutdownWrap(this, object); +} + +template +SimpleWriteWrap::SimpleWriteWrap( + StreamBase* stream, + v8::Local req_wrap_obj) + : WriteWrap(stream, req_wrap_obj), + OtherBase(stream->stream_env(), + req_wrap_obj, + AsyncWrap::PROVIDER_WRITEWRAP) { + Wrap(req_wrap_obj, static_cast(this)); +} + +template +SimpleWriteWrap::~SimpleWriteWrap() { + ClearWrap(static_cast(this)->object()); + if (kResetPersistent) { + auto& persistent = static_cast(this)->persistent(); + CHECK_EQ(persistent.IsEmpty(), false); + persistent.Reset(); + } +} + +inline WriteWrap* StreamBase::CreateWriteWrap( + v8::Local object) { + return new SimpleWriteWrap(this, object); +} + template void StreamBase::AddMethods(Environment* env, Local t, @@ -230,38 +405,35 @@ inline void ShutdownWrap::OnDone(int status) { stream()->AfterShutdown(this, status); } - -WriteWrap* WriteWrap::New(Environment* env, - Local obj, - StreamBase* wrap, - size_t extra) { - size_t storage_size = ROUND_UP(sizeof(WriteWrap), kAlignSize) + extra; - char* storage = new char[storage_size]; - - return new(storage) WriteWrap(env, obj, wrap, storage_size); +inline void WriteWrap::SetAllocatedStorage(char* data, size_t size) { + CHECK_EQ(storage_, nullptr); + storage_ = data; + storage_size_ = size; } - -void WriteWrap::Dispose() { - this->~WriteWrap(); - delete[] reinterpret_cast(this); -} - - -char* WriteWrap::Extra(size_t offset) { - return reinterpret_cast(this) + - ROUND_UP(sizeof(*this), kAlignSize) + - offset; +inline char* WriteWrap::Storage() { + return storage_; } -size_t WriteWrap::ExtraSize() const { - return storage_size_ - ROUND_UP(sizeof(*this), kAlignSize); +inline size_t WriteWrap::StorageSize() const { + return storage_size_; } inline void WriteWrap::OnDone(int status) { stream()->AfterWrite(this, status); } +inline void StreamReq::Done(int status, const char* error_str) { + AsyncWrap* async_wrap = GetAsyncWrap(); + Environment* env = async_wrap->env(); + if (error_str != nullptr) { + async_wrap->object()->Set(env->error_string(), + OneByteString(env->isolate(), error_str)); + } + + OnDone(status); +} + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/stream_base.cc b/src/stream_base.cc index 8bdcebe88ab19f..9ad9fd5bcb4a46 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -34,6 +34,11 @@ template int StreamBase::WriteString( const FunctionCallbackInfo& args); +struct Free { + void operator()(char* ptr) const { free(ptr); } +}; + + int StreamBase::ReadStartJS(const FunctionCallbackInfo& args) { return ReadStart(); } @@ -45,45 +50,10 @@ int StreamBase::ReadStopJS(const FunctionCallbackInfo& args) { int StreamBase::Shutdown(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - CHECK(args[0]->IsObject()); Local req_wrap_obj = args[0].As(); - AsyncWrap* wrap = GetAsyncWrap(); - CHECK_NE(wrap, nullptr); - AsyncHooks::DefaultTriggerAsyncIdScope(env, wrap->get_async_id()); - ShutdownWrap* req_wrap = new ShutdownWrap(env, - req_wrap_obj, - this); - - int err = DoShutdown(req_wrap); - if (err) - delete req_wrap; - return err; -} - - -void StreamBase::AfterShutdown(ShutdownWrap* req_wrap, int status) { - Environment* env = req_wrap->env(); - - // The wrap and request objects should still be there. - CHECK_EQ(req_wrap->persistent().IsEmpty(), false); - - HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); - - Local req_wrap_obj = req_wrap->object(); - Local argv[3] = { - Integer::New(env->isolate(), status), - GetObject(), - req_wrap_obj - }; - - if (req_wrap_obj->Has(env->context(), env->oncomplete_string()).FromJust()) - req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); - - delete req_wrap; + return Shutdown(req_wrap_obj); } @@ -104,19 +74,14 @@ int StreamBase::Writev(const FunctionCallbackInfo& args) { count = chunks->Length() >> 1; MaybeStackBuffer bufs(count); - uv_buf_t* buf_list = *bufs; size_t storage_size = 0; uint32_t bytes = 0; size_t offset; - WriteWrap* req_wrap; - int err; if (!all_buffers) { // Determine storage size first for (size_t i = 0; i < count; i++) { - storage_size = ROUND_UP(storage_size, WriteWrap::kAlignSize); - Local chunk = chunks->Get(i * 2); if (Buffer::HasInstance(chunk)) @@ -145,20 +110,11 @@ int StreamBase::Writev(const FunctionCallbackInfo& args) { bufs[i].len = Buffer::Length(chunk); bytes += bufs[i].len; } - - // Try writing immediately without allocation - err = DoTryWrite(&buf_list, &count); - if (err != 0 || count == 0) - goto done; } - { - AsyncWrap* wrap = GetAsyncWrap(); - CHECK_NE(wrap, nullptr); - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env, - wrap->get_async_id()); - req_wrap = WriteWrap::New(env, req_wrap_obj, this, storage_size); - } + std::unique_ptr storage; + if (storage_size > 0) + storage = std::unique_ptr(Malloc(storage_size)); offset = 0; if (!all_buffers) { @@ -174,9 +130,8 @@ int StreamBase::Writev(const FunctionCallbackInfo& args) { } // Write string - offset = ROUND_UP(offset, WriteWrap::kAlignSize); CHECK_LE(offset, storage_size); - char* str_storage = req_wrap->Extra(offset); + char* str_storage = storage.get() + offset; size_t str_size = storage_size - offset; Local string = chunk->ToString(env->context()).ToLocalChecked(); @@ -192,35 +147,17 @@ int StreamBase::Writev(const FunctionCallbackInfo& args) { offset += str_size; bytes += str_size; } - - err = DoTryWrite(&buf_list, &count); - if (err != 0 || count == 0) { - req_wrap->Dispatched(); - req_wrap->Dispose(); - goto done; - } } - err = DoWrite(req_wrap, buf_list, count, nullptr); - req_wrap_obj->Set(env->async(), True(env->isolate())); - - if (err) - req_wrap->Dispose(); - - done: - const char* msg = Error(); - if (msg != nullptr) { - req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); - ClearError(); - } + StreamWriteResult res = Write(*bufs, count, nullptr, req_wrap_obj); req_wrap_obj->Set(env->bytes_string(), Number::New(env->isolate(), bytes)); - - return err; + if (res.wrap != nullptr && storage) { + res.wrap->SetAllocatedStorage(storage.release(), storage_size); + } + return res.err; } - - int StreamBase::WriteBuffer(const FunctionCallbackInfo& args) { CHECK(args[0]->IsObject()); @@ -232,49 +169,20 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo& args) { } Local req_wrap_obj = args[0].As(); - const char* data = Buffer::Data(args[1]); - size_t length = Buffer::Length(args[1]); - WriteWrap* req_wrap; uv_buf_t buf; - buf.base = const_cast(data); - buf.len = length; - - // Try writing immediately without allocation - uv_buf_t* bufs = &buf; - size_t count = 1; - int err = DoTryWrite(&bufs, &count); - if (err != 0) - goto done; - if (count == 0) - goto done; - CHECK_EQ(count, 1); - - // Allocate, or write rest - { - AsyncWrap* wrap = GetAsyncWrap(); - CHECK_NE(wrap, nullptr); - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env, - wrap->get_async_id()); - req_wrap = WriteWrap::New(env, req_wrap_obj, this); - } + buf.base = Buffer::Data(args[1]); + buf.len = Buffer::Length(args[1]); - err = DoWrite(req_wrap, bufs, count, nullptr); - req_wrap_obj->Set(env->async(), True(env->isolate())); - req_wrap_obj->Set(env->buffer_string(), args[1]); + StreamWriteResult res = Write(&buf, 1, nullptr, req_wrap_obj); - if (err) - req_wrap->Dispose(); + if (res.async) + req_wrap_obj->Set(env->context(), env->buffer_string(), args[1]).FromJust(); + req_wrap_obj->Set(env->context(), env->bytes_string(), + Integer::NewFromUnsigned(env->isolate(), buf.len)) + .FromJust(); - done: - const char* msg = Error(); - if (msg != nullptr) { - req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); - ClearError(); - } - req_wrap_obj->Set(env->bytes_string(), - Integer::NewFromUnsigned(env->isolate(), length)); - return err; + return res.err; } @@ -305,8 +213,6 @@ int StreamBase::WriteString(const FunctionCallbackInfo& args) { return UV_ENOBUFS; // Try writing immediately if write size isn't too big - WriteWrap* req_wrap; - char* data; char stack_storage[16384]; // 16kb size_t data_size; uv_buf_t buf; @@ -325,36 +231,33 @@ int StreamBase::WriteString(const FunctionCallbackInfo& args) { size_t count = 1; err = DoTryWrite(&bufs, &count); - // Failure - if (err != 0) - goto done; - - // Success - if (count == 0) - goto done; + // Immediate failure or success + if (err != 0 || count == 0) { + req_wrap_obj->Set(env->context(), env->async(), False(env->isolate())) + .FromJust(); + req_wrap_obj->Set(env->context(), + env->bytes_string(), + Integer::NewFromUnsigned(env->isolate(), data_size)) + .FromJust(); + return err; + } // Partial write CHECK_EQ(count, 1); } - { - AsyncWrap* wrap = GetAsyncWrap(); - CHECK_NE(wrap, nullptr); - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env, - wrap->get_async_id()); - req_wrap = WriteWrap::New(env, req_wrap_obj, this, storage_size); - } - - data = req_wrap->Extra(); + std::unique_ptr data; if (try_write) { // Copy partial data - memcpy(data, buf.base, buf.len); + data = std::unique_ptr(Malloc(buf.len)); + memcpy(data.get(), buf.base, buf.len); data_size = buf.len; } else { // Write it + data = std::unique_ptr(Malloc(storage_size)); data_size = StringBytes::Write(env->isolate(), - data, + data.get(), storage_size, string, enc); @@ -362,78 +265,36 @@ int StreamBase::WriteString(const FunctionCallbackInfo& args) { CHECK_LE(data_size, storage_size); - buf = uv_buf_init(data, data_size); - - if (!IsIPCPipe()) { - err = DoWrite(req_wrap, &buf, 1, nullptr); - } else { - uv_handle_t* send_handle = nullptr; - - if (!send_handle_obj.IsEmpty()) { - HandleWrap* wrap; - ASSIGN_OR_RETURN_UNWRAP(&wrap, send_handle_obj, UV_EINVAL); - send_handle = wrap->GetHandle(); - // Reference LibuvStreamWrap instance to prevent it from being garbage - // collected before `AfterWrite` is called. - CHECK_EQ(false, req_wrap->persistent().IsEmpty()); - req_wrap_obj->Set(env->handle_string(), send_handle_obj); - } - - err = DoWrite( - req_wrap, - &buf, - 1, - reinterpret_cast(send_handle)); + buf = uv_buf_init(data.get(), data_size); + + uv_stream_t* send_handle = nullptr; + + if (IsIPCPipe() && !send_handle_obj.IsEmpty()) { + // TODO(addaleax): This relies on the fact that HandleWrap comes first + // as a superclass of each individual subclass. + // There are similar assumptions in other places in the code base. + // A better idea would be having all BaseObject's internal pointers + // refer to the BaseObject* itself; this would require refactoring + // throughout the code base but makes Node rely much less on C++ quirks. + HandleWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, send_handle_obj, UV_EINVAL); + send_handle = reinterpret_cast(wrap->GetHandle()); + // Reference LibuvStreamWrap instance to prevent it from being garbage + // collected before `AfterWrite` is called. + req_wrap_obj->Set(env->handle_string(), send_handle_obj); } - req_wrap_obj->Set(env->async(), True(env->isolate())); + StreamWriteResult res = Write(&buf, 1, send_handle, req_wrap_obj); - if (err) - req_wrap->Dispose(); + req_wrap_obj->Set(env->context(), env->bytes_string(), + Integer::NewFromUnsigned(env->isolate(), data_size)) + .FromJust(); - done: - const char* msg = Error(); - if (msg != nullptr) { - req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); - ClearError(); + if (res.wrap != nullptr) { + res.wrap->SetAllocatedStorage(data.release(), data_size); } - req_wrap_obj->Set(env->bytes_string(), - Integer::NewFromUnsigned(env->isolate(), data_size)); - return err; -} - - -void StreamBase::AfterWrite(WriteWrap* req_wrap, int status) { - Environment* env = req_wrap->env(); - - HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); - - // The wrap and request objects should still be there. - CHECK_EQ(req_wrap->persistent().IsEmpty(), false); - - // Unref handle property - Local req_wrap_obj = req_wrap->object(); - req_wrap_obj->Delete(env->context(), env->handle_string()).FromJust(); - EmitAfterWrite(req_wrap, status); - - Local argv[] = { - Integer::New(env->isolate(), status), - GetObject(), - req_wrap_obj, - Undefined(env->isolate()) - }; - - const char* msg = Error(); - if (msg != nullptr) { - argv[3] = OneByteString(env->isolate(), msg); - ClearError(); - } - - if (req_wrap_obj->Has(env->context(), env->oncomplete_string()).FromJust()) - req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); - req_wrap->Dispose(); + return res.err; } @@ -510,4 +371,39 @@ void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf) { stream->CallJSOnreadMethod(nread, obj); } + +void ReportWritesToJSStreamListener::OnStreamAfterReqFinished( + StreamReq* req_wrap, int status) { + StreamBase* stream = static_cast(stream_); + Environment* env = stream->stream_env(); + AsyncWrap* async_wrap = req_wrap->GetAsyncWrap(); + Local req_wrap_obj = async_wrap->object(); + + Local argv[] = { + Integer::New(env->isolate(), status), + stream->GetObject(), + Undefined(env->isolate()) + }; + + const char* msg = stream->Error(); + if (msg != nullptr) { + argv[2] = OneByteString(env->isolate(), msg); + stream->ClearError(); + } + + if (req_wrap_obj->Has(env->context(), env->oncomplete_string()).FromJust()) + async_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); +} + +void ReportWritesToJSStreamListener::OnStreamAfterWrite( + WriteWrap* req_wrap, int status) { + OnStreamAfterReqFinished(req_wrap, status); +} + +void ReportWritesToJSStreamListener::OnStreamAfterShutdown( + ShutdownWrap* req_wrap, int status) { + OnStreamAfterReqFinished(req_wrap, status); +} + + } // namespace node diff --git a/src/stream_base.h b/src/stream_base.h index f18b6bda0a08a4..59b8ee7b7221f0 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -14,114 +14,75 @@ namespace node { // Forward declarations +class ShutdownWrap; +class WriteWrap; class StreamBase; class StreamResource; -template +struct StreamWriteResult { + bool async; + int err; + WriteWrap* wrap; +}; + + class StreamReq { public: - explicit StreamReq(StreamBase* stream) : stream_(stream) { + static constexpr int kStreamReqField = 1; + + explicit StreamReq(StreamBase* stream, + v8::Local req_wrap_obj) : stream_(stream) { + AttachToObject(req_wrap_obj); } - inline void Done(int status, const char* error_str = nullptr) { - Base* req = static_cast(this); - Environment* env = req->env(); - if (error_str != nullptr) { - req->object()->Set(env->error_string(), - OneByteString(env->isolate(), error_str)); - } + virtual ~StreamReq() {} + virtual AsyncWrap* GetAsyncWrap() = 0; + v8::Local object(); - req->OnDone(status); - } + void Done(int status, const char* error_str = nullptr); + void Dispose(); inline StreamBase* stream() const { return stream_; } + static StreamReq* FromObject(v8::Local req_wrap_obj); + + protected: + virtual void OnDone(int status) = 0; + + void AttachToObject(v8::Local req_wrap_obj); + private: StreamBase* const stream_; }; -class ShutdownWrap : public ReqWrap, - public StreamReq { +class ShutdownWrap : public StreamReq { public: - ShutdownWrap(Environment* env, - v8::Local req_wrap_obj, - StreamBase* stream) - : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_SHUTDOWNWRAP), - StreamReq(stream) { - Wrap(req_wrap_obj, this); - } + ShutdownWrap(StreamBase* stream, + v8::Local req_wrap_obj) + : StreamReq(stream, req_wrap_obj) { } - ~ShutdownWrap() { - ClearWrap(object()); - } - - static ShutdownWrap* from_req(uv_shutdown_t* req) { - return ContainerOf(&ShutdownWrap::req_, req); - } - - size_t self_size() const override { return sizeof(*this); } - - inline void OnDone(int status); // Just calls stream()->AfterShutdown() + void OnDone(int status) override; // Just calls stream()->AfterShutdown() }; -class WriteWrap : public ReqWrap, - public StreamReq { +class WriteWrap : public StreamReq { public: - static inline WriteWrap* New(Environment* env, - v8::Local obj, - StreamBase* stream, - size_t extra = 0); - inline void Dispose(); - inline char* Extra(size_t offset = 0); - inline size_t ExtraSize() const; - - size_t self_size() const override { return storage_size_; } - - static WriteWrap* from_req(uv_write_t* req) { - return ContainerOf(&WriteWrap::req_, req); - } + char* Storage(); + size_t StorageSize() const; + void SetAllocatedStorage(char* data, size_t size); - static const size_t kAlignSize = 16; - - WriteWrap(Environment* env, - v8::Local obj, - StreamBase* stream) - : ReqWrap(env, obj, AsyncWrap::PROVIDER_WRITEWRAP), - StreamReq(stream), - storage_size_(0) { - Wrap(obj, this); - } - - inline void OnDone(int status); // Just calls stream()->AfterWrite() - - protected: - WriteWrap(Environment* env, - v8::Local obj, - StreamBase* stream, - size_t storage_size) - : ReqWrap(env, obj, AsyncWrap::PROVIDER_WRITEWRAP), - StreamReq(stream), - storage_size_(storage_size) { - Wrap(obj, this); - } + WriteWrap(StreamBase* stream, + v8::Local req_wrap_obj) + : StreamReq(stream, req_wrap_obj) { } ~WriteWrap() { - ClearWrap(object()); + free(storage_); } - void* operator new(size_t size) = delete; - void* operator new(size_t size, char* storage) { return storage; } - - // This is just to keep the compiler happy. It should never be called, since - // we don't use exceptions in node. - void operator delete(void* ptr, char* storage) { UNREACHABLE(); } + void OnDone(int status) override; // Just calls stream()->AfterWrite() private: - // People should not be using the non-placement new and delete operator on a - // WriteWrap. Ensure this never happens. - void operator delete(void* ptr) { UNREACHABLE(); } - - const size_t storage_size_; + char* storage_ = nullptr; + size_t storage_size_ = 0; }; @@ -147,15 +108,23 @@ class StreamListener { // `OnStreamRead()` is called when data is available on the socket and has // been read into the buffer provided by `OnStreamAlloc()`. // The `buf` argument is the return value of `uv_buf_t`, or may be a buffer - // with base nullpptr in case of an error. + // with base nullptr in case of an error. // `nread` is the number of read bytes (which is at most the buffer length), // or, if negative, a libuv error code. virtual void OnStreamRead(ssize_t nread, const uv_buf_t& buf) = 0; - // This is called once a Write has finished. `status` may be 0 or, + // This is called once a write has finished. `status` may be 0 or, // if negative, a libuv error code. - virtual void OnStreamAfterWrite(WriteWrap* w, int status) {} + // By default, this is simply passed on to the previous listener + // (and raises an assertion if there is none). + virtual void OnStreamAfterWrite(WriteWrap* w, int status); + + // This is called once a shutdown has finished. `status` may be 0 or, + // if negative, a libuv error code. + // By default, this is simply passed on to the previous listener + // (and raises an assertion if there is none). + virtual void OnStreamAfterShutdown(ShutdownWrap* w, int status); // This is called immediately before the stream is destroyed. virtual void OnStreamDestroy() {} @@ -174,9 +143,21 @@ class StreamListener { }; +// An (incomplete) stream listener class that calls the `.oncomplete()` +// method of the JS objects associated with the wrap objects. +class ReportWritesToJSStreamListener : public StreamListener { + public: + void OnStreamAfterWrite(WriteWrap* w, int status) override; + void OnStreamAfterShutdown(ShutdownWrap* w, int status) override; + + private: + void OnStreamAfterReqFinished(StreamReq* req_wrap, int status); +}; + + // A default emitter that just pushes data chunks as Buffer instances to // JS land via the handle’s .ondata method. -class EmitToJSStreamListener : public StreamListener { +class EmitToJSStreamListener : public ReportWritesToJSStreamListener { public: void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override; }; @@ -188,20 +169,31 @@ class StreamResource { public: virtual ~StreamResource(); - virtual int DoShutdown(ShutdownWrap* req_wrap) = 0; - virtual int DoTryWrite(uv_buf_t** bufs, size_t* count); - virtual int DoWrite(WriteWrap* w, - uv_buf_t* bufs, - size_t count, - uv_stream_t* send_handle) = 0; + // These need to be implemented on the readable side of this stream: // Start reading from the underlying resource. This is called by the consumer - // when more data is desired. + // when more data is desired. Use `EmitAlloc()` and `EmitData()` to + // pass data along to the consumer. virtual int ReadStart() = 0; // Stop reading from the underlying resource. This is called by the // consumer when its buffers are full and no more data can be handled. virtual int ReadStop() = 0; + // These need to be implemented on the writable side of this stream: + // All of these methods may return an error code synchronously. + // In that case, the finish callback should *not* be called. + + // Perform a shutdown operation, and call req_wrap->Done() when finished. + virtual int DoShutdown(ShutdownWrap* req_wrap) = 0; + // Try to write as much data as possible synchronously, and modify + // `*bufs` and `*count` accordingly. This is a no-op by default. + virtual int DoTryWrite(uv_buf_t** bufs, size_t* count); + // Perform a write of data, and call req_wrap->Done() when finished. + virtual int DoWrite(WriteWrap* w, + uv_buf_t* bufs, + size_t count, + uv_stream_t* send_handle) = 0; + // Optionally, this may provide an error message to be used for // failing writes. virtual const char* Error() const; @@ -223,6 +215,8 @@ class StreamResource { void EmitRead(ssize_t nread, const uv_buf_t& buf = uv_buf_init(nullptr, 0)); // Call the current listener's OnStreamAfterWrite() method. void EmitAfterWrite(WriteWrap* w, int status); + // Call the current listener's OnStreamAfterShutdown() method. + void EmitAfterShutdown(ShutdownWrap* w, int status); StreamListener* listener_ = nullptr; uint64_t bytes_read_ = 0; @@ -251,21 +245,40 @@ class StreamBase : public StreamResource { void CallJSOnreadMethod(ssize_t nread, v8::Local buf); - // These are called by the respective {Write,Shutdown}Wrap class. - virtual void AfterShutdown(ShutdownWrap* req, int status); - virtual void AfterWrite(WriteWrap* req, int status); - // This is named `stream_env` to avoid name clashes, because a lot of // subclasses are also `BaseObject`s. Environment* stream_env() const; - protected: - explicit StreamBase(Environment* env); + // Shut down the current stream. This request can use an existing + // ShutdownWrap object (that was created in JS), or a new one will be created. + int Shutdown(v8::Local req_wrap_obj = v8::Local()); + + // Write data to the current stream. This request can use an existing + // WriteWrap object (that was created in JS), or a new one will be created. + // This will first try to write synchronously using `DoTryWrite()`, then + // asynchronously using `DoWrite()`. + // If the return value indicates a synchronous completion, no callback will + // be invoked. + StreamWriteResult Write( + uv_buf_t* bufs, + size_t count, + uv_stream_t* send_handle = nullptr, + v8::Local req_wrap_obj = v8::Local()); + + // These can be overridden by subclasses to get more specific wrap instances. + // For example, a subclass Foo could create a FooWriteWrap or FooShutdownWrap + // (inheriting from ShutdownWrap/WriteWrap) that has extra fields, like + // an associated libuv request. + virtual ShutdownWrap* CreateShutdownWrap(v8::Local object); + virtual WriteWrap* CreateWriteWrap(v8::Local object); // One of these must be implemented virtual AsyncWrap* GetAsyncWrap() = 0; virtual v8::Local GetObject(); + protected: + explicit StreamBase(Environment* env); + // JS Methods int ReadStartJS(const v8::FunctionCallbackInfo& args); int ReadStopJS(const v8::FunctionCallbackInfo& args); @@ -292,6 +305,43 @@ class StreamBase : public StreamResource { private: Environment* env_; EmitToJSStreamListener default_listener_; + + // These are called by the respective {Write,Shutdown}Wrap class. + void AfterShutdown(ShutdownWrap* req, int status); + void AfterWrite(WriteWrap* req, int status); + + template + void AfterRequest(Wrap* req_wrap, EmitEvent emit); + + friend class WriteWrap; + friend class ShutdownWrap; +}; + + +// These are helpers for creating `ShutdownWrap`/`WriteWrap` instances. +// `OtherBase` must have a constructor that matches the `AsyncWrap` +// constructors’s (Environment*, Local, AsyncWrap::Provider) signature +// and be a subclass of `AsyncWrap`. +template +class SimpleShutdownWrap : public ShutdownWrap, public OtherBase { + public: + SimpleShutdownWrap(StreamBase* stream, + v8::Local req_wrap_obj); + ~SimpleShutdownWrap(); + + AsyncWrap* GetAsyncWrap() override { return this; } + size_t self_size() const override { return sizeof(*this); } +}; + +template +class SimpleWriteWrap : public WriteWrap, public OtherBase { + public: + SimpleWriteWrap(StreamBase* stream, + v8::Local req_wrap_obj); + ~SimpleWriteWrap(); + + AsyncWrap* GetAsyncWrap() override { return this; } + size_t self_size() const override { return sizeof(*this) + StorageSize(); } }; } // namespace node diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index bc10cf80e828f1..e1df9edd39e151 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -61,19 +61,22 @@ void LibuvStreamWrap::Initialize(Local target, [](const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); ClearWrap(args.This()); + args.This()->SetAlignedPointerInInternalField( + StreamReq::kStreamReqField, nullptr); }; Local sw = FunctionTemplate::New(env->isolate(), is_construct_call_callback); - sw->InstanceTemplate()->SetInternalFieldCount(1); + sw->InstanceTemplate()->SetInternalFieldCount(StreamReq::kStreamReqField + 1); Local wrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "ShutdownWrap"); sw->SetClassName(wrapString); AsyncWrap::AddWrapMethods(env, sw); target->Set(wrapString, sw->GetFunction()); + env->set_shutdown_wrap_constructor_function(sw->GetFunction()); Local ww = FunctionTemplate::New(env->isolate(), is_construct_call_callback); - ww->InstanceTemplate()->SetInternalFieldCount(1); + ww->InstanceTemplate()->SetInternalFieldCount(StreamReq::kStreamReqField + 1); Local writeWrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "WriteWrap"); ww->SetClassName(writeWrapString); @@ -261,8 +264,20 @@ void LibuvStreamWrap::SetBlocking(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(uv_stream_set_blocking(wrap->stream(), enable)); } +typedef SimpleShutdownWrap, false> LibuvShutdownWrap; +typedef SimpleWriteWrap, false> LibuvWriteWrap; -int LibuvStreamWrap::DoShutdown(ShutdownWrap* req_wrap) { +ShutdownWrap* LibuvStreamWrap::CreateShutdownWrap(Local object) { + return new LibuvShutdownWrap(this, object); +} + +WriteWrap* LibuvStreamWrap::CreateWriteWrap(Local object) { + return new LibuvWriteWrap(this, object); +} + + +int LibuvStreamWrap::DoShutdown(ShutdownWrap* req_wrap_) { + LibuvShutdownWrap* req_wrap = static_cast(req_wrap_); int err; err = uv_shutdown(req_wrap->req(), stream(), AfterUvShutdown); req_wrap->Dispatched(); @@ -271,7 +286,8 @@ int LibuvStreamWrap::DoShutdown(ShutdownWrap* req_wrap) { void LibuvStreamWrap::AfterUvShutdown(uv_shutdown_t* req, int status) { - ShutdownWrap* req_wrap = ShutdownWrap::from_req(req); + LibuvShutdownWrap* req_wrap = static_cast( + LibuvShutdownWrap::from_req(req)); CHECK_NE(req_wrap, nullptr); HandleScope scope(req_wrap->env()->isolate()); Context::Scope context_scope(req_wrap->env()->context()); @@ -319,10 +335,11 @@ int LibuvStreamWrap::DoTryWrite(uv_buf_t** bufs, size_t* count) { } -int LibuvStreamWrap::DoWrite(WriteWrap* w, - uv_buf_t* bufs, - size_t count, - uv_stream_t* send_handle) { +int LibuvStreamWrap::DoWrite(WriteWrap* req_wrap, + uv_buf_t* bufs, + size_t count, + uv_stream_t* send_handle) { + LibuvWriteWrap* w = static_cast(req_wrap); int r; if (send_handle == nullptr) { r = uv_write(w->req(), stream(), bufs, count, AfterUvWrite); @@ -349,7 +366,8 @@ int LibuvStreamWrap::DoWrite(WriteWrap* w, void LibuvStreamWrap::AfterUvWrite(uv_write_t* req, int status) { - WriteWrap* req_wrap = WriteWrap::from_req(req); + LibuvWriteWrap* req_wrap = static_cast( + LibuvWriteWrap::from_req(req)); CHECK_NE(req_wrap, nullptr); HandleScope scope(req_wrap->env()->isolate()); Context::Scope context_scope(req_wrap->env()->context()); diff --git a/src/stream_wrap.h b/src/stream_wrap.h index e5ad25b91e6fea..a97e8ba10f91d5 100644 --- a/src/stream_wrap.h +++ b/src/stream_wrap.h @@ -73,6 +73,9 @@ class LibuvStreamWrap : public HandleWrap, public StreamBase { return stream()->type == UV_TCP; } + ShutdownWrap* CreateShutdownWrap(v8::Local object) override; + WriteWrap* CreateWriteWrap(v8::Local object) override; + protected: LibuvStreamWrap(Environment* env, v8::Local object, diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index ee6e120ca0bf73..f2a84b83f32de2 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -285,37 +285,29 @@ void TLSWrap::EncOut() { for (size_t i = 0; i < count; i++) buf[i] = uv_buf_init(data[i], size[i]); - int err = stream_->DoTryWrite(&bufs, &count); - if (err != 0) { - InvokeQueued(err); - } else if (count == 0) { - env()->SetImmediate([](Environment* env, void* data) { - NODE_COUNT_NET_BYTES_SENT(write_size_); - static_cast(data)->OnStreamAfterWrite(nullptr, 0); - }, this, object()); + StreamWriteResult res = underlying_stream()->Write(bufs, count); + if (res.err != 0) { + InvokeQueued(res.err); return; } - Local req_wrap_obj = - env()->write_wrap_constructor_function() - ->NewInstance(env()->context()).ToLocalChecked(); - WriteWrap* write_req = WriteWrap::New(env(), - req_wrap_obj, - static_cast(stream_)); + NODE_COUNT_NET_BYTES_SENT(write_size_); - err = stream_->DoWrite(write_req, buf, count, nullptr); - - // Ignore errors, this should be already handled in js - if (err) { - write_req->Dispose(); - InvokeQueued(err); - } else { - NODE_COUNT_NET_BYTES_SENT(write_size_); + if (!res.async) { + // Simulate asynchronous finishing, TLS cannot handle this at the moment. + env()->SetImmediate([](Environment* env, void* data) { + static_cast(data)->OnStreamAfterWrite(nullptr, 0); + }, this, object()); } } void TLSWrap::OnStreamAfterWrite(WriteWrap* req_wrap, int status) { + // Report back to the previous listener as well. This is only needed for the + // "empty" writes that are passed through directly to the underlying stream. + if (req_wrap != nullptr) + previous_listener_->OnStreamAfterWrite(req_wrap, status); + if (ssl_ == nullptr) status = UV_ECANCELED; @@ -513,24 +505,24 @@ AsyncWrap* TLSWrap::GetAsyncWrap() { bool TLSWrap::IsIPCPipe() { - return static_cast(stream_)->IsIPCPipe(); + return underlying_stream()->IsIPCPipe(); } int TLSWrap::GetFD() { - return static_cast(stream_)->GetFD(); + return underlying_stream()->GetFD(); } bool TLSWrap::IsAlive() { return ssl_ != nullptr && stream_ != nullptr && - static_cast(stream_)->IsAlive(); + underlying_stream()->IsAlive(); } bool TLSWrap::IsClosing() { - return static_cast(stream_)->IsClosing(); + return underlying_stream()->IsClosing(); } @@ -580,6 +572,17 @@ int TLSWrap::DoWrite(WriteWrap* w, // However, if there is any data that should be written to the socket, // the callback should not be invoked immediately if (BIO_pending(enc_out_) == 0) { + // We destroy the current WriteWrap* object and create a new one that + // matches the underlying stream, rather than the TLSWrap itself. + + // Note: We cannot simply use w->object() because of the "optimized" + // way in which we read persistent handles; the JS object itself might be + // destroyed by w->Dispose(), and the Local we have is not a + // "real" handle in the sense the V8 is aware of its existence. + Local req_wrap_obj = + w->GetAsyncWrap()->persistent().Get(env()->isolate()); + w->Dispose(); + w = underlying_stream()->CreateWriteWrap(req_wrap_obj); return stream_->DoWrite(w, bufs, count, send_handle); } } @@ -587,7 +590,6 @@ int TLSWrap::DoWrite(WriteWrap* w, // Store the current write wrap CHECK_EQ(current_write_, nullptr); current_write_ = w; - w->Dispatched(); // Write queued data if (empty) { @@ -677,6 +679,11 @@ void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) { } +ShutdownWrap* TLSWrap::CreateShutdownWrap(Local req_wrap_object) { + return underlying_stream()->CreateShutdownWrap(req_wrap_object); +} + + int TLSWrap::DoShutdown(ShutdownWrap* req_wrap) { crypto::MarkPopErrorOnReturn mark_pop_error_on_return; diff --git a/src/tls_wrap.h b/src/tls_wrap.h index a1f0b99e86beec..afd19c027e7007 100644 --- a/src/tls_wrap.h +++ b/src/tls_wrap.h @@ -65,6 +65,8 @@ class TLSWrap : public AsyncWrap, int ReadStart() override; int ReadStop() override; + ShutdownWrap* CreateShutdownWrap( + v8::Local req_wrap_object) override; int DoShutdown(ShutdownWrap* req_wrap) override; int DoWrite(WriteWrap* w, uv_buf_t* bufs, @@ -78,6 +80,10 @@ class TLSWrap : public AsyncWrap, size_t self_size() const override { return sizeof(*this); } protected: + inline StreamBase* underlying_stream() { + return static_cast(stream_); + } + static const int kClearOutChunkSize = 16384; // Maximum number of bytes for hello parser diff --git a/test/parallel/test-tcp-wrap-connect.js b/test/parallel/test-tcp-wrap-connect.js index c2746bca64d198..9f5560a385086a 100644 --- a/test/parallel/test-tcp-wrap-connect.js +++ b/test/parallel/test-tcp-wrap-connect.js @@ -23,10 +23,10 @@ function makeConnection() { const err = client.shutdown(shutdownReq); assert.strictEqual(err, 0); - shutdownReq.oncomplete = function(status, client_, req_) { + shutdownReq.oncomplete = function(status, client_, error) { assert.strictEqual(0, status); assert.strictEqual(client, client_); - assert.strictEqual(shutdownReq, req_); + assert.strictEqual(error, undefined); shutdownCount++; client.close(); }; From f1fc426cce9db230cb83866871f355afa0b92d3b Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Mon, 12 Feb 2018 13:02:42 +0200 Subject: [PATCH 099/193] module: support main w/o extension, pjson cache This adds support for ensuring that the top-level main into Node is supported loading when it has no extension for backwards-compat with NodeJS bin workflows. In addition package.json caching is implemented in the module lookup process. PR-URL: https://github.com/nodejs/node/pull/18728 Reviewed-By: Benjamin Gruenbaum --- doc/api/esm.md | 16 ++- lib/internal/loader/DefaultResolve.js | 21 ++- lib/internal/loader/Loader.js | 59 ++------- lib/internal/loader/Translators.js | 6 +- lib/internal/process/modules.js | 45 ++++++- lib/module.js | 29 ++-- src/env.h | 23 +++- src/module_wrap.cc | 125 +++++++++++------- src/module_wrap.h | 7 +- .../es-module-loaders/example-loader.mjs | 5 +- test/fixtures/es-module-loaders/js-loader.mjs | 6 +- test/fixtures/es-modules/noext | 1 + .../test-module-main-extension-lookup.js | 2 + 13 files changed, 208 insertions(+), 137 deletions(-) create mode 100644 test/fixtures/es-modules/noext diff --git a/doc/api/esm.md b/doc/api/esm.md index 2cfa5a9f29c753..3ff2904488afc1 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -117,9 +117,12 @@ The resolve hook returns the resolved file URL and module format for a given module specifier and parent file URL: ```js -import url from 'url'; +const baseURL = new URL('file://'); +baseURL.pathname = process.cwd() + '/'; -export async function resolve(specifier, parentModuleURL, defaultResolver) { +export async function resolve(specifier, + parentModuleURL = baseURL, + defaultResolver) { return { url: new URL(specifier, parentModuleURL).href, format: 'esm' @@ -127,7 +130,9 @@ export async function resolve(specifier, parentModuleURL, defaultResolver) { } ``` -The default NodeJS ES module resolution function is provided as a third +The parentURL is provided as `undefined` when performing main Node.js load itself. + +The default Node.js ES module resolution function is provided as a third argument to the resolver for easy compatibility workflows. In addition to returning the resolved file URL value, the resolve hook also @@ -155,7 +160,10 @@ import Module from 'module'; const builtins = Module.builtinModules; const JS_EXTENSIONS = new Set(['.js', '.mjs']); -export function resolve(specifier, parentModuleURL/*, defaultResolve */) { +const baseURL = new URL('file://'); +baseURL.pathname = process.cwd() + '/'; + +export function resolve(specifier, parentModuleURL = baseURL, defaultResolve) { if (builtins.includes(specifier)) { return { url: specifier, diff --git a/lib/internal/loader/DefaultResolve.js b/lib/internal/loader/DefaultResolve.js index 69dd9537c18c2d..d815be87dd8954 100644 --- a/lib/internal/loader/DefaultResolve.js +++ b/lib/internal/loader/DefaultResolve.js @@ -2,7 +2,6 @@ const { URL } = require('url'); const CJSmodule = require('module'); -const internalURLModule = require('internal/url'); const internalFS = require('internal/fs'); const NativeModule = require('native_module'); const { extname } = require('path'); @@ -11,6 +10,7 @@ const preserveSymlinks = !!process.binding('config').preserveSymlinks; const errors = require('internal/errors'); const { resolve: moduleWrapResolve } = internalBinding('module_wrap'); const StringStartsWith = Function.call.bind(String.prototype.startsWith); +const { getURLFromFilePath, getPathFromURL } = require('internal/url'); const realpathCache = new Map(); @@ -57,7 +57,8 @@ function resolve(specifier, parentURL) { let url; try { - url = search(specifier, parentURL); + url = search(specifier, + parentURL || getURLFromFilePath(`${process.cwd()}/`).href); } catch (e) { if (typeof e.message === 'string' && StringStartsWith(e.message, 'Cannot find module')) @@ -66,17 +67,27 @@ function resolve(specifier, parentURL) { } if (!preserveSymlinks) { - const real = realpathSync(internalURLModule.getPathFromURL(url), { + const real = realpathSync(getPathFromURL(url), { [internalFS.realpathCacheKey]: realpathCache }); const old = url; - url = internalURLModule.getURLFromFilePath(real); + url = getURLFromFilePath(real); url.search = old.search; url.hash = old.hash; } const ext = extname(url.pathname); - return { url: `${url}`, format: extensionFormatMap[ext] || ext }; + + let format = extensionFormatMap[ext]; + if (!format) { + const isMain = parentURL === undefined; + if (isMain) + format = 'cjs'; + else + throw new errors.Error('ERR_UNKNOWN_FILE_EXTENSION', url.pathname); + } + + return { url: `${url}`, format }; } module.exports = resolve; diff --git a/lib/internal/loader/Loader.js b/lib/internal/loader/Loader.js index eda42645f170f6..f0edbbf921f40f 100644 --- a/lib/internal/loader/Loader.js +++ b/lib/internal/loader/Loader.js @@ -1,51 +1,21 @@ 'use strict'; -const path = require('path'); -const { getURLFromFilePath, URL } = require('internal/url'); const errors = require('internal/errors'); - const ModuleMap = require('internal/loader/ModuleMap'); const ModuleJob = require('internal/loader/ModuleJob'); const defaultResolve = require('internal/loader/DefaultResolve'); const createDynamicModule = require('internal/loader/CreateDynamicModule'); const translators = require('internal/loader/Translators'); -const { setImportModuleDynamicallyCallback } = internalBinding('module_wrap'); + const FunctionBind = Function.call.bind(Function.prototype.bind); const debug = require('util').debuglog('esm'); -// Returns a file URL for the current working directory. -function getURLStringForCwd() { - try { - return getURLFromFilePath(`${process.cwd()}/`).href; - } catch (e) { - e.stack; - // If the current working directory no longer exists. - if (e.code === 'ENOENT') { - return undefined; - } - throw e; - } -} - -function normalizeReferrerURL(referrer) { - if (typeof referrer === 'string' && path.isAbsolute(referrer)) { - return getURLFromFilePath(referrer).href; - } - return new URL(referrer).href; -} - /* A Loader instance is used as the main entry point for loading ES modules. * Currently, this is a singleton -- there is only one used for loading * the main module and everything in its dependency graph. */ class Loader { - constructor(base = getURLStringForCwd()) { - if (typeof base !== 'string') - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'base', 'string'); - - this.base = base; - this.isMain = true; - + constructor() { // methods which translate input code or other information // into es modules this.translators = translators; @@ -71,8 +41,9 @@ class Loader { this._dynamicInstantiate = undefined; } - async resolve(specifier, parentURL = this.base) { - if (typeof parentURL !== 'string') + async resolve(specifier, parentURL) { + const isMain = parentURL === undefined; + if (!isMain && typeof parentURL !== 'string') throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'parentURL', 'string'); const { url, format } = @@ -93,7 +64,7 @@ class Loader { return { url, format }; } - async import(specifier, parent = this.base) { + async import(specifier, parent) { const job = await this.getModuleJob(specifier, parent); const module = await job.run(); return module.namespace(); @@ -107,7 +78,7 @@ class Loader { this._dynamicInstantiate = FunctionBind(dynamicInstantiate, null); } - async getModuleJob(specifier, parentURL = this.base) { + async getModuleJob(specifier, parentURL) { const { url, format } = await this.resolve(specifier, parentURL); let job = this.moduleMap.get(url); if (job !== undefined) @@ -134,24 +105,16 @@ class Loader { } let inspectBrk = false; - if (this.isMain) { - if (process._breakFirstLine) { - delete process._breakFirstLine; - inspectBrk = true; - } - this.isMain = false; + if (process._breakFirstLine) { + delete process._breakFirstLine; + inspectBrk = true; } job = new ModuleJob(this, url, loaderInstance, inspectBrk); this.moduleMap.set(url, job); return job; } - - static registerImportDynamicallyCallback(loader) { - setImportModuleDynamicallyCallback(async (referrer, specifier) => { - return loader.import(specifier, normalizeReferrerURL(referrer)); - }); - } } Object.setPrototypeOf(Loader.prototype, null); + module.exports = Loader; diff --git a/lib/internal/loader/Translators.js b/lib/internal/loader/Translators.js index d2f28774177fd6..18b1b12fd15854 100644 --- a/lib/internal/loader/Translators.js +++ b/lib/internal/loader/Translators.js @@ -19,7 +19,7 @@ const JsonParse = JSON.parse; const translators = new SafeMap(); module.exports = translators; -// Stragety for loading a standard JavaScript module +// Strategy for loading a standard JavaScript module translators.set('esm', async (url) => { const source = `${await readFileAsync(new URL(url))}`; debug(`Translating StandardModule ${url}`); @@ -62,7 +62,7 @@ translators.set('builtin', async (url) => { }); }); -// Stragety for loading a node native module +// Strategy for loading a node native module translators.set('addon', async (url) => { debug(`Translating NativeModule ${url}`); return createDynamicModule(['default'], url, (reflect) => { @@ -74,7 +74,7 @@ translators.set('addon', async (url) => { }); }); -// Stragety for loading a JSON file +// Strategy for loading a JSON file translators.set('json', async (url) => { debug(`Translating JSONModule ${url}`); return createDynamicModule(['default'], url, (reflect) => { diff --git a/lib/internal/process/modules.js b/lib/internal/process/modules.js index eda47f80cddeb4..f89278ddaa2d52 100644 --- a/lib/internal/process/modules.js +++ b/lib/internal/process/modules.js @@ -1,17 +1,54 @@ 'use strict'; const { + setImportModuleDynamicallyCallback, setInitializeImportMetaObjectCallback } = internalBinding('module_wrap'); +const { getURLFromFilePath } = require('internal/url'); +const Loader = require('internal/loader/Loader'); +const path = require('path'); +const { URL } = require('url'); + +function normalizeReferrerURL(referrer) { + if (typeof referrer === 'string' && path.isAbsolute(referrer)) { + return getURLFromFilePath(referrer).href; + } + return new URL(referrer).href; +} + function initializeImportMetaObject(wrap, meta) { meta.url = wrap.url; } -function setupModules() { +let loaderResolve; +exports.loaderPromise = new Promise((resolve, reject) => { + loaderResolve = resolve; +}); + +exports.ESMLoader = undefined; + +exports.setup = function() { setInitializeImportMetaObjectCallback(initializeImportMetaObject); -} -module.exports = { - setup: setupModules + let ESMLoader = new Loader(); + const loaderPromise = (async () => { + const userLoader = process.binding('config').userLoader; + if (userLoader) { + const hooks = await ESMLoader.import( + userLoader, getURLFromFilePath(`${process.cwd()}/`).href); + ESMLoader = new Loader(); + ESMLoader.hook(hooks); + exports.ESMLoader = ESMLoader; + } + return ESMLoader; + })(); + loaderResolve(loaderPromise); + + setImportModuleDynamicallyCallback(async (referrer, specifier) => { + const loader = await loaderPromise; + return loader.import(specifier, normalizeReferrerURL(referrer)); + }); + + exports.ESMLoader = ESMLoader; }; diff --git a/lib/module.js b/lib/module.js index 5ee537f157289b..c3250608ebe0f1 100644 --- a/lib/module.js +++ b/lib/module.js @@ -24,7 +24,6 @@ const NativeModule = require('native_module'); const util = require('util'); const { decorateErrorStack } = require('internal/util'); -const internalModule = require('internal/module'); const { getURLFromFilePath } = require('internal/url'); const vm = require('vm'); const assert = require('assert').ok; @@ -35,6 +34,7 @@ const { internalModuleReadJSON, internalModuleStat } = process.binding('fs'); +const internalModule = require('internal/module'); const preserveSymlinks = !!process.binding('config').preserveSymlinks; const experimentalModules = !!process.binding('config').experimentalModules; @@ -43,10 +43,9 @@ const errors = require('internal/errors'); module.exports = Module; // these are below module.exports for the circular reference -const Loader = require('internal/loader/Loader'); +const internalESModule = require('internal/process/modules'); const ModuleJob = require('internal/loader/ModuleJob'); const createDynamicModule = require('internal/loader/CreateDynamicModule'); -let ESMLoader; function stat(filename) { filename = path.toNamespacedPath(filename); @@ -447,7 +446,6 @@ Module._resolveLookupPaths = function(request, parent, newReturn) { return (newReturn ? parentDir : [id, parentDir]); }; - // Check the cache for the requested file. // 1. If a module already exists in the cache: return its exports object. // 2. If the module is native: call `NativeModule.require()` with the @@ -460,22 +458,10 @@ Module._load = function(request, parent, isMain) { debug('Module._load REQUEST %s parent: %s', request, parent.id); } - if (isMain && experimentalModules) { - (async () => { - // loader setup - if (!ESMLoader) { - ESMLoader = new Loader(); - const userLoader = process.binding('config').userLoader; - if (userLoader) { - ESMLoader.isMain = false; - const hooks = await ESMLoader.import(userLoader); - ESMLoader = new Loader(); - ESMLoader.hook(hooks); - } - } - Loader.registerImportDynamicallyCallback(ESMLoader); - await ESMLoader.import(getURLFromFilePath(request).pathname); - })() + if (experimentalModules && isMain) { + internalESModule.loaderPromise.then((loader) => { + return loader.import(getURLFromFilePath(request).pathname); + }) .catch((e) => { decorateErrorStack(e); console.error(e); @@ -578,7 +564,8 @@ Module.prototype.load = function(filename) { Module._extensions[extension](this, filename); this.loaded = true; - if (ESMLoader) { + if (experimentalModules) { + const ESMLoader = internalESModule.ESMLoader; const url = getURLFromFilePath(filename); const urlString = `${url}`; const exports = this.exports; diff --git a/src/env.h b/src/env.h index 68b674f4fdbf91..dedf821b24f5c1 100644 --- a/src/env.h +++ b/src/env.h @@ -54,7 +54,26 @@ class performance_state; namespace loader { class ModuleWrap; -} + +struct Exists { + enum Bool { Yes, No }; +}; + +struct IsValid { + enum Bool { Yes, No }; +}; + +struct HasMain { + enum Bool { Yes, No }; +}; + +struct PackageConfig { + const Exists::Bool exists; + const IsValid::Bool is_valid; + const HasMain::Bool has_main; + const std::string main; +}; +} // namespace loader // Pick an index that's hopefully out of the way when we're embedded inside // another application. Performance-wise or memory-wise it doesn't matter: @@ -609,6 +628,8 @@ class Environment { std::unordered_multimap module_map; + std::unordered_map package_json_cache; + inline double* heap_statistics_buffer() const; inline void set_heap_statistics_buffer(double* pointer); diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 4a9c847a6a0836..3d34da570a61a0 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -461,10 +461,9 @@ enum CheckFileOptions { CLOSE_AFTER_CHECK }; -Maybe CheckFile(const URL& search, +Maybe CheckFile(const std::string& path, CheckFileOptions opt = CLOSE_AFTER_CHECK) { uv_fs_t fs_req; - std::string path = search.ToFilePath(); if (path.empty()) { return Nothing(); } @@ -481,19 +480,74 @@ Maybe CheckFile(const URL& search, uv_fs_req_cleanup(&fs_req); if (is_directory) { - uv_fs_close(nullptr, &fs_req, fd, nullptr); + CHECK_EQ(0, uv_fs_close(nullptr, &fs_req, fd, nullptr)); uv_fs_req_cleanup(&fs_req); return Nothing(); } if (opt == CLOSE_AFTER_CHECK) { - uv_fs_close(nullptr, &fs_req, fd, nullptr); + CHECK_EQ(0, uv_fs_close(nullptr, &fs_req, fd, nullptr)); uv_fs_req_cleanup(&fs_req); } return Just(fd); } +const PackageConfig& GetPackageConfig(Environment* env, + const std::string path) { + auto existing = env->package_json_cache.find(path); + if (existing != env->package_json_cache.end()) { + return existing->second; + } + Maybe check = CheckFile(path, LEAVE_OPEN_AFTER_CHECK); + if (check.IsNothing()) { + auto entry = env->package_json_cache.emplace(path, + PackageConfig { Exists::No, IsValid::Yes, HasMain::No, "" }); + return entry.first->second; + } + + Isolate* isolate = env->isolate(); + v8::HandleScope handle_scope(isolate); + + std::string pkg_src = ReadFile(check.FromJust()); + uv_fs_t fs_req; + CHECK_EQ(0, uv_fs_close(nullptr, &fs_req, check.FromJust(), nullptr)); + uv_fs_req_cleanup(&fs_req); + + Local src; + if (!String::NewFromUtf8(isolate, + pkg_src.c_str(), + v8::NewStringType::kNormal, + pkg_src.length()).ToLocal(&src)) { + auto entry = env->package_json_cache.emplace(path, + PackageConfig { Exists::No, IsValid::Yes, HasMain::No, "" }); + return entry.first->second; + } + + Local pkg_json_v; + Local pkg_json; + + if (!JSON::Parse(env->context(), src).ToLocal(&pkg_json_v) || + !pkg_json_v->ToObject(env->context()).ToLocal(&pkg_json)) { + auto entry = env->package_json_cache.emplace(path, + PackageConfig { Exists::Yes, IsValid::No, HasMain::No, "" }); + return entry.first->second; + } + + Local pkg_main; + HasMain::Bool has_main = HasMain::No; + std::string main_std; + if (pkg_json->Get(env->context(), env->main_string()).ToLocal(&pkg_main)) { + has_main = HasMain::Yes; + Utf8Value main_utf8(isolate, pkg_main); + main_std.assign(std::string(*main_utf8, main_utf8.length())); + } + + auto entry = env->package_json_cache.emplace(path, + PackageConfig { Exists::Yes, IsValid::Yes, has_main, "" }); + return entry.first->second; +} + enum ResolveExtensionsOptions { TRY_EXACT_NAME, ONLY_VIA_EXTENSIONS @@ -502,7 +556,8 @@ enum ResolveExtensionsOptions { template Maybe ResolveExtensions(const URL& search) { if (options == TRY_EXACT_NAME) { - Maybe check = CheckFile(search); + std::string filePath = search.ToFilePath(); + Maybe check = CheckFile(filePath); if (!check.IsNothing()) { return Just(search); } @@ -510,7 +565,7 @@ Maybe ResolveExtensions(const URL& search) { for (const char* extension : EXTENSIONS) { URL guess(search.path() + extension, &search); - Maybe check = CheckFile(guess); + Maybe check = CheckFile(guess.ToFilePath()); if (!check.IsNothing()) { return Just(guess); } @@ -525,44 +580,18 @@ inline Maybe ResolveIndex(const URL& search) { Maybe ResolveMain(Environment* env, const URL& search) { URL pkg("package.json", &search); - Maybe check = CheckFile(pkg, LEAVE_OPEN_AFTER_CHECK); - if (check.IsNothing()) { - return Nothing(); - } - - Isolate* isolate = env->isolate(); - Local context = isolate->GetCurrentContext(); - std::string pkg_src = ReadFile(check.FromJust()); - uv_fs_t fs_req; - uv_fs_close(nullptr, &fs_req, check.FromJust(), nullptr); - uv_fs_req_cleanup(&fs_req); - - // It's not okay for the called of this method to not be able to tell - // whether an exception is pending or not. - TryCatch try_catch(isolate); - Local src; - if (!String::NewFromUtf8(isolate, - pkg_src.c_str(), - v8::NewStringType::kNormal, - pkg_src.length()).ToLocal(&src)) { + const PackageConfig& pjson = + GetPackageConfig(env, pkg.ToFilePath()); + // Note invalid package.json should throw in resolver + // currently we silently ignore which is incorrect + if (!pjson.exists || !pjson.is_valid || !pjson.has_main) { return Nothing(); } - - Local pkg_json; - if (!JSON::Parse(context, src).ToLocal(&pkg_json) || !pkg_json->IsObject()) - return Nothing(); - Local pkg_main; - if (!pkg_json.As()->Get(context, env->main_string()) - .ToLocal(&pkg_main) || !pkg_main->IsString()) { - return Nothing(); + if (!ShouldBeTreatedAsRelativeOrAbsolutePath(pjson.main)) { + return Resolve(env, "./" + pjson.main, search); } - Utf8Value main_utf8(isolate, pkg_main.As()); - std::string main_std(*main_utf8, main_utf8.length()); - if (!ShouldBeTreatedAsRelativeOrAbsolutePath(main_std)) { - main_std.insert(0, "./"); - } - return Resolve(env, main_std, search); + return Resolve(env, pjson.main, search); } Maybe ResolveModule(Environment* env, @@ -572,7 +601,8 @@ Maybe ResolveModule(Environment* env, URL dir(""); do { dir = parent; - Maybe check = Resolve(env, "./node_modules/" + specifier, dir, true); + Maybe check = + Resolve(env, "./node_modules/" + specifier, dir, IgnoreMain); if (!check.IsNothing()) { const size_t limit = specifier.find('/'); const size_t spec_len = @@ -594,8 +624,8 @@ Maybe ResolveModule(Environment* env, Maybe ResolveDirectory(Environment* env, const URL& search, - bool read_pkg_json) { - if (read_pkg_json) { + PackageMainCheck check_pjson_main) { + if (check_pjson_main) { Maybe main = ResolveMain(env, search); if (!main.IsNothing()) return main; @@ -605,15 +635,14 @@ Maybe ResolveDirectory(Environment* env, } // anonymous namespace - Maybe Resolve(Environment* env, const std::string& specifier, const URL& base, - bool read_pkg_json) { + PackageMainCheck check_pjson_main) { URL pure_url(specifier); if (!(pure_url.flags() & URL_FLAGS_FAILED)) { // just check existence, without altering - Maybe check = CheckFile(pure_url); + Maybe check = CheckFile(pure_url.ToFilePath()); if (check.IsNothing()) { return Nothing(); } @@ -630,7 +659,7 @@ Maybe Resolve(Environment* env, if (specifier.back() != '/') { resolved = URL(specifier + "/", base); } - return ResolveDirectory(env, resolved, read_pkg_json); + return ResolveDirectory(env, resolved, check_pjson_main); } else { return ResolveModule(env, specifier, base); } @@ -667,7 +696,7 @@ void ModuleWrap::Resolve(const FunctionCallbackInfo& args) { return; } - Maybe result = node::loader::Resolve(env, specifier_std, url, true); + Maybe result = node::loader::Resolve(env, specifier_std, url); if (result.IsNothing() || (result.FromJust().flags() & URL_FLAGS_FAILED)) { std::string msg = "Cannot find module " + specifier_std; env->ThrowError(msg.c_str()); diff --git a/src/module_wrap.h b/src/module_wrap.h index 5950c5a1be0177..ee3740b56119f6 100644 --- a/src/module_wrap.h +++ b/src/module_wrap.h @@ -12,10 +12,15 @@ namespace node { namespace loader { +enum PackageMainCheck : bool { + CheckMain = true, + IgnoreMain = false +}; + v8::Maybe Resolve(Environment* env, const std::string& specifier, const url::URL& base, - bool read_pkg_json = false); + PackageMainCheck read_pkg_json = CheckMain); class ModuleWrap : public BaseObject { public: diff --git a/test/fixtures/es-module-loaders/example-loader.mjs b/test/fixtures/es-module-loaders/example-loader.mjs index 771273a8d865c1..acb4486edc1288 100644 --- a/test/fixtures/es-module-loaders/example-loader.mjs +++ b/test/fixtures/es-module-loaders/example-loader.mjs @@ -8,7 +8,10 @@ const builtins = new Set( ); const JS_EXTENSIONS = new Set(['.js', '.mjs']); -export function resolve(specifier, parentModuleURL/*, defaultResolve */) { +const baseURL = new url.URL('file://'); +baseURL.pathname = process.cwd() + '/'; + +export function resolve(specifier, parentModuleURL = baseURL /*, defaultResolve */) { if (builtins.has(specifier)) { return { url: specifier, diff --git a/test/fixtures/es-module-loaders/js-loader.mjs b/test/fixtures/es-module-loaders/js-loader.mjs index 79d9774c1d787e..2173b0b503ef45 100644 --- a/test/fixtures/es-module-loaders/js-loader.mjs +++ b/test/fixtures/es-module-loaders/js-loader.mjs @@ -3,7 +3,11 @@ const builtins = new Set( Object.keys(process.binding('natives')).filter(str => /^(?!(?:internal|node|v8)\/)/.test(str)) ) -export function resolve (specifier, base) { + +const baseURL = new _url.URL('file://'); +baseURL.pathname = process.cwd() + '/'; + +export function resolve (specifier, base = baseURL) { if (builtins.has(specifier)) { return { url: specifier, diff --git a/test/fixtures/es-modules/noext b/test/fixtures/es-modules/noext new file mode 100644 index 00000000000000..f21c9bee6df46a --- /dev/null +++ b/test/fixtures/es-modules/noext @@ -0,0 +1 @@ +exports.cjs = true; \ No newline at end of file diff --git a/test/parallel/test-module-main-extension-lookup.js b/test/parallel/test-module-main-extension-lookup.js index 0a8cc47c77b2ed..6f7bc2eb1db6b2 100644 --- a/test/parallel/test-module-main-extension-lookup.js +++ b/test/parallel/test-module-main-extension-lookup.js @@ -5,3 +5,5 @@ const { execFileSync } = require('child_process'); const node = process.argv[0]; execFileSync(node, ['--experimental-modules', 'test/es-module/test-esm-ok']); +execFileSync(node, ['--experimental-modules', + 'test/fixtures/es-modules/noext']); From 755e07cb738558841880e32795b6f1df4005c5b9 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Sun, 11 Feb 2018 17:07:39 -0500 Subject: [PATCH 100/193] test: remove unnecessary timer The timer in NAPI's test_callback_scope/test-resolve-async.js can be removed. If the test fails, it will timeout on its own. The extra timer increases the chances of the test being flaky. PR-URL: https://github.com/nodejs/node/pull/18719 Fixes: https://github.com/nodejs/node/issues/18702 Reviewed-By: Ruben Bridgewater Reviewed-By: Santiago Gimeno Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- .../test_callback_scope/test-resolve-async.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/addons-napi/test_callback_scope/test-resolve-async.js b/test/addons-napi/test_callback_scope/test-resolve-async.js index e9f4b9044c0154..77f25c9dde533f 100644 --- a/test/addons-napi/test_callback_scope/test-resolve-async.js +++ b/test/addons-napi/test_callback_scope/test-resolve-async.js @@ -1,13 +1,6 @@ 'use strict'; const common = require('../../common'); -const assert = require('assert'); const { testResolveAsync } = require(`./build/${common.buildType}/binding`); -let called = false; -testResolveAsync().then(common.mustCall(() => { - called = true; -})); - -setTimeout(common.mustCall(() => { assert(called); }), - common.platformTimeout(20)); +testResolveAsync().then(common.mustCall()); From 92c86fd84d5f9be1a22388dd5ebb91ee8039e839 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Sun, 11 Feb 2018 15:58:55 -0500 Subject: [PATCH 101/193] test: add multiline repl input regression test This commit adds a regression test for de848ac1e0483327a2ce8716c3f8567eaeacb660, which broke multiline input in the REPL. PR-URL: https://github.com/nodejs/node/pull/18718 Refs: https://github.com/nodejs/node/pull/17828 Refs: https://github.com/nodejs/node/pull/18715 Reviewed-By: Ruben Bridgewater --- test/parallel/test-repl-multiline.js | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test/parallel/test-repl-multiline.js diff --git a/test/parallel/test-repl-multiline.js b/test/parallel/test-repl-multiline.js new file mode 100644 index 00000000000000..54048bf31f2f6f --- /dev/null +++ b/test/parallel/test-repl-multiline.js @@ -0,0 +1,35 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const repl = require('repl'); +const inputStream = new common.ArrayStream(); +const outputStream = new common.ArrayStream(); +const input = ['var foo = {', '};', 'foo;']; +let output = ''; + +outputStream.write = (data) => { output += data.replace('\r', ''); }; + +const r = repl.start({ + prompt: '', + input: inputStream, + output: outputStream, + terminal: true, + useColors: false +}); + +r.on('exit', common.mustCall(() => { + const actual = output.split('\n'); + + // Validate the output, which contains terminal escape codes. + assert.strictEqual(actual.length, 6); + assert.ok(actual[0].endsWith(input[0])); + assert.ok(actual[1].includes('... ')); + assert.ok(actual[1].endsWith(input[1])); + assert.strictEqual(actual[2], 'undefined'); + assert.ok(actual[3].endsWith(input[2])); + assert.strictEqual(actual[4], '{}'); + // Ignore the last line, which is nothing but escape codes. +})); + +inputStream.run(input); +r.close(); From 7dffabbb8417bb23d3789f10463c441b1e02a535 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Tue, 13 Feb 2018 02:09:44 -0500 Subject: [PATCH 102/193] doc: move Fedor to TSC Emeritus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In a conversation Fedor requested that this PR be made. They plan to continue working on core as a Collaborator. It is this committers belief that if Fedor would like to join the TSC again in the future there is no reason that could not be made possible. Thanks for all the hard work! PR-URL: https://github.com/nodejs/node/pull/18752 Reviewed-By: Gireesh Punathil Reviewed-By: Fedor Indutny Reviewed-By: Yuta Hiroto Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Matteo Collina Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Rich Trott Reviewed-By: Jon Moss Reviewed-By: Tobias Nießen Reviewed-By: Joyee Cheung Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Michael Dawson Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Evan Lucas --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 364047f25ff387..ab4bca96f814bb 100644 --- a/README.md +++ b/README.md @@ -246,8 +246,6 @@ For more information about the governance of the Node.js project, see **Jeremiah Senkpiel** <fishrock123@rocketmail.com> * [gibfahn](https://github.com/gibfahn) - **Gibson Fahnestock** <gibfahn@gmail.com> (he/him) -* [indutny](https://github.com/indutny) - -**Fedor Indutny** <fedor.indutny@gmail.com> * [jasnell](https://github.com/jasnell) - **James M Snell** <jasnell@gmail.com> (he/him) * [joyeecheung](https://github.com/joyeecheung) - @@ -277,6 +275,8 @@ For more information about the governance of the Node.js project, see **Ben Noordhuis** <info@bnoordhuis.nl> * [chrisdickinson](https://github.com/chrisdickinson) - **Chris Dickinson** <christopher.s.dickinson@gmail.com> +* [indutny](https://github.com/indutny) - +**Fedor Indutny** <fedor.indutny@gmail.com> * [isaacs](https://github.com/isaacs) - **Isaac Z. Schlueter** <i@izs.me> * [joshgav](https://github.com/joshgav) - From d8ec49ed9d0acbce329edac5938a455c3a1ea4c3 Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Tue, 12 Dec 2017 18:35:21 -0800 Subject: [PATCH 103/193] src: update trace event macros to v8 6.4 version PR-URL: https://github.com/nodejs/node/pull/17640 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Michael Dawson --- src/tracing/trace_event.h | 97 ++++++++++++++++++++++++++++++-- src/tracing/trace_event_common.h | 27 ++++++++- 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/src/tracing/trace_event.h b/src/tracing/trace_event.h index 44a30f38e59394..4aac9e5543eb67 100644 --- a/src/tracing/trace_event.h +++ b/src/tracing/trace_event.h @@ -92,6 +92,23 @@ enum CategoryGroupEnabledFlags { // unsigned int flags) #define TRACE_EVENT_API_ADD_TRACE_EVENT node::tracing::AddTraceEventImpl +// Add a trace event to the platform tracing system. +// uint64_t TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( +// char phase, +// const uint8_t* category_group_enabled, +// const char* name, +// const char* scope, +// uint64_t id, +// uint64_t bind_id, +// int num_args, +// const char** arg_names, +// const uint8_t* arg_types, +// const uint64_t* arg_values, +// unsigned int flags, +// int64_t timestamp) +#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP \ + node::tracing::AddTraceEventWithTimestampImpl + // Set the duration field of a COMPLETE trace event. // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( // const uint8_t* category_group_enabled, @@ -207,10 +224,18 @@ enum CategoryGroupEnabledFlags { } \ } while (0) -// Adds a trace event with a given timestamp. Not Implemented. +// Adds a trace event with a given timestamp. #define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \ timestamp, flags, ...) \ - UNIMPLEMENTED() + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ + if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ + node::tracing::AddTraceEventWithTimestamp( \ + phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ + node::tracing::kGlobalScope, node::tracing::kNoId, \ + node::tracing::kNoId, flags, timestamp, ##__VA_ARGS__); \ + } \ + } while (0) // Adds a trace event with a given id and timestamp. Not Implemented. #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP( \ @@ -253,8 +278,6 @@ const int kZeroNumArgs = 0; const decltype(nullptr) kGlobalScope = nullptr; const uint64_t kNoId = 0; -extern intptr_t kRuntimeCallStatsTracingEnabled; - class TraceEventHelper { public: static v8::TracingController* GetTracingController(); @@ -404,7 +427,7 @@ static inline uint64_t AddTraceEventImpl( arg_convertibles[1].reset(reinterpret_cast( static_cast(arg_values[1]))); } - // DCHECK(num_args <= 2); + // DCHECK(num_args, 2); v8::TracingController* controller = node::tracing::TraceEventHelper::GetTracingController(); return controller->AddTraceEvent(phase, category_group_enabled, name, scope, id, @@ -412,6 +435,28 @@ static inline uint64_t AddTraceEventImpl( arg_values, arg_convertibles, flags); } +static V8_INLINE uint64_t AddTraceEventWithTimestampImpl( + char phase, const uint8_t* category_group_enabled, const char* name, + const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, + const char** arg_names, const uint8_t* arg_types, + const uint64_t* arg_values, unsigned int flags, int64_t timestamp) { + std::unique_ptr arg_convertables[2]; + if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) { + arg_convertables[0].reset(reinterpret_cast( + static_cast(arg_values[0]))); + } + if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) { + arg_convertables[1].reset(reinterpret_cast( + static_cast(arg_values[1]))); + } + // DCHECK_LE(num_args, 2); + v8::TracingController* controller = + node::tracing::TraceEventHelper::GetTracingController(); + return controller->AddTraceEventWithTimestamp( + phase, category_group_enabled, name, scope, id, bind_id, num_args, + arg_names, arg_types, arg_values, arg_convertables, flags, timestamp); +} + // Define SetTraceValue for each allowed type. It stores the type and // value in the return arguments. This allows this API to avoid declaring any // structures so that it is portable to third_party libraries. @@ -514,6 +559,48 @@ static inline uint64_t AddTraceEvent( arg_names, arg_types, arg_values, flags); } +static V8_INLINE uint64_t AddTraceEventWithTimestamp( + char phase, const uint8_t* category_group_enabled, const char* name, + const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags, + int64_t timestamp) { + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( + phase, category_group_enabled, name, scope, id, bind_id, kZeroNumArgs, + nullptr, nullptr, nullptr, flags, timestamp); +} + +template +static V8_INLINE uint64_t AddTraceEventWithTimestamp( + char phase, const uint8_t* category_group_enabled, const char* name, + const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags, + int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val) { + const int num_args = 1; + uint8_t arg_type; + uint64_t arg_value; + SetTraceValue(std::forward(arg1_val), &arg_type, &arg_value); + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( + phase, category_group_enabled, name, scope, id, bind_id, num_args, + &arg1_name, &arg_type, &arg_value, flags, timestamp); +} + +template +static V8_INLINE uint64_t AddTraceEventWithTimestamp( + char phase, const uint8_t* category_group_enabled, const char* name, + const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags, + int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val, + const char* arg2_name, ARG2_TYPE&& arg2_val) { + const int num_args = 2; + const char* arg_names[2] = {arg1_name, arg2_name}; + unsigned char arg_types[2]; + uint64_t arg_values[2]; + SetTraceValue(std::forward(arg1_val), &arg_types[0], + &arg_values[0]); + SetTraceValue(std::forward(arg2_val), &arg_types[1], + &arg_values[1]); + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( + phase, category_group_enabled, name, scope, id, bind_id, num_args, + arg_names, arg_types, arg_values, flags, timestamp); +} + // Used by TRACE_EVENTx macros. Do not use directly. class ScopedTracer { public: diff --git a/src/tracing/trace_event_common.h b/src/tracing/trace_event_common.h index e87665b8cdb12b..51869ee9525614 100644 --- a/src/tracing/trace_event_common.h +++ b/src/tracing/trace_event_common.h @@ -189,6 +189,8 @@ // trace points would carry a significant performance cost of acquiring a lock // and resolving the category. +// Check that nobody includes this file directly. Clients are supposed to +// include the surrounding "trace_event.h" of their project instead. #if defined(TRACE_EVENT0) #error "Another copy of this file has already been included." #endif @@ -258,6 +260,12 @@ TRACE_EVENT_PHASE_INSTANT, category_group, name, timestamp, \ TRACE_EVENT_FLAG_NONE | scope) +#define TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(category_group, name, scope, \ + timestamp, arg_name, arg_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ + TRACE_EVENT_PHASE_INSTANT, category_group, name, timestamp, \ + TRACE_EVENT_FLAG_NONE | scope, arg_name, arg_val) + // Records a single BEGIN event called "name" immediately, with 0, 1 or 2 // associated arguments. If the category is not enabled, then this // does nothing. @@ -353,6 +361,12 @@ TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_MARK_WITH_TIMESTAMP2( \ + category_group, name, timestamp, arg1_name, arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \ + TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \ + TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) + #define TRACE_EVENT_COPY_MARK(category_group, name) \ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_MARK, category_group, name, \ TRACE_EVENT_FLAG_COPY) @@ -771,13 +785,22 @@ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) - #define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(category_group, name, \ id, timestamp) \ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) - +#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP1( \ + category_group, name, id, timestamp, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \ + TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val) +#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0( \ + category_group, name, id, timestamp) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ + TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \ + TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE) #define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( \ category_group, name, id, timestamp) \ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ From 138bdf6114242d3db26b887650bad009e0efae1b Mon Sep 17 00:00:00 2001 From: Antoine AMARA Date: Sun, 11 Feb 2018 20:55:16 +0100 Subject: [PATCH 104/193] doc: update crypo Certficate class. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the dead link to documentation. Add a link to mozilla developper documentation because W3C deleted the reference to this element. Add a note to inform element is deprecated since HTML 5.2. PR-URL: https://github.com/nodejs/node/pull/18721 Fixes: https://github.com/nodejs/node/issues/18662 Reviewed-By: Tobias Nießen Reviewed-By: Vse Mozhet Byt --- doc/api/crypto.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 9adc9082fc2fc2..e378b3705aaa00 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -42,7 +42,10 @@ added: v0.11.8 --> SPKAC is a Certificate Signing Request mechanism originally implemented by -Netscape and now specified formally as part of [HTML5's `keygen` element][]. +Netscape and was specified formally as part of [HTML5's `keygen` element][]. + +Note that `` is deprecated since [HTML 5.2][] and new projects +should not use this element anymore. The `crypto` module provides the `Certificate` class for working with SPKAC data. The most common usage is handling output generated by the HTML5 @@ -2469,7 +2472,8 @@ the `crypto`, `tls`, and `https` modules and are generally specific to OpenSSL. [`verify.verify()`]: #crypto_verify_verify_object_signature_signatureformat [Caveats]: #crypto_support_for_weak_or_compromised_algorithms [Crypto Constants]: #crypto_crypto_constants_1 -[HTML5's `keygen` element]: https://www.w3.org/TR/html5/forms.html#the-keygen-element +[HTML 5.2]: https://www.w3.org/TR/html52/changes.html#features-removed +[HTML5's `keygen` element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen [NIST SP 800-131A]: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf [NIST SP 800-132]: http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf [NIST SP 800-38D]: http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf From 28dc56dc716681162fcaf07bc11ac657a7df471e Mon Sep 17 00:00:00 2001 From: Sho Miyamoto Date: Thu, 15 Feb 2018 01:02:12 +0900 Subject: [PATCH 105/193] fs: fix typo in promises.lchmod & lchown PR-URL: https://github.com/nodejs/node/pull/18783 Reviewed-By: James M Snell Reviewed-By: Vse Mozhet Byt Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater --- lib/fs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 6129e3c3ef35a0..71eace0aef5b0a 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -2896,7 +2896,7 @@ const promises = { if (constants.O_SYMLINK !== undefined) { const fd = await promises.open(path, constants.O_WRONLY | constants.O_SYMLINK); - return promises.fschmod(fd, mode).finally(fd.close.bind(fd)); + return promises.fchmod(fd, mode).finally(fd.close.bind(fd)); } throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED'); }, @@ -2905,7 +2905,7 @@ const promises = { if (constants.O_SYMLINK !== undefined) { const fd = await promises.open(path, constants.O_WRONLY | constants.O_SYMLINK); - return promises.fschmod(fd, uid, gid).finally(fd.close.bind(fd)); + return promises.fchown(fd, uid, gid).finally(fd.close.bind(fd)); } throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED'); }, From cfad44105d6baae44a7b5dd6ea179f7550a5038f Mon Sep 17 00:00:00 2001 From: Nikolai Vavilov Date: Wed, 7 Feb 2018 12:23:26 +0200 Subject: [PATCH 106/193] build,win: replace run-python subroutine with single find_python call A subroutine does not work as a replacement for the `python` command since one cannot use a subroutine call in a `for /F` loop. PR-URL: https://github.com/nodejs/node/pull/18621 Reviewed-By: Bartosz Sosnowski Reviewed-By: Benjamin Gruenbaum Reviewed-By: Richard Lau --- vcbuild.bat | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/vcbuild.bat b/vcbuild.bat index 5e9f250e43ce52..a3d32055de49bd 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -165,6 +165,9 @@ if "%target%"=="Clean" echo deleting %~dp0deps\icu if "%target%"=="Clean" rmdir /S /Q %~dp0deps\icu :no-depsicu +call tools\msvs\find_python.cmd +if errorlevel 1 echo Could not find python2 & goto :exit + call :getnodeversion || exit /b 1 if defined TAG set configure_flags=%configure_flags% --tag=%TAG% @@ -234,7 +237,8 @@ goto run if defined noprojgen goto msbuild @rem Generate the VS project. -call :run-python configure %configure_flags% +echo configure %configure_flags% +python configure %configure_flags% if errorlevel 1 goto create-msvs-files-failed if not exist node.sln goto create-msvs-files-failed echo Project files generated. @@ -426,7 +430,7 @@ if defined test_node_inspect goto node-test-inspect goto node-tests :node-check-deopts -call :run-python tools\test.py --mode=release --check-deopts parallel sequential -J +python tools\test.py --mode=release --check-deopts parallel sequential -J if defined test_node_inspect goto node-test-inspect goto node-tests @@ -450,7 +454,8 @@ if defined no_cctest echo Skipping cctest because no-cctest was specified && got echo running 'cctest %cctest_args%' "%config%\cctest" %cctest_args% :run-test-py -call :run-python tools\test.py %test_args% +echo running 'python tools\test.py %test_args%' +python tools\test.py %test_args% goto test-v8 :test-v8 @@ -462,7 +467,7 @@ goto lint-cpp :lint-cpp if not defined lint_cpp goto lint-js call :run-lint-cpp src\*.c src\*.cc src\*.h test\addons\*.cc test\addons\*.h test\addons-napi\*.cc test\addons-napi\*.h test\cctest\*.cc test\cctest\*.h test\gc\binding.cc tools\icu\*.cc tools\icu\*.h -call :run-python tools/check-imports.py +python tools/check-imports.py goto lint-js :run-lint-cpp @@ -478,7 +483,7 @@ for /f "tokens=*" %%G in ('dir /b /s /a %*') do ( ( endlocal set cppfilelist=%localcppfilelist% ) -call :run-python tools/cpplint.py %cppfilelist% > nul +python tools/cpplint.py %cppfilelist% > nul goto exit :add-to-list @@ -540,14 +545,6 @@ echo vcbuild.bat lint : runs the C++ and JavaScript linter echo vcbuild.bat no-cctest : skip building cctest.exe goto exit -:run-python -call tools\msvs\find_python.cmd -if errorlevel 1 echo Could not find python2 & goto :exit -set cmd1="%VCBUILD_PYTHON_LOCATION%" %* -echo %cmd1% -%cmd1% -exit /b %ERRORLEVEL% - :exit goto :EOF @@ -560,9 +557,8 @@ rem *************** set NODE_VERSION= set TAG= set FULLVERSION= -:: Call as subroutine for validation of python -call :run-python tools\getnodeversion.py > nul -for /F "tokens=*" %%i in ('"%VCBUILD_PYTHON_LOCATION%" tools\getnodeversion.py') do set NODE_VERSION=%%i + +for /F "usebackq tokens=*" %%i in (`python "%~dp0tools\getnodeversion.py"`) do set NODE_VERSION=%%i if not defined NODE_VERSION ( echo Cannot determine current version of Node.js exit /b 1 From baf84950781f253ab0244779a9e40b5dc0f4930e Mon Sep 17 00:00:00 2001 From: Miles Elam Date: Mon, 8 Jan 2018 00:11:05 -0800 Subject: [PATCH 107/193] http: process 100, 102-199 according to specs. Adding ServerResponse.writeProcessing to send 102 status codes. Added an `'information'` event to ClientRequest to handle 1xx status codes except 101 Upgrade. 101 Upgrade is excluded due to its non-informational processing according to RFC7231, Section 6.2.2. This affects several modules downstream that use the http module, e.g., node-fetch, all of whom violate HTTP RFCs due to this module. As such, this could introduce a breaking change for downstream if HTTP standards were ignored in an ad-hoc fashion. See also RFC2518 RFC8297. PR-URL: https://github.com/nodejs/node/pull/18033 Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu --- doc/api/http.md | 40 ++++++++++++++ lib/_http_client.js | 29 ++++++++--- lib/_http_server.js | 4 ++ .../test-http-information-processing.js | 52 +++++++++++++++++++ 4 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 test/parallel/test-http-information-processing.js diff --git a/doc/api/http.md b/doc/api/http.md index 0a4fe959982480..74ba9e8792c4ef 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -400,6 +400,37 @@ Emitted when the server sends a '100 Continue' HTTP response, usually because the request contained 'Expect: 100-continue'. This is an instruction that the client should send the request body. +### Event: 'information' + + +Emitted when the server sends a 1xx response (excluding 101 Upgrade). This +event is emitted with a callback containing an object with a status code. + +```js +const http = require('http'); + +const options = { + hostname: '127.0.0.1', + port: 8080, + path: '/length_request' +}; + +// Make a request +const req = http.request(options); +req.end(); + +req.on('information', (res) => { + console.log('got information prior to main response: ' + res.statusCode); +}); +``` + +101 Upgrade statuses do not fire this event due to their break from the +traditional HTTP request/response chain, such as web sockets, in-place TLS +upgrades, or HTTP 2.0. To be notified of 101 Upgrade notices, listen for the +[`'upgrade'`][] event instead. + ### Event: 'response' + +Sends a HTTP/1.1 102 Processing message to the client, indicating that +the request body should be sent. + ## Class: http.IncomingMessage ```js assert.doesNotThrow( () => { @@ -353,6 +354,7 @@ assert.doesNotThrow( However, the following will result in an `AssertionError` with the message 'Got unwanted exception (TypeError)..': + ```js assert.doesNotThrow( () => { @@ -366,6 +368,7 @@ If an `AssertionError` is thrown and a value is provided for the `message` parameter, the value of `message` will be appended to the `AssertionError` message: + ```js assert.doesNotThrow( () => { diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 331ac63c47a062..c5a2bfe8561fdb 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -121,7 +121,7 @@ assert.throws(() => thrower(TypeError)); } common.expectsError( - () => assert.doesNotThrow(() => thrower(Error), 'user message'), + () => a.doesNotThrow(() => thrower(Error), 'user message'), { type: a.AssertionError, code: 'ERR_ASSERTION', @@ -131,7 +131,7 @@ common.expectsError( ); common.expectsError( - () => assert.doesNotThrow(() => thrower(Error), 'user message'), + () => a.doesNotThrow(() => thrower(Error), 'user message'), { code: 'ERR_ASSERTION', message: /Got unwanted exception: user message\n\[object Object\]/ @@ -139,7 +139,7 @@ common.expectsError( ); common.expectsError( - () => assert.doesNotThrow(() => thrower(Error)), + () => a.doesNotThrow(() => thrower(Error)), { code: 'ERR_ASSERTION', message: /Got unwanted exception\.\n\[object Object\]/ @@ -292,7 +292,7 @@ try { // Verify AssertionError is the result from doesNotThrow with custom Error. try { - assert.doesNotThrow(() => { + a.doesNotThrow(() => { throw new TypeError('wrong type'); }, TypeError, rangeError); } catch (e) { @@ -760,7 +760,6 @@ common.expectsError( errObj.code = '404'; common.expectsError( - // eslint-disable-next-line no-restricted-syntax () => assert.throws(errFn, errObj), { code: 'ERR_ASSERTION', @@ -772,7 +771,6 @@ common.expectsError( errObj.code = 404; errObj.foo = 'bar'; common.expectsError( - // eslint-disable-next-line no-restricted-syntax () => assert.throws(errFn, errObj), { code: 'ERR_ASSERTION', @@ -791,7 +789,7 @@ common.expectsError( ); common.expectsError( - () => assert.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }), + () => a.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }), { type: TypeError, code: 'ERR_INVALID_ARG_TYPE', @@ -822,7 +820,7 @@ common.expectsError( assert.throws(() => { throw undefined; }, /undefined/); common.expectsError( // eslint-disable-next-line no-throw-literal - () => assert.doesNotThrow(() => { throw undefined; }), + () => a.doesNotThrow(() => { throw undefined; }), { type: assert.AssertionError, code: 'ERR_ASSERTION', From 1bd32087eee4b7fc59732aeb6e1003737ac98f07 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Fri, 16 Feb 2018 16:07:23 +0100 Subject: [PATCH 119/193] doc: fix deprecation number PR-URL: https://github.com/nodejs/node/pull/18818 Refs: https://github.com/nodejs/node/commit/efb32592e1b78ec2559e1a409faa049e756a9501 Reviewed-By: Colin Ihrig --- doc/api/deprecations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index d1751cdff66180..f3d63d12a7c1c5 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -893,8 +893,8 @@ Use [`asyncResource.runInAsyncScope()`][] API instead which provides a much safer, and more convenient, alternative. See https://github.com/nodejs/node/pull/18513 for more details. - -### DEP0098: async context-unaware node::MakeCallback C++ APIs + +### DEP0099: async context-unaware node::MakeCallback C++ APIs Type: Compile-time From 703e37cf3fb163a4630a10f32bf5d5ec35142019 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Thu, 8 Feb 2018 23:50:34 +0100 Subject: [PATCH 120/193] process: deprecate process.assert() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was never documented and the `assert` module should be used instead. PR-URL: https://github.com/nodejs/node/pull/18666 Reviewed-By: Matteo Collina Reviewed-By: Anatoli Papirovski Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Jeremiah Senkpiel Reviewed-By: James M Snell --- doc/api/deprecations.md | 10 ++++++++++ lib/internal/process.js | 14 +++++++++----- test/parallel/test-process-assert.js | 12 ++++++++---- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index f3d63d12a7c1c5..cf1e97397ab625 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -902,11 +902,21 @@ Certain versions of `node::MakeCallback` APIs available to native modules are deprecated. Please use the versions of the API that accept an `async_context` parameter. + +### DEP0100: process.assert() + +Type: Runtime + +`process.assert()` is deprecated. Please use the [`assert`][] module instead. + +This was never a documented feature. + [`--pending-deprecation`]: cli.html#cli_pending_deprecation [`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size [`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array [`Buffer.from(buffer)`]: buffer.html#buffer_class_method_buffer_from_buffer [`Buffer.isBuffer()`]: buffer.html#buffer_class_method_buffer_isbuffer_obj +[`assert`]: assert.html [`clearInterval()`]: timers.html#timers_clearinterval_timeout [`clearTimeout()`]: timers.html#timers_cleartimeout_timeout [`EventEmitter.listenerCount(emitter, eventName)`]: events.html#events_eventemitter_listenercount_emitter_eventname diff --git a/lib/internal/process.js b/lib/internal/process.js index 776129a140fe68..371281dfd44041 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -3,11 +3,15 @@ const errors = require('internal/errors'); const util = require('util'); const constants = process.binding('constants').os.signals; - -const assert = process.assert = function(x, msg) { - if (!x) throw new errors.Error('ERR_ASSERTION', msg || 'assertion error'); -}; - +const assert = require('assert').strict; +const { deprecate } = require('internal/util'); + +process.assert = deprecate( + function(x, msg) { + if (!x) throw new errors.Error('ERR_ASSERTION', msg || 'assertion error'); + }, + 'process.assert() is deprecated. Please use the `assert` module instead.', + 'DEP0100'); function setup_performance() { require('perf_hooks'); diff --git a/test/parallel/test-process-assert.js b/test/parallel/test-process-assert.js index f62cf1a5ced1c7..74792eebb7bd2f 100644 --- a/test/parallel/test-process-assert.js +++ b/test/parallel/test-process-assert.js @@ -2,6 +2,12 @@ const common = require('../common'); const assert = require('assert'); +common.expectWarning( + 'DeprecationWarning', + 'process.assert() is deprecated. Please use the `assert` module instead.', + 'DEP0100' +); + assert.strictEqual(process.assert(1, 'error'), undefined); common.expectsError(() => { process.assert(undefined, 'errorMessage'); @@ -9,13 +15,11 @@ common.expectsError(() => { code: 'ERR_ASSERTION', type: Error, message: 'errorMessage' -} -); +}); common.expectsError(() => { process.assert(false); }, { code: 'ERR_ASSERTION', type: Error, message: 'assertion error' -} -); +}); From 3e1e450f92f3a605bfad125d1f4288ccaa83d09b Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 8 Feb 2018 19:35:16 +0100 Subject: [PATCH 121/193] fs: use Persistent::Reset() for resetting handles PR-URL: https://github.com/nodejs/node/pull/18650 Reviewed-By: Ben Noordhuis Reviewed-By: Joyee Cheung Reviewed-By: Colin Ihrig Reviewed-By: Kyle Farnung Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: James M Snell --- src/node_file.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node_file.h b/src/node_file.h index b76caa1467b3e2..094963c53ac586 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -152,8 +152,8 @@ class FileHandle : public AsyncWrap { } ~CloseReq() { uv_fs_req_cleanup(req()); - promise_.Empty(); - ref_.Empty(); + promise_.Reset(); + ref_.Reset(); } FileHandle* file_handle(); From ec9e7922bb72ce17b453d345232a0e725883a470 Mon Sep 17 00:00:00 2001 From: Yihong Wang Date: Fri, 2 Feb 2018 10:06:33 -0800 Subject: [PATCH 122/193] test: add lib path env when node_shared=true When building the node with `--shared` option, the major output is the shared library. However, we still build a node executable which links to the shared lib. It's for testing purpose. When testing with the executable, some test cases move/copy the executable, change the relative path to the shared library and fail. Using lib path env would solve the issue. However, in macOS, need to change the install name for the shared library and use rpath in the executable. In AIX, `-brtl` linker option rebinds the symbols in the executable and addon modules could use them. Signed-off-by: Yihong Wang PR-URL: https://github.com/nodejs/node/pull/18626 Refs: https://github.com/nodejs/node/issues/18535 Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater --- node.gyp | 12 ++++++++ test/common/shared-lib-util.js | 29 +++++++++++++++++++ .../test-child-process-fork-exec-path.js | 3 ++ .../test-module-loading-globalpaths.js | 3 ++ 4 files changed, 47 insertions(+) create mode 100644 test/common/shared-lib-util.js diff --git a/node.gyp b/node.gyp index 826543a9d17ce1..8e41cc053d4a78 100644 --- a/node.gyp +++ b/node.gyp @@ -260,6 +260,11 @@ }], ], }], + [ 'node_shared=="true"', { + 'xcode_settings': { + 'OTHER_LDFLAGS': [ '-Wl,-rpath,@loader_path', ], + }, + }], [ 'node_intermediate_lib_type=="shared_library" and OS=="win"', { # On Windows, having the same name for both executable and shared # lib causes filename collision. Need a different PRODUCT_NAME for @@ -416,6 +421,10 @@ 'conditions': [ [ 'node_shared=="true" and node_module_version!="" and OS!="win"', { 'product_extension': '<(shlib_suffix)', + 'xcode_settings': { + 'LD_DYLIB_INSTALL_NAME': + '@rpath/lib<(node_core_target_name).<(shlib_suffix)' + }, }], ['node_shared=="true" and OS=="aix"', { 'product_name': 'node_base', @@ -1130,6 +1139,9 @@ '<@(library_files)', 'common.gypi', ], + 'direct_dependent_settings': { + 'ldflags': [ '-Wl,-brtl' ], + }, }, ] }], # end aix section diff --git a/test/common/shared-lib-util.js b/test/common/shared-lib-util.js new file mode 100644 index 00000000000000..7ff7518ac31e6d --- /dev/null +++ b/test/common/shared-lib-util.js @@ -0,0 +1,29 @@ +/* eslint-disable required-modules */ +'use strict'; +const path = require('path'); + +// If node executable is linked to shared lib, need to take care about the +// shared lib path. +exports.addLibraryPath = function(env) { + if (!process.config.variables.node_shared) { + return; + } + + env = env || process.env; + + env.LD_LIBRARY_PATH = + (env.LD_LIBRARY_PATH ? env.LD_LIBRARY_PATH + path.delimiter : '') + + path.join(path.dirname(process.execPath), 'lib.target'); + // For AIX. + env.LIBPATH = + (env.LIBPATH ? env.LIBPATH + path.delimiter : '') + + path.join(path.dirname(process.execPath), 'lib.target'); + // For Mac OSX. + env.DYLD_LIBRARY_PATH = + (env.DYLD_LIBRARY_PATH ? env.DYLD_LIBRARY_PATH + path.delimiter : '') + + path.dirname(process.execPath); + // For Windows. + env.PATH = + (env.PATH ? env.PATH + path.delimiter : '') + + path.dirname(process.execPath); +}; diff --git a/test/parallel/test-child-process-fork-exec-path.js b/test/parallel/test-child-process-fork-exec-path.js index 42855cd663e826..8b94ef62a93bc8 100644 --- a/test/parallel/test-child-process-fork-exec-path.js +++ b/test/parallel/test-child-process-fork-exec-path.js @@ -28,6 +28,9 @@ const tmpdir = require('../common/tmpdir'); const msg = { test: 'this' }; const nodePath = process.execPath; const copyPath = path.join(tmpdir.path, 'node-copy.exe'); +const { addLibraryPath } = require('../common/shared-lib-util'); + +addLibraryPath(process.env); if (process.env.FORK) { assert(process.send); diff --git a/test/parallel/test-module-loading-globalpaths.js b/test/parallel/test-module-loading-globalpaths.js index e3c36cb21c202e..e82e6ad4b9dd45 100644 --- a/test/parallel/test-module-loading-globalpaths.js +++ b/test/parallel/test-module-loading-globalpaths.js @@ -6,6 +6,9 @@ const path = require('path'); const fs = require('fs'); const child_process = require('child_process'); const pkgName = 'foo'; +const { addLibraryPath } = require('../common/shared-lib-util'); + +addLibraryPath(process.env); if (process.argv[2] === 'child') { console.log(require(pkgName).string); From 916cfeca774e83925466f9a171f11c9bc73e4756 Mon Sep 17 00:00:00 2001 From: "Jose M. Palacios Diaz" Date: Thu, 1 Feb 2018 11:13:35 -0500 Subject: [PATCH 123/193] lib,src: audit process.env in lib/ for setuid binary Wrap SafeGetenv() in util binding with the purpose of protecting the cases when env vars are accessed with the privileges of another user in jsland. PR-URL: https://github.com/nodejs/node/pull/18511 Fixes: https://github.com/nodejs/node/issues/9160 Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis --- lib/module.js | 7 +++++-- lib/os.js | 8 ++++---- src/node_util.cc | 13 +++++++++++++ test/parallel/test-util-internal.js | 10 +++++++++- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/module.js b/lib/module.js index 77ed83423b9057..42da5c01ce8d6f 100644 --- a/lib/module.js +++ b/lib/module.js @@ -34,6 +34,7 @@ const { internalModuleReadJSON, internalModuleStat } = process.binding('fs'); +const { safeGetenv } = process.binding('util'); const internalModule = require('internal/module'); const preserveSymlinks = !!process.binding('config').preserveSymlinks; const experimentalModules = !!process.binding('config').experimentalModules; @@ -697,10 +698,13 @@ Module._initPaths = function() { const isWindows = process.platform === 'win32'; var homeDir; + var nodePath; if (isWindows) { homeDir = process.env.USERPROFILE; + nodePath = process.env.NODE_PATH; } else { - homeDir = process.env.HOME; + homeDir = safeGetenv('HOME'); + nodePath = safeGetenv('NODE_PATH'); } // $PREFIX/lib/node, where $PREFIX is the root of the Node.js installation. @@ -719,7 +723,6 @@ Module._initPaths = function() { paths.unshift(path.resolve(homeDir, '.node_modules')); } - var nodePath = process.env.NODE_PATH; if (nodePath) { paths = nodePath.split(path.delimiter).filter(function(path) { return !!path; diff --git a/lib/os.js b/lib/os.js index 7c07a5b0d385c5..eb13139dba9a9c 100644 --- a/lib/os.js +++ b/lib/os.js @@ -21,7 +21,7 @@ 'use strict'; -const { pushValToArrayMax } = process.binding('util'); +const { pushValToArrayMax, safeGetenv } = process.binding('util'); const constants = process.binding('constants').os; const { deprecate } = require('internal/util'); const { getCIDRSuffix } = require('internal/os'); @@ -127,9 +127,9 @@ function tmpdir() { if (path.length > 1 && path.endsWith('\\') && !path.endsWith(':\\')) path = path.slice(0, -1); } else { - path = process.env.TMPDIR || - process.env.TMP || - process.env.TEMP || + path = safeGetenv('TMPDIR') || + safeGetenv('TMP') || + safeGetenv('TEMP') || '/tmp'; if (path.length > 1 && path.endsWith('/')) path = path.slice(0, -1); diff --git a/src/node_util.cc b/src/node_util.cc index 0c4eaa4aa73120..1542b533f3484d 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -14,6 +14,7 @@ using v8::Object; using v8::Private; using v8::Promise; using v8::Proxy; +using v8::String; using v8::Value; @@ -174,6 +175,16 @@ void PromiseReject(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(ret.FromMaybe(false)); } +void SafeGetenv(const FunctionCallbackInfo& args) { + CHECK(args[0]->IsString()); + Utf8Value strenvtag(args.GetIsolate(), args[0]); + std::string text; + if (!node::SafeGetenv(*strenvtag, &text)) return; + args.GetReturnValue() + .Set(String::NewFromUtf8( + args.GetIsolate(), text.c_str(), + v8::NewStringType::kNormal).ToLocalChecked()); +} void Initialize(Local target, Local unused, @@ -225,6 +236,8 @@ void Initialize(Local target, env->SetMethod(target, "createPromise", CreatePromise); env->SetMethod(target, "promiseResolve", PromiseResolve); env->SetMethod(target, "promiseReject", PromiseReject); + + env->SetMethod(target, "safeGetenv", SafeGetenv); } } // namespace util diff --git a/test/parallel/test-util-internal.js b/test/parallel/test-util-internal.js index 5fda104baf19f3..ac7cf12229487a 100644 --- a/test/parallel/test-util-internal.js +++ b/test/parallel/test-util-internal.js @@ -8,9 +8,17 @@ const fixtures = require('../common/fixtures'); const { getHiddenValue, setHiddenValue, - arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex + arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex, + safeGetenv } = process.binding('util'); +for (const oneEnv in process.env) { + assert.strictEqual( + safeGetenv(oneEnv), + process.env[oneEnv] + ); +} + assert.strictEqual( getHiddenValue({}, kArrowMessagePrivateSymbolIndex), undefined); From bd4350ca08c17354db152b9676d8369a6d1bc57d Mon Sep 17 00:00:00 2001 From: Aaron Bieber Date: Sat, 3 Feb 2018 09:52:29 -0700 Subject: [PATCH 124/193] lib: set process.execPath on OpenBSD PR-URL: https://github.com/nodejs/node/pull/18543 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- lib/internal/bootstrap_node.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index 0c2109fab36cc0..24a4e8e2da4d3f 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -75,6 +75,13 @@ // URL::ToObject() method is used. NativeModule.require('internal/url'); + // On OpenBSD process.execPath will be relative unless we + // get the full path before process.execPath is used. + if (process.platform === 'openbsd') { + const { realpathSync } = NativeModule.require('fs'); + process.execPath = realpathSync.native(process.execPath); + } + Object.defineProperty(process, 'argv0', { enumerable: true, configurable: false, From ef0e92eb827cad86c327ad0b528fa6960e2060e0 Mon Sep 17 00:00:00 2001 From: Aaron Bieber Date: Sat, 3 Feb 2018 09:53:57 -0700 Subject: [PATCH 125/193] test: update a few tests to work on OpenBSD PR-URL: https://github.com/nodejs/node/pull/18543 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/common/index.js | 1 + test/parallel/test-child-process-exec-timeout.js | 11 +++++++++-- test/parallel/test-fs-utimes.js | 4 ++-- test/parallel/test-http-dns-error.js | 8 ++++++-- test/parallel/test-net-dns-error.js | 8 ++++++-- test/parallel/test-postmortem-metadata.js | 3 +++ test/parallel/test-setproctitle.js | 2 +- test/sequential/test-module-loading.js | 12 +++++++++--- 8 files changed, 37 insertions(+), 12 deletions(-) diff --git a/test/common/index.js b/test/common/index.js index 8ffeda42dfd52c..974aa841140fcc 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -55,6 +55,7 @@ exports.isLinuxPPCBE = (process.platform === 'linux') && (os.endianness() === 'BE'); exports.isSunOS = process.platform === 'sunos'; exports.isFreeBSD = process.platform === 'freebsd'; +exports.isOpenBSD = process.platform === 'openbsd'; exports.isLinux = process.platform === 'linux'; exports.isOSX = process.platform === 'darwin'; diff --git a/test/parallel/test-child-process-exec-timeout.js b/test/parallel/test-child-process-exec-timeout.js index ed25d9bff825a9..e08aff908522f2 100644 --- a/test/parallel/test-child-process-exec-timeout.js +++ b/test/parallel/test-child-process-exec-timeout.js @@ -16,15 +16,22 @@ const cmd = `"${process.execPath}" "${__filename}" child`; // Test the case where a timeout is set, and it expires. cp.exec(cmd, { timeout: 1 }, common.mustCall((err, stdout, stderr) => { + let sigterm = 'SIGTERM'; assert.strictEqual(err.killed, true); - assert.strictEqual(err.code, null); + // TODO OpenBSD returns a null signal and 143 for code + if (common.isOpenBSD) { + assert.strictEqual(err.code, 143); + sigterm = null; + } else { + assert.strictEqual(err.code, null); + } // At least starting with Darwin Kernel Version 16.4.0, sending a SIGTERM to a // process that is still starting up kills it with SIGKILL instead of SIGTERM. // See: https://github.com/libuv/libuv/issues/1226 if (common.isOSX) assert.ok(err.signal === 'SIGTERM' || err.signal === 'SIGKILL'); else - assert.strictEqual(err.signal, 'SIGTERM'); + assert.strictEqual(err.signal, sigterm); assert.strictEqual(err.cmd, cmd); assert.strictEqual(stdout.trim(), ''); assert.strictEqual(stderr.trim(), ''); diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index db8201d7cb9449..dae9c7dc9eabfc 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -178,8 +178,8 @@ process.on('exit', function() { const path = `${tmpdir.path}/test-utimes-precision`; fs.writeFileSync(path, ''); -// test Y2K38 for all platforms [except 'arm', and 'SunOS'] -if (!process.arch.includes('arm') && !common.isSunOS) { +// test Y2K38 for all platforms [except 'arm', 'OpenBSD' and 'SunOS'] +if (!process.arch.includes('arm') && !common.isOpenBSD && !common.isSunOS) { // because 2 ** 31 doesn't look right // eslint-disable-next-line space-infix-ops const Y2K38_mtime = 2**31; diff --git a/test/parallel/test-http-dns-error.js b/test/parallel/test-http-dns-error.js index 900cf40e6b209b..06a15c89fb46b3 100644 --- a/test/parallel/test-http-dns-error.js +++ b/test/parallel/test-http-dns-error.js @@ -32,6 +32,10 @@ const https = require('https'); const host = '*'.repeat(256); const MAX_TRIES = 5; +let errCode = 'ENOTFOUND'; +if (common.isOpenBSD) + errCode = 'EAI_FAIL'; + function tryGet(mod, tries) { // Bad host name should not throw an uncatchable exception. // Ensure that there is time to attach an error listener. @@ -41,7 +45,7 @@ function tryGet(mod, tries) { tryGet(mod, ++tries); return; } - assert.strictEqual(err.code, 'ENOTFOUND'); + assert.strictEqual(err.code, errCode); })); // http.get() called req1.end() for us } @@ -57,7 +61,7 @@ function tryRequest(mod, tries) { tryRequest(mod, ++tries); return; } - assert.strictEqual(err.code, 'ENOTFOUND'); + assert.strictEqual(err.code, errCode); })); req.end(); } diff --git a/test/parallel/test-net-dns-error.js b/test/parallel/test-net-dns-error.js index beebcd8cb9cf44..a5ae415592fed4 100644 --- a/test/parallel/test-net-dns-error.js +++ b/test/parallel/test-net-dns-error.js @@ -27,17 +27,21 @@ const net = require('net'); const host = '*'.repeat(256); +let errCode = 'ENOTFOUND'; +if (common.isOpenBSD) + errCode = 'EAI_FAIL'; + function do_not_call() { throw new Error('This function should not have been called.'); } const socket = net.connect(42, host, do_not_call); socket.on('error', common.mustCall(function(err) { - assert.strictEqual(err.code, 'ENOTFOUND'); + assert.strictEqual(err.code, errCode); })); socket.on('lookup', function(err, ip, type) { assert(err instanceof Error); - assert.strictEqual(err.code, 'ENOTFOUND'); + assert.strictEqual(err.code, errCode); assert.strictEqual(ip, undefined); assert.strictEqual(type, undefined); }); diff --git a/test/parallel/test-postmortem-metadata.js b/test/parallel/test-postmortem-metadata.js index 0c06108c58bd45..72a65d32a610bf 100644 --- a/test/parallel/test-postmortem-metadata.js +++ b/test/parallel/test-postmortem-metadata.js @@ -12,6 +12,9 @@ const args = [process.execPath]; if (common.isAIX) args.unshift('-Xany', '-B'); +if (common.isOpenBSD) + common.skip('no v8 debug symbols on OpenBSD'); + const nm = spawnSync('nm', args); if (nm.error && nm.error.errno === 'ENOENT') diff --git a/test/parallel/test-setproctitle.js b/test/parallel/test-setproctitle.js index 4bb88c4ba06922..1ab6bff6a30848 100644 --- a/test/parallel/test-setproctitle.js +++ b/test/parallel/test-setproctitle.js @@ -34,7 +34,7 @@ exec(cmd, common.mustCall((error, stdout, stderr) => { assert.strictEqual(stderr, ''); // freebsd always add ' (procname)' to the process title - if (common.isFreeBSD) + if (common.isFreeBSD || common.isOpenBSD) title += ` (${path.basename(process.execPath)})`; // omitting trailing whitespace and \n diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index 6fa789f19865d6..7bc8428fac5939 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); @@ -189,7 +189,10 @@ try { require(`${loadOrder}file3`); } catch (e) { // Not a real .node module, but we know we require'd the right thing. - assert.ok(/file3\.node/.test(e.message.replace(backslash, '/'))); + if (common.isOpenBSD) // OpenBSD errors with non-ELF object error + assert.ok(/File not an ELF object/.test(e.message.replace(backslash, '/'))); + else + assert.ok(/file3\.node/.test(e.message.replace(backslash, '/'))); } assert.strictEqual(require(`${loadOrder}file4`).file4, 'file4.reg', msg); assert.strictEqual(require(`${loadOrder}file5`).file5, 'file5.reg2', msg); @@ -197,7 +200,10 @@ try { try { require(`${loadOrder}file7`); } catch (e) { - assert.ok(/file7\/index\.node/.test(e.message.replace(backslash, '/'))); + if (common.isOpenBSD) + assert.ok(/File not an ELF object/.test(e.message.replace(backslash, '/'))); + else + assert.ok(/file7\/index\.node/.test(e.message.replace(backslash, '/'))); } assert.strictEqual(require(`${loadOrder}file8`).file8, 'file8/index.reg', msg); From 43b8ce4ce741a8a6a435e4073ca5a9ec188d4515 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 13 Feb 2018 00:58:22 +0100 Subject: [PATCH 126/193] buffer: remove obsolete NaN check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These two NaN entries are not necessary and we can safely remove them. PR-URL: https://github.com/nodejs/node/pull/18744 Reviewed-By: Weijia Wang Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Yuta Hiroto Reviewed-By: Luigi Pinca --- lib/buffer.js | 7 ++----- test/parallel/test-buffer-arraybuffer.js | 3 +++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index edebf901aa8425..01e605f50a8376 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -378,10 +378,7 @@ function fromArrayBuffer(obj, byteOffset, length) { } else { // convert length to non-negative integer length = +length; - // Check for NaN - if (length !== length) { - length = 0; - } else if (length > 0) { + if (length > 0) { if (length > maxLength) throw new errors.RangeError('ERR_BUFFER_OUT_OF_BOUNDS', 'length'); } else { @@ -404,7 +401,7 @@ function fromObject(obj) { } if (obj.length !== undefined || isAnyArrayBuffer(obj.buffer)) { - if (typeof obj.length !== 'number' || obj.length !== obj.length) { + if (typeof obj.length !== 'number') { return new FastBuffer(); } return fromArrayLike(obj); diff --git a/test/parallel/test-buffer-arraybuffer.js b/test/parallel/test-buffer-arraybuffer.js index 5ecf0279e02c88..41af1eecbea4b2 100644 --- a/test/parallel/test-buffer-arraybuffer.js +++ b/test/parallel/test-buffer-arraybuffer.js @@ -148,3 +148,6 @@ b.writeDoubleBE(11.11, 0, true); message: '"length" is outside of buffer bounds' }); } + +// Test an array like entry with the length set to NaN. +assert.deepStrictEqual(Buffer.from({ length: NaN }), Buffer.alloc(0)); From 96c57fbfaa8c1644648fa1414c9ad131b1320b60 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 13 Feb 2018 00:56:35 +0100 Subject: [PATCH 127/193] lib: switch to Number.isNaN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Number.isNaN is now as fast as `val !== val`. Switch to the more readable version. Also switch all `isNaN` to `Number.isNaN`. PR-URL: https://github.com/nodejs/node/pull/18744 Reviewed-By: Weijia Wang Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Yuta Hiroto Reviewed-By: Luigi Pinca --- .eslintrc.yaml | 1 + lib/_stream_readable.js | 2 +- lib/buffer.js | 20 ++++++++++---------- lib/events.js | 6 ++---- lib/internal/crypto/random.js | 4 ++-- lib/internal/repl.js | 2 +- lib/net.js | 2 +- lib/readline.js | 2 +- lib/repl.js | 2 +- lib/zlib.js | 14 +++++++------- 10 files changed, 27 insertions(+), 28 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 377f615e8a1d20..a46caecf085bb8 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -74,6 +74,7 @@ rules: message: __defineSetter__ is deprecated. no-return-await: error no-self-assign: error + no-self-compare: error no-throw-literal: error no-unused-labels: error no-useless-call: error diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 9678d77f6c6434..5cdc0864a0e1eb 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -341,7 +341,7 @@ function howMuchToRead(n, state) { return 0; if (state.objectMode) return 1; - if (n !== n) { + if (Number.isNaN(n)) { // Only flow one buffer at a time if (state.flowing && state.length) return state.buffer.head.data.length; diff --git a/lib/buffer.js b/lib/buffer.js index 01e605f50a8376..f43f67bb9404c5 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -363,8 +363,7 @@ function fromArrayBuffer(obj, byteOffset, length) { byteOffset = 0; } else { byteOffset = +byteOffset; - // check for NaN - if (byteOffset !== byteOffset) + if (Number.isNaN(byteOffset)) byteOffset = 0; } @@ -376,7 +375,7 @@ function fromArrayBuffer(obj, byteOffset, length) { if (length === undefined) { length = maxLength; } else { - // convert length to non-negative integer + // Convert length to non-negative integer. length = +length; if (length > 0) { if (length > maxLength) @@ -760,8 +759,7 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { // Coerce to Number. Values like null and [] become 0. byteOffset = +byteOffset; // If the offset is undefined, "foo", {}, coerces to NaN, search whole buffer. - // `x !== x`-style conditionals are a faster form of `isNaN(x)` - if (byteOffset !== byteOffset) { + if (Number.isNaN(byteOffset)) { byteOffset = dir ? 0 : buffer.length; } dir = !!dir; // Cast to bool. @@ -996,15 +994,17 @@ function adjustOffset(offset, length) { // Use Math.trunc() to convert offset to an integer value that can be larger // than an Int32. Hence, don't use offset | 0 or similar techniques. offset = Math.trunc(offset); - // `x !== x`-style conditionals are a faster form of `isNaN(x)` - if (offset === 0 || offset !== offset) { + if (offset === 0) { return 0; - } else if (offset < 0) { + } + if (offset < 0) { offset += length; return offset > 0 ? offset : 0; - } else { - return offset < length ? offset : length; } + if (offset < length) { + return offset; + } + return Number.isNaN(offset) ? 0 : length; } diff --git a/lib/events.js b/lib/events.js index 9ad5ec376ff8c8..aec30e7239d13d 100644 --- a/lib/events.js +++ b/lib/events.js @@ -52,9 +52,7 @@ Object.defineProperty(EventEmitter, 'defaultMaxListeners', { return defaultMaxListeners; }, set: function(arg) { - // check whether the input is a positive number (whose value is zero or - // greater and not a NaN). - if (typeof arg !== 'number' || arg < 0 || arg !== arg) { + if (typeof arg !== 'number' || arg < 0 || Number.isNaN(arg)) { const errors = lazyErrors(); throw new errors.RangeError('ERR_OUT_OF_RANGE', 'defaultMaxListeners', @@ -79,7 +77,7 @@ EventEmitter.init = function() { // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { - if (typeof n !== 'number' || n < 0 || isNaN(n)) { + if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) { const errors = lazyErrors(); throw new errors.RangeError('ERR_OUT_OF_RANGE', 'n', 'a non-negative number', n); diff --git a/lib/internal/crypto/random.js b/lib/internal/crypto/random.js index 52afbd8af3f034..9ffaa4de76f652 100644 --- a/lib/internal/crypto/random.js +++ b/lib/internal/crypto/random.js @@ -11,7 +11,7 @@ const { kMaxLength } = require('buffer'); const kMaxUint32 = Math.pow(2, 32) - 1; function assertOffset(offset, length) { - if (typeof offset !== 'number' || offset !== offset) { + if (typeof offset !== 'number' || Number.isNaN(offset)) { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'offset', 'number'); } @@ -25,7 +25,7 @@ function assertOffset(offset, length) { } function assertSize(size, offset = 0, length = Infinity) { - if (typeof size !== 'number' || size !== size) { + if (typeof size !== 'number' || Number.isNaN(size)) { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'size', 'number'); } diff --git a/lib/internal/repl.js b/lib/internal/repl.js index adbb80b0af7e60..4c4e3c8cb4e275 100644 --- a/lib/internal/repl.js +++ b/lib/internal/repl.js @@ -51,7 +51,7 @@ function createRepl(env, opts, cb) { } const historySize = Number(env.NODE_REPL_HISTORY_SIZE); - if (!isNaN(historySize) && historySize > 0) { + if (!Number.isNaN(historySize) && historySize > 0) { opts.historySize = historySize; } else { // XXX(chrisdickinson): set here to avoid affecting existing applications diff --git a/lib/net.js b/lib/net.js index 1bc28e856df5bd..41ddda767d832a 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1304,7 +1304,7 @@ function createServerHandle(address, port, addressType, fd) { handle = new Pipe(PipeConstants.SERVER); if (process.platform === 'win32') { var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES); - if (!isNaN(instances)) { + if (!Number.isNaN(instances)) { handle.setPendingInstances(instances); } } diff --git a/lib/readline.js b/lib/readline.js index 5f28f4c43f17d5..15933e69302d84 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -103,7 +103,7 @@ function Interface(input, output, completer, terminal) { } if (typeof historySize !== 'number' || - isNaN(historySize) || + Number.isNaN(historySize) || historySize < 0) { throw new errors.RangeError( 'ERR_INVALID_OPT_VALUE', diff --git a/lib/repl.js b/lib/repl.js index 84682b1b63e6cc..bd41ecdccf6972 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -575,7 +575,7 @@ function REPLServer(prompt, // display next prompt and return. if (trimmedCmd) { if (trimmedCmd.charAt(0) === '.' && trimmedCmd.charAt(1) !== '.' && - isNaN(parseFloat(trimmedCmd))) { + Number.isNaN(parseFloat(trimmedCmd))) { const matches = trimmedCmd.match(/^\.([^\s]+)\s*(.*)$/); const keyword = matches && matches[1]; const rest = matches && matches[2]; diff --git a/lib/zlib.js b/lib/zlib.js index 6262ddb6bc6522..aff72a868612e5 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -177,7 +177,7 @@ function Zlib(opts, mode) { if (opts) { chunkSize = opts.chunkSize; - if (chunkSize !== undefined && chunkSize === chunkSize) { + if (chunkSize !== undefined && !Number.isNaN(chunkSize)) { if (chunkSize < Z_MIN_CHUNK || !Number.isFinite(chunkSize)) throw new errors.RangeError('ERR_INVALID_OPT_VALUE', 'chunkSize', @@ -187,7 +187,7 @@ function Zlib(opts, mode) { } flush = opts.flush; - if (flush !== undefined && flush === flush) { + if (flush !== undefined && !Number.isNaN(flush)) { if (flush < Z_NO_FLUSH || flush > Z_BLOCK || !Number.isFinite(flush)) throw new errors.RangeError('ERR_INVALID_OPT_VALUE', 'flush', flush); } else { @@ -195,7 +195,7 @@ function Zlib(opts, mode) { } finishFlush = opts.finishFlush; - if (finishFlush !== undefined && finishFlush === finishFlush) { + if (finishFlush !== undefined && !Number.isNaN(finishFlush)) { if (finishFlush < Z_NO_FLUSH || finishFlush > Z_BLOCK || !Number.isFinite(finishFlush)) { throw new errors.RangeError('ERR_INVALID_OPT_VALUE', @@ -207,7 +207,7 @@ function Zlib(opts, mode) { } windowBits = opts.windowBits; - if (windowBits !== undefined && windowBits === windowBits) { + if (windowBits !== undefined && !Number.isNaN(windowBits)) { if (windowBits < Z_MIN_WINDOWBITS || windowBits > Z_MAX_WINDOWBITS || !Number.isFinite(windowBits)) { throw new errors.RangeError('ERR_INVALID_OPT_VALUE', @@ -219,7 +219,7 @@ function Zlib(opts, mode) { } level = opts.level; - if (level !== undefined && level === level) { + if (level !== undefined && !Number.isNaN(level)) { if (level < Z_MIN_LEVEL || level > Z_MAX_LEVEL || !Number.isFinite(level)) { throw new errors.RangeError('ERR_INVALID_OPT_VALUE', @@ -230,7 +230,7 @@ function Zlib(opts, mode) { } memLevel = opts.memLevel; - if (memLevel !== undefined && memLevel === memLevel) { + if (memLevel !== undefined && !Number.isNaN(memLevel)) { if (memLevel < Z_MIN_MEMLEVEL || memLevel > Z_MAX_MEMLEVEL || !Number.isFinite(memLevel)) { throw new errors.RangeError('ERR_INVALID_OPT_VALUE', @@ -241,7 +241,7 @@ function Zlib(opts, mode) { } strategy = opts.strategy; - if (strategy !== undefined && strategy === strategy) { + if (strategy !== undefined && !Number.isNaN(strategy)) { if (strategy < Z_DEFAULT_STRATEGY || strategy > Z_FIXED || !Number.isFinite(strategy)) { throw new errors.TypeError('ERR_INVALID_OPT_VALUE', From 941bc93f2229d4a28c3d3246878c7fd4fbf443ec Mon Sep 17 00:00:00 2001 From: Bamieh Date: Tue, 21 Nov 2017 20:33:16 +0200 Subject: [PATCH 128/193] test: wrap countdown callback in common.mustCall This adds a implicit common.mustCall to the callback provided to the countdown. PR-URL: https://github.com/nodejs/node/pull/18506 Reviewed-By: Anatoli Papirovski Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/common/README.md | 2 +- test/common/countdown.js | 3 ++- test/fixtures/failcounter.js | 2 ++ test/parallel/test-common-countdown.js | 22 ++++++++++++++++-- test/parallel/test-http-after-connect.js | 2 +- .../test-http-agent-destroyed-socket.js | 2 +- ...test-http-agent-maxsockets-regress-4050.js | 2 +- test/parallel/test-http-agent-maxsockets.js | 4 ++-- test/parallel/test-http-client-abort.js | 6 ++--- test/parallel/test-http-client-parse-error.js | 2 +- test/parallel/test-http-exceptions.js | 23 +++++++++++-------- test/parallel/test-http2-no-more-streams.js | 4 ++-- test/parallel/test-http2-server-rst-stream.js | 4 ++-- test/parallel/test-performanceobserver.js | 4 ++-- ...imeout-removes-other-socket-unref-timer.js | 2 +- 15 files changed, 55 insertions(+), 29 deletions(-) create mode 100644 test/fixtures/failcounter.js diff --git a/test/common/README.md b/test/common/README.md index 73779fd5372d88..f0bbe7d13dc1ee 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -380,7 +380,7 @@ Synchronous version of `spawnPwd`. The `Countdown` module provides a simple countdown mechanism for tests that require a particular action to be taken after a given number of completed tasks (for instance, shutting down an HTTP server after a specific number of -requests). +requests). The Countdown will fail the test if the remainder did not reach 0. ```js diff --git a/test/common/countdown.js b/test/common/countdown.js index 93bdbbfb16da5d..5fcb77c4ed66a0 100644 --- a/test/common/countdown.js +++ b/test/common/countdown.js @@ -4,13 +4,14 @@ const assert = require('assert'); const kLimit = Symbol('limit'); const kCallback = Symbol('callback'); +const common = require('./'); class Countdown { constructor(limit, cb) { assert.strictEqual(typeof limit, 'number'); assert.strictEqual(typeof cb, 'function'); this[kLimit] = limit; - this[kCallback] = cb; + this[kCallback] = common.mustCall(cb); } dec() { diff --git a/test/fixtures/failcounter.js b/test/fixtures/failcounter.js new file mode 100644 index 00000000000000..f3bc34a7308334 --- /dev/null +++ b/test/fixtures/failcounter.js @@ -0,0 +1,2 @@ +const Countdown = require('../common/countdown'); +new Countdown(2, () => {}); diff --git a/test/parallel/test-common-countdown.js b/test/parallel/test-common-countdown.js index ec0543f36fec74..6a1a2f1bbce98a 100644 --- a/test/parallel/test-common-countdown.js +++ b/test/parallel/test-common-countdown.js @@ -3,13 +3,31 @@ const common = require('../common'); const assert = require('assert'); const Countdown = require('../common/countdown'); +const fixtures = require('../common/fixtures'); +const { execFile } = require('child_process'); let done = ''; - -const countdown = new Countdown(2, common.mustCall(() => done = true)); +const countdown = new Countdown(2, () => done = true); assert.strictEqual(countdown.remaining, 2); countdown.dec(); assert.strictEqual(countdown.remaining, 1); countdown.dec(); assert.strictEqual(countdown.remaining, 0); assert.strictEqual(done, true); + +const failFixtures = [ + [ + fixtures.path('failcounter.js'), + 'Mismatched function calls. Expected exactly 1, actual 0.', + ] +]; + +for (const p of failFixtures) { + const [file, expected] = p; + execFile(process.argv[0], [file], common.mustCall((ex, stdout, stderr) => { + assert.ok(ex); + assert.strictEqual(stderr, ''); + const firstLine = stdout.split('\n').shift(); + assert.strictEqual(firstLine, expected); + })); +} diff --git a/test/parallel/test-http-after-connect.js b/test/parallel/test-http-after-connect.js index 324186bab72324..d209c82083e639 100644 --- a/test/parallel/test-http-after-connect.js +++ b/test/parallel/test-http-after-connect.js @@ -32,7 +32,7 @@ const server = http.createServer(common.mustCall((req, res) => { setTimeout(() => res.end(req.url), 50); }, 2)); -const countdown = new Countdown(2, common.mustCall(() => server.close())); +const countdown = new Countdown(2, () => server.close()); server.on('connect', common.mustCall((req, socket) => { socket.write('HTTP/1.1 200 Connection established\r\n\r\n'); diff --git a/test/parallel/test-http-agent-destroyed-socket.js b/test/parallel/test-http-agent-destroyed-socket.js index 7970ce8bae0fcb..39f4ebef5374c1 100644 --- a/test/parallel/test-http-agent-destroyed-socket.js +++ b/test/parallel/test-http-agent-destroyed-socket.js @@ -80,7 +80,7 @@ const server = http.createServer(common.mustCall((req, res) => { assert(request1.socket.destroyed); // assert not reusing the same socket, since it was destroyed. assert.notStrictEqual(request1.socket, request2.socket); - const countdown = new Countdown(2, common.mustCall(() => server.close())); + const countdown = new Countdown(2, () => server.close()); request2.socket.on('close', common.mustCall(() => countdown.dec())); response.on('end', common.mustCall(() => countdown.dec())); response.resume(); diff --git a/test/parallel/test-http-agent-maxsockets-regress-4050.js b/test/parallel/test-http-agent-maxsockets-regress-4050.js index 57a90e4b05c79f..eb1c95d5200694 100644 --- a/test/parallel/test-http-agent-maxsockets-regress-4050.js +++ b/test/parallel/test-http-agent-maxsockets-regress-4050.js @@ -17,7 +17,7 @@ const server = http.createServer(common.mustCall((req, res) => { res.end('hello world'); }, 6)); -const countdown = new Countdown(6, common.mustCall(() => server.close())); +const countdown = new Countdown(6, () => server.close()); function get(path, callback) { return http.get({ diff --git a/test/parallel/test-http-agent-maxsockets.js b/test/parallel/test-http-agent-maxsockets.js index 4d422f4a90b4f9..267f820e0435eb 100644 --- a/test/parallel/test-http-agent-maxsockets.js +++ b/test/parallel/test-http-agent-maxsockets.js @@ -26,13 +26,13 @@ function get(path, callback) { }, callback); } -const countdown = new Countdown(2, common.mustCall(() => { +const countdown = new Countdown(2, () => { const freepool = agent.freeSockets[Object.keys(agent.freeSockets)[0]]; assert.strictEqual(freepool.length, 2, `expect keep 2 free sockets, but got ${freepool.length}`); agent.destroy(); server.close(); -})); +}); function dec() { process.nextTick(() => countdown.dec()); diff --git a/test/parallel/test-http-client-abort.js b/test/parallel/test-http-client-abort.js index 71fd2ad64cabdd..f767189ea9d593 100644 --- a/test/parallel/test-http-client-abort.js +++ b/test/parallel/test-http-client-abort.js @@ -26,7 +26,7 @@ const Countdown = require('../common/countdown'); const N = 8; -const countdown = new Countdown(N, common.mustCall(() => server.close())); +const countdown = new Countdown(N, () => server.close()); const server = http.Server(common.mustCall((req, res) => { res.writeHead(200); @@ -37,9 +37,9 @@ const server = http.Server(common.mustCall((req, res) => { server.listen(0, common.mustCall(() => { const requests = []; - const reqCountdown = new Countdown(N, common.mustCall(() => { + const reqCountdown = new Countdown(N, () => { requests.forEach((req) => req.abort()); - })); + }); const options = { port: server.address().port }; diff --git a/test/parallel/test-http-client-parse-error.js b/test/parallel/test-http-client-parse-error.js index 60f1ee45c8efc1..cb4e3ff08434dd 100644 --- a/test/parallel/test-http-client-parse-error.js +++ b/test/parallel/test-http-client-parse-error.js @@ -25,7 +25,7 @@ const http = require('http'); const net = require('net'); const Countdown = require('../common/countdown'); -const countdown = new Countdown(2, common.mustCall(() => server.close())); +const countdown = new Countdown(2, () => server.close()); const payloads = [ 'HTTP/1.1 302 Object Moved\r\nContent-Length: 0\r\n\r\nhi world', diff --git a/test/parallel/test-http-exceptions.js b/test/parallel/test-http-exceptions.js index 0b6ac5bdc1f7d0..03e30b67e18b57 100644 --- a/test/parallel/test-http-exceptions.js +++ b/test/parallel/test-http-exceptions.js @@ -21,7 +21,12 @@ 'use strict'; require('../common'); +const Countdown = require('../common/countdown'); const http = require('http'); +const NUMBER_OF_EXCEPTIONS = 4; +const countdown = new Countdown(NUMBER_OF_EXCEPTIONS, () => { + process.exit(0); +}); const server = http.createServer(function(req, res) { intentionally_not_defined(); // eslint-disable-line no-undef @@ -30,16 +35,16 @@ const server = http.createServer(function(req, res) { res.end(); }); +function onUncaughtException(err) { + console.log(`Caught an exception: ${err}`); + if (err.name === 'AssertionError') throw err; + countdown.dec(); +} + +process.on('uncaughtException', onUncaughtException); + server.listen(0, function() { - for (let i = 0; i < 4; i += 1) { + for (let i = 0; i < NUMBER_OF_EXCEPTIONS; i += 1) { http.get({ port: this.address().port, path: `/busy/${i}` }); } }); - -let exception_count = 0; - -process.on('uncaughtException', function(err) { - console.log(`Caught an exception: ${err}`); - if (err.name === 'AssertionError') throw err; - if (++exception_count === 4) process.exit(0); -}); diff --git a/test/parallel/test-http2-no-more-streams.js b/test/parallel/test-http2-no-more-streams.js index dd06a709f23023..ff0c8baa14ccdb 100644 --- a/test/parallel/test-http2-no-more-streams.js +++ b/test/parallel/test-http2-no-more-streams.js @@ -23,10 +23,10 @@ server.listen(0, common.mustCall(() => { assert.strictEqual(client.state.nextStreamID, nextID); - const countdown = new Countdown(2, common.mustCall(() => { + const countdown = new Countdown(2, () => { server.close(); client.close(); - })); + }); { // This one will be ok diff --git a/test/parallel/test-http2-server-rst-stream.js b/test/parallel/test-http2-server-rst-stream.js index c2d938c22f4483..4b59a5ebe859bc 100644 --- a/test/parallel/test-http2-server-rst-stream.js +++ b/test/parallel/test-http2-server-rst-stream.js @@ -32,10 +32,10 @@ server.on('stream', (stream, headers) => { server.listen(0, common.mustCall(() => { const client = http2.connect(`http://localhost:${server.address().port}`); - const countdown = new Countdown(tests.length, common.mustCall(() => { + const countdown = new Countdown(tests.length, () => { client.close(); server.close(); - })); + }); tests.forEach((test) => { const req = client.request({ diff --git a/test/parallel/test-performanceobserver.js b/test/parallel/test-performanceobserver.js index 196675d1f5f563..2a6299952271e1 100644 --- a/test/parallel/test-performanceobserver.js +++ b/test/parallel/test-performanceobserver.js @@ -65,10 +65,10 @@ assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION], 0); new PerformanceObserver(common.mustCall(callback, 3)); const countdown = - new Countdown(3, common.mustCall(() => { + new Countdown(3, () => { observer.disconnect(); assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_MARK], 1); - })); + }); function callback(list, obs) { assert.strictEqual(obs, observer); diff --git a/test/parallel/test-timers-socket-timeout-removes-other-socket-unref-timer.js b/test/parallel/test-timers-socket-timeout-removes-other-socket-unref-timer.js index 842c8180701aa1..5dceb386fdbdf4 100644 --- a/test/parallel/test-timers-socket-timeout-removes-other-socket-unref-timer.js +++ b/test/parallel/test-timers-socket-timeout-removes-other-socket-unref-timer.js @@ -33,7 +33,7 @@ const server = net.createServer(function onClient(client) { }); server.listen(0, common.localhostIPv4, common.mustCall(() => { - const countdown = new Countdown(2, common.mustCall(() => server.close())); + const countdown = new Countdown(2, () => server.close()); { const client = net.connect({ port: server.address().port }); From f25104e1364cf7c56ae4a09a86b64a87de326ec3 Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Fri, 16 Feb 2018 15:21:13 -0200 Subject: [PATCH 129/193] doc: remove extra space in README.md PR-URL: https://github.com/nodejs/node/pull/18822 Reviewed-By: Ruben Bridgewater --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ab4bca96f814bb..7e3a57cfedc7c2 100644 --- a/README.md +++ b/README.md @@ -427,7 +427,7 @@ For more information about the governance of the Node.js project, see * [misterdjules](https://github.com/misterdjules) - **Julien Gilli** <jgilli@nodejs.org> * [mmarchini](https://github.com/mmarchini) - -**Matheus Marchini** <matheus@sthima.com> +**Matheus Marchini** <matheus@sthima.com> * [mscdex](https://github.com/mscdex) - **Brian White** <mscdex@mscdex.net> * [MylesBorins](https://github.com/MylesBorins) - From b74a6da5d004fa43f88475d95b1ca910206eccb7 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Tue, 6 Feb 2018 18:31:14 +0100 Subject: [PATCH 130/193] child_process: fix stdio sockets creation `readable` and `writable` properties can be passed directly to the `net.Socket` constructor. This change also avoids an unnecessary call to `read(0)` on the `stdin` socket. This behavior was disclosed when trying to merge `libuv@1.19.0` and specifically this commit: https://github.com/libuv/libuv/commit/fd049399aa4ed8495928e375466970d98cb42e17. PR-URL: https://github.com/nodejs/node/pull/18701 Refs: https://github.com/libuv/libuv/pull/1655 Reviewed-By: Anna Henningsen Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig --- lib/internal/child_process.js | 12 +----------- test/async-hooks/test-pipewrap.js | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index ac2b75f24575b8..58bb46e8a27a0e 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -238,17 +238,7 @@ function flushStdio(subprocess) { function createSocket(pipe, readable) { - var s = new net.Socket({ handle: pipe }); - - if (readable) { - s.writable = false; - s.readable = true; - } else { - s.writable = true; - s.readable = false; - } - - return s; + return net.Socket({ handle: pipe, readable, writable: !readable }); } diff --git a/test/async-hooks/test-pipewrap.js b/test/async-hooks/test-pipewrap.js index 550de7907a168a..066458841fabab 100644 --- a/test/async-hooks/test-pipewrap.js +++ b/test/async-hooks/test-pipewrap.js @@ -78,7 +78,7 @@ function onexit() { // Usually it is just one event, but it can be more. assert.ok(ioEvents >= 3, `at least 3 stdout io events, got ${ioEvents}`); - checkInvocations(pipe1, { init: 1, before: 2, after: 2 }, + checkInvocations(pipe1, { init: 1, before: 1, after: 1 }, 'pipe wrap when sleep.spawn was called'); checkInvocations(pipe2, { init: 1, before: ioEvents, after: ioEvents }, 'pipe wrap when sleep.spawn was called'); From befe675af8a136abe7e5b62d2ec2549abaa4fdaf Mon Sep 17 00:00:00 2001 From: Leko Date: Sat, 20 Jan 2018 00:26:50 +0900 Subject: [PATCH 131/193] test: try to connect after server was closed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18257 Reviewed-By: Joyee Cheung Reviewed-By: Michaël Zasso Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- .../test-net-connect-handle-econnrefused.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/parallel/test-net-connect-handle-econnrefused.js b/test/parallel/test-net-connect-handle-econnrefused.js index 569aded7bf5def..3c7310b4752d72 100644 --- a/test/parallel/test-net-connect-handle-econnrefused.js +++ b/test/parallel/test-net-connect-handle-econnrefused.js @@ -27,11 +27,10 @@ const assert = require('assert'); const server = net.createServer(); server.listen(0); const port = server.address().port; -const c = net.createConnection(port); - -c.on('connect', common.mustNotCall()); - -c.on('error', common.mustCall((e) => { - assert.strictEqual('ECONNREFUSED', e.code); +server.close(common.mustCall(() => { + const c = net.createConnection(port); + c.on('connect', common.mustNotCall()); + c.on('error', common.mustCall((e) => { + assert.strictEqual('ECONNREFUSED', e.code); + })); })); -server.close(); From 85893afb0594d7de479ade90ac309e138e63f8d7 Mon Sep 17 00:00:00 2001 From: juggernaut451 Date: Thu, 15 Feb 2018 01:45:31 +0530 Subject: [PATCH 132/193] test: reduce benchmark test run time The `millions` argument was missing. PR-URL: https://github.com/nodejs/node/pull/18787 Reviewed-By: Ruben Bridgewater Reviewed-By: Benjamin Gruenbaum Reviewed-By: Rich Trott --- test/sequential/test-benchmark-buffer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/sequential/test-benchmark-buffer.js b/test/sequential/test-benchmark-buffer.js index 2cee628ada8d79..f5e0c692f367be 100644 --- a/test/sequential/test-benchmark-buffer.js +++ b/test/sequential/test-benchmark-buffer.js @@ -13,6 +13,7 @@ runBenchmark('buffers', 'encoding=utf8', 'endian=BE', 'len=2', + 'millions=0.000001', 'method=', 'n=1', 'noAssert=true', From 3c29adb84fac00dfc16c51725e4832789610c6a7 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 15 Feb 2018 11:08:27 +0100 Subject: [PATCH 133/193] test: make tls test more rigorous MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * exit naturally, don't use process.exit() * ensure callbacks are actually called PR-URL: https://github.com/nodejs/node/pull/18792 Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen Reviewed-By: Evan Lucas Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum Reviewed-By: Matheus Marchini Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- test/parallel/test-tls-connect-no-host.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/parallel/test-tls-connect-no-host.js b/test/parallel/test-tls-connect-no-host.js index d685ba90ccdd84..f6384743ac7081 100644 --- a/test/parallel/test-tls-connect-no-host.js +++ b/test/parallel/test-tls-connect-no-host.js @@ -6,7 +6,6 @@ if (!common.hasCrypto) common.skip('missing crypto'); const tls = require('tls'); - const assert = require('assert'); const cert = fixtures.readSync('test_cert.pem'); @@ -15,10 +14,10 @@ const key = fixtures.readSync('test_key.pem'); // https://github.com/nodejs/node/issues/1489 // tls.connect(options) with no options.host should accept a cert with // CN:'localhost' -tls.createServer({ +const server = tls.createServer({ key, cert -}).listen(0, function() { +}).listen(0, common.mustCall(function() { const socket = tls.connect({ port: this.address().port, ca: cert, @@ -26,8 +25,9 @@ tls.createServer({ // but tls.checkServerIdentity() breaks before the fix with: // Error: Hostname/IP doesn't match certificate's altnames: // "Host: undefined. is not cert's CN: localhost" - }, function() { + }, common.mustCall(function() { assert(socket.authorized); - process.exit(); - }); -}); + socket.destroy(); + server.close(); + })); +})); From 862389b0aacfd41770c3fa6f692aed11c2a4b3ed Mon Sep 17 00:00:00 2001 From: Seth Brenith Date: Thu, 25 Jan 2018 09:48:38 -0800 Subject: [PATCH 134/193] http: simplify checkInvalidHeaderChar In the spirit of [17399](https://github.com/nodejs/node/pull/17399), we can also simplify checkInvalidHeaderChar to use regex matching instead of a loop. This makes it faster on long matches and slower on short matches or non-matches. This change also includes some sample data from an AcmeAir benchmark run, as a rough proxy for real-world data. PR-URL: https://github.com/nodejs/node/pull/18381 Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina Reviewed-By: Joyee Cheung Reviewed-By: Benedikt Meurer Reviewed-By: Tiancheng "Timothy" Gu --- benchmark/http/check_invalid_header_char.js | 81 +++++++++++++-------- lib/_http_common.js | 46 +----------- 2 files changed, 54 insertions(+), 73 deletions(-) diff --git a/benchmark/http/check_invalid_header_char.js b/benchmark/http/check_invalid_header_char.js index 399e71b2dfcc88..c70b0d39db2ffc 100644 --- a/benchmark/http/check_invalid_header_char.js +++ b/benchmark/http/check_invalid_header_char.js @@ -3,43 +3,66 @@ const common = require('../common.js'); const _checkInvalidHeaderChar = require('_http_common')._checkInvalidHeaderChar; -// Put it here so the benchmark result lines will not be super long. -const LONG_AND_INVALID = 'Here is a value that is really a folded header ' + - 'value\r\n this should be supported, but it is not currently'; +const groupedInputs = { + // Representative set of inputs from an AcmeAir benchmark run: + // all valid strings, average length 14.4, stdev 13.0 + group_acmeair: [ + 'W/"2-d4cbb29"', 'OK', 'Express', 'X-HTTP-Method-Override', 'Express', + 'application/json', 'application/json; charset=utf-8', '206', 'OK', + 'sessionid=; Path=/', 'text/html; charset=utf-8', + 'text/html; charset=utf-8', '10', 'W/"a-eda64de5"', 'OK', 'Express', + 'application/json', 'application/json; charset=utf-8', '2', 'W/"2-d4cbb29"', + 'OK', 'Express', 'X-HTTP-Method-Override', 'sessionid=; Path=/', 'Express', + 'sessionid=; Path=/,sessionid=6b059402-d62f-4e6f-b3dd-ce5b9e487c39; Path=/', + 'text/html; charset=utf-8', 'text/html; charset=utf-8', '9', 'OK', + 'sessionid=; Path=/', 'text/html; charset=utf-8', + 'text/html; charset=utf-8', '10', 'W/"a-eda64de5"', 'OK', 'Express', + 'Express', 'X-HTTP-Method-Override', 'sessionid=; Path=/', + 'application/json' + ], + + // Put it here so the benchmark result lines will not be super long. + LONG_AND_INVALID: ['Here is a value that is really a folded header ' + + 'value\r\n this should be supported, but it is not currently'] +}; + +const inputs = [ + // Valid + '', + '1', + '\t\t\t\t\t\t\t\t\t\tFoo bar baz', + 'keep-alive', + 'close', + 'gzip', + '20091', + 'private', + 'text/html; charset=utf-8', + 'text/plain', + 'Sat, 07 May 2016 16:54:48 GMT', + 'SAMEORIGIN', + 'en-US', + + // Invalid + '中文呢', // unicode + 'foo\nbar', + '\x7F' +]; const bench = common.createBenchmark(main, { - key: [ - // Valid - '', - '1', - '\t\t\t\t\t\t\t\t\t\tFoo bar baz', - 'keep-alive', - 'close', - 'gzip', - '20091', - 'private', - 'text/html; charset=utf-8', - 'text/plain', - 'Sat, 07 May 2016 16:54:48 GMT', - 'SAMEORIGIN', - 'en-US', - - // Invalid - 'LONG_AND_INVALID', - '中文呢', // unicode - 'foo\nbar', - '\x7F' - ], + input: inputs.concat(Object.keys(groupedInputs)), n: [1e6], }); -function main({ n, key }) { - if (key === 'LONG_AND_INVALID') { - key = LONG_AND_INVALID; +function main({ n, input }) { + let inputs = [input]; + if (groupedInputs.hasOwnProperty(input)) { + inputs = groupedInputs[input]; } + + const len = inputs.length; bench.start(); for (var i = 0; i < n; i++) { - _checkInvalidHeaderChar(key); + _checkInvalidHeaderChar(inputs[i % len]); } bench.end(n); } diff --git a/lib/_http_common.js b/lib/_http_common.js index a7e8b0c59b8854..ffb90407c62175 100644 --- a/lib/_http_common.js +++ b/lib/_http_common.js @@ -242,57 +242,15 @@ function checkIsHttpToken(val) { return tokenRegExp.test(val); } +const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; /** * True if val contains an invalid field-vchar * field-value = *( field-content / obs-fold ) * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] * field-vchar = VCHAR / obs-text - * - * checkInvalidHeaderChar() is currently designed to be inlinable by v8, - * so take care when making changes to the implementation so that the source - * code size does not exceed v8's default max_inlined_source_size setting. **/ -var validHdrChars = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0 - 15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 47 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 63 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 95 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112 - 127 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128 ... - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255 -]; function checkInvalidHeaderChar(val) { - val += ''; - if (val.length < 1) - return false; - if (!validHdrChars[val.charCodeAt(0)]) - return true; - if (val.length < 2) - return false; - if (!validHdrChars[val.charCodeAt(1)]) - return true; - if (val.length < 3) - return false; - if (!validHdrChars[val.charCodeAt(2)]) - return true; - if (val.length < 4) - return false; - if (!validHdrChars[val.charCodeAt(3)]) - return true; - for (var i = 4; i < val.length; ++i) { - if (!validHdrChars[val.charCodeAt(i)]) - return true; - } - return false; + return headerCharRegex.test(val); } module.exports = { From 2960096a912df208d1f2d4096b9d4e15015ac972 Mon Sep 17 00:00:00 2001 From: juggernaut451 Date: Wed, 14 Feb 2018 22:22:12 +0530 Subject: [PATCH 135/193] test: refactor of test-tls-over-http-tunnel PR-URL: https://github.com/nodejs/node/pull/18784 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Daniel Bevenius --- test/parallel/test-tls-over-http-tunnel.js | 49 ++++++++++++---------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/test/parallel/test-tls-over-http-tunnel.js b/test/parallel/test-tls-over-http-tunnel.js index 8e9bafda5394d6..f3f2bb3f2726ed 100644 --- a/test/parallel/test-tls-over-http-tunnel.js +++ b/test/parallel/test-tls-over-http-tunnel.js @@ -24,6 +24,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +// This test ensures that the data received through tls over http tunnel +// is same as what is sent. + const assert = require('assert'); const https = require('https'); const net = require('net'); @@ -37,21 +40,21 @@ const cert = fixtures.readKey('agent1-cert.pem'); const options = { key, cert }; -const server = https.createServer(options, function(req, res) { +const server = https.createServer(options, common.mustCall((req, res) => { console.log('SERVER: got request'); res.writeHead(200, { 'content-type': 'text/plain' }); console.log('SERVER: sending response'); res.end('hello world\n'); -}); +})); -const proxy = net.createServer(function(clientSocket) { +const proxy = net.createServer((clientSocket) => { console.log('PROXY: got a client connection'); let serverSocket = null; - clientSocket.on('data', function(chunk) { + clientSocket.on('data', (chunk) => { if (!serverSocket) { // Verify the CONNECT request assert.strictEqual(`CONNECT localhost:${server.address().port} ` + @@ -65,39 +68,39 @@ const proxy = net.createServer(function(clientSocket) { console.log('PROXY: creating a tunnel'); // create the tunnel - serverSocket = net.connect(server.address().port, function() { + serverSocket = net.connect(server.address().port, common.mustCall(() => { console.log('PROXY: replying to client CONNECT request'); // Send the response clientSocket.write('HTTP/1.1 200 OK\r\nProxy-Connections: keep' + - '-alive\r\nConnections: keep-alive\r\nVia: ' + - `localhost:${proxy.address().port}\r\n\r\n`); - }); + '-alive\r\nConnections: keep-alive\r\nVia: ' + + `localhost:${proxy.address().port}\r\n\r\n`); + })); - serverSocket.on('data', function(chunk) { + serverSocket.on('data', (chunk) => { clientSocket.write(chunk); }); - serverSocket.on('end', function() { + serverSocket.on('end', common.mustCall(() => { clientSocket.destroy(); - }); + })); } else { serverSocket.write(chunk); } }); - clientSocket.on('end', function() { + clientSocket.on('end', () => { serverSocket.destroy(); }); }); server.listen(0); -proxy.listen(0, function() { +proxy.listen(0, common.mustCall(() => { console.log('CLIENT: Making CONNECT request'); const req = http.request({ - port: this.address().port, + port: proxy.address().port, method: 'CONNECT', path: `localhost:${server.address().port}`, headers: { @@ -117,7 +120,7 @@ proxy.listen(0, function() { function onUpgrade(res, socket, head) { // Hacky. - process.nextTick(function() { + process.nextTick(() => { onConnect(res, socket, head); }); } @@ -145,20 +148,20 @@ proxy.listen(0, function() { socket: socket, // reuse the socket agent: false, rejectUnauthorized: false - }, function(res) { + }, (res) => { assert.strictEqual(200, res.statusCode); - res.on('data', function(chunk) { + res.on('data', common.mustCall((chunk) => { assert.strictEqual('hello world\n', chunk.toString()); console.log('CLIENT: got HTTPS response'); gotRequest = true; - }); + })); - res.on('end', function() { + res.on('end', common.mustCall(() => { proxy.close(); server.close(); - }); - }).on('error', function(er) { + })); + }).on('error', (er) => { // We're ok with getting ECONNRESET in this test, but it's // timing-dependent, and thus unreliable. Any other errors // are just failures, though. @@ -166,8 +169,8 @@ proxy.listen(0, function() { throw er; }).end(); } -}); +})); -process.on('exit', function() { +process.on('exit', () => { assert.ok(gotRequest); }); From c86fe511f4924ebbf7291fd938e5cd952199145b Mon Sep 17 00:00:00 2001 From: Sergey Golovin Date: Wed, 14 Feb 2018 20:52:00 +0300 Subject: [PATCH 136/193] module: replace magic numbers by constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add new constants - replace "magic" numbers in "module" by constants PR-URL: https://github.com/nodejs/node/pull/18785 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Minwoo Jung Reviewed-By: Weijia Wang Reviewed-By: Benjamin Gruenbaum Reviewed-By: Matheus Marchini Reviewed-By: Jon Moss Reviewed-By: Tobias Nießen --- lib/internal/constants.js | 23 ++++++++++++++--------- lib/module.js | 39 +++++++++++++++++++++++++++------------ 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/lib/internal/constants.js b/lib/internal/constants.js index f0ffec7a447529..d059dbc7ef8fa6 100644 --- a/lib/internal/constants.js +++ b/lib/internal/constants.js @@ -2,15 +2,20 @@ module.exports = { // Alphabet chars. - CHAR_UPPERCASE_A: 65, /*A*/ - CHAR_LOWERCASE_A: 97, /*a*/ - CHAR_UPPERCASE_Z: 90, /*Z*/ - CHAR_LOWERCASE_Z: 122, /*z*/ + CHAR_UPPERCASE_A: 65, /* A */ + CHAR_LOWERCASE_A: 97, /* a */ + CHAR_UPPERCASE_Z: 90, /* Z */ + CHAR_LOWERCASE_Z: 122, /* z */ // Non-alphabetic chars. - CHAR_DOT: 46, /*.*/ - CHAR_FORWARD_SLASH: 47, /*/*/ - CHAR_BACKWARD_SLASH: 92, /*\*/ - CHAR_COLON: 58, /*:*/ - CHAR_QUESTION_MARK: 63, /*?*/ + CHAR_DOT: 46, /* . */ + CHAR_FORWARD_SLASH: 47, /* / */ + CHAR_BACKWARD_SLASH: 92, /* \ */ + CHAR_COLON: 58, /* : */ + CHAR_QUESTION_MARK: 63, /* ? */ + CHAR_UNDERSCORE: 95, /* _ */ + + // Digits + CHAR_0: 48, /* 0 */ + CHAR_9: 57, /* 9 */ }; diff --git a/lib/module.js b/lib/module.js index 42da5c01ce8d6f..be49fa8e8d7e99 100644 --- a/lib/module.js +++ b/lib/module.js @@ -47,6 +47,19 @@ module.exports = Module; const internalESModule = require('internal/process/modules'); const ModuleJob = require('internal/loader/ModuleJob'); const createDynamicModule = require('internal/loader/CreateDynamicModule'); +const { + CHAR_UPPERCASE_A, + CHAR_LOWERCASE_A, + CHAR_UPPERCASE_Z, + CHAR_LOWERCASE_Z, + CHAR_FORWARD_SLASH, + CHAR_BACKWARD_SLASH, + CHAR_COLON, + CHAR_DOT, + CHAR_UNDERSCORE, + CHAR_0, + CHAR_9, +} = require('internal/constants'); function stat(filename) { filename = path.toNamespacedPath(filename); @@ -201,7 +214,7 @@ Module._findPath = function(request, paths, isMain) { var exts; var trailingSlash = request.length > 0 && - request.charCodeAt(request.length - 1) === 47/*/*/; + request.charCodeAt(request.length - 1) === CHAR_FORWARD_SLASH; // For each path for (var i = 0; i < paths.length; i++) { @@ -276,8 +289,8 @@ if (process.platform === 'win32') { // return root node_modules when path is 'D:\\'. // path.resolve will make sure from.length >=3 in Windows. - if (from.charCodeAt(from.length - 1) === 92/*\*/ && - from.charCodeAt(from.length - 2) === 58/*:*/) + if (from.charCodeAt(from.length - 1) === CHAR_BACKWARD_SLASH && + from.charCodeAt(from.length - 2) === CHAR_COLON) return [from + 'node_modules']; const paths = []; @@ -290,7 +303,9 @@ if (process.platform === 'win32') { // Use colon as an extra condition since we can get node_modules // path for drive root like 'C:\node_modules' and don't need to // parse drive name. - if (code === 92/*\*/ || code === 47/*/*/ || code === 58/*:*/) { + if (code === CHAR_BACKWARD_SLASH || + code === CHAR_FORWARD_SLASH || + code === CHAR_COLON) { if (p !== nmLen) paths.push(from.slice(0, last) + '\\node_modules'); last = i; @@ -324,7 +339,7 @@ if (process.platform === 'win32') { var last = from.length; for (var i = from.length - 1; i >= 0; --i) { const code = from.charCodeAt(i); - if (code === 47/*/*/) { + if (code === CHAR_FORWARD_SLASH) { if (p !== nmLen) paths.push(from.slice(0, last) + '/node_modules'); last = i; @@ -357,9 +372,9 @@ Module._resolveLookupPaths = function(request, parent, newReturn) { // Check for relative path if (request.length < 2 || - request.charCodeAt(0) !== 46/*.*/ || - (request.charCodeAt(1) !== 46/*.*/ && - request.charCodeAt(1) !== 47/*/*/)) { + request.charCodeAt(0) !== CHAR_DOT || + (request.charCodeAt(1) !== CHAR_DOT && + request.charCodeAt(1) !== CHAR_FORWARD_SLASH)) { var paths = modulePaths; if (parent) { if (!parent.paths) @@ -407,10 +422,10 @@ Module._resolveLookupPaths = function(request, parent, newReturn) { // We matched 'index.', let's validate the rest for (; i < base.length; ++i) { const code = base.charCodeAt(i); - if (code !== 95/*_*/ && - (code < 48/*0*/ || code > 57/*9*/) && - (code < 65/*A*/ || code > 90/*Z*/) && - (code < 97/*a*/ || code > 122/*z*/)) + if (code !== CHAR_UNDERSCORE && + (code < CHAR_0 || code > CHAR_9) && + (code < CHAR_UPPERCASE_A || code > CHAR_UPPERCASE_Z) && + (code < CHAR_LOWERCASE_A || code > CHAR_LOWERCASE_Z)) break; } if (i === base.length) { From 181209c3bdb78b7e9ccf83de218edd28bb5f7d9e Mon Sep 17 00:00:00 2001 From: juggernaut451 Date: Thu, 15 Feb 2018 21:19:03 +0530 Subject: [PATCH 137/193] test: refactor parallel/test-tls-addca MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18798 Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Luigi Pinca Reviewed-By: Daniel Bevenius Reviewed-By: Tobias Nießen --- test/parallel/test-tls-addca.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/parallel/test-tls-addca.js b/test/parallel/test-tls-addca.js index 034334a7e41bf3..8eb88db6291457 100644 --- a/test/parallel/test-tls-addca.js +++ b/test/parallel/test-tls-addca.js @@ -1,5 +1,5 @@ 'use strict'; -require('../common'); +const common = require('../common'); const fixtures = require('../common/fixtures'); // Adding a CA certificate to contextWithCert should not also add it to @@ -32,7 +32,7 @@ clientOptions.secureContext = contextWithoutCert; connect({ client: clientOptions, server: serverOptions, -}, function(err, pair, cleanup) { +}, common.mustCall((err, pair, cleanup) => { assert(err); assert.strictEqual(err.message, 'unable to verify the first certificate'); cleanup(); @@ -43,8 +43,8 @@ connect({ connect({ client: clientOptions, server: serverOptions, - }, function(err, pair, cleanup) { + }, common.mustCall((err, pair, cleanup) => { assert.ifError(err); cleanup(); - }); -}); + })); +})); From 36386dc4e349eb593208820949a02e93dc1ffd87 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Tue, 13 Feb 2018 01:23:55 -0500 Subject: [PATCH 138/193] deps: patch V8 to 6.4.388.45 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs: https://github.com/v8/v8/compare/6.4.388.44...6.4.388.45 PR-URL: https://github.com/nodejs/node/pull/18751 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- deps/v8/gypfiles/gyp_v8 | 15 +++++---------- deps/v8/include/v8-version.h | 2 +- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/deps/v8/gypfiles/gyp_v8 b/deps/v8/gypfiles/gyp_v8 index e419b5e89e78c0..5215f513525479 100755 --- a/deps/v8/gypfiles/gyp_v8 +++ b/deps/v8/gypfiles/gyp_v8 @@ -108,19 +108,14 @@ def run_gyp(args): if __name__ == '__main__': args = sys.argv[1:] - gyp_chromium_no_action = os.environ.get('GYP_CHROMIUM_NO_ACTION') - if gyp_chromium_no_action == '1': - print 'Skipping gyp_v8 due to GYP_CHROMIUM_NO_ACTION env var.' + gyp_chromium_no_action = os.environ.get('GYP_CHROMIUM_NO_ACTION', '1') + if gyp_chromium_no_action != '0': + print 'GYP is now disabled by default.\n' + print 'If you really want to run this, set the environment variable ' + print 'GYP_CHROMIUM_NO_ACTION=0.' sys.exit(0) running_as_hook = '--running-as-hook' - if running_as_hook in args and gyp_chromium_no_action != '0': - print 'GYP is now disabled by default in runhooks.\n' - print 'If you really want to run this, either run ' - print '`python gypfiles/gyp_v8` explicitly by hand ' - print 'or set the environment variable GYP_CHROMIUM_NO_ACTION=0.' - sys.exit(0) - if running_as_hook in args: args.remove(running_as_hook) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index c3bd1dfe2dd281..8de6adcf2269e8 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 4 #define V8_BUILD_NUMBER 388 -#define V8_PATCH_LEVEL 44 +#define V8_PATCH_LEVEL 45 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) From 463d1a490f2ed4679f8805fa57084b4445ea40d6 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 13 Feb 2018 06:09:31 +0100 Subject: [PATCH 139/193] test,benchmark,doc: enable dot-notation rule This enables the eslint dot-notation rule for all code instead of only in /lib. PR-URL: https://github.com/nodejs/node/pull/18749 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Matheus Marchini --- .eslintrc.yaml | 1 + benchmark/misc/object-property-bench.js | 2 ++ doc/api/http2.md | 6 ++-- lib/.eslintrc.yaml | 2 -- test/addons-napi/test_symbol/test1.js | 3 +- test/addons-napi/test_symbol/test2.js | 2 +- test/common/index.js | 2 +- test/common/inspector-helper.js | 30 ++++++++-------- test/parallel/test-cluster-fork-env.js | 6 ++-- test/parallel/test-crypto-hmac.js | 30 ++++++++-------- ...test-event-emitter-check-listener-leaks.js | 24 ++++++------- test/parallel/test-http-automatic-headers.js | 4 +-- test/parallel/test-http-flush-headers.js | 2 +- .../test-http-flush-response-headers.js | 2 +- test/parallel/test-http-proxy.js | 4 +-- .../parallel/test-http-server-multiheaders.js | 2 +- test/parallel/test-http-write-head.js | 2 +- test/parallel/test-http.js | 4 +-- .../test-http2-compat-expect-handling.js | 2 +- ...ompat-serverresponse-createpushresponse.js | 4 +-- ...test-http2-create-client-secure-session.js | 2 +- .../test-http2-create-client-session.js | 2 +- test/parallel/test-http2-multiheaders-raw.js | 2 +- test/parallel/test-http2-multiheaders.js | 12 +++---- test/parallel/test-http2-server-rst-stream.js | 2 +- test/parallel/test-http2-server-set-header.js | 2 +- .../test-https-agent-session-reuse.js | 6 ++-- test/parallel/test-inspector-esm.js | 10 +++--- ...test-internal-util-decorate-error-stack.js | 4 +-- test/parallel/test-memory-usage-emfile.js | 2 +- .../test-module-globalpaths-nodepath.js | 4 +-- .../test-module-loading-globalpaths.js | 24 ++++++------- .../test-tls-client-getephemeralkeyinfo.js | 2 +- test/parallel/test-util-inspect.js | 2 +- test/sequential/test-init.js | 2 +- test/sequential/test-inspector-bindings.js | 14 ++++---- .../sequential/test-inspector-ip-detection.js | 6 ++-- test/sequential/test-inspector.js | 34 +++++++++---------- 38 files changed, 132 insertions(+), 134 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index a46caecf085bb8..99489d2e7d8589 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -47,6 +47,7 @@ rules: accessor-pairs: error array-callback-return: error dot-location: [error, property] + dot-notation: error eqeqeq: [error, smart] no-fallthrough: error no-global-assign: error diff --git a/benchmark/misc/object-property-bench.js b/benchmark/misc/object-property-bench.js index ddc6faed7fc8b7..3a181ed0a540f8 100644 --- a/benchmark/misc/object-property-bench.js +++ b/benchmark/misc/object-property-bench.js @@ -1,5 +1,7 @@ 'use strict'; +/* eslint-disable dot-notation */ + const common = require('../common.js'); const bench = common.createBenchmark(main, { diff --git a/doc/api/http2.md b/doc/api/http2.md index 8b428484c00d96..6dc9946118ff78 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1220,7 +1220,7 @@ const server = http2.createServer(); server.on('stream', (stream) => { stream.respond({ ':status': 200 }, { getTrailers(trailers) { - trailers['ABC'] = 'some value to send'; + trailers.ABC = 'some value to send'; } }); stream.end('some data'); @@ -1303,7 +1303,7 @@ server.on('stream', (stream) => { }; stream.respondWithFD(fd, headers, { getTrailers(trailers) { - trailers['ABC'] = 'some value to send'; + trailers.ABC = 'some value to send'; } }); }); @@ -1410,7 +1410,7 @@ const http2 = require('http2'); const server = http2.createServer(); server.on('stream', (stream) => { function getTrailers(trailers) { - trailers['ABC'] = 'some value to send'; + trailers.ABC = 'some value to send'; } stream.respondWithFile('/some/file', { 'content-type': 'text/plain' }, diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index 0b00638e2a638c..e87596d4d5c21b 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -1,6 +1,4 @@ rules: - dot-notation: error - # Custom rules in tools/eslint-rules require-buffer: error buffer-constructor: error diff --git a/test/addons-napi/test_symbol/test1.js b/test/addons-napi/test_symbol/test1.js index 25eb473c4b1b9d..9232210c46da46 100644 --- a/test/addons-napi/test_symbol/test1.js +++ b/test/addons-napi/test_symbol/test1.js @@ -8,11 +8,10 @@ const test_symbol = require(`./build/${common.buildType}/test_symbol`); const sym = test_symbol.New('test'); assert.strictEqual(sym.toString(), 'Symbol(test)'); - const myObj = {}; const fooSym = test_symbol.New('foo'); const otherSym = test_symbol.New('bar'); -myObj['foo'] = 'bar'; +myObj.foo = 'bar'; myObj[fooSym] = 'baz'; myObj[otherSym] = 'bing'; assert.strictEqual(myObj.foo, 'bar'); diff --git a/test/addons-napi/test_symbol/test2.js b/test/addons-napi/test_symbol/test2.js index 60512431110a5b..8bc731b40cb5fe 100644 --- a/test/addons-napi/test_symbol/test2.js +++ b/test/addons-napi/test_symbol/test2.js @@ -7,7 +7,7 @@ const test_symbol = require(`./build/${common.buildType}/test_symbol`); const fooSym = test_symbol.New('foo'); const myObj = {}; -myObj['foo'] = 'bar'; +myObj.foo = 'bar'; myObj[fooSym] = 'baz'; Object.keys(myObj); // -> [ 'foo' ] Object.getOwnPropertyNames(myObj); // -> [ 'foo' ] diff --git a/test/common/index.js b/test/common/index.js index 974aa841140fcc..4c2c548830fc4b 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -502,7 +502,7 @@ exports.canCreateSymLink = function() { // whoami.exe needs to be the one from System32 // If unix tools are in the path, they can shadow the one we want, // so use the full path while executing whoami - const whoamiPath = path.join(process.env['SystemRoot'], + const whoamiPath = path.join(process.env.SystemRoot, 'System32', 'whoami.exe'); try { diff --git a/test/common/inspector-helper.js b/test/common/inspector-helper.js index 52e9d01b87dd7e..de0723933f573a 100644 --- a/test/common/inspector-helper.js +++ b/test/common/inspector-helper.js @@ -168,9 +168,7 @@ class InspectorSession { reject(message.error); } else { if (message.method === 'Debugger.scriptParsed') { - const script = message['params']; - const scriptId = script['scriptId']; - const url = script['url']; + const { scriptId, url } = message.params; this._scriptsIdsByUrl.set(scriptId, url); const fileUrl = url.startsWith('file:') ? url : getURLFromFilePath(url).toString(); @@ -192,12 +190,12 @@ class InspectorSession { _sendMessage(message) { const msg = JSON.parse(JSON.stringify(message)); // Clone! - msg['id'] = this._nextId++; + msg.id = this._nextId++; if (DEBUG) console.log('[sent]', JSON.stringify(msg)); const responsePromise = new Promise((resolve, reject) => { - this._commandResponsePromises.set(msg['id'], { resolve, reject }); + this._commandResponsePromises.set(msg.id, { resolve, reject }); }); return new Promise( @@ -243,14 +241,14 @@ class InspectorSession { } _isBreakOnLineNotification(message, line, expectedScriptPath) { - if ('Debugger.paused' === message['method']) { - const callFrame = message['params']['callFrames'][0]; - const location = callFrame['location']; - const scriptPath = this._scriptsIdsByUrl.get(location['scriptId']); + if ('Debugger.paused' === message.method) { + const callFrame = message.params.callFrames[0]; + const location = callFrame.location; + const scriptPath = this._scriptsIdsByUrl.get(location.scriptId); assert.strictEqual(scriptPath.toString(), expectedScriptPath.toString(), `${scriptPath} !== ${expectedScriptPath}`); - assert.strictEqual(line, location['lineNumber']); + assert.strictEqual(line, location.lineNumber); return true; } } @@ -266,12 +264,12 @@ class InspectorSession { _matchesConsoleOutputNotification(notification, type, values) { if (!Array.isArray(values)) values = [ values ]; - if ('Runtime.consoleAPICalled' === notification['method']) { - const params = notification['params']; - if (params['type'] === type) { + if ('Runtime.consoleAPICalled' === notification.method) { + const params = notification.params; + if (params.type === type) { let i = 0; - for (const value of params['args']) { - if (value['value'] !== values[i++]) + for (const value of params.args) { + if (value.value !== values[i++]) return false; } return i === values.length; @@ -392,7 +390,7 @@ class NodeInstance { async sendUpgradeRequest() { const response = await this.httpGet(null, '/json/list'); - const devtoolsUrl = response[0]['webSocketDebuggerUrl']; + const devtoolsUrl = response[0].webSocketDebuggerUrl; const port = await this.portPromise; return http.get({ port, diff --git a/test/parallel/test-cluster-fork-env.js b/test/parallel/test-cluster-fork-env.js index 5dd28163084a21..57e7881013d0fd 100644 --- a/test/parallel/test-cluster-fork-env.js +++ b/test/parallel/test-cluster-fork-env.js @@ -31,8 +31,8 @@ const cluster = require('cluster'); if (cluster.isWorker) { const result = cluster.worker.send({ - prop: process.env['cluster_test_prop'], - overwrite: process.env['cluster_test_overwrite'] + prop: process.env.cluster_test_prop, + overwrite: process.env.cluster_test_overwrite }); assert.strictEqual(result, true); @@ -45,7 +45,7 @@ if (cluster.isWorker) { // To check that the cluster extend on the process.env we will overwrite a // property - process.env['cluster_test_overwrite'] = 'old'; + process.env.cluster_test_overwrite = 'old'; // Fork worker const worker = cluster.fork({ diff --git a/test/parallel/test-crypto-hmac.js b/test/parallel/test-crypto-hmac.js index 6c2102fe23c82c..92fa16f98cda44 100644 --- a/test/parallel/test-crypto-hmac.js +++ b/test/parallel/test-crypto-hmac.js @@ -87,13 +87,13 @@ const wikipedia = [ ]; for (let i = 0, l = wikipedia.length; i < l; i++) { - for (const hash in wikipedia[i]['hmac']) { + for (const hash in wikipedia[i].hmac) { // FIPS does not support MD5. if (common.hasFipsCrypto && hash === 'md5') continue; - const expected = wikipedia[i]['hmac'][hash]; - const actual = crypto.createHmac(hash, wikipedia[i]['key']) - .update(wikipedia[i]['data']) + const expected = wikipedia[i].hmac[hash]; + const actual = crypto.createHmac(hash, wikipedia[i].key) + .update(wikipedia[i].data) .digest('hex'); assert.strictEqual( actual, @@ -252,18 +252,18 @@ const rfc4231 = [ ]; for (let i = 0, l = rfc4231.length; i < l; i++) { - for (const hash in rfc4231[i]['hmac']) { + for (const hash in rfc4231[i].hmac) { const str = crypto.createHmac(hash, rfc4231[i].key); str.end(rfc4231[i].data); let strRes = str.read().toString('hex'); - let actual = crypto.createHmac(hash, rfc4231[i]['key']) - .update(rfc4231[i]['data']) + let actual = crypto.createHmac(hash, rfc4231[i].key) + .update(rfc4231[i].data) .digest('hex'); - if (rfc4231[i]['truncate']) { + if (rfc4231[i].truncate) { actual = actual.substr(0, 32); // first 128 bits == 32 hex chars strRes = strRes.substr(0, 32); } - const expected = rfc4231[i]['hmac'][hash]; + const expected = rfc4231[i].hmac[hash]; assert.strictEqual( actual, expected, @@ -384,10 +384,10 @@ const rfc2202_sha1 = [ if (!common.hasFipsCrypto) { for (let i = 0, l = rfc2202_md5.length; i < l; i++) { - const actual = crypto.createHmac('md5', rfc2202_md5[i]['key']) - .update(rfc2202_md5[i]['data']) + const actual = crypto.createHmac('md5', rfc2202_md5[i].key) + .update(rfc2202_md5[i].data) .digest('hex'); - const expected = rfc2202_md5[i]['hmac']; + const expected = rfc2202_md5[i].hmac; assert.strictEqual( actual, expected, @@ -396,10 +396,10 @@ if (!common.hasFipsCrypto) { } } for (let i = 0, l = rfc2202_sha1.length; i < l; i++) { - const actual = crypto.createHmac('sha1', rfc2202_sha1[i]['key']) - .update(rfc2202_sha1[i]['data']) + const actual = crypto.createHmac('sha1', rfc2202_sha1[i].key) + .update(rfc2202_sha1[i].data) .digest('hex'); - const expected = rfc2202_sha1[i]['hmac']; + const expected = rfc2202_sha1[i].hmac; assert.strictEqual( actual, expected, diff --git a/test/parallel/test-event-emitter-check-listener-leaks.js b/test/parallel/test-event-emitter-check-listener-leaks.js index e24c07506c372e..7688c61a435cfb 100644 --- a/test/parallel/test-event-emitter-check-listener-leaks.js +++ b/test/parallel/test-event-emitter-check-listener-leaks.js @@ -32,9 +32,9 @@ const events = require('events'); for (let i = 0; i < 10; i++) { e.on('default', common.mustNotCall()); } - assert.ok(!e._events['default'].hasOwnProperty('warned')); + assert.ok(!e._events.default.hasOwnProperty('warned')); e.on('default', common.mustNotCall()); - assert.ok(e._events['default'].warned); + assert.ok(e._events.default.warned); // symbol const symbol = Symbol('symbol'); @@ -49,9 +49,9 @@ const events = require('events'); for (let i = 0; i < 5; i++) { e.on('specific', common.mustNotCall()); } - assert.ok(!e._events['specific'].hasOwnProperty('warned')); + assert.ok(!e._events.specific.hasOwnProperty('warned')); e.on('specific', common.mustNotCall()); - assert.ok(e._events['specific'].warned); + assert.ok(e._events.specific.warned); // only one e.setMaxListeners(1); @@ -65,7 +65,7 @@ const events = require('events'); for (let i = 0; i < 1000; i++) { e.on('unlimited', common.mustNotCall()); } - assert.ok(!e._events['unlimited'].hasOwnProperty('warned')); + assert.ok(!e._events.unlimited.hasOwnProperty('warned')); } // process-wide @@ -76,16 +76,16 @@ const events = require('events'); for (let i = 0; i < 42; ++i) { e.on('fortytwo', common.mustNotCall()); } - assert.ok(!e._events['fortytwo'].hasOwnProperty('warned')); + assert.ok(!e._events.fortytwo.hasOwnProperty('warned')); e.on('fortytwo', common.mustNotCall()); - assert.ok(e._events['fortytwo'].hasOwnProperty('warned')); - delete e._events['fortytwo'].warned; + assert.ok(e._events.fortytwo.hasOwnProperty('warned')); + delete e._events.fortytwo.warned; events.EventEmitter.defaultMaxListeners = 44; e.on('fortytwo', common.mustNotCall()); - assert.ok(!e._events['fortytwo'].hasOwnProperty('warned')); + assert.ok(!e._events.fortytwo.hasOwnProperty('warned')); e.on('fortytwo', common.mustNotCall()); - assert.ok(e._events['fortytwo'].hasOwnProperty('warned')); + assert.ok(e._events.fortytwo.hasOwnProperty('warned')); } // but _maxListeners still has precedence over defaultMaxListeners @@ -94,9 +94,9 @@ const events = require('events'); const e = new events.EventEmitter(); e.setMaxListeners(1); e.on('uno', common.mustNotCall()); - assert.ok(!e._events['uno'].hasOwnProperty('warned')); + assert.ok(!e._events.uno.hasOwnProperty('warned')); e.on('uno', common.mustNotCall()); - assert.ok(e._events['uno'].hasOwnProperty('warned')); + assert.ok(e._events.uno.hasOwnProperty('warned')); // chainable assert.strictEqual(e, e.setMaxListeners(1)); diff --git a/test/parallel/test-http-automatic-headers.js b/test/parallel/test-http-automatic-headers.js index 5a6a8e524c76ee..5e99f1ee39dd6b 100644 --- a/test/parallel/test-http-automatic-headers.js +++ b/test/parallel/test-http-automatic-headers.js @@ -22,8 +22,8 @@ server.on('listening', common.mustCall(() => { assert.strictEqual(res.headers['x-date'], 'foo'); assert.strictEqual(res.headers['x-connection'], 'bar'); assert.strictEqual(res.headers['x-content-length'], 'baz'); - assert(res.headers['date']); - assert.strictEqual(res.headers['connection'], 'keep-alive'); + assert(res.headers.date); + assert.strictEqual(res.headers.connection, 'keep-alive'); assert.strictEqual(res.headers['content-length'], '0'); server.close(); agent.destroy(); diff --git a/test/parallel/test-http-flush-headers.js b/test/parallel/test-http-flush-headers.js index 8ca5e92e5e02bc..88e8bddaed9e54 100644 --- a/test/parallel/test-http-flush-headers.js +++ b/test/parallel/test-http-flush-headers.js @@ -5,7 +5,7 @@ const http = require('http'); const server = http.createServer(); server.on('request', function(req, res) { - assert.strictEqual(req.headers['foo'], 'bar'); + assert.strictEqual(req.headers.foo, 'bar'); res.end('ok'); server.close(); }); diff --git a/test/parallel/test-http-flush-response-headers.js b/test/parallel/test-http-flush-response-headers.js index b8045568d49ac7..0f0a1387b56733 100644 --- a/test/parallel/test-http-flush-response-headers.js +++ b/test/parallel/test-http-flush-response-headers.js @@ -20,7 +20,7 @@ server.listen(0, common.localhostIPv4, function() { req.end(); function onResponse(res) { - assert.strictEqual(res.headers['foo'], 'bar'); + assert.strictEqual(res.headers.foo, 'bar'); res.destroy(); server.close(); } diff --git a/test/parallel/test-http-proxy.js b/test/parallel/test-http-proxy.js index a6267faaa6715c..8781679c0a45b8 100644 --- a/test/parallel/test-http-proxy.js +++ b/test/parallel/test-http-proxy.js @@ -50,7 +50,7 @@ const proxy = http.createServer(function(req, res) { console.error(`proxy res headers: ${JSON.stringify(proxy_res.headers)}`); - assert.strictEqual('world', proxy_res.headers['hello']); + assert.strictEqual('world', proxy_res.headers.hello); assert.strictEqual('text/plain', proxy_res.headers['content-type']); assert.deepStrictEqual(cookies, proxy_res.headers['set-cookie']); @@ -81,7 +81,7 @@ function startReq() { console.error('got res'); assert.strictEqual(200, res.statusCode); - assert.strictEqual('world', res.headers['hello']); + assert.strictEqual('world', res.headers.hello); assert.strictEqual('text/plain', res.headers['content-type']); assert.deepStrictEqual(cookies, res.headers['set-cookie']); diff --git a/test/parallel/test-http-server-multiheaders.js b/test/parallel/test-http-server-multiheaders.js index 201a95c346ae65..bf918ad24cc168 100644 --- a/test/parallel/test-http-server-multiheaders.js +++ b/test/parallel/test-http-server-multiheaders.js @@ -38,7 +38,7 @@ const srv = http.createServer(function(req, res) { assert.strictEqual(req.headers['sec-websocket-protocol'], 'chat, share'); assert.strictEqual(req.headers['sec-websocket-extensions'], 'foo; 1, bar; 2, baz'); - assert.strictEqual(req.headers['constructor'], 'foo, bar, baz'); + assert.strictEqual(req.headers.constructor, 'foo, bar, baz'); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('EOF'); diff --git a/test/parallel/test-http-write-head.js b/test/parallel/test-http-write-head.js index 26dc01b28853ed..f2ac7cb7b39dd4 100644 --- a/test/parallel/test-http-write-head.js +++ b/test/parallel/test-http-write-head.js @@ -68,7 +68,7 @@ s.listen(0, common.mustCall(runTest)); function runTest() { http.get({ port: this.address().port }, common.mustCall((response) => { response.on('end', common.mustCall(() => { - assert.strictEqual(response.headers['test'], '2'); + assert.strictEqual(response.headers.test, '2'); assert(response.rawHeaders.includes('Test')); s.close(); })); diff --git a/test/parallel/test-http.js b/test/parallel/test-http.js index 52bebc476e1510..e9a48c0fba3826 100644 --- a/test/parallel/test-http.js +++ b/test/parallel/test-http.js @@ -33,8 +33,8 @@ const server = http.Server(common.mustCall(function(req, res) { switch (req.url) { case '/hello': assert.strictEqual(req.method, 'GET'); - assert.strictEqual(req.headers['accept'], '*/*'); - assert.strictEqual(req.headers['foo'], 'bar'); + assert.strictEqual(req.headers.accept, '*/*'); + assert.strictEqual(req.headers.foo, 'bar'); assert.strictEqual(req.headers.cookie, 'foo=bar; bar=baz; baz=quux'); break; case '/there': diff --git a/test/parallel/test-http2-compat-expect-handling.js b/test/parallel/test-http2-compat-expect-handling.js index f36032c972fc45..e987118476337d 100644 --- a/test/parallel/test-http2-compat-expect-handling.js +++ b/test/parallel/test-http2-compat-expect-handling.js @@ -11,7 +11,7 @@ const expectValue = 'meoww'; const server = http2.createServer(common.mustNotCall()); server.once('checkExpectation', common.mustCall((req, res) => { - assert.strictEqual(req.headers['expect'], expectValue); + assert.strictEqual(req.headers.expect, expectValue); res.statusCode = 417; res.end(); })); diff --git a/test/parallel/test-http2-compat-serverresponse-createpushresponse.js b/test/parallel/test-http2-compat-serverresponse-createpushresponse.js index b168c3563c32e2..e0ce51bfc7ac50 100644 --- a/test/parallel/test-http2-compat-serverresponse-createpushresponse.js +++ b/test/parallel/test-http2-compat-serverresponse-createpushresponse.js @@ -77,7 +77,7 @@ server.listen(0, common.mustCall(() => { let actual = ''; pushStream.on('push', common.mustCall((headers) => { assert.strictEqual(headers[':status'], 200); - assert(headers['date']); + assert(headers.date); })); pushStream.setEncoding('utf8'); pushStream.on('data', (chunk) => actual += chunk); @@ -89,7 +89,7 @@ server.listen(0, common.mustCall(() => { req.on('response', common.mustCall((headers) => { assert.strictEqual(headers[':status'], 200); - assert(headers['date']); + assert(headers.date); })); let actual = ''; diff --git a/test/parallel/test-http2-create-client-secure-session.js b/test/parallel/test-http2-create-client-secure-session.js index b0111e15b69c15..1f20ec8e42a871 100644 --- a/test/parallel/test-http2-create-client-secure-session.js +++ b/test/parallel/test-http2-create-client-secure-session.js @@ -62,7 +62,7 @@ function verifySecureSession(key, cert, ca, opts) { req.on('response', common.mustCall((headers) => { assert.strictEqual(headers[':status'], 200); assert.strictEqual(headers['content-type'], 'application/json'); - assert(headers['date']); + assert(headers.date); })); let data = ''; diff --git a/test/parallel/test-http2-create-client-session.js b/test/parallel/test-http2-create-client-session.js index 963db2faa173b7..34e4e975d92d81 100644 --- a/test/parallel/test-http2-create-client-session.js +++ b/test/parallel/test-http2-create-client-session.js @@ -58,7 +58,7 @@ server.on('listening', common.mustCall(() => { assert.strictEqual(headers[':status'], 200, 'status code is set'); assert.strictEqual(headers['content-type'], 'text/html', 'content type is set'); - assert(headers['date'], 'there is a date'); + assert(headers.date); })); let data = ''; diff --git a/test/parallel/test-http2-multiheaders-raw.js b/test/parallel/test-http2-multiheaders-raw.js index 50486450d5aeb7..da9aa3a68eaa51 100644 --- a/test/parallel/test-http2-multiheaders-raw.js +++ b/test/parallel/test-http2-multiheaders-raw.js @@ -12,7 +12,7 @@ const src = Object.create(null); src['www-authenticate'] = 'foo'; src['WWW-Authenticate'] = 'bar'; src['WWW-AUTHENTICATE'] = 'baz'; -src['test'] = 'foo, bar, baz'; +src.test = 'foo, bar, baz'; server.on('stream', common.mustCall((stream, headers, flags, rawHeaders) => { const expected = [ diff --git a/test/parallel/test-http2-multiheaders.js b/test/parallel/test-http2-multiheaders.js index 9bf8f76d22e60e..6611dcf054d42a 100644 --- a/test/parallel/test-http2-multiheaders.js +++ b/test/parallel/test-http2-multiheaders.js @@ -24,21 +24,21 @@ src.constructor = 'foo'; src.Constructor = 'bar'; src.CONSTRUCTOR = 'baz'; // eslint-disable-next-line no-proto -src['__proto__'] = 'foo'; -src['__PROTO__'] = 'bar'; -src['__Proto__'] = 'baz'; +src.__proto__ = 'foo'; +src.__PROTO__ = 'bar'; +src.__Proto__ = 'baz'; function checkHeaders(headers) { - assert.deepStrictEqual(headers['accept'], + assert.deepStrictEqual(headers.accept, 'abc, def, ghijklmnop'); assert.deepStrictEqual(headers['www-authenticate'], 'foo, bar, baz'); assert.deepStrictEqual(headers['proxy-authenticate'], 'foo, bar, baz'); assert.deepStrictEqual(headers['x-foo'], 'foo, bar, baz'); - assert.deepStrictEqual(headers['constructor'], 'foo, bar, baz'); + assert.deepStrictEqual(headers.constructor, 'foo, bar, baz'); // eslint-disable-next-line no-proto - assert.deepStrictEqual(headers['__proto__'], 'foo, bar, baz'); + assert.deepStrictEqual(headers.__proto__, 'foo, bar, baz'); } server.on('stream', common.mustCall((stream, headers) => { diff --git a/test/parallel/test-http2-server-rst-stream.js b/test/parallel/test-http2-server-rst-stream.js index 4b59a5ebe859bc..4a58091aa61d7f 100644 --- a/test/parallel/test-http2-server-rst-stream.js +++ b/test/parallel/test-http2-server-rst-stream.js @@ -26,7 +26,7 @@ const tests = [ const server = http2.createServer(); server.on('stream', (stream, headers) => { - stream.close(headers['rstcode'] | 0); + stream.close(headers.rstcode | 0); }); server.listen(0, common.mustCall(() => { diff --git a/test/parallel/test-http2-server-set-header.js b/test/parallel/test-http2-server-set-header.js index 4b6228053f8ece..83f373ec21b314 100644 --- a/test/parallel/test-http2-server-set-header.js +++ b/test/parallel/test-http2-server-set-header.js @@ -20,7 +20,7 @@ server.listen(0, common.mustCall(() => { const req = client.request(headers); req.setEncoding('utf8'); req.on('response', common.mustCall(function(headers) { - assert.strictEqual(headers['foobar'], 'baz'); + assert.strictEqual(headers.foobar, 'baz'); assert.strictEqual(headers['x-powered-by'], 'node-test'); })); diff --git a/test/parallel/test-https-agent-session-reuse.js b/test/parallel/test-https-agent-session-reuse.js index 0330e111e9bd47..0717a3f8165d67 100644 --- a/test/parallel/test-https-agent-session-reuse.js +++ b/test/parallel/test-https-agent-session-reuse.js @@ -112,11 +112,11 @@ const server = https.createServer(options, function(req, res) { process.on('exit', function() { assert.strictEqual(serverRequests, 6); - assert.strictEqual(clientSessions['first'].toString('hex'), + assert.strictEqual(clientSessions.first.toString('hex'), clientSessions['first-reuse'].toString('hex')); - assert.notStrictEqual(clientSessions['first'].toString('hex'), + assert.notStrictEqual(clientSessions.first.toString('hex'), clientSessions['cipher-change'].toString('hex')); - assert.notStrictEqual(clientSessions['first'].toString('hex'), + assert.notStrictEqual(clientSessions.first.toString('hex'), clientSessions['before-drop'].toString('hex')); assert.notStrictEqual(clientSessions['cipher-change'].toString('hex'), clientSessions['before-drop'].toString('hex')); diff --git a/test/parallel/test-inspector-esm.js b/test/parallel/test-inspector-esm.js index b5a1365212a4ac..696f2af9a77462 100644 --- a/test/parallel/test-inspector-esm.js +++ b/test/parallel/test-inspector-esm.js @@ -17,9 +17,9 @@ function assertNoUrlsWhileConnected(response) { function assertScopeValues({ result }, expected) { const unmatched = new Set(Object.keys(expected)); for (const actual of result) { - const value = expected[actual['name']]; - assert.strictEqual(actual['value']['value'], value); - unmatched.delete(actual['name']); + const value = expected[actual.name]; + assert.strictEqual(actual.value.value, value); + unmatched.delete(actual.name); } assert.deepStrictEqual(Array.from(unmatched.values()), []); } @@ -93,14 +93,14 @@ async function testBreakpoint(session) { } }); - assert.strictEqual(result['value'], 1002); + assert.strictEqual(result.value, 1002); result = (await session.send({ 'method': 'Runtime.evaluate', 'params': { 'expression': '5 * 5' } })).result; - assert.strictEqual(result['value'], 25); + assert.strictEqual(result.value, 25); } async function runTest() { diff --git a/test/parallel/test-internal-util-decorate-error-stack.js b/test/parallel/test-internal-util-decorate-error-stack.js index 9d20374409c9c1..5694d746c667f4 100644 --- a/test/parallel/test-internal-util-decorate-error-stack.js +++ b/test/parallel/test-internal-util-decorate-error-stack.js @@ -7,8 +7,8 @@ const internalUtil = require('internal/util'); const binding = process.binding('util'); const spawnSync = require('child_process').spawnSync; -const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol']; -const kDecoratedPrivateSymbolIndex = binding['decorated_private_symbol']; +const kArrowMessagePrivateSymbolIndex = binding.arrow_message_private_symbol; +const kDecoratedPrivateSymbolIndex = binding.decorated_private_symbol; const decorateErrorStack = internalUtil.decorateErrorStack; diff --git a/test/parallel/test-memory-usage-emfile.js b/test/parallel/test-memory-usage-emfile.js index c5345079a7f47b..f8d1fc90da7aec 100644 --- a/test/parallel/test-memory-usage-emfile.js +++ b/test/parallel/test-memory-usage-emfile.js @@ -10,4 +10,4 @@ while (files.length < 256) files.push(fs.openSync(__filename, 'r')); const r = process.memoryUsage(); -assert.strictEqual(true, r['rss'] > 0); +assert.strictEqual(true, r.rss > 0); diff --git a/test/parallel/test-module-globalpaths-nodepath.js b/test/parallel/test-module-globalpaths-nodepath.js index dce5bf12c1604e..c4492169ad7e81 100644 --- a/test/parallel/test-module-globalpaths-nodepath.js +++ b/test/parallel/test-module-globalpaths-nodepath.js @@ -30,11 +30,11 @@ const partC = ''; if (common.isWindows) { partA = 'C:\\Users\\Rocko Artischocko\\AppData\\Roaming\\npm'; partB = 'C:\\Program Files (x86)\\nodejs\\'; - process.env['NODE_PATH'] = `${partA};${partB};${partC}`; + process.env.NODE_PATH = `${partA};${partB};${partC}`; } else { partA = '/usr/test/lib/node_modules'; partB = '/usr/test/lib/node'; - process.env['NODE_PATH'] = `${partA}:${partB}:${partC}`; + process.env.NODE_PATH = `${partA}:${partB}:${partC}`; } mod._initPaths(); diff --git a/test/parallel/test-module-loading-globalpaths.js b/test/parallel/test-module-loading-globalpaths.js index e82e6ad4b9dd45..aff96543735428 100644 --- a/test/parallel/test-module-loading-globalpaths.js +++ b/test/parallel/test-module-loading-globalpaths.js @@ -42,14 +42,14 @@ if (process.argv[2] === 'child') { const env = Object.assign({}, process.env); // Turn on module debug to aid diagnosing failures. - env['NODE_DEBUG'] = 'module'; + env.NODE_DEBUG = 'module'; // Unset NODE_PATH. - delete env['NODE_PATH']; + delete env.NODE_PATH; // Test empty global path. const noPkgHomeDir = path.join(tmpdir.path, 'home-no-pkg'); fs.mkdirSync(noPkgHomeDir); - env['HOME'] = env['USERPROFILE'] = noPkgHomeDir; + env.HOME = env.USERPROFILE = noPkgHomeDir; assert.throws( () => { child_process.execFileSync(testExecPath, [ __filename, 'child' ], @@ -59,17 +59,17 @@ if (process.argv[2] === 'child') { // Test module in $HOME/.node_modules. const modHomeDir = path.join(testFixturesDir, 'home-pkg-in-node_modules'); - env['HOME'] = env['USERPROFILE'] = modHomeDir; + env.HOME = env.USERPROFILE = modHomeDir; runTest('$HOME/.node_modules', env); // Test module in $HOME/.node_libraries. const libHomeDir = path.join(testFixturesDir, 'home-pkg-in-node_libraries'); - env['HOME'] = env['USERPROFILE'] = libHomeDir; + env.HOME = env.USERPROFILE = libHomeDir; runTest('$HOME/.node_libraries', env); // Test module both $HOME/.node_modules and $HOME/.node_libraries. const bothHomeDir = path.join(testFixturesDir, 'home-pkg-in-both'); - env['HOME'] = env['USERPROFILE'] = bothHomeDir; + env.HOME = env.USERPROFILE = bothHomeDir; runTest('$HOME/.node_modules', env); // Test module in $PREFIX/lib/node. @@ -82,22 +82,22 @@ if (process.argv[2] === 'child') { const pkgPath = path.join(prefixLibNodePath, `${pkgName}.js`); fs.writeFileSync(pkgPath, `exports.string = '${expectedString}';`); - env['HOME'] = env['USERPROFILE'] = noPkgHomeDir; + env.HOME = env.USERPROFILE = noPkgHomeDir; runTest(expectedString, env); // Test module in all global folders. - env['HOME'] = env['USERPROFILE'] = bothHomeDir; + env.HOME = env.USERPROFILE = bothHomeDir; runTest('$HOME/.node_modules', env); // Test module in NODE_PATH is loaded ahead of global folders. - env['HOME'] = env['USERPROFILE'] = bothHomeDir; - env['NODE_PATH'] = path.join(testFixturesDir, 'node_path'); + env.HOME = env.USERPROFILE = bothHomeDir; + env.NODE_PATH = path.join(testFixturesDir, 'node_path'); runTest('$NODE_PATH', env); // Test module in local folder is loaded ahead of global folders. const localDir = path.join(testFixturesDir, 'local-pkg'); - env['HOME'] = env['USERPROFILE'] = bothHomeDir; - env['NODE_PATH'] = path.join(testFixturesDir, 'node_path'); + env.HOME = env.USERPROFILE = bothHomeDir; + env.NODE_PATH = path.join(testFixturesDir, 'node_path'); const child = child_process.execFileSync(testExecPath, [ path.join(localDir, 'test.js') ], { encoding: 'utf8', env: env }); diff --git a/test/parallel/test-tls-client-getephemeralkeyinfo.js b/test/parallel/test-tls-client-getephemeralkeyinfo.js index 4c1f791a7ed0f7..be6777b1ae0049 100644 --- a/test/parallel/test-tls-client-getephemeralkeyinfo.js +++ b/test/parallel/test-tls-client-getephemeralkeyinfo.js @@ -24,7 +24,7 @@ const cipherlist = { }; function test(size, type, name, next) { - const cipher = type ? cipherlist[type] : cipherlist['NOT_PFS']; + const cipher = type ? cipherlist[type] : cipherlist.NOT_PFS; if (name) tls.DEFAULT_ECDH_CURVE = name; diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 49ef4e0ecd4189..b2c8207de54c83 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -285,7 +285,7 @@ assert.strictEqual( '{ writeonly: [Setter] }'); const value = {}; - value['a'] = value; + value.a = value; assert.strictEqual(util.inspect(value), '{ a: [Circular] }'); } diff --git a/test/sequential/test-init.js b/test/sequential/test-init.js index 1f1679b5e149f8..5dd8d9ab14ea4f 100644 --- a/test/sequential/test-init.js +++ b/test/sequential/test-init.js @@ -25,7 +25,7 @@ const assert = require('assert'); const child = require('child_process'); const fixtures = require('../common/fixtures'); -if (process.env['TEST_INIT']) { +if (process.env.TEST_INIT) { return process.stdout.write('Loaded successfully!'); } diff --git a/test/sequential/test-inspector-bindings.js b/test/sequential/test-inspector-bindings.js index b2140c11a3329a..bf97d8b5124e86 100644 --- a/test/sequential/test-inspector-bindings.js +++ b/test/sequential/test-inspector-bindings.js @@ -27,9 +27,9 @@ function checkScope(session, scopeId) { } function debuggerPausedCallback(session, notification) { - const params = notification['params']; - const callFrame = params['callFrames'][0]; - const scopeId = callFrame['scopeChain'][0]['object']['objectId']; + const params = notification.params; + const callFrame = params.callFrames[0]; + const scopeId = callFrame.scopeChain[0].object.objectId; checkScope(session, scopeId); } @@ -65,11 +65,11 @@ function testSampleDebugSession() { scopeCallback = function(error, result) { const i = cur++; let v, actual, expected; - for (v of result['result']) { - actual = v['value']['value']; - expected = expects[v['name']][i]; + for (v of result.result) { + actual = v.value.value; + expected = expects[v.name][i]; if (actual !== expected) { - failures.push(`Iteration ${i} variable: ${v['name']} ` + + failures.push(`Iteration ${i} variable: ${v.name} ` + `expected: ${expected} actual: ${actual}`); } } diff --git a/test/sequential/test-inspector-ip-detection.js b/test/sequential/test-inspector-ip-detection.js index a69a57f55fcbe3..14be5e6824a4a2 100644 --- a/test/sequential/test-inspector-ip-detection.js +++ b/test/sequential/test-inspector-ip-detection.js @@ -15,12 +15,12 @@ if (!ip) function checkIpAddress(ip, response) { const res = response[0]; - const wsUrl = res['webSocketDebuggerUrl']; + const wsUrl = res.webSocketDebuggerUrl; assert.ok(wsUrl); const match = wsUrl.match(/^ws:\/\/(.*):\d+\/(.*)/); assert.strictEqual(ip, match[1]); - assert.strictEqual(res['id'], match[2]); - assert.strictEqual(ip, res['devtoolsFrontendUrl'].match(/.*ws=(.*):\d+/)[1]); + assert.strictEqual(res.id, match[2]); + assert.strictEqual(ip, res.devtoolsFrontendUrl.match(/.*ws=(.*):\d+/)[1]); } function pickIPv4Address() { diff --git a/test/sequential/test-inspector.js b/test/sequential/test-inspector.js index c34c953006276a..23b4dcb9618a44 100644 --- a/test/sequential/test-inspector.js +++ b/test/sequential/test-inspector.js @@ -9,10 +9,10 @@ const { NodeInstance } = require('../common/inspector-helper.js'); function checkListResponse(response) { assert.strictEqual(1, response.length); - assert.ok(response[0]['devtoolsFrontendUrl']); + assert.ok(response[0].devtoolsFrontendUrl); assert.ok( /ws:\/\/127\.0\.0\.1:\d+\/[0-9A-Fa-f]{8}-/ - .test(response[0]['webSocketDebuggerUrl'])); + .test(response[0].webSocketDebuggerUrl)); } function checkVersion(response) { @@ -32,7 +32,7 @@ function checkBadPath(err) { } function checkException(message) { - assert.strictEqual(message['exceptionDetails'], undefined, + assert.strictEqual(message.exceptionDetails, undefined, 'An exception occurred during execution'); } @@ -45,10 +45,10 @@ function assertNoUrlsWhileConnected(response) { function assertScopeValues({ result }, expected) { const unmatched = new Set(Object.keys(expected)); for (const actual of result) { - const value = expected[actual['name']]; + const value = expected[actual.name]; if (value) { - assert.strictEqual(value, actual['value']['value']); - unmatched.delete(actual['name']); + assert.strictEqual(value, actual.value.value); + unmatched.delete(actual.name); } } if (unmatched.size) @@ -124,14 +124,14 @@ async function testBreakpoint(session) { } }); - assert.strictEqual(1002, result['value']); + assert.strictEqual(1002, result.value); result = (await session.send({ 'method': 'Runtime.evaluate', 'params': { 'expression': '5 * 5' } })).result; - assert.strictEqual(25, result['value']); + assert.strictEqual(25, result.value); } async function testI18NCharacters(session) { @@ -168,7 +168,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.strictEqual(result['result']['value'], true); + assert.strictEqual(result.result.value, true); // the global require has the same properties as a normal `require` result = await session.send( @@ -183,7 +183,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.strictEqual(result['result']['value'], true); + assert.strictEqual(result.result.value, true); // `require` twice returns the same value result = await session.send( { @@ -199,7 +199,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.strictEqual(result['result']['value'], true); + assert.strictEqual(result.result.value, true); // after require the module appears in require.cache result = await session.send( { @@ -211,7 +211,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.deepStrictEqual(JSON.parse(result['result']['value']), + assert.deepStrictEqual(JSON.parse(result.result.value), { old: 'yes' }); // remove module from require.cache result = await session.send( @@ -222,7 +222,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.strictEqual(result['result']['value'], true); + assert.strictEqual(result.result.value, true); // require again, should get fresh (empty) exports result = await session.send( { @@ -232,7 +232,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.deepStrictEqual(JSON.parse(result['result']['value']), {}); + assert.deepStrictEqual(JSON.parse(result.result.value), {}); // require 2nd module, exports an empty object result = await session.send( { @@ -242,7 +242,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.deepStrictEqual(JSON.parse(result['result']['value']), {}); + assert.deepStrictEqual(JSON.parse(result.result.value), {}); // both modules end up with the same module.parent result = await session.send( { @@ -257,7 +257,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.deepStrictEqual(JSON.parse(result['result']['value']), { + assert.deepStrictEqual(JSON.parse(result.result.value), { parentsEqual: true, parentId: '' }); @@ -274,7 +274,7 @@ async function testCommandLineAPI(session) { } }); checkException(result); - assert.notStrictEqual(result['result']['value'], + assert.notStrictEqual(result.result.value, ''); } From ff471da1a81b325508b265290f7b49649030f4a6 Mon Sep 17 00:00:00 2001 From: Sho Miyamoto Date: Wed, 14 Feb 2018 16:18:04 +0900 Subject: [PATCH 140/193] doc: fix a typo in util.isDeepStrictEqual PR-URL: https://github.com/nodejs/node/pull/18775 Reviewed-By: Weijia Wang Reviewed-By: Ruben Bridgewater Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Vse Mozhet Byt Reviewed-By: Luigi Pinca Reviewed-By: Roman Reiss --- doc/api/util.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/util.md b/doc/api/util.md index b5a3f51ad635f9..4201e7dfd2e0bf 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -627,7 +627,7 @@ added: v9.0.0 * `val2` {any} * Returns: {boolean} -Returns `true` if there is deep strict equality between `val` and `val2`. +Returns `true` if there is deep strict equality between `val1` and `val2`. Otherwise, returns `false`. See [`assert.deepStrictEqual()`][] for more information about deep strict From 9a18b0e668e136b75de4e7b92373193bbd50be08 Mon Sep 17 00:00:00 2001 From: Sho Miyamoto Date: Wed, 14 Feb 2018 16:17:14 +0900 Subject: [PATCH 141/193] doc: add missing `Returns` in fs & util PR-URL: https://github.com/nodejs/node/pull/18775 Reviewed-By: Weijia Wang Reviewed-By: Ruben Bridgewater Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Vse Mozhet Byt Reviewed-By: Luigi Pinca Reviewed-By: Roman Reiss --- doc/api/fs.md | 16 ++++++++++++++++ doc/api/util.md | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/doc/api/fs.md b/doc/api/fs.md index 2210d7ecb3b96f..15afc61e567efc 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1207,6 +1207,7 @@ changes: * `start` {integer} * `end` {integer} * `highWaterMark` {integer} +* Returns: {stream.Readable} Returns a new [`ReadStream`][] object. (See [Readable Streams][]). @@ -1282,6 +1283,7 @@ changes: * `mode` {integer} * `autoClose` {boolean} * `start` {integer} +* Returns: {stream.Writable} Returns a new [`WriteStream`][] object. (See [Writable Stream][]). @@ -1439,6 +1441,7 @@ changes: --> * `path` {string|Buffer|URL} +* Returns: {boolean} Synchronous version of [`fs.exists()`][]. Returns `true` if the path exists, `false` otherwise. @@ -1557,6 +1560,7 @@ added: v0.1.95 --> * `fd` {integer} +* Returns: {fs.Stats} Synchronous fstat(2). Returns an instance of [`fs.Stats`][]. @@ -1831,6 +1835,7 @@ changes: --> * `path` {string|Buffer|URL} +* Returns: {fs.Stats} Synchronous lstat(2). Returns an instance of [`fs.Stats`][]. @@ -1956,6 +1961,7 @@ added: v5.10.0 * `prefix` {string} * `options` {string|Object} * `encoding` {string} **Default:** `'utf8'` +* Returns: {string} The synchronous version of [`fs.mkdtemp()`][]. Returns the created folder path. @@ -2080,6 +2086,7 @@ changes: * `path` {string|Buffer|URL} * `flags` {string|number} * `mode` {integer} **Default:** `0o666` +* Returns: {number} Synchronous version of [`fs.open()`][]. Returns an integer representing the file descriptor. @@ -2170,6 +2177,7 @@ changes: * `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} **Default:** `'utf8'` +* Returns: {Array} An array of filenames Synchronous readdir(3). Returns an array of filenames excluding `'.'` and `'..'`. @@ -2270,6 +2278,7 @@ changes: * `options` {Object|string} * `encoding` {string|null} **Default:** `null` * `flag` {string} **Default:** `'r'` +* Returns: {string|Buffer} Synchronous version of [`fs.readFile()`][]. Returns the contents of the `path`. @@ -2330,6 +2339,7 @@ changes: * `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} **Default:** `'utf8'` +* Returns: {string|Buffer} Synchronous readlink(2). Returns the symbolic link's string value. @@ -2352,6 +2362,7 @@ changes: * `offset` {integer} * `length` {integer} * `position` {integer} +* Returns: {number} Synchronous version of [`fs.read()`][]. Returns the number of `bytesRead`. @@ -2462,6 +2473,7 @@ changes: * `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} **Default:** `'utf8'` +* Returns: {string|Buffer} Synchronously computes the canonical pathname by resolving `.`, `..` and symbolic links. @@ -2492,6 +2504,7 @@ added: v9.2.0 * `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} **Default:** `'utf8'` +* Returns: {string|Buffer} Synchronous realpath(3). @@ -2629,6 +2642,7 @@ changes: --> * `path` {string|Buffer|URL} +* Returns: {fs.Stats} Synchronous stat(2). Returns an instance of [`fs.Stats`][]. @@ -3194,6 +3208,7 @@ changes: * `offset` {integer} * `length` {integer} * `position` {integer} +* Returns: {number} ## fs.writeSync(fd, string[, position[, encoding]]) @@ -3547,18 +3547,18 @@ with an `Error` object. The following example checks if the file `/etc/passwd` can be read and written by the current process. ```js -fs.promises.access('/etc/passwd', fs.constants.R_OK | fs.constants.W_OK) +fsPromises.access('/etc/passwd', fs.constants.R_OK | fs.constants.W_OK) .then(() => console.log('can access')) .catch(() => console.error('cannot access')); ``` -Using `fs.promises.access()` to check for the accessibility of a file before -calling `fs.promises.open()` is not recommended. Doing so introduces a race +Using `fsPromises.access()` to check for the accessibility of a file before +calling `fsPromises.open()` is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible. -### fs.promises.appendFile(file, data[, options]) +### fsPromises.appendFile(file, data[, options]) @@ -3578,9 +3578,9 @@ resolved with no arguments upon success. If `options` is a string, then it specifies the encoding. The `file` may be specified as a `FileHandle` that has been opened -for appending (using `fs.promises.open()`). +for appending (using `fsPromises.open()`). -### fs.promises.chmod(path, mode) +### fsPromises.chmod(path, mode) @@ -3592,7 +3592,7 @@ added: REPLACEME Changes the permissions of a file then resolves the `Promise` with no arguments upon succces. -### fs.promises.chown(path, uid, gid) +### fsPromises.chown(path, uid, gid) @@ -3605,7 +3605,7 @@ added: REPLACEME Changes the ownership of a file then resolves the `Promise` with no arguments upon success. -### fs.promises.copyFile(src, dest[, flags]) +### fsPromises.copyFile(src, dest[, flags]) @@ -3632,7 +3632,7 @@ Example: const fs = require('fs'); // destination.txt will be created or overwritten by default. -fs.promises.copyFile('source.txt', 'destination.txt') +fsPromises.copyFile('source.txt', 'destination.txt') .then(() => console.log('source.txt was copied to destination.txt')) .catch(() => console.log('The file could not be copied')); ``` @@ -3645,12 +3645,12 @@ const fs = require('fs'); const { COPYFILE_EXCL } = fs.constants; // By using COPYFILE_EXCL, the operation will fail if destination.txt exists. -fs.promises.copyFile('source.txt', 'destination.txt', COPYFILE_EXCL) +fsPromises.copyFile('source.txt', 'destination.txt', COPYFILE_EXCL) .then(() => console.log('source.txt was copied to destination.txt')) .catch(() => console.log('The file could not be copied')); ``` -### fs.promises.fchmod(filehandle, mode) +### fsPromises.fchmod(filehandle, mode) @@ -3662,7 +3662,7 @@ added: REPLACEME Asynchronous fchmod(2). The `Promise` is resolved with no arguments upon success. -### fs.promises.fchown(filehandle, uid, gid) +### fsPromises.fchown(filehandle, uid, gid) @@ -3675,7 +3675,7 @@ added: REPLACEME Changes the ownership of the file represented by `filehandle` then resolves the `Promise` with no arguments upon success. -### fs.promises.fdatasync(filehandle) +### fsPromises.fdatasync(filehandle) @@ -3686,7 +3686,7 @@ added: REPLACEME Asynchronous fdatasync(2). The `Promise` is resolved with no arguments upon success. -### fs.promises.fstat(filehandle) +### fsPromises.fstat(filehandle) @@ -3696,7 +3696,7 @@ added: REPLACEME Retrieves the [`fs.Stats`][] for the given `filehandle`. -### fs.promises.fsync(filehandle) +### fsPromises.fsync(filehandle) @@ -3707,7 +3707,7 @@ added: REPLACEME Asynchronous fsync(2). The `Promise` is resolved with no arguments upon success. -### fs.promises.ftruncate(filehandle[, len]) +### fsPromises.ftruncate(filehandle[, len]) @@ -3730,8 +3730,8 @@ console.log(fs.readFileSync('temp.txt', 'utf8')); // Prints: Node.js async function doTruncate() { - const fd = await fs.promises.open('temp.txt', 'r+'); - await fs.promises.ftruncate(fd, 4); + const fd = await fsPromises.open('temp.txt', 'r+'); + await fsPromises.ftruncate(fd, 4); console.log(fs.readFileSync('temp.txt', 'utf8')); // Prints: Node } @@ -3746,8 +3746,8 @@ console.log(fs.readFileSync('temp.txt', 'utf8')); // Prints: Node.js async function doTruncate() { - const fd = await fs.promises.open('temp.txt', 'r+'); - await fs.promises.ftruncate(fd, 10); + const fd = await fsPromises.open('temp.txt', 'r+'); + await fsPromises.ftruncate(fd, 10); console.log(fs.readFileSync('temp.txt', 'utf8')); // Prints Node.js\0\0\0 } @@ -3756,7 +3756,7 @@ doTruncate().catch(console.error); The last three bytes are null bytes ('\0'), to compensate the over-truncation. -### fs.promises.futimes(filehandle, atime, mtime) +### fsPromises.futimes(filehandle, atime, mtime) @@ -3772,7 +3772,7 @@ Change the file system timestamps of the object referenced by the supplied This function does not work on AIX versions before 7.1, it will resolve the `Promise` with an error using code `UV_ENOSYS`. -### fs.promises.lchmod(path, mode) +### fsPromises.lchmod(path, mode) @@ -3784,7 +3784,7 @@ deprecated: REPLACEME Changes the permissions on a symbolic link then resolves the `Promise` with no arguments upon success. This method is only implemented on macOS. -### fs.promises.lchown(path, uid, gid) +### fsPromises.lchown(path, uid, gid) @@ -3797,7 +3797,7 @@ deprecated: REPLACEME Changes the ownership on a symbolic link then resolves the `Promise` with no arguments upon success. This method is only implemented on macOS. -### fs.promises.link(existingPath, newPath) +### fsPromises.link(existingPath, newPath) @@ -3808,7 +3808,7 @@ added: REPLACEME Asynchronous link(2). The `Promise` is resolved with no arguments upon success. -### fs.promises.lstat(path) +### fsPromises.lstat(path) @@ -3819,7 +3819,7 @@ added: REPLACEME Asynchronous lstat(2). The `Promise` is resolved with the [`fs.Stats`][] object for the given symbolic link `path`. -### fs.promises.mkdir(path[, mode]) +### fsPromises.mkdir(path[, mode]) @@ -3831,7 +3831,7 @@ added: REPLACEME Asynchronously creates a directory then resolves the `Promise` with no arguments upon success. -### fs.promises.mkdtemp(prefix[, options]) +### fsPromises.mkdtemp(prefix[, options]) @@ -3851,7 +3851,7 @@ object with an `encoding` property specifying the character encoding to use. Example: ```js -fs.promises.mkdtemp(path.join(os.tmpdir(), 'foo-')) +fsPromises.mkdtemp(path.join(os.tmpdir(), 'foo-')) .catch(console.error); ``` @@ -3861,7 +3861,7 @@ intention is to create a temporary directory *within* `/tmp`, the `prefix` *must* end with a trailing platform-specific path separator (`require('path').sep`). -### fs.promises.open(path, flags[, mode]) +### fsPromises.open(path, flags[, mode]) @@ -3889,7 +3889,7 @@ An exception occurs if the file does not exist. the potentially stale local cache. It has a very real impact on I/O performance so using this flag is not recommended unless it is needed. - Note that this does not turn `fs.promises.open()` into a synchronous blocking + Note that this does not turn `fsPromises.open()` into a synchronous blocking call. * `'w'` - Open file for writing. @@ -3929,7 +3929,7 @@ On Linux, positional writes don't work when the file is opened in append mode. The kernel ignores the position argument and always appends the data to the end of the file. -The behavior of `fs.promises.open()` is platform-specific for some +The behavior of `fsPromises.open()` is platform-specific for some flags. As such, opening a directory on macOS and Linux with the `'a+'` flag will return an error. In contrast, on Windows and FreeBSD, a `FileHandle` will be returned. @@ -3940,11 +3940,11 @@ a colon, Node.js will open a file system stream, as described by [this MSDN page][MSDN-Using-Streams]. *Note:* On Windows, opening an existing hidden file using the `w` flag (e.g. -using `fs.promises.open()`) will fail with `EPERM`. Existing hidden +using `fsPromises.open()`) will fail with `EPERM`. Existing hidden files can be opened for writing with the `r+` flag. A call to -`fs.promises.ftruncate()` can be used to reset the file contents. +`fsPromises.ftruncate()` can be used to reset the file contents. -### fs.promises.read(filehandle, buffer, offset, length, position) +### fsPromises.read(filehandle, buffer, offset, length, position) @@ -3973,7 +3973,7 @@ Following successful read, the `Promise` is resolved with an object with a `bytesRead` property specifying the number of bytes read, and a `buffer` property that is a reference to the passed in `buffer` argument. -### fs.promises.readdir(path[, options]) +### fsPromises.readdir(path[, options]) @@ -3991,7 +3991,7 @@ object with an `encoding` property specifying the character encoding to use for the filenames. If the `encoding` is set to `'buffer'`, the filenames returned will be passed as `Buffer` objects. -### fs.promises.readFile(path[, options]) +### fsPromises.readFile(path[, options]) @@ -4010,14 +4010,14 @@ object. Otherwise, the data will be a string. If `options` is a string, then it specifies the encoding. -When the `path` is a directory, the behavior of `fs.promises.readFile()` is +When the `path` is a directory, the behavior of `fsPromises.readFile()` is platform-specific. On macOS, Linux, and Windows, the promise will be rejected with an error. On FreeBSD, a representation of the directory's contents will be returned. Any specified `FileHandle` has to support reading. -### fs.promises.readlink(path[, options]) +### fsPromises.readlink(path[, options]) @@ -4035,7 +4035,7 @@ object with an `encoding` property specifying the character encoding to use for the link path returned. If the `encoding` is set to `'buffer'`, the link path returned will be passed as a `Buffer` object. -### fs.promises.realpath(path[, options]) +### fsPromises.realpath(path[, options]) @@ -4060,7 +4060,7 @@ On Linux, when Node.js is linked against musl libc, the procfs file system must be mounted on `/proc` in order for this function to work. Glibc does not have this restriction. -### fs.promises.rename(oldPath, newPath) +### fsPromises.rename(oldPath, newPath) @@ -4072,7 +4072,7 @@ added: REPLACEME Renames `oldPath` to `newPath` and resolves the `Promise` with no arguments upon success. -### fs.promises.rmdir(path) +### fsPromises.rmdir(path) @@ -4083,11 +4083,11 @@ added: REPLACEME Removes the directory identified by `path` then resolves the `Promise` with no arguments upon success. -Using `fs.promises.rmdir()` on a file (not a directory) results in the +Using `fsPromises.rmdir()` on a file (not a directory) results in the `Promise` being rejected with an `ENOENT` error on Windows and an `ENOTDIR` error on POSIX. -### fs.promises.stat(path) +### fsPromises.stat(path) @@ -4097,7 +4097,7 @@ added: REPLACEME The `Promise` is resolved with the [`fs.Stats`][] object for the given `path`. -### fs.promises.symlink(target, path[, type]) +### fsPromises.symlink(target, path[, type]) @@ -4115,7 +4115,7 @@ The `type` argument is only used on Windows platforms and can be one of `'dir'`, points require the destination path to be absolute. When using `'junction'`, the `target` argument will automatically be normalized to absolute path. -### fs.promises.truncate(path[, len]) +### fsPromises.truncate(path[, len]) @@ -4127,7 +4127,7 @@ added: REPLACEME Truncates the `path` then resolves the `Promise` with no arguments upon success. The `path` *must* be a string or `Buffer`. -### fs.promises.unlink(path) +### fsPromises.unlink(path) @@ -4138,7 +4138,7 @@ added: REPLACEME Asynchronous unlink(2). The `Promise` is resolved with no arguments upon success. -### fs.promises.utimes(path, atime, mtime) +### fsPromises.utimes(path, atime, mtime) @@ -4157,7 +4157,7 @@ The `atime` and `mtime` arguments follow these rules: - If the value can not be converted to a number, or is `NaN`, `Infinity` or `-Infinity`, an `Error` will be thrown. -### fs.promises.write(filehandle, buffer[, offset[, length[, position]]]) +### fsPromises.write(filehandle, buffer[, offset[, length[, position]]]) @@ -4182,7 +4182,7 @@ an integer specifying the number of bytes to write. should be written. If `typeof position !== 'number'`, the data will be written at the current position. See pwrite(2). -It is unsafe to use `fs.promises.write()` multiple times on the same file +It is unsafe to use `fsPromises.write()` multiple times on the same file without waiting for the `Promise` to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended. @@ -4190,7 +4190,7 @@ On Linux, positional writes do not work when the file is opened in append mode. The kernel ignores the position argument and always appends the data to the end of the file. -### fs.promises.writeFile(file, data[, options]) +### fsPromises.writeFile(file, data[, options]) @@ -4214,7 +4214,7 @@ If `options` is a string, then it specifies the encoding. Any specified `FileHandle` has to support writing. -It is unsafe to use `fs.promises.writeFile()` multiple times on the same file +It is unsafe to use `fsPromises.writeFile()` multiple times on the same file without waiting for the `Promise` to be resolved (or rejected). diff --git a/lib/fs.js b/lib/fs.js index f78703762975b9..92e8d4fe3e2d43 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -72,9 +72,6 @@ Object.defineProperty(exports, 'constants', { value: constants }); -const kHandle = Symbol('handle'); -const { kUsePromises } = binding; - const kMinPoolSpace = 128; const { kMaxLength } = require('buffer'); @@ -2284,459 +2281,3 @@ Object.defineProperty(fs, 'SyncWriteStream', { set: internalUtil.deprecate((val) => { SyncWriteStream = val; }, 'fs.SyncWriteStream is deprecated.', 'DEP0061') }); - -// Promises API - -class FileHandle { - constructor(filehandle) { - this[kHandle] = filehandle; - } - - getAsyncId() { - return this[kHandle].getAsyncId(); - } - - get fd() { - return this[kHandle].fd; - } - - appendFile(data, options) { - return promises.appendFile(this, data, options); - } - - chmod(mode) { - return promises.fchmod(this, mode); - } - - chown(uid, gid) { - return promises.fchown(this, uid, gid); - } - - datasync() { - return promises.fdatasync(this); - } - - sync() { - return promises.fsync(this); - } - - - read(buffer, offset, length, position) { - return promises.read(this, buffer, offset, length, position); - } - - readFile(options) { - return promises.readFile(this, options); - } - - stat() { - return promises.fstat(this); - } - - truncate(len = 0) { - return promises.ftruncate(this, len); - } - - utimes(atime, mtime) { - return promises.futimes(this, atime, mtime); - } - - write(buffer, offset, length, position) { - return promises.write(this, buffer, offset, length, position); - } - - writeFile(data, options) { - return promises.writeFile(this, data, options); - } - - close() { - return this[kHandle].close(); - } -} - - -function validateFileHandle(handle) { - if (!(handle instanceof FileHandle)) - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', - 'filehandle', 'FileHandle'); -} - -async function writeFileHandle(filehandle, data, options) { - let buffer = isUint8Array(data) ? - data : Buffer.from('' + data, options.encoding || 'utf8'); - let remaining = buffer.length; - if (remaining === 0) return; - do { - const { bytesWritten } = - await promises.write(filehandle, buffer, 0, - Math.min(16384, buffer.length)); - remaining -= bytesWritten; - buffer = buffer.slice(bytesWritten); - } while (remaining > 0); -} - -async function readFileHandle(filehandle, options) { - const statFields = await binding.fstat(filehandle.fd, kUsePromises); - - let size; - if ((statFields[1/*mode*/] & S_IFMT) === S_IFREG) { - size = statFields[8/*size*/]; - } else { - size = 0; - } - - if (size === 0) - return Buffer.alloc(0); - - if (size > kMaxLength) - throw new errors.RangeError('ERR_BUFFER_TOO_LARGE'); - - const chunks = []; - const chunkSize = Math.min(size, 16384); - const buf = Buffer.alloc(chunkSize); - let read = 0; - do { - const { bytesRead, buffer } = - await promises.read(filehandle, buf, 0, buf.length); - read = bytesRead; - if (read > 0) - chunks.push(buffer.slice(0, read)); - } while (read === chunkSize); - - return Buffer.concat(chunks); -} - -// All of the functions in fs.promises are defined as async in order to -// ensure that errors thrown cause promise rejections rather than being -// thrown synchronously -const promises = { - async access(path, mode = fs.F_OK) { - path = getPathFromURL(path); - validatePath(path); - - mode = mode | 0; - return binding.access(pathModule.toNamespacedPath(path), mode, - kUsePromises); - }, - - async copyFile(src, dest, flags) { - src = getPathFromURL(src); - dest = getPathFromURL(dest); - validatePath(src, 'src'); - validatePath(dest, 'dest'); - flags = flags | 0; - return binding.copyFile(pathModule.toNamespacedPath(src), - pathModule.toNamespacedPath(dest), - flags, kUsePromises); - }, - - // Note that unlike fs.open() which uses numeric file descriptors, - // promises.open() uses the fs.FileHandle class. - async open(path, flags, mode) { - mode = modeNum(mode, 0o666); - path = getPathFromURL(path); - validatePath(path); - validateUint32(mode, 'mode'); - return new FileHandle( - await binding.openFileHandle(pathModule.toNamespacedPath(path), - stringToFlags(flags), - mode, kUsePromises)); - }, - - async read(handle, buffer, offset, length, position) { - validateFileHandle(handle); - validateBuffer(buffer); - - offset |= 0; - length |= 0; - - if (length === 0) - return { bytesRead: length, buffer }; - - validateOffsetLengthRead(offset, length, buffer.length); - - if (!isUint32(position)) - position = -1; - - const bytesRead = (await binding.read(handle.fd, buffer, offset, length, - position, kUsePromises)) || 0; - - return { bytesRead, buffer }; - }, - - async write(handle, buffer, offset, length, position) { - validateFileHandle(handle); - - if (buffer.length === 0) - return { bytesWritten: 0, buffer }; - - if (isUint8Array(buffer)) { - if (typeof offset !== 'number') - offset = 0; - if (typeof length !== 'number') - length = buffer.length - offset; - if (typeof position !== 'number') - position = null; - validateOffsetLengthWrite(offset, length, buffer.byteLength); - const bytesWritten = - (await binding.writeBuffer(handle.fd, buffer, offset, - length, position, kUsePromises)) || 0; - return { bytesWritten, buffer }; - } - - if (typeof buffer !== 'string') - buffer += ''; - if (typeof position !== 'function') { - if (typeof offset === 'function') { - position = offset; - offset = null; - } else { - position = length; - } - length = 'utf8'; - } - const bytesWritten = (await binding.writeString(handle.fd, buffer, offset, - length, kUsePromises)) || 0; - return { bytesWritten, buffer }; - }, - - async rename(oldPath, newPath) { - oldPath = getPathFromURL(oldPath); - newPath = getPathFromURL(newPath); - validatePath(oldPath, 'oldPath'); - validatePath(newPath, 'newPath'); - return binding.rename(pathModule.toNamespacedPath(oldPath), - pathModule.toNamespacedPath(newPath), - kUsePromises); - }, - - async truncate(path, len = 0) { - return promises.ftruncate(await promises.open(path, 'r+'), len); - }, - - async ftruncate(handle, len = 0) { - validateFileHandle(handle); - validateLen(len); - len = Math.max(0, len); - return binding.ftruncate(handle.fd, len, kUsePromises); - }, - - async rmdir(path) { - path = getPathFromURL(path); - validatePath(path); - return binding.rmdir(pathModule.toNamespacedPath(path), kUsePromises); - }, - - async fdatasync(handle) { - validateFileHandle(handle); - return binding.fdatasync(handle.fd, kUsePromises); - }, - - async fsync(handle) { - validateFileHandle(handle); - return binding.fsync(handle.fd, kUsePromises); - }, - - async mkdir(path, mode) { - mode = modeNum(mode, 0o777); - path = getPathFromURL(path); - validatePath(path); - validateUint32(mode, 'mode'); - return binding.mkdir(pathModule.toNamespacedPath(path), mode, kUsePromises); - }, - - async readdir(path, options) { - options = getOptions(options, {}); - path = getPathFromURL(path); - validatePath(path); - return binding.readdir(pathModule.toNamespacedPath(path), - options.encoding, kUsePromises); - }, - - async readlink(path, options) { - options = getOptions(options, {}); - path = getPathFromURL(path); - validatePath(path, 'oldPath'); - return binding.readlink(pathModule.toNamespacedPath(path), - options.encoding, kUsePromises); - }, - - async symlink(target, path, type_) { - const type = (typeof type_ === 'string' ? type_ : null); - target = getPathFromURL(target); - path = getPathFromURL(path); - validatePath(target, 'target'); - validatePath(path); - return binding.symlink(preprocessSymlinkDestination(target, type, path), - pathModule.toNamespacedPath(path), - stringToSymlinkType(type), - kUsePromises); - }, - - async fstat(handle) { - validateFileHandle(handle); - return statsFromValues(await binding.fstat(handle.fd, kUsePromises)); - }, - - async lstat(path) { - path = getPathFromURL(path); - validatePath(path); - return statsFromValues( - await binding.lstat(pathModule.toNamespacedPath(path), kUsePromises)); - }, - - async stat(path) { - path = getPathFromURL(path); - validatePath(path); - return statsFromValues( - await binding.stat(pathModule.toNamespacedPath(path), kUsePromises)); - }, - - async link(existingPath, newPath) { - existingPath = getPathFromURL(existingPath); - newPath = getPathFromURL(newPath); - validatePath(existingPath, 'existingPath'); - validatePath(newPath, 'newPath'); - return binding.link(pathModule.toNamespacedPath(existingPath), - pathModule.toNamespacedPath(newPath), - kUsePromises); - }, - - async unlink(path) { - path = getPathFromURL(path); - validatePath(path); - return binding.unlink(pathModule.toNamespacedPath(path), kUsePromises); - }, - - async fchmod(handle, mode) { - mode = modeNum(mode); - validateFileHandle(handle); - validateUint32(mode, 'mode'); - if (mode < 0 || mode > 0o777) - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'mode'); - return binding.fchmod(handle.fd, mode, kUsePromises); - }, - - async chmod(path, mode) { - path = getPathFromURL(path); - validatePath(path); - mode = modeNum(mode); - validateUint32(mode, 'mode'); - return binding.chmod(pathModule.toNamespacedPath(path), mode, kUsePromises); - }, - - async lchmod(path, mode) { - if (constants.O_SYMLINK !== undefined) { - const fd = await promises.open(path, - constants.O_WRONLY | constants.O_SYMLINK); - return promises.fchmod(fd, mode).finally(fd.close.bind(fd)); - } - throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED'); - }, - - async lchown(path, uid, gid) { - if (constants.O_SYMLINK !== undefined) { - const fd = await promises.open(path, - constants.O_WRONLY | constants.O_SYMLINK); - return promises.fchown(fd, uid, gid).finally(fd.close.bind(fd)); - } - throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED'); - }, - - async fchown(handle, uid, gid) { - validateFileHandle(handle); - validateUint32(uid, 'uid'); - validateUint32(gid, 'gid'); - return binding.fchown(handle.fd, uid, gid, kUsePromises); - }, - - async chown(path, uid, gid) { - path = getPathFromURL(path); - validatePath(path); - validateUint32(uid, 'uid'); - validateUint32(gid, 'gid'); - return binding.chown(pathModule.toNamespacedPath(path), - uid, gid, kUsePromises); - }, - - async utimes(path, atime, mtime) { - path = getPathFromURL(path); - validatePath(path); - return binding.utimes(pathModule.toNamespacedPath(path), - toUnixTimestamp(atime), - toUnixTimestamp(mtime), - kUsePromises); - }, - - async futimes(handle, atime, mtime) { - validateFileHandle(handle); - atime = toUnixTimestamp(atime, 'atime'); - mtime = toUnixTimestamp(mtime, 'mtime'); - return binding.futimes(handle.fd, atime, mtime, kUsePromises); - }, - - async realpath(path, options) { - options = getOptions(options, {}); - path = getPathFromURL(path); - validatePath(path); - return binding.realpath(path, options.encoding, kUsePromises); - }, - - async mkdtemp(prefix, options) { - options = getOptions(options, {}); - if (!prefix || typeof prefix !== 'string') { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', - 'prefix', - 'string', - prefix); - } - nullCheck(prefix); - return binding.mkdtemp(`${prefix}XXXXXX`, options.encoding, kUsePromises); - }, - - async writeFile(path, data, options) { - options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' }); - const flag = options.flag || 'w'; - - if (path instanceof FileHandle) - return writeFileHandle(path, data, options); - - const fd = await promises.open(path, flag, options.mode); - return writeFileHandle(fd, data, options).finally(fd.close.bind(fd)); - }, - - async appendFile(path, data, options) { - options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'a' }); - options = copyObject(options); - options.flag = options.flag || 'a'; - return promises.writeFile(path, data, options); - }, - - async readFile(path, options) { - options = getOptions(options, { flag: 'r' }); - - if (path instanceof FileHandle) - return readFileHandle(path, options); - - const fd = await promises.open(path, options.flag, 0o666); - return readFileHandle(fd, options).finally(fd.close.bind(fd)); - } -}; - -let warn = true; - -// TODO(jasnell): Exposing this as a property with a getter works fine with -// commonjs but is going to be problematic for named imports support under -// ESM. A different approach will have to be followed there. -Object.defineProperty(fs, 'promises', { - configurable: true, - enumerable: true, - get() { - if (warn) { - warn = false; - process.emitWarning('The fs.promises API is experimental', - 'ExperimentalWarning'); - } - return promises; - } -}); diff --git a/lib/fs/promises.js b/lib/fs/promises.js new file mode 100644 index 00000000000000..8cbcd963c772c8 --- /dev/null +++ b/lib/fs/promises.js @@ -0,0 +1,507 @@ +'use strict'; + +process.emitWarning('The fs/promises API is experimental', + 'ExperimentalWarning'); + +const { + F_OK, + O_SYMLINK, + O_WRONLY, + S_IFMT, + S_IFREG +} = process.binding('constants').fs; +const binding = process.binding('fs'); +const { Buffer, kMaxLength } = require('buffer'); +const errors = require('internal/errors'); +const { getPathFromURL } = require('internal/url'); +const { isUint8Array } = require('internal/util/types'); +const { + copyObject, + getOptions, + isUint32, + modeNum, + nullCheck, + preprocessSymlinkDestination, + statsFromValues, + stringToFlags, + stringToSymlinkType, + toUnixTimestamp, + validateBuffer, + validateLen, + validateOffsetLengthRead, + validateOffsetLengthWrite, + validatePath, + validateUint32 +} = require('internal/fs'); +const pathModule = require('path'); + +const kHandle = Symbol('handle'); +const { kUsePromises } = binding; + +class FileHandle { + constructor(filehandle) { + this[kHandle] = filehandle; + } + + getAsyncId() { + return this[kHandle].getAsyncId(); + } + + get fd() { + return this[kHandle].fd; + } + + appendFile(data, options) { + return appendFile(this, data, options); + } + + chmod(mode) { + return fchmod(this, mode); + } + + chown(uid, gid) { + return fchown(this, uid, gid); + } + + datasync() { + return fdatasync(this); + } + + sync() { + return fsync(this); + } + + read(buffer, offset, length, position) { + return read(this, buffer, offset, length, position); + } + + readFile(options) { + return readFile(this, options); + } + + stat() { + return fstat(this); + } + + truncate(len = 0) { + return ftruncate(this, len); + } + + utimes(atime, mtime) { + return futimes(this, atime, mtime); + } + + write(buffer, offset, length, position) { + return write(this, buffer, offset, length, position); + } + + writeFile(data, options) { + return writeFile(this, data, options); + } + + close() { + return this[kHandle].close(); + } +} + + +function validateFileHandle(handle) { + if (!(handle instanceof FileHandle)) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', + 'filehandle', 'FileHandle'); +} + +async function writeFileHandle(filehandle, data, options) { + let buffer = isUint8Array(data) ? + data : Buffer.from('' + data, options.encoding || 'utf8'); + let remaining = buffer.length; + if (remaining === 0) return; + do { + const { bytesWritten } = + await write(filehandle, buffer, 0, + Math.min(16384, buffer.length)); + remaining -= bytesWritten; + buffer = buffer.slice(bytesWritten); + } while (remaining > 0); +} + +async function readFileHandle(filehandle, options) { + const statFields = await binding.fstat(filehandle.fd, kUsePromises); + + let size; + if ((statFields[1/*mode*/] & S_IFMT) === S_IFREG) { + size = statFields[8/*size*/]; + } else { + size = 0; + } + + if (size === 0) + return Buffer.alloc(0); + + if (size > kMaxLength) + throw new errors.RangeError('ERR_BUFFER_TOO_LARGE'); + + const chunks = []; + const chunkSize = Math.min(size, 16384); + const buf = Buffer.alloc(chunkSize); + let totalRead = 0; + do { + const { bytesRead, buffer } = + await read(filehandle, buf, 0, buf.length); + totalRead = bytesRead; + if (totalRead > 0) + chunks.push(buffer.slice(0, totalRead)); + } while (totalRead === chunkSize); + + return Buffer.concat(chunks); +} + +// All of the functions are defined as async in order to ensure that errors +// thrown cause promise rejections rather than being thrown synchronously. +async function access(path, mode = F_OK) { + path = getPathFromURL(path); + validatePath(path); + + mode = mode | 0; + return binding.access(pathModule.toNamespacedPath(path), mode, + kUsePromises); +} + +async function copyFile(src, dest, flags) { + src = getPathFromURL(src); + dest = getPathFromURL(dest); + validatePath(src, 'src'); + validatePath(dest, 'dest'); + flags = flags | 0; + return binding.copyFile(pathModule.toNamespacedPath(src), + pathModule.toNamespacedPath(dest), + flags, kUsePromises); +} + +// Note that unlike fs.open() which uses numeric file descriptors, +// fsPromises.open() uses the fs.FileHandle class. +async function open(path, flags, mode) { + mode = modeNum(mode, 0o666); + path = getPathFromURL(path); + validatePath(path); + validateUint32(mode, 'mode'); + return new FileHandle( + await binding.openFileHandle(pathModule.toNamespacedPath(path), + stringToFlags(flags), + mode, kUsePromises)); +} + +async function read(handle, buffer, offset, length, position) { + validateFileHandle(handle); + validateBuffer(buffer); + + offset |= 0; + length |= 0; + + if (length === 0) + return { bytesRead: length, buffer }; + + validateOffsetLengthRead(offset, length, buffer.length); + + if (!isUint32(position)) + position = -1; + + const bytesRead = (await binding.read(handle.fd, buffer, offset, length, + position, kUsePromises)) || 0; + + return { bytesRead, buffer }; +} + +async function write(handle, buffer, offset, length, position) { + validateFileHandle(handle); + + if (buffer.length === 0) + return { bytesWritten: 0, buffer }; + + if (isUint8Array(buffer)) { + if (typeof offset !== 'number') + offset = 0; + if (typeof length !== 'number') + length = buffer.length - offset; + if (typeof position !== 'number') + position = null; + validateOffsetLengthWrite(offset, length, buffer.byteLength); + const bytesWritten = + (await binding.writeBuffer(handle.fd, buffer, offset, + length, position, kUsePromises)) || 0; + return { bytesWritten, buffer }; + } + + if (typeof buffer !== 'string') + buffer += ''; + if (typeof position !== 'function') { + if (typeof offset === 'function') { + position = offset; + offset = null; + } else { + position = length; + } + length = 'utf8'; + } + const bytesWritten = (await binding.writeString(handle.fd, buffer, offset, + length, kUsePromises)) || 0; + return { bytesWritten, buffer }; +} + +async function rename(oldPath, newPath) { + oldPath = getPathFromURL(oldPath); + newPath = getPathFromURL(newPath); + validatePath(oldPath, 'oldPath'); + validatePath(newPath, 'newPath'); + return binding.rename(pathModule.toNamespacedPath(oldPath), + pathModule.toNamespacedPath(newPath), + kUsePromises); +} + +async function truncate(path, len = 0) { + return ftruncate(await open(path, 'r+'), len); +} + +async function ftruncate(handle, len = 0) { + validateFileHandle(handle); + validateLen(len); + len = Math.max(0, len); + return binding.ftruncate(handle.fd, len, kUsePromises); +} + +async function rmdir(path) { + path = getPathFromURL(path); + validatePath(path); + return binding.rmdir(pathModule.toNamespacedPath(path), kUsePromises); +} + +async function fdatasync(handle) { + validateFileHandle(handle); + return binding.fdatasync(handle.fd, kUsePromises); +} + +async function fsync(handle) { + validateFileHandle(handle); + return binding.fsync(handle.fd, kUsePromises); +} + +async function mkdir(path, mode) { + mode = modeNum(mode, 0o777); + path = getPathFromURL(path); + validatePath(path); + validateUint32(mode, 'mode'); + return binding.mkdir(pathModule.toNamespacedPath(path), mode, kUsePromises); +} + +async function readdir(path, options) { + options = getOptions(options, {}); + path = getPathFromURL(path); + validatePath(path); + return binding.readdir(pathModule.toNamespacedPath(path), + options.encoding, kUsePromises); +} + +async function readlink(path, options) { + options = getOptions(options, {}); + path = getPathFromURL(path); + validatePath(path, 'oldPath'); + return binding.readlink(pathModule.toNamespacedPath(path), + options.encoding, kUsePromises); +} + +async function symlink(target, path, type_) { + const type = (typeof type_ === 'string' ? type_ : null); + target = getPathFromURL(target); + path = getPathFromURL(path); + validatePath(target, 'target'); + validatePath(path); + return binding.symlink(preprocessSymlinkDestination(target, type, path), + pathModule.toNamespacedPath(path), + stringToSymlinkType(type), + kUsePromises); +} + +async function fstat(handle) { + validateFileHandle(handle); + return statsFromValues(await binding.fstat(handle.fd, kUsePromises)); +} + +async function lstat(path) { + path = getPathFromURL(path); + validatePath(path); + return statsFromValues( + await binding.lstat(pathModule.toNamespacedPath(path), kUsePromises)); +} + +async function stat(path) { + path = getPathFromURL(path); + validatePath(path); + return statsFromValues( + await binding.stat(pathModule.toNamespacedPath(path), kUsePromises)); +} + +async function link(existingPath, newPath) { + existingPath = getPathFromURL(existingPath); + newPath = getPathFromURL(newPath); + validatePath(existingPath, 'existingPath'); + validatePath(newPath, 'newPath'); + return binding.link(pathModule.toNamespacedPath(existingPath), + pathModule.toNamespacedPath(newPath), + kUsePromises); +} + +async function unlink(path) { + path = getPathFromURL(path); + validatePath(path); + return binding.unlink(pathModule.toNamespacedPath(path), kUsePromises); +} + +async function fchmod(handle, mode) { + mode = modeNum(mode); + validateFileHandle(handle); + validateUint32(mode, 'mode'); + if (mode < 0 || mode > 0o777) + throw new errors.RangeError('ERR_OUT_OF_RANGE', 'mode'); + return binding.fchmod(handle.fd, mode, kUsePromises); +} + +async function chmod(path, mode) { + path = getPathFromURL(path); + validatePath(path); + mode = modeNum(mode); + validateUint32(mode, 'mode'); + return binding.chmod(pathModule.toNamespacedPath(path), mode, kUsePromises); +} + +async function lchmod(path, mode) { + if (O_SYMLINK !== undefined) { + const fd = await open(path, + O_WRONLY | O_SYMLINK); + return fchmod(fd, mode).finally(fd.close.bind(fd)); + } + throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED'); +} + +async function lchown(path, uid, gid) { + if (O_SYMLINK !== undefined) { + const fd = await open(path, + O_WRONLY | O_SYMLINK); + return fchmod(fd, uid, gid).finally(fd.close.bind(fd)); + } + throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED'); +} + +async function fchown(handle, uid, gid) { + validateFileHandle(handle); + validateUint32(uid, 'uid'); + validateUint32(gid, 'gid'); + return binding.fchown(handle.fd, uid, gid, kUsePromises); +} + +async function chown(path, uid, gid) { + path = getPathFromURL(path); + validatePath(path); + validateUint32(uid, 'uid'); + validateUint32(gid, 'gid'); + return binding.chown(pathModule.toNamespacedPath(path), + uid, gid, kUsePromises); +} + +async function utimes(path, atime, mtime) { + path = getPathFromURL(path); + validatePath(path); + return binding.utimes(pathModule.toNamespacedPath(path), + toUnixTimestamp(atime), + toUnixTimestamp(mtime), + kUsePromises); +} + +async function futimes(handle, atime, mtime) { + validateFileHandle(handle); + atime = toUnixTimestamp(atime, 'atime'); + mtime = toUnixTimestamp(mtime, 'mtime'); + return binding.futimes(handle.fd, atime, mtime, kUsePromises); +} + +async function realpath(path, options) { + options = getOptions(options, {}); + path = getPathFromURL(path); + validatePath(path); + return binding.realpath(path, options.encoding, kUsePromises); +} + +async function mkdtemp(prefix, options) { + options = getOptions(options, {}); + if (!prefix || typeof prefix !== 'string') { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', + 'prefix', + 'string', + prefix); + } + nullCheck(prefix); + return binding.mkdtemp(`${prefix}XXXXXX`, options.encoding, kUsePromises); +} + +async function writeFile(path, data, options) { + options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' }); + const flag = options.flag || 'w'; + + if (path instanceof FileHandle) + return writeFileHandle(path, data, options); + + const fd = await open(path, flag, options.mode); + return writeFileHandle(fd, data, options).finally(fd.close.bind(fd)); +} + +async function appendFile(path, data, options) { + options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'a' }); + options = copyObject(options); + options.flag = options.flag || 'a'; + return writeFile(path, data, options); +} + +async function readFile(path, options) { + options = getOptions(options, { flag: 'r' }); + + if (path instanceof FileHandle) + return readFileHandle(path, options); + + const fd = await open(path, options.flag, 0o666); + return readFileHandle(fd, options).finally(fd.close.bind(fd)); +} + +module.exports = { + access, + copyFile, + open, + read, + write, + rename, + truncate, + ftruncate, + rmdir, + fdatasync, + fsync, + mkdir, + readdir, + readlink, + symlink, + fstat, + lstat, + stat, + link, + unlink, + fchmod, + chmod, + lchmod, + lchown, + fchown, + chown, + utimes, + futimes, + realpath, + mkdtemp, + writeFile, + appendFile, + readFile +}; diff --git a/node.gyp b/node.gyp index 8e41cc053d4a78..08eee428560770 100644 --- a/node.gyp +++ b/node.gyp @@ -39,6 +39,7 @@ 'lib/domain.js', 'lib/events.js', 'lib/fs.js', + 'lib/fs/promises.js', 'lib/http.js', 'lib/http2.js', 'lib/_http_agent.js', diff --git a/test/parallel/test-fs-promises-writefile.js b/test/parallel/test-fs-promises-writefile.js index 655dc73a1dfdb5..e2ae289b180bc2 100644 --- a/test/parallel/test-fs-promises-writefile.js +++ b/test/parallel/test-fs-promises-writefile.js @@ -2,6 +2,7 @@ const common = require('../common'); const fs = require('fs'); +const fsPromises = require('fs/promises'); const path = require('path'); const tmpdir = require('../common/tmpdir'); const assert = require('assert'); @@ -16,20 +17,20 @@ const buffer = Buffer.from('abc'.repeat(1000)); const buffer2 = Buffer.from('xyz'.repeat(1000)); async function doWrite() { - await fs.promises.writeFile(dest, buffer); + await fsPromises.writeFile(dest, buffer); const data = fs.readFileSync(dest); assert.deepStrictEqual(data, buffer); } async function doAppend() { - await fs.promises.appendFile(dest, buffer2); + await fsPromises.appendFile(dest, buffer2); const data = fs.readFileSync(dest); const buf = Buffer.concat([buffer, buffer2]); assert.deepStrictEqual(buf, data); } async function doRead() { - const data = await fs.promises.readFile(dest); + const data = await fsPromises.readFile(dest); const buf = fs.readFileSync(dest); assert.deepStrictEqual(buf, data); } diff --git a/test/parallel/test-fs-promises.js b/test/parallel/test-fs-promises.js index 5d493208ff85cb..e24374602bfc3f 100644 --- a/test/parallel/test-fs-promises.js +++ b/test/parallel/test-fs-promises.js @@ -5,7 +5,7 @@ const assert = require('assert'); const tmpdir = require('../common/tmpdir'); const fixtures = require('../common/fixtures'); const path = require('path'); -const fs = require('fs'); +const fsPromises = require('fs/promises'); const { access, chmod, @@ -32,7 +32,7 @@ const { write, unlink, utimes -} = fs.promises; +} = fsPromises; const tmpDir = tmpdir.path; diff --git a/test/sequential/test-async-wrap-getasyncid.js b/test/sequential/test-async-wrap-getasyncid.js index 2db6ba9db661cf..1877d53dbfd3ae 100644 --- a/test/sequential/test-async-wrap-getasyncid.js +++ b/test/sequential/test-async-wrap-getasyncid.js @@ -3,6 +3,7 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); +const fsPromises = require('fs/promises'); const net = require('net'); const providers = Object.assign({}, process.binding('async_wrap').Providers); const fixtures = require('../common/fixtures'); @@ -171,7 +172,7 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check { async function openTest() { - const fd = await fs.promises.open(__filename, 'r'); + const fd = await fsPromises.open(__filename, 'r'); testInitialized(fd, 'FileHandle'); await fd.close(); } From 38f04d4da179dd3610ee07c2441601cdb2436a6a Mon Sep 17 00:00:00 2001 From: killagu Date: Sun, 11 Feb 2018 11:50:31 +0800 Subject: [PATCH 156/193] tools, test: fix prof polyfill readline `node --prof foo.js` may not print the full profile log file, leaving the last line broken (for example `tick,`. When that happens, `readline` will be stuck in an infinite loop. This patch fixes it. Also introduced `common.isCPPSymbolsNotMapped` to avoid duplicated code on tick-processor tests. PR-URL: https://github.com/nodejs/node/pull/18641 Reviewed-By: Khaidi Chu Reviewed-By: Matheus Marchini Reviewed-By: Ruben Bridgewater --- lib/internal/v8_prof_polyfill.js | 7 +++ test/common/README.md | 5 ++ test/common/index.js | 5 ++ .../test-tick-processor-builtin.js | 7 +-- .../test-tick-processor-cpp-core.js | 7 +-- ...test-tick-processor-polyfill-brokenfile.js | 62 +++++++++++++++++++ .../test-tick-processor-preprocess-flag.js | 7 +-- 7 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 test/tick-processor/test-tick-processor-polyfill-brokenfile.js diff --git a/lib/internal/v8_prof_polyfill.js b/lib/internal/v8_prof_polyfill.js index 5c6b1407120ea2..43ccc0e5d8bfac 100644 --- a/lib/internal/v8_prof_polyfill.js +++ b/lib/internal/v8_prof_polyfill.js @@ -96,6 +96,13 @@ function readline() { if (line.length === 0) { return ''; } + if (bytes === 0) { + process.emitWarning(`Profile file ${logFile} is broken`, { + code: 'BROKEN_PROFILE_FILE', + detail: `${JSON.stringify(line)} at the file end is broken` + }); + return ''; + } } } diff --git a/test/common/README.md b/test/common/README.md index 18f0e4915b19d2..e0a66e9da0c2c9 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -243,6 +243,11 @@ Platform check for Windows. Platform check for Windows 32-bit on Windows 64-bit. +### isCPPSymbolsNotMapped +* [<Boolean>] + +Platform check for C++ symbols are mapped or not. + ### leakedGlobals() * return [<Array>] diff --git a/test/common/index.js b/test/common/index.js index a38b9852086f2f..b24d2158e7d089 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -803,3 +803,8 @@ exports.hijackStdout = hijackStdWritable.bind(null, 'stdout'); exports.hijackStderr = hijackStdWritable.bind(null, 'stderr'); exports.restoreStdout = restoreWritable.bind(null, 'stdout'); exports.restoreStderr = restoreWritable.bind(null, 'stderr'); +exports.isCPPSymbolsNotMapped = exports.isWindows || + exports.isSunOS || + exports.isAIX || + exports.isLinuxPPCBE || + exports.isFreeBSD; diff --git a/test/tick-processor/test-tick-processor-builtin.js b/test/tick-processor/test-tick-processor-builtin.js index f94964813ac76a..3d4e1b9d236030 100644 --- a/test/tick-processor/test-tick-processor-builtin.js +++ b/test/tick-processor/test-tick-processor-builtin.js @@ -4,12 +4,9 @@ const common = require('../common'); if (!common.enoughTestCpu) common.skip('test is CPU-intensive'); -if (common.isWindows || - common.isSunOS || - common.isAIX || - common.isLinuxPPCBE || - common.isFreeBSD) +if (common.isCPPSymbolsNotMapped) { common.skip('C++ symbols are not mapped for this os.'); +} const base = require('./tick-processor-base.js'); diff --git a/test/tick-processor/test-tick-processor-cpp-core.js b/test/tick-processor/test-tick-processor-cpp-core.js index 76407433ea55bc..26daf60aa3c1ce 100644 --- a/test/tick-processor/test-tick-processor-cpp-core.js +++ b/test/tick-processor/test-tick-processor-cpp-core.js @@ -4,12 +4,9 @@ const common = require('../common'); if (!common.enoughTestCpu) common.skip('test is CPU-intensive'); -if (common.isWindows || - common.isSunOS || - common.isAIX || - common.isLinuxPPCBE || - common.isFreeBSD) +if (common.isCPPSymbolsNotMapped) { common.skip('C++ symbols are not mapped for this os.'); +} const base = require('./tick-processor-base.js'); diff --git a/test/tick-processor/test-tick-processor-polyfill-brokenfile.js b/test/tick-processor/test-tick-processor-polyfill-brokenfile.js new file mode 100644 index 00000000000000..3348b6f11b2e67 --- /dev/null +++ b/test/tick-processor/test-tick-processor-polyfill-brokenfile.js @@ -0,0 +1,62 @@ +'use strict'; +const common = require('../common'); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +if (!common.enoughTestCpu) + common.skip('test is CPU-intensive'); + +if (common.isCPPSymbolsNotMapped) { + common.skip('C++ symbols are not mapped for this OS.'); +} + +// This test will produce a broken profile log. +// ensure prof-polyfill not stuck in infinite loop +// and success process + + +const assert = require('assert'); +const cp = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +const LOG_FILE = path.join(tmpdir.path, 'tick-processor.log'); +const RETRY_TIMEOUT = 150; +const BROKEN_PART = 'tick,'; +const WARN_REG_EXP = /\(node:\d+\) \[BROKEN_PROFILE_FILE] Warning: Profile file .* is broken/; +const WARN_DETAIL_REG_EXP = /".*tick," at the file end is broken/; + +const code = `function f() { + this.ts = Date.now(); + setImmediate(function() { new f(); }); + }; + f();`; + +const proc = cp.spawn(process.execPath, [ + '--no_logfile_per_isolate', + '--logfile=-', + '--prof', + '-pe', code +], { + stdio: ['ignore', 'pipe', 'inherit'] +}); + +let ticks = ''; +proc.stdout.on('data', (chunk) => ticks += chunk); + + +function runPolyfill(content) { + proc.kill(); + content += BROKEN_PART; + fs.writeFileSync(LOG_FILE, content); + const child = cp.spawnSync( + `${process.execPath}`, + [ + '--prof-process', LOG_FILE + ]); + assert(WARN_REG_EXP.test(child.stderr.toString())); + assert(WARN_DETAIL_REG_EXP.test(child.stderr.toString())); + assert.strictEqual(child.status, 0); +} + +setTimeout(() => runPolyfill(ticks), RETRY_TIMEOUT); diff --git a/test/tick-processor/test-tick-processor-preprocess-flag.js b/test/tick-processor/test-tick-processor-preprocess-flag.js index 17e89f581218fb..93367361aceea3 100644 --- a/test/tick-processor/test-tick-processor-preprocess-flag.js +++ b/test/tick-processor/test-tick-processor-preprocess-flag.js @@ -4,12 +4,9 @@ const common = require('../common'); if (!common.enoughTestCpu) common.skip('test is CPU-intensive'); -if (common.isWindows || - common.isSunOS || - common.isAIX || - common.isLinuxPPCBE || - common.isFreeBSD) +if (common.isCPPSymbolsNotMapped) { common.skip('C++ symbols are not mapped for this os.'); +} const base = require('./tick-processor-base.js'); From 99d693da5c1b753d15fb7c744de0c4cb87098c93 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 7 Feb 2018 10:42:26 -0500 Subject: [PATCH 157/193] lib: replace `eval` with `vm.runInThisContext` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18623 Refs: https://github.com/nodejs/node/pull/18212#pullrequestreview-94616927 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- lib/internal/v8_prof_processor.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/internal/v8_prof_processor.js b/lib/internal/v8_prof_processor.js index 9c63430f964917..0d9cfd6df4d12a 100644 --- a/lib/internal/v8_prof_processor.js +++ b/lib/internal/v8_prof_processor.js @@ -1,4 +1,7 @@ -/* eslint-disable strict */ +'use strict'; + +const vm = require('vm'); + const scriptFiles = [ 'internal/v8_prof_polyfill', 'internal/deps/v8/tools/splaytree', @@ -31,9 +34,9 @@ if (process.platform === 'darwin') { tickArguments.push('--windows'); } tickArguments.push.apply(tickArguments, process.argv.slice(1)); -script = `(function() { +script = `(function(require) { arguments = ${JSON.stringify(tickArguments)}; function write (s) { process.stdout.write(s) } ${script} -})()`; -eval(script); +})`; +vm.runInThisContext(script)(require); From 590eacecaabe282eb602d49ba0b25d1a266a7609 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 11 Feb 2018 03:08:21 +0100 Subject: [PATCH 158/193] net: simplify net.Socket#end() `writable` is already set by the streams side, and there is a handler waiting for the writable side to finish which already takes care of the other cleanup code that was previously there; both of these things can therefore be removed. PR-URL: https://github.com/nodejs/node/pull/18708 Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Matteo Collina --- lib/net.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/net.js b/lib/net.js index 9c7986ceb7086e..ed2ea2dc27739b 100644 --- a/lib/net.js +++ b/lib/net.js @@ -525,18 +525,10 @@ Socket.prototype._read = function(n) { }; -Socket.prototype.end = function(data, encoding) { - stream.Duplex.prototype.end.call(this, data, encoding); - this.writable = false; +Socket.prototype.end = function(data, encoding, callback) { + stream.Duplex.prototype.end.call(this, data, encoding, callback); DTRACE_NET_STREAM_END(this); LTTNG_NET_STREAM_END(this); - - // just in case we're waiting for an EOF. - if (this.readable && !this._readableState.endEmitted) - this.read(0); - else - maybeDestroy(this); - return this; }; From b404aa56c0e776c9722017ca020f9d04c7aa6de2 Mon Sep 17 00:00:00 2001 From: Sergey Golovin Date: Sat, 10 Feb 2018 14:02:13 +0300 Subject: [PATCH 159/193] path: replace duplicate conditions by functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will also remove useless "code" variables by inlining path.charCodeAt. PR-URL: https://github.com/nodejs/node/pull/18693 Reviewed-By: Ben Noordhuis Reviewed-By: Tobias Nießen Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Jon Moss Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- lib/path.js | 187 +++++++++++++++++++++------------------------------- 1 file changed, 76 insertions(+), 111 deletions(-) diff --git a/lib/path.js b/lib/path.js index 248809b2e2f70b..098416adfe1a3a 100644 --- a/lib/path.js +++ b/lib/path.js @@ -40,6 +40,15 @@ function assertPath(path) { } } +function isPathSeparator(code) { + return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; +} + +function isWindowsDeviceRoot(code) { + return code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z || + code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z; +} + // Resolves . and .. elements in a path with directory names function normalizeStringWin32(path, allowAboveRoot) { var res = ''; @@ -50,11 +59,12 @@ function normalizeStringWin32(path, allowAboveRoot) { for (var i = 0; i <= path.length; ++i) { if (i < path.length) code = path.charCodeAt(i); - else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + else if (isPathSeparator(code)) break; else code = CHAR_FORWARD_SLASH; - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + + if (isPathSeparator(code)) { if (lastSlash === i - 1 || dots === 1) { // NOOP } else if (lastSlash !== i - 1 && dots === 2) { @@ -228,28 +238,26 @@ const win32 = { var len = path.length; var rootEnd = 0; - var code = path.charCodeAt(0); var device = ''; var isAbsolute = false; + const code = path.charCodeAt(0); // Try to match a root if (len > 1) { - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(code)) { // Possible UNC root // If we started with a separator, we know we at least have an // absolute path of some kind (UNC or otherwise) isAbsolute = true; - code = path.charCodeAt(1); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(1))) { // Matched double path separator at beginning var j = 2; var last = j; // Match 1 or more non-path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(j))) break; } if (j < len && j !== last) { @@ -258,8 +266,7 @@ const win32 = { last = j; // Match 1 or more path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) + if (!isPathSeparator(path.charCodeAt(j))) break; } if (j < len && j !== last) { @@ -267,11 +274,7 @@ const win32 = { last = j; // Match 1 or more non-path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - const isPathSeparator = - code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; - - if (isPathSeparator) + if (isPathSeparator(path.charCodeAt(j))) break; } if (j === len) { @@ -290,16 +293,14 @@ const win32 = { } else { rootEnd = 1; } - } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || - (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { + } else if (isWindowsDeviceRoot(code)) { // Possible device root if (path.charCodeAt(1) === CHAR_COLON) { device = path.slice(0, 2); rootEnd = 2; if (len > 2) { - code = path.charCodeAt(2); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(2))) { // Treat separator following drive name as an absolute path // indicator isAbsolute = true; @@ -308,7 +309,7 @@ const win32 = { } } } - } else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + } else if (isPathSeparator(code)) { // `path` contains just a path separator rootEnd = 1; isAbsolute = true; @@ -351,28 +352,26 @@ const win32 = { if (len === 0) return '.'; var rootEnd = 0; - var code = path.charCodeAt(0); var device; var isAbsolute = false; + const code = path.charCodeAt(0); // Try to match a root if (len > 1) { - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(code)) { // Possible UNC root // If we started with a separator, we know we at least have an absolute // path of some kind (UNC or otherwise) isAbsolute = true; - code = path.charCodeAt(1); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(1))) { // Matched double path separator at beginning var j = 2; var last = j; // Match 1 or more non-path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(j))) break; } if (j < len && j !== last) { @@ -381,8 +380,7 @@ const win32 = { last = j; // Match 1 or more path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) + if (!isPathSeparator(path.charCodeAt(j))) break; } if (j < len && j !== last) { @@ -390,8 +388,7 @@ const win32 = { last = j; // Match 1 or more non-path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(j))) break; } if (j === len) { @@ -411,16 +408,14 @@ const win32 = { } else { rootEnd = 1; } - } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || - (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { + } else if (isWindowsDeviceRoot(code)) { // Possible device root if (path.charCodeAt(1) === CHAR_COLON) { device = path.slice(0, 2); rootEnd = 2; if (len > 2) { - code = path.charCodeAt(2); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(2))) { // Treat separator following drive name as an absolute path // indicator isAbsolute = true; @@ -429,15 +424,12 @@ const win32 = { } } } - } else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + } else if (isPathSeparator(code)) { // `path` contains just a path separator, exit early to avoid unnecessary // work return '\\'; } - code = path.charCodeAt(len - 1); - var trailingSeparator = - (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH); var tail; if (rootEnd < len) tail = normalizeStringWin32(path.slice(rootEnd), !isAbsolute); @@ -445,7 +437,7 @@ const win32 = { tail = ''; if (tail.length === 0 && !isAbsolute) tail = '.'; - if (tail.length > 0 && trailingSeparator) + if (tail.length > 0 && isPathSeparator(path.charCodeAt(len - 1))) tail += '\\'; if (device === undefined) { if (isAbsolute) { @@ -476,16 +468,15 @@ const win32 = { const len = path.length; if (len === 0) return false; - var code = path.charCodeAt(0); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + + const code = path.charCodeAt(0); + if (isPathSeparator(code)) { return true; - } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || - (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { + } else if (isWindowsDeviceRoot(code)) { // Possible device root if (len > 2 && path.charCodeAt(1) === CHAR_COLON) { - code = path.charCodeAt(2); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(2))) return true; } } @@ -528,17 +519,14 @@ const win32 = { // path.join('//server', 'share') -> '\\\\server\\share\\') var needsReplace = true; var slashCount = 0; - var code = firstPart.charCodeAt(0); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(firstPart.charCodeAt(0))) { ++slashCount; const firstLen = firstPart.length; if (firstLen > 1) { - code = firstPart.charCodeAt(1); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(firstPart.charCodeAt(1))) { ++slashCount; if (firstLen > 2) { - code = firstPart.charCodeAt(2); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(firstPart.charCodeAt(2))) ++slashCount; else { // We matched a UNC path in the first part @@ -551,8 +539,7 @@ const win32 = { if (needsReplace) { // Find any more consecutive slashes we need to replace for (; slashCount < joined.length; ++slashCount) { - code = joined.charCodeAt(slashCount); - if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) + if (!isPathSeparator(joined.charCodeAt(slashCount))) break; } @@ -699,19 +686,17 @@ const win32 = { const resolvedPath = win32.resolve(path); if (resolvedPath.length >= 3) { - var code = resolvedPath.charCodeAt(0); - if (code === CHAR_BACKWARD_SLASH) { + if (resolvedPath.charCodeAt(0) === CHAR_BACKWARD_SLASH) { // Possible UNC root if (resolvedPath.charCodeAt(1) === CHAR_BACKWARD_SLASH) { - code = resolvedPath.charCodeAt(2); + const code = resolvedPath.charCodeAt(2); if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) { // Matched non-long UNC root, convert the path to a long UNC path return '\\\\?\\UNC\\' + resolvedPath.slice(2); } } - } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || - (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { + } else if (isWindowsDeviceRoot(resolvedPath.charCodeAt(0))) { // Possible device root if (resolvedPath.charCodeAt(1) === CHAR_COLON && @@ -734,24 +719,22 @@ const win32 = { var end = -1; var matchedSlash = true; var offset = 0; - var code = path.charCodeAt(0); + const code = path.charCodeAt(0); // Try to match a root if (len > 1) { - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(code)) { // Possible UNC root rootEnd = offset = 1; - code = path.charCodeAt(1); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(1))) { // Matched double path separator at beginning var j = 2; var last = j; // Match 1 or more non-path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(j))) break; } if (j < len && j !== last) { @@ -759,8 +742,7 @@ const win32 = { last = j; // Match 1 or more path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) + if (!isPathSeparator(path.charCodeAt(j))) break; } if (j < len && j !== last) { @@ -768,8 +750,7 @@ const win32 = { last = j; // Match 1 or more non-path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(j))) break; } if (j === len) { @@ -786,28 +767,25 @@ const win32 = { } } } - } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || - (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { + } else if (isWindowsDeviceRoot(code)) { // Possible device root if (path.charCodeAt(1) === CHAR_COLON) { rootEnd = offset = 2; if (len > 2) { - code = path.charCodeAt(2); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(2))) rootEnd = offset = 3; } } } - } else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + } else if (isPathSeparator(code)) { // `path` contains just a path separator, exit early to avoid // unnecessary work return path; } for (var i = len - 1; i >= offset; --i) { - code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(i))) { if (!matchedSlash) { end = i; break; @@ -842,8 +820,7 @@ const win32 = { // disregarded if (path.length >= 2) { const drive = path.charCodeAt(0); - if ((drive >= CHAR_UPPERCASE_A && drive <= CHAR_UPPERCASE_Z) || - (drive >= CHAR_LOWERCASE_A && drive <= CHAR_LOWERCASE_Z)) { + if (isWindowsDeviceRoot(drive)) { if (path.charCodeAt(1) === CHAR_COLON) start = 2; } @@ -856,7 +833,7 @@ const win32 = { var firstNonSlashEnd = -1; for (i = path.length - 1; i >= start; --i) { const code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(code)) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -895,8 +872,7 @@ const win32 = { return path.slice(start, end); } else { for (i = path.length - 1; i >= start; --i) { - const code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(i))) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -932,18 +908,16 @@ const win32 = { // Check for a drive letter prefix so as not to mistake the following // path separator as an extra separator at the end of the path that can be // disregarded - if (path.length >= 2) { - const code = path.charCodeAt(0); - if (path.charCodeAt(1) === CHAR_COLON && - ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || - (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z))) { - start = startPart = 2; - } + + if (path.length >= 2 && + path.charCodeAt(1) === CHAR_COLON && + isWindowsDeviceRoot(path.charCodeAt(0))) { + start = startPart = 2; } for (var i = path.length - 1; i >= start; --i) { const code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(code)) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -1003,23 +977,21 @@ const win32 = { var len = path.length; var rootEnd = 0; - var code = path.charCodeAt(0); + let code = path.charCodeAt(0); // Try to match a root if (len > 1) { - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(code)) { // Possible UNC root - code = path.charCodeAt(1); rootEnd = 1; - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(1))) { // Matched double path separator at beginning var j = 2; var last = j; // Match 1 or more non-path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(j))) break; } if (j < len && j !== last) { @@ -1027,8 +999,7 @@ const win32 = { last = j; // Match 1 or more path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code !== CHAR_FORWARD_SLASH && code !== CHAR_BACKWARD_SLASH) + if (!isPathSeparator(path.charCodeAt(j))) break; } if (j < len && j !== last) { @@ -1036,8 +1007,7 @@ const win32 = { last = j; // Match 1 or more non-path separators for (; j < len; ++j) { - code = path.charCodeAt(j); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) + if (isPathSeparator(path.charCodeAt(j))) break; } if (j === len) { @@ -1052,15 +1022,13 @@ const win32 = { } } } - } else if ((code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || - (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z)) { + } else if (isWindowsDeviceRoot(code)) { // Possible device root if (path.charCodeAt(1) === CHAR_COLON) { rootEnd = 2; if (len > 2) { - code = path.charCodeAt(2); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(path.charCodeAt(2))) { if (len === 3) { // `path` contains just a drive root, exit early to avoid // unnecessary work @@ -1077,7 +1045,7 @@ const win32 = { } } } - } else if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + } else if (isPathSeparator(code)) { // `path` contains just a path separator, exit early to avoid // unnecessary work ret.root = ret.dir = path; @@ -1100,7 +1068,7 @@ const win32 = { // Get non-dir info for (; i >= rootEnd; --i) { code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH) { + if (isPathSeparator(code)) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { @@ -1363,13 +1331,11 @@ const posix = { assertPath(path); if (path.length === 0) return '.'; - var code = path.charCodeAt(0); - var hasRoot = (code === CHAR_FORWARD_SLASH); + const hasRoot = path.charCodeAt(0) === CHAR_FORWARD_SLASH; var end = -1; var matchedSlash = true; for (var i = path.length - 1; i >= 1; --i) { - code = path.charCodeAt(i); - if (code === CHAR_FORWARD_SLASH) { + if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { if (!matchedSlash) { end = i; break; @@ -1534,8 +1500,7 @@ const posix = { var ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) return ret; - var code = path.charCodeAt(0); - var isAbsolute = (code === CHAR_FORWARD_SLASH); + var isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; var start; if (isAbsolute) { ret.root = '/'; @@ -1555,7 +1520,7 @@ const posix = { // Get non-dir info for (; i >= start; --i) { - code = path.charCodeAt(i); + const code = path.charCodeAt(i); if (code === CHAR_FORWARD_SLASH) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now From 1bda746c1bf8f875cebb3a8948a57bbc75189240 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Wed, 7 Feb 2018 10:33:51 +0100 Subject: [PATCH 160/193] test: stdio pipe behavior tests Add two regression tests for stdio over pipes. test-stdio-pipe-access tests if accessing stdio pipe that is being read by another process does not deadlocks Node.js. This was reported in https://github.com/nodejs/node/issues/10836 and was fixed in v8.3.0. The deadlock would happen intermittently, so we run the test 5 times. test-stdio-pipe-redirect tests if redirecting one child process stdin to another process stdout does not crash Node as reported in https://github.com/nodejs/node/issues/17493. It was fixed in https://github.com/nodejs/node/pull/18019. PR-URL: https://github.com/nodejs/node/pull/18614 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- test/parallel/test-stdio-pipe-access.js | 35 +++++++++++++++++++++ test/parallel/test-stdio-pipe-redirect.js | 38 +++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 test/parallel/test-stdio-pipe-access.js create mode 100644 test/parallel/test-stdio-pipe-redirect.js diff --git a/test/parallel/test-stdio-pipe-access.js b/test/parallel/test-stdio-pipe-access.js new file mode 100644 index 00000000000000..ef84bb83803b26 --- /dev/null +++ b/test/parallel/test-stdio-pipe-access.js @@ -0,0 +1,35 @@ +'use strict'; +require('../common'); + +// Test if Node handles acessing process.stdin if it is a redirected +// pipe without deadlocking +const { spawn, spawnSync } = require('child_process'); + +const numTries = 5; +const who = process.argv.length <= 2 ? 'runner' : process.argv[2]; + +switch (who) { + case 'runner': + for (let num = 0; num < numTries; ++num) { + spawnSync(process.argv0, + [process.argv[1], 'parent'], + { 'stdio': 'inherit' }); + } + break; + case 'parent': + const middle = spawn(process.argv0, + [process.argv[1], 'middle'], + { 'stdio': 'pipe' }); + middle.stdout.on('data', () => {}); + break; + case 'middle': + spawn(process.argv0, + [process.argv[1], 'bottom'], + { 'stdio': [ process.stdin, + process.stdout, + process.stderr ] }); + break; + case 'bottom': + process.stdin; + break; +} diff --git a/test/parallel/test-stdio-pipe-redirect.js b/test/parallel/test-stdio-pipe-redirect.js new file mode 100644 index 00000000000000..b47f5b9cf44af5 --- /dev/null +++ b/test/parallel/test-stdio-pipe-redirect.js @@ -0,0 +1,38 @@ +'use strict'; +require('../common'); + +// Test if Node handles redirecting one child process stdout to another +// process stdin without crashing. +const spawn = require('child_process').spawn; + +const writeSize = 100; +const totalDots = 10000; + +const who = process.argv.length <= 2 ? 'parent' : process.argv[2]; + +switch (who) { + case 'parent': + const consumer = spawn(process.argv0, [process.argv[1], 'consumer'], { + stdio: ['pipe', 'ignore', 'inherit'], + }); + const producer = spawn(process.argv0, [process.argv[1], 'producer'], { + stdio: ['pipe', consumer.stdin, 'inherit'], + }); + process.stdin.on('data', () => {}); + producer.on('exit', process.exit); + break; + case 'producer': + const buffer = Buffer.alloc(writeSize, '.'); + let written = 0; + const write = () => { + if (written < totalDots) { + written += writeSize; + process.stdout.write(buffer, write); + } + }; + write(); + break; + case 'consumer': + process.stdin.on('data', () => {}); + break; +} From 2fbe15b82c33fac4d09624b071e5f59862fa1dee Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Fri, 16 Feb 2018 16:18:09 -0800 Subject: [PATCH 161/193] doc: fix minor typos in GOVERNANCE.md PR-URL: https://github.com/nodejs/node/pull/18829 Reviewed-By: Vse Mozhet Byt Reviewed-By: Jon Moss Reviewed-By: James M Snell Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca --- GOVERNANCE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 4f1ff30d83411c..23c1ac8bb5106e 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -38,7 +38,7 @@ responsibility for the change. In the case of pull requests proposed by an existing Collaborator, an additional Collaborator is required for sign-off. -If one or more Collaborators oppose a proposed change, then the change can not +If one or more Collaborators oppose a proposed change, then the change cannot be accepted unless: * Discussions and/or additional changes result in no Collaborators objecting to @@ -73,7 +73,7 @@ may request that the TSC restore them to active status. ## Technical Steering Committee -A subset of the Collaborators form the Technical Steering Committee (TSC). +A subset of the Collaborators forms the Technical Steering Committee (TSC). The TSC has final authority over this project, including: * Technical direction From 81232320aa09a5ed5d4203e6b7ed708fd3f6e91b Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Fri, 16 Feb 2018 17:49:56 -0500 Subject: [PATCH 162/193] deps: patch V8 to 6.4.388.46 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18827 Refs: https://github.com/v8/v8/compare/6.4.388.45...6.4.388.46 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/heap/spaces.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 8de6adcf2269e8..cb85da2cd72a30 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 4 #define V8_BUILD_NUMBER 388 -#define V8_PATCH_LEVEL 45 +#define V8_PATCH_LEVEL 46 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/heap/spaces.cc b/deps/v8/src/heap/spaces.cc index 7657e1e6ec29d8..c3663573b028ef 100644 --- a/deps/v8/src/heap/spaces.cc +++ b/deps/v8/src/heap/spaces.cc @@ -351,8 +351,8 @@ void MemoryAllocator::Unmapper::WaitUntilCompleted() { CancelableTaskManager::kTaskAborted) { pending_unmapping_tasks_semaphore_.Wait(); } - concurrent_unmapping_tasks_active_ = 0; } + concurrent_unmapping_tasks_active_ = 0; } template From 33103e97587b3efa073d00752864210b43c5fc4a Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Fri, 16 Feb 2018 15:46:48 +0100 Subject: [PATCH 163/193] test: refactor stream-*-constructor-set-methods - Use `common.mustCall()` to ensure that callbacks are called. - Remove no longer needed variables. - Remove unnecessary `process.on('exit')` usage. PR-URL: https://github.com/nodejs/node/pull/18817 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Jon Moss Reviewed-By: Colin Ihrig --- ...tream-transform-constructor-set-methods.js | 28 +++++----- ...stream-writable-constructor-set-methods.js | 52 ++++++++----------- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/test/parallel/test-stream-transform-constructor-set-methods.js b/test/parallel/test-stream-transform-constructor-set-methods.js index 31b4c6c9bd0509..14c173b4ccfec5 100644 --- a/test/parallel/test-stream-transform-constructor-set-methods.js +++ b/test/parallel/test-stream-transform-constructor-set-methods.js @@ -1,19 +1,19 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); -const Transform = require('stream').Transform; +const { strictEqual } = require('assert'); +const { Transform } = require('stream'); -const _transform = common.mustCall(function _transform(d, e, n) { - n(); +const _transform = common.mustCall((chunk, _, next) => { + next(); }); -const _final = common.mustCall(function _final(n) { - n(); +const _final = common.mustCall((next) => { + next(); }); -const _flush = common.mustCall(function _flush(n) { - n(); +const _flush = common.mustCall((next) => { + next(); }); const t = new Transform({ @@ -22,11 +22,15 @@ const t = new Transform({ final: _final }); -const t2 = new Transform({}); +strictEqual(t._transform, _transform); +strictEqual(t._flush, _flush); +strictEqual(t._final, _final); t.end(Buffer.from('blerg')); t.resume(); +const t2 = new Transform({}); + common.expectsError(() => { t2.end(Buffer.from('blerg')); }, { @@ -34,9 +38,3 @@ common.expectsError(() => { code: 'ERR_METHOD_NOT_IMPLEMENTED', message: 'The _transform method is not implemented' }); - -process.on('exit', () => { - assert.strictEqual(t._transform, _transform); - assert.strictEqual(t._flush, _flush); - assert.strictEqual(t._final, _final); -}); diff --git a/test/parallel/test-stream-writable-constructor-set-methods.js b/test/parallel/test-stream-writable-constructor-set-methods.js index 441e8ee75b337d..425cd88ed7a336 100644 --- a/test/parallel/test-stream-writable-constructor-set-methods.js +++ b/test/parallel/test-stream-writable-constructor-set-methods.js @@ -1,45 +1,37 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); -const Writable = require('stream').Writable; +const { strictEqual } = require('assert'); +const { Writable } = require('stream'); -let _writeCalled = false; -function _write(d, e, n) { - _writeCalled = true; -} +const _write = common.mustCall((chunk, _, next) => { + next(); +}); + +const _writev = common.mustCall((chunks, next) => { + strictEqual(chunks.length, 2); + next(); +}); -const w = new Writable({ write: _write }); -w.end(Buffer.from('blerg')); +const w = new Writable({ write: _write, writev: _writev }); -let _writevCalled = false; -let dLength = 0; -function _writev(d, n) { - dLength = d.length; - _writevCalled = true; -} +strictEqual(w._write, _write); +strictEqual(w._writev, _writev); -const w2 = new Writable({ writev: _writev }); -w2.cork(); +w.write(Buffer.from('blerg')); -w2.write(Buffer.from('blerg')); -w2.write(Buffer.from('blerg')); -w2.end(); +w.cork(); +w.write(Buffer.from('blerg')); +w.write(Buffer.from('blerg')); -const w3 = new Writable(); +w.end(); -w3.on('error', common.expectsError({ +const w2 = new Writable(); + +w2.on('error', common.expectsError({ type: Error, code: 'ERR_METHOD_NOT_IMPLEMENTED', message: 'The _write method is not implemented' })); -w3.end(Buffer.from('blerg')); - -process.on('exit', function() { - assert.strictEqual(w._write, _write); - assert(_writeCalled); - assert.strictEqual(w2._writev, _writev); - assert.strictEqual(dLength, 2); - assert(_writevCalled); -}); +w2.end(Buffer.from('blerg')); From ea1a07656ee6dcbbde5de9f228ae075a9eeb6fad Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Fri, 8 Dec 2017 11:56:53 +0100 Subject: [PATCH 164/193] doc: mark accessing IPC channel fd as undefined Adds note that accessing the fd of the IPC channel in any other way than process.send, or using the IPC channel with child processes that is not Node.js is not supported. PR-URL: https://github.com/nodejs/node/pull/17545 Reviewed-By: Matteo Collina Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- doc/api/child_process.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 768eb91a83de77..80b74929b03fdb 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -621,6 +621,10 @@ pipes between the parent and child. The value is one of the following: will enable [`process.send()`][], [`process.disconnect()`][], [`process.on('disconnect')`][], and [`process.on('message')`] within the child. + + Accessing the IPC channel fd in any way other than [`process.send()`][] + or using the IPC channel with a child process that is not a Node.js instance + is not supported. 3. `'ignore'` - Instructs Node.js to ignore the fd in the child. While Node.js will always open fds 0 - 2 for the processes it spawns, setting the fd to `'ignore'` will cause Node.js to open `/dev/null` and attach it to the From ef7f5a11e8d859fa959552676f7f7f241a78c5c6 Mon Sep 17 00:00:00 2001 From: Alhadis Date: Sun, 4 Feb 2018 00:16:50 +1100 Subject: [PATCH 165/193] doc: refactor manpage to use mdoc(7) macros Like man(7), mdoc(7) is a macro package for marking up computer manuals. The main difference is that mdoc is semantic rather than presentational, providing authors with a full DSL to abstract page markup from low-level Roff commands. By contrast, `man` is minimalist and leaves formatting to the author, who is expected to have a working amount of Roff knowledge. Therefore the use of `mdoc` for marking up Node's manpage is a decidedly better choice than bare `man`. Less room is left for error and mandoc(1) offers very robust error-checking and linting. PR-URL: https://github.com/nodejs/node/pull/18559 Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock --- doc/node.1 | 694 +++++++++++++++++++++++++++-------------------------- 1 file changed, 353 insertions(+), 341 deletions(-) diff --git a/doc/node.1 b/doc/node.1 index 836b901bead12d..26092d26520247 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -1,368 +1,380 @@ -.TH NODE 1 2016 Node.js Node.js - -.\" This is a man page comment. - -.\" Man page syntax (actually roff syntax) is somewhat obscure, but the -.\" important part is is that . specifies 's syntax for that -.\" line, and \f specifies it for the characters that follow. - -.\" .B Bold line -.\" .I Italic line (Rendered as underlined text in terminals) -.\" .BI Alternating bold/italics without spaces between arguments. -.\" Use `\ ` to include an "unpaddable" (literal) space in the output. -.\" .RI Alternating roman/italic - -.\" See http://liw.fi/manpages/ for an overview, or http://www.troff.org/54.pdf -.\" for detailed language reference. - -.\" Macro to display an underlined URL in bold -.de ur -.nr CF \\n(.f -.ft 4 -\\$1 -.ft \\n(CF -.. - - -.SH NAME - -node \- Server-side JavaScript runtime - - -.SH SYNOPSIS - -.B node -.RI [ options ] -.RI [ v8\ options ] -.RI [ script.js \ | -.B -e -.RI \&" script \&" -.RI | -.B - -.RI ] -.B [--] -.RI [ arguments ] -.br -.B node debug -.RI [ script.js " | " -.B \-e -.RI \&" script \&"\ | -.IR : ] -.I ... -.br -.B node -.RB [ \-\-v8-options ] - -Execute without arguments to start the REPL. - - -.SH DESCRIPTION - -Node.js is a set of libraries for JavaScript which allows it to be used outside -of the browser. It is primarily focused on creating simple, easy to build -network clients and servers. - - -.SH OPTIONS - -.TP -.BR \-v ", " \-\-version +.\" +.\" This manpage is written in mdoc(7). +.\" +.\" * Language reference: +.\" https://man.openbsd.org/mdoc.7 +.\" +.\" * Atom editor support: +.\" https://atom.io/packages/language-roff +.\" +.\" * Linting changes: +.\" mandoc -Wall -Tlint /path/to/this.file # BSD +.\" groff -w all -z /path/to/this.file # GNU/Linux, macOS +.\" +.\" +.\" Before making changes, please note the following: +.\" +.\" * In Roff, each new sentence should begin on a new line. This gives +.\" the Roff formatter better control over text-spacing, line-wrapping, +.\" and paragraph justification. +.\" +.\" * Do not leave blank lines in the markup. If whitespace is desired +.\" for readability, put a dot in the first column to indicate a null/empty +.\" command. Comments and horizontal whitespace may optionally follow: each +.\" of these lines are an example of a null command immediately followed by +.\" a comment. +.\" +.\"====================================================================== +. +.Dd 2018 +.Dt NODE 1 +. +.Sh NAME +.Nm node +.Nd server-side JavaScript runtime +. +.\"====================================================================== +.Sh SYNOPSIS +.Nm node +.Op Ar options +.Op Ar v8-options +.Op Fl e Ar string | Ar script.js | Fl +.Op Fl \- +.Op Ar arguments ... +. +.Nm node +.Cm debug +.Op Fl e Ar string | Ar script.js | Fl | Ar : +.Ar ... +. +.Nm node +.Op Fl -v8-options +. +.\"====================================================================== +.Sh DESCRIPTION +Node.js is a set of libraries for JavaScript which allows it to be used outside of the browser. +It is primarily focused on creating simple, easy-to-build network clients and servers. +.Pp +Execute +.Nm +without arguments to start a REPL. +. +.Sh OPTIONS +.Bl -tag -width 6n +.It Fl v , Fl -version Print node's version. - -.TP -.BR \-h ", " \-\-help +. +.It Fl h , Fl -help Print node command line options. The output of this option is less detailed than this document. - -.TP -.BR \-e ", " \-\-eval " " \fR"\fIscript\fR" -Evaluate the following argument as JavaScript. - -.TP -.BR \-p ", " \-\-print " " \fR"\fIscript\fR" -Identical to \fB-e\fR but prints the result. - -.TP -.BR \-c ", " \-\-check -Syntax check the script without executing. - -.TP -.BR \-i ", " \-\-interactive +. +.It Fl e , Fl -eval Ar string +Evaluate +.Ar string +as JavaScript. +. +.It Fl p , Fl -print Ar string +Identical to +.Fl e , +but prints the result. +. +.It Fl c , Fl -check +Check the script's syntax without executing it. +Exits with an error code if script is invalid. +. +.It Fl i , Fl -interactive Open the REPL even if stdin does not appear to be a terminal. - -.TP -.BR \-r ", " \-\-require " " \fImodule\fR -Preload the specified module at startup. Follows `require()`'s module resolution -rules. \fImodule\fR may be either a path to a file, or a node module name. - -.TP -.BR \-\-inspect \fI[=[host:]port]\fR -Activate inspector on host:port. Default is 127.0.0.1:9229. - -V8 Inspector integration allows attaching Chrome DevTools and IDEs to Node.js -instances for debugging and profiling. It uses the Chrome Debugging Protocol. - -.TP -.BR \-\-inspect-brk \fI[=[host:]port]\fR -Activate inspector on host:port and break at start of user script. - -.TP -.BR \-\-inspect-port \fI=[host:]port\fR -Set the host:port to be used when the inspector is activated. - -.TP -.BR \-\-no\-deprecation +. +.It Fl r , Fl -require Ar module +Preload the specified +.Ar module +at startup. +Follows `require()`'s module resolution rules. +.Ar module +may be either a path to a file, or a node module name. +. +.It Fl -inspect Ns = Ns Ar [host:]port +Activate inspector on +.Ar host:port . +Default is +.Sy 127.0.0.1:9229 . +.Pp +V8 Inspector integration allows attaching Chrome DevTools and IDEs to Node.js instances for debugging and profiling. +It uses the Chrome Debugging Protocol. +. +.It Fl -inspect-brk Ns = Ns Ar [host:]port +Activate inspector on +.Ar host:port +and break at start of user script. +. +.It Fl -inspect-port Ns = Ns Ar [host:]port +Set the +.Ar host:port +to be used when the inspector is activated. +. +.It Fl -no-deprecation Silence deprecation warnings. - -.TP -.BR \-\-trace\-deprecation +. +.It Fl -trace-deprecation Print stack traces for deprecations. - -.TP -.BR \-\-throw\-deprecation +. +.It Fl -throw-deprecation Throw errors for deprecations. - -.TP -.BR \-\-pending\-deprecation +. +.It Fl -pending-deprecation Emit pending deprecation warnings. - -.TP -.BR \-\-no\-warnings +. +.It Fl -no-warnings Silence all process warnings (including deprecations). - -.TP -.BR \-\-napi\-modules +. +.It Fl -napi-modules Enable loading native modules compiled with the ABI-stable Node.js API (N-API) (experimental). - -.TP -.BR \-\-abort\-on\-uncaught\-exception +. +.It Fl -abort-on-uncaught-exception Aborting instead of exiting causes a core file to be generated for analysis. - -.TP -.BR \-\-trace\-warnings +. +.It Fl -trace-warnings Print stack traces for process warnings (including deprecations). - -.TP -.BR \-\-redirect\-warnings=\fIfile\fR -Write process warnings to the given file instead of printing to stderr. - -.TP -.BR \-\-trace\-sync\-io -Print a stack trace whenever synchronous I/O is detected after the first turn -of the event loop. - -.TP -.BR \-\-no\-force\-async\-hooks\-checks -Disables runtime checks for `async_hooks`. These will still be enabled -dynamically when `async_hooks` is enabled. - -.TP -.BR \-\-trace\-events\-enabled -Enables the collection of trace event tracing information. - -.TP -.BR \-\-trace\-event\-categories " " \fIcategories\fR -A comma separated list of categories that should be traced when trace event -tracing is enabled using \fB--trace-events-enabled\fR. - -.TP -.BR \-\-zero\-fill\-buffers +. +.It Fl -redirect-warnings Ns = Ns Ar file +Write process warnings to the given +.Ar file +instead of printing to stderr. +. +.It Fl -trace-sync-io +Print a stack trace whenever synchronous I/O is detected after the first turn of the event loop. +. +.It Fl -no-force-async-hooks-checks +Disable runtime checks for `async_hooks`. +These will still be enabled dynamically when `async_hooks` is enabled. +. +.It Fl -trace-events-enabled +Enable the collection of trace event tracing information. +. +.It Fl -trace-event-categories Ar categories +A comma-separated list of categories that should be traced when trace event tracing is enabled using +.Fl -trace-events-enabled . +. +.It Fl -zero-fill-buffers Automatically zero-fills all newly allocated Buffer and SlowBuffer instances. - -.TP -.BR \-\-preserve\-symlinks -Instructs the module loader to preserve symbolic links when resolving and -caching modules. - -.TP -.BR \-\-track\-heap-objects +. +.It Fl -preserve-symlinks +Instructs the module loader to preserve symbolic links when resolving and caching modules. +. +.It Fl -track-heap-objects Track heap object allocations for heap snapshots. - -.TP -.BR \-\-prof\-process -Process V8 profiler output generated using the V8 option \fB\-\-prof\fR - -.TP -.BR \-\-v8\-options -Print V8 command line options. - -Note: V8 options allow words to be separated by both dashes (\fB-\fR) or -underscores (\fB_\fR). - -For example, \fB\-\-stack\-trace\-limit\fR is equivalent to -\fB\-\-stack\_trace\_limit\fR - -.TP -.BR \-\-v8\-pool\-size =\fInum\fR -Set v8's thread pool size which will be used to allocate background jobs. -If set to 0 then V8 will choose an appropriate size of the thread pool based -on the number of online processors. If the value provided is larger than v8's -max then the largest value will be chosen. - -.TP -.BR \-\-tls\-cipher\-list =\fIlist\fR -Specify an alternative default TLS cipher list. (Requires Node.js to be built -with crypto support. (Default)) - -.TP -.BR \-\-enable\-fips -Enable FIPS-compliant crypto at startup. (Requires Node.js to be built with -\fB./configure \-\-openssl\-fips\fR) - -.TP -.BR \-\-force\-fips -Force FIPS-compliant crypto on startup. (Cannot be disabled from script code.) -(Same requirements as \fB\-\-enable\-fips\fR) - -.TP -.BR \-\-openssl\-config =\fIfile\fR -Load an OpenSSL configuration file on startup. Among other uses, this can be -used to enable FIPS-compliant crypto if Node.js is built with -\fB./configure \-\-openssl\-fips\fR. - -.TP -.BR \-\-use\-openssl\-ca,\-\-use\-bundled\-ca -Use OpenSSL's default CA store or use bundled Mozilla CA store as supplied by -current Node.js version. The default store is selectable at build-time. - -Using OpenSSL store allows for external modifications of the store. For most -Linux and BSD distributions, this store is maintained by the distribution -maintainers and system administrators. OpenSSL CA store location is dependent on -configuration of the OpenSSL library but this can be altered at runtime using -environment variables. - -The bundled CA store, as supplied by Node.js, is a snapshot of Mozilla CA store -that is fixed at release time. It is identical on all supported platforms. - -See \fBSSL_CERT_DIR\fR and \fBSSL_CERT_FILE\fR. - -.TP -.BR \-\-icu\-data\-dir =\fIfile\fR -Specify ICU data load path. (overrides \fBNODE_ICU_DATA\fR) - -.TP -.BR \-\fR -Alias for stdin, analogous to the use of - in other command line utilities, -meaning that the script will be read from stdin, and the rest of the options -are passed to that script. - -.TP -.BR \-\-\fR -Indicate the end of node options. Pass the rest of the arguments to the script. - +. +.It Fl -prof-process +Process V8 profiler output generated using the V8 option +.Fl -prof . +. +.It Fl -v8-options +Print V8 command-line options. +.Pp +Note: V8 options allow words to be separated by both dashes (\fB-\fR) or underscores (\fB_\fR). +.Pp +For example, +.Fl -stack-trace-limit +is equivalent to +.Fl -stack_trace_limit . +. +.It Fl -v8-pool-size Ns = Ns Ar num +Set V8's thread pool size which will be used to allocate background jobs. +If set to 0 then V8 will choose an appropriate size of the thread pool based on the number of online processors. +If the value provided is larger than V8's maximum, then the largest value will be chosen. +. +.It Fl -tls-cipher-list Ns = Ns Ar list +Specify an alternative default TLS cipher list. +Requires Node.js to be built with crypto support. (Default) +. +.It Fl -enable-fips +Enable FIPS-compliant crypto at startup. +Requires Node.js to be built with +.Sy ./configure --openssl-fips . +. +.It Fl -force-fips +Force FIPS-compliant crypto on startup +(Cannot be disabled from script code). +Same requirements as +.Fl -enable-fips . +. +.It Fl -openssl-config Ns = Ns Ar file +Load an OpenSSL configuration file on startup. +Among other uses, this can be used to enable FIPS-compliant crypto if Node.js is built with +.Sy ./configure --openssl-fips . +. +.It Fl -use-openssl-ca , Fl -use-bundled\-ca +Use OpenSSL's default CA store or use bundled Mozilla CA store as supplied by current Node.js version. +The default store is selectable at build-time. +.Pp +Using OpenSSL store allows for external modifications of the store. +For most Linux and BSD distributions, this store is maintained by the distribution maintainers and system administrators. +OpenSSL CA store location is dependent on configuration of the OpenSSL library but this can be altered at runtime using environment variables. +.Pp +The bundled CA store, as supplied by Node.js, is a snapshot of Mozilla CA store that is fixed at release time. +It is identical on all supported platforms. +.Pp +See +.Ev SSL_CERT_DIR +and +.Ev SSL_CERT_FILE . +. +.It Fl -icu-data-dir Ns = Ns Ar file +Specify ICU data load path. +Overrides +.Ev NODE_ICU_DATA . +. +.It Fl \-experimental-modules +Enable experimental ES module support and caching modules. +. +.It Fl \-experimental-vm-modules +Enable experimental ES module support in VM module. +. +.It Sy \- +Alias for stdin, analogous to the use of - in other command-line utilities. +The executed script is read from stdin, and remaining arguments are passed to the script. +. +.It Fl \- +Indicate the end of node options. +Pass the rest of the arguments to the script. +.Pp If no script filename or eval/print script is supplied prior to this, then the next argument will be used as a script filename. - -.SH ENVIRONMENT VARIABLES - -.TP -.BR NODE_DEBUG =\fImodule\fR[,\fI...\fR] -\',\'\-separated list of core modules that should print debug information. - -.TP -.BR NODE_DISABLE_COLORS =\fI1\fR -When set to \fI1\fR, colors will not be used in the REPL. - -.TP -.BR NODE_EXTRA_CA_CERTS =\fIfile\fR -When set, the well known "root" CAs (like VeriSign) will be extended with the -extra certificates in \fIfile\fR. The file should consist of one or more -trusted certificates in PEM format. A message will be emitted (once) with -\fBprocess.emitWarning()\fR if the file is missing or misformatted, but any -errors are otherwise ignored. - -.TP -.BR NODE_ICU_DATA =\fIfile\fR -Data path for ICU (Intl object) data. Will extend linked-in data when compiled -with small\-icu support. - -.TP -.BR NODE_NO_WARNINGS =\fI1\fR -When set to \fI1\fR, process warnings are silenced. - -.TP -.BR NODE_OPTIONS =\fIoptions...\fR -A space-separated list of command line options. \fBoptions...\fR are interpreted -as if they had been specified on the command line before the actual command line -(so they can be overridden). Node will exit with an error if an option that is -not allowed in the environment is used, such as \fB-p\fR or a script file. - -.TP -.BR NODE_PATH =\fIpath\fR[:\fI...\fR] -\':\'\-separated list of directories prefixed to the module search path. - -.TP -.BR NODE_PENDING_DEPRECATION = \fI1\fR -When set to \fI1\fR, emit pending deprecation warnings. - -.TP -.BR NODE_REPL_HISTORY =\fIfile\fR -Path to the file used to store the persistent REPL history. The default path -is \fB~/.node_repl_history\fR, which is overridden by this variable. Setting the -value to an empty string ("" or " ") disables persistent REPL history. - -.TP -.BR OPENSSL_CONF = \fIfile\fR -Load an OpenSSL configuration file on startup. Among other uses, this can be -used to enable FIPS-compliant crypto if Node.js is built with -\fB./configure \-\-openssl\-fips\fR. - +.El +. +.\" ===================================================================== +.Sh ENVIRONMENT +.Bl -tag -width 6n +.It Ev NODE_DEBUG Ar modules... +Comma-separated list of core modules that should print debug information. +. +.It Ev NODE_DISABLE_COLORS +When set to +.Ar 1 , +colors will not be used in the REPL. +. +.It Ev NODE_EXTRA_CA_CERTS Ar file +When set, the well-known +.Dq root +CAs (like VeriSign) will be extended with the extra certificates in +.Ar file . +The file should consist of one or more trusted certificates in PEM format. +.Pp +If +.Ar file +is missing or misformatted, a message will be emitted once using +.Sy process.emitWarning() , +but any errors are otherwise ignored. +. +.It Ev NODE_ICU_DATA Ar file +Data path for ICU (Intl object) data. +Will extend linked-in data when compiled with small-icu support. +. +.It Ev NODE_NO_WARNINGS +When set to +.Ar 1 , +process warnings are silenced. +. +.It Ev NODE_OPTIONS Ar options... +A space-separated list of command-line +.Ar options , +which are interpreted as if they had been specified on the command-line before the actual command (so they can be overridden). +Node will exit with an error if an option that is not allowed in the environment is used, such as +.Fl -print +or a script file. +. +.It Ev NODE_PATH Ar directories... +A colon-separated list of +.Ar directories +prefixed to the module search path. +. +.It Ev NODE_PENDING_DEPRECATION +When set to +.Ar 1 , +emit pending deprecation warnings. +. +.It Ev NODE_REPL_HISTORY Ar file +Path to the +.Ar file +used to store persistent REPL history. +The default path is +.Sy ~/.node_repl_history , +which is overridden by this variable. +Setting the value to an empty string ("" or " ") will disable persistent REPL history. +. +.It Ev OPENSSL_CONF Ar file +Load an OpenSSL configuration file on startup. +Among other uses, this can be used to enable FIPS-compliant crypto if Node.js is built with +.Sy ./configure --openssl-fips . +.Pp If the -\fB\-\-openssl\-config\fR -command line option is used, the environment variable is ignored. - -.TP -.BR SSL_CERT_DIR = \fIdir\fR -If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's directory -containing trusted certificates. - -.TP -.BR SSL_CERT_FILE = \fIfile\fR -If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's -file containing trusted certificates. - -.TP -.BR NODE_REDIRECT_WARNINGS=\fIfile\fR -Write process warnings to the given file instead of printing to stderr. -(equivalent to using the \-\-redirect\-warnings=\fIfile\fR command-line -argument). - -.SH BUGS +.Fl -openssl-config +command-line option is used, this environment variable is ignored. +. +.It Ev SSL_CERT_DIR Ar dir +If +.Fl -use-openssl-ca +is enabled, this overrides and sets OpenSSL's directory containing trusted certificates. +. +.It Ev SSL_CERT_FILE Ar file +If +.Fl -use-openssl-ca +is enabled, this overrides and sets OpenSSL's file containing trusted certificates. +. +.It Ev NODE_REDIRECT_WARNINGS Ar file +Write process warnings to the given +.Ar file +instead of printing to stderr. +Equivalent to passing +.Fl -redirect-warnings Ar file +on command-line. +.El +. +.\"===================================================================== +.Sh BUGS Bugs are tracked in GitHub Issues: -.ur https://github.com/nodejs/node/issues - - -.SH AUTHORS -Written and maintained by 1000+ contributors: -.ur https://github.com/nodejs/node/blob/master/AUTHORS - - -.SH COPYRIGHT -Copyright Node.js contributors. Node.js is available under the MIT license. - -Node.js also includes external libraries that are available under a variety -of licenses. See -.ur https://github.com/nodejs/node/blob/master/LICENSE +.Sy https://github.com/nodejs/node/issues +. +.\"====================================================================== +.Sh COPYRIGHT +Copyright Node.js contributors. +Node.js is available under the MIT license. +. +.Pp +Node.js also includes external libraries that are available under a variety of licenses. +See +.Sy https://github.com/nodejs/node/blob/master/LICENSE for the full license text. - - -.SH RESOURCES AND DOCUMENTATION +. +.\"====================================================================== +.Sh SEE ALSO Website: -.ur https://nodejs.org/ - +.Sy https://nodejs.org/ +. +.Pp Documentation: -.ur https://nodejs.org/api/ - +.Sy https://nodejs.org/api/ +. +.Pp GitHub repository & Issue Tracker: -.ur https://github.com/nodejs/node - +.Sy https://github.com/nodejs/node +. +.Pp Mailing list: -.ur http://groups.google.com/group/nodejs - +.Sy http://groups.google.com/group/nodejs +. +.Pp IRC (general questions): -.ur "chat.freenode.net #node.js" +.Sy "chat.freenode.net #node.js" (unofficial) - +. +.Pp IRC (Node.js core development): -.ur "chat.freenode.net #node-dev" +.Sy "chat.freenode.net #node-dev" +. +.\"====================================================================== +.Sh AUTHORS +Written and maintained by 1000+ contributors: +.Sy https://github.com/nodejs/node/blob/master/AUTHORS +. From c9b42c4c13a7b769dbb152b039cc28fe36072b75 Mon Sep 17 00:00:00 2001 From: juggernaut451 Date: Sun, 11 Feb 2018 21:39:05 +0530 Subject: [PATCH 166/193] test: refactor parallel/test-tls-pause Use arrow functions and common.mustCall() and add a description. PR-URL: https://github.com/nodejs/node/pull/18714 Reviewed-By: Anna Henningsen Reviewed-By: Weijia Wang Reviewed-By: Yuta Hiroto Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Richard Lau --- test/parallel/test-tls-pause.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/test/parallel/test-tls-pause.js b/test/parallel/test-tls-pause.js index 75c2832f7332f8..a6130cd4331f62 100644 --- a/test/parallel/test-tls-pause.js +++ b/test/parallel/test-tls-pause.js @@ -24,6 +24,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +// This test ensures that the data received over tls-server after pause +// is same as what it was sent + const assert = require('assert'); const tls = require('tls'); const fixtures = require('../common/fixtures'); @@ -37,24 +40,23 @@ const bufSize = 1024 * 1024; let sent = 0; let received = 0; -const server = tls.Server(options, function(socket) { +const server = tls.Server(options, common.mustCall((socket) => { socket.pipe(socket); - socket.on('data', function(c) { + socket.on('data', (c) => { console.error('data', c.length); }); -}); +})); -server.listen(0, function() { +server.listen(0, common.mustCall(() => { let resumed = false; const client = tls.connect({ - port: this.address().port, + port: server.address().port, rejectUnauthorized: false - }, function() { + }, common.mustCall(() => { console.error('connected'); client.pause(); console.error('paused'); - send(); - function send() { + const send = (() => { console.error('sending'); const ret = client.write(Buffer.allocUnsafe(bufSize)); console.error(`write => ${ret}`); @@ -69,9 +71,9 @@ server.listen(0, function() { resumed = true; client.resume(); console.error('resumed', client); - } - }); - client.on('data', function(data) { + })(); + })); + client.on('data', (data) => { console.error('data'); assert.ok(resumed); received += data.length; @@ -83,8 +85,8 @@ server.listen(0, function() { server.close(); } }); -}); +})); -process.on('exit', function() { +process.on('exit', () => { assert.strictEqual(sent, received); }); From 7ca4ca8cc36f7bf293f0d6717068eabb289262a6 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Sun, 12 Nov 2017 09:47:14 +0000 Subject: [PATCH 167/193] lib: allow process kill by signal number This brings the behaviour in line with the documentation. PR-URL: https://github.com/nodejs/node/pull/16944 Reviewed-By: Colin Ihrig Reviewed-By: Anna Henningsen Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- lib/internal/process.js | 4 ++-- test/parallel/test-process-kill-pid.js | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/internal/process.js b/lib/internal/process.js index 371281dfd44041..3de3ae1603deb5 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -162,8 +162,8 @@ function setupKillAndExit() { } // preserve null signal - if (0 === sig) { - err = process._kill(pid, 0); + if (sig === (sig | 0)) { + err = process._kill(pid, sig); } else { sig = sig || 'SIGTERM'; if (constants[sig]) { diff --git a/test/parallel/test-process-kill-pid.js b/test/parallel/test-process-kill-pid.js index 2ff35c6e4f866f..594a2a6a0bd8e6 100644 --- a/test/parallel/test-process-kill-pid.js +++ b/test/parallel/test-process-kill-pid.js @@ -57,16 +57,19 @@ assert.throws(function() { process.kill(1 / 0); }, assert.throws(function() { process.kill(-1 / 0); }, invalidPidArgument); -// Test that kill throws an error for invalid signal -const unknownSignal = common.expectsError({ +// Test that kill throws an error for unknown signal names +common.expectsError(() => process.kill(0, 'test'), { code: 'ERR_UNKNOWN_SIGNAL', type: TypeError, message: 'Unknown signal: test' }); - -assert.throws(function() { process.kill(1, 'test'); }, - unknownSignal); +// Test that kill throws an error for invalid signal numbers +common.expectsError(() => process.kill(0, 987), { + code: 'EINVAL', + type: Error, + message: 'kill EINVAL' +}); // Test kill argument processing in valid cases. // @@ -99,6 +102,11 @@ kill(0, undefined, 0, 15); kill('0', 'SIGHUP', 0, 1); kill('0', undefined, 0, 15); +// Confirm that numeric signal arguments are supported + +kill(0, 1, 0, 1); +kill(0, 15, 0, 15); + // negative numbers are meaningful on unix kill(-1, 'SIGHUP', -1, 1); kill(-1, undefined, -1, 15); From f242d4b250e50105fc2455813159ee790ac5a198 Mon Sep 17 00:00:00 2001 From: Shobhit Chittora Date: Wed, 1 Nov 2017 01:08:45 +0530 Subject: [PATCH 168/193] tools: auto fix custom crypto-check eslint rule 1. Fixer for crypto-check.js 2. Extends tests PR-URL: https://github.com/nodejs/node/pull/16647 Refs: https://github.com/nodejs/node/issues/16636 Reviewed-By: James M Snell Reviewed-By: Khaidi Chu Reviewed-By: Ruben Bridgewater --- test/parallel/test-eslint-crypto-check.js | 30 +++++++++++++++++------ tools/eslint-rules/crypto-check.js | 20 ++++++++++++++- tools/eslint-rules/rules-utils.js | 11 +++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/test/parallel/test-eslint-crypto-check.js b/test/parallel/test-eslint-crypto-check.js index f7549f171d6afd..86c28d21218154 100644 --- a/test/parallel/test-eslint-crypto-check.js +++ b/test/parallel/test-eslint-crypto-check.js @@ -15,20 +15,34 @@ new RuleTester().run('crypto-check', rule, { 'foo', 'crypto', ` - if (!common.hasCrypto) { - common.skip(); - } - require('crypto'); + if (!common.hasCrypto) { + common.skip("missing crypto"); + } + require("crypto"); ` ], invalid: [ { - code: 'require("crypto")', - errors: [{ message }] + code: 'require("common")\n' + + 'require("crypto")', + errors: [{ message }], + output: 'require("common")\n' + + 'if (!common.hasCrypto) {' + + ' common.skip("missing crypto");' + + '}\n' + + 'require("crypto")' }, { - code: 'if (common.foo) {} require("crypto")', - errors: [{ message }] + code: 'require("common")\n' + + 'if (common.foo) {}\n' + + 'require("crypto")', + errors: [{ message }], + output: 'require("common")\n' + + 'if (!common.hasCrypto) {' + + ' common.skip("missing crypto");' + + '}\n' + + 'if (common.foo) {}\n' + + 'require("crypto")' } ] }); diff --git a/tools/eslint-rules/crypto-check.js b/tools/eslint-rules/crypto-check.js index 9570c24c030ef4..42b17b0c80a225 100644 --- a/tools/eslint-rules/crypto-check.js +++ b/tools/eslint-rules/crypto-check.js @@ -23,6 +23,7 @@ const bindingModules = cryptoModules.concat(['tls_wrap']); module.exports = function(context) { const missingCheckNodes = []; const requireNodes = []; + var commonModuleNode = null; var hasSkipCall = false; function testCryptoUsage(node) { @@ -30,6 +31,10 @@ module.exports = function(context) { utils.isBinding(node, bindingModules)) { requireNodes.push(node); } + + if (utils.isCommonModule(node)) { + commonModuleNode = node; + } } function testIfStatement(node) { @@ -75,7 +80,20 @@ module.exports = function(context) { function report(nodes) { nodes.forEach((node) => { - context.report(node, msg); + context.report({ + node, + message: msg, + fix: (fixer) => { + if (commonModuleNode) { + return fixer.insertTextAfter( + commonModuleNode, + '\nif (!common.hasCrypto) {' + + ' common.skip("missing crypto");' + + '}' + ); + } + } + }); }); } diff --git a/tools/eslint-rules/rules-utils.js b/tools/eslint-rules/rules-utils.js index 0fda705fb290b7..88ecf658ce37f0 100644 --- a/tools/eslint-rules/rules-utils.js +++ b/tools/eslint-rules/rules-utils.js @@ -12,6 +12,17 @@ module.exports.isRequired = function(node, modules) { modules.includes(node.arguments[0].value); }; +/** +* Return true if common module is required +* in AST Node under inspection +*/ +var commonModuleRegExp = new RegExp(/^(\.\.\/)*common(\.js)?$/); +module.exports.isCommonModule = function(node) { + return node.callee.name === 'require' && + node.arguments.length !== 0 && + commonModuleRegExp.test(node.arguments[0].value); +}; + /** * Returns true if any of the passed in modules are used in * binding calls. From 515634210593bbc143f962409ab29f8801e933d7 Mon Sep 17 00:00:00 2001 From: Shobhit Chittora Date: Wed, 1 Nov 2017 03:22:31 +0530 Subject: [PATCH 169/193] tools: custom eslint autofix for inspector-check.js 1. Adds fixer method 2. Extends test PR-URL: https://github.com/nodejs/node/pull/16646 Refs: https://github.com/nodejs/node/issues/16636 Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- test/parallel/test-eslint-inspector-check.js | 12 +++++++++--- tools/eslint-rules/inspector-check.js | 18 +++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/test/parallel/test-eslint-inspector-check.js b/test/parallel/test-eslint-inspector-check.js index ab8314b63818c7..bdec596f8d128e 100644 --- a/test/parallel/test-eslint-inspector-check.js +++ b/test/parallel/test-eslint-inspector-check.js @@ -12,12 +12,18 @@ const message = 'Please add a skipIfInspectorDisabled() call to allow this ' + new RuleTester().run('inspector-check', rule, { valid: [ 'foo;', - 'common.skipIfInspectorDisabled(); require("inspector");' + 'require("common")\n' + + 'common.skipIfInspectorDisabled();\n' + + 'require("inspector")' ], invalid: [ { - code: 'require("inspector")', - errors: [{ message }] + code: 'require("common")\n' + + 'require("inspector")', + errors: [{ message }], + output: 'require("common")\n' + + 'common.skipIfInspectorDisabled();\n' + + 'require("inspector")' } ] }); diff --git a/tools/eslint-rules/inspector-check.js b/tools/eslint-rules/inspector-check.js index bb40a98183250c..00a2dd02963558 100644 --- a/tools/eslint-rules/inspector-check.js +++ b/tools/eslint-rules/inspector-check.js @@ -15,12 +15,17 @@ const msg = 'Please add a skipIfInspectorDisabled() call to allow this ' + module.exports = function(context) { const missingCheckNodes = []; + var commonModuleNode = null; var hasInspectorCheck = false; function testInspectorUsage(context, node) { if (utils.isRequired(node, ['inspector'])) { missingCheckNodes.push(node); } + + if (utils.isCommonModule(node)) { + commonModuleNode = node; + } } function checkMemberExpression(context, node) { @@ -32,7 +37,18 @@ module.exports = function(context) { function reportIfMissing(context) { if (!hasInspectorCheck) { missingCheckNodes.forEach((node) => { - context.report(node, msg); + context.report({ + node, + message: msg, + fix: (fixer) => { + if (commonModuleNode) { + return fixer.insertTextAfter( + commonModuleNode, + '\ncommon.skipIfInspectorDisabled();' + ); + } + } + }); }); } } From 472cde603ef60aafcff00a4d09743758dfd0d928 Mon Sep 17 00:00:00 2001 From: Sergey Golovin Date: Mon, 12 Feb 2018 19:39:43 +0300 Subject: [PATCH 170/193] fs: remove useless comments which duplicate names of variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18739 Reviewed-By: Colin Ihrig Reviewed-By: Tobias Nießen Reviewed-By: Ruben Bridgewater Reviewed-By: Anatoli Papirovski Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Matheus Marchini --- lib/fs.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 92e8d4fe3e2d43..0b17885329ab92 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -375,7 +375,7 @@ function readFileAfterStat(err) { // our internal use. var size; if ((statValues[1/*mode*/] & S_IFMT) === S_IFREG) - size = context.size = statValues[8/*size*/]; + size = context.size = statValues[8]; else size = context.size = 0; @@ -490,7 +490,7 @@ fs.readFileSync = function(path, options) { // our internal use. var size; if ((statValues[1/*mode*/] & S_IFMT) === S_IFREG) - size = statValues[8/*size*/]; + size = statValues[8]; else size = 0; var pos = 0; @@ -1654,8 +1654,8 @@ fs.realpathSync = function realpathSync(p, options) { var linkTarget = null; var id; if (!isWindows) { - var dev = statValues[0/*dev*/].toString(32); - var ino = statValues[7/*ino*/].toString(32); + var dev = statValues[0].toString(32); + var ino = statValues[7].toString(32); id = `${dev}:${ino}`; if (seenLinks[id]) { linkTarget = seenLinks[id]; @@ -1793,8 +1793,8 @@ fs.realpath = function realpath(p, options, callback) { // dev/ino always return 0 on windows, so skip the check. let id; if (!isWindows) { - var dev = statValues[0/*ino*/].toString(32); - var ino = statValues[7/*ino*/].toString(32); + var dev = statValues[0].toString(32); + var ino = statValues[7].toString(32); id = `${dev}:${ino}`; if (seenLinks[id]) { return gotTarget(null, seenLinks[id], base); From 12412ef43fb4aa8eef39defad949aa8d1fe6aa10 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 16 Feb 2018 15:55:37 +0800 Subject: [PATCH 171/193] fs: fix potential segfault in async calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the async uv_fs_* call errors out synchronously in AsyncDestCall, the after callbacks (e.g. AfterNoArgs) would delete the req_wrap in FSReqAfterScope, and AsyncDestCall would set those req_wrap to nullptr afterwards. But when it returns to the top-layer bindings, the bindings all call `req_wrap->SetReturnValue()` again without checking if `req_wrap` is nullptr, causing a segfault. This has not been caught in any of the tests because we usually do a lot of argument checking in the JS layer before invoking the uv_fs_* functions, so it's rare to get a synchronous error from them. Currently we never need the binding to return the wrap to JS layer, so we can just call `req_wrap->SetReturnValue()` to return undefined for normal FSReqWrap and the promise for FSReqPromise in AsyncDestCall instead of doing this in the top-level bindings. PR-URL: https://github.com/nodejs/node/pull/18811 Reviewed-By: Ben Noordhuis Reviewed-By: Tobias Nießen Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- src/node_file.cc | 41 +++++++---------------------------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/src/node_file.cc b/src/node_file.cc index 37b0b4e3b9c0bd..c9c7570779bcbe 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -516,6 +516,7 @@ class fs_req_wrap { DISALLOW_COPY_AND_ASSIGN(fs_req_wrap); }; +// Returns nullptr if the operation fails from the start. template inline FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap, @@ -530,16 +531,16 @@ inline FSReqBase* AsyncDestCall(Environment* env, uv_fs_t* uv_req = req_wrap->req(); uv_req->result = err; uv_req->path = nullptr; - after(uv_req); + after(uv_req); // after may delete req_wrap if there is an error req_wrap = nullptr; + } else { + req_wrap->SetReturnValue(args); } - if (req_wrap != nullptr) { - args.GetReturnValue().Set(req_wrap->persistent()); - } return req_wrap; } +// Returns nullptr if the operation fails from the start. template inline FSReqBase* AsyncCall(Environment* env, FSReqBase* req_wrap, @@ -618,7 +619,6 @@ void Access(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { // access(path, mode, req) AsyncCall(env, req_wrap, args, "access", UTF8, AfterNoArgs, uv_fs_access, *path, mode); - req_wrap->SetReturnValue(args); } else { // access(path, mode, undefined, ctx) CHECK_EQ(argc, 4); fs_req_wrap req_wrap; @@ -640,7 +640,6 @@ void Close(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { // close(fd, req) AsyncCall(env, req_wrap, args, "close", UTF8, AfterNoArgs, uv_fs_close, fd); - req_wrap->SetReturnValue(args); } else { // close(fd, undefined, ctx) CHECK_EQ(argc, 3); fs_req_wrap req_wrap; @@ -749,7 +748,6 @@ static void Stat(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { // stat(path, req) AsyncCall(env, req_wrap, args, "stat", UTF8, AfterStat, uv_fs_stat, *path); - req_wrap->SetReturnValue(args); } else { // stat(path, undefined, ctx) CHECK_EQ(argc, 3); fs_req_wrap req_wrap; @@ -774,7 +772,6 @@ static void LStat(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { // lstat(path, req) AsyncCall(env, req_wrap, args, "lstat", UTF8, AfterStat, uv_fs_lstat, *path); - req_wrap->SetReturnValue(args); } else { // lstat(path, undefined, ctx) CHECK_EQ(argc, 3); fs_req_wrap req_wrap; @@ -799,7 +796,6 @@ static void FStat(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { // fstat(fd, req) AsyncCall(env, req_wrap, args, "fstat", UTF8, AfterStat, uv_fs_fstat, fd); - req_wrap->SetReturnValue(args); } else { // fstat(fd, undefined, ctx) CHECK_EQ(argc, 3); fs_req_wrap req_wrap; @@ -853,7 +849,6 @@ static void Link(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { // link(src, dest, req) AsyncDestCall(env, req_wrap, args, "link", *dest, dest.length(), UTF8, AfterNoArgs, uv_fs_link, *src, *dest); - req_wrap->SetReturnValue(args); } else { // link(src, dest) CHECK_EQ(argc, 4); fs_req_wrap req; @@ -877,7 +872,6 @@ static void ReadLink(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { // readlink(path, encoding, req) AsyncCall(env, req_wrap, args, "readlink", encoding, AfterStringPtr, uv_fs_readlink, *path); - req_wrap->SetReturnValue(args); } else { CHECK_EQ(argc, 4); fs_req_wrap req; @@ -918,7 +912,6 @@ static void Rename(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncDestCall(env, req_wrap, args, "rename", *new_path, new_path.length(), UTF8, AfterNoArgs, uv_fs_rename, *old_path, *new_path); - req_wrap->SetReturnValue(args); } else { CHECK_EQ(argc, 4); fs_req_wrap req; @@ -942,7 +935,6 @@ static void FTruncate(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "ftruncate", UTF8, AfterNoArgs, uv_fs_ftruncate, fd, len); - req_wrap->SetReturnValue(args); } else { CHECK_EQ(argc, 4); fs_req_wrap req; @@ -963,7 +955,6 @@ static void Fdatasync(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "fdatasync", UTF8, AfterNoArgs, uv_fs_fdatasync, fd); - req_wrap->SetReturnValue(args); } else { CHECK_EQ(argc, 3); fs_req_wrap req; @@ -984,7 +975,6 @@ static void Fsync(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "fsync", UTF8, AfterNoArgs, uv_fs_fsync, fd); - req_wrap->SetReturnValue(args); } else { CHECK_EQ(argc, 3); fs_req_wrap req; @@ -1005,7 +995,6 @@ static void Unlink(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "unlink", UTF8, AfterNoArgs, uv_fs_unlink, *path); - req_wrap->SetReturnValue(args); } else { CHECK_EQ(argc, 3); fs_req_wrap req; @@ -1025,7 +1014,6 @@ static void RMDir(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "rmdir", UTF8, AfterNoArgs, uv_fs_rmdir, *path); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(rmdir, *path, *path) } @@ -1046,7 +1034,6 @@ static void MKDir(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "mkdir", UTF8, AfterNoArgs, uv_fs_mkdir, *path, mode); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(mkdir, *path, *path, mode) } @@ -1064,7 +1051,6 @@ static void RealPath(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "realpath", encoding, AfterStringPtr, uv_fs_realpath, *path); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(realpath, *path, *path); const char* link_path = static_cast(SYNC_REQ.ptr); @@ -1096,7 +1082,6 @@ static void ReadDir(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "scandir", encoding, AfterScanDir, uv_fs_scandir, *path, 0 /*flags*/); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(scandir, *path, *path, 0 /*flags*/) @@ -1167,7 +1152,6 @@ static void Open(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "open", UTF8, AfterInteger, uv_fs_open, *path, flags, mode); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(open, *path, *path, flags, mode) args.GetReturnValue().Set(SYNC_RESULT); @@ -1192,7 +1176,6 @@ static void OpenFileHandle(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "open", UTF8, AfterOpenFileHandle, uv_fs_open, *path, flags, mode); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(open, *path, *path, flags, mode) HandleScope scope(env->isolate()); @@ -1217,7 +1200,6 @@ static void CopyFile(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "copyfile", UTF8, AfterNoArgs, uv_fs_copyfile, *src, *dest, flags); - req_wrap->SetReturnValue(args); } else { SYNC_DEST_CALL(copyfile, *src, *dest, *src, *dest, flags) } @@ -1260,7 +1242,7 @@ static void WriteBuffer(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "write", UTF8, AfterInteger, uv_fs_write, fd, &uvbuf, 1, pos); - return req_wrap->SetReturnValue(args); + return; } SYNC_CALL(write, nullptr, fd, &uvbuf, 1, pos) @@ -1297,7 +1279,7 @@ static void WriteBuffers(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "write", UTF8, AfterInteger, uv_fs_write, fd, *iovs, iovs.length(), pos); - return req_wrap->SetReturnValue(args); + return; } SYNC_CALL(write, nullptr, fd, *iovs, iovs.length(), pos) @@ -1365,7 +1347,6 @@ static void WriteString(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "write", UTF8, AfterInteger, uv_fs_write, fd, &uvbuf, 1, pos); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(write, nullptr, fd, &uvbuf, 1, pos) return args.GetReturnValue().Set(SYNC_RESULT); @@ -1420,7 +1401,6 @@ static void Read(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "read", UTF8, AfterInteger, uv_fs_read, fd, &uvbuf, 1, pos); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(read, 0, fd, &uvbuf, 1, pos) args.GetReturnValue().Set(SYNC_RESULT); @@ -1446,7 +1426,6 @@ static void Chmod(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "chmod", UTF8, AfterNoArgs, uv_fs_chmod, *path, mode); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(chmod, *path, *path, mode); } @@ -1469,7 +1448,6 @@ static void FChmod(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "fchmod", UTF8, AfterNoArgs, uv_fs_fchmod, fd, mode); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(fchmod, 0, fd, mode); } @@ -1497,7 +1475,6 @@ static void Chown(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "chown", UTF8, AfterNoArgs, uv_fs_chown, *path, uid, gid); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(chown, *path, *path, uid, gid); } @@ -1522,7 +1499,6 @@ static void FChown(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "fchown", UTF8, AfterNoArgs, uv_fs_fchown, fd, uid, gid); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(fchown, 0, fd, uid, gid); } @@ -1546,7 +1522,6 @@ static void UTimes(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "utime", UTF8, AfterNoArgs, uv_fs_utime, *path, atime, mtime); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(utime, *path, *path, atime, mtime); } @@ -1567,7 +1542,6 @@ static void FUTimes(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "futime", UTF8, AfterNoArgs, uv_fs_futime, fd, atime, mtime); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(futime, 0, fd, atime, mtime); } @@ -1587,7 +1561,6 @@ static void Mkdtemp(const FunctionCallbackInfo& args) { if (req_wrap != nullptr) { AsyncCall(env, req_wrap, args, "mkdtemp", encoding, AfterStringPath, uv_fs_mkdtemp, *tmpl); - req_wrap->SetReturnValue(args); } else { SYNC_CALL(mkdtemp, *tmpl, *tmpl); const char* path = static_cast(SYNC_REQ.path); From e91ea214115b9e41269415872717ce7a741b1d7a Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Fri, 16 Feb 2018 15:01:16 +0100 Subject: [PATCH 172/193] src: add nullptr check for session in DEBUG macro Currenlty when configuring --debug-http2 /test/parallel/test-http2-getpackedsettings.js will segment fault: $ out/Debug/node test/parallel/test-http2-getpackedsettings.js Segmentation fault: 11 This is happening because the settings is created with the Environment in PackSettings: Http2Session::Http2Settings settings(env); This will cause the session to be set to nullptr. When the init function is later called the expanded DEBUG_HTTP2SESSION macro will cause the segment fault when the session is dereferenced. PR-URL: https://github.com/nodejs/node/pull/18815 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- src/node_http2.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/node_http2.h b/src/node_http2.h index 0e81eaac6ca7fe..217c19c09287af 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -39,16 +39,20 @@ void inline debug_vfprintf(const char* format, ...) { #define DEBUG_HTTP2(...) debug_vfprintf(__VA_ARGS__); #define DEBUG_HTTP2SESSION(session, message) \ do { \ - DEBUG_HTTP2("Http2Session %s (%.0lf) " message "\n", \ - session->TypeName(), \ - session->get_async_id()); \ + if (session != nullptr) { \ + DEBUG_HTTP2("Http2Session %s (%.0lf) " message "\n", \ + session->TypeName(), \ + session->get_async_id()); \ + } \ } while (0) #define DEBUG_HTTP2SESSION2(session, message, ...) \ do { \ - DEBUG_HTTP2("Http2Session %s (%.0lf) " message "\n", \ - session->TypeName(), \ - session->get_async_id(), \ + if (session != nullptr) { \ + DEBUG_HTTP2("Http2Session %s (%.0lf) " message "\n", \ + session->TypeName(), \ + session->get_async_id(), \ __VA_ARGS__); \ + } \ } while (0) #define DEBUG_HTTP2STREAM(stream, message) \ do { \ From f6721c20df67c0f5bbd1ea58d304159160be03f1 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Wed, 14 Feb 2018 12:29:17 +0000 Subject: [PATCH 173/193] stream: writable.end should return this. PR-URL: https://github.com/nodejs/node/pull/18780 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Benjamin Gruenbaum Reviewed-By: Anna Henningsen Reviewed-By: Luigi Pinca --- doc/api/stream.md | 4 ++++ lib/_stream_writable.js | 2 ++ test/parallel/test-stream-writableState-ending.js | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/api/stream.md b/doc/api/stream.md index 14be27cbf2d911..c72873c466fdb3 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -355,6 +355,9 @@ See also: [`writable.uncork()`][]. * `data` {string|Buffer} * `encoding` {string} * `callback` {Function} +* Returns: {this} Finishes sending the request. If any parts of the body are unsent, it will flush them to the stream. If the request is @@ -1041,11 +1046,16 @@ See [`response.socket`][]. ### response.end([data][, encoding][, callback]) * `data` {string|Buffer} * `encoding` {string} * `callback` {Function} +* Returns: {this} This method signals to the server that all of the response headers and body have been sent; that server should consider this message complete. diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index f513315b7cd421..985b74679c0027 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -736,7 +736,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { } if (this.finished) { - return false; + return this; } var uncork; @@ -766,12 +766,11 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { var finish = onFinish.bind(undefined, this); - var ret; if (this._hasBody && this.chunkedEncoding) { - ret = this._send('0\r\n' + this._trailer + '\r\n', 'latin1', finish); + this._send('0\r\n' + this._trailer + '\r\n', 'latin1', finish); } else { // Force a flush, HACK. - ret = this._send('', 'latin1', finish); + this._send('', 'latin1', finish); } if (uncork) @@ -788,7 +787,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { this._finish(); } - return ret; + return this; }; diff --git a/test/parallel/test-http-request-end-twice.js b/test/parallel/test-http-request-end-twice.js index 525377d2e1ccbf..47f08fd6e422f0 100644 --- a/test/parallel/test-http-request-end-twice.js +++ b/test/parallel/test-http-request-end-twice.js @@ -31,7 +31,7 @@ const server = http.Server(function(req, res) { server.listen(0, function() { const req = http.get({ port: this.address().port }, function(res) { res.on('end', function() { - assert.ok(!req.end()); + assert.strictEqual(req.end(), req); server.close(); }); res.resume(); diff --git a/test/parallel/test-http-request-end.js b/test/parallel/test-http-request-end.js index 6dd5fa4e91b1b2..a0cdcf27dd03a9 100644 --- a/test/parallel/test-http-request-end.js +++ b/test/parallel/test-http-request-end.js @@ -44,7 +44,7 @@ const server = http.Server(function(req, res) { }); server.listen(0, function() { - http.request({ + const req = http.request({ port: this.address().port, path: '/', method: 'POST' @@ -54,5 +54,9 @@ server.listen(0, function() { }).on('error', function(e) { console.log(e.message); process.exit(1); - }).end(expected); + }); + + const result = req.end(expected); + + assert.strictEqual(req, result); }); From 3d93f39190ec24284aee6acd0e0214862e651567 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Wed, 14 Feb 2018 13:39:05 +0000 Subject: [PATCH 175/193] http2: make response.end() return this PR-URL: https://github.com/nodejs/node/pull/18780 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Benjamin Gruenbaum Reviewed-By: Anna Henningsen Reviewed-By: Luigi Pinca --- doc/api/http2.md | 5 +++++ lib/internal/http2/compat.js | 2 ++ test/parallel/test-http2-compat-serverrequest-end.js | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/api/http2.md b/doc/api/http2.md index 66cf7aafa0ff48..c73ed3b0bd2fb1 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -2624,11 +2624,16 @@ See [`response.socket`][]. #### response.end([data][, encoding][, callback]) * `data` {string|Buffer} * `encoding` {string} * `callback` {Function} +* Returns: {this} This method signals to the server that all of the response headers and body have been sent; that server should consider this message complete. diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index 5e6c51377e94ba..9670843176b77e 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -596,6 +596,8 @@ class Http2ServerResponse extends Stream { this[kFinish](); else stream.end(); + + return this; } destroy(err) { diff --git a/test/parallel/test-http2-compat-serverrequest-end.js b/test/parallel/test-http2-compat-serverrequest-end.js index d34372118582db..45a678d1a950d1 100644 --- a/test/parallel/test-http2-compat-serverrequest-end.js +++ b/test/parallel/test-http2-compat-serverrequest-end.js @@ -26,7 +26,7 @@ server.listen(0, common.mustCall(function() { server.close(); })); - response.end(); + assert.strictEqual(response.end(), response); })); })); From 30f89dfbf65840025f5c833457702f13aa38fe77 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Mon, 5 Feb 2018 14:57:13 +0100 Subject: [PATCH 176/193] build: add node_lib_target_name to cctest deps Currently the cctest target depend on the node_core_target_name target. But it is the node_lib_target_name target that compiles the sources now which means that if a source file in src is updated the cctest executable will not be re-linked against it, but will remain unchanged. The code will still be compiled, just not linked which means that if you are debugging you'll not see the changes and also a warning will be displayed about this issue. This commit changes the cctest target to depend on node_lib_target_name. PR-URL: https://github.com/nodejs/node/pull/18576 Reviewed-By: Matheus Marchini Reviewed-By: Yihong Wang Reviewed-By: Gibson Fahnestock Reviewed-By: Ben Noordhuis --- node.gyp | 130 +------------------ test/cctest/node_module_reg.cc | 30 ----- test/cctest/test_node_postmortem_metadata.cc | 24 +++- 3 files changed, 25 insertions(+), 159 deletions(-) delete mode 100644 test/cctest/node_module_reg.cc diff --git a/node.gyp b/node.gyp index 08eee428560770..44c46ad2bc8854 100644 --- a/node.gyp +++ b/node.gyp @@ -921,7 +921,7 @@ 'type': 'executable', 'dependencies': [ - '<(node_core_target_name)', + '<(node_lib_target_name)', 'rename_node_bin_win', 'deps/gtest/gtest.gyp:gtest', 'node_js2c#host', @@ -930,39 +930,6 @@ 'node_dtrace_provider', ], - 'variables': { - 'obj_path': '<(obj_dir)/<(node_lib_target_name)/src', - 'obj_gen_path': '<(obj_dir)/<(node_lib_target_name)/gen', - 'obj_tracing_path': '<(obj_dir)/<(node_lib_target_name)/src/tracing', - 'obj_suffix': 'o', - 'obj_separator': '/', - 'conditions': [ - ['OS=="win"', { - 'obj_suffix': 'obj', - }], - ['GENERATOR=="ninja"', { - 'obj_path': '<(obj_dir)/src', - 'obj_gen_path': '<(obj_dir)/gen', - 'obj_tracing_path': '<(obj_dir)/src/tracing', - 'obj_separator': '/<(node_lib_target_name).', - }, { - 'conditions': [ - ['OS=="win"', { - 'obj_path': '<(obj_dir)/<(node_lib_target_name)', - 'obj_gen_path': '<(obj_dir)/<(node_lib_target_name)', - 'obj_tracing_path': '<(obj_dir)/<(node_lib_target_name)', - }], - ['OS=="aix"', { - 'obj_path': '<(obj_dir)/<(node_lib_target_name)/src', - 'obj_gen_path': '<(obj_dir)/<(node_lib_target_name)/gen', - 'obj_tracing_path': - '<(obj_dir)/<(node_lib_target_name)/src/tracing', - }], - ]} - ] - ], - }, - 'includes': [ 'node.gypi' ], @@ -979,7 +946,6 @@ 'defines': [ 'NODE_WANT_INTERNALS=1' ], 'sources': [ - 'test/cctest/node_module_reg.cc', 'test/cctest/node_test_fixture.cc', 'test/cctest/test_aliased_buffer.cc', 'test/cctest/test_base64.cc', @@ -989,120 +955,30 @@ 'test/cctest/test_url.cc' ], - 'libraries': [ - '<(obj_path)<(obj_separator)async_wrap.<(obj_suffix)', - '<(obj_path)<(obj_separator)handle_wrap.<(obj_suffix)', - '<(obj_path)<(obj_separator)env.<(obj_suffix)', - '<(obj_path)<(obj_separator)node.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_buffer.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_debug_options.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_i18n.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_perf.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_platform.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_url.<(obj_suffix)', - '<(obj_path)<(obj_separator)util.<(obj_suffix)', - '<(obj_path)<(obj_separator)string_bytes.<(obj_suffix)', - '<(obj_path)<(obj_separator)string_decoder.<(obj_suffix)', - '<(obj_path)<(obj_separator)string_search.<(obj_suffix)', - '<(obj_path)<(obj_separator)stream_base.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_constants.<(obj_suffix)', - '<(obj_tracing_path)<(obj_separator)agent.<(obj_suffix)', - '<(obj_tracing_path)<(obj_separator)node_trace_buffer.<(obj_suffix)', - '<(obj_tracing_path)<(obj_separator)node_trace_writer.<(obj_suffix)', - '<(obj_tracing_path)<(obj_separator)trace_event.<(obj_suffix)', - '<(obj_gen_path)<(obj_separator)node_javascript.<(obj_suffix)', - ], - 'conditions': [ [ 'node_use_openssl=="true"', { - 'conditions': [ - ['node_target_type!="static_library"', { - 'libraries': [ - '<(obj_path)<(obj_separator)node_crypto.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_crypto_bio.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_crypto_clienthello.<(obj_suffix)', - '<(obj_path)<(obj_separator)tls_wrap.<(obj_suffix)', - ], - }], - ], 'defines': [ 'HAVE_OPENSSL=1', ], }], [ 'node_use_perfctr=="true"', { 'defines': [ 'HAVE_PERFCTR=1' ], - 'libraries': [ - '<(obj_path)<(obj_separator)node_counters.<(obj_suffix)', - '<(obj_path)<(obj_separator)' - 'node_win32_perfctr_provider.<(obj_suffix)', - ], }], ['v8_enable_inspector==1', { 'sources': [ 'test/cctest/test_inspector_socket.cc', 'test/cctest/test_inspector_socket_server.cc' ], - 'conditions': [ - ['node_target_type!="static_library"', { - 'libraries': [ - '<(obj_path)<(obj_separator)inspector_agent.<(obj_suffix)', - '<(obj_path)<(obj_separator)inspector_io.<(obj_suffix)', - '<(obj_path)<(obj_separator)inspector_js_api.<(obj_suffix)', - '<(obj_path)<(obj_separator)inspector_socket.<(obj_suffix)', - '<(obj_path)<(obj_separator)inspector_socket_server.<(obj_suffix)', - ], - }], - ], 'defines': [ 'HAVE_INSPECTOR=1', ], - }], - [ 'node_use_dtrace=="true" and node_target_type!="static_library"', { - 'libraries': [ - '<(obj_path)<(obj_separator)node_dtrace.<(obj_suffix)', - ], - 'conditions': [ - ['OS!="mac" and OS!="linux"', { - 'libraries': [ - '<(obj_path)<(obj_separator)node_dtrace_provider.<(obj_suffix)', - '<(obj_path)<(obj_separator)node_dtrace_ustack.<(obj_suffix)', - ] - }], - ['OS=="linux"', { - 'libraries': [ - '<(SHARED_INTERMEDIATE_DIR)<(obj_separator)' - 'node_dtrace_provider.<(obj_suffix)', - ] - }], - ], - }, { - 'conditions': [ - [ 'node_use_etw=="true" and OS=="win"', { - 'libraries': [ - '<(obj_path)<(obj_separator)node_dtrace.<(obj_suffix)', - '<(obj_path)<(obj_separator)' - 'node_win32_etw_provider.<(obj_suffix)', - ], - }] - ] - }], - [ 'OS=="win" and node_target_type!="static_library"', { - 'libraries': [ - '<(obj_path)<(obj_separator)backtrace_win32.<(obj_suffix)', - ], }, { - 'conditions': [ - ['node_target_type!="static_library"', { - 'libraries': [ - '<(obj_path)<(obj_separator)backtrace_posix.<(obj_suffix)', - ], - }], - ], + 'defines': [ 'HAVE_INSPECTOR=0' ] }], ['OS=="solaris"', { 'ldflags': [ '-I<(SHARED_INTERMEDIATE_DIR)' ] }], - ] + ], } ], # end targets diff --git a/test/cctest/node_module_reg.cc b/test/cctest/node_module_reg.cc deleted file mode 100644 index bd4f20bc9f823d..00000000000000 --- a/test/cctest/node_module_reg.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Need to create empty definition for these modules' -// registration function for cctest. Because when -// building cctest, the definitions for the following -// registration functions are not included. -void _register_cares_wrap() {} -void _register_config() {} -void _register_contextify() {} -void _register_domain() {} -void _register_fs() {} -void _register_fs_event_wrap() {} -void _register_http2() {} -void _register_http_parser() {} -void _register_js_stream() {} -void _register_module_wrap() {} -void _register_os() {} -void _register_pipe_wrap() {} -void _register_process_wrap() {} -void _register_serdes() {} -void _register_signal_wrap() {} -void _register_spawn_sync() {} -void _register_stream_wrap() {} -void _register_tcp_wrap() {} -void _register_timer_wrap() {} -void _register_trace_events() {} -void _register_tty_wrap() {} -void _register_udp_wrap() {} -void _register_util() {} -void _register_uv() {} -void _register_v8() {} -void _register_zlib() {} diff --git a/test/cctest/test_node_postmortem_metadata.cc b/test/cctest/test_node_postmortem_metadata.cc index be5cc7ce8ad2c5..e901d97668f5ff 100644 --- a/test/cctest/test_node_postmortem_metadata.cc +++ b/test/cctest/test_node_postmortem_metadata.cc @@ -1,5 +1,3 @@ -#include "node_postmortem_metadata.cc" - #include "gtest/gtest.h" #include "node.h" #include "node_internals.h" @@ -7,6 +5,28 @@ #include "req_wrap-inl.h" #include "tracing/agent.h" #include "v8.h" +#include "v8abbr.h" + +extern "C" { +extern uintptr_t + nodedbg_offset_HandleWrap__handle_wrap_queue___ListNode_HandleWrap; +extern uintptr_t + nodedbg_offset_Environment__handle_wrap_queue___Environment_HandleWrapQueue; +extern int debug_symbols_generated; +extern int nodedbg_const_Environment__kContextEmbedderDataIndex__int; +extern uintptr_t + nodedbg_offset_Environment_HandleWrapQueue__head___ListNode_HandleWrap; +extern uintptr_t + nodedbg_offset_Environment__req_wrap_queue___Environment_ReqWrapQueue; +extern uintptr_t nodedbg_offset_ExternalString__data__uintptr_t; +extern uintptr_t nodedbg_offset_ListNode_ReqWrap__next___uintptr_t; +extern uintptr_t nodedbg_offset_ReqWrap__req_wrap_queue___ListNode_ReqWrapQueue; +extern uintptr_t nodedbg_offset_ListNode_HandleWrap__next___uintptr_t; +extern uintptr_t + nodedbg_offset_Environment_ReqWrapQueue__head___ListNode_ReqWrapQueue; +extern uintptr_t + nodedbg_offset_BaseObject__persistent_handle___v8_Persistent_v8_Object; +} class DebugSymbolsTest : public EnvironmentTestFixture {}; From 28f3ffba0fd732fb8faa49e02049dfb1ee5c5911 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Sun, 11 Feb 2018 19:20:42 -0500 Subject: [PATCH 177/193] timers: add helper fn for async init There are currently 3 places in Timers where the exact same code appears. Instead create a helper function that does the same job of setting asyncId & triggerAsyncId, as well as calling emitInit. PR-URL: https://github.com/nodejs/node/pull/18825 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- lib/internal/timers.js | 18 ++++++++++-------- lib/timers.js | 23 +++-------------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/lib/internal/timers.js b/lib/internal/timers.js index 0c140811f8ce88..8c1a87a65f4725 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -24,6 +24,7 @@ module.exports = { async_id_symbol, trigger_async_id_symbol, Timeout, + initAsyncResource, refreshFnSymbol, setUnrefTimeout, validateTimerDuration @@ -37,6 +38,14 @@ function getTimers() { return timers; } +function initAsyncResource(resource, type) { + const asyncId = resource[async_id_symbol] = newAsyncId(); + const triggerAsyncId = + resource[trigger_async_id_symbol] = getDefaultTriggerAsyncId(); + if (initHooksExist()) + emitInit(asyncId, type, triggerAsyncId, resource); +} + // Timer constructor function. // The entire prototype is defined in lib/timers.js function Timeout(callback, after, args, isRepeat, isUnrefed) { @@ -66,14 +75,7 @@ function Timeout(callback, after, args, isRepeat, isUnrefed) { this[unrefedSymbol] = isUnrefed; - this[async_id_symbol] = newAsyncId(); - this[trigger_async_id_symbol] = getDefaultTriggerAsyncId(); - if (initHooksExist()) { - emitInit(this[async_id_symbol], - 'Timeout', - this[trigger_async_id_symbol], - this); - } + initAsyncResource(this, 'Timeout'); } Timeout.prototype[refreshFnSymbol] = function refresh() { diff --git a/lib/timers.js b/lib/timers.js index 145550b7b5666b..bc98718fdfac02 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -30,6 +30,7 @@ const { async_id_symbol, trigger_async_id_symbol, Timeout, + initAsyncResource, validateTimerDuration } = require('internal/timers'); const internalUtil = require('internal/util'); @@ -39,12 +40,8 @@ const util = require('util'); const errors = require('internal/errors'); const debug = util.debuglog('timer'); const { - getDefaultTriggerAsyncId, - newAsyncId, - initHooksExist, destroyHooksExist, // The needed emit*() functions. - emitInit, emitBefore, emitAfter, emitDestroy @@ -188,14 +185,7 @@ function insert(item, unrefed, start) { if (!item[async_id_symbol] || item._destroyed) { item._destroyed = false; - item[async_id_symbol] = newAsyncId(); - item[trigger_async_id_symbol] = getDefaultTriggerAsyncId(); - if (initHooksExist()) { - emitInit(item[async_id_symbol], - 'Timeout', - item[trigger_async_id_symbol], - item); - } + initAsyncResource(item, 'Timeout'); } L.append(list, item); @@ -720,14 +710,7 @@ const Immediate = class Immediate { this._destroyed = false; this[kRefed] = false; - this[async_id_symbol] = newAsyncId(); - this[trigger_async_id_symbol] = getDefaultTriggerAsyncId(); - if (initHooksExist()) { - emitInit(this[async_id_symbol], - 'Immediate', - this[trigger_async_id_symbol], - this); - } + initAsyncResource(this, 'Immediate'); this.ref(); immediateInfo[kCount]++; From de0ed84f04d3ef2fd003d1b08886a86b1502b269 Mon Sep 17 00:00:00 2001 From: Kyle Farnung Date: Fri, 16 Feb 2018 16:00:23 -0800 Subject: [PATCH 178/193] tls: tls_wrap causes debug assert in vector When using a debug build (on Windows specifically) the error case for tls_wrap causes an assert to fire because the index being passed is outside the bounds of the vector. The fix is to switch to iterators. PR-URL: https://github.com/nodejs/node/pull/18830 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Minwoo Jung Reviewed-By: Colin Ihrig --- src/tls_wrap.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index f2a84b83f32de2..a889279f6c624b 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -491,8 +491,8 @@ bool TLSWrap::ClearIn() { // This can be skipped in the error case because no further writes // would succeed anyway. pending_cleartext_input_.insert(pending_cleartext_input_.end(), - &buffers[i], - &buffers[buffers.size()]); + buffers.begin() + i, + buffers.end()); } return false; From 469036add4e0e879de3e9307bca4d22a1d547793 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Mon, 19 Feb 2018 23:26:45 +0200 Subject: [PATCH 179/193] doc: fix typo in http2.md PR-URL: https://github.com/nodejs/node/pull/18872 Reviewed-By: Colin Ihrig Reviewed-By: Michael Dawson --- doc/api/http2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/http2.md b/doc/api/http2.md index c73ed3b0bd2fb1..efacbe149b7860 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1718,7 +1718,7 @@ changes: Http2ServerRequest class to use. Useful for extending the original `Http2ServerRequest`. **Default:** `Http2ServerRequest` - * `Http2ServerResponse` {htt2.Http2ServerResponse} Specifies the + * `Http2ServerResponse` {http2.Http2ServerResponse} Specifies the Http2ServerResponse class to use. Useful for extending the original `Http2ServerResponse`. **Default:** `Http2ServerResponse` From 2caa1f54582902a4feae9a4c7a2e30c6718f7005 Mon Sep 17 00:00:00 2001 From: Justin Lee Date: Mon, 19 Feb 2018 15:02:38 -0800 Subject: [PATCH 180/193] doc: fix broken link in pull-requests.md PR-URL: https://github.com/nodejs/node/pull/18873 Reviewed-By: Vse Mozhet Byt Reviewed-By: Colin Ihrig Reviewed-By: Michael Dawson --- doc/guides/contributing/pull-requests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/guides/contributing/pull-requests.md b/doc/guides/contributing/pull-requests.md index 3d7c548bbd3022..4fd2de923a0e48 100644 --- a/doc/guides/contributing/pull-requests.md +++ b/doc/guides/contributing/pull-requests.md @@ -660,4 +660,4 @@ you can take a look at the [guide for writing tests in Node.js]: ../writing-tests.md [https://ci.nodejs.org/]: https://ci.nodejs.org/ [IRC in the #node-dev channel]: https://webchat.freenode.net?channels=node-dev&uio=d4 -[Onboarding guide]: ../onboarding.md +[Onboarding guide]: ../../onboarding.md From e83adf87f58c7144e745ed18a79202577739b97c Mon Sep 17 00:00:00 2001 From: dustinnewman98 Date: Sat, 17 Feb 2018 16:09:05 -0800 Subject: [PATCH 181/193] doc: improved documentation for fs.unlink() Refs: https://github.com/nodejs/node/issues/11135 PR-URL: https://github.com/nodejs/node/pull/18843 Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Benjamin Gruenbaum Reviewed-By: Ruben Bridgewater Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Luigi Pinca Reviewed-By: Matheus Marchini --- doc/api/fs.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index a4a9e5fd3f2096..ae559d0ecff744 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -2749,8 +2749,21 @@ changes: * `callback` {Function} * `err` {Error} -Asynchronous unlink(2). No arguments other than a possible exception are given -to the completion callback. +Asynchronously removes a file or symbolic link. No arguments other than a +possible exception are given to the completion callback. + +```js +// Assuming that 'path/file.txt' is a regular file. +fs.unlink('path/file.txt', (err) => { + if (err) throw err; + console.log('path/file.txt was deleted'); +}); +``` + +`fs.unlink()` will not work on a directory, empty or otherwise. To remove a +directory, use [`fs.rmdir()`][]. + +See also: unlink(2) ## fs.unlinkSync(path) + ```js const Countdown = require('../common/countdown'); @@ -526,7 +526,7 @@ Returns the result of The http2.js module provides a handful of utilities for creating mock HTTP/2 frames for testing of HTTP/2 endpoints - + ```js const http2 = require('../common/http2'); ``` @@ -536,7 +536,7 @@ const http2 = require('../common/http2'); The `http2.Frame` is a base class that creates a `Buffer` containing a serialized HTTP/2 frame header. - + ```js // length is a 24-bit unsigned integer // type is an 8-bit unsigned integer identifying the frame type @@ -555,7 +555,7 @@ The serialized `Buffer` may be retrieved using the `frame.data` property. The `http2.DataFrame` is a subclass of `http2.Frame` that serializes a `DATA` frame. - + ```js // id is the 32-bit stream identifier // payload is a Buffer containing the DATA payload @@ -572,7 +572,7 @@ socket.write(frame.data); The `http2.HeadersFrame` is a subclass of `http2.Frame` that serializes a `HEADERS` frame. - + ```js // id is the 32-bit stream identifier // payload is a Buffer containing the HEADERS payload (see either @@ -590,7 +590,7 @@ socket.write(frame.data); The `http2.SettingsFrame` is a subclass of `http2.Frame` that serializes an empty `SETTINGS` frame. - + ```js // ack is a boolean indicating whether or not to set the ACK flag. const frame = new http2.SettingsFrame(ack); @@ -603,7 +603,7 @@ socket.write(frame.data); Set to a `Buffer` instance that contains a minimal set of serialized HTTP/2 request headers to be used as the payload of a `http2.HeadersFrame`. - + ```js const frame = new http2.HeadersFrame(1, http2.kFakeRequestHeaders, 0, true); @@ -615,7 +615,7 @@ socket.write(frame.data); Set to a `Buffer` instance that contains a minimal set of serialized HTTP/2 response headers to be used as the payload a `http2.HeadersFrame`. - + ```js const frame = new http2.HeadersFrame(1, http2.kFakeResponseHeaders, 0, true); @@ -627,7 +627,7 @@ socket.write(frame.data); Set to a `Buffer` containing the preamble bytes an HTTP/2 client must send upon initial establishment of a connection. - + ```js socket.write(http2.kClientMagic); ``` diff --git a/test/common/benchmark.js b/test/common/benchmark.js index 6496da1cfb9fe5..1fd4476ba55a35 100644 --- a/test/common/benchmark.js +++ b/test/common/benchmark.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; diff --git a/test/common/countdown.js b/test/common/countdown.js index 5fcb77c4ed66a0..67252657ec28b7 100644 --- a/test/common/countdown.js +++ b/test/common/countdown.js @@ -1,4 +1,5 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ + 'use strict'; const assert = require('assert'); diff --git a/test/common/dns.js b/test/common/dns.js index 69c67ac541cf98..07f84d7a3703c1 100644 --- a/test/common/dns.js +++ b/test/common/dns.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; const assert = require('assert'); diff --git a/test/common/duplexpair.js b/test/common/duplexpair.js index ea5bd86a041b24..fb4faca5483b76 100644 --- a/test/common/duplexpair.js +++ b/test/common/duplexpair.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; const { Duplex } = require('stream'); const assert = require('assert'); diff --git a/test/common/fixtures.js b/test/common/fixtures.js index b4b7c042e805a9..b45e5bc8091865 100644 --- a/test/common/fixtures.js +++ b/test/common/fixtures.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; const path = require('path'); diff --git a/test/common/http2.js b/test/common/http2.js index 1d4c269fffd5b5..0f3378e9b80f63 100644 --- a/test/common/http2.js +++ b/test/common/http2.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; // An HTTP/2 testing tool used to create mock frames for direct testing diff --git a/test/common/index.js b/test/common/index.js index 1fc029292abb10..54b146814a453a 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -19,7 +19,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -/* eslint-disable required-modules, crypto-check */ +/* eslint-disable node-core/required-modules, node-core/crypto-check */ 'use strict'; const process = global.process; // Some tests tamper with the process global. const path = require('path'); diff --git a/test/common/index.mjs b/test/common/index.mjs index 00eceb79d4c003..6d6fe4997bdb71 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import assert from 'assert'; diff --git a/test/common/internet.js b/test/common/internet.js index 48b532ca8e6606..3880aa114e3743 100644 --- a/test/common/internet.js +++ b/test/common/internet.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; // Utilities for internet-related tests diff --git a/test/common/shared-lib-util.js b/test/common/shared-lib-util.js index 7ff7518ac31e6d..5699c4f74c6463 100644 --- a/test/common/shared-lib-util.js +++ b/test/common/shared-lib-util.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; const path = require('path'); diff --git a/test/common/tmpdir.js b/test/common/tmpdir.js index ed731b3e7a1ffb..d0221abbb2f069 100644 --- a/test/common/tmpdir.js +++ b/test/common/tmpdir.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; const fs = require('fs'); diff --git a/test/common/wpt.js b/test/common/wpt.js index 52d8b7a580400c..7cd644dc88c097 100644 --- a/test/common/wpt.js +++ b/test/common/wpt.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; const assert = require('assert'); diff --git a/test/es-module/esm-snapshot-mutator.js b/test/es-module/esm-snapshot-mutator.js index a0dfa0c28a92bd..6c9a707306fe14 100644 --- a/test/es-module/esm-snapshot-mutator.js +++ b/test/es-module/esm-snapshot-mutator.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; const shouldSnapshotFilePath = require.resolve('./esm-snapshot.js'); require('./esm-snapshot.js'); diff --git a/test/es-module/esm-snapshot.js b/test/es-module/esm-snapshot.js index 2c3c3a459a738b..f52c6f3adff769 100644 --- a/test/es-module/esm-snapshot.js +++ b/test/es-module/esm-snapshot.js @@ -1,3 +1,3 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; module.exports = 1; diff --git a/test/es-module/test-esm-example-loader.js b/test/es-module/test-esm-example-loader.js index 9d1348292cd5a5..f7f0fd059a4d76 100644 --- a/test/es-module/test-esm-example-loader.js +++ b/test/es-module/test-esm-example-loader.js @@ -1,5 +1,5 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/example-loader.mjs -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import assert from 'assert'; import ok from './test-esm-ok.mjs'; diff --git a/test/es-module/test-esm-forbidden-globals.mjs b/test/es-module/test-esm-forbidden-globals.mjs index d3e92b9238adba..d92df1611f043e 100644 --- a/test/es-module/test-esm-forbidden-globals.mjs +++ b/test/es-module/test-esm-forbidden-globals.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ if (typeof arguments !== 'undefined') { throw new Error('not an ESM'); diff --git a/test/es-module/test-esm-json.mjs b/test/es-module/test-esm-json.mjs index 39279b74e5407c..5b432e03958600 100644 --- a/test/es-module/test-esm-json.mjs +++ b/test/es-module/test-esm-json.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import '../common/index'; import assert from 'assert'; import ok from './test-esm-ok.mjs'; diff --git a/test/es-module/test-esm-loader-dependency.mjs b/test/es-module/test-esm-loader-dependency.mjs index 5d05118dbf2879..260bf613a75ed8 100644 --- a/test/es-module/test-esm-loader-dependency.mjs +++ b/test/es-module/test-esm-loader-dependency.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/loader-with-dep.mjs -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import './test-esm-ok.mjs'; // We just test that this module doesn't fail loading diff --git a/test/es-module/test-esm-main-lookup.mjs b/test/es-module/test-esm-main-lookup.mjs index 7c81cb647cff38..12f12c845caedf 100644 --- a/test/es-module/test-esm-main-lookup.mjs +++ b/test/es-module/test-esm-main-lookup.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import assert from 'assert'; import main from '../fixtures/es-modules/pjson-main'; diff --git a/test/es-module/test-esm-named-exports.mjs b/test/es-module/test-esm-named-exports.mjs index c70e16e2167722..9698ae3d9c0907 100644 --- a/test/es-module/test-esm-named-exports.mjs +++ b/test/es-module/test-esm-named-exports.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import '../common/index'; import { readFile } from 'fs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-namespace.mjs b/test/es-module/test-esm-namespace.mjs index f6e550c2e5245e..6a5ee28a54520f 100644 --- a/test/es-module/test-esm-namespace.mjs +++ b/test/es-module/test-esm-namespace.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import '../common/index'; import * as fs from 'fs'; diff --git a/test/es-module/test-esm-ok.mjs b/test/es-module/test-esm-ok.mjs index 6712e1ab7dfca1..49de5c47ec23e7 100644 --- a/test/es-module/test-esm-ok.mjs +++ b/test/es-module/test-esm-ok.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ const isJs = true; export default isJs; diff --git a/test/es-module/test-esm-preserve-symlinks-not-found-plain.mjs b/test/es-module/test-esm-preserve-symlinks-not-found-plain.mjs index bfeb71ef3a607a..2ca0f5658119e9 100644 --- a/test/es-module/test-esm-preserve-symlinks-not-found-plain.mjs +++ b/test/es-module/test-esm-preserve-symlinks-not-found-plain.mjs @@ -1,3 +1,3 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import './not-found.js'; diff --git a/test/es-module/test-esm-preserve-symlinks-not-found.mjs b/test/es-module/test-esm-preserve-symlinks-not-found.mjs index 22c888028e7ba3..5119957bae7c6a 100644 --- a/test/es-module/test-esm-preserve-symlinks-not-found.mjs +++ b/test/es-module/test-esm-preserve-symlinks-not-found.mjs @@ -1,3 +1,3 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import './not-found'; diff --git a/test/es-module/test-esm-resolve-hook.mjs b/test/es-module/test-esm-resolve-hook.mjs index dd7ac80bec4331..e2d20a42d425dc 100644 --- a/test/es-module/test-esm-resolve-hook.mjs +++ b/test/es-module/test-esm-resolve-hook.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/js-loader.mjs -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import { namedExport } from '../fixtures/es-module-loaders/js-as-esm.js'; import assert from 'assert'; import ok from './test-esm-ok.mjs'; diff --git a/test/es-module/test-esm-shared-loader-dep.mjs b/test/es-module/test-esm-shared-loader-dep.mjs index 970bfd7121a721..03668cbc993a2f 100644 --- a/test/es-module/test-esm-shared-loader-dep.mjs +++ b/test/es-module/test-esm-shared-loader-dep.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/loader-shared-dep.mjs -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import assert from 'assert'; import './test-esm-ok.mjs'; import dep from '../fixtures/es-module-loaders/loader-dep.js'; diff --git a/test/es-module/test-esm-shebang.mjs b/test/es-module/test-esm-shebang.mjs index 43cc0f8367d8a2..96cec8ea98e921 100644 --- a/test/es-module/test-esm-shebang.mjs +++ b/test/es-module/test-esm-shebang.mjs @@ -1,6 +1,6 @@ #! }]) // isn't js // Flags: --experimental-modules -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ const isJs = true; export default isJs; diff --git a/test/es-module/test-esm-snapshot.mjs b/test/es-module/test-esm-snapshot.mjs index 878be79a34044c..4d3cf245a3ce9d 100644 --- a/test/es-module/test-esm-snapshot.mjs +++ b/test/es-module/test-esm-snapshot.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-modules -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ import '../common/index'; import './esm-snapshot-mutator'; import one from './esm-snapshot'; diff --git a/test/parallel/test-accessor-properties.js b/test/parallel/test-accessor-properties.js index b4ebf30f9b0440..713be7eac203a6 100644 --- a/test/parallel/test-accessor-properties.js +++ b/test/parallel/test-accessor-properties.js @@ -51,7 +51,7 @@ const UDP = process.binding('udp_wrap').UDP; 'object' ); - if (common.hasCrypto) { // eslint-disable-line crypto-check + if (common.hasCrypto) { // eslint-disable-line node-core/crypto-check // There are accessor properties in crypto too const crypto = process.binding('crypto'); diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index c5a2bfe8561fdb..2ea041e1e28dbd 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -23,7 +23,7 @@ 'use strict'; -/* eslint-disable prefer-common-expectserror */ +/* eslint-disable node-core/prefer-common-expectserror */ const common = require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-buffer-alloc.js b/test/parallel/test-buffer-alloc.js index bf818ed0548065..30baa30319f116 100644 --- a/test/parallel/test-buffer-alloc.js +++ b/test/parallel/test-buffer-alloc.js @@ -915,7 +915,7 @@ common.expectsError( } } -if (common.hasCrypto) { // eslint-disable-line crypto-check +if (common.hasCrypto) { // eslint-disable-line node-core/crypto-check // Test truncation after decode const crypto = require('crypto'); diff --git a/test/parallel/test-buffer-concat.js b/test/parallel/test-buffer-concat.js index fb290568309ee2..9d6c6c7d351e45 100644 --- a/test/parallel/test-buffer-concat.js +++ b/test/parallel/test-buffer-concat.js @@ -62,7 +62,7 @@ function assertWrongList(value) { }); } -// eslint-disable-next-line crypto-check +// eslint-disable-next-line node-core/crypto-check const random10 = common.hasCrypto ? require('crypto').randomBytes(10) : Buffer.alloc(10, 1); diff --git a/test/parallel/test-global-console-exists.js b/test/parallel/test-global-console-exists.js index 1434b76e12696e..f2e7ba5a9aa3a0 100644 --- a/test/parallel/test-global-console-exists.js +++ b/test/parallel/test-global-console-exists.js @@ -1,4 +1,4 @@ -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; diff --git a/test/parallel/test-http-invalid-urls.js b/test/parallel/test-http-invalid-urls.js index 51e680071a92a3..9a5567aab897f8 100644 --- a/test/parallel/test-http-invalid-urls.js +++ b/test/parallel/test-http-invalid-urls.js @@ -1,4 +1,4 @@ -/* eslint-disable crypto-check */ +/* eslint-disable node-core/crypto-check */ 'use strict'; diff --git a/test/parallel/test-querystring.js b/test/parallel/test-querystring.js index 0dd66d0eb83c81..f4046c33a11d62 100644 --- a/test/parallel/test-querystring.js +++ b/test/parallel/test-querystring.js @@ -125,9 +125,9 @@ const qsColonTestCases = [ function extendedFunction() {} extendedFunction.prototype = { a: 'b' }; const qsWeirdObjects = [ - // eslint-disable-next-line no-unescaped-regexp-dot + // eslint-disable-next-line node-core/no-unescaped-regexp-dot [{ regexp: /./g }, 'regexp=', { 'regexp': '' }], - // eslint-disable-next-line no-unescaped-regexp-dot + // eslint-disable-next-line node-core/no-unescaped-regexp-dot [{ regexp: new RegExp('.', 'g') }, 'regexp=', { 'regexp': '' }], [{ fn: () => {} }, 'fn=', { 'fn': '' }], [{ fn: new Function('') }, 'fn=', { 'fn': '' }], diff --git a/test/parallel/test-regression-object-prototype.js b/test/parallel/test-regression-object-prototype.js index 01de440344d352..821c2af584ae3b 100644 --- a/test/parallel/test-regression-object-prototype.js +++ b/test/parallel/test-regression-object-prototype.js @@ -19,7 +19,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -/* eslint-disable required-modules */ +/* eslint-disable node-core/required-modules */ 'use strict'; Object.prototype.xadsadsdasasdxx = function() { diff --git a/test/sequential/test-async-wrap-getasyncid.js b/test/sequential/test-async-wrap-getasyncid.js index 1877d53dbfd3ae..ce9465d94af4ef 100644 --- a/test/sequential/test-async-wrap-getasyncid.js +++ b/test/sequential/test-async-wrap-getasyncid.js @@ -92,7 +92,7 @@ function testInitialized(req, ctor_name) { } -if (common.hasCrypto) { // eslint-disable-line crypto-check +if (common.hasCrypto) { // eslint-disable-line node-core/crypto-check const crypto = require('crypto'); // The handle for PBKDF2 and RandomBytes isn't returned by the function call, @@ -240,7 +240,7 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check } -if (common.hasCrypto) { // eslint-disable-line crypto-check +if (common.hasCrypto) { // eslint-disable-line node-core/crypto-check const { TCP, constants: TCPConstants } = process.binding('tcp_wrap'); const tcp = new TCP(TCPConstants.SOCKET); diff --git a/test/sequential/test-inspector-overwrite-config.js b/test/sequential/test-inspector-overwrite-config.js index ecb14c6638edb5..2a00b1e0796141 100644 --- a/test/sequential/test-inspector-overwrite-config.js +++ b/test/sequential/test-inspector-overwrite-config.js @@ -8,7 +8,7 @@ // We cannot do a check for the inspector because the configuration variables // were reset/removed by overwrite-config-preload-module.js. -/* eslint-disable inspector-check */ +/* eslint-disable node-core/inspector-check */ const common = require('../common'); const assert = require('assert'); diff --git a/tools/node_modules/eslint-plugin-node-core/index.js b/tools/node_modules/eslint-plugin-node-core/index.js new file mode 100644 index 00000000000000..e27945688ee691 --- /dev/null +++ b/tools/node_modules/eslint-plugin-node-core/index.js @@ -0,0 +1,24 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +let cache; +module.exports = { + get rules() { + const RULES_DIR = module.exports.RULES_DIR; + if (!RULES_DIR) + return {}; + + if (!cache) { + cache = {}; + const files = fs.readdirSync(RULES_DIR) + .filter(filename => filename.endsWith('.js')) + for (const file of files) { + const name = file.slice(0, -3); + cache[name] = require(path.resolve(RULES_DIR, file)); + } + } + return cache; + }, +}; diff --git a/vcbuild.bat b/vcbuild.bat index a3d32055de49bd..88693a71cbdbcf 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -514,7 +514,7 @@ if defined lint_js_ci goto lint-js-ci if not defined lint_js goto exit if not exist tools\node_modules\eslint goto no-lint echo running lint-js -%config%\node tools\node_modules\eslint\bin\eslint.js --cache --rule "linebreak-style: 0" --rulesdir=tools\eslint-rules --ext=.js,.mjs,.md benchmark doc lib test tools +%config%\node tools\node_modules\eslint\bin\eslint.js --cache --rule "linebreak-style: 0" --ext=.js,.mjs,.md benchmark doc lib test tools goto exit :lint-js-ci From d28edf97fa5cb863b5497cc3964c103f782d8b62 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Tue, 20 Feb 2018 01:26:58 +0200 Subject: [PATCH 188/193] doc: fix nits in tools/doc/README.md * Sync format schemes with the current doc state. * Lowercase primitive types. * Fix typos and unify the style. * Remove tautological info. PR-URL: https://github.com/nodejs/node/pull/18874 Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: Gibson Fahnestock --- tools/doc/README.md | 77 ++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/tools/doc/README.md b/tools/doc/README.md index 0535243e92f63b..2d5317db9e6fd7 100644 --- a/tools/doc/README.md +++ b/tools/doc/README.md @@ -1,56 +1,55 @@ Here's how the node docs work. -1:1 relationship from `lib/.js` to `doc/api/.md` +1:1 relationship from `lib/.js` to `doc/api/.md`. Each type of heading has a description block. ```md -## module - +# module + + -> Stability: 3 - Stable +> Stability: 2 - Stable -description and examples. +A description and examples. -### module.property +## module.property -* Type +* {type} -description of the property. +A description of the property. -### module.someFunction(x, y, [z=100]) +## module.someFunction(x, y, [z=100]) -* `x` {String} the description of the string -* `y` {Boolean} Should I stay or should I go? -* `z` {Number} How many zebras to bring. +* `x` {string} The description of the string. +* `y` {boolean} Should I stay or should I go? +* `z` {number} How many zebras to bring. A description of the function. -### module.someNewFunction(x) +## module.someNewFunction(x) -* `x` {String} the description of the string +* `x` {string} The description of the string. This feature is not in a release yet. -### Event: 'blerg' +## Event: 'blerg' -* Argument: SomeClass object. +* `anArg` {type} A description of the listener argument. -Modules don't usually raise events on themselves. `cluster` is the +Modules don't usually raise events on themselves. `cluster` is the only exception. ## Class: SomeClass @@ -58,50 +57,50 @@ only exception. added: v0.10.0 --> -description of the class. +A description of the class. -### Class Method: SomeClass.classMethod(anArg) +### SomeClass.classMethod(anArg) -* `anArg` {Object} Just an argument - * `field` {String} anArg can have this field. - * `field2` {Boolean} Another field. Default: `false`. -* Return: {Boolean} `true` if it worked. +* `anArg` {Object} Just an argument. + * `field` {string} `anArg` can have this field. + * `field2` {boolean} Another field. Default: `false`. +* Returns: {boolean} `true` if it worked. -Description of the method for humans. +A description of the method for humans. -### someClass.nextSibling() +### SomeClass.nextSibling() -* Return: {SomeClass object | null} The next someClass in line. +* Returns: {SomeClass | null} The next `SomeClass` in line. -### someClass.someProperty +### SomeClass.someProperty -* String +* {string} -The indication of what someProperty is. +The indication of what `someProperty` is. ### Event: 'grelb' -* `isBlerg` {Boolean} +* `isBlerg` {boolean} -This event is emitted on instances of SomeClass, not on the module itself. +This event is emitted on instances of `SomeClass`, not on the module itself. ``` -* Classes have (description, Properties, Methods, Events) -* Events have (list of arguments, description) -* Functions have (list of arguments, description) -* Methods have (list of arguments, description) -* Modules have (description, Properties, Functions, Classes, Examples) -* Properties have (type, description) +* Classes have (description, Properties, Methods, Events). +* Events have (list of arguments, description). +* Functions have (list of arguments, description). +* Methods have (list of arguments, description). +* Modules have (description, Properties, Functions, Classes, Examples). +* Properties have (type, description). From 1b83a9df054a0d5bac28fef96bd0598d86dae6d8 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sat, 17 Feb 2018 19:25:07 -0800 Subject: [PATCH 189/193] doc: update onboarding.md for faster exercise completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note that the CI run for the exercise can be minimal. PR-URL: https://github.com/nodejs/node/pull/18846 Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Michaël Zasso Reviewed-By: Matheus Marchini Reviewed-By: Jon Moss Reviewed-By: Gibson Fahnestock Reviewed-By: Joyee Cheung Reviewed-By: Colin Ihrig Reviewed-By: Anna Henningsen Reviewed-By: Michael Dawson --- doc/onboarding.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/onboarding.md b/doc/onboarding.md index 296f9db7d02ef8..e2a05f2ccd17eb 100644 --- a/doc/onboarding.md +++ b/doc/onboarding.md @@ -200,7 +200,10 @@ onboarding session. * Collaborators are in alphabetical order by GitHub username. * Optionally, include your personal pronouns. * Label your pull request with the `doc` subsystem label. -* Run CI on your PR. +* Run CI on the PR. Because the PR does not affect any code, use the + `node-test-pull-request-lite` CI task. Alternatively, use the usual + `node-test-pull-request` CI task and cancel it after the linter and one other + subtask have passed. * After one or two approvals, land the PR (PRs of this type do not need to wait for 48/72 hours to land). * Be sure to add the `PR-URL: ` and appropriate `Reviewed-By:` From e53275d819fb21d4bb15a27a714f134551233cf9 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sat, 17 Feb 2018 20:06:42 -0800 Subject: [PATCH 190/193] doc: fix minor grammar/typographical issues in onboarding.md PR-URL: https://github.com/nodejs/node/pull/18847 Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Minwoo Jung Reviewed-By: Jon Moss Reviewed-By: Colin Ihrig Reviewed-By: Matheus Marchini --- doc/onboarding.md | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/doc/onboarding.md b/doc/onboarding.md index e2a05f2ccd17eb..7f262e26665906 100644 --- a/doc/onboarding.md +++ b/doc/onboarding.md @@ -36,9 +36,9 @@ onboarding session. * git: * Make sure you have whitespace=fix: `git config --global --add apply.whitespace fix` - * Always continue to PR from your own github fork - * Branches in the nodejs/node repository are only for release lines - * [See "Updating Node.js from Upstream"][] + * Always continue to PR from your own GitHub fork + * Branches in the `nodejs/node` repository are only for release lines + * See [Updating Node.js from Upstream][] * Make a new branch for each PR you submit. * Membership: Consider making your membership in the Node.js GitHub organization public. This makes it easier to identify Collaborators. @@ -68,8 +68,8 @@ onboarding session. * The best outcome is for people who come to our issue tracker to feel like they can come back again. -* We have a [Code of Conduct][] that you are expected to follow *and* hold - others accountable to +* You are expected to follow *and* hold others accountable to the + [Code of Conduct][]. ## Managing the issue tracker @@ -89,8 +89,8 @@ onboarding session. * `semver-{minor,major}`: * If a change has the remote *chance* of breaking something, use the `semver-major` label - * When adding a semver label, add a comment explaining why you're adding it. - Do it right away so you don't forget! + * When adding a `semver-*` label, add a comment explaining why you're adding + it. Do it right away so you don't forget! * [**See "Who to CC in issues"**](./onboarding-extras.md#who-to-cc-in-issues) * This will come more naturally over time @@ -114,10 +114,9 @@ onboarding session. * Secondary (but not far off) is for the person submitting code to succeed. A pull request from a new contributor is an opportunity to grow the community. * Review a bit at a time. Do not overwhelm new contributors. - * It is tempting to micro-optimize and make everything about relative - performance. Don't succumb to that temptation. We change V8 often. - Techniques that provide improved performance today may be unnecessary in - the future. + * It is tempting to micro-optimize. Don't succumb to that temptation. We + change V8 often. Techniques that provide improved performance today may be + unnecessary in the future. * Be aware: Your opinion carries a lot of weight! * Nits (requests for small changes that are not essential) are fine, but try to avoid stalling the pull request. @@ -128,7 +127,7 @@ onboarding session. by tools but are not, consider implementing the necessary tooling. * Minimum wait for comments time * There is a minimum waiting time which we try to respect for non-trivial - changes, so that people who may have important input in such a distributed + changes so that people who may have important input in such a distributed project are able to respond. * For non-trivial changes, leave the pull request open for at least 48 hours (72 hours on a weekend). @@ -151,12 +150,12 @@ onboarding session. * What belongs in Node.js: * Opinions vary – it’s good to have a broad collaborator base for that reason! - * If Node.js itself needs it (due to historic reasons), then it belongs in - Node.js - * That is to say, url is there because of http, freelist is there because of - http, etc. + * If Node.js itself needs it (due to historical reasons), then it belongs in + Node.js. + * That is to say, `url` is there because of `http`, `freelist` is there + because of `http`, etc. * Things that cannot be done outside of core, or only with significant pain - (for example `async_hooks`) + such as `async_hooks`. * Continuous Integration (CI) Testing: * [https://ci.nodejs.org/](https://ci.nodejs.org/) @@ -226,9 +225,9 @@ onboarding session. * [https://github.com/nodejs/LTS](https://github.com/nodejs/LTS) * [https://github.com/nodejs/citgm](https://github.com/nodejs/citgm) * The Node.js Foundation hosts regular summits for active contributors to the - Node.js project, where we have face-to-face discussion about our work on the - project. The foundation has travel funds to cover participants' expenses - including accommodation, transportation, visa fees etc. if needed. Check out + Node.js project, where we have face-to-face discussions about our work on the + project. The Foundation has travel funds to cover participants' expenses + including accommodations, transportation, visa fees, etc. if needed. Check out the [summit](https://github.com/nodejs/summit) repository for details. [Code of Conduct]: https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md @@ -238,4 +237,4 @@ onboarding session. [Landing Pull Requests]: https://github.com/nodejs/node/blob/master/COLLABORATOR_GUIDE.md#landing-pull-requests [https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0]: https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0 [Publicizing or hiding organization membership]: https://help.github.com/articles/publicizing-or-hiding-organization-membership/ -[See "Updating Node.js from Upstream"]: ./onboarding-extras.md#updating-nodejs-from-upstream +[Updating Node.js from Upstream]: ./onboarding-extras.md#updating-nodejs-from-upstream From 6da93153aa3e24326d076044ce25c9138546be3f Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 21 Feb 2018 12:33:39 +0100 Subject: [PATCH 191/193] build: add cmake support --- .gitignore | 5 +- CMakeLists.txt | 103 ++ Makefile | 80 +- cmake/NOTES.md | 18 + cmake/TODO.md | 6 + cmake/cares/CMakeLists.txt | 126 +++ cmake/common.cmake | 42 + cmake/gtest/CMakeLists.txt | 36 + cmake/http_parser/CMakeLists.txt | 7 + cmake/icu/CMakeLists.txt | 6 + cmake/icu/common/CMakeLists.txt | 388 +++++++ cmake/icu/i18n/CMakeLists.txt | 353 ++++++ cmake/icu/tools/CMakeLists.txt | 94 ++ cmake/nghttp2/CMakeLists.txt | 41 + cmake/node/CMakeLists.txt | 408 +++++++ cmake/openssl/CMakeLists.txt | 1218 +++++++++++++++++++++ cmake/uv/CMakeLists.txt | 211 ++++ cmake/v8/CMakeLists.txt | 1748 ++++++++++++++++++++++++++++++ cmake/v8/libbase/CMakeLists.txt | 111 ++ cmake/zlib/CMakeLists.txt | 37 + configure | 109 +- node.gyp | 1 + tools/install.py | 8 +- tools/js2c.py | 13 +- tools/test.py | 4 + 25 files changed, 5110 insertions(+), 63 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 cmake/NOTES.md create mode 100644 cmake/TODO.md create mode 100644 cmake/cares/CMakeLists.txt create mode 100644 cmake/common.cmake create mode 100644 cmake/gtest/CMakeLists.txt create mode 100644 cmake/http_parser/CMakeLists.txt create mode 100644 cmake/icu/CMakeLists.txt create mode 100644 cmake/icu/common/CMakeLists.txt create mode 100644 cmake/icu/i18n/CMakeLists.txt create mode 100644 cmake/icu/tools/CMakeLists.txt create mode 100644 cmake/nghttp2/CMakeLists.txt create mode 100644 cmake/node/CMakeLists.txt create mode 100644 cmake/openssl/CMakeLists.txt create mode 100644 cmake/uv/CMakeLists.txt create mode 100644 cmake/v8/CMakeLists.txt create mode 100644 cmake/v8/libbase/CMakeLists.txt create mode 100644 cmake/zlib/CMakeLists.txt diff --git a/.gitignore b/.gitignore index d619bb9a9caa22..9cbd65efbebb02 100644 --- a/.gitignore +++ b/.gitignore @@ -29,8 +29,8 @@ tmp/ test/tmp*/ iojs iojs_g -node -node_g +/node +/node_g *.swp .benchmark_reports icu_config.gypi @@ -39,6 +39,7 @@ node_trace.*.log coverage/ /out +/out.cmake # various stuff that VC++ produces/uses Debug/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000000000..3d5143622fc56f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.0) +find_package(PythonInterp) + +include(cmake/common.cmake) +project(node) + +# Reset this number to 0 on major V8 upgrades. +# Increment by one for each non-official patch applied to deps/v8. +set(v8_embedder_string "-node.11") +set(v8_postmortem_support $) + +set(CMAKE_VERBOSE_MAKEFILE ON) + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "RelWithDebInfo") +endif() + +if(NOT MSVC AND CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_C_FLAGS "-g -Og ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "-g -Og ${CMAKE_CXX_FLAGS}") +endif() + +if(MSVC) + #add_definitions(BUILDING_UV_SHARED=1) + #add_definitions(BUILDING_V8_SHARED=1) + add_definitions(_HAS_EXCEPTIONS=0) + add_definitions(/W2) +else() + add_definitions(-Wall -Wextra -Wno-unused-parameter) + set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") +endif() + +if(asan) + if(mac) + set(CMAKE_CXX_FLAGS "-gline-tables-only ${CMAKE_CXX_FLAGS}") + endif() + set(CMAKE_CXX_FLAGS "-fno-omit-frame-pointer ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "-fsanitize=address ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "-DLEAK_SANITIZER ${CMAKE_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "-fsanitize=address ${CMAKE_EXE_LINKER_FLAGS}") +endif() + +if(node_target_type STREQUAL "shared_library") + set(SHARED SHARED) +else() + set(SHARED) +endif() + +if(shlib_suffix) + set(CMAKE_SHARED_LIBRARY_SUFFIX ${shlib_suffix}) +endif() + +if(NOT node_shared_cares) + add_subdirectory(cmake/cares) +endif() + +if(NOT node_shared_http_parser) + add_subdirectory(cmake/http_parser) +endif() + +if(NOT node_shared_libuv) + add_subdirectory(cmake/uv) +endif() + +if(NOT node_shared_nghttp2) + add_subdirectory(cmake/nghttp2) +endif() + +if(NOT node_shared_openssl) + add_subdirectory(cmake/openssl) +endif() + +if(node_use_bundled_v8) + add_subdirectory(cmake/v8) +endif() + +if(NOT node_shared_zlib) + add_subdirectory(cmake/zlib) +endif() + +add_subdirectory(cmake/gtest) +add_subdirectory(cmake/icu) +add_subdirectory(cmake/node) + +# Silence cmake warnings about unused variables that are set by configure. +# These can't be removed outright because they are in use by the GYP build. +if(coverage OR + force_dynamic_crt OR + gas_version OR + host_arch OR + icu_gyp_path OR + icu_path OR + llvm_version OR + node_install_npm OR + node_module_version OR + node_prefix OR + target_arch OR + v8_no_strict_aliasing OR + v8_optimized_debug OR + v8_random_seed OR + v8_typed_array_max_size_in_heap OR + want_separate_host_toolset) +endif() diff --git a/Makefile b/Makefile index d5a8d1e2675135..509582aade038a 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,12 @@ BUILDTYPE ?= Release PYTHON ?= python +NINJA ?= ninja DESTDIR ?= SIGN ?= PREFIX ?= /usr/local FLAKY_TESTS ?= run +INSTALL_ARGS ?= TEST_CI_ARGS ?= STAGINGSERVER ?= node-www LOGLEVEL ?= silent @@ -16,6 +18,11 @@ GNUMAKEFLAGS += --no-print-directory GCOV ?= gcov PWD = $(CURDIR) +ifdef CMAKE + INSTALL_ARGS += --cmake + TEST_CI_ARGS += --shell=out.cmake/cmake/node/node +endif + ifdef JOBS PARALLEL_ARGS = -j $(JOBS) endif @@ -64,11 +71,19 @@ V ?= 1 .PHONY: all # BUILDTYPE=Debug builds both release and debug builds. If you want to compile # just the debug build, run `make -C out BUILDTYPE=Debug` instead. +ifdef CMAKE +ifeq ($(BUILDTYPE),Release) +all: $(NODE_EXE) +else +all: $(NODE_EXE) $(NODE_G_EXE) +endif +else ifeq ($(BUILDTYPE),Release) all: out/Makefile $(NODE_EXE) ## Default target, builds node in out/Release/node. else all: out/Makefile $(NODE_EXE) $(NODE_G_EXE) endif +endif .PHONY: help # To add a target to the help, add a double comment (##) on the target line. @@ -86,6 +101,22 @@ help: ## Print help for targets with comments. # Without the check there is a race condition between the link being deleted # and recreated which can break the addons build when running test-ci # See comments on the build-addons target for some more info +ifdef CMAKE +$(NODE_EXE): + @if [ ! -f out.cmake/build.ninja ] || \ + [ out.cmake/Makefile -nt out.cmake/build.ninja ]; then \ + $(MAKE) -C out.cmake VERBOSE=$(V); \ + else \ + if [ -z "$(V)" ]; then \ + $(NINJA) -C out.cmake; \ + else \ + $(NINJA) -v -C out.cmake; \ + fi \ + fi + @if [ ! -r $@ -o ! -L $@ ]; then \ + ln -fs out.cmake/cmake/node/$(NODE_EXE) $@; \ + fi +else $(NODE_EXE): config.gypi out/Makefile $(MAKE) -C out BUILDTYPE=Release V=$(V) if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Release/$(NODE_EXE) $@; fi @@ -102,6 +133,7 @@ out/Makefile: common.gypi deps/uv/uv.gyp deps/http_parser/http_parser.gyp \ config.gypi: configure $(error Missing or stale $@, please run ./$<) +endif .PHONY: install install: all ## Installs node into $PREFIX (default=/usr/local). @@ -263,19 +295,19 @@ test-cov: all $(MAKE) build-addons $(MAKE) build-addons-napi # $(MAKE) cctest - $(PYTHON) tools/test.py --mode=release -J \ + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release -J \ $(CI_JS_SUITES) \ $(CI_NATIVE_SUITES) $(MAKE) lint test-parallel: all - $(PYTHON) tools/test.py --mode=release parallel -J + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release parallel -J test-valgrind: all - $(PYTHON) tools/test.py --mode=release --valgrind sequential parallel message + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release --valgrind sequential parallel message test-check-deopts: all - $(PYTHON) tools/test.py --mode=release --check-deopts parallel sequential -J + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release --check-deopts parallel sequential -J benchmark/misc/function_call/build/Release/binding.node: all \ benchmark/misc/function_call/binding.cc \ @@ -398,7 +430,7 @@ clear-stalled: .PHONY: test-gc test-gc: all test/gc/build/Release/binding.node - $(PYTHON) tools/test.py --mode=release gc + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release gc .PHONY: test-gc-clean test-gc-clean: @@ -410,10 +442,10 @@ test-build-addons-napi: all build-addons-napi .PHONY: test-all test-all: test-build test/gc/build/Release/binding.node ## Run everything in test/. - $(PYTHON) tools/test.py --mode=debug,release + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=debug,release test-all-valgrind: test-build - $(PYTHON) tools/test.py --mode=debug,release --valgrind + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=debug,release --valgrind CI_NATIVE_SUITES ?= addons addons-napi CI_JS_SUITES ?= default @@ -475,29 +507,32 @@ run-ci: build-ci $(MAKE) test-ci test-release: test-build - $(PYTHON) tools/test.py --mode=release + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release test-debug: test-build - $(PYTHON) tools/test.py --mode=debug + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=debug test-message: test-build - $(PYTHON) tools/test.py message + $(PYTHON) tools/test.py $(TEST_CI_ARGS) message test-simple: | cctest # Depends on 'all'. - $(PYTHON) tools/test.py parallel sequential + $(PYTHON) tools/test.py $(TEST_CI_ARGS) parallel sequential test-pummel: all - $(PYTHON) tools/test.py pummel + $(PYTHON) tools/test.py $(TEST_CI_ARGS) pummel test-internet: all - $(PYTHON) tools/test.py internet + $(PYTHON) tools/test.py $(TEST_CI_ARGS) internet + +test-debugger: all + $(PYTHON) tools/test.py $(TEST_CI_ARGS) debugger test-node-inspect: $(NODE_EXE) USE_EMBEDDED_NODE_INSPECT=1 $(NODE) tools/test-npm-package \ --install deps/node-inspect test test-tick-processor: all - $(PYTHON) tools/test.py tick-processor + $(PYTHON) tools/test.py $(TEST_CI_ARGS) tick-processor .PHONY: test-hash-seed # Verifies the hash seed used by V8 for hashing is random. @@ -507,10 +542,10 @@ test-hash-seed: all .PHONY: test-doc test-doc: doc-only ## Builds, lints, and verifies the docs. $(MAKE) lint - $(PYTHON) tools/test.py $(CI_DOC) + $(PYTHON) tools/test.py $(TEST_CI_ARGS) $(CI_DOC) test-known-issues: all - $(PYTHON) tools/test.py known_issues + $(PYTHON) tools/test.py $(TEST_CI_ARGS) known_issues # Related CI job: node-test-npm test-npm: $(NODE_EXE) ## Run the npm test suite on deps/npm. @@ -521,7 +556,7 @@ test-npm-publish: $(NODE_EXE) .PHONY: test-addons-napi test-addons-napi: test-build-addons-napi - $(PYTHON) tools/test.py --mode=release addons-napi + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release addons-napi .PHONY: test-addons-napi-clean test-addons-napi-clean: @@ -530,7 +565,7 @@ test-addons-napi-clean: .PHONY: test-addons test-addons: test-build test-addons-napi - $(PYTHON) tools/test.py --mode=release addons + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release addons .PHONY: test-addons-clean test-addons-clean: @@ -541,19 +576,20 @@ test-addons-clean: test-timers: $(MAKE) --directory=tools faketime - $(PYTHON) tools/test.py --mode=release timers + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release timers test-timers-clean: $(MAKE) --directory=tools clean test-async-hooks: - $(PYTHON) tools/test.py --mode=release async-hooks + $(PYTHON) tools/test.py $(TEST_CI_ARGS) --mode=release async-hooks test-with-async-hooks: $(MAKE) build-addons $(MAKE) build-addons-napi $(MAKE) cctest - NODE_TEST_WITH_ASYNC_HOOKS=1 $(PYTHON) tools/test.py --mode=release -J \ + NODE_TEST_WITH_ASYNC_HOOKS=1 $(PYTHON) tools/test.py \ + $(TEST_CI_ARGS) --mode=release -J \ $(CI_JS_SUITES) \ $(CI_NATIVE_SUITES) @@ -979,7 +1015,7 @@ $(TARBALL)-headers: release-only --tag=$(TAG) \ --release-urlbase=$(RELEASE_URLBASE) \ $(CONFIG_FLAGS) $(BUILD_RELEASE_FLAGS) - HEADERS_ONLY=1 $(PYTHON) tools/install.py install '$(TARNAME)' '/' + HEADERS_ONLY=1 $(PYTHON) tools/install.py $(INSTALL_ARGS) install '$(TARNAME)' '/' find $(TARNAME)/ -type l | xargs $(RM) tar -cf $(TARNAME)-headers.tar $(TARNAME) $(RM) -r $(TARNAME) diff --git a/cmake/NOTES.md b/cmake/NOTES.md new file mode 100644 index 00000000000000..60fbe9e3110ff0 --- /dev/null +++ b/cmake/NOTES.md @@ -0,0 +1,18 @@ +## cross-compiling + +Cross-compiling arch -> arch for the same distro + release should, in theory, +just work, if that distro is a recent enough Debian or Ubuntu. Let's assume +we want to target gnueabihf: + + $ sudo apt-get install binfmt-support qemu-user g++-arm-linux-gnueabihf + + # Tell qemu where to look for shared libraries. + $ export QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf + + $ mkdir -p build && cd build + + $ cmake -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_SYSTEM_PROCESSOR=arm \ + -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \ + -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ .. + + $ make -j4 diff --git a/cmake/TODO.md b/cmake/TODO.md new file mode 100644 index 00000000000000..83378ee533eee1 --- /dev/null +++ b/cmake/TODO.md @@ -0,0 +1,6 @@ +- disable `-DNDEBUG` in release builds + +- figure out what to do with `process.config`, it's derived from `config.gypi` + +- integrate `deps/openssl/asm/Makefile` with the cmake build somehow but only + regenerate the asm sources when explicitly requested diff --git a/cmake/cares/CMakeLists.txt b/cmake/cares/CMakeLists.txt new file mode 100644 index 00000000000000..5f106394be0ecf --- /dev/null +++ b/cmake/cares/CMakeLists.txt @@ -0,0 +1,126 @@ +include(../common.cmake) +project(cares) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/cares) + +set(DEFINES CARES_STATICLIB) + +set(INCLUDES ${BASE}/include ${BASE}/src) + +set(SOURCES + ${BASE}/include/ares.h + ${BASE}/include/ares_rules.h + ${BASE}/include/ares_version.h + ${BASE}/include/nameser.h + ${BASE}/src/ares__close_sockets.c + ${BASE}/src/ares__get_hostent.c + ${BASE}/src/ares__read_line.c + ${BASE}/src/ares__timeval.c + ${BASE}/src/ares_cancel.c + ${BASE}/src/ares_create_query.c + ${BASE}/src/ares_data.c + ${BASE}/src/ares_data.h + ${BASE}/src/ares_destroy.c + ${BASE}/src/ares_dns.h + ${BASE}/src/ares_expand_name.c + ${BASE}/src/ares_expand_string.c + ${BASE}/src/ares_fds.c + ${BASE}/src/ares_free_hostent.c + ${BASE}/src/ares_free_string.c + ${BASE}/src/ares_getenv.h + ${BASE}/src/ares_gethostbyaddr.c + ${BASE}/src/ares_gethostbyname.c + ${BASE}/src/ares_getnameinfo.c + ${BASE}/src/ares_getopt.c + ${BASE}/src/ares_getopt.h + ${BASE}/src/ares_getsock.c + ${BASE}/src/ares_inet_net_pton.h + ${BASE}/src/ares_init.c + ${BASE}/src/ares_ipv6.h + ${BASE}/src/ares_library_init.c + ${BASE}/src/ares_library_init.h + ${BASE}/src/ares_llist.c + ${BASE}/src/ares_llist.h + ${BASE}/src/ares_mkquery.c + ${BASE}/src/ares_nowarn.c + ${BASE}/src/ares_nowarn.h + ${BASE}/src/ares_options.c + ${BASE}/src/ares_parse_a_reply.c + ${BASE}/src/ares_parse_aaaa_reply.c + ${BASE}/src/ares_parse_mx_reply.c + ${BASE}/src/ares_parse_naptr_reply.c + ${BASE}/src/ares_parse_ns_reply.c + ${BASE}/src/ares_parse_ptr_reply.c + ${BASE}/src/ares_parse_soa_reply.c + ${BASE}/src/ares_parse_srv_reply.c + ${BASE}/src/ares_parse_txt_reply.c + ${BASE}/src/ares_platform.h + ${BASE}/src/ares_private.h + ${BASE}/src/ares_process.c + ${BASE}/src/ares_query.c + ${BASE}/src/ares_search.c + ${BASE}/src/ares_send.c + ${BASE}/src/ares_setup.h + ${BASE}/src/ares_strcasecmp.c + ${BASE}/src/ares_strcasecmp.h + ${BASE}/src/ares_strdup.c + ${BASE}/src/ares_strdup.h + ${BASE}/src/ares_strerror.c + ${BASE}/src/ares_timeout.c + ${BASE}/src/ares_version.c + ${BASE}/src/ares_writev.c + ${BASE}/src/ares_writev.h + ${BASE}/src/bitncmp.c + ${BASE}/src/bitncmp.h + ${BASE}/src/inet_net_pton.c + ${BASE}/src/inet_ntop.c + ${BASE}/src/setup_once.h) + +if(win32) + set(LIBS ${LIBS} iphlpapi ws2_32) + set(SOURCES ${SOURCES} + ${BASE}/src/src/ares_getenv.c + ${BASE}/src/src/ares_iphlpapi.h + ${BASE}/src/src/ares_platform.c + ${BASE}/src/src/config-win32.h + ${BASE}/src/src/windows_port.c) +else() + set(DEFINES ${DEFINES} HAVE_CONFIG_H) +endif() + +if(android) + set(INCLUDES ${INCLUDES} ${BASE}/config/android) + set(SOURCES ${SOURCES} ${BASE}/config/android/ares_config.h) +endif() + +if(dragonflybsd OR freebsd) + set(INCLUDES ${INCLUDES} ${BASE}/config/freebsd) + set(SOURCES ${SOURCES} ${BASE}/config/freebsd/ares_config.h) +endif() + +if(mac) + set(INCLUDES ${INCLUDES} ${BASE}/config/darwin) + set(SOURCES ${SOURCES} ${BASE}/config/darwin/ares_config.h) +endif() + +if(openbsd) + set(INCLUDES ${INCLUDES} ${BASE}/config/openbsd) + set(SOURCES ${SOURCES} ${BASE}/config/openbsd/ares_config.h) +endif() + +if(linux) + set(INCLUDES ${INCLUDES} ${BASE}/config/linux) + set(SOURCES ${SOURCES} ${BASE}/config/linux/ares_config.h) +endif() + +if(sunos) + set(INCLUDES ${INCLUDES} ${BASE}/config/sunos) + set(LIBS ${LIBS} nsl socket) + set(SOURCES ${SOURCES} ${BASE}/config/sunos/ares_config.h) +endif() + +add_library(cares ${SHARED} ${SOURCES}) +target_compile_definitions(cares PRIVATE ${DEFINES}) +target_include_directories(cares PRIVATE ${INCLUDES}) +target_include_directories(cares PUBLIC ${BASE}/include) +target_link_libraries(cares ${LIBS}) diff --git a/cmake/common.cmake b/cmake/common.cmake new file mode 100644 index 00000000000000..2447126e85b835 --- /dev/null +++ b/cmake/common.cmake @@ -0,0 +1,42 @@ +if(NOT DEFINED NODE_PLATFORM) + if(CMAKE_SYSTEM_NAME STREQUAL "AIX") + set(NODE_PLATFORM aix) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(NODE_PLATFORM mac) + elseif(CMAKE_SYSTEM_NAME STREQUAL "DragonFly") + set(NODE_PLATFORM dragonflybsd) + elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + set(NODE_PLATFORM freebsd) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(NODE_PLATFORM linux) + elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") + set(NODE_PLATFORM netbsd) + elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") + set(NODE_PLATFORM openbsd) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(NODE_PLATFORM win32) + elseif(CMAKE_SYSTEM_NAME MATCHES "Solaris|SunOS") + set(NODE_PLATFORM sunos) + endif() +endif() + +# CMAKE_SYSTEM_PROCESSOR is always i386 on MacOS. Since we only support +# 64 bits builds anyway, default to x64. +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR + CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" OR + CMAKE_SYSTEM_PROCESSOR STREQUAL "IA64" OR + CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64" OR + CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(NODE_ARCH x64) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "i386" OR + CMAKE_SYSTEM_PROCESSOR STREQUAL "i686" OR + CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") + set(NODE_ARCH ia32) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm") + set(NODE_ARCH arm) +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64") + set(NODE_ARCH ppc64) +endif() + +set(${NODE_PLATFORM} ON) +set(${NODE_ARCH} ON) diff --git a/cmake/gtest/CMakeLists.txt b/cmake/gtest/CMakeLists.txt new file mode 100644 index 00000000000000..c77334ed019c08 --- /dev/null +++ b/cmake/gtest/CMakeLists.txt @@ -0,0 +1,36 @@ +include(../common.cmake) +project(gtest) +set(BASE ${CMAKE_SOURCE_DIR}/deps/gtest) +add_library( + gtest ${SHARED} + ${BASE}/include/gtest/gtest-death-test.h + ${BASE}/include/gtest/gtest-message.h + ${BASE}/include/gtest/gtest-param-test.h + ${BASE}/include/gtest/gtest-printers.h + ${BASE}/include/gtest/gtest-spi.h + ${BASE}/include/gtest/gtest-test-part.h + ${BASE}/include/gtest/gtest-typed-test.h + ${BASE}/include/gtest/gtest.h + ${BASE}/include/gtest/gtest_pred_impl.h + ${BASE}/include/gtest/gtest_prod.h + ${BASE}/include/gtest/internal/gtest-death-test-internal.h + ${BASE}/include/gtest/internal/gtest-filepath.h + ${BASE}/include/gtest/internal/gtest-internal.h + ${BASE}/include/gtest/internal/gtest-linked_ptr.h + ${BASE}/include/gtest/internal/gtest-param-util-generated.h + ${BASE}/include/gtest/internal/gtest-param-util.h + ${BASE}/include/gtest/internal/gtest-port.h + ${BASE}/include/gtest/internal/gtest-string.h + ${BASE}/include/gtest/internal/gtest-tuple.h + ${BASE}/include/gtest/internal/gtest-type-util.h + ${BASE}/src/gtest-death-test.cc + ${BASE}/src/gtest-filepath.cc + ${BASE}/src/gtest-internal-inl.h + ${BASE}/src/gtest-port.cc + ${BASE}/src/gtest-printers.cc + ${BASE}/src/gtest-test-part.cc + ${BASE}/src/gtest-typed-test.cc + ${BASE}/src/gtest.cc + ${BASE}/src/gtest_main.cc) +include_directories(${BASE} ${BASE}/include) +target_include_directories(gtest PUBLIC ${BASE}/include) diff --git a/cmake/http_parser/CMakeLists.txt b/cmake/http_parser/CMakeLists.txt new file mode 100644 index 00000000000000..84d4be8143f3f2 --- /dev/null +++ b/cmake/http_parser/CMakeLists.txt @@ -0,0 +1,7 @@ +include(../common.cmake) +project(http_parser) +set(BASE ${CMAKE_SOURCE_DIR}/deps/http_parser) +add_library(http_parser ${SHARED} ${BASE}/http_parser.c ${BASE}/http_parser.h) +target_compile_definitions(http_parser PRIVATE HTTP_PARSER_STRICT=0) +target_include_directories(http_parser PRIVATE ${BASE}) +target_include_directories(http_parser PUBLIC ${BASE}) diff --git a/cmake/icu/CMakeLists.txt b/cmake/icu/CMakeLists.txt new file mode 100644 index 00000000000000..ed7232314b2073 --- /dev/null +++ b/cmake/icu/CMakeLists.txt @@ -0,0 +1,6 @@ +include(../common.cmake) +project(icu) + +add_subdirectory(common) +add_subdirectory(i18n) +add_subdirectory(tools) diff --git a/cmake/icu/common/CMakeLists.txt b/cmake/icu/common/CMakeLists.txt new file mode 100644 index 00000000000000..319d3a821a9ae7 --- /dev/null +++ b/cmake/icu/common/CMakeLists.txt @@ -0,0 +1,388 @@ +include(../../common.cmake) +project(icu_common) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/icu-small/source/common) + +set(DEFINES + -DUCONFIG_NO_BREAK_ITERATION=0 + -DUCONFIG_NO_LEGACY_CONVERSION=1 + -DUCONFIG_NO_REGULAR_EXPRESSIONS=1 + -DUCONFIG_NO_SERVICE=1 + -DU_ENABLE_DYLOAD=0 + -DU_HAVE_STD_STRING=0) + +add_definitions(${DEFINES}) +include_directories(${BASE}) + +set(SOURCES + ${BASE}/appendable.cpp + ${BASE}/bmpset.cpp + ${BASE}/bmpset.h + ${BASE}/brkeng.cpp + ${BASE}/brkeng.h + ${BASE}/brkiter.cpp + ${BASE}/bytesinkutil.cpp + ${BASE}/bytesinkutil.h + ${BASE}/bytestream.cpp + ${BASE}/bytestrie.cpp + ${BASE}/bytestriebuilder.cpp + ${BASE}/bytestrieiterator.cpp + ${BASE}/caniter.cpp + ${BASE}/chariter.cpp + ${BASE}/charstr.cpp + ${BASE}/charstr.h + ${BASE}/cmemory.cpp + ${BASE}/cmemory.h + ${BASE}/cpputils.h + ${BASE}/cstr.cpp + ${BASE}/cstr.h + ${BASE}/cstring.cpp + ${BASE}/cstring.h + ${BASE}/cwchar.cpp + ${BASE}/cwchar.h + ${BASE}/dictbe.cpp + ${BASE}/dictbe.h + ${BASE}/dictionarydata.cpp + ${BASE}/dictionarydata.h + ${BASE}/dtintrv.cpp + ${BASE}/edits.cpp + ${BASE}/errorcode.cpp + ${BASE}/filteredbrk.cpp + ${BASE}/filterednormalizer2.cpp + ${BASE}/hash.h + ${BASE}/icudataver.cpp + ${BASE}/icuplug.cpp + ${BASE}/icuplugimp.h + ${BASE}/listformatter.cpp + ${BASE}/loadednormalizer2impl.cpp + ${BASE}/localsvc.h + ${BASE}/locavailable.cpp + ${BASE}/locbased.cpp + ${BASE}/locbased.h + ${BASE}/locdispnames.cpp + ${BASE}/locdspnm.cpp + ${BASE}/locid.cpp + ${BASE}/loclikely.cpp + ${BASE}/locmap.cpp + ${BASE}/locmap.h + ${BASE}/locresdata.cpp + ${BASE}/locutil.cpp + ${BASE}/locutil.h + ${BASE}/messageimpl.h + ${BASE}/messagepattern.cpp + ${BASE}/msvcres.h + ${BASE}/mutex.h + ${BASE}/norm2_nfc_data.h + ${BASE}/norm2allmodes.h + ${BASE}/normalizer2.cpp + ${BASE}/normalizer2impl.cpp + ${BASE}/normalizer2impl.h + ${BASE}/normlzr.cpp + ${BASE}/parsepos.cpp + ${BASE}/patternprops.cpp + ${BASE}/patternprops.h + ${BASE}/pluralmap.cpp + ${BASE}/pluralmap.h + ${BASE}/propname.cpp + ${BASE}/propname.h + ${BASE}/propname_data.h + ${BASE}/propsvec.cpp + ${BASE}/propsvec.h + ${BASE}/punycode.cpp + ${BASE}/punycode.h + ${BASE}/putil.cpp + ${BASE}/putilimp.h + ${BASE}/rbbi.cpp + ${BASE}/rbbi_cache.cpp + ${BASE}/rbbidata.cpp + ${BASE}/rbbidata.h + ${BASE}/rbbinode.cpp + ${BASE}/rbbinode.h + ${BASE}/rbbirb.cpp + ${BASE}/rbbirb.h + ${BASE}/rbbirpt.h + ${BASE}/rbbiscan.cpp + ${BASE}/rbbiscan.h + ${BASE}/rbbisetb.cpp + ${BASE}/rbbisetb.h + ${BASE}/rbbistbl.cpp + ${BASE}/rbbitblb.cpp + ${BASE}/rbbitblb.h + ${BASE}/resbund.cpp + ${BASE}/resbund_cnv.cpp + ${BASE}/resource.cpp + ${BASE}/resource.h + ${BASE}/ruleiter.cpp + ${BASE}/ruleiter.h + ${BASE}/schriter.cpp + ${BASE}/serv.cpp + ${BASE}/serv.h + ${BASE}/servlk.cpp + ${BASE}/servlkf.cpp + ${BASE}/servloc.h + ${BASE}/servls.cpp + ${BASE}/servnotf.cpp + ${BASE}/servnotf.h + ${BASE}/servrbf.cpp + ${BASE}/servslkf.cpp + ${BASE}/sharedobject.cpp + ${BASE}/sharedobject.h + ${BASE}/simpleformatter.cpp + ${BASE}/sprpimpl.h + ${BASE}/stringpiece.cpp + ${BASE}/stringtriebuilder.cpp + ${BASE}/uarrsort.cpp + ${BASE}/uarrsort.h + ${BASE}/uassert.h + ${BASE}/ubidi.cpp + ${BASE}/ubidi_props.cpp + ${BASE}/ubidi_props.h + ${BASE}/ubidi_props_data.h + ${BASE}/ubidiimp.h + ${BASE}/ubidiln.cpp + ${BASE}/ubiditransform.cpp + ${BASE}/ubidiwrt.cpp + ${BASE}/ubrk.cpp + ${BASE}/ubrkimpl.h + ${BASE}/ucase.cpp + ${BASE}/ucase.h + ${BASE}/ucase_props_data.h + ${BASE}/ucasemap.cpp + ${BASE}/ucasemap_imp.h + ${BASE}/ucasemap_titlecase_brkiter.cpp + ${BASE}/ucat.cpp + ${BASE}/uchar.cpp + ${BASE}/uchar_props_data.h + ${BASE}/ucharstrie.cpp + ${BASE}/ucharstriebuilder.cpp + ${BASE}/ucharstrieiterator.cpp + ${BASE}/uchriter.cpp + ${BASE}/ucln.h + ${BASE}/ucln_cmn.cpp + ${BASE}/ucln_cmn.h + ${BASE}/ucln_imp.h + ${BASE}/ucmndata.cpp + ${BASE}/ucmndata.h + ${BASE}/ucnv.cpp + ${BASE}/ucnv2022.cpp + ${BASE}/ucnv_bld.cpp + ${BASE}/ucnv_bld.h + ${BASE}/ucnv_cb.cpp + ${BASE}/ucnv_cnv.cpp + ${BASE}/ucnv_cnv.h + ${BASE}/ucnv_ct.cpp + ${BASE}/ucnv_err.cpp + ${BASE}/ucnv_ext.cpp + ${BASE}/ucnv_ext.h + ${BASE}/ucnv_imp.h + ${BASE}/ucnv_io.cpp + ${BASE}/ucnv_io.h + ${BASE}/ucnv_lmb.cpp + ${BASE}/ucnv_set.cpp + ${BASE}/ucnv_u16.cpp + ${BASE}/ucnv_u32.cpp + ${BASE}/ucnv_u7.cpp + ${BASE}/ucnv_u8.cpp + ${BASE}/ucnvbocu.cpp + ${BASE}/ucnvdisp.cpp + ${BASE}/ucnvhz.cpp + ${BASE}/ucnvisci.cpp + ${BASE}/ucnvlat1.cpp + ${BASE}/ucnvmbcs.cpp + ${BASE}/ucnvmbcs.h + ${BASE}/ucnvscsu.cpp + ${BASE}/ucnvsel.cpp + ${BASE}/ucol_data.h + ${BASE}/ucol_swp.cpp + ${BASE}/ucol_swp.h + ${BASE}/ucurr.cpp + ${BASE}/ucurrimp.h + ${BASE}/udata.cpp + ${BASE}/udatamem.cpp + ${BASE}/udatamem.h + ${BASE}/udataswp.cpp + ${BASE}/udataswp.h + ${BASE}/uelement.h + ${BASE}/uenum.cpp + ${BASE}/uenumimp.h + ${BASE}/uhash.cpp + ${BASE}/uhash.h + ${BASE}/uhash_us.cpp + ${BASE}/uidna.cpp + ${BASE}/uinit.cpp + ${BASE}/uinvchar.cpp + ${BASE}/uinvchar.h + ${BASE}/uiter.cpp + ${BASE}/ulist.cpp + ${BASE}/ulist.h + ${BASE}/ulistformatter.cpp + ${BASE}/uloc.cpp + ${BASE}/uloc_keytype.cpp + ${BASE}/uloc_tag.cpp + ${BASE}/ulocimp.h + ${BASE}/umapfile.cpp + ${BASE}/umapfile.h + ${BASE}/umath.cpp + ${BASE}/umutex.cpp + ${BASE}/umutex.h + ${BASE}/unames.cpp + ${BASE}/unifiedcache.cpp + ${BASE}/unifiedcache.h + ${BASE}/unifilt.cpp + ${BASE}/unifunct.cpp + ${BASE}/uniset.cpp + ${BASE}/uniset_closure.cpp + ${BASE}/uniset_props.cpp + ${BASE}/unisetspan.cpp + ${BASE}/unisetspan.h + ${BASE}/unistr.cpp + ${BASE}/unistr_case.cpp + ${BASE}/unistr_case_locale.cpp + ${BASE}/unistr_cnv.cpp + ${BASE}/unistr_props.cpp + ${BASE}/unistr_titlecase_brkiter.cpp + ${BASE}/unistrappender.h + ${BASE}/unorm.cpp + ${BASE}/unormcmp.cpp + ${BASE}/unormimp.h + ${BASE}/uobject.cpp + ${BASE}/uposixdefs.h + ${BASE}/uprops.cpp + ${BASE}/uprops.h + ${BASE}/ures_cnv.cpp + ${BASE}/uresbund.cpp + ${BASE}/uresdata.cpp + ${BASE}/uresdata.h + ${BASE}/uresimp.h + ${BASE}/ureslocs.h + ${BASE}/usc_impl.cpp + ${BASE}/usc_impl.h + ${BASE}/uscript.cpp + ${BASE}/uscript_props.cpp + ${BASE}/uset.cpp + ${BASE}/uset_imp.h + ${BASE}/uset_props.cpp + ${BASE}/usetiter.cpp + ${BASE}/ushape.cpp + ${BASE}/usprep.cpp + ${BASE}/ustack.cpp + ${BASE}/ustr_cnv.cpp + ${BASE}/ustr_cnv.h + ${BASE}/ustr_imp.h + ${BASE}/ustr_titlecase_brkiter.cpp + ${BASE}/ustr_wcs.cpp + ${BASE}/ustrcase.cpp + ${BASE}/ustrcase_locale.cpp + ${BASE}/ustrenum.cpp + ${BASE}/ustrenum.h + ${BASE}/ustrfmt.cpp + ${BASE}/ustrfmt.h + ${BASE}/ustring.cpp + ${BASE}/ustrtrns.cpp + ${BASE}/utext.cpp + ${BASE}/utf_impl.cpp + ${BASE}/util.cpp + ${BASE}/util.h + ${BASE}/util_props.cpp + ${BASE}/utrace.cpp + ${BASE}/utracimp.h + ${BASE}/utrie.cpp + ${BASE}/utrie.h + ${BASE}/utrie2.cpp + ${BASE}/utrie2.h + ${BASE}/utrie2_builder.cpp + ${BASE}/utrie2_impl.h + ${BASE}/uts46.cpp + ${BASE}/utypeinfo.h + ${BASE}/utypes.cpp + ${BASE}/uvector.cpp + ${BASE}/uvector.h + ${BASE}/uvectr32.cpp + ${BASE}/uvectr32.h + ${BASE}/uvectr64.cpp + ${BASE}/uvectr64.h + ${BASE}/wintz.cpp + ${BASE}/wintz.h) + +# Needs to be compiled *without* -DU_COMMON_IMPLEMENTATION=1. +add_library( + icu_common_data STATIC + ${CMAKE_CURRENT_BINARY_DIR}/icudt${icu_ver_major}_dat.c) + +if(SHARED STREQUAL SHARED) + # Compile with -fPIC when building icu_common as a shared library. + set_property(TARGET icu_common_data PROPERTY POSITION_INDEPENDENT_CODE ON) +endif() + +add_library(icu_common ${SHARED} ${SOURCES}) +target_link_libraries(icu_common icu_common_data) + +add_library( + icu_common_stubdata ${SHARED} + ${BASE}/../stubdata/stubdata.cpp + ${SOURCES}) + +target_compile_definitions(icu_common PUBLIC ${DEFINES}) +target_compile_definitions(icu_common_stubdata PUBLIC ${DEFINES}) + +target_compile_definitions(icu_common PRIVATE -DU_COMMON_IMPLEMENTATION=1) +target_compile_definitions( + icu_common_stubdata PRIVATE -DU_COMMON_IMPLEMENTATION=1) + +target_include_directories(icu_common PUBLIC ${BASE}) +target_include_directories(icu_common_stubdata PUBLIC ${BASE}) + +if(win32) + target_link_libraries(advapi32 user32) +endif() + +set(icu_data_out + ${CMAKE_CURRENT_BINARY_DIR}/icudt${icu_ver_major}${icu_endianness}.dat) + +# Note that both icutrim and icupkg byte-swap the data if necessary. +if(icu_small) + add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${CMAKE_SOURCE_DIR}/tools/icu/icutrim.py + -v + -P ${CMAKE_CURRENT_BINARY_DIR}/../tools + -D ${icu_data_in} + --delete-tmp + -T ${CMAKE_CURRENT_BINARY_DIR}/icutmp + -F ${CMAKE_SOURCE_DIR}/tools/icu/icu_small.json + -O ${icu_data_out} + -L ${icu_locales} + DEPENDS + genrb iculslocs icupkg # icutrim.py calls out to these. + ${CMAKE_SOURCE_DIR}/tools/icu/icu_small.json + ${CMAKE_SOURCE_DIR}/tools/icu/icutrim.py + ${icu_data_in} + OUTPUT + ${icu_data_out}) + if(icu_endianness) + # Silence unused variable warning. + endif() +else() + add_custom_command( + COMMAND + icupkg -t${icu_endianness} ${icu_data_in} ${icu_data_out} + DEPENDS + icupkg ${icu_data_in} + OUTPUT + ${icu_data_out}) +endif() + +# Note that the filename determines the name of the symbol; i.e., +# icudt42_dat.c is mapped by genccode to `char icudt42_dat[]`. +add_custom_command( + COMMAND + genccode + -d ${CMAKE_CURRENT_BINARY_DIR} + -f icudt${icu_ver_major}_dat + ${icu_data_out} + DEPENDS + genccode + ${icu_data_out} + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/icudt${icu_ver_major}_dat.c) diff --git a/cmake/icu/i18n/CMakeLists.txt b/cmake/icu/i18n/CMakeLists.txt new file mode 100644 index 00000000000000..43a13c431fec16 --- /dev/null +++ b/cmake/icu/i18n/CMakeLists.txt @@ -0,0 +1,353 @@ +include(../../common.cmake) +project(icu_i18n) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/icu-small/source/i18n) + +add_definitions(-DU_I18N_IMPLEMENTATION=1) +include_directories(${BASE}) + +set(SOURCES + ${BASE}/affixpatternparser.cpp + ${BASE}/affixpatternparser.h + ${BASE}/alphaindex.cpp + ${BASE}/anytrans.cpp + ${BASE}/anytrans.h + ${BASE}/astro.cpp + ${BASE}/astro.h + ${BASE}/basictz.cpp + ${BASE}/bocsu.cpp + ${BASE}/bocsu.h + ${BASE}/brktrans.cpp + ${BASE}/brktrans.h + ${BASE}/buddhcal.cpp + ${BASE}/buddhcal.h + ${BASE}/calendar.cpp + ${BASE}/casetrn.cpp + ${BASE}/casetrn.h + ${BASE}/cecal.cpp + ${BASE}/cecal.h + ${BASE}/chnsecal.cpp + ${BASE}/chnsecal.h + ${BASE}/choicfmt.cpp + ${BASE}/coleitr.cpp + ${BASE}/coll.cpp + ${BASE}/collation.cpp + ${BASE}/collation.h + ${BASE}/collationbuilder.cpp + ${BASE}/collationbuilder.h + ${BASE}/collationcompare.cpp + ${BASE}/collationcompare.h + ${BASE}/collationdata.cpp + ${BASE}/collationdata.h + ${BASE}/collationdatabuilder.cpp + ${BASE}/collationdatabuilder.h + ${BASE}/collationdatareader.cpp + ${BASE}/collationdatareader.h + ${BASE}/collationdatawriter.cpp + ${BASE}/collationdatawriter.h + ${BASE}/collationfastlatin.cpp + ${BASE}/collationfastlatin.h + ${BASE}/collationfastlatinbuilder.cpp + ${BASE}/collationfastlatinbuilder.h + ${BASE}/collationfcd.cpp + ${BASE}/collationfcd.h + ${BASE}/collationiterator.cpp + ${BASE}/collationiterator.h + ${BASE}/collationkeys.cpp + ${BASE}/collationkeys.h + ${BASE}/collationroot.cpp + ${BASE}/collationroot.h + ${BASE}/collationrootelements.cpp + ${BASE}/collationrootelements.h + ${BASE}/collationruleparser.cpp + ${BASE}/collationruleparser.h + ${BASE}/collationsets.cpp + ${BASE}/collationsets.h + ${BASE}/collationsettings.cpp + ${BASE}/collationsettings.h + ${BASE}/collationtailoring.cpp + ${BASE}/collationtailoring.h + ${BASE}/collationweights.cpp + ${BASE}/collationweights.h + ${BASE}/collunsafe.h + ${BASE}/compactdecimalformat.cpp + ${BASE}/coptccal.cpp + ${BASE}/coptccal.h + ${BASE}/cpdtrans.cpp + ${BASE}/cpdtrans.h + ${BASE}/csdetect.cpp + ${BASE}/csdetect.h + ${BASE}/csmatch.cpp + ${BASE}/csmatch.h + ${BASE}/csr2022.cpp + ${BASE}/csr2022.h + ${BASE}/csrecog.cpp + ${BASE}/csrecog.h + ${BASE}/csrmbcs.cpp + ${BASE}/csrmbcs.h + ${BASE}/csrsbcs.cpp + ${BASE}/csrsbcs.h + ${BASE}/csrucode.cpp + ${BASE}/csrucode.h + ${BASE}/csrutf8.cpp + ${BASE}/csrutf8.h + ${BASE}/curramt.cpp + ${BASE}/currfmt.cpp + ${BASE}/currfmt.h + ${BASE}/currpinf.cpp + ${BASE}/currunit.cpp + ${BASE}/dangical.cpp + ${BASE}/dangical.h + ${BASE}/datefmt.cpp + ${BASE}/dayperiodrules.cpp + ${BASE}/dayperiodrules.h + ${BASE}/dcfmtimp.h + ${BASE}/dcfmtsym.cpp + ${BASE}/decContext.cpp + ${BASE}/decContext.h + ${BASE}/decNumber.cpp + ${BASE}/decNumber.h + ${BASE}/decNumberLocal.h + ${BASE}/decfmtst.cpp + ${BASE}/decfmtst.h + ${BASE}/decimalformatpattern.cpp + ${BASE}/decimalformatpattern.h + ${BASE}/decimalformatpatternimpl.h + ${BASE}/decimfmt.cpp + ${BASE}/decimfmtimpl.cpp + ${BASE}/decimfmtimpl.h + ${BASE}/digitaffix.cpp + ${BASE}/digitaffix.h + ${BASE}/digitaffixesandpadding.cpp + ${BASE}/digitaffixesandpadding.h + ${BASE}/digitformatter.cpp + ${BASE}/digitformatter.h + ${BASE}/digitgrouping.cpp + ${BASE}/digitgrouping.h + ${BASE}/digitinterval.cpp + ${BASE}/digitinterval.h + ${BASE}/digitlst.cpp + ${BASE}/digitlst.h + ${BASE}/dt_impl.h + ${BASE}/dtfmtsym.cpp + ${BASE}/dtitv_impl.h + ${BASE}/dtitvfmt.cpp + ${BASE}/dtitvinf.cpp + ${BASE}/dtptngen.cpp + ${BASE}/dtptngen_impl.h + ${BASE}/dtrule.cpp + ${BASE}/esctrn.cpp + ${BASE}/esctrn.h + ${BASE}/ethpccal.cpp + ${BASE}/ethpccal.h + ${BASE}/fmtable.cpp + ${BASE}/fmtable_cnv.cpp + ${BASE}/fmtableimp.h + ${BASE}/format.cpp + ${BASE}/fphdlimp.cpp + ${BASE}/fphdlimp.h + ${BASE}/fpositer.cpp + ${BASE}/funcrepl.cpp + ${BASE}/funcrepl.h + ${BASE}/gender.cpp + ${BASE}/gregocal.cpp + ${BASE}/gregoimp.cpp + ${BASE}/gregoimp.h + ${BASE}/hebrwcal.cpp + ${BASE}/hebrwcal.h + ${BASE}/indiancal.cpp + ${BASE}/indiancal.h + ${BASE}/inputext.cpp + ${BASE}/inputext.h + ${BASE}/islamcal.cpp + ${BASE}/islamcal.h + ${BASE}/japancal.cpp + ${BASE}/japancal.h + ${BASE}/measfmt.cpp + ${BASE}/measunit.cpp + ${BASE}/measure.cpp + ${BASE}/msgfmt.cpp + ${BASE}/msgfmt_impl.h + ${BASE}/name2uni.cpp + ${BASE}/name2uni.h + ${BASE}/nfrlist.h + ${BASE}/nfrs.cpp + ${BASE}/nfrs.h + ${BASE}/nfrule.cpp + ${BASE}/nfrule.h + ${BASE}/nfsubs.cpp + ${BASE}/nfsubs.h + ${BASE}/nortrans.cpp + ${BASE}/nortrans.h + ${BASE}/nultrans.cpp + ${BASE}/nultrans.h + ${BASE}/numfmt.cpp + ${BASE}/numsys.cpp + ${BASE}/numsys_impl.h + ${BASE}/olsontz.cpp + ${BASE}/olsontz.h + ${BASE}/persncal.cpp + ${BASE}/persncal.h + ${BASE}/pluralaffix.cpp + ${BASE}/pluralaffix.h + ${BASE}/plurfmt.cpp + ${BASE}/plurrule.cpp + ${BASE}/plurrule_impl.h + ${BASE}/precision.cpp + ${BASE}/precision.h + ${BASE}/quant.cpp + ${BASE}/quant.h + ${BASE}/quantityformatter.cpp + ${BASE}/quantityformatter.h + ${BASE}/rbnf.cpp + ${BASE}/rbt.cpp + ${BASE}/rbt.h + ${BASE}/rbt_data.cpp + ${BASE}/rbt_data.h + ${BASE}/rbt_pars.cpp + ${BASE}/rbt_pars.h + ${BASE}/rbt_rule.cpp + ${BASE}/rbt_rule.h + ${BASE}/rbt_set.cpp + ${BASE}/rbt_set.h + ${BASE}/rbtz.cpp + ${BASE}/regexcmp.cpp + ${BASE}/regexcmp.h + ${BASE}/regexcst.h + ${BASE}/regeximp.cpp + ${BASE}/regeximp.h + ${BASE}/regexst.cpp + ${BASE}/regexst.h + ${BASE}/regextxt.cpp + ${BASE}/regextxt.h + ${BASE}/region.cpp + ${BASE}/region_impl.h + ${BASE}/reldatefmt.cpp + ${BASE}/reldtfmt.cpp + ${BASE}/reldtfmt.h + ${BASE}/rematch.cpp + ${BASE}/remtrans.cpp + ${BASE}/remtrans.h + ${BASE}/repattrn.cpp + ${BASE}/rulebasedcollator.cpp + ${BASE}/scientificnumberformatter.cpp + ${BASE}/scriptset.cpp + ${BASE}/scriptset.h + ${BASE}/search.cpp + ${BASE}/selfmt.cpp + ${BASE}/selfmtimpl.h + ${BASE}/sharedbreakiterator.cpp + ${BASE}/sharedbreakiterator.h + ${BASE}/sharedcalendar.h + ${BASE}/shareddateformatsymbols.h + ${BASE}/sharednumberformat.h + ${BASE}/sharedpluralrules.h + ${BASE}/significantdigitinterval.h + ${BASE}/simpletz.cpp + ${BASE}/smallintformatter.cpp + ${BASE}/smallintformatter.h + ${BASE}/smpdtfmt.cpp + ${BASE}/smpdtfst.cpp + ${BASE}/smpdtfst.h + ${BASE}/sortkey.cpp + ${BASE}/standardplural.cpp + ${BASE}/standardplural.h + ${BASE}/strmatch.cpp + ${BASE}/strmatch.h + ${BASE}/strrepl.cpp + ${BASE}/strrepl.h + ${BASE}/stsearch.cpp + ${BASE}/taiwncal.cpp + ${BASE}/taiwncal.h + ${BASE}/timezone.cpp + ${BASE}/titletrn.cpp + ${BASE}/titletrn.h + ${BASE}/tmunit.cpp + ${BASE}/tmutamt.cpp + ${BASE}/tmutfmt.cpp + ${BASE}/tolowtrn.cpp + ${BASE}/tolowtrn.h + ${BASE}/toupptrn.cpp + ${BASE}/toupptrn.h + ${BASE}/translit.cpp + ${BASE}/transreg.cpp + ${BASE}/transreg.h + ${BASE}/tridpars.cpp + ${BASE}/tridpars.h + ${BASE}/tzfmt.cpp + ${BASE}/tzgnames.cpp + ${BASE}/tzgnames.h + ${BASE}/tznames.cpp + ${BASE}/tznames_impl.cpp + ${BASE}/tznames_impl.h + ${BASE}/tzrule.cpp + ${BASE}/tztrans.cpp + ${BASE}/ucal.cpp + ${BASE}/ucln_in.cpp + ${BASE}/ucln_in.h + ${BASE}/ucol.cpp + ${BASE}/ucol_imp.h + ${BASE}/ucol_res.cpp + ${BASE}/ucol_sit.cpp + ${BASE}/ucoleitr.cpp + ${BASE}/ucsdet.cpp + ${BASE}/udat.cpp + ${BASE}/udateintervalformat.cpp + ${BASE}/udatpg.cpp + ${BASE}/ufieldpositer.cpp + ${BASE}/uitercollationiterator.cpp + ${BASE}/uitercollationiterator.h + ${BASE}/ulocdata.cpp + ${BASE}/umsg.cpp + ${BASE}/umsg_imp.h + ${BASE}/unesctrn.cpp + ${BASE}/unesctrn.h + ${BASE}/uni2name.cpp + ${BASE}/uni2name.h + ${BASE}/unum.cpp + ${BASE}/unumsys.cpp + ${BASE}/upluralrules.cpp + ${BASE}/uregex.cpp + ${BASE}/uregexc.cpp + ${BASE}/uregion.cpp + ${BASE}/usearch.cpp + ${BASE}/uspoof.cpp + ${BASE}/uspoof_build.cpp + ${BASE}/uspoof_conf.cpp + ${BASE}/uspoof_conf.h + ${BASE}/uspoof_impl.cpp + ${BASE}/uspoof_impl.h + ${BASE}/usrchimp.h + ${BASE}/utf16collationiterator.cpp + ${BASE}/utf16collationiterator.h + ${BASE}/utf8collationiterator.cpp + ${BASE}/utf8collationiterator.h + ${BASE}/utmscale.cpp + ${BASE}/utrans.cpp + ${BASE}/valueformatter.cpp + ${BASE}/valueformatter.h + ${BASE}/visibledigits.cpp + ${BASE}/visibledigits.h + ${BASE}/vtzone.cpp + ${BASE}/vzone.cpp + ${BASE}/vzone.h + ${BASE}/windtfmt.cpp + ${BASE}/windtfmt.h + ${BASE}/winnmfmt.cpp + ${BASE}/winnmfmt.h + ${BASE}/wintzimpl.cpp + ${BASE}/wintzimpl.h + ${BASE}/zonemeta.cpp + ${BASE}/zonemeta.h + ${BASE}/zrule.cpp + ${BASE}/zrule.h + ${BASE}/ztrans.cpp + ${BASE}/ztrans.h) + +add_library(icu_i18n ${SHARED} ${SOURCES}) +target_include_directories(icu_i18n PUBLIC ${BASE}) +target_link_libraries(icu_i18n icu_common) + +add_library(icu_i18n_stubdata ${SHARED} ${SOURCES}) +target_include_directories(icu_i18n_stubdata PUBLIC ${BASE}) +target_link_libraries(icu_i18n_stubdata icu_common_stubdata) diff --git a/cmake/icu/tools/CMakeLists.txt b/cmake/icu/tools/CMakeLists.txt new file mode 100644 index 00000000000000..adf854a4a573c5 --- /dev/null +++ b/cmake/icu/tools/CMakeLists.txt @@ -0,0 +1,94 @@ +include(../../common.cmake) +project(icu_tools) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/icu-small/source/tools) + +include_directories(${BASE}/toolutil) + +add_library( + icu_toolutil ${SHARED} + ${BASE}/toolutil/collationinfo.cpp + ${BASE}/toolutil/collationinfo.h + ${BASE}/toolutil/dbgutil.cpp + ${BASE}/toolutil/dbgutil.h + ${BASE}/toolutil/denseranges.cpp + ${BASE}/toolutil/denseranges.h + ${BASE}/toolutil/filestrm.cpp + ${BASE}/toolutil/filestrm.h + ${BASE}/toolutil/filetools.cpp + ${BASE}/toolutil/filetools.h + ${BASE}/toolutil/flagparser.cpp + ${BASE}/toolutil/flagparser.h + ${BASE}/toolutil/package.cpp + ${BASE}/toolutil/package.h + ${BASE}/toolutil/pkg_genc.cpp + ${BASE}/toolutil/pkg_genc.h + ${BASE}/toolutil/pkg_gencmn.cpp + ${BASE}/toolutil/pkg_gencmn.h + ${BASE}/toolutil/pkg_icu.cpp + ${BASE}/toolutil/pkg_icu.h + ${BASE}/toolutil/pkg_imp.h + ${BASE}/toolutil/pkgitems.cpp + ${BASE}/toolutil/ppucd.cpp + ${BASE}/toolutil/ppucd.h + ${BASE}/toolutil/swapimpl.cpp + ${BASE}/toolutil/swapimpl.h + ${BASE}/toolutil/toolutil.cpp + ${BASE}/toolutil/toolutil.h + ${BASE}/toolutil/ucbuf.cpp + ${BASE}/toolutil/ucbuf.h + ${BASE}/toolutil/ucln_tu.cpp + ${BASE}/toolutil/ucm.cpp + ${BASE}/toolutil/ucm.h + ${BASE}/toolutil/ucmstate.cpp + ${BASE}/toolutil/udbgutil.cpp + ${BASE}/toolutil/udbgutil.h + ${BASE}/toolutil/unewdata.cpp + ${BASE}/toolutil/unewdata.h + ${BASE}/toolutil/uoptions.cpp + ${BASE}/toolutil/uoptions.h + ${BASE}/toolutil/uparse.cpp + ${BASE}/toolutil/uparse.h + ${BASE}/toolutil/writesrc.cpp + ${BASE}/toolutil/writesrc.h + ${BASE}/toolutil/xmlparser.cpp + ${BASE}/toolutil/xmlparser.h) + +target_compile_definitions(icu_toolutil PRIVATE U_TOOLUTIL_IMPLEMENTATION=1) +target_link_libraries(icu_toolutil icu_common_stubdata icu_i18n_stubdata) + +add_executable( + genrb + ${BASE}/genrb/errmsg.c + ${BASE}/genrb/errmsg.h + ${BASE}/genrb/genrb.cpp + ${BASE}/genrb/genrb.h + ${BASE}/genrb/parse.cpp + ${BASE}/genrb/parse.h + ${BASE}/genrb/prscmnts.cpp + ${BASE}/genrb/prscmnts.h + ${BASE}/genrb/rbutil.c + ${BASE}/genrb/rbutil.h + ${BASE}/genrb/read.c + ${BASE}/genrb/read.h + ${BASE}/genrb/reslist.cpp + ${BASE}/genrb/reslist.h + ${BASE}/genrb/rle.c + ${BASE}/genrb/rle.h + ${BASE}/genrb/ustr.c + ${BASE}/genrb/ustr.h + ${BASE}/genrb/wrtjava.cpp + ${BASE}/genrb/wrtxml.cpp) +target_link_libraries(genrb icu_toolutil) + +add_executable( + genccode + ${BASE}/genccode/genccode.c + ${BASE}/../stubdata/stubdata.cpp) +target_link_libraries(genccode icu_toolutil) + +add_executable(icupkg ${BASE}/icupkg/icupkg.cpp) +target_link_libraries(icupkg icu_toolutil) + +add_executable(iculslocs ${CMAKE_SOURCE_DIR}/tools/icu/iculslocs.cc) +target_link_libraries(iculslocs icu_toolutil) diff --git a/cmake/nghttp2/CMakeLists.txt b/cmake/nghttp2/CMakeLists.txt new file mode 100644 index 00000000000000..886b42e70454e8 --- /dev/null +++ b/cmake/nghttp2/CMakeLists.txt @@ -0,0 +1,41 @@ +include(../common.cmake) +project(nghttp2) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/nghttp2) + +set(SOURCES + ${BASE}/lib/nghttp2_buf.c + ${BASE}/lib/nghttp2_callbacks.c + ${BASE}/lib/nghttp2_debug.c + ${BASE}/lib/nghttp2_frame.c + ${BASE}/lib/nghttp2_hd.c + ${BASE}/lib/nghttp2_hd_huffman.c + ${BASE}/lib/nghttp2_hd_huffman_data.c + ${BASE}/lib/nghttp2_helper.c + ${BASE}/lib/nghttp2_http.c + ${BASE}/lib/nghttp2_map.c + ${BASE}/lib/nghttp2_mem.c + ${BASE}/lib/nghttp2_npn.c + ${BASE}/lib/nghttp2_option.c + ${BASE}/lib/nghttp2_outbound_item.c + ${BASE}/lib/nghttp2_pq.c + ${BASE}/lib/nghttp2_priority_spec.c + ${BASE}/lib/nghttp2_queue.c + ${BASE}/lib/nghttp2_rcbuf.c + ${BASE}/lib/nghttp2_session.c + ${BASE}/lib/nghttp2_stream.c + ${BASE}/lib/nghttp2_submit.c + ${BASE}/lib/nghttp2_version.c) + +if(debug_nghttp2) + add_definitions(-DDEBUGBUILD=1) +endif() + +if(win32) + add_definitions(-DWIN32 -D_WINDOWS -DHAVE_CONFIG_H -DNGHTTP2_STATICLIB) +endif() + +include_directories(${BASE}/lib/includes) + +add_library(nghttp2 ${SHARED} ${SOURCES}) +target_include_directories(nghttp2 PUBLIC ${BASE}/lib/includes) diff --git a/cmake/node/CMakeLists.txt b/cmake/node/CMakeLists.txt new file mode 100644 index 00000000000000..42e7e059f8c7e3 --- /dev/null +++ b/cmake/node/CMakeLists.txt @@ -0,0 +1,408 @@ +include(../common.cmake) +project(node) + +set(BASE ${CMAKE_SOURCE_DIR}) + +set(LIBS cares http_parser icu_common icu_i18n icu_common_data nghttp2 uv v8) + +# TODO(bnoordhuis) Make ICU and icu-small support configurable. +add_definitions( + -DNODE_ARCH="${NODE_ARCH}" + -DNODE_HAVE_I18N_SUPPORT=1 + # -DNODE_HAVE_SMALL_ICU=1 + -DNODE_OPENSSL_SYSTEM_CERT_PATH="${openssl_system_ca_path}" + -DNODE_PLATFORM="${NODE_PLATFORM}" + -DNODE_USE_V8_PLATFORM=$ + -DNODE_WANT_INTERNALS=1 + -DV8_DEPRECATION_WARNINGS=1) + +set(JAVASCRIPT_SOURCES + ${BASE}/config.gypi + ${BASE}/deps/acorn/dist/acorn.js + ${BASE}/deps/acorn/dist/walk.js + ${BASE}/deps/node-inspect/lib/_inspect.js + ${BASE}/deps/node-inspect/lib/internal/inspect_client.js + ${BASE}/deps/node-inspect/lib/internal/inspect_repl.js + ${BASE}/deps/v8/tools/SourceMap.js + ${BASE}/deps/v8/tools/codemap.js + ${BASE}/deps/v8/tools/consarray.js + ${BASE}/deps/v8/tools/csvparser.js + ${BASE}/deps/v8/tools/logreader.js + ${BASE}/deps/v8/tools/profile.js + ${BASE}/deps/v8/tools/profile_view.js + ${BASE}/deps/v8/tools/splaytree.js + ${BASE}/deps/v8/tools/tickprocessor-driver.js + ${BASE}/deps/v8/tools/tickprocessor.js + ${BASE}/lib/_http_agent.js + ${BASE}/lib/_http_client.js + ${BASE}/lib/_http_common.js + ${BASE}/lib/_http_incoming.js + ${BASE}/lib/_http_outgoing.js + ${BASE}/lib/_http_server.js + ${BASE}/lib/_stream_duplex.js + ${BASE}/lib/_stream_passthrough.js + ${BASE}/lib/_stream_readable.js + ${BASE}/lib/_stream_transform.js + ${BASE}/lib/_stream_wrap.js + ${BASE}/lib/_stream_writable.js + ${BASE}/lib/_tls_common.js + ${BASE}/lib/_tls_legacy.js + ${BASE}/lib/_tls_wrap.js + ${BASE}/lib/assert.js + ${BASE}/lib/async_hooks.js + ${BASE}/lib/buffer.js + ${BASE}/lib/child_process.js + ${BASE}/lib/cluster.js + ${BASE}/lib/console.js + ${BASE}/lib/constants.js + ${BASE}/lib/crypto.js + ${BASE}/lib/dgram.js + ${BASE}/lib/dns.js + ${BASE}/lib/domain.js + ${BASE}/lib/events.js + ${BASE}/lib/fs.js + ${BASE}/lib/http.js + ${BASE}/lib/http2.js + ${BASE}/lib/https.js + ${BASE}/lib/inspector.js + ${BASE}/lib/internal/async_hooks.js + ${BASE}/lib/internal/bootstrap_node.js + ${BASE}/lib/internal/buffer.js + ${BASE}/lib/internal/child_process.js + ${BASE}/lib/internal/cluster/child.js + ${BASE}/lib/internal/cluster/master.js + ${BASE}/lib/internal/cluster/round_robin_handle.js + ${BASE}/lib/internal/cluster/shared_handle.js + ${BASE}/lib/internal/cluster/utils.js + ${BASE}/lib/internal/cluster/worker.js + ${BASE}/lib/internal/crypto/certificate.js + ${BASE}/lib/internal/crypto/cipher.js + ${BASE}/lib/internal/crypto/diffiehellman.js + ${BASE}/lib/internal/crypto/hash.js + ${BASE}/lib/internal/crypto/pbkdf2.js + ${BASE}/lib/internal/crypto/random.js + ${BASE}/lib/internal/crypto/sig.js + ${BASE}/lib/internal/crypto/util.js + ${BASE}/lib/internal/encoding.js + ${BASE}/lib/internal/errors.js + ${BASE}/lib/internal/freelist.js + ${BASE}/lib/internal/fs.js + ${BASE}/lib/internal/http.js + ${BASE}/lib/internal/http2/compat.js + ${BASE}/lib/internal/http2/core.js + ${BASE}/lib/internal/http2/util.js + ${BASE}/lib/internal/inspector_async_hook.js + ${BASE}/lib/internal/linkedlist.js + ${BASE}/lib/internal/loader/Loader.js + ${BASE}/lib/internal/loader/ModuleJob.js + ${BASE}/lib/internal/loader/ModuleMap.js + ${BASE}/lib/internal/loader/ModuleRequest.js + ${BASE}/lib/internal/loader/ModuleWrap.js + ${BASE}/lib/internal/loader/search.js + ${BASE}/lib/internal/module.js + ${BASE}/lib/internal/net.js + ${BASE}/lib/internal/os.js + ${BASE}/lib/internal/process.js + ${BASE}/lib/internal/process/next_tick.js + ${BASE}/lib/internal/process/promises.js + ${BASE}/lib/internal/process/stdio.js + ${BASE}/lib/internal/process/warning.js + ${BASE}/lib/internal/process/write-coverage.js + ${BASE}/lib/internal/querystring.js + ${BASE}/lib/internal/readline.js + ${BASE}/lib/internal/repl.js + ${BASE}/lib/internal/repl/await.js + ${BASE}/lib/internal/safe_globals.js + ${BASE}/lib/internal/socket_list.js + ${BASE}/lib/internal/streams/BufferList.js + ${BASE}/lib/internal/streams/destroy.js + ${BASE}/lib/internal/streams/lazy_transform.js + ${BASE}/lib/internal/streams/legacy.js + ${BASE}/lib/internal/test/unicode.js + ${BASE}/lib/internal/timers.js + ${BASE}/lib/internal/tls.js + ${BASE}/lib/internal/trace_events_async_hooks.js + ${BASE}/lib/internal/url.js + ${BASE}/lib/internal/util.js + ${BASE}/lib/internal/util/comparisons.js + ${BASE}/lib/internal/util/inspector.js + ${BASE}/lib/internal/util/types.js + ${BASE}/lib/internal/v8.js + ${BASE}/lib/internal/v8_prof_polyfill.js + ${BASE}/lib/internal/v8_prof_processor.js + ${BASE}/lib/internal/wrap_js_stream.js + ${BASE}/lib/module.js + ${BASE}/lib/net.js + ${BASE}/lib/os.js + ${BASE}/lib/path.js + ${BASE}/lib/perf_hooks.js + ${BASE}/lib/process.js + ${BASE}/lib/punycode.js + ${BASE}/lib/querystring.js + ${BASE}/lib/readline.js + ${BASE}/lib/repl.js + ${BASE}/lib/stream.js + ${BASE}/lib/string_decoder.js + ${BASE}/lib/sys.js + ${BASE}/lib/timers.js + ${BASE}/lib/tls.js + ${BASE}/lib/tty.js + ${BASE}/lib/url.js + ${BASE}/lib/util.js + ${BASE}/lib/v8.js + ${BASE}/lib/vm.js + ${BASE}/lib/zlib.js) + +set(SOURCES + ${BASE}/src/CNNICHashWhitelist.inc + ${BASE}/src/StartComAndWoSignData.inc + ${BASE}/src/async_wrap-inl.h + ${BASE}/src/async_wrap.cc + ${BASE}/src/async_wrap.h + ${BASE}/src/base_object-inl.h + ${BASE}/src/base_object.h + ${BASE}/src/cares_wrap.cc + ${BASE}/src/connect_wrap.cc + ${BASE}/src/connect_wrap.h + ${BASE}/src/connection_wrap.cc + ${BASE}/src/connection_wrap.h + ${BASE}/src/env-inl.h + ${BASE}/src/env.cc + ${BASE}/src/env.h + ${BASE}/src/freelist.h + ${BASE}/src/fs_event_wrap.cc + ${BASE}/src/handle_wrap.cc + ${BASE}/src/handle_wrap.h + ${BASE}/src/js_stream.cc + ${BASE}/src/js_stream.h + ${BASE}/src/module_wrap.cc + ${BASE}/src/module_wrap.h + ${BASE}/src/node.cc + ${BASE}/src/node.h + ${BASE}/src/node_api.cc + ${BASE}/src/node_api.h + ${BASE}/src/node_api_types.h + ${BASE}/src/node_buffer.cc + ${BASE}/src/node_buffer.h + ${BASE}/src/node_config.cc + ${BASE}/src/node_constants.cc + ${BASE}/src/node_constants.h + ${BASE}/src/node_contextify.cc + ${BASE}/src/node_debug_options.cc + ${BASE}/src/node_debug_options.h + ${BASE}/src/node_file.cc + ${BASE}/src/node_http2.cc + ${BASE}/src/node_http2.h + ${BASE}/src/node_http2_state.h + ${BASE}/src/node_http_parser.cc + ${BASE}/src/node_i18n.cc + ${BASE}/src/node_i18n.h + ${BASE}/src/node_internals.h + ${BASE}/src/node_javascript.h + ${BASE}/src/node_mutex.h + ${BASE}/src/node_os.cc + ${BASE}/src/node_perf.cc + ${BASE}/src/node_perf_common.h + ${BASE}/src/node_platform.cc + ${BASE}/src/node_platform.h + ${BASE}/src/node_revert.h + ${BASE}/src/node_root_certs.h + ${BASE}/src/node_serdes.cc + ${BASE}/src/node_stat_watcher.cc + ${BASE}/src/node_trace_events.cc + ${BASE}/src/node_url.cc + ${BASE}/src/node_util.cc + ${BASE}/src/node_v8.cc + ${BASE}/src/node_version.h + ${BASE}/src/node_watchdog.cc + ${BASE}/src/node_watchdog.h + ${BASE}/src/node_wrap.h + ${BASE}/src/node_zlib.cc + ${BASE}/src/pipe_wrap.cc + ${BASE}/src/pipe_wrap.h + ${BASE}/src/process_wrap.cc + ${BASE}/src/req_wrap-inl.h + ${BASE}/src/req_wrap.h + ${BASE}/src/signal_wrap.cc + ${BASE}/src/spawn_sync.cc + ${BASE}/src/stream_base-inl.h + ${BASE}/src/stream_base.cc + ${BASE}/src/stream_base.h + ${BASE}/src/stream_wrap.cc + ${BASE}/src/stream_wrap.h + ${BASE}/src/string_bytes.cc + ${BASE}/src/string_bytes.h + ${BASE}/src/string_search.cc + ${BASE}/src/tcp_wrap.cc + ${BASE}/src/tcp_wrap.h + ${BASE}/src/timer_wrap.cc + ${BASE}/src/tracing/agent.cc + ${BASE}/src/tracing/agent.h + ${BASE}/src/tracing/node_trace_buffer.cc + ${BASE}/src/tracing/node_trace_buffer.h + ${BASE}/src/tracing/node_trace_writer.cc + ${BASE}/src/tracing/node_trace_writer.h + ${BASE}/src/tracing/trace_event.cc + ${BASE}/src/tracing/trace_event.h + ${BASE}/src/tracing/trace_event_common.h + ${BASE}/src/tty_wrap.cc + ${BASE}/src/tty_wrap.h + ${BASE}/src/udp_wrap.cc + ${BASE}/src/udp_wrap.h + ${BASE}/src/util-inl.h + ${BASE}/src/util.cc + ${BASE}/src/util.h + ${BASE}/src/uv.cc + ${CMAKE_CURRENT_BINARY_DIR}/node_javascript.cc) + +set(CCTEST_SOURCES + ${BASE}/test/cctest/node_test_fixture.cc + ${BASE}/test/cctest/test_aliased_buffer.cc + ${BASE}/test/cctest/test_base64.cc + ${BASE}/test/cctest/test_environment.cc + ${BASE}/test/cctest/test_url.cc + ${BASE}/test/cctest/test_util.cc) + +if(debug_http2) # Poorly named flag. + add_definitions(-DNODE_DEBUG_HTTP2=1) +endif() + +if(node_enable_v8_vtunejit) + add_definitions(-DNODE_ENABLE_VTUNE_PROFILING) + set(LIBS ${LIBS} v8_vtune) +endif() + +if(node_no_browser_globals) + add_definitions(-DNODE_NO_BROWSER_GLOBALS) +endif() + +if(node_release_urlbase) + add_definitions(-DNODE_RELEASE_URLBASE="${node_release_urlbase}") +endif() + +if(node_shared) + add_definitions(-DNODE_SHARED_MODE) +endif() + +if(node_tag) + add_definitions(-DNODE_TAG="${node_tag}") +endif() + +if(node_use_openssl) + add_definitions(-DHAVE_OPENSSL=1) + set(SOURCES ${SOURCES} + ${BASE}/src/node_crypto.cc + ${BASE}/src/node_crypto.h + ${BASE}/src/node_crypto_bio.cc + ${BASE}/src/node_crypto_bio.h + ${BASE}/src/node_crypto_clienthello.cc + ${BASE}/src/node_crypto_clienthello.h + ${BASE}/src/tls_wrap.cc + ${BASE}/src/tls_wrap.h) + set(LIBS ${LIBS} crypto ssl) +else() + add_definitions(-DHAVE_OPENSSL=0) +endif() + +if(node_use_openssl AND v8_enable_inspector) + add_definitions(-DHAVE_INSPECTOR=1) + + set(SOURCES ${SOURCES} + ${BASE}/src/inspector_agent.cc + ${BASE}/src/inspector_agent.h + ${BASE}/src/inspector_js_api.cc + ${BASE}/src/inspector_io.cc + ${BASE}/src/inspector_io.h + ${BASE}/src/inspector_socket.cc + ${BASE}/src/inspector_socket.h + ${BASE}/src/inspector_socket_server.cc + ${BASE}/src/inspector_socket_server.h + ${CMAKE_CURRENT_BINARY_DIR}/v8_inspector_protocol_json.h) + + set(CCTEST_SOURCES ${CCTEST_SOURCES} + ${BASE}/test/cctest/test_inspector_socket.cc + ${BASE}/test/cctest/test_inspector_socket_server.cc) +else() + add_definitions(-DHAVE_INSPECTOR=0) +endif() + +if(node_use_openssl_ca_store) + add_definitions(-DNODE_OPENSSL_CERT_STORE) +endif() + +if(node_use_v8_platform) + add_definitions(-DNODE_USE_V8_PLATFORM=1) +else() + add_definitions(-DNODE_USE_V8_PLATFORM=0) +endif() + +if(node_shared_zlib) + set(LIBS ${LIBS} z) +else() + set(LIBS ${LIBS} zlib) +endif() + +if(node_v8_options) + add_definitions(-DNODE_V8_OPTIONS="${node_v8_options}") +endif() + +if(node_without_node_options) + add_definitions(-DNODE_WITHOUT_NODE_OPTIONS) +endif() + +if(win32) + set(SOURCES ${SOURCES} ${BASE}/src/backtrace_win32.cc) +else() + add_definitions(-D__POSIX__=1) + set(SOURCES ${SOURCES} ${BASE}/src/backtrace_posix.cc) +endif() + +if(NOT MSVC) + set(CMAKE_CXX_FLAGS "-fno-exceptions -fno-rtti ${CMAKE_CXX_FLAGS}") +endif() + +if(NOT node_use_dtrace AND NOT node_use_etw) + set(JAVASCRIPT_SOURCES ${JAVASCRIPT_SOURCES} ${BASE}/src/notrace_macros.py) +endif() + +if(NOT node_use_lttng) + set(JAVASCRIPT_SOURCES ${JAVASCRIPT_SOURCES} ${BASE}/src/nolttng_macros.py) +endif() + +if(NOT node_use_perfctr) + set(JAVASCRIPT_SOURCES ${JAVASCRIPT_SOURCES} ${BASE}/src/noperfctr_macros.py) +endif() + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/tools/js2c.py + ${BASE} + ${CMAKE_CURRENT_BINARY_DIR}/node_javascript.cc + ${JAVASCRIPT_SOURCES} + DEPENDS + ${BASE}/tools/js2c.py + ${JAVASCRIPT_SOURCES} + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/node_javascript.cc) + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/tools/compress_json.py + ${BASE}/deps/v8/src/inspector/js_protocol.json + ${CMAKE_CURRENT_BINARY_DIR}/v8_inspector_protocol_json.h + DEPENDS + ${BASE}/tools/compress_json.py + ${BASE}/deps/v8/src/inspector/js_protocol.json + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/v8_inspector_protocol_json.h) + +include_directories(${BASE}/src ${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(node ${SOURCES} ${BASE}/src/node_main.cc) +target_link_libraries(node ${LIBS}) + +add_executable(cctest ${SOURCES} ${CCTEST_SOURCES}) +target_compile_definitions(cctest PRIVATE NODE_WANT_INTERNALS=1) +target_link_libraries(cctest gtest ${LIBS}) diff --git a/cmake/openssl/CMakeLists.txt b/cmake/openssl/CMakeLists.txt new file mode 100644 index 00000000000000..8a66f452bd4713 --- /dev/null +++ b/cmake/openssl/CMakeLists.txt @@ -0,0 +1,1218 @@ +include(../common.cmake) +project(openssl) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/openssl) + +add_definitions(-DOPENSSL_NO_COMP) +add_definitions(-DOPENSSL_NO_HEARTBEATS) +add_definitions(-DOPENSSL_NO_HW) +add_definitions(-DOPENSSL_NO_SSL3) +add_definitions(-D_REENTRANT) +include_directories(${BASE}) +include_directories(${BASE}/openssl) +include_directories(${BASE}/openssl/crypto) +include_directories(${BASE}/openssl/crypto/asn1) +include_directories(${BASE}/openssl/crypto/evp) +include_directories(${BASE}/openssl/crypto/modes) +include_directories(${BASE}/openssl/include) + +# FIXME(bnoordhuis) Derived from `python -c 'import sys; print(sys.byteorder)'` +# which is wrong when cross-compiling. +if(node_byteorder STREQUAL "big") + add_definitions(-DB_ENDIAN) +else() + add_definitions(-DL_ENDIAN) +endif() + +set(CRYPTO_SOURCES + ${BASE}/openssl/crypto/aes/aes_cfb.c + ${BASE}/openssl/crypto/aes/aes_ctr.c + ${BASE}/openssl/crypto/aes/aes_ecb.c + ${BASE}/openssl/crypto/aes/aes_ige.c + ${BASE}/openssl/crypto/aes/aes_misc.c + ${BASE}/openssl/crypto/aes/aes_ofb.c + ${BASE}/openssl/crypto/aes/aes_wrap.c + ${BASE}/openssl/crypto/asn1/a_bitstr.c + ${BASE}/openssl/crypto/asn1/a_bool.c + ${BASE}/openssl/crypto/asn1/a_bytes.c + ${BASE}/openssl/crypto/asn1/a_d2i_fp.c + ${BASE}/openssl/crypto/asn1/a_digest.c + ${BASE}/openssl/crypto/asn1/a_dup.c + ${BASE}/openssl/crypto/asn1/a_enum.c + ${BASE}/openssl/crypto/asn1/a_gentm.c + ${BASE}/openssl/crypto/asn1/a_i2d_fp.c + ${BASE}/openssl/crypto/asn1/a_int.c + ${BASE}/openssl/crypto/asn1/a_mbstr.c + ${BASE}/openssl/crypto/asn1/a_object.c + ${BASE}/openssl/crypto/asn1/a_octet.c + ${BASE}/openssl/crypto/asn1/a_print.c + ${BASE}/openssl/crypto/asn1/a_set.c + ${BASE}/openssl/crypto/asn1/a_sign.c + ${BASE}/openssl/crypto/asn1/a_strex.c + ${BASE}/openssl/crypto/asn1/a_strnid.c + ${BASE}/openssl/crypto/asn1/a_time.c + ${BASE}/openssl/crypto/asn1/a_type.c + ${BASE}/openssl/crypto/asn1/a_utctm.c + ${BASE}/openssl/crypto/asn1/a_utf8.c + ${BASE}/openssl/crypto/asn1/a_verify.c + ${BASE}/openssl/crypto/asn1/ameth_lib.c + ${BASE}/openssl/crypto/asn1/asn1_err.c + ${BASE}/openssl/crypto/asn1/asn1_gen.c + ${BASE}/openssl/crypto/asn1/asn1_lib.c + ${BASE}/openssl/crypto/asn1/asn1_par.c + ${BASE}/openssl/crypto/asn1/asn_mime.c + ${BASE}/openssl/crypto/asn1/asn_moid.c + ${BASE}/openssl/crypto/asn1/asn_pack.c + ${BASE}/openssl/crypto/asn1/bio_asn1.c + ${BASE}/openssl/crypto/asn1/bio_ndef.c + ${BASE}/openssl/crypto/asn1/d2i_pr.c + ${BASE}/openssl/crypto/asn1/d2i_pu.c + ${BASE}/openssl/crypto/asn1/evp_asn1.c + ${BASE}/openssl/crypto/asn1/f_enum.c + ${BASE}/openssl/crypto/asn1/f_int.c + ${BASE}/openssl/crypto/asn1/f_string.c + ${BASE}/openssl/crypto/asn1/i2d_pr.c + ${BASE}/openssl/crypto/asn1/i2d_pu.c + ${BASE}/openssl/crypto/asn1/n_pkey.c + ${BASE}/openssl/crypto/asn1/nsseq.c + ${BASE}/openssl/crypto/asn1/p5_pbe.c + ${BASE}/openssl/crypto/asn1/p5_pbev2.c + ${BASE}/openssl/crypto/asn1/p8_pkey.c + ${BASE}/openssl/crypto/asn1/t_bitst.c + ${BASE}/openssl/crypto/asn1/t_crl.c + ${BASE}/openssl/crypto/asn1/t_pkey.c + ${BASE}/openssl/crypto/asn1/t_req.c + ${BASE}/openssl/crypto/asn1/t_spki.c + ${BASE}/openssl/crypto/asn1/t_x509.c + ${BASE}/openssl/crypto/asn1/t_x509a.c + ${BASE}/openssl/crypto/asn1/tasn_dec.c + ${BASE}/openssl/crypto/asn1/tasn_enc.c + ${BASE}/openssl/crypto/asn1/tasn_fre.c + ${BASE}/openssl/crypto/asn1/tasn_new.c + ${BASE}/openssl/crypto/asn1/tasn_prn.c + ${BASE}/openssl/crypto/asn1/tasn_typ.c + ${BASE}/openssl/crypto/asn1/tasn_utl.c + ${BASE}/openssl/crypto/asn1/x_algor.c + ${BASE}/openssl/crypto/asn1/x_attrib.c + ${BASE}/openssl/crypto/asn1/x_bignum.c + ${BASE}/openssl/crypto/asn1/x_crl.c + ${BASE}/openssl/crypto/asn1/x_exten.c + ${BASE}/openssl/crypto/asn1/x_info.c + ${BASE}/openssl/crypto/asn1/x_long.c + ${BASE}/openssl/crypto/asn1/x_name.c + ${BASE}/openssl/crypto/asn1/x_nx509.c + ${BASE}/openssl/crypto/asn1/x_pkey.c + ${BASE}/openssl/crypto/asn1/x_pubkey.c + ${BASE}/openssl/crypto/asn1/x_req.c + ${BASE}/openssl/crypto/asn1/x_sig.c + ${BASE}/openssl/crypto/asn1/x_spki.c + ${BASE}/openssl/crypto/asn1/x_val.c + ${BASE}/openssl/crypto/asn1/x_x509.c + ${BASE}/openssl/crypto/asn1/x_x509a.c + ${BASE}/openssl/crypto/bf/bf_cfb64.c + ${BASE}/openssl/crypto/bf/bf_ecb.c + ${BASE}/openssl/crypto/bf/bf_ofb64.c + ${BASE}/openssl/crypto/bf/bf_skey.c + ${BASE}/openssl/crypto/bio/b_dump.c + ${BASE}/openssl/crypto/bio/b_print.c + ${BASE}/openssl/crypto/bio/b_sock.c + ${BASE}/openssl/crypto/bio/bf_buff.c + ${BASE}/openssl/crypto/bio/bf_nbio.c + ${BASE}/openssl/crypto/bio/bf_null.c + ${BASE}/openssl/crypto/bio/bio_cb.c + ${BASE}/openssl/crypto/bio/bio_err.c + ${BASE}/openssl/crypto/bio/bio_lib.c + ${BASE}/openssl/crypto/bio/bss_acpt.c + ${BASE}/openssl/crypto/bio/bss_bio.c + ${BASE}/openssl/crypto/bio/bss_conn.c + ${BASE}/openssl/crypto/bio/bss_dgram.c + ${BASE}/openssl/crypto/bio/bss_fd.c + ${BASE}/openssl/crypto/bio/bss_file.c + ${BASE}/openssl/crypto/bio/bss_log.c + ${BASE}/openssl/crypto/bio/bss_mem.c + ${BASE}/openssl/crypto/bio/bss_null.c + ${BASE}/openssl/crypto/bio/bss_sock.c + ${BASE}/openssl/crypto/bn/bn_add.c + ${BASE}/openssl/crypto/bn/bn_blind.c + ${BASE}/openssl/crypto/bn/bn_const.c + ${BASE}/openssl/crypto/bn/bn_ctx.c + ${BASE}/openssl/crypto/bn/bn_depr.c + ${BASE}/openssl/crypto/bn/bn_div.c + ${BASE}/openssl/crypto/bn/bn_err.c + ${BASE}/openssl/crypto/bn/bn_exp.c + ${BASE}/openssl/crypto/bn/bn_exp2.c + ${BASE}/openssl/crypto/bn/bn_gcd.c + ${BASE}/openssl/crypto/bn/bn_gf2m.c + ${BASE}/openssl/crypto/bn/bn_kron.c + ${BASE}/openssl/crypto/bn/bn_lib.c + ${BASE}/openssl/crypto/bn/bn_mod.c + ${BASE}/openssl/crypto/bn/bn_mont.c + ${BASE}/openssl/crypto/bn/bn_mpi.c + ${BASE}/openssl/crypto/bn/bn_mul.c + ${BASE}/openssl/crypto/bn/bn_nist.c + ${BASE}/openssl/crypto/bn/bn_prime.c + ${BASE}/openssl/crypto/bn/bn_print.c + ${BASE}/openssl/crypto/bn/bn_rand.c + ${BASE}/openssl/crypto/bn/bn_recp.c + ${BASE}/openssl/crypto/bn/bn_shift.c + ${BASE}/openssl/crypto/bn/bn_sqr.c + ${BASE}/openssl/crypto/bn/bn_sqrt.c + ${BASE}/openssl/crypto/bn/bn_word.c + ${BASE}/openssl/crypto/bn/bn_x931p.c + ${BASE}/openssl/crypto/buffer/buf_err.c + ${BASE}/openssl/crypto/buffer/buf_str.c + ${BASE}/openssl/crypto/buffer/buffer.c + ${BASE}/openssl/crypto/camellia/cmll_cfb.c + ${BASE}/openssl/crypto/camellia/cmll_ctr.c + ${BASE}/openssl/crypto/camellia/cmll_ecb.c + ${BASE}/openssl/crypto/camellia/cmll_ofb.c + ${BASE}/openssl/crypto/camellia/cmll_utl.c + ${BASE}/openssl/crypto/cast/c_cfb64.c + ${BASE}/openssl/crypto/cast/c_ecb.c + ${BASE}/openssl/crypto/cast/c_ofb64.c + ${BASE}/openssl/crypto/cast/c_skey.c + ${BASE}/openssl/crypto/cmac/cm_ameth.c + ${BASE}/openssl/crypto/cmac/cm_pmeth.c + ${BASE}/openssl/crypto/cmac/cmac.c + ${BASE}/openssl/crypto/cms/cms_asn1.c + ${BASE}/openssl/crypto/cms/cms_att.c + ${BASE}/openssl/crypto/cms/cms_cd.c + ${BASE}/openssl/crypto/cms/cms_dd.c + ${BASE}/openssl/crypto/cms/cms_enc.c + ${BASE}/openssl/crypto/cms/cms_env.c + ${BASE}/openssl/crypto/cms/cms_err.c + ${BASE}/openssl/crypto/cms/cms_ess.c + ${BASE}/openssl/crypto/cms/cms_io.c + ${BASE}/openssl/crypto/cms/cms_kari.c + ${BASE}/openssl/crypto/cms/cms_lib.c + ${BASE}/openssl/crypto/cms/cms_pwri.c + ${BASE}/openssl/crypto/cms/cms_sd.c + ${BASE}/openssl/crypto/cms/cms_smime.c + ${BASE}/openssl/crypto/conf/conf_api.c + ${BASE}/openssl/crypto/conf/conf_def.c + ${BASE}/openssl/crypto/conf/conf_err.c + ${BASE}/openssl/crypto/conf/conf_lib.c + ${BASE}/openssl/crypto/conf/conf_mall.c + ${BASE}/openssl/crypto/conf/conf_mod.c + ${BASE}/openssl/crypto/conf/conf_sap.c + ${BASE}/openssl/crypto/cpt_err.c + ${BASE}/openssl/crypto/cryptlib.c + ${BASE}/openssl/crypto/cversion.c + ${BASE}/openssl/crypto/des/cbc_cksm.c + ${BASE}/openssl/crypto/des/cbc_enc.c + ${BASE}/openssl/crypto/des/cfb64ede.c + ${BASE}/openssl/crypto/des/cfb64enc.c + ${BASE}/openssl/crypto/des/cfb_enc.c + ${BASE}/openssl/crypto/des/des_old.c + ${BASE}/openssl/crypto/des/des_old2.c + ${BASE}/openssl/crypto/des/ecb3_enc.c + ${BASE}/openssl/crypto/des/ecb_enc.c + ${BASE}/openssl/crypto/des/ede_cbcm_enc.c + ${BASE}/openssl/crypto/des/enc_read.c + ${BASE}/openssl/crypto/des/enc_writ.c + ${BASE}/openssl/crypto/des/fcrypt.c + ${BASE}/openssl/crypto/des/ofb64ede.c + ${BASE}/openssl/crypto/des/ofb64enc.c + ${BASE}/openssl/crypto/des/ofb_enc.c + ${BASE}/openssl/crypto/des/pcbc_enc.c + ${BASE}/openssl/crypto/des/qud_cksm.c + ${BASE}/openssl/crypto/des/rand_key.c + ${BASE}/openssl/crypto/des/read2pwd.c + ${BASE}/openssl/crypto/des/rpc_enc.c + ${BASE}/openssl/crypto/des/set_key.c + ${BASE}/openssl/crypto/des/str2key.c + ${BASE}/openssl/crypto/des/xcbc_enc.c + ${BASE}/openssl/crypto/dh/dh_ameth.c + ${BASE}/openssl/crypto/dh/dh_asn1.c + ${BASE}/openssl/crypto/dh/dh_check.c + ${BASE}/openssl/crypto/dh/dh_depr.c + ${BASE}/openssl/crypto/dh/dh_err.c + ${BASE}/openssl/crypto/dh/dh_gen.c + ${BASE}/openssl/crypto/dh/dh_kdf.c + ${BASE}/openssl/crypto/dh/dh_key.c + ${BASE}/openssl/crypto/dh/dh_lib.c + ${BASE}/openssl/crypto/dh/dh_pmeth.c + ${BASE}/openssl/crypto/dh/dh_prn.c + ${BASE}/openssl/crypto/dh/dh_rfc5114.c + ${BASE}/openssl/crypto/dsa/dsa_ameth.c + ${BASE}/openssl/crypto/dsa/dsa_asn1.c + ${BASE}/openssl/crypto/dsa/dsa_depr.c + ${BASE}/openssl/crypto/dsa/dsa_err.c + ${BASE}/openssl/crypto/dsa/dsa_gen.c + ${BASE}/openssl/crypto/dsa/dsa_key.c + ${BASE}/openssl/crypto/dsa/dsa_lib.c + ${BASE}/openssl/crypto/dsa/dsa_ossl.c + ${BASE}/openssl/crypto/dsa/dsa_pmeth.c + ${BASE}/openssl/crypto/dsa/dsa_prn.c + ${BASE}/openssl/crypto/dsa/dsa_sign.c + ${BASE}/openssl/crypto/dsa/dsa_vrf.c + ${BASE}/openssl/crypto/dso/dso_beos.c + ${BASE}/openssl/crypto/dso/dso_dl.c + ${BASE}/openssl/crypto/dso/dso_dlfcn.c + ${BASE}/openssl/crypto/dso/dso_err.c + ${BASE}/openssl/crypto/dso/dso_lib.c + ${BASE}/openssl/crypto/dso/dso_null.c + ${BASE}/openssl/crypto/dso/dso_openssl.c + ${BASE}/openssl/crypto/dso/dso_vms.c + ${BASE}/openssl/crypto/dso/dso_win32.c + ${BASE}/openssl/crypto/ebcdic.c + ${BASE}/openssl/crypto/ec/ec2_mult.c + ${BASE}/openssl/crypto/ec/ec2_oct.c + ${BASE}/openssl/crypto/ec/ec2_smpl.c + ${BASE}/openssl/crypto/ec/ec_ameth.c + ${BASE}/openssl/crypto/ec/ec_asn1.c + ${BASE}/openssl/crypto/ec/ec_check.c + ${BASE}/openssl/crypto/ec/ec_curve.c + ${BASE}/openssl/crypto/ec/ec_cvt.c + ${BASE}/openssl/crypto/ec/ec_err.c + ${BASE}/openssl/crypto/ec/ec_key.c + ${BASE}/openssl/crypto/ec/ec_lib.c + ${BASE}/openssl/crypto/ec/ec_mult.c + ${BASE}/openssl/crypto/ec/ec_oct.c + ${BASE}/openssl/crypto/ec/ec_pmeth.c + ${BASE}/openssl/crypto/ec/ec_print.c + ${BASE}/openssl/crypto/ec/eck_prn.c + ${BASE}/openssl/crypto/ec/ecp_mont.c + ${BASE}/openssl/crypto/ec/ecp_nist.c + ${BASE}/openssl/crypto/ec/ecp_nistp224.c + ${BASE}/openssl/crypto/ec/ecp_nistp256.c + ${BASE}/openssl/crypto/ec/ecp_nistp521.c + ${BASE}/openssl/crypto/ec/ecp_nistputil.c + ${BASE}/openssl/crypto/ec/ecp_oct.c + ${BASE}/openssl/crypto/ec/ecp_smpl.c + ${BASE}/openssl/crypto/ecdh/ech_err.c + ${BASE}/openssl/crypto/ecdh/ech_kdf.c + ${BASE}/openssl/crypto/ecdh/ech_key.c + ${BASE}/openssl/crypto/ecdh/ech_lib.c + ${BASE}/openssl/crypto/ecdh/ech_ossl.c + ${BASE}/openssl/crypto/ecdsa/ecs_asn1.c + ${BASE}/openssl/crypto/ecdsa/ecs_err.c + ${BASE}/openssl/crypto/ecdsa/ecs_lib.c + ${BASE}/openssl/crypto/ecdsa/ecs_ossl.c + ${BASE}/openssl/crypto/ecdsa/ecs_sign.c + ${BASE}/openssl/crypto/ecdsa/ecs_vrf.c + ${BASE}/openssl/crypto/engine/eng_all.c + ${BASE}/openssl/crypto/engine/eng_cnf.c + ${BASE}/openssl/crypto/engine/eng_cryptodev.c + ${BASE}/openssl/crypto/engine/eng_ctrl.c + ${BASE}/openssl/crypto/engine/eng_dyn.c + ${BASE}/openssl/crypto/engine/eng_err.c + ${BASE}/openssl/crypto/engine/eng_fat.c + ${BASE}/openssl/crypto/engine/eng_init.c + ${BASE}/openssl/crypto/engine/eng_lib.c + ${BASE}/openssl/crypto/engine/eng_list.c + ${BASE}/openssl/crypto/engine/eng_openssl.c + ${BASE}/openssl/crypto/engine/eng_pkey.c + ${BASE}/openssl/crypto/engine/eng_rdrand.c + ${BASE}/openssl/crypto/engine/eng_table.c + ${BASE}/openssl/crypto/engine/tb_asnmth.c + ${BASE}/openssl/crypto/engine/tb_cipher.c + ${BASE}/openssl/crypto/engine/tb_dh.c + ${BASE}/openssl/crypto/engine/tb_digest.c + ${BASE}/openssl/crypto/engine/tb_dsa.c + ${BASE}/openssl/crypto/engine/tb_ecdh.c + ${BASE}/openssl/crypto/engine/tb_ecdsa.c + ${BASE}/openssl/crypto/engine/tb_pkmeth.c + ${BASE}/openssl/crypto/engine/tb_rand.c + ${BASE}/openssl/crypto/engine/tb_rsa.c + ${BASE}/openssl/crypto/engine/tb_store.c + ${BASE}/openssl/crypto/err/err.c + ${BASE}/openssl/crypto/err/err_all.c + ${BASE}/openssl/crypto/err/err_prn.c + ${BASE}/openssl/crypto/evp/bio_b64.c + ${BASE}/openssl/crypto/evp/bio_enc.c + ${BASE}/openssl/crypto/evp/bio_md.c + ${BASE}/openssl/crypto/evp/bio_ok.c + ${BASE}/openssl/crypto/evp/c_all.c + ${BASE}/openssl/crypto/evp/c_allc.c + ${BASE}/openssl/crypto/evp/c_alld.c + ${BASE}/openssl/crypto/evp/digest.c + ${BASE}/openssl/crypto/evp/e_aes.c + ${BASE}/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c + ${BASE}/openssl/crypto/evp/e_aes_cbc_hmac_sha256.c + ${BASE}/openssl/crypto/evp/e_bf.c + ${BASE}/openssl/crypto/evp/e_camellia.c + ${BASE}/openssl/crypto/evp/e_cast.c + ${BASE}/openssl/crypto/evp/e_des.c + ${BASE}/openssl/crypto/evp/e_des3.c + ${BASE}/openssl/crypto/evp/e_idea.c + ${BASE}/openssl/crypto/evp/e_null.c + ${BASE}/openssl/crypto/evp/e_old.c + ${BASE}/openssl/crypto/evp/e_rc2.c + ${BASE}/openssl/crypto/evp/e_rc4.c + ${BASE}/openssl/crypto/evp/e_rc4_hmac_md5.c + ${BASE}/openssl/crypto/evp/e_rc5.c + ${BASE}/openssl/crypto/evp/e_seed.c + ${BASE}/openssl/crypto/evp/e_xcbc_d.c + ${BASE}/openssl/crypto/evp/encode.c + ${BASE}/openssl/crypto/evp/evp_acnf.c + ${BASE}/openssl/crypto/evp/evp_cnf.c + ${BASE}/openssl/crypto/evp/evp_enc.c + ${BASE}/openssl/crypto/evp/evp_err.c + ${BASE}/openssl/crypto/evp/evp_key.c + ${BASE}/openssl/crypto/evp/evp_lib.c + ${BASE}/openssl/crypto/evp/evp_pbe.c + ${BASE}/openssl/crypto/evp/evp_pkey.c + ${BASE}/openssl/crypto/evp/m_dss.c + ${BASE}/openssl/crypto/evp/m_dss1.c + ${BASE}/openssl/crypto/evp/m_ecdsa.c + ${BASE}/openssl/crypto/evp/m_md2.c + ${BASE}/openssl/crypto/evp/m_md4.c + ${BASE}/openssl/crypto/evp/m_md5.c + ${BASE}/openssl/crypto/evp/m_mdc2.c + ${BASE}/openssl/crypto/evp/m_null.c + ${BASE}/openssl/crypto/evp/m_ripemd.c + ${BASE}/openssl/crypto/evp/m_sha.c + ${BASE}/openssl/crypto/evp/m_sha1.c + ${BASE}/openssl/crypto/evp/m_sigver.c + ${BASE}/openssl/crypto/evp/m_wp.c + ${BASE}/openssl/crypto/evp/names.c + ${BASE}/openssl/crypto/evp/p5_crpt.c + ${BASE}/openssl/crypto/evp/p5_crpt2.c + ${BASE}/openssl/crypto/evp/p_dec.c + ${BASE}/openssl/crypto/evp/p_enc.c + ${BASE}/openssl/crypto/evp/p_lib.c + ${BASE}/openssl/crypto/evp/p_open.c + ${BASE}/openssl/crypto/evp/p_seal.c + ${BASE}/openssl/crypto/evp/p_sign.c + ${BASE}/openssl/crypto/evp/p_verify.c + ${BASE}/openssl/crypto/evp/pmeth_fn.c + ${BASE}/openssl/crypto/evp/pmeth_gn.c + ${BASE}/openssl/crypto/evp/pmeth_lib.c + ${BASE}/openssl/crypto/ex_data.c + ${BASE}/openssl/crypto/fips_ers.c + ${BASE}/openssl/crypto/hmac/hm_ameth.c + ${BASE}/openssl/crypto/hmac/hm_pmeth.c + ${BASE}/openssl/crypto/hmac/hmac.c + ${BASE}/openssl/crypto/idea/i_cbc.c + ${BASE}/openssl/crypto/idea/i_cfb64.c + ${BASE}/openssl/crypto/idea/i_ecb.c + ${BASE}/openssl/crypto/idea/i_ofb64.c + ${BASE}/openssl/crypto/idea/i_skey.c + ${BASE}/openssl/crypto/krb5/krb5_asn.c + ${BASE}/openssl/crypto/lhash/lh_stats.c + ${BASE}/openssl/crypto/lhash/lhash.c + ${BASE}/openssl/crypto/md4/md4_dgst.c + ${BASE}/openssl/crypto/md4/md4_one.c + ${BASE}/openssl/crypto/md5/md5_dgst.c + ${BASE}/openssl/crypto/md5/md5_one.c + ${BASE}/openssl/crypto/mdc2/mdc2_one.c + ${BASE}/openssl/crypto/mdc2/mdc2dgst.c + ${BASE}/openssl/crypto/mem.c + ${BASE}/openssl/crypto/mem_dbg.c + ${BASE}/openssl/crypto/modes/cbc128.c + ${BASE}/openssl/crypto/modes/ccm128.c + ${BASE}/openssl/crypto/modes/cfb128.c + ${BASE}/openssl/crypto/modes/ctr128.c + ${BASE}/openssl/crypto/modes/cts128.c + ${BASE}/openssl/crypto/modes/gcm128.c + ${BASE}/openssl/crypto/modes/ofb128.c + ${BASE}/openssl/crypto/modes/wrap128.c + ${BASE}/openssl/crypto/modes/xts128.c + ${BASE}/openssl/crypto/o_dir.c + ${BASE}/openssl/crypto/o_fips.c + ${BASE}/openssl/crypto/o_init.c + ${BASE}/openssl/crypto/o_str.c + ${BASE}/openssl/crypto/o_time.c + ${BASE}/openssl/crypto/objects/o_names.c + ${BASE}/openssl/crypto/objects/obj_dat.c + ${BASE}/openssl/crypto/objects/obj_err.c + ${BASE}/openssl/crypto/objects/obj_lib.c + ${BASE}/openssl/crypto/objects/obj_xref.c + ${BASE}/openssl/crypto/ocsp/ocsp_asn.c + ${BASE}/openssl/crypto/ocsp/ocsp_cl.c + ${BASE}/openssl/crypto/ocsp/ocsp_err.c + ${BASE}/openssl/crypto/ocsp/ocsp_ext.c + ${BASE}/openssl/crypto/ocsp/ocsp_ht.c + ${BASE}/openssl/crypto/ocsp/ocsp_lib.c + ${BASE}/openssl/crypto/ocsp/ocsp_prn.c + ${BASE}/openssl/crypto/ocsp/ocsp_srv.c + ${BASE}/openssl/crypto/ocsp/ocsp_vfy.c + ${BASE}/openssl/crypto/pem/pem_all.c + ${BASE}/openssl/crypto/pem/pem_err.c + ${BASE}/openssl/crypto/pem/pem_info.c + ${BASE}/openssl/crypto/pem/pem_lib.c + ${BASE}/openssl/crypto/pem/pem_oth.c + ${BASE}/openssl/crypto/pem/pem_pk8.c + ${BASE}/openssl/crypto/pem/pem_pkey.c + ${BASE}/openssl/crypto/pem/pem_seal.c + ${BASE}/openssl/crypto/pem/pem_sign.c + ${BASE}/openssl/crypto/pem/pem_x509.c + ${BASE}/openssl/crypto/pem/pem_xaux.c + ${BASE}/openssl/crypto/pem/pvkfmt.c + ${BASE}/openssl/crypto/pkcs12/p12_add.c + ${BASE}/openssl/crypto/pkcs12/p12_asn.c + ${BASE}/openssl/crypto/pkcs12/p12_attr.c + ${BASE}/openssl/crypto/pkcs12/p12_crpt.c + ${BASE}/openssl/crypto/pkcs12/p12_crt.c + ${BASE}/openssl/crypto/pkcs12/p12_decr.c + ${BASE}/openssl/crypto/pkcs12/p12_init.c + ${BASE}/openssl/crypto/pkcs12/p12_key.c + ${BASE}/openssl/crypto/pkcs12/p12_kiss.c + ${BASE}/openssl/crypto/pkcs12/p12_mutl.c + ${BASE}/openssl/crypto/pkcs12/p12_npas.c + ${BASE}/openssl/crypto/pkcs12/p12_p8d.c + ${BASE}/openssl/crypto/pkcs12/p12_p8e.c + ${BASE}/openssl/crypto/pkcs12/p12_utl.c + ${BASE}/openssl/crypto/pkcs12/pk12err.c + ${BASE}/openssl/crypto/pkcs7/bio_pk7.c + ${BASE}/openssl/crypto/pkcs7/pk7_asn1.c + ${BASE}/openssl/crypto/pkcs7/pk7_attr.c + ${BASE}/openssl/crypto/pkcs7/pk7_doit.c + ${BASE}/openssl/crypto/pkcs7/pk7_lib.c + ${BASE}/openssl/crypto/pkcs7/pk7_mime.c + ${BASE}/openssl/crypto/pkcs7/pk7_smime.c + ${BASE}/openssl/crypto/pkcs7/pkcs7err.c + ${BASE}/openssl/crypto/pqueue/pqueue.c + ${BASE}/openssl/crypto/rand/md_rand.c + ${BASE}/openssl/crypto/rand/rand_egd.c + ${BASE}/openssl/crypto/rand/rand_err.c + ${BASE}/openssl/crypto/rand/rand_lib.c + ${BASE}/openssl/crypto/rand/rand_nw.c + ${BASE}/openssl/crypto/rand/rand_os2.c + ${BASE}/openssl/crypto/rand/rand_unix.c + ${BASE}/openssl/crypto/rand/rand_win.c + ${BASE}/openssl/crypto/rand/randfile.c + ${BASE}/openssl/crypto/rc2/rc2_cbc.c + ${BASE}/openssl/crypto/rc2/rc2_ecb.c + ${BASE}/openssl/crypto/rc2/rc2_skey.c + ${BASE}/openssl/crypto/rc2/rc2cfb64.c + ${BASE}/openssl/crypto/rc2/rc2ofb64.c + ${BASE}/openssl/crypto/rc4/rc4_utl.c + ${BASE}/openssl/crypto/ripemd/rmd_dgst.c + ${BASE}/openssl/crypto/ripemd/rmd_one.c + ${BASE}/openssl/crypto/rsa/rsa_ameth.c + ${BASE}/openssl/crypto/rsa/rsa_asn1.c + ${BASE}/openssl/crypto/rsa/rsa_chk.c + ${BASE}/openssl/crypto/rsa/rsa_crpt.c + ${BASE}/openssl/crypto/rsa/rsa_depr.c + ${BASE}/openssl/crypto/rsa/rsa_eay.c + ${BASE}/openssl/crypto/rsa/rsa_err.c + ${BASE}/openssl/crypto/rsa/rsa_gen.c + ${BASE}/openssl/crypto/rsa/rsa_lib.c + ${BASE}/openssl/crypto/rsa/rsa_none.c + ${BASE}/openssl/crypto/rsa/rsa_null.c + ${BASE}/openssl/crypto/rsa/rsa_oaep.c + ${BASE}/openssl/crypto/rsa/rsa_pk1.c + ${BASE}/openssl/crypto/rsa/rsa_pmeth.c + ${BASE}/openssl/crypto/rsa/rsa_prn.c + ${BASE}/openssl/crypto/rsa/rsa_pss.c + ${BASE}/openssl/crypto/rsa/rsa_saos.c + ${BASE}/openssl/crypto/rsa/rsa_sign.c + ${BASE}/openssl/crypto/rsa/rsa_ssl.c + ${BASE}/openssl/crypto/rsa/rsa_x931.c + ${BASE}/openssl/crypto/seed/seed.c + ${BASE}/openssl/crypto/seed/seed_cbc.c + ${BASE}/openssl/crypto/seed/seed_cfb.c + ${BASE}/openssl/crypto/seed/seed_ecb.c + ${BASE}/openssl/crypto/seed/seed_ofb.c + ${BASE}/openssl/crypto/sha/sha1_one.c + ${BASE}/openssl/crypto/sha/sha1dgst.c + ${BASE}/openssl/crypto/sha/sha256.c + ${BASE}/openssl/crypto/sha/sha512.c + ${BASE}/openssl/crypto/sha/sha_dgst.c + ${BASE}/openssl/crypto/sha/sha_one.c + ${BASE}/openssl/crypto/srp/srp_lib.c + ${BASE}/openssl/crypto/srp/srp_vfy.c + ${BASE}/openssl/crypto/stack/stack.c + ${BASE}/openssl/crypto/ts/ts_asn1.c + ${BASE}/openssl/crypto/ts/ts_conf.c + ${BASE}/openssl/crypto/ts/ts_err.c + ${BASE}/openssl/crypto/ts/ts_lib.c + ${BASE}/openssl/crypto/ts/ts_req_print.c + ${BASE}/openssl/crypto/ts/ts_req_utils.c + ${BASE}/openssl/crypto/ts/ts_rsp_print.c + ${BASE}/openssl/crypto/ts/ts_rsp_sign.c + ${BASE}/openssl/crypto/ts/ts_rsp_utils.c + ${BASE}/openssl/crypto/ts/ts_rsp_verify.c + ${BASE}/openssl/crypto/ts/ts_verify_ctx.c + ${BASE}/openssl/crypto/txt_db/txt_db.c + ${BASE}/openssl/crypto/ui/ui_err.c + ${BASE}/openssl/crypto/ui/ui_lib.c + ${BASE}/openssl/crypto/ui/ui_openssl.c + ${BASE}/openssl/crypto/ui/ui_util.c + ${BASE}/openssl/crypto/uid.c + ${BASE}/openssl/crypto/whrlpool/wp_dgst.c + ${BASE}/openssl/crypto/x509/by_dir.c + ${BASE}/openssl/crypto/x509/by_file.c + ${BASE}/openssl/crypto/x509/x509_att.c + ${BASE}/openssl/crypto/x509/x509_cmp.c + ${BASE}/openssl/crypto/x509/x509_d2.c + ${BASE}/openssl/crypto/x509/x509_def.c + ${BASE}/openssl/crypto/x509/x509_err.c + ${BASE}/openssl/crypto/x509/x509_ext.c + ${BASE}/openssl/crypto/x509/x509_lu.c + ${BASE}/openssl/crypto/x509/x509_obj.c + ${BASE}/openssl/crypto/x509/x509_r2x.c + ${BASE}/openssl/crypto/x509/x509_req.c + ${BASE}/openssl/crypto/x509/x509_set.c + ${BASE}/openssl/crypto/x509/x509_trs.c + ${BASE}/openssl/crypto/x509/x509_txt.c + ${BASE}/openssl/crypto/x509/x509_v3.c + ${BASE}/openssl/crypto/x509/x509_vfy.c + ${BASE}/openssl/crypto/x509/x509_vpm.c + ${BASE}/openssl/crypto/x509/x509cset.c + ${BASE}/openssl/crypto/x509/x509name.c + ${BASE}/openssl/crypto/x509/x509rset.c + ${BASE}/openssl/crypto/x509/x509spki.c + ${BASE}/openssl/crypto/x509/x509type.c + ${BASE}/openssl/crypto/x509/x_all.c + ${BASE}/openssl/crypto/x509v3/pcy_cache.c + ${BASE}/openssl/crypto/x509v3/pcy_data.c + ${BASE}/openssl/crypto/x509v3/pcy_lib.c + ${BASE}/openssl/crypto/x509v3/pcy_map.c + ${BASE}/openssl/crypto/x509v3/pcy_node.c + ${BASE}/openssl/crypto/x509v3/pcy_tree.c + ${BASE}/openssl/crypto/x509v3/v3_addr.c + ${BASE}/openssl/crypto/x509v3/v3_akey.c + ${BASE}/openssl/crypto/x509v3/v3_akeya.c + ${BASE}/openssl/crypto/x509v3/v3_alt.c + ${BASE}/openssl/crypto/x509v3/v3_asid.c + ${BASE}/openssl/crypto/x509v3/v3_bcons.c + ${BASE}/openssl/crypto/x509v3/v3_bitst.c + ${BASE}/openssl/crypto/x509v3/v3_conf.c + ${BASE}/openssl/crypto/x509v3/v3_cpols.c + ${BASE}/openssl/crypto/x509v3/v3_crld.c + ${BASE}/openssl/crypto/x509v3/v3_enum.c + ${BASE}/openssl/crypto/x509v3/v3_extku.c + ${BASE}/openssl/crypto/x509v3/v3_genn.c + ${BASE}/openssl/crypto/x509v3/v3_ia5.c + ${BASE}/openssl/crypto/x509v3/v3_info.c + ${BASE}/openssl/crypto/x509v3/v3_int.c + ${BASE}/openssl/crypto/x509v3/v3_lib.c + ${BASE}/openssl/crypto/x509v3/v3_ncons.c + ${BASE}/openssl/crypto/x509v3/v3_ocsp.c + ${BASE}/openssl/crypto/x509v3/v3_pci.c + ${BASE}/openssl/crypto/x509v3/v3_pcia.c + ${BASE}/openssl/crypto/x509v3/v3_pcons.c + ${BASE}/openssl/crypto/x509v3/v3_pku.c + ${BASE}/openssl/crypto/x509v3/v3_pmaps.c + ${BASE}/openssl/crypto/x509v3/v3_prn.c + ${BASE}/openssl/crypto/x509v3/v3_purp.c + ${BASE}/openssl/crypto/x509v3/v3_scts.c + ${BASE}/openssl/crypto/x509v3/v3_skey.c + ${BASE}/openssl/crypto/x509v3/v3_sxnet.c + ${BASE}/openssl/crypto/x509v3/v3_utl.c + ${BASE}/openssl/crypto/x509v3/v3err.c + ${BASE}/openssl/engines/e_4758cca.c + ${BASE}/openssl/engines/e_aep.c + ${BASE}/openssl/engines/e_atalla.c + ${BASE}/openssl/engines/e_capi.c + ${BASE}/openssl/engines/e_chil.c + ${BASE}/openssl/engines/e_cswift.c + ${BASE}/openssl/engines/e_gmp.c + ${BASE}/openssl/engines/e_nuron.c + ${BASE}/openssl/engines/e_sureware.c + ${BASE}/openssl/engines/e_ubsec.c) + +set(SSL_SOURCES + ${BASE}/openssl/ssl/bio_ssl.c + ${BASE}/openssl/ssl/d1_both.c + ${BASE}/openssl/ssl/d1_clnt.c + ${BASE}/openssl/ssl/d1_lib.c + ${BASE}/openssl/ssl/d1_meth.c + ${BASE}/openssl/ssl/d1_pkt.c + ${BASE}/openssl/ssl/d1_srtp.c + ${BASE}/openssl/ssl/d1_srvr.c + ${BASE}/openssl/ssl/kssl.c + ${BASE}/openssl/ssl/s23_clnt.c + ${BASE}/openssl/ssl/s23_lib.c + ${BASE}/openssl/ssl/s23_meth.c + ${BASE}/openssl/ssl/s23_pkt.c + ${BASE}/openssl/ssl/s23_srvr.c + ${BASE}/openssl/ssl/s2_clnt.c + ${BASE}/openssl/ssl/s2_enc.c + ${BASE}/openssl/ssl/s2_lib.c + ${BASE}/openssl/ssl/s2_meth.c + ${BASE}/openssl/ssl/s2_pkt.c + ${BASE}/openssl/ssl/s2_srvr.c + ${BASE}/openssl/ssl/s3_both.c + ${BASE}/openssl/ssl/s3_cbc.c + ${BASE}/openssl/ssl/s3_clnt.c + ${BASE}/openssl/ssl/s3_enc.c + ${BASE}/openssl/ssl/s3_lib.c + ${BASE}/openssl/ssl/s3_meth.c + ${BASE}/openssl/ssl/s3_pkt.c + ${BASE}/openssl/ssl/s3_srvr.c + ${BASE}/openssl/ssl/ssl_algs.c + ${BASE}/openssl/ssl/ssl_asn1.c + ${BASE}/openssl/ssl/ssl_cert.c + ${BASE}/openssl/ssl/ssl_ciph.c + ${BASE}/openssl/ssl/ssl_conf.c + ${BASE}/openssl/ssl/ssl_err.c + ${BASE}/openssl/ssl/ssl_err2.c + ${BASE}/openssl/ssl/ssl_lib.c + ${BASE}/openssl/ssl/ssl_rsa.c + ${BASE}/openssl/ssl/ssl_sess.c + ${BASE}/openssl/ssl/ssl_stat.c + ${BASE}/openssl/ssl/ssl_txt.c + ${BASE}/openssl/ssl/ssl_utst.c + ${BASE}/openssl/ssl/t1_clnt.c + ${BASE}/openssl/ssl/t1_enc.c + ${BASE}/openssl/ssl/t1_ext.c + ${BASE}/openssl/ssl/t1_lib.c + ${BASE}/openssl/ssl/t1_meth.c + ${BASE}/openssl/ssl/t1_reneg.c + ${BASE}/openssl/ssl/t1_srvr.c + ${BASE}/openssl/ssl/t1_trce.c + ${BASE}/openssl/ssl/tls_srp.c) + +set(openssl_defines_asm + -DAES_ASM + -DCPUID_ASM + -DOPENSSL_BN_ASM_MONT + -DOPENSSL_CPUID_OBJ + -DSHA1_ASM + -DSHA256_ASM + -DSHA512_ASM + -DGHASH_ASM) + +set(openssl_defines_arm64 + -DOPENSSL_CPUID_OBJ + -DSHA1_ASM + -DSHA256_ASM + -DSHA512_ASM) + +set(openssl_defines_non_arm + -DVPAES_ASM + -DBN_ASM + -DBF_ASM + -DBNCO_ASM + -DDES_ASM + -DLIB_BN_ASM + -DMD5_ASM + -DOPENSSL_BN_ASM + -DRIP_ASM + -DRMD160_ASM + -DWHIRLPOOL_ASM + -DWP_ASM) + +set(openssl_defines_all_win + -DDSO_WIN32 + -D_CRT_SECURE_NO_DEPRECATE + # following two defines are moved from openssconf.h + -DOPENSSL_NO_DYNAMIC_ENGINE + # to avoid build errors on Win. See openssl/engines/e_capi.c + -DOPENSSL_NO_CAPIENG) + +set(openssl_defines_all_non_win + -DDSO_DLFCN + -DHAVE_DLFCN_H) + +set(openssl_defines_ia32_elf + ${openssl_defines_non_arm} + -DOPENSSL_BN_ASM_PART_WORDS) + +set(openssl_defines_ia32_mac + ${openssl_defines_non_arm} + -DOPENSSL_BN_ASM_PART_WORDS) + +set(openssl_defines_ia32_win + ${openssl_defines_non_arm} + -DOPENSSL_BN_ASM_PART_WORDS) + +set(openssl_defines_x64_elf + ${openssl_defines_non_arm} + -DOPENSSL_BN_ASM_MONT5 + -DOPENSSL_BN_ASM_GF2m + -DOPENSSL_IA32_SSE2 + -DBSAES_ASM) + +set(openssl_defines_x64_mac + ${openssl_defines_non_arm} + -DOPENSSL_BN_ASM_MONT5 + -DOPENSSL_BN_ASM_GF2m + -DOPENSSL_IA32_SSE2 + -DBSAES_ASM) + +set(openssl_defines_x64_win + ${openssl_defines_non_arm} + -DOPENSSL_BN_ASM_MONT5 + -DOPENSSL_BN_ASM_GF2m + -DOPENSSL_IA32_SSE2 + -DBSAES_ASM) + +set(openssl_sources_no_asm + ${BASE}/openssl/crypto/aes/aes_cbc.c + ${BASE}/openssl/crypto/aes/aes_core.c + ${BASE}/openssl/crypto/bf/bf_enc.c + ${BASE}/openssl/crypto/bn/bn_asm.c + ${BASE}/openssl/crypto/cast/c_enc.c + ${BASE}/openssl/crypto/camellia/camellia.c + ${BASE}/openssl/crypto/camellia/cmll_cbc.c + ${BASE}/openssl/crypto/camellia/cmll_misc.c + ${BASE}/openssl/crypto/des/des_enc.c + ${BASE}/openssl/crypto/des/fcrypt_b.c + ${BASE}/openssl/crypto/mem_clr.c + ${BASE}/openssl/crypto/rc4/rc4_enc.c + ${BASE}/openssl/crypto/rc4/rc4_skey.c + ${BASE}/openssl/crypto/whrlpool/wp_block.c) + +set(openssl_sources_asm_latest_ia32_elf_gas + ${BASE}/asm/x86-elf-gas/aes/aes-586.s + ${BASE}/asm/x86-elf-gas/aes/aesni-x86.s + ${BASE}/asm/x86-elf-gas/aes/vpaes-x86.s + ${BASE}/asm/x86-elf-gas/bf/bf-586.s + ${BASE}/asm/x86-elf-gas/bn/bn-586.s + ${BASE}/asm/x86-elf-gas/bn/co-586.s + ${BASE}/asm/x86-elf-gas/bn/x86-mont.s + ${BASE}/asm/x86-elf-gas/bn/x86-gf2m.s + ${BASE}/asm/x86-elf-gas/camellia/cmll-x86.s + ${BASE}/asm/x86-elf-gas/cast/cast-586.s + ${BASE}/asm/x86-elf-gas/des/crypt586.s + ${BASE}/asm/x86-elf-gas/des/des-586.s + ${BASE}/asm/x86-elf-gas/md5/md5-586.s + ${BASE}/asm/x86-elf-gas/rc4/rc4-586.s + ${BASE}/asm/x86-elf-gas/ripemd/rmd-586.s + ${BASE}/asm/x86-elf-gas/sha/sha1-586.s + ${BASE}/asm/x86-elf-gas/sha/sha256-586.s + ${BASE}/asm/x86-elf-gas/sha/sha512-586.s + ${BASE}/asm/x86-elf-gas/whrlpool/wp-mmx.s + ${BASE}/asm/x86-elf-gas/modes/ghash-x86.s + ${BASE}/asm/x86-elf-gas/x86cpuid.s) + +set(openssl_sources_asm_obsolete_ia32_elf_gas + ${BASE}/asm_obsolete/x86-elf-gas/aes/aes-586.s + ${BASE}/asm_obsolete/x86-elf-gas/aes/aesni-x86.s + ${BASE}/asm_obsolete/x86-elf-gas/aes/vpaes-x86.s + ${BASE}/asm_obsolete/x86-elf-gas/bf/bf-586.s + ${BASE}/asm_obsolete/x86-elf-gas/bn/bn-586.s + ${BASE}/asm_obsolete/x86-elf-gas/bn/co-586.s + ${BASE}/asm_obsolete/x86-elf-gas/bn/x86-mont.s + ${BASE}/asm_obsolete/x86-elf-gas/bn/x86-gf2m.s + ${BASE}/asm_obsolete/x86-elf-gas/camellia/cmll-x86.s + ${BASE}/asm_obsolete/x86-elf-gas/cast/cast-586.s + ${BASE}/asm_obsolete/x86-elf-gas/des/crypt586.s + ${BASE}/asm_obsolete/x86-elf-gas/des/des-586.s + ${BASE}/asm_obsolete/x86-elf-gas/md5/md5-586.s + ${BASE}/asm_obsolete/x86-elf-gas/rc4/rc4-586.s + ${BASE}/asm_obsolete/x86-elf-gas/ripemd/rmd-586.s + ${BASE}/asm_obsolete/x86-elf-gas/sha/sha1-586.s + ${BASE}/asm_obsolete/x86-elf-gas/sha/sha256-586.s + ${BASE}/asm_obsolete/x86-elf-gas/sha/sha512-586.s + ${BASE}/asm_obsolete/x86-elf-gas/whrlpool/wp-mmx.s + ${BASE}/asm_obsolete/x86-elf-gas/modes/ghash-x86.s + ${BASE}/asm_obsolete/x86-elf-gas/x86cpuid.s) + +set(openssl_sources_common_ia32 + ${BASE}/openssl/crypto/whrlpool/wp_block.c) + +set(openssl_sources_asm_latest_x64_elf_gas + ${BASE}/asm/x64-elf-gas/aes/aes-x86_64.s + ${BASE}/asm/x64-elf-gas/aes/aesni-mb-x86_64.s + ${BASE}/asm/x64-elf-gas/aes/aesni-sha256-x86_64.s + ${BASE}/asm/x64-elf-gas/aes/aesni-x86_64.s + ${BASE}/asm/x64-elf-gas/aes/vpaes-x86_64.s + ${BASE}/asm/x64-elf-gas/aes/bsaes-x86_64.s + ${BASE}/asm/x64-elf-gas/aes/aesni-sha1-x86_64.s + ${BASE}/asm/x64-elf-gas/bn/rsaz-avx2.s + ${BASE}/asm/x64-elf-gas/bn/rsaz-x86_64.s + ${BASE}/asm/x64-elf-gas/bn/x86_64-mont.s + ${BASE}/asm/x64-elf-gas/bn/x86_64-mont5.s + ${BASE}/asm/x64-elf-gas/bn/x86_64-gf2m.s + ${BASE}/asm/x64-elf-gas/camellia/cmll-x86_64.s + ${BASE}/asm/x64-elf-gas/ec/ecp_nistz256-x86_64.s + ${BASE}/asm/x64-elf-gas/md5/md5-x86_64.s + ${BASE}/asm/x64-elf-gas/rc4/rc4-x86_64.s + ${BASE}/asm/x64-elf-gas/rc4/rc4-md5-x86_64.s + ${BASE}/asm/x64-elf-gas/sha/sha1-mb-x86_64.s + ${BASE}/asm/x64-elf-gas/sha/sha1-x86_64.s + ${BASE}/asm/x64-elf-gas/sha/sha256-mb-x86_64.s + ${BASE}/asm/x64-elf-gas/sha/sha256-x86_64.s + ${BASE}/asm/x64-elf-gas/sha/sha512-x86_64.s + ${BASE}/asm/x64-elf-gas/whrlpool/wp-x86_64.s + ${BASE}/asm/x64-elf-gas/modes/aesni-gcm-x86_64.s + ${BASE}/asm/x64-elf-gas/modes/ghash-x86_64.s + ${BASE}/asm/x64-elf-gas/x86_64cpuid.s) + +set(openssl_sources_asm_obsolete_x64_elf_gas + ${BASE}/asm_obsolete/x64-elf-gas/aes/aes-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/aes/aesni-mb-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/aes/aesni-sha256-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/aes/aesni-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/aes/vpaes-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/aes/bsaes-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/aes/aesni-sha1-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/bn/rsaz-avx2.s + ${BASE}/asm_obsolete/x64-elf-gas/bn/rsaz-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/bn/x86_64-mont.s + ${BASE}/asm_obsolete/x64-elf-gas/bn/x86_64-mont5.s + ${BASE}/asm_obsolete/x64-elf-gas/bn/x86_64-gf2m.s + ${BASE}/asm_obsolete/x64-elf-gas/camellia/cmll-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/ec/ecp_nistz256-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/md5/md5-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/rc4/rc4-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/rc4/rc4-md5-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/sha/sha1-mb-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/sha/sha1-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/sha/sha256-mb-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/sha/sha256-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/sha/sha512-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/whrlpool/wp-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/modes/aesni-gcm-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/modes/ghash-x86_64.s + ${BASE}/asm_obsolete/x64-elf-gas/x86_64cpuid.s) + +set(openssl_sources_common_x64_elf_gas + # Non-generated asm + ${BASE}/openssl/crypto/bn/asm/x86_64-gcc.c + # No asm available + ${BASE}/openssl/crypto/bf/bf_enc.c + ${BASE}/openssl/crypto/bn/rsaz_exp.c + ${BASE}/openssl/crypto/cast/c_enc.c + ${BASE}/openssl/crypto/camellia/cmll_misc.c + ${BASE}/openssl/crypto/des/des_enc.c + ${BASE}/openssl/crypto/des/fcrypt_b.c + ${BASE}/openssl/crypto/ec/ecp_nistz256.c + ${BASE}/openssl/crypto/ui/ui_compat.c) + +set(openssl_sources_asm_latest_ia32_mac_gas + ${BASE}/asm/x86-macosx-gas/aes/aes-586.s + ${BASE}/asm/x86-macosx-gas/aes/aesni-x86.s + ${BASE}/asm/x86-macosx-gas/aes/vpaes-x86.s + ${BASE}/asm/x86-macosx-gas/bf/bf-586.s + ${BASE}/asm/x86-macosx-gas/bn/bn-586.s + ${BASE}/asm/x86-macosx-gas/bn/co-586.s + ${BASE}/asm/x86-macosx-gas/bn/x86-mont.s + ${BASE}/asm/x86-macosx-gas/bn/x86-gf2m.s + ${BASE}/asm/x86-macosx-gas/camellia/cmll-x86.s + ${BASE}/asm/x86-macosx-gas/cast/cast-586.s + ${BASE}/asm/x86-macosx-gas/des/crypt586.s + ${BASE}/asm/x86-macosx-gas/des/des-586.s + ${BASE}/asm/x86-macosx-gas/md5/md5-586.s + ${BASE}/asm/x86-macosx-gas/rc4/rc4-586.s + ${BASE}/asm/x86-macosx-gas/ripemd/rmd-586.s + ${BASE}/asm/x86-macosx-gas/sha/sha1-586.s + ${BASE}/asm/x86-macosx-gas/sha/sha256-586.s + ${BASE}/asm/x86-macosx-gas/sha/sha512-586.s + ${BASE}/asm/x86-macosx-gas/whrlpool/wp-mmx.s + ${BASE}/asm/x86-macosx-gas/modes/ghash-x86.s + ${BASE}/asm/x86-macosx-gas/x86cpuid.s) + +set(openssl_sources_asm_obsolete_ia32_mac_gas + ${BASE}/asm_obsolete/x86-macosx-gas/aes/aes-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/aes/aesni-x86.s + ${BASE}/asm_obsolete/x86-macosx-gas/aes/vpaes-x86.s + ${BASE}/asm_obsolete/x86-macosx-gas/bf/bf-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/bn/bn-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/bn/co-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/bn/x86-mont.s + ${BASE}/asm_obsolete/x86-macosx-gas/bn/x86-gf2m.s + ${BASE}/asm_obsolete/x86-macosx-gas/camellia/cmll-x86.s + ${BASE}/asm_obsolete/x86-macosx-gas/cast/cast-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/des/crypt586.s + ${BASE}/asm_obsolete/x86-macosx-gas/des/des-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/md5/md5-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/rc4/rc4-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/ripemd/rmd-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/sha/sha1-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/sha/sha256-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/sha/sha512-586.s + ${BASE}/asm_obsolete/x86-macosx-gas/whrlpool/wp-mmx.s + ${BASE}/asm_obsolete/x86-macosx-gas/modes/ghash-x86.s + ${BASE}/asm_obsolete/x86-macosx-gas/x86cpuid.s) + +set(openssl_sources_asm_latest_x64_mac_gas + ${BASE}/asm/x64-macosx-gas/aes/aes-x86_64.s + ${BASE}/asm/x64-macosx-gas/aes/aesni-x86_64.s + ${BASE}/asm/x64-macosx-gas/aes/vpaes-x86_64.s + ${BASE}/asm/x64-macosx-gas/aes/aesni-mb-x86_64.s + ${BASE}/asm/x64-macosx-gas/aes/aesni-sha256-x86_64.s + ${BASE}/asm/x64-macosx-gas/aes/bsaes-x86_64.s + ${BASE}/asm/x64-macosx-gas/aes/aesni-sha1-x86_64.s + ${BASE}/asm/x64-macosx-gas/bn/rsaz-avx2.s + ${BASE}/asm/x64-macosx-gas/bn/rsaz-x86_64.s + ${BASE}/asm/x64-macosx-gas/bn/x86_64-mont.s + ${BASE}/asm/x64-macosx-gas/bn/x86_64-mont5.s + ${BASE}/asm/x64-macosx-gas/bn/x86_64-gf2m.s + ${BASE}/asm/x64-macosx-gas/camellia/cmll-x86_64.s + ${BASE}/asm/x64-macosx-gas/ec/ecp_nistz256-x86_64.s + ${BASE}/asm/x64-macosx-gas/md5/md5-x86_64.s + ${BASE}/asm/x64-macosx-gas/sha/sha1-mb-x86_64.s + ${BASE}/asm/x64-macosx-gas/sha/sha1-x86_64.s + ${BASE}/asm/x64-macosx-gas/sha/sha256-mb-x86_64.s + ${BASE}/asm/x64-macosx-gas/sha/sha256-x86_64.s + ${BASE}/asm/x64-macosx-gas/sha/sha512-x86_64.s + ${BASE}/asm/x64-macosx-gas/whrlpool/wp-x86_64.s + ${BASE}/asm/x64-macosx-gas/modes/aesni-gcm-x86_64.s + ${BASE}/asm/x64-macosx-gas/modes/ghash-x86_64.s + ${BASE}/asm/x64-macosx-gas/x86_64cpuid.s) + +set(openssl_sources_asm_obsolete_x64_mac_gas + ${BASE}/asm_obsolete/x64-macosx-gas/aes/aes-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/aes/aesni-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/aes/vpaes-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/aes/aesni-mb-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/aes/aesni-sha256-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/aes/bsaes-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/aes/aesni-sha1-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/bn/rsaz-avx2.s + ${BASE}/asm_obsolete/x64-macosx-gas/bn/rsaz-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/bn/x86_64-mont.s + ${BASE}/asm_obsolete/x64-macosx-gas/bn/x86_64-mont5.s + ${BASE}/asm_obsolete/x64-macosx-gas/bn/x86_64-gf2m.s + ${BASE}/asm_obsolete/x64-macosx-gas/camellia/cmll-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/ec/ecp_nistz256-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/md5/md5-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/sha/sha1-mb-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/sha/sha1-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/sha/sha256-mb-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/sha/sha256-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/sha/sha512-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/whrlpool/wp-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/modes/aesni-gcm-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/modes/ghash-x86_64.s + ${BASE}/asm_obsolete/x64-macosx-gas/x86_64cpuid.s) + +set(openssl_sources_common_x64_mac_gas + # Non-generated asm + ${BASE}/openssl/crypto/bn/asm/x86_64-gcc.c + # No asm available + ${BASE}/openssl/crypto/bf/bf_enc.c + ${BASE}/openssl/crypto/bn/rsaz_exp.c + ${BASE}/openssl/crypto/cast/c_enc.c + ${BASE}/openssl/crypto/camellia/cmll_misc.c + ${BASE}/openssl/crypto/des/des_enc.c + ${BASE}/openssl/crypto/des/fcrypt_b.c + ${BASE}/openssl/crypto/ec/ecp_nistz256.c + ${BASE}/openssl/crypto/ui/ui_compat.c + ${BASE}/openssl/crypto/rc4/rc4_skey.c + ${BASE}/openssl/crypto/rc4/rc4_enc.c) + +set(openssl_sources_arm_void_gas + ${BASE}/asm/arm-void-gas/aes/aes-armv4.S + ${BASE}/asm/arm-void-gas/aes/bsaes-armv7.S + ${BASE}/asm/arm-void-gas/aes/aesv8-armx.S + ${BASE}/asm/arm-void-gas/bn/armv4-mont.S + ${BASE}/asm/arm-void-gas/bn/armv4-gf2m.S + ${BASE}/asm/arm-void-gas/sha/sha1-armv4-large.S + ${BASE}/asm/arm-void-gas/sha/sha512-armv4.S + ${BASE}/asm/arm-void-gas/sha/sha256-armv4.S + ${BASE}/asm/arm-void-gas/modes/ghash-armv4.S + ${BASE}/asm/arm-void-gas/modes/ghashv8-armx.S + # No asm available + ${BASE}/openssl/crypto/aes/aes_cbc.c + ${BASE}/openssl/crypto/bf/bf_enc.c + ${BASE}/openssl/crypto/bn/bn_asm.c + ${BASE}/openssl/crypto/cast/c_enc.c + ${BASE}/openssl/crypto/camellia/camellia.c + ${BASE}/openssl/crypto/camellia/cmll_cbc.c + ${BASE}/openssl/crypto/camellia/cmll_misc.c + ${BASE}/openssl/crypto/des/des_enc.c + ${BASE}/openssl/crypto/des/fcrypt_b.c + ${BASE}/openssl/crypto/rc4/rc4_enc.c + ${BASE}/openssl/crypto/rc4/rc4_skey.c + ${BASE}/openssl/crypto/ui/ui_compat.c + ${BASE}/openssl/crypto/whrlpool/wp_block.c + # PCAP stuff + ${BASE}/openssl/crypto/armcap.c + ${BASE}/openssl/crypto/armv4cpuid.S) + +set(openssl_sources_arm64_linux64_gas + ${BASE}/asm/arm64-linux64-gas/aes/aesv8-armx.S + ${BASE}/asm/arm64-linux64-gas/modes/ghashv8-armx.S + ${BASE}/asm/arm64-linux64-gas/sha/sha1-armv8.S + ${BASE}/asm/arm64-linux64-gas/sha/sha256-armv8.S + ${BASE}/asm/arm64-linux64-gas/sha/sha512-armv8.S + # No asm available + ${BASE}/openssl/crypto/aes/aes_core.c + ${BASE}/openssl/crypto/aes/aes_cbc.c + ${BASE}/openssl/crypto/bn/bn_asm.c + ${BASE}/openssl/crypto/bf/bf_enc.c + ${BASE}/openssl/crypto/cast/c_enc.c + ${BASE}/openssl/crypto/camellia/camellia.c + ${BASE}/openssl/crypto/camellia/cmll_cbc.c + ${BASE}/openssl/crypto/camellia/cmll_misc.c + ${BASE}/openssl/crypto/des/des_enc.c + ${BASE}/openssl/crypto/des/fcrypt_b.c + ${BASE}/openssl/crypto/rc4/rc4_enc.c + ${BASE}/openssl/crypto/rc4/rc4_skey.c + ${BASE}/openssl/crypto/whrlpool/wp_block.c + ${BASE}/openssl/crypto/mem_clr.c + # PCAP stuff + ${BASE}/openssl/crypto/armcap.c + ${BASE}/openssl/crypto/arm64cpuid.S) + +set(openssl_sources_asm_ia32_win_masm + ${BASE}/asm/x86-win32-masm/aes/aes-586.asm + ${BASE}/asm/x86-win32-masm/aes/aesni-x86.asm + ${BASE}/asm/x86-win32-masm/aes/vpaes-x86.asm + ${BASE}/asm/x86-win32-masm/bf/bf-586.asm + ${BASE}/asm/x86-win32-masm/bn/bn-586.asm + ${BASE}/asm/x86-win32-masm/bn/co-586.asm + ${BASE}/asm/x86-win32-masm/bn/x86-mont.asm + ${BASE}/asm/x86-win32-masm/bn/x86-gf2m.asm + ${BASE}/asm/x86-win32-masm/camellia/cmll-x86.asm + ${BASE}/asm/x86-win32-masm/cast/cast-586.asm + ${BASE}/asm/x86-win32-masm/des/crypt586.asm + ${BASE}/asm/x86-win32-masm/des/des-586.asm + ${BASE}/asm/x86-win32-masm/md5/md5-586.asm + ${BASE}/asm/x86-win32-masm/rc4/rc4-586.asm + ${BASE}/asm/x86-win32-masm/ripemd/rmd-586.asm + ${BASE}/asm/x86-win32-masm/sha/sha1-586.asm + ${BASE}/asm/x86-win32-masm/sha/sha256-586.asm + ${BASE}/asm/x86-win32-masm/sha/sha512-586.asm + ${BASE}/asm/x86-win32-masm/whrlpool/wp-mmx.asm + ${BASE}/asm/x86-win32-masm/modes/ghash-x86.asm + ${BASE}/asm/x86-win32-masm/x86cpuid.asm) + +set(openssl_sources_asm_latest_x64_win_masm + ${BASE}/asm/x64-win32-masm/aes/aes-x86_64.asm + ${BASE}/asm/x64-win32-masm/aes/aesni-x86_64.asm + ${BASE}/asm/x64-win32-masm/aes/aesni-mb-x86_64.asm + ${BASE}/asm/x64-win32-masm/aes/aesni-sha256-x86_64.asm + ${BASE}/asm/x64-win32-masm/aes/vpaes-x86_64.asm + ${BASE}/asm/x64-win32-masm/aes/bsaes-x86_64.asm + ${BASE}/asm/x64-win32-masm/aes/aesni-sha1-x86_64.asm + ${BASE}/asm/x64-win32-masm/bn/rsaz-avx2.asm + ${BASE}/asm/x64-win32-masm/bn/rsaz-x86_64.asm + ${BASE}/asm/x64-win32-masm/bn/x86_64-mont.asm + ${BASE}/asm/x64-win32-masm/bn/x86_64-mont5.asm + ${BASE}/asm/x64-win32-masm/bn/x86_64-gf2m.asm + ${BASE}/asm/x64-win32-masm/camellia/cmll-x86_64.asm + ${BASE}/asm/x64-win32-masm/ec/ecp_nistz256-x86_64.asm + ${BASE}/asm/x64-win32-masm/md5/md5-x86_64.asm + ${BASE}/asm/x64-win32-masm/rc4/rc4-x86_64.asm + ${BASE}/asm/x64-win32-masm/rc4/rc4-md5-x86_64.asm + ${BASE}/asm/x64-win32-masm/sha/sha1-mb-x86_64.asm + ${BASE}/asm/x64-win32-masm/sha/sha1-x86_64.asm + ${BASE}/asm/x64-win32-masm/sha/sha256-mb-x86_64.asm + ${BASE}/asm/x64-win32-masm/sha/sha256-x86_64.asm + ${BASE}/asm/x64-win32-masm/sha/sha512-x86_64.asm + ${BASE}/asm/x64-win32-masm/whrlpool/wp-x86_64.asm + ${BASE}/asm/x64-win32-masm/modes/aesni-gcm-x86_64.asm + ${BASE}/asm/x64-win32-masm/modes/ghash-x86_64.asm + ${BASE}/asm/x64-win32-masm/x86_64cpuid.asm) + +set(openssl_sources_asm_obsolete_x64_win_masm + ${BASE}/asm_obsolete/x64-win32-masm/aes/aes-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/aes/aesni-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/aes/aesni-mb-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/aes/aesni-sha256-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/aes/vpaes-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/aes/bsaes-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/aes/aesni-sha1-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/bn/rsaz-avx2.asm + ${BASE}/asm_obsolete/x64-win32-masm/bn/rsaz-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/bn/x86_64-mont.asm + ${BASE}/asm_obsolete/x64-win32-masm/bn/x86_64-mont5.asm + ${BASE}/asm_obsolete/x64-win32-masm/bn/x86_64-gf2m.asm + ${BASE}/asm_obsolete/x64-win32-masm/camellia/cmll-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/ec/ecp_nistz256-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/md5/md5-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/rc4/rc4-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/rc4/rc4-md5-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/sha/sha1-mb-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/sha/sha1-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/sha/sha256-mb-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/sha/sha256-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/sha/sha512-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/whrlpool/wp-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/modes/aesni-gcm-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/modes/ghash-x86_64.asm + ${BASE}/asm_obsolete/x64-win32-masm/x86_64cpuid.asm) + +set(openssl_sources_common_x64_win_masm + # No asm available + ${BASE}/openssl/crypto/bn/bn_asm.c + ${BASE}/openssl/crypto/bf/bf_enc.c + ${BASE}/openssl/crypto/bn/rsaz_exp.c + ${BASE}/openssl/crypto/cast/c_enc.c + ${BASE}/openssl/crypto/camellia/cmll_misc.c + ${BASE}/openssl/crypto/des/des_enc.c + ${BASE}/openssl/crypto/des/fcrypt_b.c + ${BASE}/openssl/crypto/ec/ecp_nistz256.c + ${BASE}/openssl/crypto/ui/ui_compat.c) + +set(openssl_sources_x64_win_masm + ${openssl_sources_common_x64_win_masm} + ${openssl_sources_asm_latest_x64_win_masm}) + +set(openssl_sources_ia32_mac_gas + ${openssl_sources_common_ia32} + ${openssl_sources_asm_latest_ia32_mac_gas}) + +set(openssl_sources_x64_mac_gas + ${openssl_sources_common_x64_mac_gas} + ${openssl_sources_asm_latest_x64_mac_gas}) + +set(openssl_sources_ia32_elf_gas + ${openssl_sources_common_ia32} + ${openssl_sources_asm_latest_ia32_elf_gas}) + +set(openssl_sources_x64_elf_gas + ${openssl_sources_common_x64_elf_gas} + ${openssl_sources_asm_latest_x64_elf_gas}) + +if(NOT openssl_no_asm AND arm) + add_definitions(${openssl_defines_asm}) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_arm_void_gas}) +elseif(NOT openssl_no_asm AND arm64) + add_definitions(${openssl_defines_arm64}) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_arm64_linux64_gas}) +elseif(NOT openssl_no_asm AND ia32 AND mac) + add_definitions(${openssl_defines_asm} ${openssl_defines_ia32_mac}) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_ia32_mac_gas}) +elseif(NOT openssl_no_asm AND ia32 AND win) + add_definitions(${openssl_defines_asm} ${openssl_defines_ia32_win}) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_ia32_win_masm}) +elseif(NOT openssl_no_asm AND ia32) + add_definitions(${openssl_defines_asm} ${openssl_defines_ia32_elf}) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_ia32_elf_gas}) +elseif(NOT openssl_no_asm AND x64 AND mac) + add_definitions(${openssl_defines_asm} ${openssl_defines_x64_mac}) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_x64_mac_gas}) +elseif(NOT openssl_no_asm AND x64 AND win) + add_definitions(${openssl_defines_asm} ${openssl_defines_x64_win}) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_x64_win_masm}) +elseif(NOT openssl_no_asm AND x64) + add_definitions(${openssl_defines_asm} ${openssl_defines_x64_elf}) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_x64_elf_gas}) +else() + # openssl_no_asm in effect or no asm available for this arch/os combo. + add_definitions(-DOPENSSL_NO_ASM) + set(CRYPTO_SOURCES ${CRYPTO_SOURCES} ${openssl_sources_no_asm}) + set(openssl_no_asm FALSE) +endif() + +if(NOT openssl_no_asm) + enable_language(ASM) +endif() + +if(win32) + # TODO(bnoordhuis) Use /safeseh, see commit 01fa5ee. + add_definitions( + -DDSO_WIN32 + -DMK1MF_BUILD + -DOPENSSL_NO_CAPIENG + -DOPENSSL_NO_DYNAMIC_ENGINE + -DOPENSSL_SYSNAME_WIN32 + -DWIN32_LEAN_AND_MEAN + -D_CRT_SECURE_NO_DEPRECATE) + link_libraries(ws2_32 gdi32 advapi32 crypt32 user32) +else() + add_definitions( + -DDSO_DLFCN + -DENGINESDIR="/dev/null" + -DHAVE_DLFCN_H + -DTERMIOS) + if(mac) + add_definitions(-DOPENSSLDIR="/System/Library/OpenSSL/") + else() + add_definitions(-DOPENSSLDIR="/etc/ssl") + endif() +endif() + +add_library(crypto ${SHARED} ${CRYPTO_SOURCES}) + +if(openssl_fips) + target_include_directories(crypto PUBLIC ${openssl_fips}/include) + target_compile_definitions(crypto PUBLIC OPENSSL_FIPS) + add_definitions(-DOPENSSL_FIPS) +else() + target_include_directories(crypto PUBLIC ${BASE}/openssl/include) +endif() + +add_library(ssl ${SHARED} ${SSL_SOURCES}) +target_link_libraries(ssl crypto) +target_include_directories(ssl PUBLIC ${BASE}/openssl/include) diff --git a/cmake/uv/CMakeLists.txt b/cmake/uv/CMakeLists.txt new file mode 100644 index 00000000000000..787ebb48ce702b --- /dev/null +++ b/cmake/uv/CMakeLists.txt @@ -0,0 +1,211 @@ +include(../common.cmake) +project(uv) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/uv) + +set(SOURCES + ${BASE}/include/tree.h + ${BASE}/include/uv-errno.h + ${BASE}/include/uv-threadpool.h + ${BASE}/include/uv-version.h + ${BASE}/include/uv.h + ${BASE}/src/fs-poll.c + ${BASE}/src/heap-inl.h + ${BASE}/src/inet.c + ${BASE}/src/queue.h + ${BASE}/src/threadpool.c + ${BASE}/src/uv-common.c + ${BASE}/src/uv-common.h + ${BASE}/src/version.c) + +if(win32) + set(DEFINES ${DEFINES} _GNU_SOURCE _WIN32_WINNT=0x0600) + set(LIBS ${LIBS} advapi32 iphlpapi psapi shell32 user32 userenv ws2_32) + set(SOURCES ${SOURCES} + ${BASE}/include/uv-win.h + ${BASE}/src/win/async.c + ${BASE}/src/win/atomicops-inl.h + ${BASE}/src/win/core.c + ${BASE}/src/win/detect-wakeup.c + ${BASE}/src/win/dl.c + ${BASE}/src/win/error.c + ${BASE}/src/win/fs.c + ${BASE}/src/win/fs-event.c + ${BASE}/src/win/getaddrinfo.c + ${BASE}/src/win/getnameinfo.c + ${BASE}/src/win/handle.c + ${BASE}/src/win/handle-inl.h + ${BASE}/src/win/internal.h + ${BASE}/src/win/loop-watcher.c + ${BASE}/src/win/pipe.c + ${BASE}/src/win/thread.c + ${BASE}/src/win/poll.c + ${BASE}/src/win/process.c + ${BASE}/src/win/process-stdio.c + ${BASE}/src/win/req.c + ${BASE}/src/win/req-inl.h + ${BASE}/src/win/signal.c + ${BASE}/src/win/snprintf.c + ${BASE}/src/win/stream.c + ${BASE}/src/win/stream-inl.h + ${BASE}/src/win/tcp.c + ${BASE}/src/win/tty.c + ${BASE}/src/win/timer.c + ${BASE}/src/win/udp.c + ${BASE}/src/win/util.c + ${BASE}/src/win/winapi.c + ${BASE}/src/win/winapi.h + ${BASE}/src/win/winsock.c + ${BASE}/src/win/winsock.h) +else() + set(DEFINES ${DEFINES} _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE) + set(LIBS ${LIBS} pthread) + set(SOURCES + ${SOURCES} + ${BASE}/include/uv-aix.h + ${BASE}/include/uv-bsd.h + ${BASE}/include/uv-darwin.h + ${BASE}/include/uv-linux.h + ${BASE}/include/uv-sunos.h + ${BASE}/include/uv-unix.h + ${BASE}/src/unix/async.c + ${BASE}/src/unix/atomic-ops.h + ${BASE}/src/unix/core.c + ${BASE}/src/unix/dl.c + ${BASE}/src/unix/fs.c + ${BASE}/src/unix/getaddrinfo.c + ${BASE}/src/unix/getnameinfo.c + ${BASE}/src/unix/internal.h + ${BASE}/src/unix/loop-watcher.c + ${BASE}/src/unix/loop.c + ${BASE}/src/unix/pipe.c + ${BASE}/src/unix/poll.c + ${BASE}/src/unix/process.c + ${BASE}/src/unix/signal.c + ${BASE}/src/unix/spinlock.h + ${BASE}/src/unix/stream.c + ${BASE}/src/unix/tcp.c + ${BASE}/src/unix/thread.c + ${BASE}/src/unix/timer.c + ${BASE}/src/unix/tty.c + ${BASE}/src/unix/udp.c) +endif() + +if(aix) + set(DEFINES ${DEFINES} _ALL_SOURCE) + set(DEFINES ${DEFINES} _LINUX_SOURCE_COMPAT) + set(DEFINES ${DEFINES} _THREAD_SAFE) + set(DEFINES ${DEFINES} _XOPEN_SOURCE=500) + set(LIBS ${LIBS} perfstat) + set(SOURCES ${SOURCES} ${BASE}/src/unix/aix.c) +endif() + +if(android) + set(LIBS ${LIBS} dl) + set(SOURCES ${SOURCES} + ${BASE}/src/unix/android-ifaddrs.c + ${BASE}/src/unix/linux-core.c + ${BASE}/src/unix/linux-inotify.c + ${BASE}/src/unix/linux-syscalls.c + ${BASE}/src/unix/linux-syscalls.h + ${BASE}/src/unix/procfs-exepath.c + ${BASE}/src/unix/pthread-barrier.c + ${BASE}/src/unix/pthread-fixes.c + ${BASE}/src/unix/sysinfo-loadavg.c + ${BASE}/src/unix/sysinfo-memory.c) +endif() + +if(android OR ios OR linux OR mac OR os390) + set(SOURCES ${SOURCES} ${BASE}/src/unix/proctitle.c) +endif() + +if(dragonflybsd OR freebsd) + set(SOURCES ${SOURCES} ${BASE}/src/unix/freebsd.c) +endif() + +if(dragonflybsd OR freebsd OR netbsd OR openbsd) + set(SOURCES ${SOURCES} ${BASE}/src/unix/posix-hrtime.c) + set(LIBS ${LIBS} kvm) +endif() + +if(dragonflybsd OR freebsd OR ios OR mac OR netbsd OR openbsd) + set(SOURCES ${SOURCES} + ${BASE}/src/unix/bsd-ifaddrs.c + ${BASE}/src/unix/kqueue.c) +endif() + +if(ios OR mac) + set(DEFINES ${DEFINES} _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1) + set(SOURCES ${SOURCES} + ${BASE}/src/unix/darwin-proctitle.c + ${BASE}/src/unix/darwin.c + ${BASE}/src/unix/fsevents.c + ${BASE}/src/unix/pthread-barrier.c) +endif() + +if(linux) + set(DEFINES ${DEFINES} _GNU_SOURCE _POSIX_C_SOURCE=200112) + set(LIBS ${LIBS} dl rt) + set(SOURCES ${SOURCES} + ${BASE}/src/unix/linux-core.c + ${BASE}/src/unix/linux-inotify.c + ${BASE}/src/unix/linux-syscalls.c + ${BASE}/src/unix/linux-syscalls.h + ${BASE}/src/unix/procfs-exepath.c + ${BASE}/src/unix/sysinfo-loadavg.c + ${BASE}/src/unix/sysinfo-memory.c) +endif() + +if(netbsd) + set(SOURCES ${SOURCES} ${BASE}/src/unix/netbsd.c) +endif() + +if(openbsd) + set(SOURCES ${SOURCES} ${BASE}/src/unix/openbsd.c) +endif() + +if(os390) + set(DEFINES ${DEFINES} PATH_MAX=255) + set(DEFINES ${DEFINES} _AE_BIMODAL) + set(DEFINES ${DEFINES} _ALL_SOURCE) + set(DEFINES ${DEFINES} _LARGE_TIME_API) + set(DEFINES ${DEFINES} _OPEN_MSGQ_EXT) + set(DEFINES ${DEFINES} _OPEN_SYS_FILE_EXT) + set(DEFINES ${DEFINES} _OPEN_SYS_IF_EXT) + set(DEFINES ${DEFINES} _OPEN_SYS_SOCK_IPV6) + set(DEFINES ${DEFINES} _UNIX03_SOURCE) + set(DEFINES ${DEFINES} _UNIX03_THREADS) + set(DEFINES ${DEFINES} _UNIX03_WITHDRAWN) + set(DEFINES ${DEFINES} _XOPEN_SOURCE_EXTENDED) + set(SOURCES ${SOURCES} + ${BASE}/src/unix/pthread-fixes.c + ${BASE}/src/unix/pthread-barrier.c + ${BASE}/src/unix/os390.c + ${BASE}/src/unix/os390-syscalls.c) +endif() + +if(sunos) + set(DEFINES ${DEFINES} __EXTENSIONS__ _XOPEN_SOURCE=500) + set(LIBS ${LIBS} kstat nsl sendfile socket) + set(SOURCES ${SOURCES} + ${BASE}/src/unix/no-proctitle.c + ${BASE}/src/unix/sunos.c) +endif() + +add_library(uv ${SHARED} ${SOURCES}) +target_compile_definitions(uv PRIVATE ${DEFINES}) +target_include_directories(uv PRIVATE ${BASE}/src) +target_include_directories(uv PUBLIC ${BASE}/include) +target_link_libraries(uv ${LIBS}) + +if(NOT win32) + target_compile_definitions(uv PUBLIC _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE) +endif() + +if(linux) + target_compile_definitions(uv PUBLIC _POSIX_C_SOURCE=200112) +endif() + +if(mac) + target_compile_definitions(uv PUBLIC _DARWIN_USE_64_BIT_INODE=1) +endif() diff --git a/cmake/v8/CMakeLists.txt b/cmake/v8/CMakeLists.txt new file mode 100644 index 00000000000000..5e35b673f26906 --- /dev/null +++ b/cmake/v8/CMakeLists.txt @@ -0,0 +1,1748 @@ +include(../common.cmake) +project(v8) + +add_subdirectory(libbase) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/v8) + +set(DEFINES + -DV8_CONCURRENT_MARKING + -DENABLE_DISASSEMBLER + -DOBJECT_PRINT + -DV8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=0) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(DEFINES ${DEFINES} + -DDEBUG + -DENABLE_SLOW_DCHECKS + -DV8_ENABLE_CHECKS + -DV8_TRACE_MAPS + -DVERIFY_HEAP) +endif() + +if(v8_embedder_string) + set(DEFINES ${DEFINES} -DV8_EMBEDDER_STRING="${v8_embedder_string}") +endif() + +set(INITIALIZERS_SOURCES + ${BASE}/src/builtins/builtins-arguments-gen.cc + ${BASE}/src/builtins/builtins-arguments-gen.h + ${BASE}/src/builtins/builtins-array-gen.cc + ${BASE}/src/builtins/builtins-async-function-gen.cc + ${BASE}/src/builtins/builtins-async-gen.cc + ${BASE}/src/builtins/builtins-async-gen.h + ${BASE}/src/builtins/builtins-async-generator-gen.cc + ${BASE}/src/builtins/builtins-async-iterator-gen.cc + ${BASE}/src/builtins/builtins-boolean-gen.cc + ${BASE}/src/builtins/builtins-call-gen.cc + ${BASE}/src/builtins/builtins-call-gen.h + ${BASE}/src/builtins/builtins-collections-gen.cc + ${BASE}/src/builtins/builtins-console-gen.cc + ${BASE}/src/builtins/builtins-constructor-gen.cc + ${BASE}/src/builtins/builtins-constructor-gen.h + ${BASE}/src/builtins/builtins-constructor.h + ${BASE}/src/builtins/builtins-conversion-gen.cc + ${BASE}/src/builtins/builtins-date-gen.cc + ${BASE}/src/builtins/builtins-debug-gen.cc + ${BASE}/src/builtins/builtins-function-gen.cc + ${BASE}/src/builtins/builtins-generator-gen.cc + ${BASE}/src/builtins/builtins-global-gen.cc + ${BASE}/src/builtins/builtins-handler-gen.cc + ${BASE}/src/builtins/builtins-ic-gen.cc + ${BASE}/src/builtins/builtins-internal-gen.cc + ${BASE}/src/builtins/builtins-interpreter-gen.cc + ${BASE}/src/builtins/builtins-iterator-gen.cc + ${BASE}/src/builtins/builtins-iterator-gen.h + ${BASE}/src/builtins/builtins-math-gen.cc + ${BASE}/src/builtins/builtins-math-gen.h + ${BASE}/src/builtins/builtins-number-gen.cc + ${BASE}/src/builtins/builtins-object-gen.cc + ${BASE}/src/builtins/builtins-promise-gen.cc + ${BASE}/src/builtins/builtins-promise-gen.h + ${BASE}/src/builtins/builtins-proxy-gen.cc + ${BASE}/src/builtins/builtins-proxy-gen.h + ${BASE}/src/builtins/builtins-reflect-gen.cc + ${BASE}/src/builtins/builtins-regexp-gen.cc + ${BASE}/src/builtins/builtins-regexp-gen.h + ${BASE}/src/builtins/builtins-sharedarraybuffer-gen.cc + ${BASE}/src/builtins/builtins-string-gen.cc + ${BASE}/src/builtins/builtins-string-gen.h + ${BASE}/src/builtins/builtins-symbol-gen.cc + ${BASE}/src/builtins/builtins-typedarray-gen.cc + ${BASE}/src/builtins/builtins-utils-gen.h + ${BASE}/src/builtins/builtins-wasm-gen.cc + ${BASE}/src/builtins/setup-builtins-internal.cc + ${BASE}/src/heap/setup-heap-internal.cc + ${BASE}/src/ic/accessor-assembler.cc + ${BASE}/src/ic/accessor-assembler.h + ${BASE}/src/ic/binary-op-assembler.cc + ${BASE}/src/ic/binary-op-assembler.h + ${BASE}/src/ic/keyed-store-generic.cc + ${BASE}/src/ic/keyed-store-generic.h + ${BASE}/src/interpreter/interpreter-assembler.cc + ${BASE}/src/interpreter/interpreter-assembler.h + ${BASE}/src/interpreter/interpreter-generator.cc + ${BASE}/src/interpreter/interpreter-generator.h + ${BASE}/src/interpreter/interpreter-intrinsics-generator.cc + ${BASE}/src/interpreter/interpreter-intrinsics-generator.h + ${BASE}/src/interpreter/setup-interpreter-internal.cc + ${BASE}/src/interpreter/setup-interpreter.h) + +set(SOURCES + ${BASE}/include/v8-debug.h + ${BASE}/include/v8-platform.h + ${BASE}/include/v8-profiler.h + ${BASE}/include/v8-testing.h + ${BASE}/include/v8-util.h + ${BASE}/include/v8-value-serializer-version.h + ${BASE}/include/v8-version-string.h + ${BASE}/include/v8-version.h + ${BASE}/include/v8.h + ${BASE}/include/v8config.h + ${BASE}/src/accessors.cc + ${BASE}/src/accessors.h + ${BASE}/src/address-map.cc + ${BASE}/src/address-map.h + ${BASE}/src/allocation-site-scopes.h + ${BASE}/src/allocation.cc + ${BASE}/src/allocation.h + ${BASE}/src/api-arguments-inl.h + ${BASE}/src/api-arguments.cc + ${BASE}/src/api-arguments.h + ${BASE}/src/api-natives.cc + ${BASE}/src/api-natives.h + ${BASE}/src/api.cc + ${BASE}/src/api.h + ${BASE}/src/arguments.cc + ${BASE}/src/arguments.h + ${BASE}/src/asmjs/asm-js.cc + ${BASE}/src/asmjs/asm-js.h + ${BASE}/src/asmjs/asm-names.h + ${BASE}/src/asmjs/asm-parser.cc + ${BASE}/src/asmjs/asm-parser.h + ${BASE}/src/asmjs/asm-scanner.cc + ${BASE}/src/asmjs/asm-scanner.h + ${BASE}/src/asmjs/asm-types.cc + ${BASE}/src/asmjs/asm-types.h + ${BASE}/src/asmjs/switch-logic.cc + ${BASE}/src/asmjs/switch-logic.h + ${BASE}/src/assembler-inl.h + ${BASE}/src/assembler.cc + ${BASE}/src/assembler.h + ${BASE}/src/assert-scope.cc + ${BASE}/src/assert-scope.h + ${BASE}/src/ast/ast-function-literal-id-reindexer.cc + ${BASE}/src/ast/ast-function-literal-id-reindexer.h + ${BASE}/src/ast/ast-numbering.cc + ${BASE}/src/ast/ast-numbering.h + ${BASE}/src/ast/ast-source-ranges.h + ${BASE}/src/ast/ast-traversal-visitor.h + ${BASE}/src/ast/ast-value-factory.cc + ${BASE}/src/ast/ast-value-factory.h + ${BASE}/src/ast/ast.cc + ${BASE}/src/ast/ast.h + ${BASE}/src/ast/compile-time-value.cc + ${BASE}/src/ast/compile-time-value.h + ${BASE}/src/ast/context-slot-cache.cc + ${BASE}/src/ast/context-slot-cache.h + ${BASE}/src/ast/modules.cc + ${BASE}/src/ast/modules.h + ${BASE}/src/ast/prettyprinter.cc + ${BASE}/src/ast/prettyprinter.h + ${BASE}/src/ast/scopes.cc + ${BASE}/src/ast/scopes.h + ${BASE}/src/ast/variables.cc + ${BASE}/src/ast/variables.h + ${BASE}/src/bailout-reason.cc + ${BASE}/src/bailout-reason.h + ${BASE}/src/basic-block-profiler.cc + ${BASE}/src/basic-block-profiler.h + ${BASE}/src/bignum-dtoa.cc + ${BASE}/src/bignum-dtoa.h + ${BASE}/src/bignum.cc + ${BASE}/src/bignum.h + ${BASE}/src/bit-vector.cc + ${BASE}/src/bit-vector.h + ${BASE}/src/bootstrapper.cc + ${BASE}/src/bootstrapper.h + ${BASE}/src/boxed-float.h + ${BASE}/src/builtins/builtins-api.cc + ${BASE}/src/builtins/builtins-array.cc + ${BASE}/src/builtins/builtins-arraybuffer.cc + ${BASE}/src/builtins/builtins-bigint.cc + ${BASE}/src/builtins/builtins-boolean.cc + ${BASE}/src/builtins/builtins-call.cc + ${BASE}/src/builtins/builtins-callsite.cc + ${BASE}/src/builtins/builtins-collections.cc + ${BASE}/src/builtins/builtins-console.cc + ${BASE}/src/builtins/builtins-constructor.h + ${BASE}/src/builtins/builtins-dataview.cc + ${BASE}/src/builtins/builtins-date.cc + ${BASE}/src/builtins/builtins-definitions.h + ${BASE}/src/builtins/builtins-descriptors.h + ${BASE}/src/builtins/builtins-error.cc + ${BASE}/src/builtins/builtins-function.cc + ${BASE}/src/builtins/builtins-global.cc + ${BASE}/src/builtins/builtins-internal.cc + ${BASE}/src/builtins/builtins-interpreter.cc + ${BASE}/src/builtins/builtins-json.cc + ${BASE}/src/builtins/builtins-math.cc + ${BASE}/src/builtins/builtins-number.cc + ${BASE}/src/builtins/builtins-object.cc + ${BASE}/src/builtins/builtins-promise.cc + ${BASE}/src/builtins/builtins-reflect.cc + ${BASE}/src/builtins/builtins-regexp.cc + ${BASE}/src/builtins/builtins-sharedarraybuffer.cc + ${BASE}/src/builtins/builtins-string.cc + ${BASE}/src/builtins/builtins-symbol.cc + ${BASE}/src/builtins/builtins-typedarray.cc + ${BASE}/src/builtins/builtins-utils.h + ${BASE}/src/builtins/builtins.cc + ${BASE}/src/builtins/builtins.h + ${BASE}/src/cached-powers.cc + ${BASE}/src/cached-powers.h + ${BASE}/src/callable.h + ${BASE}/src/cancelable-task.cc + ${BASE}/src/cancelable-task.h + ${BASE}/src/char-predicates-inl.h + ${BASE}/src/char-predicates.cc + ${BASE}/src/char-predicates.h + ${BASE}/src/checks.h + ${BASE}/src/code-events.h + ${BASE}/src/code-factory.cc + ${BASE}/src/code-factory.h + ${BASE}/src/code-stub-assembler.cc + ${BASE}/src/code-stub-assembler.h + ${BASE}/src/code-stubs-utils.h + ${BASE}/src/code-stubs.cc + ${BASE}/src/code-stubs.h + ${BASE}/src/codegen.cc + ${BASE}/src/codegen.h + ${BASE}/src/collector.h + ${BASE}/src/compilation-cache.cc + ${BASE}/src/compilation-cache.h + ${BASE}/src/compilation-dependencies.cc + ${BASE}/src/compilation-dependencies.h + ${BASE}/src/compilation-info.cc + ${BASE}/src/compilation-info.h + ${BASE}/src/compilation-statistics.cc + ${BASE}/src/compilation-statistics.h + ${BASE}/src/compiler-dispatcher/compiler-dispatcher-job.cc + ${BASE}/src/compiler-dispatcher/compiler-dispatcher-job.h + ${BASE}/src/compiler-dispatcher/compiler-dispatcher-tracer.cc + ${BASE}/src/compiler-dispatcher/compiler-dispatcher-tracer.h + ${BASE}/src/compiler-dispatcher/compiler-dispatcher.cc + ${BASE}/src/compiler-dispatcher/compiler-dispatcher.h + ${BASE}/src/compiler-dispatcher/optimizing-compile-dispatcher.cc + ${BASE}/src/compiler-dispatcher/optimizing-compile-dispatcher.h + ${BASE}/src/compiler-dispatcher/unoptimized-compile-job.cc + ${BASE}/src/compiler-dispatcher/unoptimized-compile-job.h + ${BASE}/src/compiler.cc + ${BASE}/src/compiler.h + ${BASE}/src/compiler/access-builder.cc + ${BASE}/src/compiler/access-builder.h + ${BASE}/src/compiler/access-info.cc + ${BASE}/src/compiler/access-info.h + ${BASE}/src/compiler/all-nodes.cc + ${BASE}/src/compiler/all-nodes.h + ${BASE}/src/compiler/allocation-builder.h + ${BASE}/src/compiler/basic-block-instrumentor.cc + ${BASE}/src/compiler/basic-block-instrumentor.h + ${BASE}/src/compiler/branch-elimination.cc + ${BASE}/src/compiler/branch-elimination.h + ${BASE}/src/compiler/bytecode-analysis.cc + ${BASE}/src/compiler/bytecode-analysis.h + ${BASE}/src/compiler/bytecode-graph-builder.cc + ${BASE}/src/compiler/bytecode-graph-builder.h + ${BASE}/src/compiler/bytecode-liveness-map.cc + ${BASE}/src/compiler/bytecode-liveness-map.h + ${BASE}/src/compiler/c-linkage.cc + ${BASE}/src/compiler/checkpoint-elimination.cc + ${BASE}/src/compiler/checkpoint-elimination.h + ${BASE}/src/compiler/code-assembler.cc + ${BASE}/src/compiler/code-assembler.h + ${BASE}/src/compiler/code-generator-impl.h + ${BASE}/src/compiler/code-generator.cc + ${BASE}/src/compiler/code-generator.h + ${BASE}/src/compiler/common-node-cache.cc + ${BASE}/src/compiler/common-node-cache.h + ${BASE}/src/compiler/common-operator-reducer.cc + ${BASE}/src/compiler/common-operator-reducer.h + ${BASE}/src/compiler/common-operator.cc + ${BASE}/src/compiler/common-operator.h + ${BASE}/src/compiler/compiler-source-position-table.cc + ${BASE}/src/compiler/compiler-source-position-table.h + ${BASE}/src/compiler/control-equivalence.cc + ${BASE}/src/compiler/control-equivalence.h + ${BASE}/src/compiler/control-flow-optimizer.cc + ${BASE}/src/compiler/control-flow-optimizer.h + ${BASE}/src/compiler/dead-code-elimination.cc + ${BASE}/src/compiler/dead-code-elimination.h + ${BASE}/src/compiler/diamond.h + ${BASE}/src/compiler/effect-control-linearizer.cc + ${BASE}/src/compiler/effect-control-linearizer.h + ${BASE}/src/compiler/escape-analysis-reducer.cc + ${BASE}/src/compiler/escape-analysis-reducer.h + ${BASE}/src/compiler/escape-analysis.cc + ${BASE}/src/compiler/escape-analysis.h + ${BASE}/src/compiler/frame-elider.cc + ${BASE}/src/compiler/frame-elider.h + ${BASE}/src/compiler/frame-states.cc + ${BASE}/src/compiler/frame-states.h + ${BASE}/src/compiler/frame.cc + ${BASE}/src/compiler/frame.h + ${BASE}/src/compiler/gap-resolver.cc + ${BASE}/src/compiler/gap-resolver.h + ${BASE}/src/compiler/graph-assembler.cc + ${BASE}/src/compiler/graph-assembler.h + ${BASE}/src/compiler/graph-reducer.cc + ${BASE}/src/compiler/graph-reducer.h + ${BASE}/src/compiler/graph-trimmer.cc + ${BASE}/src/compiler/graph-trimmer.h + ${BASE}/src/compiler/graph-visualizer.cc + ${BASE}/src/compiler/graph-visualizer.h + ${BASE}/src/compiler/graph.cc + ${BASE}/src/compiler/graph.h + ${BASE}/src/compiler/instruction-codes.h + ${BASE}/src/compiler/instruction-scheduler.cc + ${BASE}/src/compiler/instruction-scheduler.h + ${BASE}/src/compiler/instruction-selector-impl.h + ${BASE}/src/compiler/instruction-selector.cc + ${BASE}/src/compiler/instruction-selector.h + ${BASE}/src/compiler/instruction.cc + ${BASE}/src/compiler/instruction.h + ${BASE}/src/compiler/int64-lowering.cc + ${BASE}/src/compiler/int64-lowering.h + ${BASE}/src/compiler/js-builtin-reducer.cc + ${BASE}/src/compiler/js-builtin-reducer.h + ${BASE}/src/compiler/js-call-reducer.cc + ${BASE}/src/compiler/js-call-reducer.h + ${BASE}/src/compiler/js-context-specialization.cc + ${BASE}/src/compiler/js-context-specialization.h + ${BASE}/src/compiler/js-create-lowering.cc + ${BASE}/src/compiler/js-create-lowering.h + ${BASE}/src/compiler/js-generic-lowering.cc + ${BASE}/src/compiler/js-generic-lowering.h + ${BASE}/src/compiler/js-graph.cc + ${BASE}/src/compiler/js-graph.h + ${BASE}/src/compiler/js-inlining-heuristic.cc + ${BASE}/src/compiler/js-inlining-heuristic.h + ${BASE}/src/compiler/js-inlining.cc + ${BASE}/src/compiler/js-inlining.h + ${BASE}/src/compiler/js-intrinsic-lowering.cc + ${BASE}/src/compiler/js-intrinsic-lowering.h + ${BASE}/src/compiler/js-native-context-specialization.cc + ${BASE}/src/compiler/js-native-context-specialization.h + ${BASE}/src/compiler/js-operator.cc + ${BASE}/src/compiler/js-operator.h + ${BASE}/src/compiler/js-type-hint-lowering.cc + ${BASE}/src/compiler/js-type-hint-lowering.h + ${BASE}/src/compiler/js-typed-lowering.cc + ${BASE}/src/compiler/js-typed-lowering.h + ${BASE}/src/compiler/jump-threading.cc + ${BASE}/src/compiler/jump-threading.h + ${BASE}/src/compiler/linkage.cc + ${BASE}/src/compiler/linkage.h + ${BASE}/src/compiler/live-range-separator.cc + ${BASE}/src/compiler/live-range-separator.h + ${BASE}/src/compiler/load-elimination.cc + ${BASE}/src/compiler/load-elimination.h + ${BASE}/src/compiler/loop-analysis.cc + ${BASE}/src/compiler/loop-analysis.h + ${BASE}/src/compiler/loop-peeling.cc + ${BASE}/src/compiler/loop-peeling.h + ${BASE}/src/compiler/loop-variable-optimizer.cc + ${BASE}/src/compiler/loop-variable-optimizer.h + ${BASE}/src/compiler/machine-graph-verifier.cc + ${BASE}/src/compiler/machine-graph-verifier.h + ${BASE}/src/compiler/machine-operator-reducer.cc + ${BASE}/src/compiler/machine-operator-reducer.h + ${BASE}/src/compiler/machine-operator.cc + ${BASE}/src/compiler/machine-operator.h + ${BASE}/src/compiler/memory-optimizer.cc + ${BASE}/src/compiler/memory-optimizer.h + ${BASE}/src/compiler/move-optimizer.cc + ${BASE}/src/compiler/move-optimizer.h + ${BASE}/src/compiler/node-aux-data.h + ${BASE}/src/compiler/node-cache.cc + ${BASE}/src/compiler/node-cache.h + ${BASE}/src/compiler/node-marker.cc + ${BASE}/src/compiler/node-marker.h + ${BASE}/src/compiler/node-matchers.cc + ${BASE}/src/compiler/node-matchers.h + ${BASE}/src/compiler/node-properties.cc + ${BASE}/src/compiler/node-properties.h + ${BASE}/src/compiler/node.cc + ${BASE}/src/compiler/node.h + ${BASE}/src/compiler/opcodes.cc + ${BASE}/src/compiler/opcodes.h + ${BASE}/src/compiler/operation-typer.cc + ${BASE}/src/compiler/operation-typer.h + ${BASE}/src/compiler/operator-properties.cc + ${BASE}/src/compiler/operator-properties.h + ${BASE}/src/compiler/operator.cc + ${BASE}/src/compiler/operator.h + ${BASE}/src/compiler/osr.cc + ${BASE}/src/compiler/osr.h + ${BASE}/src/compiler/persistent-map.h + ${BASE}/src/compiler/pipeline-statistics.cc + ${BASE}/src/compiler/pipeline-statistics.h + ${BASE}/src/compiler/pipeline.cc + ${BASE}/src/compiler/pipeline.h + ${BASE}/src/compiler/property-access-builder.cc + ${BASE}/src/compiler/property-access-builder.h + ${BASE}/src/compiler/raw-machine-assembler.cc + ${BASE}/src/compiler/raw-machine-assembler.h + ${BASE}/src/compiler/redundancy-elimination.cc + ${BASE}/src/compiler/redundancy-elimination.h + ${BASE}/src/compiler/register-allocator-verifier.cc + ${BASE}/src/compiler/register-allocator-verifier.h + ${BASE}/src/compiler/register-allocator.cc + ${BASE}/src/compiler/register-allocator.h + ${BASE}/src/compiler/representation-change.cc + ${BASE}/src/compiler/representation-change.h + ${BASE}/src/compiler/schedule.cc + ${BASE}/src/compiler/schedule.h + ${BASE}/src/compiler/scheduler.cc + ${BASE}/src/compiler/scheduler.h + ${BASE}/src/compiler/select-lowering.cc + ${BASE}/src/compiler/select-lowering.h + ${BASE}/src/compiler/simd-scalar-lowering.cc + ${BASE}/src/compiler/simd-scalar-lowering.h + ${BASE}/src/compiler/simplified-lowering.cc + ${BASE}/src/compiler/simplified-lowering.h + ${BASE}/src/compiler/simplified-operator-reducer.cc + ${BASE}/src/compiler/simplified-operator-reducer.h + ${BASE}/src/compiler/simplified-operator.cc + ${BASE}/src/compiler/simplified-operator.h + ${BASE}/src/compiler/state-values-utils.cc + ${BASE}/src/compiler/state-values-utils.h + ${BASE}/src/compiler/store-store-elimination.cc + ${BASE}/src/compiler/store-store-elimination.h + ${BASE}/src/compiler/type-cache.cc + ${BASE}/src/compiler/type-cache.h + ${BASE}/src/compiler/typed-optimization.cc + ${BASE}/src/compiler/typed-optimization.h + ${BASE}/src/compiler/typer.cc + ${BASE}/src/compiler/typer.h + ${BASE}/src/compiler/types.cc + ${BASE}/src/compiler/types.h + ${BASE}/src/compiler/unwinding-info-writer.h + ${BASE}/src/compiler/value-numbering-reducer.cc + ${BASE}/src/compiler/value-numbering-reducer.h + ${BASE}/src/compiler/verifier.cc + ${BASE}/src/compiler/verifier.h + ${BASE}/src/compiler/wasm-compiler.cc + ${BASE}/src/compiler/wasm-compiler.h + ${BASE}/src/compiler/wasm-linkage.cc + ${BASE}/src/compiler/zone-stats.cc + ${BASE}/src/compiler/zone-stats.h + ${BASE}/src/contexts-inl.h + ${BASE}/src/contexts.cc + ${BASE}/src/contexts.h + ${BASE}/src/conversions-inl.h + ${BASE}/src/conversions.cc + ${BASE}/src/conversions.h + ${BASE}/src/counters-inl.h + ${BASE}/src/counters.cc + ${BASE}/src/counters.h + ${BASE}/src/date.cc + ${BASE}/src/date.h + ${BASE}/src/dateparser-inl.h + ${BASE}/src/dateparser.cc + ${BASE}/src/dateparser.h + ${BASE}/src/debug/debug-coverage.cc + ${BASE}/src/debug/debug-coverage.h + ${BASE}/src/debug/debug-evaluate.cc + ${BASE}/src/debug/debug-evaluate.h + ${BASE}/src/debug/debug-frames.cc + ${BASE}/src/debug/debug-frames.h + ${BASE}/src/debug/debug-interface.h + ${BASE}/src/debug/debug-scope-iterator.cc + ${BASE}/src/debug/debug-scope-iterator.h + ${BASE}/src/debug/debug-scopes.cc + ${BASE}/src/debug/debug-scopes.h + ${BASE}/src/debug/debug-stack-trace-iterator.cc + ${BASE}/src/debug/debug-stack-trace-iterator.h + ${BASE}/src/debug/debug-type-profile.cc + ${BASE}/src/debug/debug-type-profile.h + ${BASE}/src/debug/debug.cc + ${BASE}/src/debug/debug.h + ${BASE}/src/debug/interface-types.h + ${BASE}/src/debug/liveedit.cc + ${BASE}/src/debug/liveedit.h + ${BASE}/src/deoptimize-reason.cc + ${BASE}/src/deoptimize-reason.h + ${BASE}/src/deoptimizer.cc + ${BASE}/src/deoptimizer.h + ${BASE}/src/detachable-vector.h + ${BASE}/src/disasm.h + ${BASE}/src/disassembler.cc + ${BASE}/src/disassembler.h + ${BASE}/src/diy-fp.cc + ${BASE}/src/diy-fp.h + ${BASE}/src/double.h + ${BASE}/src/dtoa.cc + ${BASE}/src/dtoa.h + ${BASE}/src/eh-frame.cc + ${BASE}/src/eh-frame.h + ${BASE}/src/elements-kind.cc + ${BASE}/src/elements-kind.h + ${BASE}/src/elements.cc + ${BASE}/src/elements.h + ${BASE}/src/execution.cc + ${BASE}/src/execution.h + ${BASE}/src/extensions/externalize-string-extension.cc + ${BASE}/src/extensions/externalize-string-extension.h + ${BASE}/src/extensions/free-buffer-extension.cc + ${BASE}/src/extensions/free-buffer-extension.h + ${BASE}/src/extensions/gc-extension.cc + ${BASE}/src/extensions/gc-extension.h + ${BASE}/src/extensions/ignition-statistics-extension.cc + ${BASE}/src/extensions/ignition-statistics-extension.h + ${BASE}/src/extensions/statistics-extension.cc + ${BASE}/src/extensions/statistics-extension.h + ${BASE}/src/extensions/trigger-failure-extension.cc + ${BASE}/src/extensions/trigger-failure-extension.h + ${BASE}/src/external-reference-table.cc + ${BASE}/src/external-reference-table.h + ${BASE}/src/factory-inl.h + ${BASE}/src/factory.cc + ${BASE}/src/factory.h + ${BASE}/src/fast-dtoa.cc + ${BASE}/src/fast-dtoa.h + ${BASE}/src/feedback-vector-inl.h + ${BASE}/src/feedback-vector.cc + ${BASE}/src/feedback-vector.h + ${BASE}/src/field-index-inl.h + ${BASE}/src/field-index.h + ${BASE}/src/field-type.cc + ${BASE}/src/field-type.h + ${BASE}/src/fixed-dtoa.cc + ${BASE}/src/fixed-dtoa.h + ${BASE}/src/flag-definitions.h + ${BASE}/src/flags.cc + ${BASE}/src/flags.h + ${BASE}/src/frame-constants.h + ${BASE}/src/frames-inl.h + ${BASE}/src/frames.cc + ${BASE}/src/frames.h + ${BASE}/src/futex-emulation.cc + ${BASE}/src/futex-emulation.h + ${BASE}/src/gdb-jit.cc + ${BASE}/src/gdb-jit.h + ${BASE}/src/global-handles.cc + ${BASE}/src/global-handles.h + ${BASE}/src/globals.h + ${BASE}/src/handles-inl.h + ${BASE}/src/handles.cc + ${BASE}/src/handles.h + ${BASE}/src/heap-symbols.h + ${BASE}/src/heap/array-buffer-collector.cc + ${BASE}/src/heap/array-buffer-collector.h + ${BASE}/src/heap/array-buffer-tracker-inl.h + ${BASE}/src/heap/array-buffer-tracker.cc + ${BASE}/src/heap/array-buffer-tracker.h + ${BASE}/src/heap/barrier.h + ${BASE}/src/heap/code-stats.cc + ${BASE}/src/heap/code-stats.h + ${BASE}/src/heap/concurrent-marking.cc + ${BASE}/src/heap/concurrent-marking.h + ${BASE}/src/heap/embedder-tracing.cc + ${BASE}/src/heap/embedder-tracing.h + ${BASE}/src/heap/gc-idle-time-handler.cc + ${BASE}/src/heap/gc-idle-time-handler.h + ${BASE}/src/heap/gc-tracer.cc + ${BASE}/src/heap/gc-tracer.h + ${BASE}/src/heap/heap-inl.h + ${BASE}/src/heap/heap.cc + ${BASE}/src/heap/heap.h + ${BASE}/src/heap/incremental-marking-inl.h + ${BASE}/src/heap/incremental-marking-job.cc + ${BASE}/src/heap/incremental-marking-job.h + ${BASE}/src/heap/incremental-marking.cc + ${BASE}/src/heap/incremental-marking.h + ${BASE}/src/heap/invalidated-slots-inl.h + ${BASE}/src/heap/invalidated-slots.cc + ${BASE}/src/heap/invalidated-slots.h + ${BASE}/src/heap/item-parallel-job.h + ${BASE}/src/heap/mark-compact-inl.h + ${BASE}/src/heap/mark-compact.cc + ${BASE}/src/heap/mark-compact.h + ${BASE}/src/heap/marking.cc + ${BASE}/src/heap/marking.h + ${BASE}/src/heap/memory-reducer.cc + ${BASE}/src/heap/memory-reducer.h + ${BASE}/src/heap/object-stats.cc + ${BASE}/src/heap/object-stats.h + ${BASE}/src/heap/objects-visiting-inl.h + ${BASE}/src/heap/objects-visiting.cc + ${BASE}/src/heap/objects-visiting.h + ${BASE}/src/heap/remembered-set.h + ${BASE}/src/heap/scavenge-job.cc + ${BASE}/src/heap/scavenge-job.h + ${BASE}/src/heap/scavenger-inl.h + ${BASE}/src/heap/scavenger.cc + ${BASE}/src/heap/scavenger.h + ${BASE}/src/heap/slot-set.h + ${BASE}/src/heap/spaces-inl.h + ${BASE}/src/heap/spaces.cc + ${BASE}/src/heap/spaces.h + ${BASE}/src/heap/store-buffer.cc + ${BASE}/src/heap/store-buffer.h + ${BASE}/src/heap/sweeper.cc + ${BASE}/src/heap/sweeper.h + ${BASE}/src/heap/worklist.h + ${BASE}/src/ic/call-optimization.cc + ${BASE}/src/ic/call-optimization.h + ${BASE}/src/ic/handler-configuration-inl.h + ${BASE}/src/ic/handler-configuration.cc + ${BASE}/src/ic/handler-configuration.h + ${BASE}/src/ic/ic-inl.h + ${BASE}/src/ic/ic-stats.cc + ${BASE}/src/ic/ic-stats.h + ${BASE}/src/ic/ic.cc + ${BASE}/src/ic/ic.h + ${BASE}/src/ic/stub-cache.cc + ${BASE}/src/ic/stub-cache.h + ${BASE}/src/icu_util.cc + ${BASE}/src/icu_util.h + ${BASE}/src/identity-map.cc + ${BASE}/src/identity-map.h + ${BASE}/src/interface-descriptors.cc + ${BASE}/src/interface-descriptors.h + ${BASE}/src/interpreter/block-coverage-builder.h + ${BASE}/src/interpreter/bytecode-array-accessor.cc + ${BASE}/src/interpreter/bytecode-array-accessor.h + ${BASE}/src/interpreter/bytecode-array-builder.cc + ${BASE}/src/interpreter/bytecode-array-builder.h + ${BASE}/src/interpreter/bytecode-array-iterator.cc + ${BASE}/src/interpreter/bytecode-array-iterator.h + ${BASE}/src/interpreter/bytecode-array-random-iterator.cc + ${BASE}/src/interpreter/bytecode-array-random-iterator.h + ${BASE}/src/interpreter/bytecode-array-writer.cc + ${BASE}/src/interpreter/bytecode-array-writer.h + ${BASE}/src/interpreter/bytecode-decoder.cc + ${BASE}/src/interpreter/bytecode-decoder.h + ${BASE}/src/interpreter/bytecode-flags.cc + ${BASE}/src/interpreter/bytecode-flags.h + ${BASE}/src/interpreter/bytecode-generator.cc + ${BASE}/src/interpreter/bytecode-generator.h + ${BASE}/src/interpreter/bytecode-jump-table.h + ${BASE}/src/interpreter/bytecode-label.cc + ${BASE}/src/interpreter/bytecode-label.h + ${BASE}/src/interpreter/bytecode-node.cc + ${BASE}/src/interpreter/bytecode-node.h + ${BASE}/src/interpreter/bytecode-operands.cc + ${BASE}/src/interpreter/bytecode-operands.h + ${BASE}/src/interpreter/bytecode-register-allocator.h + ${BASE}/src/interpreter/bytecode-register-optimizer.cc + ${BASE}/src/interpreter/bytecode-register-optimizer.h + ${BASE}/src/interpreter/bytecode-register.cc + ${BASE}/src/interpreter/bytecode-register.h + ${BASE}/src/interpreter/bytecode-source-info.cc + ${BASE}/src/interpreter/bytecode-source-info.h + ${BASE}/src/interpreter/bytecode-traits.h + ${BASE}/src/interpreter/bytecodes.cc + ${BASE}/src/interpreter/bytecodes.h + ${BASE}/src/interpreter/constant-array-builder.cc + ${BASE}/src/interpreter/constant-array-builder.h + ${BASE}/src/interpreter/control-flow-builders.cc + ${BASE}/src/interpreter/control-flow-builders.h + ${BASE}/src/interpreter/handler-table-builder.cc + ${BASE}/src/interpreter/handler-table-builder.h + ${BASE}/src/interpreter/interpreter-generator.h + ${BASE}/src/interpreter/interpreter-intrinsics.cc + ${BASE}/src/interpreter/interpreter-intrinsics.h + ${BASE}/src/interpreter/interpreter.cc + ${BASE}/src/interpreter/interpreter.h + ${BASE}/src/isolate-inl.h + ${BASE}/src/isolate.cc + ${BASE}/src/isolate.h + ${BASE}/src/json-parser.cc + ${BASE}/src/json-parser.h + ${BASE}/src/json-stringifier.cc + ${BASE}/src/json-stringifier.h + ${BASE}/src/keys.cc + ${BASE}/src/keys.h + ${BASE}/src/label.h + ${BASE}/src/layout-descriptor-inl.h + ${BASE}/src/layout-descriptor.cc + ${BASE}/src/layout-descriptor.h + ${BASE}/src/locked-queue-inl.h + ${BASE}/src/locked-queue.h + ${BASE}/src/log-inl.h + ${BASE}/src/log-utils.cc + ${BASE}/src/log-utils.h + ${BASE}/src/log.cc + ${BASE}/src/log.h + ${BASE}/src/lookup-cache-inl.h + ${BASE}/src/lookup-cache.cc + ${BASE}/src/lookup-cache.h + ${BASE}/src/lookup.cc + ${BASE}/src/lookup.h + ${BASE}/src/machine-type.cc + ${BASE}/src/machine-type.h + ${BASE}/src/macro-assembler-inl.h + ${BASE}/src/macro-assembler.h + ${BASE}/src/managed.h + ${BASE}/src/map-updater.cc + ${BASE}/src/map-updater.h + ${BASE}/src/messages.cc + ${BASE}/src/messages.h + ${BASE}/src/msan.h + ${BASE}/src/objects-body-descriptors-inl.h + ${BASE}/src/objects-body-descriptors.h + ${BASE}/src/objects-debug.cc + ${BASE}/src/objects-inl.h + ${BASE}/src/objects-printer.cc + ${BASE}/src/objects.cc + ${BASE}/src/objects.h + ${BASE}/src/objects/arguments-inl.h + ${BASE}/src/objects/arguments.h + ${BASE}/src/objects/bigint.cc + ${BASE}/src/objects/bigint.h + ${BASE}/src/objects/code-inl.h + ${BASE}/src/objects/code.h + ${BASE}/src/objects/compilation-cache-inl.h + ${BASE}/src/objects/compilation-cache.h + ${BASE}/src/objects/debug-objects-inl.h + ${BASE}/src/objects/debug-objects.cc + ${BASE}/src/objects/debug-objects.h + ${BASE}/src/objects/descriptor-array.h + ${BASE}/src/objects/dictionary.h + ${BASE}/src/objects/frame-array-inl.h + ${BASE}/src/objects/frame-array.h + ${BASE}/src/objects/hash-table-inl.h + ${BASE}/src/objects/hash-table.h + ${BASE}/src/objects/js-array.h + ${BASE}/src/objects/js-array-inl.h + ${BASE}/src/objects/js-regexp.h + ${BASE}/src/objects/js-regexp-inl.h + ${BASE}/src/objects/literal-objects.cc + ${BASE}/src/objects/literal-objects.h + ${BASE}/src/objects/map-inl.h + ${BASE}/src/objects/map.h + ${BASE}/src/objects/module-inl.h + ${BASE}/src/objects/module.cc + ${BASE}/src/objects/module.h + ${BASE}/src/objects/name-inl.h + ${BASE}/src/objects/name.h + ${BASE}/src/objects/object-macros-undef.h + ${BASE}/src/objects/object-macros.h + ${BASE}/src/objects/property-descriptor-object-inl.h + ${BASE}/src/objects/property-descriptor-object.h + ${BASE}/src/objects/regexp-match-info.h + ${BASE}/src/objects/scope-info.cc + ${BASE}/src/objects/scope-info.h + ${BASE}/src/objects/script-inl.h + ${BASE}/src/objects/script.h + ${BASE}/src/objects/shared-function-info-inl.h + ${BASE}/src/objects/shared-function-info.h + ${BASE}/src/objects/string-inl.h + ${BASE}/src/objects/string-table.h + ${BASE}/src/objects/string.h + ${BASE}/src/objects/template-objects.cc + ${BASE}/src/objects/template-objects.h + ${BASE}/src/ostreams.cc + ${BASE}/src/ostreams.h + ${BASE}/src/parsing/background-parsing-task.cc + ${BASE}/src/parsing/background-parsing-task.h + ${BASE}/src/parsing/duplicate-finder.h + ${BASE}/src/parsing/expression-classifier.h + ${BASE}/src/parsing/expression-scope-reparenter.cc + ${BASE}/src/parsing/expression-scope-reparenter.h + ${BASE}/src/parsing/func-name-inferrer.cc + ${BASE}/src/parsing/func-name-inferrer.h + ${BASE}/src/parsing/parse-info.cc + ${BASE}/src/parsing/parse-info.h + ${BASE}/src/parsing/parser-base.h + ${BASE}/src/parsing/parser.cc + ${BASE}/src/parsing/parser.h + ${BASE}/src/parsing/parsing.cc + ${BASE}/src/parsing/parsing.h + ${BASE}/src/parsing/pattern-rewriter.cc + ${BASE}/src/parsing/preparse-data-format.h + ${BASE}/src/parsing/preparse-data.cc + ${BASE}/src/parsing/preparse-data.h + ${BASE}/src/parsing/preparsed-scope-data.cc + ${BASE}/src/parsing/preparsed-scope-data.h + ${BASE}/src/parsing/preparser.cc + ${BASE}/src/parsing/preparser.h + ${BASE}/src/parsing/rewriter.cc + ${BASE}/src/parsing/rewriter.h + ${BASE}/src/parsing/scanner-character-streams.cc + ${BASE}/src/parsing/scanner-character-streams.h + ${BASE}/src/parsing/scanner.cc + ${BASE}/src/parsing/scanner.h + ${BASE}/src/parsing/token.cc + ${BASE}/src/parsing/token.h + ${BASE}/src/pending-compilation-error-handler.cc + ${BASE}/src/pending-compilation-error-handler.h + ${BASE}/src/perf-jit.cc + ${BASE}/src/perf-jit.h + ${BASE}/src/profiler/allocation-tracker.cc + ${BASE}/src/profiler/allocation-tracker.h + ${BASE}/src/profiler/circular-queue-inl.h + ${BASE}/src/profiler/circular-queue.h + ${BASE}/src/profiler/cpu-profiler-inl.h + ${BASE}/src/profiler/cpu-profiler.cc + ${BASE}/src/profiler/cpu-profiler.h + ${BASE}/src/profiler/heap-profiler.cc + ${BASE}/src/profiler/heap-profiler.h + ${BASE}/src/profiler/heap-snapshot-generator-inl.h + ${BASE}/src/profiler/heap-snapshot-generator.cc + ${BASE}/src/profiler/heap-snapshot-generator.h + ${BASE}/src/profiler/profile-generator-inl.h + ${BASE}/src/profiler/profile-generator.cc + ${BASE}/src/profiler/profile-generator.h + ${BASE}/src/profiler/profiler-listener.cc + ${BASE}/src/profiler/profiler-listener.h + ${BASE}/src/profiler/sampling-heap-profiler.cc + ${BASE}/src/profiler/sampling-heap-profiler.h + ${BASE}/src/profiler/strings-storage.cc + ${BASE}/src/profiler/strings-storage.h + ${BASE}/src/profiler/tick-sample.cc + ${BASE}/src/profiler/tick-sample.h + ${BASE}/src/profiler/tracing-cpu-profiler.cc + ${BASE}/src/profiler/tracing-cpu-profiler.h + ${BASE}/src/profiler/unbound-queue-inl.h + ${BASE}/src/profiler/unbound-queue.h + ${BASE}/src/property-descriptor.cc + ${BASE}/src/property-descriptor.h + ${BASE}/src/property-details.h + ${BASE}/src/property.cc + ${BASE}/src/property.h + ${BASE}/src/prototype.h + ${BASE}/src/regexp/bytecodes-irregexp.h + ${BASE}/src/regexp/interpreter-irregexp.cc + ${BASE}/src/regexp/interpreter-irregexp.h + ${BASE}/src/regexp/jsregexp-inl.h + ${BASE}/src/regexp/jsregexp.cc + ${BASE}/src/regexp/jsregexp.h + ${BASE}/src/regexp/regexp-ast.cc + ${BASE}/src/regexp/regexp-ast.h + ${BASE}/src/regexp/regexp-macro-assembler-irregexp-inl.h + ${BASE}/src/regexp/regexp-macro-assembler-irregexp.cc + ${BASE}/src/regexp/regexp-macro-assembler-irregexp.h + ${BASE}/src/regexp/regexp-macro-assembler-tracer.cc + ${BASE}/src/regexp/regexp-macro-assembler-tracer.h + ${BASE}/src/regexp/regexp-macro-assembler.cc + ${BASE}/src/regexp/regexp-macro-assembler.h + ${BASE}/src/regexp/regexp-parser.cc + ${BASE}/src/regexp/regexp-parser.h + ${BASE}/src/regexp/regexp-stack.cc + ${BASE}/src/regexp/regexp-stack.h + ${BASE}/src/regexp/regexp-utils.cc + ${BASE}/src/regexp/regexp-utils.h + ${BASE}/src/register-configuration.cc + ${BASE}/src/register-configuration.h + ${BASE}/src/reglist.h + ${BASE}/src/runtime-profiler.cc + ${BASE}/src/runtime-profiler.h + ${BASE}/src/runtime/runtime-array.cc + ${BASE}/src/runtime/runtime-atomics.cc + ${BASE}/src/runtime/runtime-bigint.cc + ${BASE}/src/runtime/runtime-classes.cc + ${BASE}/src/runtime/runtime-collections.cc + ${BASE}/src/runtime/runtime-compiler.cc + ${BASE}/src/runtime/runtime-date.cc + ${BASE}/src/runtime/runtime-debug.cc + ${BASE}/src/runtime/runtime-error.cc + ${BASE}/src/runtime/runtime-forin.cc + ${BASE}/src/runtime/runtime-function.cc + ${BASE}/src/runtime/runtime-futex.cc + ${BASE}/src/runtime/runtime-generator.cc + ${BASE}/src/runtime/runtime-internal.cc + ${BASE}/src/runtime/runtime-interpreter.cc + ${BASE}/src/runtime/runtime-literals.cc + ${BASE}/src/runtime/runtime-liveedit.cc + ${BASE}/src/runtime/runtime-maths.cc + ${BASE}/src/runtime/runtime-module.cc + ${BASE}/src/runtime/runtime-numbers.cc + ${BASE}/src/runtime/runtime-object.cc + ${BASE}/src/runtime/runtime-operators.cc + ${BASE}/src/runtime/runtime-promise.cc + ${BASE}/src/runtime/runtime-proxy.cc + ${BASE}/src/runtime/runtime-regexp.cc + ${BASE}/src/runtime/runtime-scopes.cc + ${BASE}/src/runtime/runtime-strings.cc + ${BASE}/src/runtime/runtime-symbol.cc + ${BASE}/src/runtime/runtime-test.cc + ${BASE}/src/runtime/runtime-typedarray.cc + ${BASE}/src/runtime/runtime-utils.h + ${BASE}/src/runtime/runtime-wasm.cc + ${BASE}/src/runtime/runtime.cc + ${BASE}/src/runtime/runtime.h + ${BASE}/src/safepoint-table.cc + ${BASE}/src/safepoint-table.h + ${BASE}/src/setup-isolate.h + ${BASE}/src/signature.h + ${BASE}/src/simulator.h + ${BASE}/src/snapshot/builtin-deserializer-allocator.cc + ${BASE}/src/snapshot/builtin-deserializer-allocator.h + ${BASE}/src/snapshot/builtin-deserializer.cc + ${BASE}/src/snapshot/builtin-deserializer.h + ${BASE}/src/snapshot/builtin-serializer-allocator.cc + ${BASE}/src/snapshot/builtin-serializer-allocator.h + ${BASE}/src/snapshot/builtin-serializer.cc + ${BASE}/src/snapshot/builtin-serializer.h + ${BASE}/src/snapshot/builtin-snapshot-utils.cc + ${BASE}/src/snapshot/builtin-snapshot-utils.h + ${BASE}/src/snapshot/code-serializer.cc + ${BASE}/src/snapshot/code-serializer.h + ${BASE}/src/snapshot/default-deserializer-allocator.cc + ${BASE}/src/snapshot/default-deserializer-allocator.h + ${BASE}/src/snapshot/default-serializer-allocator.cc + ${BASE}/src/snapshot/default-serializer-allocator.h + ${BASE}/src/snapshot/deserializer.cc + ${BASE}/src/snapshot/deserializer.h + ${BASE}/src/snapshot/natives-common.cc + ${BASE}/src/snapshot/natives.h + ${BASE}/src/snapshot/object-deserializer.cc + ${BASE}/src/snapshot/object-deserializer.h + ${BASE}/src/snapshot/partial-deserializer.cc + ${BASE}/src/snapshot/partial-deserializer.h + ${BASE}/src/snapshot/partial-serializer.cc + ${BASE}/src/snapshot/partial-serializer.h + ${BASE}/src/snapshot/serializer-common.cc + ${BASE}/src/snapshot/serializer-common.h + ${BASE}/src/snapshot/serializer.cc + ${BASE}/src/snapshot/serializer.h + ${BASE}/src/snapshot/snapshot-common.cc + ${BASE}/src/snapshot/snapshot-source-sink.cc + ${BASE}/src/snapshot/snapshot-source-sink.h + ${BASE}/src/snapshot/snapshot.h + ${BASE}/src/snapshot/startup-deserializer.cc + ${BASE}/src/snapshot/startup-deserializer.h + ${BASE}/src/snapshot/startup-serializer.cc + ${BASE}/src/snapshot/startup-serializer.h + ${BASE}/src/source-position-table.cc + ${BASE}/src/source-position-table.h + ${BASE}/src/source-position.cc + ${BASE}/src/source-position.h + ${BASE}/src/splay-tree-inl.h + ${BASE}/src/splay-tree.h + ${BASE}/src/startup-data-util.cc + ${BASE}/src/startup-data-util.h + ${BASE}/src/string-builder.cc + ${BASE}/src/string-builder.h + ${BASE}/src/string-case.cc + ${BASE}/src/string-case.h + ${BASE}/src/string-hasher-inl.h + ${BASE}/src/string-hasher.h + ${BASE}/src/string-search.h + ${BASE}/src/string-stream.cc + ${BASE}/src/string-stream.h + ${BASE}/src/strtod.cc + ${BASE}/src/strtod.h + ${BASE}/src/tracing/trace-event.cc + ${BASE}/src/tracing/trace-event.h + ${BASE}/src/tracing/traced-value.cc + ${BASE}/src/tracing/traced-value.h + ${BASE}/src/tracing/tracing-category-observer.cc + ${BASE}/src/tracing/tracing-category-observer.h + ${BASE}/src/transitions-inl.h + ${BASE}/src/transitions.cc + ${BASE}/src/transitions.h + ${BASE}/src/trap-handler/handler-outside.cc + ${BASE}/src/trap-handler/handler-shared.cc + ${BASE}/src/trap-handler/trap-handler-internal.h + ${BASE}/src/trap-handler/trap-handler.h + ${BASE}/src/type-hints.cc + ${BASE}/src/type-hints.h + ${BASE}/src/unicode-cache-inl.h + ${BASE}/src/unicode-cache.h + ${BASE}/src/unicode-decoder.cc + ${BASE}/src/unicode-decoder.h + ${BASE}/src/unicode-inl.h + ${BASE}/src/unicode.cc + ${BASE}/src/unicode.h + ${BASE}/src/uri.cc + ${BASE}/src/uri.h + ${BASE}/src/utils-inl.h + ${BASE}/src/utils.cc + ${BASE}/src/utils.h + ${BASE}/src/v8.cc + ${BASE}/src/v8.h + ${BASE}/src/v8memory.h + ${BASE}/src/v8threads.cc + ${BASE}/src/v8threads.h + ${BASE}/src/value-serializer.cc + ${BASE}/src/value-serializer.h + ${BASE}/src/vector.h + ${BASE}/src/version.cc + ${BASE}/src/version.h + ${BASE}/src/visitors.cc + ${BASE}/src/visitors.h + ${BASE}/src/vm-state-inl.h + ${BASE}/src/vm-state.h + ${BASE}/src/wasm/baseline/liftoff-assembler.cc + ${BASE}/src/wasm/baseline/liftoff-assembler.h + ${BASE}/src/wasm/baseline/liftoff-compiler.cc + ${BASE}/src/wasm/compilation-manager.cc + ${BASE}/src/wasm/compilation-manager.h + ${BASE}/src/wasm/decoder.h + ${BASE}/src/wasm/function-body-decoder-impl.h + ${BASE}/src/wasm/function-body-decoder.cc + ${BASE}/src/wasm/function-body-decoder.h + ${BASE}/src/wasm/leb-helper.h + ${BASE}/src/wasm/local-decl-encoder.cc + ${BASE}/src/wasm/local-decl-encoder.h + ${BASE}/src/wasm/memory-tracing.cc + ${BASE}/src/wasm/memory-tracing.h + ${BASE}/src/wasm/module-compiler.cc + ${BASE}/src/wasm/module-compiler.h + ${BASE}/src/wasm/module-decoder.cc + ${BASE}/src/wasm/module-decoder.h + ${BASE}/src/wasm/signature-map.cc + ${BASE}/src/wasm/signature-map.h + ${BASE}/src/wasm/streaming-decoder.cc + ${BASE}/src/wasm/streaming-decoder.h + ${BASE}/src/wasm/wasm-api.cc + ${BASE}/src/wasm/wasm-api.h + ${BASE}/src/wasm/wasm-code-specialization.cc + ${BASE}/src/wasm/wasm-code-specialization.h + ${BASE}/src/wasm/wasm-code-wrapper.cc + ${BASE}/src/wasm/wasm-code-wrapper.h + ${BASE}/src/wasm/wasm-debug.cc + ${BASE}/src/wasm/wasm-external-refs.cc + ${BASE}/src/wasm/wasm-external-refs.h + ${BASE}/src/wasm/wasm-interpreter.cc + ${BASE}/src/wasm/wasm-interpreter.h + ${BASE}/src/wasm/wasm-heap.cc + ${BASE}/src/wasm/wasm-heap.h + ${BASE}/src/wasm/wasm-js.cc + ${BASE}/src/wasm/wasm-js.h + ${BASE}/src/wasm/wasm-limits.h + ${BASE}/src/wasm/wasm-memory.cc + ${BASE}/src/wasm/wasm-memory.h + ${BASE}/src/wasm/wasm-module-builder.cc + ${BASE}/src/wasm/wasm-module-builder.h + ${BASE}/src/wasm/wasm-module.cc + ${BASE}/src/wasm/wasm-module.h + ${BASE}/src/wasm/wasm-objects-inl.h + ${BASE}/src/wasm/wasm-objects.cc + ${BASE}/src/wasm/wasm-objects.h + ${BASE}/src/wasm/wasm-opcodes.cc + ${BASE}/src/wasm/wasm-opcodes.h + ${BASE}/src/wasm/wasm-result.cc + ${BASE}/src/wasm/wasm-result.h + ${BASE}/src/wasm/wasm-serialization.cc + ${BASE}/src/wasm/wasm-serialization.h + ${BASE}/src/wasm/wasm-text.cc + ${BASE}/src/wasm/wasm-text.h + ${BASE}/src/wasm/wasm-value.h + ${BASE}/src/zone/accounting-allocator.cc + ${BASE}/src/zone/accounting-allocator.h + ${BASE}/src/zone/zone-allocator.h + ${BASE}/src/zone/zone-chunk-list.h + ${BASE}/src/zone/zone-containers.h + ${BASE}/src/zone/zone-handle-set.h + ${BASE}/src/zone/zone-list-inl.h + ${BASE}/src/zone/zone-segment.cc + ${BASE}/src/zone/zone-segment.cc + ${BASE}/src/zone/zone-segment.h + ${BASE}/src/zone/zone-segment.h + ${BASE}/src/zone/zone.cc + ${BASE}/src/zone/zone.h + ${CMAKE_CURRENT_BINARY_DIR}/experimental-extra-libraries.cc + ${CMAKE_CURRENT_BINARY_DIR}/extra-libraries.cc + ${CMAKE_CURRENT_BINARY_DIR}/libraries.cc) + +# Order matters. +set(LIBRARY_FILES + ${BASE}/src/js/macros.py + ${BASE}/src/messages.h + ${BASE}/src/js/prologue.js + ${BASE}/src/js/v8natives.js + ${BASE}/src/js/array.js + ${BASE}/src/js/typedarray.js + ${BASE}/src/js/messages.js + ${BASE}/src/js/spread.js + ${BASE}/src/js/proxy.js + ${BASE}/src/debug/mirrors.js + ${BASE}/src/debug/debug.js + ${BASE}/src/debug/liveedit.js) + +set(D8_SOURCES + ${BASE}/src/d8-console.cc + ${BASE}/src/d8-console.h + ${BASE}/src/d8.cc + ${BASE}/src/d8.h + ${CMAKE_CURRENT_BINARY_DIR}/d8-js.cc) + +set(D8_LIBRARY_FILES + ${BASE}/src/d8.js + ${BASE}/src/js/macros.py) + +if(win32) + set(D8_SOURCES ${D8_SOURCES} ${BASE}/src/d8-windows.cc) +else() + set(D8_SOURCES ${D8_SOURCES} ${BASE}/src/d8-posix.cc) +endif() + +if(arm) + set(DEFINES ${DEFINES} -DCAN_USE_ARMV7_INSTRUCTIONS -DV8_TARGET_ARCH_ARM) + + set(SOURCES ${SOURCES} + ${BASE}/src/arm/assembler-arm-inl.h + ${BASE}/src/arm/assembler-arm.cc + ${BASE}/src/arm/assembler-arm.h + ${BASE}/src/arm/code-stubs-arm.cc + ${BASE}/src/arm/code-stubs-arm.h + ${BASE}/src/arm/codegen-arm.cc + ${BASE}/src/arm/constants-arm.cc + ${BASE}/src/arm/constants-arm.h + ${BASE}/src/arm/cpu-arm.cc + ${BASE}/src/arm/deoptimizer-arm.cc + ${BASE}/src/arm/disasm-arm.cc + ${BASE}/src/arm/eh-frame-arm.cc + ${BASE}/src/arm/frame-constants-arm.cc + ${BASE}/src/arm/frame-constants-arm.h + ${BASE}/src/arm/interface-descriptors-arm.cc + ${BASE}/src/arm/interface-descriptors-arm.h + ${BASE}/src/arm/macro-assembler-arm.cc + ${BASE}/src/arm/macro-assembler-arm.h + ${BASE}/src/arm/simulator-arm.cc + ${BASE}/src/arm/simulator-arm.h + ${BASE}/src/compiler/arm/code-generator-arm.cc + ${BASE}/src/compiler/arm/instruction-codes-arm.h + ${BASE}/src/compiler/arm/instruction-scheduler-arm.cc + ${BASE}/src/compiler/arm/instruction-selector-arm.cc + ${BASE}/src/compiler/arm/unwinding-info-writer-arm.cc + ${BASE}/src/compiler/arm/unwinding-info-writer-arm.h + ${BASE}/src/debug/arm/debug-arm.cc + ${BASE}/src/regexp/arm/regexp-macro-assembler-arm.cc + ${BASE}/src/regexp/arm/regexp-macro-assembler-arm.h + ${BASE}/src/wasm/baseline/arm/liftoff-assembler-arm-defs.h + ${BASE}/src/wasm/baseline/arm/liftoff-assembler-arm.h) + + + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/arm/builtins-arm.cc) +elseif(arm64) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_ARM64) + + set(SOURCES ${SOURCES} + ${BASE}/src/arm64/assembler-arm64-inl.h + ${BASE}/src/arm64/assembler-arm64.cc + ${BASE}/src/arm64/assembler-arm64.h + ${BASE}/src/arm64/code-stubs-arm64.cc + ${BASE}/src/arm64/code-stubs-arm64.h + ${BASE}/src/arm64/codegen-arm64.cc + ${BASE}/src/arm64/constants-arm64.h + ${BASE}/src/arm64/cpu-arm64.cc + ${BASE}/src/arm64/decoder-arm64-inl.h + ${BASE}/src/arm64/decoder-arm64.cc + ${BASE}/src/arm64/decoder-arm64.h + ${BASE}/src/arm64/deoptimizer-arm64.cc + ${BASE}/src/arm64/disasm-arm64.cc + ${BASE}/src/arm64/disasm-arm64.h + ${BASE}/src/arm64/eh-frame-arm64.cc + ${BASE}/src/arm64/frame-constants-arm64.cc + ${BASE}/src/arm64/frame-constants-arm64.h + ${BASE}/src/arm64/instructions-arm64-constants.cc + ${BASE}/src/arm64/instructions-arm64.cc + ${BASE}/src/arm64/instructions-arm64.h + ${BASE}/src/arm64/instrument-arm64.cc + ${BASE}/src/arm64/instrument-arm64.h + ${BASE}/src/arm64/interface-descriptors-arm64.cc + ${BASE}/src/arm64/interface-descriptors-arm64.h + ${BASE}/src/arm64/macro-assembler-arm64-inl.h + ${BASE}/src/arm64/macro-assembler-arm64.cc + ${BASE}/src/arm64/macro-assembler-arm64.h + ${BASE}/src/arm64/simulator-arm64.cc + ${BASE}/src/arm64/simulator-arm64.h + ${BASE}/src/arm64/utils-arm64.cc + ${BASE}/src/arm64/utils-arm64.h + ${BASE}/src/compiler/arm64/code-generator-arm64.cc + ${BASE}/src/compiler/arm64/instruction-codes-arm64.h + ${BASE}/src/compiler/arm64/instruction-scheduler-arm64.cc + ${BASE}/src/compiler/arm64/instruction-selector-arm64.cc + ${BASE}/src/compiler/arm64/unwinding-info-writer-arm64.cc + ${BASE}/src/compiler/arm64/unwinding-info-writer-arm64.h + ${BASE}/src/debug/arm64/debug-arm64.cc + ${BASE}/src/regexp/arm64/regexp-macro-assembler-arm64.cc + ${BASE}/src/regexp/arm64/regexp-macro-assembler-arm64.h + ${BASE}/src/wasm/baseline/arm64/liftoff-assembler-arm64-defs.h + ${BASE}/src/wasm/baseline/arm64/liftoff-assembler-arm64.h) + + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/arm64/builtins-arm64.cc) +elseif(ia32) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_IA32) + + set(SOURCES ${SOURCES} + ${BASE}/src/compiler/ia32/code-generator-ia32.cc + ${BASE}/src/compiler/ia32/instruction-codes-ia32.h + ${BASE}/src/compiler/ia32/instruction-scheduler-ia32.cc + ${BASE}/src/compiler/ia32/instruction-selector-ia32.cc + ${BASE}/src/debug/ia32/debug-ia32.cc + ${BASE}/src/ia32/assembler-ia32-inl.h + ${BASE}/src/ia32/assembler-ia32.cc + ${BASE}/src/ia32/assembler-ia32.h + ${BASE}/src/ia32/code-stubs-ia32.cc + ${BASE}/src/ia32/codegen-ia32.cc + ${BASE}/src/ia32/cpu-ia32.cc + ${BASE}/src/ia32/deoptimizer-ia32.cc + ${BASE}/src/ia32/disasm-ia32.cc + ${BASE}/src/ia32/frame-constants-ia32.cc + ${BASE}/src/ia32/frame-constants-ia32.h + ${BASE}/src/ia32/interface-descriptors-ia32.cc + ${BASE}/src/ia32/macro-assembler-ia32.cc + ${BASE}/src/ia32/macro-assembler-ia32.h + ${BASE}/src/ia32/simulator-ia32.cc + ${BASE}/src/ia32/simulator-ia32.h + ${BASE}/src/ia32/sse-intr.h + ${BASE}/src/regexp/ia32/regexp-macro-assembler-ia32.cc + ${BASE}/src/regexp/ia32/regexp-macro-assembler-ia32.h + ${BASE}/src/wasm/baseline/ia32/liftoff-assembler-ia32-defs.h + ${BASE}/src/wasm/baseline/ia32/liftoff-assembler-ia32.h) + + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/ia32/builtins-ia32.cc) +elseif(mips OR mipsel) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_MIPS) + + set(SOURCES ${SOURCES} + ${BASE}/src/compiler/mips/code-generator-mips.cc + ${BASE}/src/compiler/mips/instruction-codes-mips.h + ${BASE}/src/compiler/mips/instruction-scheduler-mips.cc + ${BASE}/src/compiler/mips/instruction-selector-mips.cc + ${BASE}/src/debug/mips/debug-mips.cc + ${BASE}/src/mips/assembler-mips-inl.h + ${BASE}/src/mips/assembler-mips.cc + ${BASE}/src/mips/assembler-mips.h + ${BASE}/src/mips/code-stubs-mips.cc + ${BASE}/src/mips/codegen-mips.cc + ${BASE}/src/mips/constants-mips.cc + ${BASE}/src/mips/constants-mips.h + ${BASE}/src/mips/cpu-mips.cc + ${BASE}/src/mips/deoptimizer-mips.cc + ${BASE}/src/mips/disasm-mips.cc + ${BASE}/src/mips/frame-constants-mips.cc + ${BASE}/src/mips/frame-constants-mips.h + ${BASE}/src/mips/interface-descriptors-mips.cc + ${BASE}/src/mips/macro-assembler-mips.cc + ${BASE}/src/mips/macro-assembler-mips.h + ${BASE}/src/mips/simulator-mips.cc + ${BASE}/src/mips/simulator-mips.h + ${BASE}/src/regexp/mips/regexp-macro-assembler-mips.cc + ${BASE}/src/regexp/mips/regexp-macro-assembler-mips.h + ${BASE}/src/wasm/baseline/mips/liftoff-assembler-mips-defs.h + ${BASE}/src/wasm/baseline/mips/liftoff-assembler-mips.h) + + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/mips/builtins-mips.cc) +elseif(mips64 OR mips64el) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_MIPS64) + + set(SOURCES ${SOURCES} + ${BASE}/src/compiler/mips64/code-generator-mips64.cc + ${BASE}/src/compiler/mips64/instruction-codes-mips64.h + ${BASE}/src/compiler/mips64/instruction-scheduler-mips64.cc + ${BASE}/src/compiler/mips64/instruction-selector-mips64.cc + ${BASE}/src/debug/mips64/debug-mips64.cc + ${BASE}/src/mips64/assembler-mips64-inl.h + ${BASE}/src/mips64/assembler-mips64.cc + ${BASE}/src/mips64/assembler-mips64.h + ${BASE}/src/mips64/code-stubs-mips64.cc + ${BASE}/src/mips64/codegen-mips64.cc + ${BASE}/src/mips64/constants-mips64.cc + ${BASE}/src/mips64/constants-mips64.h + ${BASE}/src/mips64/cpu-mips64.cc + ${BASE}/src/mips64/deoptimizer-mips64.cc + ${BASE}/src/mips64/disasm-mips64.cc + ${BASE}/src/mips64/frame-constants-mips64.cc + ${BASE}/src/mips64/frame-constants-mips64.h + ${BASE}/src/mips64/interface-descriptors-mips64.cc + ${BASE}/src/mips64/macro-assembler-mips64.cc + ${BASE}/src/mips64/macro-assembler-mips64.h + ${BASE}/src/mips64/simulator-mips64.cc + ${BASE}/src/mips64/simulator-mips64.h + ${BASE}/src/regexp/mips64/regexp-macro-assembler-mips64.cc + ${BASE}/src/regexp/mips64/regexp-macro-assembler-mips64.h + ${BASE}/src/wasm/baseline/mips64/liftoff-assembler-mips64-defs.h + ${BASE}/src/wasm/baseline/mips64/liftoff-assembler-mips64.h) + + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/mips64/builtins-mips64.cc) +elseif(ppc OR ppc64) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_PPC) + + if(ppc64) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_PPC64) + endif() + + set(SOURCES ${SOURCES} + ${BASE}/src/compiler/ppc/code-generator-ppc.cc + ${BASE}/src/compiler/ppc/instruction-codes-ppc.h + ${BASE}/src/compiler/ppc/instruction-scheduler-ppc.cc + ${BASE}/src/compiler/ppc/instruction-selector-ppc.cc + ${BASE}/src/debug/ppc/debug-ppc.cc + ${BASE}/src/ppc/assembler-ppc-inl.h + ${BASE}/src/ppc/assembler-ppc.cc + ${BASE}/src/ppc/assembler-ppc.h + ${BASE}/src/ppc/code-stubs-ppc.cc + ${BASE}/src/ppc/codegen-ppc.cc + ${BASE}/src/ppc/constants-ppc.cc + ${BASE}/src/ppc/constants-ppc.h + ${BASE}/src/ppc/cpu-ppc.cc + ${BASE}/src/ppc/deoptimizer-ppc.cc + ${BASE}/src/ppc/disasm-ppc.cc + ${BASE}/src/ppc/frame-constants-ppc.cc + ${BASE}/src/ppc/frame-constants-ppc.h + ${BASE}/src/ppc/interface-descriptors-ppc.cc + ${BASE}/src/ppc/macro-assembler-ppc.cc + ${BASE}/src/ppc/macro-assembler-ppc.h + ${BASE}/src/ppc/simulator-ppc.cc + ${BASE}/src/ppc/simulator-ppc.h + ${BASE}/src/regexp/ppc/regexp-macro-assembler-ppc.cc + ${BASE}/src/regexp/ppc/regexp-macro-assembler-ppc.h + ${BASE}/src/wasm/baseline/ppc/liftoff-assembler-ppc-defs.h + ${BASE}/src/wasm/baseline/ppc/liftoff-assembler-ppc.h) + + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/ppc/builtins-ppc.cc) +elseif(s390 OR s390x) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_S390) + + if(s390x) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_S390X) + endif() + + set(SOURCES ${SOURCES} + ${BASE}/src/compiler/s390/code-generator-s390.cc + ${BASE}/src/compiler/s390/instruction-codes-s390.h + ${BASE}/src/compiler/s390/instruction-scheduler-s390.cc + ${BASE}/src/compiler/s390/instruction-selector-s390.cc + ${BASE}/src/debug/s390/debug-s390.cc + ${BASE}/src/regexp/s390/regexp-macro-assembler-s390.cc + ${BASE}/src/regexp/s390/regexp-macro-assembler-s390.h + ${BASE}/src/s390/assembler-s390-inl.h + ${BASE}/src/s390/assembler-s390.cc + ${BASE}/src/s390/assembler-s390.h + ${BASE}/src/s390/code-stubs-s390.cc + ${BASE}/src/s390/codegen-s390.cc + ${BASE}/src/s390/constants-s390.cc + ${BASE}/src/s390/constants-s390.h + ${BASE}/src/s390/cpu-s390.cc + ${BASE}/src/s390/deoptimizer-s390.cc + ${BASE}/src/s390/disasm-s390.cc + ${BASE}/src/s390/frame-constants-s390.cc + ${BASE}/src/s390/frame-constants-s390.h + ${BASE}/src/s390/interface-descriptors-s390.cc + ${BASE}/src/s390/macro-assembler-s390.cc + ${BASE}/src/s390/macro-assembler-s390.h + ${BASE}/src/s390/simulator-s390.cc + ${BASE}/src/s390/simulator-s390.h + ${BASE}/src/wasm/baseline/s390/liftoff-assembler-s390-defs.h + ${BASE}/src/wasm/baseline/s390/liftoff-assembler-s390.h) + + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/s390/builtins-s390.cc) +elseif(x64) + set(DEFINES ${DEFINES} -DV8_TARGET_ARCH_X64) + + set(SOURCES ${SOURCES} + ${BASE}/src/compiler/x64/code-generator-x64.cc + ${BASE}/src/compiler/x64/instruction-codes-x64.h + ${BASE}/src/compiler/x64/instruction-scheduler-x64.cc + ${BASE}/src/compiler/x64/instruction-selector-x64.cc + ${BASE}/src/compiler/x64/unwinding-info-writer-x64.cc + ${BASE}/src/compiler/x64/unwinding-info-writer-x64.h + ${BASE}/src/debug/x64/debug-x64.cc + ${BASE}/src/regexp/x64/regexp-macro-assembler-x64.cc + ${BASE}/src/regexp/x64/regexp-macro-assembler-x64.h + ${BASE}/src/third_party/valgrind/valgrind.h + ${BASE}/src/x64/assembler-x64-inl.h + ${BASE}/src/x64/assembler-x64.cc + ${BASE}/src/x64/assembler-x64.h + ${BASE}/src/x64/code-stubs-x64.cc + ${BASE}/src/x64/codegen-x64.cc + ${BASE}/src/x64/cpu-x64.cc + ${BASE}/src/x64/deoptimizer-x64.cc + ${BASE}/src/x64/disasm-x64.cc + ${BASE}/src/x64/eh-frame-x64.cc + ${BASE}/src/x64/frame-constants-x64.cc + ${BASE}/src/x64/frame-constants-x64.h + ${BASE}/src/x64/interface-descriptors-x64.cc + ${BASE}/src/x64/macro-assembler-x64.cc + ${BASE}/src/x64/macro-assembler-x64.h + ${BASE}/src/x64/simulator-x64.cc + ${BASE}/src/x64/simulator-x64.h + ${BASE}/src/x64/sse-instr.h + ${BASE}/src/wasm/baseline/x64/liftoff-assembler-x64-defs.h + ${BASE}/src/wasm/baseline/x64/liftoff-assembler-x64.h) + + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/x64/builtins-x64.cc) +endif() + +if(x64 AND linux) + set(SOURCES ${SOURCES} ${BASE}/src/trap-handler/handler-inside.cc) +endif() + +# libv8_platform +set(SOURCES ${SOURCES} + ${BASE}/include/libplatform/libplatform-export.h + ${BASE}/include/libplatform/libplatform.h + ${BASE}/include/libplatform/v8-tracing.h + ${BASE}/src/libplatform/default-background-task-runner.cc + ${BASE}/src/libplatform/default-background-task-runner.h + ${BASE}/src/libplatform/default-foreground-task-runner.cc + ${BASE}/src/libplatform/default-foreground-task-runner.h + ${BASE}/src/libplatform/default-platform.cc + ${BASE}/src/libplatform/default-platform.h + ${BASE}/src/libplatform/task-queue.cc + ${BASE}/src/libplatform/task-queue.h + ${BASE}/src/libplatform/tracing/trace-buffer.cc + ${BASE}/src/libplatform/tracing/trace-buffer.h + ${BASE}/src/libplatform/tracing/trace-config.cc + ${BASE}/src/libplatform/tracing/trace-object.cc + ${BASE}/src/libplatform/tracing/trace-writer.cc + ${BASE}/src/libplatform/tracing/trace-writer.h + ${BASE}/src/libplatform/tracing/tracing-controller.cc + ${BASE}/src/libplatform/worker-thread.cc + ${BASE}/src/libplatform/worker-thread.h) + +# libv8_sampler +set(SOURCES ${SOURCES} + ${BASE}/src/libsampler/sampler.cc + ${BASE}/src/libsampler/sampler.h) + +# v8_inspector +set(v8_inspector_generated_sources + ${CMAKE_CURRENT_BINARY_DIR}/include/inspector/Debugger.h + ${CMAKE_CURRENT_BINARY_DIR}/include/inspector/Runtime.h + ${CMAKE_CURRENT_BINARY_DIR}/include/inspector/Schema.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Console.cpp + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Console.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Debugger.cpp + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Debugger.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Forward.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/HeapProfiler.cpp + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/HeapProfiler.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Profiler.cpp + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Profiler.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Protocol.cpp + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Protocol.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Runtime.cpp + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Runtime.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Schema.cpp + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/protocol/Schema.h) + +set(v8_inspector_protocol_files + ${BASE}/third_party/inspector_protocol/lib/Allocator_h.template + ${BASE}/third_party/inspector_protocol/lib/Array_h.template + ${BASE}/third_party/inspector_protocol/lib/Collections_h.template + ${BASE}/third_party/inspector_protocol/lib/DispatcherBase_cpp.template + ${BASE}/third_party/inspector_protocol/lib/DispatcherBase_h.template + ${BASE}/third_party/inspector_protocol/lib/ErrorSupport_cpp.template + ${BASE}/third_party/inspector_protocol/lib/ErrorSupport_h.template + ${BASE}/third_party/inspector_protocol/lib/Forward_h.template + ${BASE}/third_party/inspector_protocol/lib/FrontendChannel_h.template + ${BASE}/third_party/inspector_protocol/lib/Maybe_h.template + ${BASE}/third_party/inspector_protocol/lib/Object_cpp.template + ${BASE}/third_party/inspector_protocol/lib/Object_h.template + ${BASE}/third_party/inspector_protocol/lib/Parser_cpp.template + ${BASE}/third_party/inspector_protocol/lib/Parser_h.template + ${BASE}/third_party/inspector_protocol/lib/Protocol_cpp.template + ${BASE}/third_party/inspector_protocol/lib/ValueConversions_h.template + ${BASE}/third_party/inspector_protocol/lib/Values_cpp.template + ${BASE}/third_party/inspector_protocol/lib/Values_h.template + ${BASE}/third_party/inspector_protocol/templates/Exported_h.template + ${BASE}/third_party/inspector_protocol/templates/Imported_h.template + ${BASE}/third_party/inspector_protocol/templates/TypeBuilder_cpp.template + ${BASE}/third_party/inspector_protocol/templates/TypeBuilder_h.template) + +set(v8_postmortem_source_files + ${BASE}/src/objects-inl.h + ${BASE}/src/objects.h + ${BASE}/src/objects/code-inl.h + ${BASE}/src/objects/code.h + ${BASE}/src/objects/js-array-inl.h + ${BASE}/src/objects/js-array.h + ${BASE}/src/objects/js-regexp-inl.h + ${BASE}/src/objects/js-regexp.h + ${BASE}/src/objects/map-inl.h + ${BASE}/src/objects/map.h + ${BASE}/src/objects/script-inl.h + ${BASE}/src/objects/script.h + ${BASE}/src/objects/shared-function-info-inl.h + ${BASE}/src/objects/shared-function-info.h + ${BASE}/src/objects/string-inl.h + ${BASE}/src/objects/string.h) + +if(v8_enable_inspector) + set(SOURCES ${SOURCES} + ${BASE}/include/v8-inspector-protocol.h + ${BASE}/include/v8-inspector.h + ${BASE}/src/inspector/injected-script.cc + ${BASE}/src/inspector/injected-script.h + ${BASE}/src/inspector/inspected-context.cc + ${BASE}/src/inspector/inspected-context.h + ${BASE}/src/inspector/remote-object-id.cc + ${BASE}/src/inspector/remote-object-id.h + ${BASE}/src/inspector/search-util.cc + ${BASE}/src/inspector/search-util.h + ${BASE}/src/inspector/string-16.cc + ${BASE}/src/inspector/string-16.h + ${BASE}/src/inspector/string-util.cc + ${BASE}/src/inspector/string-util.h + ${BASE}/src/inspector/test-interface.cc + ${BASE}/src/inspector/test-interface.h + ${BASE}/src/inspector/v8-console-agent-impl.cc + ${BASE}/src/inspector/v8-console-agent-impl.h + ${BASE}/src/inspector/v8-console-message.cc + ${BASE}/src/inspector/v8-console-message.h + ${BASE}/src/inspector/v8-console.cc + ${BASE}/src/inspector/v8-console.h + ${BASE}/src/inspector/v8-debugger-agent-impl.cc + ${BASE}/src/inspector/v8-debugger-agent-impl.h + ${BASE}/src/inspector/v8-debugger-script.cc + ${BASE}/src/inspector/v8-debugger-script.h + ${BASE}/src/inspector/v8-debugger.cc + ${BASE}/src/inspector/v8-debugger.h + ${BASE}/src/inspector/v8-function-call.cc + ${BASE}/src/inspector/v8-function-call.h + ${BASE}/src/inspector/v8-heap-profiler-agent-impl.cc + ${BASE}/src/inspector/v8-heap-profiler-agent-impl.h + ${BASE}/src/inspector/v8-injected-script-host.cc + ${BASE}/src/inspector/v8-injected-script-host.h + ${BASE}/src/inspector/v8-inspector-impl.cc + ${BASE}/src/inspector/v8-inspector-impl.h + ${BASE}/src/inspector/v8-inspector-session-impl.cc + ${BASE}/src/inspector/v8-inspector-session-impl.h + ${BASE}/src/inspector/v8-internal-value-type.cc + ${BASE}/src/inspector/v8-internal-value-type.h + ${BASE}/src/inspector/v8-profiler-agent-impl.cc + ${BASE}/src/inspector/v8-profiler-agent-impl.h + ${BASE}/src/inspector/v8-regex.cc + ${BASE}/src/inspector/v8-regex.h + ${BASE}/src/inspector/v8-runtime-agent-impl.cc + ${BASE}/src/inspector/v8-runtime-agent-impl.h + ${BASE}/src/inspector/v8-schema-agent-impl.cc + ${BASE}/src/inspector/v8-schema-agent-impl.h + ${BASE}/src/inspector/v8-stack-trace-impl.cc + ${BASE}/src/inspector/v8-stack-trace-impl.h + ${BASE}/src/inspector/v8-value-utils.cc + ${BASE}/src/inspector/v8-value-utils.h + ${BASE}/src/inspector/wasm-translation.cc + ${BASE}/src/inspector/wasm-translation.h + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/injected-script-source.h + ${v8_inspector_generated_sources}) +endif() + +if(NOT v8_enable_i18n_support EQUAL 0) + set(DEFINES ${DEFINES} + -DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC + -DV8_INTL_SUPPORT) + set(SOURCES ${SOURCES} + ${BASE}/src/builtins/builtins-intl.cc + ${BASE}/src/builtins/builtins-intl.h + ${BASE}/src/char-predicates.cc + ${BASE}/src/intl.cc + ${BASE}/src/intl.h + ${BASE}/src/objects/intl-objects.cc + ${BASE}/src/objects/intl-objects.h + ${BASE}/src/runtime/runtime-intl.cc) + set(INITIALIZERS_SOURCES ${INITIALIZERS_SOURCES} + ${BASE}/src/builtins/builtins-intl-gen.cc) + set(LIBS ${LIBS} icu_common icu_i18n) + set(LIBRARY_FILES ${LIBRARY_FILES} ${BASE}/src/js/intl.js) +endif() + +if(v8_enable_gdbjit) + set(DEFINES ${DEFINES} -DENABLE_GDB_JIT_INTERFACE) +endif() + +if(v8_trace_maps) + set(DEFINES ${DEFINES} -DV8_TRACE_MAPS) +endif() + +if(v8_postmortem_support) + # FIXME(bnoordhuis) Symbols do not show up in the final binary yet + # thanks to the -Wl,--as-needed link flag. + set(SOURCES ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/postmortem.cc) +endif() + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/tools/js2c.py + ${CMAKE_CURRENT_BINARY_DIR}/libraries.cc + CORE + ${LIBRARY_FILES} + DEPENDS + ${BASE}/tools/js2c.py + ${LIBRARY_FILES} + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/libraries.cc) + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/tools/js2c.py + ${CMAKE_CURRENT_BINARY_DIR}/d8-js.cc + D8 + ${D8_LIBRARY_FILES} + DEPENDS + ${BASE}/tools/js2c.py + ${D8_LIBRARY_FILES} + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/d8-js.cc) + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/tools/js2c.py + ${CMAKE_CURRENT_BINARY_DIR}/extra-libraries.cc + EXTRAS + DEPENDS + ${BASE}/tools/js2c.py + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/extra-libraries.cc) + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/tools/js2c.py + ${CMAKE_CURRENT_BINARY_DIR}/experimental-extra-libraries.cc + EXPERIMENTAL_EXTRAS + DEPENDS + ${BASE}/tools/js2c.py + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/experimental-extra-libraries.cc) + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/third_party/inspector_protocol/CodeGenerator.py + --jinja_dir ${BASE}/third_party + --output_base ${CMAKE_CURRENT_BINARY_DIR}/src/inspector + --config ${BASE}/src/inspector/inspector_protocol_config.json + DEPENDS + ${BASE}/src/inspector/inspector_protocol_config.json + ${BASE}/src/inspector/js_protocol.json + ${BASE}/third_party/inspector_protocol/CodeGenerator.py + ${v8_inspector_protocol_files} + OUTPUT + ${v8_inspector_generated_sources}) + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/src/inspector/build/xxd.py + InjectedScriptSource_js + ${BASE}/src/inspector/injected-script-source.js + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/injected-script-source.h + DEPENDS + ${BASE}/src/inspector/build/xxd.py + ${BASE}/src/inspector/injected-script-source.js + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector/injected-script-source.h) + +add_custom_command( + COMMAND + ${CMAKE_COMMAND} -E make_directory + ${CMAKE_CURRENT_BINARY_DIR}/include/inspector + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/include/inspector + ${CMAKE_CURRENT_BINARY_DIR}/src/inspector) + +add_custom_command( + COMMAND + ${PYTHON_EXECUTABLE} + ${BASE}/tools/gen-postmortem-metadata.py + ${CMAKE_CURRENT_BINARY_DIR}/postmortem.cc + ${v8_postmortem_source_files} + DEPENDS + ${BASE}/tools/gen-postmortem-metadata.py + ${v8_postmortem_source_files} + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/postmortem.cc) + +add_definitions(${DEFINES}) +include_directories(${BASE} ${BASE}/include ${CMAKE_CURRENT_BINARY_DIR}) +link_libraries(${LIBS}) + +# Shared between the v8 and v8_base targets. +set(v8_common_compile_definitions + PUBLIC V8_PROMISE_INTERNAL_FIELD_COUNT=${v8_promise_internal_field_count} + PRIVATE V8_PROMISE_INTERNAL_FIELD_COUNT=${v8_promise_internal_field_count}) +set(v8_common_include_directories PUBLIC ${BASE}/include) + +add_library(v8_base ${SHARED} ${SOURCES}) +target_compile_definitions(v8_base ${v8_common_compile_definitions}) +target_include_directories(v8_base ${v8_common_include_directories}) +target_link_libraries(v8_base v8_libbase) + +if(v8_use_snapshot) + add_definitions(-DV8_USE_SNAPSHOT) + + add_library(v8_builtins_generators ${SHARED} ${INITIALIZERS_SOURCES}) + target_link_libraries(v8_builtins_generators v8_base) + + add_executable( + v8_mksnapshot + ${BASE}/src/setup-isolate-full.cc + ${BASE}/src/snapshot/mksnapshot.cc + ${BASE}/src/snapshot/snapshot-empty.cc) + target_link_libraries(v8_mksnapshot v8_base v8_builtins_generators) + + add_custom_command( + COMMAND + v8_mksnapshot --startup_src ${CMAKE_CURRENT_BINARY_DIR}/snapshot.cc + DEPENDS + v8_mksnapshot + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/snapshot.cc) + + add_library( + v8 ${SHARED} + ${SOURCES} + ${BASE}/src/setup-isolate-deserialize.cc + ${CMAKE_CURRENT_BINARY_DIR}/snapshot.cc) +else() + add_library(v8 ${SHARED} ${SOURCES} ${BASE}/src/snapshot/snapshot-empty.cc) +endif() + +target_link_libraries(v8 v8_libbase) +target_compile_definitions(v8 ${v8_common_compile_definitions}) +target_include_directories(v8 ${v8_common_include_directories}) + +if(node_enable_v8_vtunejit) + add_library( + v8_vtune ${SHARED} + ${BASE}/src/third_party/vtune/ittnotify_config.h + ${BASE}/src/third_party/vtune/ittnotify_types.h + ${BASE}/src/third_party/vtune/jitprofiling.cc + ${BASE}/src/third_party/vtune/jitprofiling.h + ${BASE}/src/third_party/vtune/v8-vtune.h + ${BASE}/src/third_party/vtune/vtune-jit.cc + ${BASE}/src/third_party/vtune/vtune-jit.h) + target_link_libraries(v8_vtune v8_base) + target_compile_definitions(v8_vtune PUBLIC ENABLE_VTUNE_JIT_INTERFACE) +endif() + +if(node_enable_d8) + add_executable(d8 ${D8_SOURCES}) + target_link_libraries(d8 v8) +endif() + +if(NOT MSVC) + set(CMAKE_CXX_FLAGS "-fno-exceptions -fno-rtti ${CMAKE_CXX_FLAGS}") +endif() + +# Ensure no surprising artifacts from 80bit double math with x86. +if(ia32) + if(win32) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2 -mfpmath=sse -mmmx") + endif() +endif() diff --git a/cmake/v8/libbase/CMakeLists.txt b/cmake/v8/libbase/CMakeLists.txt new file mode 100644 index 00000000000000..0c710f25b4f1be --- /dev/null +++ b/cmake/v8/libbase/CMakeLists.txt @@ -0,0 +1,111 @@ +include(../../common.cmake) +project(v8_libbase) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions(-DDEBUG) +endif() + +set(BASE ${CMAKE_SOURCE_DIR}/deps/v8) + +set(SOURCES + ${BASE}/src/base/adapters.h + ${BASE}/src/base/atomic-utils.h + ${BASE}/src/base/atomicops.h + ${BASE}/src/base/atomicops_internals_atomicword_compat.h + ${BASE}/src/base/atomicops_internals_portable.h + ${BASE}/src/base/atomicops_internals_std.h + ${BASE}/src/base/base-export.h + ${BASE}/src/base/bits.cc + ${BASE}/src/base/bits.h + ${BASE}/src/base/build_config.h + ${BASE}/src/base/compiler-specific.h + ${BASE}/src/base/cpu.cc + ${BASE}/src/base/cpu.h + ${BASE}/src/base/debug/stack_trace_posix.cc + ${BASE}/src/base/debug/stack_trace.h + ${BASE}/src/base/division-by-constant.cc + ${BASE}/src/base/division-by-constant.h + ${BASE}/src/base/export-template.h + ${BASE}/src/base/file-utils.cc + ${BASE}/src/base/file-utils.h + ${BASE}/src/base/flags.h + ${BASE}/src/base/format-macros.h + ${BASE}/src/base/free_deleter.h + ${BASE}/src/base/functional.cc + ${BASE}/src/base/functional.h + ${BASE}/src/base/hashmap-entry.h + ${BASE}/src/base/hashmap.h + ${BASE}/src/base/ieee754.cc + ${BASE}/src/base/ieee754.h + ${BASE}/src/base/iterator.h + ${BASE}/src/base/lazy-instance.h + ${BASE}/src/base/logging.cc + ${BASE}/src/base/logging.h + ${BASE}/src/base/macros.h + ${BASE}/src/base/once.cc + ${BASE}/src/base/once.h + ${BASE}/src/base/optional.h + ${BASE}/src/base/platform/condition-variable.cc + ${BASE}/src/base/platform/condition-variable.h + ${BASE}/src/base/platform/elapsed-timer.h + ${BASE}/src/base/platform/mutex.cc + ${BASE}/src/base/platform/mutex.h + ${BASE}/src/base/platform/platform.h + ${BASE}/src/base/platform/semaphore.cc + ${BASE}/src/base/platform/semaphore.h + ${BASE}/src/base/platform/time.cc + ${BASE}/src/base/platform/time.h + ${BASE}/src/base/ring-buffer.h + ${BASE}/src/base/safe_conversions.h + ${BASE}/src/base/safe_conversions_impl.h + ${BASE}/src/base/safe_math.h + ${BASE}/src/base/safe_math_impl.h + ${BASE}/src/base/sys-info.cc + ${BASE}/src/base/sys-info.h + ${BASE}/src/base/template-utils.h + ${BASE}/src/base/timezone-cache.h + ${BASE}/src/base/tsan.h + ${BASE}/src/base/utils/random-number-generator.cc + ${BASE}/src/base/utils/random-number-generator.h) + +if(NOT win32) + set(LIBS ${LIBS} pthread) + set(SOURCES ${SOURCES} + ${BASE}/src/base/platform/platform-posix-time.cc + ${BASE}/src/base/platform/platform-posix-time.h + ${BASE}/src/base/platform/platform-posix.cc + ${BASE}/src/base/platform/platform-posix.h) + if(NOT android) + set(SOURCES ${SOURCES} ${BASE}/src/base/debug/stack_trace_posix.cc) + endif() +endif() + +if(aix) + set(SOURCES ${SOURCES} ${BASE}/src/base/platform/platform-aix.cc) +elseif(android) + set(SOURCES ${SOURCES} ${BASE}/src/base/debug/stack_trace_android.cc) +elseif(freebsd) + set(SOURCES ${SOURCES} ${BASE}/src/base/platform/platform-freebsd.cc) +elseif(linux) + set(SOURCES ${SOURCES} ${BASE}/src/base/platform/platform-linux.cc) + set(LIBS ${LIBS} dl rt) +elseif(mac) + set(SOURCES ${SOURCES} ${BASE}/src/base/platform/platform-macos.cc) +elseif(netbsd OR openbsd) + set(SOURCES ${SOURCES} ${BASE}/src/base/platform/platform-openbsd.cc) + set(LIBS ${LIBS} execinfo) +elseif(sunos) + set(SOURCES ${SOURCES} ${BASE}/src/base/platform/platform-solaris.cc) + set(LIBS ${LIBS} nsl rt) +elseif(win32) + set(SOURCES ${SOURCES} + ${BASE}/src/base/debug/stack_trace_win.cc + ${BASE}/src/base/platform/platform-win32.cc + ${BASE}/src/base/win32-headers.h) + set(LIBS ${LIBS} dbghelp shlwapi winmm ws2_32) +endif() + +include_directories(${BASE}) +link_libraries(${LIBS}) + +add_library(v8_libbase ${SHARED} ${SOURCES}) diff --git a/cmake/zlib/CMakeLists.txt b/cmake/zlib/CMakeLists.txt new file mode 100644 index 00000000000000..80e245ff749dca --- /dev/null +++ b/cmake/zlib/CMakeLists.txt @@ -0,0 +1,37 @@ +include(../common.cmake) +project(zlib) + +set(BASE ${CMAKE_SOURCE_DIR}/deps/zlib) + +add_library( + zlib ${SHARED} + ${BASE}/adler32.c + ${BASE}/compress.c + ${BASE}/crc32.c + ${BASE}/crc32.h + ${BASE}/deflate.c + ${BASE}/deflate.h + ${BASE}/gzclose.c + ${BASE}/gzguts.h + ${BASE}/gzlib.c + ${BASE}/gzread.c + ${BASE}/gzwrite.c + ${BASE}/infback.c + ${BASE}/inffast.c + ${BASE}/inffast.h + ${BASE}/inffixed.h + ${BASE}/inflate.c + ${BASE}/inflate.h + ${BASE}/inftrees.c + ${BASE}/inftrees.h + ${BASE}/trees.c + ${BASE}/trees.h + ${BASE}/uncompr.c + ${BASE}/zconf.h + ${BASE}/zlib.h + ${BASE}/zutil.c + ${BASE}/zutil.h) + +if(NOT MSVC) + target_compile_definitions(zlib PRIVATE Z_HAVE_UNISTD_H HAVE_HIDDEN) +endif() diff --git a/configure b/configure index 8a9f2044cb22da..1874fbe2483a44 100755 --- a/configure +++ b/configure @@ -548,6 +548,12 @@ parser.add_option('--without-bundled-v8', help='do not use V8 includes from the bundled deps folder. ' + '(This mode is not officially supported for regular applications)') +parser.add_option('--cmake', + action='store', + dest='cmake', + default=None, + help='build using cmake, not GYP') + # Create compile_commands.json in out/Debug and out/Release. parser.add_option('-C', action='store_true', @@ -1049,6 +1055,7 @@ def configure_openssl(o): o['variables']['node_use_openssl'] = b(not options.without_ssl) o['variables']['node_shared_openssl'] = b(options.shared_openssl) o['variables']['openssl_no_asm'] = 1 if options.openssl_no_asm else 0 + o['variables']['node_use_openssl_ca_store'] = b(options.use_openssl_ca_store) if options.use_openssl_ca_store: o['defines'] += ['NODE_OPENSSL_CERT_STORE'] if options.openssl_system_ca_path: @@ -1344,15 +1351,18 @@ def configure_intl(o): 'source/data/in', icu_data_file_l) # relative to dep.. - icu_data_in = os.path.join('..','..', icu_full_path, 'source/data/in', icu_data_file_l) + icu_data_in = ( + os.path.abspath( + os.path.join(icu_full_path, 'source/data/in', icu_data_file_l))) if not os.path.isfile(icu_data_path) and icu_endianness != 'l': # use host endianness icu_data_path = os.path.join(icu_full_path, 'source/data/in', icu_data_file) # relative to dep.. - icu_data_in = os.path.join('..', icu_full_path, 'source/data/in', - icu_data_file) + icu_data_in = ( + os.path.abspath( + os.path.join(icu_full_path, 'source/data/in', icu_data_file))) # this is the input '.dat' file to use .. icudt*.dat # may be little-endian if from a icu-project.org tarball o['variables']['icu_data_in'] = icu_data_in @@ -1382,6 +1392,7 @@ def configure_intl(o): pprint.pformat(icu_config, indent=2) + '\n') return # end of configure_intl + def configure_inspector(o): disable_inspector = (options.without_inspector or options.with_intl in (None, 'none') or @@ -1389,6 +1400,52 @@ def configure_inspector(o): o['variables']['v8_enable_inspector'] = 0 if disable_inspector else 1 +def configure_gyp(o): + gyp_args = ['--no-parallel'] + + if options.use_xcode: + gyp_args += ['-f', 'xcode'] + elif options.use_ninja: + gyp_args += ['-f', 'ninja'] + elif flavor == 'win' and sys.platform != 'msys': + gyp_args += ['-f', 'msvs', '-G', 'msvs_version=auto'] + else: + gyp_args += ['-f', 'make-' + flavor] + + if options.compile_commands_json: + gyp_args += ['-f', 'compile_commands_json'] + + gyp_args += args + + if warn.warned: + warn('warnings were emitted in the configure phase') + + run_gyp(gyp_args) + + +def configure_cmake(o): + cmake_args = [options.cmake] + + for k, v in o['variables'].items(): + if v == 'true': v = 'ON' + if v == 'false': v = 'OFF' + cmake_args.append('-D{}={}'.format(k, v)) + + try: + os.mkdir('out.cmake') + except OSError as e: + if e.errno != errno.EEXIST: raise e # Unexpected error. + + try: + os.unlink('out.cmake/CMakeCache.txt') + except OSError as e: + if e.errno != errno.ENOENT: raise e # Unexpected error. + + cmake_args.extend(args) # Support `./configure -- -Dvar=42` + cmake_args.append('..') + sys.exit(subprocess.Popen(cmake_args, cwd='out.cmake').wait()) + + def make_bin_override(): if sys.platform == 'win32': raise Exception('make_bin_override should not be called on win32.') @@ -1422,6 +1479,13 @@ def make_bin_override(): return bin_override + +# TODO(bnoordhuis) Remove, |flavor| is specific to GYP. +flavor_params = {} +if options.dest_os: + flavor_params['flavor'] = options.dest_os +flavor = GetFlavor(flavor_params) + output = { 'variables': {}, 'include_dirs': [], @@ -1433,13 +1497,6 @@ output = { # Print a warning when the compiler is too old. check_compiler(output) -# determine the "flavor" (operating system) we're building for, -# leveraging gyp's GetFlavor function -flavor_params = {} -if (options.dest_os): - flavor_params['flavor'] = options.dest_os -flavor = GetFlavor(flavor_params) - configure_node(output) configure_library('zlib', output) configure_library('http_parser', output) @@ -1483,11 +1540,6 @@ output = { if make_global_settings: output['make_global_settings'] = make_global_settings -pprint.pprint(output, indent=2) - -write('config.gypi', do_not_edit + - pprint.pformat(output, indent=2) + '\n') - config = { 'BUILDTYPE': 'Debug' if options.debug else 'Release', 'USE_XCODE': str(int(options.use_xcode or 0)), @@ -1495,6 +1547,9 @@ config = { 'NODE_TARGET_TYPE': variables['node_target_type'], } +if options.cmake: + config['CMAKE'] = options.cmake + if options.prefix: config['PREFIX'] = options.prefix @@ -1507,23 +1562,11 @@ if bin_override: write('config.mk', do_not_edit + config) -gyp_args = ['--no-parallel'] +# Used by both the GYP and the cmake builds to populate `process.config`. +write('config.gypi', do_not_edit + pprint.pformat(output, indent=2) + '\n') +pprint.pprint(output, indent=2) -if options.use_xcode: - gyp_args += ['-f', 'xcode'] -elif options.use_ninja: - gyp_args += ['-f', 'ninja'] -elif flavor == 'win' and sys.platform != 'msys': - gyp_args += ['-f', 'msvs', '-G', 'msvs_version=auto'] +if options.cmake: + configure_cmake(output) else: - gyp_args += ['-f', 'make-' + flavor] - -if options.compile_commands_json: - gyp_args += ['-f', 'compile_commands_json'] - -gyp_args += args - -if warn.warned: - warn('warnings were emitted in the configure phase') - -run_gyp(gyp_args) + configure_gyp(output) diff --git a/node.gyp b/node.gyp index 44c46ad2bc8854..bb2cabf82266dd 100644 --- a/node.gyp +++ b/node.gyp @@ -745,6 +745,7 @@ 'action': [ 'python', 'tools/js2c.py', + '', # Unused in GYP build. '<@(_outputs)', '<@(_inputs)', ], diff --git a/tools/install.py b/tools/install.py index be2bab5463ca00..7692585702de58 100755 --- a/tools/install.py +++ b/tools/install.py @@ -13,6 +13,7 @@ install_path = None # base target directory (DESTDIR + PREFIX from Makefile) target_defaults = None variables = None +cmake = False def abspath(*args): path = os.path.join(*args) @@ -119,7 +120,7 @@ def subdir_files(path, dest, action): def files(action): is_windows = sys.platform == 'win32' output_file = 'node' - output_prefix = 'out/Release/' + output_prefix = 'out.cmake/cmake/node/' if cmake else 'out/Release/' if 'false' == variables.get('node_shared'): if is_windows: @@ -131,7 +132,7 @@ def files(action): output_file = 'lib' + output_file + '.' + variables.get('shlib_suffix') # GYP will output to lib.target except on OS X, this is hardcoded # in its source - see the _InstallableTargetInstallPath function. - if sys.platform != 'darwin': + if not cmake and sys.platform != 'darwin': output_prefix += 'lib.target/' if 'false' == variables.get('node_shared'): @@ -224,4 +225,7 @@ def run(args): raise RuntimeError('Bad command: %s\n' % cmd) if __name__ == '__main__': + if '--cmake' in sys.argv: + sys.argv = [arg for arg in sys.argv if arg != '--cmake'] + cmake = True run(sys.argv[:]) diff --git a/tools/js2c.py b/tools/js2c.py index 5a97fdaecfa51e..0d5707534749a9 100755 --- a/tools/js2c.py +++ b/tools/js2c.py @@ -240,7 +240,7 @@ def Render(var, data): return template.format(var=var, data=data) -def JS2C(source, target): +def JS2C(base, source, target): modules = [] consts = {} macros = {} @@ -268,6 +268,10 @@ def JS2C(source, target): # On Windows, "./foo.bar" in the .gyp file is passed as "foo.bar" # so don't assume there is always a slash in the file path. + if base: + assert name.startswith(base) + name = name[1+len(base):] + if '/' in name or '\\' in name: split = re.split('/|\\\\', name) if split[0] == 'deps': @@ -305,9 +309,10 @@ def JS2C(source, target): output.close() def main(): - natives = sys.argv[1] - source_files = sys.argv[2:] - JS2C(source_files, [natives]) + base = sys.argv[1] + natives = sys.argv[2] + source_files = sys.argv[3:] + JS2C(base, source_files, [natives]) if __name__ == "__main__": main() diff --git a/tools/test.py b/tools/test.py index 230774b25619da..22b560022fe896 100755 --- a/tools/test.py +++ b/tools/test.py @@ -894,6 +894,7 @@ def __init__(self, workspace, buildspace, verbose, vm, args, expect_fail, self.workspace = workspace self.buildspace = buildspace self.verbose = verbose + self.vm = vm self.node_args = args self.expect_fail = expect_fail self.timeout = timeout @@ -905,6 +906,9 @@ def __init__(self, workspace, buildspace, verbose, vm, args, expect_fail, self.v8_enable_inspector = True def GetVm(self, arch, mode): + if not self.vm.endswith('shell'): + return self.vm + if arch == 'none': name = 'out/Debug/node' if mode == 'debug' else 'out/Release/node' else: From fc1b2c671a956476ff5a4c5f2ca87645ac29f408 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 21 Feb 2018 12:33:39 +0100 Subject: [PATCH 192/193] tools: print iculslocs error messages to stderr Don't print them to stdout because stdout gets redirected to file. Errors were effectively being swallowed since said file was deleted afterwards. --- tools/icu/iculslocs.cc | 44 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/tools/icu/iculslocs.cc b/tools/icu/iculslocs.cc index 3ceb8d2a4d81d0..0a4dd66021c56b 100644 --- a/tools/icu/iculslocs.cc +++ b/tools/icu/iculslocs.cc @@ -105,16 +105,17 @@ void usage() { PROG); } -#define ASSERT_SUCCESS(status, what) \ - if (U_FAILURE(*status)) { \ - printf("%s:%d: %s: ERROR: %s %s\n", \ - __FILE__, \ - __LINE__, \ - PROG, \ - u_errorName(*status), \ - what); \ - return 1; \ - } +#define ASSERT_SUCCESS(status, what) \ + do { \ + if (U_FAILURE(*status)) { \ + fprintf(stderr, "%s:%d: ERROR: %s %s\n", \ + __FILE__, \ + __LINE__, \ + u_errorName(*status), \ + what); \ + return 1; \ + } \ + } while (0) /** * @param status changed from reference to pointer to match node.js style @@ -167,12 +168,12 @@ int localeExists(const char* loc, UBool* exists) { return 0; // "good" failure } else { // some other failure.. - printf("%s:%d: %s: ERROR %s opening %s for test.\n", - __FILE__, - __LINE__, - u_errorName(status), - packageName.data(), - loc); + fprintf(stderr, "%s:%d: %s: ERROR %s opening %s for test.\n", + __FILE__, + __LINE__, + u_errorName(status), + packageName.data(), + loc); return 1; // abort } } @@ -218,7 +219,8 @@ int dumpAllButInstalledLocales(int lev, fprintf(bf, "\"}"); } break; default: { - printf("ERROR: unhandled type in dumpAllButInstalledLocales().\n"); + fprintf(stderr, + "ERROR: unhandled type in dumpAllButInstalledLocales().\n"); return 1; } break; } @@ -239,7 +241,7 @@ int list(const char* toBundle) { } bf = fopen(toBundle, "wb"); if (bf == NULL) { // NOLINT (readability/null_usage) - printf("ERROR: Could not open '%s' for writing.\n", toBundle); + fprintf(stderr, "ERROR: Could not open '%s' for writing.\n", toBundle); return 1; } fprintf(bf, "\xEF\xBB\xBF"); // write UTF-8 BOM @@ -280,7 +282,7 @@ int list(const char* toBundle) { " // First, everything besides InstalledLocales:\n", locale); if (dumpAllButInstalledLocales(0, &bund, bf, &status)) { - printf("Error dumping prolog for %s\n", toBundle); + fprintf(stderr, "Error dumping prolog for %s\n", toBundle); fclose(bf); return 1; } @@ -349,7 +351,7 @@ int main(int argc, const char* argv[]) { VERBOSE++; } else if (!strcmp(arg, "-i") && (argsLeft >= 1)) { if (i != 1) { - printf("ERROR: -i must be the first argument given.\n"); + fprintf(stderr, "ERROR: -i must be the first argument given.\n"); usage(); return 1; } @@ -380,7 +382,7 @@ int main(int argc, const char* argv[]) { return 1; } } else { - printf("Unknown or malformed option: %s\n", arg); + fprintf(stderr, "Unknown or malformed option: %s\n", arg); usage(); return 1; } From 726ba1ce0cd9186701014b59bd9275bac68e1829 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 21 Feb 2018 12:33:39 +0100 Subject: [PATCH 193/193] tools: improve iculslocs error messages --- tools/icu/iculslocs.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/icu/iculslocs.cc b/tools/icu/iculslocs.cc index 0a4dd66021c56b..6b47c21002edf1 100644 --- a/tools/icu/iculslocs.cc +++ b/tools/icu/iculslocs.cc @@ -105,14 +105,15 @@ void usage() { PROG); } -#define ASSERT_SUCCESS(status, what) \ +#define ASSERT_SUCCESS(status, ...) \ do { \ if (U_FAILURE(*status)) { \ - fprintf(stderr, "%s:%d: ERROR: %s %s\n", \ + fprintf(stderr, "%s:%d: ERROR: %s ", \ __FILE__, \ __LINE__, \ - u_errorName(*status), \ - what); \ + u_errorName(*status)); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ return 1; \ } \ } while (0) @@ -258,7 +259,7 @@ int list(const char* toBundle) { icu::LocalUResourceBundlePointer bund( ures_openDirect(packageName.data(), locale, &status)); - ASSERT_SUCCESS(&status, "while opening the bundle"); + ASSERT_SUCCESS(&status, "while opening bundle %s", packageName.data()); icu::LocalUResourceBundlePointer installedLocales( // NOLINTNEXTLINE (readability/null_usage) ures_getByKey(bund.getAlias(), INSTALLEDLOCALES, NULL, &status));