From 5ab062608eab1f5fb326fcf2adf66a1e483253da Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Thu, 18 Jan 2018 03:58:22 +0200 Subject: [PATCH 001/131] doc: add missing link references PR-URL: https://github.com/nodejs/node/pull/18222 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- doc/api/assert.md | 1 + doc/api/errors.md | 1 + 2 files changed, 2 insertions(+) diff --git a/doc/api/assert.md b/doc/api/assert.md index 280d10b8cd4a5b..b91aa8991ea0cc 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -719,6 +719,7 @@ For more information, see [MDN's guide on equality comparisons and sameness][mdn-equality-guide]. [`Error.captureStackTrace`]: errors.html#errors_error_capturestacktrace_targetobject_constructoropt +[`Error`]: errors.html#errors_class_error [`Map`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map [`Object.is()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is [`RegExp`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions diff --git a/doc/api/errors.md b/doc/api/errors.md index 25b57ddac5c4ee..3b153a7c301ea5 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1571,6 +1571,7 @@ Creation of a [`zlib`][] object failed due to incorrect configuration. [`hash.digest()`]: crypto.html#crypto_hash_digest_encoding [`hash.update()`]: crypto.html#crypto_hash_update_data_inputencoding [`readable._read()`]: stream.html#stream_readable_read_size_1 +[`server.close()`]: net.html#net_server_close_callback [`sign.sign()`]: crypto.html#crypto_sign_sign_privatekey_outputformat [`stream.pipe()`]: stream.html#stream_readable_pipe_destination_options [`stream.push()`]: stream.html#stream_readable_push_chunk_encoding From a7a712b8c3da8493d39221287e758800d5113b1c Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Wed, 17 Jan 2018 00:35:54 +0200 Subject: [PATCH 002/131] inspector: --inspect-brk for es modules Reworked rebase of PR #17360 with feedback PR-URL: https://github.com/nodejs/node/pull/18194 Fixes: https://github.com/nodejs/node/issues/17340 Reviewed-By: Eugene Ostroukhov Reviewed-By: James M Snell --- lib/internal/loader/Loader.js | 11 +- lib/internal/loader/ModuleJob.js | 6 +- lib/module.js | 1 + test/common/inspector-helper.js | 43 +++++-- test/fixtures/es-modules/loop.mjs | 10 ++ ...est-inspect-async-hook-setup-at-inspect.js | 1 + test/parallel/test-inspector-esm.js | 120 ++++++++++++++++++ ...st-inspector-no-crash-ws-after-bindings.js | 1 + ...spector-async-hook-setup-at-inspect-brk.js | 1 + ...st-inspector-async-hook-setup-at-signal.js | 1 + ...spector-async-stack-traces-promise-then.js | 1 + ...spector-async-stack-traces-set-interval.js | 1 + test/sequential/test-inspector-break-e.js | 1 + .../test-inspector-break-when-eval.js | 1 + .../test-inspector-debug-brk-flag.js | 6 +- test/sequential/test-inspector-debug-end.js | 1 + test/sequential/test-inspector-exception.js | 1 + .../sequential/test-inspector-ip-detection.js | 1 + .../test-inspector-not-blocked-on-idle.js | 1 + .../test-inspector-scriptparsed-context.js | 1 + .../test-inspector-stop-profile-after-done.js | 1 + test/sequential/test-inspector.js | 13 +- 22 files changed, 202 insertions(+), 22 deletions(-) create mode 100644 test/fixtures/es-modules/loop.mjs create mode 100644 test/parallel/test-inspector-esm.js diff --git a/lib/internal/loader/Loader.js b/lib/internal/loader/Loader.js index 2e6a69af316261..eda42645f170f6 100644 --- a/lib/internal/loader/Loader.js +++ b/lib/internal/loader/Loader.js @@ -44,6 +44,7 @@ class Loader { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'base', 'string'); this.base = base; + this.isMain = true; // methods which translate input code or other information // into es modules @@ -132,7 +133,15 @@ class Loader { loaderInstance = translators.get(format); } - job = new ModuleJob(this, url, loaderInstance); + let inspectBrk = false; + if (this.isMain) { + if (process._breakFirstLine) { + delete process._breakFirstLine; + inspectBrk = true; + } + this.isMain = false; + } + job = new ModuleJob(this, url, loaderInstance, inspectBrk); this.moduleMap.set(url, job); return job; } diff --git a/lib/internal/loader/ModuleJob.js b/lib/internal/loader/ModuleJob.js index 8aa1b4b0513500..2d6325b85c6322 100644 --- a/lib/internal/loader/ModuleJob.js +++ b/lib/internal/loader/ModuleJob.js @@ -14,7 +14,7 @@ const enableDebug = (process.env.NODE_DEBUG || '').match(/\besm\b/) || class ModuleJob { // `loader` is the Loader instance used for loading dependencies. // `moduleProvider` is a function - constructor(loader, url, moduleProvider) { + constructor(loader, url, moduleProvider, inspectBrk) { this.loader = loader; this.error = null; this.hadError = false; @@ -30,6 +30,10 @@ class ModuleJob { const dependencyJobs = []; ({ module: this.module, reflect: this.reflect } = await this.modulePromise); + if (inspectBrk) { + const initWrapper = process.binding('inspector').callAndPauseOnStart; + initWrapper(this.module.instantiate, this.module); + } assert(this.module instanceof ModuleWrap); this.module.link(async (dependencySpecifier) => { const dependencyJobPromise = diff --git a/lib/module.js b/lib/module.js index 63e878b17e0f4c..22a3e354c31617 100644 --- a/lib/module.js +++ b/lib/module.js @@ -464,6 +464,7 @@ Module._load = function(request, parent, isMain) { ESMLoader = new Loader(); const userLoader = process.binding('config').userLoader; if (userLoader) { + ESMLoader.isMain = false; const hooks = await ESMLoader.import(userLoader); ESMLoader = new Loader(); ESMLoader.hook(hooks); diff --git a/test/common/inspector-helper.js b/test/common/inspector-helper.js index 1f1738e31b75a8..5e927f215055b9 100644 --- a/test/common/inspector-helper.js +++ b/test/common/inspector-helper.js @@ -5,7 +5,9 @@ const fs = require('fs'); const http = require('http'); const fixtures = require('../common/fixtures'); const { spawn } = require('child_process'); -const url = require('url'); +const { URL, parse: parseURL } = require('url'); +const { getURLFromFilePath } = require('internal/url'); +const path = require('path'); const _MAINSCRIPT = fixtures.path('loop.js'); const DEBUG = false; @@ -171,8 +173,9 @@ class InspectorSession { const scriptId = script['scriptId']; const url = script['url']; this._scriptsIdsByUrl.set(scriptId, url); - if (url === _MAINSCRIPT) + if (getURLFromFilePath(url).toString() === this.scriptURL().toString()) { this.mainScriptId = scriptId; + } } if (this._notificationCallback) { @@ -238,11 +241,13 @@ class InspectorSession { return notification; } - _isBreakOnLineNotification(message, line, url) { + _isBreakOnLineNotification(message, line, expectedScriptPath) { if ('Debugger.paused' === message['method']) { const callFrame = message['params']['callFrames'][0]; const location = callFrame['location']; - assert.strictEqual(url, this._scriptsIdsByUrl.get(location['scriptId'])); + const scriptPath = this._scriptsIdsByUrl.get(location['scriptId']); + assert(scriptPath.toString() === expectedScriptPath.toString(), + `${scriptPath} !== ${expectedScriptPath}`); assert.strictEqual(line, location['lineNumber']); return true; } @@ -291,12 +296,26 @@ class InspectorSession { 'Waiting for the debugger to disconnect...'); await this.disconnect(); } + + scriptPath() { + return this._instance.scriptPath(); + } + + script() { + return this._instance.script(); + } + + scriptURL() { + return getURLFromFilePath(this.scriptPath()); + } } class NodeInstance { constructor(inspectorFlags = ['--inspect-brk=0'], scriptContents = '', scriptFile = _MAINSCRIPT) { + this._scriptPath = scriptFile; + this._script = scriptFile ? null : scriptContents; this._portCallback = null; this.portPromise = new Promise((resolve) => this._portCallback = resolve); this._process = spawnChildProcess(inspectorFlags, scriptContents, @@ -375,7 +394,7 @@ class NodeInstance { const port = await this.portPromise; return http.get({ port, - path: url.parse(devtoolsUrl).path, + path: parseURL(devtoolsUrl).path, headers: { 'Connection': 'Upgrade', 'Upgrade': 'websocket', @@ -425,10 +444,16 @@ class NodeInstance { kill() { this._process.kill(); } -} -function readMainScriptSource() { - return fs.readFileSync(_MAINSCRIPT, 'utf8'); + scriptPath() { + return this._scriptPath; + } + + script() { + if (this._script === null) + this._script = fs.readFileSync(this.scriptPath(), 'utf8'); + return this._script; + } } function onResolvedOrRejected(promise, callback) { @@ -469,7 +494,5 @@ function fires(promise, error, timeoutMs) { } module.exports = { - mainScriptPath: _MAINSCRIPT, - readMainScriptSource, NodeInstance }; diff --git a/test/fixtures/es-modules/loop.mjs b/test/fixtures/es-modules/loop.mjs new file mode 100644 index 00000000000000..33a382bdde7dab --- /dev/null +++ b/test/fixtures/es-modules/loop.mjs @@ -0,0 +1,10 @@ +var t = 1; +var k = 1; +console.log('A message', 5); +while (t > 0) { + if (t++ === 1000) { + t = 0; + console.log(`Outputed message #${k++}`); + } +} +process.exit(55); \ No newline at end of file diff --git a/test/parallel/test-inspect-async-hook-setup-at-inspect.js b/test/parallel/test-inspect-async-hook-setup-at-inspect.js index 869ec21ca991a4..6b1c875138ba01 100644 --- a/test/parallel/test-inspect-async-hook-setup-at-inspect.js +++ b/test/parallel/test-inspect-async-hook-setup-at-inspect.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/parallel/test-inspector-esm.js b/test/parallel/test-inspector-esm.js new file mode 100644 index 00000000000000..b5a1365212a4ac --- /dev/null +++ b/test/parallel/test-inspector-esm.js @@ -0,0 +1,120 @@ +// Flags: --expose-internals +'use strict'; +const common = require('../common'); + +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const fixtures = require('../common/fixtures'); +const { NodeInstance } = require('../common/inspector-helper.js'); + +function assertNoUrlsWhileConnected(response) { + assert.strictEqual(response.length, 1); + assert.ok(!response[0].hasOwnProperty('devtoolsFrontendUrl')); + assert.ok(!response[0].hasOwnProperty('webSocketDebuggerUrl')); +} + +function assertScopeValues({ result }, expected) { + const unmatched = new Set(Object.keys(expected)); + for (const actual of result) { + const value = expected[actual['name']]; + assert.strictEqual(actual['value']['value'], value); + unmatched.delete(actual['name']); + } + assert.deepStrictEqual(Array.from(unmatched.values()), []); +} + +async function testBreakpointOnStart(session) { + console.log('[test]', + 'Verifying debugger stops on start (--inspect-brk option)'); + const commands = [ + { 'method': 'Runtime.enable' }, + { 'method': 'Debugger.enable' }, + { 'method': 'Debugger.setPauseOnExceptions', + 'params': { 'state': 'none' } }, + { 'method': 'Debugger.setAsyncCallStackDepth', + 'params': { 'maxDepth': 0 } }, + { 'method': 'Profiler.enable' }, + { 'method': 'Profiler.setSamplingInterval', + 'params': { 'interval': 100 } }, + { 'method': 'Debugger.setBlackboxPatterns', + 'params': { 'patterns': [] } }, + { 'method': 'Runtime.runIfWaitingForDebugger' } + ]; + + await session.send(commands); + await session.waitForBreakOnLine(0, session.scriptURL()); +} + +async function testBreakpoint(session) { + console.log('[test]', 'Setting a breakpoint and verifying it is hit'); + const commands = [ + { 'method': 'Debugger.setBreakpointByUrl', + 'params': { 'lineNumber': 5, + 'url': session.scriptURL(), + 'columnNumber': 0, + 'condition': '' + } + }, + { 'method': 'Debugger.resume' }, + ]; + await session.send(commands); + const { scriptSource } = await session.send({ + 'method': 'Debugger.getScriptSource', + 'params': { 'scriptId': session.mainScriptId } }); + assert(scriptSource && (scriptSource.includes(session.script())), + `Script source is wrong: ${scriptSource}`); + + await session.waitForConsoleOutput('log', ['A message', 5]); + const paused = await session.waitForBreakOnLine(5, session.scriptURL()); + const scopeId = paused.params.callFrames[0].scopeChain[0].object.objectId; + + console.log('[test]', 'Verify we can read current application state'); + const response = await session.send({ + 'method': 'Runtime.getProperties', + 'params': { + 'objectId': scopeId, + 'ownProperties': false, + 'accessorPropertiesOnly': false, + 'generatePreview': true + } + }); + assertScopeValues(response, { t: 1001, k: 1 }); + + let { result } = await session.send({ + 'method': 'Debugger.evaluateOnCallFrame', 'params': { + 'callFrameId': '{"ordinal":0,"injectedScriptId":1}', + 'expression': 'k + t', + 'objectGroup': 'console', + 'includeCommandLineAPI': true, + 'silent': false, + 'returnByValue': false, + 'generatePreview': true + } + }); + + assert.strictEqual(result['value'], 1002); + + result = (await session.send({ + 'method': 'Runtime.evaluate', 'params': { + 'expression': '5 * 5' + } + })).result; + assert.strictEqual(result['value'], 25); +} + +async function runTest() { + const child = new NodeInstance(['--inspect-brk=0', '--experimental-modules'], + '', fixtures.path('es-modules/loop.mjs')); + + const session = await child.connectInspectorSession(); + assertNoUrlsWhileConnected(await child.httpGet(null, '/json/list')); + await testBreakpointOnStart(session); + await testBreakpoint(session); + await session.runToCompletion(); + assert.strictEqual((await child.expectShutdown()).exitCode, 55); +} + +common.crashOnUnhandledRejection(); + +runTest(); diff --git a/test/parallel/test-inspector-no-crash-ws-after-bindings.js b/test/parallel/test-inspector-no-crash-ws-after-bindings.js index 286373068e8e9b..15fa96952ed125 100644 --- a/test/parallel/test-inspector-no-crash-ws-after-bindings.js +++ b/test/parallel/test-inspector-no-crash-ws-after-bindings.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-async-hook-setup-at-inspect-brk.js b/test/sequential/test-inspector-async-hook-setup-at-inspect-brk.js index 980e9e4d46e1a9..e0c3b4dcb86e37 100644 --- a/test/sequential/test-inspector-async-hook-setup-at-inspect-brk.js +++ b/test/sequential/test-inspector-async-hook-setup-at-inspect-brk.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-async-hook-setup-at-signal.js b/test/sequential/test-inspector-async-hook-setup-at-signal.js index 5ff7dec9473ac2..e0b87b0ebb162c 100644 --- a/test/sequential/test-inspector-async-hook-setup-at-signal.js +++ b/test/sequential/test-inspector-async-hook-setup-at-signal.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-async-stack-traces-promise-then.js b/test/sequential/test-inspector-async-stack-traces-promise-then.js index 9ed61d5ae13675..b5cb651ff4efca 100644 --- a/test/sequential/test-inspector-async-stack-traces-promise-then.js +++ b/test/sequential/test-inspector-async-stack-traces-promise-then.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-async-stack-traces-set-interval.js b/test/sequential/test-inspector-async-stack-traces-set-interval.js index e778bfc80280b0..326032d40b20e6 100644 --- a/test/sequential/test-inspector-async-stack-traces-set-interval.js +++ b/test/sequential/test-inspector-async-stack-traces-set-interval.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-break-e.js b/test/sequential/test-inspector-break-e.js index 9ae47253f49484..8db403ad2cd0d0 100644 --- a/test/sequential/test-inspector-break-e.js +++ b/test/sequential/test-inspector-break-e.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); diff --git a/test/sequential/test-inspector-break-when-eval.js b/test/sequential/test-inspector-break-when-eval.js index e5d01cb189337a..b14e01a30185ed 100644 --- a/test/sequential/test-inspector-break-when-eval.js +++ b/test/sequential/test-inspector-break-when-eval.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-debug-brk-flag.js b/test/sequential/test-inspector-debug-brk-flag.js index 235e7043d80f45..61eb4f97c655dc 100644 --- a/test/sequential/test-inspector-debug-brk-flag.js +++ b/test/sequential/test-inspector-debug-brk-flag.js @@ -1,11 +1,11 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); const assert = require('assert'); -const { mainScriptPath, - NodeInstance } = require('../common/inspector-helper.js'); +const { NodeInstance } = require('../common/inspector-helper.js'); async function testBreakpointOnStart(session) { const commands = [ @@ -24,7 +24,7 @@ async function testBreakpointOnStart(session) { ]; session.send(commands); - await session.waitForBreakOnLine(0, mainScriptPath); + await session.waitForBreakOnLine(0, session.scriptPath()); } async function runTests() { diff --git a/test/sequential/test-inspector-debug-end.js b/test/sequential/test-inspector-debug-end.js index effef9f23315b9..dadee26258d346 100644 --- a/test/sequential/test-inspector-debug-end.js +++ b/test/sequential/test-inspector-debug-end.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-exception.js b/test/sequential/test-inspector-exception.js index 743742f50f1b20..3f83b37c7265a8 100644 --- a/test/sequential/test-inspector-exception.js +++ b/test/sequential/test-inspector-exception.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); diff --git a/test/sequential/test-inspector-ip-detection.js b/test/sequential/test-inspector-ip-detection.js index f7dee4494d3c03..a69a57f55fcbe3 100644 --- a/test/sequential/test-inspector-ip-detection.js +++ b/test/sequential/test-inspector-ip-detection.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); diff --git a/test/sequential/test-inspector-not-blocked-on-idle.js b/test/sequential/test-inspector-not-blocked-on-idle.js index 68e4eaaa57cd3f..3b1befe35df199 100644 --- a/test/sequential/test-inspector-not-blocked-on-idle.js +++ b/test/sequential/test-inspector-not-blocked-on-idle.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-scriptparsed-context.js b/test/sequential/test-inspector-scriptparsed-context.js index f295d737da7e34..abffbfe5fc67f2 100644 --- a/test/sequential/test-inspector-scriptparsed-context.js +++ b/test/sequential/test-inspector-scriptparsed-context.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector-stop-profile-after-done.js b/test/sequential/test-inspector-stop-profile-after-done.js index d0285df175b66f..7069e490255ce5 100644 --- a/test/sequential/test-inspector-stop-profile-after-done.js +++ b/test/sequential/test-inspector-stop-profile-after-done.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); diff --git a/test/sequential/test-inspector.js b/test/sequential/test-inspector.js index 992a12e90229ed..c34c953006276a 100644 --- a/test/sequential/test-inspector.js +++ b/test/sequential/test-inspector.js @@ -1,12 +1,11 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); const assert = require('assert'); -const { mainScriptPath, - readMainScriptSource, - NodeInstance } = require('../common/inspector-helper.js'); +const { NodeInstance } = require('../common/inspector-helper.js'); function checkListResponse(response) { assert.strictEqual(1, response.length); @@ -75,7 +74,7 @@ async function testBreakpointOnStart(session) { ]; await session.send(commands); - await session.waitForBreakOnLine(0, mainScriptPath); + await session.waitForBreakOnLine(0, session.scriptPath()); } async function testBreakpoint(session) { @@ -83,7 +82,7 @@ async function testBreakpoint(session) { const commands = [ { 'method': 'Debugger.setBreakpointByUrl', 'params': { 'lineNumber': 5, - 'url': mainScriptPath, + 'url': session.scriptPath(), 'columnNumber': 0, 'condition': '' } @@ -94,11 +93,11 @@ async function testBreakpoint(session) { const { scriptSource } = await session.send({ 'method': 'Debugger.getScriptSource', 'params': { 'scriptId': session.mainScriptId } }); - assert(scriptSource && (scriptSource.includes(readMainScriptSource())), + assert(scriptSource && (scriptSource.includes(session.script())), `Script source is wrong: ${scriptSource}`); await session.waitForConsoleOutput('log', ['A message', 5]); - const paused = await session.waitForBreakOnLine(5, mainScriptPath); + const paused = await session.waitForBreakOnLine(5, session.scriptPath()); const scopeId = paused.params.callFrames[0].scopeChain[0].object.objectId; console.log('[test]', 'Verify we can read current application state'); From 130d6f3a46745326e9d86f7dcadb6a67f8e74757 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 22 Jan 2018 12:12:38 -0500 Subject: [PATCH 003/131] test: fix a bug & lint issues in inspector-helper PR-URL: https://github.com/nodejs/node/pull/18293 Reviewed-By: Eugene Ostroukhov Reviewed-By: Luigi Pinca Reviewed-By: Guy Bedford --- test/common/inspector-helper.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/common/inspector-helper.js b/test/common/inspector-helper.js index 5e927f215055b9..52e9d01b87dd7e 100644 --- a/test/common/inspector-helper.js +++ b/test/common/inspector-helper.js @@ -5,9 +5,8 @@ const fs = require('fs'); const http = require('http'); const fixtures = require('../common/fixtures'); const { spawn } = require('child_process'); -const { URL, parse: parseURL } = require('url'); +const { parse: parseURL } = require('url'); const { getURLFromFilePath } = require('internal/url'); -const path = require('path'); const _MAINSCRIPT = fixtures.path('loop.js'); const DEBUG = false; @@ -173,7 +172,9 @@ class InspectorSession { const scriptId = script['scriptId']; const url = script['url']; this._scriptsIdsByUrl.set(scriptId, url); - if (getURLFromFilePath(url).toString() === this.scriptURL().toString()) { + const fileUrl = url.startsWith('file:') ? + url : getURLFromFilePath(url).toString(); + if (fileUrl === this.scriptURL().toString()) { this.mainScriptId = scriptId; } } @@ -246,8 +247,9 @@ class InspectorSession { const callFrame = message['params']['callFrames'][0]; const location = callFrame['location']; const scriptPath = this._scriptsIdsByUrl.get(location['scriptId']); - assert(scriptPath.toString() === expectedScriptPath.toString(), - `${scriptPath} !== ${expectedScriptPath}`); + assert.strictEqual(scriptPath.toString(), + expectedScriptPath.toString(), + `${scriptPath} !== ${expectedScriptPath}`); assert.strictEqual(line, location['lineNumber']); return true; } From 3d7bdb4ab27be219815fa381ff864f0dadf41b27 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 20 Jan 2018 01:00:34 +0100 Subject: [PATCH 004/131] test: fix flaky cluster unix socket test Ensure `common.tmpDir` exists before trying to chdir into it. Fixes a "ENOENT: no such file or directory, uv_chdir" error when the temporary directory is removed before running the test. PR-URL: https://github.com/nodejs/node/pull/17407 Reviewed-By: Richard Lau --- test/parallel/test-cluster-net-listen-relative-path.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/parallel/test-cluster-net-listen-relative-path.js b/test/parallel/test-cluster-net-listen-relative-path.js index 0fcc6a0dca4160..2f95d05203d424 100644 --- a/test/parallel/test-cluster-net-listen-relative-path.js +++ b/test/parallel/test-cluster-net-listen-relative-path.js @@ -20,6 +20,7 @@ assert.strictEqual(path.resolve(socketDir, socketName).length > 100, true, if (cluster.isMaster) { // ensure that the worker exits peacefully + common.refreshTmpDir(); process.chdir(common.tmpDir); fs.mkdirSync(socketDir); cluster.fork().on('exit', common.mustCall(function(statusCode) { From 87648e245b5b487f9b738f81a8ec534d3f439b26 Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Tue, 23 Jan 2018 10:29:26 +0100 Subject: [PATCH 005/131] test: force context allocation in test module V8's behavior changed in c3bd741efd. Top-level variables in a module are no longer context-allocated by default. PR-URL: https://github.com/nodejs/node/pull/18312 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- test/fixtures/es-modules/loop.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/fixtures/es-modules/loop.mjs b/test/fixtures/es-modules/loop.mjs index 33a382bdde7dab..edd111abb9e9b7 100644 --- a/test/fixtures/es-modules/loop.mjs +++ b/test/fixtures/es-modules/loop.mjs @@ -7,4 +7,7 @@ while (t > 0) { console.log(`Outputed message #${k++}`); } } -process.exit(55); \ No newline at end of file +process.exit(55); + +// test/parallel/test-inspector-esm.js expects t and k to be context-allocated. +(function force_context_allocation() { return t + k; }) From 384d4e4e435f099ac017b27a7d7f1f099c284531 Mon Sep 17 00:00:00 2001 From: Seth Brenith Date: Tue, 23 Jan 2018 16:04:17 -0800 Subject: [PATCH 006/131] http: switch on string values Long ago, V8 was much faster switching on string lengths than values. That is no longer the case, so we can simplify a couple of methods. PR-URL: https://github.com/nodejs/node/pull/18351 Reviewed-By: James M Snell Reviewed-By: Kyle Farnung Reviewed-By: Anatoli Papirovski Reviewed-By: Gireesh Punathil Reviewed-By: Colin Ihrig Reviewed-By: Jon Moss --- benchmark/http/set_header.js | 30 +++++++++++++++++++++++++++ lib/_http_outgoing.js | 39 +++++++++++++++--------------------- 2 files changed, 46 insertions(+), 23 deletions(-) create mode 100644 benchmark/http/set_header.js diff --git a/benchmark/http/set_header.js b/benchmark/http/set_header.js new file mode 100644 index 00000000000000..22de61b3f847a3 --- /dev/null +++ b/benchmark/http/set_header.js @@ -0,0 +1,30 @@ +'use strict'; + +const common = require('../common.js'); +const { OutgoingMessage } = require('_http_outgoing'); + +const bench = common.createBenchmark(main, { + value: [ + 'X-Powered-By', + 'Vary', + 'Set-Cookie', + 'Content-Type', + 'Content-Length', + 'Connection', + 'Transfer-Encoding' + ], + n: [1e6], +}); + +function main(conf) { + const n = +conf.n; + const value = conf.value; + + const og = new OutgoingMessage(); + + bench.start(); + for (var i = 0; i < n; i++) { + og.setHeader(value, ''); + } + bench.end(n); +} diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 8fecfc8a8db878..58d0753cffdb3e 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -515,18 +515,15 @@ OutgoingMessage.prototype.setHeader = function setHeader(name, value) { const key = name.toLowerCase(); this[outHeadersKey][key] = [name, value]; - switch (key.length) { - case 10: - if (key === 'connection') - this._removedConnection = false; + switch (key) { + case 'connection': + this._removedConnection = false; break; - case 14: - if (key === 'content-length') - this._removedContLen = false; + case 'content-length': + this._removedContLen = false; break; - case 17: - if (key === 'transfer-encoding') - this._removedTE = false; + case 'transfer-encoding': + this._removedTE = false; break; } }; @@ -588,22 +585,18 @@ OutgoingMessage.prototype.removeHeader = function removeHeader(name) { var key = name.toLowerCase(); - switch (key.length) { - case 10: - if (key === 'connection') - this._removedConnection = true; + switch (key) { + case 'connection': + this._removedConnection = true; break; - case 14: - if (key === 'content-length') - this._removedContLen = true; + case 'content-length': + this._removedContLen = true; break; - case 17: - if (key === 'transfer-encoding') - this._removedTE = true; + case 'transfer-encoding': + this._removedTE = true; break; - case 4: - if (key === 'date') - this.sendDate = false; + case 'date': + this.sendDate = false; break; } From f4fbcf371e1bf6076deb7ed6cfa57ae6ff252d62 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Fri, 19 Jan 2018 15:42:59 -0500 Subject: [PATCH 007/131] domain: further abstract usage in C++ Move the majority of C++ domain-related code into JS land by introducing a top level domain callback which handles entering & exiting the domain. Move the rest of the domain necessities into their own file that creates an internal binding, to avoid exposing domain-related code on the process object. Modify an existing test slightly to better test domain-related code. PR-URL: https://github.com/nodejs/node/pull/18291 Reviewed-By: Ben Noordhuis Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- lib/domain.js | 12 +++- node.gyp | 1 + src/env-inl.h | 9 --- src/env.h | 7 +-- src/node.cc | 78 +++--------------------- src/node_domain.cc | 34 +++++++++++ src/node_internals.h | 1 + test/addons/repl-domain-abort/binding.cc | 16 +++-- test/addons/repl-domain-abort/test.js | 3 +- test/cctest/node_module_reg.cc | 1 + 10 files changed, 72 insertions(+), 90 deletions(-) create mode 100644 src/node_domain.cc diff --git a/lib/domain.js b/lib/domain.js index 9670a53629e16b..08fbd207f171d3 100644 --- a/lib/domain.js +++ b/lib/domain.js @@ -94,11 +94,21 @@ process.setUncaughtExceptionCaptureCallback = function(fn) { throw err; }; +function topLevelDomainCallback(cb, ...args) { + const domain = this.domain; + if (domain) + domain.enter(); + const ret = Reflect.apply(cb, this, args); + if (domain) + domain.exit(); + return ret; +} + // It's possible to enter one domain while already inside // another one. The stack is each entered domain. const stack = []; exports._stack = stack; -process._setupDomainUse(); +internalBinding('domain').enable(topLevelDomainCallback); function updateExceptionCapture() { if (stack.every((domain) => domain.listenerCount('error') === 0)) { diff --git a/node.gyp b/node.gyp index f79aee554c6bca..7966a4f159e0ef 100644 --- a/node.gyp +++ b/node.gyp @@ -293,6 +293,7 @@ 'src/node_constants.cc', 'src/node_contextify.cc', 'src/node_debug_options.cc', + 'src/node_domain.cc', 'src/node_file.cc', 'src/node_http2.cc', 'src/node_http_parser.cc', diff --git a/src/env-inl.h b/src/env-inl.h index 7cdd9cecd378b9..bf919644dfbe49 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -278,7 +278,6 @@ inline Environment::Environment(IsolateData* isolate_data, : isolate_(context->GetIsolate()), isolate_data_(isolate_data), timer_base_(uv_now(isolate_data->event_loop())), - using_domains_(false), printed_error_(false), trace_sync_io_(false), abort_on_uncaught_exception_(false), @@ -379,14 +378,6 @@ inline uint64_t Environment::timer_base() const { return timer_base_; } -inline bool Environment::using_domains() const { - return using_domains_; -} - -inline void Environment::set_using_domains(bool value) { - using_domains_ = value; -} - inline bool Environment::printed_error() const { return printed_error_; } diff --git a/src/env.h b/src/env.h index 7c78ba63396a0c..bc08e6baef280a 100644 --- a/src/env.h +++ b/src/env.h @@ -91,7 +91,6 @@ class ModuleWrap; V(decorated_private_symbol, "node:decorated") \ V(npn_buffer_private_symbol, "node:npnBuffer") \ V(selected_npn_buffer_private_symbol, "node:selectedNpnBuffer") \ - V(domain_private_symbol, "node:domain") \ // Strings are per-isolate primitives but Environment proxies them // for the sake of convenience. Strings should be ASCII-only. @@ -128,7 +127,6 @@ class ModuleWrap; V(dns_soa_string, "SOA") \ V(dns_srv_string, "SRV") \ V(dns_txt_string, "TXT") \ - V(domain_string, "domain") \ V(emit_warning_string, "emitWarning") \ V(exchange_string, "exchange") \ V(encoding_string, "encoding") \ @@ -283,6 +281,7 @@ class ModuleWrap; V(async_hooks_binding, v8::Object) \ V(buffer_prototype_object, v8::Object) \ V(context, v8::Context) \ + V(domain_callback, v8::Function) \ V(host_import_module_dynamically_callback, v8::Function) \ V(http2ping_constructor_template, v8::ObjectTemplate) \ V(http2stream_constructor_template, v8::ObjectTemplate) \ @@ -537,9 +536,6 @@ class Environment { inline IsolateData* isolate_data() const; - inline bool using_domains() const; - inline void set_using_domains(bool value); - inline bool printed_error() const; inline void set_printed_error(bool value); @@ -693,7 +689,6 @@ class Environment { AsyncHooks async_hooks_; TickInfo tick_info_; const uint64_t timer_base_; - bool using_domains_; bool printed_error_; bool trace_sync_io_; bool abort_on_uncaught_exception_; diff --git a/src/node.cc b/src/node.cc index 7fe1e385d7a1f0..7cace30f5997e4 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1118,62 +1118,6 @@ bool ShouldAbortOnUncaughtException(Isolate* isolate) { } -Local GetDomainProperty(Environment* env, Local object) { - Local domain_v = - object->GetPrivate(env->context(), env->domain_private_symbol()) - .ToLocalChecked(); - if (domain_v->IsObject()) { - return domain_v; - } - return object->Get(env->context(), env->domain_string()).ToLocalChecked(); -} - - -void DomainEnter(Environment* env, Local object) { - Local domain_v = GetDomainProperty(env, object); - if (domain_v->IsObject()) { - Local domain = domain_v.As(); - Local enter_v = domain->Get(env->enter_string()); - if (enter_v->IsFunction()) { - if (enter_v.As()->Call(domain, 0, nullptr).IsEmpty()) { - FatalError("node::AsyncWrap::MakeCallback", - "domain enter callback threw, please report this"); - } - } - } -} - - -void DomainExit(Environment* env, v8::Local object) { - Local domain_v = GetDomainProperty(env, object); - if (domain_v->IsObject()) { - Local domain = domain_v.As(); - Local exit_v = domain->Get(env->exit_string()); - if (exit_v->IsFunction()) { - if (exit_v.As()->Call(domain, 0, nullptr).IsEmpty()) { - FatalError("node::AsyncWrap::MakeCallback", - "domain exit callback threw, please report this"); - } - } - } -} - -void SetupDomainUse(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - if (env->using_domains()) - return; - env->set_using_domains(true); - - HandleScope scope(env->isolate()); - - // Do a little housekeeping. - env->process_object()->Delete( - env->context(), - FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")).FromJust(); -} - - void RunMicrotasks(const FunctionCallbackInfo& args) { args.GetIsolate()->RunMicrotasks(); } @@ -1294,11 +1238,6 @@ InternalCallbackScope::InternalCallbackScope(Environment* env, // If you hit this assertion, you forgot to enter the v8::Context first. CHECK_EQ(Environment::GetCurrent(env->isolate()), env); - if (asyncContext.async_id == 0 && env->using_domains() && - !object_.IsEmpty()) { - DomainEnter(env, object_); - } - if (asyncContext.async_id != 0) { // No need to check a return value because the application will exit if // an exception occurs. @@ -1328,11 +1267,6 @@ void InternalCallbackScope::Close() { AsyncWrap::EmitAfter(env_, async_context_.async_id); } - if (async_context_.async_id == 0 && env_->using_domains() && - !object_.IsEmpty()) { - DomainExit(env_, object_); - } - if (IsInnerMakeCallback()) { return; } @@ -1379,7 +1313,16 @@ MaybeLocal InternalMakeCallback(Environment* env, return Undefined(env->isolate()); } - MaybeLocal ret = callback->Call(env->context(), recv, argc, argv); + Local domain_cb = env->domain_callback(); + MaybeLocal ret; + if (asyncContext.async_id != 0 || domain_cb.IsEmpty() || recv.IsEmpty()) { + ret = callback->Call(env->context(), recv, argc, argv); + } else { + std::vector> args(1 + argc); + args[0] = callback; + std::copy(&argv[0], &argv[argc], &args[1]); + ret = domain_cb->Call(env->context(), recv, args.size(), &args[0]); + } if (ret.IsEmpty()) { // NOTE: For backwards compatibility with public API we return Undefined() @@ -3635,7 +3578,6 @@ void SetupProcessObject(Environment* env, env->SetMethod(process, "_setupProcessObject", SetupProcessObject); env->SetMethod(process, "_setupNextTick", SetupNextTick); env->SetMethod(process, "_setupPromises", SetupPromises); - env->SetMethod(process, "_setupDomainUse", SetupDomainUse); } diff --git a/src/node_domain.cc b/src/node_domain.cc new file mode 100644 index 00000000000000..f4f585ac4f43e2 --- /dev/null +++ b/src/node_domain.cc @@ -0,0 +1,34 @@ +#include "v8.h" +#include "node_internals.h" + +namespace node { +namespace domain { + +using v8::Context; +using v8::Function; +using v8::FunctionCallbackInfo; +using v8::Local; +using v8::Object; +using v8::Value; + + +void Enable(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + CHECK(args[0]->IsFunction()); + + env->set_domain_callback(args[0].As()); +} + +void Initialize(Local target, + Local unused, + Local context) { + Environment* env = Environment::GetCurrent(context); + + env->SetMethod(target, "enable", Enable); +} + +} // namespace domain +} // namespace node + +NODE_MODULE_CONTEXT_AWARE_INTERNAL(domain, node::domain::Initialize) diff --git a/src/node_internals.h b/src/node_internals.h index 06f7b6bdeb23ed..469d8723368714 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -104,6 +104,7 @@ struct sockaddr; V(cares_wrap) \ V(config) \ V(contextify) \ + V(domain) \ V(fs) \ V(fs_event_wrap) \ V(http2) \ diff --git a/test/addons/repl-domain-abort/binding.cc b/test/addons/repl-domain-abort/binding.cc index 1b4dbfa84e5054..d2f7560048fd46 100644 --- a/test/addons/repl-domain-abort/binding.cc +++ b/test/addons/repl-domain-abort/binding.cc @@ -22,6 +22,7 @@ #include #include +using v8::Boolean; using v8::Function; using v8::FunctionCallbackInfo; using v8::Local; @@ -31,11 +32,16 @@ using v8::Value; void Method(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); - node::MakeCallback(isolate, - isolate->GetCurrentContext()->Global(), - args[0].As(), - 0, - nullptr); + Local params[] = { + Boolean::New(isolate, true), + Boolean::New(isolate, false) + }; + Local ret = node::MakeCallback(isolate, + isolate->GetCurrentContext()->Global(), + args[0].As(), + 2, + params); + assert(ret->IsTrue()); } void init(Local exports) { diff --git a/test/addons/repl-domain-abort/test.js b/test/addons/repl-domain-abort/test.js index 1d6116159c85b6..2049fe6e6a23f5 100644 --- a/test/addons/repl-domain-abort/test.js +++ b/test/addons/repl-domain-abort/test.js @@ -40,7 +40,8 @@ const lines = [ // This line shouldn't cause an assertion error. `require('${buildPath}')` + // Log output to double check callback ran. - '.method(function() { console.log(\'cb_ran\'); });', + '.method(function(v1, v2) {' + + 'console.log(\'cb_ran\'); return v1 === true && v2 === false; });', ]; const dInput = new stream.Readable(); diff --git a/test/cctest/node_module_reg.cc b/test/cctest/node_module_reg.cc index a0736d2cc3e692..bd4f20bc9f823d 100644 --- a/test/cctest/node_module_reg.cc +++ b/test/cctest/node_module_reg.cc @@ -5,6 +5,7 @@ void _register_cares_wrap() {} void _register_config() {} void _register_contextify() {} +void _register_domain() {} void _register_fs() {} void _register_fs_event_wrap() {} void _register_http2() {} From f86f6a70354263efb15fb144409381b4aa3cf042 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Fri, 10 Nov 2017 10:40:55 -0800 Subject: [PATCH 008/131] doc: Update tools/icu/README.md - remove TODOs: the one about defaults has been addressed, and the one about testing is a work item that doesn't belong in a doc. - add some background information Fixes: https://github.com/nodejs/node/issues/7843 PR-URL: https://github.com/nodejs/node/pull/16939 Reviewed-By: James M Snell Reviewed-By: Michael Dawson --- tools/icu/README.md | 61 +++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/tools/icu/README.md b/tools/icu/README.md index 2b5d74ac205fb6..de17f2b033cc49 100644 --- a/tools/icu/README.md +++ b/tools/icu/README.md @@ -1,4 +1,15 @@ -# Notes about the icu directory. +# Notes about the `tools/icu` subdirectory + +This directory contains tools, data, and information about the [http://icu-project.org](ICU) (International Components for Unicode) integration. ICU is used to provide internationalization functionality. + +- `patches/` are one-off patches, actually entire source file replacements, organized by ICU version number. +- `icu_small.json` controls the "small" (English only) ICU. It is input to `icutrim.py` +- `icu-generic.gyp` is the build file used for most ICU builds within ICU. +- `icu-system.gyp` is an alternate build file used when `--with-intl=system-icu` is invoked. It builds against the `pkg-config` located ICU. +- `iculslocs.cc` is source for the `iculslocs` utility, invoked by `icutrim.py` as part of repackaging. Not used separately. See source for more details. +- `no-op.cc` — empty function to convince gyp to use a C++ compiler. +- `README.md` — you are here +- `shrink-icu-src.py` — this is used during upgrade (see guide below) ## How to upgrade ICU @@ -12,13 +23,13 @@ make ``` -(The equivalent `vcbuild.bat` commands should work also. Note that we use the `.tgz` and not the `.zip` here, -that is because of line endings.) +> _Note_ in theory, the equivalent `vcbuild.bat` commands should work also, +but the commands below are makefile-centric. -- (note- may need to make changes in `icu-generic.gyp` or `tools/icu/patches` for -version specific stuff) +- If there are ICU version-specific changes needed, you may need to make changes in `icu-generic.gyp` or add patch files to `tools/icu/patches`. + - Specifically, look for the lists in `sources!` in the `icu-generic.gyp` for files to exclude. -- Verify the node build works +- Verify the node build works: ```shell make test-ci @@ -27,13 +38,12 @@ make test-ci Also running + ```js new Intl.DateTimeFormat('es', {month: 'long'}).format(new Date(9E8)); ``` …Should return `January` not `enero`. -(TODO here: improve [testing](https://github.com/nodejs/Intl/issues/16)) - - Now, copy `deps/icu` over to `deps/icu-small` @@ -43,25 +53,25 @@ python tools/icu/shrink-icu-src.py - Now, do a clean rebuild of node to test: -(TODO: fix this when these options become default) - ```shell -./configure --with-intl=small-icu --with-icu-source=deps/icu-small +make -k distclean +./configure make ``` - Test this newly default-generated Node.js + ```js process.versions.icu; new Intl.DateTimeFormat('es', {month: 'long'}).format(new Date(9E8)); ``` -(should return your updated ICU version number, and also `January` again.) +(This should print your updated ICU version number, and also `January` again.) -- You are ready to check in the updated `deps/small-icu`. -This is a big commit, so make this a separate commit from other changes. +You are ready to check in the updated `deps/small-icu`. This is a big commit, +so make this a separate commit from the smaller changes. - Now, rebuild the Node license. @@ -85,22 +95,23 @@ make test-ci - commit the change to `configure` along with the updated `LICENSE` file. + - Note: To simplify review, I often will “pre-land” this patch, meaning that I run the patch through `curl -L https://github.com/nodejs/node/pull/xxx.patch | git am -3 --whitespace=fix` per the collaborator’s guide… and then push that patched branch into my PR's branch. This reduces the whitespace changes that show up in the PR, since the final land will eliminate those anyway. + ----- -## Notes about these tools +## Postscript about the tools -The files in this directory were written for the node.js effort. It's -the intent of their author (Steven R. Loomis / srl295) to merge them -upstream into ICU, pending much discussion within the ICU-PMC. +The files in this directory were written for the node.js effort. +It was the intent of their author (Steven R. Loomis / srl295) to +merge them upstream into ICU, pending much discussion within the +ICU-TC. `icu_small.json` is somewhat node-specific as it specifies a "small ICU" configuration file for the `icutrim.py` script. `icutrim.py` and `iculslocs.cpp` may themselves be superseded by components built into -ICU in the future. - -The following tickets were opened during this work, and their -resolution may inform the reader as to the current state of icu-trim -upstream: +ICU in the future. As of this writing, however, the tools are separate +entities within Node, although theyare being scrutinized by interested +members of the ICU-TC. The “upstream” ICU bugs are given below. * [#10919](http://bugs.icu-project.org/trac/ticket/10919) (experimental branch - may copy any source patches here) @@ -108,7 +119,3 @@ upstream: (data packaging improvements) * [#10923](http://bugs.icu-project.org/trac/ticket/10923) (rewrite data building in python) - -When/if components (not including the `.json` file) are merged into -ICU, this code and `configure` will be updated to detect and use those -variants rather than the ones in this directory. From f48b47c4cf4f50f5b8899415deef283b2cf7d0c4 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 29 Jan 2018 20:08:21 -0500 Subject: [PATCH 009/131] tools: fix icu readme lint error PR-URL: https://github.com/nodejs/node/pull/18445 Reviewed-By: Colin Ihrig Reviewed-By: Vse Mozhet Byt --- tools/icu/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/icu/README.md b/tools/icu/README.md index de17f2b033cc49..e1c753ebf3347e 100644 --- a/tools/icu/README.md +++ b/tools/icu/README.md @@ -24,7 +24,7 @@ make ``` > _Note_ in theory, the equivalent `vcbuild.bat` commands should work also, -but the commands below are makefile-centric. +> but the commands below are makefile-centric. - If there are ICU version-specific changes needed, you may need to make changes in `icu-generic.gyp` or add patch files to `tools/icu/patches`. - Specifically, look for the lists in `sources!` in the `icu-generic.gyp` for files to exclude. From 835807eb604f599e263b74778eac6e945f0dbff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Thu, 25 Jan 2018 16:50:05 +0100 Subject: [PATCH 010/131] doc: warn about GCM authenticity PR-URL: https://github.com/nodejs/node/pull/18376 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- doc/api/crypto.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index f264f4ed20538e..ac1c709429ff36 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -425,6 +425,14 @@ received _authentication tag_. If no tag is provided, or if the cipher text has been tampered with, [`decipher.final()`][] will throw, indicating that the cipher text should be discarded due to failed authentication. +Note that this Node.js version does not verify the length of GCM authentication +tags. Such a check *must* be implemented by applications and is crucial to the +authenticity of the encrypted data, otherwise, an attacker can use an +arbitrarily short authentication tag to increase the chances of successfully +passing authentication (up to 0.39%). It is highly recommended to associate one +of the values 16, 15, 14, 13, 12, 8 or 4 bytes with each key, and to only permit +authentication tags of that length, see [NIST SP 800-38D][]. + The `decipher.setAuthTag()` method must be called before [`decipher.final()`][]. @@ -2414,6 +2422,7 @@ the `crypto`, `tls`, and `https` modules and are generally specific to OpenSSL. [HTML5's `keygen` element]: https://www.w3.org/TR/html5/forms.html#the-keygen-element [NIST SP 800-131A]: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf [NIST SP 800-132]: http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf +[NIST SP 800-38D]: http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf [Nonce-Disrespecting Adversaries]: https://github.com/nonce-disrespect/nonce-disrespect [OpenSSL's SPKAC implementation]: https://www.openssl.org/docs/man1.0.2/apps/spkac.html [RFC 2412]: https://www.rfc-editor.org/rfc/rfc2412.txt From 08a93ef9ebe39eaaaf3f64a71182c33af1f629d7 Mon Sep 17 00:00:00 2001 From: Roman Reiss Date: Mon, 29 Jan 2018 21:28:48 +0100 Subject: [PATCH 011/131] doc: fix manpage warnings Fixes: https://github.com/nodejs/node/issues/18434 Reviewed-By: Ben Noordhuis Reviewed-By: Daniel Bevenius Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Colin Ihrig --- doc/node.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/node.1 b/doc/node.1 index a4395c099b9600..836b901bead12d 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -37,9 +37,9 @@ node \- Server-side JavaScript runtime .RI [ script.js \ | .B -e .RI \&" script \&" -.R | +.RI | .B - -.R ] +.RI ] .B [--] .RI [ arguments ] .br From 8dc159df5f0d0b92e077113d0cea200e25ce6534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BA=D0=BE=D0=B2=D0=BE=D1=80=D0=BE=D0=B4=D0=B0=20?= =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=90=D0=BD=D0=B4=D1=80?= =?UTF-8?q?=D0=B5=D0=B5=D0=B2=D0=B8=D1=87?= Date: Mon, 29 Jan 2018 20:10:31 +0300 Subject: [PATCH 012/131] doc: add pending-deprecation to COLLABORATOR_GUIDE This is described as being a doc-only deprecation subset. Refs: https://github.com/nodejs/node/issues/18417 PR-URL: https://github.com/nodejs/node/pull/18433 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Daniel Bevenius Reviewed-By: Rich Trott --- COLLABORATOR_GUIDE.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/COLLABORATOR_GUIDE.md b/COLLABORATOR_GUIDE.md index 5a1d51dafe375c..e00437ee7cfe37 100644 --- a/COLLABORATOR_GUIDE.md +++ b/COLLABORATOR_GUIDE.md @@ -368,7 +368,10 @@ Node.js uses three Deprecation levels: being staged for deprecation in a future Node.js major release. An explicit notice indicating the deprecated status is added to the API documentation but no functional changes are implemented in the code. There will be no - runtime deprecation warnings emitted for such deprecations. + runtime deprecation warnings emitted for such deprecations by default. + Documentation-only deprecations may trigger a runtime warning when launched + with [`--pending-deprecation`][] flag (or its alternative, + `NODE_PENDING_DEPRECATION=1` environment variable). * *Runtime Deprecation* refers to the use of process warnings emitted at runtime the first time that a deprecated API is used. A command-line @@ -744,6 +747,7 @@ LTS working group and the Release team. [backporting guide]: doc/guides/backporting-to-release-lines.md [Stability Index]: doc/api/documentation.md#stability-index [Enhancement Proposal]: https://github.com/nodejs/node-eps +[`--pending-deprecation`]: doc/api/cli.md#--pending-deprecation [git-username]: https://help.github.com/articles/setting-your-username-in-git/ [`node-core-utils`]: https://github.com/nodejs/node-core-utils [TSC]: https://github.com/nodejs/TSC From 1b7618d3be05afae4558df239e5996753231f5bf Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Wed, 24 Jan 2018 10:50:50 -0800 Subject: [PATCH 013/131] doc: reorder section on updating PR branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It makes more sense to provide instructions on how to update the PR branch before instructions on pushing the commit. PR-URL: https://github.com/nodejs/node/pull/18355 Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Jon Moss --- COLLABORATOR_GUIDE.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/COLLABORATOR_GUIDE.md b/COLLABORATOR_GUIDE.md index e00437ee7cfe37..95ef0653552c1e 100644 --- a/COLLABORATOR_GUIDE.md +++ b/COLLABORATOR_GUIDE.md @@ -596,20 +596,20 @@ Validate that the commit message is properly formatted using $ git rev-list upstream/master...HEAD | xargs core-validate-commit ``` +Optional: When landing your own commits, force push the amended commit to the +branch you used to open the pull request. If your branch is called `bugfix`, +then the command would be `git push --force-with-lease origin master:bugfix`. +When the pull request is closed, this will cause the pull request to +show the purple merged status rather than the red closed status that is +usually used for pull requests that weren't merged. + Time to push it: ```text $ git push upstream master ``` -* Optional: Force push the amended commit to the branch you used to -open the pull request. If your branch is called `bugfix`, then the -command would be `git push --force-with-lease origin master:bugfix`. -When the pull request is closed, this will cause the pull request to -show the purple merged status rather than the red closed status that is -usually used for pull requests that weren't merged. Only do this when -landing your own contributions. -* Close the pull request with a "Landed in ``" comment. If +Close the pull request with a "Landed in ``" comment. If your pull request shows the purple merged status then you should still add the "Landed in .." comment if you added multiple commits. From 10b33455d27a6eed91f941924dffccf65ea66852 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Tue, 30 Jan 2018 13:34:57 -0500 Subject: [PATCH 014/131] src: fix vector subscript out of range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18460 Fixes: https://github.com/nodejs/node/issues/18459 Reviewed-By: Tobias Nießen Reviewed-By: Nikolai Vavilov Reviewed-By: Colin Ihrig Reviewed-By: Khaidi Chu --- src/node.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node.cc b/src/node.cc index 7cace30f5997e4..86cbe3138789f2 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1320,7 +1320,7 @@ MaybeLocal InternalMakeCallback(Environment* env, } else { std::vector> args(1 + argc); args[0] = callback; - std::copy(&argv[0], &argv[argc], &args[1]); + std::copy(&argv[0], &argv[argc], args.begin() + 1); ret = domain_cb->Call(env->context(), recv, args.size(), &args[0]); } From 1c0690910c833efaae75ed243416e958dd574723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Tue, 30 Jan 2018 23:40:29 +0100 Subject: [PATCH 015/131] url: simplify loop in parser PR-URL: https://github.com/nodejs/node/pull/18468 Reviewed-By: Ruben Bridgewater Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- lib/url.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/url.js b/lib/url.js index d27891d36b12d2..cb524fd9a87347 100644 --- a/lib/url.js +++ b/lib/url.js @@ -883,7 +883,7 @@ Url.prototype.resolveObject = function resolveObject(relative) { // if the path is allowed to go above the root, restore leading ..s if (!mustEndAbs && !removeAllDots) { - for (; up--; up) { + while (up--) { srcPath.unshift('..'); } } From fea9f94da068984716db869eb4297adc7ca0a4fd Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 31 Jan 2018 09:35:31 -0800 Subject: [PATCH 016/131] doc: add Gibson Fahnestock to TSC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Welcome Gibson to the TSC! PR-URL: https://github.com/nodejs/node/pull/18481 Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Daniel Bevenius Reviewed-By: Jon Moss Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Evan Lucas Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Richard Lau Reviewed-By: Michael Dawson --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 47b8694797637b..2e8139bd1f98d7 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,8 @@ For more information about the governance of the Node.js project, see **Franziska Hinkelmann** <franziska.hinkelmann@gmail.com> (she/her) * [Fishrock123](https://github.com/Fishrock123) - **Jeremiah Senkpiel** <fishrock123@rocketmail.com> +* [gibfahn](https://github.com/gibfahn) - +**Gibson Fahnestock** <gibfahn@gmail.com> (he/him) * [indutny](https://github.com/indutny) - **Fedor Indutny** <fedor.indutny@gmail.com> * [jasnell](https://github.com/jasnell) - From c8b92e2a1b3d1dfdaaf6fa8d6c7b078b0632d5bf Mon Sep 17 00:00:00 2001 From: Aaron Kau Date: Sat, 27 Jan 2018 14:20:13 -0500 Subject: [PATCH 017/131] n-api: change assert ok check to notStrictEqual. PR-URL: https://github.com/nodejs/node/pull/18414 Reviewed-By: Gireesh Punathil Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- test/addons-napi/test_general/test.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/test/addons-napi/test_general/test.js b/test/addons-napi/test_general/test.js index ee6618c8121289..c89d718ca18575 100644 --- a/test/addons-napi/test_general/test.js +++ b/test/addons-napi/test_general/test.js @@ -28,9 +28,9 @@ assert.strictEqual(test_general.testGetPrototype(baseObject), Object.getPrototypeOf(baseObject)); assert.strictEqual(test_general.testGetPrototype(extendedObject), Object.getPrototypeOf(extendedObject)); -assert.ok(test_general.testGetPrototype(baseObject) !== - test_general.testGetPrototype(extendedObject), - 'Prototypes for base and extended should be different'); +// Prototypes for base and extended should be different. +assert.notStrictEqual(test_general.testGetPrototype(baseObject), + test_general.testGetPrototype(extendedObject)); // test version management functions // expected version is currently 1 @@ -70,17 +70,15 @@ assert.strictEqual(test_general.derefItemWasCalled(), true, // Assert that wrapping twice fails. const x = {}; test_general.wrap(x); -assert.throws(function() { - test_general.wrap(x); -}, Error); +assert.throws(() => test_general.wrap(x), Error); // Ensure that wrapping, removing the wrap, and then wrapping again works. const y = {}; test_general.wrap(y); test_general.removeWrap(y); -assert.doesNotThrow(function() { - test_general.wrap(y); -}, Error, 'Wrapping twice succeeds if a remove_wrap() separates the instances'); +assert.doesNotThrow(() => test_general.wrap(y), Error, + 'Wrapping twice succeeds if a remove_wrap()' + + ' separates the instances'); // Ensure that removing a wrap and garbage collecting does not fire the // finalize callback. From 0915a85cce0c1a4025ca14fa3f65b9e989b555e2 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 10 Jan 2018 09:42:10 -0800 Subject: [PATCH 018/131] perf_hooks: add warning when too many entries in the timeline PR-URL: https://github.com/nodejs/node/pull/18087 Reviewed-By: Matteo Collina --- doc/api/perf_hooks.md | 14 +++++++ lib/perf_hooks.js | 49 +++++++++++++++++++++-- test/parallel/test-performance-warning.js | 29 ++++++++++++++ 3 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 test/parallel/test-performance-warning.js diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index 6d98d25af37cbc..608bee8d574680 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -125,6 +125,20 @@ Creates a new `PerformanceMark` entry in the Performance Timeline. A `performanceEntry.duration` is always `0`. Performance marks are used to mark specific significant moments in the Performance Timeline. +### performance.maxEntries + + +Value: {number} + +The maximum number of Performance Entry items that should be added to the +Performance Timeline. This limit is not strictly enforced, but a process +warning will be emitted if the number of entries in the timeline exceeds +this limit. + +Defaults to 150. + ### performance.measure(name, startMark, endMark) -* Returns: {Worker} A reference to `worker`. +* Returns: {cluster.Worker} A reference to `worker`. In a worker, this function will close all servers, wait for the `'close'` event on those servers, and then disconnect the IPC channel. diff --git a/doc/api/console.md b/doc/api/console.md index 84b7e2c11dac8e..0cc55b7fcbc53a 100644 --- a/doc/api/console.md +++ b/doc/api/console.md @@ -78,8 +78,8 @@ const { Console } = console; ``` ### new Console(stdout[, stderr]) -* `stdout` {Writable} -* `stderr` {Writable} +* `stdout` {stream.Writable} +* `stderr` {stream.Writable} Creates a new `Console` with one or two writable stream instances. `stdout` is a writable stream to print log or info output. `stderr` is used for warning or diff --git a/doc/api/fs.md b/doc/api/fs.md index f26dc6efbd204b..78c22e7d0678ff 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -799,7 +799,7 @@ changes: * `path` {string|Buffer|URL} * `mode` {integer} **Default:** `fs.constants.F_OK` -* Returns: `undefined` +* Returns: {undefined} Synchronously tests a user's permissions for the file or directory specified by `path`. The `mode` argument is an optional integer that specifies the diff --git a/doc/api/http2.md b/doc/api/http2.md index f4d20e2922c9b4..63500bd8cd158f 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -770,7 +770,7 @@ they respectively default to: added: v8.4.0 --> -* Extends: {Duplex} +* Extends: {stream.Duplex} Each instance of the `Http2Stream` class represents a bidirectional HTTP/2 communications stream over an `Http2Session` instance. Any single `Http2Session` diff --git a/doc/api/process.md b/doc/api/process.md index 405d6296353f88..fc2a450f9814a5 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -659,7 +659,7 @@ changes: * `module` {Object} * `filename` {string} -* `flags` {os.constants.dlopen}. Defaults to `os.constants.dlopen.RTLD_LAZY`. +* `flags` {os.constants.dlopen} Defaults to `os.constants.dlopen.RTLD_LAZY`. The `process.dlopen()` method allows to dynamically load shared objects. It is primarily used by `require()` to load diff --git a/doc/api/readline.md b/doc/api/readline.md index 7ba1277dce2d9c..42d07da2d0e418 100644 --- a/doc/api/readline.md +++ b/doc/api/readline.md @@ -323,7 +323,7 @@ Interface's `input` *as if it were provided by the user*. added: v0.7.7 --> -* `stream` {Writable} +* `stream` {stream.Writable} * `dir` {number} * `-1` - to the left from cursor * `1` - to the right from cursor @@ -338,7 +338,7 @@ in a specified direction identified by `dir`. added: v0.7.7 --> -* `stream` {Writable} +* `stream` {stream.Writable} The `readline.clearScreenDown()` method clears the given [TTY][] stream from the current position of the cursor down. @@ -362,9 +362,9 @@ changes: --> * `options` {Object} - * `input` {Readable} The [Readable][] stream to listen to. This option is + * `input` {stream.Readable} The [Readable][] stream to listen to. This option is *required*. - * `output` {Writable} The [Writable][] stream to write readline data to. + * `output` {stream.Writable} The [Writable][] stream to write readline data to. * `completer` {Function} An optional function used for Tab autocompletion. * `terminal` {boolean} `true` if the `input` and `output` streams should be treated like a TTY, and have ANSI/VT100 escape codes written to it. @@ -444,7 +444,7 @@ function completer(linePartial, callback) { added: v0.7.7 --> -* `stream` {Writable} +* `stream` {stream.Writable} * `x` {number} * `y` {number} @@ -456,7 +456,7 @@ given [TTY][] `stream`. added: v0.7.7 --> -* `stream` {Readable} +* `stream` {stream.Readable} * `interface` {readline.Interface} The `readline.emitKeypressEvents()` method causes the given [Readable][] @@ -482,7 +482,7 @@ if (process.stdin.isTTY) added: v0.7.7 --> -* `stream` {Writable} +* `stream` {stream.Writable} * `dx` {number} * `dy` {number} diff --git a/doc/api/repl.md b/doc/api/repl.md index a1dfffa9cc0c0a..506f54a4b8a2a8 100644 --- a/doc/api/repl.md +++ b/doc/api/repl.md @@ -412,9 +412,9 @@ changes: * `options` {Object|string} * `prompt` {string} The input prompt to display. Defaults to `> ` (with a trailing space). - * `input` {Readable} The Readable stream from which REPL input will be read. + * `input` {stream.Readable} The Readable stream from which REPL input will be read. Defaults to `process.stdin`. - * `output` {Writable} The Writable stream to which REPL output will be + * `output` {stream.Writable} The Writable stream to which REPL output will be written. Defaults to `process.stdout`. * `terminal` {boolean} If `true`, specifies that the `output` should be treated as a TTY terminal, and have ANSI/VT100 escape codes written to it. diff --git a/doc/api/stream.md b/doc/api/stream.md index c0351a3679445e..f4ac45837f59b0 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -394,7 +394,7 @@ changes: --> * `encoding` {string} The new default encoding -* Returns: `this` +* Returns: {this} The `writable.setDefaultEncoding()` method sets the default `encoding` for a [Writable][] stream. @@ -533,7 +533,7 @@ A Writable stream in object mode will always ignore the `encoding` argument. added: v8.0.0 --> -* Returns: `this` +* Returns: {this} Destroy the stream, and emit the passed error. After this call, the writable stream has ended. Implementors should not override this method, @@ -818,7 +818,7 @@ readable.isPaused(); // === false added: v0.9.4 --> -* Returns: `this` +* Returns: {this} The `readable.pause()` method will cause a stream in flowing mode to stop emitting [`'data'`][] events, switching out of flowing mode. Any data that @@ -967,7 +967,7 @@ the status of the `highWaterMark`. added: v0.9.4 --> -* Returns: `this` +* Returns: {this} The `readable.resume()` method causes an explicitly paused Readable stream to resume emitting [`'data'`][] events, switching the stream into flowing mode. @@ -990,7 +990,7 @@ added: v0.9.4 --> * `encoding` {string} The encoding to use. -* Returns: `this` +* Returns: {this} The `readable.setEncoding()` method sets the character encoding for data read from the Readable stream. diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js index 4ef0a6d04cb581..0ab73162dd59e0 100644 --- a/tools/doc/type-parser.js +++ b/tools/doc/type-parser.js @@ -13,13 +13,13 @@ const jsPrimitives = { 'undefined': 'Undefined' }; const jsGlobalTypes = [ - 'Error', 'Object', 'Function', 'Array', 'TypedArray', 'Uint8Array', - 'Uint16Array', 'Uint32Array', 'Int8Array', 'Int16Array', 'Int32Array', - 'Uint8ClampedArray', 'Float32Array', 'Float64Array', 'Date', 'RegExp', - 'ArrayBuffer', 'DataView', 'Promise', 'EvalError', 'RangeError', - 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', 'Proxy', 'Map', - 'Set', 'WeakMap', 'WeakSet', 'Generator', 'GeneratorFunction', - 'AsyncFunction', 'SharedArrayBuffer' + 'Array', 'ArrayBuffer', 'AsyncFunction', 'DataView', 'Date', 'Error', + 'EvalError', 'Float32Array', 'Float64Array', 'Function', 'Generator', + 'GeneratorFunction', 'Int16Array', 'Int32Array', 'Int8Array', 'Map', 'Object', + 'Promise', 'Proxy', 'RangeError', 'ReferenceError', 'RegExp', 'Set', + 'SharedArrayBuffer', 'SyntaxError', 'TypeError', 'TypedArray', 'URIError', + 'Uint16Array', 'Uint32Array', 'Uint8Array', 'Uint8ClampedArray', 'WeakMap', + 'WeakSet' ]; const typeMap = { 'Iterable': @@ -27,39 +27,68 @@ const typeMap = { 'Iterator': `${jsDocPrefix}Reference/Iteration_protocols#The_iterator_protocol`, + 'this': `${jsDocPrefix}Reference/Operators/this`, + + 'AsyncHook': 'async_hooks.html#async_hooks_async_hooks_createhook_callbacks', + 'Buffer': 'buffer.html#buffer_class_buffer', 'ChildProcess': 'child_process.html#child_process_class_childprocess', 'cluster.Worker': 'cluster.html#cluster_class_worker', + 'crypto.constants': 'crypto.html#crypto_crypto_constants_1', + 'dgram.Socket': 'dgram.html#dgram_class_dgram_socket', + 'Domain': 'domain.html#domain_class_domain', + 'EventEmitter': 'events.html#events_class_eventemitter', + 'fs.Stats': 'fs.html#fs_class_fs_stats', + 'http.Agent': 'http.html#http_class_http_agent', 'http.ClientRequest': 'http.html#http_class_http_clientrequest', 'http.IncomingMessage': 'http.html#http_class_http_incomingmessage', 'http.Server': 'http.html#http_class_http_server', 'http.ServerResponse': 'http.html#http_class_http_serverresponse', + 'ClientHttp2Stream': 'http2.html#http2_class_clienthttp2stream', 'HTTP2 Headers Object': 'http2.html#http2_headers_object', 'HTTP2 Settings Object': 'http2.html#http2_settings_object', + 'http2.Http2ServerRequest': 'http2.html#http2_class_http2_http2serverrequest', + 'http2.Http2ServerResponse': + 'http2.html#http2_class_http2_http2serverresponse', + 'Http2Server': 'http2.html#http2_class_http2server', + 'Http2Session': 'http2.html#http2_class_http2session', + 'Http2Stream': 'http2.html#http2_class_http2stream', + 'ServerHttp2Stream': 'http2.html#http2_class_serverhttp2stream', 'Handle': 'net.html#net_server_listen_handle_backlog_callback', + 'net.Server': 'net.html#net_class_net_server', 'net.Socket': 'net.html#net_class_net_socket', - 'ServerHttp2Stream': 'http2.html#http2_class_serverhttp2stream', + 'os.constants.dlopen': 'os.html#os_dlopen_constants', + + 'PerformanceObserver': + 'perf_hooks.html#perf_hooks_class_performanceobserver_callback', + 'PerformanceObserverEntryList': + 'perf_hooks.html#perf_hooks_class_performanceobserverentrylist', + + 'readline.Interface': 'readline.html#readline_class_interface', 'Stream': 'stream.html#stream_stream', + 'stream.Duplex': 'stream.html#stream_class_stream_duplex', 'stream.Readable': 'stream.html#stream_class_stream_readable', 'stream.Writable': 'stream.html#stream_class_stream_writable', - 'stream.Duplex': 'stream.html#stream_class_stream_duplex', - - 'tls.TLSSocket': 'tls.html#tls_class_tls_tlssocket', + 'Immediate': 'timers.html#timers_class_immediate', + 'Timeout': 'timers.html#timers_class_timeout', 'Timer': 'timers.html#timers_timers', + 'tls.Server': 'tls.html#tls_class_tls_server', + 'tls.TLSSocket': 'tls.html#tls_class_tls_tlssocket', + 'URL': 'url.html#url_the_whatwg_url_api', 'URLSearchParams': 'url.html#url_class_urlsearchparams' }; From dba6652d23cadc4af3f6aefd54e046500551bf61 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 24 Dec 2017 22:38:11 -0800 Subject: [PATCH 020/131] test: move tmpdir to submodule of common Move tmpdir functionality to its own module (common/tmpdir). PR-URL: https://github.com/nodejs/node/pull/17856 Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock Reviewed-By: Ruben Bridgewater Reviewed-By: Joyee Cheung --- .../http/http_server_for_chunky_client.js | 13 +--- benchmark/module/module-loader.js | 8 +-- test/addons/load-long-path/test.js | 5 +- test/addons/symlinked-module/test.js | 5 +- test/async-hooks/test-graph.pipeconnect.js | 3 +- test/async-hooks/test-pipeconnectwrap.js | 3 +- test/common/README.md | 24 ++++--- test/common/index.js | 66 +----------------- test/common/tmpdir.js | 67 +++++++++++++++++++ test/es-module/test-esm-preserve-symlinks.js | 5 +- test/es-module/test-esm-symlink.js | 5 +- test/known_issues/test-cwd-enoent-file.js | 5 +- .../test-module-deleted-extensions.js | 7 +- test/parallel/test-benchmark-fs.js | 7 +- .../test-child-process-fork-exec-path.js | 5 +- .../test-cli-node-options-disallowed.js | 5 +- test/parallel/test-cli-node-options.js | 5 +- test/parallel/test-cluster-cwd.js | 9 +-- test/parallel/test-cluster-eaccess.js | 3 +- test/parallel/test-cluster-http-pipe.js | 3 +- .../test-cluster-net-listen-relative-path.js | 6 +- test/parallel/test-crypto-sign-verify.js | 7 +- test/parallel/test-cwd-enoent-preload.js | 5 +- test/parallel/test-cwd-enoent-repl.js | 6 +- test/parallel/test-cwd-enoent.js | 6 +- test/parallel/test-file-write-stream.js | 5 +- test/parallel/test-file-write-stream2.js | 8 ++- test/parallel/test-file-write-stream3.js | 6 +- test/parallel/test-fs-access.js | 10 +-- test/parallel/test-fs-append-file-sync.js | 13 ++-- test/parallel/test-fs-append-file.js | 16 +++-- test/parallel/test-fs-buffer.js | 7 +- test/parallel/test-fs-buffertype-writesync.js | 8 ++- test/parallel/test-fs-chmod.js | 9 +-- test/parallel/test-fs-copyfile.js | 5 +- test/parallel/test-fs-fsync.js | 5 +- test/parallel/test-fs-link.js | 7 +- test/parallel/test-fs-long-path.js | 8 ++- test/parallel/test-fs-make-callback.js | 5 +- test/parallel/test-fs-mkdir-rmdir.js | 5 +- test/parallel/test-fs-mkdir.js | 9 +-- test/parallel/test-fs-mkdtemp.js | 15 +++-- .../test-fs-non-number-arguments-throw.js | 5 +- test/parallel/test-fs-open-flags.js | 5 +- test/parallel/test-fs-open-numeric-flags.js | 7 +- test/parallel/test-fs-options-immutable.js | 15 +++-- test/parallel/test-fs-promisified.js | 5 +- test/parallel/test-fs-read-stream-fd.js | 7 +- test/parallel/test-fs-readdir-ucs2.js | 7 +- test/parallel/test-fs-readdir.js | 6 +- test/parallel/test-fs-readfile-pipe-large.js | 6 +- test/parallel/test-fs-readfile-unlink.js | 8 ++- .../test-fs-readfilesync-pipe-large.js | 6 +- test/parallel/test-fs-realpath.js | 8 ++- test/parallel/test-fs-sir-writes-alot.js | 8 ++- test/parallel/test-fs-stream-double-close.js | 9 +-- .../test-fs-symlink-dir-junction-relative.js | 8 ++- test/parallel/test-fs-symlink-dir-junction.js | 6 +- test/parallel/test-fs-symlink.js | 5 +- test/parallel/test-fs-syncwritestream.js | 5 +- test/parallel/test-fs-truncate-GH-6233.js | 6 +- test/parallel/test-fs-truncate-fd.js | 5 +- test/parallel/test-fs-truncate-sync.js | 7 +- test/parallel/test-fs-truncate.js | 5 +- test/parallel/test-fs-utimes.js | 19 +++--- test/parallel/test-fs-watch-encoding.js | 11 +-- test/parallel/test-fs-watch-recursive.js | 6 +- test/parallel/test-fs-watch.js | 5 +- test/parallel/test-fs-watchfile.js | 8 ++- test/parallel/test-fs-write-buffer.js | 15 +++-- test/parallel/test-fs-write-file-buffer.js | 7 +- .../test-fs-write-file-invalid-path.js | 7 +- test/parallel/test-fs-write-file-sync.js | 9 +-- .../parallel/test-fs-write-file-uint8array.js | 5 +- test/parallel/test-fs-write-file.js | 11 +-- .../test-fs-write-stream-autoclose-option.js | 6 +- .../test-fs-write-stream-change-open.js | 8 ++- ...-fs-write-stream-close-without-callback.js | 7 +- .../test-fs-write-stream-double-close.js | 9 +-- .../parallel/test-fs-write-stream-encoding.js | 7 +- test/parallel/test-fs-write-stream-end.js | 7 +- test/parallel/test-fs-write-stream-err.js | 5 +- .../test-fs-write-stream-throw-type-error.js | 6 +- test/parallel/test-fs-write-stream.js | 8 ++- test/parallel/test-fs-write-string-coerce.js | 5 +- test/parallel/test-fs-write-sync.js | 7 +- test/parallel/test-fs-write.js | 12 ++-- test/parallel/test-http-agent-getname.js | 6 +- test/parallel/test-http-chunk-problem.js | 6 +- ...ent-abort-keep-alive-queued-unix-socket.js | 3 +- .../test-http-client-abort-unix-socket.js | 3 +- test/parallel/test-http-client-pipe-end.js | 3 +- .../test-http-client-response-domain.js | 3 +- .../test-http-get-pipeline-problem.js | 9 +-- test/parallel/test-http-pipe-fs.js | 5 +- .../test-http-unix-socket-keep-alive.js | 3 +- test/parallel/test-http-unix-socket.js | 3 +- .../test-http2-compat-serverrequest-pipe.js | 5 +- test/parallel/test-http2-pipe.js | 5 +- .../test-https-unix-socket-self-signed.js | 3 +- .../test-internal-fs-syncwritestream.js | 5 +- .../parallel/test-module-circular-symlinks.js | 5 +- .../test-module-loading-globalpaths.js | 7 +- .../test-module-symlinked-peer-modules.js | 5 +- test/parallel/test-net-connect-options-fd.js | 3 +- .../parallel/test-net-connect-options-path.js | 3 +- test/parallel/test-net-pingpong.js | 3 +- test/parallel/test-net-pipe-connect-errors.js | 5 +- .../parallel/test-net-server-listen-handle.js | 3 +- test/parallel/test-net-server-listen-path.js | 3 +- test/parallel/test-npm-install.js | 7 +- test/parallel/test-pipe-address.js | 3 +- test/parallel/test-pipe-file-to-http.js | 5 +- test/parallel/test-pipe-stream.js | 3 +- test/parallel/test-pipe-unref.js | 3 +- test/parallel/test-pipe-writev.js | 3 +- test/parallel/test-process-chdir.js | 10 +-- test/parallel/test-process-execpath.js | 5 +- .../test-process-redirect-warnings-env.js | 5 +- .../test-process-redirect-warnings.js | 5 +- test/parallel/test-regress-GH-3739.js | 6 +- test/parallel/test-repl-history-perm.js | 5 +- test/parallel/test-repl-persistent-history.js | 13 ++-- test/parallel/test-repl-save-load.js | 11 +-- test/parallel/test-repl.js | 3 +- test/parallel/test-require-long-path.js | 10 +-- test/parallel/test-require-symlink.js | 7 +- test/parallel/test-require-unicode.js | 7 +- test/parallel/test-stdin-from-file.js | 5 +- test/parallel/test-stdout-to-file.js | 5 +- test/parallel/test-tls-connect-pipe.js | 3 +- .../test-tls-net-connect-prefer-path.js | 3 +- .../parallel/test-tls-wrap-econnreset-pipe.js | 3 +- test/parallel/test-trace-events-all.js | 5 +- .../parallel/test-trace-events-async-hooks.js | 5 +- test/parallel/test-trace-events-binding.js | 5 +- .../test-trace-events-category-used.js | 5 +- test/parallel/test-trace-events-none.js | 5 +- .../test-trace-events-process-exit.js | 6 +- test/parallel/test-trace-events-v8.js | 5 +- test/parallel/test-zlib-from-gzip.js | 5 +- test/pummel/test-fs-largefile.js | 7 +- test/pummel/test-fs-watch-file-slow.js | 4 +- test/pummel/test-fs-watch-file.js | 4 +- test/pummel/test-fs-watch-non-recursive.js | 4 +- test/pummel/test-regress-GH-814.js | 6 +- test/pummel/test-regress-GH-814_2.js | 5 +- test/pummel/test-tls-session-timeout.js | 4 +- test/sequential/test-async-wrap-getasyncid.js | 3 +- .../test-fs-readfile-tostring-fail.js | 5 +- test/sequential/test-fs-watch.js | 6 +- .../test-http2-timeout-large-write-file.js | 5 +- test/sequential/test-module-loading.js | 3 +- test/sequential/test-regress-GH-4027.js | 5 +- test/tick-processor/tick-processor-base.js | 7 +- 155 files changed, 645 insertions(+), 456 deletions(-) create mode 100644 test/common/tmpdir.js diff --git a/benchmark/http/http_server_for_chunky_client.js b/benchmark/http/http_server_for_chunky_client.js index f079544e03d48e..1e5a4583669c0f 100644 --- a/benchmark/http/http_server_for_chunky_client.js +++ b/benchmark/http/http_server_for_chunky_client.js @@ -2,22 +2,15 @@ const assert = require('assert'); const http = require('http'); -const fs = require('fs'); const { fork } = require('child_process'); const common = require('../common.js'); -const { PIPE, tmpDir } = require('../../test/common'); +const { PIPE } = require('../../test/common'); +const tmpdir = require('../../test/common/tmpdir'); process.env.PIPE_NAME = PIPE; -try { - fs.accessSync(tmpDir, fs.F_OK); -} catch (e) { - fs.mkdirSync(tmpDir); -} +tmpdir.refresh(); var server; -try { - fs.unlinkSync(process.env.PIPE_NAME); -} catch (e) { /* ignore */ } server = http.createServer(function(req, res) { const headers = { diff --git a/benchmark/module/module-loader.js b/benchmark/module/module-loader.js index 8393d1f92e0e6c..25f0ece70169e7 100644 --- a/benchmark/module/module-loader.js +++ b/benchmark/module/module-loader.js @@ -3,8 +3,8 @@ const fs = require('fs'); const path = require('path'); const common = require('../common.js'); -const { refreshTmpDir, tmpDir } = require('../../test/common'); -const benchmarkDirectory = path.join(tmpDir, 'nodejs-benchmark-module'); +const tmpdir = require('../../test/common/tmpdir'); +const benchmarkDirectory = path.join(tmpdir.path, 'nodejs-benchmark-module'); const bench = common.createBenchmark(main, { thousands: [50], @@ -15,7 +15,7 @@ const bench = common.createBenchmark(main, { function main({ thousands, fullPath, useCache }) { const n = thousands * 1e3; - refreshTmpDir(); + tmpdir.refresh(); try { fs.mkdirSync(benchmarkDirectory); } catch (e) {} for (var i = 0; i <= n; i++) { @@ -35,7 +35,7 @@ function main({ thousands, fullPath, useCache }) { else measureDir(n, useCache === 'true'); - refreshTmpDir(); + tmpdir.refresh(); } function measureFull(n, useCache) { diff --git a/test/addons/load-long-path/test.js b/test/addons/load-long-path/test.js index accb90d2638274..ee09230676b5e8 100644 --- a/test/addons/load-long-path/test.js +++ b/test/addons/load-long-path/test.js @@ -7,12 +7,13 @@ const fs = require('fs'); const path = require('path'); const assert = require('assert'); -common.refreshTmpDir(); +const tmpdir = require('../../common/tmpdir'); +tmpdir.refresh(); // make a path that is more than 260 chars long. // Any given folder cannot have a name longer than 260 characters, // so create 10 nested folders each with 30 character long names. -let addonDestinationDir = path.resolve(common.tmpDir); +let addonDestinationDir = path.resolve(tmpdir.path); for (let i = 0; i < 10; i++) { addonDestinationDir = path.join(addonDestinationDir, 'x'.repeat(30)); diff --git a/test/addons/symlinked-module/test.js b/test/addons/symlinked-module/test.js index d9455c027bd36b..53306399cb520b 100644 --- a/test/addons/symlinked-module/test.js +++ b/test/addons/symlinked-module/test.js @@ -12,10 +12,11 @@ const assert = require('assert'); // This test should pass in Node.js v4 and v5. This test will pass in Node.js // with https://github.com/nodejs/node/pull/5950 reverted. -common.refreshTmpDir(); +const tmpdir = require('../../common/tmpdir'); +tmpdir.refresh(); const addonPath = path.join(__dirname, 'build', common.buildType); -const addonLink = path.join(common.tmpDir, 'addon'); +const addonLink = path.join(tmpdir.path, 'addon'); try { fs.symlinkSync(addonPath, addonLink); diff --git a/test/async-hooks/test-graph.pipeconnect.js b/test/async-hooks/test-graph.pipeconnect.js index b3ea5c6e4219e9..03d2902c835d48 100644 --- a/test/async-hooks/test-graph.pipeconnect.js +++ b/test/async-hooks/test-graph.pipeconnect.js @@ -6,7 +6,8 @@ const verifyGraph = require('./verify-graph'); const net = require('net'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const hooks = initHooks(); hooks.enable(); diff --git a/test/async-hooks/test-pipeconnectwrap.js b/test/async-hooks/test-pipeconnectwrap.js index a993f0c8feedd3..df4b8110e67ec4 100644 --- a/test/async-hooks/test-pipeconnectwrap.js +++ b/test/async-hooks/test-pipeconnectwrap.js @@ -8,7 +8,8 @@ const { checkInvocations } = require('./hook-checks'); const net = require('net'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const hooks = initHooks(); hooks.enable(); diff --git a/test/common/README.md b/test/common/README.md index da38de742e4805..1906ffd7e29992 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -12,6 +12,7 @@ This directory contains modules used to test the Node.js implementation. * [Fixtures module](#fixtures-module) * [HTTP2 module](#http2-module) * [Internet module](#internet-module) +* [tmpdir module](#tmpdir-module) * [WPT module](#wpt-module) ## Benchmark Module @@ -332,11 +333,6 @@ A port number for tests to use if one is needed. Logs '1..0 # Skipped: ' + `msg` -### refreshTmpDir() -* return [<String>] - -Deletes the testing 'tmp' directory and recreates it. - ### restoreStderr() Restore the original `process.stderr.write`. Used to restore `stderr` to its @@ -384,11 +380,6 @@ Platform normalizes the `pwd` command. Synchronous version of `spawnPwd`. -### tmpDir -* [<String>] - -The realpath of the 'tmp' directory. - ## Countdown Module The `Countdown` module provides a simple countdown mechanism for tests that @@ -670,6 +661,19 @@ via `NODE_TEST_*` environment variables. For example, to configure `internet.addresses.INET_HOST`, set the environment variable `NODE_TEST_INET_HOST` to a specified host. +## tmpdir Module + +The `tmpdir` module supports the use of a temporary directory for testing. + +### path +* [<String>] + +The realpath of the testing temporary directory. + +### refresh() + +Deletes and recreates the testing temporary directory. + ## WPT Module The wpt.js module is a port of parts of diff --git a/test/common/index.js b/test/common/index.js index 9ae27e232e3ca8..b4aa51b1f8d171 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -30,16 +30,10 @@ const stream = require('stream'); const util = require('util'); const Timer = process.binding('timer_wrap').Timer; const { fixturesDir } = require('./fixtures'); - -const testRoot = process.env.NODE_TEST_DIR ? - fs.realpathSync(process.env.NODE_TEST_DIR) : path.resolve(__dirname, '..'); +const tmpdir = require('./tmpdir'); const noop = () => {}; -// Using a `.` prefixed name, which is the convention for "hidden" on POSIX, -// gets tools to ignore it by default or by simple rules, especially eslint. -let tmpDirName = '.tmp'; - Object.defineProperty(exports, 'PORT', { get: () => { if (+process.env.TEST_PARALLEL) { @@ -120,62 +114,6 @@ if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) { }).enable(); } -function rimrafSync(p) { - let st; - try { - st = fs.lstatSync(p); - } catch (e) { - if (e.code === 'ENOENT') - return; - } - - try { - if (st && st.isDirectory()) - rmdirSync(p, null); - else - fs.unlinkSync(p); - } catch (e) { - if (e.code === 'ENOENT') - return; - if (e.code === 'EPERM') - return rmdirSync(p, e); - if (e.code !== 'EISDIR') - throw e; - rmdirSync(p, e); - } -} - -function rmdirSync(p, originalEr) { - try { - fs.rmdirSync(p); - } catch (e) { - if (e.code === 'ENOTDIR') - throw originalEr; - if (e.code === 'ENOTEMPTY' || e.code === 'EEXIST' || e.code === 'EPERM') { - const enc = exports.isLinux ? 'buffer' : 'utf8'; - fs.readdirSync(p, enc).forEach((f) => { - if (f instanceof Buffer) { - const buf = Buffer.concat([Buffer.from(p), Buffer.from(path.sep), f]); - rimrafSync(buf); - } else { - rimrafSync(path.join(p, f)); - } - }); - fs.rmdirSync(p); - } - } -} - -exports.refreshTmpDir = function() { - rimrafSync(exports.tmpDir); - fs.mkdirSync(exports.tmpDir); -}; - -if (process.env.TEST_THREAD_ID) { - tmpDirName += `.${process.env.TEST_THREAD_ID}`; -} -exports.tmpDir = path.join(testRoot, tmpDirName); - let opensslCli = null; let inFreeBSDJail = null; let localhostIPv4 = null; @@ -269,7 +207,7 @@ Object.defineProperty(exports, 'hasFipsCrypto', { }); { - const localRelative = path.relative(process.cwd(), `${exports.tmpDir}/`); + const localRelative = path.relative(process.cwd(), `${tmpdir.path}/`); const pipePrefix = exports.isWindows ? '\\\\.\\pipe\\' : localRelative; const pipeName = `node-test.${process.pid}.sock`; exports.PIPE = path.join(pipePrefix, pipeName); diff --git a/test/common/tmpdir.js b/test/common/tmpdir.js new file mode 100644 index 00000000000000..ed731b3e7a1ffb --- /dev/null +++ b/test/common/tmpdir.js @@ -0,0 +1,67 @@ +/* eslint-disable required-modules */ +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +function rimrafSync(p) { + let st; + try { + st = fs.lstatSync(p); + } catch (e) { + if (e.code === 'ENOENT') + return; + } + + try { + if (st && st.isDirectory()) + rmdirSync(p, null); + else + fs.unlinkSync(p); + } catch (e) { + if (e.code === 'ENOENT') + return; + if (e.code === 'EPERM') + return rmdirSync(p, e); + if (e.code !== 'EISDIR') + throw e; + rmdirSync(p, e); + } +} + +function rmdirSync(p, originalEr) { + try { + fs.rmdirSync(p); + } catch (e) { + if (e.code === 'ENOTDIR') + throw originalEr; + if (e.code === 'ENOTEMPTY' || e.code === 'EEXIST' || e.code === 'EPERM') { + const enc = process.platform === 'linux' ? 'buffer' : 'utf8'; + fs.readdirSync(p, enc).forEach((f) => { + if (f instanceof Buffer) { + const buf = Buffer.concat([Buffer.from(p), Buffer.from(path.sep), f]); + rimrafSync(buf); + } else { + rimrafSync(path.join(p, f)); + } + }); + fs.rmdirSync(p); + } + } +} + +const testRoot = process.env.NODE_TEST_DIR ? + fs.realpathSync(process.env.NODE_TEST_DIR) : path.resolve(__dirname, '..'); + +// Using a `.` prefixed name, which is the convention for "hidden" on POSIX, +// gets tools to ignore it by default or by simple rules, especially eslint. +let tmpdirName = '.tmp'; +if (process.env.TEST_THREAD_ID) { + tmpdirName += `.${process.env.TEST_THREAD_ID}`; +} +exports.path = path.join(testRoot, tmpdirName); + +exports.refresh = () => { + rimrafSync(exports.path); + fs.mkdirSync(exports.path); +}; diff --git a/test/es-module/test-esm-preserve-symlinks.js b/test/es-module/test-esm-preserve-symlinks.js index eea5bf061b2fa3..e8473c36473bd2 100644 --- a/test/es-module/test-esm-preserve-symlinks.js +++ b/test/es-module/test-esm-preserve-symlinks.js @@ -7,8 +7,9 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -common.refreshTmpDir(); -const tmpDir = common.tmpDir; +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +const tmpDir = tmpdir.path; const entry = path.join(tmpDir, 'entry.js'); const real = path.join(tmpDir, 'real.js'); diff --git a/test/es-module/test-esm-symlink.js b/test/es-module/test-esm-symlink.js index 3b7d689bf8f5f2..074230ac06c4b5 100644 --- a/test/es-module/test-esm-symlink.js +++ b/test/es-module/test-esm-symlink.js @@ -6,8 +6,9 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -common.refreshTmpDir(); -const tmpDir = common.tmpDir; +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +const tmpDir = tmpdir.path; const entry = path.join(tmpDir, 'entry.mjs'); const real = path.join(tmpDir, 'index.mjs'); diff --git a/test/known_issues/test-cwd-enoent-file.js b/test/known_issues/test-cwd-enoent-file.js index 01e6e8359fb522..0f75896134f7e3 100644 --- a/test/known_issues/test-cwd-enoent-file.js +++ b/test/known_issues/test-cwd-enoent-file.js @@ -17,8 +17,9 @@ const fs = require('fs'); if (process.argv[2] === 'child') { // Do nothing. } else { - common.refreshTmpDir(); - const dir = fs.mkdtempSync(`${common.tmpDir}/`); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); + const dir = fs.mkdtempSync(`${tmpdir.path}/`); process.chdir(dir); fs.rmdirSync(dir); assert.throws(process.cwd, diff --git a/test/known_issues/test-module-deleted-extensions.js b/test/known_issues/test-module-deleted-extensions.js index 45ec41ad6041ad..3a51e8725eec60 100644 --- a/test/known_issues/test-module-deleted-extensions.js +++ b/test/known_issues/test-module-deleted-extensions.js @@ -4,9 +4,10 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const file = path.join(common.tmpDir, 'test-extensions.foo.bar'); +const tmpdir = require('../common/tmpdir'); +const file = path.join(tmpdir.path, 'test-extensions.foo.bar'); -common.refreshTmpDir(); +tmpdir.refresh(); fs.writeFileSync(file, '', 'utf8'); require.extensions['.foo.bar'] = (module, path) => {}; delete require.extensions['.foo.bar']; @@ -14,4 +15,4 @@ require.extensions['.bar'] = common.mustCall((module, path) => { assert.strictEqual(module.id, file); assert.strictEqual(path, file); }); -require(path.join(common.tmpDir, 'test-extensions')); +require(path.join(tmpdir.path, 'test-extensions')); diff --git a/test/parallel/test-benchmark-fs.js b/test/parallel/test-benchmark-fs.js index e960482a636e33..ad01b4e5803ce5 100644 --- a/test/parallel/test-benchmark-fs.js +++ b/test/parallel/test-benchmark-fs.js @@ -1,9 +1,10 @@ 'use strict'; -const common = require('../common'); +require('../common'); const runBenchmark = require('../common/benchmark'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); runBenchmark('fs', [ 'n=1', @@ -16,4 +17,4 @@ runBenchmark('fs', [ 'statSyncType=fstatSync', 'encodingType=buf', 'filesize=1024' -], { NODE_TMPDIR: common.tmpDir, NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); +], { NODE_TMPDIR: tmpdir.path, NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/parallel/test-child-process-fork-exec-path.js b/test/parallel/test-child-process-fork-exec-path.js index 06c6244eddaac4..42855cd663e826 100644 --- a/test/parallel/test-child-process-fork-exec-path.js +++ b/test/parallel/test-child-process-fork-exec-path.js @@ -24,9 +24,10 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const tmpdir = require('../common/tmpdir'); const msg = { test: 'this' }; const nodePath = process.execPath; -const copyPath = path.join(common.tmpDir, 'node-copy.exe'); +const copyPath = path.join(tmpdir.path, 'node-copy.exe'); if (process.env.FORK) { assert(process.send); @@ -34,7 +35,7 @@ if (process.env.FORK) { process.send(msg); process.exit(); } else { - common.refreshTmpDir(); + tmpdir.refresh(); try { fs.unlinkSync(copyPath); } catch (e) { diff --git a/test/parallel/test-cli-node-options-disallowed.js b/test/parallel/test-cli-node-options-disallowed.js index b55543bfa243bc..e4ae2d1aea28f2 100644 --- a/test/parallel/test-cli-node-options-disallowed.js +++ b/test/parallel/test-cli-node-options-disallowed.js @@ -8,8 +8,9 @@ if (process.config.variables.node_without_node_options) const assert = require('assert'); const exec = require('child_process').execFile; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); disallow('--version'); disallow('-v'); diff --git a/test/parallel/test-cli-node-options.js b/test/parallel/test-cli-node-options.js index 85c35508566ff1..29358134c22c99 100644 --- a/test/parallel/test-cli-node-options.js +++ b/test/parallel/test-cli-node-options.js @@ -8,8 +8,9 @@ if (process.config.variables.node_without_node_options) const assert = require('assert'); const exec = require('child_process').execFile; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); expect(`-r ${require.resolve('../fixtures/printA.js')}`, 'A\nB\n'); expect('--no-deprecation', 'B\n'); diff --git a/test/parallel/test-cluster-cwd.js b/test/parallel/test-cluster-cwd.js index ce3fdca51e907c..485276befaf39b 100644 --- a/test/parallel/test-cluster-cwd.js +++ b/test/parallel/test-cluster-cwd.js @@ -2,19 +2,20 @@ const common = require('../common'); const assert = require('assert'); const cluster = require('cluster'); +const tmpdir = require('../common/tmpdir'); if (cluster.isMaster) { - common.refreshTmpDir(); + tmpdir.refresh(); assert.strictEqual(cluster.settings.cwd, undefined); cluster.fork().on('message', common.mustCall((msg) => { assert.strictEqual(msg, process.cwd()); })); - cluster.setupMaster({ cwd: common.tmpDir }); - assert.strictEqual(cluster.settings.cwd, common.tmpDir); + cluster.setupMaster({ cwd: tmpdir.path }); + assert.strictEqual(cluster.settings.cwd, tmpdir.path); cluster.fork().on('message', common.mustCall((msg) => { - assert.strictEqual(msg, common.tmpDir); + assert.strictEqual(msg, tmpdir.path); })); } else { process.send(process.cwd()); diff --git a/test/parallel/test-cluster-eaccess.js b/test/parallel/test-cluster-eaccess.js index ecf0862fa3bab5..c6a2a8ac25e251 100644 --- a/test/parallel/test-cluster-eaccess.js +++ b/test/parallel/test-cluster-eaccess.js @@ -33,7 +33,8 @@ const net = require('net'); if (cluster.isMaster && process.argv.length !== 3) { // cluster.isMaster - common.refreshTmpDir(); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); const PIPE_NAME = common.PIPE; const worker = cluster.fork({ PIPE_NAME }); diff --git a/test/parallel/test-cluster-http-pipe.js b/test/parallel/test-cluster-http-pipe.js index 96f741e80443b7..9e58fb297b28fe 100644 --- a/test/parallel/test-cluster-http-pipe.js +++ b/test/parallel/test-cluster-http-pipe.js @@ -32,7 +32,8 @@ const cluster = require('cluster'); const http = require('http'); if (cluster.isMaster) { - common.refreshTmpDir(); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); const worker = cluster.fork(); worker.on('message', common.mustCall((msg) => { assert.strictEqual(msg, 'DONE'); diff --git a/test/parallel/test-cluster-net-listen-relative-path.js b/test/parallel/test-cluster-net-listen-relative-path.js index 2f95d05203d424..ce9ead9e2eb958 100644 --- a/test/parallel/test-cluster-net-listen-relative-path.js +++ b/test/parallel/test-cluster-net-listen-relative-path.js @@ -6,6 +6,8 @@ const net = require('net'); const path = require('path'); const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); + if (common.isWindows) common.skip('On Windows named pipes live in their own ' + 'filesystem and don\'t have a ~100 byte limit'); @@ -20,8 +22,8 @@ assert.strictEqual(path.resolve(socketDir, socketName).length > 100, true, if (cluster.isMaster) { // ensure that the worker exits peacefully - common.refreshTmpDir(); - process.chdir(common.tmpDir); + tmpdir.refresh(); + process.chdir(tmpdir.path); fs.mkdirSync(socketDir); cluster.fork().on('exit', common.mustCall(function(statusCode) { assert.strictEqual(statusCode, 0); diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js index abdbcd3a1e5350..d105b5b2bb27e3 100644 --- a/test/parallel/test-crypto-sign-verify.js +++ b/test/parallel/test-crypto-sign-verify.js @@ -297,11 +297,12 @@ common.expectsError( padding: crypto.constants.RSA_PKCS1_PSS_PADDING }); - common.refreshTmpDir(); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); - const sigfile = path.join(common.tmpDir, 's5.sig'); + const sigfile = path.join(tmpdir.path, 's5.sig'); fs.writeFileSync(sigfile, s5); - const msgfile = path.join(common.tmpDir, 's5.msg'); + const msgfile = path.join(tmpdir.path, 's5.msg'); fs.writeFileSync(msgfile, msg); const cmd = diff --git a/test/parallel/test-cwd-enoent-preload.js b/test/parallel/test-cwd-enoent-preload.js index ec9f1fee754d9c..b83ff6ff883a05 100644 --- a/test/parallel/test-cwd-enoent-preload.js +++ b/test/parallel/test-cwd-enoent-preload.js @@ -8,10 +8,11 @@ const assert = require('assert'); const fs = require('fs'); const spawn = require('child_process').spawn; const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); -const dirname = `${common.tmpDir}/cwd-does-not-exist-${process.pid}`; +const dirname = `${tmpdir.path}/cwd-does-not-exist-${process.pid}`; const abspathFile = fixtures.path('a.js'); -common.refreshTmpDir(); +tmpdir.refresh(); fs.mkdirSync(dirname); process.chdir(dirname); fs.rmdirSync(dirname); diff --git a/test/parallel/test-cwd-enoent-repl.js b/test/parallel/test-cwd-enoent-repl.js index 8f846af9030c08..d42679d8688e06 100644 --- a/test/parallel/test-cwd-enoent-repl.js +++ b/test/parallel/test-cwd-enoent-repl.js @@ -8,8 +8,10 @@ const assert = require('assert'); const fs = require('fs'); const spawn = require('child_process').spawn; -const dirname = `${common.tmpDir}/cwd-does-not-exist-${process.pid}`; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); + +const dirname = `${tmpdir.path}/cwd-does-not-exist-${process.pid}`; +tmpdir.refresh(); fs.mkdirSync(dirname); process.chdir(dirname); fs.rmdirSync(dirname); diff --git a/test/parallel/test-cwd-enoent.js b/test/parallel/test-cwd-enoent.js index c1b520aedd321d..e5d93f46ce60c0 100644 --- a/test/parallel/test-cwd-enoent.js +++ b/test/parallel/test-cwd-enoent.js @@ -8,8 +8,10 @@ const assert = require('assert'); const fs = require('fs'); const spawn = require('child_process').spawn; -const dirname = `${common.tmpDir}/cwd-does-not-exist-${process.pid}`; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); + +const dirname = `${tmpdir.path}/cwd-does-not-exist-${process.pid}`; +tmpdir.refresh(); fs.mkdirSync(dirname); process.chdir(dirname); fs.rmdirSync(dirname); diff --git a/test/parallel/test-file-write-stream.js b/test/parallel/test-file-write-stream.js index 645c4a637b0538..4860417dd29bc5 100644 --- a/test/parallel/test-file-write-stream.js +++ b/test/parallel/test-file-write-stream.js @@ -25,8 +25,9 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const fn = path.join(common.tmpDir, 'write.txt'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +const fn = path.join(tmpdir.path, 'write.txt'); +tmpdir.refresh(); const file = fs.createWriteStream(fn, { highWaterMark: 10 }); diff --git a/test/parallel/test-file-write-stream2.js b/test/parallel/test-file-write-stream2.js index 1f838f0869260a..2db06640e18dba 100644 --- a/test/parallel/test-file-write-stream2.js +++ b/test/parallel/test-file-write-stream2.js @@ -20,14 +20,16 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); -const filepath = path.join(common.tmpDir, 'write.txt'); + +const filepath = path.join(tmpdir.path, 'write.txt'); const EXPECTED = '012345678910'; @@ -58,7 +60,7 @@ function removeTestFile() { } -common.refreshTmpDir(); +tmpdir.refresh(); // drain at 0, return false at 10. const file = fs.createWriteStream(filepath, { diff --git a/test/parallel/test-file-write-stream3.js b/test/parallel/test-file-write-stream3.js index fe9a61c5827338..50f78748be3f30 100644 --- a/test/parallel/test-file-write-stream3.js +++ b/test/parallel/test-file-write-stream3.js @@ -25,8 +25,10 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); -const filepath = path.join(common.tmpDir, 'write_pos.txt'); + +const filepath = path.join(tmpdir.path, 'write_pos.txt'); const cb_expected = 'write open close write open close write open close '; @@ -51,7 +53,7 @@ process.on('exit', function() { }); -common.refreshTmpDir(); +tmpdir.refresh(); function run_test_1() { diff --git a/test/parallel/test-fs-access.js b/test/parallel/test-fs-access.js index 3e90bf94859266..867c19cc3cfa1e 100644 --- a/test/parallel/test-fs-access.js +++ b/test/parallel/test-fs-access.js @@ -3,16 +3,18 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const doesNotExist = path.join(common.tmpDir, '__this_should_not_exist'); -const readOnlyFile = path.join(common.tmpDir, 'read_only_file'); -const readWriteFile = path.join(common.tmpDir, 'read_write_file'); + +const tmpdir = require('../common/tmpdir'); +const doesNotExist = path.join(tmpdir.path, '__this_should_not_exist'); +const readOnlyFile = path.join(tmpdir.path, 'read_only_file'); +const readWriteFile = path.join(tmpdir.path, 'read_write_file'); function createFileWithPerms(file, mode) { fs.writeFileSync(file, ''); fs.chmodSync(file, mode); } -common.refreshTmpDir(); +tmpdir.refresh(); createFileWithPerms(readOnlyFile, 0o444); createFileWithPerms(readWriteFile, 0o666); diff --git a/test/parallel/test-fs-append-file-sync.js b/test/parallel/test-fs-append-file-sync.js index 31e95c2e368656..b836d81bd5985c 100644 --- a/test/parallel/test-fs-append-file-sync.js +++ b/test/parallel/test-fs-append-file-sync.js @@ -36,10 +36,11 @@ const data = '南越国是前203年至前111年存在于岭南地区的一个国 '历经五代君主。南越国是岭南地区的第一个有记载的政权国家,采用封建制和郡县制并存的制度,' + '它的建立保证了秦末乱世岭南地区社会秩序的稳定,有效的改善了岭南地区落后的政治、##济现状。\n'; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // test that empty file will be created and have content added -const filename = join(common.tmpDir, 'append-sync.txt'); +const filename = join(tmpdir.path, 'append-sync.txt'); fs.appendFileSync(filename, data); @@ -48,7 +49,7 @@ const fileData = fs.readFileSync(filename); assert.strictEqual(Buffer.byteLength(data), fileData.length); // test that appends data to a non empty file -const filename2 = join(common.tmpDir, 'append-sync2.txt'); +const filename2 = join(tmpdir.path, 'append-sync2.txt'); fs.writeFileSync(filename2, currentFileData); fs.appendFileSync(filename2, data); @@ -59,7 +60,7 @@ assert.strictEqual(Buffer.byteLength(data) + currentFileData.length, fileData2.length); // test that appendFileSync accepts buffers -const filename3 = join(common.tmpDir, 'append-sync3.txt'); +const filename3 = join(tmpdir.path, 'append-sync3.txt'); fs.writeFileSync(filename3, currentFileData); const buf = Buffer.from(data, 'utf8'); @@ -70,7 +71,7 @@ const fileData3 = fs.readFileSync(filename3); assert.strictEqual(buf.length + currentFileData.length, fileData3.length); // test that appendFile accepts numbers. -const filename4 = join(common.tmpDir, 'append-sync4.txt'); +const filename4 = join(tmpdir.path, 'append-sync4.txt'); fs.writeFileSync(filename4, currentFileData, { mode: m }); fs.appendFileSync(filename4, num, { mode: m }); @@ -87,7 +88,7 @@ assert.strictEqual(Buffer.byteLength(String(num)) + currentFileData.length, fileData4.length); // test that appendFile accepts file descriptors -const filename5 = join(common.tmpDir, 'append-sync5.txt'); +const filename5 = join(tmpdir.path, 'append-sync5.txt'); fs.writeFileSync(filename5, currentFileData); const filename5fd = fs.openSync(filename5, 'a+', 0o600); diff --git a/test/parallel/test-fs-append-file.js b/test/parallel/test-fs-append-file.js index e3e4c273d3292d..8e9a0619b0a4fb 100644 --- a/test/parallel/test-fs-append-file.js +++ b/test/parallel/test-fs-append-file.js @@ -25,7 +25,9 @@ const assert = require('assert'); const fs = require('fs'); const join = require('path').join; -const filename = join(common.tmpDir, 'append.txt'); +const tmpdir = require('../common/tmpdir'); + +const filename = join(tmpdir.path, 'append.txt'); const currentFileData = 'ABCD'; @@ -40,7 +42,7 @@ const s = '南越国是前203年至前111年存在于岭南地区的一个国家 let ncallbacks = 0; -common.refreshTmpDir(); +tmpdir.refresh(); // test that empty file will be created and have content added fs.appendFile(filename, s, function(e) { @@ -56,7 +58,7 @@ fs.appendFile(filename, s, function(e) { }); // test that appends data to a non empty file -const filename2 = join(common.tmpDir, 'append2.txt'); +const filename2 = join(tmpdir.path, 'append2.txt'); fs.writeFileSync(filename2, currentFileData); fs.appendFile(filename2, s, function(e) { @@ -73,7 +75,7 @@ fs.appendFile(filename2, s, function(e) { }); // test that appendFile accepts buffers -const filename3 = join(common.tmpDir, 'append3.txt'); +const filename3 = join(tmpdir.path, 'append3.txt'); fs.writeFileSync(filename3, currentFileData); const buf = Buffer.from(s, 'utf8'); @@ -91,7 +93,7 @@ fs.appendFile(filename3, buf, function(e) { }); // test that appendFile accepts numbers. -const filename4 = join(common.tmpDir, 'append4.txt'); +const filename4 = join(tmpdir.path, 'append4.txt'); fs.writeFileSync(filename4, currentFileData); const m = 0o600; @@ -115,7 +117,7 @@ fs.appendFile(filename4, n, { mode: m }, function(e) { }); // test that appendFile accepts file descriptors -const filename5 = join(common.tmpDir, 'append5.txt'); +const filename5 = join(tmpdir.path, 'append5.txt'); fs.writeFileSync(filename5, currentFileData); fs.open(filename5, 'a+', function(e, fd) { @@ -146,7 +148,7 @@ fs.open(filename5, 'a+', function(e, fd) { // test that a missing callback emits a warning, even if the last argument is a // function. -const filename6 = join(common.tmpDir, 'append6.txt'); +const filename6 = join(tmpdir.path, 'append6.txt'); const warn = 'Calling an asynchronous function without callback is deprecated.'; common.expectWarning('DeprecationWarning', warn); fs.appendFile(filename6, console.log); diff --git a/test/parallel/test-fs-buffer.js b/test/parallel/test-fs-buffer.js index 1cbead434469e9..84234e8a7a0bd7 100644 --- a/test/parallel/test-fs-buffer.js +++ b/test/parallel/test-fs-buffer.js @@ -6,16 +6,17 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); assert.doesNotThrow(() => { - fs.access(Buffer.from(common.tmpDir), common.mustCall((err) => { + fs.access(Buffer.from(tmpdir.path), common.mustCall((err) => { assert.ifError(err); })); }); assert.doesNotThrow(() => { - const buf = Buffer.from(path.join(common.tmpDir, 'a.txt')); + const buf = Buffer.from(path.join(tmpdir.path, 'a.txt')); fs.open(buf, 'w+', common.mustCall((err, fd) => { assert.ifError(err); assert(fd); diff --git a/test/parallel/test-fs-buffertype-writesync.js b/test/parallel/test-fs-buffertype-writesync.js index 73a6f211893aaf..d5257d214bdb81 100644 --- a/test/parallel/test-fs-buffertype-writesync.js +++ b/test/parallel/test-fs-buffertype-writesync.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); // This test ensures that writeSync does support inputs which // are then correctly converted into string buffers. @@ -8,10 +8,12 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const filePath = path.join(common.tmpDir, 'test_buffer_type'); +const tmpdir = require('../common/tmpdir'); + +const filePath = path.join(tmpdir.path, 'test_buffer_type'); const v = [true, false, 0, 1, Infinity, () => {}, {}, [], undefined, null]; -common.refreshTmpDir(); +tmpdir.refresh(); v.forEach((value) => { const fd = fs.openSync(filePath, 'w'); diff --git a/test/parallel/test-fs-chmod.js b/test/parallel/test-fs-chmod.js index 7d4b7a10dbd9b4..98190d1f75ee01 100644 --- a/test/parallel/test-fs-chmod.js +++ b/test/parallel/test-fs-chmod.js @@ -71,10 +71,11 @@ if (common.isWindows) { mode_sync = 0o644; } -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const file1 = path.join(common.tmpDir, 'a.js'); -const file2 = path.join(common.tmpDir, 'a1.js'); +const file1 = path.join(tmpdir.path, 'a.js'); +const file2 = path.join(tmpdir.path, 'a1.js'); // Create file1. fs.closeSync(fs.openSync(file1, 'w')); @@ -121,7 +122,7 @@ fs.open(file2, 'w', common.mustCall((err, fd) => { // lchmod if (fs.lchmod) { - const link = path.join(common.tmpDir, 'symbolic-link'); + const link = path.join(tmpdir.path, 'symbolic-link'); fs.symlinkSync(file2, link); diff --git a/test/parallel/test-fs-copyfile.js b/test/parallel/test-fs-copyfile.js index 2977a5984706c3..574ea61c9f52a2 100644 --- a/test/parallel/test-fs-copyfile.js +++ b/test/parallel/test-fs-copyfile.js @@ -1,11 +1,12 @@ 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); const src = fixtures.path('a.js'); -const dest = path.join(common.tmpDir, 'copyfile.out'); +const dest = path.join(tmpdir.path, 'copyfile.out'); const { COPYFILE_EXCL, UV_FS_COPYFILE_EXCL } = fs.constants; function verify(src, dest) { @@ -19,7 +20,7 @@ function verify(src, dest) { assert.strictEqual(srcStat.size, destStat.size); } -common.refreshTmpDir(); +tmpdir.refresh(); // Verify that flags are defined. assert.strictEqual(typeof COPYFILE_EXCL, 'number'); diff --git a/test/parallel/test-fs-fsync.js b/test/parallel/test-fs-fsync.js index c55056e501f648..4040d2d550764e 100644 --- a/test/parallel/test-fs-fsync.js +++ b/test/parallel/test-fs-fsync.js @@ -23,15 +23,16 @@ const common = require('../common'); const assert = require('assert'); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const fs = require('fs'); const path = require('path'); const fileFixture = fixtures.path('a.js'); -const fileTemp = path.join(common.tmpDir, 'a.js'); +const fileTemp = path.join(tmpdir.path, 'a.js'); // Copy fixtures to temp. -common.refreshTmpDir(); +tmpdir.refresh(); fs.copyFileSync(fileFixture, fileTemp); fs.open(fileTemp, 'a', 0o777, common.mustCall(function(err, fd) { diff --git a/test/parallel/test-fs-link.js b/test/parallel/test-fs-link.js index 525392aa2be01c..8ee9b29f1ee9da 100644 --- a/test/parallel/test-fs-link.js +++ b/test/parallel/test-fs-link.js @@ -4,11 +4,12 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // test creating and reading hard link -const srcPath = path.join(common.tmpDir, 'hardlink-target.txt'); -const dstPath = path.join(common.tmpDir, 'link1.js'); +const srcPath = path.join(tmpdir.path, 'hardlink-target.txt'); +const dstPath = path.join(tmpdir.path, 'link1.js'); fs.writeFileSync(srcPath, 'hello world'); function callback(err) { diff --git a/test/parallel/test-fs-long-path.js b/test/parallel/test-fs-long-path.js index ae60b16f1a3f97..74f63868b81054 100644 --- a/test/parallel/test-fs-long-path.js +++ b/test/parallel/test-fs-long-path.js @@ -28,12 +28,14 @@ const fs = require('fs'); const path = require('path'); const assert = require('assert'); +const tmpdir = require('../common/tmpdir'); + // make a path that will be at least 260 chars long. -const fileNameLen = Math.max(260 - common.tmpDir.length - 1, 1); -const fileName = path.join(common.tmpDir, 'x'.repeat(fileNameLen)); +const fileNameLen = Math.max(260 - tmpdir.path.length - 1, 1); +const fileName = path.join(tmpdir.path, 'x'.repeat(fileNameLen)); const fullPath = path.resolve(fileName); -common.refreshTmpDir(); +tmpdir.refresh(); console.log({ filenameLength: fileName.length, diff --git a/test/parallel/test-fs-make-callback.js b/test/parallel/test-fs-make-callback.js index 79cf4e0bed7525..ca948ede182759 100644 --- a/test/parallel/test-fs-make-callback.js +++ b/test/parallel/test-fs-make-callback.js @@ -7,12 +7,13 @@ const callbackThrowValues = [null, true, false, 0, 1, 'foo', /foo/, [], {}]; const { sep } = require('path'); const warn = 'Calling an asynchronous function without callback is deprecated.'; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); function testMakeCallback(cb) { return function() { // fs.mkdtemp() calls makeCallback() on its third argument - fs.mkdtemp(`${common.tmpDir}${sep}`, {}, cb); + fs.mkdtemp(`${tmpdir.path}${sep}`, {}, cb); }; } diff --git a/test/parallel/test-fs-mkdir-rmdir.js b/test/parallel/test-fs-mkdir-rmdir.js index 8c22331e85e3cd..865a5dba951555 100644 --- a/test/parallel/test-fs-mkdir-rmdir.js +++ b/test/parallel/test-fs-mkdir-rmdir.js @@ -4,9 +4,10 @@ const common = require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const d = path.join(common.tmpDir, 'dir'); +const tmpdir = require('../common/tmpdir'); +const d = path.join(tmpdir.path, 'dir'); -common.refreshTmpDir(); +tmpdir.refresh(); // Make sure the directory does not exist assert(!common.fileExists(d)); diff --git a/test/parallel/test-fs-mkdir.js b/test/parallel/test-fs-mkdir.js index 54585a3f12a64b..6b4f3c921d670b 100644 --- a/test/parallel/test-fs-mkdir.js +++ b/test/parallel/test-fs-mkdir.js @@ -24,10 +24,11 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); { - const pathname = `${common.tmpDir}/test1`; + const pathname = `${tmpdir.path}/test1`; fs.mkdir(pathname, common.mustCall(function(err) { assert.strictEqual(err, null); @@ -36,7 +37,7 @@ common.refreshTmpDir(); } { - const pathname = `${common.tmpDir}/test2`; + const pathname = `${tmpdir.path}/test2`; fs.mkdir(pathname, 0o777, common.mustCall(function(err) { assert.strictEqual(err, null); @@ -45,7 +46,7 @@ common.refreshTmpDir(); } { - const pathname = `${common.tmpDir}/test3`; + const pathname = `${tmpdir.path}/test3`; fs.mkdirSync(pathname); diff --git a/test/parallel/test-fs-mkdtemp.js b/test/parallel/test-fs-mkdtemp.js index 38a306b85c7aa8..b27ab864173dd2 100644 --- a/test/parallel/test-fs-mkdtemp.js +++ b/test/parallel/test-fs-mkdtemp.js @@ -5,14 +5,15 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const tmpFolder = fs.mkdtempSync(path.join(common.tmpDir, 'foo.')); +const tmpFolder = fs.mkdtempSync(path.join(tmpdir.path, 'foo.')); assert.strictEqual(path.basename(tmpFolder).length, 'foo.XXXXXX'.length); assert(common.fileExists(tmpFolder)); -const utf8 = fs.mkdtempSync(path.join(common.tmpDir, '\u0222abc.')); +const utf8 = fs.mkdtempSync(path.join(tmpdir.path, '\u0222abc.')); assert.strictEqual(Buffer.byteLength(path.basename(utf8)), Buffer.byteLength('\u0222abc.XXXXXX')); assert(common.fileExists(utf8)); @@ -23,13 +24,13 @@ function handler(err, folder) { assert.strictEqual(this, undefined); } -fs.mkdtemp(path.join(common.tmpDir, 'bar.'), common.mustCall(handler)); +fs.mkdtemp(path.join(tmpdir.path, 'bar.'), common.mustCall(handler)); // Same test as above, but making sure that passing an options object doesn't // affect the way the callback function is handled. -fs.mkdtemp(path.join(common.tmpDir, 'bar.'), {}, common.mustCall(handler)); +fs.mkdtemp(path.join(tmpdir.path, 'bar.'), {}, common.mustCall(handler)); // Making sure that not passing a callback doesn't crash, as a default function // is passed internally. -assert.doesNotThrow(() => fs.mkdtemp(path.join(common.tmpDir, 'bar-'))); -assert.doesNotThrow(() => fs.mkdtemp(path.join(common.tmpDir, 'bar-'), {})); +assert.doesNotThrow(() => fs.mkdtemp(path.join(tmpdir.path, 'bar-'))); +assert.doesNotThrow(() => fs.mkdtemp(path.join(tmpdir.path, 'bar-'), {})); diff --git a/test/parallel/test-fs-non-number-arguments-throw.js b/test/parallel/test-fs-non-number-arguments-throw.js index 9e73502c2908fa..61ed3f6c285dd0 100644 --- a/test/parallel/test-fs-non-number-arguments-throw.js +++ b/test/parallel/test-fs-non-number-arguments-throw.js @@ -4,9 +4,10 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const tempFile = path.join(common.tmpDir, 'fs-non-number-arguments-throw'); +const tmpdir = require('../common/tmpdir'); +const tempFile = path.join(tmpdir.path, 'fs-non-number-arguments-throw'); -common.refreshTmpDir(); +tmpdir.refresh(); fs.writeFileSync(tempFile, 'abc\ndef'); // a sanity check when using numbers instead of strings diff --git a/test/parallel/test-fs-open-flags.js b/test/parallel/test-fs-open-flags.js index aa87f8ced8793e..acf5c739a930c3 100644 --- a/test/parallel/test-fs-open-flags.js +++ b/test/parallel/test-fs-open-flags.js @@ -84,8 +84,9 @@ common.expectsError( ); if (common.isLinux || common.isOSX) { - common.refreshTmpDir(); - const file = path.join(common.tmpDir, 'a.js'); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); + const file = path.join(tmpdir.path, 'a.js'); fs.copyFileSync(fixtures.path('a.js'), file); fs.open(file, O_DSYNC, common.mustCall(assert.ifError)); } diff --git a/test/parallel/test-fs-open-numeric-flags.js b/test/parallel/test-fs-open-numeric-flags.js index 1bd9a043927039..0e5ab6997e3342 100644 --- a/test/parallel/test-fs-open-numeric-flags.js +++ b/test/parallel/test-fs-open-numeric-flags.js @@ -1,14 +1,15 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // O_WRONLY without O_CREAT shall fail with ENOENT -const pathNE = path.join(common.tmpDir, 'file-should-not-exist'); +const pathNE = path.join(tmpdir.path, 'file-should-not-exist'); assert.throws( () => fs.openSync(pathNE, fs.constants.O_WRONLY), (e) => e.code === 'ENOENT' diff --git a/test/parallel/test-fs-options-immutable.js b/test/parallel/test-fs-options-immutable.js index 9d88cf0fa42697..ca5079b07dab3f 100644 --- a/test/parallel/test-fs-options-immutable.js +++ b/test/parallel/test-fs-options-immutable.js @@ -14,7 +14,8 @@ const path = require('path'); const errHandler = (e) => assert.ifError(e); const options = Object.freeze({}); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); { assert.doesNotThrow(() => @@ -31,8 +32,8 @@ common.refreshTmpDir(); } if (common.canCreateSymLink()) { - const sourceFile = path.resolve(common.tmpDir, 'test-readlink'); - const linkFile = path.resolve(common.tmpDir, 'test-readlink-link'); + const sourceFile = path.resolve(tmpdir.path, 'test-readlink'); + const linkFile = path.resolve(tmpdir.path, 'test-readlink-link'); fs.writeFileSync(sourceFile, ''); fs.symlinkSync(sourceFile, linkFile); @@ -44,7 +45,7 @@ if (common.canCreateSymLink()) { } { - const fileName = path.resolve(common.tmpDir, 'writeFile'); + const fileName = path.resolve(tmpdir.path, 'writeFile'); assert.doesNotThrow(() => fs.writeFileSync(fileName, 'ABCD', options)); assert.doesNotThrow(() => fs.writeFile(fileName, 'ABCD', options, common.mustCall(errHandler)) @@ -52,7 +53,7 @@ if (common.canCreateSymLink()) { } { - const fileName = path.resolve(common.tmpDir, 'appendFile'); + const fileName = path.resolve(tmpdir.path, 'appendFile'); assert.doesNotThrow(() => fs.appendFileSync(fileName, 'ABCD', options)); assert.doesNotThrow(() => fs.appendFile(fileName, 'ABCD', options, common.mustCall(errHandler)) @@ -82,7 +83,7 @@ if (common.canCreateSymLink()) { } { - const tempFileName = path.resolve(common.tmpDir, 'mkdtemp-'); + const tempFileName = path.resolve(tmpdir.path, 'mkdtemp-'); assert.doesNotThrow(() => fs.mkdtempSync(tempFileName, options)); assert.doesNotThrow(() => fs.mkdtemp(tempFileName, options, common.mustCall(errHandler)) @@ -90,7 +91,7 @@ if (common.canCreateSymLink()) { } { - const fileName = path.resolve(common.tmpDir, 'streams'); + const fileName = path.resolve(tmpdir.path, 'streams'); assert.doesNotThrow(() => { fs.WriteStream(fileName, options).once('open', common.mustCall(() => { assert.doesNotThrow(() => fs.ReadStream(fileName, options)); diff --git a/test/parallel/test-fs-promisified.js b/test/parallel/test-fs-promisified.js index ac6e22f9690821..13cf5e0e0f45f3 100644 --- a/test/parallel/test-fs-promisified.js +++ b/test/parallel/test-fs-promisified.js @@ -20,9 +20,10 @@ const exists = promisify(fs.exists); })); } -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); { - const filename = path.join(common.tmpDir, 'write-promise.txt'); + const filename = path.join(tmpdir.path, 'write-promise.txt'); const fd = fs.openSync(filename, 'w'); write(fd, Buffer.from('foobar')).then(common.mustCall((obj) => { assert.strictEqual(typeof obj.bytesWritten, 'number'); diff --git a/test/parallel/test-fs-read-stream-fd.js b/test/parallel/test-fs-read-stream-fd.js index c5ee6c05ef1e5a..7d4b264002b9f3 100644 --- a/test/parallel/test-fs-read-stream-fd.js +++ b/test/parallel/test-fs-read-stream-fd.js @@ -20,15 +20,16 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const fs = require('fs'); const assert = require('assert'); const path = require('path'); -const file = path.join(common.tmpDir, '/read_stream_fd_test.txt'); +const tmpdir = require('../common/tmpdir'); +const file = path.join(tmpdir.path, '/read_stream_fd_test.txt'); const input = 'hello world'; let output = ''; -common.refreshTmpDir(); +tmpdir.refresh(); fs.writeFileSync(file, input); const fd = fs.openSync(file, 'r'); diff --git a/test/parallel/test-fs-readdir-ucs2.js b/test/parallel/test-fs-readdir-ucs2.js index debcfb7750becd..b17dc8d7292664 100644 --- a/test/parallel/test-fs-readdir-ucs2.js +++ b/test/parallel/test-fs-readdir-ucs2.js @@ -8,9 +8,10 @@ const path = require('path'); const fs = require('fs'); const assert = require('assert'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const filename = '\uD83D\uDC04'; -const root = Buffer.from(`${common.tmpDir}${path.sep}`); +const root = Buffer.from(`${tmpdir.path}${path.sep}`); const filebuff = Buffer.from(filename, 'ucs2'); const fullpath = Buffer.concat([root, filebuff]); @@ -22,7 +23,7 @@ try { throw e; } -fs.readdir(common.tmpDir, 'ucs2', common.mustCall((err, list) => { +fs.readdir(tmpdir.path, 'ucs2', common.mustCall((err, list) => { assert.ifError(err); assert.strictEqual(1, list.length); const fn = list[0]; diff --git a/test/parallel/test-fs-readdir.js b/test/parallel/test-fs-readdir.js index a5c7ebfe688c41..cc30007d70a78e 100644 --- a/test/parallel/test-fs-readdir.js +++ b/test/parallel/test-fs-readdir.js @@ -4,11 +4,13 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); -const readdirDir = common.tmpDir; +const tmpdir = require('../common/tmpdir'); + +const readdirDir = tmpdir.path; const files = ['empty', 'files', 'for', 'just', 'testing']; // Make sure tmp directory is clean -common.refreshTmpDir(); +tmpdir.refresh(); // Create the necessary files files.forEach(function(currentFile) { diff --git a/test/parallel/test-fs-readfile-pipe-large.js b/test/parallel/test-fs-readfile-pipe-large.js index 17831f81f6df83..740a3876a2d76c 100644 --- a/test/parallel/test-fs-readfile-pipe-large.js +++ b/test/parallel/test-fs-readfile-pipe-large.js @@ -18,9 +18,11 @@ if (process.argv[2] === 'child') { return; } -const filename = path.join(common.tmpDir, '/readfile_pipe_large_test.txt'); +const tmpdir = require('../common/tmpdir'); + +const filename = path.join(tmpdir.path, '/readfile_pipe_large_test.txt'); const dataExpected = 'a'.repeat(999999); -common.refreshTmpDir(); +tmpdir.refresh(); fs.writeFileSync(filename, dataExpected); const exec = require('child_process').exec; diff --git a/test/parallel/test-fs-readfile-unlink.js b/test/parallel/test-fs-readfile-unlink.js index 9ec2e849bee19f..1ed6fefb5ccfc7 100644 --- a/test/parallel/test-fs-readfile-unlink.js +++ b/test/parallel/test-fs-readfile-unlink.js @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); // Test that unlink succeeds immediately after readFile completes. @@ -28,10 +28,12 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const fileName = path.resolve(common.tmpDir, 'test.bin'); +const tmpdir = require('../common/tmpdir'); + +const fileName = path.resolve(tmpdir.path, 'test.bin'); const buf = Buffer.alloc(512 * 1024, 42); -common.refreshTmpDir(); +tmpdir.refresh(); fs.writeFileSync(fileName, buf); diff --git a/test/parallel/test-fs-readfilesync-pipe-large.js b/test/parallel/test-fs-readfilesync-pipe-large.js index f9dea90d104fad..18a06b1ba117db 100644 --- a/test/parallel/test-fs-readfilesync-pipe-large.js +++ b/test/parallel/test-fs-readfilesync-pipe-large.js @@ -15,9 +15,11 @@ if (process.argv[2] === 'child') { return; } -const filename = path.join(common.tmpDir, '/readfilesync_pipe_large_test.txt'); +const tmpdir = require('../common/tmpdir'); + +const filename = path.join(tmpdir.path, '/readfilesync_pipe_large_test.txt'); const dataExpected = 'a'.repeat(999999); -common.refreshTmpDir(); +tmpdir.refresh(); fs.writeFileSync(filename, dataExpected); const exec = require('child_process').exec; diff --git a/test/parallel/test-fs-realpath.js b/test/parallel/test-fs-realpath.js index cee45b2c899cdf..6cfd79cecfb694 100644 --- a/test/parallel/test-fs-realpath.js +++ b/test/parallel/test-fs-realpath.js @@ -22,6 +22,7 @@ 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const assert = require('assert'); const fs = require('fs'); @@ -31,9 +32,9 @@ let async_completed = 0; let async_expected = 0; const unlink = []; let skipSymlinks = false; -const tmpDir = common.tmpDir; +const tmpDir = tmpdir.path; -common.refreshTmpDir(); +tmpdir.refresh(); let root = '/'; let assertEqualPath = assert.strictEqual; @@ -391,7 +392,8 @@ function test_up_multiple(realpath, realpathSync, cb) { common.printSkipMessage('symlink test (no privs)'); return cb(); } - common.refreshTmpDir(); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); fs.mkdirSync(tmp('a'), 0o755); fs.mkdirSync(tmp('a/b'), 0o755); fs.symlinkSync('..', tmp('a/d'), 'dir'); diff --git a/test/parallel/test-fs-sir-writes-alot.js b/test/parallel/test-fs-sir-writes-alot.js index 3a3458a552ee7a..5d8c3dfec90aab 100644 --- a/test/parallel/test-fs-sir-writes-alot.js +++ b/test/parallel/test-fs-sir-writes-alot.js @@ -20,14 +20,16 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const fs = require('fs'); const assert = require('assert'); const join = require('path').join; -const filename = join(common.tmpDir, 'out.txt'); +const tmpdir = require('../common/tmpdir'); -common.refreshTmpDir(); +const filename = join(tmpdir.path, 'out.txt'); + +tmpdir.refresh(); const fd = fs.openSync(filename, 'w'); diff --git a/test/parallel/test-fs-stream-double-close.js b/test/parallel/test-fs-stream-double-close.js index 3a8086d0ac0a3b..8c0037b24312ff 100644 --- a/test/parallel/test-fs-stream-double-close.js +++ b/test/parallel/test-fs-stream-double-close.js @@ -23,15 +23,16 @@ const common = require('../common'); const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); test1(fs.createReadStream(__filename)); test2(fs.createReadStream(__filename)); test3(fs.createReadStream(__filename)); -test1(fs.createWriteStream(`${common.tmpDir}/dummy1`)); -test2(fs.createWriteStream(`${common.tmpDir}/dummy2`)); -test3(fs.createWriteStream(`${common.tmpDir}/dummy3`)); +test1(fs.createWriteStream(`${tmpdir.path}/dummy1`)); +test2(fs.createWriteStream(`${tmpdir.path}/dummy2`)); +test3(fs.createWriteStream(`${tmpdir.path}/dummy3`)); function test1(stream) { stream.destroy(); diff --git a/test/parallel/test-fs-symlink-dir-junction-relative.js b/test/parallel/test-fs-symlink-dir-junction-relative.js index 7cb50b0291d0d5..308ab040488471 100644 --- a/test/parallel/test-fs-symlink-dir-junction-relative.js +++ b/test/parallel/test-fs-symlink-dir-junction-relative.js @@ -28,12 +28,14 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const linkPath1 = path.join(common.tmpDir, 'junction1'); -const linkPath2 = path.join(common.tmpDir, 'junction2'); +const tmpdir = require('../common/tmpdir'); + +const linkPath1 = path.join(tmpdir.path, 'junction1'); +const linkPath2 = path.join(tmpdir.path, 'junction2'); const linkTarget = fixtures.fixturesDir; const linkData = fixtures.fixturesDir; -common.refreshTmpDir(); +tmpdir.refresh(); // Test fs.symlink() fs.symlink(linkData, linkPath1, 'junction', common.mustCall(function(err) { diff --git a/test/parallel/test-fs-symlink-dir-junction.js b/test/parallel/test-fs-symlink-dir-junction.js index f7ba3a6d384923..cd9459bf44afe1 100644 --- a/test/parallel/test-fs-symlink-dir-junction.js +++ b/test/parallel/test-fs-symlink-dir-junction.js @@ -26,11 +26,13 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); + // test creating and reading symbolic link const linkData = fixtures.path('cycles/'); -const linkPath = path.join(common.tmpDir, 'cycles_link'); +const linkPath = path.join(tmpdir.path, 'cycles_link'); -common.refreshTmpDir(); +tmpdir.refresh(); fs.symlink(linkData, linkPath, 'junction', common.mustCall(function(err) { assert.ifError(err); diff --git a/test/parallel/test-fs-symlink.js b/test/parallel/test-fs-symlink.js index 1de7532068c5e5..89142137dd23cf 100644 --- a/test/parallel/test-fs-symlink.js +++ b/test/parallel/test-fs-symlink.js @@ -32,11 +32,12 @@ const fs = require('fs'); let linkTime; let fileTime; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // test creating and reading symbolic link const linkData = fixtures.path('/cycles/root.js'); -const linkPath = path.join(common.tmpDir, 'symlink1.js'); +const linkPath = path.join(tmpdir.path, 'symlink1.js'); fs.symlink(linkData, linkPath, common.mustCall(function(err) { assert.ifError(err); diff --git a/test/parallel/test-fs-syncwritestream.js b/test/parallel/test-fs-syncwritestream.js index 236c412c45b543..a014277a6ba259 100644 --- a/test/parallel/test-fs-syncwritestream.js +++ b/test/parallel/test-fs-syncwritestream.js @@ -21,9 +21,10 @@ if (process.argv[2] === 'child') { return; } -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const filename = path.join(common.tmpDir, 'stdout'); +const filename = path.join(tmpdir.path, 'stdout'); const stdoutFd = fs.openSync(filename, 'w'); const proc = spawn(process.execPath, [__filename, 'child'], { diff --git a/test/parallel/test-fs-truncate-GH-6233.js b/test/parallel/test-fs-truncate-GH-6233.js index 07bd272024f99b..87663c63616ffa 100644 --- a/test/parallel/test-fs-truncate-GH-6233.js +++ b/test/parallel/test-fs-truncate-GH-6233.js @@ -24,9 +24,11 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); -const filename = `${common.tmpDir}/truncate-file.txt`; +const tmpdir = require('../common/tmpdir'); -common.refreshTmpDir(); +const filename = `${tmpdir.path}/truncate-file.txt`; + +tmpdir.refresh(); // Synchronous test. { diff --git a/test/parallel/test-fs-truncate-fd.js b/test/parallel/test-fs-truncate-fd.js index 6776dfb2668f48..ee6f66f720a038 100644 --- a/test/parallel/test-fs-truncate-fd.js +++ b/test/parallel/test-fs-truncate-fd.js @@ -3,8 +3,9 @@ const common = require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const tmp = common.tmpDir; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +const tmp = tmpdir.path; +tmpdir.refresh(); const filename = path.resolve(tmp, 'truncate-file.txt'); fs.writeFileSync(filename, 'hello world', 'utf8'); diff --git a/test/parallel/test-fs-truncate-sync.js b/test/parallel/test-fs-truncate-sync.js index a7ce2f4d97f3fe..66250cf4386b34 100644 --- a/test/parallel/test-fs-truncate-sync.js +++ b/test/parallel/test-fs-truncate-sync.js @@ -1,11 +1,12 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const tmp = common.tmpDir; +const tmpdir = require('../common/tmpdir'); +const tmp = tmpdir.path; -common.refreshTmpDir(); +tmpdir.refresh(); const filename = path.resolve(tmp, 'truncate-sync-file.txt'); diff --git a/test/parallel/test-fs-truncate.js b/test/parallel/test-fs-truncate.js index 4119d53c4f8d95..c1916b946d330f 100644 --- a/test/parallel/test-fs-truncate.js +++ b/test/parallel/test-fs-truncate.js @@ -24,11 +24,12 @@ const common = require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const tmp = common.tmpDir; +const tmpdir = require('../common/tmpdir'); +const tmp = tmpdir.path; const filename = path.resolve(tmp, 'truncate-file.txt'); const data = Buffer.alloc(1024 * 16, 'x'); -common.refreshTmpDir(); +tmpdir.refresh(); let stat; diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index 9bcf6039cd60bc..103b4640961937 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -25,7 +25,8 @@ const assert = require('assert'); const util = require('util'); const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); let tests_ok = 0; let tests_run = 0; @@ -73,8 +74,8 @@ function testIt(atime, mtime, callback) { // test synchronized code paths, these functions throw on failure // function syncTests() { - fs.utimesSync(common.tmpDir, atime, mtime); - expect_ok('utimesSync', common.tmpDir, undefined, atime, mtime); + fs.utimesSync(tmpdir.path, atime, mtime); + expect_ok('utimesSync', tmpdir.path, undefined, atime, mtime); tests_run++; // some systems don't have futimes @@ -109,17 +110,17 @@ function testIt(atime, mtime, callback) { // // test async code paths // - fs.utimes(common.tmpDir, atime, mtime, common.mustCall(function(err) { - expect_ok('utimes', common.tmpDir, err, atime, mtime); + fs.utimes(tmpdir.path, atime, mtime, common.mustCall(function(err) { + expect_ok('utimes', tmpdir.path, err, atime, mtime); fs.utimes('foobarbaz', atime, mtime, common.mustCall(function(err) { expect_errno('utimes', 'foobarbaz', err, 'ENOENT'); // don't close this fd if (common.isWindows) { - fd = fs.openSync(common.tmpDir, 'r+'); + fd = fs.openSync(tmpdir.path, 'r+'); } else { - fd = fs.openSync(common.tmpDir, 'r'); + fd = fs.openSync(tmpdir.path, 'r'); } fs.futimes(fd, atime, mtime, common.mustCall(function(err) { @@ -139,7 +140,7 @@ function testIt(atime, mtime, callback) { tests_run++; } -const stats = fs.statSync(common.tmpDir); +const stats = fs.statSync(tmpdir.path); // run tests const runTest = common.mustCall(testIt, 6); @@ -168,7 +169,7 @@ process.on('exit', function() { // Ref: https://github.com/nodejs/node/issues/13255 -const path = `${common.tmpDir}/test-utimes-precision`; +const path = `${tmpdir.path}/test-utimes-precision`; fs.writeFileSync(path, ''); // test Y2K38 for all platforms [except 'arm', and 'SunOS'] diff --git a/test/parallel/test-fs-watch-encoding.js b/test/parallel/test-fs-watch-encoding.js index 5226899d2f33a8..1cea6255098360 100644 --- a/test/parallel/test-fs-watch-encoding.js +++ b/test/parallel/test-fs-watch-encoding.js @@ -22,10 +22,11 @@ if (common.isAIX) const fs = require('fs'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const fn = '新建文夹件.txt'; -const a = path.join(common.tmpDir, fn); +const a = path.join(tmpdir.path, fn); const watchers = new Set(); @@ -42,7 +43,7 @@ function unregisterWatcher(watcher) { } const watcher1 = fs.watch( - common.tmpDir, + tmpdir.path, { encoding: 'hex' }, (event, filename) => { if (['e696b0e5bbbae69687e5a4b9e4bbb62e747874', null].includes(filename)) @@ -52,7 +53,7 @@ const watcher1 = fs.watch( registerWatcher(watcher1); const watcher2 = fs.watch( - common.tmpDir, + tmpdir.path, (event, filename) => { if ([fn, null].includes(filename)) done(watcher2); @@ -61,7 +62,7 @@ const watcher2 = fs.watch( registerWatcher(watcher2); const watcher3 = fs.watch( - common.tmpDir, + tmpdir.path, { encoding: 'buffer' }, (event, filename) => { if (filename instanceof Buffer && filename.toString('utf8') === fn) diff --git a/test/parallel/test-fs-watch-recursive.js b/test/parallel/test-fs-watch-recursive.js index 3e3746df1ef336..82d87aa2ecbb93 100644 --- a/test/parallel/test-fs-watch-recursive.js +++ b/test/parallel/test-fs-watch-recursive.js @@ -9,10 +9,12 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const testDir = common.tmpDir; +const tmpdir = require('../common/tmpdir'); + +const testDir = tmpdir.path; const filenameOne = 'watch.txt'; -common.refreshTmpDir(); +tmpdir.refresh(); const testsubdir = fs.mkdtempSync(testDir + path.sep); const relativePathOne = path.join(path.basename(testsubdir), filenameOne); diff --git a/test/parallel/test-fs-watch.js b/test/parallel/test-fs-watch.js index a82535d5378e86..7affe370c7ed03 100644 --- a/test/parallel/test-fs-watch.js +++ b/test/parallel/test-fs-watch.js @@ -14,7 +14,7 @@ class WatchTestCase { this.field = field; this.shouldSkip = !shouldInclude; } - get dirPath() { return join(common.tmpDir, this.dirName); } + get dirPath() { return join(tmpdir.path, this.dirName); } get filePath() { return join(this.dirPath, this.fileName); } } @@ -35,7 +35,8 @@ const cases = [ ) ]; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); for (const testCase of cases) { if (testCase.shouldSkip) continue; diff --git a/test/parallel/test-fs-watchfile.js b/test/parallel/test-fs-watchfile.js index 163eac5ae90a22..3c24ae84ac036b 100644 --- a/test/parallel/test-fs-watchfile.js +++ b/test/parallel/test-fs-watchfile.js @@ -5,6 +5,8 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const tmpdir = require('../common/tmpdir'); + // Basic usage tests. common.expectsError( () => { @@ -28,7 +30,7 @@ common.expectsError(function() { fs.watchFile(new Object(), common.mustNotCall()); }, { code: 'ERR_INVALID_ARG_TYPE', type: TypeError }); -const enoentFile = path.join(common.tmpDir, 'non-existent-file'); +const enoentFile = path.join(tmpdir.path, 'non-existent-file'); const expectedStatObject = new fs.Stats( 0, // dev 0, // mode @@ -46,7 +48,7 @@ const expectedStatObject = new fs.Stats( Date.UTC(1970, 0, 1, 0, 0, 0) // birthtime ); -common.refreshTmpDir(); +tmpdir.refresh(); // If the file initially didn't exist, and gets created at a later point of // time, the callback should be invoked again with proper values in stat object @@ -80,7 +82,7 @@ watcher.start(); // should not crash // Watch events should callback with a filename on supported systems. // Omitting AIX. It works but not reliably. if (common.isLinux || common.isOSX || common.isWindows) { - const dir = path.join(common.tmpDir, 'watch'); + const dir = path.join(tmpdir.path, 'watch'); fs.mkdir(dir, common.mustCall(function(err) { if (err) assert.fail(err); diff --git a/test/parallel/test-fs-write-buffer.js b/test/parallel/test-fs-write-buffer.js index ed998958ae060f..6e6154642a583d 100644 --- a/test/parallel/test-fs-write-buffer.js +++ b/test/parallel/test-fs-write-buffer.js @@ -26,11 +26,12 @@ const path = require('path'); const fs = require('fs'); const expected = Buffer.from('hello'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // fs.write with all parameters provided: { - const filename = path.join(common.tmpDir, 'write1.txt'); + const filename = path.join(tmpdir.path, 'write1.txt'); fs.open(filename, 'w', 0o644, common.mustCall((err, fd) => { assert.ifError(err); @@ -50,7 +51,7 @@ common.refreshTmpDir(); // fs.write with a buffer, without the length parameter: { - const filename = path.join(common.tmpDir, 'write2.txt'); + const filename = path.join(tmpdir.path, 'write2.txt'); fs.open(filename, 'w', 0o644, common.mustCall((err, fd) => { assert.ifError(err); @@ -70,7 +71,7 @@ common.refreshTmpDir(); // fs.write with a buffer, without the offset and length parameters: { - const filename = path.join(common.tmpDir, 'write3.txt'); + const filename = path.join(tmpdir.path, 'write3.txt'); fs.open(filename, 'w', 0o644, common.mustCall(function(err, fd) { assert.ifError(err); @@ -90,7 +91,7 @@ common.refreshTmpDir(); // fs.write with the offset passed as undefined followed by the callback: { - const filename = path.join(common.tmpDir, 'write4.txt'); + const filename = path.join(tmpdir.path, 'write4.txt'); fs.open(filename, 'w', 0o644, common.mustCall(function(err, fd) { assert.ifError(err); @@ -110,7 +111,7 @@ common.refreshTmpDir(); // fs.write with offset and length passed as undefined followed by the callback: { - const filename = path.join(common.tmpDir, 'write5.txt'); + const filename = path.join(tmpdir.path, 'write5.txt'); fs.open(filename, 'w', 0o644, common.mustCall((err, fd) => { assert.ifError(err); @@ -130,7 +131,7 @@ common.refreshTmpDir(); // fs.write with a Uint8Array, without the offset and length parameters: { - const filename = path.join(common.tmpDir, 'write6.txt'); + const filename = path.join(tmpdir.path, 'write6.txt'); fs.open(filename, 'w', 0o644, common.mustCall((err, fd) => { assert.ifError(err); diff --git a/test/parallel/test-fs-write-file-buffer.js b/test/parallel/test-fs-write-file-buffer.js index f2039c87ab4f0e..82fb7ad69a443b 100644 --- a/test/parallel/test-fs-write-file-buffer.js +++ b/test/parallel/test-fs-write-file-buffer.js @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const join = require('path').join; const util = require('util'); const fs = require('fs'); @@ -46,9 +46,10 @@ let data = [ data = data.join('\n'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const buf = Buffer.from(data, 'base64'); -fs.writeFileSync(join(common.tmpDir, 'test.jpg'), buf); +fs.writeFileSync(join(tmpdir.path, 'test.jpg'), buf); util.log('Done!'); diff --git a/test/parallel/test-fs-write-file-invalid-path.js b/test/parallel/test-fs-write-file-invalid-path.js index c45eaccf2bc193..a4c8ff5bf73a03 100644 --- a/test/parallel/test-fs-write-file-invalid-path.js +++ b/test/parallel/test-fs-write-file-invalid-path.js @@ -8,7 +8,8 @@ const path = require('path'); if (!common.isWindows) common.skip('This test is for Windows only.'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const DATA_VALUE = 'hello'; @@ -17,7 +18,7 @@ const DATA_VALUE = 'hello'; const RESERVED_CHARACTERS = '<>"|?*'; [...RESERVED_CHARACTERS].forEach((ch) => { - const pathname = path.join(common.tmpDir, `somefile_${ch}`); + const pathname = path.join(tmpdir.path, `somefile_${ch}`); assert.throws( () => { fs.writeFileSync(pathname, DATA_VALUE); @@ -28,7 +29,7 @@ const RESERVED_CHARACTERS = '<>"|?*'; // Test for ':' (NTFS data streams). // Refs: https://msdn.microsoft.com/en-us/library/windows/desktop/bb540537.aspx -const pathname = path.join(common.tmpDir, 'foo:bar'); +const pathname = path.join(tmpdir.path, 'foo:bar'); fs.writeFileSync(pathname, DATA_VALUE); let content = ''; diff --git a/test/parallel/test-fs-write-file-sync.js b/test/parallel/test-fs-write-file-sync.js index aa3864962c90af..9a19b9f6e93439 100644 --- a/test/parallel/test-fs-write-file-sync.js +++ b/test/parallel/test-fs-write-file-sync.js @@ -46,10 +46,11 @@ if (common.isWindows) { mode = 0o755; } -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // Test writeFileSync -const file1 = path.join(common.tmpDir, 'testWriteFileSync.txt'); +const file1 = path.join(tmpdir.path, 'testWriteFileSync.txt'); fs.writeFileSync(file1, '123', { mode }); @@ -59,7 +60,7 @@ assert.strictEqual(content, '123'); assert.strictEqual(fs.statSync(file1).mode & 0o777, mode); // Test appendFileSync -const file2 = path.join(common.tmpDir, 'testAppendFileSync.txt'); +const file2 = path.join(tmpdir.path, 'testAppendFileSync.txt'); fs.appendFileSync(file2, 'abc', { mode }); @@ -69,7 +70,7 @@ assert.strictEqual(content, 'abc'); assert.strictEqual(fs.statSync(file2).mode & mode, mode); // Test writeFileSync with file descriptor -const file3 = path.join(common.tmpDir, 'testWriteFileSyncFd.txt'); +const file3 = path.join(tmpdir.path, 'testWriteFileSyncFd.txt'); const fd = fs.openSync(file3, 'w+', mode); fs.writeFileSync(fd, '123'); diff --git a/test/parallel/test-fs-write-file-uint8array.js b/test/parallel/test-fs-write-file-uint8array.js index 219379c77a920d..592bdb05814e06 100644 --- a/test/parallel/test-fs-write-file-uint8array.js +++ b/test/parallel/test-fs-write-file-uint8array.js @@ -4,9 +4,10 @@ const assert = require('assert'); const fs = require('fs'); const join = require('path').join; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const filename = join(common.tmpDir, 'test.txt'); +const filename = join(tmpdir.path, 'test.txt'); const s = '南越国是前203年至前111年存在于岭南地区的一个国家,国都位于番禺,疆域包括今天中国的广东、' + '广西两省区的大部份地区,福建省、湖南、贵州、云南的一小部份地区和越南的北部。' + diff --git a/test/parallel/test-fs-write-file.js b/test/parallel/test-fs-write-file.js index 6dd1a58ecba832..b137e55547201e 100644 --- a/test/parallel/test-fs-write-file.js +++ b/test/parallel/test-fs-write-file.js @@ -25,9 +25,10 @@ const assert = require('assert'); const fs = require('fs'); const join = require('path').join; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const filename = join(common.tmpDir, 'test.txt'); +const filename = join(tmpdir.path, 'test.txt'); const n = 220; const s = '南越国是前203年至前111年存在于岭南地区的一个国家,国都位于番禺,疆域包括今天中国的广东、' + @@ -48,7 +49,7 @@ fs.writeFile(filename, s, common.mustCall(function(e) { })); // test that writeFile accepts buffers -const filename2 = join(common.tmpDir, 'test2.txt'); +const filename2 = join(tmpdir.path, 'test2.txt'); const buf = Buffer.from(s, 'utf8'); fs.writeFile(filename2, buf, common.mustCall(function(e) { @@ -62,7 +63,7 @@ fs.writeFile(filename2, buf, common.mustCall(function(e) { })); // test that writeFile accepts numbers. -const filename3 = join(common.tmpDir, 'test3.txt'); +const filename3 = join(tmpdir.path, 'test3.txt'); const m = 0o600; fs.writeFile(filename3, n, { mode: m }, common.mustCall(function(e) { @@ -82,7 +83,7 @@ fs.writeFile(filename3, n, { mode: m }, common.mustCall(function(e) { })); // test that writeFile accepts file descriptors -const filename4 = join(common.tmpDir, 'test4.txt'); +const filename4 = join(tmpdir.path, 'test4.txt'); fs.open(filename4, 'w+', common.mustCall(function(e, fd) { assert.ifError(e); diff --git a/test/parallel/test-fs-write-stream-autoclose-option.js b/test/parallel/test-fs-write-stream-autoclose-option.js index cc22ef660a15b8..e39f4d615ab7e0 100644 --- a/test/parallel/test-fs-write-stream-autoclose-option.js +++ b/test/parallel/test-fs-write-stream-autoclose-option.js @@ -4,8 +4,10 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const file = path.join(common.tmpDir, 'write-autoclose-opt1.txt'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); + +const file = path.join(tmpdir.path, 'write-autoclose-opt1.txt'); +tmpdir.refresh(); let stream = fs.createWriteStream(file, { flags: 'w+', autoClose: false }); stream.write('Test1'); stream.end(); diff --git a/test/parallel/test-fs-write-stream-change-open.js b/test/parallel/test-fs-write-stream-change-open.js index 50860f2e405f18..8f79e59427e50d 100644 --- a/test/parallel/test-fs-write-stream-change-open.js +++ b/test/parallel/test-fs-write-stream-change-open.js @@ -20,14 +20,16 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const file = path.join(common.tmpDir, 'write.txt'); +const tmpdir = require('../common/tmpdir'); -common.refreshTmpDir(); +const file = path.join(tmpdir.path, 'write.txt'); + +tmpdir.refresh(); const stream = fs.WriteStream(file); const _fs_close = fs.close; diff --git a/test/parallel/test-fs-write-stream-close-without-callback.js b/test/parallel/test-fs-write-stream-close-without-callback.js index 95b52fe7af7082..b07c799efdb2d4 100644 --- a/test/parallel/test-fs-write-stream-close-without-callback.js +++ b/test/parallel/test-fs-write-stream-close-without-callback.js @@ -1,12 +1,13 @@ 'use strict'; -const common = require('../common'); +require('../common'); const fs = require('fs'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const s = fs.createWriteStream(path.join(common.tmpDir, 'nocallback')); +const s = fs.createWriteStream(path.join(tmpdir.path, 'nocallback')); s.end('hello world'); s.close(); diff --git a/test/parallel/test-fs-write-stream-double-close.js b/test/parallel/test-fs-write-stream-double-close.js index 10ce9077a0afd4..28e53061f74c3b 100644 --- a/test/parallel/test-fs-write-stream-double-close.js +++ b/test/parallel/test-fs-write-stream-double-close.js @@ -5,17 +5,18 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); { - const s = fs.createWriteStream(path.join(common.tmpDir, 'rw')); + const s = fs.createWriteStream(path.join(tmpdir.path, 'rw')); s.close(common.mustCall()); s.close(common.mustCall()); } { - const s = fs.createWriteStream(path.join(common.tmpDir, 'rw2')); + const s = fs.createWriteStream(path.join(tmpdir.path, 'rw2')); let emits = 0; s.on('close', () => { @@ -36,7 +37,7 @@ common.refreshTmpDir(); } { - const s = fs.createWriteStream(path.join(common.tmpDir, 'rw'), { + const s = fs.createWriteStream(path.join(tmpdir.path, 'rw'), { autoClose: false }); diff --git a/test/parallel/test-fs-write-stream-encoding.js b/test/parallel/test-fs-write-stream-encoding.js index 5fb810887721d9..5803d99fd7b33d 100644 --- a/test/parallel/test-fs-write-stream-encoding.js +++ b/test/parallel/test-fs-write-stream-encoding.js @@ -1,17 +1,18 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const fixtures = require('../common/fixtures'); const fs = require('fs'); const path = require('path'); const stream = require('stream'); +const tmpdir = require('../common/tmpdir'); const firstEncoding = 'base64'; const secondEncoding = 'latin1'; const examplePath = fixtures.path('x.txt'); -const dummyPath = path.join(common.tmpDir, 'x.txt'); +const dummyPath = path.join(tmpdir.path, 'x.txt'); -common.refreshTmpDir(); +tmpdir.refresh(); const exampleReadStream = fs.createReadStream(examplePath, { encoding: firstEncoding diff --git a/test/parallel/test-fs-write-stream-end.js b/test/parallel/test-fs-write-stream-end.js index 9c889b94e4cba2..36e7cb5504cab0 100644 --- a/test/parallel/test-fs-write-stream-end.js +++ b/test/parallel/test-fs-write-stream-end.js @@ -25,17 +25,18 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); { - const file = path.join(common.tmpDir, 'write-end-test0.txt'); + const file = path.join(tmpdir.path, 'write-end-test0.txt'); const stream = fs.createWriteStream(file); stream.end(); stream.on('close', common.mustCall()); } { - const file = path.join(common.tmpDir, 'write-end-test1.txt'); + const file = path.join(tmpdir.path, 'write-end-test1.txt'); const stream = fs.createWriteStream(file); stream.end('a\n', 'utf8'); stream.on('close', common.mustCall(function() { diff --git a/test/parallel/test-fs-write-stream-err.js b/test/parallel/test-fs-write-stream-err.js index 077bfb24b75cff..36bf9dbcfb068e 100644 --- a/test/parallel/test-fs-write-stream-err.js +++ b/test/parallel/test-fs-write-stream-err.js @@ -24,9 +24,10 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const stream = fs.createWriteStream(`${common.tmpDir}/out`, { +const stream = fs.createWriteStream(`${tmpdir.path}/out`, { highWaterMark: 10 }); const err = new Error('BAM'); diff --git a/test/parallel/test-fs-write-stream-throw-type-error.js b/test/parallel/test-fs-write-stream-throw-type-error.js index 42538906a5be11..73312afa6b6423 100644 --- a/test/parallel/test-fs-write-stream-throw-type-error.js +++ b/test/parallel/test-fs-write-stream-throw-type-error.js @@ -4,9 +4,11 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const example = path.join(common.tmpDir, 'dummy'); +const tmpdir = require('../common/tmpdir'); -common.refreshTmpDir(); +const example = path.join(tmpdir.path, 'dummy'); + +tmpdir.refresh(); assert.doesNotThrow(() => { fs.createWriteStream(example, undefined); diff --git a/test/parallel/test-fs-write-stream.js b/test/parallel/test-fs-write-stream.js index bba2debf9156e5..6cf5ff3b69f533 100644 --- a/test/parallel/test-fs-write-stream.js +++ b/test/parallel/test-fs-write-stream.js @@ -20,14 +20,16 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const file = path.join(common.tmpDir, 'write.txt'); +const tmpdir = require('../common/tmpdir'); -common.refreshTmpDir(); +const file = path.join(tmpdir.path, 'write.txt'); + +tmpdir.refresh(); { const stream = fs.WriteStream(file); diff --git a/test/parallel/test-fs-write-string-coerce.js b/test/parallel/test-fs-write-string-coerce.js index 9356bc71850303..4581c319277a78 100644 --- a/test/parallel/test-fs-write-string-coerce.js +++ b/test/parallel/test-fs-write-string-coerce.js @@ -4,9 +4,10 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const fn = path.join(common.tmpDir, 'write-string-coerce.txt'); +const fn = path.join(tmpdir.path, 'write-string-coerce.txt'); const data = true; const expected = String(data); diff --git a/test/parallel/test-fs-write-sync.js b/test/parallel/test-fs-write-sync.js index 41a9f2c8887b32..4ca7a1dd570eb0 100644 --- a/test/parallel/test-fs-write-sync.js +++ b/test/parallel/test-fs-write-sync.js @@ -20,13 +20,14 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const filename = path.join(common.tmpDir, 'write.txt'); +const tmpdir = require('../common/tmpdir'); +const filename = path.join(tmpdir.path, 'write.txt'); -common.refreshTmpDir(); +tmpdir.refresh(); // fs.writeSync with all parameters provided: { diff --git a/test/parallel/test-fs-write.js b/test/parallel/test-fs-write.js index ccf2d9b40f7934..5dd9ca0e902a1e 100644 --- a/test/parallel/test-fs-write.js +++ b/test/parallel/test-fs-write.js @@ -24,14 +24,16 @@ const common = require('../common'); const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const fn = path.join(common.tmpDir, 'write.txt'); -const fn2 = path.join(common.tmpDir, 'write2.txt'); -const fn3 = path.join(common.tmpDir, 'write3.txt'); +const tmpdir = require('../common/tmpdir'); + +tmpdir.refresh(); + +const fn = path.join(tmpdir.path, 'write.txt'); +const fn2 = path.join(tmpdir.path, 'write2.txt'); +const fn3 = path.join(tmpdir.path, 'write3.txt'); const expected = 'ümlaut.'; const constants = fs.constants; -common.refreshTmpDir(); - fs.open(fn, 'w', 0o644, common.mustCall(function(err, fd) { assert.ifError(err); diff --git a/test/parallel/test-http-agent-getname.js b/test/parallel/test-http-agent-getname.js index 4b4e9ac26b44a5..31dc255ba558db 100644 --- a/test/parallel/test-http-agent-getname.js +++ b/test/parallel/test-http-agent-getname.js @@ -1,10 +1,12 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const http = require('http'); const path = require('path'); +const tmpdir = require('../common/tmpdir'); + const agent = new http.Agent(); // default to localhost @@ -33,7 +35,7 @@ assert.strictEqual( ); // unix socket -const socketPath = path.join(common.tmpDir, 'foo', 'bar'); +const socketPath = path.join(tmpdir.path, 'foo', 'bar'); assert.strictEqual( agent.getName({ socketPath diff --git a/test/parallel/test-http-chunk-problem.js b/test/parallel/test-http-chunk-problem.js index 46a7406e74595a..f999f055fc0a91 100644 --- a/test/parallel/test-http-chunk-problem.js +++ b/test/parallel/test-http-chunk-problem.js @@ -37,7 +37,9 @@ if (process.argv[2] === 'shasum') { const http = require('http'); const cp = require('child_process'); -const filename = require('path').join(common.tmpDir, 'big'); +const tmpdir = require('../common/tmpdir'); + +const filename = require('path').join(tmpdir.path, 'big'); let server; function executeRequest(cb) { @@ -59,7 +61,7 @@ function executeRequest(cb) { } -common.refreshTmpDir(); +tmpdir.refresh(); const ddcmd = common.ddCommand(filename, 10240); diff --git a/test/parallel/test-http-client-abort-keep-alive-queued-unix-socket.js b/test/parallel/test-http-client-abort-keep-alive-queued-unix-socket.js index efcbfe8dc5846f..745ed4ceeee887 100644 --- a/test/parallel/test-http-client-abort-keep-alive-queued-unix-socket.js +++ b/test/parallel/test-http-client-abort-keep-alive-queued-unix-socket.js @@ -16,7 +16,8 @@ class Agent extends http.Agent { const server = http.createServer((req, res) => res.end()); const socketPath = common.PIPE; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); server.listen(socketPath, common.mustCall(() => { const agent = new Agent({ diff --git a/test/parallel/test-http-client-abort-unix-socket.js b/test/parallel/test-http-client-abort-unix-socket.js index 3fb2cd9b869f45..bf666b7935a3a6 100644 --- a/test/parallel/test-http-client-abort-unix-socket.js +++ b/test/parallel/test-http-client-abort-unix-socket.js @@ -12,7 +12,8 @@ class Agent extends http.Agent { } } -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); server.listen(common.PIPE, common.mustCall(() => { const req = http.get({ diff --git a/test/parallel/test-http-client-pipe-end.js b/test/parallel/test-http-client-pipe-end.js index 4b9f168e9907f2..9dcdbe4a49d83a 100644 --- a/test/parallel/test-http-client-pipe-end.js +++ b/test/parallel/test-http-client-pipe-end.js @@ -34,7 +34,8 @@ const server = http.createServer(function(req, res) { }); }); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); server.listen(common.PIPE, function() { const req = http.request({ diff --git a/test/parallel/test-http-client-response-domain.js b/test/parallel/test-http-client-response-domain.js index ff73fd51cc5d73..0a32e929141e45 100644 --- a/test/parallel/test-http-client-response-domain.js +++ b/test/parallel/test-http-client-response-domain.js @@ -27,7 +27,8 @@ const domain = require('domain'); let d; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // first fire up a simple HTTP server const server = http.createServer(function(req, res) { diff --git a/test/parallel/test-http-get-pipeline-problem.js b/test/parallel/test-http-get-pipeline-problem.js index 3182c1faacd802..b8b11e7e77c29a 100644 --- a/test/parallel/test-http-get-pipeline-problem.js +++ b/test/parallel/test-http-get-pipeline-problem.js @@ -32,7 +32,8 @@ const Countdown = require('../common/countdown'); http.globalAgent.maxSockets = 1; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const image = fixtures.readSync('/person.jpg'); @@ -68,7 +69,7 @@ server.listen(0, function() { http.get(opts, function(res) { console.error(`recv ${x}`); - const s = fs.createWriteStream(`${common.tmpDir}/${x}.jpg`); + const s = fs.createWriteStream(`${tmpdir.path}/${x}.jpg`); res.pipe(s); s.on('finish', function() { @@ -85,13 +86,13 @@ server.listen(0, function() { function checkFiles() { // Should see 1.jpg, 2.jpg, ..., 100.jpg in tmpDir - const files = fs.readdirSync(common.tmpDir); + const files = fs.readdirSync(tmpdir.path); assert(total <= files.length); for (let i = 0; i < total; i++) { const fn = `${i}.jpg`; assert.ok(files.includes(fn), `couldn't find '${fn}'`); - const stat = fs.statSync(`${common.tmpDir}/${fn}`); + const stat = fs.statSync(`${tmpdir.path}/${fn}`); assert.strictEqual( image.length, stat.size, `size doesn't match on '${fn}'. Got ${stat.size} bytes`); diff --git a/test/parallel/test-http-pipe-fs.js b/test/parallel/test-http-pipe-fs.js index fd625bb4acc541..dfb44ff3b25d99 100644 --- a/test/parallel/test-http-pipe-fs.js +++ b/test/parallel/test-http-pipe-fs.js @@ -29,9 +29,10 @@ const NUMBER_OF_STREAMS = 2; const countdown = new Countdown(NUMBER_OF_STREAMS, () => server.close()); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const file = path.join(common.tmpDir, 'http-pipe-fs-test.txt'); +const file = path.join(tmpdir.path, 'http-pipe-fs-test.txt'); const server = http.createServer(common.mustCall(function(req, res) { const stream = fs.createWriteStream(file); diff --git a/test/parallel/test-http-unix-socket-keep-alive.js b/test/parallel/test-http-unix-socket-keep-alive.js index 668c440325e0ec..11b3d9b39264a4 100644 --- a/test/parallel/test-http-unix-socket-keep-alive.js +++ b/test/parallel/test-http-unix-socket-keep-alive.js @@ -5,7 +5,8 @@ const http = require('http'); const server = http.createServer((req, res) => res.end()); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); server.listen(common.PIPE, common.mustCall(() => asyncLoop(makeKeepAliveRequest, 10, common.mustCall(() => diff --git a/test/parallel/test-http-unix-socket.js b/test/parallel/test-http-unix-socket.js index 6d5897cacbecc2..08a533b26875ba 100644 --- a/test/parallel/test-http-unix-socket.js +++ b/test/parallel/test-http-unix-socket.js @@ -34,7 +34,8 @@ const server = http.createServer(function(req, res) { res.end(); }); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); server.listen(common.PIPE, common.mustCall(function() { diff --git a/test/parallel/test-http2-compat-serverrequest-pipe.js b/test/parallel/test-http2-compat-serverrequest-pipe.js index becc62c6621e7f..53e54cdf913b0e 100644 --- a/test/parallel/test-http2-compat-serverrequest-pipe.js +++ b/test/parallel/test-http2-compat-serverrequest-pipe.js @@ -11,9 +11,10 @@ const path = require('path'); // piping should work as expected with createWriteStream -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const loc = fixtures.path('url-tests.js'); -const fn = path.join(common.tmpDir, 'http2-url-tests.js'); +const fn = path.join(tmpdir.path, 'http2-url-tests.js'); const server = http2.createServer(); diff --git a/test/parallel/test-http2-pipe.js b/test/parallel/test-http2-pipe.js index 891fc6e292b909..2a759f9848721b 100644 --- a/test/parallel/test-http2-pipe.js +++ b/test/parallel/test-http2-pipe.js @@ -11,9 +11,10 @@ const path = require('path'); // piping should work as expected with createWriteStream -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const loc = fixtures.path('url-tests.js'); -const fn = path.join(common.tmpDir, 'http2-url-tests.js'); +const fn = path.join(tmpdir.path, 'http2-url-tests.js'); const server = http2.createServer(); diff --git a/test/parallel/test-https-unix-socket-self-signed.js b/test/parallel/test-https-unix-socket-self-signed.js index 6e7cf827472a88..48207a7a22f52a 100644 --- a/test/parallel/test-https-unix-socket-self-signed.js +++ b/test/parallel/test-https-unix-socket-self-signed.js @@ -4,7 +4,8 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const fixtures = require('../common/fixtures'); const https = require('https'); diff --git a/test/parallel/test-internal-fs-syncwritestream.js b/test/parallel/test-internal-fs-syncwritestream.js index 9e0024df3481b2..c474d21cb43826 100644 --- a/test/parallel/test-internal-fs-syncwritestream.js +++ b/test/parallel/test-internal-fs-syncwritestream.js @@ -7,9 +7,10 @@ const fs = require('fs'); const path = require('path'); const SyncWriteStream = require('internal/fs').SyncWriteStream; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const filename = path.join(common.tmpDir, 'sync-write-stream.txt'); +const filename = path.join(tmpdir.path, 'sync-write-stream.txt'); // Verify constructing the instance with default options. { diff --git a/test/parallel/test-module-circular-symlinks.js b/test/parallel/test-module-circular-symlinks.js index b5e04a9c622da8..e8d80640df0b17 100644 --- a/test/parallel/test-module-circular-symlinks.js +++ b/test/parallel/test-module-circular-symlinks.js @@ -29,8 +29,9 @@ const fs = require('fs'); // └── node_modules // └── moduleA -> {tmpDir}/node_modules/moduleA -common.refreshTmpDir(); -const tmpDir = common.tmpDir; +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +const tmpDir = tmpdir.path; const node_modules = path.join(tmpDir, 'node_modules'); const moduleA = path.join(node_modules, 'moduleA'); diff --git a/test/parallel/test-module-loading-globalpaths.js b/test/parallel/test-module-loading-globalpaths.js index cd3144f8cd41a4..e3c36cb21c202e 100644 --- a/test/parallel/test-module-loading-globalpaths.js +++ b/test/parallel/test-module-loading-globalpaths.js @@ -10,10 +10,11 @@ const pkgName = 'foo'; if (process.argv[2] === 'child') { console.log(require(pkgName).string); } else { - common.refreshTmpDir(); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); // Copy node binary into a test $PREFIX directory. - const prefixPath = path.join(common.tmpDir, 'install'); + const prefixPath = path.join(tmpdir.path, 'install'); fs.mkdirSync(prefixPath); let testExecPath; if (common.isWindows) { @@ -43,7 +44,7 @@ if (process.argv[2] === 'child') { delete env['NODE_PATH']; // Test empty global path. - const noPkgHomeDir = path.join(common.tmpDir, 'home-no-pkg'); + const noPkgHomeDir = path.join(tmpdir.path, 'home-no-pkg'); fs.mkdirSync(noPkgHomeDir); env['HOME'] = env['USERPROFILE'] = noPkgHomeDir; assert.throws( diff --git a/test/parallel/test-module-symlinked-peer-modules.js b/test/parallel/test-module-symlinked-peer-modules.js index e3d538c42b0bf6..f93dea720f9a12 100644 --- a/test/parallel/test-module-symlinked-peer-modules.js +++ b/test/parallel/test-module-symlinked-peer-modules.js @@ -13,9 +13,10 @@ const fs = require('fs'); const path = require('path'); const assert = require('assert'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const tmpDir = common.tmpDir; +const tmpDir = tmpdir.path; // Creates the following structure // {tmpDir} diff --git a/test/parallel/test-net-connect-options-fd.js b/test/parallel/test-net-connect-options-fd.js index 50c2a08efeb194..76a5e30755b15c 100644 --- a/test/parallel/test-net-connect-options-fd.js +++ b/test/parallel/test-net-connect-options-fd.js @@ -8,7 +8,8 @@ const net = require('net'); const path = require('path'); const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); function testClients(getSocketOpt, getConnectOpt, getConnectCb) { const cloneOptions = (index) => diff --git a/test/parallel/test-net-connect-options-path.js b/test/parallel/test-net-connect-options-path.js index 3868b85a78a6d2..9a2737c371bbf5 100644 --- a/test/parallel/test-net-connect-options-path.js +++ b/test/parallel/test-net-connect-options-path.js @@ -5,7 +5,8 @@ const net = require('net'); // This file tests the option handling of net.connect, // net.createConnect, and new Socket().connect -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const CLIENT_VARIANTS = 12; diff --git a/test/parallel/test-net-pingpong.js b/test/parallel/test-net-pingpong.js index c83cfaf94349df..9fc59db4e2ff2f 100644 --- a/test/parallel/test-net-pingpong.js +++ b/test/parallel/test-net-pingpong.js @@ -128,7 +128,8 @@ function pingPongTest(port, host) { } /* All are run at once, so run on different ports */ -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); pingPongTest(common.PIPE); pingPongTest(0); pingPongTest(0, 'localhost'); diff --git a/test/parallel/test-net-pipe-connect-errors.js b/test/parallel/test-net-pipe-connect-errors.js index 119bca19fcc762..8db452669991f0 100644 --- a/test/parallel/test-net-pipe-connect-errors.js +++ b/test/parallel/test-net-pipe-connect-errors.js @@ -36,12 +36,13 @@ if (common.isWindows) { // file instead emptyTxt = fixtures.path('empty.txt'); } else { - common.refreshTmpDir(); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); // Keep the file name very short so that we don't exceed the 108 char limit // on CI for a POSIX socket. Even though this isn't actually a socket file, // the error will be different from the one we are expecting if we exceed the // limit. - emptyTxt = `${common.tmpDir}0.txt`; + emptyTxt = `${tmpdir.path}0.txt`; function cleanup() { try { diff --git a/test/parallel/test-net-server-listen-handle.js b/test/parallel/test-net-server-listen-handle.js index 2b56817d2c61d7..532674bc7a2819 100644 --- a/test/parallel/test-net-server-listen-handle.js +++ b/test/parallel/test-net-server-listen-handle.js @@ -8,7 +8,8 @@ const uv = process.binding('uv'); const { TCP, constants: TCPConstants } = process.binding('tcp_wrap'); const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); function closeServer() { return common.mustCall(function() { diff --git a/test/parallel/test-net-server-listen-path.js b/test/parallel/test-net-server-listen-path.js index 53173fa66d120a..b16b7c7ba81236 100644 --- a/test/parallel/test-net-server-listen-path.js +++ b/test/parallel/test-net-server-listen-path.js @@ -3,7 +3,8 @@ const common = require('../common'); const net = require('net'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); function closeServer() { return common.mustCall(function() { diff --git a/test/parallel/test-npm-install.js b/test/parallel/test-npm-install.js index d826eb09ed4756..dc9f60b799e0f6 100644 --- a/test/parallel/test-npm-install.js +++ b/test/parallel/test-npm-install.js @@ -9,10 +9,11 @@ const assert = require('assert'); const fs = require('fs'); const fixtures = require('../common/fixtures'); -common.refreshTmpDir(); -const npmSandbox = path.join(common.tmpDir, 'npm-sandbox'); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +const npmSandbox = path.join(tmpdir.path, 'npm-sandbox'); fs.mkdirSync(npmSandbox); -const installDir = path.join(common.tmpDir, 'install-dir'); +const installDir = path.join(tmpdir.path, 'install-dir'); fs.mkdirSync(installDir); const npmPath = path.join( diff --git a/test/parallel/test-pipe-address.js b/test/parallel/test-pipe-address.js index 10552abee7b60f..3550434932e934 100644 --- a/test/parallel/test-pipe-address.js +++ b/test/parallel/test-pipe-address.js @@ -4,7 +4,8 @@ const assert = require('assert'); const net = require('net'); const server = net.createServer(common.mustNotCall()); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); server.listen(common.PIPE, common.mustCall(function() { assert.strictEqual(server.address(), common.PIPE); diff --git a/test/parallel/test-pipe-file-to-http.js b/test/parallel/test-pipe-file-to-http.js index 244dcd1a990fbf..cfe289c30caa9d 100644 --- a/test/parallel/test-pipe-file-to-http.js +++ b/test/parallel/test-pipe-file-to-http.js @@ -27,9 +27,10 @@ const http = require('http'); const path = require('path'); const cp = require('child_process'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const filename = path.join(common.tmpDir || '/tmp', 'big'); +const filename = path.join(tmpdir.path || '/tmp', 'big'); let count = 0; const server = http.createServer(function(req, res) { diff --git a/test/parallel/test-pipe-stream.js b/test/parallel/test-pipe-stream.js index 8fd9d31d499089..c7d9a0a626559e 100644 --- a/test/parallel/test-pipe-stream.js +++ b/test/parallel/test-pipe-stream.js @@ -3,7 +3,8 @@ const common = require('../common'); const assert = require('assert'); const net = require('net'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); function test(clazz, cb) { let have_ping = false; diff --git a/test/parallel/test-pipe-unref.js b/test/parallel/test-pipe-unref.js index cfe7a97ca59fd3..1e0245b5444f62 100644 --- a/test/parallel/test-pipe-unref.js +++ b/test/parallel/test-pipe-unref.js @@ -4,7 +4,8 @@ const net = require('net'); // This test should end immediately after `unref` is called -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const s = net.Server(); s.listen(common.PIPE); diff --git a/test/parallel/test-pipe-writev.js b/test/parallel/test-pipe-writev.js index db95a4b181849f..5e5b42e6a78d88 100644 --- a/test/parallel/test-pipe-writev.js +++ b/test/parallel/test-pipe-writev.js @@ -7,7 +7,8 @@ if (common.isWindows) const assert = require('assert'); const net = require('net'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const server = net.createServer((connection) => { connection.on('error', (err) => { diff --git a/test/parallel/test-process-chdir.js b/test/parallel/test-process-chdir.js index 61707706a322bc..c0a245ffd3483b 100644 --- a/test/parallel/test-process-chdir.js +++ b/test/parallel/test-process-chdir.js @@ -1,10 +1,12 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const tmpdir = require('../common/tmpdir'); + process.chdir('..'); assert.notStrictEqual(process.cwd(), __dirname); process.chdir(__dirname); @@ -18,10 +20,10 @@ if (process.versions.icu) { // ICU is unavailable, use characters that can't be decomposed dirName = 'weird \ud83d\udc04 characters \ud83d\udc05'; } -const dir = path.resolve(common.tmpDir, dirName); +const dir = path.resolve(tmpdir.path, dirName); // Make sure that the tmp directory is clean -common.refreshTmpDir(); +tmpdir.refresh(); fs.mkdirSync(dir); process.chdir(dir); @@ -29,7 +31,7 @@ assert.strictEqual(process.cwd().normalize(), dir.normalize()); process.chdir('..'); assert.strictEqual(process.cwd().normalize(), - path.resolve(common.tmpDir).normalize()); + path.resolve(tmpdir.path).normalize()); const errMessage = /^TypeError: Bad argument\.$/; assert.throws(function() { process.chdir({}); }, diff --git a/test/parallel/test-process-execpath.js b/test/parallel/test-process-execpath.js index d70d1dfd389875..68aef90b303449 100644 --- a/test/parallel/test-process-execpath.js +++ b/test/parallel/test-process-execpath.js @@ -14,9 +14,10 @@ if (process.argv[2] === 'child') { // The console.log() output is part of the test here. console.log(process.execPath); } else { - common.refreshTmpDir(); + const tmpdir = require('../common/tmpdir'); + tmpdir.refresh(); - const symlinkedNode = path.join(common.tmpDir, 'symlinked-node'); + const symlinkedNode = path.join(tmpdir.path, 'symlinked-node'); fs.symlinkSync(process.execPath, symlinkedNode); const proc = child_process.spawnSync(symlinkedNode, [__filename, 'child']); diff --git a/test/parallel/test-process-redirect-warnings-env.js b/test/parallel/test-process-redirect-warnings-env.js index 59e236ab89f8e3..5031152a48baf0 100644 --- a/test/parallel/test-process-redirect-warnings-env.js +++ b/test/parallel/test-process-redirect-warnings-env.js @@ -12,10 +12,11 @@ const fork = require('child_process').fork; const path = require('path'); const assert = require('assert'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const warnmod = require.resolve(fixtures.path('warnings.js')); -const warnpath = path.join(common.tmpDir, 'warnings.txt'); +const warnpath = path.join(tmpdir.path, 'warnings.txt'); fork(warnmod, { env: Object.assign({}, process.env, { NODE_REDIRECT_WARNINGS: warnpath }) }) diff --git a/test/parallel/test-process-redirect-warnings.js b/test/parallel/test-process-redirect-warnings.js index 76f376240ba9b9..b4f55fa8345409 100644 --- a/test/parallel/test-process-redirect-warnings.js +++ b/test/parallel/test-process-redirect-warnings.js @@ -12,10 +12,11 @@ const fork = require('child_process').fork; const path = require('path'); const assert = require('assert'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const warnmod = fixtures.path('warnings.js'); -const warnpath = path.join(common.tmpDir, 'warnings.txt'); +const warnpath = path.join(tmpdir.path, 'warnings.txt'); fork(warnmod, { execArgv: [`--redirect-warnings=${warnpath}`] }) .on('exit', common.mustCall(() => { diff --git a/test/parallel/test-regress-GH-3739.js b/test/parallel/test-regress-GH-3739.js index d41accc2e6ec0a..dbf77ad785cac9 100644 --- a/test/parallel/test-regress-GH-3739.js +++ b/test/parallel/test-regress-GH-3739.js @@ -5,10 +5,12 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); -let dir = path.resolve(common.tmpDir); +const tmpdir = require('../common/tmpdir'); + +let dir = path.resolve(tmpdir.path); // Make sure that the tmp directory is clean -common.refreshTmpDir(); +tmpdir.refresh(); // Make a long path. for (let i = 0; i < 50; i++) { diff --git a/test/parallel/test-repl-history-perm.js b/test/parallel/test-repl-history-perm.js index 9f14ece568dc80..b125fa551dc858 100644 --- a/test/parallel/test-repl-history-perm.js +++ b/test/parallel/test-repl-history-perm.js @@ -31,8 +31,9 @@ stream._write = function(c, e, cb) { }; stream.readable = stream.writable = true; -common.refreshTmpDir(); -const replHistoryPath = path.join(common.tmpDir, '.node_repl_history'); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +const replHistoryPath = path.join(tmpdir.path, '.node_repl_history'); const checkResults = common.mustCall(function(err, r) { assert.ifError(err); diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js index 3ba71f1f175413..396203d949f4ba 100644 --- a/test/parallel/test-repl-persistent-history.js +++ b/test/parallel/test-repl-persistent-history.js @@ -11,11 +11,12 @@ const fs = require('fs'); const path = require('path'); const os = require('os'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // Mock os.homedir() os.homedir = function() { - return common.tmpDir; + return tmpdir.path; }; // Create an input stream specialized for testing an array of actions @@ -55,16 +56,16 @@ const CLEAR = { ctrl: true, name: 'u' }; // File paths const historyFixturePath = fixtures.path('.node_repl_history'); -const historyPath = path.join(common.tmpDir, '.fixture_copy_repl_history'); -const historyPathFail = path.join(common.tmpDir, '.node_repl\u0000_history'); +const historyPath = path.join(tmpdir.path, '.fixture_copy_repl_history'); +const historyPathFail = path.join(tmpdir.path, '.node_repl\u0000_history'); const oldHistoryPathObj = fixtures.path('old-repl-history-file-obj.json'); const oldHistoryPathFaulty = fixtures.path('old-repl-history-file-faulty.json'); const oldHistoryPath = fixtures.path('old-repl-history-file.json'); const enoentHistoryPath = fixtures.path('enoent-repl-history-file.json'); const emptyHistoryPath = fixtures.path('.empty-repl-history-file'); -const defaultHistoryPath = path.join(common.tmpDir, '.node_repl_history'); +const defaultHistoryPath = path.join(tmpdir.path, '.node_repl_history'); const emptyHiddenHistoryPath = fixtures.path('.empty-hidden-repl-history-file'); -const devNullHistoryPath = path.join(common.tmpDir, +const devNullHistoryPath = path.join(tmpdir.path, '.dev-null-repl-history-file'); // Common message bits const prompt = '> '; diff --git a/test/parallel/test-repl-save-load.js b/test/parallel/test-repl-save-load.js index 2be272473b652a..3778ffac3ec379 100644 --- a/test/parallel/test-repl-save-load.js +++ b/test/parallel/test-repl-save-load.js @@ -25,7 +25,8 @@ const assert = require('assert'); const join = require('path').join; const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const repl = require('repl'); @@ -39,7 +40,7 @@ const testFile = [ 'var top = function() {', 'var inner = {one:1};' ]; -const saveFileName = join(common.tmpDir, 'test.save.js'); +const saveFileName = join(tmpdir.path, 'test.save.js'); // input some data putIn.run(testFile); @@ -91,7 +92,7 @@ testMe.complete('inner.o', function(error, data) { // clear the REPL putIn.run(['.clear']); -let loadFile = join(common.tmpDir, 'file.does.not.exist'); +let loadFile = join(tmpdir.path, 'file.does.not.exist'); // should not break putIn.write = function(data) { @@ -103,7 +104,7 @@ putIn.write = function(data) { putIn.run([`.load ${loadFile}`]); // throw error on loading directory -loadFile = common.tmpDir; +loadFile = tmpdir.path; putIn.write = function(data) { assert.strictEqual(data, `Failed to load:${loadFile} is not a valid file\n`); putIn.write = () => {}; @@ -115,7 +116,7 @@ putIn.run(['.clear']); // NUL (\0) is disallowed in filenames in UNIX-like operating systems and // Windows so we can use that to test failed saves -const invalidFileName = join(common.tmpDir, '\0\0\0\0\0'); +const invalidFileName = join(tmpdir.path, '\0\0\0\0\0'); // should not break putIn.write = function(data) { diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index 7419148dfaf2df..942b1d341c4c0a 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -22,12 +22,13 @@ 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const assert = require('assert'); const net = require('net'); const repl = require('repl'); common.globalCheck = false; -common.refreshTmpDir(); +tmpdir.refresh(); common.crashOnUnhandledRejection(); const message = 'Read, Eval, Print Loop'; diff --git a/test/parallel/test-require-long-path.js b/test/parallel/test-require-long-path.js index aaaf07d48ae897..548a0b5425df39 100644 --- a/test/parallel/test-require-long-path.js +++ b/test/parallel/test-require-long-path.js @@ -6,15 +6,17 @@ if (!common.isWindows) const fs = require('fs'); const path = require('path'); +const tmpdir = require('../common/tmpdir'); + // make a path that is more than 260 chars long. -const dirNameLen = Math.max(260 - common.tmpDir.length, 1); -const dirName = path.join(common.tmpDir, 'x'.repeat(dirNameLen)); +const dirNameLen = Math.max(260 - tmpdir.path.length, 1); +const dirName = path.join(tmpdir.path, 'x'.repeat(dirNameLen)); const fullDirPath = path.resolve(dirName); const indexFile = path.join(fullDirPath, 'index.js'); const otherFile = path.join(fullDirPath, 'other.js'); -common.refreshTmpDir(); +tmpdir.refresh(); fs.mkdirSync(fullDirPath); fs.writeFileSync(indexFile, 'require("./other");'); @@ -23,4 +25,4 @@ fs.writeFileSync(otherFile, ''); require(indexFile); require(otherFile); -common.refreshTmpDir(); +tmpdir.refresh(); diff --git a/test/parallel/test-require-symlink.js b/test/parallel/test-require-symlink.js index 60962156f2f286..d245c21dd1fdb4 100644 --- a/test/parallel/test-require-symlink.js +++ b/test/parallel/test-require-symlink.js @@ -14,12 +14,13 @@ const process = require('process'); // Setup: Copy fixtures to tmp directory. const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const dirName = 'module-require-symlink'; const fixtureSource = fixtures.path(dirName); -const tmpDirTarget = path.join(common.tmpDir, dirName); +const tmpDirTarget = path.join(tmpdir.path, dirName); // Copy fixtureSource to linkTarget recursively. -common.refreshTmpDir(); +tmpdir.refresh(); function copyDir(source, target) { fs.mkdirSync(target); @@ -40,7 +41,7 @@ copyDir(fixtureSource, tmpDirTarget); // Move to tmp dir and do everything with relative paths there so that the test // doesn't incorrectly fail due to a symlink somewhere else in the absolute // path. -process.chdir(common.tmpDir); +process.chdir(tmpdir.path); const linkDir = path.join(dirName, 'node_modules', diff --git a/test/parallel/test-require-unicode.js b/test/parallel/test-require-unicode.js index 93a8787cdfe7c8..530ff3bb56c3d0 100644 --- a/test/parallel/test-require-unicode.js +++ b/test/parallel/test-require-unicode.js @@ -1,13 +1,14 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const dirname = path.join(common.tmpDir, '\u4e2d\u6587\u76ee\u5f55'); +const dirname = path.join(tmpdir.path, '\u4e2d\u6587\u76ee\u5f55'); fs.mkdirSync(dirname); fs.writeFileSync(path.join(dirname, 'file.js'), 'module.exports = 42;'); fs.writeFileSync(path.join(dirname, 'package.json'), diff --git a/test/parallel/test-stdin-from-file.js b/test/parallel/test-stdin-from-file.js index 148464e51a8c1a..eda8e068fe37fe 100644 --- a/test/parallel/test-stdin-from-file.js +++ b/test/parallel/test-stdin-from-file.js @@ -1,13 +1,14 @@ 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const assert = require('assert'); const { join } = require('path'); const childProcess = require('child_process'); const fs = require('fs'); const stdoutScript = fixtures.path('echo-close-check.js'); -const tmpFile = join(common.tmpDir, 'stdin.txt'); +const tmpFile = join(tmpdir.path, 'stdin.txt'); const cmd = `"${process.argv[0]}" "${stdoutScript}" < "${tmpFile}"`; @@ -24,7 +25,7 @@ const string = 'abc\nümlaut.\nsomething else\n' + '有效的改善了岭南地区落后的政治、##济现状。\n'; -common.refreshTmpDir(); +tmpdir.refresh(); console.log(`${cmd}\n\n`); diff --git a/test/parallel/test-stdout-to-file.js b/test/parallel/test-stdout-to-file.js index 6869fafa1cfaf9..a02531ca41fbdb 100644 --- a/test/parallel/test-stdout-to-file.js +++ b/test/parallel/test-stdout-to-file.js @@ -5,12 +5,13 @@ const path = require('path'); const childProcess = require('child_process'); const fs = require('fs'); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const scriptString = fixtures.path('print-chars.js'); const scriptBuffer = fixtures.path('print-chars-from-buffer.js'); -const tmpFile = path.join(common.tmpDir, 'stdout.txt'); +const tmpFile = path.join(tmpdir.path, 'stdout.txt'); -common.refreshTmpDir(); +tmpdir.refresh(); function test(size, useBuffer, cb) { const cmd = `"${process.argv[0]}" "${ diff --git a/test/parallel/test-tls-connect-pipe.js b/test/parallel/test-tls-connect-pipe.js index f609659d195499..88e78b7a2b2e59 100644 --- a/test/parallel/test-tls-connect-pipe.js +++ b/test/parallel/test-tls-connect-pipe.js @@ -33,7 +33,8 @@ const options = { cert: fixtures.readKey('agent1-cert.pem') }; -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const server = tls.Server(options, common.mustCall(function(socket) { server.close(); diff --git a/test/parallel/test-tls-net-connect-prefer-path.js b/test/parallel/test-tls-net-connect-prefer-path.js index 19a3ba4b37b383..263501ae0330ac 100644 --- a/test/parallel/test-tls-net-connect-prefer-path.js +++ b/test/parallel/test-tls-net-connect-prefer-path.js @@ -8,7 +8,8 @@ const fixtures = require('../common/fixtures'); if (!common.hasCrypto) common.skip('missing crypto'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const tls = require('tls'); const net = require('net'); diff --git a/test/parallel/test-tls-wrap-econnreset-pipe.js b/test/parallel/test-tls-wrap-econnreset-pipe.js index ef6efaedc34aa7..b400e35d412392 100644 --- a/test/parallel/test-tls-wrap-econnreset-pipe.js +++ b/test/parallel/test-tls-wrap-econnreset-pipe.js @@ -8,7 +8,8 @@ const assert = require('assert'); const tls = require('tls'); const net = require('net'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const server = net.createServer((c) => { c.end(); diff --git a/test/parallel/test-trace-events-all.js b/test/parallel/test-trace-events-all.js index 329f99f591244d..07c53236597220 100644 --- a/test/parallel/test-trace-events-all.js +++ b/test/parallel/test-trace-events-all.js @@ -8,8 +8,9 @@ const CODE = 'setTimeout(() => { for (var i = 0; i < 100000; i++) { "test" + i } }, 1)'; const FILE_NAME = 'node_trace.1.log'; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); const proc = cp.spawn(process.execPath, [ '--trace-events-enabled', '-e', CODE ]); diff --git a/test/parallel/test-trace-events-async-hooks.js b/test/parallel/test-trace-events-async-hooks.js index e1f78f791a636d..b15d83b07a5799 100644 --- a/test/parallel/test-trace-events-async-hooks.js +++ b/test/parallel/test-trace-events-async-hooks.js @@ -8,8 +8,9 @@ const CODE = 'setTimeout(() => { for (var i = 0; i < 100000; i++) { "test" + i } }, 1)'; const FILE_NAME = 'node_trace.1.log'; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); const proc = cp.spawn(process.execPath, [ '--trace-events-enabled', diff --git a/test/parallel/test-trace-events-binding.js b/test/parallel/test-trace-events-binding.js index 9a182821bac18e..fc4e7f99f87c1b 100644 --- a/test/parallel/test-trace-events-binding.js +++ b/test/parallel/test-trace-events-binding.js @@ -20,8 +20,9 @@ const CODE = ` `; const FILE_NAME = 'node_trace.1.log'; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); const proc = cp.spawn(process.execPath, [ '--trace-events-enabled', diff --git a/test/parallel/test-trace-events-category-used.js b/test/parallel/test-trace-events-category-used.js index 39d09ad862d787..aa0662b7493568 100644 --- a/test/parallel/test-trace-events-category-used.js +++ b/test/parallel/test-trace-events-category-used.js @@ -7,8 +7,9 @@ const CODE = `console.log( process.binding("trace_events").categoryGroupEnabled("custom") );`; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); const procEnabled = cp.spawn( process.execPath, diff --git a/test/parallel/test-trace-events-none.js b/test/parallel/test-trace-events-none.js index 9a4d587f2db0e1..7a87fc5cbd3a8d 100644 --- a/test/parallel/test-trace-events-none.js +++ b/test/parallel/test-trace-events-none.js @@ -7,8 +7,9 @@ const CODE = 'setTimeout(() => { for (var i = 0; i < 100000; i++) { "test" + i } }, 1)'; const FILE_NAME = 'node_trace.1.log'; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); const proc_no_categories = cp.spawn( process.execPath, diff --git a/test/parallel/test-trace-events-process-exit.js b/test/parallel/test-trace-events-process-exit.js index be45cb1d3e0f22..9f164ee6279720 100644 --- a/test/parallel/test-trace-events-process-exit.js +++ b/test/parallel/test-trace-events-process-exit.js @@ -4,10 +4,12 @@ const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); + const FILE_NAME = 'node_trace.1.log'; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +tmpdir.refresh(); +process.chdir(tmpdir.path); const proc = cp.spawn(process.execPath, [ '--trace-events-enabled', diff --git a/test/parallel/test-trace-events-v8.js b/test/parallel/test-trace-events-v8.js index b17b1473ecaf0c..49c34b8f17bbb2 100644 --- a/test/parallel/test-trace-events-v8.js +++ b/test/parallel/test-trace-events-v8.js @@ -8,8 +8,9 @@ const CODE = 'setTimeout(() => { for (var i = 0; i < 100000; i++) { "test" + i } }, 1)'; const FILE_NAME = 'node_trace.1.log'; -common.refreshTmpDir(); -process.chdir(common.tmpDir); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +process.chdir(tmpdir.path); const proc = cp.spawn(process.execPath, [ '--trace-events-enabled', diff --git a/test/parallel/test-zlib-from-gzip.js b/test/parallel/test-zlib-from-gzip.js index f62dd10f323adc..99c3f1757e05d8 100644 --- a/test/parallel/test-zlib-from-gzip.js +++ b/test/parallel/test-zlib-from-gzip.js @@ -29,7 +29,8 @@ const zlib = require('zlib'); const path = require('path'); const fixtures = require('../common/fixtures'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); const gunzip = zlib.createGunzip(); @@ -37,7 +38,7 @@ const fs = require('fs'); const fixture = fixtures.path('person.jpg.gz'); const unzippedFixture = fixtures.path('person.jpg'); -const outputFile = path.resolve(common.tmpDir, 'person.jpg'); +const outputFile = path.resolve(tmpdir.path, 'person.jpg'); const expect = fs.readFileSync(unzippedFixture); const inp = fs.createReadStream(fixture); const out = fs.createWriteStream(outputFile); diff --git a/test/pummel/test-fs-largefile.js b/test/pummel/test-fs-largefile.js index b0cb24a60fe4d6..786e325ce3333d 100644 --- a/test/pummel/test-fs-largefile.js +++ b/test/pummel/test-fs-largefile.js @@ -20,15 +20,16 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const filepath = path.join(common.tmpDir, 'large.txt'); +const filepath = path.join(tmpdir.path, 'large.txt'); const fd = fs.openSync(filepath, 'w+'); const offset = 5 * 1024 * 1024 * 1024; // 5GB const message = 'Large File'; diff --git a/test/pummel/test-fs-watch-file-slow.js b/test/pummel/test-fs-watch-file-slow.js index 9ae9922ec8b2d6..7b7065cffbfe64 100644 --- a/test/pummel/test-fs-watch-file-slow.js +++ b/test/pummel/test-fs-watch-file-slow.js @@ -25,7 +25,9 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -const FILENAME = path.join(common.tmpDir, 'watch-me'); +const tmpdir = require('../common/tmpdir'); + +const FILENAME = path.join(tmpdir.path, 'watch-me'); const TIMEOUT = 1300; let nevents = 0; diff --git a/test/pummel/test-fs-watch-file.js b/test/pummel/test-fs-watch-file.js index 3b036257b3b492..c893c9dfa6e268 100644 --- a/test/pummel/test-fs-watch-file.js +++ b/test/pummel/test-fs-watch-file.js @@ -25,12 +25,14 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); +const tmpdir = require('../common/tmpdir'); + let watchSeenOne = 0; let watchSeenTwo = 0; let watchSeenThree = 0; let watchSeenFour = 0; -const testDir = common.tmpDir; +const testDir = tmpdir.path; const filenameOne = 'watch.txt'; const filepathOne = path.join(testDir, filenameOne); diff --git a/test/pummel/test-fs-watch-non-recursive.js b/test/pummel/test-fs-watch-non-recursive.js index 02447cf5215e5a..2b10f9b24da746 100644 --- a/test/pummel/test-fs-watch-non-recursive.js +++ b/test/pummel/test-fs-watch-non-recursive.js @@ -24,7 +24,9 @@ const common = require('../common'); const path = require('path'); const fs = require('fs'); -const testDir = common.tmpDir; +const tmpdir = require('tmpdir'); + +const testDir = tmpdir.path; const testsubdir = path.join(testDir, 'testsubdir'); const filepath = path.join(testsubdir, 'watch.txt'); diff --git a/test/pummel/test-regress-GH-814.js b/test/pummel/test-regress-GH-814.js index a43a67fe77cc2e..a62df944863062 100644 --- a/test/pummel/test-regress-GH-814.js +++ b/test/pummel/test-regress-GH-814.js @@ -22,9 +22,11 @@ 'use strict'; // Flags: --expose_gc -const common = require('../common'); +require('../common'); const assert = require('assert'); +const tmpdir = require('../common/tmpdir'); + function newBuffer(size, value) { const buffer = Buffer.allocUnsafe(size); while (size--) { @@ -36,7 +38,7 @@ function newBuffer(size, value) { } const fs = require('fs'); -const testFileName = require('path').join(common.tmpDir, 'GH-814_testFile.txt'); +const testFileName = require('path').join(tmpdir.path, 'GH-814_testFile.txt'); const testFileFD = fs.openSync(testFileName, 'w'); console.log(testFileName); diff --git a/test/pummel/test-regress-GH-814_2.js b/test/pummel/test-regress-GH-814_2.js index 516a8727c65012..a183e082f86aa6 100644 --- a/test/pummel/test-regress-GH-814_2.js +++ b/test/pummel/test-regress-GH-814_2.js @@ -22,11 +22,12 @@ 'use strict'; // Flags: --expose_gc -const common = require('../common'); +require('../common'); const assert = require('assert'); const fs = require('fs'); -const testFileName = require('path').join(common.tmpDir, 'GH-814_test.txt'); +const tmpdir = require('../common/tmpdir'); +const testFileName = require('path').join(tmpdir.path, 'GH-814_test.txt'); const testFD = fs.openSync(testFileName, 'w'); console.error(`${testFileName}\n`); diff --git a/test/pummel/test-tls-session-timeout.js b/test/pummel/test-tls-session-timeout.js index 56fdfa16ea7eb5..49c38102fc5c5c 100644 --- a/test/pummel/test-tls-session-timeout.js +++ b/test/pummel/test-tls-session-timeout.js @@ -28,6 +28,8 @@ if (!common.opensslCli) if (!common.hasCrypto) common.skip('missing crypto'); +const tmpdir = require('../common/tmpdir'); + doTest(); // This test consists of three TLS requests -- @@ -65,7 +67,7 @@ function doTest() { const sessionFileName = (function() { const ticketFileName = 'tls-session-ticket.txt'; - const tmpPath = join(common.tmpDir, ticketFileName); + const tmpPath = join(tmpdir.path, ticketFileName); fs.writeFileSync(tmpPath, fixtures.readSync(ticketFileName)); return tmpPath; }()); diff --git a/test/sequential/test-async-wrap-getasyncid.js b/test/sequential/test-async-wrap-getasyncid.js index fa8e310540103e..79deab0a25634c 100644 --- a/test/sequential/test-async-wrap-getasyncid.js +++ b/test/sequential/test-async-wrap-getasyncid.js @@ -6,6 +6,7 @@ const fs = require('fs'); const net = require('net'); const providers = Object.assign({}, process.binding('async_wrap').Providers); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); // Make sure that all Providers are tested. { @@ -146,7 +147,7 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check } { - common.refreshTmpDir(); + tmpdir.refresh(); const server = net.createServer(common.mustCall((socket) => { server.close(); diff --git a/test/sequential/test-fs-readfile-tostring-fail.js b/test/sequential/test-fs-readfile-tostring-fail.js index c79e13daebac30..88cf7347efbfdf 100644 --- a/test/sequential/test-fs-readfile-tostring-fail.js +++ b/test/sequential/test-fs-readfile-tostring-fail.js @@ -13,9 +13,10 @@ const kStringMaxLength = process.binding('buffer').kStringMaxLength; if (common.isAIX && (Number(cp.execSync('ulimit -f')) * 512) < kStringMaxLength) common.skip('intensive toString tests due to file size confinements'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const file = path.join(common.tmpDir, 'toobig.txt'); +const file = path.join(tmpdir.path, 'toobig.txt'); const stream = fs.createWriteStream(file, { flags: 'a' }); diff --git a/test/sequential/test-fs-watch.js b/test/sequential/test-fs-watch.js index 9f1e95e8c0fbe3..31708ee6144c7d 100644 --- a/test/sequential/test-fs-watch.js +++ b/test/sequential/test-fs-watch.js @@ -26,14 +26,16 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const tmpdir = require('../common/tmpdir'); + const expectFilePath = common.isWindows || common.isLinux || common.isOSX || common.isAIX; -const testDir = common.tmpDir; +const testDir = tmpdir.path; -common.refreshTmpDir(); +tmpdir.refresh(); { const filepath = path.join(testDir, 'watch.txt'); diff --git a/test/sequential/test-http2-timeout-large-write-file.js b/test/sequential/test-http2-timeout-large-write-file.js index e32f6037eef9e3..910e7a0fc497bd 100644 --- a/test/sequential/test-http2-timeout-large-write-file.js +++ b/test/sequential/test-http2-timeout-large-write-file.js @@ -8,7 +8,8 @@ const fs = require('fs'); const http2 = require('http2'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); // This test assesses whether long-running writes can complete // or timeout because the session or stream are not aware that the @@ -29,7 +30,7 @@ let offsetTimeout = common.platformTimeout(100); let didReceiveData = false; const content = Buffer.alloc(writeSize, 0x44); -const filepath = path.join(common.tmpDir, 'http2-large-write.tmp'); +const filepath = path.join(tmpdir.path, 'http2-large-write.tmp'); fs.writeFileSync(filepath, content, 'binary'); const fd = fs.openSync(filepath, 'r'); diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index 6f40e8d8008ec3..8b097142698e6f 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -250,7 +250,8 @@ try { assert.deepStrictEqual(children, { 'common/index.js': { - 'common/fixtures.js': {} + 'common/fixtures.js': {}, + 'common/tmpdir.js': {} }, 'fixtures/not-main-module.js': {}, 'fixtures/a.js': { diff --git a/test/sequential/test-regress-GH-4027.js b/test/sequential/test-regress-GH-4027.js index 6ab6afcfd6bc2e..8936537323581e 100644 --- a/test/sequential/test-regress-GH-4027.js +++ b/test/sequential/test-regress-GH-4027.js @@ -25,9 +25,10 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const filename = path.join(common.tmpDir, 'watched'); +const filename = path.join(tmpdir.path, 'watched'); fs.writeFileSync(filename, 'quis custodiet ipsos custodes'); fs.watchFile(filename, { interval: 50 }, common.mustCall(function(curr, prev) { diff --git a/test/tick-processor/tick-processor-base.js b/test/tick-processor/tick-processor-base.js index 3017dc6bb47250..33944655258bef 100644 --- a/test/tick-processor/tick-processor-base.js +++ b/test/tick-processor/tick-processor-base.js @@ -1,12 +1,13 @@ 'use strict'; -const common = require('../common'); +require('../common'); const fs = require('fs'); const cp = require('child_process'); const path = require('path'); -common.refreshTmpDir(); +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); -const LOG_FILE = path.join(common.tmpDir, 'tick-processor.log'); +const LOG_FILE = path.join(tmpdir.path, 'tick-processor.log'); const RETRY_TIMEOUT = 150; function runTest(test) { From 1c9ab28171d02402c74613a1811ed8769c5e8702 Mon Sep 17 00:00:00 2001 From: Bryan English Date: Thu, 26 Oct 2017 16:20:45 -0700 Subject: [PATCH 021/131] test: fix flaky test-http-dns-error Under some conditions, the error received from getaddrinfo might actually be EAGAIN, meaning the request should be retried. Allowing for 5 retries before erroring out. Also replace one-off function with common.mustNotCall(). PR-URL: https://github.com/nodejs/node/pull/16534 Reviewed-By: Refael Ackermann Reviewed-By: James M Snell --- test/parallel/test-http-dns-error.js | 35 ++++++++++++++++++---------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/test/parallel/test-http-dns-error.js b/test/parallel/test-http-dns-error.js index 723b710647682b..900cf40e6b209b 100644 --- a/test/parallel/test-http-dns-error.js +++ b/test/parallel/test-http-dns-error.js @@ -30,30 +30,41 @@ const http = require('http'); const https = require('https'); const host = '*'.repeat(256); +const MAX_TRIES = 5; -function do_not_call() { - throw new Error('This function should not have been called.'); -} - -function test(mod) { - +function tryGet(mod, tries) { // Bad host name should not throw an uncatchable exception. // Ensure that there is time to attach an error listener. - const req1 = mod.get({ host: host, port: 42 }, do_not_call); - req1.on('error', common.mustCall(function(err) { + const req = mod.get({ host: host, port: 42 }, common.mustNotCall()); + req.on('error', common.mustCall(function(err) { + if (err.code === 'EAGAIN' && tries < MAX_TRIES) { + tryGet(mod, ++tries); + return; + } assert.strictEqual(err.code, 'ENOTFOUND'); })); // http.get() called req1.end() for us +} - const req2 = mod.request({ +function tryRequest(mod, tries) { + const req = mod.request({ method: 'GET', host: host, port: 42 - }, do_not_call); - req2.on('error', common.mustCall(function(err) { + }, common.mustNotCall()); + req.on('error', common.mustCall(function(err) { + if (err.code === 'EAGAIN' && tries < MAX_TRIES) { + tryRequest(mod, ++tries); + return; + } assert.strictEqual(err.code, 'ENOTFOUND'); })); - req2.end(); + req.end(); +} + +function test(mod) { + tryGet(mod, 0); + tryRequest(mod, 0); } if (common.hasCrypto) { From 16e918c67299dabaf09eeb4a47d184e8488580ad Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Tue, 24 Oct 2017 14:11:57 +1100 Subject: [PATCH 022/131] http: process headers after setting up agent Added tests to clarify the implicit behaviour of array header setting vs object header setting PR-URL: https://github.com/nodejs/node/pull/16568 Reviewed-By: James M Snell Reviewed-By: Matteo Collina --- lib/_http_client.js | 91 ++++++++++--------- .../test-http-client-headers-array.js | 60 ++++++++++++ 2 files changed, 108 insertions(+), 43 deletions(-) create mode 100644 test/parallel/test-http-client-headers-array.js diff --git a/lib/_http_client.js b/lib/_http_client.js index 2287c2751b8ce6..9dea39d0216c80 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -164,6 +164,40 @@ function ClientRequest(options, cb) { this.once('response', cb); } + if (method === 'GET' || + method === 'HEAD' || + method === 'DELETE' || + method === 'OPTIONS' || + method === 'CONNECT') { + this.useChunkedEncodingByDefault = false; + } else { + this.useChunkedEncodingByDefault = true; + } + + this._ended = false; + this.res = null; + this.aborted = undefined; + this.timeoutCb = null; + this.upgradeOrConnect = false; + this.parser = null; + this.maxHeadersCount = null; + + var called = false; + + if (this.agent) { + // If there is an agent we should default to Connection:keep-alive, + // but only if the Agent will actually reuse the connection! + // If it's not a keepAlive agent, and the maxSockets==Infinity, then + // there's never a case where this socket will actually be reused + if (!this.agent.keepAlive && !Number.isFinite(this.agent.maxSockets)) { + this._last = true; + this.shouldKeepAlive = false; + } else { + this._last = false; + this.shouldKeepAlive = true; + } + } + var headersArray = Array.isArray(options.headers); if (!headersArray) { if (options.headers) { @@ -173,6 +207,7 @@ function ClientRequest(options, cb) { this.setHeader(key, options.headers[key]); } } + if (host && !this.getHeader('host') && setHost) { var hostHeader = host; @@ -191,45 +226,25 @@ function ClientRequest(options, cb) { } this.setHeader('Host', hostHeader); } - } - if (options.auth && !this.getHeader('Authorization')) { - this.setHeader('Authorization', 'Basic ' + - Buffer.from(options.auth).toString('base64')); - } + if (options.auth && !this.getHeader('Authorization')) { + this.setHeader('Authorization', 'Basic ' + + Buffer.from(options.auth).toString('base64')); + } - if (method === 'GET' || - method === 'HEAD' || - method === 'DELETE' || - method === 'OPTIONS' || - method === 'CONNECT') { - this.useChunkedEncodingByDefault = false; - } else { - this.useChunkedEncodingByDefault = true; - } + if (this.getHeader('expect')) { + if (this._header) { + throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'render'); + } - if (headersArray) { - this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n', - options.headers); - } else if (this.getHeader('expect')) { - if (this._header) { - throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'render'); + this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n', + this[outHeadersKey]); } - + } else { this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n', - this[outHeadersKey]); + options.headers); } - this._ended = false; - this.res = null; - this.aborted = undefined; - this.timeoutCb = null; - this.upgradeOrConnect = false; - this.parser = null; - this.maxHeadersCount = null; - - var called = false; - var oncreate = (err, socket) => { if (called) return; @@ -242,18 +257,8 @@ function ClientRequest(options, cb) { this._deferToConnect(null, null, () => this._flush()); }; + // initiate connection if (this.agent) { - // If there is an agent we should default to Connection:keep-alive, - // but only if the Agent will actually reuse the connection! - // If it's not a keepAlive agent, and the maxSockets==Infinity, then - // there's never a case where this socket will actually be reused - if (!this.agent.keepAlive && !Number.isFinite(this.agent.maxSockets)) { - this._last = true; - this.shouldKeepAlive = false; - } else { - this._last = false; - this.shouldKeepAlive = true; - } this.agent.addRequest(this, options); } else { // No agent, default to Connection:close. diff --git a/test/parallel/test-http-client-headers-array.js b/test/parallel/test-http-client-headers-array.js new file mode 100644 index 00000000000000..dffe04bb108401 --- /dev/null +++ b/test/parallel/test-http-client-headers-array.js @@ -0,0 +1,60 @@ +'use strict'; + +require('../common'); + +const assert = require('assert'); +const http = require('http'); + +function execute(options) { + http.createServer(function(req, res) { + const expectHeaders = { + 'x-foo': 'boom', + cookie: 'a=1; b=2; c=3', + connection: 'close' + }; + + // no Host header when you set headers an array + if (!Array.isArray(options.headers)) { + expectHeaders.host = `localhost:${this.address().port}`; + } + + // no Authorization header when you set headers an array + if (options.auth && !Array.isArray(options.headers)) { + expectHeaders.authorization = + `Basic ${Buffer.from(options.auth).toString('base64')}`; + } + + this.close(); + + assert.deepStrictEqual(req.headers, expectHeaders); + + res.end(); + }).listen(0, function() { + options = Object.assign(options, { + port: this.address().port, + path: '/' + }); + const req = http.request(options); + req.end(); + }); +} + +// should be the same except for implicit Host header on the first two +execute({ headers: { 'x-foo': 'boom', 'cookie': 'a=1; b=2; c=3' } }); +execute({ headers: { 'x-foo': 'boom', 'cookie': [ 'a=1', 'b=2', 'c=3' ] } }); +execute({ headers: [[ 'x-foo', 'boom' ], [ 'cookie', 'a=1; b=2; c=3' ]] }); +execute({ headers: [ + [ 'x-foo', 'boom' ], [ 'cookie', [ 'a=1', 'b=2', 'c=3' ]] +] }); +execute({ headers: [ + [ 'x-foo', 'boom' ], [ 'cookie', 'a=1' ], + [ 'cookie', 'b=2' ], [ 'cookie', 'c=3'] +] }); + +// Authorization and Host header both missing from the second +execute({ auth: 'foo:bar', headers: + { 'x-foo': 'boom', 'cookie': 'a=1; b=2; c=3' } }); +execute({ auth: 'foo:bar', headers: [ + [ 'x-foo', 'boom' ], [ 'cookie', 'a=1' ], + [ 'cookie', 'b=2' ], [ 'cookie', 'c=3'] +] }); From 6d3862d8ca072073ae35eed81c6f59d1cf13f011 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Wed, 6 Dec 2017 09:03:42 +0100 Subject: [PATCH 023/131] crypto: use non-deprecated v8::Object::Set This commit updates node_crypto to use the non-deprecated Set functions that return a v8::Maybe. PR-URL: https://github.com/nodejs/node/pull/17482 Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis Reviewed-By: Ruben Bridgewater --- src/node_crypto.cc | 141 +++++++++++++++++++++++++++------------------ 1 file changed, 86 insertions(+), 55 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 68efa676f0c475..5e331a0b7ca506 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -1745,26 +1745,31 @@ void SSLWrap::OnClientHello(void* arg, Base* w = static_cast(arg); Environment* env = w->ssl_env(); HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); + Local context = env->context(); + Context::Scope context_scope(context); Local hello_obj = Object::New(env->isolate()); Local buff = Buffer::Copy( env, reinterpret_cast(hello.session_id()), hello.session_size()).ToLocalChecked(); - hello_obj->Set(env->session_id_string(), buff); + hello_obj->Set(context, env->session_id_string(), buff).FromJust(); if (hello.servername() == nullptr) { - hello_obj->Set(env->servername_string(), String::Empty(env->isolate())); + hello_obj->Set(context, + env->servername_string(), + String::Empty(env->isolate())).FromJust(); } else { Local servername = OneByteString(env->isolate(), hello.servername(), hello.servername_size()); - hello_obj->Set(env->servername_string(), servername); + hello_obj->Set(context, env->servername_string(), servername).FromJust(); } - hello_obj->Set(env->tls_ticket_string(), - Boolean::New(env->isolate(), hello.has_ticket())); - hello_obj->Set(env->ocsp_request_string(), - Boolean::New(env->isolate(), hello.ocsp_request())); + hello_obj->Set(context, + env->tls_ticket_string(), + Boolean::New(env->isolate(), hello.has_ticket())).FromJust(); + hello_obj->Set(context, + env->ocsp_request_string(), + Boolean::New(env->isolate(), hello.ocsp_request())).FromJust(); Local argv[] = { hello_obj }; w->MakeCallback(env->onclienthello_string(), arraysize(argv), argv); @@ -1809,7 +1814,7 @@ static bool SafeX509ExtPrint(BIO* out, X509_EXTENSION* ext) { static Local X509ToObject(Environment* env, X509* cert) { EscapableHandleScope scope(env->isolate()); - + Local context = env->context(); Local info = Object::New(env->isolate()); BIO* bio = BIO_new(BIO_s_mem()); @@ -1819,18 +1824,20 @@ static Local X509ToObject(Environment* env, X509* cert) { 0, X509_NAME_FLAGS) > 0) { BIO_get_mem_ptr(bio, &mem); - info->Set(env->subject_string(), + info->Set(context, env->subject_string(), String::NewFromUtf8(env->isolate(), mem->data, - String::kNormalString, mem->length)); + String::kNormalString, + mem->length)).FromJust(); } USE(BIO_reset(bio)); X509_NAME* issuer_name = X509_get_issuer_name(cert); if (X509_NAME_print_ex(bio, issuer_name, 0, X509_NAME_FLAGS) > 0) { BIO_get_mem_ptr(bio, &mem); - info->Set(env->issuer_string(), + info->Set(context, env->issuer_string(), String::NewFromUtf8(env->isolate(), mem->data, - String::kNormalString, mem->length)); + String::kNormalString, + mem->length)).FromJust(); } USE(BIO_reset(bio)); @@ -1855,9 +1862,10 @@ static Local X509ToObject(Environment* env, X509* cert) { } BIO_get_mem_ptr(bio, &mem); - info->Set(keys[i], + info->Set(context, keys[i], String::NewFromUtf8(env->isolate(), mem->data, - String::kNormalString, mem->length)); + String::kNormalString, + mem->length)).FromJust(); USE(BIO_reset(bio)); } @@ -1873,9 +1881,10 @@ static Local X509ToObject(Environment* env, X509* cert) { RSA_get0_key(rsa, &n, &e, nullptr); BN_print(bio, n); BIO_get_mem_ptr(bio, &mem); - info->Set(env->modulus_string(), + info->Set(context, env->modulus_string(), String::NewFromUtf8(env->isolate(), mem->data, - String::kNormalString, mem->length)); + String::kNormalString, + mem->length)).FromJust(); USE(BIO_reset(bio)); uint64_t exponent_word = static_cast(BN_get_word(e)); @@ -1887,9 +1896,10 @@ static Local X509ToObject(Environment* env, X509* cert) { BIO_printf(bio, "0x%x%08x", hi, lo); } BIO_get_mem_ptr(bio, &mem); - info->Set(env->exponent_string(), + info->Set(context, env->exponent_string(), String::NewFromUtf8(env->isolate(), mem->data, - String::kNormalString, mem->length)); + String::kNormalString, + mem->length)).FromJust(); USE(BIO_reset(bio)); } @@ -1904,16 +1914,18 @@ static Local X509ToObject(Environment* env, X509* cert) { ASN1_TIME_print(bio, X509_get_notBefore(cert)); BIO_get_mem_ptr(bio, &mem); - info->Set(env->valid_from_string(), + info->Set(context, env->valid_from_string(), String::NewFromUtf8(env->isolate(), mem->data, - String::kNormalString, mem->length)); + String::kNormalString, + mem->length)).FromJust(); USE(BIO_reset(bio)); ASN1_TIME_print(bio, X509_get_notAfter(cert)); BIO_get_mem_ptr(bio, &mem); - info->Set(env->valid_to_string(), + info->Set(context, env->valid_to_string(), String::NewFromUtf8(env->isolate(), mem->data, - String::kNormalString, mem->length)); + String::kNormalString, + mem->length)).FromJust(); BIO_free_all(bio); unsigned int md_size, i; @@ -1934,8 +1946,8 @@ static Local X509ToObject(Environment* env, X509* cert) { fingerprint[0] = '\0'; } - info->Set(env->fingerprint_string(), - OneByteString(env->isolate(), fingerprint)); + info->Set(context, env->fingerprint_string(), + OneByteString(env->isolate(), fingerprint)).FromJust(); } STACK_OF(ASN1_OBJECT)* eku = static_cast( @@ -1947,18 +1959,20 @@ static Local X509ToObject(Environment* env, X509* cert) { int j = 0; for (int i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { if (OBJ_obj2txt(buf, sizeof(buf), sk_ASN1_OBJECT_value(eku, i), 1) >= 0) - ext_key_usage->Set(j++, OneByteString(env->isolate(), buf)); + ext_key_usage->Set(context, + j++, + OneByteString(env->isolate(), buf)).FromJust(); } sk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free); - info->Set(env->ext_key_usage_string(), ext_key_usage); + info->Set(context, env->ext_key_usage_string(), ext_key_usage).FromJust(); } if (ASN1_INTEGER* serial_number = X509_get_serialNumber(cert)) { if (BIGNUM* bn = ASN1_INTEGER_to_BN(serial_number, nullptr)) { if (char* buf = BN_bn2hex(bn)) { - info->Set(env->serial_number_string(), - OneByteString(env->isolate(), buf)); + info->Set(context, env->serial_number_string(), + OneByteString(env->isolate(), buf)).FromJust(); OPENSSL_free(buf); } BN_free(bn); @@ -1971,7 +1985,7 @@ static Local X509ToObject(Environment* env, X509* cert) { unsigned char* serialized = reinterpret_cast( Buffer::Data(buff)); i2d_X509(cert, &serialized); - info->Set(env->raw_string(), buff); + info->Set(context, env->raw_string(), buff).FromJust(); return scope.Escape(info); } @@ -1984,6 +1998,7 @@ void SSLWrap::GetPeerCertificate( Base* w; ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->ssl_env(); + Local context = env->context(); ClearErrorOnReturn clear_error_on_return; @@ -2035,7 +2050,7 @@ void SSLWrap::GetPeerCertificate( continue; Local ca_info = X509ToObject(env, ca); - info->Set(env->issuercert_string(), ca_info); + info->Set(context, env->issuercert_string(), ca_info).FromJust(); info = ca_info; // NOTE: Intentionally freeing cert that is not used anymore @@ -2058,7 +2073,7 @@ void SSLWrap::GetPeerCertificate( break; Local ca_info = X509ToObject(env, ca); - info->Set(env->issuercert_string(), ca_info); + info->Set(context, env->issuercert_string(), ca_info).FromJust(); info = ca_info; // NOTE: Intentionally freeing cert that is not used anymore @@ -2070,7 +2085,7 @@ void SSLWrap::GetPeerCertificate( // Self-issued certificate if (X509_check_issued(cert, cert) == X509_V_OK) - info->Set(env->issuercert_string(), info); + info->Set(context, env->issuercert_string(), info).FromJust(); CHECK_NE(cert, nullptr); @@ -2266,6 +2281,7 @@ void SSLWrap::GetEphemeralKeyInfo( Base* w; ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = Environment::GetCurrent(args); + Local context = env->context(); CHECK_NE(w->ssl_, nullptr); @@ -2280,22 +2296,24 @@ void SSLWrap::GetEphemeralKeyInfo( if (SSL_get_server_tmp_key(w->ssl_, &key)) { switch (EVP_PKEY_id(key)) { case EVP_PKEY_DH: - info->Set(env->type_string(), - FIXED_ONE_BYTE_STRING(env->isolate(), "DH")); - info->Set(env->size_string(), - Integer::New(env->isolate(), EVP_PKEY_bits(key))); + info->Set(context, env->type_string(), + FIXED_ONE_BYTE_STRING(env->isolate(), "DH")).FromJust(); + info->Set(context, env->size_string(), + Integer::New(env->isolate(), EVP_PKEY_bits(key))).FromJust(); break; case EVP_PKEY_EC: { EC_KEY* ec = EVP_PKEY_get1_EC_KEY(key); int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); EC_KEY_free(ec); - info->Set(env->type_string(), - FIXED_ONE_BYTE_STRING(env->isolate(), "ECDH")); - info->Set(env->name_string(), - OneByteString(args.GetIsolate(), OBJ_nid2sn(nid))); - info->Set(env->size_string(), - Integer::New(env->isolate(), EVP_PKEY_bits(key))); + info->Set(context, env->type_string(), + FIXED_ONE_BYTE_STRING(env->isolate(), "ECDH")).FromJust(); + info->Set(context, env->name_string(), + OneByteString(args.GetIsolate(), + OBJ_nid2sn(nid))).FromJust(); + info->Set(context, env->size_string(), + Integer::New(env->isolate(), + EVP_PKEY_bits(key))).FromJust(); } } EVP_PKEY_free(key); @@ -2388,7 +2406,8 @@ void SSLWrap::VerifyError(const FunctionCallbackInfo& args) { Local reason_string = OneByteString(isolate, reason); Local exception_value = Exception::Error(reason_string); Local exception_object = exception_value->ToObject(isolate); - exception_object->Set(w->env()->code_string(), OneByteString(isolate, code)); + exception_object->Set(w->env()->context(), w->env()->code_string(), + OneByteString(isolate, code)).FromJust(); args.GetReturnValue().Set(exception_object); } @@ -2398,6 +2417,7 @@ void SSLWrap::GetCurrentCipher(const FunctionCallbackInfo& args) { Base* w; ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->ssl_env(); + Local context = env->context(); const SSL_CIPHER* c = SSL_get_current_cipher(w->ssl_); if (c == nullptr) @@ -2405,9 +2425,10 @@ void SSLWrap::GetCurrentCipher(const FunctionCallbackInfo& args) { Local info = Object::New(env->isolate()); const char* cipher_name = SSL_CIPHER_get_name(c); - info->Set(env->name_string(), OneByteString(args.GetIsolate(), cipher_name)); - info->Set(env->version_string(), - OneByteString(args.GetIsolate(), "TLSv1/SSLv3")); + info->Set(context, env->name_string(), + OneByteString(args.GetIsolate(), cipher_name)).FromJust(); + info->Set(context, env->version_string(), + OneByteString(args.GetIsolate(), "TLSv1/SSLv3")).FromJust(); args.GetReturnValue().Set(info); } @@ -2716,19 +2737,22 @@ int SSLWrap::SSLCertCallback(SSL* s, void* arg) { return -1; Environment* env = w->env(); + Local context = env->context(); HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); + Context::Scope context_scope(context); w->cert_cb_running_ = true; Local info = Object::New(env->isolate()); const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); if (servername == nullptr) { - info->Set(env->servername_string(), String::Empty(env->isolate())); + info->Set(context, + env->servername_string(), + String::Empty(env->isolate())).FromJust(); } else { Local str = OneByteString(env->isolate(), servername, strlen(servername)); - info->Set(env->servername_string(), str); + info->Set(context, env->servername_string(), str).FromJust(); } bool ocsp = false; @@ -2736,7 +2760,8 @@ int SSLWrap::SSLCertCallback(SSL* s, void* arg) { ocsp = SSL_get_tlsext_status_type(s) == TLSEXT_STATUSTYPE_ocsp; #endif - info->Set(env->ocsp_request_string(), Boolean::New(env->isolate(), ocsp)); + info->Set(context, env->ocsp_request_string(), + Boolean::New(env->isolate(), ocsp)).FromJust(); Local argv[] = { info }; w->MakeCallback(env->oncertcb_string(), arraysize(argv), argv); @@ -5653,7 +5678,7 @@ void PBKDF2(const FunctionCallbackInfo& args) { keylen)); if (args[5]->IsFunction()) { - obj->Set(env->ondone_string(), args[5]); + obj->Set(env->context(), env->ondone_string(), args[5]).FromJust(); uv_queue_work(env->event_loop(), req.release()->work_req(), @@ -5841,7 +5866,7 @@ void RandomBytes(const FunctionCallbackInfo& args) { RandomBytesRequest::FREE_DATA)); if (args[1]->IsFunction()) { - obj->Set(env->ondone_string(), args[1]); + obj->Set(env->context(), env->ondone_string(), args[1]).FromJust(); uv_queue_work(env->event_loop(), req.release()->work_req(), @@ -5910,7 +5935,10 @@ void GetSSLCiphers(const FunctionCallbackInfo& args) { for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) { const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i); - arr->Set(i, OneByteString(args.GetIsolate(), SSL_CIPHER_get_name(cipher))); + arr->Set(env->context(), + i, + OneByteString(args.GetIsolate(), + SSL_CIPHER_get_name(cipher))).FromJust(); } SSL_free(ssl); @@ -5973,7 +6001,10 @@ void GetCurves(const FunctionCallbackInfo& args) { if (EC_get_builtin_curves(curves, num_curves)) { for (size_t i = 0; i < num_curves; i++) { - arr->Set(i, OneByteString(env->isolate(), OBJ_nid2sn(curves[i].nid))); + arr->Set(env->context(), + i, + OneByteString(env->isolate(), + OBJ_nid2sn(curves[i].nid))).FromJust(); } } From f023d58f089e9bd7c41ccf45e13f4f0c33e58301 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:14:21 +0100 Subject: [PATCH 024/131] benchmark: fix platform in basename-win32 It should say `win32` and not `posix`. PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/path/basename-win32.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark/path/basename-win32.js b/benchmark/path/basename-win32.js index 8a66f56d6e3295..937dc6f6948c5d 100644 --- a/benchmark/path/basename-win32.js +++ b/benchmark/path/basename-win32.js @@ -1,6 +1,6 @@ 'use strict'; const common = require('../common.js'); -const { posix } = require('path'); +const { win32 } = require('path'); const bench = common.createBenchmark(main, { pathext: [ @@ -28,7 +28,7 @@ function main({ n, pathext }) { bench.start(); for (var i = 0; i < n; i++) { - posix.basename(pathext, ext); + win32.basename(pathext, ext); } bench.end(n); } From 0ac2a9d337fb2387d3d00bf14f0298f9f13e4d1f Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:15:59 +0100 Subject: [PATCH 025/131] benchmark: fix variables not being set Due to the destructuring the outer variables were not set anymore. PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/tls/tls-connect.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/benchmark/tls/tls-connect.js b/benchmark/tls/tls-connect.js index 67f2d5f8a932e0..da0f5e08d5e6db 100644 --- a/benchmark/tls/tls-connect.js +++ b/benchmark/tls/tls-connect.js @@ -11,12 +11,13 @@ const bench = common.createBenchmark(main, { var clientConn = 0; var serverConn = 0; -var server; var dur; var concurrency; var running = true; -function main({ dur, concurrency }) { +function main(conf) { + dur = conf.dur; + concurrency = conf.concurrency; const cert_dir = path.resolve(__dirname, '../../test/fixtures'); const options = { key: fs.readFileSync(`${cert_dir}/test_key.pem`), @@ -25,7 +26,7 @@ function main({ dur, concurrency }) { ciphers: 'AES256-GCM-SHA384' }; - server = tls.createServer(options, onConnection); + const server = tls.createServer(options, onConnection); server.listen(common.PORT, onListening); } From d20e5241e8d6c948b4c9c2bb09604495a56d9108 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:17:21 +0100 Subject: [PATCH 026/131] benchmark: (assert) refactor PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/assert/deepequal-buffer.js | 45 +++--------- benchmark/assert/deepequal-map.js | 2 +- benchmark/assert/deepequal-object.js | 44 +++--------- .../deepequal-prims-and-objs-big-array-set.js | 69 ++++++------------- .../deepequal-prims-and-objs-big-loop.js | 45 +++--------- benchmark/assert/deepequal-set.js | 2 +- benchmark/assert/deepequal-typedarrays.js | 44 +++--------- 7 files changed, 56 insertions(+), 195 deletions(-) diff --git a/benchmark/assert/deepequal-buffer.js b/benchmark/assert/deepequal-buffer.js index 0e7494544d3387..9556a81ec3b151 100644 --- a/benchmark/assert/deepequal-buffer.js +++ b/benchmark/assert/deepequal-buffer.js @@ -14,8 +14,6 @@ const bench = common.createBenchmark(main, { }); function main({ len, n, method }) { - var i; - const data = Buffer.allocUnsafe(len + 1); const actual = Buffer.alloc(len); const expected = Buffer.alloc(len); @@ -24,40 +22,13 @@ function main({ len, n, method }) { data.copy(expected); data.copy(expectedWrong); - switch (method) { - case '': - // Empty string falls through to next line as default, mostly for tests. - case 'deepEqual': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.deepEqual(actual, expected); - } - bench.end(n); - break; - case 'deepStrictEqual': - bench.start(); - for (i = 0; i < n; ++i) { - assert.deepStrictEqual(actual, expected); - } - bench.end(n); - break; - case 'notDeepEqual': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.notDeepEqual(actual, expectedWrong); - } - bench.end(n); - break; - case 'notDeepStrictEqual': - bench.start(); - for (i = 0; i < n; ++i) { - assert.notDeepStrictEqual(actual, expectedWrong); - } - bench.end(n); - break; - default: - throw new Error('Unsupported method'); + // eslint-disable-next-line no-restricted-properties + const fn = method !== '' ? assert[method] : assert.deepEqual; + const value2 = method.includes('not') ? expectedWrong : expected; + + bench.start(); + for (var i = 0; i < n; ++i) { + fn(actual, value2); } + bench.end(n); } diff --git a/benchmark/assert/deepequal-map.js b/benchmark/assert/deepequal-map.js index 085274e8bfb943..bdd3c5c6b8c514 100644 --- a/benchmark/assert/deepequal-map.js +++ b/benchmark/assert/deepequal-map.js @@ -117,6 +117,6 @@ function main({ n, len, method }) { benchmark(assert.notDeepEqual, n, values, values2); break; default: - throw new Error('Unsupported method'); + throw new Error(`Unsupported method ${method}`); } } diff --git a/benchmark/assert/deepequal-object.js b/benchmark/assert/deepequal-object.js index 2c2549d58485fc..4c95006b3b8bc7 100644 --- a/benchmark/assert/deepequal-object.js +++ b/benchmark/assert/deepequal-object.js @@ -28,47 +28,19 @@ function createObj(source, add = '') { function main({ size, n, method }) { // TODO: Fix this "hack". `n` should not be manipulated. n = n / size; - var i; const source = Array.apply(null, Array(size)); const actual = createObj(source); const expected = createObj(source); const expectedWrong = createObj(source, '4'); - switch (method) { - case '': - // Empty string falls through to next line as default, mostly for tests. - case 'deepEqual': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.deepEqual(actual, expected); - } - bench.end(n); - break; - case 'deepStrictEqual': - bench.start(); - for (i = 0; i < n; ++i) { - assert.deepStrictEqual(actual, expected); - } - bench.end(n); - break; - case 'notDeepEqual': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.notDeepEqual(actual, expectedWrong); - } - bench.end(n); - break; - case 'notDeepStrictEqual': - bench.start(); - for (i = 0; i < n; ++i) { - assert.notDeepStrictEqual(actual, expectedWrong); - } - bench.end(n); - break; - default: - throw new Error('Unsupported method'); + // eslint-disable-next-line no-restricted-properties + const fn = method !== '' ? assert[method] : assert.deepEqual; + const value2 = method.includes('not') ? expectedWrong : expected; + + bench.start(); + for (var i = 0; i < n; ++i) { + fn(actual, value2); } + bench.end(n); } diff --git a/benchmark/assert/deepequal-prims-and-objs-big-array-set.js b/benchmark/assert/deepequal-prims-and-objs-big-array-set.js index 04802a76928cb2..90dbf1059361a5 100644 --- a/benchmark/assert/deepequal-prims-and-objs-big-array-set.js +++ b/benchmark/assert/deepequal-prims-and-objs-big-array-set.js @@ -30,12 +30,19 @@ const bench = common.createBenchmark(main, { ] }); +function run(fn, n, actual, expected) { + bench.start(); + for (var i = 0; i < n; ++i) { + fn(actual, expected); + } + bench.end(n); +} + function main({ n, len, primitive, method }) { const prim = primValues[primitive]; const actual = []; const expected = []; const expectedWrong = []; - var i; for (var x = 0; x < len; x++) { actual.push(prim); @@ -51,69 +58,37 @@ function main({ n, len, primitive, method }) { const expectedWrongSet = new Set(expectedWrong); switch (method) { + // Empty string falls through to next line as default, mostly for tests. case '': - // Empty string falls through to next line as default, mostly for tests. case 'deepEqual_Array': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.deepEqual(actual, expected); - } - bench.end(n); + // eslint-disable-next-line no-restricted-properties + run(assert.deepEqual, n, actual, expected); break; case 'deepStrictEqual_Array': - bench.start(); - for (i = 0; i < n; ++i) { - assert.deepStrictEqual(actual, expected); - } - bench.end(n); + run(assert.deepStrictEqual, n, actual, expected); break; case 'notDeepEqual_Array': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.notDeepEqual(actual, expectedWrong); - } - bench.end(n); + // eslint-disable-next-line no-restricted-properties + run(assert.notDeepEqual, n, actual, expectedWrong); break; case 'notDeepStrictEqual_Array': - bench.start(); - for (i = 0; i < n; ++i) { - assert.notDeepStrictEqual(actual, expectedWrong); - } - bench.end(n); + run(assert.notDeepStrictEqual, n, actual, expectedWrong); break; case 'deepEqual_Set': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.deepEqual(actualSet, expectedSet); - } - bench.end(n); + // eslint-disable-next-line no-restricted-properties + run(assert.deepEqual, n, actualSet, expectedSet); break; case 'deepStrictEqual_Set': - bench.start(); - for (i = 0; i < n; ++i) { - assert.deepStrictEqual(actualSet, expectedSet); - } - bench.end(n); + run(assert.deepStrictEqual, n, actualSet, expectedSet); break; case 'notDeepEqual_Set': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.notDeepEqual(actualSet, expectedWrongSet); - } - bench.end(n); + // eslint-disable-next-line no-restricted-properties + run(assert.notDeepEqual, n, actualSet, expectedWrongSet); break; case 'notDeepStrictEqual_Set': - bench.start(); - for (i = 0; i < n; ++i) { - assert.notDeepStrictEqual(actualSet, expectedWrongSet); - } - bench.end(n); + run(assert.notDeepStrictEqual, n, actualSet, expectedWrongSet); break; default: - throw new Error('Unsupported method'); + throw new Error(`Unsupported method "${method}"`); } } diff --git a/benchmark/assert/deepequal-prims-and-objs-big-loop.js b/benchmark/assert/deepequal-prims-and-objs-big-loop.js index 09797dfaf2df21..ec51201d51839d 100644 --- a/benchmark/assert/deepequal-prims-and-objs-big-loop.js +++ b/benchmark/assert/deepequal-prims-and-objs-big-loop.js @@ -29,43 +29,14 @@ function main({ n, primitive, method }) { const actual = prim; const expected = prim; const expectedWrong = 'b'; - var i; - // Creates new array to avoid loop invariant code motion - switch (method) { - case '': - // Empty string falls through to next line as default, mostly for tests. - case 'deepEqual': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.deepEqual([actual], [expected]); - } - bench.end(n); - break; - case 'deepStrictEqual': - bench.start(); - for (i = 0; i < n; ++i) { - assert.deepStrictEqual([actual], [expected]); - } - bench.end(n); - break; - case 'notDeepEqual': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.notDeepEqual([actual], [expectedWrong]); - } - bench.end(n); - break; - case 'notDeepStrictEqual': - bench.start(); - for (i = 0; i < n; ++i) { - assert.notDeepStrictEqual([actual], [expectedWrong]); - } - bench.end(n); - break; - default: - throw new Error('Unsupported method'); + // eslint-disable-next-line no-restricted-properties + const fn = method !== '' ? assert[method] : assert.deepEqual; + const value2 = method.includes('not') ? expectedWrong : expected; + + bench.start(); + for (var i = 0; i < n; ++i) { + fn([actual], [value2]); } + bench.end(n); } diff --git a/benchmark/assert/deepequal-set.js b/benchmark/assert/deepequal-set.js index ebcf33cc6d5254..e70ddf10e93626 100644 --- a/benchmark/assert/deepequal-set.js +++ b/benchmark/assert/deepequal-set.js @@ -126,6 +126,6 @@ function main({ n, len, method }) { benchmark(assert.notDeepEqual, n, values, values2); break; default: - throw new Error('Unsupported method'); + throw new Error(`Unsupported method "${method}"`); } } diff --git a/benchmark/assert/deepequal-typedarrays.js b/benchmark/assert/deepequal-typedarrays.js index 01546801ff3004..50e6e525b20a0c 100644 --- a/benchmark/assert/deepequal-typedarrays.js +++ b/benchmark/assert/deepequal-typedarrays.js @@ -31,42 +31,14 @@ function main({ type, n, len, method }) { const expectedWrong = Buffer.alloc(len); const wrongIndex = Math.floor(len / 2); expectedWrong[wrongIndex] = 123; - var i; - switch (method) { - case '': - // Empty string falls through to next line as default, mostly for tests. - case 'deepEqual': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.deepEqual(actual, expected); - } - bench.end(n); - break; - case 'deepStrictEqual': - bench.start(); - for (i = 0; i < n; ++i) { - assert.deepStrictEqual(actual, expected); - } - bench.end(n); - break; - case 'notDeepEqual': - bench.start(); - for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-properties - assert.notDeepEqual(actual, expectedWrong); - } - bench.end(n); - break; - case 'notDeepStrictEqual': - bench.start(); - for (i = 0; i < n; ++i) { - assert.notDeepStrictEqual(actual, expectedWrong); - } - bench.end(n); - break; - default: - throw new Error('Unsupported method'); + // eslint-disable-next-line no-restricted-properties + const fn = method !== '' ? assert[method] : assert.deepEqual; + const value2 = method.includes('not') ? expectedWrong : expected; + + bench.start(); + for (var i = 0; i < n; ++i) { + fn(actual, value2); } + bench.end(n); } From 4f09f08618c252ab6763916932f7580d6e5775a4 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:17:39 +0100 Subject: [PATCH 027/131] benchmark: (buffer) refactor PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/buffers/buffer-bytelength.js | 3 +- benchmark/buffers/buffer-compare-offset.js | 12 ++---- benchmark/buffers/buffer-creation.js | 43 ++++++++-------------- benchmark/buffers/buffer-hex.js | 5 ++- benchmark/buffers/buffer-iterate.js | 18 +++------ benchmark/buffers/buffer-read-float.js | 23 +++++------- benchmark/buffers/buffer-read.js | 12 ++---- benchmark/buffers/buffer-write.js | 31 ++++++---------- benchmark/buffers/buffer_zero.js | 9 ++--- 9 files changed, 56 insertions(+), 100 deletions(-) diff --git a/benchmark/buffers/buffer-bytelength.js b/benchmark/buffers/buffer-bytelength.js index 0617b4feb3f140..fa8852a233ea88 100644 --- a/benchmark/buffers/buffer-bytelength.js +++ b/benchmark/buffers/buffer-bytelength.js @@ -17,10 +17,9 @@ const chars = [ function main({ n, len, encoding }) { var strings = []; - var results; + var results = [ len * 16 ]; if (encoding === 'buffer') { strings = [ Buffer.alloc(len * 16, 'a') ]; - results = [ len * 16 ]; } else { for (const string of chars) { // Strings must be built differently, depending on encoding diff --git a/benchmark/buffers/buffer-compare-offset.js b/benchmark/buffers/buffer-compare-offset.js index 850fe11d3f429e..551fcd2f0cec37 100644 --- a/benchmark/buffers/buffer-compare-offset.js +++ b/benchmark/buffers/buffer-compare-offset.js @@ -8,26 +8,22 @@ const bench = common.createBenchmark(main, { }); function compareUsingSlice(b0, b1, len, iter) { - var i; - bench.start(); - for (i = 0; i < iter; i++) + for (var i = 0; i < iter; i++) Buffer.compare(b0.slice(1, len), b1.slice(1, len)); - bench.end(iter / 1e6); } function compareUsingOffset(b0, b1, len, iter) { - var i; - bench.start(); - for (i = 0; i < iter; i++) + for (var i = 0; i < iter; i++) b0.compare(b1, 1, len, 1, len); - bench.end(iter / 1e6); } function main({ millions, size, method }) { const iter = millions * 1e6; const fn = method === 'slice' ? compareUsingSlice : compareUsingOffset; + bench.start(); fn(Buffer.alloc(size, 'a'), Buffer.alloc(size, 'b'), size >> 1, iter); + bench.end(millions); } diff --git a/benchmark/buffers/buffer-creation.js b/benchmark/buffers/buffer-creation.js index 73e620955e91db..a7b340131eb8aa 100644 --- a/benchmark/buffers/buffer-creation.js +++ b/benchmark/buffers/buffer-creation.js @@ -16,51 +16,38 @@ const bench = common.createBenchmark(main, { }); function main({ len, n, type }) { + let fn, i; switch (type) { case '': case 'fast-alloc': - bench.start(); - for (let i = 0; i < n * 1024; i++) { - Buffer.alloc(len); - } - bench.end(n); + fn = Buffer.alloc; break; case 'fast-alloc-fill': bench.start(); - for (let i = 0; i < n * 1024; i++) { + for (i = 0; i < n * 1024; i++) { Buffer.alloc(len, 0); } bench.end(n); - break; + return; case 'fast-allocUnsafe': - bench.start(); - for (let i = 0; i < n * 1024; i++) { - Buffer.allocUnsafe(len); - } - bench.end(n); + fn = Buffer.allocUnsafe; break; case 'slow-allocUnsafe': - bench.start(); - for (let i = 0; i < n * 1024; i++) { - Buffer.allocUnsafeSlow(len); - } - bench.end(n); + fn = Buffer.allocUnsafeSlow; break; case 'slow': - bench.start(); - for (let i = 0; i < n * 1024; i++) { - SlowBuffer(len); - } - bench.end(n); + fn = SlowBuffer; break; case 'buffer()': - bench.start(); - for (let i = 0; i < n * 1024; i++) { - Buffer(len); - } - bench.end(n); + fn = Buffer; break; default: - assert.fail(null, null, 'Should not get here'); + assert.fail('Should not get here'); + } + + bench.start(); + for (i = 0; i < n * 1024; i++) { + fn(len); } + bench.end(n); } diff --git a/benchmark/buffers/buffer-hex.js b/benchmark/buffers/buffer-hex.js index 1bdef81139ffe7..4d87313961aa67 100644 --- a/benchmark/buffers/buffer-hex.js +++ b/benchmark/buffers/buffer-hex.js @@ -9,15 +9,16 @@ const bench = common.createBenchmark(main, { function main({ len, n }) { const buf = Buffer.alloc(len); + var i; - for (let i = 0; i < buf.length; i++) + for (i = 0; i < buf.length; i++) buf[i] = i & 0xff; const hex = buf.toString('hex'); bench.start(); - for (let i = 0; i < n; i += 1) + for (i = 0; i < n; i += 1) Buffer.from(hex, 'hex'); bench.end(n); diff --git a/benchmark/buffers/buffer-iterate.js b/benchmark/buffers/buffer-iterate.js index 8531e1cae82115..7a275b0bcb8182 100644 --- a/benchmark/buffers/buffer-iterate.js +++ b/benchmark/buffers/buffer-iterate.js @@ -20,36 +20,30 @@ function main({ size, type, method, n }) { const clazz = type === 'fast' ? Buffer : SlowBuffer; const buffer = new clazz(size); buffer.fill(0); - methods[method || 'for'](buffer, n); -} - + const fn = methods[method || 'for']; -function benchFor(buffer, n) { bench.start(); + fn(buffer, n); + bench.end(n); +} +function benchFor(buffer, n) { for (var k = 0; k < n; k++) { for (var i = 0; i < buffer.length; i++) { assert(buffer[i] === 0); } } - - bench.end(n); } function benchForOf(buffer, n) { - bench.start(); - for (var k = 0; k < n; k++) { for (const b of buffer) { assert(b === 0); } } - bench.end(n); } function benchIterator(buffer, n) { - bench.start(); - for (var k = 0; k < n; k++) { const iter = buffer[Symbol.iterator](); var cur = iter.next(); @@ -60,6 +54,4 @@ function benchIterator(buffer, n) { } } - - bench.end(n); } diff --git a/benchmark/buffers/buffer-read-float.js b/benchmark/buffers/buffer-read-float.js index 5dda2486c6711a..afd9edf5578308 100644 --- a/benchmark/buffers/buffer-read-float.js +++ b/benchmark/buffers/buffer-read-float.js @@ -9,12 +9,10 @@ const bench = common.createBenchmark(main, { millions: [1] }); -function main(conf) { - const noAssert = conf.noAssert === 'true'; - const len = +conf.millions * 1e6; +function main({ noAssert, millions, type, endian, value }) { + noAssert = noAssert === 'true'; + type = type || 'Double'; const buff = Buffer.alloc(8); - const type = conf.type || 'Double'; - const endian = conf.endian; const fn = `read${type}${endian}`; const values = { Double: { @@ -32,15 +30,12 @@ function main(conf) { nan: NaN, }, }; - const value = values[type][conf.value]; - buff[`write${type}${endian}`](value, 0, noAssert); - const testFunction = new Function('buff', ` - for (var i = 0; i !== ${len}; i++) { - buff.${fn}(0, ${JSON.stringify(noAssert)}); - } - `); + buff[`write${type}${endian}`](values[type][value], 0, noAssert); + bench.start(); - testFunction(buff); - bench.end(len / 1e6); + for (var i = 0; i !== millions * 1e6; i++) { + buff[fn](0, noAssert); + } + bench.end(millions); } diff --git a/benchmark/buffers/buffer-read.js b/benchmark/buffers/buffer-read.js index 41e842f3123623..868f5cede8bd2d 100644 --- a/benchmark/buffers/buffer-read.js +++ b/benchmark/buffers/buffer-read.js @@ -27,18 +27,14 @@ const bench = common.createBenchmark(main, { function main({ noAssert, millions, buf, type }) { noAssert = noAssert === 'true'; - const len = millions * 1e6; const clazz = buf === 'fast' ? Buffer : require('buffer').SlowBuffer; const buff = new clazz(8); const fn = `read${type || 'UInt8'}`; buff.writeDoubleLE(0, 0, noAssert); - const testFunction = new Function('buff', ` - for (var i = 0; i !== ${len}; i++) { - buff.${fn}(0, ${JSON.stringify(noAssert)}); - } - `); bench.start(); - testFunction(buff); - bench.end(len / 1e6); + for (var i = 0; i !== millions * 1e6; i++) { + buff[fn](0, noAssert); + } + bench.end(millions); } diff --git a/benchmark/buffers/buffer-write.js b/benchmark/buffers/buffer-write.js index ce2fbe3103cb83..823e95bf15d704 100644 --- a/benchmark/buffers/buffer-write.js +++ b/benchmark/buffers/buffer-write.js @@ -46,36 +46,29 @@ const mod = { }; function main({ noAssert, millions, buf, type }) { - const len = millions * 1e6; const clazz = buf === 'fast' ? Buffer : require('buffer').SlowBuffer; const buff = new clazz(8); const fn = `write${type || 'UInt8'}`; if (/Int/.test(fn)) - benchInt(buff, fn, len, noAssert); + benchInt(buff, fn, millions, noAssert); else - benchFloat(buff, fn, len, noAssert); + benchFloat(buff, fn, millions, noAssert); } -function benchInt(buff, fn, len, noAssert) { +function benchInt(buff, fn, millions, noAssert) { const m = mod[fn]; - const testFunction = new Function('buff', ` - for (var i = 0; i !== ${len}; i++) { - buff.${fn}(i & ${m}, 0, ${noAssert}); - } - `); bench.start(); - testFunction(buff); - bench.end(len / 1e6); + for (var i = 0; i !== millions * 1e6; i++) { + buff[fn](i & m, 0, noAssert); + } + bench.end(millions); } -function benchFloat(buff, fn, len, noAssert) { - const testFunction = new Function('buff', ` - for (var i = 0; i !== ${len}; i++) { - buff.${fn}(i, 0, ${noAssert}); - } - `); +function benchFloat(buff, fn, millions, noAssert) { bench.start(); - testFunction(buff); - bench.end(len / 1e6); + for (var i = 0; i !== millions * 1e6; i++) { + buff[fn](i, 0, noAssert); + } + bench.end(millions); } diff --git a/benchmark/buffers/buffer_zero.js b/benchmark/buffers/buffer_zero.js index 06b68c313f1241..1263732dce8e43 100644 --- a/benchmark/buffers/buffer_zero.js +++ b/benchmark/buffers/buffer_zero.js @@ -11,12 +11,9 @@ const zeroBuffer = Buffer.alloc(0); const zeroString = ''; function main({ n, type }) { - bench.start(); - - if (type === 'buffer') - for (let i = 0; i < n * 1024; i++) Buffer.from(zeroBuffer); - else if (type === 'string') - for (let i = 0; i < n * 1024; i++) Buffer.from(zeroString); + const data = type === 'buffer' ? zeroBuffer : zeroString; + bench.start(); + for (var i = 0; i < n * 1024; i++) Buffer.from(data); bench.end(n); } From 3d205a3e8eb52b646c711f809d5683b3f57d4b2f Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:17:56 +0100 Subject: [PATCH 028/131] benchmark: (crypto) refactor PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/crypto/aes-gcm-throughput.js | 8 ++++---- benchmark/crypto/cipher-stream.js | 19 +++++++++---------- benchmark/crypto/get-ciphers.js | 6 ++---- benchmark/crypto/hash-stream-creation.js | 15 +++++++-------- benchmark/crypto/hash-stream-throughput.js | 15 +++++++-------- .../crypto/rsa-encrypt-decrypt-throughput.js | 6 +++--- .../crypto/rsa-sign-verify-throughput.js | 6 +++--- 7 files changed, 35 insertions(+), 40 deletions(-) diff --git a/benchmark/crypto/aes-gcm-throughput.js b/benchmark/crypto/aes-gcm-throughput.js index 246455de78ad88..5c1e71e7280575 100644 --- a/benchmark/crypto/aes-gcm-throughput.js +++ b/benchmark/crypto/aes-gcm-throughput.js @@ -8,13 +8,13 @@ const bench = common.createBenchmark(main, { len: [1024, 4 * 1024, 16 * 1024, 64 * 1024, 256 * 1024, 1024 * 1024] }); -function main(conf) { - const message = Buffer.alloc(conf.len, 'b'); - const key = crypto.randomBytes(keylen[conf.cipher]); +function main({ n, len, cipher }) { + const message = Buffer.alloc(len, 'b'); + const key = crypto.randomBytes(keylen[cipher]); const iv = crypto.randomBytes(12); const associate_data = Buffer.alloc(16, 'z'); bench.start(); - AEAD_Bench(conf.cipher, message, associate_data, key, iv, conf.n, conf.len); + AEAD_Bench(cipher, message, associate_data, key, iv, n, len); } function AEAD_Bench(cipher, message, associate_data, key, iv, n, len) { diff --git a/benchmark/crypto/cipher-stream.js b/benchmark/crypto/cipher-stream.js index ca36bd736d9aea..64f6ff7b7292be 100644 --- a/benchmark/crypto/cipher-stream.js +++ b/benchmark/crypto/cipher-stream.js @@ -9,8 +9,7 @@ const bench = common.createBenchmark(main, { api: ['legacy', 'stream'] }); -function main(conf) { - var api = conf.api; +function main({ api, cipher, type, len, writes }) { if (api === 'stream' && /^v0\.[0-8]\./.test(process.version)) { console.error('Crypto streams not available until v0.10'); // use the legacy, just so that we can compare them. @@ -33,25 +32,25 @@ function main(conf) { // alice_secret and bob_secret should be the same assert(alice_secret === bob_secret); - const alice_cipher = crypto.createCipher(conf.cipher, alice_secret); - const bob_cipher = crypto.createDecipher(conf.cipher, bob_secret); + const alice_cipher = crypto.createCipher(cipher, alice_secret); + const bob_cipher = crypto.createDecipher(cipher, bob_secret); var message; var encoding; - switch (conf.type) { + switch (type) { case 'asc': - message = 'a'.repeat(conf.len); + message = 'a'.repeat(len); encoding = 'ascii'; break; case 'utf': - message = 'ü'.repeat(conf.len / 2); + message = 'ü'.repeat(len / 2); encoding = 'utf8'; break; case 'buf': - message = Buffer.alloc(conf.len, 'b'); + message = Buffer.alloc(len, 'b'); break; default: - throw new Error(`unknown message type: ${conf.type}`); + throw new Error(`unknown message type: ${type}`); } const fn = api === 'stream' ? streamWrite : legacyWrite; @@ -59,7 +58,7 @@ function main(conf) { // write data as fast as possible to alice, and have bob decrypt. // use old API for comparison to v0.8 bench.start(); - fn(alice_cipher, bob_cipher, message, encoding, conf.writes); + fn(alice_cipher, bob_cipher, message, encoding, writes); } function streamWrite(alice, bob, message, encoding, writes) { diff --git a/benchmark/crypto/get-ciphers.js b/benchmark/crypto/get-ciphers.js index 3f5ad17ad38716..d4c10a2427d360 100644 --- a/benchmark/crypto/get-ciphers.js +++ b/benchmark/crypto/get-ciphers.js @@ -7,12 +7,10 @@ const bench = common.createBenchmark(main, { v: ['crypto', 'tls'] }); -function main(conf) { - const n = +conf.n; - const v = conf.v; +function main({ n, v }) { const method = require(v).getCiphers; var i = 0; - // first call to getChipers will dominate the results + // First call to getChipers will dominate the results if (n > 1) { for (; i < n; i++) method(); diff --git a/benchmark/crypto/hash-stream-creation.js b/benchmark/crypto/hash-stream-creation.js index 5ac5a4f70b5c55..faaa12a9e5d484 100644 --- a/benchmark/crypto/hash-stream-creation.js +++ b/benchmark/crypto/hash-stream-creation.js @@ -13,8 +13,7 @@ const bench = common.createBenchmark(main, { api: ['legacy', 'stream'] }); -function main(conf) { - var api = conf.api; +function main({ api, type, len, out, writes, algo }) { if (api === 'stream' && /^v0\.[0-8]\./.test(process.version)) { console.error('Crypto streams not available until v0.10'); // use the legacy, just so that we can compare them. @@ -23,26 +22,26 @@ function main(conf) { var message; var encoding; - switch (conf.type) { + switch (type) { case 'asc': - message = 'a'.repeat(conf.len); + message = 'a'.repeat(len); encoding = 'ascii'; break; case 'utf': - message = 'ü'.repeat(conf.len / 2); + message = 'ü'.repeat(len / 2); encoding = 'utf8'; break; case 'buf': - message = Buffer.alloc(conf.len, 'b'); + message = Buffer.alloc(len, 'b'); break; default: - throw new Error(`unknown message type: ${conf.type}`); + throw new Error(`unknown message type: ${type}`); } const fn = api === 'stream' ? streamWrite : legacyWrite; bench.start(); - fn(conf.algo, message, encoding, conf.writes, conf.len, conf.out); + fn(algo, message, encoding, writes, len, out); } function legacyWrite(algo, message, encoding, writes, len, outEnc) { diff --git a/benchmark/crypto/hash-stream-throughput.js b/benchmark/crypto/hash-stream-throughput.js index 21ec3c7902b367..934e7a0b11bdae 100644 --- a/benchmark/crypto/hash-stream-throughput.js +++ b/benchmark/crypto/hash-stream-throughput.js @@ -12,8 +12,7 @@ const bench = common.createBenchmark(main, { api: ['legacy', 'stream'] }); -function main(conf) { - var api = conf.api; +function main({ api, type, len, algo, writes }) { if (api === 'stream' && /^v0\.[0-8]\./.test(process.version)) { console.error('Crypto streams not available until v0.10'); // use the legacy, just so that we can compare them. @@ -22,26 +21,26 @@ function main(conf) { var message; var encoding; - switch (conf.type) { + switch (type) { case 'asc': - message = 'a'.repeat(conf.len); + message = 'a'.repeat(len); encoding = 'ascii'; break; case 'utf': - message = 'ü'.repeat(conf.len / 2); + message = 'ü'.repeat(len / 2); encoding = 'utf8'; break; case 'buf': - message = Buffer.alloc(conf.len, 'b'); + message = Buffer.alloc(len, 'b'); break; default: - throw new Error(`unknown message type: ${conf.type}`); + throw new Error(`unknown message type: ${type}`); } const fn = api === 'stream' ? streamWrite : legacyWrite; bench.start(); - fn(conf.algo, message, encoding, conf.writes, conf.len); + fn(algo, message, encoding, writes, len); } function legacyWrite(algo, message, encoding, writes, len) { diff --git a/benchmark/crypto/rsa-encrypt-decrypt-throughput.js b/benchmark/crypto/rsa-encrypt-decrypt-throughput.js index edab5ae08f7d63..40b69c31f977ca 100644 --- a/benchmark/crypto/rsa-encrypt-decrypt-throughput.js +++ b/benchmark/crypto/rsa-encrypt-decrypt-throughput.js @@ -22,10 +22,10 @@ const bench = common.createBenchmark(main, { len: [16, 32, 64] }); -function main(conf) { - const message = Buffer.alloc(conf.len, 'b'); +function main({ len, algo, keylen, n }) { + const message = Buffer.alloc(len, 'b'); bench.start(); - StreamWrite(conf.algo, conf.keylen, message, conf.n, conf.len); + StreamWrite(algo, keylen, message, n, len); } function StreamWrite(algo, keylen, message, n, len) { diff --git a/benchmark/crypto/rsa-sign-verify-throughput.js b/benchmark/crypto/rsa-sign-verify-throughput.js index bcde3a43d4d77a..3a0373b57d0bba 100644 --- a/benchmark/crypto/rsa-sign-verify-throughput.js +++ b/benchmark/crypto/rsa-sign-verify-throughput.js @@ -23,10 +23,10 @@ const bench = common.createBenchmark(main, { len: [1024, 102400, 2 * 102400, 3 * 102400, 1024 * 1024] }); -function main(conf) { - const message = Buffer.alloc(conf.len, 'b'); +function main({ len, algo, keylen, writes }) { + const message = Buffer.alloc(len, 'b'); bench.start(); - StreamWrite(conf.algo, conf.keylen, message, conf.writes, conf.len); + StreamWrite(algo, keylen, message, writes, len); } function StreamWrite(algo, keylen, message, writes, len) { From 10a560aade92e98317baba35c4de27abd6a0e82f Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:18:12 +0100 Subject: [PATCH 029/131] benchmark: (url) refactor PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- .../url/legacy-vs-whatwg-url-get-prop.js | 4 +- benchmark/url/legacy-vs-whatwg-url-parse.js | 4 +- ...legacy-vs-whatwg-url-searchparams-parse.js | 4 +- ...cy-vs-whatwg-url-searchparams-serialize.js | 4 +- .../url/legacy-vs-whatwg-url-serialize.js | 4 +- benchmark/url/url-searchparams-iteration.js | 2 +- benchmark/url/url-searchparams-read.js | 41 +++---------------- benchmark/url/url-searchparams-sort.js | 3 +- 8 files changed, 17 insertions(+), 49 deletions(-) diff --git a/benchmark/url/legacy-vs-whatwg-url-get-prop.js b/benchmark/url/legacy-vs-whatwg-url-get-prop.js index 93603c258cf1f2..2cc3ab8c75e65c 100644 --- a/benchmark/url/legacy-vs-whatwg-url-get-prop.js +++ b/benchmark/url/legacy-vs-whatwg-url-get-prop.js @@ -74,7 +74,7 @@ function useWHATWG(n, input) { function main({ type, n, method }) { const input = inputs[type]; if (!input) { - throw new Error('Unknown input type'); + throw new Error(`Unknown input type "${type}"`); } var noDead; // Avoid dead code elimination. @@ -86,7 +86,7 @@ function main({ type, n, method }) { noDead = useWHATWG(n, input); break; default: - throw new Error('Unknown method'); + throw new Error(`Unknown method "${method}"`); } assert.ok(noDead); diff --git a/benchmark/url/legacy-vs-whatwg-url-parse.js b/benchmark/url/legacy-vs-whatwg-url-parse.js index da42d5a189af47..2be55e17cc354b 100644 --- a/benchmark/url/legacy-vs-whatwg-url-parse.js +++ b/benchmark/url/legacy-vs-whatwg-url-parse.js @@ -34,7 +34,7 @@ function useWHATWG(n, input) { function main({ type, n, method }) { const input = inputs[type]; if (!input) { - throw new Error('Unknown input type'); + throw new Error(`Unknown input type "${type}"`); } var noDead; // Avoid dead code elimination. @@ -46,7 +46,7 @@ function main({ type, n, method }) { noDead = useWHATWG(n, input); break; default: - throw new Error('Unknown method'); + throw new Error(`Unknown method ${method}`); } assert.ok(noDead); diff --git a/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js b/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js index 51953ec8707374..e915ceb54f917f 100644 --- a/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js +++ b/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js @@ -31,7 +31,7 @@ function useWHATWG(n, input) { function main({ type, n, method }) { const input = inputs[type]; if (!input) { - throw new Error('Unknown input type'); + throw new Error(`Unknown input type "${type}"`); } switch (method) { @@ -42,6 +42,6 @@ function main({ type, n, method }) { useWHATWG(n, input); break; default: - throw new Error('Unknown method'); + throw new Error(`Unknown method ${method}`); } } diff --git a/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js b/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js index 3490782a1bf421..8fe3e546f0780d 100644 --- a/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js +++ b/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js @@ -33,7 +33,7 @@ function useWHATWG(n, input, prop) { function main({ type, n, method }) { const input = inputs[type]; if (!input) { - throw new Error('Unknown input type'); + throw new Error(`Unknown input type "${type}"`); } switch (method) { @@ -44,6 +44,6 @@ function main({ type, n, method }) { useWHATWG(n, input); break; default: - throw new Error('Unknown method'); + throw new Error(`Unknown method ${method}`); } } diff --git a/benchmark/url/legacy-vs-whatwg-url-serialize.js b/benchmark/url/legacy-vs-whatwg-url-serialize.js index e92b941b5d57e5..017ec4328c590b 100644 --- a/benchmark/url/legacy-vs-whatwg-url-serialize.js +++ b/benchmark/url/legacy-vs-whatwg-url-serialize.js @@ -36,7 +36,7 @@ function useWHATWG(n, input, prop) { function main({ type, n, method }) { const input = inputs[type]; if (!input) { - throw new Error('Unknown input type'); + throw new Error(`Unknown input type "${type}"`); } var noDead; // Avoid dead code elimination. @@ -48,7 +48,7 @@ function main({ type, n, method }) { noDead = useWHATWG(n, input); break; default: - throw new Error('Unknown method'); + throw new Error(`Unknown method ${method}`); } assert.ok(noDead); diff --git a/benchmark/url/url-searchparams-iteration.js b/benchmark/url/url-searchparams-iteration.js index 2b13992bdfcfc0..cae2ef5df61956 100644 --- a/benchmark/url/url-searchparams-iteration.js +++ b/benchmark/url/url-searchparams-iteration.js @@ -53,6 +53,6 @@ function main({ method, n }) { iterator(n); break; default: - throw new Error('Unknown method'); + throw new Error(`Unknown method ${method}`); } } diff --git a/benchmark/url/url-searchparams-read.js b/benchmark/url/url-searchparams-read.js index 29235ee81e0e14..0cf66dabbc36dc 100644 --- a/benchmark/url/url-searchparams-read.js +++ b/benchmark/url/url-searchparams-read.js @@ -10,45 +10,14 @@ const bench = common.createBenchmark(main, { const str = 'one=single&two=first&three=first&two=2nd&three=2nd&three=3rd'; -function get(n, param) { - const params = new URLSearchParams(str); - - bench.start(); - for (var i = 0; i < n; i += 1) - params.get(param); - bench.end(n); -} - -function getAll(n, param) { - const params = new URLSearchParams(str); - - bench.start(); - for (var i = 0; i < n; i += 1) - params.getAll(param); - bench.end(n); -} - -function has(n, param) { +function main({ method, param, n }) { const params = new URLSearchParams(str); + const fn = params[method]; + if (!fn) + throw new Error(`Unknown method ${method}`); bench.start(); for (var i = 0; i < n; i += 1) - params.has(param); + fn(param); bench.end(n); } - -function main({ method, param, n }) { - switch (method) { - case 'get': - get(n, param); - break; - case 'getAll': - getAll(n, param); - break; - case 'has': - has(n, param); - break; - default: - throw new Error('Unknown method'); - } -} diff --git a/benchmark/url/url-searchparams-sort.js b/benchmark/url/url-searchparams-sort.js index 524dacb6d52dc4..fe152bf823468f 100644 --- a/benchmark/url/url-searchparams-sort.js +++ b/benchmark/url/url-searchparams-sort.js @@ -37,9 +37,8 @@ function main({ type, n }) { const params = new URLSearchParams(); const array = getParams(input); - var i; bench.start(); - for (i = 0; i < n; i++) { + for (var i = 0; i < n; i++) { params[searchParams] = array.slice(); params.sort(); } From 5213f8c886e2ed89e9838fa2a141b4db128da16c Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:18:30 +0100 Subject: [PATCH 030/131] benchmark: (es) refactor PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/es/defaultparams-bench.js | 24 ++++----- benchmark/es/destructuring-bench.js | 20 ++++---- benchmark/es/destructuring-object-bench.js | 20 ++++---- benchmark/es/foreach-bench.js | 43 +++++++--------- benchmark/es/map-bench.js | 58 ++++++++++------------ benchmark/es/restparams-bench.js | 38 ++++++-------- benchmark/es/spread-bench.js | 15 +++--- benchmark/es/string-concatenations.js | 3 +- benchmark/es/string-repeat.js | 2 +- 9 files changed, 94 insertions(+), 129 deletions(-) diff --git a/benchmark/es/defaultparams-bench.js b/benchmark/es/defaultparams-bench.js index ce2132718ca369..a00b50137c1af3 100644 --- a/benchmark/es/defaultparams-bench.js +++ b/benchmark/es/defaultparams-bench.js @@ -20,37 +20,31 @@ function defaultParams(x = 1, y = 2) { assert.strictEqual(y, 2); } -function runOldStyleDefaults(n) { - - var i = 0; +function runOldStyleDefaults(millions) { bench.start(); - for (; i < n; i++) + for (var i = 0; i < millions * 1e6; i++) oldStyleDefaults(); - bench.end(n / 1e6); + bench.end(millions); } -function runDefaultParams(n) { - - var i = 0; +function runDefaultParams(millions) { bench.start(); - for (; i < n; i++) + for (var i = 0; i < millions * 1e6; i++) defaultParams(); - bench.end(n / 1e6); + bench.end(millions); } function main({ millions, method }) { - const n = millions * 1e6; - switch (method) { case '': // Empty string falls through to next line as default, mostly for tests. case 'withoutdefaults': - runOldStyleDefaults(n); + runOldStyleDefaults(millions); break; case 'withdefaults': - runDefaultParams(n); + runDefaultParams(millions); break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } } diff --git a/benchmark/es/destructuring-bench.js b/benchmark/es/destructuring-bench.js index f244506860d248..2168940bdc44f0 100644 --- a/benchmark/es/destructuring-bench.js +++ b/benchmark/es/destructuring-bench.js @@ -8,10 +8,10 @@ const bench = common.createBenchmark(main, { millions: [100] }); -function runSwapManual(n) { +function runSwapManual(millions) { var x, y, r; bench.start(); - for (var i = 0; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { x = 1, y = 2; r = x; x = y; @@ -19,34 +19,32 @@ function runSwapManual(n) { assert.strictEqual(x, 2); assert.strictEqual(y, 1); } - bench.end(n / 1e6); + bench.end(millions); } -function runSwapDestructured(n) { +function runSwapDestructured(millions) { var x, y; bench.start(); - for (var i = 0; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { x = 1, y = 2; [x, y] = [y, x]; assert.strictEqual(x, 2); assert.strictEqual(y, 1); } - bench.end(n / 1e6); + bench.end(millions); } function main({ millions, method }) { - const n = millions * 1e6; - switch (method) { case '': // Empty string falls through to next line as default, mostly for tests. case 'swap': - runSwapManual(n); + runSwapManual(millions); break; case 'destructure': - runSwapDestructured(n); + runSwapDestructured(millions); break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } } diff --git a/benchmark/es/destructuring-object-bench.js b/benchmark/es/destructuring-object-bench.js index 73687f018de9dd..a84977c59bc2cd 100644 --- a/benchmark/es/destructuring-object-bench.js +++ b/benchmark/es/destructuring-object-bench.js @@ -7,45 +7,43 @@ const bench = common.createBenchmark(main, { millions: [100] }); -function runNormal(n) { +function runNormal(millions) { var i = 0; const o = { x: 0, y: 1 }; bench.start(); - for (; i < n; i++) { + for (; i < millions * 1e6; i++) { /* eslint-disable no-unused-vars */ const x = o.x; const y = o.y; const r = o.r || 2; /* eslint-enable no-unused-vars */ } - bench.end(n / 1e6); + bench.end(millions); } -function runDestructured(n) { +function runDestructured(millions) { var i = 0; const o = { x: 0, y: 1 }; bench.start(); - for (; i < n; i++) { + for (; i < millions * 1e6; i++) { /* eslint-disable no-unused-vars */ const { x, y, r = 2 } = o; /* eslint-enable no-unused-vars */ } - bench.end(n / 1e6); + bench.end(millions); } function main({ millions, method }) { - const n = millions * 1e6; - switch (method) { case '': // Empty string falls through to next line as default, mostly for tests. case 'normal': - runNormal(n); + runNormal(millions); break; case 'destructureObject': - runDestructured(n); + runDestructured(millions); break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } } diff --git a/benchmark/es/foreach-bench.js b/benchmark/es/foreach-bench.js index c7caa7cee6f461..e9179ed8dedb6d 100644 --- a/benchmark/es/foreach-bench.js +++ b/benchmark/es/foreach-bench.js @@ -8,56 +8,51 @@ const bench = common.createBenchmark(main, { millions: [5] }); -function useFor(n, items, count) { - var i, j; +function useFor(millions, items, count) { bench.start(); - for (i = 0; i < n; i++) { - for (j = 0; j < count; j++) { + for (var i = 0; i < millions * 1e6; i++) { + for (var j = 0; j < count; j++) { /* eslint-disable no-unused-vars */ const item = items[j]; /* esline-enable no-unused-vars */ } } - bench.end(n / 1e6); + bench.end(millions); } -function useForOf(n, items) { - var i, item; +function useForOf(millions, items) { + var item; bench.start(); - for (i = 0; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { for (item of items) {} } - bench.end(n / 1e6); + bench.end(millions); } -function useForIn(n, items) { - var i, j, item; +function useForIn(millions, items) { bench.start(); - for (i = 0; i < n; i++) { - for (j in items) { + for (var i = 0; i < millions * 1e6; i++) { + for (var j in items) { /* eslint-disable no-unused-vars */ - item = items[j]; + const item = items[j]; /* esline-enable no-unused-vars */ } } - bench.end(n / 1e6); + bench.end(millions); } -function useForEach(n, items) { - var i; +function useForEach(millions, items) { bench.start(); - for (i = 0; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { items.forEach((item) => {}); } - bench.end(n / 1e6); + bench.end(millions); } function main({ millions, count, method }) { - const n = millions * 1e6; const items = new Array(count); - var i; var fn; - for (i = 0; i < count; i++) + for (var i = 0; i < count; i++) items[i] = i; switch (method) { @@ -76,7 +71,7 @@ function main({ millions, count, method }) { fn = useForEach; break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } - fn(n, items, count); + fn(millions, items, count); } diff --git a/benchmark/es/map-bench.js b/benchmark/es/map-bench.js index ba8e35c2eb934f..445031aa9831de 100644 --- a/benchmark/es/map-bench.js +++ b/benchmark/es/map-bench.js @@ -11,63 +11,59 @@ const bench = common.createBenchmark(main, { millions: [1] }); -function runObject(n) { +function runObject(millions) { const m = {}; - var i = 0; bench.start(); - for (; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { m[`i${i}`] = i; m[`s${i}`] = String(i); assert.strictEqual(String(m[`i${i}`]), m[`s${i}`]); m[`i${i}`] = undefined; m[`s${i}`] = undefined; } - bench.end(n / 1e6); + bench.end(millions); } -function runNullProtoObject(n) { +function runNullProtoObject(millions) { const m = Object.create(null); - var i = 0; bench.start(); - for (; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { m[`i${i}`] = i; m[`s${i}`] = String(i); assert.strictEqual(String(m[`i${i}`]), m[`s${i}`]); m[`i${i}`] = undefined; m[`s${i}`] = undefined; } - bench.end(n / 1e6); + bench.end(millions); } -function runNullProtoLiteralObject(n) { +function runNullProtoLiteralObject(millions) { const m = { __proto__: null }; - var i = 0; bench.start(); - for (; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { m[`i${i}`] = i; m[`s${i}`] = String(i); assert.strictEqual(String(m[`i${i}`]), m[`s${i}`]); m[`i${i}`] = undefined; m[`s${i}`] = undefined; } - bench.end(n / 1e6); + bench.end(millions); } function StorageObject() {} StorageObject.prototype = Object.create(null); -function runStorageObject(n) { +function runStorageObject(millions) { const m = new StorageObject(); - var i = 0; bench.start(); - for (; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { m[`i${i}`] = i; m[`s${i}`] = String(i); assert.strictEqual(String(m[`i${i}`]), m[`s${i}`]); m[`i${i}`] = undefined; m[`s${i}`] = undefined; } - bench.end(n / 1e6); + bench.end(millions); } function fakeMap() { @@ -80,59 +76,55 @@ function fakeMap() { }; } -function runFakeMap(n) { +function runFakeMap(millions) { const m = fakeMap(); - var i = 0; bench.start(); - for (; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { m.set(`i${i}`, i); m.set(`s${i}`, String(i)); assert.strictEqual(String(m.get(`i${i}`)), m.get(`s${i}`)); m.set(`i${i}`, undefined); m.set(`s${i}`, undefined); } - bench.end(n / 1e6); + bench.end(millions); } -function runMap(n) { +function runMap(millions) { const m = new Map(); - var i = 0; bench.start(); - for (; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { m.set(`i${i}`, i); m.set(`s${i}`, String(i)); assert.strictEqual(String(m.get(`i${i}`)), m.get(`s${i}`)); m.set(`i${i}`, undefined); m.set(`s${i}`, undefined); } - bench.end(n / 1e6); + bench.end(millions); } function main({ millions, method }) { - const n = millions * 1e6; - switch (method) { case '': // Empty string falls through to next line as default, mostly for tests. case 'object': - runObject(n); + runObject(millions); break; case 'nullProtoObject': - runNullProtoObject(n); + runNullProtoObject(millions); break; case 'nullProtoLiteralObject': - runNullProtoLiteralObject(n); + runNullProtoLiteralObject(millions); break; case 'storageObject': - runStorageObject(n); + runStorageObject(millions); break; case 'fakeMap': - runFakeMap(n); + runFakeMap(millions); break; case 'map': - runMap(n); + runMap(millions); break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } } diff --git a/benchmark/es/restparams-bench.js b/benchmark/es/restparams-bench.js index 78299d292ce6f6..6ad766f10f16f6 100644 --- a/benchmark/es/restparams-bench.js +++ b/benchmark/es/restparams-bench.js @@ -33,49 +33,39 @@ function useArguments() { assert.strictEqual(arguments[3], 'b'); } -function runCopyArguments(n) { - - var i = 0; - bench.start(); - for (; i < n; i++) +function runCopyArguments(millions) { + for (var i = 0; i < millions * 1e6; i++) copyArguments(1, 2, 'a', 'b'); - bench.end(n / 1e6); } -function runRestArguments(n) { - - var i = 0; - bench.start(); - for (; i < n; i++) +function runRestArguments(millions) { + for (var i = 0; i < millions * 1e6; i++) restArguments(1, 2, 'a', 'b'); - bench.end(n / 1e6); } -function runUseArguments(n) { - - var i = 0; - bench.start(); - for (; i < n; i++) +function runUseArguments(millions) { + for (var i = 0; i < millions * 1e6; i++) useArguments(1, 2, 'a', 'b'); - bench.end(n / 1e6); } function main({ millions, method }) { - const n = millions * 1e6; - + var fn; switch (method) { case '': // Empty string falls through to next line as default, mostly for tests. case 'copy': - runCopyArguments(n); + fn = runCopyArguments; break; case 'rest': - runRestArguments(n); + fn = runRestArguments; break; case 'arguments': - runUseArguments(n); + fn = runUseArguments; break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } + bench.start(); + fn(millions); + bench.end(millions); } diff --git a/benchmark/es/spread-bench.js b/benchmark/es/spread-bench.js index 3c6cc93ea4f817..067299cd650919 100644 --- a/benchmark/es/spread-bench.js +++ b/benchmark/es/spread-bench.js @@ -24,7 +24,6 @@ function makeTest(count, rest) { } function main({ millions, context, count, rest, method }) { - const n = millions * 1e6; const ctx = context === 'context' ? {} : null; var fn = makeTest(count, rest); const args = new Array(count); @@ -37,25 +36,25 @@ function main({ millions, context, count, rest, method }) { // Empty string falls through to next line as default, mostly for tests. case 'apply': bench.start(); - for (i = 0; i < n; i++) + for (i = 0; i < millions * 1e6; i++) fn.apply(ctx, args); - bench.end(n / 1e6); + bench.end(millions); break; case 'spread': if (ctx !== null) fn = fn.bind(ctx); bench.start(); - for (i = 0; i < n; i++) + for (i = 0; i < millions * 1e6; i++) fn(...args); - bench.end(n / 1e6); + bench.end(millions); break; case 'call-spread': bench.start(); - for (i = 0; i < n; i++) + for (i = 0; i < millions * 1e6; i++) fn.call(ctx, ...args); - bench.end(n / 1e6); + bench.end(millions); break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } } diff --git a/benchmark/es/string-concatenations.js b/benchmark/es/string-concatenations.js index a40b7fa8c3b9f9..72fb7f9969b604 100644 --- a/benchmark/es/string-concatenations.js +++ b/benchmark/es/string-concatenations.js @@ -16,7 +16,6 @@ const configs = { const bench = common.createBenchmark(main, configs); - function main({ n, mode }) { const str = 'abc'; const num = 123; @@ -63,7 +62,7 @@ function main({ n, mode }) { bench.end(n); break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${mode}"`); } return string; diff --git a/benchmark/es/string-repeat.js b/benchmark/es/string-repeat.js index e5bdbb5cc193c1..9e33e4acf47118 100644 --- a/benchmark/es/string-repeat.js +++ b/benchmark/es/string-repeat.js @@ -33,7 +33,7 @@ function main({ n, size, encoding, mode }) { bench.end(n); break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${mode}"`); } assert.strictEqual([...str].length, size); From 0d7b697b1ee02f0a3046de2387c056bc5f408ce1 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:18:55 +0100 Subject: [PATCH 031/131] benchmark: (http(2)) refactor PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/http/bench-parser.js | 3 --- benchmark/http/simple.js | 4 +--- benchmark/http/upgrade.js | 2 -- benchmark/http2/respond-with-fd.js | 3 +-- benchmark/http2/simple.js | 5 +---- benchmark/http2/write.js | 3 +-- 6 files changed, 4 insertions(+), 16 deletions(-) diff --git a/benchmark/http/bench-parser.js b/benchmark/http/bench-parser.js index 4c691d71345da3..d629fe67e59e76 100644 --- a/benchmark/http/bench-parser.js +++ b/benchmark/http/bench-parser.js @@ -14,7 +14,6 @@ const bench = common.createBenchmark(main, { n: [1e5], }); - function main({ len, n }) { var header = `GET /hello HTTP/1.1${CRLF}Content-Type: text/plain${CRLF}`; @@ -26,7 +25,6 @@ function main({ len, n }) { processHeader(Buffer.from(header), n); } - function processHeader(header, n) { const parser = newParser(REQUEST); @@ -38,7 +36,6 @@ function processHeader(header, n) { bench.end(n); } - function newParser(type) { const parser = new HTTPParser(type); diff --git a/benchmark/http/simple.js b/benchmark/http/simple.js index d5351815fc1b7e..bbc59a341d15ba 100644 --- a/benchmark/http/simple.js +++ b/benchmark/http/simple.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common.js'); -const PORT = common.PORT; const bench = common.createBenchmark(main, { // unicode confuses ab on os x. @@ -13,9 +12,8 @@ const bench = common.createBenchmark(main, { }); function main({ type, len, chunks, c, chunkedEnc, res }) { - process.env.PORT = PORT; var server = require('../fixtures/simple-http-server.js') - .listen(PORT) + .listen(common.PORT) .on('listening', function() { const path = `/${type}/${len}/${chunks}/${res}/${chunkedEnc}`; diff --git a/benchmark/http/upgrade.js b/benchmark/http/upgrade.js index 0feaecc8ff19e6..6b39323396a2e3 100644 --- a/benchmark/http/upgrade.js +++ b/benchmark/http/upgrade.js @@ -1,7 +1,6 @@ 'use strict'; const common = require('../common.js'); -const PORT = common.PORT; const net = require('net'); const bench = common.createBenchmark(main, { @@ -20,7 +19,6 @@ const resData = 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + '\r\n\r\n'; function main({ n }) { - process.env.PORT = PORT; var server = require('../fixtures/simple-http-server.js') .listen(common.PORT) .on('listening', function() { diff --git a/benchmark/http2/respond-with-fd.js b/benchmark/http2/respond-with-fd.js index 6076cf91be9d84..fa7b2fbd16b3e6 100644 --- a/benchmark/http2/respond-with-fd.js +++ b/benchmark/http2/respond-with-fd.js @@ -1,7 +1,6 @@ 'use strict'; const common = require('../common.js'); -const PORT = common.PORT; const path = require('path'); const fs = require('fs'); @@ -25,7 +24,7 @@ function main({ requests, streams, clients }) { stream.respondWithFD(fd); stream.on('error', (err) => {}); }); - server.listen(PORT, () => { + server.listen(common.PORT, () => { bench.http({ path: '/', requests, diff --git a/benchmark/http2/simple.js b/benchmark/http2/simple.js index 37c78d340181a8..cf017e6735411e 100644 --- a/benchmark/http2/simple.js +++ b/benchmark/http2/simple.js @@ -1,11 +1,8 @@ 'use strict'; const common = require('../common.js'); -const PORT = common.PORT; - const path = require('path'); const fs = require('fs'); - const file = path.join(path.resolve(__dirname, '../fixtures'), 'alice.html'); const bench = common.createBenchmark(main, { @@ -24,7 +21,7 @@ function main({ requests, streams, clients }) { out.pipe(stream); stream.on('error', (err) => {}); }); - server.listen(PORT, () => { + server.listen(common.PORT, () => { bench.http({ path: '/', requests, diff --git a/benchmark/http2/write.js b/benchmark/http2/write.js index 7a802ef84fd9ed..6fcb1254ca3f05 100644 --- a/benchmark/http2/write.js +++ b/benchmark/http2/write.js @@ -1,7 +1,6 @@ 'use strict'; const common = require('../common.js'); -const PORT = common.PORT; const bench = common.createBenchmark(main, { streams: [100, 200, 1000], @@ -26,7 +25,7 @@ function main({ streams, length, size }) { } write(); }); - server.listen(PORT, () => { + server.listen(common.PORT, () => { bench.http({ path: '/', requests: 10000, From bb808e33c92c72fe37774facae7b94bb6f29be3a Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:19:14 +0100 Subject: [PATCH 032/131] benchmark: (timers) refactor PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/timers/set-immediate-breadth.js | 2 +- benchmark/timers/set-immediate-depth-args.js | 2 +- benchmark/timers/timers-cancel-pooled.js | 2 +- benchmark/timers/timers-cancel-unpooled.js | 2 +- benchmark/timers/timers-insert-unpooled.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/benchmark/timers/set-immediate-breadth.js b/benchmark/timers/set-immediate-breadth.js index a4b217b5bff8d6..4f7d2cd2761334 100644 --- a/benchmark/timers/set-immediate-breadth.js +++ b/benchmark/timers/set-immediate-breadth.js @@ -9,7 +9,7 @@ function main({ millions }) { const N = millions * 1e6; process.on('exit', function() { - bench.end(N / 1e6); + bench.end(millions); }); function cb() {} diff --git a/benchmark/timers/set-immediate-depth-args.js b/benchmark/timers/set-immediate-depth-args.js index fe1340c4bd55f2..aa5ec95f7dad30 100644 --- a/benchmark/timers/set-immediate-depth-args.js +++ b/benchmark/timers/set-immediate-depth-args.js @@ -9,7 +9,7 @@ function main({ millions }) { const N = millions * 1e6; process.on('exit', function() { - bench.end(N / 1e6); + bench.end(millions); }); function cb3(n, arg2, arg3) { diff --git a/benchmark/timers/timers-cancel-pooled.js b/benchmark/timers/timers-cancel-pooled.js index 33897507c83937..3e262f820a3e08 100644 --- a/benchmark/timers/timers-cancel-pooled.js +++ b/benchmark/timers/timers-cancel-pooled.js @@ -28,5 +28,5 @@ function main({ millions }) { } function cb() { - assert(false, 'Timer should not call callback'); + assert.fail('Timer should not call callback'); } diff --git a/benchmark/timers/timers-cancel-unpooled.js b/benchmark/timers/timers-cancel-unpooled.js index 57e0139dfe1a4a..158667311330a4 100644 --- a/benchmark/timers/timers-cancel-unpooled.js +++ b/benchmark/timers/timers-cancel-unpooled.js @@ -22,5 +22,5 @@ function main({ millions }) { } function cb() { - assert(false, `Timer ${this._idleTimeout} should not call callback`); + assert.fail(`Timer ${this._idleTimeout} should not call callback`); } diff --git a/benchmark/timers/timers-insert-unpooled.js b/benchmark/timers/timers-insert-unpooled.js index 56526633358e42..fbbeebb759ff3a 100644 --- a/benchmark/timers/timers-insert-unpooled.js +++ b/benchmark/timers/timers-insert-unpooled.js @@ -23,5 +23,5 @@ function main({ millions }) { } function cb() { - assert(false, `Timer ${this._idleTimeout} should not call callback`); + assert.fail(`Timer ${this._idleTimeout} should not call callback`); } From 8aabb86ea3149598a55834b88603d92feab457d2 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 23 Jan 2018 13:19:30 +0100 Subject: [PATCH 033/131] benchmark: refactor PR-URL: https://github.com/nodejs/node/pull/18320 Reviewed-By: James M Snell --- benchmark/async_hooks/gc-tracking.js | 7 ++++--- benchmark/dgram/bind-params.js | 7 ++++--- benchmark/domain/domain-fn-args.js | 11 +---------- benchmark/fs/bench-realpath.js | 4 +--- benchmark/fs/bench-realpathSync.js | 20 +++----------------- benchmark/fs/write-stream-throughput.js | 7 ------- benchmark/misc/freelist.js | 3 +-- benchmark/misc/function_call/index.js | 4 +--- benchmark/misc/object-property-bench.js | 2 +- benchmark/misc/punycode.js | 5 ++--- benchmark/module/module-loader.js | 24 +++++++++++------------- benchmark/tls/convertprotocols.js | 7 ++++--- benchmark/util/format.js | 4 +--- benchmark/util/inspect-array.js | 5 ++--- benchmark/v8/get-stats.js | 3 +-- benchmark/vm/run-in-context.js | 4 +--- benchmark/vm/run-in-this-context.js | 4 +--- 17 files changed, 39 insertions(+), 82 deletions(-) diff --git a/benchmark/async_hooks/gc-tracking.js b/benchmark/async_hooks/gc-tracking.js index a569fb8fa92485..d74b2bac463e28 100644 --- a/benchmark/async_hooks/gc-tracking.js +++ b/benchmark/async_hooks/gc-tracking.js @@ -22,22 +22,23 @@ function endAfterGC(n) { } function main({ n, method }) { + var i; switch (method) { case 'trackingEnabled': bench.start(); - for (let i = 0; i < n; i++) { + for (i = 0; i < n; i++) { new AsyncResource('foobar'); } endAfterGC(n); break; case 'trackingDisabled': bench.start(); - for (let i = 0; i < n; i++) { + for (i = 0; i < n; i++) { new AsyncResource('foobar', { requireManualDestroy: true }); } endAfterGC(n); break; default: - throw new Error('Unsupported method'); + throw new Error(`Unsupported method "${method}"`); } } diff --git a/benchmark/dgram/bind-params.js b/benchmark/dgram/bind-params.js index 5f7999f7a39241..ea1f430eed929b 100644 --- a/benchmark/dgram/bind-params.js +++ b/benchmark/dgram/bind-params.js @@ -15,10 +15,11 @@ const noop = () => {}; function main({ n, port, address }) { port = port === 'true' ? 0 : undefined; address = address === 'true' ? '0.0.0.0' : undefined; + var i; if (port !== undefined && address !== undefined) { bench.start(); - for (let i = 0; i < n; i++) { + for (i = 0; i < n; i++) { dgram.createSocket('udp4').bind(port, address) .on('error', noop) .unref(); @@ -26,7 +27,7 @@ function main({ n, port, address }) { bench.end(n); } else if (port !== undefined) { bench.start(); - for (let i = 0; i < n; i++) { + for (i = 0; i < n; i++) { dgram.createSocket('udp4') .bind(port) .on('error', noop) @@ -35,7 +36,7 @@ function main({ n, port, address }) { bench.end(n); } else if (port === undefined && address === undefined) { bench.start(); - for (let i = 0; i < n; i++) { + for (i = 0; i < n; i++) { dgram.createSocket('udp4') .bind() .on('error', noop) diff --git a/benchmark/domain/domain-fn-args.js b/benchmark/domain/domain-fn-args.js index fe912e34d206e8..c889b35442d046 100644 --- a/benchmark/domain/domain-fn-args.js +++ b/benchmark/domain/domain-fn-args.js @@ -28,15 +28,6 @@ function main({ n, args }) { bench.end(n); } -function fn(a, b, c) { - if (!a) - a = 1; - - if (!b) - b = 2; - - if (!c) - c = 3; - +function fn(a = 1, b = 2, c = 3) { return a + b + c; } diff --git a/benchmark/fs/bench-realpath.js b/benchmark/fs/bench-realpath.js index 6690d7e87b091f..de03e71b42d585 100644 --- a/benchmark/fs/bench-realpath.js +++ b/benchmark/fs/bench-realpath.js @@ -16,10 +16,8 @@ function main({ n, pathType }) { bench.start(); if (pathType === 'relative') relativePath(n); - else if (pathType === 'resolved') - resolvedPath(n); else - throw new Error(`unknown "pathType": ${pathType}`); + resolvedPath(n); } function relativePath(n) { diff --git a/benchmark/fs/bench-realpathSync.js b/benchmark/fs/bench-realpathSync.js index 1c751156f73d53..7a01bd18cb72bf 100644 --- a/benchmark/fs/bench-realpathSync.js +++ b/benchmark/fs/bench-realpathSync.js @@ -15,24 +15,10 @@ const bench = common.createBenchmark(main, { function main({ n, pathType }) { + const path = pathType === 'relative' ? relative_path : resolved_path; bench.start(); - if (pathType === 'relative') - relativePath(n); - else if (pathType === 'resolved') - resolvedPath(n); - else - throw new Error(`unknown "pathType": ${pathType}`); - bench.end(n); -} - -function relativePath(n) { - for (var i = 0; i < n; i++) { - fs.realpathSync(relative_path); - } -} - -function resolvedPath(n) { for (var i = 0; i < n; i++) { - fs.realpathSync(resolved_path); + fs.realpathSync(path); } + bench.end(n); } diff --git a/benchmark/fs/write-stream-throughput.js b/benchmark/fs/write-stream-throughput.js index 6fe00cde48cabb..60ad47bc4eabe1 100644 --- a/benchmark/fs/write-stream-throughput.js +++ b/benchmark/fs/write-stream-throughput.js @@ -36,7 +36,6 @@ function main({ dur, encodingType, size }) { try { fs.unlinkSync(filename); } catch (e) {} var started = false; - var ending = false; var ended = false; var f = fs.createWriteStream(filename); @@ -52,15 +51,9 @@ function main({ dur, encodingType, size }) { function write() { - // don't try to write after we end, even if a 'drain' event comes. - // v0.8 streams are so sloppy! - if (ending) - return; - if (!started) { started = true; setTimeout(function() { - ending = true; f.end(); }, dur * 1000); bench.start(); diff --git a/benchmark/misc/freelist.js b/benchmark/misc/freelist.js index 0530255728ffeb..8c3281cc407363 100644 --- a/benchmark/misc/freelist.js +++ b/benchmark/misc/freelist.js @@ -12,7 +12,6 @@ function main({ n }) { const FreeList = require('internal/freelist'); const poolSize = 1000; const list = new FreeList('test', poolSize, Object); - var i; var j; const used = []; @@ -23,7 +22,7 @@ function main({ n }) { bench.start(); - for (i = 0; i < n; i++) { + for (var i = 0; i < n; i++) { // Return all the items to the pool for (j = 0; j < poolSize; j++) { list.free(used[j]); diff --git a/benchmark/misc/function_call/index.js b/benchmark/misc/function_call/index.js index 91efa573597cc7..28561bc48cd7c3 100644 --- a/benchmark/misc/function_call/index.js +++ b/benchmark/misc/function_call/index.js @@ -32,11 +32,9 @@ const bench = common.createBenchmark(main, { }); function main({ millions, type }) { - const n = millions * 1e6; - const fn = type === 'cxx' ? cxx : js; bench.start(); - for (var i = 0; i < n; i++) { + for (var i = 0; i < millions * 1e6; i++) { fn(); } bench.end(millions); diff --git a/benchmark/misc/object-property-bench.js b/benchmark/misc/object-property-bench.js index 37da82d88758fd..ddc6faed7fc8b7 100644 --- a/benchmark/misc/object-property-bench.js +++ b/benchmark/misc/object-property-bench.js @@ -78,6 +78,6 @@ function main({ millions, method }) { runSymbol(n); break; default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } } diff --git a/benchmark/misc/punycode.js b/benchmark/misc/punycode.js index 7016fa11712bbc..369adcf17d3973 100644 --- a/benchmark/misc/punycode.js +++ b/benchmark/misc/punycode.js @@ -55,9 +55,8 @@ function runPunycode(n, val) { } function runICU(n, val) { - var i = 0; bench.start(); - for (; i < n; i++) + for (var i = 0; i < n; i++) usingICU(val); bench.end(n); } @@ -76,6 +75,6 @@ function main({ n, val, method }) { } // fallthrough default: - throw new Error('Unexpected method'); + throw new Error(`Unexpected method "${method}"`); } } diff --git a/benchmark/module/module-loader.js b/benchmark/module/module-loader.js index 25f0ece70169e7..58d4dcf81c9316 100644 --- a/benchmark/module/module-loader.js +++ b/benchmark/module/module-loader.js @@ -13,12 +13,10 @@ const bench = common.createBenchmark(main, { }); function main({ thousands, fullPath, useCache }) { - const n = thousands * 1e3; - tmpdir.refresh(); try { fs.mkdirSync(benchmarkDirectory); } catch (e) {} - for (var i = 0; i <= n; i++) { + for (var i = 0; i <= thousands * 1e3; i++) { fs.mkdirSync(`${benchmarkDirectory}${i}`); fs.writeFileSync( `${benchmarkDirectory}${i}/package.json`, @@ -31,37 +29,37 @@ function main({ thousands, fullPath, useCache }) { } if (fullPath === 'true') - measureFull(n, useCache === 'true'); + measureFull(thousands, useCache === 'true'); else - measureDir(n, useCache === 'true'); + measureDir(thousands, useCache === 'true'); tmpdir.refresh(); } -function measureFull(n, useCache) { +function measureFull(thousands, useCache) { var i; if (useCache) { - for (i = 0; i <= n; i++) { + for (i = 0; i <= thousands * 1e3; i++) { require(`${benchmarkDirectory}${i}/index.js`); } } bench.start(); - for (i = 0; i <= n; i++) { + for (i = 0; i <= thousands * 1e3; i++) { require(`${benchmarkDirectory}${i}/index.js`); } - bench.end(n / 1e3); + bench.end(thousands); } -function measureDir(n, useCache) { +function measureDir(thousands, useCache) { var i; if (useCache) { - for (i = 0; i <= n; i++) { + for (i = 0; i <= thousands * 1e3; i++) { require(`${benchmarkDirectory}${i}`); } } bench.start(); - for (i = 0; i <= n; i++) { + for (i = 0; i <= thousands * 1e3; i++) { require(`${benchmarkDirectory}${i}`); } - bench.end(n / 1e3); + bench.end(thousands); } diff --git a/benchmark/tls/convertprotocols.js b/benchmark/tls/convertprotocols.js index 1ee2672bee7bd7..9f4969344d1bcd 100644 --- a/benchmark/tls/convertprotocols.js +++ b/benchmark/tls/convertprotocols.js @@ -8,14 +8,15 @@ const bench = common.createBenchmark(main, { }); function main({ n }) { - var i = 0; + const input = ['ABC', 'XYZ123', 'FOO']; var m = {}; // First call dominates results if (n > 1) { - tls.convertNPNProtocols(['ABC', 'XYZ123', 'FOO'], m); + tls.convertNPNProtocols(input, m); m = {}; } bench.start(); - for (; i < n; i++) tls.convertNPNProtocols(['ABC', 'XYZ123', 'FOO'], m); + for (var i = 0; i < n; i++) + tls.convertNPNProtocols(input, m); bench.end(n); } diff --git a/benchmark/util/format.js b/benchmark/util/format.js index 5f9c4c3b594497..042b8a93ccfcf2 100644 --- a/benchmark/util/format.js +++ b/benchmark/util/format.js @@ -22,9 +22,7 @@ const bench = common.createBenchmark(main, { function main({ n, type }) { // For testing, if supplied with an empty type, default to string. - type = type || 'string'; - - const [first, second] = inputs[type]; + const [first, second] = inputs[type || 'string']; bench.start(); for (var i = 0; i < n; i++) { diff --git a/benchmark/util/inspect-array.js b/benchmark/util/inspect-array.js index 74332d18579865..8b3c54aeb942fe 100644 --- a/benchmark/util/inspect-array.js +++ b/benchmark/util/inspect-array.js @@ -18,14 +18,13 @@ function main({ n, len, type }) { var arr = Array(len); var i, opts; - // For testing, if supplied with an empty type, default to denseArray. - type = type || 'denseArray'; - switch (type) { case 'denseArray_showHidden': opts = { showHidden: true }; arr = arr.fill('denseArray'); break; + // For testing, if supplied with an empty type, default to denseArray. + case '': case 'denseArray': arr = arr.fill('denseArray'); break; diff --git a/benchmark/v8/get-stats.js b/benchmark/v8/get-stats.js index 6ee742858629c2..84a0655f5db4fa 100644 --- a/benchmark/v8/get-stats.js +++ b/benchmark/v8/get-stats.js @@ -12,9 +12,8 @@ const bench = common.createBenchmark(main, { }); function main({ method, n }) { - var i = 0; bench.start(); - for (; i < n; i++) + for (var i = 0; i < n; i++) v8[method](); bench.end(n); } diff --git a/benchmark/vm/run-in-context.js b/benchmark/vm/run-in-context.js index da8f56a6e0153b..9b57067a19c9ac 100644 --- a/benchmark/vm/run-in-context.js +++ b/benchmark/vm/run-in-context.js @@ -17,12 +17,10 @@ function main({ n, breakOnSigint, withSigintListener }) { if (withSigintListener) process.on('SIGINT', () => {}); - var i = 0; - const contextifiedSandbox = vm.createContext(); bench.start(); - for (; i < n; i++) + for (var i = 0; i < n; i++) vm.runInContext('0', contextifiedSandbox, options); bench.end(n); } diff --git a/benchmark/vm/run-in-this-context.js b/benchmark/vm/run-in-this-context.js index 33fd3a34d81f8f..0754287376d58c 100644 --- a/benchmark/vm/run-in-this-context.js +++ b/benchmark/vm/run-in-this-context.js @@ -17,10 +17,8 @@ function main({ n, breakOnSigint, withSigintListener }) { if (withSigintListener) process.on('SIGINT', () => {}); - var i = 0; - bench.start(); - for (; i < n; i++) + for (var i = 0; i < n; i++) vm.runInThisContext('0', options); bench.end(n); } From 6f2c51c46235963256ffb342e11ac69b66c06525 Mon Sep 17 00:00:00 2001 From: Ivan Filenko Date: Wed, 24 Jan 2018 01:42:40 +0300 Subject: [PATCH 034/131] src: free memory before re-setting URLHost value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/18302 PR-URL: https://github.com/nodejs/node/pull/18357 Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Tobias Nießen --- src/node_url.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/node_url.cc b/src/node_url.cc index 853a23d40d7d1e..cac2831af6ef7f 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -92,6 +92,16 @@ class URLHost { Value value_; HostType type_ = HostType::H_FAILED; + inline void Reset() { + using string = std::string; + switch (type_) { + case HostType::H_DOMAIN: value_.domain.~string(); break; + case HostType::H_OPAQUE: value_.opaque.~string(); break; + default: break; + } + type_ = HostType::H_FAILED; + } + // Setting the string members of the union with = is brittle because // it relies on them being initialized to a state that requires no // destruction of old data. @@ -101,23 +111,20 @@ class URLHost { // These helpers are the easiest solution but we might want to consider // just not forcing strings into an union. inline void SetOpaque(std::string&& string) { + Reset(); type_ = HostType::H_OPAQUE; new(&value_.opaque) std::string(std::move(string)); } inline void SetDomain(std::string&& string) { + Reset(); type_ = HostType::H_DOMAIN; new(&value_.domain) std::string(std::move(string)); } }; URLHost::~URLHost() { - using string = std::string; - switch (type_) { - case HostType::H_DOMAIN: value_.domain.~string(); break; - case HostType::H_OPAQUE: value_.opaque.~string(); break; - default: break; - } + Reset(); } #define ARGS(XX) \ From 3a15d71bbbb36f5dced6d454fd10da440df329ae Mon Sep 17 00:00:00 2001 From: Shobhit Chittora Date: Wed, 1 Nov 2017 02:12:56 +0530 Subject: [PATCH 035/131] tools: auto fix custom eslint rule 1. Extends tests 2. Refactors code 3. Adds fixer Refs: #16636 PR-URL: https://github.com/nodejs/node/pull/16652 Refs: https://github.com/nodejs/node/issues/16636 Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen --- .../test-eslint-prefer-assert-methods.js | 37 +++++++++++++------ tools/eslint-rules/prefer-assert-methods.js | 18 ++++++++- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/test/parallel/test-eslint-prefer-assert-methods.js b/test/parallel/test-eslint-prefer-assert-methods.js index 57596132d88ec3..2d05a4851bf781 100644 --- a/test/parallel/test-eslint-prefer-assert-methods.js +++ b/test/parallel/test-eslint-prefer-assert-methods.js @@ -7,31 +7,46 @@ const rule = require('../../tools/eslint-rules/prefer-assert-methods'); new RuleTester().run('prefer-assert-methods', rule, { valid: [ - 'assert.strictEqual(foo, bar)', - 'assert(foo === bar && baz)' + 'assert.strictEqual(foo, bar);', + 'assert(foo === bar && baz);', + 'assert.notStrictEqual(foo, bar);', + 'assert(foo !== bar && baz);', + 'assert.equal(foo, bar);', + 'assert(foo == bar && baz);', + 'assert.notEqual(foo, bar);', + 'assert(foo != bar && baz);', + 'assert.ok(foo);', + 'assert.ok(foo != bar);', + 'assert.ok(foo === bar && baz);' ], invalid: [ { - code: 'assert(foo == bar)', - errors: [{ message: "'assert.equal' should be used instead of '=='" }] + code: 'assert(foo == bar);', + errors: [{ + message: "'assert.equal' should be used instead of '=='" + }], + output: 'assert.equal(foo, bar);' }, { - code: 'assert(foo === bar)', + code: 'assert(foo === bar);', errors: [{ message: "'assert.strictEqual' should be used instead of '==='" - }] + }], + output: 'assert.strictEqual(foo, bar);' }, { - code: 'assert(foo != bar)', + code: 'assert(foo != bar);', errors: [{ message: "'assert.notEqual' should be used instead of '!='" - }] + }], + output: 'assert.notEqual(foo, bar);' }, { - code: 'assert(foo !== bar)', + code: 'assert(foo !== bar);', errors: [{ message: "'assert.notStrictEqual' should be used instead of '!=='" - }] - }, + }], + output: 'assert.notStrictEqual(foo, bar);' + } ] }); diff --git a/tools/eslint-rules/prefer-assert-methods.js b/tools/eslint-rules/prefer-assert-methods.js index 0604fd3ed99046..2917d40de40810 100644 --- a/tools/eslint-rules/prefer-assert-methods.js +++ b/tools/eslint-rules/prefer-assert-methods.js @@ -1,3 +1,7 @@ +/** + * @fileoverview Prohibit the use of assert operators ( ===, !==, ==, != ) + */ + 'use strict'; const astSelector = 'ExpressionStatement[expression.type="CallExpression"]' + @@ -21,7 +25,19 @@ module.exports = function(context) { const arg = node.expression.arguments[0]; const assertMethod = preferedAssertMethod[arg.operator]; if (assertMethod) { - context.report(node, parseError(assertMethod, arg.operator)); + context.report({ + node, + message: parseError(assertMethod, arg.operator), + fix: (fixer) => { + const sourceCode = context.getSourceCode(); + const left = sourceCode.getText(arg.left); + const right = sourceCode.getText(arg.right); + return fixer.replaceText( + node, + `assert.${assertMethod}(${left}, ${right});` + ); + } + }); } } }; From aa90b1a4c824604a3891f5a70362508383efe88b Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 26 Jan 2018 00:09:55 +0800 Subject: [PATCH 036/131] benchmark: cut down http benchmark run time PR-URL: https://github.com/nodejs/node/pull/18379 Reviewed-By: Jon Moss Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- benchmark/_http-benchmarkers.js | 2 +- benchmark/http/set-header.js | 32 ++++++++++++++++++++++++++++++++ benchmark/http/simple.js | 5 ++--- 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 benchmark/http/set-header.js diff --git a/benchmark/_http-benchmarkers.js b/benchmark/_http-benchmarkers.js index 55ebcc96ba21ed..76e02504b27ec1 100644 --- a/benchmark/_http-benchmarkers.js +++ b/benchmark/_http-benchmarkers.js @@ -185,7 +185,7 @@ exports.run = function(options, callback) { port: exports.PORT, path: '/', connections: 100, - duration: 10, + duration: 5, benchmarker: exports.default_http_benchmarker }, options); if (!options.benchmarker) { diff --git a/benchmark/http/set-header.js b/benchmark/http/set-header.js new file mode 100644 index 00000000000000..f0987f2cc77150 --- /dev/null +++ b/benchmark/http/set-header.js @@ -0,0 +1,32 @@ +'use strict'; +const common = require('../common.js'); +const PORT = common.PORT; + +const bench = common.createBenchmark(main, { + res: ['normal', 'setHeader', 'setHeaderWH'] +}); + +const type = 'bytes'; +const len = 4; +const chunks = 0; +const chunkedEnc = 0; +const c = 50; + +// normal: writeHead(status, {...}) +// setHeader: statusCode = status, setHeader(...) x2 +// setHeaderWH: setHeader(...), writeHead(status, ...) +function main({ res }) { + process.env.PORT = PORT; + var server = require('../fixtures/simple-http-server.js') + .listen(PORT) + .on('listening', function() { + const path = `/${type}/${len}/${chunks}/normal/${chunkedEnc}`; + + bench.http({ + path: path, + connections: c + }, function() { + server.close(); + }); + }); +} diff --git a/benchmark/http/simple.js b/benchmark/http/simple.js index bbc59a341d15ba..6d1851c45e17b2 100644 --- a/benchmark/http/simple.js +++ b/benchmark/http/simple.js @@ -7,15 +7,14 @@ const bench = common.createBenchmark(main, { len: [4, 1024, 102400], chunks: [1, 4], c: [50, 500], - chunkedEnc: [1, 0], - res: ['normal', 'setHeader', 'setHeaderWH'] + chunkedEnc: [1, 0] }); function main({ type, len, chunks, c, chunkedEnc, res }) { var server = require('../fixtures/simple-http-server.js') .listen(common.PORT) .on('listening', function() { - const path = `/${type}/${len}/${chunks}/${res}/${chunkedEnc}`; + const path = `/${type}/${len}/${chunks}/normal/${chunkedEnc}`; bench.http({ path: path, From 4dff070dd58a30d36983eb819b604242ddc842c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=88=9A?= Date: Thu, 25 Jan 2018 23:45:17 +0800 Subject: [PATCH 037/131] doc: improve stream documentation PR-URL: https://github.com/nodejs/node/pull/18375 Reviewed-By: Jon Moss Reviewed-By: Ruben Bridgewater --- doc/api/stream.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api/stream.md b/doc/api/stream.md index f4ac45837f59b0..529a6681e316b1 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -580,8 +580,8 @@ The Readable can switch back to paused mode using one of the following: * If there are no pipe destinations, by calling the [`stream.pause()`][stream-pause] method. -* If there are pipe destinations, by removing any [`'data'`][] event - handlers, and removing all pipe destinations by calling the +* If there are pipe destinations, by removing all pipe destinations. + Multiple pipe destinations may be removed by calling the [`stream.unpipe()`][] method. The important concept to remember is that a Readable will not generate data @@ -1428,7 +1428,7 @@ write succeeded. All calls to `writable.write()` that occur between the time `writable._write()` is called and the `callback` is called will cause the written data to be -buffered. Once the `callback` is invoked, the stream will emit a [`'drain'`][] +buffered. When the `callback` is invoked, the stream might emit a [`'drain'`][] event. If a stream implementation is capable of processing multiple chunks of data at once, the `writable._writev()` method should be implemented. From f939aa7d2305259eee0870b65b7d7140b8e5c751 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 29 Jan 2018 03:04:45 +0100 Subject: [PATCH 038/131] test: speed up parallel/test-tls-session-cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This test had some unnecessary timeouts that made it run for a much longer time than necessary (about 9 s rather than 0.2 s). PR-URL: https://github.com/nodejs/node/pull/18424 Reviewed-By: Colin Ihrig Reviewed-By: Weijia Wang Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- test/parallel/test-tls-session-cache.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/parallel/test-tls-session-cache.js b/test/parallel/test-tls-session-cache.js index 2bbf3b642da1b8..7778dd03100857 100644 --- a/test/parallel/test-tls-session-cache.js +++ b/test/parallel/test-tls-session-cache.js @@ -69,11 +69,11 @@ function doTest(testOptions, callback) { server.on('newSession', function(id, data, cb) { ++newSessionCount; // Emulate asynchronous store - setTimeout(function() { + setImmediate(() => { assert.ok(!session); session = { id, data }; cb(); - }, 1000); + }); }); server.on('resumeSession', function(id, callback) { ++resumeCount; @@ -89,9 +89,9 @@ function doTest(testOptions, callback) { } // Just to check that async really works there - setTimeout(function() { + setImmediate(() => { callback(null, data); - }, 100); + }); }); server.listen(0, function() { @@ -132,7 +132,7 @@ function doTest(testOptions, callback) { } assert.strictEqual(code, 0); server.close(common.mustCall(function() { - setTimeout(callback, 100); + setImmediate(callback); })); })); } From 0429820ce7daae55fa48ea377a3e867098104fa2 Mon Sep 17 00:00:00 2001 From: "Timothy O. Peters" Date: Sun, 28 Jan 2018 19:25:56 +0100 Subject: [PATCH 039/131] lib: extract validation functions PR-URL: https://github.com/nodejs/node/pull/18421 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- lib/internal/encoding.js | 59 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/lib/internal/encoding.js b/lib/internal/encoding.js index 763ee42426b343..fa178f3a8c7caa 100644 --- a/lib/internal/encoding.js +++ b/lib/internal/encoding.js @@ -32,6 +32,21 @@ function lazyBuffer() { return Buffer; } +function validateEncoder(obj) { + if (obj == null || obj[kEncoder] !== true) + throw new errors.TypeError('ERR_INVALID_THIS', 'TextEncoder'); +} + +function validateDecoder(obj) { + if (obj == null || obj[kDecoder] !== true) + throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder'); +} + +function validateArgument(prop, expected, propName, expectedName) { + if (typeof prop !== expected) + throw new errors.Error('ERR_INVALID_ARG_TYPE', propName, expectedName); +} + const CONVERTER_FLAGS_FLUSH = 0x1; const CONVERTER_FLAGS_FATAL = 0x2; const CONVERTER_FLAGS_IGNORE_BOM = 0x4; @@ -288,20 +303,17 @@ class TextEncoder { } get encoding() { - if (this == null || this[kEncoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextEncoder'); + validateEncoder(this); return 'utf-8'; } encode(input = '') { - if (this == null || this[kEncoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextEncoder'); + validateEncoder(this); return encodeUtf8String(`${input}`); } [inspect](depth, opts) { - if (this == null || this[kEncoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextEncoder'); + validateEncoder(this); if (typeof depth === 'number' && depth < 0) return opts.stylize('[Object]', 'special'); var ctor = getConstructorOf(this); @@ -329,8 +341,7 @@ const { hasConverter, TextDecoder } = makeTextDecoderJS(); function hasTextDecoder(encoding = 'utf-8') { - if (typeof encoding !== 'string') - throw new errors.Error('ERR_INVALID_ARG_TYPE', 'encoding', 'string'); + validateArgument(encoding, 'string', 'encoding', 'string'); return hasConverter(getEncodingFromLabel(encoding)); } @@ -344,8 +355,7 @@ function makeTextDecoderICU() { class TextDecoder { constructor(encoding = 'utf-8', options = {}) { encoding = `${encoding}`; - if (typeof options !== 'object') - throw new errors.Error('ERR_INVALID_ARG_TYPE', 'options', 'Object'); + validateArgument(options, 'object', 'options', 'Object'); const enc = getEncodingFromLabel(encoding); if (enc === undefined) @@ -369,17 +379,14 @@ function makeTextDecoderICU() { decode(input = empty, options = {}) { - if (this == null || this[kDecoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder'); + validateDecoder(this); if (isArrayBuffer(input)) { input = lazyBuffer().from(input); } else if (!isArrayBufferView(input)) { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'input', ['ArrayBuffer', 'ArrayBufferView']); } - if (typeof options !== 'object') { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object'); - } + validateArgument(options, 'object', 'options', 'Object'); var flags = 0; if (options !== null) @@ -416,8 +423,7 @@ function makeTextDecoderJS() { class TextDecoder { constructor(encoding = 'utf-8', options = {}) { encoding = `${encoding}`; - if (typeof options !== 'object') - throw new errors.Error('ERR_INVALID_ARG_TYPE', 'options', 'Object'); + validateArgument(options, 'object', 'options', 'Object'); const enc = getEncodingFromLabel(encoding); if (enc === undefined || !hasConverter(enc)) @@ -440,8 +446,7 @@ function makeTextDecoderJS() { } decode(input = empty, options = {}) { - if (this == null || this[kDecoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder'); + validateDecoder(this); if (isArrayBuffer(input)) { input = lazyBuffer().from(input); } else if (isArrayBufferView(input)) { @@ -451,9 +456,7 @@ function makeTextDecoderJS() { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'input', ['ArrayBuffer', 'ArrayBufferView']); } - if (typeof options !== 'object') { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object'); - } + validateArgument(options, 'object', 'options', 'Object'); if (this[kFlags] & CONVERTER_FLAGS_FLUSH) { this[kBOMSeen] = false; @@ -496,27 +499,23 @@ function makeTextDecoderJS() { TextDecoder.prototype, Object.getOwnPropertyDescriptors({ get encoding() { - if (this == null || this[kDecoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder'); + validateDecoder(this); return this[kEncoding]; }, get fatal() { - if (this == null || this[kDecoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder'); + validateDecoder(this); return (this[kFlags] & CONVERTER_FLAGS_FATAL) === CONVERTER_FLAGS_FATAL; }, get ignoreBOM() { - if (this == null || this[kDecoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder'); + validateDecoder(this); return (this[kFlags] & CONVERTER_FLAGS_IGNORE_BOM) === CONVERTER_FLAGS_IGNORE_BOM; }, [inspect](depth, opts) { - if (this == null || this[kDecoder] !== true) - throw new errors.TypeError('ERR_INVALID_THIS', 'TextDecoder'); + validateDecoder(this); if (typeof depth === 'number' && depth < 0) return opts.stylize('[Object]', 'special'); var ctor = getConstructorOf(this); From bbd2ff20097002c0db82b3700b0f4b1e98bcecda Mon Sep 17 00:00:00 2001 From: Ben Wilcox Date: Sat, 27 Jan 2018 14:39:55 -0500 Subject: [PATCH 040/131] test: show pending exception error in napi tests Shows the result of the wasPending in the error message if the assertion fails. PR-URL: https://github.com/nodejs/node/pull/18413 Reviewed-By: James M Snell Reviewed-By: Rich Trott Reviewed-By: Ruben Bridgewater --- test/addons-napi/test_exception/test.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/addons-napi/test_exception/test.js b/test/addons-napi/test_exception/test.js index 83961411df7574..787b7d78b1c72b 100644 --- a/test/addons-napi/test_exception/test.js +++ b/test/addons-napi/test_exception/test.js @@ -20,9 +20,10 @@ const theError = new Error('Some error'); // Test that the exception thrown above was marked as pending // before it was handled on the JS side - assert.strictEqual(test_exception.wasPending(), true, - 'VM was marked as having an exception pending' + - ' when it was allowed through'); + const exception_pending = test_exception.wasPending(); + assert.strictEqual(exception_pending, true, + 'Exception not pending as expected,' + + ` .wasPending() returned ${exception_pending}`); // Test that the native side does not capture a non-existing exception returnedError = test_exception.returnException(common.mustCall()); @@ -44,7 +45,8 @@ const theError = new Error('Some error'); ` ${caughtError} was passed`); // Test that the exception state remains clear when no exception is thrown - assert.strictEqual(test_exception.wasPending(), false, - 'VM was not marked as having an exception pending' + - ' when none was allowed through'); + const exception_pending = test_exception.wasPending(); + assert.strictEqual(exception_pending, false, + 'Exception state did not remain clear as expected,' + + ` .wasPending() returned ${exception_pending}`); } From 20f33e478925196a5152e060e063ab1696e67868 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 30 Jan 2018 18:41:25 +0800 Subject: [PATCH 041/131] benchmark: shorten config name in http benchmark Shorten the config name in check_invalid_header_char so it would not result in long lines that make the benchmark result hard to read. PR-URL: https://github.com/nodejs/node/pull/18452 Reviewed-By: Luigi Pinca Reviewed-By: Weijia Wang Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- benchmark/http/check_invalid_header_char.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/benchmark/http/check_invalid_header_char.js b/benchmark/http/check_invalid_header_char.js index b9933d690e25cc..399e71b2dfcc88 100644 --- a/benchmark/http/check_invalid_header_char.js +++ b/benchmark/http/check_invalid_header_char.js @@ -3,6 +3,10 @@ const common = require('../common.js'); const _checkInvalidHeaderChar = require('_http_common')._checkInvalidHeaderChar; +// Put it here so the benchmark result lines will not be super long. +const LONG_AND_INVALID = 'Here is a value that is really a folded header ' + + 'value\r\n this should be supported, but it is not currently'; + const bench = common.createBenchmark(main, { key: [ // Valid @@ -21,8 +25,7 @@ const bench = common.createBenchmark(main, { 'en-US', // Invalid - 'Here is a value that is really a folded header value\r\n this should be \ - supported, but it is not currently', + 'LONG_AND_INVALID', '中文呢', // unicode 'foo\nbar', '\x7F' @@ -31,6 +34,9 @@ const bench = common.createBenchmark(main, { }); function main({ n, key }) { + if (key === 'LONG_AND_INVALID') { + key = LONG_AND_INVALID; + } bench.start(); for (var i = 0; i < n; i++) { _checkInvalidHeaderChar(key); From bdd57cf8dbdf492d3a92991942a07d619eba2110 Mon Sep 17 00:00:00 2001 From: Qingyan Li Date: Mon, 22 Jan 2018 16:39:25 +0800 Subject: [PATCH 042/131] lib: remove debugger dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18426 Refs: https://github.com/nodejs/node/commit/719247ff9575d1a4ab6adc11e6923e9b2335053c Reviewed-By: Michaël Zasso Reviewed-By: Franziska Hinkelmann Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Eugene Ostroukhov Reviewed-By: James M Snell Reviewed-By: Jon Moss Reviewed-By: Anatoli Papirovski Reviewed-By: Ruben Bridgewater --- lib/internal/bootstrap_node.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index a6ac7b66afbc0b..6b718df2acba5a 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -60,11 +60,7 @@ NativeModule.require('internal/trace_events_async_hooks').setup(); NativeModule.require('internal/inspector_async_hook').setup(); - // Do not initialize channel in debugger agent, it deletes env variable - // and the main thread won't see it. - if (process.argv[1] !== '--debug-agent') - _process.setupChannel(); - + _process.setupChannel(); _process.setupRawDebug(); const browserGlobals = !process._noBrowserGlobals; From 06051b9e5717e4d944fda549556059a9a92138be Mon Sep 17 00:00:00 2001 From: Leko Date: Mon, 11 Dec 2017 13:05:54 +0900 Subject: [PATCH 043/131] src: allow --perf-(basic-)?prof in NODE_OPTIONS PR-URL: https://github.com/nodejs/node/pull/17600 Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Benjamin Gruenbaum Reviewed-By: Joyee Cheung Reviewed-By: Michael Dawson --- doc/api/cli.md | 2 ++ src/node.cc | 2 ++ test/parallel/test-cli-node-options.js | 9 +++++++++ 3 files changed, 13 insertions(+) diff --git a/doc/api/cli.md b/doc/api/cli.md index b8ea4826dec2fe..6bae0a67c3d101 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -475,6 +475,8 @@ Node options that are allowed are: V8 options that are allowed are: - `--abort-on-uncaught-exception` - `--max-old-space-size` +- `--perf-basic-prof` +- `--perf-prof` - `--stack-trace-limit` ### `NODE_PENDING_DEPRECATION=1` diff --git a/src/node.cc b/src/node.cc index 86cbe3138789f2..683e053c7b7d5f 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3871,6 +3871,8 @@ static void CheckIfAllowedInEnv(const char* exe, bool is_env, "--icu-data-dir", // V8 options (define with '_', which allows '-' or '_') + "--perf_prof", + "--perf_basic_prof", "--abort_on_uncaught_exception", "--max_old_space_size", "--stack_trace_limit", diff --git a/test/parallel/test-cli-node-options.js b/test/parallel/test-cli-node-options.js index 29358134c22c99..c9f2d5eace022d 100644 --- a/test/parallel/test-cli-node-options.js +++ b/test/parallel/test-cli-node-options.js @@ -26,6 +26,15 @@ expect('--zero-fill-buffers', 'B\n'); expect('--v8-pool-size=10', 'B\n'); expect('--trace-event-categories node', 'B\n'); +if (!common.isWindows) { + expect('--perf-basic-prof', 'B\n'); +} + +if (common.isLinux && ['arm', 'x64', 'mips'].includes(process.arch)) { + // PerfJitLogger is only implemented in Linux. + expect('--perf-prof', 'B\n'); +} + if (common.hasCrypto) { expect('--use-openssl-ca', 'B\n'); expect('--use-bundled-ca', 'B\n'); From a1e45b2b214dfefa361b592f2115bcd3a97a5e93 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Wed, 24 Jan 2018 10:42:54 -0800 Subject: [PATCH 044/131] deps: update node-inspect to 1.11.3 Highlights: * Using a random port works (`node inspect --port=0 script.js`) * `takeHeapSnapshot()` creates valid snapshots again PR-URL: https://github.com/nodejs/node/pull/18354 Reviewed-By: Richard Lau --- deps/node-inspect/CHANGELOG.md | 9 +++++ deps/node-inspect/README.md | 2 +- deps/node-inspect/lib/_inspect.js | 31 ++++++-------- .../lib/internal/inspect_client.js | 10 +++-- .../node-inspect/lib/internal/inspect_repl.js | 20 +++++----- deps/node-inspect/package.json | 4 +- deps/node-inspect/test/cli/break.test.js | 4 +- .../test/cli/heap-profiler.test.js | 34 ++++++++++++++++ deps/node-inspect/test/cli/launch.test.js | 40 +++++++++++++++++++ deps/node-inspect/test/cli/start-cli.js | 4 +- 10 files changed, 118 insertions(+), 40 deletions(-) create mode 100644 deps/node-inspect/test/cli/heap-profiler.test.js diff --git a/deps/node-inspect/CHANGELOG.md b/deps/node-inspect/CHANGELOG.md index 41ed928e781ff6..0db3a7842eb15d 100644 --- a/deps/node-inspect/CHANGELOG.md +++ b/deps/node-inspect/CHANGELOG.md @@ -1,3 +1,12 @@ +### 1.11.3 + +* [`93caa0f`](https://github.com/nodejs/node-inspect/commit/93caa0f5267c7ab452b258d3b03329a0bb5ac7f7) **docs:** Add missing oc in protocol +* [`2d87cbe`](https://github.com/nodejs/node-inspect/commit/2d87cbe76aa968dfc1ac69d9571af1be81abd8e0) **fix:** Make --inspect-port=0 work +* [`ebfd02e`](https://github.com/nodejs/node-inspect/commit/ebfd02ece9b642586023f7791da71defeb13d746) **chore:** Bump tap to 10.7 +* [`c07adb1`](https://github.com/nodejs/node-inspect/commit/c07adb17b164c1cf3da8d38659ea9f5d7ff42e9c) **test:** Use useful break location +* [`94f0bf9`](https://github.com/nodejs/node-inspect/commit/94f0bf97d24c376baf3ecced2088d81715a73464) **fix:** Fix `takeHeapSnapshot()` truncation bug + + ### 1.11.2 * [`42e0cd1`](https://github.com/nodejs/node-inspect/commit/42e0cd111d89ed09faba1c0ec45089b0b44de011) **fix:** look for generic hint text diff --git a/deps/node-inspect/README.md b/deps/node-inspect/README.md index ecd939b3ea26a8..b52cc188a62f5b 100644 --- a/deps/node-inspect/README.md +++ b/deps/node-inspect/README.md @@ -10,7 +10,7 @@ node has two options: 1. `node --debug `: Start `file` with remote debugging enabled. 2. `node debug `: Start an interactive CLI debugger for ``. -But for the Chrome inspector protol, +But for the Chrome inspector protocol, there's only one: `node --inspect `. This project tries to provide the missing second option diff --git a/deps/node-inspect/lib/_inspect.js b/deps/node-inspect/lib/_inspect.js index 26912274cdaec4..d846efbe6a4a52 100644 --- a/deps/node-inspect/lib/_inspect.js +++ b/deps/node-inspect/lib/_inspect.js @@ -42,18 +42,9 @@ const [ InspectClient, createRepl ] = const debuglog = util.debuglog('inspect'); -const DEBUG_PORT_PATTERN = /^--(?:debug|inspect)(?:-port|-brk)?=(\d{1,5})$/; -function getDefaultPort() { - for (const arg of process.execArgv) { - const match = arg.match(DEBUG_PORT_PATTERN); - if (match) { - return +match[1]; - } - } - return 9229; -} - function portIsFree(host, port, timeout = 2000) { + if (port === 0) return Promise.resolve(); // Binding to a random port. + const retryDelay = 150; let didTimeOut = false; @@ -110,9 +101,11 @@ function runScript(script, scriptArgs, inspectHost, inspectPort, childPrint) { let output = ''; function waitForListenHint(text) { output += text; - if (/Debugger listening on/.test(output)) { + if (/Debugger listening on ws:\/\/\[?(.+?)\]?:(\d+)\//.test(output)) { + const host = RegExp.$1; + const port = Number.parseInt(RegExp.$2); child.stderr.removeListener('data', waitForListenHint); - resolve(child); + resolve([child, port, host]); } } @@ -160,10 +153,11 @@ class NodeInspector { options.port, this.childPrint.bind(this)); } else { - this._runScript = () => Promise.resolve(null); + this._runScript = + () => Promise.resolve([null, options.port, options.host]); } - this.client = new InspectClient(options.port, options.host); + this.client = new InspectClient(); this.domainNames = ['Debugger', 'HeapProfiler', 'Profiler', 'Runtime']; this.domainNames.forEach((domain) => { @@ -223,9 +217,8 @@ class NodeInspector { run() { this.killChild(); - const { host, port } = this.options; - return this._runScript().then((child) => { + return this._runScript().then(([child, port, host]) => { this.child = child; let connectionAttempts = 0; @@ -233,7 +226,7 @@ class NodeInspector { ++connectionAttempts; debuglog('connection attempt #%d', connectionAttempts); this.stdout.write('.'); - return this.client.connect() + return this.client.connect(port, host) .then(() => { debuglog('connection established'); this.stdout.write(' ok'); @@ -288,7 +281,7 @@ class NodeInspector { function parseArgv([target, ...args]) { let host = '127.0.0.1'; - let port = getDefaultPort(); + let port = 9229; let isRemote = false; let script = target; let scriptArgs = args; diff --git a/deps/node-inspect/lib/internal/inspect_client.js b/deps/node-inspect/lib/internal/inspect_client.js index c247e2add87706..9b8529de21aae2 100644 --- a/deps/node-inspect/lib/internal/inspect_client.js +++ b/deps/node-inspect/lib/internal/inspect_client.js @@ -164,12 +164,12 @@ function decodeFrameHybi17(data) { } class Client extends EventEmitter { - constructor(port, host) { + constructor() { super(); this.handleChunk = this._handleChunk.bind(this); - this._port = port; - this._host = host; + this._port = undefined; + this._host = undefined; this.reset(); } @@ -284,7 +284,9 @@ class Client extends EventEmitter { }); } - connect() { + connect(port, host) { + this._port = port; + this._host = host; return this._discoverWebsocketPath() .then((urlPath) => this._connectWebsocket(urlPath)); } diff --git a/deps/node-inspect/lib/internal/inspect_repl.js b/deps/node-inspect/lib/internal/inspect_repl.js index 937c1843d3a3ee..38fe4684cf6d71 100644 --- a/deps/node-inspect/lib/internal/inspect_repl.js +++ b/deps/node-inspect/lib/internal/inspect_repl.js @@ -900,10 +900,8 @@ function createRepl(inspector) { return new Promise((resolve, reject) => { const absoluteFile = Path.resolve(filename); const writer = FS.createWriteStream(absoluteFile); - let totalSize; let sizeWritten = 0; function onProgress({ done, total, finished }) { - totalSize = total; if (finished) { print('Heap snaphost prepared.'); } else { @@ -913,13 +911,18 @@ function createRepl(inspector) { function onChunk({ chunk }) { sizeWritten += chunk.length; writer.write(chunk); - print(`Writing snapshot: ${sizeWritten}/${totalSize}`, true); - if (sizeWritten >= totalSize) { - writer.end(); + print(`Writing snapshot: ${sizeWritten}`, true); + } + function onResolve() { + writer.end(() => { teardown(); print(`Wrote snapshot: ${absoluteFile}`); resolve(); - } + }); + } + function onReject(error) { + teardown(); + reject(error); } function teardown() { HeapProfiler.removeListener( @@ -932,10 +935,7 @@ function createRepl(inspector) { print('Heap snapshot: 0/0', true); HeapProfiler.takeHeapSnapshot({ reportProgress: true }) - .then(null, (error) => { - teardown(); - reject(error); - }); + .then(onResolve, onReject); }); }, diff --git a/deps/node-inspect/package.json b/deps/node-inspect/package.json index 070abfa8fe51be..d25376b5d4bb96 100644 --- a/deps/node-inspect/package.json +++ b/deps/node-inspect/package.json @@ -1,6 +1,6 @@ { "name": "node-inspect", - "version": "1.11.2", + "version": "1.11.3", "description": "Node Inspect", "license": "MIT", "main": "lib/_inspect.js", @@ -29,7 +29,7 @@ "devDependencies": { "eslint": "^3.10.2", "nlm": "^3.0.0", - "tap": "^7.1.2" + "tap": "^10.7.0" }, "author": { "name": "Jan Krems", diff --git a/deps/node-inspect/test/cli/break.test.js b/deps/node-inspect/test/cli/break.test.js index 59b12cde388c01..ce8c8d6d7d99bd 100644 --- a/deps/node-inspect/test/cli/break.test.js +++ b/deps/node-inspect/test/cli/break.test.js @@ -134,7 +134,7 @@ test('sb before loading file', (t) => { return cli.waitForInitialBreak() .then(() => cli.waitForPrompt()) - .then(() => cli.command('sb("other.js", 3)')) + .then(() => cli.command('sb("other.js", 2)')) .then(() => { t.match( cli.output, @@ -145,7 +145,7 @@ test('sb before loading file', (t) => { .then(() => { t.match( cli.output, - `break in ${otherScript}:3`, + `break in ${otherScript}:2`, 'found breakpoint in file that was not loaded yet'); }) .then(() => cli.quit()) diff --git a/deps/node-inspect/test/cli/heap-profiler.test.js b/deps/node-inspect/test/cli/heap-profiler.test.js new file mode 100644 index 00000000000000..ebd734e03cb06d --- /dev/null +++ b/deps/node-inspect/test/cli/heap-profiler.test.js @@ -0,0 +1,34 @@ +'use strict'; +const { test } = require('tap'); +const { readFileSync, unlinkSync } = require('fs'); + +const startCLI = require('./start-cli'); +const filename = 'node.heapsnapshot'; + +function cleanup() { + try { + unlinkSync(filename); + } catch (_) { + // Ignore. + } +} + +cleanup(); + +test('Heap profiler take snapshot', (t) => { + const cli = startCLI(['examples/empty.js']); + + function onFatal(error) { + cli.quit(); + throw error; + } + + // Check that the snapshot is valid JSON. + return cli.waitForInitialBreak() + .then(() => cli.waitForPrompt()) + .then(() => cli.command('takeHeapSnapshot()')) + .then(() => JSON.parse(readFileSync(filename, 'utf8'))) + .then(() => cleanup()) + .then(() => cli.quit()) + .then(null, onFatal); +}); diff --git a/deps/node-inspect/test/cli/launch.test.js b/deps/node-inspect/test/cli/launch.test.js index f7efc6eb3f2139..8808d47a08b900 100644 --- a/deps/node-inspect/test/cli/launch.test.js +++ b/deps/node-inspect/test/cli/launch.test.js @@ -26,6 +26,46 @@ test('custom port', (t) => { }); }); +test('random port', (t) => { + const script = Path.join('examples', 'three-lines.js'); + + const cli = startCLI(['--port=0', script]); + + return cli.waitForInitialBreak() + .then(() => cli.waitForPrompt()) + .then(() => { + t.match(cli.output, 'debug>', 'prints a prompt'); + t.match( + cli.output, + /< Debugger listening on /, + 'forwards child output'); + }) + .then(() => cli.quit()) + .then((code) => { + t.equal(code, 0, 'exits with success'); + }); +}); + +test('random port with --inspect-port=0', (t) => { + const script = Path.join('examples', 'three-lines.js'); + + const cli = startCLI([script], ['--inspect-port=0']); + + return cli.waitForInitialBreak() + .then(() => cli.waitForPrompt()) + .then(() => { + t.match(cli.output, 'debug>', 'prints a prompt'); + t.match( + cli.output, + /< Debugger listening on /, + 'forwards child output'); + }) + .then(() => cli.quit()) + .then((code) => { + t.equal(code, 0, 'exits with success'); + }); +}); + test('examples/three-lines.js', (t) => { const script = Path.join('examples', 'three-lines.js'); const cli = startCLI([script]); diff --git a/deps/node-inspect/test/cli/start-cli.js b/deps/node-inspect/test/cli/start-cli.js index ae904308e02270..b086dcd8ba218d 100644 --- a/deps/node-inspect/test/cli/start-cli.js +++ b/deps/node-inspect/test/cli/start-cli.js @@ -16,8 +16,8 @@ const BREAK_MESSAGE = new RegExp('(?:' + [ 'exception', 'other', 'promiseRejection', ].join('|') + ') in', 'i'); -function startCLI(args) { - const child = spawn(process.execPath, [CLI, ...args]); +function startCLI(args, flags = []) { + const child = spawn(process.execPath, [...flags, CLI, ...args]); let isFirstStdoutChunk = true; const outputBuffer = []; From dfa467fb55f4b327f49a5b62d27d6c4fe62d4148 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 29 Jan 2018 13:58:45 -0800 Subject: [PATCH 045/131] benchmark: spread operator benchmark Benchmark comparing `util._extend()`, `Object.assign()`, and the spread operator for object assignment. `util._extend()` still wins currently. PR-URL: https://github.com/nodejs/node/pull/18442 Reviewed-By: Colin Ihrig Reviewed-By: Weijia Wang Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Yuta Hiroto --- benchmark/es/spread-assign.js | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 benchmark/es/spread-assign.js diff --git a/benchmark/es/spread-assign.js b/benchmark/es/spread-assign.js new file mode 100644 index 00000000000000..00c634ff879501 --- /dev/null +++ b/benchmark/es/spread-assign.js @@ -0,0 +1,46 @@ +'use strict'; + +const common = require('../common.js'); +const util = require('util'); + +const bench = common.createBenchmark(main, { + method: ['spread', 'assign', '_extend'], + count: [5, 10, 20], + millions: [1] +}); + +function main({ millions, context, count, rest, method }) { + const n = millions * 1e6; + + const src = {}; + for (let n = 0; n < count; n++) + src[`p${n}`] = n; + + let obj; // eslint-disable-line + let i; + + switch (method) { + case '': + // Empty string falls through to next line as default, mostly for tests. + case '_extend': + bench.start(); + for (i = 0; i < n; i++) + obj = util._extend({}, src); + bench.end(n); + break; + case 'assign': + bench.start(); + for (i = 0; i < n; i++) + obj = Object.assign({}, src); + bench.end(n); + break; + case 'spread': + bench.start(); + for (i = 0; i < n; i++) + obj = { ...src }; + bench.end(n); + break; + default: + throw new Error('Unexpected method'); + } +} From 3d8db8b9463c3ae60f7589c33ee14ee0b7f6fea3 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 31 Jan 2018 16:02:35 -0800 Subject: [PATCH 046/131] test: mark test-inspector-stop-profile-after-done flaky This test is consistently failing and making CI red. PR-URL: https://github.com/nodejs/node/pull/18491 Refs: https://github.com/nodejs/node/issues/16772 Reviewed-By: Gibson Fahnestock Reviewed-By: Colin Ihrig --- test/sequential/sequential.status | 1 + 1 file changed, 1 insertion(+) diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status index b95db2a111ea67..5c0b460154f84f 100644 --- a/test/sequential/sequential.status +++ b/test/sequential/sequential.status @@ -13,6 +13,7 @@ test-inspector-debug-end : PASS, FLAKY test-inspector-async-hook-setup-at-signal: PASS, FLAKY test-http2-ping-flood : PASS, FLAKY test-http2-settings-flood : PASS, FLAKY +test-inspector-stop-profile-after-done: PASS, FLAKY [$system==linux] From b2eff72deb33961a2edcff7e5b797cf80ba2852d Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Tue, 30 Jan 2018 13:49:40 -0800 Subject: [PATCH 047/131] async_hooks: clean up comments With some of the recent work, some of the comments were no longer representative of the code, or were otherwise unclear. This commit fixes some obvious issues I found. Ref: https://github.com/nodejs/node/commit/83e5215a4e8438a43b9f0002b7a43e2fd2dd37a4 Ref: https://github.com/nodejs/node/commit/0784b0440c05464f79b857f7d8698fcc953d3fb3 PR-URL: https://github.com/nodejs/node/pull/18467 Reviewed-By: Andreas Madsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater --- lib/internal/async_hooks.js | 23 ++++++++++++----------- src/async_wrap.cc | 4 ++-- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 26da41cacf354a..1e9b89ce5e65ff 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -11,16 +11,17 @@ const async_wrap = process.binding('async_wrap'); * the various asynchronous states of the application. These are: * kExecutionAsyncId: The async_id assigned to the resource responsible for the * current execution stack. - * kTriggerAsyncId: The trigger_async_id of the resource responsible for - * the current execution stack. + * kTriggerAsyncId: The async_id of the resource that caused (or 'triggered') + * the resource corresponding to the current execution stack. * kAsyncIdCounter: Incremental counter tracking the next assigned async_id. * kDefaultTriggerAsyncId: Written immediately before a resource's constructor - * that sets the value of the init()'s triggerAsyncId. The order of - * retrieving the triggerAsyncId value is passing directly to the - * constructor -> value set in kDefaultTriggerAsyncId -> executionAsyncId of - * the current resource. + * that sets the value of the init()'s triggerAsyncId. The precedence order + * of retrieving the triggerAsyncId value is: + * 1. the value passed directly to the constructor + * 2. value set in kDefaultTriggerAsyncId + * 3. executionAsyncId of the current resource. * - * async_ids_fast_stack is a Float64Array that contains part of the async ID + * async_ids_stack is a Float64Array that contains part of the async ID * stack. Each pushAsyncIds() call adds two doubles to it, and each * popAsyncIds() call removes two doubles from it. * It has a fixed size, so if that is exceeded, calls to the native @@ -28,10 +29,10 @@ const async_wrap = process.binding('async_wrap'); */ const { async_id_symbol, async_hook_fields, async_id_fields } = async_wrap; // Store the pair executionAsyncId and triggerAsyncId in a std::stack on -// Environment::AsyncHooks::ids_stack_ tracks the resource responsible for the -// current execution stack. This is unwound as each resource exits. In the case -// of a fatal exception this stack is emptied after calling each hook's after() -// callback. +// Environment::AsyncHooks::async_ids_stack_ tracks the resource responsible for +// the current execution stack. This is unwound as each resource exits. In the +// case of a fatal exception this stack is emptied after calling each hook's +// after() callback. const { pushAsyncIds: pushAsyncIds_, popAsyncIds: popAsyncIds_ } = async_wrap; // For performance reasons, only track Promises when a hook is enabled. const { enablePromiseHook, disablePromiseHook } = async_wrap; diff --git a/src/async_wrap.cc b/src/async_wrap.cc index f770348b9c9183..20d21e31df8d5b 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -532,12 +532,12 @@ void AsyncWrap::Initialize(Local target, // this way to allow JS and C++ to read/write each value as quickly as // possible. The fields are represented as follows: // - // kAsyncUid: Maintains the state of the next unique id to be assigned. + // kAsyncIdCounter: Maintains the state of the next unique id to be assigned. // // kDefaultTriggerAsyncId: Write the id of the resource responsible for a // handle's creation just before calling the new handle's constructor. // After the new handle is constructed kDefaultTriggerAsyncId is set back - // to 0. + // to -1. FORCE_SET_TARGET_FIELD(target, "async_id_fields", env->async_hooks()->async_id_fields().GetJSArray()); From a418ae579944a64b117e8518478e4a745f7ee99c Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 31 Jan 2018 09:36:51 -0800 Subject: [PATCH 048/131] doc: move Brian White to TSC Emeriti list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18482 Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso Reviewed-By: Daniel Bevenius Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Jon Moss Reviewed-By: Evan Lucas Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Michael Dawson --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2e8139bd1f98d7..42ac41871bb937 100644 --- a/README.md +++ b/README.md @@ -257,8 +257,6 @@ For more information about the governance of the Node.js project, see **Matteo Collina** <matteo.collina@gmail.com> (he/him) * [mhdawson](https://github.com/mhdawson) - **Michael Dawson** <michael_dawson@ca.ibm.com> (he/him) -* [mscdex](https://github.com/mscdex) - -**Brian White** <mscdex@mscdex.net> * [MylesBorins](https://github.com/MylesBorins) - **Myles Borins** <myles.borins@gmail.com> (he/him) * [ofrobots](https://github.com/ofrobots) - @@ -284,6 +282,8 @@ For more information about the governance of the Node.js project, see **Isaac Z. Schlueter** <i@izs.me> * [joshgav](https://github.com/joshgav) - **Josh Gavant** <josh.gavant@outlook.com> +* [mscdex](https://github.com/mscdex) - +**Brian White** <mscdex@mscdex.net> * [nebrius](https://github.com/nebrius) - **Bryan Hughes** <bryan@nebri.us> * [orangemocha](https://github.com/orangemocha) - From 8d37cca5f342381002125fc235586fbfbce48613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=88=9A?= Date: Sun, 14 Jan 2018 23:34:18 +0800 Subject: [PATCH 049/131] stream: delete redundant code In `Writable.prototype.end()`, `state.ending` is true after calling `endWritable()` and it doesn't reset to false. In `Writable.prototype.uncork()`, `state.finished` must be false if `state.bufferedRequest` is true. PR-URL: https://github.com/nodejs/node/pull/18145 Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina --- lib/_stream_writable.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 895563bb39de25..b259d31cd9fcde 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -307,7 +307,6 @@ Writable.prototype.uncork = function() { if (!state.writing && !state.corked && - !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); @@ -579,7 +578,7 @@ Writable.prototype.end = function(chunk, encoding, cb) { } // ignore unnecessary end() calls. - if (!state.ending && !state.finished) + if (!state.ending) endWritable(this, state, cb); }; From 524f93f5d20a4c077869df11b363c0022896f049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=88=9A?= Date: Mon, 15 Jan 2018 14:45:11 +0800 Subject: [PATCH 050/131] stream: delete redundant code `state.corkedRequestsFree` of a writable stream is always not null. PR-URL: https://github.com/nodejs/node/pull/18145 Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina --- lib/_stream_writable.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index b259d31cd9fcde..9c1b32b81dc957 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -657,11 +657,9 @@ function onCorkedFinish(corkReq, state, err) { cb(err); entry = entry.next; } - if (state.corkedRequestsFree) { - state.corkedRequestsFree.next = corkReq; - } else { - state.corkedRequestsFree = corkReq; - } + + // reuse the free corkReq. + state.corkedRequestsFree.next = corkReq; } Object.defineProperty(Writable.prototype, 'destroyed', { From 582fa6aa7258a26c6d22a589c362affdd47991ed Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 30 Jan 2018 20:27:17 +0100 Subject: [PATCH 051/131] process: fix reading zero-length env vars on win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up until now, Node did not clear the current error code attempting to read environment variables on Windows. Since checking the error code is the way we distinguish between missing and zero-length environment variables, this could lead to a false positive when the error code was still tainted. In the simplest case, accessing a missing variable and then a zero-length one would lead Node to believe that both calls yielded an error. Before: > process.env.I=''; process.env.Q; process.env.I undefined > process.env.I=''; /*process.env.Q;*/ process.env.I '' After: > process.env.I=''; process.env.Q; process.env.I '' > process.env.I=''; /*process.env.Q;*/ process.env.I '' This only affects Node 8 and above, since before 1aa595e5bd64241451b3884d3029b9b9aa97c42d we always constructed a `v8::String::Value` instance for passing the lookup key to the OS, which in in turn always made a heap allocation and therefore reset the error code. PR-URL: https://github.com/nodejs/node/pull/18463 Reviewed-By: Ben Noordhuis Reviewed-By: Jeremiah Senkpiel Reviewed-By: Fedor Indutny Reviewed-By: Tobias Nießen Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Ruben Bridgewater --- src/node.cc | 2 ++ .../test-process-env-windows-error-reset.js | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 test/parallel/test-process-env-windows-error-reset.js diff --git a/src/node.cc b/src/node.cc index 683e053c7b7d5f..39f441b1eab539 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2916,6 +2916,7 @@ static void EnvGetter(Local property, #else // _WIN32 node::TwoByteValue key(isolate, property); WCHAR buffer[32767]; // The maximum size allowed for environment variables. + SetLastError(ERROR_SUCCESS); DWORD result = GetEnvironmentVariableW(reinterpret_cast(*key), buffer, arraysize(buffer)); @@ -2964,6 +2965,7 @@ static void EnvQuery(Local property, #else // _WIN32 node::TwoByteValue key(info.GetIsolate(), property); WCHAR* key_ptr = reinterpret_cast(*key); + SetLastError(ERROR_SUCCESS); if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 || GetLastError() == ERROR_SUCCESS) { rc = 0; diff --git a/test/parallel/test-process-env-windows-error-reset.js b/test/parallel/test-process-env-windows-error-reset.js new file mode 100644 index 00000000000000..59e5f287d82346 --- /dev/null +++ b/test/parallel/test-process-env-windows-error-reset.js @@ -0,0 +1,22 @@ +'use strict'; +require('../common'); +const assert = require('assert'); + +// This checks that after accessing a missing env var, a subsequent +// env read will succeed even for empty variables. + +{ + process.env.FOO = ''; + process.env.NONEXISTENT_ENV_VAR; + const foo = process.env.FOO; + + assert.strictEqual(foo, ''); +} + +{ + process.env.FOO = ''; + process.env.NONEXISTENT_ENV_VAR; + const hasFoo = 'FOO' in process.env; + + assert.strictEqual(hasFoo, true); +} From c7f14827804c935fa9edf344d240dfb0c97d000c Mon Sep 17 00:00:00 2001 From: Aaron Bieber Date: Mon, 29 Jan 2018 20:05:51 -0700 Subject: [PATCH 052/131] v8: add missing ',' in OpenBSD's 'sources' section. Add stack_trace_posix to 'sources' as well. Fixes https://github.com/nodejs/node/issues/15784 Fixes https://github.com/nodejs/help/issues/992 add stack_trace_posix to OpenBSD's sources PR-URL: https://github.com/nodejs/node/pull/18448 Reviewed-By: Daniel Bevenius Reviewed-By: James M Snell --- deps/v8/src/v8.gyp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deps/v8/src/v8.gyp b/deps/v8/src/v8.gyp index bf7635ee339e2a..1c56842f81a548 100644 --- a/deps/v8/src/v8.gyp +++ b/deps/v8/src/v8.gyp @@ -2044,9 +2044,10 @@ '-L/usr/local/lib -lexecinfo', ]}, 'sources': [ + 'base/debug/stack_trace_posix.cc', 'base/platform/platform-openbsd.cc', 'base/platform/platform-posix.h', - 'base/platform/platform-posix.cc' + 'base/platform/platform-posix.cc', 'base/platform/platform-posix-time.h', 'base/platform/platform-posix-time.cc', ], From 680ca8a5c7327c7087d7ef073152b54ff7a04a33 Mon Sep 17 00:00:00 2001 From: Aaron Bieber Date: Tue, 30 Jan 2018 15:14:27 -0700 Subject: [PATCH 053/131] build: add cflags for OpenBSD, remove stray comma. PR-URL: https://github.com/nodejs/node/pull/18448 Reviewed-By: Daniel Bevenius Reviewed-By: James M Snell --- common.gypi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common.gypi b/common.gypi index 0108301e3fb28c..08ef48ccedcccf 100644 --- a/common.gypi +++ b/common.gypi @@ -288,7 +288,7 @@ ], }], [ 'OS in "linux freebsd openbsd solaris aix"', { - 'cflags': [ '-pthread', ], + 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], [ 'OS in "linux freebsd openbsd solaris android aix cloudabi"', { @@ -301,6 +301,7 @@ 'standalone_static_library': 1, }], ['OS=="openbsd"', { + 'cflags': [ '-I/usr/local/include' ], 'ldflags': [ '-Wl,-z,wxneeded' ], }], ], From 8621f55845125b1cd1d797bb26935bc1022012ae Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 31 Jan 2018 09:53:10 -0800 Subject: [PATCH 054/131] doc: streamline README intro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shorten text that is duplicated from website and supply link. PR-URL: https://github.com/nodejs/node/pull/18483 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Luigi Pinca Reviewed-By: Joyee Cheung Reviewed-By: Daniel Bevenius Reviewed-By: Ruben Bridgewater --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 42ac41871bb937..fec27447c24cbc 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,9 @@

-Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js -uses an event-driven, non-blocking I/O model that makes it lightweight and -efficient. The Node.js package ecosystem, [npm][], is the largest ecosystem of -open source libraries in the world. +Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. For +more information on using Node.js, see the +[Node.js Website][]. The Node.js project is supported by the [Node.js Foundation](https://nodejs.org/en/foundation/). Contributions, @@ -593,7 +592,6 @@ Previous releases may also have been signed with one of the following GPG keys: * [Contributing to the project][] * [Working Groups][] -[npm]: https://www.npmjs.com [Code of Conduct]: https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md [Contributing to the project]: CONTRIBUTING.md [Node.js Help]: https://github.com/nodejs/help From 9a8bc9af60c4e0616af16e8b9d70d9d7095dc5a6 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 1 Feb 2018 01:12:05 -0500 Subject: [PATCH 055/131] string_decoder: reset decoder on end This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: https://github.com/nodejs/node/pull/18494 Fixes: https://github.com/nodejs/node/issues/16564 Refs: https://github.com/nodejs/node/pull/16594 Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen --- lib/string_decoder.js | 15 +++++-- test/parallel/test-string-decoder-end.js | 51 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/lib/string_decoder.js b/lib/string_decoder.js index 891ab5bdba65f3..1e569ba6b26a4c 100644 --- a/lib/string_decoder.js +++ b/lib/string_decoder.js @@ -210,8 +210,11 @@ function utf8Text(buf, i) { // character. function utf8End(buf) { const r = (buf && buf.length ? this.write(buf) : ''); - if (this.lastNeed) + if (this.lastNeed) { + this.lastNeed = 0; + this.lastTotal = 0; return r + '\ufffd'; + } return r; } @@ -246,6 +249,8 @@ function utf16End(buf) { const r = (buf && buf.length ? this.write(buf) : ''); if (this.lastNeed) { const end = this.lastTotal - this.lastNeed; + this.lastNeed = 0; + this.lastTotal = 0; return r + this.lastChar.toString('utf16le', 0, end); } return r; @@ -269,8 +274,12 @@ function base64Text(buf, i) { function base64End(buf) { const r = (buf && buf.length ? this.write(buf) : ''); - if (this.lastNeed) - return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + if (this.lastNeed) { + const end = 3 - this.lastNeed; + this.lastNeed = 0; + this.lastTotal = 0; + return r + this.lastChar.toString('base64', 0, end); + } return r; } diff --git a/test/parallel/test-string-decoder-end.js b/test/parallel/test-string-decoder-end.js index 0284ee9f6c48c7..2762ef096289db 100644 --- a/test/parallel/test-string-decoder-end.js +++ b/test/parallel/test-string-decoder-end.js @@ -39,6 +39,46 @@ for (let i = 1; i <= 16; i++) { encodings.forEach(testEncoding); +testEnd('utf8', Buffer.of(0xE2), Buffer.of(0x61), '\uFFFDa'); +testEnd('utf8', Buffer.of(0xE2), Buffer.of(0x82), '\uFFFD\uFFFD'); +testEnd('utf8', Buffer.of(0xE2), Buffer.of(0xE2), '\uFFFD\uFFFD'); +testEnd('utf8', Buffer.of(0xE2, 0x82), Buffer.of(0x61), '\uFFFDa'); +testEnd('utf8', Buffer.of(0xE2, 0x82), Buffer.of(0xAC), '\uFFFD\uFFFD'); +testEnd('utf8', Buffer.of(0xE2, 0x82), Buffer.of(0xE2), '\uFFFD\uFFFD'); +testEnd('utf8', Buffer.of(0xE2, 0x82, 0xAC), Buffer.of(0x61), '€a'); + +testEnd('utf16le', Buffer.of(0x3D), Buffer.of(0x61, 0x00), 'a'); +testEnd('utf16le', Buffer.of(0x3D), Buffer.of(0xD8, 0x4D, 0xDC), '\u4DD8'); +testEnd('utf16le', Buffer.of(0x3D, 0xD8), Buffer.of(), '\uD83D'); +testEnd('utf16le', Buffer.of(0x3D, 0xD8), Buffer.of(0x61, 0x00), '\uD83Da'); +testEnd( + 'utf16le', + Buffer.of(0x3D, 0xD8), + Buffer.of(0x4D, 0xDC), + '\uD83D\uDC4D' +); +testEnd('utf16le', Buffer.of(0x3D, 0xD8, 0x4D), Buffer.of(), '\uD83D'); +testEnd( + 'utf16le', + Buffer.of(0x3D, 0xD8, 0x4D), + Buffer.of(0x61, 0x00), + '\uD83Da' +); +testEnd('utf16le', Buffer.of(0x3D, 0xD8, 0x4D), Buffer.of(0xDC), '\uD83D'); +testEnd( + 'utf16le', + Buffer.of(0x3D, 0xD8, 0x4D, 0xDC), + Buffer.of(0x61, 0x00), + '👍a' +); + +testEnd('base64', Buffer.of(0x61), Buffer.of(), 'YQ=='); +testEnd('base64', Buffer.of(0x61), Buffer.of(0x61), 'YQ==YQ=='); +testEnd('base64', Buffer.of(0x61, 0x61), Buffer.of(), 'YWE='); +testEnd('base64', Buffer.of(0x61, 0x61), Buffer.of(0x61), 'YWE=YQ=='); +testEnd('base64', Buffer.of(0x61, 0x61, 0x61), Buffer.of(), 'YWFh'); +testEnd('base64', Buffer.of(0x61, 0x61, 0x61), Buffer.of(0x61), 'YWFhYQ=='); + function testEncoding(encoding) { bufs.forEach((buf) => { testBuf(encoding, buf); @@ -66,3 +106,14 @@ function testBuf(encoding, buf) { assert.strictEqual(res1, res3, 'one byte at a time should match toString'); assert.strictEqual(res2, res3, 'all bytes at once should match toString'); } + +function testEnd(encoding, incomplete, next, expected) { + let res = ''; + const s = new SD(encoding); + res += s.write(incomplete); + res += s.end(); + res += s.write(next); + res += s.end(); + + assert.strictEqual(res, expected); +} From fe32d68e68e466bec90bcb515b68b8b2852549c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=88=9A?= Date: Sun, 21 Jan 2018 16:13:14 +0800 Subject: [PATCH 056/131] stream: delete unused code In implementation of `stream.Writable`, `writable._write()` is always called with a callback that is `_writableState.onwrite()`. And In `afterTransform()`, `ts.writechunk` and `ts.writecb` are assigned to null. So, `ts.writecb` is a true value if `ts.writechunk` isn't null. PR-URL: https://github.com/nodejs/node/pull/18278 Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- lib/_stream_transform.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/_stream_transform.js b/lib/_stream_transform.js index b8d4a7704aebdb..a9fcddda2d9c83 100644 --- a/lib/_stream_transform.js +++ b/lib/_stream_transform.js @@ -180,7 +180,7 @@ Transform.prototype._write = function(chunk, encoding, cb) { Transform.prototype._read = function(n) { var ts = this._transformState; - if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + if (ts.writechunk !== null && !ts.transforming) { ts.transforming = true; this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); } else { From 1385daf4a1c6f76d7e8e347fb2a2529e1acf6882 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Mon, 22 Jan 2018 23:13:02 -0500 Subject: [PATCH 057/131] n-api: implement wrapping using private properties PR-URL: https://github.com/nodejs/node/pull/18311 Reviewed-By: Anna Henningsen Reviewed-By: Michael Dawson Fixes: https://github.com/nodejs/node/issues/14367 --- src/env.h | 2 + src/node_api.cc | 160 +++++++++++++++--------------------------------- 2 files changed, 52 insertions(+), 110 deletions(-) diff --git a/src/env.h b/src/env.h index bc08e6baef280a..5ebd56a3fff633 100644 --- a/src/env.h +++ b/src/env.h @@ -91,6 +91,8 @@ class ModuleWrap; V(decorated_private_symbol, "node:decorated") \ V(npn_buffer_private_symbol, "node:npnBuffer") \ V(selected_npn_buffer_private_symbol, "node:selectedNpnBuffer") \ + V(napi_env, "node:napi:env") \ + V(napi_wrapper, "node:napi:wrapper") \ // Strings are per-isolate primitives but Environment proxies them // for the sake of convenience. Strings should be ASCII-only. diff --git a/src/node_api.cc b/src/node_api.cc index 27ab6707de7a6f..78841d14882eeb 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -17,6 +17,7 @@ #include #include "node_api.h" #include "node_internals.h" +#include "env.h" static napi_status napi_set_last_error(napi_env env, napi_status error_code, @@ -46,6 +47,9 @@ struct napi_env__ { uv_loop_t* loop = nullptr; }; +#define NAPI_PRIVATE_KEY(context, suffix) \ + (node::Environment::GetCurrent((context))->napi_ ## suffix()) + #define ENV_OBJECT_TEMPLATE(env, prefix, destination, field_count) \ do { \ if ((env)->prefix ## _template.IsEmpty()) { \ @@ -373,6 +377,10 @@ class Reference : private Finalizer { } public: + void* Data() { + return _finalize_data; + } + static Reference* New(napi_env env, v8::Local value, uint32_t initial_refcount, @@ -732,45 +740,6 @@ v8::Local CreateAccessorCallbackData(napi_env env, return cbdata; } -int kWrapperFields = 3; - -// Pointer used to identify items wrapped by N-API. Used by FindWrapper and -// napi_wrap(). -const char napi_wrap_name[] = "N-API Wrapper"; - -// Search the object's prototype chain for the wrapper object. Usually the -// wrapper would be the first in the chain, but it is OK for other objects to -// be inserted in the prototype chain. -static -bool FindWrapper(v8::Local obj, - v8::Local* result = nullptr, - v8::Local* parent = nullptr) { - v8::Local wrapper = obj; - - do { - v8::Local proto = wrapper->GetPrototype(); - if (proto.IsEmpty() || !proto->IsObject()) { - return false; - } - if (parent != nullptr) { - *parent = wrapper; - } - wrapper = proto.As(); - if (wrapper->InternalFieldCount() == kWrapperFields) { - v8::Local external = wrapper->GetInternalField(1); - if (external->IsExternal() && - external.As()->Value() == v8impl::napi_wrap_name) { - break; - } - } - } while (true); - - if (result != nullptr) { - *result = wrapper; - } - return true; -} - static void DeleteEnv(napi_env env, void* data, void* hint) { delete env; } @@ -787,11 +756,8 @@ napi_env GetEnv(v8::Local context) { // because we need to stop hard if either of them is empty. // // Re https://github.com/nodejs/node/pull/14217#discussion_r128775149 - auto key = v8::Private::ForApi(isolate, - v8::String::NewFromOneByte(isolate, - reinterpret_cast("N-API Environment"), - v8::NewStringType::kInternalized).ToLocalChecked()); - auto value = global->GetPrivate(context, key).ToLocalChecked(); + auto value = global->GetPrivate(context, NAPI_PRIVATE_KEY(context, env)) + .ToLocalChecked(); if (value->IsExternal()) { result = static_cast(value.As()->Value()); @@ -801,7 +767,8 @@ napi_env GetEnv(v8::Local context) { // We must also stop hard if the result of assigning the env to the global // is either nothing or false. - CHECK(global->SetPrivate(context, key, external).FromJust()); + CHECK(global->SetPrivate(context, NAPI_PRIVATE_KEY(context, env), external) + .FromJust()); // Create a self-destructing reference to external that will get rid of the // napi_env when external goes out of scope. @@ -811,28 +778,46 @@ napi_env GetEnv(v8::Local context) { return result; } +enum UnwrapAction { + KeepWrap, + RemoveWrap +}; + static napi_status Unwrap(napi_env env, napi_value js_object, void** result, - v8::Local* wrapper, - v8::Local* parent = nullptr) { + UnwrapAction action) { + NAPI_PREAMBLE(env); CHECK_ARG(env, js_object); - CHECK_ARG(env, result); + if (action == KeepWrap) { + CHECK_ARG(env, result); + } + + v8::Isolate* isolate = env->isolate; + v8::Local context = isolate->GetCurrentContext(); v8::Local value = v8impl::V8LocalValueFromJsValue(js_object); RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg); v8::Local obj = value.As(); - RETURN_STATUS_IF_FALSE( - env, v8impl::FindWrapper(obj, wrapper, parent), napi_invalid_arg); + auto val = obj->GetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper)) + .ToLocalChecked(); + RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg); + Reference* reference = + static_cast(val.As()->Value()); - v8::Local unwrappedValue = (*wrapper)->GetInternalField(0); - RETURN_STATUS_IF_FALSE(env, unwrappedValue->IsExternal(), napi_invalid_arg); + if (result) { + *result = reference->Data(); + } - *result = unwrappedValue.As()->Value(); + if (action == RemoveWrap) { + CHECK(obj->DeletePrivate(context, NAPI_PRIVATE_KEY(context, wrapper)) + .FromJust()); + Reference::Delete(reference); + } - return napi_ok; + return GET_RETURN_STATUS(env); } static @@ -2391,26 +2376,9 @@ napi_status napi_wrap(napi_env env, v8::Local obj = value.As(); // If we've already wrapped this object, we error out. - RETURN_STATUS_IF_FALSE(env, !v8impl::FindWrapper(obj), napi_invalid_arg); - - // Create a wrapper object with an internal field to hold the wrapped pointer - // and a second internal field to identify the owner as N-API. - v8::Local wrapper_template; - ENV_OBJECT_TEMPLATE(env, wrap, wrapper_template, v8impl::kWrapperFields); - - auto maybe_object = wrapper_template->NewInstance(context); - CHECK_MAYBE_EMPTY(env, maybe_object, napi_generic_failure); - v8::Local wrapper = maybe_object.ToLocalChecked(); - - // Store the pointer as an external in the wrapper. - wrapper->SetInternalField(0, v8::External::New(isolate, native_object)); - wrapper->SetInternalField(1, v8::External::New(isolate, - reinterpret_cast(const_cast(v8impl::napi_wrap_name)))); - - // Insert the wrapper into the object's prototype chain. - v8::Local proto = obj->GetPrototype(); - CHECK(wrapper->SetPrototype(context, proto).FromJust()); - CHECK(obj->SetPrototype(context, wrapper).FromJust()); + RETURN_STATUS_IF_FALSE(env, + !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper)).FromJust(), + napi_invalid_arg); v8impl::Reference* reference = nullptr; if (result != nullptr) { @@ -2422,52 +2390,24 @@ napi_status napi_wrap(napi_env env, reference = v8impl::Reference::New( env, obj, 0, false, finalize_cb, native_object, finalize_hint); *result = reinterpret_cast(reference); - } else if (finalize_cb != nullptr) { - // Create a self-deleting reference just for the finalize callback. - reference = v8impl::Reference::New( - env, obj, 0, true, finalize_cb, native_object, finalize_hint); + } else { + // Create a self-deleting reference. + reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb, + native_object, finalize_cb == nullptr ? nullptr : finalize_hint); } - if (reference != nullptr) { - wrapper->SetInternalField(2, v8::External::New(isolate, reference)); - } + CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper), + v8::External::New(isolate, reference)).FromJust()); return GET_RETURN_STATUS(env); } napi_status napi_unwrap(napi_env env, napi_value obj, void** result) { - // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw - // JS exceptions. - CHECK_ENV(env); - v8::Local wrapper; - return napi_set_last_error(env, v8impl::Unwrap(env, obj, result, &wrapper)); + return v8impl::Unwrap(env, obj, result, v8impl::KeepWrap); } napi_status napi_remove_wrap(napi_env env, napi_value obj, void** result) { - NAPI_PREAMBLE(env); - v8::Local wrapper; - v8::Local parent; - napi_status status = v8impl::Unwrap(env, obj, result, &wrapper, &parent); - if (status != napi_ok) { - return napi_set_last_error(env, status); - } - - v8::Local external = wrapper->GetInternalField(2); - if (external->IsExternal()) { - v8impl::Reference::Delete( - static_cast(external.As()->Value())); - } - - if (!parent.IsEmpty()) { - v8::Maybe maybe = parent->SetPrototype( - env->isolate->GetCurrentContext(), wrapper->GetPrototype()); - CHECK_MAYBE_NOTHING(env, maybe, napi_generic_failure); - if (!maybe.FromMaybe(false)) { - return napi_set_last_error(env, napi_generic_failure); - } - } - - return GET_RETURN_STATUS(env); + return v8impl::Unwrap(env, obj, result, v8impl::RemoveWrap); } napi_status napi_create_external(napi_env env, From d73797200bd925aefe5b7101251665e59987deb5 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Mon, 29 Jan 2018 10:23:02 +0100 Subject: [PATCH 058/131] net: remove redundant code from _writeGeneric() The encoding is already handled by `Writable.prototype.write()`. PR-URL: https://github.com/nodejs/node/pull/18429 Reviewed-By: Matteo Collina Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater --- lib/net.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/net.js b/lib/net.js index 540f7ce800d520..54c161c382a306 100644 --- a/lib/net.js +++ b/lib/net.js @@ -758,13 +758,7 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) { // Retain chunks if (err === 0) req._chunks = chunks; } else { - var enc; - if (data instanceof Buffer) { - enc = 'buffer'; - } else { - enc = encoding; - } - err = createWriteReq(req, this._handle, data, enc); + err = createWriteReq(req, this._handle, data, encoding); } if (err) From 35d3df9dd550fb87ad90ea7cd57eb6853e8b9510 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Thu, 1 Feb 2018 08:10:18 -0500 Subject: [PATCH 059/131] test: add test for tls benchmarks PR-URL: https://github.com/nodejs/node/pull/18489 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- benchmark/tls/throughput.js | 2 +- test/sequential/test-benchmark-tls.js | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/sequential/test-benchmark-tls.js diff --git a/benchmark/tls/throughput.js b/benchmark/tls/throughput.js index f63257c49693d6..1ca52ad9496237 100644 --- a/benchmark/tls/throughput.js +++ b/benchmark/tls/throughput.js @@ -40,11 +40,11 @@ function main({ dur, type, size }) { }; server = tls.createServer(options, onConnection); - setTimeout(done, dur * 1000); var conn; server.listen(common.PORT, function() { const opt = { port: common.PORT, rejectUnauthorized: false }; conn = tls.connect(opt, function() { + setTimeout(done, dur * 1000); bench.start(); conn.on('drain', write); write(); diff --git a/test/sequential/test-benchmark-tls.js b/test/sequential/test-benchmark-tls.js new file mode 100644 index 00000000000000..7c87aa3cbcd89e --- /dev/null +++ b/test/sequential/test-benchmark-tls.js @@ -0,0 +1,25 @@ +'use strict'; + +const common = require('../common'); + +if (!common.enoughTestMem) + common.skip('Insufficient memory for TLS benchmark test'); + +// Because the TLS benchmarks use hardcoded ports, this should be in sequential +// rather than parallel to make sure it does not conflict with tests that choose +// random available ports. + +const runBenchmark = require('../common/benchmark'); + +runBenchmark('tls', + [ + 'concurrency=1', + 'dur=0.1', + 'n=1', + 'size=2', + 'type=asc' + ], + { + NODEJS_BENCHMARK_ZERO_ALLOWED: 1, + duration: 0 + }); From e079247116b3fce4f3c5398a4394b0505c853165 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 29 Jan 2018 14:42:40 -0500 Subject: [PATCH 060/131] http: remove domain specific code Due to some changes to async tracking of http and also in how domains are handled, it's no longer necessary to manually copy domain from req to res in http code. PR-URL: https://github.com/nodejs/node/pull/18477 Refs: https://github.com/nodejs/node/pull/16222 Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Khaidi Chu Reviewed-By: Jeremiah Senkpiel --- lib/_http_client.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index 9dea39d0216c80..62eef956b3574e 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -495,12 +495,6 @@ function parserOnIncomingClient(res, shouldKeepAlive) { var socket = this.socket; var req = socket._httpMessage; - // propagate "domain" setting... - if (req.domain && !res.domain) { - debug('setting "res.domain"'); - res.domain = req.domain; - } - debug('AGENT incoming response!'); if (req.res) { From 3962051dae1918dec8ad39891915cef576c21089 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 29 Jan 2018 14:52:01 -0500 Subject: [PATCH 061/131] timers: remove domain specific code It is no longer necessary to explicitly set the handle to inherit the Timeout domain. PR-URL: https://github.com/nodejs/node/pull/18477 Refs: https://github.com/nodejs/node/pull/16222 Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Khaidi Chu Reviewed-By: Jeremiah Senkpiel --- lib/timers.js | 1 - test/parallel/test-domain-timers.js | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/timers.js b/lib/timers.js index d637ca91ae48e9..a6adbf74f255d6 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -603,7 +603,6 @@ Timeout.prototype.unref = function() { this._handle.owner = this; this._handle[kOnTimeout] = unrefdHandle; this._handle.start(delay); - this._handle.domain = this.domain; this._handle.unref(); } return this; diff --git a/test/parallel/test-domain-timers.js b/test/parallel/test-domain-timers.js index fe7247b2a92c95..f9857a991af880 100644 --- a/test/parallel/test-domain-timers.js +++ b/test/parallel/test-domain-timers.js @@ -30,13 +30,19 @@ timeoutd.on('error', common.mustCall(function(e) { assert.strictEqual(e.message, 'Timeout UNREFd', 'Domain should catch timer error'); clearTimeout(timeout); -})); +}, 2)); +let t; timeoutd.run(function() { setTimeout(function() { throw new Error('Timeout UNREFd'); }, 0).unref(); + + t = setTimeout(function() { + throw new Error('Timeout UNREFd'); + }, 0); }); +t.unref(); const immediated = domain.create(); From c76d38025914734574250e651a62ca796345a36a Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Mon, 29 Jan 2018 10:58:29 -0800 Subject: [PATCH 062/131] doc: remove removed apis from http2 docs PR-URL: https://github.com/nodejs/node/pull/18439 Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski --- doc/api/http2.md | 144 +++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 85 deletions(-) diff --git a/doc/api/http2.md b/doc/api/http2.md index 63500bd8cd158f..54a3b92849ac80 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -19,8 +19,8 @@ compatibility with the existing [HTTP/1][] module API. However, the [Compatibility API][] is. The `http2` Core API is much more symmetric between client and server than the -`http` API. For instance, most events, like `error` and `socketError`, can be -emitted either by client-side code or server-side code. +`http` API. For instance, most events, like `error`, `connect` and `stream`, can +be emitted either by client-side code or server-side code. ### Server-side example @@ -36,7 +36,6 @@ const server = http2.createSecureServer({ cert: fs.readFileSync('localhost-cert.pem') }); server.on('error', (err) => console.error(err)); -server.on('socketError', (err) => console.error(err)); server.on('stream', (stream, headers) => { // stream is a Duplex @@ -68,7 +67,6 @@ const client = http2.connect('https://localhost:8443', { ca: fs.readFileSync('localhost-cert.pem') }); client.on('error', (err) => console.error(err)); -client.on('socketError', (err) => console.error(err)); const req = client.request({ ':path': '/' }); @@ -479,44 +477,6 @@ Used to set a callback function that is called when there is no activity on the `Http2Session` after `msecs` milliseconds. The given `callback` is registered as a listener on the `'timeout'` event. -#### http2session.close(options[, callback]) - - -* `options` {Object} - * `errorCode` {number} The HTTP/2 [error code][] to return. Note that this is - *not* the same thing as an HTTP Response Status Code. **Default:** `0x00` - (No Error). - * `lastStreamID` {number} The Stream ID of the last successfully processed - `Http2Stream` on this `Http2Session`. If unspecified, will default to the - ID of the most recently received stream. - * `opaqueData` {Buffer|Uint8Array} A `Buffer` or `Uint8Array` instance - containing arbitrary additional data to send to the peer upon disconnection. - This is used, typically, to provide additional data for debugging failures, - if necessary. -* `callback` {Function} A callback that is invoked after the session shutdown - has been completed. -* Returns: {undefined} - -Attempts to shut down this `Http2Session` using HTTP/2 defined procedures. -If specified, the given `callback` function will be invoked once the shutdown -process has completed. - -If the `Http2Session` instance is a server-side session and the `errorCode` -option is `0x00` (No Error), a "graceful" shutdown will be initiated. During a -"graceful" shutdown, the session will first send a `GOAWAY` frame to -the connected peer identifying the last processed stream as 231-1. -Then, on the next tick of the event loop, a second `GOAWAY` frame identifying -the most recently processed stream identifier is sent. This process allows the -remote peer to begin preparing for the connection to be terminated. - -```js -session.close({ - opaqueData: Buffer.from('add some debugging data here') -}, () => session.destroy()); -``` - #### http2session.socket +* `alt`: {string} +* `origin`: {string} +* `streamId`: {number} + The `'altsvc'` event is emitted whenever an `ALTSVC` frame is received by the client. The event is emitted with the `ALTSVC` value, origin, and stream -ID, if any. If no `origin` is provided in the `ALTSVC` frame, `origin` will +ID. If no `origin` is provided in the `ALTSVC` frame, `origin` will be an empty string. ```js const http2 = require('http2'); const client = http2.connect('https://example.org'); -client.on('altsvc', (alt, origin, stream) => { +client.on('altsvc', (alt, origin, streamId) => { console.log(alt); console.log(origin); - console.log(stream); + console.log(streamId); }); ``` @@ -1472,10 +1436,9 @@ added: v8.4.0 * Extends: {net.Server} -In `Http2Server`, there is no `'clientError'` event as there is in -HTTP1. However, there are `'socketError'`, `'sessionError'`, and -`'streamError'`, for errors emitted on the socket, `Http2Session`, or -`Http2Stream`. +In `Http2Server`, there are no `'clientError'` events as there are in +HTTP1. However, there are `'sessionError'`, and `'streamError'` events for +errors emitted on the socket, or from `Http2Session` or `Http2Stream` instances. #### Event: 'checkContinue' + +* `request` {http2.Http2ServerRequest} +* `response` {http2.Http2ServerResponse} + +If a [`'request'`][] listener is registered or [`http2.createSecureServer()`][] +is supplied a callback function, the `'checkContinue'` event is emitted each +time a request with an HTTP `Expect: 100-continue` is received. If this event +is not listened for, the server will automatically respond with a status +`100 Continue` as appropriate. + +Handling this event involves calling [`response.writeContinue()`][] if the client +should continue to send the request body, or generating an appropriate HTTP +response (e.g. 400 Bad Request) if the client should not continue to send the +request body. + +Note that when this event is emitted and handled, the [`'request'`][] event will +not be emitted. + +#### Event: 'request' -The `'sessionError'` event is emitted when an `'error'` event is emitted by -an `Http2Session` object associated with the `Http2SecureServer`. +* `request` {http2.Http2ServerRequest} +* `response` {http2.Http2ServerResponse} -#### Event: 'unknownProtocol' +Emitted each time there is a request. Note that there may be multiple requests +per session. See the [Compatibility API][]. + +#### Event: 'session' -The `'unknownProtocol'` event is emitted when a connecting client fails to -negotiate an allowed protocol (i.e. HTTP/2 or HTTP/1.1). The event handler -receives the socket for handling. If no listener is registered for this event, -the connection is terminated. See the [Compatibility API][]. +The `'session'` event is emitted when a new `Http2Session` is created by the +`Http2SecureServer`. + +#### Event: 'sessionError' + + +The `'sessionError'` event is emitted when an `'error'` event is emitted by +an `Http2Session` object associated with the `Http2SecureServer`. #### Event: 'stream' -* `request` {http2.Http2ServerRequest} -* `response` {http2.Http2ServerResponse} - -Emitted each time there is a request. Note that there may be multiple requests -per session. See the [Compatibility API][]. +The `'timeout'` event is emitted when there is no activity on the Server for +a given number of milliseconds set using `http2secureServer.setTimeout()`. -#### Event: 'timeout' +#### Event: 'unknownProtocol' -#### Event: 'checkContinue' - - -* `request` {http2.Http2ServerRequest} -* `response` {http2.Http2ServerResponse} - -If a [`'request'`][] listener is registered or [`http2.createSecureServer()`][] -is supplied a callback function, the `'checkContinue'` event is emitted each -time a request with an HTTP `Expect: 100-continue` is received. If this event -is not listened for, the server will automatically respond with a status -`100 Continue` as appropriate. - -Handling this event involves calling [`response.writeContinue()`][] if the client -should continue to send the request body, or generating an appropriate HTTP -response (e.g. 400 Bad Request) if the client should not continue to send the -request body. - -Note that when this event is emitted and handled, the [`'request'`][] event will -not be emitted. +The `'unknownProtocol'` event is emitted when a connecting client fails to +negotiate an allowed protocol (i.e. HTTP/2 or HTTP/1.1). The event handler +receives the socket for handling. If no listener is registered for this event, +the connection is terminated. See the [Compatibility API][]. ### http2.createServer(options[, onRequestHandler]) +```C +NAPI_EXTERN napi_status napi_open_callback_scope(napi_env env, + napi_value resource_object, + napi_async_context context, + napi_callback_scope* result) +``` +- `[in] env`: The environment that the API is invoked under. +- `[in] resource_object`: An optional object associated with the async work + that will be passed to possible async_hooks [`init` hooks][]. +- `[in] context`: Context for the async operation that is +invoking the callback. This should be a value previously obtained +from [`napi_async_init`][]. +- `[out] result`: The newly created scope. + +There are cases(for example resolving promises) where it is +necessary to have the equivalent of the scope associated with a callback +in place when making certain N-API calls. If there is no other script on +the stack the [`napi_open_callback_scope`][] and +[`napi_close_callback_scope`][] functions can be used to open/close +the required scope. + +### *napi_close_callback_scope* + +```C +NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env, + napi_callback_scope scope) +``` +- `[in] env`: The environment that the API is invoked under. +- `[in] scope`: The scope to be closed. + ## Version Management ### napi_get_node_version @@ -3716,6 +3752,7 @@ NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, [`napi_async_init`]: #n_api_napi_async_init [`napi_cancel_async_work`]: #n_api_napi_cancel_async_work [`napi_close_escapable_handle_scope`]: #n_api_napi_close_escapable_handle_scope +[`napi_close_callback_scope`]: #n_api_napi_close_callback_scope [`napi_close_handle_scope`]: #n_api_napi_close_handle_scope [`napi_create_async_work`]: #n_api_napi_create_async_work [`napi_create_error`]: #n_api_napi_create_error @@ -3741,6 +3778,7 @@ NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, [`napi_get_last_error_info`]: #n_api_napi_get_last_error_info [`napi_get_and_clear_last_exception`]: #n_api_napi_get_and_clear_last_exception [`napi_make_callback`]: #n_api_napi_make_callback +[`napi_open_callback_scope`]: #n_api_napi_open_callback_scope [`napi_open_escapable_handle_scope`]: #n_api_napi_open_escapable_handle_scope [`napi_open_handle_scope`]: #n_api_napi_open_handle_scope [`napi_property_descriptor`]: #n_api_napi_property_descriptor diff --git a/src/node_api.cc b/src/node_api.cc index 611f6c8085e384..2c5f3066f728b1 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -44,6 +44,7 @@ struct napi_env__ { v8::Persistent accessor_data_template; napi_extended_error_info last_error; int open_handle_scopes = 0; + int open_callback_scopes = 0; uv_loop_t* loop = nullptr; }; @@ -253,6 +254,18 @@ V8EscapableHandleScopeFromJsEscapableHandleScope( return reinterpret_cast(s); } +static +napi_callback_scope JsCallbackScopeFromV8CallbackScope( + node::CallbackScope* s) { + return reinterpret_cast(s); +} + +static +node::CallbackScope* V8CallbackScopeFromJsCallbackScope( + napi_callback_scope s) { + return reinterpret_cast(s); +} + //=== Conversion between V8 Handles and napi_value ======================== // This asserts v8::Local<> will always be implemented with a single @@ -544,6 +557,7 @@ class CallbackWrapperBase : public CallbackWrapper { napi_clear_last_error(env); int open_handle_scopes = env->open_handle_scopes; + int open_callback_scopes = env->open_callback_scopes; napi_value result = cb(env, cbinfo_wrapper); @@ -552,6 +566,7 @@ class CallbackWrapperBase : public CallbackWrapper { } CHECK_EQ(env->open_handle_scopes, open_handle_scopes); + CHECK_EQ(env->open_callback_scopes, open_callback_scopes); if (!env->last_exception.IsEmpty()) { isolate->ThrowException( @@ -911,7 +926,8 @@ const char* error_messages[] = {nullptr, "An exception is pending", "The async work item was cancelled", "napi_escape_handle already called on scope", - "Invalid handle scope usage"}; + "Invalid handle scope usage", + "Invalid callback scope usage"}; static inline napi_status napi_clear_last_error(napi_env env) { env->last_error.error_code = napi_ok; @@ -942,9 +958,9 @@ napi_status napi_get_last_error_info(napi_env env, // We don't have a napi_status_last as this would result in an ABI // change each time a message was added. static_assert( - node::arraysize(error_messages) == napi_handle_scope_mismatch + 1, + node::arraysize(error_messages) == napi_callback_scope_mismatch + 1, "Count of error messages must match count of error values"); - CHECK_LE(env->last_error.error_code, napi_handle_scope_mismatch); + CHECK_LE(env->last_error.error_code, napi_callback_scope_mismatch); // Wait until someone requests the last error information to fetch the error // message string @@ -2633,6 +2649,46 @@ napi_status napi_escape_handle(napi_env env, return napi_set_last_error(env, napi_escape_called_twice); } +napi_status napi_open_callback_scope(napi_env env, + napi_value resource_object, + napi_async_context async_context_handle, + napi_callback_scope* result) { + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); + CHECK_ARG(env, result); + + v8::Local context = env->isolate->GetCurrentContext(); + + node::async_context* node_async_context = + reinterpret_cast(async_context_handle); + + v8::Local resource; + CHECK_TO_OBJECT(env, context, resource, resource_object); + + *result = v8impl::JsCallbackScopeFromV8CallbackScope( + new node::CallbackScope(env->isolate, + resource, + *node_async_context)); + + env->open_callback_scopes++; + return napi_clear_last_error(env); +} + +napi_status napi_close_callback_scope(napi_env env, napi_callback_scope scope) { + // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw + // JS exceptions. + CHECK_ENV(env); + CHECK_ARG(env, scope); + if (env->open_callback_scopes == 0) { + return napi_callback_scope_mismatch; + } + + env->open_callback_scopes--; + delete v8impl::V8CallbackScopeFromJsCallbackScope(scope); + return napi_clear_last_error(env); +} + napi_status napi_new_instance(napi_env env, napi_value constructor, size_t argc, diff --git a/src/node_api.h b/src/node_api.h index c7527051694537..e9b3645e404530 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -424,6 +424,14 @@ NAPI_EXTERN napi_status napi_escape_handle(napi_env env, napi_value escapee, napi_value* result); +NAPI_EXTERN napi_status napi_open_callback_scope(napi_env env, + napi_value resource_object, + napi_async_context context, + napi_callback_scope* result); + +NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env, + napi_callback_scope scope); + // Methods to support error handling NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error); NAPI_EXTERN napi_status napi_throw_error(napi_env env, diff --git a/src/node_api_types.h b/src/node_api_types.h index 230c1f4ae3446f..76f38802e83e2e 100644 --- a/src/node_api_types.h +++ b/src/node_api_types.h @@ -15,6 +15,7 @@ typedef struct napi_value__ *napi_value; typedef struct napi_ref__ *napi_ref; typedef struct napi_handle_scope__ *napi_handle_scope; typedef struct napi_escapable_handle_scope__ *napi_escapable_handle_scope; +typedef struct napi_callback_scope__ *napi_callback_scope; typedef struct napi_callback_info__ *napi_callback_info; typedef struct napi_async_context__ *napi_async_context; typedef struct napi_async_work__ *napi_async_work; @@ -70,7 +71,8 @@ typedef enum { napi_pending_exception, napi_cancelled, napi_escape_called_twice, - napi_handle_scope_mismatch + napi_handle_scope_mismatch, + napi_callback_scope_mismatch } napi_status; typedef napi_value (*napi_callback)(napi_env env, diff --git a/test/addons-napi/test_callback_scope/binding.cc b/test/addons-napi/test_callback_scope/binding.cc new file mode 100644 index 00000000000000..e6631b6ac7bb52 --- /dev/null +++ b/test/addons-napi/test_callback_scope/binding.cc @@ -0,0 +1,138 @@ +#include "node_api.h" +#include "uv.h" +#include "../common.h" + +namespace { + +// the test needs to fake out the async structure, so we need to use +// the raw structure here and then cast as done behind the scenes +// in napi calls. +struct async_context { + double async_id; + double trigger_async_id; +}; + + +napi_value RunInCallbackScope(napi_env env, napi_callback_info info) { + size_t argc; + napi_value args[4]; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr)); + NAPI_ASSERT(env, argc == 4 , "Wrong number of arguments"); + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + + napi_valuetype valuetype; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_object, + "Wrong type of arguments. Expects an object as first argument."); + + NAPI_CALL(env, napi_typeof(env, args[1], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_number, + "Wrong type of arguments. Expects a number as second argument."); + + NAPI_CALL(env, napi_typeof(env, args[2], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_number, + "Wrong type of arguments. Expects a number as third argument."); + + NAPI_CALL(env, napi_typeof(env, args[3], &valuetype)); + NAPI_ASSERT(env, valuetype == napi_function, + "Wrong type of arguments. Expects a function as third argument."); + + struct async_context context; + NAPI_CALL(env, napi_get_value_double(env, args[1], &context.async_id)); + NAPI_CALL(env, + napi_get_value_double(env, args[2], &context.trigger_async_id)); + + napi_callback_scope scope = nullptr; + NAPI_CALL( + env, + napi_open_callback_scope(env, + args[0], + reinterpret_cast(&context), + &scope)); + + // if the function has an exception pending after the call that is ok + // so we don't use NAPI_CALL as we must close the callback scope regardless + napi_value result = nullptr; + napi_status function_call_result = + napi_call_function(env, args[0], args[3], 0, nullptr, &result); + if (function_call_result != napi_ok) { + GET_AND_THROW_LAST_ERROR((env)); + } + + NAPI_CALL(env, napi_close_callback_scope(env, scope)); + + return result; +} + +static napi_env shared_env = nullptr; +static napi_deferred deferred = nullptr; + +static void Callback(uv_work_t* req, int ignored) { + napi_env env = shared_env; + + napi_handle_scope handle_scope = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_open_handle_scope(env, &handle_scope)); + + napi_value resource_name; + NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8( + env, "test", NAPI_AUTO_LENGTH, &resource_name)); + napi_async_context context; + NAPI_CALL_RETURN_VOID(env, + napi_async_init(env, nullptr, resource_name, &context)); + + napi_value resource_object; + NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &resource_object)); + + napi_value undefined_value; + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined_value)); + + napi_callback_scope scope = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_open_callback_scope(env, + resource_object, + context, + &scope)); + + NAPI_CALL_RETURN_VOID(env, + napi_resolve_deferred(env, deferred, undefined_value)); + + NAPI_CALL_RETURN_VOID(env, napi_close_callback_scope(env, scope)); + + NAPI_CALL_RETURN_VOID(env, napi_close_handle_scope(env, handle_scope)); + delete req; +} + +napi_value TestResolveAsync(napi_env env, napi_callback_info info) { + napi_value promise = nullptr; + if (deferred == nullptr) { + shared_env = env; + NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); + + uv_loop_t* loop = nullptr; + NAPI_CALL(env, napi_get_uv_event_loop(env, &loop)); + + uv_work_t* req = new uv_work_t(); + uv_queue_work(loop, + req, + [](uv_work_t*) {}, + Callback); + } + return promise; +} + +napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor descriptors[] = { + DECLARE_NAPI_PROPERTY("runInCallbackScope", RunInCallbackScope), + DECLARE_NAPI_PROPERTY("testResolveAsync", TestResolveAsync) + }; + + NAPI_CALL(env, napi_define_properties( + env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); + + return exports; +} + +} // anonymous namespace + +NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) diff --git a/test/addons-napi/test_callback_scope/binding.gyp b/test/addons-napi/test_callback_scope/binding.gyp new file mode 100644 index 00000000000000..7ede63d94a0d77 --- /dev/null +++ b/test/addons-napi/test_callback_scope/binding.gyp @@ -0,0 +1,9 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'defines': [ 'V8_DEPRECATION_WARNINGS=1' ], + 'sources': [ 'binding.cc' ] + } + ] +} diff --git a/test/addons-napi/test_callback_scope/test-async-hooks.js b/test/addons-napi/test_callback_scope/test-async-hooks.js new file mode 100644 index 00000000000000..1a11bf60398f9b --- /dev/null +++ b/test/addons-napi/test_callback_scope/test-async-hooks.js @@ -0,0 +1,29 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const async_hooks = require('async_hooks'); + +// The async_hook that we enable would register the process.emitWarning() +// call from loading the N-API addon as asynchronous activity because +// it contains a process.nextTick() call. Monkey patch it to be a no-op +// before we load the addon in order to avoid this. +process.emitWarning = () => {}; + +const { runInCallbackScope } = require(`./build/${common.buildType}/binding`); + +let insideHook = false; +async_hooks.createHook({ + before: common.mustCall((id) => { + assert.strictEqual(id, 1000); + insideHook = true; + }), + after: common.mustCall((id) => { + assert.strictEqual(id, 1000); + insideHook = false; + }) +}).enable(); + +runInCallbackScope({}, 1000, 1000, () => { + assert(insideHook); +}); diff --git a/test/addons-napi/test_callback_scope/test-resolve-async.js b/test/addons-napi/test_callback_scope/test-resolve-async.js new file mode 100644 index 00000000000000..e9f4b9044c0154 --- /dev/null +++ b/test/addons-napi/test_callback_scope/test-resolve-async.js @@ -0,0 +1,13 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const { testResolveAsync } = require(`./build/${common.buildType}/binding`); + +let called = false; +testResolveAsync().then(common.mustCall(() => { + called = true; +})); + +setTimeout(common.mustCall(() => { assert(called); }), + common.platformTimeout(20)); diff --git a/test/addons-napi/test_callback_scope/test.js b/test/addons-napi/test_callback_scope/test.js new file mode 100644 index 00000000000000..2f2efe5f47b98a --- /dev/null +++ b/test/addons-napi/test_callback_scope/test.js @@ -0,0 +1,17 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const { runInCallbackScope } = require(`./build/${common.buildType}/binding`); + +assert.strictEqual(runInCallbackScope({}, 0, 0, () => 42), 42); + +{ + process.once('uncaughtException', common.mustCall((err) => { + assert.strictEqual(err.message, 'foo'); + })); + + runInCallbackScope({}, 0, 0, () => { + throw new Error('foo'); + }); +} From cf588e0ba1e39ba74bcff9891f3c038ec275fb08 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 2 Feb 2018 20:34:19 -0500 Subject: [PATCH 079/131] n-api: remove extra reference from test PR-URL: https://github.com/nodejs/node/pull/18542 Reviewed-By: Michael Dawson Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Colin Ihrig --- test/addons-napi/test_constructor/test_constructor.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/addons-napi/test_constructor/test_constructor.c b/test/addons-napi/test_constructor/test_constructor.c index 70f53ec5a92f55..4ee8323dd6ed40 100644 --- a/test/addons-napi/test_constructor/test_constructor.c +++ b/test/addons-napi/test_constructor/test_constructor.c @@ -3,7 +3,6 @@ static double value_ = 1; static double static_value_ = 10; -napi_ref constructor_; napi_value GetValue(napi_env env, napi_callback_info info) { size_t argc = 0; @@ -80,8 +79,6 @@ napi_value Init(napi_env env, napi_value exports) { NAPI_CALL(env, napi_define_class(env, "MyObject", NAPI_AUTO_LENGTH, New, NULL, sizeof(properties)/sizeof(*properties), properties, &cons)); - NAPI_CALL(env, napi_create_reference(env, cons, 1, &constructor_)); - return cons; } From b439ded223e5c3b4e6aa04b0a5fc7db0865c88d5 Mon Sep 17 00:00:00 2001 From: Weijia Wang <381152119@qq.com> Date: Fri, 2 Feb 2018 17:37:25 +0800 Subject: [PATCH 080/131] test: improve tests for test-http-url.parse PR-URL: https://github.com/nodejs/node/pull/18523 Reviewed-By: Jon Moss Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- ...p-url.parse-auth-with-header-in-request.js | 2 +- test/parallel/test-http-url.parse-auth.js | 2 +- test/parallel/test-http-url.parse-basic.js | 2 +- .../test-http-url.parse-https.request.js | 2 +- ....parse-only-support-http-https-protocol.js | 79 +++++-------------- test/parallel/test-http-url.parse-path.js | 2 +- test/parallel/test-http-url.parse-post.js | 2 +- test/parallel/test-http-url.parse-search.js | 2 +- 8 files changed, 25 insertions(+), 68 deletions(-) diff --git a/test/parallel/test-http-url.parse-auth-with-header-in-request.js b/test/parallel/test-http-url.parse-auth-with-header-in-request.js index b91dc143831086..c10f5ed7b0d31b 100644 --- a/test/parallel/test-http-url.parse-auth-with-header-in-request.js +++ b/test/parallel/test-http-url.parse-auth-with-header-in-request.js @@ -32,7 +32,7 @@ function check(request) { const server = http.createServer(function(request, response) { // run the check function - check.call(this, request, response); + check(request); response.writeHead(200, {}); response.end('ok'); server.close(); diff --git a/test/parallel/test-http-url.parse-auth.js b/test/parallel/test-http-url.parse-auth.js index d166120ac2930c..ab597e132c8012 100644 --- a/test/parallel/test-http-url.parse-auth.js +++ b/test/parallel/test-http-url.parse-auth.js @@ -32,7 +32,7 @@ function check(request) { const server = http.createServer(function(request, response) { // run the check function - check.call(this, request, response); + check(request); response.writeHead(200, {}); response.end('ok'); server.close(); diff --git a/test/parallel/test-http-url.parse-basic.js b/test/parallel/test-http-url.parse-basic.js index 0aa7616d05b205..a6ecd3918f1803 100644 --- a/test/parallel/test-http-url.parse-basic.js +++ b/test/parallel/test-http-url.parse-basic.js @@ -40,7 +40,7 @@ function check(request) { const server = http.createServer(function(request, response) { // run the check function - check.call(this, request, response); + check(request); response.writeHead(200, {}); response.end('ok'); server.close(); diff --git a/test/parallel/test-http-url.parse-https.request.js b/test/parallel/test-http-url.parse-https.request.js index 87b7ac02e90573..f58be0257c1fc5 100644 --- a/test/parallel/test-http-url.parse-https.request.js +++ b/test/parallel/test-http-url.parse-https.request.js @@ -42,7 +42,7 @@ function check(request) { const server = https.createServer(httpsOptions, function(request, response) { // run the check function - check.call(this, request, response); + check(request); response.writeHead(200, {}); response.end('ok'); server.close(); diff --git a/test/parallel/test-http-url.parse-only-support-http-https-protocol.js b/test/parallel/test-http-url.parse-only-support-http-https-protocol.js index 903b4ba598babb..986f75d3076434 100644 --- a/test/parallel/test-http-url.parse-only-support-http-https-protocol.js +++ b/test/parallel/test-http-url.parse-only-support-http-https-protocol.js @@ -20,68 +20,25 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -require('../common'); -const assert = require('assert'); +const common = require('../common'); const http = require('http'); const url = require('url'); - -assert.throws(function() { - http.request(url.parse('file:///whatever')); -}, function(err) { - if (err instanceof Error) { - assert.strictEqual( - err.message, 'Protocol "file:" not supported. Expected "http:"'); - return true; - } -}); - -assert.throws(function() { - http.request(url.parse('mailto:asdf@asdf.com')); -}, function(err) { - if (err instanceof Error) { - assert.strictEqual( - err.message, 'Protocol "mailto:" not supported. Expected "http:"'); - return true; - } -}); - -assert.throws(function() { - http.request(url.parse('ftp://www.example.com')); -}, function(err) { - if (err instanceof Error) { - assert.strictEqual( - err.message, 'Protocol "ftp:" not supported. Expected "http:"'); - return true; - } -}); - -assert.throws(function() { - http.request(url.parse('javascript:alert(\'hello\');')); -}, function(err) { - if (err instanceof Error) { - assert.strictEqual( - err.message, 'Protocol "javascript:" not supported. Expected "http:"'); - return true; - } -}); - -assert.throws(function() { - http.request(url.parse('xmpp:isaacschlueter@jabber.org')); -}, function(err) { - if (err instanceof Error) { - assert.strictEqual( - err.message, 'Protocol "xmpp:" not supported. Expected "http:"'); - return true; - } -}); - -assert.throws(function() { - http.request(url.parse('f://some.host/path')); -}, function(err) { - if (err instanceof Error) { - assert.strictEqual( - err.message, 'Protocol "f:" not supported. Expected "http:"'); - return true; - } +const invalidUrls = [ + 'file:///whatever', + 'mailto:asdf@asdf.com', + 'ftp://www.example.com', + 'javascript:alert(\'hello\');', + 'xmpp:foo@bar.com', + 'f://some.host/path' +]; + +invalidUrls.forEach((invalid) => { + common.expectsError( + () => { http.request(url.parse(invalid)); }, + { + code: 'ERR_INVALID_PROTOCOL', + type: Error + } + ); }); diff --git a/test/parallel/test-http-url.parse-path.js b/test/parallel/test-http-url.parse-path.js index ab2e550f558cea..4cc5fbf48e015d 100644 --- a/test/parallel/test-http-url.parse-path.js +++ b/test/parallel/test-http-url.parse-path.js @@ -32,7 +32,7 @@ function check(request) { const server = http.createServer(function(request, response) { // run the check function - check.call(this, request, response); + check(request); response.writeHead(200, {}); response.end('ok'); server.close(); diff --git a/test/parallel/test-http-url.parse-post.js b/test/parallel/test-http-url.parse-post.js index dab2e8f97ddac8..d8803cbfd267db 100644 --- a/test/parallel/test-http-url.parse-post.js +++ b/test/parallel/test-http-url.parse-post.js @@ -39,7 +39,7 @@ function check(request) { const server = http.createServer(function(request, response) { // run the check function - check.call(this, request, response); + check(request); response.writeHead(200, {}); response.end('ok'); server.close(); diff --git a/test/parallel/test-http-url.parse-search.js b/test/parallel/test-http-url.parse-search.js index 53d06556c318f5..111cf97874b4d3 100644 --- a/test/parallel/test-http-url.parse-search.js +++ b/test/parallel/test-http-url.parse-search.js @@ -32,7 +32,7 @@ function check(request) { const server = http.createServer(function(request, response) { // run the check function - check.call(this, request, response); + check(request); response.writeHead(200, {}); response.end('ok'); server.close(); From 2d7fe3d30d5ba8d7509ecd7f8128c4afe3aa837c Mon Sep 17 00:00:00 2001 From: Weijia Wang <381152119@qq.com> Date: Wed, 31 Jan 2018 17:57:05 +0800 Subject: [PATCH 081/131] doc: add introduce about cli options PR-URL: https://github.com/nodejs/node/pull/18475 Reviewed-By: Jeremiah Senkpiel Reviewed-By: James M Snell --- doc/guides/writing-and-running-benchmarks.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/guides/writing-and-running-benchmarks.md b/doc/guides/writing-and-running-benchmarks.md index 22e235df323d52..66b5072a4979d7 100644 --- a/doc/guides/writing-and-running-benchmarks.md +++ b/doc/guides/writing-and-running-benchmarks.md @@ -184,6 +184,17 @@ The `compare.js` tool will then produce a csv file with the benchmark results. $ node benchmark/compare.js --old ./node-master --new ./node-pr-5134 string_decoder > compare-pr-5134.csv ``` +*Tips: there are some useful options of `benchmark/compare.js`. For example, if you want to compare the benchmark of a single script instead of a whole module, you can use the `--filter` option:* + +```console + --new ./new-node-binary new node binary (required) + --old ./old-node-binary old node binary (required) + --runs 30 number of samples + --filter pattern string to filter benchmark scripts + --set variable=value set benchmark variable (can be repeated) + --no-progress don't show benchmark progress indicator +``` + For analysing the benchmark results use the `compare.R` tool. ```console From 529f42cf4a8ffe0e2590b2cd58caff1462986aa6 Mon Sep 17 00:00:00 2001 From: Camilo Gonzalez Date: Wed, 31 Jan 2018 00:16:19 -0500 Subject: [PATCH 082/131] build: add doc linting when runnning `make lint` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/18466 PR-URL: https://github.com/nodejs/node/pull/18472 Reviewed-By: Joyee Cheung Reviewed-By: Ruben Bridgewater Reviewed-By: Michaël Zasso --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index eaebe4f2b55a4b..b69b8786a30701 100644 --- a/Makefile +++ b/Makefile @@ -1183,6 +1183,7 @@ lint: ## Run JS, C++, MD and doc linters. $(MAKE) lint-js || EXIT_STATUS=$$? ; \ $(MAKE) lint-cpp || EXIT_STATUS=$$? ; \ $(MAKE) lint-addon-docs || EXIT_STATUS=$$? ; \ + $(MAKE) lint-md || EXIT_STATUS=$$? ; \ exit $$EXIT_STATUS CONFLICT_RE=^>>>>>>> [0-9A-Fa-f]+|^<<<<<<< [A-Za-z]+ From 07d39c73b9669a941be92c82d8ec99687903cb1f Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Tue, 6 Feb 2018 02:00:12 +0200 Subject: [PATCH 083/131] doc: fix typo in n-api.md PR-URL: https://github.com/nodejs/node/pull/18590 Reviewed-By: Jon Moss Reviewed-By: Weijia Wang Reviewed-By: Colin Ihrig Reviewed-By: Rich Trott Reviewed-By: Daniel Bevenius Reviewed-By: Yuta Hiroto --- doc/api/n-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 44ee567166d6bd..38cf7a88420be5 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -3449,7 +3449,7 @@ invoking the callback. This should be a value previously obtained from [`napi_async_init`][]. - `[out] result`: The newly created scope. -There are cases(for example resolving promises) where it is +There are cases (for example resolving promises) where it is necessary to have the equivalent of the scope associated with a callback in place when making certain N-API calls. If there is no other script on the stack the [`napi_open_callback_scope`][] and From 984570d4ff49dc955619028386ab1481310f63e2 Mon Sep 17 00:00:00 2001 From: BufoViridis <30531954+BufoViridis@users.noreply.github.com> Date: Tue, 30 Jan 2018 19:43:50 +0200 Subject: [PATCH 084/131] src: fix crypto.pbkdf2 callback error argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Callbacks should always return `null` instead of `undefined` if no error occurred. PR-URL: https://github.com/nodejs/node/pull/18458 Reviewed-By: Ben Noordhuis Reviewed-By: Tobias Nießen Reviewed-By: Fedor Indutny Reviewed-By: James M Snell --- src/node_crypto.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 5e331a0b7ca506..a398f745537b54 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -5599,7 +5599,7 @@ void PBKDF2Request::Work(uv_work_t* work_req) { void PBKDF2Request::After(Local (*argv)[2]) { if (success_) { - (*argv)[0] = Undefined(env()->isolate()); + (*argv)[0] = Null(env()->isolate()); (*argv)[1] = Buffer::New(env(), key_, keylen_).ToLocalChecked(); key_ = nullptr; keylen_ = 0; From 4dd13c787881e936da5a26a6054ca77164c82178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=88=9A?= Date: Fri, 2 Feb 2018 18:40:01 +0800 Subject: [PATCH 085/131] doc: modify the return value of request.write() PR-URL: https://github.com/nodejs/node/pull/18526 Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- doc/api/http.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/api/http.md b/doc/api/http.md index d2c6d3ec98f3e9..58e5b53eaf41d3 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -681,7 +681,9 @@ Defaults to `'utf8'`. The `callback` argument is optional and will be called when this chunk of data is flushed. -Returns `request`. +Returns `true` if the entire data was flushed successfully to the kernel +buffer. Returns `false` if all or part of the data was queued in user memory. +`'drain'` will be emitted when the buffer is free again. ## Class: http.Server + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/15752 + description: The `options` argument is supported now. +--> +- `options` {Object} + * `IncomingMessage` {http.IncomingMessage} Specifies the IncomingMessage class + to be used. Useful for extending the original `IncomingMessage`. Defaults + to: `IncomingMessage` + * `ServerResponse` {http.ServerResponse} Specifies the ServerResponse class to + be used. Useful for extending the original `ServerResponse`. Defaults to: + `ServerResponse` - `requestListener` {Function} * Returns: {http.Server} diff --git a/doc/api/https.md b/doc/api/https.md index cb22873a01e1ba..29f5d35ab87233 100644 --- a/doc/api/https.md +++ b/doc/api/https.md @@ -65,7 +65,8 @@ See [`http.Server#keepAliveTimeout`][]. -- `options` {Object} Accepts `options` from [`tls.createServer()`][] and [`tls.createSecureContext()`][]. +- `options` {Object} Accepts `options` from [`tls.createServer()`][], + [`tls.createSecureContext()`][] and [`http.createServer()`][]. - `requestListener` {Function} A listener to be added to the `request` event. Example: @@ -258,6 +259,7 @@ const req = https.request(options, (res) => { [`http.Server#setTimeout()`]: http.html#http_server_settimeout_msecs_callback [`http.Server#timeout`]: http.html#http_server_timeout [`http.Server`]: http.html#http_class_http_server +[`http.createServer()`]: http.html#httpcreateserveroptions-requestlistener [`http.close()`]: http.html#http_server_close_callback [`http.get()`]: http.html#http_http_get_options_callback [`http.request()`]: http.html#http_http_request_options_callback diff --git a/lib/_http_common.js b/lib/_http_common.js index b4caf5939e5afc..a7e8b0c59b8854 100644 --- a/lib/_http_common.js +++ b/lib/_http_common.js @@ -34,6 +34,7 @@ const { const debug = require('util').debuglog('http'); +const kIncomingMessage = Symbol('IncomingMessage'); const kOnHeaders = HTTPParser.kOnHeaders | 0; const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0; const kOnBody = HTTPParser.kOnBody | 0; @@ -73,7 +74,11 @@ function parserOnHeadersComplete(versionMajor, versionMinor, headers, method, parser._url = ''; } - parser.incoming = new IncomingMessage(parser.socket); + // Parser is also used by http client + var ParserIncomingMessage = parser.socket && parser.socket.server ? + parser.socket.server[kIncomingMessage] : IncomingMessage; + + parser.incoming = new ParserIncomingMessage(parser.socket); parser.incoming.httpVersionMajor = versionMajor; parser.incoming.httpVersionMinor = versionMinor; parser.incoming.httpVersion = `${versionMajor}.${versionMinor}`; @@ -300,5 +305,6 @@ module.exports = { freeParser, httpSocketSetup, methods, - parsers + parsers, + kIncomingMessage }; diff --git a/lib/_http_server.js b/lib/_http_server.js index c60119822a98d5..9541993df53321 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -33,6 +33,7 @@ const { continueExpression, chunkExpression, httpSocketSetup, + kIncomingMessage, _checkInvalidHeaderChar: checkInvalidHeaderChar } = require('_http_common'); const { OutgoingMessage } = require('_http_outgoing'); @@ -41,9 +42,12 @@ const { defaultTriggerAsyncIdScope, getOrSetAsyncId } = require('internal/async_hooks'); +const { IncomingMessage } = require('_http_incoming'); const errors = require('internal/errors'); const Buffer = require('buffer').Buffer; +const kServerResponse = Symbol('ServerResponse'); + const STATUS_CODES = { 100: 'Continue', 101: 'Switching Protocols', @@ -263,9 +267,19 @@ function writeHead(statusCode, reason, obj) { // Docs-only deprecated: DEP0063 ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead; +function Server(options, requestListener) { + if (!(this instanceof Server)) return new Server(options, requestListener); + + if (typeof options === 'function') { + requestListener = options; + options = {}; + } else if (options == null || typeof options === 'object') { + options = util._extend({}, options); + } + + this[kIncomingMessage] = options.IncomingMessage || IncomingMessage; + this[kServerResponse] = options.ServerResponse || ServerResponse; -function Server(requestListener) { - if (!(this instanceof Server)) return new Server(requestListener); net.Server.call(this, { allowHalfOpen: true }); if (requestListener) { @@ -587,7 +601,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) { } } - var res = new ServerResponse(req); + var res = new server[kServerResponse](req); res._onPendingData = updateOutgoingData.bind(undefined, socket, state); res.shouldKeepAlive = keepAlive; @@ -690,5 +704,6 @@ module.exports = { STATUS_CODES, Server, ServerResponse, - _connectionListener: connectionListener + _connectionListener: connectionListener, + kServerResponse }; diff --git a/lib/https.js b/lib/https.js index 5013791fe2de25..741ce84d2f8820 100644 --- a/lib/https.js +++ b/lib/https.js @@ -36,6 +36,9 @@ const { inherits } = util; const debug = util.debuglog('https'); const { urlToOptions, searchParamsSymbol } = require('internal/url'); const errors = require('internal/errors'); +const { IncomingMessage, ServerResponse } = require('http'); +const { kIncomingMessage } = require('_http_common'); +const { kServerResponse } = require('_http_server'); function Server(opts, requestListener) { if (!(this instanceof Server)) return new Server(opts, requestListener); @@ -57,6 +60,9 @@ function Server(opts, requestListener) { opts.ALPNProtocols = ['http/1.1']; } + this[kIncomingMessage] = opts.IncomingMessage || IncomingMessage; + this[kServerResponse] = opts.ServerResponse || ServerResponse; + tls.Server.call(this, opts, _connectionListener); this.httpAllowHalfOpen = false; diff --git a/test/parallel/test-http-server-options-incoming-message.js b/test/parallel/test-http-server-options-incoming-message.js new file mode 100644 index 00000000000000..a4bfa1b7646fc6 --- /dev/null +++ b/test/parallel/test-http-server-options-incoming-message.js @@ -0,0 +1,41 @@ +'use strict'; + +/** + * This test covers http.Server({ IncomingMessage }) option: + * With IncomingMessage option the server should use + * the new class for creating req Object instead of the default + * http.IncomingMessage. + */ +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +class MyIncomingMessage extends http.IncomingMessage { + getUserAgent() { + return this.headers['user-agent'] || 'unknown'; + } +} + +const server = http.Server({ + IncomingMessage: MyIncomingMessage +}, common.mustCall(function(req, res) { + assert.strictEqual(req.getUserAgent(), 'node-test'); + res.statusCode = 200; + res.end(); +})); +server.listen(); + +server.on('listening', function makeRequest() { + http.get({ + port: this.address().port, + headers: { + 'User-Agent': 'node-test' + } + }, (res) => { + assert.strictEqual(res.statusCode, 200); + res.on('end', () => { + server.close(); + }); + res.resume(); + }); +}); diff --git a/test/parallel/test-http-server-options-server-response.js b/test/parallel/test-http-server-options-server-response.js new file mode 100644 index 00000000000000..f5adf39bed6d16 --- /dev/null +++ b/test/parallel/test-http-server-options-server-response.js @@ -0,0 +1,35 @@ +'use strict'; + +/** + * This test covers http.Server({ ServerResponse }) option: + * With ServerResponse option the server should use + * the new class for creating res Object instead of the default + * http.ServerResponse. + */ +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +class MyServerResponse extends http.ServerResponse { + status(code) { + return this.writeHead(code, { 'Content-Type': 'text/plain' }); + } +} + +const server = http.Server({ + ServerResponse: MyServerResponse +}, common.mustCall(function(req, res) { + res.status(200); + res.end(); +})); +server.listen(); + +server.on('listening', function makeRequest() { + http.get({ port: this.address().port }, (res) => { + assert.strictEqual(res.statusCode, 200); + res.on('end', () => { + server.close(); + }); + res.resume(); + }); +}); diff --git a/test/parallel/test-https-server-options-incoming-message.js b/test/parallel/test-https-server-options-incoming-message.js new file mode 100644 index 00000000000000..102ee56751b800 --- /dev/null +++ b/test/parallel/test-https-server-options-incoming-message.js @@ -0,0 +1,51 @@ +'use strict'; + +/** + * This test covers http.Server({ IncomingMessage }) option: + * With IncomingMessage option the server should use + * the new class for creating req Object instead of the default + * http.IncomingMessage. + */ +const common = require('../common'); +const fixtures = require('../common/fixtures'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const http = require('http'); +const https = require('https'); + +class MyIncomingMessage extends http.IncomingMessage { + getUserAgent() { + return this.headers['user-agent'] || 'unknown'; + } +} + +const server = https.createServer({ + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem'), + ca: fixtures.readKey('ca1-cert.pem'), + IncomingMessage: MyIncomingMessage +}, common.mustCall(function(req, res) { + assert.strictEqual(req.getUserAgent(), 'node-test'); + res.statusCode = 200; + res.end(); +})); +server.listen(); + +server.on('listening', function makeRequest() { + https.get({ + port: this.address().port, + rejectUnauthorized: false, + headers: { + 'User-Agent': 'node-test' + } + }, (res) => { + assert.strictEqual(res.statusCode, 200); + res.on('end', () => { + server.close(); + }); + res.resume(); + }); +}); diff --git a/test/parallel/test-https-server-options-server-response.js b/test/parallel/test-https-server-options-server-response.js new file mode 100644 index 00000000000000..8745415f8b6596 --- /dev/null +++ b/test/parallel/test-https-server-options-server-response.js @@ -0,0 +1,47 @@ +'use strict'; + +/** + * This test covers http.Server({ ServerResponse }) option: + * With ServerResponse option the server should use + * the new class for creating res Object instead of the default + * http.ServerResponse. + */ +const common = require('../common'); +const fixtures = require('../common/fixtures'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const http = require('http'); +const https = require('https'); + +class MyServerResponse extends http.ServerResponse { + status(code) { + return this.writeHead(code, { 'Content-Type': 'text/plain' }); + } +} + +const server = https.createServer({ + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem'), + ca: fixtures.readKey('ca1-cert.pem'), + ServerResponse: MyServerResponse +}, common.mustCall(function(req, res) { + res.status(200); + res.end(); +})); +server.listen(); + +server.on('listening', function makeRequest() { + https.get({ + port: this.address().port, + rejectUnauthorized: false + }, (res) => { + assert.strictEqual(res.statusCode, 200); + res.on('end', () => { + server.close(); + }); + res.resume(); + }); +}); From 9de08f663adb2719bd47401b39b68e84b029de6e Mon Sep 17 00:00:00 2001 From: Peter Marton Date: Fri, 27 Oct 2017 09:18:59 +0200 Subject: [PATCH 088/131] http2: add http fallback options to .createServer This adds the Http1IncomingMessage and Http1ServerReponse options to http2.createServer(). PR-URL: https://github.com/nodejs/node/pull/15752 Reviewed-By: Matteo Collina Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell Reviewed-By: Evan Lucas --- doc/api/http2.md | 12 ++- lib/internal/http2/core.js | 15 +++- ...ttp2-https-fallback-http-server-options.js | 90 +++++++++++++++++++ 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-http2-https-fallback-http-server-options.js diff --git a/doc/api/http2.md b/doc/api/http2.md index 54a3b92849ac80..dd6acccee951a5 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1655,6 +1655,10 @@ changes: pr-url: https://github.com/nodejs/node/pull/16676 description: Added the `maxHeaderListPairs` option with a default limit of 128 header pairs. + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/15752 + description: Added the `Http1IncomingMessage` and `Http1ServerResponse` + option. --> * `options` {Object} @@ -1698,12 +1702,18 @@ changes: * `peerMaxConcurrentStreams` {number} Sets the maximum number of concurrent streams for the remote peer as if a SETTINGS frame had been received. Will be overridden if the remote peer sets its own value for. - `maxConcurrentStreams`. **Default** `100` + `maxConcurrentStreams`. **Default:** `100` * `selectPadding` {Function} When `options.paddingStrategy` is equal to `http2.constants.PADDING_STRATEGY_CALLBACK`, provides the callback function used to determine the padding. See [Using options.selectPadding][]. * `settings` {HTTP2 Settings Object} The initial settings to send to the remote peer upon connection. + * `Http1IncomingMessage` {http.IncomingMessage} Specifies the IncomingMessage + class to used for HTTP/1 fallback. Useful for extending the original + `http.IncomingMessage`. **Default:** `http.IncomingMessage` + * `Http1ServerResponse` {http.ServerResponse} Specifies the ServerResponse + class to used for HTTP/1 fallback. Useful for extending the original + `http.ServerResponse`. **Default:** `http.ServerResponse` * `onRequestHandler` {Function} See [Compatibility API][] * Returns: {Http2Server} diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 4ded895279bec2..15a79b7fd5cdea 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -5,6 +5,7 @@ require('internal/util').assertCrypto(); const { async_id_symbol } = process.binding('async_wrap'); +const http = require('http'); const binding = process.binding('http2'); const assert = require('assert'); const { Buffer } = require('buffer'); @@ -67,6 +68,8 @@ const NETServer = net.Server; const TLSServer = tls.Server; const kInspect = require('internal/util').customInspectSymbol; +const { kIncomingMessage } = require('_http_common'); +const { kServerResponse } = require('_http_server'); const kAlpnProtocol = Symbol('alpnProtocol'); const kAuthority = Symbol('authority'); @@ -2442,8 +2445,11 @@ function connectionListener(socket) { if (socket.alpnProtocol === false || socket.alpnProtocol === 'http/1.1') { // Fallback to HTTP/1.1 - if (options.allowHTTP1 === true) + if (options.allowHTTP1 === true) { + socket.server[kIncomingMessage] = options.Http1IncomingMessage; + socket.server[kServerResponse] = options.Http1ServerResponse; return httpConnectionListener.call(this, socket); + } // Let event handler deal with the socket if (!this.emit('unknownProtocol', socket)) socket.destroy(); @@ -2474,6 +2480,13 @@ function initializeOptions(options) { options.allowHalfOpen = true; assertIsObject(options.settings, 'options.settings'); options.settings = Object.assign({}, options.settings); + + // Used only with allowHTTP1 + options.Http1IncomingMessage = options.Http1IncomingMessage || + http.IncomingMessage; + options.Http1ServerResponse = options.Http1ServerResponse || + http.ServerResponse; + return options; } diff --git a/test/parallel/test-http2-https-fallback-http-server-options.js b/test/parallel/test-http2-https-fallback-http-server-options.js new file mode 100644 index 00000000000000..20e2b122a24e8c --- /dev/null +++ b/test/parallel/test-http2-https-fallback-http-server-options.js @@ -0,0 +1,90 @@ +// Flags: --expose-http2 +'use strict'; + +const common = require('../common'); +const fixtures = require('../common/fixtures'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const url = require('url'); +const tls = require('tls'); +const http2 = require('http2'); +const https = require('https'); +const http = require('http'); + +const key = fixtures.readKey('agent8-key.pem'); +const cert = fixtures.readKey('agent8-cert.pem'); +const ca = fixtures.readKey('fake-startcom-root-cert.pem'); + +function onRequest(request, response) { + const { socket: { alpnProtocol } } = request.httpVersion === '2.0' ? + request.stream.session : request; + response.status(200); + response.end(JSON.stringify({ + alpnProtocol, + httpVersion: request.httpVersion, + userAgent: request.getUserAgent() + })); +} + +class MyIncomingMessage extends http.IncomingMessage { + getUserAgent() { + return this.headers['user-agent'] || 'unknown'; + } +} + +class MyServerResponse extends http.ServerResponse { + status(code) { + return this.writeHead(code, { 'Content-Type': 'application/json' }); + } +} + +// HTTP/2 & HTTP/1.1 server +{ + const server = http2.createSecureServer( + { + cert, + key, allowHTTP1: true, + Http1IncomingMessage: MyIncomingMessage, + Http1ServerResponse: MyServerResponse + }, + common.mustCall(onRequest, 1) + ); + + server.listen(0); + + server.on('listening', common.mustCall(() => { + const { port } = server.address(); + const origin = `https://localhost:${port}`; + + // HTTP/1.1 client + https.get( + Object.assign(url.parse(origin), { + secureContext: tls.createSecureContext({ ca }), + headers: { 'User-Agent': 'node-test' } + }), + common.mustCall((response) => { + assert.strictEqual(response.statusCode, 200); + assert.strictEqual(response.statusMessage, 'OK'); + assert.strictEqual( + response.headers['content-type'], + 'application/json' + ); + + response.setEncoding('utf8'); + let raw = ''; + response.on('data', (chunk) => { raw += chunk; }); + response.on('end', common.mustCall(() => { + const { alpnProtocol, httpVersion, userAgent } = JSON.parse(raw); + assert.strictEqual(alpnProtocol, false); + assert.strictEqual(httpVersion, '1.1'); + assert.strictEqual(userAgent, 'node-test'); + + server.close(); + })); + }) + ); + })); +} From 420a9073e52e4f29a699e3e4ef62cfb9121c7c78 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Tue, 6 Feb 2018 18:38:31 +0200 Subject: [PATCH 089/131] doc: fix typo in http2.md PR-URL: https://github.com/nodejs/node/pull/18602 Reviewed-By: Anatoli Papirovski Reviewed-By: Luigi Pinca --- doc/api/http2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/http2.md b/doc/api/http2.md index dd6acccee951a5..a56e561b2ab8f6 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1701,7 +1701,7 @@ changes: and the total frame length will *not* necessarily be aligned at 8 bytes. * `peerMaxConcurrentStreams` {number} Sets the maximum number of concurrent streams for the remote peer as if a SETTINGS frame had been received. Will - be overridden if the remote peer sets its own value for. + be overridden if the remote peer sets its own value for `maxConcurrentStreams`. **Default:** `100` * `selectPadding` {Function} When `options.paddingStrategy` is equal to `http2.constants.PADDING_STRATEGY_CALLBACK`, provides the callback function From cf8c43244b0003210c8f3290638fd17ef9f7e10f Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Tue, 6 Feb 2018 22:34:50 +0100 Subject: [PATCH 090/131] doc: add missing "changes" key in YAML comment PR-URL: https://github.com/nodejs/node/pull/18605 Reviewed-By: Anna Henningsen Reviewed-By: Anatoli Papirovski --- doc/api/http.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/http.md b/doc/api/http.md index 1b15247cb7d5f5..d2a5f0ce43d377 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -1666,6 +1666,7 @@ Found'`. ## http.createServer([options][, requestListener]) - `algorithm` {string} - `key` {string | Buffer | TypedArray | DataView} - `iv` {string | Buffer | TypedArray | DataView} From dc44a2ef65a3da2d0ca56876b3b60e1ae084c282 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Fri, 9 Feb 2018 04:08:30 +0200 Subject: [PATCH 109/131] doc: fix links in YAML metadata of assert.md PR-URL: https://github.com/nodejs/node/pull/18670 Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca --- doc/api/assert.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index da02053f31785e..1c4567eaa58aaa 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -113,7 +113,9 @@ changes: description: Enumerable symbol properties are now compared. - version: v9.0.0 pr-url: https://github.com/nodejs/node/pull/15036 - description: NaN is now compared using the [SameValueZero][] comparison. + description: NaN is now compared using the + [SameValueZero](https://tc39.github.io/ecma262/#sec-samevaluezero) + comparison. - version: v8.5.0 pr-url: https://github.com/nodejs/node/pull/15001 description: Error names and messages are now properly compared @@ -461,7 +463,9 @@ changes: description: -0 and +0 are not considered equal anymore. - version: v9.0.0 pr-url: https://github.com/nodejs/node/pull/15036 - description: NaN is now compared using the [SameValueZero][] comparison. + description: NaN is now compared using the + [SameValueZero](https://tc39.github.io/ecma262/#sec-samevaluezero) + comparison. - version: v9.0.0 pr-url: https://github.com/nodejs/node/pull/15001 description: Error names and messages are now properly compared From 557ec07a75fa57d098cbcc748bdb7db2538e4c52 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 9 Feb 2018 09:00:00 -0600 Subject: [PATCH 110/131] doc: add devsnek to collaborators PR-URL: https://github.com/nodejs/node/pull/18679 Fixes: https://github.com/nodejs/node/issues/18544 Reviewed-By: Joyee Cheung Reviewed-By: Anatoli Papirovski Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Vse Mozhet Byt --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9767b71d0919c0..714fde2c143cf7 100644 --- a/README.md +++ b/README.md @@ -340,6 +340,8 @@ For more information about the governance of the Node.js project, see **Daniel Bevenius** <daniel.bevenius@gmail.com> * [DavidCai1993](https://github.com/DavidCai1993) - **David Cai** <davidcai1993@yahoo.com> (he/him) +* [devsnek](https://github.com/devsnek) - +**Gus Caplan** <me@gus.host> (he/him) * [edsadr](https://github.com/edsadr) - **Adrian Estrada** <edsadr@gmail.com> (he/him) * [eljefedelrodeodeljefe](https://github.com/eljefedelrodeodeljefe) - From 5dbe33c11e75e108449c858c3208a51458aa041e Mon Sep 17 00:00:00 2001 From: Peter Marton Date: Thu, 5 Oct 2017 14:24:12 +0200 Subject: [PATCH 111/131] http2: add req and res options to server creation Add optional Http2ServerRequest and Http2ServerResponse options to createServer and createSecureServer. Allows custom req & res classes that extend the default ones to be used without overriding the prototype. PR-URL: https://github.com/nodejs/node/pull/15560 Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Anatoli Papirovski Reviewed-By: Anna Henningsen --- doc/api/http2.md | 8 ++++ lib/internal/http2/compat.js | 8 ++-- lib/internal/http2/core.js | 10 ++++- .../test-http2-options-server-request.js | 40 +++++++++++++++++++ .../test-http2-options-server-response.js | 34 ++++++++++++++++ 5 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 test/parallel/test-http2-options-server-request.js create mode 100644 test/parallel/test-http2-options-server-response.js diff --git a/doc/api/http2.md b/doc/api/http2.md index a56e561b2ab8f6..63700ae0051ce9 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1714,6 +1714,14 @@ changes: * `Http1ServerResponse` {http.ServerResponse} Specifies the ServerResponse class to used for HTTP/1 fallback. Useful for extending the original `http.ServerResponse`. **Default:** `http.ServerResponse` + * `Http2ServerRequest` {http2.Http2ServerRequest} Specifies the + Http2ServerRequest class to use. + Useful for extending the original `Http2ServerRequest`. + **Default:** `Http2ServerRequest` + * `Http2ServerResponse` {htt2.Http2ServerResponse} Specifies the + Http2ServerResponse class to use. + Useful for extending the original `Http2ServerResponse`. + **Default:** `Http2ServerResponse` * `onRequestHandler` {Function} See [Compatibility API][] * Returns: {Http2Server} diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index b5dd81c80f4038..5e6c51377e94ba 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -661,11 +661,11 @@ class Http2ServerResponse extends Stream { } } -function onServerStream(stream, headers, flags, rawHeaders) { +function onServerStream(ServerRequest, ServerResponse, + stream, headers, flags, rawHeaders) { const server = this; - const request = new Http2ServerRequest(stream, headers, undefined, - rawHeaders); - const response = new Http2ServerResponse(stream); + const request = new ServerRequest(stream, headers, undefined, rawHeaders); + const response = new ServerResponse(stream); // Check for the CONNECT method const method = headers[HTTP2_HEADER_METHOD]; diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 15a79b7fd5cdea..70acda5c1d41f4 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -2487,6 +2487,10 @@ function initializeOptions(options) { options.Http1ServerResponse = options.Http1ServerResponse || http.ServerResponse; + options.Http2ServerRequest = options.Http2ServerRequest || + Http2ServerRequest; + options.Http2ServerResponse = options.Http2ServerResponse || + Http2ServerResponse; return options; } @@ -2552,7 +2556,11 @@ class Http2Server extends NETServer { function setupCompat(ev) { if (ev === 'request') { this.removeListener('newListener', setupCompat); - this.on('stream', onServerStream); + this.on('stream', onServerStream.bind( + this, + this[kOptions].Http2ServerRequest, + this[kOptions].Http2ServerResponse) + ); } } diff --git a/test/parallel/test-http2-options-server-request.js b/test/parallel/test-http2-options-server-request.js new file mode 100644 index 00000000000000..2143d379823d51 --- /dev/null +++ b/test/parallel/test-http2-options-server-request.js @@ -0,0 +1,40 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const h2 = require('http2'); + +class MyServerRequest extends h2.Http2ServerRequest { + getUserAgent() { + return this.headers['user-agent'] || 'unknown'; + } +} + +const server = h2.createServer({ + Http2ServerRequest: MyServerRequest +}, (req, res) => { + assert.strictEqual(req.getUserAgent(), 'node-test'); + + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end(); +}); +server.listen(0); + +server.on('listening', common.mustCall(() => { + + const client = h2.connect(`http://localhost:${server.address().port}`); + const req = client.request({ + ':path': '/', + 'User-Agent': 'node-test' + }); + + req.on('response', common.mustCall()); + + req.resume(); + req.on('end', common.mustCall(() => { + server.close(); + client.destroy(); + })); +})); diff --git a/test/parallel/test-http2-options-server-response.js b/test/parallel/test-http2-options-server-response.js new file mode 100644 index 00000000000000..6f1ae1881d22d8 --- /dev/null +++ b/test/parallel/test-http2-options-server-response.js @@ -0,0 +1,34 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const h2 = require('http2'); + +class MyServerResponse extends h2.Http2ServerResponse { + status(code) { + return this.writeHead(code, { 'Content-Type': 'text/plain' }); + } +} + +const server = h2.createServer({ + Http2ServerResponse: MyServerResponse +}, (req, res) => { + res.status(200); + res.end(); +}); +server.listen(0); + +server.on('listening', common.mustCall(() => { + + const client = h2.connect(`http://localhost:${server.address().port}`); + const req = client.request({ ':path': '/' }); + + req.on('response', common.mustCall()); + + req.resume(); + req.on('end', common.mustCall(() => { + server.close(); + client.destroy(); + })); +})); From ba05498a2026cde3fa0928a8f5f8a0e037923391 Mon Sep 17 00:00:00 2001 From: Justin Lee Date: Fri, 9 Feb 2018 09:02:50 -0800 Subject: [PATCH 112/131] doc: fix links to Style Guide and CPP Style Guide PR-URL: https://github.com/nodejs/node/pull/18683 Reviewed-By: Vse Mozhet Byt Reviewed-By: Joyee Cheung Reviewed-By: Ruben Bridgewater Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig --- doc/guides/contributing/pull-requests.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/guides/contributing/pull-requests.md b/doc/guides/contributing/pull-requests.md index 5812c8c54645e2..3d7c548bbd3022 100644 --- a/doc/guides/contributing/pull-requests.md +++ b/doc/guides/contributing/pull-requests.md @@ -109,12 +109,12 @@ If you are modifying code, please be sure to run `make lint` from time to time to ensure that the changes follow the Node.js code style guide. Any documentation you write (including code comments and API documentation) -should follow the [Style Guide](doc/STYLE_GUIDE.md). Code samples included +should follow the [Style Guide](../../STYLE_GUIDE.md). Code samples included in the API docs will also be checked when running `make lint` (or `vcbuild.bat lint` on Windows). For contributing C++ code, you may want to look at the -[C++ Style Guide](CPP_STYLE_GUIDE.md). +[C++ Style Guide](../../../CPP_STYLE_GUIDE.md). ### Step 4: Commit From 44e4999f11b6ce2f07832feb6064765ed5c762e7 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Wed, 7 Feb 2018 16:42:21 -0800 Subject: [PATCH 113/131] src: add "icu::" prefix before ICU symbols In ICU 61.x, icu4c will no longer put its declarations in the global namespace. Everything will be in the "icu::" namespace (or icu_60:: in the linker). Prepare for this. https://ssl.icu-project.org/trac/ticket/13460 --- src/inspector_io.cc | 9 +++++---- src/node_i18n.cc | 2 +- tools/icu/iculslocs.cc | 14 +++++++------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/inspector_io.cc b/src/inspector_io.cc index 9af4458c6b20f1..01ddc296b08693 100644 --- a/src/inspector_io.cc +++ b/src/inspector_io.cc @@ -74,11 +74,11 @@ std::string StringViewToUtf8(const StringView& view) { size_t result_length = view.length() * sizeof(*source); std::string result(result_length, '\0'); - UnicodeString utf16(unicodeSource, view.length()); + icu::UnicodeString utf16(unicodeSource, view.length()); // ICU components for std::string compatibility are not enabled in build... bool done = false; while (!done) { - CheckedArrayByteSink sink(&result[0], result_length); + icu::CheckedArrayByteSink sink(&result[0], result_length); utf16.toUTF8(sink); result_length = sink.NumberOfBytesAppended(); result.resize(result_length); @@ -111,8 +111,9 @@ void ReleasePairOnAsyncClose(uv_handle_t* async) { } // namespace std::unique_ptr Utf8ToStringView(const std::string& message) { - UnicodeString utf16 = - UnicodeString::fromUTF8(StringPiece(message.data(), message.length())); + icu::UnicodeString utf16 = + icu::UnicodeString::fromUTF8(icu::StringPiece(message.data(), + message.length())); StringView view(reinterpret_cast(utf16.getBuffer()), utf16.length()); return StringBuffer::create(view); diff --git a/src/node_i18n.cc b/src/node_i18n.cc index 71ae6a000336e2..d65fc55ed1fee5 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -523,7 +523,7 @@ const char* GetVersion(const char* type, } else if (!strcmp(type, TYPE_UNICODE)) { return U_UNICODE_VERSION; } else if (!strcmp(type, TYPE_TZ)) { - return TimeZone::getTZDataVersion(*status); + return icu::TimeZone::getTZDataVersion(*status); } else if (!strcmp(type, TYPE_CLDR)) { UVersionInfo versionArray; ulocdata_getCLDRVersion(versionArray, status); diff --git a/tools/icu/iculslocs.cc b/tools/icu/iculslocs.cc index ca312b783565c4..3ceb8d2a4d81d0 100644 --- a/tools/icu/iculslocs.cc +++ b/tools/icu/iculslocs.cc @@ -64,7 +64,7 @@ int VERBOSE = 0; #define RES_INDEX "res_index" #define INSTALLEDLOCALES "InstalledLocales" -CharString packageName; +icu::CharString packageName; const char* locale = RES_INDEX; // locale referring to our index void usage() { @@ -147,7 +147,7 @@ int localeExists(const char* loc, UBool* exists) { if (VERBOSE > 1) { printf("Trying to open %s:%s\n", packageName.data(), loc); } - LocalUResourceBundlePointer aResource( + icu::LocalUResourceBundlePointer aResource( ures_openDirect(packageName.data(), loc, &status)); *exists = FALSE; if (U_SUCCESS(status)) { @@ -189,11 +189,11 @@ void printIndent(FILE* bf, int indent) { * @return 0 for OK, 1 for err */ int dumpAllButInstalledLocales(int lev, - LocalUResourceBundlePointer* bund, + icu::LocalUResourceBundlePointer* bund, FILE* bf, UErrorCode* status) { ures_resetIterator(bund->getAlias()); - LocalUResourceBundlePointer t; + icu::LocalUResourceBundlePointer t; while (U_SUCCESS(*status) && ures_hasNext(bund->getAlias())) { t.adoptInstead(ures_getNextResource(bund->getAlias(), t.orphan(), status)); ASSERT_SUCCESS(status, "while processing table"); @@ -254,10 +254,10 @@ int list(const char* toBundle) { printf("\"locale\": %s\n", locale); } - LocalUResourceBundlePointer bund( + icu::LocalUResourceBundlePointer bund( ures_openDirect(packageName.data(), locale, &status)); ASSERT_SUCCESS(&status, "while opening the bundle"); - LocalUResourceBundlePointer installedLocales( + icu::LocalUResourceBundlePointer installedLocales( // NOLINTNEXTLINE (readability/null_usage) ures_getByKey(bund.getAlias(), INSTALLEDLOCALES, NULL, &status)); ASSERT_SUCCESS(&status, "while fetching installed locales"); @@ -295,7 +295,7 @@ int list(const char* toBundle) { } // OK, now list them. - LocalUResourceBundlePointer subkey; + icu::LocalUResourceBundlePointer subkey; int validCount = 0; for (int32_t i = 0; i < count; i++) { From f5d8a23166c841ff75d750f432016442e0c81b85 Mon Sep 17 00:00:00 2001 From: Jeff Principe Date: Mon, 16 Oct 2017 21:23:29 -0700 Subject: [PATCH 114/131] https: add extra options to Agent#getName() Adds the remaining options from tls.createSecureContext() to the string generated by Agent#getName(). This allows https.request() to accept the options and generate unique sockets appropriately. PR-URL: https://github.com/nodejs/node/pull/16402 Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- doc/api/https.md | 11 +-- lib/https.js | 24 +++++ .../test-https-agent-additional-options.js | 87 +++++++++++++++++++ test/parallel/test-https-agent-getname.js | 12 ++- .../test-https-agent-secure-protocol.js | 57 ------------ 5 files changed, 127 insertions(+), 64 deletions(-) create mode 100644 test/parallel/test-https-agent-additional-options.js delete mode 100644 test/parallel/test-https-agent-secure-protocol.js diff --git a/doc/api/https.md b/doc/api/https.md index da536d7ac84cad..4ac82220c85cef 100644 --- a/doc/api/https.md +++ b/doc/api/https.md @@ -12,7 +12,7 @@ separate module. added: v0.4.5 --> -An Agent object for HTTPS similar to [`http.Agent`][]. See [`https.request()`][] +An [`Agent`][] object for HTTPS similar to [`http.Agent`][]. See [`https.request()`][] for more information. ## Class: https.Server @@ -168,9 +168,10 @@ changes: Makes a request to a secure web server. -The following additional `options` from [`tls.connect()`][] are also accepted -when using a custom [`Agent`][]: `ca`, `cert`, `ciphers`, `clientCertEngine`, -`key`, `passphrase`, `pfx`, `rejectUnauthorized`, `secureProtocol`, `servername` +The following additional `options` from [`tls.connect()`][] are also accepted: +`ca`, `cert`, `ciphers`, `clientCertEngine`, `crl`, `dhparam`, `ecdhCurve`, +`honorCipherOrder`, `key`, `passphrase`, `pfx`, `rejectUnauthorized`, +`secureOptions`, `secureProtocol`, `servername`, `sessionIdContext` `options` can be an object, a string, or a [`URL`][] object. If `options` is a string, it is automatically parsed with [`url.parse()`][]. If it is a [`URL`][] @@ -220,7 +221,7 @@ const req = https.request(options, (res) => { }); ``` -Alternatively, opt out of connection pooling by not using an `Agent`. +Alternatively, opt out of connection pooling by not using an [`Agent`][]. Example: diff --git a/lib/https.js b/lib/https.js index 741ce84d2f8820..84ddeb5036a900 100644 --- a/lib/https.js +++ b/lib/https.js @@ -194,6 +194,30 @@ Agent.prototype.getName = function getName(options) { if (options.secureProtocol) name += options.secureProtocol; + name += ':'; + if (options.crl) + name += options.crl; + + name += ':'; + if (options.honorCipherOrder !== undefined) + name += options.honorCipherOrder; + + name += ':'; + if (options.ecdhCurve) + name += options.ecdhCurve; + + name += ':'; + if (options.dhparam) + name += options.dhparam; + + name += ':'; + if (options.secureOptions !== undefined) + name += options.secureOptions; + + name += ':'; + if (options.sessionIdContext) + name += options.sessionIdContext; + return name; }; diff --git a/test/parallel/test-https-agent-additional-options.js b/test/parallel/test-https-agent-additional-options.js new file mode 100644 index 00000000000000..8d10524d902ca7 --- /dev/null +++ b/test/parallel/test-https-agent-additional-options.js @@ -0,0 +1,87 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const crypto = require('crypto'); +const https = require('https'); +const fixtures = require('../common/fixtures'); + +const options = { + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem'), + ca: fixtures.readKey('ca1-cert.pem') +}; + +const server = https.Server(options, function(req, res) { + res.writeHead(200); + res.end('hello world\n'); +}); + +function getBaseOptions(port) { + return { + path: '/', + port: port, + ca: options.ca, + rejectUnautorized: true, + servername: 'agent1', + }; +} + +const updatedValues = new Map([ + ['dhparam', fixtures.readKey('dh2048.pem')], + ['ecdhCurve', 'secp384r1'], + ['honorCipherOrder', true], + ['secureOptions', crypto.constants.SSL_OP_CIPHER_SERVER_PREFERENCE], + ['secureProtocol', 'TLSv1_method'], + ['sessionIdContext', 'sessionIdContext'], +]); + +function variations(iter, port, cb) { + const { done, value } = iter.next(); + if (done) { + return common.mustCall(cb); + } else { + const [key, val] = value; + return common.mustCall(function(res) { + res.resume(); + https.globalAgent.once('free', common.mustCall(function() { + https.get( + Object.assign({}, getBaseOptions(port), { [key]: val }), + variations(iter, port, cb) + ); + })); + }); + } +} + +server.listen(0, common.mustCall(function() { + const port = this.address().port; + const globalAgent = https.globalAgent; + globalAgent.keepAlive = true; + https.get(getBaseOptions(port), variations( + updatedValues.entries(), + port, + common.mustCall(function(res) { + res.resume(); + globalAgent.once('free', common.mustCall(function() { + // Verify that different keep-alived connections are created + // for the base call and each variation + const keys = Object.keys(globalAgent.freeSockets); + assert.strictEqual(keys.length, 1 + updatedValues.size); + let i = 1; + for (const [, value] of updatedValues) { + assert.ok( + keys[i].startsWith(value.toString() + ':') || + keys[i].endsWith(':' + value.toString()) || + keys[i].includes(':' + value.toString() + ':') + ); + i++; + } + globalAgent.destroy(); + server.close(); + })); + }) + )); +})); diff --git a/test/parallel/test-https-agent-getname.js b/test/parallel/test-https-agent-getname.js index 0cdc9568d84470..c29e09731df0b2 100644 --- a/test/parallel/test-https-agent-getname.js +++ b/test/parallel/test-https-agent-getname.js @@ -12,7 +12,7 @@ const agent = new https.Agent(); // empty options assert.strictEqual( agent.getName({}), - 'localhost:::::::::::' + 'localhost:::::::::::::::::' ); // pass all options arguments @@ -23,13 +23,21 @@ const options = { ca: 'ca', cert: 'cert', ciphers: 'ciphers', + crl: [Buffer.from('c'), Buffer.from('r'), Buffer.from('l')], + dhparam: 'dhparam', + ecdhCurve: 'ecdhCurve', + honorCipherOrder: false, key: 'key', pfx: 'pfx', rejectUnauthorized: false, + secureOptions: 0, + secureProtocol: 'secureProtocol', servername: 'localhost', + sessionIdContext: 'sessionIdContext' }; assert.strictEqual( agent.getName(options), - '0.0.0.0:443:192.168.1.1:ca:cert::ciphers:key:pfx:false:localhost:' + '0.0.0.0:443:192.168.1.1:ca:cert::ciphers:key:pfx:false:localhost:' + + 'secureProtocol:c,r,l:false:ecdhCurve:dhparam:0:sessionIdContext' ); diff --git a/test/parallel/test-https-agent-secure-protocol.js b/test/parallel/test-https-agent-secure-protocol.js deleted file mode 100644 index 82554952e8446b..00000000000000 --- a/test/parallel/test-https-agent-secure-protocol.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -const common = require('../common'); -if (!common.hasCrypto) - common.skip('missing crypto'); - -const assert = require('assert'); -const https = require('https'); -const fixtures = require('../common/fixtures'); - -const options = { - key: fixtures.readKey('agent1-key.pem'), - cert: fixtures.readKey('agent1-cert.pem'), - ca: fixtures.readKey('ca1-cert.pem') -}; - -const server = https.Server(options, function(req, res) { - res.writeHead(200); - res.end('hello world\n'); -}); - -server.listen(0, common.mustCall(function() { - const port = this.address().port; - const globalAgent = https.globalAgent; - globalAgent.keepAlive = true; - https.get({ - path: '/', - port: port, - ca: options.ca, - rejectUnauthorized: true, - servername: 'agent1', - secureProtocol: 'SSLv23_method' - }, common.mustCall(function(res) { - res.resume(); - globalAgent.once('free', common.mustCall(function() { - https.get({ - path: '/', - port: port, - ca: options.ca, - rejectUnauthorized: true, - servername: 'agent1', - secureProtocol: 'TLSv1_method' - }, common.mustCall(function(res) { - res.resume(); - globalAgent.once('free', common.mustCall(function() { - // Verify that two keep-alive connections are created - // due to the different secureProtocol settings: - const keys = Object.keys(globalAgent.freeSockets); - assert.strictEqual(keys.length, 2); - assert.ok(keys[0].includes(':SSLv23_method')); - assert.ok(keys[1].includes(':TLSv1_method')); - globalAgent.destroy(); - server.close(); - })); - })); - })); - })); -})); From 1462b86b5a5726902c7aaf8ee8d95535cc307e22 Mon Sep 17 00:00:00 2001 From: alejandro estrada Date: Thu, 8 Feb 2018 13:01:33 -0500 Subject: [PATCH 115/131] src: replace var for let / const. Replace var for let or const. PR-URL: https://github.com/nodejs/node/pull/18649 Reviewed-By: Ruben Bridgewater Reviewed-By: Julian Duque Reviewed-By: James M Snell --- lib/internal/async_hooks.js | 4 ++-- lib/internal/bootstrap_node.js | 8 ++++---- lib/internal/readline.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 1e9b89ce5e65ff..ea49239a6178bb 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -262,7 +262,7 @@ function getOrSetAsyncId(object) { // the user to safeguard this call and make sure it's zero'd out when the // constructor is complete. function getDefaultTriggerAsyncId() { - var defaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; + let defaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; // If defaultTriggerAsyncId isn't set, use the executionAsyncId if (defaultTriggerAsyncId < 0) defaultTriggerAsyncId = async_id_fields[kExecutionAsyncId]; @@ -276,7 +276,7 @@ function defaultTriggerAsyncIdScope(triggerAsyncId, block, ...args) { const oldDefaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; async_id_fields[kDefaultTriggerAsyncId] = triggerAsyncId; - var ret; + let ret; try { ret = Reflect.apply(block, null, args); } finally { diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index 6b718df2acba5a..2766a8d28d0874 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -173,7 +173,7 @@ const fs = NativeModule.require('fs'); // read the source const filename = Module._resolveFilename(process.argv[1]); - var source = fs.readFileSync(filename, 'utf-8'); + const source = fs.readFileSync(filename, 'utf-8'); checkScriptSyntax(source, filename); process.exit(0); } @@ -219,7 +219,7 @@ // Read all of stdin - execute it. process.stdin.setEncoding('utf8'); - var code = ''; + let code = ''; process.stdin.on('data', function(d) { code += d; }); @@ -467,7 +467,7 @@ const versionTypes = icu.getVersion().split(','); for (var n = 0; n < versionTypes.length; n++) { - var name = versionTypes[n]; + const name = versionTypes[n]; const version = icu.getVersion(name); Object.defineProperty(process.versions, name, { writable: false, @@ -632,7 +632,7 @@ ]; NativeModule.prototype.compile = function() { - var source = NativeModule.getSource(this.id); + let source = NativeModule.getSource(this.id); source = NativeModule.wrap(source); this.loading = true; diff --git a/lib/internal/readline.js b/lib/internal/readline.js index b15ed4972ef7f2..e3d3007a75c645 100644 --- a/lib/internal/readline.js +++ b/lib/internal/readline.js @@ -9,8 +9,8 @@ const ansi = const kEscape = '\x1b'; -var getStringWidth; -var isFullWidthCodePoint; +let getStringWidth; +let isFullWidthCodePoint; function CSI(strings, ...args) { let ret = `${kEscape}[`; From cd1f35de4d6a76cb50be5c54fdb1d8e43c22a6eb Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 9 Feb 2018 01:22:37 +0800 Subject: [PATCH 116/131] fs: fix stack overflow in fs.readdirSync Previously, fs.readdirSync calls the function returned by env->push_values_to_array_function() in batch and check the returned Maybe right away in C++, which can lead to assertions if the call stack already reaches the maximum size. This patch fixes that by returning early the call fails so the stack overflow error will be properly thrown into JS land. PR-URL: https://github.com/nodejs/node/pull/18647 Fixes: https://github.com/nodejs/node/issues/18645 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- src/node_file.cc | 12 +++++++++--- .../parallel/test-fs-readdir-stack-overflow.js | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 test/parallel/test-fs-readdir-stack-overflow.js diff --git a/src/node_file.cc b/src/node_file.cc index c1f0853820157d..2790f274100a60 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -913,14 +913,20 @@ static void ReadDir(const FunctionCallbackInfo& args) { name_v[name_idx++] = filename.ToLocalChecked(); if (name_idx >= arraysize(name_v)) { - fn->Call(env->context(), names, name_idx, name_v) - .ToLocalChecked(); + MaybeLocal ret = fn->Call(env->context(), names, name_idx, + name_v); + if (ret.IsEmpty()) { + return; + } name_idx = 0; } } if (name_idx > 0) { - fn->Call(env->context(), names, name_idx, name_v).ToLocalChecked(); + MaybeLocal ret = fn->Call(env->context(), names, name_idx, name_v); + if (ret.IsEmpty()) { + return; + } } args.GetReturnValue().Set(names); diff --git a/test/parallel/test-fs-readdir-stack-overflow.js b/test/parallel/test-fs-readdir-stack-overflow.js new file mode 100644 index 00000000000000..b7dea52cc37ec5 --- /dev/null +++ b/test/parallel/test-fs-readdir-stack-overflow.js @@ -0,0 +1,18 @@ +'use strict'; + +const common = require('../common'); + +const fs = require('fs'); + +function recurse() { + fs.readdirSync('.'); + recurse(); +} + +common.expectsError( + () => recurse(), + { + type: RangeError, + message: 'Maximum call stack size exceeded' + } +); From 2433c8757ae943b5c82e6067771186be0ad0db98 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 9 Feb 2018 14:14:28 -0500 Subject: [PATCH 117/131] doc: add history for url.parse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18685 Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Luigi Pinca Reviewed-By: Michael Dawson Reviewed-By: Tobias Nießen Reviewed-By: Ruben Bridgewater Reviewed-By: Сковорода Никита Андреевич --- doc/api/url.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/api/url.md b/doc/api/url.md index d015b4e35ce077..38cb95d6097ae9 100644 --- a/doc/api/url.md +++ b/doc/api/url.md @@ -1030,6 +1030,11 @@ The formatting process operates as follows: ### url.parse(urlString[, parseQueryString[, slashesDenoteHost]]) * `urlString` {string} The URL string to parse. From 083c6f8e1cf8c30fd74496391b44f1b4368461e0 Mon Sep 17 00:00:00 2001 From: Aonghus O Nia Date: Thu, 8 Feb 2018 17:01:23 -0500 Subject: [PATCH 118/131] doc: fix exporting a function example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missing the length argument in napi_create_function. PR-URL: https://github.com/nodejs/node/pull/18661 Reviewed-By: Michael Dawson Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- doc/api/n-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 38cf7a88420be5..c1d7d2fe0a1e0b 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -918,7 +918,7 @@ For example, to set a function to be returned by the `require()` for the addon: napi_value Init(napi_env env, napi_value exports) { napi_value method; napi_status status; - status = napi_create_function(env, "exports", Method, NULL, &method); + status = napi_create_function(env, "exports", NAPI_AUTO_LENGTH, Method, NULL, &method); if (status != napi_ok) return NULL; return method; } From 2bbc5dd38edb5b1598c30bd3fac662703b826796 Mon Sep 17 00:00:00 2001 From: Mihail Bodrov Date: Fri, 9 Feb 2018 02:42:23 +0300 Subject: [PATCH 119/131] buffer: simplify check size in assertSize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/18665 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso Reviewed-By: Joyee Cheung Reviewed-By: Anatoli Papirovski Reviewed-By: James M Snell --- lib/buffer.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 91b30012ef65d5..95d41206c67142 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -237,9 +237,7 @@ function assertSize(size) { if (typeof size !== 'number') { err = new errors.TypeError('ERR_INVALID_ARG_TYPE', 'size', 'number', size); - } else if (size < 0) { - err = new errors.RangeError('ERR_INVALID_OPT_VALUE', 'size', size); - } else if (size > kMaxLength) { + } else if (size < 0 || size > kMaxLength) { err = new errors.RangeError('ERR_INVALID_OPT_VALUE', 'size', size); } From a53067c439a2f2f11eecf1e74d7c5cf16d92ac6a Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Fri, 9 Feb 2018 14:23:42 +0100 Subject: [PATCH 120/131] build: no longer have v8-debug.h as dependency. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref: https://github.com/nodejs/node/issues/18643 PR-URL: https://github.com/nodejs/node/pull/18677 Refs: https://github.com/nodejs/node/issues/18643 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- node.gyp | 1 - 1 file changed, 1 deletion(-) diff --git a/node.gyp b/node.gyp index 7966a4f159e0ef..fb40152c6b2620 100644 --- a/node.gyp +++ b/node.gyp @@ -376,7 +376,6 @@ 'src/util-inl.h', 'deps/http_parser/http_parser.h', 'deps/v8/include/v8.h', - 'deps/v8/include/v8-debug.h', # javascript files to make for an even more pleasant IDE experience '<@(library_files)', # node.gyp is added to the project by default. From 38451b9fd2c404c0fda4e628d0c86d8feef0733f Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Fri, 9 Feb 2018 10:20:20 -0600 Subject: [PATCH 121/131] doc: add error check to fs example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the err passed to the callback of fs.open() was not checked. PR-URL: https://github.com/nodejs/node/pull/18681 Reviewed-By: Anatoli Papirovski Reviewed-By: Vse Mozhet Byt Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- doc/api/fs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/fs.md b/doc/api/fs.md index 48e1ea1bb177a5..b79461b8ee9887 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -1397,6 +1397,7 @@ fs.open('myfile', 'wx', (err, fd) => { fs.exists('myfile', (exists) => { if (exists) { fs.open('myfile', 'r', (err, fd) => { + if (err) throw err; readMyData(fd); }); } else { From 28207e3afa4b18849ca7ab95a6add601e9798c3b Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Sat, 10 Feb 2018 09:32:49 +0100 Subject: [PATCH 122/131] test: fix flaky repl-timeout-throw Don't disconnect the child until all exceptions are thrown. Fixes: https://github.com/nodejs/node/issues/18659 PR-URL: https://github.com/nodejs/node/pull/18692 Fixes: https://github.com/nodejs/node/issues/18659 Reviewed-By: Ben Noordhuis Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig --- test/sequential/test-repl-timeout-throw.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/sequential/test-repl-timeout-throw.js b/test/sequential/test-repl-timeout-throw.js index aa933394b42ae7..3636b93ddfc2b2 100644 --- a/test/sequential/test-repl-timeout-throw.js +++ b/test/sequential/test-repl-timeout-throw.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const spawn = require('child_process').spawn; @@ -13,6 +13,8 @@ child.stdout.setEncoding('utf8'); child.stdout.on('data', function(c) { process.stdout.write(c); stdout += c; + if (stdout.includes('> THROW 2')) + child.stdin.end(); }); child.stdin.write = function(original) { @@ -46,8 +48,6 @@ child.stdout.once('data', function() { ' });\n' + ' });\n' + '});"";\n'); - - setTimeout(child.stdin.end.bind(child.stdin), common.platformTimeout(200)); } }); From 3bf848178be6810443153b28a1e056cf6f48827a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Sat, 10 Feb 2018 16:32:01 +0100 Subject: [PATCH 123/131] doc: mark NAPI_AUTO_LENGTH as code PR-URL: https://github.com/nodejs/node/pull/18697 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Jeremiah Senkpiel Reviewed-By: Luigi Pinca --- doc/api/n-api.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index c1d7d2fe0a1e0b..1b94e71d1a1ade 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -554,10 +554,10 @@ NAPI_NO_RETURN void napi_fatal_error(const char* location, - `[in] location`: Optional location at which the error occurred. - `[in] location_len`: The length of the location in bytes, or -NAPI_AUTO_LENGTH if it is null-terminated. +`NAPI_AUTO_LENGTH` if it is null-terminated. - `[in] message`: The message associated with the error. - `[in] message_len`: The length of the message in bytes, or -NAPI_AUTO_LENGTH if it is +`NAPI_AUTO_LENGTH` if it is null-terminated. The function call does not return, the process will be terminated. @@ -1255,7 +1255,7 @@ napi_status napi_create_function(napi_env env, - `[in] utf8name`: A string representing the name of the function encoded as UTF8. - `[in] length`: The length of the utf8name in bytes, or -NAPI_AUTO_LENGTH if it is null-terminated. +`NAPI_AUTO_LENGTH` if it is null-terminated. - `[in] cb`: A function pointer to the native function to be invoked when the created function is invoked from JavaScript. - `[in] data`: Optional arbitrary context data to be passed into the native @@ -1483,7 +1483,7 @@ napi_status napi_create_string_latin1(napi_env env, - `[in] env`: The environment that the API is invoked under. - `[in] str`: Character buffer representing a ISO-8859-1-encoded string. - `[in] length`: The length of the string in bytes, or -NAPI_AUTO_LENGTH if it is null-terminated. +`NAPI_AUTO_LENGTH` if it is null-terminated. - `[out] result`: A `napi_value` representing a JavaScript String. Returns `napi_ok` if the API succeeded. @@ -1507,7 +1507,7 @@ napi_status napi_create_string_utf16(napi_env env, - `[in] env`: The environment that the API is invoked under. - `[in] str`: Character buffer representing a UTF16-LE-encoded string. - `[in] length`: The length of the string in two-byte code units, or -NAPI_AUTO_LENGTH if it is null-terminated. +`NAPI_AUTO_LENGTH` if it is null-terminated. - `[out] result`: A `napi_value` representing a JavaScript String. Returns `napi_ok` if the API succeeded. @@ -1530,7 +1530,7 @@ napi_status napi_create_string_utf8(napi_env env, - `[in] env`: The environment that the API is invoked under. - `[in] str`: Character buffer representing a UTF8-encoded string. -- `[in] length`: The length of the string in bytes, or NAPI_AUTO_LENGTH +- `[in] length`: The length of the string in bytes, or `NAPI_AUTO_LENGTH` if it is null-terminated. - `[out] result`: A `napi_value` representing a JavaScript String. @@ -3053,7 +3053,7 @@ napi_status napi_define_class(napi_env env, - `[in] utf8name`: Name of the JavaScript constructor function; this is not required to be the same as the C++ class name, though it is recommended for clarity. - - `[in] length`: The length of the utf8name in bytes, or NAPI_AUTO_LENGTH + - `[in] length`: The length of the utf8name in bytes, or `NAPI_AUTO_LENGTH` if it is null-terminated. - `[in] constructor`: Callback function that handles constructing instances of the class. (This should be a static method on the class, not an actual From f1ff1070b81bb7eaf7a2fffce3044bde976612c9 Mon Sep 17 00:00:00 2001 From: Mihail Bodrov Date: Sat, 10 Feb 2018 19:38:45 +0300 Subject: [PATCH 124/131] url: simplify constructor URLSearchParams. Remove needless check null PR-URL: https://github.com/nodejs/node/pull/18700 Reviewed-By: Ruben Bridgewater Reviewed-By: Gus Caplan Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- lib/internal/url.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/internal/url.js b/lib/internal/url.js index b395e77b046f10..cae4037b6e7792 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -98,8 +98,7 @@ class URLSearchParams { constructor(init = undefined) { if (init === null || init === undefined) { this[searchParams] = []; - } else if ((typeof init === 'object' && init !== null) || - typeof init === 'function') { + } else if (typeof init === 'object' || typeof init === 'function') { const method = init[Symbol.iterator]; if (method === this[Symbol.iterator]) { // While the spec does not have this branch, we can use it as a From 9da102f435158bc12659856523383ad7ca1f44b4 Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Wed, 7 Feb 2018 17:46:49 -0800 Subject: [PATCH 125/131] async_hooks: rename PromiseWrap.parentId Rename the `parentId` property on the PromiseWrap object to a `isChainedPromise` property. The former wasn't quite useful as it was always defined to be the same value as the trigger id available in the init hook. Instead rename the property to be closer to the information it communicates: whether the promise is a chained promise or not. PR-URL: https://github.com/nodejs/node/pull/18633 Fixes: https://github.com/nodejs/node/issues/18470 Reviewed-By: Andreas Madsen Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu --- doc/api/async_hooks.md | 6 +++--- src/async_wrap.cc | 25 +++++++++++------------ test/parallel/test-async-hooks-promise.js | 4 ++-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index e0922fcd1134f5..2156477ae13c61 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -301,10 +301,10 @@ and document their own resource objects. For example, such a resource object could contain the SQL query being executed. In the case of Promises, the `resource` object will have `promise` property -that refers to the Promise that is being initialized, and a `parentId` property -set to the `asyncId` of a parent Promise, if there is one, and `undefined` +that refers to the Promise that is being initialized, and a `isChainedPromise` +property, set to `true` if the promise has a parent promise, and `false` otherwise. For example, in the case of `b = a.then(handler)`, `a` is considered -a parent Promise of `b`. +a parent Promise of `b`. Here, `b` is considered a chained promise. *Note*: In some cases the resource object is reused for performance reasons, it is thus not safe to use it as a key in a `WeakMap` or add properties to it. diff --git a/src/async_wrap.cc b/src/async_wrap.cc index 20d21e31df8d5b..c9dfc40c0ca52d 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -239,7 +239,7 @@ class PromiseWrap : public AsyncWrap { size_t self_size() const override { return sizeof(*this); } static constexpr int kPromiseField = 1; - static constexpr int kParentAsyncIdField = 2; + static constexpr int kIsChainedPromiseField = 2; static constexpr int kInternalFieldCount = 3; static PromiseWrap* New(Environment* env, @@ -248,8 +248,8 @@ class PromiseWrap : public AsyncWrap { bool silent); static void GetPromise(Local property, const PropertyCallbackInfo& info); - static void getParentAsyncId(Local property, - const PropertyCallbackInfo& info); + static void getIsChainedPromise(Local property, + const PropertyCallbackInfo& info); }; PromiseWrap* PromiseWrap::New(Environment* env, @@ -259,11 +259,10 @@ PromiseWrap* PromiseWrap::New(Environment* env, Local object = env->promise_wrap_template() ->NewInstance(env->context()).ToLocalChecked(); object->SetInternalField(PromiseWrap::kPromiseField, promise); - if (parent_wrap != nullptr) { - object->SetInternalField(PromiseWrap::kParentAsyncIdField, - Number::New(env->isolate(), - parent_wrap->get_async_id())); - } + object->SetInternalField(PromiseWrap::kIsChainedPromiseField, + parent_wrap != nullptr ? + v8::True(env->isolate()) : + v8::False(env->isolate())); CHECK_EQ(promise->GetAlignedPointerFromInternalField(0), nullptr); promise->SetInternalField(0, object); return new PromiseWrap(env, object, silent); @@ -274,10 +273,10 @@ void PromiseWrap::GetPromise(Local property, info.GetReturnValue().Set(info.Holder()->GetInternalField(kPromiseField)); } -void PromiseWrap::getParentAsyncId(Local property, - const PropertyCallbackInfo& info) { +void PromiseWrap::getIsChainedPromise(Local property, + const PropertyCallbackInfo& info) { info.GetReturnValue().Set( - info.Holder()->GetInternalField(kParentAsyncIdField)); + info.Holder()->GetInternalField(kIsChainedPromiseField)); } static void PromiseHook(PromiseHookType type, Local promise, @@ -377,8 +376,8 @@ static void SetupHooks(const FunctionCallbackInfo& args) { FIXED_ONE_BYTE_STRING(env->isolate(), "promise"), PromiseWrap::GetPromise); promise_wrap_template->SetAccessor( - FIXED_ONE_BYTE_STRING(env->isolate(), "parentId"), - PromiseWrap::getParentAsyncId); + FIXED_ONE_BYTE_STRING(env->isolate(), "isChainedPromise"), + PromiseWrap::getIsChainedPromise); env->set_promise_wrap_template(promise_wrap_template); } } diff --git a/test/parallel/test-async-hooks-promise.js b/test/parallel/test-async-hooks-promise.js index d712fd616c647b..4b36f6026b36c6 100644 --- a/test/parallel/test-async-hooks-promise.js +++ b/test/parallel/test-async-hooks-promise.js @@ -21,8 +21,8 @@ const a = Promise.resolve(42); const b = a.then(common.mustCall()); assert.strictEqual(initCalls[0].triggerId, 1); -assert.strictEqual(initCalls[0].resource.parentId, undefined); +assert.strictEqual(initCalls[0].resource.isChainedPromise, false); assert.strictEqual(initCalls[0].resource.promise, a); assert.strictEqual(initCalls[1].triggerId, initCalls[0].id); -assert.strictEqual(initCalls[1].resource.parentId, initCalls[0].id); +assert.strictEqual(initCalls[1].resource.isChainedPromise, true); assert.strictEqual(initCalls[1].resource.promise, b); From 80cd943791c30c147dc296963ddfeee43d96f48c Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 12 Feb 2018 12:31:23 +0100 Subject: [PATCH 126/131] tools: fix eslint isRequired Currently the call can lead to a TypeError with the message: `Cannot read property 'value' of undefined`. This fixes it by first checking that the first argument is truthy. PR-URL: https://github.com/nodejs/node/pull/18729 Reviewed-By: Anatoli Papirovski Reviewed-By: Benjamin Gruenbaum --- tools/eslint-rules/rules-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/eslint-rules/rules-utils.js b/tools/eslint-rules/rules-utils.js index 2bfab1c6399ee8..0fda705fb290b7 100644 --- a/tools/eslint-rules/rules-utils.js +++ b/tools/eslint-rules/rules-utils.js @@ -8,7 +8,7 @@ * require calls. */ module.exports.isRequired = function(node, modules) { - return node.callee.name === 'require' && + return node.callee.name === 'require' && node.arguments.length !== 0 && modules.includes(node.arguments[0].value); }; From 0315dd0146041521dcc4e9f89bac620ea5036933 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 9 Dec 2017 10:32:34 -0600 Subject: [PATCH 127/131] src: flatten ContextifyContext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flattens ContextifyContext allows the context interface to be used in other parts of the code base. PR-URL: https://github.com/nodejs/node/pull/17560 Reviewed-By: Michaël Zasso Reviewed-By: Tiancheng "Timothy" Gu --- node.gyp | 1 + src/node_contextify.cc | 907 ++++++++++++++++++++--------------------- src/node_contextify.h | 100 +++++ 3 files changed, 546 insertions(+), 462 deletions(-) create mode 100644 src/node_contextify.h diff --git a/node.gyp b/node.gyp index fb40152c6b2620..aef032cd5c5132 100644 --- a/node.gyp +++ b/node.gyp @@ -343,6 +343,7 @@ 'src/node.h', 'src/node_buffer.h', 'src/node_constants.h', + 'src/node_contextify.h', 'src/node_debug_options.h', 'src/node_http2.h', 'src/node_http2_state.h', diff --git a/src/node_contextify.cc b/src/node_contextify.cc index d50c6023dc8349..6fe9276d82ecab 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -23,8 +23,10 @@ #include "node_watchdog.h" #include "base_object-inl.h" #include "v8-debug.h" +#include "node_contextify.h" namespace node { +namespace contextify { using v8::Array; using v8::ArrayBuffer; @@ -92,550 +94,531 @@ Local Uint32ToName(Local context, uint32_t index) { .ToLocalChecked(); } -class ContextifyContext { - protected: - // V8 reserves the first field in context objects for the debugger. We use the - // second field to hold a reference to the sandbox object. - enum { kSandboxObjectIndex = 1 }; - - Environment* const env_; - Persistent context_; - - public: - ContextifyContext(Environment* env, - Local sandbox_obj, - Local options_obj) - : env_(env) { - Local v8_context = CreateV8Context(env, sandbox_obj, options_obj); - context_.Reset(env->isolate(), v8_context); - - // Allocation failure or maximum call stack size reached - if (context_.IsEmpty()) - return; - context_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter); - context_.MarkIndependent(); - } - - - ~ContextifyContext() { - context_.Reset(); - } - +} // anonymous namespace - inline Environment* env() const { - return env_; - } +ContextifyContext::ContextifyContext( + Environment* env, + Local sandbox_obj, Local options_obj) : env_(env) { + Local v8_context = CreateV8Context(env, sandbox_obj, options_obj); + context_.Reset(env->isolate(), v8_context); + + // Allocation failure or maximum call stack size reached + if (context_.IsEmpty()) + return; + context_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter); + context_.MarkIndependent(); +} - inline Local context() const { - return PersistentToLocal(env()->isolate(), context_); - } +ContextifyContext::~ContextifyContext() { + context_.Reset(); +} - inline Local global_proxy() const { - return context()->Global(); - } +// This is an object that just keeps an internal pointer to this +// ContextifyContext. It's passed to the NamedPropertyHandler. If we +// pass the main JavaScript context object we're embedded in, then the +// NamedPropertyHandler will store a reference to it forever and keep it +// from getting gc'd. +Local ContextifyContext::CreateDataWrapper(Environment* env) { + EscapableHandleScope scope(env->isolate()); + Local wrapper = + env->script_data_constructor_function() + ->NewInstance(env->context()).FromMaybe(Local()); + if (wrapper.IsEmpty()) + return scope.Escape(Local::New(env->isolate(), Local())); + + Wrap(wrapper, this); + return scope.Escape(wrapper); +} - inline Local sandbox() const { - return Local::Cast(context()->GetEmbedderData(kSandboxObjectIndex)); +Local ContextifyContext::CreateV8Context( + Environment* env, + Local sandbox_obj, + Local options_obj) { + EscapableHandleScope scope(env->isolate()); + Local function_template = + FunctionTemplate::New(env->isolate()); + + function_template->SetClassName(sandbox_obj->GetConstructorName()); + + Local object_template = + function_template->InstanceTemplate(); + + NamedPropertyHandlerConfiguration config(PropertyGetterCallback, + PropertySetterCallback, + PropertyDescriptorCallback, + PropertyDeleterCallback, + PropertyEnumeratorCallback, + PropertyDefinerCallback, + CreateDataWrapper(env)); + + IndexedPropertyHandlerConfiguration indexed_config( + IndexedPropertyGetterCallback, + IndexedPropertySetterCallback, + IndexedPropertyDescriptorCallback, + IndexedPropertyDeleterCallback, + PropertyEnumeratorCallback, + IndexedPropertyDefinerCallback, + CreateDataWrapper(env)); + + object_template->SetHandler(config); + object_template->SetHandler(indexed_config); + + Local ctx = NewContext(env->isolate(), object_template); + + if (ctx.IsEmpty()) { + env->ThrowError("Could not instantiate context"); + return Local(); } - // This is an object that just keeps an internal pointer to this - // ContextifyContext. It's passed to the NamedPropertyHandler. If we - // pass the main JavaScript context object we're embedded in, then the - // NamedPropertyHandler will store a reference to it forever and keep it - // from getting gc'd. - Local CreateDataWrapper(Environment* env) { - EscapableHandleScope scope(env->isolate()); - Local wrapper = - env->script_data_constructor_function() - ->NewInstance(env->context()).FromMaybe(Local()); - if (wrapper.IsEmpty()) - return scope.Escape(Local::New(env->isolate(), Local())); - - Wrap(wrapper, this); - return scope.Escape(wrapper); + ctx->SetSecurityToken(env->context()->GetSecurityToken()); + + // We need to tie the lifetime of the sandbox object with the lifetime of + // newly created context. We do this by making them hold references to each + // other. The context can directly hold a reference to the sandbox as an + // embedder data field. However, we cannot hold a reference to a v8::Context + // directly in an Object, we instead hold onto the new context's global + // object instead (which then has a reference to the context). + ctx->SetEmbedderData(kSandboxObjectIndex, sandbox_obj); + sandbox_obj->SetPrivate(env->context(), + env->contextify_global_private_symbol(), + ctx->Global()); + + Local name = + options_obj->Get(env->context(), env->name_string()) + .ToLocalChecked(); + CHECK(name->IsString()); + Utf8Value name_val(env->isolate(), name); + + ContextInfo info(*name_val); + + Local origin = + options_obj->Get(env->context(), + FIXED_ONE_BYTE_STRING(env->isolate(), "origin")) + .ToLocalChecked(); + if (!origin->IsUndefined()) { + CHECK(origin->IsString()); + Utf8Value origin_val(env->isolate(), origin); + info.origin = *origin_val; } + env->AssignToContext(ctx, info); - Local CreateV8Context(Environment* env, - Local sandbox_obj, - Local options_obj) { - EscapableHandleScope scope(env->isolate()); - Local function_template = - FunctionTemplate::New(env->isolate()); - - function_template->SetClassName(sandbox_obj->GetConstructorName()); - - Local object_template = - function_template->InstanceTemplate(); - - NamedPropertyHandlerConfiguration config(PropertyGetterCallback, - PropertySetterCallback, - PropertyDescriptorCallback, - PropertyDeleterCallback, - PropertyEnumeratorCallback, - PropertyDefinerCallback, - CreateDataWrapper(env)); - - IndexedPropertyHandlerConfiguration indexed_config( - IndexedPropertyGetterCallback, - IndexedPropertySetterCallback, - IndexedPropertyDescriptorCallback, - IndexedPropertyDeleterCallback, - PropertyEnumeratorCallback, - IndexedPropertyDefinerCallback, - CreateDataWrapper(env)); - - object_template->SetHandler(config); - object_template->SetHandler(indexed_config); + return scope.Escape(ctx); +} - Local ctx = NewContext(env->isolate(), object_template); - if (ctx.IsEmpty()) { - env->ThrowError("Could not instantiate context"); - return Local(); - } +void ContextifyContext::Init(Environment* env, Local target) { + Local function_template = + FunctionTemplate::New(env->isolate()); + function_template->InstanceTemplate()->SetInternalFieldCount(1); + env->set_script_data_constructor_function(function_template->GetFunction()); - ctx->SetSecurityToken(env->context()->GetSecurityToken()); - - // We need to tie the lifetime of the sandbox object with the lifetime of - // newly created context. We do this by making them hold references to each - // other. The context can directly hold a reference to the sandbox as an - // embedder data field. However, we cannot hold a reference to a v8::Context - // directly in an Object, we instead hold onto the new context's global - // object instead (which then has a reference to the context). - ctx->SetEmbedderData(kSandboxObjectIndex, sandbox_obj); - sandbox_obj->SetPrivate(env->context(), - env->contextify_global_private_symbol(), - ctx->Global()); - - Local name = - options_obj->Get(env->context(), env->name_string()) - .ToLocalChecked(); - CHECK(name->IsString()); - Utf8Value name_val(env->isolate(), name); - - ContextInfo info(*name_val); - - Local origin = - options_obj->Get(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "origin")) - .ToLocalChecked(); - if (!origin->IsUndefined()) { - CHECK(origin->IsString()); - Utf8Value origin_val(env->isolate(), origin); - info.origin = *origin_val; - } + env->SetMethod(target, "runInDebugContext", RunInDebugContext); + env->SetMethod(target, "makeContext", MakeContext); + env->SetMethod(target, "isContext", IsContext); +} - env->AssignToContext(ctx, info); - return scope.Escape(ctx); +void ContextifyContext::RunInDebugContext( + const FunctionCallbackInfo& args) { + Local script_source(args[0]->ToString(args.GetIsolate())); + if (script_source.IsEmpty()) + return; // Exception pending. + Local debug_context = Debug::GetDebugContext(args.GetIsolate()); + Environment* env = Environment::GetCurrent(args); + if (debug_context.IsEmpty()) { + // Force-load the debug context. + auto dummy_event_listener = [] (const Debug::EventDetails&) {}; + Debug::SetDebugEventListener(args.GetIsolate(), dummy_event_listener); + debug_context = Debug::GetDebugContext(args.GetIsolate()); + CHECK(!debug_context.IsEmpty()); + // Ensure that the debug context has an Environment assigned in case + // a fatal error is raised. The fatal exception handler in node.cc + // is not equipped to deal with contexts that don't have one and + // can't easily be taught that due to a deficiency in the V8 API: + // there is no way for the embedder to tell if the data index is + // in use. + const int index = Environment::kContextEmbedderDataIndex; + debug_context->SetAlignedPointerInEmbedderData(index, env); } - - static void Init(Environment* env, Local target) { - Local function_template = - FunctionTemplate::New(env->isolate()); - function_template->InstanceTemplate()->SetInternalFieldCount(1); - env->set_script_data_constructor_function(function_template->GetFunction()); - - env->SetMethod(target, "runInDebugContext", RunInDebugContext); - env->SetMethod(target, "makeContext", MakeContext); - env->SetMethod(target, "isContext", IsContext); - } + Context::Scope context_scope(debug_context); + MaybeLocal