diff --git a/lib/_http_agent.js b/lib/_http_agent.js index 5a18e40b4f13b8..50cee72c674fd9 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -61,7 +61,7 @@ function Agent(options) { this.maxFreeSockets = this.options.maxFreeSockets || 256; this.on('free', (socket, options) => { - var name = this.getName(options); + const name = this.getName(options); debug('agent.on(free)', name); if (socket.writable && @@ -74,14 +74,14 @@ function Agent(options) { } else { // If there are no pending requests, then put it in // the freeSockets pool, but only if we're allowed to do so. - var req = socket._httpMessage; + const req = socket._httpMessage; if (req && req.shouldKeepAlive && socket.writable && this.keepAlive) { - var freeSockets = this.freeSockets[name]; - var freeLen = freeSockets ? freeSockets.length : 0; - var count = freeLen; + let freeSockets = this.freeSockets[name]; + const freeLen = freeSockets ? freeSockets.length : 0; + let count = freeLen; if (this.sockets[name]) count += this.sockets[name].length; @@ -113,7 +113,7 @@ Agent.prototype.createConnection = net.createConnection; // Get the key for a given set of request options Agent.prototype.getName = function getName(options) { - var name = options.host || 'localhost'; + let name = options.host || 'localhost'; name += ':'; if (options.port) @@ -153,17 +153,17 @@ Agent.prototype.addRequest = function addRequest(req, options, port/*legacy*/, if (!options.servername) options.servername = calculateServerName(options, req); - var name = this.getName(options); + const name = this.getName(options); if (!this.sockets[name]) { this.sockets[name] = []; } - var freeLen = this.freeSockets[name] ? this.freeSockets[name].length : 0; - var sockLen = freeLen + this.sockets[name].length; + const freeLen = this.freeSockets[name] ? this.freeSockets[name].length : 0; + const sockLen = freeLen + this.sockets[name].length; if (freeLen) { // we have a free socket, so use that. - var socket = this.freeSockets[name].shift(); + const socket = this.freeSockets[name].shift(); // Guard against an uninitialized or user supplied Socket. if (socket._handle && typeof socket._handle.asyncReset === 'function') { // Assign the handle a new asyncId and run any init() hooks. @@ -201,12 +201,12 @@ Agent.prototype.createSocket = function createSocket(req, options, cb) { if (!options.servername) options.servername = calculateServerName(options, req); - var name = this.getName(options); + const name = this.getName(options); options._agentKey = name; debug('createConnection', name, options); options.encoding = null; - var called = false; + let called = false; const oncreate = (err, s) => { if (called) @@ -282,19 +282,19 @@ function installListeners(agent, s, options) { } Agent.prototype.removeSocket = function removeSocket(s, options) { - var name = this.getName(options); + const name = this.getName(options); debug('removeSocket', name, 'writable:', s.writable); - var sets = [this.sockets]; + const sets = [this.sockets]; // If the socket was destroyed, remove it from the free buffers too. if (!s.writable) sets.push(this.freeSockets); for (var sk = 0; sk < sets.length; sk++) { - var sockets = sets[sk]; + const sockets = sets[sk]; if (sockets[name]) { - var index = sockets[name].indexOf(s); + const index = sockets[name].indexOf(s); if (index !== -1) { sockets[name].splice(index, 1); // Don't leak @@ -306,7 +306,7 @@ Agent.prototype.removeSocket = function removeSocket(s, options) { if (this.requests[name] && this.requests[name].length) { debug('removeSocket, have a request, make a socket'); - var req = this.requests[name][0]; + const req = this.requests[name][0]; // If we have pending requests and a socket gets closed make a new one this.createSocket(req, options, handleSocketCreation(req, false)); } @@ -325,12 +325,12 @@ Agent.prototype.reuseSocket = function reuseSocket(socket, req) { }; Agent.prototype.destroy = function destroy() { - var sets = [this.freeSockets, this.sockets]; + const sets = [this.freeSockets, this.sockets]; for (var s = 0; s < sets.length; s++) { - var set = sets[s]; - var keys = Object.keys(set); + const set = sets[s]; + const keys = Object.keys(set); for (var v = 0; v < keys.length; v++) { - var setName = set[keys[v]]; + const setName = set[keys[v]]; for (var n = 0; n < setName.length; n++) { setName[n].destroy(); } diff --git a/lib/_http_client.js b/lib/_http_client.js index 8e3d61a75612ca..a7ad03f228c238 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -76,8 +76,8 @@ function ClientRequest(options, cb) { options = util._extend({}, options); } - var agent = options.agent; - var defaultAgent = options._defaultAgent || Agent.globalAgent; + let agent = options.agent; + const defaultAgent = options._defaultAgent || Agent.globalAgent; if (agent === false) { agent = new defaultAgent.constructor(); } else if (agent === null || agent === undefined) { @@ -92,12 +92,12 @@ function ClientRequest(options, cb) { } this.agent = agent; - var protocol = options.protocol || defaultAgent.protocol; - var expectedProtocol = defaultAgent.protocol; + const protocol = options.protocol || defaultAgent.protocol; + let expectedProtocol = defaultAgent.protocol; if (this.agent && this.agent.protocol) expectedProtocol = this.agent.protocol; - var path; + let path; if (options.path) { path = String(options.path); if (INVALID_PATH_REGEX.test(path)) @@ -108,20 +108,20 @@ function ClientRequest(options, cb) { throw new ERR_INVALID_PROTOCOL(protocol, expectedProtocol); } - var defaultPort = options.defaultPort || + const defaultPort = options.defaultPort || this.agent && this.agent.defaultPort; - var port = options.port = options.port || defaultPort || 80; - var host = options.host = validateHost(options.hostname, 'hostname') || + const port = options.port = options.port || defaultPort || 80; + const host = options.host = validateHost(options.hostname, 'hostname') || validateHost(options.host, 'host') || 'localhost'; - var setHost = (options.setHost === undefined); + const setHost = (options.setHost === undefined); this.socketPath = options.socketPath; this.timeout = options.timeout; - var method = options.method; - var methodIsString = (typeof method === 'string'); + let method = options.method; + const methodIsString = (typeof method === 'string'); if (method !== null && method !== undefined && !methodIsString) { throw new ERR_INVALID_ARG_TYPE('method', 'string', method); } @@ -158,7 +158,7 @@ function ClientRequest(options, cb) { this.parser = null; this.maxHeadersCount = null; - var called = false; + let called = false; if (this.agent) { // If there is an agent we should default to Connection:keep-alive, @@ -174,23 +174,23 @@ function ClientRequest(options, cb) { } } - var headersArray = Array.isArray(options.headers); + const headersArray = Array.isArray(options.headers); if (!headersArray) { if (options.headers) { - var keys = Object.keys(options.headers); + const keys = Object.keys(options.headers); for (var i = 0; i < keys.length; i++) { - var key = keys[i]; + const key = keys[i]; this.setHeader(key, options.headers[key]); } } if (host && !this.getHeader('host') && setHost) { - var hostHeader = host; + let hostHeader = host; // For the Host header, ensure that IPv6 addresses are enclosed // in square brackets, as defined by URI formatting // https://tools.ietf.org/html/rfc3986#section-3.2.2 - var posColon = hostHeader.indexOf(':'); + const posColon = hostHeader.indexOf(':'); if (posColon !== -1 && hostHeader.indexOf(':', posColon + 1) !== -1 && hostHeader.charCodeAt(0) !== 91/*'['*/) { @@ -221,7 +221,7 @@ function ClientRequest(options, cb) { options.headers); } - var oncreate = (err, socket) => { + const oncreate = (err, socket) => { if (called) return; called = true; @@ -307,15 +307,15 @@ function emitAbortNT() { function createHangUpError() { - var error = new Error('socket hang up'); + const error = new Error('socket hang up'); error.code = 'ECONNRESET'; return error; } function socketCloseListener() { - var socket = this; - var req = socket._httpMessage; + const socket = this; + const req = socket._httpMessage; debug('HTTP socket close'); // Pull through final chunk, if anything is buffered. @@ -325,11 +325,11 @@ function socketCloseListener() { // NOTE: It's important to get parser here, because it could be freed by // the `socketOnData`. - var parser = socket.parser; + const parser = socket.parser; if (req.res && req.res.readable) { // Socket closed before we emitted 'end' below. if (!req.res.complete) req.res.emit('aborted'); - var res = req.res; + const res = req.res; res.on('end', function() { res.emit('close'); }); @@ -358,8 +358,8 @@ function socketCloseListener() { } function socketErrorListener(err) { - var socket = this; - var req = socket._httpMessage; + const socket = this; + const req = socket._httpMessage; debug('SOCKET ERROR:', err.message, err.stack); if (req) { @@ -372,7 +372,7 @@ function socketErrorListener(err) { // Handle any pending data socket.read(); - var parser = socket.parser; + const parser = socket.parser; if (parser) { parser.finish(); freeParser(parser, req, socket); @@ -385,16 +385,16 @@ function socketErrorListener(err) { } function freeSocketErrorListener(err) { - var socket = this; + const socket = this; debug('SOCKET ERROR on FREE socket:', err.message, err.stack); socket.destroy(); socket.emit('agentRemove'); } function socketOnEnd() { - var socket = this; - var req = this._httpMessage; - var parser = this.parser; + const socket = this; + const req = this._httpMessage; + const parser = this.parser; if (!req.res && !req.socket._hadError) { // If we don't have a response then we know that the socket @@ -410,13 +410,13 @@ function socketOnEnd() { } function socketOnData(d) { - var socket = this; - var req = this._httpMessage; - var parser = this.parser; + const socket = this; + const req = this._httpMessage; + const parser = this.parser; assert(parser && parser.socket === socket); - var ret = parser.execute(d); + const ret = parser.execute(d); if (ret instanceof Error) { debug('parse error', ret); freeParser(parser, req, socket); @@ -425,8 +425,8 @@ function socketOnData(d) { req.emit('error', ret); } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT - var bytesParsed = ret; - var res = parser.incoming; + const bytesParsed = ret; + const res = parser.incoming; req.res = res; socket.removeListener('data', socketOnData); @@ -435,9 +435,9 @@ function socketOnData(d) { parser.finish(); freeParser(parser, req, socket); - var bodyHead = d.slice(bytesParsed, d.length); + const bodyHead = d.slice(bytesParsed, d.length); - var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; + const eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; if (req.listenerCount(eventName) > 0) { req.upgradeOrConnect = true; @@ -477,8 +477,8 @@ function statusIsInformational(status) { // client function parserOnIncomingClient(res, shouldKeepAlive) { - var socket = this.socket; - var req = socket._httpMessage; + const socket = this.socket; + const req = socket._httpMessage; debug('AGENT incoming response!'); @@ -525,7 +525,7 @@ function parserOnIncomingClient(res, shouldKeepAlive) { // add our listener first, so that we guarantee socket cleanup res.on('end', responseOnEnd); req.on('prefinish', requestOnPrefinish); - var handled = req.emit('response', res); + const handled = req.emit('response', res); // If the user did not listen for the 'response' event, then they // can't possibly read the data, so we ._dump() it into the void @@ -541,7 +541,7 @@ function parserOnIncomingClient(res, shouldKeepAlive) { // client function responseKeepAlive(res, req) { - var socket = req.socket; + const socket = req.socket; if (!req.shouldKeepAlive) { if (socket.writable) { @@ -595,7 +595,7 @@ function emitFreeNT(socket) { } function tickOnSocket(req, socket) { - var parser = parsers.alloc(); + const parser = parsers.alloc(); req.socket = socket; req.connection = socket; parser.reinitialize(HTTPParser.RESPONSE); @@ -702,7 +702,7 @@ ClientRequest.prototype.setTimeout = function setTimeout(msecs, callback) { // Set timeoutCb so that it'll get cleaned up on request end this.timeoutCb = emitTimeout; if (this.socket) { - var sock = this.socket; + const sock = this.socket; this.socket.once('connect', function() { sock.setTimeout(msecs, emitTimeout); }); diff --git a/lib/_http_common.js b/lib/_http_common.js index ffb90407c62175..cbbe5fd0a66b78 100644 --- a/lib/_http_common.js +++ b/lib/_http_common.js @@ -62,7 +62,7 @@ function parserOnHeaders(headers, url) { function parserOnHeadersComplete(versionMajor, versionMinor, headers, method, url, statusCode, statusMessage, upgrade, shouldKeepAlive) { - var parser = this; + const parser = this; if (!headers) { headers = parser._headers; @@ -75,7 +75,7 @@ function parserOnHeadersComplete(versionMajor, versionMinor, headers, method, } // Parser is also used by http client - var ParserIncomingMessage = parser.socket && parser.socket.server ? + const ParserIncomingMessage = parser.socket && parser.socket.server ? parser.socket.server[kIncomingMessage] : IncomingMessage; parser.incoming = new ParserIncomingMessage(parser.socket); @@ -84,7 +84,7 @@ function parserOnHeadersComplete(versionMajor, versionMinor, headers, method, parser.incoming.httpVersion = `${versionMajor}.${versionMinor}`; parser.incoming.url = url; - var n = headers.length; + let n = headers.length; // If parser.maxHeaderPairs <= 0 assume that there's no limit. if (parser.maxHeaderPairs > 0) @@ -120,32 +120,32 @@ function parserOnHeadersComplete(versionMajor, versionMinor, headers, method, // XXX This is a mess. // TODO: http.Parser should be a Writable emits request/response events. function parserOnBody(b, start, len) { - var parser = this; - var stream = parser.incoming; + const parser = this; + const stream = parser.incoming; // if the stream has already been removed, then drop it. if (!stream) return; - var socket = stream.socket; + const socket = stream.socket; // pretend this was the result of a stream._read call. if (len > 0 && !stream._dumped) { - var slice = b.slice(start, start + len); - var ret = stream.push(slice); + const slice = b.slice(start, start + len); + const ret = stream.push(slice); if (!ret) readStop(socket); } } function parserOnMessageComplete() { - var parser = this; - var stream = parser.incoming; + const parser = this; + const stream = parser.incoming; if (stream) { stream.complete = true; // Emit any trailing headers. - var headers = parser._headers; + const headers = parser._headers; if (headers) { parser.incoming._addHeaderLines(headers, headers.length); parser._headers = []; @@ -161,8 +161,8 @@ function parserOnMessageComplete() { } -var parsers = new FreeList('parsers', 1000, function() { - var parser = new HTTPParser(HTTPParser.REQUEST); +const parsers = new FreeList('parsers', 1000, function() { + const parser = new HTTPParser(HTTPParser.REQUEST); parser._headers = []; parser._url = ''; diff --git a/lib/_http_incoming.js b/lib/_http_incoming.js index a84cb64bdb8144..8a0642920f5ae7 100644 --- a/lib/_http_incoming.js +++ b/lib/_http_incoming.js @@ -99,7 +99,7 @@ IncomingMessage.prototype.destroy = function destroy(error) { IncomingMessage.prototype._addHeaderLines = _addHeaderLines; function _addHeaderLines(headers, n) { if (headers && headers.length) { - var dest; + let dest; if (this.complete) { this.rawTrailers = headers; dest = this.trailers; @@ -129,7 +129,7 @@ function _addHeaderLines(headers, n) { // 'array' header list is taken from: // https://mxr.mozilla.org/mozilla/source/netwerk/protocol/http/src/nsHttpHeaderArray.cpp function matchKnownFields(field) { - var low = false; + let low = false; while (true) { switch (field) { case 'Content-Type': @@ -266,7 +266,7 @@ function matchKnownFields(field) { IncomingMessage.prototype._addHeaderLine = _addHeaderLine; function _addHeaderLine(field, value, dest) { field = matchKnownFields(field); - var flag = field.charCodeAt(0); + const flag = field.charCodeAt(0); if (flag === 0 || flag === 2) { field = field.slice(1); // Make a delimited list diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 9cb9c29b3651e2..af659b47aacca9 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -52,10 +52,10 @@ const { utcDate } = internalHttp; const kIsCorked = Symbol('isCorked'); -var RE_FIELDS = +const RE_FIELDS = /^(?:Connection|Transfer-Encoding|Content-Length|Date|Expect|Trailer|Upgrade)$/i; -var RE_CONN_VALUES = /(?:^|\W)close|upgrade(?:$|\W)/ig; -var RE_TE_CHUNKED = common.chunkExpression; +const RE_CONN_VALUES = /(?:^|\W)close|upgrade(?:$|\W)/ig; +const RE_TE_CHUNKED = common.chunkExpression; // isCookieField performs a case-insensitive comparison of a provided string // against the word "cookie." This method (at least as of V8 5.4) is faster than @@ -63,7 +63,7 @@ var RE_TE_CHUNKED = common.chunkExpression; // inlined. function isCookieField(s) { if (s.length !== 6) return false; - var ch = s.charCodeAt(0); + let ch = s.charCodeAt(0); if (ch !== 99 && ch !== 67) return false; ch = s.charCodeAt(1); if (ch !== 111 && ch !== 79) return false; @@ -180,14 +180,14 @@ OutgoingMessage.prototype._renderHeaders = function _renderHeaders() { throw new ERR_HTTP_HEADERS_SENT('render'); } - var headersMap = this[outHeadersKey]; + const headersMap = this[outHeadersKey]; if (!headersMap) return {}; - var headers = {}; - var keys = Object.keys(headersMap); + const headers = {}; + const keys = Object.keys(headersMap); for (var i = 0, l = keys.length; i < l; i++) { - var key = keys[i]; + const key = keys[i]; headers[headersMap[key][0]] = headersMap[key][1]; } return headers; @@ -235,7 +235,7 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback) { (encoding === 'utf8' || encoding === 'latin1' || !encoding)) { data = this._header + data; } else { - var header = this._header; + const header = this._header; if (this.output.length === 0) { this.output = [header]; this.outputEncodings = ['latin1']; @@ -302,7 +302,7 @@ OutgoingMessage.prototype._storeHeader = _storeHeader; function _storeHeader(firstLine, headers) { // firstLine in the case of request is: 'GET /index.html HTTP/1.1\r\n' // in the case of response it is: 'HTTP/1.1 200 OK\r\n' - var state = { + const state = { connection: false, connUpgrade: false, contLen: false, @@ -314,14 +314,14 @@ function _storeHeader(firstLine, headers) { header: firstLine }; - var field; - var key; - var value; - var i; - var j; + let field; + let key; + let value; + let i; + let j; if (headers === this[outHeadersKey]) { for (key in headers) { - var entry = headers[key]; + const entry = headers[key]; field = entry[0]; value = entry[1]; @@ -349,7 +349,7 @@ function _storeHeader(firstLine, headers) { } } } else if (headers) { - var keys = Object.keys(headers); + const keys = Object.keys(headers); for (i = 0; i < keys.length; i++) { field = keys[i]; value = headers[field]; @@ -386,7 +386,7 @@ function _storeHeader(firstLine, headers) { // It was pointed out that this might confuse reverse proxies to the point // of creating security liabilities, so suppress the zero chunk and force // the connection to close. - var statusCode = this.statusCode; + const statusCode = this.statusCode; if ((statusCode === 204 || statusCode === 304) && this.chunkedEncoding) { debug(statusCode + ' response should not use chunked encoding,' + ' closing connection.'); @@ -399,7 +399,7 @@ function _storeHeader(firstLine, headers) { this._last = true; this.shouldKeepAlive = false; } else if (!state.connection) { - var shouldSendKeepAlive = this.shouldKeepAlive && + const shouldSendKeepAlive = this.shouldKeepAlive && (state.contLen || this.useChunkedEncodingByDefault || this.agent); if (shouldSendKeepAlive) { state.header += 'Connection: keep-alive\r\n'; @@ -455,8 +455,8 @@ function storeHeader(self, state, key, value, validate) { } function matchConnValue(self, state, value) { - var sawClose = false; - var m = RE_CONN_VALUES.exec(value); + let sawClose = false; + let m = RE_CONN_VALUES.exec(value); while (m) { if (m[0].length === 5) sawClose = true; @@ -471,10 +471,10 @@ function matchConnValue(self, state, value) { } function matchHeader(self, state, field, value) { - var m = RE_FIELDS.exec(field); + const m = RE_FIELDS.exec(field); if (!m) return; - var len = m[0].length; + const len = m[0].length; if (len === 10) { state.connection = true; matchConnValue(self, state, value); @@ -488,7 +488,7 @@ function matchHeader(self, state, field, value) { } else if (len === 6) { state.expect = true; } else if (len === 7) { - var ch = m[0].charCodeAt(0); + const ch = m[0].charCodeAt(0); if (ch === 85 || ch === 117) state.upgrade = true; else @@ -545,7 +545,7 @@ OutgoingMessage.prototype.getHeader = function getHeader(name) { if (!this[outHeadersKey]) return; - var entry = this[outHeadersKey][name.toLowerCase()]; + const entry = this[outHeadersKey][name.toLowerCase()]; if (!entry) return; return entry[1]; @@ -592,7 +592,7 @@ OutgoingMessage.prototype.removeHeader = function removeHeader(name) { throw new ERR_HTTP_HEADERS_SENT('remove'); } - var key = name.toLowerCase(); + const key = name.toLowerCase(); switch (key) { case 'connection': @@ -670,7 +670,7 @@ function write_(msg, chunk, encoding, callback, fromEnd) { process.nextTick(connectionCorkNT, msg, msg.connection); } - var len, ret; + let len, ret; if (msg.chunkedEncoding) { if (typeof chunk === 'string') len = Buffer.byteLength(chunk, encoding); @@ -711,11 +711,11 @@ function escapeHeaderValue(value) { OutgoingMessage.prototype.addTrailers = function addTrailers(headers) { this._trailer = ''; - var keys = Object.keys(headers); - var isArray = Array.isArray(headers); - var field, value; + const keys = Object.keys(headers); + const isArray = Array.isArray(headers); + let field, value; for (var i = 0, l = keys.length; i < l; i++) { - var key = keys[i]; + const key = keys[i]; if (isArray) { field = headers[key][0]; value = headers[key][1]; @@ -751,7 +751,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { return this; } - var uncork; + let uncork; if (chunk) { if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) { throw new ERR_INVALID_ARG_TYPE('first argument', ['string', 'Buffer']); @@ -775,7 +775,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { if (typeof callback === 'function') this.once('finish', callback); - var finish = onFinish.bind(undefined, this); + const finish = onFinish.bind(undefined, this); if (this._hasBody && this.chunkedEncoding) { this._send('0\r\n' + this._trailer + '\r\n', 'latin1', finish); @@ -828,8 +828,8 @@ OutgoingMessage.prototype._finish = function _finish() { // This function, outgoingFlush(), is called by both the Server and Client // to attempt to flush any pending messages out to the socket. OutgoingMessage.prototype._flush = function _flush() { - var socket = this.socket; - var ret; + const socket = this.socket; + let ret; if (socket && socket.writable) { // There might be remaining data in this.output; write it out @@ -846,14 +846,14 @@ OutgoingMessage.prototype._flush = function _flush() { }; OutgoingMessage.prototype._flushOutput = function _flushOutput(socket) { - var ret; - var outputLength = this.output.length; + let ret; + const outputLength = this.output.length; if (outputLength <= 0) return ret; - var output = this.output; - var outputEncodings = this.outputEncodings; - var outputCallbacks = this.outputCallbacks; + const output = this.output; + const outputEncodings = this.outputEncodings; + const outputCallbacks = this.outputCallbacks; socket.cork(); for (var i = 0; i < outputLength; i++) { ret = socket.write(output[i], outputEncodings[i], outputCallbacks[i]); diff --git a/lib/_http_server.js b/lib/_http_server.js index 498800dd1ee445..d92e86c7a0d3df 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -201,7 +201,7 @@ ServerResponse.prototype._implicitHeader = function _implicitHeader() { ServerResponse.prototype.writeHead = writeHead; function writeHead(statusCode, reason, obj) { - var originalStatusCode = statusCode; + const originalStatusCode = statusCode; statusCode |= 0; if (statusCode < 100 || statusCode > 999) { @@ -220,12 +220,12 @@ function writeHead(statusCode, reason, obj) { } this.statusCode = statusCode; - var headers; + let headers; if (this[outHeadersKey]) { // Slow-case: when progressive API and header fields are passed. - var k; + let k; if (obj) { - var keys = Object.keys(obj); + const keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { k = keys[i]; if (k) this.setHeader(k, obj[k]); @@ -244,7 +244,7 @@ function writeHead(statusCode, reason, obj) { if (checkInvalidHeaderChar(this.statusMessage)) throw new ERR_INVALID_CHAR('statusMessage'); - var statusLine = `HTTP/1.1 ${statusCode} ${this.statusMessage}${CRLF}`; + const statusLine = `HTTP/1.1 ${statusCode} ${this.statusMessage}${CRLF}`; if (statusCode === 204 || statusCode === 304 || (statusCode >= 100 && statusCode <= 199)) { @@ -338,7 +338,7 @@ function connectionListenerInternal(server, socket) { socket.setTimeout(server.timeout); socket.on('timeout', socketOnTimeout); - var parser = parsers.alloc(); + const parser = parsers.alloc(); parser.reinitialize(HTTPParser.REQUEST); parser.socket = socket; socket.parser = parser; @@ -352,7 +352,7 @@ function connectionListenerInternal(server, socket) { parser.maxHeaderPairs = 2000; } - var state = { + const state = { onData: null, onEnd: null, onClose: null, @@ -386,7 +386,7 @@ function connectionListenerInternal(server, socket) { // We only consume the socket if it has never been consumed before. if (socket._handle) { - var external = socket._handle._externalStream; + const external = socket._handle._externalStream; if (!socket._handle._consumed && external) { parser._consumed = true; socket._handle._consumed = true; @@ -409,7 +409,7 @@ function updateOutgoingData(socket, state, delta) { } function socketOnDrain(socket, state) { - var needPause = state.outgoingData > socket.writableHighWaterMark; + const needPause = state.outgoingData > socket.writableHighWaterMark; // If we previously paused, then start reading again. if (socket._paused && !needPause) { @@ -421,11 +421,11 @@ function socketOnDrain(socket, state) { } function socketOnTimeout() { - var req = this.parser && this.parser.incoming; - var reqTimeout = req && !req.complete && req.emit('timeout', this); - var res = this._httpMessage; - var resTimeout = res && res.emit('timeout', this); - var serverTimeout = this.server.emit('timeout', this); + const req = this.parser && this.parser.incoming; + const reqTimeout = req && !req.complete && req.emit('timeout', this); + const res = this._httpMessage; + const resTimeout = res && res.emit('timeout', this); + const serverTimeout = this.server.emit('timeout', this); if (!reqTimeout && !resTimeout && !serverTimeout) this.destroy(); @@ -443,7 +443,7 @@ function socketOnClose(socket, state) { function abortIncoming(incoming) { while (incoming.length) { - var req = incoming.shift(); + const req = incoming.shift(); req.emit('aborted'); req.emit('close'); } @@ -451,7 +451,7 @@ function abortIncoming(incoming) { } function socketOnEnd(server, socket, parser, state) { - var ret = parser.finish(); + const ret = parser.finish(); if (ret instanceof Error) { debug('parse error'); @@ -475,7 +475,7 @@ function socketOnData(server, socket, parser, state, d) { assert(!socket._paused); debug('SERVER socketOnData %d', d.length); - var ret = parser.execute(d); + const ret = parser.execute(d); onParserExecuteCommon(server, socket, parser, state, ret, d); } @@ -511,8 +511,8 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) { socketOnError.call(socket, ret); } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT - var bytesParsed = ret; - var req = parser.incoming; + const bytesParsed = ret; + const req = parser.incoming; debug('SERVER upgrade or connect', req.method); if (!d) @@ -529,10 +529,10 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) { freeParser(parser, req, null); parser = null; - var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; + const eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; if (server.listenerCount(eventName) > 0) { debug('SERVER have listener for %s', eventName); - var bodyHead = d.slice(bytesParsed, d.length); + const bodyHead = d.slice(bytesParsed, d.length); socket.readableFlowing = null; server.emit(eventName, req, socket, bodyHead); @@ -579,7 +579,7 @@ function resOnFinish(req, res, socket, state, server) { } } else { // start sending the next message - var m = state.outgoing.shift(); + const m = state.outgoing.shift(); if (m) { m.assignSocket(socket); } @@ -598,7 +598,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) { // so that we don't become overwhelmed by a flood of // pipelined requests that may never be resolved. if (!socket._paused) { - var ws = socket._writableState; + const ws = socket._writableState; if (ws.needDrain || state.outgoingData >= socket.writableHighWaterMark) { socket._paused = true; // We also need to pause the parser, but don't do that until after @@ -608,7 +608,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) { } } - var res = new server[kServerResponse](req); + const res = new server[kServerResponse](req); res._onPendingData = updateOutgoingData.bind(undefined, socket, state); res.shouldKeepAlive = keepAlive; @@ -694,7 +694,7 @@ function unconsume(parser, socket) { } function socketOnWrap(ev, fn) { - var res = net.Socket.prototype.on.call(this, ev, fn); + const res = net.Socket.prototype.on.call(this, ev, fn); if (!this.parser) { this.on = net.Socket.prototype.on; return res; diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 9d475ab6eaa673..bb71d18a800217 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -40,7 +40,7 @@ const { } = require('internal/errors').codes; const ReadableAsyncIterator = require('internal/streams/async_iterator'); const { emitExperimentalWarning } = require('internal/util'); -var StringDecoder; +let StringDecoder; util.inherits(Readable, Stream); @@ -72,7 +72,7 @@ function ReadableState(options, stream) { // However, some cases require setting options to different // values for the readable and the writable sides of the duplex stream. // These options can be provided separately as readableXXX and writableXXX. - var isDuplex = stream instanceof Stream.Duplex; + const isDuplex = stream instanceof Stream.Duplex; // object stream flag. Used to make read(n) ignore n and to // make all the buffer merging and length checks go away @@ -193,8 +193,8 @@ Readable.prototype._destroy = function(err, cb) { // similar to how Writable.write() returns true if you should // write() some more. Readable.prototype.push = function(chunk, encoding) { - var state = this._readableState; - var skipChunkCheck; + const state = this._readableState; + let skipChunkCheck; if (!state.objectMode) { if (typeof chunk === 'string') { @@ -218,12 +218,12 @@ Readable.prototype.unshift = function(chunk) { }; function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { - var state = stream._readableState; + const state = stream._readableState; if (chunk === null) { state.reading = false; onEofChunk(stream, state); } else { - var er; + let er; if (!skipChunkCheck) er = chunkInvalid(state, chunk); if (er) { @@ -284,7 +284,7 @@ function addChunk(stream, state, chunk, addToFront) { } function chunkInvalid(state, chunk) { - var er; + let er; if (!Stream._isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && @@ -372,8 +372,8 @@ function howMuchToRead(n, state) { Readable.prototype.read = function(n) { debug('read', n); n = parseInt(n, 10); - var state = this._readableState; - var nOrig = n; + const state = this._readableState; + const nOrig = n; if (n !== 0) state.emittedReadable = false; @@ -424,7 +424,7 @@ Readable.prototype.read = function(n) { // 3. Actually pull the requested chunks out of the buffer and return. // if we need a readable event, then we need to do some reading. - var doRead = state.needReadable; + let doRead = state.needReadable; debug('need readable', doRead); // if we currently have less than the highWaterMark, then also read some @@ -454,7 +454,7 @@ Readable.prototype.read = function(n) { n = howMuchToRead(nOrig, state); } - var ret; + let ret; if (n > 0) ret = fromList(n, state); else @@ -488,7 +488,7 @@ Readable.prototype.read = function(n) { function onEofChunk(stream, state) { if (state.ended) return; if (state.decoder) { - var chunk = state.decoder.end(); + const chunk = state.decoder.end(); if (chunk && chunk.length) { state.buffer.push(chunk); state.length += state.objectMode ? 1 : chunk.length; @@ -515,7 +515,7 @@ function onEofChunk(stream, state) { // another read() call => stack overflow. This way, it might trigger // a nextTick recursion warning, but that's not so bad. function emitReadable(stream) { - var state = stream._readableState; + const state = stream._readableState; state.needReadable = false; if (!state.emittedReadable) { debug('emitReadable', state.flowing); @@ -525,7 +525,7 @@ function emitReadable(stream) { } function emitReadable_(stream) { - var state = stream._readableState; + const state = stream._readableState; debug('emit readable'); if (!state.destroyed && (state.length || state.ended)) { stream.emit('readable'); @@ -549,7 +549,7 @@ function maybeReadMore(stream, state) { } function maybeReadMore_(stream, state) { - var len = state.length; + let len = state.length; while (!state.reading && !state.ended && state.length < state.highWaterMark) { debug('maybeReadMore read 0'); @@ -572,8 +572,8 @@ Readable.prototype._read = function(n) { }; Readable.prototype.pipe = function(dest, pipeOpts) { - var src = this; - var state = this._readableState; + const src = this; + const state = this._readableState; switch (state.pipesCount) { case 0: @@ -589,11 +589,11 @@ Readable.prototype.pipe = function(dest, pipeOpts) { state.pipesCount += 1; debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); - var doEnd = (!pipeOpts || pipeOpts.end !== false) && + const doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; - var endFn = doEnd ? onend : unpipe; + const endFn = doEnd ? onend : unpipe; if (state.endEmitted) process.nextTick(endFn); else @@ -619,10 +619,10 @@ Readable.prototype.pipe = function(dest, pipeOpts) { // on the source. This would be more elegant with a .once() // handler in flow(), but adding and removing repeatedly is // too slow. - var ondrain = pipeOnDrain(src); + const ondrain = pipeOnDrain(src); dest.on('drain', ondrain); - var cleanedUp = false; + let cleanedUp = false; function cleanup() { debug('cleanup'); // cleanup event handlers once the pipe is broken @@ -650,7 +650,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { src.on('data', ondata); function ondata(chunk) { debug('ondata'); - var ret = dest.write(chunk); + const ret = dest.write(chunk); debug('dest.write', ret); if (ret === false) { // If the user unpiped during `dest.write()`, it is possible @@ -712,7 +712,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { function pipeOnDrain(src) { return function() { - var state = src._readableState; + const state = src._readableState; debug('pipeOnDrain', state.awaitDrain); if (state.awaitDrain) state.awaitDrain--; @@ -725,8 +725,8 @@ function pipeOnDrain(src) { Readable.prototype.unpipe = function(dest) { - var state = this._readableState; - var unpipeInfo = { hasUnpiped: false }; + const state = this._readableState; + const unpipeInfo = { hasUnpiped: false }; // if we're not piping anywhere, then do nothing. if (state.pipesCount === 0) @@ -754,8 +754,8 @@ Readable.prototype.unpipe = function(dest) { if (!dest) { // remove all. - var dests = state.pipes; - var len = state.pipesCount; + const dests = state.pipes; + const len = state.pipesCount; state.pipes = null; state.pipesCount = 0; state.flowing = false; @@ -766,7 +766,7 @@ Readable.prototype.unpipe = function(dest) { } // try to find the right one. - var index = state.pipes.indexOf(dest); + const index = state.pipes.indexOf(dest); if (index === -1) return this; @@ -814,7 +814,7 @@ function nReadingNextTick(self) { // pause() and resume() are remnants of the legacy readable stream API // If the user uses them, then switch into old mode. Readable.prototype.resume = function() { - var state = this._readableState; + const state = this._readableState; if (!state.flowing) { debug('resume'); state.flowing = true; @@ -863,13 +863,13 @@ function flow(stream) { // This is *not* part of the readable stream interface. // It is an ugly unfortunate mess of history. Readable.prototype.wrap = function(stream) { - var state = this._readableState; - var paused = false; + const state = this._readableState; + let paused = false; stream.on('end', () => { debug('wrapped end'); if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); + const chunk = state.decoder.end(); if (chunk && chunk.length) this.push(chunk); } @@ -888,7 +888,7 @@ Readable.prototype.wrap = function(stream) { else if (!state.objectMode && (!chunk || !chunk.length)) return; - var ret = this.push(chunk); + const ret = this.push(chunk); if (!ret) { paused = true; stream.pause(); @@ -897,7 +897,7 @@ Readable.prototype.wrap = function(stream) { // proxy all the other methods. // important when wrapping filters and duplexes. - for (var i in stream) { + for (const i in stream) { if (this[i] === undefined && typeof stream[i] === 'function') { this[i] = function(method) { return function() { @@ -988,7 +988,7 @@ function fromList(n, state) { if (state.length === 0) return null; - var ret; + let ret; if (state.objectMode) ret = state.buffer.shift(); else if (!n || n >= state.length) { @@ -1009,7 +1009,7 @@ function fromList(n, state) { } function endReadable(stream) { - var state = stream._readableState; + const state = stream._readableState; debug('endReadable', state.endEmitted); if (!state.endEmitted) { diff --git a/lib/_stream_transform.js b/lib/_stream_transform.js index 679f79b80dfb35..e84fcc9cdea890 100644 --- a/lib/_stream_transform.js +++ b/lib/_stream_transform.js @@ -76,10 +76,10 @@ util.inherits(Transform, Duplex); function afterTransform(er, data) { - var ts = this._transformState; + const ts = this._transformState; ts.transforming = false; - var cb = ts.writecb; + const cb = ts.writecb; if (cb === null) { return this.emit('error', new ERR_MULTIPLE_CALLBACK()); @@ -93,7 +93,7 @@ function afterTransform(er, data) { cb(er); - var rs = this._readableState; + const rs = this._readableState; rs.reading = false; if (rs.needReadable || rs.length < rs.highWaterMark) { this._read(rs.highWaterMark); @@ -166,12 +166,12 @@ Transform.prototype._transform = function(chunk, encoding, cb) { }; Transform.prototype._write = function(chunk, encoding, cb) { - var ts = this._transformState; + const ts = this._transformState; ts.writecb = cb; ts.writechunk = chunk; ts.writeencoding = encoding; if (!ts.transforming) { - var rs = this._readableState; + const rs = this._readableState; if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) @@ -183,7 +183,7 @@ Transform.prototype._write = function(chunk, encoding, cb) { // _transform does all the work. // That we got here means that the readable side wants more data. Transform.prototype._read = function(n) { - var ts = this._transformState; + const ts = this._transformState; if (ts.writechunk !== null && !ts.transforming) { ts.transforming = true; diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 5f9bf79ae41a26..122719ee741b98 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -56,7 +56,7 @@ function WritableState(options, stream) { // However, some cases require setting options to different // values for the readable and the writable sides of the duplex stream. // These options can be provided separately as readableXXX and writableXXX. - var isDuplex = stream instanceof Stream.Duplex; + const isDuplex = stream instanceof Stream.Duplex; // object stream flag to indicate whether or not this stream // contains buffers or objects. @@ -89,7 +89,7 @@ function WritableState(options, stream) { // should we decode strings into buffers before passing to _write? // this is here so that some node-core streams can optimize string // handling at a lower level. - var noDecode = options.decodeStrings === false; + const noDecode = options.decodeStrings === false; this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string @@ -150,14 +150,14 @@ function WritableState(options, stream) { // allocate the first CorkedRequest, there is always // one allocated and free to use, and we maintain at most two - var corkReq = { next: null, entry: null, finish: undefined }; + const corkReq = { next: null, entry: null, finish: undefined }; corkReq.finish = onCorkedFinish.bind(undefined, corkReq, this); this.corkedRequestsFree = corkReq; } WritableState.prototype.getBuffer = function getBuffer() { - var current = this.bufferedRequest; - var out = []; + let current = this.bufferedRequest; + const out = []; while (current) { out.push(current); current = current.next; @@ -174,7 +174,7 @@ Object.defineProperty(WritableState.prototype, 'buffer', { // Test _writableState for inheritance to account for Duplex streams, // whose prototype chain only points to Readable. -var realHasInstance; +let realHasInstance; if (typeof Symbol === 'function' && Symbol.hasInstance) { realHasInstance = Function.prototype[Symbol.hasInstance]; Object.defineProperty(Writable, Symbol.hasInstance, { @@ -235,7 +235,7 @@ Writable.prototype.pipe = function() { function writeAfterEnd(stream, cb) { - var er = new ERR_STREAM_WRITE_AFTER_END(); + const er = new ERR_STREAM_WRITE_AFTER_END(); // TODO: defer error events consistently everywhere, not just the cb stream.emit('error', er); process.nextTick(cb, er); @@ -245,8 +245,8 @@ function writeAfterEnd(stream, cb) { // mode the stream is in. Currently this means that `null` is never accepted // and undefined/non-string values are only allowed in object mode. function validChunk(stream, state, chunk, cb) { - var valid = true; - var er = false; + let valid = true; + let er = false; if (chunk === null) { er = new ERR_STREAM_NULL_VALUES(); @@ -262,9 +262,9 @@ function validChunk(stream, state, chunk, cb) { } Writable.prototype.write = function(chunk, encoding, cb) { - var state = this._writableState; - var ret = false; - var isBuf = !state.objectMode && Stream._isUint8Array(chunk); + const state = this._writableState; + let ret = false; + const isBuf = !state.objectMode && Stream._isUint8Array(chunk); if (isBuf && Object.getPrototypeOf(chunk) !== Buffer.prototype) { chunk = Stream._uint8ArrayToBuffer(chunk); @@ -294,13 +294,13 @@ Writable.prototype.write = function(chunk, encoding, cb) { }; Writable.prototype.cork = function() { - var state = this._writableState; + const state = this._writableState; state.corked++; }; Writable.prototype.uncork = function() { - var state = this._writableState; + const state = this._writableState; if (state.corked) { state.corked--; @@ -357,24 +357,24 @@ Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { // If we return false, then we need a drain event, so set that flag. function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { if (!isBuf) { - var newChunk = decodeChunk(state, chunk, encoding); + const newChunk = decodeChunk(state, chunk, encoding); if (chunk !== newChunk) { isBuf = true; encoding = 'buffer'; chunk = newChunk; } } - var len = state.objectMode ? 1 : chunk.length; + const len = state.objectMode ? 1 : chunk.length; state.length += len; - var ret = state.length < state.highWaterMark; + const ret = state.length < state.highWaterMark; // we must ensure that previous needDrain will not be reset to false. if (!ret) state.needDrain = true; if (state.writing || state.corked) { - var last = state.lastBufferedRequest; + const last = state.lastBufferedRequest; state.lastBufferedRequest = { chunk, encoding, @@ -441,9 +441,9 @@ function onwriteStateUpdate(state) { } function onwrite(stream, er) { - var state = stream._writableState; - var sync = state.sync; - var cb = state.writecb; + const state = stream._writableState; + const sync = state.sync; + const cb = state.writecb; onwriteStateUpdate(state); @@ -451,7 +451,7 @@ function onwrite(stream, er) { onwriteError(stream, state, sync, er, cb); else { // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(state); + const finished = needFinish(state); if (!finished && !state.corked && @@ -489,17 +489,17 @@ function onwriteDrain(stream, state) { // if there's something in the buffer waiting, then process it function clearBuffer(stream, state) { state.bufferProcessing = true; - var entry = state.bufferedRequest; + let entry = state.bufferedRequest; if (stream._writev && entry && entry.next) { // Fast case, write everything using _writev() - var l = state.bufferedRequestCount; - var buffer = new Array(l); - var holder = state.corkedRequestsFree; + const l = state.bufferedRequestCount; + const buffer = new Array(l); + const holder = state.corkedRequestsFree; holder.entry = entry; - var count = 0; - var allBuffers = true; + let count = 0; + let allBuffers = true; while (entry) { buffer[count] = entry; if (!entry.isBuf) @@ -519,7 +519,7 @@ function clearBuffer(stream, state) { state.corkedRequestsFree = holder.next; holder.next = null; } else { - var corkReq = { next: null, entry: null, finish: undefined }; + const corkReq = { next: null, entry: null, finish: undefined }; corkReq.finish = onCorkedFinish.bind(undefined, corkReq, state); state.corkedRequestsFree = corkReq; } @@ -527,10 +527,10 @@ function clearBuffer(stream, state) { } else { // Slow case, write chunks one-by-one while (entry) { - var chunk = entry.chunk; - var encoding = entry.encoding; - var cb = entry.callback; - var len = state.objectMode ? 1 : chunk.length; + const chunk = entry.chunk; + const encoding = entry.encoding; + const cb = entry.callback; + const len = state.objectMode ? 1 : chunk.length; doWrite(stream, state, false, len, chunk, encoding, cb); entry = entry.next; @@ -559,7 +559,7 @@ Writable.prototype._write = function(chunk, encoding, cb) { Writable.prototype._writev = null; Writable.prototype.end = function(chunk, encoding, cb) { - var state = this._writableState; + const state = this._writableState; if (typeof chunk === 'function') { cb = chunk; @@ -628,7 +628,7 @@ function prefinish(stream, state) { } function finishMaybe(stream, state) { - var need = needFinish(state); + const need = needFinish(state); if (need) { prefinish(stream, state); if (state.pendingcb === 0) { @@ -653,10 +653,10 @@ function endWritable(stream, state, cb) { } function onCorkedFinish(corkReq, state, err) { - var entry = corkReq.entry; + let entry = corkReq.entry; corkReq.entry = null; while (entry) { - var cb = entry.callback; + const cb = entry.callback; state.pendingcb--; cb(err); entry = entry.next; diff --git a/lib/_tls_common.js b/lib/_tls_common.js index f63acad8ad174e..531e528a91f767 100644 --- a/lib/_tls_common.js +++ b/lib/_tls_common.js @@ -32,7 +32,7 @@ const { const { SSL_OP_CIPHER_SERVER_PREFERENCE } = process.binding('constants').crypto; // Lazily loaded -var crypto = null; +let crypto = null; const binding = process.binding('crypto'); const NativeSecureContext = binding.SecureContext; @@ -81,19 +81,19 @@ ecdhCurveWarning.emitted = false; exports.createSecureContext = function createSecureContext(options, context) { if (!options) options = {}; - var secureOptions = options.secureOptions; + let secureOptions = options.secureOptions; if (options.honorCipherOrder) secureOptions |= SSL_OP_CIPHER_SERVER_PREFERENCE; - var c = new SecureContext(options.secureProtocol, secureOptions, context); - var i; - var val; + const c = new SecureContext(options.secureProtocol, secureOptions, context); + let i; + let val; if (context) return c; // NOTE: It's important to add CA before the cert to be able to load // cert's issuer in C++ code. - var ca = options.ca; + const ca = options.ca; if (ca) { if (Array.isArray(ca)) { for (i = 0; i < ca.length; ++i) { @@ -109,7 +109,7 @@ exports.createSecureContext = function createSecureContext(options, context) { c.context.addRootCerts(); } - var cert = options.cert; + const cert = options.cert; if (cert) { if (Array.isArray(cert)) { for (i = 0; i < cert.length; ++i) { @@ -127,8 +127,8 @@ exports.createSecureContext = function createSecureContext(options, context) { // `ssl_set_pkey` returns `0` when the key does not match the cert, but // `ssl_set_cert` returns `1` and nullifies the key in the SSL structure // which leads to the crash later on. - var key = options.key; - var passphrase = options.passphrase; + const key = options.key; + const passphrase = options.passphrase; if (key) { if (Array.isArray(key)) { for (i = 0; i < key.length; ++i) { @@ -235,7 +235,7 @@ exports.translatePeerCertificate = function translatePeerCertificate(c) { } if (c.subject != null) c.subject = parseCertString(c.subject); if (c.infoAccess != null) { - var info = c.infoAccess; + const info = c.infoAccess; c.infoAccess = Object.create(null); // XXX: More key validation? diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 8ac497902eb596..c04a18d29e5f15 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -108,7 +108,7 @@ function onhandshakedone() { function loadSession(hello) { const owner = this.owner; - var once = false; + let once = false; function onSession(err, session) { if (once) return owner.destroy(new ERR_MULTIPLE_CALLBACK()); @@ -221,7 +221,7 @@ function onnewsession(key, session) { if (!owner.server) return; - var once = false; + let once = false; const done = () => { if (once) return; @@ -279,7 +279,7 @@ function initRead(tls, wrapped) { // Socket already has some buffered data - emulate receiving it if (wrapped && wrapped.readableLength) { - var buf; + let buf; while ((buf = wrapped.read()) !== null) tls._handle.receive(buf); } @@ -313,7 +313,7 @@ function TLSSocket(socket, opts) { this[kRes] = null; // Wrap plain JS Stream into StreamWrap - var wrap; + let wrap; if ((socket instanceof net.Socket && socket._handle) || !socket) wrap = socket; else @@ -348,7 +348,7 @@ function TLSSocket(socket, opts) { util.inherits(TLSSocket, net.Socket); exports.TLSSocket = TLSSocket; -var proxiedMethods = [ +const proxiedMethods = [ 'ref', 'unref', 'open', 'bind', 'listen', 'connect', 'bind6', 'connect6', 'getsockname', 'getpeername', 'setNoDelay', 'setKeepAlive', 'setSimultaneousAccepts', 'setBlocking', @@ -402,12 +402,12 @@ TLSSocket.prototype.disableRenegotiation = function disableRenegotiation() { }; TLSSocket.prototype._wrapHandle = function(wrap) { - var handle; + let handle; if (wrap) handle = wrap._handle; - var options = this._tlsOptions; + const options = this._tlsOptions; if (!handle) { handle = options.pipe ? new Pipe(PipeConstants.SOCKET) : @@ -473,8 +473,8 @@ TLSSocket.prototype._destroySSL = function _destroySSL() { }; TLSSocket.prototype._init = function(socket, wrap) { - var options = this._tlsOptions; - var ssl = this._handle; + const options = this._tlsOptions; + const ssl = this._handle; this.server = options.server; @@ -609,7 +609,7 @@ TLSSocket.prototype._handleTimeout = function() { }; TLSSocket.prototype._emitTLSError = function(err) { - var e = this._tlsError(err); + const e = this._tlsError(err); if (e) this.emit('error', e); }; @@ -885,7 +885,7 @@ function Server(options, listener) { // Handle option defaults: this.setOptions(options); - var sharedCreds = tls.createSecureContext({ + const sharedCreds = tls.createSecureContext({ pfx: this.pfx, key: this.key, passphrase: this.passphrase, @@ -974,7 +974,7 @@ Server.prototype.setOptions = function(options) { if (options.dhparam) this.dhparam = options.dhparam; if (options.sessionTimeout) this.sessionTimeout = options.sessionTimeout; if (options.ticketKeys) this.ticketKeys = options.ticketKeys; - var secureOptions = options.secureOptions || 0; + const secureOptions = options.secureOptions || 0; if (options.honorCipherOrder !== undefined) this.honorCipherOrder = !!options.honorCipherOrder; else @@ -999,7 +999,7 @@ Server.prototype.addContext = function(servername, context) { throw new ERR_TLS_REQUIRED_SERVER_NAME(); } - var re = new RegExp('^' + + const re = new RegExp('^' + servername.replace(/([.^$+?\-\\[\]{}])/g, '\\$1') .replace(/\*/g, '[^.]*') + '$'); @@ -1036,9 +1036,9 @@ function SNICallback(servername, callback) { // // function normalizeConnectArgs(listArgs) { - var args = net._normalizeArgs(listArgs); - var options = args[0]; - var cb = args[1]; + const args = net._normalizeArgs(listArgs); + const options = args[0]; + const cb = args[1]; // If args[0] was options, then normalize dealt with it. // If args[0] is port, or args[0], args[1] is host, port, we need to @@ -1116,10 +1116,10 @@ function onConnectEnd() { exports.connect = function(...args /* [port,] [host,] [options,] [cb] */) { args = normalizeConnectArgs(args); - var options = args[0]; - var cb = args[1]; + let options = args[0]; + const cb = args[1]; - var defaults = { + const defaults = { rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED, ciphers: tls.DEFAULT_CIPHERS, checkServerIdentity: tls.checkServerIdentity, @@ -1139,7 +1139,7 @@ exports.connect = function(...args /* [port,] [host,] [options,] [cb] */) { const context = options.secureContext || tls.createSecureContext(options); - var socket = new TLSSocket(options.socket, { + const socket = new TLSSocket(options.socket, { pipe: !!options.path, secureContext: context, isServer: false, diff --git a/lib/assert.js b/lib/assert.js index 797252afc0e01e..fc6eb0285be8bc 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -36,7 +36,7 @@ const { openSync, closeSync, readSync } = require('fs'); const { parseExpressionAt } = require('internal/deps/acorn/dist/acorn'); const { inspect } = require('util'); const { EOL } = require('os'); -const { NativeModule } = require('internal/bootstrap/loaders'); +const { NativeModule } = require('internal/bootstrap_loaders'); // Escape control characters but not \n and \t to keep the line breaks and // indentation intact. @@ -120,12 +120,12 @@ assert.fail = fail; assert.AssertionError = AssertionError; function getBuffer(fd, assertLine) { - var lines = 0; + let lines = 0; // Prevent blocking the event loop by limiting the maximum amount of // data that may be read. - var maxReads = 64; // bytesPerRead * maxReads = 512 kb - var bytesRead = 0; - var startBuffer = 0; // Start reading from that char on + let maxReads = 64; // bytesPerRead * maxReads = 512 kb + let bytesRead = 0; + let startBuffer = 0; // Start reading from that char on const bytesPerRead = 8192; const buffers = []; do { @@ -168,7 +168,7 @@ function getErrMessage(call) { return; } - var fd; + let fd; try { fd = openSync(filename, 'r', 0o666); const buffers = getBuffer(fd, line); @@ -185,7 +185,7 @@ function getErrMessage(call) { // not user defined function names. const ok = name === 'ok' ? '.ok' : ''; const args = node.arguments; - var message = code + let message = code .slice(args[0].start, args[args.length - 1].end) .replace(escapeSequencesRegExp, escapeFn); message = 'The expression evaluated to a falsy value:' + @@ -207,7 +207,7 @@ function getErrMessage(call) { } function innerOk(args, fn) { - var [value, message] = args; + let [value, message] = args; if (!value) { let generatedMessage = false; diff --git a/lib/buffer.js b/lib/buffer.js index b369d27a1ed471..c8e17bd6e324cd 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -41,7 +41,7 @@ const { // that test/parallel/test-buffer-bindingobj-no-zerofill.js is written. let isAnyArrayBuffer; try { - const { internalBinding } = require('internal/bootstrap/loaders'); + const { internalBinding } = require('internal/bootstrap_loaders'); isAnyArrayBuffer = internalBinding('types').isAnyArrayBuffer; } catch (e) { isAnyArrayBuffer = require('util').types.isAnyArrayBuffer; @@ -103,7 +103,7 @@ const constants = Object.defineProperties({}, { }); Buffer.poolSize = 8 * 1024; -var poolSize, poolOffset, allocPool; +let poolSize, poolOffset, allocPool; setupBufferJS(Buffer.prototype, bindingObj); @@ -139,7 +139,7 @@ function alignPool() { } } -var bufferWarn = true; +let bufferWarn = true; const bufferWarning = 'The Buffer() and new Buffer() constructors are not ' + 'recommended for use due to security and usability ' + 'concerns. Please use the new Buffer.alloc(), ' + @@ -220,7 +220,7 @@ Buffer.from = function from(value, encodingOrOffset, length) { if (valueOf !== null && valueOf !== undefined && valueOf !== value) return Buffer.from(valueOf, encodingOrOffset, length); - var b = fromObject(value); + const b = fromObject(value); if (b) return b; @@ -308,7 +308,7 @@ function allocate(size) { if (size < (Buffer.poolSize >>> 1)) { if (size > (poolSize - poolOffset)) createPool(); - var b = new FastBuffer(allocPool, poolOffset, size); + const b = new FastBuffer(allocPool, poolOffset, size); poolOffset += size; alignPool(); return b; @@ -318,7 +318,7 @@ function allocate(size) { } function fromString(string, encoding) { - var length; + let length; if (typeof encoding !== 'string' || encoding.length === 0) { if (string.length === 0) return new FastBuffer(); @@ -337,7 +337,7 @@ function fromString(string, encoding) { if (length > (poolSize - poolOffset)) createPool(); - var b = new FastBuffer(allocPool, poolOffset, length); + const b = new FastBuffer(allocPool, poolOffset, length); const actual = b.write(string, encoding); if (actual !== length) { // byteLength() may overestimate. That's a rare case, though. @@ -435,7 +435,7 @@ Buffer.isEncoding = function isEncoding(encoding) { Buffer[kIsEncodingSymbol] = Buffer.isEncoding; Buffer.concat = function concat(list, length) { - var i; + let i; if (!Array.isArray(list)) { throw new ERR_INVALID_ARG_TYPE('list', ['Array', 'Buffer', 'Uint8Array']); } @@ -451,10 +451,10 @@ Buffer.concat = function concat(list, length) { length = length >>> 0; } - var buffer = Buffer.allocUnsafe(length); - var pos = 0; + const buffer = Buffer.allocUnsafe(length); + let pos = 0; for (i = 0; i < list.length; i++) { - var buf = list[i]; + const buf = list[i]; if (!isUint8Array(buf)) { throw new ERR_INVALID_ARG_TYPE('list', ['Array', 'Buffer', 'Uint8Array']); } @@ -657,8 +657,8 @@ Buffer.prototype.equals = function equals(b) { // Override how buffers are presented by util.inspect(). Buffer.prototype[customInspectSymbol] = function inspect() { - var str = ''; - var max = exports.INSPECT_MAX_BYTES; + let str = ''; + const max = exports.INSPECT_MAX_BYTES; str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim(); if (this.length > max) str += ' ... '; @@ -756,7 +756,7 @@ function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { } function slowIndexOf(buffer, val, byteOffset, encoding, dir) { - var loweredCase = false; + let loweredCase = false; for (;;) { switch (encoding) { case 'utf8': @@ -893,7 +893,7 @@ Buffer.prototype.write = function write(string, offset, length, encoding) { length = undefined; } - var remaining = this.length - offset; + const remaining = this.length - offset; if (length === undefined || length > remaining) length = remaining; diff --git a/lib/child_process.js b/lib/child_process.js index c18329554a46b9..2da76222467b8d 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -62,10 +62,10 @@ function stdioStringToArray(option) { exports.fork = function(modulePath /*, args, options*/) { // Get options and args arguments. - var execArgv; - var options = {}; - var args = []; - var pos = 1; + let execArgv; + const options = {}; + const args = []; + let pos = 1; if (pos < arguments.length && Array.isArray(arguments[pos])) { args = arguments[pos++]; } @@ -112,7 +112,7 @@ exports.fork = function(modulePath /*, args, options*/) { exports._forkChild = function(fd) { // set process.send() - var p = new Pipe(PipeConstants.IPC); + const p = new Pipe(PipeConstants.IPC); p.open(fd); p.unref(); const control = setupChannel(process, p); @@ -144,7 +144,7 @@ function normalizeExecArgs(command, options, callback) { exports.exec = function(command /*, options, callback*/) { - var opts = normalizeExecArgs.apply(null, arguments); + const opts = normalizeExecArgs.apply(null, arguments); return exports.execFile(opts.file, opts.options, opts.callback); @@ -173,9 +173,9 @@ Object.defineProperty(exports.exec, util.promisify.custom, { }); exports.execFile = function(file /*, args, options, callback*/) { - var args = []; - var callback; - var options = { + const args = []; + let callback; + const options = { encoding: 'utf8', timeout: 0, maxBuffer: 200 * 1024, @@ -186,7 +186,7 @@ exports.execFile = function(file /*, args, options, callback*/) { }; // Parse the optional positional parameters. - var pos = 1; + let pos = 1; if (pos < arguments.length && Array.isArray(arguments[pos])) { args = arguments[pos++]; } else if (pos < arguments.length && arguments[pos] == null) { @@ -215,7 +215,7 @@ exports.execFile = function(file /*, args, options, callback*/) { options.killSignal = sanitizeKillSignal(options.killSignal); - var child = spawn(file, args, { + const child = spawn(file, args, { cwd: options.cwd, env: options.env, gid: options.gid, @@ -225,9 +225,9 @@ exports.execFile = function(file /*, args, options, callback*/) { windowsVerbatimArguments: !!options.windowsVerbatimArguments }); - var encoding; - var _stdout; - var _stderr; + let encoding; + let _stdout; + let _stderr; if (options.encoding !== 'buffer' && Buffer.isEncoding(options.encoding)) { encoding = options.encoding; _stdout = ''; @@ -237,15 +237,15 @@ exports.execFile = function(file /*, args, options, callback*/) { _stderr = []; encoding = null; } - var stdoutLen = 0; - var stderrLen = 0; - var killed = false; - var exited = false; - var timeoutId; + let stdoutLen = 0; + let stderrLen = 0; + let killed = false; + let exited = false; + let timeoutId; - var ex = null; + let ex = null; - var cmd = file; + let cmd = file; function exithandler(code, signal) { if (exited) return; @@ -259,8 +259,8 @@ exports.execFile = function(file /*, args, options, callback*/) { if (!callback) return; // merge chunks - var stdout; - var stderr; + let stdout; + let stderr; if (encoding) { stdout = _stdout; stderr = _stderr; @@ -485,11 +485,11 @@ function normalizeSpawnArguments(file, args, options) { args.unshift(file); } - var env = options.env || process.env; - var envPairs = []; + const env = options.env || process.env; + const envPairs = []; // Prototype values are intentionally included. - for (var key in env) { + for (const key in env) { const value = env[key]; if (value !== undefined) { envPairs.push(`${key}=${value}`); @@ -507,10 +507,10 @@ function normalizeSpawnArguments(file, args, options) { } -var spawn = exports.spawn = function(/*file, args, options*/) { - var opts = normalizeSpawnArguments.apply(null, arguments); - var options = opts.options; - var child = new ChildProcess(); +const spawn = exports.spawn = function(/*file, args, options*/) { + const opts = normalizeSpawnArguments.apply(null, arguments); + const options = opts.options; + const child = new ChildProcess(); debug('spawn', opts.args, options); @@ -531,9 +531,9 @@ var spawn = exports.spawn = function(/*file, args, options*/) { }; function spawnSync(/*file, args, options*/) { - var opts = normalizeSpawnArguments.apply(null, arguments); + const opts = normalizeSpawnArguments.apply(null, arguments); - var options = opts.options; + const options = opts.options; debug('spawnSync', opts.args, options); @@ -553,15 +553,15 @@ function spawnSync(/*file, args, options*/) { options.stdio = _validateStdio(options.stdio || 'pipe', true).stdio; if (options.input) { - var stdin = options.stdio[0] = util._extend({}, options.stdio[0]); + const stdin = options.stdio[0] = util._extend({}, options.stdio[0]); stdin.input = options.input; } // We may want to pass data in on any given fd, ensure it is a valid buffer for (var i = 0; i < options.stdio.length; i++) { - var input = options.stdio[i] && options.stdio[i].input; + const input = options.stdio[i] && options.stdio[i].input; if (input != null) { - var pipe = options.stdio[i] = util._extend({}, options.stdio[i]); + const pipe = options.stdio[i] = util._extend({}, options.stdio[i]); if (isUint8Array(input)) { pipe.input = input; } else if (typeof input === 'string') { @@ -580,11 +580,11 @@ exports.spawnSync = spawnSync; function checkExecSyncError(ret, args, cmd) { - var err; + let err; if (ret.error) { err = ret.error; } else if (ret.status !== 0) { - var msg = 'Command failed: '; + let msg = 'Command failed: '; msg += cmd || args.join(' '); if (ret.stderr && ret.stderr.length > 0) msg += `\n${ret.stderr.toString()}`; @@ -598,15 +598,15 @@ function checkExecSyncError(ret, args, cmd) { function execFileSync(/*command, args, options*/) { - var opts = normalizeSpawnArguments.apply(null, arguments); - var inheritStderr = !opts.options.stdio; + const opts = normalizeSpawnArguments.apply(null, arguments); + const inheritStderr = !opts.options.stdio; - var ret = spawnSync(opts.file, opts.args.slice(1), opts.options); + const ret = spawnSync(opts.file, opts.args.slice(1), opts.options); if (inheritStderr && ret.stderr) process.stderr.write(ret.stderr); - var err = checkExecSyncError(ret, opts.args, undefined); + const err = checkExecSyncError(ret, opts.args, undefined); if (err) throw err; @@ -617,15 +617,15 @@ exports.execFileSync = execFileSync; function execSync(command /*, options*/) { - var opts = normalizeExecArgs.apply(null, arguments); - var inheritStderr = !opts.options.stdio; + const opts = normalizeExecArgs.apply(null, arguments); + const inheritStderr = !opts.options.stdio; - var ret = spawnSync(opts.file, opts.options); + const ret = spawnSync(opts.file, opts.options); if (inheritStderr && ret.stderr) process.stderr.write(ret.stderr); - var err = checkExecSyncError(ret, opts.args, command); + const err = checkExecSyncError(ret, opts.args, command); if (err) throw err; diff --git a/lib/console.js b/lib/console.js index b77832b9876735..b01772f058fee6 100644 --- a/lib/console.js +++ b/lib/console.js @@ -43,7 +43,7 @@ function Console(stdout, stderr, ignoreErrors = true) { throw new ERR_CONSOLE_WRITABLE_STREAM('stderr'); } - var prop = { + const prop = { writable: true, enumerable: false, configurable: true @@ -67,9 +67,9 @@ function Console(stdout, stderr, ignoreErrors = true) { this[kGroupIndent] = ''; // bind the prototype functions to this Console instance - var keys = Object.keys(Console.prototype); + const keys = Object.keys(Console.prototype); for (var v = 0; v < keys.length; v++) { - var k = keys[v]; + const k = keys[v]; this[k] = this[k].bind(this); } } diff --git a/lib/dgram.js b/lib/dgram.js index b9caeddabe2374..c06d51d57e9f71 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -55,7 +55,7 @@ const RECV_BUFFER = true; const SEND_BUFFER = false; // Lazily loaded -var cluster = null; +let cluster = null; const errnoException = errors.errnoException; const exceptionWithHostPort = errors.exceptionWithHostPort; @@ -99,10 +99,10 @@ function _createSocketHandle(address, port, addressType, fd, flags) { // Opening an existing fd is not supported for UDP handles. assert(typeof fd !== 'number' || fd < 0); - var handle = newHandle(addressType); + const handle = newHandle(addressType); if (port || address) { - var err = handle.bind(address, port || 0, flags); + const err = handle.bind(address, port || 0, flags); if (err) { handle.close(); return err; @@ -116,18 +116,18 @@ const kOptionSymbol = Symbol('options symbol'); function Socket(type, listener) { EventEmitter.call(this); - var lookup; + let lookup; this[kOptionSymbol] = {}; if (type !== null && typeof type === 'object') { - var options = type; + const options = type; type = options.type; lookup = options.lookup; this[kOptionSymbol].recvBufferSize = options.recvBufferSize; this[kOptionSymbol].sendBufferSize = options.sendBufferSize; } - var handle = newHandle(type, lookup); + const handle = newHandle(type, lookup); handle.owner = this; this._handle = handle; @@ -212,8 +212,8 @@ Socket.prototype.bind = function(port_, address_ /*, callback*/) { return this; } - var address; - var exclusive; + let address; + let exclusive; if (port !== null && typeof port === 'object') { address = port.address || ''; @@ -243,14 +243,14 @@ Socket.prototype.bind = function(port_, address_ /*, callback*/) { if (!cluster) cluster = require('cluster'); - var flags = 0; + let flags = 0; if (this._reuseAddr) flags |= UV_UDP_REUSEADDR; if (cluster.isWorker && !exclusive) { const onHandle = (err, handle) => { if (err) { - var ex = exceptionWithHostPort(err, 'bind', ip, port); + const ex = exceptionWithHostPort(err, 'bind', ip, port); this.emit('error', ex); this._bindState = BIND_STATE_UNBOUND; return; @@ -276,7 +276,7 @@ Socket.prototype.bind = function(port_, address_ /*, callback*/) { const err = this._handle.bind(ip, port || 0, flags); if (err) { - var ex = exceptionWithHostPort(err, 'bind', ip, port); + const ex = exceptionWithHostPort(err, 'bind', ip, port); this.emit('error', ex); this._bindState = BIND_STATE_UNBOUND; // Todo: close? @@ -337,7 +337,7 @@ function fixBufferList(list) { const newlist = new Array(list.length); for (var i = 0, l = list.length; i < l; i++) { - var buf = list[i]; + const buf = list[i]; if (typeof buf === 'string') newlist[i] = Buffer.from(buf); else if (!isUint8Array(buf)) @@ -479,7 +479,7 @@ function doSend(ex, self, ip, list, address, port, callback) { return; } - var req = new SendWrap(); + const req = new SendWrap(); req.list = list; // Keep reference alive. req.address = address; req.port = port; @@ -488,7 +488,7 @@ function doSend(ex, self, ip, list, address, port, callback) { req.oncomplete = afterSend; } - var err = self._handle.send(req, + const err = self._handle.send(req, list, list.length, port, @@ -542,8 +542,8 @@ function socketCloseNT(self) { Socket.prototype.address = function() { this._healthCheck(); - var out = {}; - var err = this._handle.getsockname(out); + const out = {}; + const err = this._handle.getsockname(out); if (err) { throw errnoException(err, 'getsockname'); } @@ -553,7 +553,7 @@ Socket.prototype.address = function() { Socket.prototype.setBroadcast = function(arg) { - var err = this._handle.setBroadcast(arg ? 1 : 0); + const err = this._handle.setBroadcast(arg ? 1 : 0); if (err) { throw errnoException(err, 'setBroadcast'); } @@ -565,7 +565,7 @@ Socket.prototype.setTTL = function(ttl) { throw new ERR_INVALID_ARG_TYPE('ttl', 'number', ttl); } - var err = this._handle.setTTL(ttl); + const err = this._handle.setTTL(ttl); if (err) { throw errnoException(err, 'setTTL'); } @@ -579,7 +579,7 @@ Socket.prototype.setMulticastTTL = function(ttl) { throw new ERR_INVALID_ARG_TYPE('ttl', 'number', ttl); } - var err = this._handle.setMulticastTTL(ttl); + const err = this._handle.setMulticastTTL(ttl); if (err) { throw errnoException(err, 'setMulticastTTL'); } @@ -589,7 +589,7 @@ Socket.prototype.setMulticastTTL = function(ttl) { Socket.prototype.setMulticastLoopback = function(arg) { - var err = this._handle.setMulticastLoopback(arg ? 1 : 0); + const err = this._handle.setMulticastLoopback(arg ? 1 : 0); if (err) { throw errnoException(err, 'setMulticastLoopback'); } @@ -619,7 +619,7 @@ Socket.prototype.addMembership = function(multicastAddress, throw new ERR_MISSING_ARGS('multicastAddress'); } - var err = this._handle.addMembership(multicastAddress, interfaceAddress); + const err = this._handle.addMembership(multicastAddress, interfaceAddress); if (err) { throw errnoException(err, 'addMembership'); } @@ -634,7 +634,7 @@ Socket.prototype.dropMembership = function(multicastAddress, throw new ERR_MISSING_ARGS('multicastAddress'); } - var err = this._handle.dropMembership(multicastAddress, interfaceAddress); + const err = this._handle.dropMembership(multicastAddress, interfaceAddress); if (err) { throw errnoException(err, 'dropMembership'); } @@ -660,7 +660,7 @@ Socket.prototype._stopReceiving = function() { function onMessage(nread, handle, buf, rinfo) { - var self = handle.owner; + const self = handle.owner; if (nread < 0) { return self.emit('error', errnoException(nread, 'recvmsg')); } diff --git a/lib/dns.js b/lib/dns.js index cb8b2ca0beb4cd..ecb4206d66e92d 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -62,7 +62,7 @@ function onlookupall(err, addresses) { return this.callback(dnsException(err, 'getaddrinfo', this.hostname)); } - var family = this.family; + const family = this.family; for (var i = 0; i < addresses.length; i++) { const addr = addresses[i]; addresses[i] = { @@ -78,10 +78,10 @@ function onlookupall(err, addresses) { // Easy DNS A/AAAA look up // lookup(hostname, [options,] callback) function lookup(hostname, options, callback) { - var hints = 0; - var family = -1; - var all = false; - var verbatim = false; + let hints = 0; + let family = -1; + let all = false; + let verbatim = false; // Parse arguments if (hostname && typeof hostname !== 'string') { @@ -119,7 +119,7 @@ function lookup(hostname, options, callback) { return {}; } - var matchedFamily = isIP(hostname); + const matchedFamily = isIP(hostname); if (matchedFamily) { if (all) { process.nextTick( @@ -130,13 +130,13 @@ function lookup(hostname, options, callback) { return {}; } - var req = new GetAddrInfoReqWrap(); + const req = new GetAddrInfoReqWrap(); req.callback = callback; req.family = family; req.hostname = hostname; req.oncomplete = all ? onlookupall : onlookup; - var err = cares.getaddrinfo(req, hostname, family, hints, verbatim); + const err = cares.getaddrinfo(req, hostname, family, hints, verbatim); if (err) { process.nextTick(callback, dnsException(err, 'getaddrinfo', hostname)); return {}; @@ -172,13 +172,13 @@ function lookupService(host, port, callback) { port = +port; - var req = new GetNameInfoReqWrap(); + const req = new GetNameInfoReqWrap(); req.callback = callback; req.host = host; req.port = port; req.oncomplete = onlookupservice; - var err = cares.getnameinfo(req, host, port); + const err = cares.getnameinfo(req, host, port); if (err) throw dnsException(err, 'getnameinfo', host); return req; } @@ -210,7 +210,7 @@ class Resolver { function resolver(bindingName) { function query(name, /* options, */ callback) { - var options; + let options; if (arguments.length > 2) { options = callback; callback = arguments[2]; @@ -222,13 +222,13 @@ function resolver(bindingName) { throw new ERR_INVALID_CALLBACK(); } - var req = new QueryReqWrap(); + const req = new QueryReqWrap(); req.bindingName = bindingName; req.callback = callback; req.hostname = name; req.oncomplete = onresolve; req.ttl = !!(options && options.ttl); - var err = this._handle[bindingName](req, name); + const err = this._handle[bindingName](req, name); if (err) throw dnsException(err, bindingName); return req; } @@ -236,7 +236,7 @@ function resolver(bindingName) { return query; } -var resolveMap = Object.create(null); +const resolveMap = Object.create(null); Resolver.prototype.resolveAny = resolveMap.ANY = resolver('queryAny'); Resolver.prototype.resolve4 = resolveMap.A = resolver('queryA'); Resolver.prototype.resolve6 = resolveMap.AAAA = resolver('queryAaaa'); @@ -253,7 +253,7 @@ Resolver.prototype.reverse = resolver('getHostByAddr'); Resolver.prototype.resolve = resolve; function resolve(hostname, rrtype, callback) { - var resolver; + let resolver; if (typeof rrtype === 'string') { resolver = resolveMap[rrtype]; } else if (typeof rrtype === 'function') { @@ -293,7 +293,7 @@ function setServers(servers) { const addrSplitRE = /(^.+?)(?::(\d+))?$/; servers.forEach((serv) => { - var ipVersion = isIP(serv); + const ipVersion = isIP(serv); if (ipVersion !== 0) return newSet.push([ipVersion, serv, IANA_DNS_PORT]); @@ -325,7 +325,7 @@ function setServers(servers) { // reset the servers to the old servers, because ares probably unset them this._handle.setServers(orig.join(',')); - var err = cares.strerror(errorNumber); + const err = cares.strerror(errorNumber); throw new ERR_DNS_SET_SERVERS_FAILED(err, servers); } } diff --git a/lib/domain.js b/lib/domain.js index 170f29172788a4..64ddfc41db3552 100644 --- a/lib/domain.js +++ b/lib/domain.js @@ -34,11 +34,11 @@ const { ERR_UNHANDLED_ERROR } = require('internal/errors').codes; const { createHook } = require('async_hooks'); -const { internalBinding } = require('internal/bootstrap/loaders'); +const { internalBinding } = require('internal/bootstrap_loaders'); // overwrite process.domain with a getter/setter that will allow for more // effective optimizations -var _domain = [null]; +const _domain = [null]; Object.defineProperty(process, 'domain', { enumerable: true, get: function() { @@ -193,7 +193,7 @@ Domain.prototype.members = undefined; // Called by process._fatalException in case an error was thrown. Domain.prototype._errorHandler = function _errorHandler(er) { - var caught = false; + let caught = false; if (!util.isPrimitive(er)) { er.domain = this; @@ -276,7 +276,7 @@ Domain.prototype.enter = function() { Domain.prototype.exit = function() { // don't do anything if this domain is not on the stack. - var index = stack.lastIndexOf(this); + const index = stack.lastIndexOf(this); if (index === -1) return; // exit all domains until this one. @@ -320,19 +320,19 @@ Domain.prototype.add = function(ee) { Domain.prototype.remove = function(ee) { ee.domain = null; - var index = this.members.indexOf(ee); + const index = this.members.indexOf(ee); if (index !== -1) this.members.splice(index, 1); }; Domain.prototype.run = function(fn) { - var ret; + let ret; this.enter(); if (arguments.length >= 2) { - var len = arguments.length; - var args = new Array(len - 1); + const len = arguments.length; + const args = new Array(len - 1); for (var i = 1; i < len; i++) args[i - 1] = arguments[i]; @@ -349,7 +349,7 @@ Domain.prototype.run = function(fn) { function intercepted(_this, self, cb, fnargs) { if (fnargs[0] && fnargs[0] instanceof Error) { - var er = fnargs[0]; + const er = fnargs[0]; util._extend(er, { domainBound: cb, domainThrown: false, @@ -359,8 +359,8 @@ function intercepted(_this, self, cb, fnargs) { return; } - var args = []; - var i, ret; + const args = []; + let i, ret; self.enter(); if (fnargs.length > 1) { @@ -377,7 +377,7 @@ function intercepted(_this, self, cb, fnargs) { Domain.prototype.intercept = function(cb) { - var self = this; + const self = this; function runIntercepted() { return intercepted(this, self, cb, arguments); @@ -388,7 +388,7 @@ Domain.prototype.intercept = function(cb) { function bound(_this, self, cb, fnargs) { - var ret; + const ret; self.enter(); if (fnargs.length > 0) @@ -402,7 +402,7 @@ function bound(_this, self, cb, fnargs) { Domain.prototype.bind = function(cb) { - var self = this; + const self = this; function runBound() { return bound(this, self, cb, arguments); diff --git a/lib/events.js b/lib/events.js index 2a8cf60c91cb78..5d0adc336b43fa 100644 --- a/lib/events.js +++ b/lib/events.js @@ -21,7 +21,7 @@ 'use strict'; -var spliceOne; +let spliceOne; function EventEmitter() { EventEmitter.init.call(this); @@ -39,9 +39,9 @@ EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. -var defaultMaxListeners = 10; +const defaultMaxListeners = 10; -var errors; +let errors; function lazyErrors() { if (errors === undefined) errors = require('internal/errors').codes; @@ -191,9 +191,9 @@ EventEmitter.prototype.emit = function emit(type, ...args) { }; function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; + let m; + let events; + let existing; if (typeof listener !== 'function') { const errors = lazyErrors(); @@ -276,8 +276,8 @@ function onceWrapper(...args) { } function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target, type, listener }; - var wrapped = onceWrapper.bind(state); + const state = { fired: false, wrapFn: undefined, target, type, listener }; + const wrapped = onceWrapper.bind(state); wrapped.listener = listener; state.wrapFn = wrapped; return wrapped; @@ -305,7 +305,7 @@ EventEmitter.prototype.prependOnceListener = // Emits a 'removeListener' event if and only if the listener was removed. EventEmitter.prototype.removeListener = function removeListener(type, listener) { - var list, events, position, i, originalListener; + let list, events, position, i, originalListener; if (typeof listener !== 'function') { const errors = lazyErrors(); @@ -364,7 +364,7 @@ EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { - var listeners, events, i; + let listeners, events, i; events = this._events; if (events === undefined) @@ -386,8 +386,8 @@ EventEmitter.prototype.removeAllListeners = // emit removeListener for all listeners on all events if (arguments.length === 0) { - var keys = Object.keys(events); - var key; + const keys = Object.keys(events); + let key; for (i = 0; i < keys.length; ++i) { key = keys[i]; if (key === 'removeListener') continue; @@ -468,7 +468,7 @@ EventEmitter.prototype.eventNames = function eventNames() { }; function arrayClone(arr, n) { - var copy = new Array(n); + const copy = new Array(n); for (var i = 0; i < n; ++i) copy[i] = arr[i]; return copy; diff --git a/lib/fs.js b/lib/fs.js index f890e431d2a9f5..c3e2c18782685c 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -182,7 +182,7 @@ fs.access = function(path, mode, callback) { validatePath(path); mode = mode | 0; - var req = new FSReqWrap(); + const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); binding.access(pathModule.toNamespacedPath(path), mode, req); }; @@ -241,9 +241,9 @@ fs.existsSync = function(path) { fs.readFile = function(path, options, callback) { callback = maybeCallback(callback || options); options = getOptions(options, { flag: 'r' }); - var context = new ReadFileContext(callback, options.encoding); + const context = new ReadFileContext(callback, options.encoding); context.isUserFd = isFd(path); // file descriptor ownership - var req = new FSReqWrap(); + const req = new FSReqWrap(); req.context = context; req.oncomplete = readFileAfterOpen; @@ -277,9 +277,9 @@ function ReadFileContext(callback, encoding) { } ReadFileContext.prototype.read = function() { - var buffer; - var offset; - var length; + let buffer; + let offset; + let length; if (this.size === 0) { buffer = this.buffer = Buffer.allocUnsafeSlow(kReadFileBufferLength); @@ -291,7 +291,7 @@ ReadFileContext.prototype.read = function() { length = Math.min(kReadFileBufferLength, this.size - this.pos); } - var req = new FSReqWrap(); + const req = new FSReqWrap(); req.oncomplete = readFileAfterRead; req.context = this; @@ -299,7 +299,7 @@ ReadFileContext.prototype.read = function() { }; ReadFileContext.prototype.close = function(err) { - var req = new FSReqWrap(); + const req = new FSReqWrap(); req.oncomplete = readFileAfterClose; req.context = this; this.err = err; @@ -315,7 +315,7 @@ ReadFileContext.prototype.close = function(err) { }; function readFileAfterOpen(err, fd) { - var context = this.context; + const context = this.context; if (err) { context.callback(err); @@ -324,19 +324,19 @@ function readFileAfterOpen(err, fd) { context.fd = fd; - var req = new FSReqWrap(); + const req = new FSReqWrap(); req.oncomplete = readFileAfterStat; req.context = context; binding.fstat(fd, req); } function readFileAfterStat(err) { - var context = this.context; + const context = this.context; if (err) return context.close(err); - var size; + let size; if (isFileType(S_IFREG)) size = context.size = statValues[8]; else @@ -363,7 +363,7 @@ function readFileAfterStat(err) { } function readFileAfterRead(err, bytesRead) { - var context = this.context; + const context = this.context; if (err) return context.close(err); @@ -386,9 +386,9 @@ function readFileAfterRead(err, bytesRead) { } function readFileAfterClose(err) { - var context = this.context; - var buffer = null; - var callback = context.callback; + const context = this.context; + let buffer = null; + const callback = context.callback; if (context.err || err) return callback(context.err || err); @@ -420,8 +420,8 @@ function tryStatSync(fd, isUserFd) { } function tryCreateBuffer(size, fd, isUserFd) { - var threw = true; - var buffer; + let threw = true; + let buffer; try { buffer = Buffer.allocUnsafe(size); threw = false; @@ -432,8 +432,8 @@ function tryCreateBuffer(size, fd, isUserFd) { } function tryReadSync(fd, isUserFd, buffer, pos, len) { - var threw = true; - var bytesRead; + let threw = true; + let bytesRead; try { bytesRead = fs.readSync(fd, buffer, pos, len); threw = false; @@ -445,18 +445,18 @@ function tryReadSync(fd, isUserFd, buffer, pos, len) { fs.readFileSync = function(path, options) { options = getOptions(options, { flag: 'r' }); - var isUserFd = isFd(path); // file descriptor ownership - var fd = isUserFd ? path : fs.openSync(path, options.flag || 'r', 0o666); + const isUserFd = isFd(path); // file descriptor ownership + const fd = isUserFd ? path : fs.openSync(path, options.flag || 'r', 0o666); tryStatSync(fd, isUserFd); - var size; + let size; if (isFileType(S_IFREG)) size = statValues[8]; else size = 0; - var pos = 0; - var buffer; // single buffer with file data - var buffers; // list for when size is unknown + let pos = 0; + let buffer; // single buffer with file data + let buffers; // list for when size is unknown if (size === 0) { buffers = []; @@ -464,7 +464,7 @@ fs.readFileSync = function(path, options) { buffer = tryCreateBuffer(size, fd, isUserFd); } - var bytesRead; + let bytesRead; if (size !== 0) { do { @@ -514,7 +514,7 @@ fs.closeSync = function(fd) { }; fs.open = function(path, flags, mode, callback_) { - var callback = makeCallback(arguments[arguments.length - 1]); + const callback = makeCallback(arguments[arguments.length - 1]); mode = modeNum(mode, 0o666); path = getPathFromURL(path); @@ -713,7 +713,7 @@ fs.truncate = function(path, len, callback) { callback = maybeCallback(callback); fs.open(path, 'r+', function(er, fd) { if (er) return callback(er); - var req = new FSReqWrap(); + const req = new FSReqWrap(); req.oncomplete = function oncomplete(er) { fs.close(fd, function(er2) { callback(er || er2); @@ -733,8 +733,8 @@ fs.truncateSync = function(path, len) { len = 0; } // allow error to be thrown, but still close fd. - var fd = fs.openSync(path, 'r+'); - var ret; + const fd = fs.openSync(path, 'r+'); + let ret; try { ret = fs.ftruncateSync(fd, len); @@ -929,8 +929,8 @@ fs.readlinkSync = function(path, options) { }; fs.symlink = function(target, path, type_, callback_) { - var type = (typeof type_ === 'string' ? type_ : null); - var callback = makeCallback(arguments[arguments.length - 1]); + const type = (typeof type_ === 'string' ? type_ : null); + const callback = makeCallback(arguments[arguments.length - 1]); target = getPathFromURL(target); path = getPathFromURL(path); @@ -1250,9 +1250,9 @@ fs.writeFile = function(path, data, options, callback) { }); function writeFd(fd, isUserFd) { - var buffer = isUint8Array(data) ? + const buffer = isUint8Array(data) ? data : Buffer.from('' + data, options.encoding || 'utf8'); - var position = /a/.test(flag) ? null : 0; + const position = /a/.test(flag) ? null : 0; writeAll(fd, isUserFd, buffer, 0, buffer.length, position, callback); } @@ -1262,18 +1262,18 @@ fs.writeFileSync = function(path, data, options) { options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' }); const flag = options.flag || 'w'; - var isUserFd = isFd(path); // file descriptor ownership - var fd = isUserFd ? path : fs.openSync(path, flag, options.mode); + const isUserFd = isFd(path); // file descriptor ownership + const fd = isUserFd ? path : fs.openSync(path, flag, options.mode); if (!isUint8Array(data)) { data = Buffer.from('' + data, options.encoding || 'utf8'); } - var offset = 0; - var length = data.length; - var position = /a/.test(flag) ? null : 0; + let offset = 0; + let length = data.length; + let position = /a/.test(flag) ? null : 0; try { while (length > 0) { - var written = fs.writeSync(fd, data, offset, length, position); + const written = fs.writeSync(fd, data, offset, length, position); offset += written; length -= written; if (position !== null) { @@ -1315,7 +1315,7 @@ fs.appendFileSync = function(path, data, options) { function FSWatcher() { EventEmitter.call(this); - var self = this; + const self = this; this._handle = new FSEvent(); this._handle.owner = this; @@ -1357,7 +1357,7 @@ FSWatcher.prototype.start = function(filename, filename = getPathFromURL(filename); validatePath(filename, 'filename'); - var err = this._handle.start(pathModule.toNamespacedPath(filename), + const err = this._handle.start(pathModule.toNamespacedPath(filename), persistent, recursive, encoding); @@ -1424,12 +1424,12 @@ function statsFromPrevValues() { function StatWatcher() { EventEmitter.call(this); - var self = this; + const self = this; this._handle = new binding.StatWatcher(); // uv_fs_poll is a little more powerful than ev_stat but we curb it for // the sake of backwards compatibility - var oldStatus = -1; + let oldStatus = -1; this._handle.onchange = function(newStatus) { if (oldStatus === -1 && @@ -1471,9 +1471,9 @@ fs.watchFile = function(filename, options, listener) { filename = getPathFromURL(filename); validatePath(filename); filename = pathModule.resolve(filename); - var stat; + let stat; - var defaults = { + const defaults = { // Poll interval in milliseconds. 5007 is what libev used to use. It's // a little on the slow side but let's stick with it for now to keep // behavioral changes to a minimum. @@ -1508,7 +1508,7 @@ fs.unwatchFile = function(filename, listener) { filename = getPathFromURL(filename); validatePath(filename); filename = pathModule.resolve(filename); - var stat = statWatchers.get(filename); + const stat = statWatchers.get(filename); if (stat === undefined) return; @@ -1525,7 +1525,7 @@ fs.unwatchFile = function(filename, listener) { }; -var splitRoot; +let splitRoot; if (isWindows) { // Regex to find the device root on Windows (e.g. 'c:\\'), including trailing // slash. @@ -1555,7 +1555,7 @@ function encodeRealpathResult(result, options) { } // Finds the next portion of a (partial) path, up to the next path delimiter -var nextPart; +let nextPart; if (isWindows) { nextPart = function nextPart(p, i) { for (; i < p.length; ++i) { @@ -1595,13 +1595,13 @@ fs.realpathSync = function realpathSync(p, options) { const original = p; // current character position in p - var pos; + let pos; // the partial path so far, including a trailing slash if any - var current; + let current; // the partial path without a trailing slash (except when pointing at a root) - var base; + let base; // the partial path scanned in the previous round, with slash - var previous; + let previous; // Skip over roots current = base = splitRoot(p); @@ -1620,10 +1620,10 @@ fs.realpathSync = function realpathSync(p, options) { // NB: p.length changes. while (pos < p.length) { // find the next part - var result = nextPart(p, pos); + const result = nextPart(p, pos); previous = current; if (result === -1) { - var last = p.slice(pos); + const last = p.slice(pos); current += last; base = previous + last; pos = p.length; @@ -1641,15 +1641,15 @@ fs.realpathSync = function realpathSync(p, options) { continue; } - var resolvedLink; - var maybeCachedResolved = cache && cache.get(base); + let resolvedLink; + const maybeCachedResolved = cache && cache.get(base); if (maybeCachedResolved) { resolvedLink = maybeCachedResolved; } else { // Use stats array directly to avoid creating an fs.Stats instance just // for our internal use. - var baseLong = pathModule.toNamespacedPath(base); + const baseLong = pathModule.toNamespacedPath(base); const ctx = { path: base }; binding.lstat(baseLong, undefined, ctx); handleErrorFromBinding(ctx); @@ -1662,11 +1662,11 @@ fs.realpathSync = function realpathSync(p, options) { // read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. - var linkTarget = null; - var id; + let linkTarget = null; + let id; if (!isWindows) { - var dev = statValues[0].toString(32); - var ino = statValues[7].toString(32); + const dev = statValues[0].toString(32); + const ino = statValues[7].toString(32); id = `${dev}:${ino}`; if (seenLinks[id]) { linkTarget = seenLinks[id]; @@ -1734,13 +1734,13 @@ fs.realpath = function realpath(p, options, callback) { const knownHard = Object.create(null); // current character position in p - var pos; + let pos; // the partial path so far, including a trailing slash if any - var current; + let current; // the partial path without a trailing slash (except when pointing at a root) - var base; + let base; // the partial path scanned in the previous round, with slash - var previous; + let previous; current = base = splitRoot(p); pos = current.length; @@ -1765,10 +1765,10 @@ fs.realpath = function realpath(p, options, callback) { } // find the next part - var result = nextPart(p, pos); + const result = nextPart(p, pos); previous = current; if (result === -1) { - var last = p.slice(pos); + const last = p.slice(pos); current += last; base = previous + last; pos = p.length; @@ -1806,8 +1806,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].toString(32); - var ino = statValues[7].toString(32); + const dev = statValues[0].toString(32); + const ino = statValues[7].toString(32); id = `${dev}:${ino}`; if (seenLinks[id]) { return gotTarget(null, seenLinks[id], base); @@ -1826,7 +1826,7 @@ fs.realpath = function realpath(p, options, callback) { function gotTarget(err, target, base) { if (err) return callback(err); - var resolvedLink = pathModule.resolve(previous, target); + const resolvedLink = pathModule.resolve(previous, target); gotResolvedLink(resolvedLink); } @@ -1867,7 +1867,7 @@ fs.mkdtemp = function(prefix, options, callback) { throw new ERR_INVALID_ARG_TYPE('prefix', 'string', prefix); } nullCheck(prefix, 'prefix'); - var req = new FSReqWrap(); + const req = new FSReqWrap(); req.oncomplete = callback; binding.mkdtemp(`${prefix}XXXXXX`, options.encoding, req); }; @@ -1932,7 +1932,7 @@ fs.copyFileSync = function(src, dest, flags) { }; -var pool; +let pool; function allocNewPool(poolSize) { pool = Buffer.allocUnsafe(poolSize); @@ -2006,7 +2006,7 @@ function ReadStream(path, options) { fs.FileReadStream = fs.ReadStream; // support the legacy name ReadStream.prototype.open = function() { - var self = this; + const self = this; fs.open(this.path, this.flags, this.mode, function(er, fd) { if (er) { if (self.autoClose) { @@ -2041,9 +2041,9 @@ ReadStream.prototype._read = function(n) { // Grab another reference to the pool in the case that while we're // in the thread pool another read() finishes up the pool, and // allocates a new one. - var thisPool = pool; - var toRead = Math.min(pool.length - pool.used, n); - var start = pool.used; + const thisPool = pool; + let toRead = Math.min(pool.length - pool.used, n); + const start = pool.used; if (this.pos !== undefined) toRead = Math.min(this.end - this.pos + 1, toRead); @@ -2061,7 +2061,7 @@ ReadStream.prototype._read = function(n) { } this.emit('error', er); } else { - var b = null; + let b = null; if (bytesRead > 0) { this.bytesRead += bytesRead; b = thisPool.slice(start, start + bytesRead); @@ -2226,10 +2226,10 @@ WriteStream.prototype._writev = function(data, cb) { const self = this; const len = data.length; const chunks = new Array(len); - var size = 0; + let size = 0; for (var i = 0; i < len; i++) { - var chunk = data[i].chunk; + const chunk = data[i].chunk; chunks[i] = chunk; size += chunk.length; @@ -2276,7 +2276,7 @@ WriteStream.prototype.destroySoon = WriteStream.prototype.end; // SyncWriteStream is internal. DO NOT USE. // This undocumented API was never intended to be made public. -var SyncWriteStream = internalFS.SyncWriteStream; +const SyncWriteStream = internalFS.SyncWriteStream; Object.defineProperty(fs, 'SyncWriteStream', { configurable: true, get: internalUtil.deprecate(() => SyncWriteStream, diff --git a/lib/http.js b/lib/http.js index 701a5ccb86cc21..4fa652439e0704 100644 --- a/lib/http.js +++ b/lib/http.js @@ -39,7 +39,7 @@ function request(options, cb) { } function get(options, cb) { - var req = request(options, cb); + const req = request(options, cb); req.end(); return req; } diff --git a/lib/https.js b/lib/https.js index b9e2d56492dbec..499369c0699260 100644 --- a/lib/https.js +++ b/lib/https.js @@ -156,7 +156,7 @@ inherits(Agent, HttpAgent); Agent.prototype.createConnection = createConnection; Agent.prototype.getName = function getName(options) { - var name = HttpAgent.prototype.getName.call(this, options); + let name = HttpAgent.prototype.getName.call(this, options); name += ':'; if (options.ca) diff --git a/lib/internal/bootstrap_loaders.js b/lib/internal/bootstrap_loaders.js new file mode 100644 index 00000000000000..e409438dfcacfd --- /dev/null +++ b/lib/internal/bootstrap_loaders.js @@ -0,0 +1,229 @@ +// This file creates the internal module & binding loaders used by built-in +// modules. In contrast, user land modules are loaded using +// lib/module.js (CommonJS Modules) or lib/internal/loader/* (ES Modules). +// +// This file is compiled and run by node.cc before bootstrap_node.js +// was called, therefore the loaders are bootstraped before we start to +// actually bootstrap Node.js. It creates the following objects: +// +// C++ binding loaders: +// - process.binding(): the legacy C++ binding loader, accessible from user land +// because it is an object attached to the global process object. +// These C++ bindings are created using NODE_BUILTIN_MODULE_CONTEXT_AWARE() +// and have their nm_flags set to NM_F_BUILTIN. We do not make any guarantees +// about the stability of these bindings, but still have to take care of +// compatibility issues caused by them from time to time. +// - process._linkedBinding(): intended to be used by embedders to add +// additional C++ bindings in their applications. These C++ bindings +// can be created using NODE_MODULE_CONTEXT_AWARE_CPP() with the flag +// NM_F_LINKED. +// - internalBinding(): the private internal C++ binding loader, inaccessible +// from user land because they are only available from NativeModule.require() +// These C++ bindings are created using NODE_MODULE_CONTEXT_AWARE_INTERNAL() +// and have their nm_flags set to NM_F_INTERNAL. +// +// Internal JavaScript module loader: +// - NativeModule: a minimal module system used to load the JavaScript core +// modules found in lib/**/*.js and deps/**/*.js. All core modules are +// compiled into the node binary via node_javascript.cc generated by js2c.py, +// so they can be loaded faster without the cost of I/O. This class makes the +// lib/internal/*, deps/internal/* modules and internalBinding() available by +// default to core modules, and lets the core modules require itself via +// require('internal/bootstrap_loaders') even when this file is not written in +// CommonJS style. +// +// Other objects: +// - process.moduleLoadList: an array recording the bindings and the modules +// loaded in the process and the order in which they are loaded. + +'use strict'; + +(function bootstrapInternalLoaders(process, getBinding, getLinkedBinding, + getInternalBinding) { + + // Set up process.moduleLoadList + const moduleLoadList = []; + Object.defineProperty(process, 'moduleLoadList', { + value: moduleLoadList, + configurable: true, + enumerable: true, + writable: false + }); + + // Set up process.binding() and process._linkedBinding() + { + const bindingObj = Object.create(null); + + process.binding = function binding(module) { + module = String(module); + let mod = bindingObj[module]; + if (typeof mod !== 'object') { + mod = bindingObj[module] = getBinding(module); + moduleLoadList.push(`Binding ${module}`); + } + return mod; + }; + + process._linkedBinding = function _linkedBinding(module) { + module = String(module); + let mod = bindingObj[module]; + if (typeof mod !== 'object') + mod = bindingObj[module] = getLinkedBinding(module); + return mod; + }; + } + + // Set up internalBinding() in the closure + let internalBinding; + { + const bindingObj = Object.create(null); + internalBinding = function internalBinding(module) { + let mod = bindingObj[module]; + if (typeof mod !== 'object') { + mod = bindingObj[module] = getInternalBinding(module); + moduleLoadList.push(`Internal Binding ${module}`); + } + return mod; + }; + } + + // Minimal sandbox helper + const ContextifyScript = process.binding('contextify').ContextifyScript; + function runInThisContext(code, options) { + const script = new ContextifyScript(code, options); + return script.runInThisContext(); + } + + // Set up NativeModule + function NativeModule(id) { + this.filename = `${id}.js`; + this.id = id; + this.exports = {}; + this.loaded = false; + this.loading = false; + } + + NativeModule._source = getBinding('natives'); + NativeModule._cache = {}; + + const config = getBinding('config'); + + // Think of this as module.exports in this file even though it is not + // written in CommonJS style. + const loaderExports = { internalBinding, NativeModule }; + const loaderId = 'internal/bootstrap_loaders'; + NativeModule.require = function(id) { + if (id === loaderId) { + return loaderExports; + } + + const cached = NativeModule.getCached(id); + if (cached && (cached.loaded || cached.loading)) { + return cached.exports; + } + + if (!NativeModule.exists(id)) { + // Model the error off the internal/errors.js model, but + // do not use that module given that it could actually be + // the one causing the error if there's a bug in Node.js + const err = new Error(`No such built-in module: ${id}`); + err.code = 'ERR_UNKNOWN_BUILTIN_MODULE'; + err.name = 'Error [ERR_UNKNOWN_BUILTIN_MODULE]'; + throw err; + } + + moduleLoadList.push(`NativeModule ${id}`); + + const nativeModule = new NativeModule(id); + + nativeModule.cache(); + nativeModule.compile(); + + return nativeModule.exports; + }; + + NativeModule.requireForDeps = function(id) { + if (!NativeModule.exists(id) || + // TODO(TimothyGu): remove when DEP0084 reaches end of life. + id.startsWith('node-inspect/') || + id.startsWith('v8/')) { + id = `internal/deps/${id}`; + } + return NativeModule.require(id); + }; + + NativeModule.getCached = function(id) { + return NativeModule._cache[id]; + }; + + NativeModule.exists = function(id) { + return NativeModule._source.hasOwnProperty(id); + }; + + if (config.exposeInternals) { + NativeModule.nonInternalExists = function(id) { + // Do not expose this to user land even with --expose-internals + if (id === loaderId) { + return false; + } + return NativeModule.exists(id); + }; + + NativeModule.isInternal = function(id) { + // Do not expose this to user land even with --expose-internals + return id === loaderId; + }; + } else { + NativeModule.nonInternalExists = function(id) { + return NativeModule.exists(id) && !NativeModule.isInternal(id); + }; + + NativeModule.isInternal = function(id) { + return id.startsWith('internal/'); + }; + } + + NativeModule.getSource = function(id) { + return NativeModule._source[id]; + }; + + NativeModule.wrap = function(script) { + return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; + }; + + NativeModule.wrapper = [ + '(function (exports, require, module, process) {', + '\n});' + ]; + + NativeModule.prototype.compile = function() { + let source = NativeModule.getSource(this.id); + source = NativeModule.wrap(source); + + this.loading = true; + + try { + const fn = runInThisContext(source, { + filename: this.filename, + lineOffset: 0, + displayErrors: true + }); + const requireFn = this.id.startsWith('internal/deps/') ? + NativeModule.requireForDeps : + NativeModule.require; + fn(this.exports, requireFn, this, process); + + this.loaded = true; + } finally { + this.loading = false; + } + }; + + NativeModule.prototype.cache = function() { + NativeModule._cache[this.id] = this; + }; + + // This will be passed to the bootstrapNodeJSCore function in + // bootstrap_node.js. + return loaderExports; +}); diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js new file mode 100644 index 00000000000000..6cdbebc0c125b5 --- /dev/null +++ b/lib/internal/bootstrap_node.js @@ -0,0 +1,563 @@ +// Hello, and welcome to hacking node.js! +// +// This file is invoked by node::LoadEnvironment in src/node.cc, and is +// responsible for bootstrapping the node.js core. As special caution is given +// to the performance of the startup process, many dependencies are invoked +// lazily. +// +// Before this file is run, lib/internal/bootstrap_loaders.js gets run first +// to bootstrap the internal binding and module loaders, including +// process.binding(), process._linkedBinding(), internalBinding() and +// NativeModule. And then { internalBinding, NativeModule } will be passed +// into this bootstrapper to bootstrap Node.js core. + +'use strict'; + +(function bootstrapNodeJSCore(process, { internalBinding, NativeModule }) { + const exceptionHandlerState = { captureFn: null }; + + function startup() { + const EventEmitter = NativeModule.require('events'); + + const origProcProto = Object.getPrototypeOf(process); + Object.setPrototypeOf(origProcProto, EventEmitter.prototype); + + EventEmitter.call(process); + + setupProcessObject(); + + // do this good and early, since it handles errors. + setupProcessFatal(); + + setupV8(); + setupProcessICUVersions(); + + setupGlobalVariables(); + + const _process = NativeModule.require('internal/process'); + _process.setupConfig(NativeModule._source); + _process.setupSignalHandlers(); + _process.setupUncaughtExceptionCapture(exceptionHandlerState); + NativeModule.require('internal/process/warning').setup(); + NativeModule.require('internal/process/next_tick').setup(); + NativeModule.require('internal/process/stdio').setup(); + + const perf = process.binding('performance'); + const { + NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE, + NODE_PERFORMANCE_MILESTONE_THIRD_PARTY_MAIN_START, + NODE_PERFORMANCE_MILESTONE_THIRD_PARTY_MAIN_END, + NODE_PERFORMANCE_MILESTONE_CLUSTER_SETUP_START, + NODE_PERFORMANCE_MILESTONE_CLUSTER_SETUP_END, + NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_START, + NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_END, + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_START, + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_END + } = perf.constants; + + _process.setup_hrtime(); + _process.setup_performance(); + _process.setup_cpuUsage(); + _process.setupMemoryUsage(); + _process.setupKillAndExit(); + if (global.__coverage__) + NativeModule.require('internal/process/write-coverage').setup(); + + NativeModule.require('internal/trace_events_async_hooks').setup(); + NativeModule.require('internal/inspector_async_hook').setup(); + + _process.setupChannel(); + _process.setupRawDebug(); + + const browserGlobals = !process._noBrowserGlobals; + if (browserGlobals) { + setupGlobalTimeouts(); + setupGlobalConsole(); + setupGlobalURL(); + } + + // Ensure setURLConstructor() is called before the native + // 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, + value: process.argv[0] + }); + process.argv[0] = process.execPath; + + // Handle `--debug*` deprecation and invalidation + if (process._invalidDebug) { + process.emitWarning( + '`node --debug` and `node --debug-brk` are invalid. ' + + 'Please use `node --inspect` or `node --inspect-brk` instead.', + 'DeprecationWarning', 'DEP0062', startup, true); + process.exit(9); + } else if (process._deprecatedDebugBrk) { + process.emitWarning( + '`node --inspect --debug-brk` is deprecated. ' + + 'Please use `node --inspect-brk` instead.', + 'DeprecationWarning', 'DEP0062', startup, true); + } + + if (process.binding('config').experimentalModules) { + process.emitWarning( + 'The ESM module loader is experimental.', + 'ExperimentalWarning', undefined); + NativeModule.require('internal/process/modules').setup(); + } + + { + // Install legacy getters on the `util` binding for typechecking. + // TODO(addaleax): Turn into a full runtime deprecation. + const { pendingDeprecation } = process.binding('config'); + const { deprecate } = NativeModule.require('internal/util'); + const utilBinding = process.binding('util'); + const types = internalBinding('types'); + for (const name of [ + 'isArrayBuffer', 'isArrayBufferView', 'isAsyncFunction', + 'isDataView', 'isDate', 'isExternal', 'isMap', 'isMapIterator', + 'isNativeError', 'isPromise', 'isRegExp', 'isSet', 'isSetIterator', + 'isTypedArray', 'isUint8Array', 'isAnyArrayBuffer' + ]) { + utilBinding[name] = pendingDeprecation ? + deprecate(types[name], + 'Accessing native typechecking bindings of Node ' + + 'directly is deprecated. ' + + `Please use \`util.types.${name}\` instead.`, + 'DEP0103') : + types[name]; + } + } + + // There are various modes that Node can run in. The most common two + // are running from a script and running the REPL - but there are a few + // others like the debugger or running --eval arguments. Here we decide + // which mode we run in. + + if (NativeModule.exists('_third_party_main')) { + // To allow people to extend Node in different ways, this hook allows + // one to drop a file lib/_third_party_main.js into the build + // directory which will be executed instead of Node's normal loading. + process.nextTick(function() { + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_THIRD_PARTY_MAIN_START); + NativeModule.require('_third_party_main'); + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_THIRD_PARTY_MAIN_END); + }); + + } else if (process.argv[1] === 'inspect' || process.argv[1] === 'debug') { + if (process.argv[1] === 'debug') { + process.emitWarning( + '`node debug` is deprecated. Please use `node inspect` instead.', + 'DeprecationWarning', 'DEP0068'); + } + + // Start the debugger agent + process.nextTick(function() { + NativeModule.require('internal/deps/node-inspect/lib/_inspect').start(); + }); + + } else if (process.profProcess) { + NativeModule.require('internal/v8_prof_processor'); + + } else { + // There is user code to be run + + // If this is a worker in cluster mode, start up the communication + // channel. This needs to be done before any user code gets executed + // (including preload modules). + if (process.argv[1] && process.env.NODE_UNIQUE_ID) { + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_CLUSTER_SETUP_START); + const cluster = NativeModule.require('cluster'); + cluster._setupWorker(); + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_CLUSTER_SETUP_END); + // Make sure it's not accidentally inherited by child processes. + delete process.env.NODE_UNIQUE_ID; + } + + if (process._eval != null && !process._forceRepl) { + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_START); + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_END); + // User passed '-e' or '--eval' arguments to Node without '-i' or + // '--interactive' + + perf.markMilestone( + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_START); + preloadModules(); + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_END); + + const internalModule = NativeModule.require('internal/module'); + internalModule.addBuiltinLibsToObject(global); + evalScript('[eval]'); + } else if (process.argv[1] && process.argv[1] !== '-') { + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_START); + // make process.argv[1] into a full path + const path = NativeModule.require('path'); + process.argv[1] = path.resolve(process.argv[1]); + + const Module = NativeModule.require('module'); + + // check if user passed `-c` or `--check` arguments to Node. + if (process._syntax_check_only != null) { + const fs = NativeModule.require('fs'); + // read the source + const filename = Module._resolveFilename(process.argv[1]); + const source = fs.readFileSync(filename, 'utf-8'); + checkScriptSyntax(source, filename); + process.exit(0); + } + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_END); + perf.markMilestone( + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_START); + preloadModules(); + perf.markMilestone( + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_END); + Module.runMain(); + } else { + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_START); + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_END); + perf.markMilestone( + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_START); + preloadModules(); + perf.markMilestone( + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_END); + // If -i or --interactive were passed, or stdin is a TTY. + if (process._forceRepl || NativeModule.require('tty').isatty(0)) { + // REPL + const cliRepl = NativeModule.require('internal/repl'); + cliRepl.createInternalRepl(process.env, function(err, repl) { + if (err) { + throw err; + } + repl.on('exit', function() { + if (repl._flushing) { + repl.pause(); + return repl.once('flushHistory', function() { + process.exit(); + }); + } + process.exit(); + }); + }); + + if (process._eval != null) { + // User passed '-e' or '--eval' + evalScript('[eval]'); + } + } else { + // Read all of stdin - execute it. + process.stdin.setEncoding('utf8'); + + let code = ''; + process.stdin.on('data', function(d) { + code += d; + }); + + process.stdin.on('end', function() { + if (process._syntax_check_only != null) { + checkScriptSyntax(code, '[stdin]'); + } else { + process._eval = code; + evalScript('[stdin]'); + } + }); + } + } + } + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE); + } + + function setupProcessObject() { + process._setupProcessObject(pushValueToArray); + + function pushValueToArray() { + for (var i = 0; i < arguments.length; i++) + this.push(arguments[i]); + } + } + + function setupGlobalVariables() { + Object.defineProperty(global, Symbol.toStringTag, { + value: 'global', + writable: false, + enumerable: false, + configurable: true + }); + global.process = process; + const util = NativeModule.require('util'); + + function makeGetter(name) { + return util.deprecate(function() { + return this; + }, `'${name}' is deprecated, use 'global'`, 'DEP0016'); + } + + function makeSetter(name) { + return util.deprecate(function(value) { + Object.defineProperty(this, name, { + configurable: true, + writable: true, + enumerable: true, + value: value + }); + }, `'${name}' is deprecated, use 'global'`, 'DEP0016'); + } + + Object.defineProperties(global, { + GLOBAL: { + configurable: true, + get: makeGetter('GLOBAL'), + set: makeSetter('GLOBAL') + }, + root: { + configurable: true, + get: makeGetter('root'), + set: makeSetter('root') + } + }); + + // This, as side effect, removes `setupBufferJS` from the buffer binding, + // and exposes it on `internal/buffer`. + NativeModule.require('internal/buffer'); + + global.Buffer = NativeModule.require('buffer').Buffer; + process.domain = null; + process._exiting = false; + } + + function setupGlobalTimeouts() { + const timers = NativeModule.require('timers'); + global.clearImmediate = timers.clearImmediate; + global.clearInterval = timers.clearInterval; + global.clearTimeout = timers.clearTimeout; + global.setImmediate = timers.setImmediate; + global.setInterval = timers.setInterval; + global.setTimeout = timers.setTimeout; + } + + function setupGlobalConsole() { + const originalConsole = global.console; + const Module = NativeModule.require('module'); + // Setup Node.js global.console + const wrappedConsole = NativeModule.require('console'); + Object.defineProperty(global, 'console', { + configurable: true, + enumerable: false, + value: wrappedConsole + }); + setupInspector(originalConsole, wrappedConsole, Module); + } + + function setupGlobalURL() { + const { URL, URLSearchParams } = NativeModule.require('internal/url'); + Object.defineProperties(global, { + URL: { + value: URL, + writable: true, + configurable: true, + enumerable: false + }, + URLSearchParams: { + value: URLSearchParams, + writable: true, + configurable: true, + enumerable: false + } + }); + } + + function setupInspector(originalConsole, wrappedConsole, Module) { + if (!process.config.variables.v8_enable_inspector) { + return; + } + const { addCommandLineAPI, consoleCall } = process.binding('inspector'); + // Setup inspector command line API + const { makeRequireFunction } = NativeModule.require('internal/module'); + const path = NativeModule.require('path'); + const cwd = tryGetCwd(path); + + const consoleAPIModule = new Module(''); + consoleAPIModule.paths = + Module._nodeModulePaths(cwd).concat(Module.globalPaths); + addCommandLineAPI('require', makeRequireFunction(consoleAPIModule)); + const config = {}; + for (const key of Object.keys(wrappedConsole)) { + if (!originalConsole.hasOwnProperty(key)) + continue; + // If global console has the same method as inspector console, + // then wrap these two methods into one. Native wrapper will preserve + // the original stack. + wrappedConsole[key] = consoleCall.bind(wrappedConsole, + originalConsole[key], + wrappedConsole[key], + config); + } + for (const key of Object.keys(originalConsole)) { + if (wrappedConsole.hasOwnProperty(key)) + continue; + wrappedConsole[key] = originalConsole[key]; + } + } + + function noop() {} + + function setupProcessFatal() { + const { + executionAsyncId, + clearDefaultTriggerAsyncId, + clearAsyncIdStack, + hasAsyncIdStack, + afterHooksExist, + emitAfter + } = NativeModule.require('internal/async_hooks'); + + process._fatalException = function(er) { + // It's possible that defaultTriggerAsyncId was set for a constructor + // call that threw and was never cleared. So clear it now. + clearDefaultTriggerAsyncId(); + + if (exceptionHandlerState.captureFn !== null) { + exceptionHandlerState.captureFn(er); + } else if (!process.emit('uncaughtException', er)) { + // If someone handled it, then great. otherwise, die in C++ land + // since that means that we'll exit the process, emit the 'exit' event + try { + if (!process._exiting) { + process._exiting = true; + process.emit('exit', 1); + } + } catch (er) { + // nothing to be done about it at this point. + } + try { + const { kExpandStackSymbol } = NativeModule.require('internal/util'); + if (typeof er[kExpandStackSymbol] === 'function') + er[kExpandStackSymbol](); + } catch (er) {} + return false; + } + + // If we handled an error, then make sure any ticks get processed + // by ensuring that the next Immediate cycle isn't empty + NativeModule.require('timers').setImmediate(noop); + + // Emit the after() hooks now that the exception has been handled. + if (afterHooksExist()) { + do { + emitAfter(executionAsyncId()); + } while (hasAsyncIdStack()); + // Or completely empty the id stack. + } else { + clearAsyncIdStack(); + } + + return true; + }; + } + + function setupV8() { + // Warm up the map and set iterator preview functions. V8 compiles + // functions lazily (unless --nolazy is set) so we need to do this + // before we turn off --allow_natives_syntax again. + const v8 = NativeModule.require('internal/v8'); + v8.previewMapIterator(new Map().entries(), 1); + v8.previewSetIterator(new Set().entries(), 1); + // Disable --allow_natives_syntax again unless it was explicitly + // specified on the command line. + const re = /^--allow[-_]natives[-_]syntax$/; + if (!process.execArgv.some((s) => re.test(s))) + process.binding('v8').setFlagsFromString('--noallow_natives_syntax'); + } + + function setupProcessICUVersions() { + const icu = process.binding('config').hasIntl ? + process.binding('icu') : undefined; + if (!icu) return; // no Intl/ICU: nothing to add here. + // With no argument, getVersion() returns a comma separated list + // of possible types. + const versionTypes = icu.getVersion().split(','); + + for (var n = 0; n < versionTypes.length; n++) { + const name = versionTypes[n]; + const version = icu.getVersion(name); + Object.defineProperty(process.versions, name, { + writable: false, + enumerable: true, + value: version + }); + } + } + + function tryGetCwd(path) { + try { + return process.cwd(); + } catch (ex) { + // getcwd(3) can fail if the current working directory has been deleted. + // Fall back to the directory name of the (absolute) executable path. + // It's not really correct but what are the alternatives? + return path.dirname(process.execPath); + } + } + + function wrapForBreakOnFirstLine(source) { + if (!process._breakFirstLine) + return source; + const fn = `function() {\n\n${source};\n\n}`; + return `process.binding('inspector').callAndPauseOnStart(${fn}, {})`; + } + + function evalScript(name) { + const Module = NativeModule.require('module'); + const path = NativeModule.require('path'); + const cwd = tryGetCwd(path); + + const module = new Module(name); + module.filename = path.join(cwd, name); + module.paths = Module._nodeModulePaths(cwd); + const body = wrapForBreakOnFirstLine(process._eval); + const script = `global.__filename = ${JSON.stringify(name)};\n` + + 'global.exports = exports;\n' + + 'global.module = module;\n' + + 'global.__dirname = __dirname;\n' + + 'global.require = require;\n' + + 'return require("vm").runInThisContext(' + + `${JSON.stringify(body)}, { filename: ` + + `${JSON.stringify(name)}, displayErrors: true });\n`; + const result = module._compile(script, `${name}-wrapper`); + if (process._print_eval) console.log(result); + // Handle any nextTicks added in the first tick of the program. + process._tickCallback(); + } + + // Load preload modules + function preloadModules() { + if (process._preload_modules) { + NativeModule.require('module')._preloadModules(process._preload_modules); + } + } + + function checkScriptSyntax(source, filename) { + const Module = NativeModule.require('module'); + const vm = NativeModule.require('vm'); + const internalModule = NativeModule.require('internal/module'); + + // remove Shebang + source = internalModule.stripShebang(source); + // remove BOM + source = internalModule.stripBOM(source); + // wrap it + source = Module.wrap(source); + // compile the script, this will throw if it fails + new vm.Script(source, { displayErrors: true, filename }); + } + + startup(); +}); diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 3c8a314bf04644..264d268165440f 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -69,7 +69,7 @@ const handleConversion = { }, got: function(message, handle, emit) { - var server = new net.Server(); + const server = new net.Server(); server.listen(handle, function() { emit(server); }); @@ -86,8 +86,8 @@ const handleConversion = { // the worker should keep track of the socket message.key = socket.server._connectionKey; - var firstTime = !this.channel.sockets.send[message.key]; - var socketList = getSocketList('send', this, message.key); + const firstTime = !this.channel.sockets.send[message.key]; + const socketList = getSocketList('send', this, message.key); // the server should no longer expose a .connection property // and when asked to close it should query the socket status from @@ -99,7 +99,7 @@ const handleConversion = { socket.server._connections--; } - var handle = socket._handle; + const handle = socket._handle; // remove handle from socket object, it will be closed when the socket // will be sent @@ -130,14 +130,14 @@ const handleConversion = { }, got: function(message, handle, emit) { - var socket = new net.Socket({ handle: handle }); + const socket = new net.Socket({ handle: handle }); socket.readable = socket.writable = true; // if the socket was created by net.Server we will track the socket if (message.key) { // add socket to connections list - var socketList = getSocketList('got', this, message.key); + const socketList = getSocketList('got', this, message.key); socketList.add({ socket: socket }); @@ -169,7 +169,7 @@ const handleConversion = { }, got: function(message, handle, emit) { - var socket = new dgram.Socket(message.dgramType); + const socket = new dgram.Socket(message.dgramType); socket.bind(handle, function() { emit(socket); @@ -209,7 +209,7 @@ function ChildProcess() { this._handle = null; if (exitCode < 0) { - var syscall = this.spawnfile ? 'spawn ' + this.spawnfile : 'spawn'; + const syscall = this.spawnfile ? 'spawn ' + this.spawnfile : 'spawn'; const err = errnoException(exitCode, syscall); if (this.spawnfile) @@ -270,16 +270,16 @@ function closePendingHandle(target) { ChildProcess.prototype.spawn = function(options) { - var ipc; - var ipcFd; - var i; + let ipc; + let ipcFd; + let i; if (options === null || typeof options !== 'object') { throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); } // If no `stdio` option was given - use default - var stdio = options.stdio || 'pipe'; + let stdio = options.stdio || 'pipe'; stdio = _validateStdio(stdio, false); @@ -312,7 +312,7 @@ ChildProcess.prototype.spawn = function(options) { else throw new ERR_INVALID_ARG_TYPE('options.args', 'Array', options.args); - var err = this._handle.spawn(options); + const err = this._handle.spawn(options); // Run-time errors should emit an error, not throw an exception. if (err === UV_EAGAIN || @@ -396,7 +396,7 @@ ChildProcess.prototype.kill = function(sig) { convertToValidSignal(sig === undefined ? 'SIGTERM' : sig); if (this._handle) { - var err = this._handle.kill(signal); + const err = this._handle.kill(signal); if (err === 0) { /* Success. */ this.killed = true; @@ -461,9 +461,9 @@ function setupChannel(target, channel) { const control = new Control(channel); - var decoder = new StringDecoder('utf8'); - var jsonBuffer = ''; - var pendingHandle = null; + const decoder = new StringDecoder('utf8'); + let jsonBuffer = ''; + let pendingHandle = null; channel.buffering = false; channel.pendingHandle = null; channel.onread = function(nread, pool) { @@ -475,10 +475,10 @@ function setupChannel(target, channel) { pendingHandle = recvHandle; // Linebreak is used as a message end sign - var chunks = decoder.write(pool).split('\n'); - var numCompleteChunks = chunks.length - 1; + const chunks = decoder.write(pool).split('\n'); + const numCompleteChunks = chunks.length - 1; // Last line does not have trailing linebreak - var incompleteChunk = chunks[numCompleteChunks]; + const incompleteChunk = chunks[numCompleteChunks]; if (numCompleteChunks === 0) { jsonBuffer += incompleteChunk; this.buffering = jsonBuffer.length !== 0; @@ -487,7 +487,7 @@ function setupChannel(target, channel) { chunks[0] = jsonBuffer + chunks[0]; for (var i = 0; i < numCompleteChunks; i++) { - var message = JSON.parse(chunks[i]); + const message = JSON.parse(chunks[i]); // There will be at most one NODE_HANDLE message in every chunk we // read because SCM_RIGHTS messages don't get coalesced. Make sure @@ -537,7 +537,7 @@ function setupChannel(target, channel) { } assert(Array.isArray(target._handleQueue)); - var queue = target._handleQueue; + const queue = target._handleQueue; target._handleQueue = null; if (target._pendingMessage) { @@ -548,7 +548,7 @@ function setupChannel(target, channel) { } for (var i = 0; i < queue.length; i++) { - var args = queue[i]; + const args = queue[i]; target._send(args.message, args.handle, args.options, args.callback); } @@ -573,7 +573,7 @@ function setupChannel(target, channel) { // a message. target._send({ cmd: 'NODE_HANDLE_ACK' }, null, true); - var obj = handleConversion[message.type]; + const obj = handleConversion[message.type]; // Update simultaneous accepts on Windows if (process.platform === 'win32') { @@ -659,7 +659,7 @@ function setupChannel(target, channel) { return this._handleQueue.length === 1; } - var obj = handleConversion[message.type]; + const obj = handleConversion[message.type]; // convert TCP object to native handle object handle = handleConversion[message.type].send.call(target, @@ -689,11 +689,11 @@ function setupChannel(target, channel) { return this._handleQueue.length === 1; } - var req = new WriteWrap(); + const req = new WriteWrap(); req.async = false; - var string = JSON.stringify(message) + '\n'; - var err = channel.writeUtf8String(req, string, handle); + const string = JSON.stringify(message) + '\n'; + const err = channel.writeUtf8String(req, string, handle); if (err === 0) { if (handle) { @@ -768,7 +768,7 @@ function setupChannel(target, channel) { if (this._pendingMessage) closePendingHandle(this); - var fired = false; + let fired = false; function finish() { if (fired) return; fired = true; @@ -796,7 +796,7 @@ function setupChannel(target, channel) { if (!target.channel) return; - var eventName = (internal ? 'internalMessage' : 'message'); + const eventName = (internal ? 'internalMessage' : 'message'); process.nextTick(emit, eventName, message, handle); } @@ -817,8 +817,8 @@ function isInternal(message) { function nop() { } function _validateStdio(stdio, sync) { - var ipc; - var ipcFd; + let ipc; + let ipcFd; // Replace shortcut with an array if (typeof stdio === 'string') { @@ -857,7 +857,7 @@ function _validateStdio(stdio, sync) { if (stdio === 'ignore') { acc.push({ type: 'ignore' }); } else if (stdio === 'pipe' || typeof stdio === 'number' && stdio < 0) { - var a = { + const a = { type: 'pipe', readable: i === 0, writable: i !== 0 @@ -897,7 +897,7 @@ function _validateStdio(stdio, sync) { }); } else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) || getHandleWrapType(stdio._handle)) { - var handle = getHandleWrapType(stdio) ? + const handle = getHandleWrapType(stdio) ? stdio : getHandleWrapType(stdio.handle) ? stdio.handle : stdio._handle; @@ -925,10 +925,10 @@ function _validateStdio(stdio, sync) { function getSocketList(type, worker, key) { - var sockets = worker.channel.sockets[type]; - var socketList = sockets[key]; + const sockets = worker.channel.sockets[type]; + let socketList = sockets[key]; if (!socketList) { - var Construct = type === 'send' ? SocketListSend : SocketListReceive; + const Construct = type === 'send' ? SocketListSend : SocketListReceive; socketList = sockets[key] = new Construct(worker, key); } return socketList; @@ -944,8 +944,8 @@ function maybeClose(subprocess) { } function spawnSync(opts) { - var options = opts.options; - var result = spawn_sync.spawn(options); + const options = opts.options; + const result = spawn_sync.spawn(options); if (result.output && options.encoding && options.encoding !== 'buffer') { for (var i = 0; i < result.output.length; i++) { diff --git a/lib/internal/cluster/child.js b/lib/internal/cluster/child.js index 40c1a12327558f..3ec2bcebbb3fa0 100644 --- a/lib/internal/cluster/child.js +++ b/lib/internal/cluster/child.js @@ -120,7 +120,7 @@ function rr(message, indexesKey, cb) { if (message.errno) return cb(message.errno, null); - var key = message.key; + let key = message.key; function listen(backlog) { // TODO(bnoordhuis) Send a message to the master that tells it to @@ -202,7 +202,7 @@ function _disconnect(masterInitiated) { } } - for (var key in handles) { + for (const key in handles) { const handle = handles[key]; delete handles[key]; waitingCount++; diff --git a/lib/internal/cluster/master.js b/lib/internal/cluster/master.js index 3c6a398f117433..871c320c32e8ec 100644 --- a/lib/internal/cluster/master.js +++ b/lib/internal/cluster/master.js @@ -26,12 +26,12 @@ cluster.settings = {}; cluster.SCHED_NONE = SCHED_NONE; // Leave it to the operating system. cluster.SCHED_RR = SCHED_RR; // Master distributes connections. -var ids = 0; -var debugPortOffset = 1; -var initialized = false; +let ids = 0; +let debugPortOffset = 1; +let initialized = false; // XXX(bnoordhuis) Fold cluster.schedulingPolicy into cluster.settings? -var schedulingPolicy = { +let schedulingPolicy = { 'none': SCHED_NONE, 'rr': SCHED_RR }[process.env.NODE_CLUSTER_SCHED_POLICY]; @@ -45,7 +45,7 @@ if (schedulingPolicy === undefined) { cluster.schedulingPolicy = schedulingPolicy; cluster.setupMaster = function(options) { - var settings = { + const settings = { args: process.argv.slice(2), exec: process.argv[1], execArgv: process.execArgv, @@ -79,7 +79,7 @@ cluster.setupMaster = function(options) { if (message.cmd !== 'NODE_DEBUG_ENABLED') return; - var key; + let key; for (key in cluster.workers) { const worker = cluster.workers[key]; @@ -153,7 +153,7 @@ function removeWorker(worker) { function removeHandlesForWorker(worker) { assert(worker); - for (var key in handles) { + for (const key in handles) { const handle = handles[key]; if (handle.remove(worker)) @@ -229,7 +229,8 @@ cluster.disconnect = function(cb) { if (workers.length === 0) { process.nextTick(() => intercom.emit('disconnect')); } else { - for (var key in workers) { + let key; + for (key in workers) { key = workers[key]; if (cluster.workers[key].isConnected()) @@ -278,7 +279,7 @@ function queryServer(worker, message) { message.fd, message.index]; const key = args.join(':'); - var handle = handles[key]; + let handle = handles[key]; if (handle === undefined) { let address = message.address; @@ -293,7 +294,7 @@ function queryServer(worker, message) { address = message.address; } - var constructor = RoundRobinHandle; + let constructor = RoundRobinHandle; // UDP is exempt from round-robin connection balancing for what should // be obvious reasons: it's connectionless. There is nothing to send to // the workers except raw datagrams and that's pointless. diff --git a/lib/internal/cluster/round_robin_handle.js b/lib/internal/cluster/round_robin_handle.js index b2dff017e8b6ee..fa68b4028c2049 100644 --- a/lib/internal/cluster/round_robin_handle.js +++ b/lib/internal/cluster/round_robin_handle.js @@ -70,7 +70,7 @@ RoundRobinHandle.prototype.remove = function(worker) { if (index !== -1) this.free.splice(index, 1); - if (getOwnPropertyNames(this.all).length !== 0) + if (getOwnPropertyNames(this.all).length !== 0) return false; for (var handle; handle = this.handles.shift(); handle.close()) diff --git a/lib/internal/cluster/shared_handle.js b/lib/internal/cluster/shared_handle.js index fe6042142e31f6..2ccd08af56f08c 100644 --- a/lib/internal/cluster/shared_handle.js +++ b/lib/internal/cluster/shared_handle.js @@ -11,7 +11,7 @@ function SharedHandle(key, address, port, addressType, fd, flags) { this.handle = null; this.errno = 0; - var rval; + let rval; if (addressType === 'udp4' || addressType === 'udp6') rval = dgram._createSocketHandle(address, port, addressType, fd, flags); else diff --git a/lib/internal/cluster/utils.js b/lib/internal/cluster/utils.js index ba72ff90945d3c..38549befd131c9 100644 --- a/lib/internal/cluster/utils.js +++ b/lib/internal/cluster/utils.js @@ -8,7 +8,7 @@ module.exports = { }; const callbacks = {}; -var seq = 0; +let seq = 0; function sendHelper(proc, message, handle, cb) { if (!proc.connected) @@ -32,7 +32,7 @@ function internal(worker, cb) { if (message.cmd !== 'NODE_CLUSTER') return; - var fn = cb; + let fn = cb; if (message.ack !== undefined && callbacks[message.ack] !== undefined) { fn = callbacks[message.ack]; diff --git a/lib/internal/crypto/diffiehellman.js b/lib/internal/crypto/diffiehellman.js index f6d525c215ca63..dc1c9b9d8724a4 100644 --- a/lib/internal/crypto/diffiehellman.js +++ b/lib/internal/crypto/diffiehellman.js @@ -84,7 +84,7 @@ DiffieHellmanGroup.prototype.generateKeys = dhGenerateKeys; function dhGenerateKeys(encoding) { - var keys = this._handle.generateKeys(); + let keys = this._handle.generateKeys(); encoding = encoding || getDefaultEncoding(); if (encoding && encoding !== 'buffer') keys = keys.toString(encoding); @@ -100,7 +100,7 @@ function dhComputeSecret(key, inEnc, outEnc) { const encoding = getDefaultEncoding(); inEnc = inEnc || encoding; outEnc = outEnc || encoding; - var ret = this._handle.computeSecret(toBuf(key, inEnc)); + let ret = this._handle.computeSecret(toBuf(key, inEnc)); if (typeof ret === 'string') throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY(); if (outEnc && outEnc !== 'buffer') @@ -114,7 +114,7 @@ DiffieHellmanGroup.prototype.getPrime = dhGetPrime; function dhGetPrime(encoding) { - var prime = this._handle.getPrime(); + let prime = this._handle.getPrime(); encoding = encoding || getDefaultEncoding(); if (encoding && encoding !== 'buffer') prime = prime.toString(encoding); @@ -127,7 +127,7 @@ DiffieHellmanGroup.prototype.getGenerator = dhGetGenerator; function dhGetGenerator(encoding) { - var generator = this._handle.getGenerator(); + let generator = this._handle.getGenerator(); encoding = encoding || getDefaultEncoding(); if (encoding && encoding !== 'buffer') generator = generator.toString(encoding); @@ -140,7 +140,7 @@ DiffieHellmanGroup.prototype.getPublicKey = dhGetPublicKey; function dhGetPublicKey(encoding) { - var key = this._handle.getPublicKey(); + let key = this._handle.getPublicKey(); encoding = encoding || getDefaultEncoding(); if (encoding && encoding !== 'buffer') key = key.toString(encoding); @@ -153,7 +153,7 @@ DiffieHellmanGroup.prototype.getPrivateKey = dhGetPrivateKey; function dhGetPrivateKey(encoding) { - var key = this._handle.getPrivateKey(); + let key = this._handle.getPrivateKey(); encoding = encoding || getDefaultEncoding(); if (encoding && encoding !== 'buffer') key = key.toString(encoding); @@ -197,7 +197,7 @@ ECDH.prototype.generateKeys = function generateKeys(encoding, format) { }; ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) { - var f; + let f; if (format) { if (format === 'compressed') f = POINT_CONVERSION_COMPRESSED; @@ -211,7 +211,7 @@ ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) { } else { f = POINT_CONVERSION_UNCOMPRESSED; } - var key = this._handle.getPublicKey(f); + let key = this._handle.getPublicKey(f); encoding = encoding || getDefaultEncoding(); if (encoding && encoding !== 'buffer') key = key.toString(encoding); diff --git a/lib/internal/crypto/sig.js b/lib/internal/crypto/sig.js index 688ad43ddddf63..835c60cd8cf165 100644 --- a/lib/internal/crypto/sig.js +++ b/lib/internal/crypto/sig.js @@ -56,11 +56,11 @@ Sign.prototype.sign = function sign(options, encoding) { if (!options) throw new ERR_CRYPTO_SIGN_KEY_REQUIRED(); - var key = options.key || options; - var passphrase = options.passphrase || null; + let key = options.key || options; + const passphrase = options.passphrase || null; // Options specific to RSA - var rsaPadding = RSA_PKCS1_PADDING; + let rsaPadding = RSA_PKCS1_PADDING; if (options.hasOwnProperty('padding')) { if (options.padding === options.padding >> 0) { rsaPadding = options.padding; @@ -69,7 +69,7 @@ Sign.prototype.sign = function sign(options, encoding) { } } - var pssSaltLength = RSA_PSS_SALTLEN_AUTO; + let pssSaltLength = RSA_PSS_SALTLEN_AUTO; if (options.hasOwnProperty('saltLength')) { if (options.saltLength === options.saltLength >> 0) { pssSaltLength = options.saltLength; @@ -86,7 +86,7 @@ Sign.prototype.sign = function sign(options, encoding) { ); } - var ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength); + let ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength); encoding = encoding || getDefaultEncoding(); if (encoding && encoding !== 'buffer') @@ -113,11 +113,11 @@ Verify.prototype._write = Sign.prototype._write; Verify.prototype.update = Sign.prototype.update; Verify.prototype.verify = function verify(options, signature, sigEncoding) { - var key = options.key || options; + let key = options.key || options; sigEncoding = sigEncoding || getDefaultEncoding(); // Options specific to RSA - var rsaPadding = RSA_PKCS1_PADDING; + let rsaPadding = RSA_PKCS1_PADDING; if (options.hasOwnProperty('padding')) { if (options.padding === options.padding >> 0) { rsaPadding = options.padding; @@ -126,7 +126,7 @@ Verify.prototype.verify = function verify(options, signature, sigEncoding) { } } - var pssSaltLength = RSA_PSS_SALTLEN_AUTO; + let pssSaltLength = RSA_PSS_SALTLEN_AUTO; if (options.hasOwnProperty('saltLength')) { if (options.saltLength === options.saltLength >> 0) { pssSaltLength = options.saltLength; diff --git a/lib/internal/crypto/util.js b/lib/internal/crypto/util.js index 19c35ac4cdff58..3cb4f5ab65b923 100644 --- a/lib/internal/crypto/util.js +++ b/lib/internal/crypto/util.js @@ -26,7 +26,7 @@ const { isArrayBufferView } = require('internal/util/types'); -var defaultEncoding = 'buffer'; +let defaultEncoding = 'buffer'; function setDefaultEncoding(val) { defaultEncoding = val; diff --git a/lib/internal/encoding.js b/lib/internal/encoding.js index 9cd47f861f908f..322fcd6440a0b3 100644 --- a/lib/internal/encoding.js +++ b/lib/internal/encoding.js @@ -23,7 +23,7 @@ const { const { isArrayBufferView } = require('internal/util/types'); -const { internalBinding } = require('internal/bootstrap/loaders'); +const { internalBinding } = require('internal/bootstrap_loaders'); const { isArrayBuffer } = internalBinding('types'); @@ -32,7 +32,7 @@ const { encodeUtf8String } = process.binding('buffer'); -var Buffer; +let Buffer; function lazyBuffer() { if (Buffer === undefined) Buffer = require('buffer').Buffer; @@ -277,8 +277,8 @@ const encodings = new Map([ // Unfortunately, String.prototype.trim also removes non-ascii whitespace, // so we have to do this manually function trimAsciiWhitespace(label) { - var s = 0; - var e = label.length; + let s = 0; + let e = label.length; while (s < e && ( label[s] === '\u0009' || label[s] === '\u000a' || @@ -323,8 +323,8 @@ class TextEncoder { validateEncoder(this); if (typeof depth === 'number' && depth < 0) return opts.stylize('[Object]', 'special'); - var ctor = getConstructorOf(this); - var obj = Object.create({ + const ctor = getConstructorOf(this); + const obj = Object.create({ constructor: ctor === null ? TextEncoder : ctor }); obj.encoding = this.encoding; @@ -368,7 +368,7 @@ function makeTextDecoderICU() { if (enc === undefined) throw new ERR_ENCODING_NOT_SUPPORTED(encoding); - var flags = 0; + let flags = 0; if (options !== null) { flags |= options.fatal ? CONVERTER_FLAGS_FATAL : 0; flags |= options.ignoreBOM ? CONVERTER_FLAGS_IGNORE_BOM : 0; @@ -395,7 +395,7 @@ function makeTextDecoderICU() { } validateArgument(options, 'object', 'options', 'Object'); - var flags = 0; + let flags = 0; if (options !== null) flags |= options.stream ? 0 : CONVERTER_FLAGS_FLUSH; @@ -413,7 +413,7 @@ function makeTextDecoderICU() { } function makeTextDecoderJS() { - var StringDecoder; + let StringDecoder; function lazyStringDecoder() { if (StringDecoder === undefined) ({ StringDecoder } = require('string_decoder')); @@ -435,7 +435,7 @@ function makeTextDecoderJS() { if (enc === undefined || !hasConverter(enc)) throw new ERR_ENCODING_NOT_SUPPORTED(encoding); - var flags = 0; + let flags = 0; if (options !== null) { if (options.fatal) { throw new ERR_NO_ICU('"fatal" option'); @@ -524,8 +524,8 @@ function makeTextDecoderJS() { validateDecoder(this); if (typeof depth === 'number' && depth < 0) return opts.stylize('[Object]', 'special'); - var ctor = getConstructorOf(this); - var obj = Object.create({ + const ctor = getConstructorOf(this); + const obj = Object.create({ constructor: ctor === null ? TextDecoder : ctor }); obj.encoding = this.encoding; diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 3d0b6cf9b39177..f3e825dd342988 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -15,9 +15,9 @@ const kInfo = Symbol('info'); const messages = new Map(); const codes = {}; -var green = ''; -var red = ''; -var white = ''; +let green = ''; +let red = ''; +let white = ''; const { errmap, @@ -29,8 +29,8 @@ const { kMaxLength } = process.binding('buffer'); const { defineProperty } = Object; // Lazily loaded -var util_ = null; -var buffer; +let util_ = null; +let buffer; function lazyUtil() { if (!util_) { @@ -39,7 +39,7 @@ function lazyUtil() { return util_; } -var internalUtil = null; +let internalUtil = null; function lazyInternalUtil() { if (!internalUtil) { internalUtil = require('internal/util'); @@ -205,11 +205,11 @@ class SystemError extends makeNodeError(Error) { } function createErrDiff(actual, expected, operator) { - var other = ''; - var res = ''; - var lastPos = 0; - var end = ''; - var skipped = false; + let other = ''; + let res = ''; + let lastPos = 0; + let end = ''; + let skipped = false; const util = lazyUtil(); const actualLines = util .inspect(actual, { compact: false, customInspect: false }).split('\n'); @@ -221,9 +221,9 @@ function createErrDiff(actual, expected, operator) { // Remove all ending lines that match (this optimizes the output for // readability by reducing the number of total changed lines). - var a = actualLines[actualLines.length - 1]; - var b = expectedLines[expectedLines.length - 1]; - var i = 0; + let a = actualLines[actualLines.length - 1]; + let b = expectedLines[expectedLines.length - 1]; + let i = 0; while (a === b) { if (i++ < 2) { end = `\n ${a}${end}`; @@ -247,7 +247,7 @@ function createErrDiff(actual, expected, operator) { } const maxLines = Math.max(actualLines.length, expectedLines.length); - var printedLines = 0; + let printedLines = 0; for (i = 0; i < maxLines; i++) { // Only extra expected lines exist const cur = i - lastPos; @@ -321,7 +321,7 @@ class AssertionError extends Error { if (typeof options !== 'object' || options === null) { throw new codes.ERR_INVALID_ARG_TYPE('options', 'Object'); } - var { + let { actual, expected, message, @@ -714,9 +714,7 @@ E('ERR_HTTP2_PING_LENGTH', 'HTTP2 ping payload must be 8 bytes', RangeError); E('ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED', 'Cannot set HTTP/2 pseudo-headers', Error); E('ERR_HTTP2_PUSH_DISABLED', 'HTTP/2 client has disabled push streams', Error); -E('ERR_HTTP2_SEND_FILE', 'Directories cannot be sent', Error); -E('ERR_HTTP2_SEND_FILE_NOSEEK', - 'Offset or length can only be specified for regular files', Error); +E('ERR_HTTP2_SEND_FILE', 'Only regular files can be sent', Error); E('ERR_HTTP2_SESSION_ERROR', 'Session closed with error code %s', Error); E('ERR_HTTP2_SOCKET_BOUND', 'The socket is already bound to an Http2Session', Error); @@ -946,7 +944,7 @@ function invalidArgType(name, expected, actual) { let msg; if (Array.isArray(name)) { - var names = name.map((val) => `"${val}"`).join(', '); + const names = name.map((val) => `"${val}"`).join(', '); msg = `The ${names} arguments ${determiner} ${oneOf(expected, 'type')}`; } else if (name.endsWith(' argument')) { // for the case like 'first argument' diff --git a/lib/internal/fs.js b/lib/internal/fs.js index 36155d4d67f1f5..fd6c6ce0425572 100644 --- a/lib/internal/fs.js +++ b/lib/internal/fs.js @@ -46,8 +46,8 @@ function assertEncoding(encoding) { } function copyObject(source) { - var target = {}; - for (var key in source) + const target = {}; + for (const key in source) target[key] = source[key]; return target; } diff --git a/lib/internal/http.js b/lib/internal/http.js index 2b9c948aeefb30..67c9239c87de0c 100644 --- a/lib/internal/http.js +++ b/lib/internal/http.js @@ -2,7 +2,7 @@ const { setUnrefTimeout } = require('internal/timers'); -var dateCache; +let dateCache; function utcDate() { if (!dateCache) { const d = new Date(); diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 9315474364f59c..2a4ef0421f7c84 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -4,13 +4,9 @@ require('internal/util').assertCrypto(); -const { internalBinding } = require('internal/bootstrap/loaders'); const { async_id_symbol } = require('internal/async_hooks').symbols; -const { UV_EOF } = process.binding('uv'); const http = require('http'); const binding = process.binding('http2'); -const { FileHandle } = process.binding('fs'); -const { StreamPipe } = internalBinding('stream_pipe'); const assert = require('assert'); const { Buffer } = require('buffer'); const EventEmitter = require('events'); @@ -42,7 +38,6 @@ const { ERR_HTTP2_PING_LENGTH, ERR_HTTP2_PUSH_DISABLED, ERR_HTTP2_SEND_FILE, - ERR_HTTP2_SEND_FILE_NOSEEK, ERR_HTTP2_SESSION_ERROR, ERR_HTTP2_SETTINGS_CANCEL, ERR_HTTP2_SOCKET_BOUND, @@ -70,7 +65,6 @@ const { onServerStream, const { utcDate } = require('internal/http'); const { promisify } = require('internal/util'); const { isArrayBufferView } = require('internal/util/types'); -const { defaultTriggerAsyncIdScope } = require('internal/async_hooks'); const { _connectionListener: httpConnectionListener } = require('http'); const { createPromise, promiseResolve } = process.binding('util'); const debug = util.debuglog('http2'); @@ -351,7 +345,9 @@ function onStreamClose(code) { stream.end(); } - state.fd = -1; + if (state.fd !== undefined) + tryClose(state.fd); + // Defer destroy we actually emit end. if (stream._readableState.endEmitted || code !== NGHTTP2_NO_ERROR) { // If errored or ended, we can destroy immediately. @@ -1932,26 +1928,6 @@ function processHeaders(headers) { return headers; } -function onFileCloseError(stream, err) { - stream.emit(err); -} - -function onFileUnpipe() { - const stream = this.sink[kOwner]; - if (stream.ownsFd) - this.source.close().catch(onFileCloseError.bind(stream)); - else - this.source.releaseFD(); -} - -// This is only called once the pipe has returned back control, so -// it only has to handle errors and End-of-File. -function onPipedFileHandleRead(err) { - if (err < 0 && err !== UV_EOF) { - this.stream.close(NGHTTP2_INTERNAL_ERROR); - } -} - function processRespondWithFD(self, fd, headers, offset = 0, length = -1, streamOptions = 0) { const state = self[kState]; @@ -1964,32 +1940,18 @@ function processRespondWithFD(self, fd, headers, offset = 0, length = -1, return; } - // Close the writable side of the stream, but only as far as the writable - // stream implementation is concerned. - self._final = null; + + // Close the writable side of the stream self.end(); - const ret = self[kHandle].respond(headersList, streamOptions); + const ret = self[kHandle].respondFD(fd, headersList, + offset, length, + streamOptions); if (ret < 0) { self.destroy(new NghttpError(ret)); return; } - - defaultTriggerAsyncIdScope(self[async_id_symbol], startFilePipe, - self, fd, offset, length); -} - -function startFilePipe(self, fd, offset, length) { - const handle = new FileHandle(fd, offset, length); - handle.onread = onPipedFileHandleRead; - handle.stream = self; - - const pipe = new StreamPipe(handle._externalStream, - self[kHandle]._externalStream); - pipe.onunpipe = onFileUnpipe; - pipe.start(); - // exact length of the file doesn't matter here, since the // stream is closing anyway - just use 1 to signify that // a write does exist @@ -2046,21 +2008,12 @@ function doSendFileFD(session, options, fd, headers, streamOptions, err, stat) { } if (!stat.isFile()) { - const isDirectory = stat.isDirectory(); - if (options.offset !== undefined || options.offset > 0 || - options.length !== undefined || options.length >= 0 || - isDirectory) { - const err = isDirectory ? - new ERR_HTTP2_SEND_FILE() : new ERR_HTTP2_SEND_FILE_NOSEEK(); - if (onError) - onError(err); - else - this.destroy(err); - return; - } - - options.offset = -1; - options.length = -1; + const err = new ERR_HTTP2_SEND_FILE(); + if (onError) + onError(err); + else + this.destroy(err); + return; } if (this.destroyed || this.closed) { @@ -2085,14 +2038,12 @@ function doSendFileFD(session, options, fd, headers, streamOptions, err, stat) { return; } - if (stat.isFile()) { - statOptions.length = - statOptions.length < 0 ? stat.size - (+statOptions.offset) : - Math.min(stat.size - (+statOptions.offset), - statOptions.length); + statOptions.length = + statOptions.length < 0 ? stat.size - (+statOptions.offset) : + Math.min(stat.size - (+statOptions.offset), + statOptions.length); - headers[HTTP2_HEADER_CONTENT_LENGTH] = statOptions.length; - } + headers[HTTP2_HEADER_CONTENT_LENGTH] = statOptions.length; processRespondWithFD(this, fd, headers, options.offset | 0, @@ -2319,9 +2270,8 @@ class ServerHttp2Stream extends Http2Stream { throw new ERR_INVALID_ARG_TYPE('fd', 'number'); debug(`Http2Stream ${this[kID]} [Http2Session ` + - `${sessionName(session[kType])}]: initiating response from fd`); + `${sessionName(session[kType])}]: initiating response`); this[kUpdateTimer](); - this.ownsFd = false; headers = processHeaders(headers); const statusCode = headers[HTTP2_HEADER_STATUS] |= 0; @@ -2383,9 +2333,9 @@ class ServerHttp2Stream extends Http2Stream { const session = this[kSession]; debug(`Http2Stream ${this[kID]} [Http2Session ` + - `${sessionName(session[kType])}]: initiating response from file`); + `${sessionName(session[kType])}]: initiating response`); this[kUpdateTimer](); - this.ownsFd = true; + headers = processHeaders(headers); const statusCode = headers[HTTP2_HEADER_STATUS] |= 0; diff --git a/lib/internal/http2/util.js b/lib/internal/http2/util.js index b9bd580af273f6..2a13781d19706f 100644 --- a/lib/internal/http2/util.js +++ b/lib/internal/http2/util.js @@ -185,7 +185,7 @@ const IDX_OPTIONS_MAX_SESSION_MEMORY = 8; const IDX_OPTIONS_FLAGS = 9; function updateOptionsBuffer(options) { - var flags = 0; + let flags = 0; if (typeof options.maxDeflateDynamicTableSize === 'number') { flags |= (1 << IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE); optionsBuffer[IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE] = @@ -299,7 +299,7 @@ function getSettings(session, remote) { } function updateSettingsBuffer(settings) { - var flags = 0; + let flags = 0; if (typeof settings.headerTableSize === 'number') { flags |= (1 << IDX_SETTINGS_HEADER_TABLE_SIZE); settingsBuffer[IDX_SETTINGS_HEADER_TABLE_SIZE] = @@ -503,11 +503,11 @@ function assertWithinRange(name, value, min = 0, max = Infinity) { function toHeaderObject(headers) { const obj = Object.create(null); for (var n = 0; n < headers.length; n = n + 2) { - var name = headers[n]; - var value = headers[n + 1]; + const name = headers[n]; + let value = headers[n + 1]; if (name === HTTP2_HEADER_STATUS) value |= 0; - var existing = obj[name]; + const existing = obj[name]; if (existing === undefined) { obj[name] = value; } else if (!kSingleValueHeaders.has(name)) { diff --git a/lib/internal/loader/CreateDynamicModule.js b/lib/internal/loader/CreateDynamicModule.js new file mode 100644 index 00000000000000..8c289171386a0d --- /dev/null +++ b/lib/internal/loader/CreateDynamicModule.js @@ -0,0 +1,61 @@ +'use strict'; + +const { internalBinding } = require('internal/bootstrap_loaders'); +const { ModuleWrap } = internalBinding('module_wrap'); +const debug = require('util').debuglog('esm'); +const ArrayJoin = Function.call.bind(Array.prototype.join); +const ArrayMap = Function.call.bind(Array.prototype.map); + +const createDynamicModule = (exports, url = '', evaluate) => { + debug( + `creating ESM facade for ${url} with exports: ${ArrayJoin(exports, ', ')}` + ); + const names = ArrayMap(exports, (name) => `${name}`); + // Create two modules: One whose exports are get- and set-able ('reflective'), + // and one which re-exports all of these but additionally may + // run an executor function once everything is set up. + const src = ` + export let executor; + ${ArrayJoin(ArrayMap(names, (name) => `export let $${name};`), '\n')} + /* This function is implicitly returned as the module's completion value */ + (() => ({ + setExecutor: fn => executor = fn, + reflect: { + exports: { ${ + ArrayJoin(ArrayMap(names, (name) => ` + ${name}: { + get: () => $${name}, + set: v => $${name} = v + }`), ', \n')} + } + } + }));`; + const reflectiveModule = new ModuleWrap(src, `cjs-facade:${url}`); + reflectiveModule.instantiate(); + const { setExecutor, reflect } = reflectiveModule.evaluate()(); + // public exposed ESM + const reexports = ` + import { + executor, + ${ArrayMap(names, (name) => `$${name}`)} + } from ""; + export { + ${ArrayJoin(ArrayMap(names, (name) => `$${name} as ${name}`), ', ')} + } + if (typeof executor === "function") { + // add await to this later if top level await comes along + executor() + }`; + if (typeof evaluate === 'function') { + setExecutor(() => evaluate(reflect)); + } + const module = new ModuleWrap(reexports, `${url}`); + module.link(async () => reflectiveModule); + module.instantiate(); + return { + module, + reflect + }; +}; + +module.exports = createDynamicModule; diff --git a/lib/internal/loader/DefaultResolve.js b/lib/internal/loader/DefaultResolve.js new file mode 100644 index 00000000000000..f99e0c98b9271e --- /dev/null +++ b/lib/internal/loader/DefaultResolve.js @@ -0,0 +1,98 @@ +'use strict'; + +const { URL } = require('url'); +const CJSmodule = require('module'); +const internalFS = require('internal/fs'); +const { NativeModule, internalBinding } = require('internal/bootstrap_loaders'); +const { extname } = require('path'); +const { realpathSync } = require('fs'); +const preserveSymlinks = !!process.binding('config').preserveSymlinks; +const { + ERR_MISSING_MODULE, + ERR_MODULE_RESOLUTION_LEGACY, + ERR_UNKNOWN_FILE_EXTENSION +} = require('internal/errors').codes; +const { resolve: moduleWrapResolve } = internalBinding('module_wrap'); +const StringStartsWith = Function.call.bind(String.prototype.startsWith); +const { getURLFromFilePath, getPathFromURL } = require('internal/url'); + +const realpathCache = new Map(); + +function search(target, base) { + if (base === undefined) { + // We cannot search without a base. + throw new ERR_MISSING_MODULE(target); + } + try { + return moduleWrapResolve(target, base); + } catch (e) { + e.stack; // cause V8 to generate stack before rethrow + let error = e; + try { + const questionedBase = new URL(base); + const tmpMod = new CJSmodule(questionedBase.pathname, null); + tmpMod.paths = CJSmodule._nodeModulePaths( + new URL('./', questionedBase).pathname); + const found = CJSmodule._resolveFilename(target, tmpMod); + error = new ERR_MODULE_RESOLUTION_LEGACY(target, base, found); + } catch (problemChecking) { + // ignore + } + throw error; + } +} + +const extensionFormatMap = { + '__proto__': null, + '.mjs': 'esm', + '.json': 'json', + '.node': 'addon', + '.js': 'cjs' +}; + +function resolve(specifier, parentURL) { + if (NativeModule.nonInternalExists(specifier)) { + return { + url: specifier, + format: 'builtin' + }; + } + + let url; + try { + url = search(specifier, + parentURL || getURLFromFilePath(`${process.cwd()}/`).href); + } catch (e) { + if (typeof e.message === 'string' && + StringStartsWith(e.message, 'Cannot find module')) + e.code = 'MODULE_NOT_FOUND'; + throw e; + } + + if (!preserveSymlinks) { + const real = realpathSync(getPathFromURL(url), { + [internalFS.realpathCacheKey]: realpathCache + }); + const old = url; + url = getURLFromFilePath(real); + url.search = old.search; + url.hash = old.hash; + } + + const ext = extname(url.pathname); + + let format = extensionFormatMap[ext]; + if (!format) { + const isMain = parentURL === undefined; + if (isMain) + format = 'cjs'; + else + throw new ERR_UNKNOWN_FILE_EXTENSION(url.pathname); + } + + return { url: `${url}`, format }; +} + +module.exports = resolve; +// exported for tests +module.exports.search = search; diff --git a/lib/internal/loader/Loader.js b/lib/internal/loader/Loader.js new file mode 100644 index 00000000000000..e4457cfd817ba1 --- /dev/null +++ b/lib/internal/loader/Loader.js @@ -0,0 +1,125 @@ +'use strict'; + +const { + ERR_INVALID_ARG_TYPE, + ERR_INVALID_PROTOCOL, + ERR_MISSING_DYNAMIC_INTSTANTIATE_HOOK, + ERR_UNKNOWN_MODULE_FORMAT +} = require('internal/errors').codes; +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 FunctionBind = Function.call.bind(Function.prototype.bind); + +const debug = require('util').debuglog('esm'); + +/* 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() { + // methods which translate input code or other information + // into es modules + this.translators = translators; + + // registry of loaded modules, akin to `require.cache` + this.moduleMap = new ModuleMap(); + + // The resolver has the signature + // (specifier : string, parentURL : string, defaultResolve) + // -> Promise<{ url : string, format: string }> + // where defaultResolve is ModuleRequest.resolve (having the same + // signature itself). + // If `.format` on the returned value is 'dynamic', .dynamicInstantiate + // will be used as described below. + this._resolve = defaultResolve; + // This hook is only called when resolve(...).format is 'dynamic' and + // has the signature + // (url : string) -> Promise<{ exports: { ... }, execute: function }> + // Where `exports` is an object whose property names define the exported + // names of the generated module. `execute` is a function that receives + // an object with the same keys as `exports`, whose values are get/set + // functions for the actual exported values. + this._dynamicInstantiate = undefined; + } + + async resolve(specifier, parentURL) { + const isMain = parentURL === undefined; + if (!isMain && typeof parentURL !== 'string') + throw new ERR_INVALID_ARG_TYPE('parentURL', 'string'); + + const { url, format } = + await this._resolve(specifier, parentURL, defaultResolve); + + if (typeof url !== 'string') + throw new ERR_INVALID_ARG_TYPE('url', 'string'); + + if (typeof format !== 'string') + throw new ERR_INVALID_ARG_TYPE('format', 'string'); + + if (format === 'builtin') + return { url: `node:${url}`, format }; + + if (format !== 'dynamic' && !url.startsWith('file:')) + throw new ERR_INVALID_PROTOCOL(url, 'file:'); + + return { url, format }; + } + + async import(specifier, parent) { + const job = await this.getModuleJob(specifier, parent); + const module = await job.run(); + return module.namespace(); + } + + hook({ resolve, dynamicInstantiate }) { + // Use .bind() to avoid giving access to the Loader instance when called. + if (resolve !== undefined) + this._resolve = FunctionBind(resolve, null); + if (dynamicInstantiate !== undefined) + this._dynamicInstantiate = FunctionBind(dynamicInstantiate, null); + } + + async getModuleJob(specifier, parentURL) { + const { url, format } = await this.resolve(specifier, parentURL); + let job = this.moduleMap.get(url); + if (job !== undefined) + return job; + + let loaderInstance; + if (format === 'dynamic') { + if (typeof this._dynamicInstantiate !== 'function') + throw new ERR_MISSING_DYNAMIC_INTSTANTIATE_HOOK(); + + loaderInstance = async (url) => { + debug(`Translating dynamic ${url}`); + const { exports, execute } = await this._dynamicInstantiate(url); + return createDynamicModule(exports, url, (reflect) => { + debug(`Loading dynamic ${url}`); + execute(reflect.exports); + }); + }; + } else { + if (!translators.has(format)) + throw new ERR_UNKNOWN_MODULE_FORMAT(format); + + loaderInstance = translators.get(format); + } + + let inspectBrk = false; + if (process._breakFirstLine) { + delete process._breakFirstLine; + inspectBrk = true; + } + job = new ModuleJob(this, url, loaderInstance, inspectBrk); + this.moduleMap.set(url, job); + return job; + } +} + +Object.setPrototypeOf(Loader.prototype, null); + +module.exports = Loader; diff --git a/lib/internal/loader/ModuleJob.js b/lib/internal/loader/ModuleJob.js new file mode 100644 index 00000000000000..162b0504d3d313 --- /dev/null +++ b/lib/internal/loader/ModuleJob.js @@ -0,0 +1,117 @@ +'use strict'; + +const { internalBinding } = require('internal/bootstrap_loaders'); +const { ModuleWrap } = internalBinding('module_wrap'); +const { SafeSet, SafePromise } = require('internal/safe_globals'); +const { decorateErrorStack } = require('internal/util'); +const assert = require('assert'); +const resolvedPromise = SafePromise.resolve(); + +/* A ModuleJob tracks the loading of a single Module, and the ModuleJobs of + * its dependencies, over time. */ +class ModuleJob { + // `loader` is the Loader instance used for loading dependencies. + // `moduleProvider` is a function + constructor(loader, url, moduleProvider, inspectBrk) { + this.loader = loader; + this.error = null; + this.hadError = false; + this.inspectBrk = inspectBrk; + + // This is a Promise<{ module, reflect }>, whose fields will be copied + // onto `this` by `link()` below once it has been resolved. + this.modulePromise = moduleProvider(url); + this.module = undefined; + this.reflect = undefined; + + // Wait for the ModuleWrap instance being linked with all dependencies. + const link = async () => { + ({ module: this.module, + reflect: this.reflect } = await this.modulePromise); + assert(this.module instanceof ModuleWrap); + + const dependencyJobs = []; + const promises = this.module.link(async (specifier) => { + const jobPromise = this.loader.getModuleJob(specifier, url); + dependencyJobs.push(jobPromise); + return (await (await jobPromise).modulePromise).module; + }); + + if (promises !== undefined) + await SafePromise.all(promises); + + return SafePromise.all(dependencyJobs); + }; + // Promise for the list of all dependencyJobs. + this.linked = link(); + + // instantiated == deep dependency jobs wrappers instantiated, + // module wrapper instantiated + this.instantiated = undefined; + } + + async instantiate() { + if (!this.instantiated) { + return this.instantiated = this._instantiate(); + } + await this.instantiated; + return this.module; + } + + // This method instantiates the module associated with this job and its + // entire dependency graph, i.e. creates all the module namespaces and the + // exported/imported variables. + async _instantiate() { + const jobsInGraph = new SafeSet(); + + const addJobsToDependencyGraph = async (moduleJob) => { + if (jobsInGraph.has(moduleJob)) { + return; + } + jobsInGraph.add(moduleJob); + const dependencyJobs = await moduleJob.linked; + return Promise.all(dependencyJobs.map(addJobsToDependencyGraph)); + }; + try { + await addJobsToDependencyGraph(this); + } catch (e) { + if (!this.hadError) { + this.error = e; + this.hadError = true; + } + throw e; + } + try { + if (this.inspectBrk) { + const initWrapper = process.binding('inspector').callAndPauseOnStart; + initWrapper(this.module.instantiate, this.module); + } else { + this.module.instantiate(); + } + } catch (e) { + decorateErrorStack(e); + throw e; + } + for (const dependencyJob of jobsInGraph) { + // Calling `this.module.instantiate()` instantiates not only the + // ModuleWrap in this module, but all modules in the graph. + dependencyJob.instantiated = resolvedPromise; + } + return this.module; + } + + async run() { + const module = await this.instantiate(); + try { + module.evaluate(); + } catch (e) { + e.stack; + this.hadError = true; + this.error = e; + throw e; + } + return module; + } +} +Object.setPrototypeOf(ModuleJob.prototype, null); +module.exports = ModuleJob; diff --git a/lib/internal/loader/ModuleMap.js b/lib/internal/loader/ModuleMap.js new file mode 100644 index 00000000000000..dce8f834ba6d10 --- /dev/null +++ b/lib/internal/loader/ModuleMap.js @@ -0,0 +1,33 @@ +'use strict'; + +const ModuleJob = require('internal/loader/ModuleJob'); +const { SafeMap } = require('internal/safe_globals'); +const debug = require('util').debuglog('esm'); +const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes; + +// Tracks the state of the loader-level module cache +class ModuleMap extends SafeMap { + get(url) { + if (typeof url !== 'string') { + throw new ERR_INVALID_ARG_TYPE('url', 'string'); + } + return super.get(url); + } + set(url, job) { + if (typeof url !== 'string') { + throw new ERR_INVALID_ARG_TYPE('url', 'string'); + } + if (job instanceof ModuleJob !== true) { + throw new ERR_INVALID_ARG_TYPE('job', 'ModuleJob'); + } + debug(`Storing ${url} in ModuleMap`); + return super.set(url, job); + } + has(url) { + if (typeof url !== 'string') { + throw new ERR_INVALID_ARG_TYPE('url', 'string'); + } + return super.has(url); + } +} +module.exports = ModuleMap; diff --git a/lib/internal/loader/Translators.js b/lib/internal/loader/Translators.js new file mode 100644 index 00000000000000..74dd4358274d3b --- /dev/null +++ b/lib/internal/loader/Translators.js @@ -0,0 +1,92 @@ +'use strict'; + +const { NativeModule, internalBinding } = require('internal/bootstrap_loaders'); +const { ModuleWrap } = internalBinding('module_wrap'); +const internalCJSModule = require('internal/module'); +const CJSModule = require('module'); +const internalURLModule = require('internal/url'); +const createDynamicModule = require('internal/loader/CreateDynamicModule'); +const fs = require('fs'); +const { _makeLong } = require('path'); +const { SafeMap } = require('internal/safe_globals'); +const { URL } = require('url'); +const debug = require('util').debuglog('esm'); +const readFileAsync = require('util').promisify(fs.readFile); +const readFileSync = fs.readFileSync; +const StringReplace = Function.call.bind(String.prototype.replace); +const JsonParse = JSON.parse; + +const translators = new SafeMap(); +module.exports = translators; + +// Strategy for loading a standard JavaScript module +translators.set('esm', async (url) => { + const source = `${await readFileAsync(new URL(url))}`; + debug(`Translating StandardModule ${url}`); + return { + module: new ModuleWrap(internalCJSModule.stripShebang(source), url), + reflect: undefined + }; +}); + +// Strategy for loading a node-style CommonJS module +const isWindows = process.platform === 'win32'; +const winSepRegEx = /\//g; +translators.set('cjs', async (url) => { + debug(`Translating CJSModule ${url}`); + const pathname = internalURLModule.getPathFromURL(new URL(url)); + const module = CJSModule._cache[ + isWindows ? StringReplace(pathname, winSepRegEx, '\\') : pathname]; + if (module && module.loaded) { + const ctx = createDynamicModule(['default'], url); + ctx.reflect.exports.default.set(module.exports); + return ctx; + } + return createDynamicModule(['default'], url, () => { + debug(`Loading CJSModule ${url}`); + // we don't care about the return val of _load here because Module#load + // will handle it for us by checking the loader registry and filling the + // exports like above + CJSModule._load(pathname); + }); +}); + +// Strategy for loading a node builtin CommonJS module that isn't +// through normal resolution +translators.set('builtin', async (url) => { + debug(`Translating BuiltinModule ${url}`); + return createDynamicModule(['default'], url, (reflect) => { + debug(`Loading BuiltinModule ${url}`); + const exports = NativeModule.require(url.slice(5)); + reflect.exports.default.set(exports); + }); +}); + +// Strategy for loading a node native module +translators.set('addon', async (url) => { + debug(`Translating NativeModule ${url}`); + return createDynamicModule(['default'], url, (reflect) => { + debug(`Loading NativeModule ${url}`); + const module = { exports: {} }; + const pathname = internalURLModule.getPathFromURL(new URL(url)); + process.dlopen(module, _makeLong(pathname)); + reflect.exports.default.set(module.exports); + }); +}); + +// Strategy for loading a JSON file +translators.set('json', async (url) => { + debug(`Translating JSONModule ${url}`); + return createDynamicModule(['default'], url, (reflect) => { + debug(`Loading JSONModule ${url}`); + const pathname = internalURLModule.getPathFromURL(new URL(url)); + const content = readFileSync(pathname, 'utf8'); + try { + const exports = JsonParse(internalCJSModule.stripBOM(content)); + reflect.exports.default.set(exports); + } catch (err) { + err.message = pathname + ': ' + err.message; + throw err; + } + }); +}); diff --git a/lib/internal/module.js b/lib/internal/module.js new file mode 100644 index 00000000000000..6c331b37d83ede --- /dev/null +++ b/lib/internal/module.js @@ -0,0 +1,158 @@ +'use strict'; + +const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes; + +const { + CHAR_LINE_FEED, + CHAR_CARRIAGE_RETURN, + CHAR_EXCLAMATION_MARK, + CHAR_HASH, +} = require('internal/constants'); + +// Invoke with makeRequireFunction(module) where |module| is the Module object +// to use as the context for the require() function. +function makeRequireFunction(mod) { + const Module = mod.constructor; + + function require(path) { + try { + exports.requireDepth += 1; + return mod.require(path); + } finally { + exports.requireDepth -= 1; + } + } + + function resolve(request, options) { + if (typeof request !== 'string') { + throw new ERR_INVALID_ARG_TYPE('request', 'string', request); + } + return Module._resolveFilename(request, mod, false, options); + } + + require.resolve = resolve; + + function paths(request) { + if (typeof request !== 'string') { + throw new ERR_INVALID_ARG_TYPE('request', 'string', request); + } + return Module._resolveLookupPaths(request, mod, true); + } + + resolve.paths = paths; + + require.main = process.mainModule; + + // Enable support to add extra extension types. + require.extensions = Module._extensions; + + require.cache = Module._cache; + + return require; +} + +/** + * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + * because the buffer-to-string conversion in `fs.readFileSync()` + * translates it to FEFF, the UTF-16 BOM. + */ +function stripBOM(content) { + if (content.charCodeAt(0) === 0xFEFF) { + content = content.slice(1); + } + return content; +} + +/** + * Find end of shebang line and slice it off + */ +function stripShebang(content) { + // Remove shebang + const contLen = content.length; + if (contLen >= 2) { + if (content.charCodeAt(0) === CHAR_HASH && + content.charCodeAt(1) === CHAR_EXCLAMATION_MARK) { + if (contLen === 2) { + // Exact match + content = ''; + } else { + // Find end of shebang line and slice it off + let i = 2; + for (; i < contLen; ++i) { + const code = content.charCodeAt(i); + if (code === CHAR_LINE_FEED || code === CHAR_CARRIAGE_RETURN) + break; + } + if (i === contLen) + content = ''; + else { + // Note that this actually includes the newline character(s) in the + // new output. This duplicates the behavior of the regular expression + // that was previously used to replace the shebang line + content = content.slice(i); + } + } + } + } + return content; +} + +const builtinLibs = [ + 'assert', 'async_hooks', 'buffer', 'child_process', 'cluster', 'crypto', + 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'http2', 'https', 'net', + 'os', 'path', 'perf_hooks', 'punycode', 'querystring', 'readline', 'repl', + 'stream', 'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib' +]; + +if (typeof process.binding('inspector').connect === 'function') { + builtinLibs.push('inspector'); + builtinLibs.sort(); +} + +function addBuiltinLibsToObject(object) { + // Make built-in modules available directly (loaded lazily). + builtinLibs.forEach((name) => { + // Goals of this mechanism are: + // - Lazy loading of built-in modules + // - Having all built-in modules available as non-enumerable properties + // - Allowing the user to re-assign these variables as if there were no + // pre-existing globals with the same name. + + const setReal = (val) => { + // Deleting the property before re-assigning it disables the + // getter/setter mechanism. + delete object[name]; + object[name] = val; + }; + + Object.defineProperty(object, name, { + get: () => { + const lib = require(name); + + // Disable the current getter/setter and set up a new + // non-enumerable property. + delete object[name]; + Object.defineProperty(object, name, { + get: () => lib, + set: setReal, + configurable: true, + enumerable: false + }); + + return lib; + }, + set: setReal, + configurable: true, + enumerable: false + }); + }); +} + +module.exports = exports = { + addBuiltinLibsToObject, + builtinLibs, + makeRequireFunction, + requireDepth: 0, + stripBOM, + stripShebang +}; diff --git a/lib/internal/process.js b/lib/internal/process.js index d64fe9877198b8..1aebe9c2434494 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -153,7 +153,7 @@ function setupKillAndExit() { }; process.kill = function(pid, sig) { - var err; + let err; // eslint-disable-next-line eqeqeq if (pid != (pid | 0)) { diff --git a/lib/internal/process/modules.js b/lib/internal/process/modules.js new file mode 100644 index 00000000000000..1592761f54df25 --- /dev/null +++ b/lib/internal/process/modules.js @@ -0,0 +1,55 @@ +'use strict'; + +const { internalBinding } = require('internal/bootstrap_loaders'); +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; +} + +let loaderResolve; +exports.loaderPromise = new Promise((resolve, reject) => { + loaderResolve = resolve; +}); + +exports.ESMLoader = undefined; + +exports.setup = function() { + setInitializeImportMetaObjectCallback(initializeImportMetaObject); + + 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/internal/process/next_tick.js b/lib/internal/process/next_tick.js index 7acf266cb7f73d..2dfe8555bdd628 100644 --- a/lib/internal/process/next_tick.js +++ b/lib/internal/process/next_tick.js @@ -57,8 +57,8 @@ function setupNextTick() { } } - var head = new FixedQueue(); - var tail = head; + let head = new FixedQueue(); + let tail = head; function push(data) { if (head.bottom === head.top) { @@ -146,7 +146,7 @@ function setupNextTick() { if (process._exiting) return; - var args; + let args; switch (arguments.length) { case 1: break; case 2: args = [arguments[1]]; break; diff --git a/lib/internal/process/stdio.js b/lib/internal/process/stdio.js index 29aee7d09bdab9..42c73d218fc10d 100644 --- a/lib/internal/process/stdio.js +++ b/lib/internal/process/stdio.js @@ -10,9 +10,9 @@ const { exports.setup = setupStdio; function setupStdio() { - var stdin; - var stdout; - var stderr; + let stdin; + let stdout; + let stderr; function getStdout() { if (stdout) return stdout; @@ -52,7 +52,7 @@ function setupStdio() { switch (tty_wrap.guessHandleType(fd)) { case 'TTY': - var tty = require('tty'); + const tty = require('tty'); stdin = new tty.ReadStream(fd, { highWaterMark: 0, readable: true, @@ -61,13 +61,13 @@ function setupStdio() { break; case 'FILE': - var fs = require('fs'); + const fs = require('fs'); stdin = new fs.ReadStream(null, { fd: fd, autoClose: false }); break; case 'PIPE': case 'TCP': - var net = require('net'); + const net = require('net'); // It could be that process has been started with an IPC channel // sitting on fd=0, in such case the pipe for this fd is already @@ -145,27 +145,27 @@ function setupStdio() { } function createWritableStdioStream(fd) { - var stream; + let stream; const tty_wrap = process.binding('tty_wrap'); // Note stream._type is used for test-module-load-list.js switch (tty_wrap.guessHandleType(fd)) { case 'TTY': - var tty = require('tty'); + const tty = require('tty'); stream = new tty.WriteStream(fd); stream._type = 'tty'; break; case 'FILE': - var fs = require('internal/fs'); + const fs = require('internal/fs'); stream = new fs.SyncWriteStream(fd, { autoClose: false }); stream._type = 'fs'; break; case 'PIPE': case 'TCP': - var net = require('net'); + const net = require('net'); stream = new net.Socket({ fd: fd, readable: false, diff --git a/lib/internal/process/warning.js b/lib/internal/process/warning.js index df2d0c103b0092..c509339d53b2f9 100644 --- a/lib/internal/process/warning.js +++ b/lib/internal/process/warning.js @@ -6,12 +6,12 @@ const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes; exports.setup = setupProcessWarnings; -var cachedFd; -var acquiringFd = false; +let cachedFd; +let acquiringFd = false; function nop() {} // Lazily loaded -var fs = null; +let fs = null; function writeOut(message) { if (console && typeof console.error === 'function') @@ -83,7 +83,7 @@ function setupProcessWarnings() { if (isDeprecation && process.noDeprecation) return; const trace = process.traceProcessWarnings || (isDeprecation && process.traceDeprecation); - var msg = `${prefix}`; + let msg = `${prefix}`; if (warning.code) msg += `[${warning.code}] `; if (trace && warning.stack) { @@ -105,7 +105,7 @@ function setupProcessWarnings() { // process.emitWarning(str[, type[, code]][, ctor]) // process.emitWarning(str[, options]) process.emitWarning = function(warning, type, code, ctor, now) { - var detail; + let detail; if (type !== null && typeof type === 'object' && !Array.isArray(type)) { ctor = type.ctor; code = type.code; diff --git a/lib/internal/repl.js b/lib/internal/repl.js index 4c4e3c8cb4e275..c3672a34b6bb26 100644 --- a/lib/internal/repl.js +++ b/lib/internal/repl.js @@ -91,9 +91,9 @@ function setupHistory(repl, historyPath, ready) { } } - var timer = null; - var writing = false; - var pending = false; + let timer = null; + let writing = false; + let pending = false; repl.pause(); // History files are conventionally not readable by others: // https://github.com/nodejs/node/issues/3392 diff --git a/lib/internal/socket_list.js b/lib/internal/socket_list.js index 55077af1305121..c2f124438090f4 100644 --- a/lib/internal/socket_list.js +++ b/lib/internal/socket_list.js @@ -14,7 +14,7 @@ class SocketListSend extends EventEmitter { } _request(msg, cmd, callback) { - var self = this; + const self = this; if (!this.child.connected) return onclose(); this.child.send(msg); diff --git a/lib/internal/streams/BufferList.js b/lib/internal/streams/BufferList.js index a72bf37a31410b..99efaa4113edc7 100644 --- a/lib/internal/streams/BufferList.js +++ b/lib/internal/streams/BufferList.js @@ -52,8 +52,8 @@ module.exports = class BufferList { join(s) { if (this.length === 0) return ''; - var p = this.head; - var ret = '' + p.data; + let p = this.head; + let ret = '' + p.data; while (p = p.next) ret += s + p.data; return ret; @@ -63,8 +63,8 @@ module.exports = class BufferList { if (this.length === 0) return Buffer.alloc(0); const ret = Buffer.allocUnsafe(n >>> 0); - var p = this.head; - var i = 0; + let p = this.head; + let i = 0; while (p) { copyBuffer(p.data, ret, i); i += p.data.length; @@ -75,7 +75,7 @@ module.exports = class BufferList { // Consumes a specified amount of bytes or characters from the buffered data. consume(n, hasStrings) { - var ret; + let ret; if (n < this.head.data.length) { // `slice` is the same for buffers and strings. ret = this.head.data.slice(0, n); @@ -96,9 +96,9 @@ module.exports = class BufferList { // Consumes a specified amount of characters from the buffered data. _getString(n) { - var p = this.head; - var c = 1; - var ret = p.data; + let p = this.head; + let c = 1; + let ret = p.data; n -= ret.length; while (p = p.next) { const str = p.data; @@ -130,8 +130,8 @@ module.exports = class BufferList { // Consumes a specified amount of bytes from the buffered data. _getBuffer(n) { const ret = Buffer.allocUnsafe(n); - var p = this.head; - var c = 1; + let p = this.head; + let c = 1; p.data.copy(ret); n -= p.data.length; while (p = p.next) { diff --git a/lib/internal/streams/legacy.js b/lib/internal/streams/legacy.js index 9790696bfc7131..de8a12c76b21af 100644 --- a/lib/internal/streams/legacy.js +++ b/lib/internal/streams/legacy.js @@ -9,7 +9,7 @@ function Stream() { util.inherits(Stream, EE); Stream.prototype.pipe = function(dest, options) { - var source = this; + const source = this; function ondata(chunk) { if (dest.writable && dest.write(chunk) === false && source.pause) { @@ -34,7 +34,7 @@ Stream.prototype.pipe = function(dest, options) { source.on('close', onclose); } - var didOnEnd = false; + let didOnEnd = false; function onend() { if (didOnEnd) return; didOnEnd = true; diff --git a/lib/internal/test/binding.js b/lib/internal/test/binding.js index f9f018a78226ce..aae89ce7a0f5ea 100644 --- a/lib/internal/test/binding.js +++ b/lib/internal/test/binding.js @@ -8,7 +8,7 @@ process.emitWarning( // 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. -const { internalBinding } = require('internal/bootstrap/loaders'); +const { internalBinding } = require('internal/bootstrap_loaders'); module.exports = { ModuleWrap: internalBinding('module_wrap').ModuleWrap, }; diff --git a/lib/internal/timers.js b/lib/internal/timers.js index 26fc3f941bb5f9..fcfdf6b97399f0 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -34,7 +34,7 @@ module.exports = { validateTimerDuration }; -var timers; +let timers; function getTimers() { if (timers === undefined) { timers = require('timers'); diff --git a/lib/internal/tls.js b/lib/internal/tls.js index 6d367dbf285ff7..4e468a2dd72a74 100644 --- a/lib/internal/tls.js +++ b/lib/internal/tls.js @@ -3,13 +3,13 @@ // Example: // C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org function parseCertString(s) { - var out = Object.create(null); - var parts = s.split('\n'); + const out = Object.create(null); + const parts = s.split('\n'); for (var i = 0, len = parts.length; i < len; i++) { - var sepIndex = parts[i].indexOf('='); + const sepIndex = parts[i].indexOf('='); if (sepIndex > 0) { - var key = parts[i].slice(0, sepIndex); - var value = parts[i].slice(sepIndex + 1); + const key = parts[i].slice(0, sepIndex); + const value = parts[i].slice(sepIndex + 1); if (key in out) { if (!Array.isArray(out[key])) { out[key] = [out[key]]; diff --git a/lib/internal/url.js b/lib/internal/url.js index 842d26c4aac9b6..29e99f3f45b800 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -177,19 +177,19 @@ class URLSearchParams { if (typeof recurseTimes === 'number' && recurseTimes < 0) return ctx.stylize('[Object]', 'special'); - var separator = ', '; - var innerOpts = util._extend({}, ctx); + const separator = ', '; + const innerOpts = util._extend({}, ctx); if (recurseTimes !== null) { innerOpts.depth = recurseTimes - 1; } - var innerInspect = (v) => util.inspect(v, innerOpts); + const innerInspect = (v) => util.inspect(v, innerOpts); - var list = this[searchParams]; - var output = []; + const list = this[searchParams]; + const output = []; for (var i = 0; i < list.length; i += 2) output.push(`${innerInspect(list[i])} => ${innerInspect(list[i + 1])}`); - var length = output.reduce( + const length = output.reduce( (prev, cur) => prev + removeColors(cur).length + separator.length, -separator.length ); @@ -205,7 +205,7 @@ class URLSearchParams { function onParseComplete(flags, protocol, username, password, host, port, path, query, fragment) { - var ctx = this[context]; + const ctx = this[context]; ctx.flags = flags; ctx.scheme = protocol; ctx.username = (flags & URL_FLAGS_HAS_USERNAME) !== 0 ? username : ''; @@ -343,9 +343,9 @@ class URL { if (typeof depth === 'number' && depth < 0) return opts.stylize('[Object]', 'special'); - var ctor = getConstructorOf(this); + const ctor = getConstructorOf(this); - var obj = Object.create({ + const obj = Object.create({ constructor: ctor === null ? URL : ctor }); @@ -387,7 +387,7 @@ Object.defineProperties(URL.prototype, { auth: true }, options); const ctx = this[context]; - var ret = ctx.scheme; + let ret = ctx.scheme; if (ctx.host !== null) { ret += '//'; const has_username = ctx.username !== ''; @@ -533,7 +533,7 @@ Object.defineProperties(URL.prototype, { configurable: true, get() { const ctx = this[context]; - var ret = ctx.host || ''; + let ret = ctx.host || ''; if (ctx.port !== null) ret += `:${ctx.port}`; return ret; @@ -701,13 +701,13 @@ function initSearchParams(url, init) { // Ref: https://url.spec.whatwg.org/#concept-urlencoded-parser function parseParams(qs) { const out = []; - var pairStart = 0; - var lastPos = 0; - var seenSep = false; - var buf = ''; - var encoded = false; - var encodeCheck = 0; - var i; + let pairStart = 0; + let lastPos = 0; + let seenSep = false; + let buf = ''; + let encoded = false; + let encodeCheck = 0; + let i; for (i = 0; i < qs.length; ++i) { const code = qs.charCodeAt(i); @@ -819,11 +819,11 @@ function escapeParam(str) { if (len === 0) return ''; - var out = ''; - var lastPos = 0; + let out = ''; + let lastPos = 0; for (var i = 0; i < len; i++) { - var c = str.charCodeAt(i); + let c = str.charCodeAt(i); // ASCII if (c < 0x80) { @@ -855,7 +855,7 @@ function escapeParam(str) { } // Surrogate pair ++i; - var c2; + let c2; if (i < len) c2 = str.charCodeAt(i) & 0x3FF; else { @@ -885,7 +885,7 @@ function serializeParams(array) { if (len === 0) return ''; - var output = `${escapeParam(array[0])}=${escapeParam(array[1])}`; + let output = `${escapeParam(array[0])}=${escapeParam(array[1])}`; for (var i = 2; i < len; i += 2) output += `&${escapeParam(array[i])}=${escapeParam(array[i + 1])}`; return output; @@ -924,7 +924,7 @@ function defineIDLClass(proto, classStr, obj) { function merge(out, start, mid, end, lBuffer, rBuffer) { const sizeLeft = mid - start; const sizeRight = end - mid; - var l, r, o; + let l, r, o; for (l = 0; l < sizeLeft; l++) lBuffer[l] = out[start + l]; @@ -1055,7 +1055,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { // If there are any name-value pairs whose name is `name`, in `list`, set // the value of the first such name-value pair to `value` and remove the // others. - var found = false; + let found = false; for (var i = 0; i < list.length;) { const cur = list[i]; if (cur === name) { @@ -1091,9 +1091,9 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { // Simple stable in-place insertion sort // Derived from v8/src/js/array.js for (var i = 2; i < len; i += 2) { - var curKey = a[i]; - var curVal = a[i + 1]; - var j; + const curKey = a[i]; + const curVal = a[i + 1]; + let j; for (j = i - 2; j >= 0; j -= 2) { if (a[j] > curKey) { a[j + 2] = a[j]; @@ -1111,8 +1111,8 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { const rBuffer = new Array(len); for (var step = 2; step < len; step *= 2) { for (var start = 0; start < len - 2; start += 2 * step) { - var mid = start + step; - var end = mid + step; + const mid = start + step; + let end = mid + step; end = end < len ? end : len; if (mid > end) continue; @@ -1145,7 +1145,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', { let list = this[searchParams]; - var i = 0; + let i = 0; while (i < list.length) { const key = list[i]; const value = list[i + 1]; @@ -1303,7 +1303,7 @@ function domainToUnicode(domain) { // options object as expected by the http.request and https.request // APIs. function urlToOptions(url) { - var options = { + const options = { protocol: url.protocol, hostname: url.hostname, hash: url.hash, @@ -1322,11 +1322,11 @@ function urlToOptions(url) { } function getPathFromURLWin32(url) { - var hostname = url.hostname; - var pathname = url.pathname; + const hostname = url.hostname; + let pathname = url.pathname; for (var n = 0; n < pathname.length; n++) { if (pathname[n] === '%') { - var third = pathname.codePointAt(n + 2) | 0x20; + let third = pathname.codePointAt(n + 2) | 0x20; if ((pathname[n + 1] === '2' && third === 102) || // 2f 2F / (pathname[n + 1] === '5' && third === 99)) { // 5c 5C \ throw new ERR_INVALID_FILE_URL_PATH( @@ -1346,8 +1346,8 @@ function getPathFromURLWin32(url) { return `//${domainToUnicode(hostname)}${pathname}`; } else { // Otherwise, it's a local path that requires a drive letter - var letter = pathname.codePointAt(1) | 0x20; - var sep = pathname[2]; + const letter = pathname.codePointAt(1) | 0x20; + const sep = pathname[2]; if (letter < 97 || letter > 122 || // a..z A..Z (sep !== ':')) { throw new ERR_INVALID_FILE_URL_PATH('must be absolute'); @@ -1360,10 +1360,10 @@ function getPathFromURLPosix(url) { if (url.hostname !== '') { throw new ERR_INVALID_FILE_URL_HOST(platform); } - var pathname = url.pathname; + const pathname = url.pathname; for (var n = 0; n < pathname.length; n++) { if (pathname[n] === '%') { - var third = pathname.codePointAt(n + 2) | 0x20; + const third = pathname.codePointAt(n + 2) | 0x20; if (pathname[n + 1] === '2' && third === 102) { throw new ERR_INVALID_FILE_URL_PATH( 'must not include encoded / characters' @@ -1403,7 +1403,7 @@ NativeURL.prototype = URL.prototype; function constructUrl(flags, protocol, username, password, host, port, path, query, fragment) { - var ctx = new URLContext(); + const ctx = new URLContext(); ctx.flags = flags; ctx.scheme = protocol; ctx.username = (flags & URL_FLAGS_HAS_USERNAME) !== 0 ? username : ''; diff --git a/lib/internal/util/comparisons.js b/lib/internal/util/comparisons.js index 119fb66611a7c6..d8ace749ed0e94 100644 --- a/lib/internal/util/comparisons.js +++ b/lib/internal/util/comparisons.js @@ -2,7 +2,7 @@ const { compare } = process.binding('buffer'); const { isArrayBufferView } = require('internal/util/types'); -const { internalBinding } = require('internal/bootstrap/loaders'); +const { internalBinding } = require('internal/bootstrap_loaders'); const { isDate, isMap, isRegExp, isSet } = internalBinding('types'); function objectToString(o) { @@ -123,8 +123,8 @@ function strictDeepEqual(val1, val2, memos) { if (!innerDeepEqual(val1Value, val2.valueOf(), true)) return false; // Fast path for boxed primitives - var lengthval1 = 0; - var lengthval2 = 0; + let lengthval1 = 0; + let lengthval2 = 0; if (typeof val1Value === 'string') { lengthval1 = val1.length; lengthval2 = val2.length; @@ -181,17 +181,17 @@ function keyCheck(val1, val2, strict, memos, lengthA, lengthB) { // c) Equivalent values for every corresponding key/index // d) For Sets and Maps, equal contents // Note: this accounts for both named and indexed properties on Arrays. - var aKeys = Object.keys(val1); - var bKeys = Object.keys(val2); - var i; + let aKeys = Object.keys(val1); + let bKeys = Object.keys(val2); + let i; // The pair must have the same number of owned properties. if (aKeys.length !== bKeys.length) return false; if (strict) { - var symbolKeysA = Object.getOwnPropertySymbols(val1); - var symbolKeysB = Object.getOwnPropertySymbols(val2); + let symbolKeysA = Object.getOwnPropertySymbols(val1); + let symbolKeysB = Object.getOwnPropertySymbols(val2); if (symbolKeysA.length !== 0) { symbolKeysA = symbolKeysA.filter((k) => propertyIsEnumerable.call(val1, k)); @@ -294,7 +294,7 @@ function setHasLoosePrim(a, b, val) { if (altValues === undefined) return false; - var matches = 1; + let matches = 1; for (var i = 0; i < altValues.length; i++) { if (b.has(altValues[i])) { matches--; @@ -319,7 +319,7 @@ function setEquiv(a, b, strict, memo) { // This is a lazily initiated Set of entries which have to be compared // pairwise. - var set = null; + let set = null; for (const val of a) { // Note: Checking for the objects first improves the performance for object // heavy sets but it is a minor slow down for primitives. As they are fast @@ -355,7 +355,7 @@ function setEquiv(a, b, strict, memo) { } function findLooseMatchingPrimitives(prim) { - var values, number; + let values, number; switch (typeof prim) { case 'number': values = ['' + prim]; @@ -393,7 +393,7 @@ function mapHasLoosePrim(a, b, key1, memo, item1, item2) { const setA = new Set(); const setB = new Set(); - var keyCount = 1; + let keyCount = 1; setA.add(item1); if (b.has(key1)) { @@ -445,7 +445,7 @@ function mapEquiv(a, b, strict, memo) { if (a.size !== b.size) return false; - var set = null; + let set = null; for (const [key, item1] of a) { if (typeof key === 'object' && key !== null) { diff --git a/lib/internal/v8_prof_polyfill.js b/lib/internal/v8_prof_polyfill.js index 43ccc0e5d8bfac..9ca304db7ccef7 100644 --- a/lib/internal/v8_prof_polyfill.js +++ b/lib/internal/v8_prof_polyfill.js @@ -70,7 +70,7 @@ try { const fd = fs.openSync(logFile, 'r'); const buf = Buffer.allocUnsafe(4096); const dec = new (require('string_decoder').StringDecoder)('utf-8'); -var line = ''; +let line = ''; { const message = versionCheck(peekline(), process.versions.v8); diff --git a/lib/internal/v8_prof_processor.js b/lib/internal/v8_prof_processor.js index 6c7a4db6641935..dc2944839f802c 100644 --- a/lib/internal/v8_prof_processor.js +++ b/lib/internal/v8_prof_processor.js @@ -16,7 +16,7 @@ const scriptFiles = [ 'internal/deps/v8/tools/SourceMap', 'internal/deps/v8/tools/tickprocessor-driver' ]; -var script = ''; +let script = ''; scriptFiles.forEach(function(s) { script += process.binding('natives')[s] + '\n'; diff --git a/lib/internal/vm/Module.js b/lib/internal/vm/Module.js index feb4bb190f7759..6d8f7f76d8354b 100644 --- a/lib/internal/vm/Module.js +++ b/lib/internal/vm/Module.js @@ -1,6 +1,6 @@ 'use strict'; -const { internalBinding } = require('internal/bootstrap/loaders'); +const { internalBinding } = require('internal/bootstrap_loaders'); const { emitExperimentalWarning } = require('internal/util'); const { URL } = require('internal/url'); const { kParsingContext, isContext } = process.binding('contextify'); diff --git a/lib/module.js b/lib/module.js index 962f18b054cc90..790b0652eda2b3 100644 --- a/lib/module.js +++ b/lib/module.js @@ -1,3 +1,781 @@ +// 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. + 'use strict'; -module.exports = require('internal/modules/cjs/loader'); +const { NativeModule } = require('internal/bootstrap_loaders'); +const util = require('util'); +const { decorateErrorStack } = require('internal/util'); +const { getURLFromFilePath } = require('internal/url'); +const vm = require('vm'); +const assert = require('assert').ok; +const fs = require('fs'); +const internalFS = require('internal/fs'); +const path = require('path'); +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; + +const { + ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, + ERR_REQUIRE_ESM +} = require('internal/errors').codes; + +module.exports = Module; + +// these are below module.exports for the circular reference +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); + const cache = stat.cache; + if (cache !== null) { + const result = cache.get(filename); + if (result !== undefined) return result; + } + const result = internalModuleStat(filename); + if (cache !== null) cache.set(filename, result); + return result; +} +stat.cache = null; + +function updateChildren(parent, child, scan) { + const children = parent && parent.children; + if (children && !(scan && children.includes(child))) + children.push(child); +} + +function Module(id, parent) { + this.id = id; + this.exports = {}; + this.parent = parent; + updateChildren(parent, this, false); + this.filename = null; + this.loaded = false; + this.children = []; +} + +const builtinModules = Object.keys(NativeModule._source) + .filter(NativeModule.nonInternalExists); + +Object.freeze(builtinModules); +Module.builtinModules = builtinModules; + +Module._cache = Object.create(null); +Module._pathCache = Object.create(null); +Module._extensions = Object.create(null); +let modulePaths = []; +Module.globalPaths = []; + +Module.wrap = function(script) { + return Module.wrapper[0] + script + Module.wrapper[1]; +}; + +Module.wrapper = [ + '(function (exports, require, module, __filename, __dirname) { ', + '\n});' +]; + +const debug = util.debuglog('module'); + +Module._debug = util.deprecate(debug, 'Module._debug is deprecated.', + 'DEP0077'); + +// given a module name, and a list of paths to test, returns the first +// matching file in the following precedence. +// +// require("a.") +// -> a. +// +// require("a") +// -> a +// -> a. +// -> a/index. + +// check if the directory is a package.json dir +const packageMainCache = Object.create(null); + +function readPackage(requestPath) { + const entry = packageMainCache[requestPath]; + if (entry) + return entry; + + const jsonPath = path.resolve(requestPath, 'package.json'); + const json = internalModuleReadJSON(path.toNamespacedPath(jsonPath)); + + if (json === undefined) { + return false; + } + let pkg; + try { + pkg = packageMainCache[requestPath] = JSON.parse(json).main; + + } catch (e) { + e.path = jsonPath; + e.message = 'Error parsing ' + jsonPath + ': ' + e.message; + throw e; + } + return pkg; +} + +function tryPackage(requestPath, exts, isMain) { + const pkg = readPackage(requestPath); + + if (!pkg) return false; + + const filename = path.resolve(requestPath, pkg); + return tryFile(filename, isMain) || + tryExtensions(filename, exts, isMain) || + tryExtensions(path.resolve(filename, 'index'), exts, isMain); +} + +// In order to minimize unnecessary lstat() calls, +// this cache is a list of known-real paths. +// Set to an empty Map to reset. +const realpathCache = new Map(); + +// check if the file exists and is not a directory +// if using --preserve-symlinks and isMain is false, +// keep symlinks intact, otherwise resolve to the +// absolute realpath. +function tryFile(requestPath, isMain) { + const rc = stat(requestPath); + if (preserveSymlinks && !isMain) { + return rc === 0 && path.resolve(requestPath); + } + return rc === 0 && toRealPath(requestPath); +} + +function toRealPath(requestPath) { + return fs.realpathSync(requestPath, { + [internalFS.realpathCacheKey]: realpathCache + }); +} + +// given a path, check if the file exists with any of the set extensions +function tryExtensions(p, exts, isMain) { + for (var i = 0; i < exts.length; i++) { + const filename = tryFile(p + exts[i], isMain); + + if (filename) { + return filename; + } + } + return false; +} + +let warned = false; +Module._findPath = function(request, paths, isMain) { + if (path.isAbsolute(request)) { + paths = ['']; + } else if (!paths || paths.length === 0) { + return false; + } + + const cacheKey = request + '\x00' + + (paths.length === 1 ? paths[0] : paths.join('\x00')); + const entry = Module._pathCache[cacheKey]; + if (entry) + return entry; + + let exts; + let trailingSlash = request.length > 0 && + request.charCodeAt(request.length - 1) === CHAR_FORWARD_SLASH; + if (!trailingSlash) { + trailingSlash = /(?:^|\/)\.?\.$/.test(request); + } + + // For each path + for (var i = 0; i < paths.length; i++) { + // Don't search further if path doesn't exist + const curPath = paths[i]; + if (curPath && stat(curPath) < 1) continue; + const basePath = path.resolve(curPath, request); + let filename; + + const rc = stat(basePath); + if (!trailingSlash) { + if (rc === 0) { // File. + if (preserveSymlinks && !isMain) { + filename = path.resolve(basePath); + } else { + filename = toRealPath(basePath); + } + } + + if (!filename) { + // try it with each of the extensions + if (exts === undefined) + exts = Object.keys(Module._extensions); + filename = tryExtensions(basePath, exts, isMain); + } + } + + if (!filename && rc === 1) { // Directory. + // try it with each of the extensions at "index" + if (exts === undefined) + exts = Object.keys(Module._extensions); + filename = tryPackage(basePath, exts, isMain); + if (!filename) { + filename = tryExtensions(path.resolve(basePath, 'index'), exts, isMain); + } + } + + if (filename) { + // Warn once if '.' resolved outside the module dir + if (request === '.' && i > 0) { + if (!warned) { + warned = true; + process.emitWarning( + 'warning: require(\'.\') resolved outside the package ' + + 'directory. This functionality is deprecated and will be removed ' + + 'soon.', + 'DeprecationWarning', 'DEP0019'); + } + } + + Module._pathCache[cacheKey] = filename; + return filename; + } + } + return false; +}; + +// 'node_modules' character codes reversed +const nmChars = [ 115, 101, 108, 117, 100, 111, 109, 95, 101, 100, 111, 110 ]; +const nmLen = nmChars.length; +if (process.platform === 'win32') { + // 'from' is the __dirname of the module. + Module._nodeModulePaths = function(from) { + // guarantee that 'from' is absolute. + from = path.resolve(from); + + // note: this approach *only* works when the path is guaranteed + // to be absolute. Doing a fully-edge-case-correct path.split + // that works on both Windows and Posix is non-trivial. + + // return root node_modules when path is 'D:\\'. + // path.resolve will make sure from.length >=3 in Windows. + if (from.charCodeAt(from.length - 1) === CHAR_BACKWARD_SLASH && + from.charCodeAt(from.length - 2) === CHAR_COLON) + return [from + 'node_modules']; + + const paths = []; + let p = 0; + let last = from.length; + for (var i = from.length - 1; i >= 0; --i) { + const code = from.charCodeAt(i); + // The path segment separator check ('\' and '/') was used to get + // node_modules path for every path segment. + // 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 === CHAR_BACKWARD_SLASH || + code === CHAR_FORWARD_SLASH || + code === CHAR_COLON) { + if (p !== nmLen) + paths.push(from.slice(0, last) + '\\node_modules'); + last = i; + p = 0; + } else if (p !== -1) { + if (nmChars[p] === code) { + ++p; + } else { + p = -1; + } + } + } + + return paths; + }; +} else { // posix + // 'from' is the __dirname of the module. + Module._nodeModulePaths = function(from) { + // guarantee that 'from' is absolute. + from = path.resolve(from); + // Return early not only to avoid unnecessary work, but to *avoid* returning + // an array of two items for a root: [ '//node_modules', '/node_modules' ] + if (from === '/') + return ['/node_modules']; + + // note: this approach *only* works when the path is guaranteed + // to be absolute. Doing a fully-edge-case-correct path.split + // that works on both Windows and Posix is non-trivial. + const paths = []; + let p = 0; + let last = from.length; + for (var i = from.length - 1; i >= 0; --i) { + const code = from.charCodeAt(i); + if (code === CHAR_FORWARD_SLASH) { + if (p !== nmLen) + paths.push(from.slice(0, last) + '/node_modules'); + last = i; + p = 0; + } else if (p !== -1) { + if (nmChars[p] === code) { + ++p; + } else { + p = -1; + } + } + } + + // Append /node_modules to handle root paths. + paths.push('/node_modules'); + + return paths; + }; +} + + +// 'index.' character codes +const indexChars = [ 105, 110, 100, 101, 120, 46 ]; +const indexLen = indexChars.length; +Module._resolveLookupPaths = function(request, parent, newReturn) { + if (NativeModule.nonInternalExists(request)) { + debug('looking for %j in []', request); + return (newReturn ? null : [request, []]); + } + + // Check for relative path + if (request.length < 2 || + request.charCodeAt(0) !== CHAR_DOT || + (request.charCodeAt(1) !== CHAR_DOT && + request.charCodeAt(1) !== CHAR_FORWARD_SLASH)) { + let paths = modulePaths; + if (parent) { + if (!parent.paths) + paths = parent.paths = []; + else + paths = parent.paths.concat(paths); + } + + // Maintain backwards compat with certain broken uses of require('.') + // by putting the module's directory in front of the lookup paths. + if (request === '.') { + if (parent && parent.filename) { + paths.unshift(path.dirname(parent.filename)); + } else { + paths.unshift(path.resolve(request)); + } + } + + debug('looking for %j in %j', request, paths); + return (newReturn ? (paths.length > 0 ? paths : null) : [request, paths]); + } + + // with --eval, parent.id is not set and parent.filename is null + if (!parent || !parent.id || !parent.filename) { + // make require('./path/to/foo') work - normally the path is taken + // from realpath(__filename) but with eval there is no filename + const mainPaths = ['.'].concat(Module._nodeModulePaths('.'), modulePaths); + + debug('looking for %j in %j', request, mainPaths); + return (newReturn ? mainPaths : [request, mainPaths]); + } + + // Is the parent an index module? + // We can assume the parent has a valid extension, + // as it already has been accepted as a module. + const base = path.basename(parent.filename); + let parentIdPath; + if (base.length > indexLen) { + let i = 0; + for (; i < indexLen; ++i) { + if (indexChars[i] !== base.charCodeAt(i)) + break; + } + if (i === indexLen) { + // We matched 'index.', let's validate the rest + for (; i < base.length; ++i) { + const code = base.charCodeAt(i); + 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) { + // Is an index module + parentIdPath = parent.id; + } else { + // Not an index module + parentIdPath = path.dirname(parent.id); + } + } else { + // Not an index module + parentIdPath = path.dirname(parent.id); + } + } else { + // Not an index module + parentIdPath = path.dirname(parent.id); + } + let id = path.resolve(parentIdPath, request); + + // make sure require('./path') and require('path') get distinct ids, even + // when called from the toplevel js file + if (parentIdPath === '.' && id.indexOf('/') === -1) { + id = './' + id; + } + + debug('RELATIVE: requested: %s set ID to: %s from %s', request, id, + parent.id); + + const parentDir = [path.dirname(parent.filename)]; + debug('looking for %j in %j', id, parentDir); + 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 +// filename and return the result. +// 3. Otherwise, create a new module for the file and save it to the cache. +// Then have it load the file contents before returning its exports +// object. +Module._load = function(request, parent, isMain) { + if (parent) { + debug('Module._load REQUEST %s parent: %s', request, parent.id); + } + + if (experimentalModules && isMain) { + internalESModule.loaderPromise.then((loader) => { + return loader.import(getURLFromFilePath(request).pathname); + }) + .catch((e) => { + decorateErrorStack(e); + console.error(e); + process.exit(1); + }); + return; + } + + const filename = Module._resolveFilename(request, parent, isMain); + + const cachedModule = Module._cache[filename]; + if (cachedModule) { + updateChildren(parent, cachedModule, true); + return cachedModule.exports; + } + + if (NativeModule.nonInternalExists(filename)) { + debug('load native module %s', request); + return NativeModule.require(filename); + } + + // Don't call updateChildren(), Module constructor already does. + const module = new Module(filename, parent); + + if (isMain) { + process.mainModule = module; + module.id = '.'; + } + + Module._cache[filename] = module; + + tryModuleLoad(module, filename); + + return module.exports; +}; + +function tryModuleLoad(module, filename) { + let threw = true; + try { + module.load(filename); + threw = false; + } finally { + if (threw) { + delete Module._cache[filename]; + } + } +} + +Module._resolveFilename = function(request, parent, isMain, options) { + if (NativeModule.nonInternalExists(request)) { + return request; + } + + let paths; + + if (typeof options === 'object' && options !== null && + Array.isArray(options.paths)) { + const fakeParent = new Module('', null); + + paths = []; + + for (var i = 0; i < options.paths.length; i++) { + const path = options.paths[i]; + fakeParent.paths = Module._nodeModulePaths(path); + const lookupPaths = Module._resolveLookupPaths(request, fakeParent, true); + + if (!paths.includes(path)) + paths.push(path); + + for (var j = 0; j < lookupPaths.length; j++) { + if (!paths.includes(lookupPaths[j])) + paths.push(lookupPaths[j]); + } + } + } else { + paths = Module._resolveLookupPaths(request, parent, true); + } + + // look up the filename first, since that's the cache key. + const filename = Module._findPath(request, paths, isMain); + if (!filename) { + const err = new Error(`Cannot find module '${request}'`); + err.code = 'MODULE_NOT_FOUND'; + throw err; + } + return filename; +}; + + +// Given a file name, pass it to the proper extension handler. +Module.prototype.load = function(filename) { + debug('load %j for module %j', filename, this.id); + + assert(!this.loaded); + this.filename = filename; + this.paths = Module._nodeModulePaths(path.dirname(filename)); + + let extension = path.extname(filename) || '.js'; + if (!Module._extensions[extension]) extension = '.js'; + Module._extensions[extension](this, filename); + this.loaded = true; + + if (experimentalModules) { + const ESMLoader = internalESModule.ESMLoader; + const url = getURLFromFilePath(filename); + const urlString = `${url}`; + const exports = this.exports; + if (ESMLoader.moduleMap.has(urlString) !== true) { + ESMLoader.moduleMap.set( + urlString, + new ModuleJob(ESMLoader, url, async () => { + const ctx = createDynamicModule( + ['default'], url); + ctx.reflect.exports.default.set(exports); + return ctx; + }) + ); + } else { + const job = ESMLoader.moduleMap.get(urlString); + if (job.reflect) + job.reflect.exports.default.set(exports); + } + } +}; + + +// Loads a module at the given file path. Returns that module's +// `exports` property. +Module.prototype.require = function(id) { + if (typeof id !== 'string') { + throw new ERR_INVALID_ARG_TYPE('id', 'string', id); + } + if (id === '') { + throw new ERR_INVALID_ARG_VALUE('id', id, + 'must be a non-empty string'); + } + return Module._load(id, this, /* isMain */ false); +}; + + +// Resolved path to process.argv[1] will be lazily placed here +// (needed for setting breakpoint when called with --inspect-brk) +let resolvedArgv; + + +// Run the file contents in the correct scope or sandbox. Expose +// the correct helper variables (require, module, exports) to +// the file. +// Returns exception, if any. +Module.prototype._compile = function(content, filename) { + + content = internalModule.stripShebang(content); + + // create wrapper function + const wrapper = Module.wrap(content); + + const compiledWrapper = vm.runInThisContext(wrapper, { + filename: filename, + lineOffset: 0, + displayErrors: true + }); + + let inspectorWrapper = null; + if (process._breakFirstLine && process._eval == null) { + if (!resolvedArgv) { + // we enter the repl if we're not given a filename argument. + if (process.argv[1]) { + resolvedArgv = Module._resolveFilename(process.argv[1], null, false); + } else { + resolvedArgv = 'repl'; + } + } + + // Set breakpoint on module start + if (filename === resolvedArgv) { + delete process._breakFirstLine; + inspectorWrapper = process.binding('inspector').callAndPauseOnStart; + } + } + const dirname = path.dirname(filename); + const require = internalModule.makeRequireFunction(this); + const depth = internalModule.requireDepth; + if (depth === 0) stat.cache = new Map(); + let result; + if (inspectorWrapper) { + result = inspectorWrapper(compiledWrapper, this.exports, this.exports, + require, this, filename, dirname); + } else { + result = compiledWrapper.call(this.exports, this.exports, require, this, + filename, dirname); + } + if (depth === 0) stat.cache = null; + return result; +}; + + +// Native extension for .js +Module._extensions['.js'] = function(module, filename) { + const content = fs.readFileSync(filename, 'utf8'); + module._compile(internalModule.stripBOM(content), filename); +}; + + +// Native extension for .json +Module._extensions['.json'] = function(module, filename) { + const content = fs.readFileSync(filename, 'utf8'); + try { + module.exports = JSON.parse(internalModule.stripBOM(content)); + } catch (err) { + err.message = filename + ': ' + err.message; + throw err; + } +}; + + +//Native extension for .node +Module._extensions['.node'] = function(module, filename) { + return process.dlopen(module, path.toNamespacedPath(filename)); +}; + +if (experimentalModules) { + Module._extensions['.mjs'] = function(module, filename) { + throw new ERR_REQUIRE_ESM(filename); + }; +} + +// bootstrap main module. +Module.runMain = function() { + // Load the main module--the command line argument. + Module._load(process.argv[1], null, true); + // Handle any nextTicks added in the first tick of the program + process._tickCallback(); +}; + +Module._initPaths = function() { + const isWindows = process.platform === 'win32'; + + let homeDir; + let nodePath; + if (isWindows) { + homeDir = process.env.USERPROFILE; + nodePath = process.env.NODE_PATH; + } else { + homeDir = safeGetenv('HOME'); + nodePath = safeGetenv('NODE_PATH'); + } + + // $PREFIX/lib/node, where $PREFIX is the root of the Node.js installation. + let prefixDir; + // process.execPath is $PREFIX/bin/node except on Windows where it is + // $PREFIX\node.exe. + if (isWindows) { + prefixDir = path.resolve(process.execPath, '..'); + } else { + prefixDir = path.resolve(process.execPath, '..', '..'); + } + let paths = [path.resolve(prefixDir, 'lib', 'node')]; + + if (homeDir) { + paths.unshift(path.resolve(homeDir, '.node_libraries')); + paths.unshift(path.resolve(homeDir, '.node_modules')); + } + + if (nodePath) { + paths = nodePath.split(path.delimiter).filter(function(path) { + return !!path; + }).concat(paths); + } + + modulePaths = paths; + + // clone as a shallow copy, for introspection. + Module.globalPaths = modulePaths.slice(0); +}; + +Module._preloadModules = function(requests) { + if (!Array.isArray(requests)) + return; + + // Preloaded modules have a dummy parent module which is deemed to exist + // in the current working directory. This seeds the search path for + // preloaded modules. + const parent = new Module('internal/preload', null); + try { + parent.paths = Module._nodeModulePaths(process.cwd()); + } catch (e) { + if (e.code !== 'ENOENT') { + throw e; + } + } + for (var n = 0; n < requests.length; n++) + parent.require(requests[n]); +}; + +Module._initPaths(); + +// backwards compatibility +Module.Module = Module; diff --git a/lib/net.js b/lib/net.js index 19f5b135891eb2..aca952834a1645 100644 --- a/lib/net.js +++ b/lib/net.js @@ -70,7 +70,7 @@ const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); // `cluster` is only used by `listenInCluster` so for startup performance // reasons it's lazy loaded. -var cluster = null; +let cluster = null; const errnoException = errors.errnoException; const exceptionWithHostPort = errors.exceptionWithHostPort; @@ -132,10 +132,10 @@ function createServer(options, connectionListener) { // connect(path, [cb]); // function connect(...args) { - var normalized = normalizeArgs(args); - var options = normalized[0]; + const normalized = normalizeArgs(args); + const options = normalized[0]; debug('createConnection', normalized); - var socket = new Socket(options); + const socket = new Socket(options); if (options.timeout) { socket.setTimeout(options.timeout); @@ -156,7 +156,7 @@ function connect(...args) { // For Server.prototype.listen(), the [...] part is [, backlog] // but will not be handled here (handled in listen()) function normalizeArgs(args) { - var arr; + let arr; if (args.length === 0) { arr = [{}, null]; @@ -165,7 +165,7 @@ function normalizeArgs(args) { } const arg0 = args[0]; - var options = {}; + let options = {}; if (typeof arg0 === 'object' && arg0 !== null) { // (options[...][, cb]) options = arg0; @@ -180,7 +180,7 @@ function normalizeArgs(args) { } } - var cb = args[args.length - 1]; + const cb = args[args.length - 1]; if (typeof cb !== 'function') arr = [options, null]; else @@ -260,7 +260,7 @@ function Socket(options) { (this._handle instanceof Pipe) && process.platform === 'win32') { // Make stdout and stderr blocking on Windows - var err = this._handle.setBlocking(true); + const err = this._handle.setBlocking(true); if (err) throw errnoException(err, 'setBlocking'); @@ -318,7 +318,7 @@ Socket.prototype._unrefTimer = function _unrefTimer() { function shutdownSocket(self, callback) { - var req = new ShutdownWrap(); + const req = new ShutdownWrap(); req.oncomplete = afterShutdown; req.handle = self._handle; req.callback = callback; @@ -348,7 +348,7 @@ Socket.prototype._final = function(cb) { return this.destroy(); } - var err = defaultTriggerAsyncIdScope( + const err = defaultTriggerAsyncIdScope( this[async_id_symbol], shutdownSocket, this, cb ); @@ -358,7 +358,7 @@ Socket.prototype._final = function(cb) { function afterShutdown(status, handle) { - var self = handle.owner; + const self = handle.owner; debug('afterShutdown destroyed=%j', self.destroyed, self._readableState); @@ -386,7 +386,7 @@ function writeAfterFIN(chunk, encoding, cb) { encoding = null; } - var er = new Error('This socket has been ended by the other party'); + const er = new Error('This socket has been ended by the other party'); er.code = 'EPIPE'; // TODO: defer error events consistently everywhere, not just the cb this.emit('error', er); @@ -513,7 +513,7 @@ Socket.prototype._read = function(n) { // not already reading, start the flow debug('Socket._read readStart'); this._handle.reading = true; - var err = this._handle.readStart(); + const err = this._handle.readStart(); if (err) this.destroy(errnoException(err, 'read')); } @@ -571,7 +571,7 @@ Socket.prototype._destroy = function(exception, cb) { if (this._handle) { if (this !== process.stderr) debug('close handle'); - var isException = exception ? true : false; + const isException = exception ? true : false; // `bytesRead` should be accessible after `.destroy()` this[BYTES_READ] = this._handle.bytesRead; @@ -600,8 +600,8 @@ Socket.prototype._destroy = function(exception, cb) { // This function is called whenever the handle gets a // buffer, or when there's an error reading. function onread(nread, buffer) { - var handle = this; - var self = handle.owner; + const handle = this; + const self = handle.owner; assert(handle === self._handle, 'handle != self._handle'); self._unrefTimer(); @@ -617,12 +617,12 @@ function onread(nread, buffer) { // called again. // Optimization: emit the original buffer with end points - var ret = self.push(buffer); + const ret = self.push(buffer); if (handle.reading && !ret) { handle.reading = false; debug('readStop'); - var err = handle.readStop(); + const err = handle.readStop(); if (err) self.destroy(errnoException(err, 'read')); } @@ -666,8 +666,8 @@ Socket.prototype._getpeername = function() { if (!this._handle || !this._handle.getpeername) { return {}; } - var out = {}; - var err = this._handle.getpeername(out); + const out = {}; + const err = this._handle.getpeername(out); if (err) return {}; // FIXME(bnoordhuis) Throw? this._peername = out; } @@ -704,8 +704,8 @@ Socket.prototype._getsockname = function() { return {}; } if (!this._sockname) { - var out = {}; - var err = this._handle.getsockname(out); + const out = {}; + const err = this._handle.getsockname(out); if (err) return {}; // FIXME(bnoordhuis) Throw? this._sockname = out; } @@ -745,16 +745,16 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) { return false; } - var req = new WriteWrap(); + const req = new WriteWrap(); req.handle = this._handle; req.oncomplete = afterWrite; req.async = false; - var err; + let err; if (writev) { - var allBuffers = data.allBuffers; - var chunks; - var i; + const allBuffers = data.allBuffers; + let chunks; + let i; if (allBuffers) { chunks = data; for (i = 0; i < data.length; i++) @@ -762,7 +762,7 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) { } else { chunks = new Array(data.length << 1); for (i = 0; i < data.length; i++) { - var entry = data[i]; + const entry = data[i]; chunks[i * 2] = entry.chunk; chunks[i * 2 + 1] = entry.encoding; } @@ -828,7 +828,7 @@ function createWriteReq(req, handle, data, encoding) { protoGetter('bytesWritten', function bytesWritten() { - var bytes = this._bytesDispatched; + let bytes = this._bytesDispatched; const state = this._writableState; const data = this._pendingData; const encoding = this._pendingEncoding; @@ -866,7 +866,7 @@ protoGetter('bytesWritten', function bytesWritten() { function afterWrite(status, handle, err) { - var self = handle.owner; + const self = handle.owner; if (self !== process.stderr && self !== process.stdout) debug('afterWrite', status); @@ -880,7 +880,7 @@ function afterWrite(status, handle, err) { } if (status < 0) { - var ex = errnoException(status, 'write', this.error); + const ex = errnoException(status, 'write', this.error); debug('write failure', ex); self.destroy(ex, this.cb); return; @@ -906,7 +906,7 @@ function checkBindError(err, port, handle) { // getsockname() method. Non-issue for now, the cluster module doesn't // really support pipes anyway. if (err === 0 && port > 0 && handle.getsockname) { - var out = {}; + const out = {}; err = handle.getsockname(out); if (err === 0 && port !== out.port) { debug(`checkBindError, bound to ${out.port} instead of ${port}`); @@ -924,7 +924,7 @@ function internalConnect( assert(self.connecting); - var err; + let err; if (localAddress || localPort) { if (addressType === 4) { @@ -969,8 +969,8 @@ function internalConnect( } if (err) { - var sockname = self._getsockname(); - var details; + const sockname = self._getsockname(); + let details; if (sockname) { details = sockname.address + ':' + sockname.port; @@ -993,8 +993,8 @@ Socket.prototype.connect = function(...args) { } else { normalized = normalizeArgs(args); } - var options = normalized[0]; - var cb = normalized[1]; + const options = normalized[0]; + const cb = normalized[1]; if (this.write !== Socket.prototype.write) this.write = Socket.prototype.write; @@ -1007,7 +1007,7 @@ Socket.prototype.connect = function(...args) { } const path = options.path; - var pipe = !!path; + const pipe = !!path; debug('pipe', pipe, path); if (!this._handle) { @@ -1041,10 +1041,10 @@ Socket.prototype.connect = function(...args) { function lookupAndConnect(self, options) { - var host = options.host || 'localhost'; - var port = options.port; - var localAddress = options.localAddress; - var localPort = options.localPort; + const host = options.host || 'localhost'; + let port = options.port; + const localAddress = options.localAddress; + const localPort = options.localPort; if (localAddress && !isIP(localAddress)) { throw new ERR_INVALID_IP_ADDRESS(localAddress); @@ -1066,7 +1066,7 @@ function lookupAndConnect(self, options) { port |= 0; // If host is an IP, skip performing a lookup - var addressType = isIP(host); + const addressType = isIP(host); if (addressType) { defaultTriggerAsyncIdScope(self[async_id_symbol], process.nextTick, () => { if (self.connecting) @@ -1083,7 +1083,7 @@ function lookupAndConnect(self, options) { throw new ERR_INVALID_ARG_TYPE('options.lookup', 'Function', options.lookup); - var dnsopts = { + const dnsopts = { family: options.family, hints: options.hints || 0 }; @@ -1098,7 +1098,7 @@ function lookupAndConnect(self, options) { debug('connect: find host', host); debug('connect: dns options', dnsopts); self._host = host; - var lookup = options.lookup || dns.lookup; + const lookup = options.lookup || dns.lookup; defaultTriggerAsyncIdScope(self[async_id_symbol], function() { lookup(host, dnsopts, function emitLookup(err, ip, addressType) { self.emit('lookup', err, ip, addressType, host); @@ -1164,7 +1164,7 @@ Socket.prototype.unref = function() { function afterConnect(status, handle, req, readable, writable) { - var self = handle.owner; + const self = handle.owner; // callback may come after call to destroy if (self.destroyed) { @@ -1195,11 +1195,11 @@ function afterConnect(status, handle, req, readable, writable) { } else { self.connecting = false; - var details; + let details; if (req.localAddress && req.localPort) { details = req.localAddress + ':' + req.localPort; } - var ex = exceptionWithHostPort(status, + const ex = exceptionWithHostPort(status, 'connect', req.address, req.port, @@ -1266,11 +1266,11 @@ function toNumber(x) { return (x = Number(x)) >= 0 ? x : false; } // Returns handle if it can be created, or error code if it can't function createServerHandle(address, port, addressType, fd) { - var err = 0; + let err = 0; // assign handle in listen, and clean up if bind or listen fails - var handle; + let handle; - var isTCP = false; + let isTCP = false; if (typeof fd === 'number' && fd >= 0) { try { handle = createHandle(fd, true); @@ -1286,7 +1286,7 @@ function createServerHandle(address, port, addressType, fd) { } else if (port === -1 && addressType === -1) { handle = new Pipe(PipeConstants.SERVER); if (process.platform === 'win32') { - var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES); + const instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES); if (!Number.isNaN(instances)) { handle.setPendingInstances(instances); } @@ -1331,7 +1331,7 @@ function setupListenHandle(address, port, addressType, backlog, fd) { } else { debug('setupListenHandle: create a handle'); - var rval = null; + let rval = null; // Try to bind to the unspecified IPv6 address, see if IPv6 is available if (!address && typeof fd !== 'number') { @@ -1351,7 +1351,7 @@ function setupListenHandle(address, port, addressType, backlog, fd) { rval = createServerHandle(address, port, addressType, fd); if (typeof rval === 'number') { - var error = exceptionWithHostPort(rval, 'listen', address, port); + const error = exceptionWithHostPort(rval, 'listen', address, port); process.nextTick(emitErrorNT, this, error); return; } @@ -1365,10 +1365,10 @@ function setupListenHandle(address, port, addressType, backlog, fd) { // Use a backlog of 512 entries. We pass 511 to the listen() call because // the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); // which will thus give us a backlog of 512 entries. - var err = this._handle.listen(backlog || 511); + const err = this._handle.listen(backlog || 511); if (err) { - var ex = exceptionWithHostPort(err, 'listen', address, port); + const ex = exceptionWithHostPort(err, 'listen', address, port); this._handle.close(); this._handle = null; defaultTriggerAsyncIdScope(this[async_id_symbol], @@ -1435,7 +1435,7 @@ function listenInCluster(server, address, port, addressType, err = checkBindError(err, port, handle); if (err) { - var ex = exceptionWithHostPort(err, 'bind', address, port); + const ex = exceptionWithHostPort(err, 'bind', address, port); return server.emit('error', ex); } @@ -1449,19 +1449,19 @@ function listenInCluster(server, address, port, addressType, Server.prototype.listen = function(...args) { - var normalized = normalizeArgs(args); - var options = normalized[0]; - var cb = normalized[1]; + const normalized = normalizeArgs(args); + let options = normalized[0]; + const cb = normalized[1]; if (this._handle) { throw new ERR_SERVER_ALREADY_LISTEN(); } - var hasCallback = (cb !== null); + const hasCallback = (cb !== null); if (hasCallback) { this.once('listening', cb); } - var backlogFromArgs = + const backlogFromArgs = // (handle, backlog) or (path, backlog) or (port, backlog) toNumber(args.length > 1 && args[1]) || toNumber(args.length > 2 && args[2]); // (port, host, backlog) @@ -1492,7 +1492,7 @@ Server.prototype.listen = function(...args) { // ([port][, host][, backlog][, cb]) where port is specified // or (options[, cb]) where options.port is specified // or if options.port is normalized as 0 before - var backlog; + let backlog; if (typeof options.port === 'number' || typeof options.port === 'string') { if (!isLegalPort(options.port)) { throw new ERR_SOCKET_BAD_PORT(options.port); @@ -1513,7 +1513,7 @@ Server.prototype.listen = function(...args) { // (path[, backlog][, cb]) or (options[, cb]) // where path or options.path is a UNIX domain socket or Windows pipe if (options.path && isPipeName(options.path)) { - var pipeName = this._pipeName = options.path; + const pipeName = this._pipeName = options.path; backlog = options.backlog || backlogFromArgs; listenInCluster(this, pipeName, -1, -1, backlog, undefined, options.exclusive); @@ -1545,8 +1545,8 @@ Object.defineProperty(Server.prototype, 'listening', { Server.prototype.address = function() { if (this._handle && this._handle.getsockname) { - var out = {}; - var err = this._handle.getsockname(out); + const out = {}; + const err = this._handle.getsockname(out); if (err) { throw errnoException(err, 'address'); } @@ -1559,8 +1559,8 @@ Server.prototype.address = function() { }; function onconnection(err, clientHandle) { - var handle = this; - var self = handle.owner; + const handle = this; + const self = handle.owner; debug('onconnection'); @@ -1574,7 +1574,7 @@ function onconnection(err, clientHandle) { return; } - var socket = new Socket({ + const socket = new Socket({ handle: clientHandle, allowHalfOpen: self.allowHalfOpen, pauseOnCreate: self.pauseOnConnect @@ -1609,8 +1609,8 @@ Server.prototype.getConnections = function(cb) { } // Poll workers - var left = this._workers.length; - var total = this._connections; + let left = this._workers.length; + let total = this._connections; function oncount(err, count) { if (err) { @@ -1647,7 +1647,7 @@ Server.prototype.close = function(cb) { } if (this._usingWorkers) { - var left = this._workers.length; + let left = this._workers.length; const onWorkerClose = () => { if (--left !== 0) return; @@ -1723,10 +1723,10 @@ Server.prototype.unref = function() { return this; }; -var _setSimultaneousAccepts; +let _setSimultaneousAccepts; if (process.platform === 'win32') { - var simultaneousAccepts; + let simultaneousAccepts; _setSimultaneousAccepts = function(handle) { if (handle === undefined) { diff --git a/lib/os.js b/lib/os.js index eb13139dba9a9c..b7d0afa2e3d358 100644 --- a/lib/os.js +++ b/lib/os.js @@ -119,7 +119,7 @@ function platform() { platform[Symbol.toPrimitive] = () => process.platform; function tmpdir() { - var path; + let path; if (isWindows) { path = process.env.TEMP || process.env.TMP || diff --git a/lib/path.js b/lib/path.js index 7a4868852698db..0abf10f0c2381c 100644 --- a/lib/path.js +++ b/lib/path.js @@ -50,12 +50,12 @@ function isWindowsDeviceRoot(code) { } // Resolves . and .. elements in a path with directory names -function normalizeString(path, allowAboveRoot, separator) { - var res = ''; - var lastSegmentLength = 0; - var lastSlash = -1; - var dots = 0; - var code; +function normalizeStringWin32(path, allowAboveRoot) { + let res = ''; + let lastSegmentLength = 0; + let lastSlash = -1; + let dots = 0; + let code; for (var i = 0; i <= path.length; ++i) { if (i < path.length) code = path.charCodeAt(i); @@ -72,14 +72,14 @@ function normalizeString(path, allowAboveRoot, separator) { res.charCodeAt(res.length - 1) !== CHAR_DOT || res.charCodeAt(res.length - 2) !== CHAR_DOT) { if (res.length > 2) { - const lastSlashIndex = res.lastIndexOf(separator); + const lastSlashIndex = res.lastIndexOf('\\'); if (lastSlashIndex !== res.length - 1) { if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { res = res.slice(0, lastSlashIndex); - lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); + lastSegmentLength = res.length - 1 - res.lastIndexOf('\\'); } lastSlash = i; dots = 0; @@ -95,14 +95,82 @@ function normalizeString(path, allowAboveRoot, separator) { } if (allowAboveRoot) { if (res.length > 0) - res += `${separator}..`; + res += '\\..'; else res = '..'; lastSegmentLength = 2; } } else { if (res.length > 0) - res += separator + path.slice(lastSlash + 1, i); + res += '\\' + path.slice(lastSlash + 1, i); + else + res = path.slice(lastSlash + 1, i); + lastSegmentLength = i - lastSlash - 1; + } + lastSlash = i; + dots = 0; + } else if (code === CHAR_DOT && dots !== -1) { + ++dots; + } else { + dots = -1; + } + } + return res; +} + +// Resolves . and .. elements in a path with directory names +function normalizeStringPosix(path, allowAboveRoot) { + let res = ''; + let lastSegmentLength = 0; + let lastSlash = -1; + let dots = 0; + let code; + for (var i = 0; i <= path.length; ++i) { + if (i < path.length) + code = path.charCodeAt(i); + else if (code === CHAR_FORWARD_SLASH) + break; + else + 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) !== CHAR_DOT || + res.charCodeAt(res.length - 2) !== CHAR_DOT) { + if (res.length > 2) { + const lastSlashIndex = res.lastIndexOf('/'); + if (lastSlashIndex !== res.length - 1) { + if (lastSlashIndex === -1) { + res = ''; + lastSegmentLength = 0; + } else { + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf('/'); + } + lastSlash = i; + dots = 0; + continue; + } + } else if (res.length === 2 || res.length === 1) { + res = ''; + lastSegmentLength = 0; + lastSlash = i; + dots = 0; + continue; + } + } + if (allowAboveRoot) { + if (res.length > 0) + res += '/..'; + else + res = '..'; + lastSegmentLength = 2; + } + } else { + if (res.length > 0) + res += '/' + path.slice(lastSlash + 1, i); else res = path.slice(lastSlash + 1, i); lastSegmentLength = i - lastSlash - 1; @@ -134,12 +202,12 @@ function _format(sep, pathObject) { const win32 = { // path.resolve([from ...], to) resolve: function resolve() { - var resolvedDevice = ''; - var resolvedTail = ''; - var resolvedAbsolute = false; + let resolvedDevice = ''; + let resolvedTail = ''; + let resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1; i--) { - var path; + let path; if (i >= 0) { path = arguments[i]; } else if (!resolvedDevice) { @@ -168,10 +236,10 @@ const win32 = { continue; } - var len = path.length; - var rootEnd = 0; - var device = ''; - var isAbsolute = false; + const len = path.length; + let rootEnd = 0; + let device = ''; + let isAbsolute = false; const code = path.charCodeAt(0); // Try to match a root @@ -185,8 +253,8 @@ const win32 = { if (isPathSeparator(path.charCodeAt(1))) { // Matched double path separator at beginning - var j = 2; - var last = j; + let j = 2; + let last = j; // Match 1 or more non-path separators for (; j < len; ++j) { if (isPathSeparator(path.charCodeAt(j))) @@ -272,7 +340,7 @@ const win32 = { // fails) // Normalize the tail path - resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\'); + resolvedTail = normalizeStringWin32(resolvedTail, !resolvedAbsolute); return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || '.'; @@ -283,9 +351,9 @@ const win32 = { const len = path.length; if (len === 0) return '.'; - var rootEnd = 0; - var device; - var isAbsolute = false; + let rootEnd = 0; + let device; + let isAbsolute = false; const code = path.charCodeAt(0); // Try to match a root @@ -299,8 +367,8 @@ const win32 = { if (isPathSeparator(path.charCodeAt(1))) { // Matched double path separator at beginning - var j = 2; - var last = j; + let j = 2; + let last = j; // Match 1 or more non-path separators for (; j < len; ++j) { if (isPathSeparator(path.charCodeAt(j))) @@ -362,9 +430,9 @@ const win32 = { return '\\'; } - var tail; + let tail; if (rootEnd < len) - tail = normalizeString(path.slice(rootEnd), !isAbsolute, '\\'); + tail = normalizeStringWin32(path.slice(rootEnd), !isAbsolute); else tail = ''; if (tail.length === 0 && !isAbsolute) @@ -420,10 +488,10 @@ const win32 = { if (arguments.length === 0) return '.'; - var joined; - var firstPart; + let joined; + let firstPart; for (var i = 0; i < arguments.length; ++i) { - var arg = arguments[i]; + const arg = arguments[i]; assertPath(arg); if (arg.length > 0) { if (joined === undefined) @@ -449,8 +517,8 @@ const win32 = { // This means that the user can use join to construct UNC paths from // a server name and a share name; for example: // path.join('//server', 'share') -> '\\\\server\\share\\') - var needsReplace = true; - var slashCount = 0; + let needsReplace = true; + let slashCount = 0; if (isPathSeparator(firstPart.charCodeAt(0))) { ++slashCount; const firstLen = firstPart.length; @@ -495,8 +563,8 @@ const win32 = { if (from === to) return ''; - var fromOrig = win32.resolve(from); - var toOrig = win32.resolve(to); + const fromOrig = win32.resolve(from); + const toOrig = win32.resolve(to); if (fromOrig === toOrig) return ''; @@ -508,37 +576,37 @@ const win32 = { return ''; // Trim any leading backslashes - var fromStart = 0; + let fromStart = 0; for (; fromStart < from.length; ++fromStart) { if (from.charCodeAt(fromStart) !== CHAR_BACKWARD_SLASH) break; } // Trim trailing backslashes (applicable to UNC paths only) - var fromEnd = from.length; + let fromEnd = from.length; for (; fromEnd - 1 > fromStart; --fromEnd) { if (from.charCodeAt(fromEnd - 1) !== CHAR_BACKWARD_SLASH) break; } - var fromLen = (fromEnd - fromStart); + const fromLen = (fromEnd - fromStart); // Trim any leading backslashes - var toStart = 0; + let toStart = 0; for (; toStart < to.length; ++toStart) { if (to.charCodeAt(toStart) !== CHAR_BACKWARD_SLASH) break; } // Trim trailing backslashes (applicable to UNC paths only) - var toEnd = to.length; + let toEnd = to.length; for (; toEnd - 1 > toStart; --toEnd) { if (to.charCodeAt(toEnd - 1) !== CHAR_BACKWARD_SLASH) break; } - var toLen = (toEnd - toStart); + const toLen = (toEnd - toStart); // Compare paths to find the longest common path from root - var length = (fromLen < toLen ? fromLen : toLen); - var lastCommonSep = -1; - var i = 0; + const length = (fromLen < toLen ? fromLen : toLen); + let lastCommonSep = -1; + let i = 0; for (; i <= length; ++i) { if (i === length) { if (toLen > length) { @@ -565,8 +633,8 @@ const win32 = { } break; } - var fromCode = from.charCodeAt(fromStart + i); - var toCode = to.charCodeAt(toStart + i); + const fromCode = from.charCodeAt(fromStart + i); + const toCode = to.charCodeAt(toStart + i); if (fromCode !== toCode) break; else if (fromCode === CHAR_BACKWARD_SLASH) @@ -579,7 +647,7 @@ const win32 = { return toOrig; } - var out = ''; + let out = ''; if (lastCommonSep === -1) lastCommonSep = 0; // Generate the relative path based on the path difference between `to` and @@ -647,10 +715,10 @@ const win32 = { const len = path.length; if (len === 0) return '.'; - var rootEnd = -1; - var end = -1; - var matchedSlash = true; - var offset = 0; + let rootEnd = -1; + let end = -1; + let matchedSlash = true; + let offset = 0; const code = path.charCodeAt(0); // Try to match a root @@ -662,8 +730,8 @@ const win32 = { if (isPathSeparator(path.charCodeAt(1))) { // Matched double path separator at beginning - var j = 2; - var last = j; + let j = 2; + let last = j; // Match 1 or more non-path separators for (; j < len; ++j) { if (isPathSeparator(path.charCodeAt(j))) @@ -742,10 +810,10 @@ const win32 = { if (ext !== undefined && typeof ext !== 'string') throw new ERR_INVALID_ARG_TYPE('ext', 'string'); assertPath(path); - var start = 0; - var end = -1; - var matchedSlash = true; - var i; + let start = 0; + let end = -1; + let matchedSlash = true; + let i; // 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 @@ -761,8 +829,8 @@ const win32 = { if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { if (ext.length === path.length && ext === path) return ''; - var extIdx = ext.length - 1; - var firstNonSlashEnd = -1; + let extIdx = ext.length - 1; + let firstNonSlashEnd = -1; for (i = path.length - 1; i >= start; --i) { const code = path.charCodeAt(i); if (isPathSeparator(code)) { @@ -828,14 +896,14 @@ const win32 = { extname: function extname(path) { assertPath(path); - var start = 0; - var startDot = -1; - var startPart = 0; - var end = -1; - var matchedSlash = true; + let start = 0; + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; // Track the state of characters (if any) we see before our first dot and // after any path separator we find - var preDotState = 0; + let preDotState = 0; // 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 @@ -902,12 +970,12 @@ const win32 = { parse: function parse(path) { assertPath(path); - var ret = { root: '', dir: '', base: '', ext: '', name: '' }; + const ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) return ret; - var len = path.length; - var rootEnd = 0; + const len = path.length; + let rootEnd = 0; let code = path.charCodeAt(0); // Try to match a root @@ -918,8 +986,8 @@ const win32 = { rootEnd = 1; if (isPathSeparator(path.charCodeAt(1))) { // Matched double path separator at beginning - var j = 2; - var last = j; + let j = 2; + let last = j; // Match 1 or more non-path separators for (; j < len; ++j) { if (isPathSeparator(path.charCodeAt(j))) @@ -986,15 +1054,15 @@ const win32 = { if (rootEnd > 0) ret.root = path.slice(0, rootEnd); - var startDot = -1; - var startPart = rootEnd; - var end = -1; - var matchedSlash = true; - var i = path.length - 1; + let startDot = -1; + let startPart = rootEnd; + let end = -1; + let matchedSlash = true; + let i = path.length - 1; // Track the state of characters (if any) we see before our first dot and // after any path separator we find - var preDotState = 0; + let preDotState = 0; // Get non-dir info for (; i >= rootEnd; --i) { @@ -1066,12 +1134,12 @@ const win32 = { const posix = { // path.resolve([from ...], to) resolve: function resolve() { - var resolvedPath = ''; - var resolvedAbsolute = false; - var cwd; + let resolvedPath = ''; + let resolvedAbsolute = false; + let cwd; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path; + let path; if (i >= 0) path = arguments[i]; else { @@ -1095,7 +1163,7 @@ const posix = { // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path - resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/'); + resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute); if (resolvedAbsolute) { if (resolvedPath.length > 0) @@ -1121,7 +1189,7 @@ const posix = { path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH; // Normalize the path - path = normalizeString(path, !isAbsolute, '/'); + path = normalizeStringPosix(path, !isAbsolute); if (path.length === 0 && !isAbsolute) path = '.'; @@ -1143,9 +1211,9 @@ const posix = { join: function join() { if (arguments.length === 0) return '.'; - var joined; + let joined; for (var i = 0; i < arguments.length; ++i) { - var arg = arguments[i]; + const arg = arguments[i]; assertPath(arg); if (arg.length > 0) { if (joined === undefined) @@ -1174,27 +1242,27 @@ const posix = { return ''; // Trim any leading backslashes - var fromStart = 1; + let fromStart = 1; for (; fromStart < from.length; ++fromStart) { if (from.charCodeAt(fromStart) !== CHAR_FORWARD_SLASH) break; } - var fromEnd = from.length; - var fromLen = (fromEnd - fromStart); + const fromEnd = from.length; + const fromLen = (fromEnd - fromStart); // Trim any leading backslashes - var toStart = 1; + let toStart = 1; for (; toStart < to.length; ++toStart) { if (to.charCodeAt(toStart) !== CHAR_FORWARD_SLASH) break; } - var toEnd = to.length; - var toLen = (toEnd - toStart); + const toEnd = to.length; + const toLen = (toEnd - toStart); // Compare paths to find the longest common path from root - var length = (fromLen < toLen ? fromLen : toLen); - var lastCommonSep = -1; - var i = 0; + const length = (fromLen < toLen ? fromLen : toLen); + let lastCommonSep = -1; + let i = 0; for (; i <= length; ++i) { if (i === length) { if (toLen > length) { @@ -1220,15 +1288,15 @@ const posix = { } break; } - var fromCode = from.charCodeAt(fromStart + i); - var toCode = to.charCodeAt(toStart + i); + const fromCode = from.charCodeAt(fromStart + i); + const toCode = to.charCodeAt(toStart + i); if (fromCode !== toCode) break; else if (fromCode === CHAR_FORWARD_SLASH) lastCommonSep = i; } - var out = ''; + let out = ''; // Generate the relative path based on the path difference between `to` // and `from` for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { @@ -1263,8 +1331,8 @@ const posix = { if (path.length === 0) return '.'; const hasRoot = path.charCodeAt(0) === CHAR_FORWARD_SLASH; - var end = -1; - var matchedSlash = true; + let end = -1; + let matchedSlash = true; for (var i = path.length - 1; i >= 1; --i) { if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) { if (!matchedSlash) { @@ -1290,16 +1358,16 @@ const posix = { throw new ERR_INVALID_ARG_TYPE('ext', 'string'); assertPath(path); - var start = 0; - var end = -1; - var matchedSlash = true; - var i; + let start = 0; + let end = -1; + let matchedSlash = true; + let i; if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { if (ext.length === path.length && ext === path) return ''; - var extIdx = ext.length - 1; - var firstNonSlashEnd = -1; + let extIdx = ext.length - 1; + let firstNonSlashEnd = -1; for (i = path.length - 1; i >= 0; --i) { const code = path.charCodeAt(i); if (code === CHAR_FORWARD_SLASH) { @@ -1365,13 +1433,13 @@ const posix = { extname: function extname(path) { assertPath(path); - var startDot = -1; - var startPart = 0; - var end = -1; - var matchedSlash = true; + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; // Track the state of characters (if any) we see before our first dot and // after any path separator we find - var preDotState = 0; + let preDotState = 0; for (var i = path.length - 1; i >= 0; --i) { const code = path.charCodeAt(i); if (code === CHAR_FORWARD_SLASH) { @@ -1427,26 +1495,26 @@ const posix = { parse: function parse(path) { assertPath(path); - var ret = { root: '', dir: '', base: '', ext: '', name: '' }; + const ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) return ret; - var isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; - var start; + const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH; + let start; if (isAbsolute) { ret.root = '/'; start = 1; } else { start = 0; } - var startDot = -1; - var startPart = 0; - var end = -1; - var matchedSlash = true; - var i = path.length - 1; + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + let i = path.length - 1; // Track the state of characters (if any) we see before our first dot and // after any path separator we find - var preDotState = 0; + let preDotState = 0; // Get non-dir info for (; i >= start; --i) { diff --git a/lib/querystring.js b/lib/querystring.js index 3bedd493f4b34f..95458bd258ebcc 100644 --- a/lib/querystring.js +++ b/lib/querystring.js @@ -64,16 +64,16 @@ const unhexTable = [ ]; // a safe fast alternative to decodeURIComponent function unescapeBuffer(s, decodeSpaces) { - var out = Buffer.allocUnsafe(s.length); - var index = 0; - var outIndex = 0; - var currentChar; - var nextChar; - var hexHigh; - var hexLow; - var maxLength = s.length - 2; + const out = Buffer.allocUnsafe(s.length); + let index = 0; + let outIndex = 0; + let currentChar; + let nextChar; + let hexHigh; + let hexLow; + const maxLength = s.length - 2; // Flag to know if some hex chars have been decoded - var hasHex = false; + let hasHex = false; while (index < s.length) { currentChar = s.charCodeAt(index); if (currentChar === 43 /*'+'*/ && decodeSpaces) { @@ -140,11 +140,11 @@ function qsEscape(str) { else str += ''; } - var out = ''; - var lastPos = 0; + let out = ''; + let lastPos = 0; for (var i = 0; i < str.length; ++i) { - var c = str.charCodeAt(i); + let c = str.charCodeAt(i); // ASCII if (c < 0x80) { @@ -179,7 +179,7 @@ function qsEscape(str) { if (i >= str.length) throw new ERR_INVALID_URI(); - var c2 = str.charCodeAt(i) & 0x3FF; + const c2 = str.charCodeAt(i) & 0x3FF; lastPos = i + 1; c = 0x10000 + (((c & 0x3FF) << 10) | c2); @@ -206,28 +206,25 @@ function stringifyPrimitive(v) { } -function stringify(obj, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - - var encode = QueryString.escape; +function stringify(obj, sep = '&', eq = '=', options) { + let encode = QueryString.escape; if (options && typeof options.encodeURIComponent === 'function') { encode = options.encodeURIComponent; } if (obj !== null && typeof obj === 'object') { - var keys = Object.keys(obj); - var len = keys.length; - var flast = len - 1; - var fields = ''; + const keys = Object.keys(obj); + const len = keys.length; + const flast = len - 1; + let fields = ''; for (var i = 0; i < len; ++i) { - var k = keys[i]; - var v = obj[k]; - var ks = encode(stringifyPrimitive(k)) + eq; + const k = keys[i]; + const v = obj[k]; + const ks = encode(stringifyPrimitive(k)) + eq; if (Array.isArray(v)) { - var vlen = v.length; - var vlast = vlen - 1; + const vlen = v.length; + const vlast = vlen - 1; for (var j = 0; j < vlen; ++j) { fields += ks + encode(stringifyPrimitive(v[j])); if (j < vlast) @@ -265,12 +262,12 @@ function parse(qs, sep, eq, options) { return obj; } - var sepCodes = (!sep ? defSepCodes : charCodes(sep + '')); - var eqCodes = (!eq ? defEqCodes : charCodes(eq + '')); + const sepCodes = (!sep ? defSepCodes : charCodes(sep + '')); + const eqCodes = (!eq ? defEqCodes : charCodes(eq + '')); const sepLen = sepCodes.length; const eqLen = eqCodes.length; - var pairs = 1000; + let pairs = 1000; if (options && typeof options.maxKeys === 'number') { // -1 is used in place of a value like Infinity for meaning // "unlimited pairs" because of additional checks V8 (at least as of v5.4) @@ -281,21 +278,21 @@ function parse(qs, sep, eq, options) { pairs = (options.maxKeys > 0 ? options.maxKeys : -1); } - var decode = QueryString.unescape; + let decode = QueryString.unescape; if (options && typeof options.decodeURIComponent === 'function') { decode = options.decodeURIComponent; } const customDecode = (decode !== qsUnescape); - var lastPos = 0; - var sepIdx = 0; - var eqIdx = 0; - var key = ''; - var value = ''; - var keyEncoded = customDecode; - var valEncoded = customDecode; + let lastPos = 0; + let sepIdx = 0; + let eqIdx = 0; + let key = ''; + let value = ''; + let keyEncoded = customDecode; + let valEncoded = customDecode; const plusChar = (customDecode ? '%20' : ' '); - var encodeCheck = 0; + let encodeCheck = 0; for (var i = 0; i < qs.length; ++i) { const code = qs.charCodeAt(i); diff --git a/lib/readline.js b/lib/readline.js index 124fc8111b2f09..72c666f0dfe7d4 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -79,8 +79,8 @@ function Interface(input, output, completer, terminal) { this._previousKey = null; EventEmitter.call(this); - var historySize; - var removeHistoryDuplicates = false; + let historySize; + let removeHistoryDuplicates = false; let crlfDelay; let prompt = '> '; @@ -118,7 +118,7 @@ function Interface(input, output, completer, terminal) { terminal = !!output.isTTY; } - var self = this; + const self = this; this.output = output; this.input = input; @@ -227,7 +227,7 @@ Object.defineProperty(Interface.prototype, 'columns', { configurable: true, enumerable: true, get: function() { - var columns = Infinity; + let columns = Infinity; if (this.output && this.output.columns) columns = this.output.columns; return columns; @@ -277,7 +277,7 @@ Interface.prototype.question = function(query, cb) { Interface.prototype._onLine = function(line) { if (this._questionCallback) { - var cb = this._questionCallback; + const cb = this._questionCallback; this._questionCallback = null; this.setPrompt(this._oldPrompt); cb(line); @@ -325,16 +325,16 @@ Interface.prototype._addHistory = function() { Interface.prototype._refreshLine = function() { // line length - var line = this._prompt + this.line; - var dispPos = this._getDisplayPos(line); - var lineCols = dispPos.cols; - var lineRows = dispPos.rows; + const line = this._prompt + this.line; + const dispPos = this._getDisplayPos(line); + const lineCols = dispPos.cols; + const lineRows = dispPos.rows; // cursor position - var cursorPos = this._getCursorPos(); + const cursorPos = this._getCursorPos(); // first move to the bottom of the current line, based on cursor pos - var prevRows = this.prevRows || 0; + const prevRows = this.prevRows || 0; if (prevRows > 0) { moveCursor(this.output, 0, -prevRows); } @@ -355,7 +355,7 @@ Interface.prototype._refreshLine = function() { // Move cursor to original position. cursorTo(this.output, cursorPos.cols); - var diff = lineRows - cursorPos.rows; + const diff = lineRows - cursorPos.rows; if (diff > 0) { moveCursor(this.output, 0, -diff); } @@ -402,7 +402,7 @@ Interface.prototype._normalWrite = function(b) { if (b === undefined) { return; } - var string = this._decoder.write(b); + let string = this._decoder.write(b); if (this._sawReturnAt && Date.now() - this._sawReturnAt <= this.crlfDelay) { string = string.replace(/^\n/, ''); @@ -410,7 +410,7 @@ Interface.prototype._normalWrite = function(b) { } // Run test() on the new string chunk, not on the entire line buffer. - var newPartContainsEnding = lineEnding.test(string); + const newPartContainsEnding = lineEnding.test(string); if (this._line_buffer) { string = this._line_buffer + string; @@ -420,7 +420,7 @@ Interface.prototype._normalWrite = function(b) { this._sawReturnAt = string.endsWith('\r') ? Date.now() : 0; // got one or more newlines; process into "line" events - var lines = string.split(lineEnding); + const lines = string.split(lineEnding); // either '' or (conceivably) the unfinished portion of the next line string = lines.pop(); this._line_buffer = string; @@ -434,8 +434,8 @@ Interface.prototype._normalWrite = function(b) { Interface.prototype._insertString = function(c) { if (this.cursor < this.line.length) { - var beg = this.line.slice(0, this.cursor); - var end = this.line.slice(this.cursor, this.line.length); + const beg = this.line.slice(0, this.cursor); + const end = this.line.slice(this.cursor, this.line.length); this.line = beg + c + end; this.cursor += c.length; this._refreshLine(); @@ -455,7 +455,7 @@ Interface.prototype._insertString = function(c) { }; Interface.prototype._tabComplete = function(lastKeypressWasTab) { - var self = this; + const self = this; self.pause(); self.completer(self.line.slice(0, self.cursor), function onComplete(err, rv) { @@ -472,16 +472,16 @@ Interface.prototype._tabComplete = function(lastKeypressWasTab) { // Apply/show completions. if (lastKeypressWasTab) { self._writeToOutput('\r\n'); - var width = completions.reduce(function completionReducer(a, b) { + const width = completions.reduce(function completionReducer(a, b) { return a.length > b.length ? a : b; }).length + 2; // 2 space padding - var maxColumns = Math.floor(self.columns / width); + let maxColumns = Math.floor(self.columns / width); if (!maxColumns || maxColumns === Infinity) { maxColumns = 1; } - var group = []; + const group = []; for (var i = 0; i < completions.length; i++) { - var c = completions[i]; + const c = completions[i]; if (c === '') { handleGroup(self, group, width, maxColumns); group = []; @@ -493,8 +493,8 @@ Interface.prototype._tabComplete = function(lastKeypressWasTab) { } // If there is a common prefix to all matches, then apply that portion. - var f = completions.filter((e) => e); - var prefix = commonPrefix(f); + const f = completions.filter((e) => e); + const prefix = commonPrefix(f); if (prefix.length > completeOn.length) { self._insertString(prefix.slice(completeOn.length)); } @@ -509,14 +509,14 @@ function handleGroup(self, group, width, maxColumns) { if (group.length === 0) { return; } - var minRows = Math.ceil(group.length / maxColumns); + const minRows = Math.ceil(group.length / maxColumns); for (var row = 0; row < minRows; row++) { for (var col = 0; col < maxColumns; col++) { - var idx = row * maxColumns + col; + const idx = row * maxColumns + col; if (idx >= group.length) { break; } - var item = group[idx]; + const item = group[idx]; self._writeToOutput(item); if (col < maxColumns - 1) { for (var s = 0; s < width - item.length; s++) { @@ -534,9 +534,9 @@ function commonPrefix(strings) { return ''; } if (strings.length === 1) return strings[0]; - var sorted = strings.slice().sort(); - var min = sorted[0]; - var max = sorted[sorted.length - 1]; + const sorted = strings.slice().sort(); + const min = sorted[0]; + const max = sorted[sorted.length - 1]; for (var i = 0, len = min.length; i < len; i++) { if (min[i] !== max[i]) { return min.slice(0, i); @@ -548,8 +548,8 @@ function commonPrefix(strings) { Interface.prototype._wordLeft = function() { if (this.cursor > 0) { - var leading = this.line.slice(0, this.cursor); - var match = leading.match(/(?:[^\w\s]+|\w+|)\s*$/); + const leading = this.line.slice(0, this.cursor); + const match = leading.match(/(?:[^\w\s]+|\w+|)\s*$/); this._moveCursor(-match[0].length); } }; @@ -557,8 +557,8 @@ Interface.prototype._wordLeft = function() { Interface.prototype._wordRight = function() { if (this.cursor < this.line.length) { - var trailing = this.line.slice(this.cursor); - var match = trailing.match(/^(?:\s+|\W+|\w+)\s*/); + const trailing = this.line.slice(this.cursor); + const match = trailing.match(/^(?:\s+|\W+|\w+)\s*/); this._moveCursor(match[0].length); } }; @@ -584,8 +584,8 @@ Interface.prototype._deleteRight = function() { Interface.prototype._deleteWordLeft = function() { if (this.cursor > 0) { - var leading = this.line.slice(0, this.cursor); - var match = leading.match(/(?:[^\w\s]+|\w+|)\s*$/); + let leading = this.line.slice(0, this.cursor); + const match = leading.match(/(?:[^\w\s]+|\w+|)\s*$/); leading = leading.slice(0, leading.length - match[0].length); this.line = leading + this.line.slice(this.cursor, this.line.length); this.cursor = leading.length; @@ -596,8 +596,8 @@ Interface.prototype._deleteWordLeft = function() { Interface.prototype._deleteWordRight = function() { if (this.cursor < this.line.length) { - var trailing = this.line.slice(this.cursor); - var match = trailing.match(/^(?:\s+|\W+|\w+)\s*/); + const trailing = this.line.slice(this.cursor); + const match = trailing.match(/^(?:\s+|\W+|\w+)\s*/); this.line = this.line.slice(0, this.cursor) + trailing.slice(match[0].length); this._refreshLine(); @@ -628,7 +628,7 @@ Interface.prototype.clearLine = function() { Interface.prototype._line = function() { - var line = this._addHistory(); + const line = this._addHistory(); this.clearLine(); this._onLine(line); }; @@ -663,10 +663,10 @@ Interface.prototype._historyPrev = function() { // Returns the last character's display position of the given string Interface.prototype._getDisplayPos = function(str) { - var offset = 0; - var col = this.columns; - var row = 0; - var code; + let offset = 0; + const col = this.columns; + let row = 0; + let code; str = stripVTControlCharacters(str); for (var i = 0, len = str.length; i < len; i++) { code = str.codePointAt(i); @@ -688,19 +688,19 @@ Interface.prototype._getDisplayPos = function(str) { offset += 2; } } - var cols = offset % col; - var rows = row + (offset - cols) / col; + const cols = offset % col; + const rows = row + (offset - cols) / col; return { cols: cols, rows: rows }; }; // Returns current cursor's position and line Interface.prototype._getCursorPos = function() { - var columns = this.columns; - var strBeforeCursor = this._prompt + this.line.substring(0, this.cursor); - var dispPos = this._getDisplayPos(stripVTControlCharacters(strBeforeCursor)); - var cols = dispPos.cols; - var rows = dispPos.rows; + const columns = this.columns; + const strBeforeCursor = this._prompt + this.line.substring(0, this.cursor); + const dispPos = this._getDisplayPos(stripVTControlCharacters(strBeforeCursor)); + let cols = dispPos.cols; + let rows = dispPos.rows; // If the cursor is on a full-width character which steps over the line, // move the cursor to the beginning of the next line. if (cols + 1 === columns && @@ -716,20 +716,20 @@ Interface.prototype._getCursorPos = function() { // This function moves cursor dx places to the right // (-dx for left) and refreshes the line if it is needed Interface.prototype._moveCursor = function(dx) { - var oldcursor = this.cursor; - var oldPos = this._getCursorPos(); + const oldcursor = this.cursor; + const oldPos = this._getCursorPos(); this.cursor += dx; // bounds check if (this.cursor < 0) this.cursor = 0; else if (this.cursor > this.line.length) this.cursor = this.line.length; - var newPos = this._getCursorPos(); + const newPos = this._getCursorPos(); // check if cursors are in the same line if (oldPos.rows === newPos.rows) { - var diffCursor = this.cursor - oldcursor; - var diffWidth; + const diffCursor = this.cursor - oldcursor; + let diffWidth; if (diffCursor < 0) { diffWidth = -getStringWidth( this.line.substring(this.cursor, oldcursor) @@ -969,7 +969,7 @@ Interface.prototype._ttyWrite = function(s, key) { s = s.toString('utf-8'); if (s) { - var lines = s.split(/\r\n|\n|\r/); + const lines = s.split(/\r\n|\n|\r/); for (var i = 0, len = lines.length; i < len; i++) { if (i > 0) { this._line(); @@ -997,7 +997,7 @@ function emitKeypressEvents(stream, iface) { function onData(b) { if (stream.listenerCount('keypress') > 0) { - var r = stream[KEYPRESS_DECODER].write(b); + const r = stream[KEYPRESS_DECODER].write(b); if (r) { clearTimeout(timeoutId); diff --git a/lib/repl.js b/lib/repl.js index 06703da131c301..f7ecf55e7756c6 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -42,11 +42,7 @@ 'use strict'; -const { - builtinLibs, - makeRequireFunction, - addBuiltinLibsToObject -} = require('internal/modules/cjs/helpers'); +const internalModule = require('internal/module'); const { processTopLevelAwait } = require('internal/repl/await'); const internalUtil = require('internal/util'); const { isTypedArray } = require('internal/util/types'); @@ -59,7 +55,7 @@ const path = require('path'); const fs = require('fs'); const { Interface } = require('readline'); const { Console } = require('console'); -const CJSModule = require('internal/modules/cjs/loader'); +const Module = require('module'); const domain = require('domain'); const debug = util.debuglog('repl'); const { @@ -100,7 +96,7 @@ try { } // Hack for repl require to work properly with node_modules folders -module.paths = CJSModule._nodeModulePaths(module.filename); +module.paths = Module._nodeModulePaths(module.filename); // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. @@ -116,7 +112,7 @@ writer.options = Object.assign({}, util.inspect.defaultOptions, { showProxy: true, depth: 2 }); -exports._builtinLibs = builtinLibs; +exports._builtinLibs = internalModule.builtinLibs; function REPLServer(prompt, stream, @@ -133,7 +129,7 @@ function REPLServer(prompt, replMode); } - var options, input, output, dom, breakEvalOnSigint; + let options, input, output, dom, breakEvalOnSigint; if (prompt !== null && typeof prompt === 'object') { // an options object was given options = prompt; @@ -157,7 +153,7 @@ function REPLServer(prompt, throw new ERR_INVALID_REPL_EVAL_CONFIG(); } - var self = this; + const self = this; self._domain = dom || domain.create(); self.useGlobal = !!useGlobal; @@ -212,10 +208,10 @@ function REPLServer(prompt, } function defaultEval(code, context, file, cb) { - var err, result, script, wrappedErr; - var wrappedCmd = false; - var awaitPromise = false; - var input = code; + let err, result, script, wrappedErr; + let wrappedCmd = false; + let awaitPromise = false; + const input = code; if (/^\s*\{/.test(code) && /\}\s*$/.test(code)) { // It's confusing for `{ a : 1 }` to be interpreted as a block @@ -507,7 +503,7 @@ function REPLServer(prompt, } function _parseREPLKeyword(keyword, rest) { - var cmd = this.commands[keyword]; + const cmd = this.commands[keyword]; if (cmd) { cmd.action.call(this, rest); return true; @@ -528,8 +524,8 @@ function REPLServer(prompt, self.emit('exit'); }); - var sawSIGINT = false; - var sawCtrlD = false; + let sawSIGINT = false; + let sawCtrlD = false; const prioritizedSigintQueue = new Set(); self.on('SIGINT', function onSigInt() { if (prioritizedSigintQueue.size > 0) { @@ -539,7 +535,7 @@ function REPLServer(prompt, return; } - var empty = self.line.length === 0; + const empty = self.line.length === 0; self.clearLine(); _turnOffEditorMode(self); @@ -729,7 +725,7 @@ exports.start = function(prompt, useGlobal, ignoreUndefined, replMode) { - var repl = new REPLServer(prompt, + const repl = new REPLServer(prompt, source, eval_, useGlobal, @@ -759,7 +755,7 @@ REPLServer.prototype.close = function close() { }; REPLServer.prototype.createContext = function() { - var context; + let context; if (this.useGlobal) { context = global; } else { @@ -781,9 +777,9 @@ REPLServer.prototype.createContext = function() { value: _console }); - var names = Object.getOwnPropertyNames(global); + const names = Object.getOwnPropertyNames(global); for (var n = 0; n < names.length; n++) { - var name = names[n]; + const name = names[n]; if (name === 'console' || name === 'global') continue; if (GLOBAL_OBJECT_PROPERTY_MAP[name] === undefined) { @@ -793,15 +789,14 @@ REPLServer.prototype.createContext = function() { } } - var module = new CJSModule(''); - module.paths = - CJSModule._resolveLookupPaths('', parentModule, true) || []; + const module = new Module(''); + module.paths = Module._resolveLookupPaths('', parentModule, true) || []; - var require = makeRequireFunction(module); + const require = internalModule.makeRequireFunction(module); context.module = module; context.require = require; - addBuiltinLibsToObject(context); + internalModule.addBuiltinLibsToObject(context); return context; }; @@ -843,7 +838,7 @@ REPLServer.prototype.resetContext = function() { }; REPLServer.prototype.displayPrompt = function(preserveCursor) { - var prompt = this._initialPrompt; + let prompt = this._initialPrompt; if (this[kBufferedCommandSymbol].length) { prompt = '...'; const len = this.lines.level.length ? this.lines.level.length - 1 : 0; @@ -953,16 +948,16 @@ function complete(line, callback) { if (this[kBufferedCommandSymbol] !== undefined && this[kBufferedCommandSymbol].length) { // Get a new array of inputted lines - var tmp = this.lines.slice(); + const tmp = this.lines.slice(); // Kill off all function declarations to push all local variables into // global scope for (var n = 0; n < this.lines.level.length; n++) { - var kill = this.lines.level[n]; + const kill = this.lines.level[n]; if (kill.isFunction) tmp[kill.line] = ''; } - var flat = new ArrayStream(); // make a new "input" stream - var magic = new REPLServer('', flat); // make a nested REPL + const flat = new ArrayStream(); // make a new "input" stream + const magic = new REPLServer('', flat); // make a nested REPL replMap.set(magic, replMap.get(this)); flat.run(tmp); // eval the flattened code // all this is only profitable if the nested REPL @@ -972,14 +967,14 @@ function complete(line, callback) { } } - var completions; + let completions; // List of completion lists, one for each inheritance "level" - var completionGroups = []; - var completeOn, i, group, c; + const completionGroups = []; + let completeOn, i, group, c; // REPL commands (e.g. ".break"). - var filter; - var match = null; + let filter; + let match = null; match = line.match(/^\s*\.(\w*)$/); if (match) { completionGroups.push(Object.keys(this.commands)); @@ -992,14 +987,14 @@ function complete(line, callback) { } else if (match = line.match(requireRE)) { // require('...') const exts = Object.keys(this.context.require.extensions); - var indexRe = new RegExp('^index(?:' + exts.map(regexpEscape).join('|') + + const indexRe = new RegExp('^index(?:' + exts.map(regexpEscape).join('|') + ')$'); - var versionedFileNamesRe = /-\d+\.\d+/; + const versionedFileNamesRe = /-\d+\.\d+/; completeOn = match[1]; - var subdir = match[2] || ''; + const subdir = match[2] || ''; filter = match[1]; - var dir, files, f, name, base, ext, abs, subfiles, s, isDirectory; + let dir, files, f, name, base, ext, abs, subfiles, s, isDirectory; group = []; let paths = []; @@ -1010,7 +1005,7 @@ function complete(line, callback) { } else if (/^\.\.?\//.test(completeOn)) { paths = [process.cwd()]; } else { - paths = module.paths.concat(CJSModule.globalPaths); + paths = module.paths.concat(Module.globalPaths); } for (i = 0; i < paths.length; i++) { @@ -1074,7 +1069,7 @@ function complete(line, callback) { } else if (line.length === 0 || /\w|\.|\$/.test(line[line.length - 1])) { match = simpleExpressionRE.exec(line); if (line.length === 0 || match) { - var expr; + let expr; completeOn = (match ? match[0] : ''); if (line.length === 0) { filter = ''; @@ -1083,19 +1078,19 @@ function complete(line, callback) { filter = ''; expr = match[0].slice(0, match[0].length - 1); } else { - var bits = match[0].split('.'); + const bits = match[0].split('.'); filter = bits.pop(); expr = bits.join('.'); } // Resolve expr and get its completions. - var memberGroups = []; + const memberGroups = []; if (!expr) { // If context is instance of vm.ScriptContext // Get global vars synchronously if (this.useGlobal || vm.isContext(this.context)) { completionGroups.push(getGlobalLexicalScopeNames(this[kContextId])); - var contextProto = this.context; + const contextProto = this.context; while (contextProto = Object.getPrototypeOf(contextProto)) { completionGroups.push( filteredOwnPropertyNames.call(this, contextProto)); @@ -1135,8 +1130,8 @@ function complete(line, callback) { } // works for non-objects try { - var sentinel = 5; - var p; + let sentinel = 5; + let p; if (typeof obj === 'object' || typeof obj === 'function') { p = Object.getPrototypeOf(obj); } else { @@ -1179,7 +1174,7 @@ function complete(line, callback) { function completionGroupsLoaded() { // Filter, sort (within each group), uniq and merge the completion groups. if (completionGroups.length && filter) { - var newCompletionGroups = []; + const newCompletionGroups = []; for (i = 0; i < completionGroups.length; i++) { group = completionGroups[i] .filter((elem) => elem.indexOf(filter) === 0); @@ -1191,7 +1186,7 @@ function complete(line, callback) { } if (completionGroups.length) { - var uniq = {}; // Unique completions across all groups + const uniq = {}; // Unique completions across all groups completions = []; // Completion group 0 is the "closest" // (least far up the inheritance chain) @@ -1286,11 +1281,11 @@ function _memory(cmd) { if (cmd) { // Going down is { and ( e.g. function() { // going up is } and ) - var dw = cmd.match(/{|\(/g); - var up = cmd.match(/}|\)/g); + let dw = cmd.match(/{|\(/g); + let up = cmd.match(/}|\)/g); up = up ? up.length : 0; dw = dw ? dw.length : 0; - var depth = dw - up; + let depth = dw - up; if (depth) { (function workIt() { @@ -1309,9 +1304,9 @@ function _memory(cmd) { }); } else if (depth < 0) { // Going... up. - var curr = self.lines.level.pop(); + const curr = self.lines.level.pop(); if (curr) { - var tmp = curr.depth + depth; + const tmp = curr.depth + depth; if (tmp < 0) { // More to go, recurse depth += curr.depth; @@ -1374,7 +1369,7 @@ function defineDefaultCommands(repl) { } }); - var clearMessage; + let clearMessage; if (repl.useGlobal) { clearMessage = 'Alias for .break'; } else { @@ -1408,10 +1403,10 @@ function defineDefaultCommands(repl) { 0 ); for (var n = 0; n < names.length; n++) { - var name = names[n]; - var cmd = this.commands[name]; - var spaces = ' '.repeat(longestNameLength - name.length + 3); - var line = `.${name}${cmd.help ? spaces + cmd.help : ''}\n`; + const name = names[n]; + const cmd = this.commands[name]; + const spaces = ' '.repeat(longestNameLength - name.length + 3); + const line = `.${name}${cmd.help ? spaces + cmd.help : ''}\n`; this.outputStream.write(line); } this.displayPrompt(); @@ -1435,11 +1430,11 @@ function defineDefaultCommands(repl) { help: 'Load JS from a file into the REPL session', action: function(file) { try { - var stats = fs.statSync(file); + const stats = fs.statSync(file); if (stats && stats.isFile()) { _turnOnEditorMode(this); - var data = fs.readFileSync(file, 'utf8'); - var lines = data.split('\n'); + const data = fs.readFileSync(file, 'utf8'); + const lines = data.split('\n'); for (var n = 0; n < lines.length; n++) { if (lines[n]) this.write(`${lines[n]}\n`); @@ -1476,7 +1471,7 @@ function regexpEscape(s) { // then let the user try to recover by adding more input. function isRecoverableError(e, code) { if (e && e.name === 'SyntaxError') { - var message = e.message; + const message = e.message; if (message === 'Unterminated template literal' || message === 'Unexpected end of input') { return true; @@ -1496,12 +1491,12 @@ function isRecoverableError(e, code) { // Check whether a code snippet should be forced to fail in the REPL. function isCodeRecoverable(code) { - var current, previous, stringLiteral; - var isBlockComment = false; - var isSingleComment = false; - var isRegExpLiteral = false; - var lastChar = code.charAt(code.length - 2); - var prevTokenChar = null; + let current, previous, stringLiteral; + let isBlockComment = false; + let isSingleComment = false; + let isRegExpLiteral = false; + const lastChar = code.charAt(code.length - 2); + let prevTokenChar = null; for (var i = 0; i < code.length; i++) { previous = current; diff --git a/lib/string_decoder.js b/lib/string_decoder.js index a6ae64c0624b0e..4cb50ca97b7f2b 100644 --- a/lib/string_decoder.js +++ b/lib/string_decoder.js @@ -22,7 +22,7 @@ 'use strict'; const { Buffer } = require('buffer'); -const { internalBinding } = require('internal/bootstrap/loaders'); +const { internalBinding } = require('internal/bootstrap_loaders'); const { kIncompleteCharactersStart, kIncompleteCharactersEnd, diff --git a/lib/timers.js b/lib/timers.js index 32f6ccb00cd4c6..7592479a94e9f8 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -177,7 +177,7 @@ function insert(item, unrefed, start) { const lists = unrefed === true ? unrefedLists : refedLists; // Use an existing list if there is one, otherwise we need to make a new one. - var list = lists[msecs]; + let list = lists[msecs]; if (list === undefined) { debug('no %d list was found in insert, creating a new one', msecs); lists[msecs] = list = new TimersList(msecs, unrefed); @@ -219,14 +219,14 @@ function listOnTimeout(handle, now) { debug('timeout callback %d', msecs); debug('now: %d', now); - var diff, timer; + let diff, timer; while (timer = L.peek(list)) { diff = now - timer._idleStart; // Check if this loop iteration is too early for the next timer. // This happens if there are more timers scheduled for later in the list. if (diff < msecs) { - var timeRemaining = msecs - (TimerWrap.now() - timer._idleStart); + let timeRemaining = msecs - (TimerWrap.now() - timer._idleStart); if (timeRemaining <= 0) { timeRemaining = 1; } @@ -282,7 +282,7 @@ function tryOnTimeout(timer, start) { timer._called = true; const timerAsyncId = (typeof timer[async_id_symbol] === 'number') ? timer[async_id_symbol] : null; - var threw = true; + let threw = true; if (timerAsyncId !== null) emitBefore(timerAsyncId, timer[trigger_async_id_symbol]); try { @@ -378,7 +378,7 @@ function setTimeout(callback, after, arg1, arg2, arg3) { throw new ERR_INVALID_CALLBACK(); } - var i, args; + let i, args; switch (arguments.length) { // fast cases case 1: @@ -469,7 +469,7 @@ exports.setInterval = function(callback, repeat, arg1, arg2, arg3) { throw new ERR_INVALID_CALLBACK(); } - var i, args; + let i, args; switch (arguments.length) { // fast cases case 1: @@ -528,7 +528,7 @@ Timeout.prototype.unref = function() { } else if (typeof this._onTimeout === 'function') { const now = TimerWrap.now(); if (!this._idleStart) this._idleStart = now; - var delay = this._idleStart + this._idleTimeout - now; + let delay = this._idleStart + this._idleTimeout - now; if (delay < 0) delay = 0; // Prevent running cb again when unref() is called during the same cb @@ -625,7 +625,7 @@ const outstandingQueue = new ImmediateList(); function processImmediate() { const queue = outstandingQueue.head !== null ? outstandingQueue : immediateQueue; - var immediate = queue.head; + let immediate = queue.head; const tail = queue.tail; // Clear the linked list early in case new `setImmediate()` calls occur while @@ -661,7 +661,7 @@ function processImmediate() { // An optimization so that the try/finally only de-optimizes (since at least v8 // 4.7) what is in this smaller function. function tryOnImmediate(immediate, oldTail, count, refCount) { - var threw = true; + let threw = true; try { // make the actual call outside the try/finally to allow it to be optimized runCallback(immediate); @@ -742,7 +742,7 @@ function setImmediate(callback, arg1, arg2, arg3) { throw new ERR_INVALID_CALLBACK(); } - var i, args; + let i, args; switch (arguments.length) { // fast cases case 1: diff --git a/lib/tls.js b/lib/tls.js index 5d7999f1fb61ad..648a4e3f7c7178 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -58,12 +58,12 @@ exports.getCiphers = internalUtil.cachedResult( function convertProtocols(protocols) { const lens = new Array(protocols.length); const buff = Buffer.allocUnsafe(protocols.reduce((p, c, i) => { - var len = Buffer.byteLength(c); + const len = Buffer.byteLength(c); lens[i] = len; return p + 1 + len; }, 0)); - var offset = 0; + let offset = 0; for (var i = 0, c = protocols.length; i < c; i++) { buff[offset++] = lens[i]; buff.write(protocols[i], offset); diff --git a/lib/url.js b/lib/url.js index 61662b4a97abe1..882c43403b7502 100644 --- a/lib/url.js +++ b/lib/url.js @@ -135,7 +135,7 @@ const { function urlParse(url, parseQueryString, slashesDenoteHost) { if (url instanceof Url) return url; - var urlObject = new Url(); + const urlObject = new Url(); urlObject.parse(url, parseQueryString, slashesDenoteHost); return urlObject; } @@ -148,12 +148,12 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // Copy chrome, IE, opera backslash-handling behavior. // Back slashes before the query string get converted to forward slashes // See: https://code.google.com/p/chromium/issues/detail?id=25916 - var hasHash = false; - var start = -1; - var end = -1; - var rest = ''; - var lastPos = 0; - var i = 0; + let hasHash = false; + let start = -1; + let end = -1; + let rest = ''; + let lastPos = 0; + let i = 0; for (var inWs = false, split = false; i < url.length; ++i) { const code = url.charCodeAt(i); @@ -244,10 +244,10 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { } } - var proto = protocolPattern.exec(rest); + let proto = protocolPattern.exec(rest); if (proto) { proto = proto[0]; - var lowerProto = proto.toLowerCase(); + const lowerProto = proto.toLowerCase(); this.protocol = lowerProto; rest = rest.slice(proto.length); } @@ -257,7 +257,7 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. if (slashesDenoteHost || proto || hostPattern.test(rest)) { - var slashes = rest.charCodeAt(0) === CHAR_FORWARD_SLASH && + const slashes = rest.charCodeAt(0) === CHAR_FORWARD_SLASH && rest.charCodeAt(1) === CHAR_FORWARD_SLASH; if (slashes && !(proto && hostlessProtocol[proto])) { rest = rest.slice(2); @@ -283,9 +283,9 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // v0.12 TODO(isaacs): This is not quite how Chrome does things. // Review our test case against browsers more comprehensively. - var hostEnd = -1; - var atSign = -1; - var nonHost = -1; + let hostEnd = -1; + let atSign = -1; + let nonHost = -1; for (i = 0; i < rest.length; ++i) { switch (rest.charCodeAt(i)) { case CHAR_TAB: @@ -347,11 +347,11 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { if (typeof this.hostname !== 'string') this.hostname = ''; - var hostname = this.hostname; + const hostname = this.hostname; // if hostname begins with [ and ends with ] // assume that it's an IPv6 address. - var ipv6Hostname = hostname.charCodeAt(0) === CHAR_LEFT_SQUARE_BRACKET && + const ipv6Hostname = hostname.charCodeAt(0) === CHAR_LEFT_SQUARE_BRACKET && hostname.charCodeAt(hostname.length - 1) === CHAR_RIGHT_SQUARE_BRACKET; // validate a little. @@ -379,8 +379,8 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { this.hostname = toASCII(this.hostname, true); } - var p = this.port ? ':' + this.port : ''; - var h = this.hostname || ''; + const p = this.port ? ':' + this.port : ''; + const h = this.hostname || ''; this.host = h + p; // strip [ and ] from the hostname @@ -402,8 +402,8 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { rest = autoEscapeStr(rest); } - var questionIdx = -1; - var hashIdx = -1; + let questionIdx = -1; + let hashIdx = -1; for (i = 0; i < rest.length; ++i) { const code = rest.charCodeAt(i); if (code === CHAR_HASH) { @@ -500,11 +500,11 @@ const escapedCodes = [ // Also escape single quotes in case of an XSS attack. // Return the escaped string. function autoEscapeStr(rest) { - var escaped = ''; - var lastEscapedPos = 0; + let escaped = ''; + let lastEscapedPos = 0; for (var i = 0; i < rest.length; ++i) { // `escaped` contains substring up to the last escaped character. - var escapedChar = escapedCodes[rest.charCodeAt(i)]; + const escapedChar = escapedCodes[rest.charCodeAt(i)]; if (escapedChar) { // Concat if there are ordinary characters in the middle. if (i > lastEscapedPos) @@ -535,7 +535,7 @@ function urlFormat(urlObject, options) { throw new ERR_INVALID_ARG_TYPE('urlObject', ['Object', 'string'], urlObject); } else if (!(urlObject instanceof Url)) { - var format = urlObject[formatSymbol]; + const format = urlObject[formatSymbol]; return format ? format.call(urlObject, options) : Url.prototype.format.call(urlObject); @@ -544,17 +544,17 @@ function urlFormat(urlObject, options) { } Url.prototype.format = function format() { - var auth = this.auth || ''; + let auth = this.auth || ''; if (auth) { auth = encodeAuth(auth); auth += '@'; } - var protocol = this.protocol || ''; - var pathname = this.pathname || ''; - var hash = this.hash || ''; - var host = ''; - var query = ''; + const protocol = this.protocol || ''; + const pathname = this.pathname || ''; + const hash = this.hash || ''; + let host = ''; + let query = ''; if (this.host) { host = auth + this.host; @@ -572,13 +572,13 @@ Url.prototype.format = function format() { if (this.query !== null && typeof this.query === 'object') query = querystring.stringify(this.query); - var search = this.search || (query && ('?' + query)) || ''; + const search = this.search || (query && ('?' + query)) || ''; if (protocol && protocol.charCodeAt(protocol.length - 1) !== 58/*:*/) protocol += ':'; - var newPathname = ''; - var lastPos = 0; + let newPathname = ''; + let lastPos = 0; for (var i = 0; i < pathname.length; ++i) { switch (pathname.charCodeAt(i)) { case CHAR_HASH: @@ -643,15 +643,15 @@ function urlResolveObject(source, relative) { Url.prototype.resolveObject = function resolveObject(relative) { if (typeof relative === 'string') { - var rel = new Url(); + const rel = new Url(); rel.parse(relative, false, true); relative = rel; } - var result = new Url(); - var tkeys = Object.keys(this); + const result = new Url(); + const tkeys = Object.keys(this); for (var tk = 0; tk < tkeys.length; tk++) { - var tkey = tkeys[tk]; + const tkey = tkeys[tk]; result[tkey] = this[tkey]; } @@ -668,9 +668,9 @@ Url.prototype.resolveObject = function resolveObject(relative) { // hrefs like //foo/bar always cut to the protocol. if (relative.slashes && !relative.protocol) { // take everything except the protocol from relative - var rkeys = Object.keys(relative); + const rkeys = Object.keys(relative); for (var rk = 0; rk < rkeys.length; rk++) { - var rkey = rkeys[rk]; + const rkey = rkeys[rk]; if (rkey !== 'protocol') result[rkey] = relative[rkey]; } @@ -695,9 +695,9 @@ Url.prototype.resolveObject = function resolveObject(relative) { // because that's known to be hostless. // anything else is assumed to be absolute. if (!slashedProtocol[relative.protocol]) { - var keys = Object.keys(relative); + const keys = Object.keys(relative); for (var v = 0; v < keys.length; v++) { - var k = keys[v]; + const k = keys[v]; result[k] = relative[k]; } result.href = result.format(); @@ -726,8 +726,8 @@ Url.prototype.resolveObject = function resolveObject(relative) { result.port = relative.port; // to support http.request if (result.pathname || result.search) { - var p = result.pathname || ''; - var s = result.search || ''; + const p = result.pathname || ''; + const s = result.search || ''; result.path = p + s; } result.slashes = result.slashes || relative.slashes; @@ -735,16 +735,16 @@ Url.prototype.resolveObject = function resolveObject(relative) { return result; } - var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'); - var isRelAbs = ( + const isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'); + const isRelAbs = ( relative.host || relative.pathname && relative.pathname.charAt(0) === '/' ); - var mustEndAbs = (isRelAbs || isSourceAbs || + let mustEndAbs = (isRelAbs || isSourceAbs || (result.host && relative.pathname)); - var removeAllDots = mustEndAbs; - var srcPath = result.pathname && result.pathname.split('/') || []; - var relPath = relative.pathname && relative.pathname.split('/') || []; - var noLeadingSlashes = result.protocol && !slashedProtocol[result.protocol]; + const removeAllDots = mustEndAbs; + let srcPath = result.pathname && result.pathname.split('/') || []; + const relPath = relative.pathname && relative.pathname.split('/') || []; + const noLeadingSlashes = result.protocol && !slashedProtocol[result.protocol]; // if the url is a non-slashed url, then relative // links like ../.. should be able @@ -839,14 +839,14 @@ Url.prototype.resolveObject = function resolveObject(relative) { // if a url ENDs in . or .., then it must get a trailing slash. // however, if it ends in anything else non-slashy, // then it must NOT get a trailing slash. - var last = srcPath.slice(-1)[0]; - var hasTrailingSlash = ( + let last = srcPath.slice(-1)[0]; + const hasTrailingSlash = ( (result.host || relative.host || srcPath.length > 1) && (last === '.' || last === '..') || last === ''); // strip single dots, resolve double dots to parent dir // if the path tries to go above the root, `up` ends up > 0 - var up = 0; + let up = 0; for (var i = srcPath.length - 1; i >= 0; i--) { last = srcPath[i]; if (last === '.') { @@ -876,7 +876,7 @@ Url.prototype.resolveObject = function resolveObject(relative) { srcPath.push(''); } - var isAbsolute = srcPath[0] === '' || + const isAbsolute = srcPath[0] === '' || (srcPath[0] && srcPath[0].charAt(0) === '/'); // put the host back @@ -919,8 +919,8 @@ Url.prototype.resolveObject = function resolveObject(relative) { }; Url.prototype.parseHost = function parseHost() { - var host = this.host; - var port = portPattern.exec(host); + let host = this.host; + let port = portPattern.exec(host); if (port) { port = port[0]; if (port !== ':') { @@ -950,10 +950,10 @@ const noEscapeAuth = [ function encodeAuth(str) { // faster encodeURIComponent alternative for encoding auth uri components - var out = ''; - var lastPos = 0; + let out = ''; + let lastPos = 0; for (var i = 0; i < str.length; ++i) { - var c = str.charCodeAt(i); + const c = str.charCodeAt(i); // ASCII if (c < 0x80) { @@ -984,7 +984,7 @@ function encodeAuth(str) { } // Surrogate pair ++i; - var c2; + let c2; if (i < str.length) c2 = str.charCodeAt(i) & 0x3FF; else diff --git a/lib/util.js b/lib/util.js index b64d103cb30bca..95bf17519b174b 100644 --- a/lib/util.js +++ b/lib/util.js @@ -39,7 +39,7 @@ const { kRejected, } = process.binding('util'); -const { internalBinding } = require('internal/bootstrap/loaders'); +const { internalBinding } = require('internal/bootstrap_loaders'); const types = internalBinding('types'); Object.assign(types, require('internal/util/types')); const { diff --git a/lib/zlib.js b/lib/zlib.js index 4adfd1ffa289fb..8282ee4695c52d 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -63,7 +63,7 @@ const codes = { const ckeys = Object.keys(codes); for (var ck = 0; ck < ckeys.length; ck++) { - var ckey = ckeys[ck]; + const ckey = ckeys[ck]; codes[codes[ckey]] = ckey; } @@ -99,14 +99,14 @@ function zlibBufferOnError(err) { } function zlibBufferOnEnd() { - var buf; - var err; + let buf; + let err; if (this.nread >= kMaxLength) { err = new ERR_BUFFER_TOO_LARGE(); } else if (this.nread === 0) { buf = Buffer.alloc(0); } else { - var bufs = this.buffers; + const bufs = this.buffers; buf = (bufs.length === 1 ? bufs[0] : Buffer.concat(bufs, this.nread)); } this.close(); @@ -138,7 +138,7 @@ function zlibBufferSync(engine, buffer) { } function zlibOnError(message, errno) { - var self = this.jsref; + const self = this.jsref; // there is no way to cleanly recover. // continuing only obscures problems. _close(self); @@ -210,14 +210,14 @@ function checkRangesOrGetDefault(number, name, lower, upper, def) { // true or false if there is anything in the queue when // you call the .write() method. function Zlib(opts, mode) { - var chunkSize = Z_DEFAULT_CHUNK; - var flush = Z_NO_FLUSH; - var finishFlush = Z_FINISH; - var windowBits = Z_DEFAULT_WINDOWBITS; - var level = Z_DEFAULT_COMPRESSION; - var memLevel = Z_DEFAULT_MEMLEVEL; - var strategy = Z_DEFAULT_STRATEGY; - var dictionary; + let chunkSize = Z_DEFAULT_CHUNK; + let flush = Z_NO_FLUSH; + let finishFlush = Z_FINISH; + let windowBits = Z_DEFAULT_WINDOWBITS; + let level = Z_DEFAULT_COMPRESSION; + let memLevel = Z_DEFAULT_MEMLEVEL; + let strategy = Z_DEFAULT_STRATEGY; + let dictionary; // The Zlib class is not exported to user land, the mode should only be // passed in by us. @@ -358,7 +358,7 @@ function maxFlush(a, b) { } Zlib.prototype.flush = function flush(kind, callback) { - var ws = this._writableState; + const ws = this._writableState; if (typeof kind === 'function' || (kind === undefined && !callback)) { callback = kind; @@ -399,8 +399,8 @@ Zlib.prototype._transform = function _transform(chunk, encoding, cb) { // (or whatever flag was provided using opts.finishFlush). // If it's explicitly flushing at some other time, then we use // Z_FULL_FLUSH. Otherwise, use the original opts.flush flag. - var flushFlag; - var ws = this._writableState; + let flushFlag; + const ws = this._writableState; if ((ws.ending || ws.ended) && ws.length === chunk.byteLength) { flushFlag = this._finishFlushFlag; } else { @@ -422,22 +422,22 @@ Zlib.prototype._processChunk = function _processChunk(chunk, flushFlag, cb) { }; function processChunkSync(self, chunk, flushFlag) { - var availInBefore = chunk.byteLength; - var availOutBefore = self._chunkSize - self._outOffset; - var inOff = 0; - var availOutAfter; - var availInAfter; - - var buffers = null; - var nread = 0; - var inputRead = 0; - var state = self._writeState; - var handle = self._handle; - var buffer = self._outBuffer; - var offset = self._outOffset; - var chunkSize = self._chunkSize; - - var error; + let availInBefore = chunk.byteLength; + let availOutBefore = self._chunkSize - self._outOffset; + let inOff = 0; + let availOutAfter; + let availInAfter; + + let buffers = null; + let nread = 0; + let inputRead = 0; + const state = self._writeState; + const handle = self._handle; + let buffer = self._outBuffer; + let offset = self._outOffset; + const chunkSize = self._chunkSize; + + let error; self.on('error', function(er) { error = er; }); @@ -456,12 +456,12 @@ function processChunkSync(self, chunk, flushFlag) { availOutAfter = state[0]; availInAfter = state[1]; - var inDelta = (availInBefore - availInAfter); + const inDelta = (availInBefore - availInAfter); inputRead += inDelta; - var have = availOutBefore - availOutAfter; + const have = availOutBefore - availOutAfter; if (have > 0) { - var out = buffer.slice(offset, offset + have); + const out = buffer.slice(offset, offset + have); offset += have; if (!buffers) buffers = [out]; @@ -507,7 +507,7 @@ function processChunkSync(self, chunk, flushFlag) { } function processChunk(self, chunk, flushFlag, cb) { - var handle = self._handle; + const handle = self._handle; if (!handle) assert(false, 'zlib binding closed'); @@ -531,9 +531,9 @@ function processCallback() { // This callback's context (`this`) is the `_handle` (ZCtx) object. It is // important to null out the values once they are no longer needed since // `_handle` can stay in memory long after the buffer is needed. - var handle = this; - var self = this.jsref; - var state = self._writeState; + const handle = this; + const self = this.jsref; + const state = self._writeState; if (self._hadError) { this.buffer = null; @@ -545,15 +545,15 @@ function processCallback() { return; } - var availOutAfter = state[0]; - var availInAfter = state[1]; + const availOutAfter = state[0]; + const availInAfter = state[1]; - var inDelta = (handle.availInBefore - availInAfter); + const inDelta = (handle.availInBefore - availInAfter); self.bytesRead += inDelta; - var have = handle.availOutBefore - availOutAfter; + const have = handle.availOutBefore - availOutAfter; if (have > 0) { - var out = self._outBuffer.slice(self._outOffset, self._outOffset + have); + const out = self._outBuffer.slice(self._outOffset, self._outOffset + have); self._outOffset += have; self.push(out); } else if (have < 0) { @@ -731,7 +731,7 @@ Object.defineProperties(module.exports, { // expose all the zlib constants const bkeys = Object.keys(constants); for (var bk = 0; bk < bkeys.length; bk++) { - var bkey = bkeys[bk]; + const bkey = bkeys[bk]; Object.defineProperty(module.exports, bkey, { enumerable: true, value: constants[bkey], writable: false });