diff --git a/Makefile b/Makefile index 0a217bd8932d92..78c288930db6a0 100644 --- a/Makefile +++ b/Makefile @@ -205,6 +205,9 @@ test-parallel: all test-valgrind: all $(PYTHON) tools/test.py --mode=release --valgrind sequential parallel message +test-check-deopts: all + $(PYTHON) tools/test.py --mode=release --check-deopts parallel sequential -J + # Implicitly depends on $(NODE_EXE). We don't depend on it explicitly because # it always triggers a rebuild due to it being a .PHONY rule. See the comment # near the build-addons rule for more background. diff --git a/lib/_http_agent.js b/lib/_http_agent.js index 351417a7ba6a74..88f4df402a9b80 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -130,13 +130,14 @@ Agent.prototype.getName = function getName(options) { return name; }; -Agent.prototype.addRequest = function addRequest(req, options) { +Agent.prototype.addRequest = function addRequest(req, options, port/*legacy*/, + localAddress/*legacy*/) { // Legacy API: addRequest(req, host, port, localAddress) if (typeof options === 'string') { options = { host: options, - port: arguments[2], - localAddress: arguments[3] + port, + localAddress }; } diff --git a/lib/_http_client.js b/lib/_http_client.js index 42387d0930b583..e1f064e832d224 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -127,8 +127,8 @@ function ClientRequest(options, cb) { 'Expected "' + expectedProtocol + '"'); } - const defaultPort = options.defaultPort || - this.agent && this.agent.defaultPort; + var defaultPort = options.defaultPort || + this.agent && this.agent.defaultPort; var port = options.port = options.port || defaultPort || 80; var host = options.host = validateHost(options.hostname, 'hostname') || @@ -226,7 +226,7 @@ function ClientRequest(options, cb) { var called = false; - const oncreate = (err, socket) => { + var oncreate = (err, socket) => { if (called) return; called = true; @@ -238,14 +238,15 @@ function ClientRequest(options, cb) { this._deferToConnect(null, null, () => this._flush()); }; + var newSocket; if (this.socketPath) { this._last = true; this.shouldKeepAlive = false; - const optionsPath = { + var optionsPath = { path: this.socketPath, timeout: this.timeout }; - const newSocket = this.agent.createConnection(optionsPath, oncreate); + newSocket = this.agent.createConnection(optionsPath, oncreate); if (newSocket && !called) { called = true; this.onSocket(newSocket); @@ -270,7 +271,7 @@ function ClientRequest(options, cb) { this._last = true; this.shouldKeepAlive = false; if (typeof options.createConnection === 'function') { - const newSocket = options.createConnection(options, oncreate); + newSocket = options.createConnection(options, oncreate); if (newSocket && !called) { called = true; this.onSocket(newSocket); diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index b2859ea3d28af8..879e5ddb53fe40 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -686,7 +686,7 @@ Readable.prototype.unpipe = function(dest) { } // try to find the right one. - const index = state.pipes.indexOf(dest); + var index = state.pipes.indexOf(dest); if (index === -1) return this; diff --git a/lib/fs.js b/lib/fs.js index 83c0d8085de3d0..ac1f90109a9eda 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -82,8 +82,8 @@ function getOptions(options, defaultOptions) { } function copyObject(source) { - const target = {}; - for (const key in source) + var target = {}; + for (var key in source) target[key] = source[key]; return target; } @@ -320,7 +320,7 @@ fs.existsSync = function(path) { }; fs.readFile = function(path, options, callback) { - callback = maybeCallback(arguments[arguments.length - 1]); + callback = maybeCallback(callback || options); options = getOptions(options, { flag: 'r' }); if (handleError((path = getPathFromURL(path)), callback)) @@ -1216,9 +1216,7 @@ fs.futimesSync = function(fd, atime, mtime) { binding.futimes(fd, atime, mtime); }; -function writeAll(fd, isUserFd, buffer, offset, length, position, callback_) { - var callback = maybeCallback(arguments[arguments.length - 1]); - +function writeAll(fd, isUserFd, buffer, offset, length, position, callback) { // write(fd, buffer, offset, length, position, callback) fs.write(fd, buffer, offset, length, position, function(writeErr, written) { if (writeErr) { @@ -1249,7 +1247,7 @@ function writeAll(fd, isUserFd, buffer, offset, length, position, callback_) { } fs.writeFile = function(path, data, options, callback) { - callback = maybeCallback(arguments[arguments.length - 1]); + callback = maybeCallback(callback || options); options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'w' }); const flag = options.flag || 'w'; diff --git a/lib/internal/cluster/child.js b/lib/internal/cluster/child.js index 3275eec720c738..98c5e7b5597f74 100644 --- a/lib/internal/cluster/child.js +++ b/lib/internal/cluster/child.js @@ -99,7 +99,7 @@ function shared(message, handle, indexesKey, cb) { delete handles[key]; delete indexes[indexesKey]; return close.apply(this, arguments); - }; + }.bind(handle); assert(handles[key] === undefined); handles[key] = handle; cb(message.errno, handle); @@ -192,7 +192,7 @@ function _disconnect(masterInitiated) { } } - for (const key in handles) { + for (var key in handles) { const handle = handles[key]; delete handles[key]; waitingCount++; diff --git a/lib/internal/process/stdio.js b/lib/internal/process/stdio.js index b6c866e194bdbb..adfe1e8e0b049f 100644 --- a/lib/internal/process/stdio.js +++ b/lib/internal/process/stdio.js @@ -51,7 +51,7 @@ function setupStdio() { switch (tty_wrap.guessHandleType(fd)) { case 'TTY': - const tty = require('tty'); + var tty = require('tty'); stdin = new tty.ReadStream(fd, { highWaterMark: 0, readable: true, @@ -60,13 +60,13 @@ function setupStdio() { break; case 'FILE': - const fs = require('fs'); + var fs = require('fs'); stdin = new fs.ReadStream(null, { fd: fd, autoClose: false }); break; case 'PIPE': case 'TCP': - const net = require('net'); + var 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 @@ -152,20 +152,20 @@ function createWritableStdioStream(fd) { switch (tty_wrap.guessHandleType(fd)) { case 'TTY': - const tty = require('tty'); + var tty = require('tty'); stream = new tty.WriteStream(fd); stream._type = 'tty'; break; case 'FILE': - const fs = require('internal/fs'); + var fs = require('internal/fs'); stream = new fs.SyncWriteStream(fd, { autoClose: false }); stream._type = 'fs'; break; case 'PIPE': case 'TCP': - const net = require('net'); + var net = require('net'); stream = new net.Socket({ fd: fd, readable: false, diff --git a/lib/internal/url.js b/lib/internal/url.js index fc651ad59a8071..2ff397c6b6ec1b 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -232,9 +232,9 @@ class URL { if (typeof depth === 'number' && depth < 0) return opts.stylize('[Object]', 'special'); - const ctor = getConstructorOf(this); + var ctor = getConstructorOf(this); - const obj = Object.create({ + var obj = Object.create({ constructor: ctor === null ? URL : ctor }); @@ -879,20 +879,20 @@ class URLSearchParams { if (typeof recurseTimes === 'number' && recurseTimes < 0) return ctx.stylize('[Object]', 'special'); - const separator = ', '; - const innerOpts = Object.assign({}, ctx); + var separator = ', '; + var innerOpts = Object.assign({}, ctx); if (recurseTimes !== null) { innerOpts.depth = recurseTimes - 1; } - const innerInspect = (v) => util.inspect(v, innerOpts); + var innerInspect = (v) => util.inspect(v, innerOpts); - const list = this[searchParams]; - const output = []; + var list = this[searchParams]; + var output = []; for (var i = 0; i < list.length; i += 2) output.push(`${innerInspect(list[i])} => ${innerInspect(list[i + 1])}`); - const colorRe = /\u001b\[\d\d?m/g; - const length = output.reduce( + var colorRe = /\u001b\[\d\d?m/g; + var length = output.reduce( (prev, cur) => prev + cur.replace(colorRe, '').length + separator.length, -separator.length ); diff --git a/lib/internal/util.js b/lib/internal/util.js index 4c11e59271a601..e6993c5d56d66a 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -162,7 +162,7 @@ function getSignalsToNamesMapping() { return signalsToNamesMapping; signalsToNamesMapping = Object.create(null); - for (const key in signals) { + for (var key in signals) { signalsToNamesMapping[signals[key]] = key; } diff --git a/lib/net.js b/lib/net.js index 898f14e9ae27c0..d50b3729d968a9 100644 --- a/lib/net.js +++ b/lib/net.js @@ -81,15 +81,15 @@ function createServer(options, connectionListener) { // connect(path, [cb]); // function connect() { - const args = new Array(arguments.length); + var args = new Array(arguments.length); for (var i = 0; i < arguments.length; i++) args[i] = arguments[i]; // TODO(joyeecheung): use destructuring when V8 is fast enough - const normalized = normalizeArgs(args); - const options = normalized[0]; - const cb = normalized[1]; + var normalized = normalizeArgs(args); + var options = normalized[0]; + var cb = normalized[1]; debug('createConnection', normalized); - const socket = new Socket(options); + var socket = new Socket(options); if (options.timeout) { socket.setTimeout(options.timeout); @@ -915,13 +915,13 @@ function internalConnect( Socket.prototype.connect = function() { - const args = new Array(arguments.length); + var args = new Array(arguments.length); for (var i = 0; i < arguments.length; i++) args[i] = arguments[i]; // TODO(joyeecheung): use destructuring when V8 is fast enough - const normalized = normalizeArgs(args); - const options = normalized[0]; - const cb = normalized[1]; + var normalized = normalizeArgs(args); + var options = normalized[0]; + var cb = normalized[1]; return realConnect.call(this, options, cb); }; @@ -1373,19 +1373,19 @@ function listenInCluster(server, address, port, addressType, Server.prototype.listen = function() { - const args = new Array(arguments.length); + var args = new Array(arguments.length); for (var i = 0; i < arguments.length; i++) args[i] = arguments[i]; // TODO(joyeecheung): use destructuring when V8 is fast enough - const normalized = normalizeArgs(args); + var normalized = normalizeArgs(args); var options = normalized[0]; - const cb = normalized[1]; + var cb = normalized[1]; var hasCallback = (cb !== null); if (hasCallback) { this.once('listening', cb); } - const backlogFromArgs = + var backlogFromArgs = // (handle, backlog) or (path, backlog) or (port, backlog) toNumber(args.length > 1 && args[1]) || toNumber(args.length > 2 && args[2]); // (port, host, backlog) @@ -1414,11 +1414,12 @@ Server.prototype.listen = function() { // ([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; if (typeof options.port === 'number' || typeof options.port === 'string') { if (!isLegalPort(options.port)) { throw new RangeError('"port" argument must be >= 0 and < 65536'); } - const backlog = options.backlog || backlogFromArgs; + backlog = options.backlog || backlogFromArgs; // start TCP server listening on host:port if (options.host) { lookupAndListen(this, options.port | 0, options.host, backlog, @@ -1434,8 +1435,8 @@ Server.prototype.listen = function() { // (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)) { - const pipeName = this._pipeName = options.path; - const backlog = options.backlog || backlogFromArgs; + var pipeName = this._pipeName = options.path; + backlog = options.backlog || backlogFromArgs; listenInCluster(this, pipeName, -1, -1, backlog, undefined, options.exclusive); return this; diff --git a/lib/readline.js b/lib/readline.js index d32456155663ec..947daddaddc03c 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -470,8 +470,8 @@ Interface.prototype._tabComplete = function(lastKeypressWasTab) { } // If there is a common prefix to all matches, then apply that portion. - const f = completions.filter(function(e) { if (e) return e; }); - const prefix = commonPrefix(f); + var f = completions.filter(function(e) { if (e) return e; }); + var prefix = commonPrefix(f); if (prefix.length > completeOn.length) { self._insertString(prefix.slice(completeOn.length)); } diff --git a/lib/repl.js b/lib/repl.js index 3a56dd675008f9..cff49cea35a8d1 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -601,10 +601,10 @@ REPLServer.prototype.createContext = function() { } } - const module = new Module(''); + var module = new Module(''); module.paths = Module._resolveLookupPaths('', parentModule, true) || []; - const require = internalModule.makeRequireFunction(module); + var require = internalModule.makeRequireFunction(module); context.module = module; context.require = require; diff --git a/lib/util.js b/lib/util.js index ddf43a760c2cc9..4e626a3accc3f8 100644 --- a/lib/util.js +++ b/lib/util.js @@ -669,7 +669,7 @@ function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { } visibleLength++; } - const remaining = value.length - index; + var remaining = value.length - index; if (remaining > 0) { output.push(`... ${remaining} more item${remaining > 1 ? 's' : ''}`); } diff --git a/test/common.js b/test/common.js index 25a2d9c1d2fe0c..ca538a1961f8a6 100644 --- a/test/common.js +++ b/test/common.js @@ -385,7 +385,8 @@ exports.allowGlobals = allowGlobals; function leakedGlobals() { const leaked = []; - for (const val in global) + // eslint-disable-next-line no-var + for (var val in global) if (!knownGlobals.includes(global[val])) leaked.push(val); diff --git a/test/parallel/test-repl-.editor.js b/test/parallel/test-repl-editor.js similarity index 100% rename from test/parallel/test-repl-.editor.js rename to test/parallel/test-repl-editor.js diff --git a/test/parallel/test-repl-.save.load.js b/test/parallel/test-repl-save-load.js similarity index 100% rename from test/parallel/test-repl-.save.load.js rename to test/parallel/test-repl-save-load.js diff --git a/tools/test.py b/tools/test.py index 7efc2574025057..4f341ad42177e8 100755 --- a/tools/test.py +++ b/tools/test.py @@ -341,6 +341,39 @@ def HasRun(self, output): def Done(self): pass +class DeoptsCheckProgressIndicator(SimpleProgressIndicator): + + def Starting(self): + pass + + def AboutToRun(self, case): + pass + + def HasRun(self, output): + # Print test name as (for example) "parallel/test-assert". Tests that are + # scraped from the addons documentation are all named test.js, making it + # hard to decipher what test is running when only the filename is printed. + prefix = abspath(join(dirname(__file__), '../test')) + os.sep + command = output.command[-1] + if command.endswith('.js'): command = command[:-3] + if command.startswith(prefix): command = command[len(prefix):] + command = command.replace('\\', '/') + + stdout = output.output.stdout.strip() + printed_file = False + for line in stdout.splitlines(): + if (line.startswith("[aborted optimiz") or \ + line.startswith("[disabled optimiz")) and \ + ("because:" in line or "reason:" in line): + if not printed_file: + printed_file = True + print '==== %s ====' % command + self.failed.append(output) + print ' %s' % line + + def Done(self): + pass + class CompactProgressIndicator(ProgressIndicator): @@ -433,7 +466,8 @@ def ClearLine(self, last_line_length): 'dots': DotsProgressIndicator, 'color': ColorProgressIndicator, 'tap': TapProgressIndicator, - 'mono': MonochromeProgressIndicator + 'mono': MonochromeProgressIndicator, + 'deopts': DeoptsCheckProgressIndicator } @@ -1383,6 +1417,8 @@ def BuildOptions(): help="Expect test cases to fail", default=False, action="store_true") result.add_option("--valgrind", help="Run tests through valgrind", default=False, action="store_true") + result.add_option("--check-deopts", help="Check tests for permanent deoptimizations", + default=False, action="store_true") result.add_option("--cat", help="Print the source of the tests", default=False, action="store_true") result.add_option("--flaky-tests", @@ -1586,6 +1622,14 @@ def Main(): run_valgrind = join(workspace, "tools", "run-valgrind.py") options.special_command = "python -u " + run_valgrind + " @" + if options.check_deopts: + options.node_args.append("--trace-opt") + options.node_args.append("--trace-file-names") + # --always-opt is needed because many tests do not run long enough for the + # optimizer to kick in, so this flag will force it to run. + options.node_args.append("--always-opt") + options.progress = "deopts" + shell = abspath(options.shell) buildspace = dirname(shell) diff --git a/vcbuild.bat b/vcbuild.bat index fc267ebcda42a8..f5d2164fbdeebf 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -42,6 +42,7 @@ set build_addons= set dll= set build_addons_napi= set test_node_inspect= +set test_check_deopts= :next-arg if "%1"=="" goto args-done @@ -74,6 +75,7 @@ if /i "%1"=="test-pummel" set test_args=%test_args% pummel&goto arg-ok if /i "%1"=="test-all" set test_args=%test_args% sequential parallel message gc inspector internet pummel&set build_testgc_addon=1&set cpplint=1&set jslint=1&goto arg-ok if /i "%1"=="test-known-issues" set test_args=%test_args% known_issues&goto arg-ok if /i "%1"=="test-node-inspect" set test_node_inspect=1&goto arg-ok +if /i "%1"=="test-check-deopts" set test_check_deopts=1&goto arg-ok if /i "%1"=="jslint" set jslint=1&goto arg-ok if /i "%1"=="jslint-ci" set jslint_ci=1&goto arg-ok if /i "%1"=="lint" set cpplint=1&set jslint=1&goto arg-ok @@ -361,7 +363,16 @@ endlocal goto run-tests :run-tests -if not defined test_node_inspect goto node-tests +if defined test_check_deopts goto node-check-deopts +if defined test_node_inspect goto node-test-inspect +goto node-tests + +:node-check-deopts +python tools\test.py --mode=release --check-deopts parallel sequential -J +if defined test_node_inspect goto node-test-inspect +goto node-tests + +:node-test-inspect set USE_EMBEDDED_NODE_INSPECT=1 %config%\node tools\test-npm-package.js --install deps\node-inspect test goto node-tests