From e573c99bfdec6686ef8209b96e71226266ad792b Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 1 May 2019 22:49:04 +0200 Subject: [PATCH 001/129] assert: fix `assert.fail()` stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes sure the error message visible in the error stack created when using `assert.fail()` without any arguments or the message set to `undefined` or `null` as only argument. That was masked before due to other changes. PR-URL: https://github.com/nodejs/node/pull/27525 Reviewed-By: Rich Trott Reviewed-By: Michaël Zasso --- lib/assert.js | 14 ++++++-------- test/parallel/test-assert-fail.js | 3 ++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index ffa71bfad8d412..dece9a08a78142 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -92,9 +92,10 @@ function innerFail(obj) { function fail(actual, expected, message, operator, stackStartFn) { const argsLen = arguments.length; - let internalMessage; - if (argsLen === 0) { - internalMessage = 'Failed'; + let internalMessage = false; + if (actual == null && argsLen <= 1) { + internalMessage = true; + message = 'Failed'; } else if (argsLen === 1) { message = actual; actual = undefined; @@ -118,14 +119,11 @@ function fail(actual, expected, message, operator, stackStartFn) { actual, expected, operator: operator === undefined ? 'fail' : operator, - stackStartFn: stackStartFn || fail + stackStartFn: stackStartFn || fail, + message }; - if (message !== undefined) { - errArgs.message = message; - } const err = new AssertionError(errArgs); if (internalMessage) { - err.message = internalMessage; err.generatedMessage = true; } throw err; diff --git a/test/parallel/test-assert-fail.js b/test/parallel/test-assert-fail.js index 51c69372dd8e5d..e2003f2ce91da8 100644 --- a/test/parallel/test-assert-fail.js +++ b/test/parallel/test-assert-fail.js @@ -13,7 +13,8 @@ assert.throws( operator: 'fail', actual: undefined, expected: undefined, - generatedMessage: true + generatedMessage: true, + stack: /Failed/ } ); From 3367bad08038b6c4c38c96f8935a994368eb2dfc Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 1 May 2019 23:52:37 +0200 Subject: [PATCH 002/129] assert: refine assertion message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes sure that the error message is more appropriate than before by checking closer what operator is used and which is not. It also increases the total number of lines printed to the user. PR-URL: https://github.com/nodejs/node/pull/27525 Reviewed-By: Rich Trott Reviewed-By: Michaël Zasso --- lib/internal/assert/assertion_error.js | 63 ++++++++++--------- test/parallel/test-assert-deep.js | 28 ++++++--- test/parallel/test-assert.js | 26 +++++--- .../test-assert-position-indicator.js | 2 +- 4 files changed, 74 insertions(+), 45 deletions(-) diff --git a/lib/internal/assert/assertion_error.js b/lib/internal/assert/assertion_error.js index 7ab74e6777cdc1..048d7be75fc662 100644 --- a/lib/internal/assert/assertion_error.js +++ b/lib/internal/assert/assertion_error.js @@ -17,19 +17,18 @@ const kReadableOperator = { strictEqual: 'Expected values to be strictly equal:', strictEqualObject: 'Expected "actual" to be reference-equal to "expected":', deepEqual: 'Expected values to be loosely deep-equal:', - equal: 'Expected values to be loosely equal:', notDeepStrictEqual: 'Expected "actual" not to be strictly deep-equal to:', notStrictEqual: 'Expected "actual" to be strictly unequal to:', notStrictEqualObject: 'Expected "actual" not to be reference-equal to "expected":', notDeepEqual: 'Expected "actual" not to be loosely deep-equal to:', - notEqual: 'Expected "actual" to be loosely unequal to:', notIdentical: 'Values identical but not reference-equal:', + notDeepEqualUnequal: 'Expected values not to be loosely deep-equal:' }; // Comparing short primitives should just show === / !== instead of using the // diff. -const kMaxShortLength = 10; +const kMaxShortLength = 12; function copyError(source) { const keys = Object.keys(source); @@ -81,13 +80,12 @@ function createErrDiff(actual, expected, operator) { let i = 0; let indicator = ''; - // In case both values are objects explicitly mark them as not reference equal - // for the `strictEqual` operator. + // In case both values are objects or functions explicitly mark them as not + // reference equal for the `strictEqual` operator. if (operator === 'strictEqual' && - typeof actual === 'object' && - typeof expected === 'object' && - actual !== null && - expected !== null) { + ((typeof actual === 'object' && actual !== null && + typeof expected === 'object' && expected !== null) || + (typeof actual === 'function' && typeof expected === 'function'))) { operator = 'strictEqualObject'; } @@ -153,9 +151,9 @@ function createErrDiff(actual, expected, operator) { // Only remove lines in case it makes sense to collapse those. // TODO: Accept env to always show the full error. - if (actualLines.length > 30) { - actualLines[26] = `${blue}...${white}`; - while (actualLines.length > 27) { + if (actualLines.length > 50) { + actualLines[46] = `${blue}...${white}`; + while (actualLines.length > 47) { actualLines.pop(); } } @@ -282,8 +280,8 @@ function createErrDiff(actual, expected, operator) { } } } - // Inspected object to big (Show ~20 rows max) - if (printedLines > 20 && i < maxLines - 2) { + // Inspected object to big (Show ~50 rows max) + if (printedLines > 50 && i < maxLines - 2) { return `${msg}${skippedMsg}\n${res}\n${blue}...${white}${other}\n` + `${blue}...${white}`; } @@ -348,39 +346,41 @@ class AssertionError extends Error { let base = kReadableOperator[operator]; const res = inspectValue(actual).split('\n'); - // In case "actual" is an object, it should not be reference equal. + // In case "actual" is an object or a function, it should not be + // reference equal. if (operator === 'notStrictEqual' && - typeof actual === 'object' && - actual !== null) { + (typeof actual === 'object' && actual !== null || + typeof actual === 'function')) { base = kReadableOperator.notStrictEqualObject; } // Only remove lines in case it makes sense to collapse those. // TODO: Accept env to always show the full error. - if (res.length > 30) { - res[26] = `${blue}...${white}`; - while (res.length > 27) { + if (res.length > 50) { + res[46] = `${blue}...${white}`; + while (res.length > 47) { res.pop(); } } // Only print a single input. if (res.length === 1) { - super(`${base} ${res[0]}`); + super(`${base}${res[0].length > 5 ? '\n\n' : ' '}${res[0]}`); } else { super(`${base}\n\n${res.join('\n')}\n`); } } else { let res = inspectValue(actual); - let other = ''; + let other = inspectValue(expected); const knownOperators = kReadableOperator[operator]; - if (operator === 'notDeepEqual' || operator === 'notEqual') { - res = `${kReadableOperator[operator]}\n\n${res}`; + if ((operator === 'notDeepEqual' || operator === 'notEqual') && + res === other) { + res = `${knownOperators}\n\n${res}`; if (res.length > 1024) { res = `${res.slice(0, 1021)}...`; } + super(res); } else { - other = `${inspectValue(expected)}`; if (res.length > 512) { res = `${res.slice(0, 509)}...`; } @@ -388,12 +388,19 @@ class AssertionError extends Error { other = `${other.slice(0, 509)}...`; } if (operator === 'deepEqual' || operator === 'equal') { - res = `${knownOperators}\n\n${res}\n\nshould equal\n\n`; + const eq = operator === 'deepEqual' ? 'deep-equal' : 'equal'; + res = `${knownOperators}\n\n${res}\n\nshould loosely ${eq}\n\n`; } else { - other = ` ${operator} ${other}`; + const newOperator = kReadableOperator[`${operator}Unequal`]; + if (newOperator) { + const eq = operator === 'notDeepEqual' ? 'deep-equal' : 'equal'; + res = `${newOperator}\n\n${res}\n\nshould not loosely ${eq}\n\n`; + } else { + other = ` ${operator} ${other}`; + } } + super(`${res}${other}`); } - super(`${res}${other}`); } } diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js index 3675a18a284fd4..013c47121b95b0 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -195,7 +195,7 @@ function assertDeepAndStrictEqual(a, b) { function assertNotDeepOrStrict(a, b, err) { assert.throws( () => assert.deepEqual(a, b), - err || re`${a}\n\nshould equal\n\n${b}` + err || re`${a}\n\nshould loosely deep-equal\n\n${b}` ); assert.throws( () => assert.deepStrictEqual(a, b), @@ -204,7 +204,7 @@ function assertNotDeepOrStrict(a, b, err) { assert.throws( () => assert.deepEqual(b, a), - err || re`${b}\n\nshould equal\n\n${a}` + err || re`${b}\n\nshould loosely deep-equal\n\n${a}` ); assert.throws( () => assert.deepStrictEqual(b, a), @@ -651,6 +651,20 @@ assertDeepAndStrictEqual(-0, -0); assertDeepAndStrictEqual(a, b); } +assert.throws( + () => assert.notDeepEqual(1, true), + { + message: /1\n\nshould not loosely deep-equal\n\ntrue/ + } +); + +assert.throws( + () => assert.notDeepEqual(1, 1), + { + message: /Expected "actual" not to be loosely deep-equal to:\n\n1/ + } +); + assert.deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)); assert.throws(() => { assert.deepEqual(new Date(), new Date(2000, 3, 14)); }, @@ -779,7 +793,7 @@ assert.throws( () => assert.notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), { name: 'AssertionError', - message: 'Expected "actual" not to be strictly deep-equal to: ' + + message: 'Expected "actual" not to be strictly deep-equal to:\n\n' + util.inspect(new Date(2000, 3, 14)) } ); @@ -815,11 +829,11 @@ assert.throws( message: `${defaultMsgStartFull}\n\n+ /a/m\n- /a/` }); assert.throws( - () => assert.deepStrictEqual(/a/igm, /a/im), + () => assert.deepStrictEqual(/aa/igm, /aa/im), { code: 'ERR_ASSERTION', name: 'AssertionError', - message: `${defaultMsgStartFull}\n\n+ /a/gim\n- /a/im\n ^` + message: `${defaultMsgStartFull}\n\n+ /aa/gim\n- /aa/im\n ^` }); { @@ -939,12 +953,12 @@ assert.deepStrictEqual(obj1, obj2); } // Strict equal with identical objects that are not identical -// by reference and longer than 30 elements +// by reference and longer than 50 elements // E.g., assert.deepStrictEqual({ a: Symbol() }, { a: Symbol() }) { const a = {}; const b = {}; - for (let i = 0; i < 35; i++) { + for (let i = 0; i < 55; i++) { a[`symbol${i}`] = Symbol(); b[`symbol${i}`] = Symbol(); } diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 003e67b380d88d..a189f69b9a1813 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -80,12 +80,20 @@ assert.throws( assert.throws( () => a.notStrictEqual('a '.repeat(30), 'a '.repeat(30)), { - message: 'Expected "actual" to be strictly unequal to: ' + + message: 'Expected "actual" to be strictly unequal to:\n\n' + `'${'a '.repeat(30)}'`, name: 'AssertionError' } ); +assert.throws( + () => a.notEqual(1, 1), + { + message: '1 != 1', + operator: '!=' + } +); + a.notStrictEqual(2, '2'); // Testing the throwing. @@ -281,15 +289,15 @@ testShortAssertionMessage('a', '"a"'); testShortAssertionMessage('foo', '\'foo\''); testShortAssertionMessage(0, '0'); testShortAssertionMessage(Symbol(), 'Symbol()'); +testShortAssertionMessage(undefined, 'undefined'); +testShortAssertionMessage(-Infinity, '-Infinity'); +testShortAssertionMessage(function() {}, '[Function]'); testAssertionMessage([], '[]'); testAssertionMessage(/a/, '/a/'); testAssertionMessage(/abc/gim, '/abc/gim'); testAssertionMessage({}, '{}'); -testAssertionMessage(undefined, 'undefined'); -testAssertionMessage(-Infinity, '-Infinity'); testAssertionMessage([1, 2, 3], '[\n+ 1,\n+ 2,\n+ 3\n+ ]'); testAssertionMessage(function f() {}, '[Function: f]'); -testAssertionMessage(function() {}, '[Function]'); testAssertionMessage(circular, '{\n+ x: [Circular],\n+ y: 1\n+ }'); testAssertionMessage({ a: undefined, b: null }, '{\n+ a: undefined,\n+ b: null\n+ }'); @@ -579,12 +587,12 @@ assert.throws( `${actExp} ... Lines skipped\n` + '\n' + ' [\n' + - '+ 1,\n'.repeat(10) + + '+ 1,\n'.repeat(25) + '...\n' + - '- 2,\n'.repeat(10) + + '- 2,\n'.repeat(25) + '...'; assert.throws( - () => assert.deepEqual(Array(12).fill(1), Array(12).fill(2)), + () => assert.deepEqual(Array(28).fill(1), Array(28).fill(2)), { message }); const obj1 = {}; @@ -612,8 +620,8 @@ assert.throws( ); message = 'Expected "actual" not to be strictly deep-equal to:' + - `\n\n[${'\n 1,'.repeat(25)}\n...\n`; - const data = Array(31).fill(1); + `\n\n[${'\n 1,'.repeat(45)}\n...\n`; + const data = Array(51).fill(1); assert.throws( () => assert.notDeepEqual(data, data), { message }); diff --git a/test/pseudo-tty/test-assert-position-indicator.js b/test/pseudo-tty/test-assert-position-indicator.js index 26f82b5b13fb1b..e56299d2744761 100644 --- a/test/pseudo-tty/test-assert-position-indicator.js +++ b/test/pseudo-tty/test-assert-position-indicator.js @@ -13,6 +13,6 @@ assert.throws( // Confirm that there is a position indicator. assert.throws( - () => { assert.deepStrictEqual('aaa', 'aaaa'); }, + () => { assert.deepStrictEqual('aaaa', 'aaaaa'); }, (err) => err.message.includes('^') ); From ec642f18cc269151986c247755a866e0516ba2f3 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 1 May 2019 23:54:02 +0200 Subject: [PATCH 003/129] assert: use less read operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reduces the total amount of reads when using `assert.ok()` with a falsy value. That increases the read performance significantly. Also remove a comment that can not be addressed. PR-URL: https://github.com/nodejs/node/pull/27525 Reviewed-By: Rich Trott Reviewed-By: Michaël Zasso --- lib/assert.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index dece9a08a78142..6e0b850b40c6a7 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -172,8 +172,8 @@ function getCode(fd, line, column) { let lines = 0; // Prevent blocking the event loop by limiting the maximum amount of // data that may be read. - let maxReads = 64; // bytesPerRead * maxReads = 512 kb - const bytesPerRead = 8192; + let maxReads = 32; // bytesPerRead * maxReads = 512 kb + const bytesPerRead = 16384; // Use a single buffer up front that is reused until the call site is found. let buffer = Buffer.allocUnsafe(bytesPerRead); while (maxReads-- !== 0) { @@ -619,11 +619,6 @@ function checkIsPromise(obj) { // Accept native ES6 promises and promises that are implemented in a similar // way. Do not accept thenables that use a function as `obj` and that have no // `catch` handler. - - // TODO: thenables are checked up until they have the correct methods, - // but according to documentation, the `then` method should receive - // the `fulfill` and `reject` arguments as well or it may be never resolved. - return isPromise(obj) || obj !== null && typeof obj === 'object' && typeof obj.then === 'function' && From a5dab9e85acc9b6c575e49dfdce2237ce284b97b Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Mon, 29 Apr 2019 17:27:25 +0200 Subject: [PATCH 004/129] test: deflake test-tls-js-stream `socket.destroy()` can destory the stream before the chunk to write with `socket.end()` is actually sent. Furthermore `socket.destroy()` destroys `p` and not the actual raw socket. As a result it is possible that the connection is left open. Remove `socket.destroy()` to ensure that the chunk is sent. Also use `common.mustCall()` to ensure that the `'secureConnection'` and `'secureConnect'` events are emitted exactly once. PR-URL: https://github.com/nodejs/node/pull/27478 Fixes: https://github.com/nodejs/node/issues/26938 Reviewed-By: Rich Trott Reviewed-By: Sam Roberts Reviewed-By: Fedor Indutny --- test/parallel/parallel.status | 2 -- test/parallel/test-tls-js-stream.js | 33 +++++++++++------------------ 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 33576ffc633a9f..c0a3f2a4c0000f 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -25,8 +25,6 @@ test-http2-client-upload-reject: PASS,FLAKY [$system==linux] [$system==macos] -# https://github.com/nodejs/node/issues/26938 -test-tls-js-stream: PASS,FLAKY [$arch==arm || $arch==arm64] # https://github.com/nodejs/node/issues/26610 diff --git a/test/parallel/test-tls-js-stream.js b/test/parallel/test-tls-js-stream.js index 908f4c48876a56..298252962ba9cd 100644 --- a/test/parallel/test-tls-js-stream.js +++ b/test/parallel/test-tls-js-stream.js @@ -6,24 +6,19 @@ if (!common.hasCrypto) const fixtures = require('../common/fixtures'); -const assert = require('assert'); const net = require('net'); const stream = require('stream'); const tls = require('tls'); -const connected = { - client: 0, - server: 0 -}; - const server = tls.createServer({ key: fixtures.readKey('agent1-key.pem'), cert: fixtures.readKey('agent1-cert.pem') -}, function(c) { +}, common.mustCall(function(c) { console.log('new client'); - connected.server++; + + c.resume(); c.end('ohai'); -}).listen(0, function() { +})).listen(0, common.mustCall(function() { const raw = net.connect(this.address().port); let pending = false; @@ -32,6 +27,10 @@ const server = tls.createServer({ p._read(); }); + raw.on('end', function() { + p.push(null); + }); + const p = new stream.Duplex({ read: function read() { pending = false; @@ -53,23 +52,15 @@ const server = tls.createServer({ const socket = tls.connect({ socket: p, rejectUnauthorized: false - }, function() { + }, common.mustCall(function() { console.log('client secure'); - connected.client++; - - socket.end('hello'); socket.resume(); - socket.destroy(); - }); + socket.end('hello'); + })); socket.once('close', function() { console.log('client close'); server.close(); }); -}); - -process.once('exit', function() { - assert.strictEqual(connected.client, 1); - assert.strictEqual(connected.server, 1); -}); +})); From c0cdf30e6e4c31fd0c95457f418f6de58f2fd8e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Wed, 24 Apr 2019 22:43:31 +0200 Subject: [PATCH 005/129] doc: improve CCM example Applications should never attempt to use the deciphered message if authentication fails. In reality, this is usually not a problem since OpenSSL does not disclose the plaintext in this case, but it is still a design mistake and can lead to critical security problems in other cipher modes and implementations. PR-URL: https://github.com/nodejs/node/pull/27396 Reviewed-By: Sam Roberts Reviewed-By: Benjamin Gruenbaum Reviewed-By: Ben Noordhuis Reviewed-By: Rich Trott --- doc/api/crypto.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index e6392d2d511442..21df0e55987f8b 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -2885,6 +2885,7 @@ try { decipher.final(); } catch (err) { console.error('Authentication failed!'); + return; } console.log(receivedPlaintext); From c53a674be7fce781251d11b41d0bc67e8fe90e24 Mon Sep 17 00:00:00 2001 From: Aditya Pratap Singh Date: Sat, 4 May 2019 13:45:48 +0200 Subject: [PATCH 006/129] doc: add example to test doc for clarity Update the documentation for test execution for tests in a single file PR-URL: https://github.com/nodejs/node/pull/27561 Reviewed-By: Rich Trott Reviewed-By: Trivikram Kamat --- BUILDING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index a077eb933b1df4..8f35fa20cde45b 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -295,10 +295,11 @@ If you want to run the linter without running tests, use `make lint`/`vcbuild lint`. It will run both JavaScript linting and C++ linting. -If you are updating tests and just want to run a single test to check it: +If you are updating tests and want to run tests in a single test file +(e.g. `test/parallel/test-stream2-transform.js`): ```text -$ python tools/test.py -J --mode=release parallel/test-stream2-transform +$ python tools/test.py parallel/test-stream2-transform.js ``` You can execute the entire suite of tests for a given subsystem From b6e540a9a2f9e96c90399de5f197d205c34b87ee Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sun, 5 May 2019 10:12:08 +0200 Subject: [PATCH 007/129] test: fix flaky test-tls-multiple-cas-as-string The following error is emitted in a nondeterministic way on the server side socket on macOS: ``` events.js:173 throw er; // Unhandled 'error' event ^ Error: read ECONNRESET at TLSWrap.onStreamRead (internal/stream_base_commons.js:183:27) Emitted 'error' event at: at emitErrorNT (internal/streams/destroy.js:91:8) at emitErrorAndCloseNT (internal/streams/destroy.js:59:3) at processTicksAndRejections (internal/process/task_queues.js:84:9) ``` Prevent the error from being emitted by moving the `socket.end()` call to the client. Also, run tests in parallel and use `common.mustCall()`. PR-URL: https://github.com/nodejs/node/pull/27569 Reviewed-By: Rich Trott Reviewed-By: Sam Roberts --- .../test-tls-multiple-cas-as-string.js | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/test/parallel/test-tls-multiple-cas-as-string.js b/test/parallel/test-tls-multiple-cas-as-string.js index 2612de55fe988f..679d6b6c4cdc42 100644 --- a/test/parallel/test-tls-multiple-cas-as-string.js +++ b/test/parallel/test-tls-multiple-cas-as-string.js @@ -15,26 +15,29 @@ const ca2 = fixtures.readKey('ca2-cert.pem', 'utf8'); const cert = fixtures.readKey('agent3-cert.pem', 'utf8'); const key = fixtures.readKey('agent3-key.pem', 'utf8'); -function test(ca, next) { - const server = tls.createServer({ ca, cert, key }, function(conn) { - this.close(); - conn.end(); - }); +function test(ca) { + const server = tls.createServer({ ca, cert, key }); server.addContext('agent3', { ca, cert, key }); const host = common.localhostIPv4; - server.listen(0, host, function() { - tls.connect({ servername: 'agent3', host, port: this.address().port, ca }); - }); - - if (next) { - server.once('close', next); - } + server.listen(0, host, common.mustCall(() => { + const socket = tls.connect({ + servername: 'agent3', + host, + port: server.address().port, + ca + }, common.mustCall(() => { + socket.end(); + })); + + socket.on('close', () => { + server.close(); + }); + })); } // `ca1` is not actually necessary for the certificate validation -- maybe // the fixtures should be written in a way that requires it? -const array = [ca1, ca2]; -const string = `${ca1}\n${ca2}`; -test(array, common.mustCall(() => test(string))); +test([ca1, ca2]); +test(`${ca1}\n${ca2}`); From 815a95734e99ab0ac6c82163ad5699308ef1e2ff Mon Sep 17 00:00:00 2001 From: cjihrig Date: Fri, 3 May 2019 09:49:47 -0400 Subject: [PATCH 008/129] test: refactor test-tls-enable-trace-cli.js PR-URL: https://github.com/nodejs/node/pull/27553 Reviewed-By: Sam Roberts Reviewed-By: Luigi Pinca Reviewed-By: Rich Trott --- test/parallel/test-tls-enable-trace-cli.js | 26 ++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/test/parallel/test-tls-enable-trace-cli.js b/test/parallel/test-tls-enable-trace-cli.js index 5b7189af702dad..d41334a0f51d63 100644 --- a/test/parallel/test-tls-enable-trace-cli.js +++ b/test/parallel/test-tls-enable-trace-cli.js @@ -22,23 +22,24 @@ const child = fork(__filename, ['test'], { execArgv: ['--trace-tls'] }); +let stdout = ''; let stderr = ''; +child.stdout.setEncoding('utf8'); child.stderr.setEncoding('utf8'); +child.stdout.on('data', (data) => stdout += data); child.stderr.on('data', (data) => stderr += data); -child.on('close', common.mustCall(() => { +child.on('close', common.mustCall((code, signal) => { + // For debugging and observation of actual trace output. + console.log(stderr); + + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout.trim(), ''); assert(/Warning: Enabling --trace-tls can expose sensitive/.test(stderr)); assert(/Received Record/.test(stderr)); assert(/ClientHello/.test(stderr)); })); -// For debugging and observation of actual trace output. -child.stderr.pipe(process.stderr); -child.stdout.pipe(process.stdout); - -child.on('exit', common.mustCall((code) => { - assert.strictEqual(code, 0); -})); - function test() { const { connect, keys @@ -54,6 +55,13 @@ function test() { key: keys.agent6.key }, }, common.mustCall((err, pair, cleanup) => { + if (err) { + console.error(err); + console.error(err.opensslErrorStack); + console.error(err.reason); + assert(err); + } + return cleanup(); })); } From c78de13238444d0b91607bff49195c38da669ce5 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Thu, 17 May 2018 16:25:36 +0200 Subject: [PATCH 009/129] repl: handle uncaughtException properly When running the REPL as standalone program it's now possible to use `process.on('uncaughtException', listener)`. It is going to use those listeners from now on and the regular error output is suppressed. It also fixes the issue that REPL instances started inside of an application would silence all application errors. It is now prohibited to add the exception listener in such REPL instances. Trying to add such listeners throws an `ERR_INVALID_REPL_INPUT` error. Fixes: https://github.com/nodejs/node/issues/19998 PR-URL: https://github.com/nodejs/node/pull/27151 Fixes: https://github.com/nodejs/node/issues/19998 Reviewed-By: Lance Ball Reviewed-By: Rich Trott --- doc/api/errors.md | 11 ++- doc/api/repl.md | 34 ++++++++- lib/internal/errors.js | 1 + lib/repl.js | 59 +++++++++++---- .../parallel/test-repl-pretty-custom-stack.js | 2 - .../test-repl-uncaught-exception-async.js | 44 ++++++++++++ ...test-repl-uncaught-exception-standalone.js | 38 ++++++++++ test/parallel/test-repl-uncaught-exception.js | 72 +++++++++++++++++++ 8 files changed, 244 insertions(+), 17 deletions(-) create mode 100644 test/parallel/test-repl-uncaught-exception-async.js create mode 100644 test/parallel/test-repl-uncaught-exception-standalone.js create mode 100644 test/parallel/test-repl-uncaught-exception.js diff --git a/doc/api/errors.md b/doc/api/errors.md index 2cb4bc067e24b8..9420e07b16c871 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1310,8 +1310,14 @@ An invalid `options.protocol` was passed to `http.request()`. ### ERR_INVALID_REPL_EVAL_CONFIG -Both `breakEvalOnSigint` and `eval` options were set in the REPL config, which -is not supported. +Both `breakEvalOnSigint` and `eval` options were set in the [`REPL`][] config, +which is not supported. + + +### ERR_INVALID_REPL_INPUT + +The input may not be used in the [`REPL`][]. All prohibited inputs are +documented in the [`REPL`][]'s documentation. ### ERR_INVALID_RETURN_PROPERTY @@ -2307,6 +2313,7 @@ such as `process.stdout.on('data')`. [`Class: assert.AssertionError`]: assert.html#assert_class_assert_assertionerror [`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE [`EventEmitter`]: events.html#events_class_eventemitter +[`REPL`]: repl.html [`Writable`]: stream.html#stream_class_stream_writable [`child_process`]: child_process.html [`cipher.getAuthTag()`]: crypto.html#crypto_cipher_getauthtag diff --git a/doc/api/repl.md b/doc/api/repl.md index e0ec27b7e3bada..563817c632297f 100644 --- a/doc/api/repl.md +++ b/doc/api/repl.md @@ -138,16 +138,47 @@ global or scoped variable, the input `fs` will be evaluated on-demand as ``` #### Global Uncaught Exceptions + The REPL uses the [`domain`][] module to catch all uncaught exceptions for that REPL session. This use of the [`domain`][] module in the REPL has these side effects: -* Uncaught exceptions do not emit the [`'uncaughtException'`][] event. +* Uncaught exceptions only emit the [`'uncaughtException'`][] event if the + `repl` is used as standalone program. If the `repl` is included anywhere in + another application, adding a listener for this event will throw an + [`ERR_INVALID_REPL_INPUT`][] exception. * Trying to use [`process.setUncaughtExceptionCaptureCallback()`][] throws an [`ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE`][] error. +As standalone program: + +```js +process.on('uncaughtException', () => console.log('Uncaught')); + +throw new Error('foobar'); +// Uncaught +``` + +When used in another application: + +```js +process.on('uncaughtException', () => console.log('Uncaught')); +// TypeError [ERR_INVALID_REPL_INPUT]: Listeners for `uncaughtException` +// cannot be used in the REPL + +throw new Error('foobar'); +// Thrown: +// Error: foobar +``` + #### Assignment of the `_` (underscore) variable + +Type: Documentation-only + +The legacy HTTP parser, used by default in versions of Node.js prior to 12.0.0, +is deprecated. This deprecation applies to users of the +[`--http-parser=legacy`][] command-line flag. + +[`--http-parser=legacy`]: cli.html#cli_http_parser_library [`--pending-deprecation`]: cli.html#cli_pending_deprecation [`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size [`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array From 876441eefb0ca15ce90c1b5debcc6f59bdd2e536 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 9 May 2019 13:17:19 -0700 Subject: [PATCH 016/129] meta: move orangemocha to Collaborator Emeriti list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alexis confirmed in email that that they should be moved to the Emeriti list. PR-URL: https://github.com/nodejs/node/pull/27626 Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso Reviewed-By: Richard Lau Reviewed-By: Alexis Campailla Reviewed-By: Ruben Bridgewater --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 749c32be0676c5..92bc23073379c7 100644 --- a/README.md +++ b/README.md @@ -401,8 +401,6 @@ For information about the governance of the Node.js project, see **Teddy Katz** <teddy.katz@gmail.com> (he/him) * [ofrobots](https://github.com/ofrobots) - **Ali Ijaz Sheikh** <ofrobots@google.com> (he/him) -* [orangemocha](https://github.com/orangemocha) - -**Alexis Campailla** <orangemocha@nodejs.org> * [oyyd](https://github.com/oyyd) - **Ouyang Yadong** <oyydoibh@gmail.com> (he/him) * [pmq20](https://github.com/pmq20) - @@ -506,6 +504,8 @@ For information about the governance of the Node.js project, see **Christopher Monsanto** <chris@monsan.to> * [Olegas](https://github.com/Olegas) - **Oleg Elifantiev** <oleg@elifantiev.ru> +* [orangemocha](https://github.com/orangemocha) - +**Alexis Campailla** <orangemocha@nodejs.org> * [othiym23](https://github.com/othiym23) - **Forrest L Norvell** <ogd@aoaioxxysz.net> (he/him) * [petkaantonov](https://github.com/petkaantonov) - From 14d58c2f954666b0c2a265a0604d34e8f08e0903 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 7 May 2019 15:06:48 -0700 Subject: [PATCH 017/129] meta: move pmq20 to Collaborator Emeriti list Minqi Pan confirmed in email that they were fine with being moved to Collaborator Emeritus. PR-URL: https://github.com/nodejs/node/pull/27602 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Anto Aravinth Reviewed-By: Trivikram Kamat --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92bc23073379c7..9d9c012047a490 100644 --- a/README.md +++ b/README.md @@ -403,8 +403,6 @@ For information about the governance of the Node.js project, see **Ali Ijaz Sheikh** <ofrobots@google.com> (he/him) * [oyyd](https://github.com/oyyd) - **Ouyang Yadong** <oyydoibh@gmail.com> (he/him) -* [pmq20](https://github.com/pmq20) - -**Minqi Pan** <pmq2001@gmail.com> * [princejwesley](https://github.com/princejwesley) - **Prince John Wesley** <princejohnwesley@gmail.com> * [psmarshall](https://github.com/psmarshall) - @@ -514,6 +512,8 @@ For information about the governance of the Node.js project, see **Phillip Johnsen** <johphi@gmail.com> * [piscisaureus](https://github.com/piscisaureus) - **Bert Belder** <bertbelder@gmail.com> +* [pmq20](https://github.com/pmq20) - +**Minqi Pan** <pmq2001@gmail.com> * [rlidwka](https://github.com/rlidwka) - **Alex Kocharin** <alex@kocharin.ru> * [rmg](https://github.com/rmg) - From 6bef4c0083207646aef6e1a29b844c2e162f1914 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 7 May 2019 15:12:26 -0700 Subject: [PATCH 018/129] meta: move AnnaMag to Collaborator Emeriti list AnnaMag hasn't authored/landed/reviewed code in quite some time. I sent them an email asking about becoming Emeritus but did not get a response. It's easy enough to re-onboard someone back to active status if they become active again, so I think this is a pretty safe change to make. I'll specifically request a review of this change from them so they get notified and can comment/review/block/approve/etc. this. PR-URL: https://github.com/nodejs/node/pull/27603 Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Anto Aravinth Reviewed-By: Franziska Hinkelmann Reviewed-By: Trivikram Kamat --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d9c012047a490..c346fd06bd77c4 100644 --- a/README.md +++ b/README.md @@ -247,8 +247,6 @@ For information about the governance of the Node.js project, see **Aleksei Koziatinskii** <ak239spb@gmail.com> * [AndreasMadsen](https://github.com/AndreasMadsen) - **Andreas Madsen** <amwebdk@gmail.com> (he/him) -* [AnnaMag](https://github.com/AnnaMag) - -**Anna M. Kedzierska** <anna.m.kedzierska@gmail.com> * [antsmartian](https://github.com/antsmartian) - **Anto Aravinth** <anto.aravinth.cse@gmail.com> (he/him) * [apapirovski](https://github.com/apapirovski) - @@ -486,6 +484,8 @@ For information about the governance of the Node.js project, see * [andrasq](https://github.com/andrasq) - **Andras** <andras@kinvey.com> +* [AnnaMag](https://github.com/AnnaMag) - +**Anna M. Kedzierska** <anna.m.kedzierska@gmail.com> * [imran-iq](https://github.com/imran-iq) - **Imran Iqbal** <imran@imraniqbal.org> * [isaacs](https://github.com/isaacs) - From 217e6b5a068e21e0ce25518ffd207058f4a32235 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 7 May 2019 21:14:43 -0700 Subject: [PATCH 019/129] tools: switch to camelcasing in apilinks.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use camelcasing in tools/doc/apilinks.js. PR-URL: https://github.com/nodejs/node/pull/27607 Reviewed-By: Ruben Bridgewater Reviewed-By: Anto Aravinth Reviewed-By: Michaël Zasso Reviewed-By: Yongsheng Zhang Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig Reviewed-By: Richard Lau Reviewed-By: Franziska Hinkelmann Reviewed-By: Trivikram Kamat --- tools/doc/apilinks.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/doc/apilinks.js b/tools/doc/apilinks.js index 514d22e8dcd375..461805dac3a811 100644 --- a/tools/doc/apilinks.js +++ b/tools/doc/apilinks.js @@ -36,10 +36,10 @@ function execSync(command) { } // Determine origin repo and tag (or hash) of the most recent commit. -const local_branch = execSync('git name-rev --name-only HEAD'); -const tracking_remote = execSync(`git config branch.${local_branch}.remote`); -const remote_url = execSync(`git config remote.${tracking_remote}.url`); -const repo = (remote_url.match(/(\w+\/\w+)\.git\r?\n?$/) || +const localBranch = execSync('git name-rev --name-only HEAD'); +const trackingRemote = execSync(`git config branch.${localBranch}.remote`); +const remoteUrl = execSync(`git config remote.${trackingRemote}.url`); +const repo = (remoteUrl.match(/(\w+\/\w+)\.git\r?\n?$/) || ['', 'nodejs/node'])[1]; const hash = execSync('git log -1 --pretty=%H') || 'master'; From fd823ea7a897d04012ba3e7ea41a0178dd6be5f1 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 7 May 2019 21:28:37 -0700 Subject: [PATCH 020/129] tools: enable camelcase linting in tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27607 Reviewed-By: Ruben Bridgewater Reviewed-By: Anto Aravinth Reviewed-By: Michaël Zasso Reviewed-By: Yongsheng Zhang Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig Reviewed-By: Richard Lau Reviewed-By: Franziska Hinkelmann Reviewed-By: Trivikram Kamat --- tools/.eslintrc.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/.eslintrc.yaml b/tools/.eslintrc.yaml index ffc36c66bdfc9d..fbc3738465169f 100644 --- a/tools/.eslintrc.yaml +++ b/tools/.eslintrc.yaml @@ -3,6 +3,11 @@ env: es6: true rules: + camelcase: + - error + - properties: 'never' + ignoreDestructuring: true + allow: ['child_process'] comma-dangle: - error - arrays: 'always-multiline' From 66cf89f57d77ba00009aa071ca7240d6d9febeb7 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Thu, 9 May 2019 15:59:04 +1000 Subject: [PATCH 021/129] doc: move Rod Vagg to TSC emeritus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27633 Refs: https://github.com/nodejs/create-node-meeting-artifacts/pull/63 Refs: https://github.com/nodejs/email/pull/142 Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Сковорода Никита Андреевич Reviewed-By: James M Snell Reviewed-By: Rich Trott --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c346fd06bd77c4..763b733ec8a3e5 100644 --- a/README.md +++ b/README.md @@ -195,8 +195,6 @@ For information about the governance of the Node.js project, see **Michael Dawson** <michael_dawson@ca.ibm.com> (he/him) * [MylesBorins](https://github.com/MylesBorins) - **Myles Borins** <myles.borins@gmail.com> (he/him) -* [rvagg](https://github.com/rvagg) - -**Rod Vagg** <rod@vagg.org> * [sam-github](https://github.com/sam-github) - **Sam Roberts** <vieuxtech@gmail.com> * [targos](https://github.com/targos) - @@ -232,6 +230,8 @@ For information about the governance of the Node.js project, see **Alexis Campailla** <orangemocha@nodejs.org> * [piscisaureus](https://github.com/piscisaureus) - **Bert Belder** <bertbelder@gmail.com> +* [rvagg](https://github.com/rvagg) - +**Rod Vagg** <r@va.gg> * [shigeki](https://github.com/shigeki) - **Shigeki Ohtsu** <ohtsu@ohtsu.org> (he/him) * [TimothyGu](https://github.com/TimothyGu) - From 62fe3422fbc3a633c6bdce98207eb61938260c35 Mon Sep 17 00:00:00 2001 From: gengjiawen Date: Sun, 5 May 2019 00:06:57 +0800 Subject: [PATCH 022/129] src: refactor deprecated UVException usage in pipe-wrap.cc PR-URL: https://github.com/nodejs/node/pull/27562 Reviewed-By: Anna Henningsen Reviewed-By: Rich Trott Reviewed-By: Anto Aravinth Reviewed-By: Colin Ihrig --- src/pipe_wrap.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 26ccfd8a47caee..c2be4320387549 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -41,6 +41,7 @@ using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::HandleScope; using v8::Int32; +using v8::Isolate; using v8::Local; using v8::MaybeLocal; using v8::Object; @@ -216,8 +217,9 @@ void PipeWrap::Open(const FunctionCallbackInfo& args) { int err = uv_pipe_open(&wrap->handle_, fd); wrap->set_fd(fd); + Isolate* isolate = env->isolate(); if (err != 0) - env->isolate()->ThrowException(UVException(err, "uv_pipe_open")); + isolate->ThrowException(UVException(isolate, err, "uv_pipe_open")); } From f6642e90b26a7efcacb9ac8e315695046dd756c4 Mon Sep 17 00:00:00 2001 From: Preveen Padmanabhan Date: Sun, 5 May 2019 09:13:58 +0530 Subject: [PATCH 023/129] src: elevate namespaces in node_worker.cc In node_worker.cc there are few instances where v8 namespaced entitites are used inline. Elevate them with `using` semantics. PR-URL: https://github.com/nodejs/node/pull/27568 Reviewed-By: Gireesh Punathil Reviewed-By: Richard Lau Reviewed-By: Yongsheng Zhang Reviewed-By: Colin Ihrig Reviewed-By: Rich Trott Reviewed-By: Luigi Pinca --- src/node_worker.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/node_worker.cc b/src/node_worker.cc index f9b675e96ad1f1..f95407a5ed4eef 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -16,6 +16,7 @@ #include using node::options_parser::kDisallowedInEnvironment; +using v8::Array; using v8::ArrayBuffer; using v8::Boolean; using v8::Context; @@ -27,6 +28,7 @@ using v8::Integer; using v8::Isolate; using v8::Local; using v8::Locker; +using v8::MaybeLocal; using v8::Number; using v8::Object; using v8::SealHandleScope; @@ -414,30 +416,30 @@ void Worker::New(const FunctionCallbackInfo& args) { if (!args[0]->IsNullOrUndefined()) { Utf8Value value( args.GetIsolate(), - args[0]->ToString(env->context()).FromMaybe(v8::Local())); + args[0]->ToString(env->context()).FromMaybe(Local())); url.append(value.out(), value.length()); } if (args[1]->IsArray()) { - v8::Local array = args[1].As(); + Local array = args[1].As(); // The first argument is reserved for program name, but we don't need it // in workers. has_explicit_exec_argv = true; std::vector exec_argv = {""}; uint32_t length = array->Length(); for (uint32_t i = 0; i < length; i++) { - v8::Local arg; + Local arg; if (!array->Get(env->context(), i).ToLocal(&arg)) { return; } - v8::MaybeLocal arg_v8_string = + MaybeLocal arg_v8_string = arg->ToString(env->context()); if (arg_v8_string.IsEmpty()) { return; } Utf8Value arg_utf8_value( args.GetIsolate(), - arg_v8_string.FromMaybe(v8::Local())); + arg_v8_string.FromMaybe(Local())); std::string arg_string(arg_utf8_value.out(), arg_utf8_value.length()); exec_argv.push_back(arg_string); } @@ -459,7 +461,7 @@ void Worker::New(const FunctionCallbackInfo& args) { // The first argument is program name. invalid_args.erase(invalid_args.begin()); if (errors.size() > 0 || invalid_args.size() > 0) { - v8::Local error; + Local error; if (!ToV8Value(env->context(), errors.size() > 0 ? errors : invalid_args) .ToLocal(&error)) { From c6ab6b279c6a42e9ada09f18edad9b38709cb33c Mon Sep 17 00:00:00 2001 From: Roman Reiss Date: Wed, 8 May 2019 20:45:10 +0200 Subject: [PATCH 024/129] tools: enable block-scoped-var eslint rule PR-URL: https://github.com/nodejs/node/pull/27616 Reviewed-By: Rich Trott Reviewed-By: Anna Henningsen Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Trivikram Kamat --- .eslintrc.js | 1 + benchmark/fixtures/simple-http-server.js | 3 ++- benchmark/http/_chunky_http_client.js | 6 +++--- benchmark/http/cluster.js | 3 ++- benchmark/napi/function_call/index.js | 3 ++- benchmark/util/priority-queue.js | 4 ++-- lib/dgram.js | 3 ++- lib/internal/child_process.js | 4 +++- lib/internal/util.js | 5 +++-- lib/internal/util/inspect.js | 14 ++++++++------ lib/url.js | 5 +++-- 11 files changed, 31 insertions(+), 20 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index cfada1f65c181e..b8ce85fa82247b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -59,6 +59,7 @@ module.exports = { 'array-callback-return': 'error', 'arrow-parens': ['error', 'always'], 'arrow-spacing': ['error', { before: true, after: true }], + 'block-scoped-var': 'error', 'block-spacing': 'error', 'brace-style': ['error', '1tbs', { allowSingleLine: true }], 'capitalized-comments': ['error', 'always', { diff --git a/benchmark/fixtures/simple-http-server.js b/benchmark/fixtures/simple-http-server.js index 013ac468f551ff..2b4f1ea956d7cc 100644 --- a/benchmark/fixtures/simple-http-server.js +++ b/benchmark/fixtures/simple-http-server.js @@ -10,8 +10,9 @@ const storedUnicode = Object.create(null); const useDomains = process.env.NODE_USE_DOMAINS; // Set up one global domain. +let domain; if (useDomains) { - var domain = require('domain'); + domain = require('domain'); const gdom = domain.create(); gdom.on('error', (er) => { console.error('Error on global domain', er); diff --git a/benchmark/http/_chunky_http_client.js b/benchmark/http/_chunky_http_client.js index 5164f8c6199e35..1bf7fa284a835b 100644 --- a/benchmark/http/_chunky_http_client.js +++ b/benchmark/http/_chunky_http_client.js @@ -16,7 +16,7 @@ function main({ len, n }) { const headers = []; // Chose 7 because 9 showed "Connection error" / "Connection closed" // An odd number could result in a better length dispersion. - for (var i = 7; i <= 7 * 7 * 7; i *= 7) + for (let i = 7; i <= 7 * 7 * 7; i *= 7) headers.push('o'.repeat(i)); function WriteHTTPHeaders(channel, has_keep_alive, extra_header_count) { @@ -31,7 +31,7 @@ function main({ len, n }) { 'Chrome/39.0.2171.71 Safari/537.36'); todo.push('Accept-Encoding: gzip, deflate, sdch'); todo.push('Accept-Language: en-US,en;q=0.8'); - for (var i = 0; i < extra_header_count; i++) { + for (let i = 0; i < extra_header_count; i++) { // Utilize first three powers of a small integer for an odd cycle and // because the fourth power of some integers overloads the server. todo.push(`X-Header-${i}: ${headers[i % 3]}`); @@ -41,7 +41,7 @@ function main({ len, n }) { todo = todo.join('\r\n'); // Using odd numbers in many places may increase length coverage. const chunksize = 37; - for (i = 0; i < todo.length; i += chunksize) { + for (let i = 0; i < todo.length; i += chunksize) { const cur = todo.slice(i, i + chunksize); channel.write(cur); } diff --git a/benchmark/http/cluster.js b/benchmark/http/cluster.js index 7f72db533ed142..c2d6d8e1a70c90 100644 --- a/benchmark/http/cluster.js +++ b/benchmark/http/cluster.js @@ -3,8 +3,9 @@ const common = require('../common.js'); const PORT = common.PORT; const cluster = require('cluster'); +let bench; if (cluster.isMaster) { - var bench = common.createBenchmark(main, { + bench = common.createBenchmark(main, { // Unicode confuses ab on os x. type: ['bytes', 'buffer'], len: [4, 1024, 102400], diff --git a/benchmark/napi/function_call/index.js b/benchmark/napi/function_call/index.js index b63d805fe309cc..3eebf9c05acdb1 100644 --- a/benchmark/napi/function_call/index.js +++ b/benchmark/napi/function_call/index.js @@ -11,8 +11,9 @@ const common = require('../../common.js'); // which is quite common for benchmarks. so in that case, just // abort quietly. +let binding; try { - var binding = require(`./build/${common.buildType}/binding`); + binding = require(`./build/${common.buildType}/binding`); } catch { console.error('misc/function_call.js Binding failed to load'); process.exit(0); diff --git a/benchmark/util/priority-queue.js b/benchmark/util/priority-queue.js index 9cff7cbbacba84..ea4601a0021b9a 100644 --- a/benchmark/util/priority-queue.js +++ b/benchmark/util/priority-queue.js @@ -10,9 +10,9 @@ function main({ n, type }) { const PriorityQueue = require('internal/priority_queue'); const queue = new PriorityQueue(); bench.start(); - for (var i = 0; i < n; i++) + for (let i = 0; i < n; i++) queue.insert(Math.random() * 1e7 | 0); - for (i = 0; i < n; i++) + for (let i = 0; i < n; i++) queue.shift(); bench.end(n); } diff --git a/lib/dgram.js b/lib/dgram.js index b38aa39c215aeb..cb20c4499ad981 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -91,8 +91,9 @@ function Socket(type, listener) { let recvBufferSize; let sendBufferSize; + let options; if (type !== null && typeof type === 'object') { - var options = type; + options = type; type = options.type; lookup = options.lookup; recvBufferSize = options.recvBufferSize; diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 03c0ed9159f64a..2f081d9111f553 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -693,6 +693,8 @@ function setupChannel(target, channel) { options = { swallowErrors: options }; } + let obj; + // Package messages with a handle object if (handle) { // This message will be handled by an internalMessage event handler @@ -727,7 +729,7 @@ function setupChannel(target, channel) { return this._handleQueue.length === 1; } - var obj = handleConversion[message.type]; + obj = handleConversion[message.type]; // convert TCP object to native handle object handle = handleConversion[message.type].send.call(target, diff --git a/lib/internal/util.js b/lib/internal/util.js index 14c8baa68c85e6..ed2493d9b4a814 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -316,12 +316,13 @@ promisify.custom = kCustomPromisifiedSymbol; function join(output, separator) { let str = ''; if (output.length !== 0) { - for (var i = 0; i < output.length - 1; i++) { + const lastIndex = output.length - 1; + for (let i = 0; i < lastIndex; i++) { // It is faster not to use a template string here str += output[i]; str += separator; } - str += output[i]; + str += output[lastIndex]; } return str; } diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 90be07535730c4..e51ea04c4a0208 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -312,7 +312,8 @@ function strEscape(str) { let result = ''; let last = 0; - for (var i = 0; i < str.length; i++) { + const lastIndex = str.length; + for (let i = 0; i < lastIndex; i++) { const point = str.charCodeAt(i); if (point === singleQuote || point === 92 || point < 32) { if (last === i) { @@ -324,7 +325,7 @@ function strEscape(str) { } } - if (last !== i) { + if (last !== lastIndex) { result += str.slice(last); } return addQuotes(result, singleQuote); @@ -1059,10 +1060,11 @@ function formatPrimitive(fn, value, ctx) { if (matches.length > 1) { const indent = ' '.repeat(ctx.indentationLvl); let res = `${fn(strEscape(matches[0]), 'string')} +\n`; - for (var i = 1; i < matches.length - 1; i++) { + const lastIndex = matches.length - 1; + for (let i = 1; i < lastIndex; i++) { res += `${indent} ${fn(strEscape(matches[i]), 'string')} +\n`; } - res += `${indent} ${fn(strEscape(matches[i]), 'string')}`; + res += `${indent} ${fn(strEscape(matches[lastIndex]), 'string')}`; return res; } } @@ -1185,10 +1187,10 @@ function formatTypedArray(ctx, value, recurseTimes) { const elementFormatter = value.length > 0 && typeof value[0] === 'number' ? formatNumber : formatBigInt; - for (var i = 0; i < maxLength; ++i) + for (let i = 0; i < maxLength; ++i) output[i] = elementFormatter(ctx.stylize, value[i]); if (remaining > 0) { - output[i] = `... ${remaining} more item${remaining > 1 ? 's' : ''}`; + output[maxLength] = `... ${remaining} more item${remaining > 1 ? 's' : ''}`; } if (ctx.showHidden) { // .buffer goes last, it's not a primitive like the others. diff --git a/lib/url.js b/lib/url.js index be483ae2bcf95a..665bd436148819 100644 --- a/lib/url.js +++ b/lib/url.js @@ -267,9 +267,10 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // user@server is *always* interpreted as a hostname, and url // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. + let slashes; if (slashesDenoteHost || proto || hostPattern.test(rest)) { - var slashes = rest.charCodeAt(0) === CHAR_FORWARD_SLASH && - rest.charCodeAt(1) === CHAR_FORWARD_SLASH; + slashes = rest.charCodeAt(0) === CHAR_FORWARD_SLASH && + rest.charCodeAt(1) === CHAR_FORWARD_SLASH; if (slashes && !(proto && hostlessProtocol.has(lowerProto))) { rest = rest.slice(2); this.slashes = true; From d7fcd75f629883d369632910d9f73204cbbcf562 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 7 May 2019 21:49:09 -0700 Subject: [PATCH 025/129] test: remove unneeded `--expose-internals` test/wpt/test-timers.js does not appear to need the `--expose-internals` flag. Remove it. PR-URL: https://github.com/nodejs/node/pull/27608 Reviewed-By: Joyee Cheung Reviewed-By: Ruben Bridgewater Reviewed-By: Yongsheng Zhang Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Trivikram Kamat --- test/wpt/test-timers.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/wpt/test-timers.js b/test/wpt/test-timers.js index a9fc262d3b1beb..4d342305400215 100644 --- a/test/wpt/test-timers.js +++ b/test/wpt/test-timers.js @@ -1,7 +1,5 @@ 'use strict'; -// Flags: --expose-internals - require('../common'); const { WPTRunner } = require('../common/wpt'); From 691866f12467321e1be3adf80c0aa5e5bec285fe Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Thu, 9 May 2019 10:12:16 -0700 Subject: [PATCH 026/129] test: fix test-linux-perf flakiness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new V8 seems to be optimizing the functions we use in this test faster than before. Increasing the sampling frequency for Linux perf fixes the issue. PR-URL: https://github.com/nodejs/node/pull/27615 Refs: https://github.com/v8/v8/compare/7.4.288.21...7.4.288.27 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: Franziska Hinkelmann Reviewed-By: Rich Trott --- test/v8-updates/test-linux-perf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/v8-updates/test-linux-perf.js b/test/v8-updates/test-linux-perf.js index 0a7f199e040d58..40823b8e8bd3b1 100644 --- a/test/v8-updates/test-linux-perf.js +++ b/test/v8-updates/test-linux-perf.js @@ -24,7 +24,7 @@ if (process.config.variables.node_shared) const perfArgs = [ 'record', - '-F500', + '-F999', '-g', '--', process.execPath, From 76c9e86609f991864e80ba4a2779a4f8a60b891e Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Wed, 8 May 2019 09:49:38 -0700 Subject: [PATCH 027/129] deps: patch V8 to 7.4.288.27 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs: https://github.com/v8/v8/compare/7.4.288.21...7.4.288.27 PR-URL: https://github.com/nodejs/node/pull/27615 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: Franziska Hinkelmann Reviewed-By: Rich Trott --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/api.cc | 3 +- deps/v8/src/arm64/assembler-arm64.cc | 15 +---- deps/v8/src/arm64/deoptimizer-arm64.cc | 12 ++-- deps/v8/src/arm64/macro-assembler-arm64.cc | 50 ++++++--------- deps/v8/src/arm64/register-arm64.h | 16 +---- deps/v8/src/builtins/arm64/builtins-arm64.cc | 12 ---- deps/v8/src/compiler/access-info.cc | 8 +++ deps/v8/src/compiler/int64-lowering.cc | 21 ++++++- deps/v8/src/compiler/int64-lowering.h | 1 + deps/v8/src/conversions-inl.h | 21 ++++++- deps/v8/src/objects.cc | 11 +++- deps/v8/src/objects/js-promise.h | 4 +- deps/v8/src/runtime/runtime-promise.cc | 4 +- deps/v8/src/snapshot/code-serializer.cc | 61 ++++++++++++++++++ .../wasm/baseline/liftoff-assembler-defs.h | 5 +- deps/v8/test/cctest/cctest.status | 10 +++ deps/v8/test/cctest/test-log.cc | 63 +++++++++++++++++++ deps/v8/test/cctest/test-serialize.cc | 14 ++++- .../cctest/wasm/test-run-wasm-atomics64.cc | 32 +++++++++- .../mjsunit/regress/regress-crbug-944865.js | 15 +++++ .../background-compile-task-unittest.cc | 4 +- .../compiler-dispatcher-unittest.cc | 4 +- .../unittests/microtask-queue-unittest.cc | 63 ++++++++++++++++++- 24 files changed, 349 insertions(+), 102 deletions(-) create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-944865.js diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 849443fffd9fb3..4093306dc83585 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 7 #define V8_MINOR_VERSION 4 #define V8_BUILD_NUMBER 288 -#define V8_PATCH_LEVEL 21 +#define V8_PATCH_LEVEL 27 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index eae3fd27921d45..f3e5da870ead56 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -8538,7 +8538,8 @@ void Isolate::EnqueueMicrotask(Local v8_function) { if (!i::JSReceiver::GetContextForMicrotask(function).ToHandle( &handler_context)) handler_context = isolate->native_context(); - handler_context->microtask_queue()->EnqueueMicrotask(this, v8_function); + MicrotaskQueue* microtask_queue = handler_context->microtask_queue(); + if (microtask_queue) microtask_queue->EnqueueMicrotask(this, v8_function); } void Isolate::EnqueueMicrotask(MicrotaskCallback callback, void* data) { diff --git a/deps/v8/src/arm64/assembler-arm64.cc b/deps/v8/src/arm64/assembler-arm64.cc index 8a5a82fba8b53c..ca205a996c5192 100644 --- a/deps/v8/src/arm64/assembler-arm64.cc +++ b/deps/v8/src/arm64/assembler-arm64.cc @@ -109,14 +109,9 @@ CPURegList CPURegList::GetCalleeSavedV(int size) { CPURegList CPURegList::GetCallerSaved(int size) { -#if defined(V8_OS_WIN) - // x18 is reserved as platform register on Windows arm64. + // x18 is the platform register and is reserved for the use of platform ABIs. // Registers x0-x17 and lr (x30) are caller-saved. CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 17); -#else - // Registers x0-x18 and lr (x30) are caller-saved. - CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18); -#endif list.Combine(lr); return list; } @@ -149,13 +144,7 @@ CPURegList CPURegList::GetSafepointSavedRegisters() { list.Remove(16); list.Remove(17); -// Don't add x18 to safepoint list on Windows arm64 because it is reserved -// as platform register. -#if !defined(V8_OS_WIN) - // Add x18 to the safepoint list, as although it's not in kJSCallerSaved, it - // is a caller-saved register according to the procedure call standard. - list.Combine(18); -#endif + // x18 is the platform register and is reserved for the use of platform ABIs. // Add the link register (x30) to the safepoint list. list.Combine(30); diff --git a/deps/v8/src/arm64/deoptimizer-arm64.cc b/deps/v8/src/arm64/deoptimizer-arm64.cc index 9e239886246224..78540e7d6f646e 100644 --- a/deps/v8/src/arm64/deoptimizer-arm64.cc +++ b/deps/v8/src/arm64/deoptimizer-arm64.cc @@ -55,6 +55,12 @@ void CopyRegListToFrame(MacroAssembler* masm, const Register& dst, masm->Sub(dst, dst, dst_offset); } +// TODO(jgruber): There's a hack here to explicitly skip restoration of the +// so-called 'arm64 platform register' x18. The register may be in use by the +// OS, thus we should not clobber it. Instead of this hack, it would be nicer +// not to add x18 to the list of saved registers in the first place. The +// complication here is that we require `reg_list.Count() % 2 == 0` in multiple +// spots. void RestoreRegList(MacroAssembler* masm, const CPURegList& reg_list, const Register& src_base, int src_offset) { DCHECK_EQ(reg_list.Count() % 2, 0); @@ -68,10 +74,8 @@ void RestoreRegList(MacroAssembler* masm, const CPURegList& reg_list, Register src = temps.AcquireX(); masm->Add(src, src_base, src_offset); -#if defined(V8_OS_WIN) - // x18 is reserved as platform register on Windows. + // x18 is the platform register and is reserved for the use of platform ABIs. restore_list.Remove(x18); -#endif // Restore every register in restore_list from src. while (!restore_list.IsEmpty()) { @@ -79,12 +83,10 @@ void RestoreRegList(MacroAssembler* masm, const CPURegList& reg_list, CPURegister reg1 = restore_list.PopLowestIndex(); int offset0 = reg0.code() * reg_size; -#if defined(V8_OS_WIN) if (reg1 == NoCPUReg) { masm->Ldr(reg0, MemOperand(src, offset0)); break; } -#endif int offset1 = reg1.code() * reg_size; diff --git a/deps/v8/src/arm64/macro-assembler-arm64.cc b/deps/v8/src/arm64/macro-assembler-arm64.cc index be1099912fb458..af2605e5c57381 100644 --- a/deps/v8/src/arm64/macro-assembler-arm64.cc +++ b/deps/v8/src/arm64/macro-assembler-arm64.cc @@ -48,20 +48,15 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode, // However, we leave it in the argument list to mirror the prototype for // Push/PopCallerSaved(). -#if defined(V8_OS_WIN) - // X18 is excluded from caller-saved register list on Windows ARM64 which - // makes caller-saved registers in odd number. padreg is used accordingly - // to maintain the alignment. + // X18 is excluded from caller-saved register list on ARM64 which makes + // caller-saved registers in odd number. padreg is used accordingly to + // maintain the alignment. DCHECK_EQ(list.Count() % 2, 1); if (exclusion.Is(no_reg)) { bytes += kXRegSizeInBits / 8; } else { bytes -= kXRegSizeInBits / 8; } -#else - DCHECK_EQ(list.Count() % 2, 0); - USE(exclusion); -#endif bytes += list.Count() * kXRegSizeInBits / 8; @@ -77,21 +72,13 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, int bytes = 0; auto list = kCallerSaved; -#if defined(V8_OS_WIN) - // X18 is excluded from caller-saved register list on Windows ARM64, use - // padreg accordingly to maintain alignment. + // X18 is excluded from caller-saved register list on ARM64, use padreg + // accordingly to maintain alignment. if (!exclusion.Is(no_reg)) { list.Remove(exclusion); } else { list.Combine(padreg); } -#else - if (!exclusion.Is(no_reg)) { - // Replace the excluded register with padding to maintain alignment. - list.Remove(exclusion); - list.Combine(padreg); - } -#endif DCHECK_EQ(list.Count() % 2, 0); PushCPURegList(list); @@ -115,21 +102,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion) { auto list = kCallerSaved; -#if defined(V8_OS_WIN) - // X18 is excluded from caller-saved register list on Windows ARM64, use - // padreg accordingly to maintain alignment. + // X18 is excluded from caller-saved register list on ARM64, use padreg + // accordingly to maintain alignment. if (!exclusion.Is(no_reg)) { list.Remove(exclusion); } else { list.Combine(padreg); } -#else - if (!exclusion.Is(no_reg)) { - // Replace the excluded register with padding to maintain alignment. - list.Remove(exclusion); - list.Combine(padreg); - } -#endif DCHECK_EQ(list.Count() % 2, 0); PopCPURegList(list); @@ -3389,14 +3368,20 @@ void MacroAssembler::Printf(const char * format, TmpList()->set_list(0); FPTmpList()->set_list(0); + // x18 is the platform register and is reserved for the use of platform ABIs. + // It is not part of the kCallerSaved list, but we add it here anyway to + // ensure `reg_list.Count() % 2 == 0` which is required in multiple spots. + CPURegList saved_registers = kCallerSaved; + saved_registers.Combine(x18.code()); + // Preserve all caller-saved registers as well as NZCV. // PushCPURegList asserts that the size of each list is a multiple of 16 // bytes. - PushCPURegList(kCallerSaved); + PushCPURegList(saved_registers); PushCPURegList(kCallerSavedV); // We can use caller-saved registers as scratch values (except for argN). - CPURegList tmp_list = kCallerSaved; + CPURegList tmp_list = saved_registers; CPURegList fp_tmp_list = kCallerSavedV; tmp_list.Remove(arg0, arg1, arg2, arg3); fp_tmp_list.Remove(arg0, arg1, arg2, arg3); @@ -3416,7 +3401,8 @@ void MacroAssembler::Printf(const char * format, // to PrintfNoPreserve as an argument. Register arg_sp = temps.AcquireX(); Add(arg_sp, sp, - kCallerSaved.TotalSizeInBytes() + kCallerSavedV.TotalSizeInBytes()); + saved_registers.TotalSizeInBytes() + + kCallerSavedV.TotalSizeInBytes()); if (arg0_sp) arg0 = Register::Create(arg_sp.code(), arg0.SizeInBits()); if (arg1_sp) arg1 = Register::Create(arg_sp.code(), arg1.SizeInBits()); if (arg2_sp) arg2 = Register::Create(arg_sp.code(), arg2.SizeInBits()); @@ -3441,7 +3427,7 @@ void MacroAssembler::Printf(const char * format, } PopCPURegList(kCallerSavedV); - PopCPURegList(kCallerSaved); + PopCPURegList(saved_registers); TmpList()->set_list(old_tmp_list); FPTmpList()->set_list(old_fp_tmp_list); diff --git a/deps/v8/src/arm64/register-arm64.h b/deps/v8/src/arm64/register-arm64.h index 008268de590b50..6d5b55b40e0f7f 100644 --- a/deps/v8/src/arm64/register-arm64.h +++ b/deps/v8/src/arm64/register-arm64.h @@ -28,20 +28,13 @@ namespace internal { R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \ R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31) -#if defined(V8_OS_WIN) -// x18 is reserved as platform register on Windows ARM64. +// x18 is the platform register and is reserved for the use of platform ABIs. +// It is known to be reserved by the OS at least on Windows and iOS. #define ALLOCATABLE_GENERAL_REGISTERS(R) \ R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x25) \ R(x27) R(x28) -#else -#define ALLOCATABLE_GENERAL_REGISTERS(R) \ - R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ - R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ - R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x25) \ - R(x27) R(x28) -#endif #define FLOAT_REGISTERS(V) \ V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \ @@ -728,12 +721,7 @@ constexpr Register kJSFunctionRegister = x1; constexpr Register kContextRegister = cp; constexpr Register kAllocateSizeRegister = x1; -#if defined(V8_OS_WIN) -// x18 is reserved as platform register on Windows ARM64. constexpr Register kSpeculationPoisonRegister = x23; -#else -constexpr Register kSpeculationPoisonRegister = x18; -#endif constexpr Register kInterpreterAccumulatorRegister = x0; constexpr Register kInterpreterBytecodeOffsetRegister = x19; diff --git a/deps/v8/src/builtins/arm64/builtins-arm64.cc b/deps/v8/src/builtins/arm64/builtins-arm64.cc index 35ed82a83e035d..0a5e691cf35cce 100644 --- a/deps/v8/src/builtins/arm64/builtins-arm64.cc +++ b/deps/v8/src/builtins/arm64/builtins-arm64.cc @@ -1278,15 +1278,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { __ Mov( kInterpreterDispatchTableRegister, ExternalReference::interpreter_dispatch_table_address(masm->isolate())); -#if defined(V8_OS_WIN) __ Ldrb(x23, MemOperand(kInterpreterBytecodeArrayRegister, kInterpreterBytecodeOffsetRegister)); __ Mov(x1, Operand(x23, LSL, kSystemPointerSizeLog2)); -#else - __ Ldrb(x18, MemOperand(kInterpreterBytecodeArrayRegister, - kInterpreterBytecodeOffsetRegister)); - __ Mov(x1, Operand(x18, LSL, kSystemPointerSizeLog2)); -#endif __ Ldr(kJavaScriptCallCodeStartRegister, MemOperand(kInterpreterDispatchTableRegister, x1)); __ Call(kJavaScriptCallCodeStartRegister); @@ -1531,15 +1525,9 @@ static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) { __ SmiUntag(kInterpreterBytecodeOffsetRegister); // Dispatch to the target bytecode. -#if defined(V8_OS_WIN) __ Ldrb(x23, MemOperand(kInterpreterBytecodeArrayRegister, kInterpreterBytecodeOffsetRegister)); __ Mov(x1, Operand(x23, LSL, kSystemPointerSizeLog2)); -#else - __ Ldrb(x18, MemOperand(kInterpreterBytecodeArrayRegister, - kInterpreterBytecodeOffsetRegister)); - __ Mov(x1, Operand(x18, LSL, kSystemPointerSizeLog2)); -#endif __ Ldr(kJavaScriptCallCodeStartRegister, MemOperand(kInterpreterDispatchTableRegister, x1)); __ Jump(kJavaScriptCallCodeStartRegister); diff --git a/deps/v8/src/compiler/access-info.cc b/deps/v8/src/compiler/access-info.cc index ac46eeb07b6656..aadf52bc7cc0f9 100644 --- a/deps/v8/src/compiler/access-info.cc +++ b/deps/v8/src/compiler/access-info.cc @@ -327,6 +327,14 @@ bool AccessInfoFactory::ComputeDataFieldAccessInfo( PropertyDetails const details = descriptors->GetDetails(number); int index = descriptors->GetFieldIndex(number); Representation details_representation = details.representation(); + if (details_representation.IsNone()) { + // The ICs collect feedback in PREMONOMORPHIC state already, + // but at this point the {receiver_map} might still contain + // fields for which the representation has not yet been + // determined by the runtime. So we need to catch this case + // here and fall back to use the regular IC logic instead. + return false; + } FieldIndex field_index = FieldIndex::ForPropertyIndex(*map, index, details_representation); Type field_type = Type::NonInternal(); diff --git a/deps/v8/src/compiler/int64-lowering.cc b/deps/v8/src/compiler/int64-lowering.cc index 4fd2454e54a517..f631e15773a05a 100644 --- a/deps/v8/src/compiler/int64-lowering.cc +++ b/deps/v8/src/compiler/int64-lowering.cc @@ -119,6 +119,7 @@ int GetReturnCountAfterLowering(Signature* signature) { void Int64Lowering::LowerWord64AtomicBinop(Node* node, const Operator* op) { DCHECK_EQ(5, node->InputCount()); + LowerMemoryBaseAndIndex(node); Node* value = node->InputAt(2); node->ReplaceInput(2, GetReplacementLow(value)); node->InsertInput(zone(), 3, GetReplacementHigh(value)); @@ -143,9 +144,6 @@ int Int64Lowering::GetParameterCountAfterLowering( void Int64Lowering::GetIndexNodes(Node* index, Node*& index_low, Node*& index_high) { - if (HasReplacementLow(index)) { - index = GetReplacementLow(index); - } #if defined(V8_TARGET_LITTLE_ENDIAN) index_low = index; index_high = graph()->NewNode(machine()->Int32Add(), index, @@ -179,6 +177,7 @@ void Int64Lowering::LowerNode(Node* node) { } if (rep == MachineRepresentation::kWord64) { + LowerMemoryBaseAndIndex(node); Node* base = node->InputAt(0); Node* index = node->InputAt(1); Node* index_low; @@ -228,6 +227,7 @@ void Int64Lowering::LowerNode(Node* node) { // a new store node to store the high word. The effect and control edges // are copied from the original store to the new store node, the effect // edge of the original store is redirected to the new store. + LowerMemoryBaseAndIndex(node); Node* base = node->InputAt(0); Node* index = node->InputAt(1); Node* index_low; @@ -900,6 +900,7 @@ void Int64Lowering::LowerNode(Node* node) { DCHECK_EQ(5, node->InputCount()); MachineRepresentation rep = AtomicStoreRepresentationOf(node->op()); if (rep == MachineRepresentation::kWord64) { + LowerMemoryBaseAndIndex(node); Node* value = node->InputAt(2); node->ReplaceInput(2, GetReplacementLow(value)); node->InsertInput(zone(), 3, GetReplacementHigh(value)); @@ -930,6 +931,7 @@ void Int64Lowering::LowerNode(Node* node) { case IrOpcode::kWord64AtomicCompareExchange: { MachineType type = AtomicOpType(node->op()); if (type == MachineType::Uint64()) { + LowerMemoryBaseAndIndex(node); Node* old_value = node->InputAt(2); Node* new_value = node->InputAt(3); node->ReplaceInput(2, GetReplacementLow(old_value)); @@ -1051,6 +1053,19 @@ void Int64Lowering::ReplaceNodeWithProjections(Node* node) { ReplaceNode(node, low_node, high_node); } +void Int64Lowering::LowerMemoryBaseAndIndex(Node* node) { + DCHECK(node != nullptr); + // Low word only replacements for memory operands for 32-bit address space. + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + if (HasReplacementLow(base)) { + node->ReplaceInput(0, GetReplacementLow(base)); + } + if (HasReplacementLow(index)) { + node->ReplaceInput(1, GetReplacementLow(index)); + } +} + } // namespace compiler } // namespace internal } // namespace v8 diff --git a/deps/v8/src/compiler/int64-lowering.h b/deps/v8/src/compiler/int64-lowering.h index ab403f904a8d90..f440858c6823e1 100644 --- a/deps/v8/src/compiler/int64-lowering.h +++ b/deps/v8/src/compiler/int64-lowering.h @@ -61,6 +61,7 @@ class V8_EXPORT_PRIVATE Int64Lowering { void PreparePhiReplacement(Node* phi); void GetIndexNodes(Node* index, Node*& index_low, Node*& index_high); void ReplaceNodeWithProjections(Node* node); + void LowerMemoryBaseAndIndex(Node* node); struct NodeState { Node* node; diff --git a/deps/v8/src/conversions-inl.h b/deps/v8/src/conversions-inl.h index 8aaeae9e7adde2..34d9069aee353b 100644 --- a/deps/v8/src/conversions-inl.h +++ b/deps/v8/src/conversions-inl.h @@ -59,9 +59,24 @@ inline unsigned int FastD2UI(double x) { inline float DoubleToFloat32(double x) { - typedef std::numeric_limits limits; - if (x > limits::max()) return limits::infinity(); - if (x < limits::lowest()) return -limits::infinity(); + using limits = std::numeric_limits; + if (x > limits::max()) { + // kRoundingThreshold is the maximum double that rounds down to + // the maximum representable float. Its mantissa bits are: + // 1111111111111111111111101111111111111111111111111111 + // [<--- float range --->] + // Note the zero-bit right after the float mantissa range, which + // determines the rounding-down. + static const double kRoundingThreshold = 3.4028235677973362e+38; + if (x <= kRoundingThreshold) return limits::max(); + return limits::infinity(); + } + if (x < limits::lowest()) { + // Same as above, mirrored to negative numbers. + static const double kRoundingThreshold = -3.4028235677973362e+38; + if (x >= kRoundingThreshold) return limits::lowest(); + return -limits::infinity(); + } return static_cast(x); } diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 0dc72661c03374..8337b3d4cf47ba 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -5999,7 +5999,9 @@ MaybeHandle JSPromise::Resolve(Handle promise, promise) .Check(); } - isolate->native_context()->microtask_queue()->EnqueueMicrotask(*task); + MicrotaskQueue* microtask_queue = + isolate->native_context()->microtask_queue(); + if (microtask_queue) microtask_queue->EnqueueMicrotask(*task); // 13. Return undefined. return isolate->factory()->undefined_value(); @@ -6081,8 +6083,11 @@ Handle JSPromise::TriggerPromiseReactions(Isolate* isolate, PromiseRejectReactionJobTask::kPromiseOrCapabilityOffset)); } - handler_context->microtask_queue()->EnqueueMicrotask( - *Handle::cast(task)); + MicrotaskQueue* microtask_queue = handler_context->microtask_queue(); + if (microtask_queue) { + microtask_queue->EnqueueMicrotask( + *Handle::cast(task)); + } } return isolate->factory()->undefined_value(); diff --git a/deps/v8/src/objects/js-promise.h b/deps/v8/src/objects/js-promise.h index 19fd8bdeb0b309..181ebc0a85ab44 100644 --- a/deps/v8/src/objects/js-promise.h +++ b/deps/v8/src/objects/js-promise.h @@ -53,8 +53,8 @@ class JSPromise : public JSObject { void set_status(Promise::PromiseState status); // ES section #sec-fulfillpromise - static Handle Fulfill(Handle promise, - Handle value); + V8_EXPORT_PRIVATE static Handle Fulfill(Handle promise, + Handle value); // ES section #sec-rejectpromise static Handle Reject(Handle promise, Handle reason, bool debug_event = true); diff --git a/deps/v8/src/runtime/runtime-promise.cc b/deps/v8/src/runtime/runtime-promise.cc index dc361b95e83a12..d39c7190a348f2 100644 --- a/deps/v8/src/runtime/runtime-promise.cc +++ b/deps/v8/src/runtime/runtime-promise.cc @@ -79,7 +79,9 @@ RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) { Handle microtask = isolate->factory()->NewCallableTask( function, handle(function->native_context(), isolate)); - function->native_context()->microtask_queue()->EnqueueMicrotask(*microtask); + MicrotaskQueue* microtask_queue = + function->native_context()->microtask_queue(); + if (microtask_queue) microtask_queue->EnqueueMicrotask(*microtask); return ReadOnlyRoots(isolate).undefined_value(); } diff --git a/deps/v8/src/snapshot/code-serializer.cc b/deps/v8/src/snapshot/code-serializer.cc index f72446564f47f5..47aa104bae79e1 100644 --- a/deps/v8/src/snapshot/code-serializer.cc +++ b/deps/v8/src/snapshot/code-serializer.cc @@ -187,6 +187,18 @@ void CodeSerializer::SerializeObject(HeapObject obj) { return; } + // NOTE(mmarchini): If we try to serialize an InterpreterData our process + // will crash since it stores a code object. Instead, we serialize the + // bytecode array stored within the InterpreterData, which is the important + // information. On deserialization we'll create our code objects again, if + // --interpreted-frames-native-stack is on. See v8:9122 for more context +#ifndef V8_TARGET_ARCH_ARM + if (V8_UNLIKELY(FLAG_interpreted_frames_native_stack) && + obj->IsInterpreterData()) { + obj = InterpreterData::cast(obj)->bytecode_array(); + } +#endif // V8_TARGET_ARCH_ARM + if (obj->IsBytecodeArray()) { // Clear the stack frame cache if present BytecodeArray::cast(obj)->ClearFrameCacheFromSourcePositionTable(); @@ -210,6 +222,48 @@ void CodeSerializer::SerializeGeneric(HeapObject heap_object) { serializer.Serialize(); } +#ifndef V8_TARGET_ARCH_ARM +// NOTE(mmarchini): when FLAG_interpreted_frames_native_stack is on, we want to +// create duplicates of InterpreterEntryTrampoline for the deserialized +// functions, otherwise we'll call the builtin IET for those functions (which +// is not what a user of this flag wants). +void CreateInterpreterDataForDeserializedCode(Isolate* isolate, + Handle sfi, + bool log_code_creation) { + Script script = Script::cast(sfi->script()); + Handle