From edf42985d71e9ab16f77e28d1359c64abc99b425 Mon Sep 17 00:00:00 2001 From: Gireesh Punathil Date: Sat, 26 May 2018 11:18:02 +0530 Subject: [PATCH 01/93] test: fix worker send error In test-child-process-fork-closed-channel-segfault.js, race condition is observed between the server getting closed and the worker sending a message. Accommodate the potential errors. Earlier, the same race was observed between the client and server and was addressed through ignoring the relevant errors through error handler. The same mechanism is re-used for worker too. The only difference is that the filter is applied at the callback instead of at the worker's error listener. Refs: https://github.com/nodejs/node/issues/3635#issuecomment-157714683 Fixes: https://github.com/nodejs/node/issues/20836 PR-URL: https://github.com/nodejs/node/pull/20973 Reviewed-By: Rich Trott Reviewed-By: Colin Ihrig Reviewed-By: Jon Moss Reviewed-By: Matheus Marchini Reviewed-By: Joyee Cheung Reviewed-By: Bartosz Sosnowski --- ...-child-process-fork-closed-channel-segfault.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-child-process-fork-closed-channel-segfault.js b/test/parallel/test-child-process-fork-closed-channel-segfault.js index 14cb4b8fd97ae9..c24a62379bf66e 100644 --- a/test/parallel/test-child-process-fork-closed-channel-segfault.js +++ b/test/parallel/test-child-process-fork-closed-channel-segfault.js @@ -31,6 +31,16 @@ const server = net .listen(0, function() { const worker = cluster.fork(); + worker.on('error', function(err) { + if ( + err.code !== 'ECONNRESET' && + err.code !== 'ECONNREFUSED' && + err.code !== 'EMFILE' + ) { + throw err; + } + }); + function send(callback) { const s = net.connect(server.address().port, function() { worker.send({}, s, callback); @@ -66,7 +76,10 @@ const server = net send(function(err) { // Ignore errors when sending the second handle because the worker // may already have exited. - if (err && err.code !== 'ERR_IPC_CHANNEL_CLOSED') { + if (err && err.code !== 'ERR_IPC_CHANNEL_CLOSED' && + err.code !== 'ECONNRESET' && + err.code !== 'ECONNREFUSED' && + err.code !== 'EMFILE') { throw err; } }); From ab43581f15388bf48291b36af1c85bad410416d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rodr=C3=ADguez=20Baquero?= Date: Sun, 27 May 2018 20:33:48 -0500 Subject: [PATCH 02/93] doc: make constants enumeration consistent Add missing prefix `crypto.constants.` to `RSA_PKCS1_PADDING` in `crypto.privateEncrypt()`, `crypto.privateDecrypt()`, `crypto.publicEncrypt()`, and `crypto.publicDecrypt()`. PR-URL: https://github.com/nodejs/node/pull/20991 Reviewed-By: Weijia Wang Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Trivikram Kamat Reviewed-By: Vse Mozhet Byt --- doc/api/crypto.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index c985d92ca39e16..276570cff4a1a8 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1897,7 +1897,8 @@ added: v0.11.14 - `passphrase` {string} An optional passphrase for the private key. - `padding` {crypto.constants} An optional padding value defined in `crypto.constants`, which may be: `crypto.constants.RSA_NO_PADDING`, - `RSA_PKCS1_PADDING`, or `crypto.constants.RSA_PKCS1_OAEP_PADDING`. + `crypto.constants.RSA_PKCS1_PADDING`, or + `crypto.constants.RSA_PKCS1_OAEP_PADDING`. - `buffer` {Buffer | TypedArray | DataView} - Returns: {Buffer} A new `Buffer` with the decrypted content. @@ -1915,7 +1916,7 @@ added: v1.1.0 - `passphrase` {string} An optional passphrase for the private key. - `padding` {crypto.constants} An optional padding value defined in `crypto.constants`, which may be: `crypto.constants.RSA_NO_PADDING` or - `RSA_PKCS1_PADDING`. + `crypto.constants.RSA_PKCS1_PADDING`. - `buffer` {Buffer | TypedArray | DataView} - Returns: {Buffer} A new `Buffer` with the encrypted content. @@ -1933,7 +1934,7 @@ added: v1.1.0 - `passphrase` {string} An optional passphrase for the private key. - `padding` {crypto.constants} An optional padding value defined in `crypto.constants`, which may be: `crypto.constants.RSA_NO_PADDING` or - `RSA_PKCS1_PADDING`. + `crypto.constants.RSA_PKCS1_PADDING`. - `buffer` {Buffer | TypedArray | DataView} - Returns: {Buffer} A new `Buffer` with the decrypted content. @@ -1954,7 +1955,8 @@ added: v0.11.14 - `passphrase` {string} An optional passphrase for the private key. - `padding` {crypto.constants} An optional padding value defined in `crypto.constants`, which may be: `crypto.constants.RSA_NO_PADDING`, - `RSA_PKCS1_PADDING`, or `crypto.constants.RSA_PKCS1_OAEP_PADDING`. + `crypto.constants.RSA_PKCS1_PADDING`, or + `crypto.constants.RSA_PKCS1_OAEP_PADDING`. - `buffer` {Buffer | TypedArray | DataView} - Returns: {Buffer} A new `Buffer` with the encrypted content. From d4f507b23be77064cd10c736cc3a62c939c3ddc6 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Mon, 28 May 2018 08:46:34 +0200 Subject: [PATCH 03/93] src: remove unused req_wrap-inl.h This commit removes the inclusion of req_wrap-inl.h from udp_wrap.h, and tty_wrap.cc as they are not used. PR-URL: https://github.com/nodejs/node/pull/20996 Reviewed-By: Ben Noordhuis Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Trivikram Kamat Reviewed-By: James M Snell --- src/tty_wrap.cc | 1 - src/udp_wrap.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index cd8589cc7fc2e7..175b32879bbb83 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -25,7 +25,6 @@ #include "handle_wrap.h" #include "node_buffer.h" #include "node_wrap.h" -#include "req_wrap-inl.h" #include "stream_base-inl.h" #include "stream_wrap.h" #include "util-inl.h" diff --git a/src/udp_wrap.h b/src/udp_wrap.h index b0f90420519520..01eb8b961f0cf2 100644 --- a/src/udp_wrap.h +++ b/src/udp_wrap.h @@ -27,7 +27,6 @@ #include "async_wrap.h" #include "env.h" #include "handle_wrap.h" -#include "req_wrap-inl.h" #include "uv.h" #include "v8.h" From 8dc7c883a7ce58b70937153422a38b9d322c6fd5 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sat, 28 Apr 2018 13:00:04 +0200 Subject: [PATCH 04/93] doc: improve note on zlib APIs threadpool usage Raise awareness against the catastrophic memory fragmentation that can be created while using the asynchronous zlib APIs. PR-URL: https://github.com/nodejs/node/pull/20380 Refs: https://github.com/nodejs/node/issues/8871 Reviewed-By: Ruben Bridgewater Reviewed-By: Anatoli Papirovski --- doc/api/zlib.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/api/zlib.md b/doc/api/zlib.md index 0e66abdcfb0766..e6c5504bff5dbb 100644 --- a/doc/api/zlib.md +++ b/doc/api/zlib.md @@ -48,9 +48,9 @@ zlib.unzip(buffer, (err, buffer) => { ## Threadpool Usage Note that all zlib APIs except those that are explicitly synchronous use libuv's -threadpool, which can have surprising and negative performance implications for -some applications, see the [`UV_THREADPOOL_SIZE`][] documentation for more -information. +threadpool. This can lead to surprising effects in some applications, such as +subpar performance (which can be mitigated by adjusting the [pool size][]) +and/or unrecoverable and catastrophic memory fragmentation. ## Compressing HTTP requests and responses @@ -777,9 +777,9 @@ Decompress a chunk of data with [`Unzip`][]. [`Inflate`]: #zlib_class_zlib_inflate [`InflateRaw`]: #zlib_class_zlib_inflateraw [`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray -[`UV_THREADPOOL_SIZE`]: cli.html#cli_uv_threadpool_size_size [`Unzip`]: #zlib_class_zlib_unzip [`options`]: #zlib_class_options [`zlib.bytesWritten`]: #zlib_zlib_byteswritten [Memory Usage Tuning]: #zlib_memory_usage_tuning +[pool size]: cli.html#cli_uv_threadpool_size_size [zlib documentation]: https://zlib.net/manual.html#Constants From c2ae93db632972f3f2f29ed240b06e8409bacaa8 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Tue, 29 May 2018 19:48:44 +0200 Subject: [PATCH 05/93] doc: add missing link for 10.3.0 changelog PR-URL: https://github.com/nodejs/node/pull/21017 Reviewed-By: Joyee Cheung Reviewed-By: Matheus Marchini Reviewed-By: Ruben Bridgewater Reviewed-By: Jon Moss Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Trivikram Kamat Reviewed-By: Daniel Bevenius --- doc/changelogs/CHANGELOG_V10.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/changelogs/CHANGELOG_V10.md b/doc/changelogs/CHANGELOG_V10.md index 180fd0d5220e6a..d01b2901301ce3 100644 --- a/doc/changelogs/CHANGELOG_V10.md +++ b/doc/changelogs/CHANGELOG_V10.md @@ -9,6 +9,7 @@ +10.3.0
10.2.1
10.2.0
10.1.0
From ebbd036d0b7c3a25ae8764e29633f81a5e9500da Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 24 May 2018 14:00:56 +0200 Subject: [PATCH 06/93] src: remove unused private data member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/20974 Reviewed-By: Anna Henningsen Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Joyee Cheung Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Tobias Nießen --- src/tracing/node_trace_buffer.cc | 2 +- src/tracing/node_trace_buffer.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tracing/node_trace_buffer.cc b/src/tracing/node_trace_buffer.cc index 6e552d659ad6a6..70a0ad4b311610 100644 --- a/src/tracing/node_trace_buffer.cc +++ b/src/tracing/node_trace_buffer.cc @@ -88,7 +88,7 @@ void InternalTraceBuffer::ExtractHandle( NodeTraceBuffer::NodeTraceBuffer(size_t max_chunks, Agent* agent, uv_loop_t* tracing_loop) - : tracing_loop_(tracing_loop), agent_(agent), + : tracing_loop_(tracing_loop), buffer1_(max_chunks, 0, agent), buffer2_(max_chunks, 1, agent) { current_buf_.store(&buffer1_); diff --git a/src/tracing/node_trace_buffer.h b/src/tracing/node_trace_buffer.h index f08e6a69da2104..b59ae4f0a0e4ef 100644 --- a/src/tracing/node_trace_buffer.h +++ b/src/tracing/node_trace_buffer.h @@ -72,7 +72,6 @@ class NodeTraceBuffer : public TraceBuffer { Mutex exit_mutex_; // Used to wait until async handles have been closed. ConditionVariable exit_cond_; - Agent* agent_; std::atomic current_buf_; InternalTraceBuffer buffer1_; InternalTraceBuffer buffer2_; From 04af69750c0abd8c9d1bca8805674017c8a122f5 Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Tue, 29 May 2018 16:03:32 -0300 Subject: [PATCH 07/93] test: mark test-child-process-fork-net as flaky `flaky-test-child-process-fork-net` has been failing constantly for the past few days, and all solutions suggestes so far were didn't work. Marking it as faky while the issue is not fixed. Ref: https://github.com/nodejs/node/pull/21012 Ref: https://github.com/nodejs/node/pull/20973 Ref: https://github.com/nodejs/node/pull/20973 PR-URL: https://github.com/nodejs/node/pull/21018 Refs: https://github.com/nodejs/node/pull/21012 Refs: https://github.com/nodejs/node/pull/20973 Refs: https://github.com/nodejs/node/pull/20973 Reviewed-By: Ruben Bridgewater Reviewed-By: Jon Moss Reviewed-By: Anatoli Papirovski Reviewed-By: Michael Dawson Reviewed-By: James M Snell Reviewed-By: Trivikram Kamat --- test/parallel/parallel.status | 1 + 1 file changed, 1 insertion(+) diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 899e6adfac060d..e4b757bbd3dac9 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -9,6 +9,7 @@ prefix parallel test-postmortem-metadata: PASS,FLAKY [$system==win32] +test-child-process-fork-net: PASS,FLAKY [$system==linux] From 44ef458d9cc060789bbb952f6e793c67f098b081 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 9 May 2018 11:48:30 -0500 Subject: [PATCH 08/93] fs: ensure options.flag defaults to 'r' in readFile When passing {} or { encoding: 'utf8' } as options to readFile, the flag is not defaulted to 'r' unlike normal fs. This fix makes fs.promises.readFile() act consistent with fs.readFile(). It also fixes another issue with fs.promises.readfile() where it returned a Buffer instead of an empty string when encoding is provided. PR-URL: https://github.com/nodejs/node/pull/20268 Reviewed-By: James M Snell Reviewed-By: Ron Korving Reviewed-By: Trivikram Kamat Reviewed-By: Ruben Bridgewater --- lib/internal/fs/promises.js | 5 +++-- .../test-fs-promises-readfile-empty.js | 19 +++++++++++++++++++ test/parallel/test-fs-readfile-empty.js | 4 ++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-fs-promises-readfile-empty.js diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index a80a5283c52e3c..97ac4c6c495b3d 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -137,7 +137,7 @@ async function readFileHandle(filehandle, options) { } if (size === 0) - return Buffer.alloc(0); + return options.encoding ? '' : Buffer.alloc(0); if (size > kMaxLength) throw new ERR_FS_FILE_TOO_LARGE(size); @@ -459,11 +459,12 @@ async function appendFile(path, data, options) { async function readFile(path, options) { options = getOptions(options, { flag: 'r' }); + const flag = options.flag || 'r'; if (path instanceof FileHandle) return readFileHandle(path, options); - const fd = await open(path, options.flag, 0o666); + const fd = await open(path, flag, 0o666); return readFileHandle(fd, options).finally(fd.close.bind(fd)); } diff --git a/test/parallel/test-fs-promises-readfile-empty.js b/test/parallel/test-fs-promises-readfile-empty.js new file mode 100644 index 00000000000000..24c17655c62135 --- /dev/null +++ b/test/parallel/test-fs-promises-readfile-empty.js @@ -0,0 +1,19 @@ +'use strict'; +const common = require('../common'); + +const assert = require('assert'); +const { promises: fs } = require('fs'); +const fixtures = require('../common/fixtures'); + +const fn = fixtures.path('empty.txt'); + +common.crashOnUnhandledRejection(); + +fs.readFile(fn) + .then(assert.ok); + +fs.readFile(fn, 'utf8') + .then(assert.strictEqual.bind(this, '')); + +fs.readFile(fn, { encoding: 'utf8' }) + .then(assert.strictEqual.bind(this, '')); diff --git a/test/parallel/test-fs-readfile-empty.js b/test/parallel/test-fs-readfile-empty.js index 21f99fc6be24ba..36eccfb1162713 100644 --- a/test/parallel/test-fs-readfile-empty.js +++ b/test/parallel/test-fs-readfile-empty.js @@ -38,5 +38,9 @@ fs.readFile(fn, 'utf8', function(err, data) { assert.strictEqual('', data); }); +fs.readFile(fn, { encoding: 'utf8' }, function(err, data) { + assert.strictEqual('', data); +}); + assert.ok(fs.readFileSync(fn)); assert.strictEqual('', fs.readFileSync(fn, 'utf8')); From ff5f20fc7ba676d66b4d1f18a564ef6ce72b0870 Mon Sep 17 00:00:00 2001 From: Masashi Hirano Date: Tue, 8 May 2018 02:16:18 +0900 Subject: [PATCH 09/93] test: add test for fs.promises.lchmod To increase test coverage for fs.promises by adding a test for lchmod. PR-URL: https://github.com/nodejs/node/pull/20584 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Richard Lau Reviewed-By: Michael Dawson --- test/parallel/test-fs-promises.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-fs-promises.js b/test/parallel/test-fs-promises.js index 992f30afec233e..b7e01544162e81 100644 --- a/test/parallel/test-fs-promises.js +++ b/test/parallel/test-fs-promises.js @@ -18,6 +18,7 @@ const { ftruncate, futimes, link, + lchmod, lstat, mkdir, mkdtemp, @@ -160,7 +161,6 @@ function verifyStatObject(stat) { if (common.canCreateSymLink()) { const newLink = path.resolve(tmpDir, 'baz3.js'); await symlink(newPath, newLink); - stats = await lstat(newLink); verifyStatObject(stats); @@ -168,6 +168,14 @@ function verifyStatObject(stat) { (await realpath(newLink)).toLowerCase()); assert.strictEqual(newPath.toLowerCase(), (await readlink(newLink)).toLowerCase()); + if (common.isOSX) { + // lchmod is only available on macOS + const newMode = 0o666; + await lchmod(newLink, newMode); + stats = await lstat(newLink); + assert.strictEqual(stats.mode & 0o777, newMode); + } + await unlink(newLink); } From adbbf0d6255d30f9a2020baa14578bf90f55d6e2 Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Tue, 29 May 2018 11:50:46 -0300 Subject: [PATCH 10/93] test: mark test-fs-readfile-tostring-fail as flaky test-fs-readfile-tostring-fail is failing frequently on OSX machines. There's a PR to fix this issue in libuv, but while the fix don't land on Node.js this test should be marked as flaky. Ref: https://github.com/nodejs/node/issues/16601 Ref: https://github.com/libuv/libuv/pull/1742 PR-URL: https://github.com/nodejs/node/pull/21013 Refs: https://github.com/nodejs/node/issues/16601 Refs: https://github.com/libuv/libuv/pull/1742 Reviewed-By: Ruben Bridgewater Reviewed-By: Jon Moss Reviewed-By: Luigi Pinca Reviewed-By: Anatoli Papirovski Reviewed-By: Michael Dawson Reviewed-By: James M Snell Reviewed-By: Trivikram Kamat Reviewed-By: Gireesh Punathil --- test/sequential/sequential.status | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status index cf4763b00129cc..07df25bbc754b6 100644 --- a/test/sequential/sequential.status +++ b/test/sequential/sequential.status @@ -15,6 +15,9 @@ test-inspector-async-hook-setup-at-signal: PASS, FLAKY [$system==linux] [$system==macos] +# This test will be flaky until https://github.com/libuv/libuv/pull/1742 lands +# on Node.js. +test-fs-readfile-tostring-fail: PASS, FLAKY [$system==solaris] # Also applies to SmartOS From b2808ed92921d0c86d2ee16ea01fdb8f1e456c55 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 25 May 2018 08:36:26 -0500 Subject: [PATCH 11/93] util: fix inspection of module namespaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/20962 Reviewed-By: Guy Bedford Reviewed-By: Matheus Marchini Reviewed-By: Michaël Zasso Reviewed-By: Ruben Bridgewater --- lib/util.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index 79f3cc7205398b..900ced1b46133f 100644 --- a/lib/util.js +++ b/lib/util.js @@ -488,7 +488,23 @@ function formatValue(ctx, value, recurseTimes) { if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } else { - keys = Object.keys(value); + // This might throw if `value` is a Module Namespace Object from an + // unevaluated module, but we don't want to perform the actual type + // check because it's expensive. + // TODO(devsnek): track https://github.com/tc39/ecma262/issues/1209 + // and modify this logic as needed. + try { + keys = Object.keys(value); + } catch (err) { + if (types.isNativeError(err) && + err.name === 'ReferenceError' && + types.isModuleNamespaceObject(value)) { + keys = Object.getOwnPropertyNames(value); + } else { + throw err; + } + } + if (symbols.length !== 0) symbols = symbols.filter((key) => propertyIsEnumerable.call(value, key)); } @@ -782,7 +798,7 @@ function formatNamespaceObject(ctx, value, recurseTimes, keys) { try { output[i] = formatProperty(ctx, value, recurseTimes, keys[i], 0); } catch (err) { - if (!(err instanceof ReferenceError)) { + if (!(types.isNativeError(err) && err.name === 'ReferenceError')) { throw err; } // Use the existing functionality. This makes sure the indentation and From 1b8e8e90af65a536e0856b41e8426d069670806a Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 24 May 2018 16:25:18 -0700 Subject: [PATCH 12/93] doc: make minor improvements to fs.realpath() docs Make canonical vs. unique text more precise and eliminate quotation marks. Remove repeated text from fs.realpathSync(), linking to fs.realpath() instead. PR-URL: https://github.com/nodejs/node/pull/20953 Reviewed-By: Ruben Bridgewater Reviewed-By: Vse Mozhet Byt Reviewed-By: James M Snell --- doc/api/fs.md | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index c3aa16ac2515ef..435cc56d18dffe 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -2481,7 +2481,7 @@ changes: Asynchronously computes the canonical pathname by resolving `.`, `..` and symbolic links. -Note that "canonical" does not mean "unique": hard links and bind mounts can +A canonical pathname is not necessarily unique. Hard links and bind mounts can expose a file system entity through many pathnames. This function behaves like realpath(3), with some exceptions: @@ -2556,26 +2556,7 @@ changes: * `encoding` {string} **Default:** `'utf8'` * Returns: {string|Buffer} -Synchronously computes the canonical pathname by resolving `.`, `..` and -symbolic links. - -Note that "canonical" does not mean "unique": hard links and bind mounts can -expose a file system entity through many pathnames. - -This function behaves like realpath(3), with some exceptions: - -1. No case conversion is performed on case-insensitive file systems. - -2. The maximum number of symbolic links is platform-independent and generally - (much) higher than what the native realpath(3) implementation supports. - -The optional `options` argument can be a string specifying an encoding, or an -object with an `encoding` property specifying the character encoding to use for -the returned value. If the `encoding` is set to `'buffer'`, the path returned -will be passed as a `Buffer` object. - -If `path` resolves to a socket or a pipe, the function will return a system -dependent name for that object. +Synchronous version of [`fs.realpath()`][]. Returns the resolved pathname. ## fs.realpathSync.native(path[, options]) \n%s\n", first_newline); PrintF("\n<--- JS stacktrace --->\n%s\n", js_stacktrace); } - Utils::ReportOOMFailure(location, is_heap_oom); + Utils::ReportOOMFailure(isolate, location, is_heap_oom); // If the fatal error handler returns, we stop execution. FATAL("API fatal error handler returned after process out of memory"); } @@ -415,8 +419,8 @@ void Utils::ReportApiFailure(const char* location, const char* message) { isolate->SignalFatalError(); } -void Utils::ReportOOMFailure(const char* location, bool is_heap_oom) { - i::Isolate* isolate = i::Isolate::Current(); +void Utils::ReportOOMFailure(i::Isolate* isolate, const char* location, + bool is_heap_oom) { OOMErrorCallback oom_callback = isolate->oom_behavior(); if (oom_callback == nullptr) { // TODO(wfh): Remove this fallback once Blink is setting OOM handler. See @@ -704,7 +708,7 @@ StartupData SnapshotCreator::CreateBlob( // context even after we have disposed of the context. isolate->heap()->CollectAllAvailableGarbage( i::GarbageCollectionReason::kSnapshotCreator); - isolate->heap()->CompactWeakFixedArrays(); + isolate->heap()->CompactFixedArraysOfWeakCells(); i::DisallowHeapAllocation no_gc_from_here_on; @@ -728,15 +732,33 @@ StartupData SnapshotCreator::CreateBlob( i::SerializedHandleChecker handle_checker(isolate, &contexts); CHECK(handle_checker.CheckGlobalAndEternalHandles()); - // Complete in-object slack tracking for all functions. i::HeapIterator heap_iterator(isolate->heap()); while (i::HeapObject* current_obj = heap_iterator.next()) { - if (!current_obj->IsJSFunction()) continue; - i::JSFunction* fun = i::JSFunction::cast(current_obj); - fun->CompleteInobjectSlackTrackingIfActive(); + if (current_obj->IsJSFunction()) { + i::JSFunction* fun = i::JSFunction::cast(current_obj); + + // Complete in-object slack tracking for all functions. + fun->CompleteInobjectSlackTrackingIfActive(); + + // Also, clear out feedback vectors. + fun->feedback_cell()->set_value(isolate->heap()->undefined_value()); + } + + // Clear out re-compilable data from all shared function infos. Any + // JSFunctions using these SFIs will have their code pointers reset by the + // partial serializer. + if (current_obj->IsSharedFunctionInfo() && + function_code_handling == FunctionCodeHandling::kClear) { + i::SharedFunctionInfo* shared = i::SharedFunctionInfo::cast(current_obj); + if (shared->CanFlushCompiled()) { + shared->FlushCompiled(); + } + DCHECK(shared->HasCodeObject() || shared->HasBuiltinId() || + shared->IsApiFunction()); + } } - i::StartupSerializer startup_serializer(isolate, function_code_handling); + i::StartupSerializer startup_serializer(isolate); startup_serializer.SerializeStrongReferences(); // Serialize each context with a new partial serializer. @@ -1221,13 +1243,18 @@ static i::Handle EmbedderDataFor(Context* context, if (!Utils::ApiCheck(can_grow, location, "Index too large")) { return i::Handle(); } - int new_size = i::Max(index, data->length() << 1) + 1; + int new_size = index + 1; int grow_by = new_size - data->length(); data = isolate->factory()->CopyFixedArrayAndGrow(data, grow_by); env->set_embedder_data(*data); return data; } +uint32_t Context::GetNumberOfEmbedderDataFields() { + i::Handle context = Utils::OpenHandle(this); + CHECK(context->IsNativeContext()); + return static_cast(context->embedder_data()->length()); +} v8::Local Context::SlowGetEmbedderData(int index) { const char* location = "v8::Context::GetEmbedderData()"; @@ -1375,7 +1402,8 @@ void FunctionTemplate::Inherit(v8::Local value) { static Local FunctionTemplateNew( i::Isolate* isolate, FunctionCallback callback, v8::Local data, v8::Local signature, int length, bool do_not_cache, - v8::Local cached_property_name = v8::Local()) { + v8::Local cached_property_name = v8::Local(), + SideEffectType side_effect_type = SideEffectType::kHasSideEffect) { i::Handle struct_obj = isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE, i::TENURED); i::Handle obj = @@ -1388,7 +1416,7 @@ static Local FunctionTemplateNew( } obj->set_serial_number(i::Smi::FromInt(next_serial_number)); if (callback != 0) { - Utils::ToLocal(obj)->SetCallHandler(callback, data); + Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type); } obj->set_length(length); obj->set_undetectable(false); @@ -1413,8 +1441,8 @@ Local FunctionTemplate::New( // function templates when the isolate is created for serialization. LOG_API(i_isolate, FunctionTemplate, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); - auto templ = - FunctionTemplateNew(i_isolate, callback, data, signature, length, false); + auto templ = FunctionTemplateNew(i_isolate, callback, data, signature, length, + false, Local(), side_effect_type); if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype(); return templ; } @@ -1442,7 +1470,7 @@ Local FunctionTemplate::NewWithCache( LOG_API(i_isolate, FunctionTemplate, NewWithCache); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); return FunctionTemplateNew(i_isolate, callback, data, signature, length, - false, cache_property); + false, cache_property, side_effect_type); } Local Signature::New(Isolate* isolate, @@ -1470,10 +1498,8 @@ void FunctionTemplate::SetCallHandler(FunctionCallback callback, i::Isolate* isolate = info->GetIsolate(); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); - i::Handle struct_obj = - isolate->factory()->NewStruct(i::TUPLE3_TYPE, i::TENURED); - i::Handle obj = - i::Handle::cast(struct_obj); + i::Handle obj = isolate->factory()->NewCallHandlerInfo( + side_effect_type == SideEffectType::kHasNoSideEffect); SET_FIELD_WRAPPED(obj, set_callback, callback); SET_FIELD_WRAPPED(obj, set_js_callback, obj->redirected_callback()); if (data.IsEmpty()) { @@ -1781,6 +1807,9 @@ static i::Handle CreateInterceptorInfo( static_cast(PropertyHandlerFlags::kAllCanRead)); obj->set_non_masking(static_cast(flags) & static_cast(PropertyHandlerFlags::kNonMasking)); + obj->set_has_no_side_effect( + static_cast(flags) & + static_cast(PropertyHandlerFlags::kHasNoSideEffect)); if (data.IsEmpty()) { data = v8::Undefined(reinterpret_cast(isolate)); @@ -1940,7 +1969,6 @@ void ObjectTemplate::SetHandler( cons->set_indexed_property_handler(*obj); } - void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback, Local data) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); @@ -1948,10 +1976,7 @@ void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback, i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetCallAsFunctionHandler"); - i::Handle struct_obj = - isolate->factory()->NewStruct(i::TUPLE3_TYPE, i::TENURED); - i::Handle obj = - i::Handle::cast(struct_obj); + i::Handle obj = isolate->factory()->NewCallHandlerInfo(); SET_FIELD_WRAPPED(obj, set_callback, callback); SET_FIELD_WRAPPED(obj, set_js_callback, obj->redirected_callback()); if (data.IsEmpty()) { @@ -2374,22 +2399,14 @@ MaybeLocal ScriptCompiler::CompileUnboundInternal( source->host_defined_options); i::MaybeHandle maybe_function_info = i::Compiler::GetSharedFunctionInfoForScript( - str, script_details, source->resource_options, nullptr, &script_data, + str, script_details, source->resource_options, nullptr, script_data, options, no_cache_reason, i::NOT_NATIVES_CODE); - has_pending_exception = !maybe_function_info.ToHandle(&result); - if (has_pending_exception && script_data != nullptr) { - // This case won't happen during normal operation; we have compiled - // successfully and produced cached data, and but the second compilation - // of the same source code fails. - delete script_data; - script_data = nullptr; - } - RETURN_ON_FAILED_EXECUTION(UnboundScript); - if (options == kConsumeCodeCache) { source->cached_data->rejected = script_data->rejected(); } delete script_data; + has_pending_exception = !maybe_function_info.ToHandle(&result); + RETURN_ON_FAILED_EXECUTION(UnboundScript); RETURN_ESCAPED(ToApiHandle(result)); } @@ -2483,6 +2500,10 @@ MaybeLocal ScriptCompiler::CompileFunctionInContext( Function); TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler"); + DCHECK(options == CompileOptions::kConsumeCodeCache || + options == CompileOptions::kEagerCompile || + options == CompileOptions::kNoCompileOptions); + i::Handle context = Utils::OpenHandle(*v8_context); i::Handle outer_info(context->closure()->shared(), isolate); @@ -2511,25 +2532,30 @@ MaybeLocal ScriptCompiler::CompileFunctionInContext( extension); } - i::Handle name_obj; - int line_offset = 0; - int column_offset = 0; - if (!source->resource_name.IsEmpty()) { - name_obj = Utils::OpenHandle(*(source->resource_name)); - } - if (!source->resource_line_offset.IsEmpty()) { - line_offset = static_cast(source->resource_line_offset->Value()); - } - if (!source->resource_column_offset.IsEmpty()) { - column_offset = static_cast(source->resource_column_offset->Value()); + i::Compiler::ScriptDetails script_details = GetScriptDetails( + isolate, source->resource_name, source->resource_line_offset, + source->resource_column_offset, source->source_map_url, + source->host_defined_options); + + i::ScriptData* script_data = nullptr; + if (options == kConsumeCodeCache) { + DCHECK(source->cached_data); + // ScriptData takes care of pointer-aligning the data. + script_data = new i::ScriptData(source->cached_data->data, + source->cached_data->length); } i::Handle result; has_pending_exception = !i::Compiler::GetWrappedFunction( Utils::OpenHandle(*source->source_string), arguments_list, context, - line_offset, column_offset, name_obj, source->resource_options) + script_details, source->resource_options, script_data, options, + no_cache_reason) .ToHandle(&result); + if (options == kConsumeCodeCache) { + source->cached_data->rejected = script_data->rejected(); + } + delete script_data; RETURN_ON_FAILED_EXECUTION(Function); RETURN_ESCAPED(Utils::CallableToLocal(result)); } @@ -2603,37 +2629,18 @@ ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache( i::Handle shared = i::Handle::cast( Utils::OpenHandle(*unbound_script)); - i::Isolate* isolate = shared->GetIsolate(); - TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute"); - base::ElapsedTimer timer; - if (i::FLAG_profile_deserialization) { - timer.Start(); - } - i::HistogramTimerScope histogram_timer( - isolate->counters()->compile_serialize()); - i::RuntimeCallTimerScope runtimeTimer( - isolate, i::RuntimeCallCounterId::kCompileSerialize); - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileSerialize"); - + i::Handle source_str = Utils::OpenHandle(*source); DCHECK(shared->is_toplevel()); - i::Handle script(i::Script::cast(shared->script())); - // TODO(7110): Enable serialization of Asm modules once the AsmWasmData is - // context independent. - if (script->ContainsAsmModule()) return nullptr; - if (isolate->debug()->is_loaded()) return nullptr; - - i::ScriptData* script_data = - i::CodeSerializer::Serialize(isolate, shared, Utils::OpenHandle(*source)); - CachedData* result = new CachedData( - script_data->data(), script_data->length(), CachedData::BufferOwned); - script_data->ReleaseDataOwnership(); - delete script_data; + return i::CodeSerializer::Serialize(shared, source_str); +} - if (i::FLAG_profile_deserialization) { - i::PrintF("[Serializing took %0.3f ms]\n", - timer.Elapsed().InMillisecondsF()); - } - return result; +ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCacheForFunction( + Local function, Local source) { + i::Handle shared( + i::Handle::cast(Utils::OpenHandle(*function))->shared()); + i::Handle source_str = Utils::OpenHandle(*source); + CHECK(shared->is_wrapped()); + return i::CodeSerializer::Serialize(shared, source_str); } MaybeLocal + + @@ -68,13 +70,13 @@ +

V8 Heap Statistics

-

V8 Heap Statistics

Visualize object statistics that have been gathered using

  • --trace-gc-object-stats on V8
  • @@ -85,6 +87,10 @@

    V8 Heap Statistics

    v8.gc_stats.
+

+ Note that you only get a data point on major GCs. You can enforce this by + using the --gc-global flag. +

Note that the visualizer needs to run on a web server due to HTML imports requiring this.finalizeGC(gc)); + this.sortInstanceTypePeakMemory(); } getLabel() { let label = `${this.address}: gc=#${Object.keys(this.gcs).length}`; - const peakSizeMB = Math.round(this.peakMemory / 1024 / 1024 * 100) / 100; - label += ` max=${peakSizeMB}MB` + label += ` peak=${formatBytes(this.peakMemory)}` return label; } finalizeGC(gc_data) { this.data_sets.forEach(key => this.finalizeDataSet(gc_data[key])); - if ('live' in gc_data) { - this.peakMemory = Math.max(this.peakMemory, gc_data['live'].overall); + if (!('live' in gc_data)) return; + let liveData = gc_data.live; + this.peakMemory = Math.max(this.peakMemory, liveData.overall); + let data = liveData.instance_type_data; + for (let name in data) { + let prev = this.instanceTypePeakMemory[name] || 0; + this.instanceTypePeakMemory[name] = Math.max(prev, data[name].overall); } } finalizeDataSet(data_set) { // Create a ranked instance type array that sorts instance types by // memory size (overall). - data_set.ranked_instance_types = - [...data_set.non_empty_instance_types].sort(function(a, b) { - if (data_set.instance_type_data[a].overall > - data_set.instance_type_data[b].overall) { - return 1; - } else if ( - data_set.instance_type_data[a].overall < - data_set.instance_type_data[b].overall) { - return -1; - } - return 0; + let data = data_set.instance_type_data; + let ranked_instance_types = + [...data_set.non_empty_instance_types].sort((a, b) => { + return data[a].overall - data[b].overall; }); + // Reassemble the instance_type list sorted by size. + let sorted_data = Object.create(null); + let max = 0; + ranked_instance_types.forEach((name) => { + let entry = sorted_data[name] = data[name]; + max = Math.max(max, entry.overall); + }); + data_set.instance_type_data = data; + data_set.singleInstancePeakMemory = max; Object.entries(data_set.instance_type_data).forEach(([name, entry]) => { this.checkHistogram( @@ -74,4 +85,21 @@ class Isolate { `${type}: sum('${histogram}') > overall (${sum} > ${overall})`); } } + + sortInstanceTypePeakMemory() { + let entries = Object.entries(this.instanceTypePeakMemory); + entries.sort((a, b) => {return b[1] - a[1]}); + this.instanceTypePeakMemory = Object.create(null); + let max = 0; + for (let [key, value] of entries) { + this.instanceTypePeakMemory[key] = value; + max = Math.max(max, value); + } + this.singleInstanceTypePeakMemory = max; + } + + getInstanceTypePeakMemory(type) { + if (!(type in this.instanceTypePeakMemory)) return 0; + return this.instanceTypePeakMemory[type]; + } } diff --git a/deps/v8/tools/heap-stats/trace-file-reader.html b/deps/v8/tools/heap-stats/trace-file-reader.html index 73de98ab03f70e..649d32bb40655c 100644 --- a/deps/v8/tools/heap-stats/trace-file-reader.html +++ b/deps/v8/tools/heap-stats/trace-file-reader.html @@ -11,6 +11,16 @@ border: solid 1px #000000; border-radius: 5px; cursor: pointer; + transition: all 0.5s ease-in-out; +} + +#fileReader.done { + height: 20px; + line-height: 20px; +} + +#fileReader:hover { + background-color: #e0edfe ; } .loading #fileReader { @@ -21,11 +31,12 @@ display: none; } + #loader { display: none; } -.loading #loader{ +.loading #loader { display: block; position: fixed; top: 0px; @@ -51,7 +62,7 @@ @keyframes spin { 0% { transform: rotate(0deg); - }; + }; 100% { transform: rotate(360deg); }; @@ -59,7 +70,7 @@

-
+
Drag and drop a trace file into this area, or click to choose from disk. diff --git a/deps/v8/tools/heap-stats/trace-file-reader.js b/deps/v8/tools/heap-stats/trace-file-reader.js index ef563a43cb35ed..4ad1269835b095 100644 --- a/deps/v8/tools/heap-stats/trace-file-reader.js +++ b/deps/v8/tools/heap-stats/trace-file-reader.js @@ -17,6 +17,7 @@ class TraceFileReader extends HTMLElement { this.addEventListener('dragover', e => this.handleDragOver(e)); this.addEventListener('drop', e => this.handleChange(e)); this.$('#file').addEventListener('change', e => this.handleChange(e)); + this.$('#fileReader').addEventListener('keydown', e => this.handleKeyEvent(e)); } $(id) { @@ -31,6 +32,10 @@ class TraceFileReader extends HTMLElement { this.$('#label').innerText = text; } + handleKeyEvent(event) { + if (event.key == "Enter") this.handleClick(event); + } + handleClick(event) { this.$('#file').click(); } @@ -46,13 +51,16 @@ class TraceFileReader extends HTMLElement { event.preventDefault(); } - connectedCallback() {} + connectedCallback() { + this.$('#fileReader').focus(); + } readFile(file) { if (!file) { this.updateLabel('Failed to load file.'); return; } + this.$('#fileReader').blur(); this.section.className = 'loading'; const reader = new FileReader(); @@ -63,15 +71,17 @@ class TraceFileReader extends HTMLElement { const textResult = pako.inflate(e.target.result, {to: 'string'}); this.processRawText(file, textResult); this.section.className = 'success'; + this.$('#fileReader').classList.add('done'); } catch (err) { console.error(err); this.section.className = 'failure'; } }; - reader.readAsArrayBuffer(file); + // Delay the loading a bit to allow for CSS animations to happen. + setTimeout(() => reader.readAsArrayBuffer(file), 10); } else { reader.onload = (e) => this.processRawText(file, e.target.result); - reader.readAsText(file); + setTimeout(() => reader.readAsText(file), 10); } } @@ -96,10 +106,12 @@ class TraceFileReader extends HTMLElement { data_object.gcs[entry.id] = {non_empty_instance_types: new Set()}; } if ('time' in entry) { - if (data_object.end === null || data_object.end < entry.time) + if (data_object.end === null || data_object.end < entry.time) { data_object.end = entry.time; - if (data_object.start === null || data_object.start > entry.time) + } + if (data_object.start === null || data_object.start > entry.time) { data_object.start = entry.time; + } } } diff --git a/deps/v8/tools/ic-processor.js b/deps/v8/tools/ic-processor.js index 93f40b38a08634..9a78d16943f019 100644 --- a/deps/v8/tools/ic-processor.js +++ b/deps/v8/tools/ic-processor.js @@ -56,6 +56,9 @@ function IcProcessor() { 'KeyedStoreIC': { parsers : propertyICParser, processor: this.processPropertyIC.bind(this, "KeyedStoreIC") }, + 'StoreInArrayLiteralIC': { + parsers : propertyICParser, + processor: this.processPropertyIC.bind(this, "StoreInArrayLiteralIC") }, }); this.deserializedEntriesNames_ = []; this.profile_ = new Profile(); @@ -64,6 +67,7 @@ function IcProcessor() { this.StoreIC = 0; this.KeyedLoadIC = 0; this.KeyedStoreIC = 0; + this.StoreInArrayLiteralIC = 0; } inherits(IcProcessor, LogReader); @@ -104,6 +108,7 @@ IcProcessor.prototype.processLogFile = function(fileName) { print("Store: " + this.StoreIC); print("KeyedLoad: " + this.KeyedLoadIC); print("KeyedStore: " + this.KeyedStoreIC); + print("StoreInArrayLiteral: " + this.StoreInArrayLiteralIC); }; IcProcessor.prototype.addEntry = function(entry) { diff --git a/deps/v8/tools/isolate_driver.py b/deps/v8/tools/isolate_driver.py deleted file mode 100644 index 32077e236f5be1..00000000000000 --- a/deps/v8/tools/isolate_driver.py +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/env python -# Copyright 2015 the V8 project authors. All rights reserved. -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Adaptor script called through gni/isolate.gni. - -Creates a wrapping .isolate which 'includes' the original one, that can be -consumed by tools/swarming_client/isolate.py. Path variables are determined -based on the current working directory. The relative_cwd in the .isolated file -is determined based on the .isolate file that declare the 'command' variable to -be used so the wrapping .isolate doesn't affect this value. - -This script loads build.ninja and processes it to determine all the executables -referenced by the isolated target. It adds them in the wrapping .isolate file. - -WARNING: The target to use for build.ninja analysis is the base name of the -.isolate file plus '_run'. For example, 'foo_test.isolate' would have the target -'foo_test_run' analysed. -""" - -import errno -import glob -import json -import logging -import os -import posixpath -import StringIO -import subprocess -import sys -import time - -TOOLS_DIR = os.path.dirname(os.path.abspath(__file__)) -SWARMING_CLIENT_DIR = os.path.join(TOOLS_DIR, 'swarming_client') -SRC_DIR = os.path.dirname(TOOLS_DIR) - -sys.path.insert(0, SWARMING_CLIENT_DIR) - -import isolate_format - - -def load_ninja_recursively(build_dir, ninja_path, build_steps): - """Crudely extracts all the subninja and build referenced in ninja_path. - - In particular, it ignores rule and variable declarations. The goal is to be - performant (well, as much as python can be performant) which is currently in - the <200ms range for a complete chromium tree. As such the code is laid out - for performance instead of readability. - """ - logging.debug('Loading %s', ninja_path) - try: - with open(os.path.join(build_dir, ninja_path), 'rb') as f: - line = None - merge_line = '' - subninja = [] - for line in f: - line = line.rstrip() - if not line: - continue - - if line[-1] == '$': - # The next line needs to be merged in. - merge_line += line[:-1] - continue - - if merge_line: - line = merge_line + line - merge_line = '' - - statement = line[:line.find(' ')] - if statement == 'build': - # Save the dependency list as a raw string. Only the lines needed will - # be processed with raw_build_to_deps(). This saves a good 70ms of - # processing time. - build_target, dependencies = line[6:].split(': ', 1) - # Interestingly, trying to be smart and only saving the build steps - # with the intended extensions ('', '.stamp', '.so') slows down - # parsing even if 90% of the build rules can be skipped. - # On Windows, a single step may generate two target, so split items - # accordingly. It has only been seen for .exe/.exe.pdb combos. - for i in build_target.strip().split(): - build_steps[i] = dependencies - elif statement == 'subninja': - subninja.append(line[9:]) - except IOError: - print >> sys.stderr, 'Failed to open %s' % ninja_path - raise - - total = 1 - for rel_path in subninja: - try: - # Load each of the files referenced. - # TODO(maruel): Skip the files known to not be needed. It saves an aweful - # lot of processing time. - total += load_ninja_recursively(build_dir, rel_path, build_steps) - except IOError: - print >> sys.stderr, '... as referenced by %s' % ninja_path - raise - return total - - -def load_ninja(build_dir): - """Loads the tree of .ninja files in build_dir.""" - build_steps = {} - total = load_ninja_recursively(build_dir, 'build.ninja', build_steps) - logging.info('Loaded %d ninja files, %d build steps', total, len(build_steps)) - return build_steps - - -def using_blacklist(item): - """Returns True if an item should be analyzed. - - Ignores many rules that are assumed to not depend on a dynamic library. If - the assumption doesn't hold true anymore for a file format, remove it from - this list. This is simply an optimization. - """ - # *.json is ignored below, *.isolated.gen.json is an exception, it is produced - # by isolate_driver.py in 'test_isolation_mode==prepare'. - if item.endswith('.isolated.gen.json'): - return True - IGNORED = ( - '.a', '.cc', '.css', '.dat', '.def', '.frag', '.h', '.html', '.isolate', - '.js', '.json', '.manifest', '.o', '.obj', '.pak', '.png', '.pdb', '.py', - '.strings', '.test', '.txt', '.vert', - ) - # ninja files use native path format. - ext = os.path.splitext(item)[1] - if ext in IGNORED: - return False - # Special case Windows, keep .dll.lib but discard .lib. - if item.endswith('.dll.lib'): - return True - if ext == '.lib': - return False - return item not in ('', '|', '||') - - -def raw_build_to_deps(item): - """Converts a raw ninja build statement into the list of interesting - dependencies. - """ - # TODO(maruel): Use a whitelist instead? .stamp, .so.TOC, .dylib.TOC, - # .dll.lib, .exe and empty. - # The first item is the build rule, e.g. 'link', 'cxx', 'phony', etc. - return filter(using_blacklist, item.split(' ')[1:]) - - -def collect_deps(target, build_steps, dependencies_added, rules_seen): - """Recursively adds all the interesting dependencies for |target| - into |dependencies_added|. - """ - if rules_seen is None: - rules_seen = set() - if target in rules_seen: - # TODO(maruel): Figure out how it happens. - logging.warning('Circular dependency for %s!', target) - return - rules_seen.add(target) - try: - dependencies = raw_build_to_deps(build_steps[target]) - except KeyError: - logging.info('Failed to find a build step to generate: %s', target) - return - logging.debug('collect_deps(%s) -> %s', target, dependencies) - for dependency in dependencies: - dependencies_added.add(dependency) - collect_deps(dependency, build_steps, dependencies_added, rules_seen) - - -def post_process_deps(build_dir, dependencies): - """Processes the dependency list with OS specific rules.""" - def filter_item(i): - if i.endswith('.so.TOC'): - # Remove only the suffix .TOC, not the .so! - return i[:-4] - if i.endswith('.dylib.TOC'): - # Remove only the suffix .TOC, not the .dylib! - return i[:-4] - if i.endswith('.dll.lib'): - # Remove only the suffix .lib, not the .dll! - return i[:-4] - return i - - def is_exe(i): - # This script is only for adding new binaries that are created as part of - # the component build. - ext = os.path.splitext(i)[1] - # On POSIX, executables have no extension. - if ext not in ('', '.dll', '.dylib', '.exe', '.nexe', '.so'): - return False - if os.path.isabs(i): - # In some rare case, there's dependency set explicitly on files outside - # the checkout. - return False - - # Check for execute access and strip directories. This gets rid of all the - # phony rules. - p = os.path.join(build_dir, i) - return os.access(p, os.X_OK) and not os.path.isdir(p) - - return filter(is_exe, map(filter_item, dependencies)) - - -def create_wrapper(args, isolate_index, isolated_index): - """Creates a wrapper .isolate that add dynamic libs. - - The original .isolate is not modified. - """ - cwd = os.getcwd() - isolate = args[isolate_index] - # The code assumes the .isolate file is always specified path-less in cwd. Fix - # if this assumption doesn't hold true. - assert os.path.basename(isolate) == isolate, isolate - - # This will look like ../out/Debug. This is based against cwd. Note that this - # must equal the value provided as PRODUCT_DIR. - build_dir = os.path.dirname(args[isolated_index]) - - # This will look like chrome/unit_tests.isolate. It is based against SRC_DIR. - # It's used to calculate temp_isolate. - src_isolate = os.path.relpath(os.path.join(cwd, isolate), SRC_DIR) - - # The wrapping .isolate. This will look like - # ../out/Debug/gen/chrome/unit_tests.isolate. - temp_isolate = os.path.join(build_dir, 'gen', src_isolate) - temp_isolate_dir = os.path.dirname(temp_isolate) - - # Relative path between the new and old .isolate file. - isolate_relpath = os.path.relpath( - '.', temp_isolate_dir).replace(os.path.sep, '/') - - # It's a big assumption here that the name of the isolate file matches the - # primary target '_run'. Fix accordingly if this doesn't hold true, e.g. - # complain to maruel@. - target = isolate[:-len('.isolate')] + '_run' - build_steps = load_ninja(build_dir) - binary_deps = set() - collect_deps(target, build_steps, binary_deps, None) - binary_deps = post_process_deps(build_dir, binary_deps) - logging.debug( - 'Binary dependencies:%s', ''.join('\n ' + i for i in binary_deps)) - - # Now do actual wrapping .isolate. - isolate_dict = { - 'includes': [ - posixpath.join(isolate_relpath, isolate), - ], - 'variables': { - # Will look like ['<(PRODUCT_DIR)/lib/flibuser_prefs.so']. - 'files': sorted( - '<(PRODUCT_DIR)/%s' % i.replace(os.path.sep, '/') - for i in binary_deps), - }, - } - # Some .isolate files have the same temp directory and the build system may - # run this script in parallel so make directories safely here. - try: - os.makedirs(temp_isolate_dir) - except OSError as e: - if e.errno != errno.EEXIST: - raise - comment = ( - '# Warning: this file was AUTOGENERATED.\n' - '# DO NO EDIT.\n') - out = StringIO.StringIO() - isolate_format.print_all(comment, isolate_dict, out) - isolate_content = out.getvalue() - with open(temp_isolate, 'wb') as f: - f.write(isolate_content) - logging.info('Added %d dynamic libs', len(binary_deps)) - logging.debug('%s', isolate_content) - args[isolate_index] = temp_isolate - - -def prepare_isolate_call(args, output): - """Gathers all information required to run isolate.py later. - - Dumps it as JSON to |output| file. - """ - with open(output, 'wb') as f: - json.dump({ - 'args': args, - 'dir': os.getcwd(), - 'version': 1, - }, f, indent=2, sort_keys=True) - - -def rebase_directories(args, abs_base): - """Rebases all paths to be relative to abs_base.""" - def replace(index): - args[index] = os.path.relpath(os.path.abspath(args[index]), abs_base) - for i, arg in enumerate(args): - if arg in ['--isolate', '--isolated']: - replace(i + 1) - if arg == '--path-variable': - # Path variables have a triple form: --path-variable NAME . - replace(i + 2) - - -def main(): - logging.basicConfig(level=logging.ERROR, format='%(levelname)7s %(message)s') - args = sys.argv[1:] - mode = args[0] if args else None - isolate = None - isolated = None - for i, arg in enumerate(args): - if arg == '--isolate': - isolate = i + 1 - if arg == '--isolated': - isolated = i + 1 - if isolate is None or isolated is None or not mode: - print >> sys.stderr, 'Internal failure' - return 1 - - # Make sure all paths are relative to the isolate file. This is an - # expectation of the go binaries. In gn, this script is not called - # relative to the isolate file, but relative to the product dir. - new_base = os.path.abspath(os.path.dirname(args[isolate])) - rebase_directories(args, new_base) - assert args[isolate] == os.path.basename(args[isolate]) - os.chdir(new_base) - - create_wrapper(args, isolate, isolated) - - # In 'prepare' mode just collect all required information for postponed - # isolated.py invocation later, store it in *.isolated.gen.json file. - if mode == 'prepare': - prepare_isolate_call(args[1:], args[isolated] + '.gen.json') - return 0 - - swarming_client = os.path.join(SRC_DIR, 'tools', 'swarming_client') - sys.stdout.flush() - result = subprocess.call( - [sys.executable, os.path.join(swarming_client, 'isolate.py')] + args) - return result - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/deps/v8/tools/jsfunfuzz/BUILD.gn b/deps/v8/tools/jsfunfuzz/BUILD.gn new file mode 100644 index 00000000000000..3c40460f8db743 --- /dev/null +++ b/deps/v8/tools/jsfunfuzz/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../../gni/v8.gni") + +group("v8_jsfunfuzz") { + testonly = true + + data_deps = [ + "../..:d8", + ] + + data = [ + # Grab current directory. This avoids adding logic for checking the + # existence of the jsfunfuzz subdirectory. + "./", + ] +} diff --git a/deps/v8/tools/jsfunfuzz/jsfunfuzz.isolate b/deps/v8/tools/jsfunfuzz/jsfunfuzz.isolate deleted file mode 100644 index 56cb4a733f3052..00000000000000 --- a/deps/v8/tools/jsfunfuzz/jsfunfuzz.isolate +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2016 the V8 project authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -{ - 'variables': { - 'command': [ - 'fuzz-harness.sh', - ], - 'files': [ - # Grab current directory. This avoids adding logic for checking the - # existence of the jsfunfuzz subdirectory. - './', - ], - }, - 'includes': [ - '../../src/d8.isolate', - ], -} diff --git a/deps/v8/tools/mb/mb.py b/deps/v8/tools/mb/mb.py index b97ce455c2513f..b2ae0c763f6a15 100755 --- a/deps/v8/tools/mb/mb.py +++ b/deps/v8/tools/mb/mb.py @@ -233,10 +233,6 @@ def AddCommonOptions(subp): self.args = parser.parse_args(argv) - # TODO(machenbach): This prepares passing swarming targets to isolate on the - # infra side. - self.args.swarming_targets_file = None - def DumpInputFiles(self): def DumpContentsOfFilePassedTo(arg_name, path): @@ -393,7 +389,7 @@ def _DefaultDimensions(self): elif self.platform.startswith('linux'): os_dim = ('os', 'Ubuntu-14.04') elif self.platform == 'win32': - os_dim = ('os', 'Windows-10-14393') + os_dim = ('os', 'Windows-10') else: raise MBErr('unrecognized platform string "%s"' % self.platform) diff --git a/deps/v8/tools/mb/mb_unittest.py b/deps/v8/tools/mb/mb_unittest.py index 0413457eab2999..dbd599645d6752 100755 --- a/deps/v8/tools/mb/mb_unittest.py +++ b/deps/v8/tools/mb/mb_unittest.py @@ -360,8 +360,6 @@ def test_gen_fails(self): mbw.Call = lambda cmd, env=None, buffer_output=True: (1, '', '') self.check(['gen', '-c', 'debug_goma', '//out/Default'], mbw=mbw, ret=1) - # TODO(machenbach): Comment back in after swarming file parameter is used. - """ def test_gen_swarming(self): files = { '/tmp/swarming_targets': 'base_unittests\n', @@ -549,7 +547,6 @@ def run_stub(cmd, **_kwargs): 'base_unittests'], mbw=mbw, ret=0) self.check(['run', '-s', '-c', 'debug_goma', '-d', 'os', 'Win7', '//out/Default', 'base_unittests'], mbw=mbw, ret=0) - """ # pylint: disable=pointless-string-statement def test_lookup(self): self.check(['lookup', '-c', 'debug_goma'], ret=0) diff --git a/deps/v8/tools/node/fetch_deps.py b/deps/v8/tools/node/fetch_deps.py index 09a4e6cb97c8aa..945dbb7677f4f3 100755 --- a/deps/v8/tools/node/fetch_deps.py +++ b/deps/v8/tools/node/fetch_deps.py @@ -22,10 +22,10 @@ "managed" : False, "custom_deps" : { # These deps are already part of Node.js. - "v8/base/trace_event/common" : None, - "v8/testing/gtest" : None, - "v8/third_party/jinja2" : None, - "v8/third_party/markupsafe" : None, + "v8/base/trace_event/common" : None, + "v8/third_party/googletest/src" : None, + "v8/third_party/jinja2" : None, + "v8/third_party/markupsafe" : None, # These deps are unnecessary for building. "v8/test/benchmarks/data" : None, "v8/testing/gmock" : None, @@ -36,7 +36,6 @@ "v8/third_party/catapult" : None, "v8/third_party/colorama/src" : None, "v8/third_party/instrumented_libraries" : None, - "v8/tools/gyp" : None, "v8/tools/luci-go" : None, "v8/tools/swarming_client" : None, }, @@ -72,10 +71,11 @@ def FetchDeps(v8_path): env = os.environ.copy() # gclient needs to have depot_tools in the PATH. env["PATH"] = depot_tools + os.pathsep + env["PATH"] + gclient = os.path.join(depot_tools, "gclient.py") spec = "solutions = %s" % GCLIENT_SOLUTION - subprocess.check_call(["gclient", "sync", "--spec", spec], - cwd=os.path.join(v8_path, os.path.pardir), - env=env) + subprocess.check_call([sys.executable, gclient, "sync", "--spec", spec], + cwd=os.path.join(v8_path, os.path.pardir), + env=env) except: raise finally: diff --git a/deps/v8/tools/node/node_common.py b/deps/v8/tools/node/node_common.py index f7ca3a6a79c59b..72fbd9641aa44b 100755 --- a/deps/v8/tools/node/node_common.py +++ b/deps/v8/tools/node/node_common.py @@ -15,9 +15,8 @@ def EnsureDepotTools(v8_path, fetch_if_not_exist): def _Get(v8_path): depot_tools = os.path.join(v8_path, "_depot_tools") try: - gclient_path = os.path.join(depot_tools, "gclient") - gclient_check = subprocess.check_output([gclient_path, "--version"]) - if "gclient.py" in gclient_check: + gclient_path = os.path.join(depot_tools, "gclient.py") + if os.path.isfile(gclient_path): return depot_tools except: pass diff --git a/deps/v8/tools/node/test_update_node.py b/deps/v8/tools/node/test_update_node.py index 1a29b4ea619976..785517b8c85900 100755 --- a/deps/v8/tools/node/test_update_node.py +++ b/deps/v8/tools/node/test_update_node.py @@ -18,12 +18,16 @@ # Expectations. EXPECTED_GITIGNORE = """ -/testing/gtest/* -!/testing/gtest/include -/testing/gtest/include/* -!/testing/gtest/include/gtest -/testing/gtest/include/gtest/* -!/testing/gtest/include/gtest/gtest_prod.h +/third_party/googletest/* +!/third_party/googletest/src +/third_party/googletest/src/* +!/third_party/googletest/src/googletest +/third_party/googletest/src/googletest/* +!/third_party/googletest/src/googletest/include +/third_party/googletest/src/googletest/include/* +!/third_party/googletest/src/googletest/include/gtest +/third_party/googletest/src/googletest/include/gtest/* +!/third_party/googletest/src/googletest/include/gtest/gtest_prod.h !/third_party/jinja2 !/third_party/markupsafe /unrelated @@ -34,6 +38,7 @@ rename deps/v8/baz/{delete_me => v8_new} (100%) delete mode 100644 deps/v8/include/v8-version.h rename deps/v8/{delete_me => new/v8_new} (100%) + create mode 100644 deps/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h create mode 100644 deps/v8/third_party/jinja2/jinja2 create mode 100644 deps/v8/third_party/markupsafe/markupsafe create mode 100644 deps/v8/v8_new @@ -43,9 +48,9 @@ 'v8_new', 'new/v8_new', 'baz/v8_new', - 'testing/gtest/gtest_new', - 'testing/gtest/new/gtest_new', - 'testing/gtest/baz/gtest_new', + '/third_party/googletest/src/googletest/include/gtest/gtest_new', + '/third_party/googletest/src/googletest/include/gtest/new/gtest_new', + '/third_party/googletest/src/googletest/include/gtest/baz/gtest_new', 'third_party/jinja2/jinja2', 'third_party/markupsafe/markupsafe' ] diff --git a/deps/v8/tools/node/testdata/v8/.gitignore b/deps/v8/tools/node/testdata/v8/.gitignore index 855286229f8dea..cc2f1ca20223bd 100644 --- a/deps/v8/tools/node/testdata/v8/.gitignore +++ b/deps/v8/tools/node/testdata/v8/.gitignore @@ -1,4 +1,3 @@ /unrelated -/testing/gtest /third_party/jinja2 -/third_party/markupsafe \ No newline at end of file +/third_party/markupsafe diff --git a/deps/v8/tools/node/testdata/v8/testing/gtest/baz/gtest_foo b/deps/v8/tools/node/testdata/v8/testing/gtest/baz/gtest_foo new file mode 100644 index 00000000000000..eb1ae458f8ee6e --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/testing/gtest/baz/gtest_foo @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/testing/gtest/baz/gtest_new b/deps/v8/tools/node/testdata/v8/testing/gtest/baz/gtest_new new file mode 100644 index 00000000000000..eb1ae458f8ee6e --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/testing/gtest/baz/gtest_new @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/testing/gtest/gtest_bar b/deps/v8/tools/node/testdata/v8/testing/gtest/gtest_bar new file mode 100644 index 00000000000000..eb1ae458f8ee6e --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/testing/gtest/gtest_bar @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/testing/gtest/gtest_new b/deps/v8/tools/node/testdata/v8/testing/gtest/gtest_new new file mode 100644 index 00000000000000..eb1ae458f8ee6e --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/testing/gtest/gtest_new @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/testing/gtest/new/gtest_new b/deps/v8/tools/node/testdata/v8/testing/gtest/new/gtest_new new file mode 100644 index 00000000000000..eb1ae458f8ee6e --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/testing/gtest/new/gtest_new @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/update_node.py b/deps/v8/tools/node/update_node.py index 5d7e4daff4eabf..759e9d5aac72e2 100755 --- a/deps/v8/tools/node/update_node.py +++ b/deps/v8/tools/node/update_node.py @@ -34,23 +34,28 @@ TARGET_SUBDIR = os.path.join("deps", "v8") SUB_REPOSITORIES = [ ["base", "trace_event", "common"], - ["testing", "gtest"], + ["third_party", "googletest", "src"], ["third_party", "jinja2"], ["third_party", "markupsafe"] ] DELETE_FROM_GITIGNORE = [ "/base", - "/testing/gtest", + "/third_party/googletest/src", "/third_party/jinja2", "/third_party/markupsafe" ] # Node.js requires only a single header file from gtest to build V8. # Both jinja2 and markupsafe are required to generate part of the inspector. -ADD_TO_GITIGNORE = [ "/testing/gtest/*", - "!/testing/gtest/include", - "/testing/gtest/include/*", - "!/testing/gtest/include/gtest", - "/testing/gtest/include/gtest/*", - "!/testing/gtest/include/gtest/gtest_prod.h", +ADD_TO_GITIGNORE = [ "/third_party/googletest/*", + "!/third_party/googletest/BUILD.gn", + "!/third_party/googletest/src", + "/third_party/googletest/src/*", + "!/third_party/googletest/src/googletest", + "/third_party/googletest/src/googletest/*", + "!/third_party/googletest/src/googletest/include", + "/third_party/googletest/src/googletest/include/*", + "!/third_party/googletest/src/googletest/include/gtest", + "/third_party/googletest/src/googletest/include/gtest/*", + "!/third_party/googletest/src/googletest/include/gtest/gtest_prod.h", "!/third_party/jinja2", "!/third_party/markupsafe" ] diff --git a/deps/v8/tools/predictable_wrapper.py b/deps/v8/tools/predictable_wrapper.py index cf7bf00b3f6fab..c357c13b41b8bd 100644 --- a/deps/v8/tools/predictable_wrapper.py +++ b/deps/v8/tools/predictable_wrapper.py @@ -19,6 +19,7 @@ from testrunner.local import command MAX_TRIES = 3 +TIMEOUT = 120 def main(args): def allocation_str(stdout): @@ -27,7 +28,7 @@ def allocation_str(stdout): return line return None - cmd = command.Command(args[0], args[1:]) + cmd = command.Command(args[0], args[1:], timeout=TIMEOUT) previous_allocations = None for run in range(1, MAX_TRIES + 1): diff --git a/deps/v8/tools/presubmit.py b/deps/v8/tools/presubmit.py index 917b6e2383094e..29469be7589dc5 100755 --- a/deps/v8/tools/presubmit.py +++ b/deps/v8/tools/presubmit.py @@ -60,7 +60,9 @@ -build/header_guard -build/include_what_you_use -readability/fn_size +-readability/multiline_comment -runtime/references +-whitespace/comments """.split() LINT_OUTPUT_PATTERN = re.compile(r'^.+[:(]\d+[:)]|^Done processing') diff --git a/deps/v8/tools/release/auto_roll.py b/deps/v8/tools/release/auto_roll.py index b27675e60c86aa..ea83bfcd36dc8e 100755 --- a/deps/v8/tools/release/auto_roll.py +++ b/deps/v8/tools/release/auto_roll.py @@ -20,7 +20,7 @@ https://v8-roll.appspot.com/ This only works with a Google account. -CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel""") +CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel;luci.chromium.try:android_optional_gpu_tests_rel""") class Preparation(Step): MESSAGE = "Preparation." @@ -40,7 +40,7 @@ def RunStep(self): self["last_roll"] = self._options.last_roll if not self["last_roll"]: # Interpret the DEPS file to retrieve the v8 revision. - # TODO(machenbach): This should be part or the roll-deps api of + # TODO(machenbach): This should be part or the setdep api of # depot_tools. Var = lambda var: '%s' exec(FileToText(os.path.join(self._options.chromium, "DEPS"))) @@ -140,7 +140,7 @@ def RunStep(self): self['json_output']['monitoring_state'] = 'upload' cwd = self._options.chromium # Patch DEPS file. - if self.Command("roll-dep-svn", "v8 %s" % + if self.Command("gclient", "setdep -r src/v8@%s" % self["roll"], cwd=cwd) is None: self.Die("Failed to create deps for %s" % self["roll"]) diff --git a/deps/v8/tools/release/test_scripts.py b/deps/v8/tools/release/test_scripts.py index 759012d83348ca..25aa803daf23ae 100755 --- a/deps/v8/tools/release/test_scripts.py +++ b/deps/v8/tools/release/test_scripts.py @@ -1037,7 +1037,7 @@ def CheckVersionCommit(): https://v8-roll.appspot.com/ This only works with a Google account. -CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel +CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel;luci.chromium.try:android_optional_gpu_tests_rel TBR=reviewer@chromium.org""" @@ -1113,7 +1113,8 @@ def WriteDeps(): Cmd("git pull", "", cwd=chrome_dir), Cmd("git fetch origin", ""), Cmd("git new-branch work-branch", "", cwd=chrome_dir), - Cmd("roll-dep-svn v8 roll_hsh", "rolled", cb=WriteDeps, cwd=chrome_dir), + Cmd("gclient setdep -r src/v8@roll_hsh", "", cb=WriteDeps, + cwd=chrome_dir), Cmd(("git commit -am \"%s\" " "--author \"author@chromium.org \"" % self.ROLL_COMMIT_MSG), diff --git a/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/baz/gtest_new b/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/baz/gtest_new new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/gtest_new b/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/gtest_new new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h b/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h new file mode 100644 index 00000000000000..847c8bc75ed4fd --- /dev/null +++ b/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/gtest_prod.h @@ -0,0 +1 @@ +gtest_prod diff --git a/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/new/gtest_new b/deps/v8/tools/release/testdata/v8/third_party/googletest/src/googletest/include/gtest/new/gtest_new new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/deps/v8/tools/run-num-fuzzer.isolate b/deps/v8/tools/run-num-fuzzer.isolate deleted file mode 100644 index e9acbd4cb08455..00000000000000 --- a/deps/v8/tools/run-num-fuzzer.isolate +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2017 the V8 project authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -{ - 'variables': { - 'command': [ - 'run-num-fuzzer.py', - ], - 'files': [ - 'run-num-fuzzer.py', - ], - }, - 'includes': [ - 'testrunner/testrunner.isolate', - '../src/d8.isolate', - '../test/benchmarks/benchmarks.isolate', - '../test/mjsunit/mjsunit.isolate', - '../test/webkit/webkit.isolate', - ], -} diff --git a/deps/v8/tools/run_perf.py b/deps/v8/tools/run_perf.py index e19f6a056bb022..2bd4372453d367 100755 --- a/deps/v8/tools/run_perf.py +++ b/deps/v8/tools/run_perf.py @@ -793,6 +793,12 @@ def _PushExecutable(self, shell_dir, target_dir, binary): target_dir, skip_if_missing=True, ) + self._PushFile( + shell_dir, + "snapshot_blob_trusted.bin", + target_dir, + skip_if_missing=True, + ) self._PushFile( shell_dir, "icudtl.dat", diff --git a/deps/v8/tools/testrunner/base_runner.py b/deps/v8/tools/testrunner/base_runner.py index 7721360e2a01a5..cfea1527d4af37 100644 --- a/deps/v8/tools/testrunner/base_runner.py +++ b/deps/v8/tools/testrunner/base_runner.py @@ -599,6 +599,10 @@ def _get_statusfile_variables(self, options): self.build_config.mips_arch_variant == "r6" and self.build_config.mips_use_msa) + mips_arch_variant = ( + self.build_config.arch in ['mipsel', 'mips', 'mips64', 'mips64el'] and + self.build_config.mips_arch_variant) + # TODO(all): Combine "simulator" and "simulator_run". # TODO(machenbach): In GN we can derive simulator run from # target_arch != v8_target_arch in the dumped build config. @@ -613,6 +617,7 @@ def _get_statusfile_variables(self, options): "gc_stress": False, "gcov_coverage": self.build_config.gcov_coverage, "isolates": options.isolates, + "mips_arch_variant": mips_arch_variant, "mode": self.mode_options.status_mode, "msan": self.build_config.msan, "no_harness": options.no_harness, diff --git a/deps/v8/tools/testrunner/local/statusfile.py b/deps/v8/tools/testrunner/local/statusfile.py index e3adaa298a60d0..ecfbf008a23997 100644 --- a/deps/v8/tools/testrunner/local/statusfile.py +++ b/deps/v8/tools/testrunner/local/statusfile.py @@ -59,7 +59,7 @@ "android_arm", "android_arm64", "android_ia32", "android_x64", "arm", "arm64", "ia32", "mips", "mipsel", "mips64", "mips64el", "x64", "ppc", "ppc64", "s390", "s390x", "macos", "windows", - "linux", "aix"]: + "linux", "aix", "r1", "r2", "r3", "r5", "r6"]: VARIABLES[var] = var # Allow using variants as keywords. diff --git a/deps/v8/tools/testrunner/local/variants.py b/deps/v8/tools/testrunner/local/variants.py index 25de235da1e645..1c29f1d1955ecf 100644 --- a/deps/v8/tools/testrunner/local/variants.py +++ b/deps/v8/tools/testrunner/local/variants.py @@ -17,13 +17,12 @@ "nooptimization": [["--noopt"]], "slow_path": [["--force-slow-path"]], "stress": [["--stress-opt", "--always-opt"]], - "stress_background_compile": [["--background-compile", "--stress-background-compile"]], + "stress_background_compile": [["--stress-background-compile"]], "stress_incremental_marking": [["--stress-incremental-marking"]], # Trigger stress sampling allocation profiler with sample interval = 2^14 "stress_sampling": [["--stress-sampling-allocation-profiler=16384"]], "trusted": [["--no-untrusted-code-mitigations"]], "wasm_traps": [["--wasm-trap-handler", "--invoke-weak-callbacks"]], - "wasm_no_native": [["--no-wasm-jit-to-native"]], } SLOW_VARIANTS = set([ diff --git a/deps/v8/tools/testrunner/standard_runner.py b/deps/v8/tools/testrunner/standard_runner.py index d3d2bd53a6fbe1..bea00476f4e63a 100755 --- a/deps/v8/tools/testrunner/standard_runner.py +++ b/deps/v8/tools/testrunner/standard_runner.py @@ -44,7 +44,7 @@ # Shortcut for the two above ("more" first - it has the longer running tests). "exhaustive": MORE_VARIANTS + VARIANTS, # Additional variants, run on a subset of bots. - "extra": ["future", "liftoff", "trusted", "wasm_no_native"], + "extra": ["future", "liftoff", "trusted"], } GC_STRESS_FLAGS = ["--gc-interval=500", "--stress-compaction", diff --git a/deps/v8/tools/testrunner/testrunner.isolate b/deps/v8/tools/testrunner/testrunner.isolate deleted file mode 100644 index 56667c20215b51..00000000000000 --- a/deps/v8/tools/testrunner/testrunner.isolate +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2015 the V8 project authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -{ - 'variables': { - 'command': [ - '../run-tests.py', - ], - 'files': [ - '<(PRODUCT_DIR)/v8_build_config.json', - '../run-tests.py', - './' - ], - }, - 'conditions': [ - ['coverage==1 and sanitizer_coverage=="bb,trace-pc-guard"', { - 'variables': { - 'files': [ - '../sanitizers/sancov_merger.py', - '../../third_party/llvm/projects/compiler-rt/lib/sanitizer_common/scripts/sancov.py', - ], - }, - }], - ], -} diff --git a/deps/v8/tools/toolchain/BUILD.gn b/deps/v8/tools/toolchain/BUILD.gn index b2462054c4efad..b252c5eed5392c 100644 --- a/deps/v8/tools/toolchain/BUILD.gn +++ b/deps/v8/tools/toolchain/BUILD.gn @@ -15,9 +15,79 @@ gcc_toolchain("mips-bundled") { ar = "${toolprefix}ar" ld = cxx + # Flag that sets endianness + extra_ldflags = "-EB" + extra_cppflags = "-EB" + toolchain_args = { current_cpu = "mips" current_os = "linux" is_clang = false } } + +gcc_toolchain("mips64-bundled") { + toolprefix = rebase_path("//tools/mips_toolchain/bin/mips-mti-linux-gnu-", + root_build_dir) + cc = "${toolprefix}gcc" + cxx = "${toolprefix}g++" + + readelf = "${toolprefix}readelf" + nm = "${toolprefix}nm" + ar = "${toolprefix}ar" + ld = cxx + + # Flag that sets endianness and ABI + extra_ldflags = "-EB -mabi=64" + extra_cppflags = "-EB -mabi=64" + + toolchain_args = { + current_cpu = "mips64" + current_os = "linux" + is_clang = false + } +} + +gcc_toolchain("mipsel-bundled") { + toolprefix = rebase_path("//tools/mips_toolchain/bin/mips-mti-linux-gnu-", + root_build_dir) + cc = "${toolprefix}gcc" + cxx = "${toolprefix}g++" + + readelf = "${toolprefix}readelf" + nm = "${toolprefix}nm" + ar = "${toolprefix}ar" + ld = cxx + + # Flag that sets endianness + extra_ldflags = "-EL" + extra_cppflags = "-EL" + + toolchain_args = { + current_cpu = "mipsel" + current_os = "linux" + is_clang = false + } +} + +gcc_toolchain("mips64el-bundled") { + toolprefix = rebase_path("//tools/mips_toolchain/bin/mips-mti-linux-gnu-", + root_build_dir) + cc = "${toolprefix}gcc" + cxx = "${toolprefix}g++" + + readelf = "${toolprefix}readelf" + nm = "${toolprefix}nm" + ar = "${toolprefix}ar" + ld = cxx + + # Flag that sets endianness and ABI + extra_ldflags = "-EL -mabi=64" + extra_cppflags = "-EL -mabi=64" + + toolchain_args = { + current_cpu = "mips64el" + current_os = "linux" + is_clang = false + } +} diff --git a/deps/v8/tools/v8heapconst.py b/deps/v8/tools/v8heapconst.py index 5659cdd03c8814..1e57ce64a9e297 100644 --- a/deps/v8/tools/v8heapconst.py +++ b/deps/v8/tools/v8heapconst.py @@ -52,50 +52,67 @@ 148: "FIXED_BIGINT64_ARRAY_TYPE", 149: "FIXED_BIGUINT64_ARRAY_TYPE", 150: "FIXED_DOUBLE_ARRAY_TYPE", - 151: "FILLER_TYPE", - 152: "ACCESS_CHECK_INFO_TYPE", - 153: "ACCESSOR_INFO_TYPE", - 154: "ACCESSOR_PAIR_TYPE", - 155: "ALIASED_ARGUMENTS_ENTRY_TYPE", - 156: "ALLOCATION_MEMENTO_TYPE", - 157: "ALLOCATION_SITE_TYPE", - 158: "ASYNC_GENERATOR_REQUEST_TYPE", - 159: "CONTEXT_EXTENSION_TYPE", - 160: "DEBUG_INFO_TYPE", - 161: "FUNCTION_TEMPLATE_INFO_TYPE", - 162: "INTERCEPTOR_INFO_TYPE", - 163: "MODULE_INFO_ENTRY_TYPE", - 164: "MODULE_TYPE", - 165: "OBJECT_TEMPLATE_INFO_TYPE", - 166: "PROMISE_CAPABILITY_TYPE", - 167: "PROMISE_REACTION_TYPE", - 168: "PROTOTYPE_INFO_TYPE", - 169: "SCRIPT_TYPE", - 170: "STACK_FRAME_INFO_TYPE", - 171: "TUPLE2_TYPE", - 172: "TUPLE3_TYPE", - 173: "CALLABLE_TASK_TYPE", - 174: "CALLBACK_TASK_TYPE", - 175: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE", - 176: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE", - 177: "PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE", - 178: "FIXED_ARRAY_TYPE", - 179: "DESCRIPTOR_ARRAY_TYPE", - 180: "HASH_TABLE_TYPE", - 181: "SCOPE_INFO_TYPE", - 182: "TRANSITION_ARRAY_TYPE", - 183: "CELL_TYPE", - 184: "CODE_DATA_CONTAINER_TYPE", - 185: "FEEDBACK_CELL_TYPE", - 186: "FEEDBACK_VECTOR_TYPE", - 187: "LOAD_HANDLER_TYPE", - 188: "PROPERTY_ARRAY_TYPE", - 189: "PROPERTY_CELL_TYPE", - 190: "SHARED_FUNCTION_INFO_TYPE", - 191: "SMALL_ORDERED_HASH_MAP_TYPE", - 192: "SMALL_ORDERED_HASH_SET_TYPE", - 193: "STORE_HANDLER_TYPE", - 194: "WEAK_CELL_TYPE", + 151: "FEEDBACK_METADATA_TYPE", + 152: "FILLER_TYPE", + 153: "ACCESS_CHECK_INFO_TYPE", + 154: "ACCESSOR_INFO_TYPE", + 155: "ACCESSOR_PAIR_TYPE", + 156: "ALIASED_ARGUMENTS_ENTRY_TYPE", + 157: "ALLOCATION_MEMENTO_TYPE", + 158: "ALLOCATION_SITE_TYPE", + 159: "ASYNC_GENERATOR_REQUEST_TYPE", + 160: "CONTEXT_EXTENSION_TYPE", + 161: "DEBUG_INFO_TYPE", + 162: "FUNCTION_TEMPLATE_INFO_TYPE", + 163: "INTERCEPTOR_INFO_TYPE", + 164: "INTERPRETER_DATA_TYPE", + 165: "MODULE_INFO_ENTRY_TYPE", + 166: "MODULE_TYPE", + 167: "OBJECT_TEMPLATE_INFO_TYPE", + 168: "PROMISE_CAPABILITY_TYPE", + 169: "PROMISE_REACTION_TYPE", + 170: "PROTOTYPE_INFO_TYPE", + 171: "SCRIPT_TYPE", + 172: "STACK_FRAME_INFO_TYPE", + 173: "TUPLE2_TYPE", + 174: "TUPLE3_TYPE", + 175: "WASM_COMPILED_MODULE_TYPE", + 176: "WASM_DEBUG_INFO_TYPE", + 177: "WASM_SHARED_MODULE_DATA_TYPE", + 178: "CALLABLE_TASK_TYPE", + 179: "CALLBACK_TASK_TYPE", + 180: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE", + 181: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE", + 182: "PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE", + 183: "FIXED_ARRAY_TYPE", + 184: "BOILERPLATE_DESCRIPTION_TYPE", + 185: "DESCRIPTOR_ARRAY_TYPE", + 186: "HASH_TABLE_TYPE", + 187: "SCOPE_INFO_TYPE", + 188: "TRANSITION_ARRAY_TYPE", + 189: "BLOCK_CONTEXT_TYPE", + 190: "CATCH_CONTEXT_TYPE", + 191: "DEBUG_EVALUATE_CONTEXT_TYPE", + 192: "EVAL_CONTEXT_TYPE", + 193: "FUNCTION_CONTEXT_TYPE", + 194: "MODULE_CONTEXT_TYPE", + 195: "NATIVE_CONTEXT_TYPE", + 196: "SCRIPT_CONTEXT_TYPE", + 197: "WITH_CONTEXT_TYPE", + 198: "CALL_HANDLER_INFO_TYPE", + 199: "CELL_TYPE", + 200: "CODE_DATA_CONTAINER_TYPE", + 201: "FEEDBACK_CELL_TYPE", + 202: "FEEDBACK_VECTOR_TYPE", + 203: "LOAD_HANDLER_TYPE", + 204: "PROPERTY_ARRAY_TYPE", + 205: "PROPERTY_CELL_TYPE", + 206: "SHARED_FUNCTION_INFO_TYPE", + 207: "SMALL_ORDERED_HASH_MAP_TYPE", + 208: "SMALL_ORDERED_HASH_SET_TYPE", + 209: "STORE_HANDLER_TYPE", + 210: "WEAK_CELL_TYPE", + 211: "WEAK_FIXED_ARRAY_TYPE", 1024: "JS_PROXY_TYPE", 1025: "JS_GLOBAL_OBJECT_TYPE", 1026: "JS_GLOBAL_PROXY_TYPE", @@ -106,201 +123,173 @@ 1057: "JS_OBJECT_TYPE", 1058: "JS_ARGUMENTS_TYPE", 1059: "JS_ARRAY_BUFFER_TYPE", - 1060: "JS_ARRAY_TYPE", - 1061: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE", - 1062: "JS_ASYNC_GENERATOR_OBJECT_TYPE", - 1063: "JS_CONTEXT_EXTENSION_OBJECT_TYPE", - 1064: "JS_DATE_TYPE", - 1065: "JS_ERROR_TYPE", - 1066: "JS_GENERATOR_OBJECT_TYPE", - 1067: "JS_MAP_TYPE", - 1068: "JS_MAP_KEY_ITERATOR_TYPE", - 1069: "JS_MAP_KEY_VALUE_ITERATOR_TYPE", - 1070: "JS_MAP_VALUE_ITERATOR_TYPE", - 1071: "JS_MESSAGE_OBJECT_TYPE", - 1072: "JS_PROMISE_TYPE", - 1073: "JS_REGEXP_TYPE", - 1074: "JS_SET_TYPE", - 1075: "JS_SET_KEY_VALUE_ITERATOR_TYPE", - 1076: "JS_SET_VALUE_ITERATOR_TYPE", - 1077: "JS_STRING_ITERATOR_TYPE", - 1078: "JS_WEAK_MAP_TYPE", - 1079: "JS_WEAK_SET_TYPE", - 1080: "JS_TYPED_ARRAY_TYPE", - 1081: "JS_DATA_VIEW_TYPE", - 1082: "JS_TYPED_ARRAY_KEY_ITERATOR_TYPE", - 1083: "JS_FAST_ARRAY_KEY_ITERATOR_TYPE", - 1084: "JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE", - 1085: "JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1086: "JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1087: "JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1088: "JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1089: "JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1090: "JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1091: "JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1092: "JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1093: "JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1094: "JS_BIGUINT64_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1095: "JS_BIGINT64_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1096: "JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1097: "JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1098: "JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1099: "JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1100: "JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1101: "JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1102: "JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE", - 1103: "JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE", - 1104: "JS_INT8_ARRAY_VALUE_ITERATOR_TYPE", - 1105: "JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE", - 1106: "JS_INT16_ARRAY_VALUE_ITERATOR_TYPE", - 1107: "JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE", - 1108: "JS_INT32_ARRAY_VALUE_ITERATOR_TYPE", - 1109: "JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE", - 1110: "JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE", - 1111: "JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE", - 1112: "JS_BIGUINT64_ARRAY_VALUE_ITERATOR_TYPE", - 1113: "JS_BIGINT64_ARRAY_VALUE_ITERATOR_TYPE", - 1114: "JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE", - 1115: "JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE", - 1116: "JS_FAST_ARRAY_VALUE_ITERATOR_TYPE", - 1117: "JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE", - 1118: "JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE", - 1119: "JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE", - 1120: "JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE", - 1121: "WASM_INSTANCE_TYPE", - 1122: "WASM_MEMORY_TYPE", - 1123: "WASM_MODULE_TYPE", - 1124: "WASM_TABLE_TYPE", - 1125: "JS_BOUND_FUNCTION_TYPE", - 1126: "JS_FUNCTION_TYPE", + 1060: "JS_ARRAY_ITERATOR_TYPE", + 1061: "JS_ARRAY_TYPE", + 1062: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE", + 1063: "JS_ASYNC_GENERATOR_OBJECT_TYPE", + 1064: "JS_CONTEXT_EXTENSION_OBJECT_TYPE", + 1065: "JS_DATE_TYPE", + 1066: "JS_ERROR_TYPE", + 1067: "JS_GENERATOR_OBJECT_TYPE", + 1068: "JS_MAP_TYPE", + 1069: "JS_MAP_KEY_ITERATOR_TYPE", + 1070: "JS_MAP_KEY_VALUE_ITERATOR_TYPE", + 1071: "JS_MAP_VALUE_ITERATOR_TYPE", + 1072: "JS_MESSAGE_OBJECT_TYPE", + 1073: "JS_PROMISE_TYPE", + 1074: "JS_REGEXP_TYPE", + 1075: "JS_REGEXP_STRING_ITERATOR_TYPE", + 1076: "JS_SET_TYPE", + 1077: "JS_SET_KEY_VALUE_ITERATOR_TYPE", + 1078: "JS_SET_VALUE_ITERATOR_TYPE", + 1079: "JS_STRING_ITERATOR_TYPE", + 1080: "JS_WEAK_MAP_TYPE", + 1081: "JS_WEAK_SET_TYPE", + 1082: "JS_TYPED_ARRAY_TYPE", + 1083: "JS_DATA_VIEW_TYPE", + 1084: "WASM_GLOBAL_TYPE", + 1085: "WASM_INSTANCE_TYPE", + 1086: "WASM_MEMORY_TYPE", + 1087: "WASM_MODULE_TYPE", + 1088: "WASM_TABLE_TYPE", + 1089: "JS_BOUND_FUNCTION_TYPE", + 1090: "JS_FUNCTION_TYPE", } # List of known V8 maps. KNOWN_MAPS = { - 0x02201: (138, "FreeSpaceMap"), - 0x02251: (132, "MetaMap"), - 0x022a1: (131, "NullMap"), - 0x022f1: (179, "DescriptorArrayMap"), - 0x02341: (178, "FixedArrayMap"), - 0x02391: (151, "OnePointerFillerMap"), - 0x023e1: (151, "TwoPointerFillerMap"), - 0x02431: (131, "UninitializedMap"), - 0x02481: (8, "OneByteInternalizedStringMap"), - 0x024d1: (131, "UndefinedMap"), - 0x02521: (129, "HeapNumberMap"), - 0x02571: (131, "TheHoleMap"), - 0x025c1: (131, "BooleanMap"), - 0x02611: (136, "ByteArrayMap"), - 0x02661: (178, "FixedCOWArrayMap"), - 0x026b1: (180, "HashTableMap"), - 0x02701: (128, "SymbolMap"), - 0x02751: (72, "OneByteStringMap"), - 0x027a1: (181, "ScopeInfoMap"), - 0x027f1: (190, "SharedFunctionInfoMap"), - 0x02841: (133, "CodeMap"), - 0x02891: (178, "FunctionContextMap"), - 0x028e1: (183, "CellMap"), - 0x02931: (194, "WeakCellMap"), - 0x02981: (189, "GlobalPropertyCellMap"), - 0x029d1: (135, "ForeignMap"), - 0x02a21: (182, "TransitionArrayMap"), - 0x02a71: (186, "FeedbackVectorMap"), - 0x02ac1: (131, "ArgumentsMarkerMap"), - 0x02b11: (131, "ExceptionMap"), - 0x02b61: (131, "TerminationExceptionMap"), - 0x02bb1: (131, "OptimizedOutMap"), - 0x02c01: (131, "StaleRegisterMap"), - 0x02c51: (178, "NativeContextMap"), - 0x02ca1: (178, "ModuleContextMap"), - 0x02cf1: (178, "EvalContextMap"), - 0x02d41: (178, "ScriptContextMap"), - 0x02d91: (178, "BlockContextMap"), - 0x02de1: (178, "CatchContextMap"), - 0x02e31: (178, "WithContextMap"), - 0x02e81: (178, "DebugEvaluateContextMap"), - 0x02ed1: (178, "ScriptContextTableMap"), - 0x02f21: (178, "ArrayListMap"), - 0x02f71: (150, "FixedDoubleArrayMap"), - 0x02fc1: (134, "MutableHeapNumberMap"), - 0x03011: (180, "OrderedHashMapMap"), - 0x03061: (180, "OrderedHashSetMap"), - 0x030b1: (180, "NameDictionaryMap"), - 0x03101: (180, "GlobalDictionaryMap"), - 0x03151: (180, "NumberDictionaryMap"), - 0x031a1: (180, "SimpleNumberDictionaryMap"), - 0x031f1: (180, "StringTableMap"), - 0x03241: (180, "WeakHashTableMap"), - 0x03291: (178, "SloppyArgumentsElementsMap"), - 0x032e1: (191, "SmallOrderedHashMapMap"), - 0x03331: (192, "SmallOrderedHashSetMap"), - 0x03381: (184, "CodeDataContainerMap"), - 0x033d1: (1071, "JSMessageObjectMap"), - 0x03421: (1057, "ExternalMap"), - 0x03471: (137, "BytecodeArrayMap"), - 0x034c1: (178, "ModuleInfoMap"), - 0x03511: (185, "NoClosuresCellMap"), - 0x03561: (185, "OneClosureCellMap"), - 0x035b1: (185, "ManyClosuresCellMap"), - 0x03601: (188, "PropertyArrayMap"), - 0x03651: (130, "BigIntMap"), - 0x036a1: (106, "NativeSourceStringMap"), - 0x036f1: (64, "StringMap"), - 0x03741: (73, "ConsOneByteStringMap"), - 0x03791: (65, "ConsStringMap"), - 0x037e1: (77, "ThinOneByteStringMap"), - 0x03831: (69, "ThinStringMap"), - 0x03881: (67, "SlicedStringMap"), - 0x038d1: (75, "SlicedOneByteStringMap"), - 0x03921: (66, "ExternalStringMap"), - 0x03971: (82, "ExternalStringWithOneByteDataMap"), - 0x039c1: (74, "ExternalOneByteStringMap"), - 0x03a11: (98, "ShortExternalStringMap"), - 0x03a61: (114, "ShortExternalStringWithOneByteDataMap"), - 0x03ab1: (0, "InternalizedStringMap"), - 0x03b01: (2, "ExternalInternalizedStringMap"), - 0x03b51: (18, "ExternalInternalizedStringWithOneByteDataMap"), - 0x03ba1: (10, "ExternalOneByteInternalizedStringMap"), - 0x03bf1: (34, "ShortExternalInternalizedStringMap"), - 0x03c41: (50, "ShortExternalInternalizedStringWithOneByteDataMap"), - 0x03c91: (42, "ShortExternalOneByteInternalizedStringMap"), - 0x03ce1: (106, "ShortExternalOneByteStringMap"), - 0x03d31: (140, "FixedUint8ArrayMap"), - 0x03d81: (139, "FixedInt8ArrayMap"), - 0x03dd1: (142, "FixedUint16ArrayMap"), - 0x03e21: (141, "FixedInt16ArrayMap"), - 0x03e71: (144, "FixedUint32ArrayMap"), - 0x03ec1: (143, "FixedInt32ArrayMap"), - 0x03f11: (145, "FixedFloat32ArrayMap"), - 0x03f61: (146, "FixedFloat64ArrayMap"), - 0x03fb1: (147, "FixedUint8ClampedArrayMap"), - 0x04001: (149, "FixedBigUint64ArrayMap"), - 0x04051: (148, "FixedBigInt64ArrayMap"), - 0x040a1: (171, "Tuple2Map"), - 0x040f1: (169, "ScriptMap"), - 0x04141: (162, "InterceptorInfoMap"), - 0x04191: (153, "AccessorInfoMap"), - 0x041e1: (152, "AccessCheckInfoMap"), - 0x04231: (154, "AccessorPairMap"), - 0x04281: (155, "AliasedArgumentsEntryMap"), - 0x042d1: (156, "AllocationMementoMap"), - 0x04321: (157, "AllocationSiteMap"), - 0x04371: (158, "AsyncGeneratorRequestMap"), - 0x043c1: (159, "ContextExtensionMap"), - 0x04411: (160, "DebugInfoMap"), - 0x04461: (161, "FunctionTemplateInfoMap"), - 0x044b1: (163, "ModuleInfoEntryMap"), - 0x04501: (164, "ModuleMap"), - 0x04551: (165, "ObjectTemplateInfoMap"), - 0x045a1: (166, "PromiseCapabilityMap"), - 0x045f1: (167, "PromiseReactionMap"), - 0x04641: (168, "PrototypeInfoMap"), - 0x04691: (170, "StackFrameInfoMap"), - 0x046e1: (172, "Tuple3Map"), - 0x04731: (173, "CallableTaskMap"), - 0x04781: (174, "CallbackTaskMap"), - 0x047d1: (175, "PromiseFulfillReactionJobTaskMap"), - 0x04821: (176, "PromiseRejectReactionJobTaskMap"), - 0x04871: (177, "PromiseResolveThenableJobTaskMap"), + ("MAP_SPACE", 0x02201): (138, "FreeSpaceMap"), + ("MAP_SPACE", 0x02259): (132, "MetaMap"), + ("MAP_SPACE", 0x022b1): (131, "NullMap"), + ("MAP_SPACE", 0x02309): (185, "DescriptorArrayMap"), + ("MAP_SPACE", 0x02361): (183, "FixedArrayMap"), + ("MAP_SPACE", 0x023b9): (152, "OnePointerFillerMap"), + ("MAP_SPACE", 0x02411): (152, "TwoPointerFillerMap"), + ("MAP_SPACE", 0x02469): (131, "UninitializedMap"), + ("MAP_SPACE", 0x024c1): (8, "OneByteInternalizedStringMap"), + ("MAP_SPACE", 0x02519): (131, "UndefinedMap"), + ("MAP_SPACE", 0x02571): (129, "HeapNumberMap"), + ("MAP_SPACE", 0x025c9): (131, "TheHoleMap"), + ("MAP_SPACE", 0x02621): (131, "BooleanMap"), + ("MAP_SPACE", 0x02679): (136, "ByteArrayMap"), + ("MAP_SPACE", 0x026d1): (183, "FixedCOWArrayMap"), + ("MAP_SPACE", 0x02729): (186, "HashTableMap"), + ("MAP_SPACE", 0x02781): (128, "SymbolMap"), + ("MAP_SPACE", 0x027d9): (72, "OneByteStringMap"), + ("MAP_SPACE", 0x02831): (187, "ScopeInfoMap"), + ("MAP_SPACE", 0x02889): (206, "SharedFunctionInfoMap"), + ("MAP_SPACE", 0x028e1): (133, "CodeMap"), + ("MAP_SPACE", 0x02939): (193, "FunctionContextMap"), + ("MAP_SPACE", 0x02991): (199, "CellMap"), + ("MAP_SPACE", 0x029e9): (210, "WeakCellMap"), + ("MAP_SPACE", 0x02a41): (205, "GlobalPropertyCellMap"), + ("MAP_SPACE", 0x02a99): (135, "ForeignMap"), + ("MAP_SPACE", 0x02af1): (188, "TransitionArrayMap"), + ("MAP_SPACE", 0x02b49): (202, "FeedbackVectorMap"), + ("MAP_SPACE", 0x02ba1): (131, "ArgumentsMarkerMap"), + ("MAP_SPACE", 0x02bf9): (131, "ExceptionMap"), + ("MAP_SPACE", 0x02c51): (131, "TerminationExceptionMap"), + ("MAP_SPACE", 0x02ca9): (131, "OptimizedOutMap"), + ("MAP_SPACE", 0x02d01): (131, "StaleRegisterMap"), + ("MAP_SPACE", 0x02d59): (195, "NativeContextMap"), + ("MAP_SPACE", 0x02db1): (194, "ModuleContextMap"), + ("MAP_SPACE", 0x02e09): (192, "EvalContextMap"), + ("MAP_SPACE", 0x02e61): (196, "ScriptContextMap"), + ("MAP_SPACE", 0x02eb9): (189, "BlockContextMap"), + ("MAP_SPACE", 0x02f11): (190, "CatchContextMap"), + ("MAP_SPACE", 0x02f69): (197, "WithContextMap"), + ("MAP_SPACE", 0x02fc1): (191, "DebugEvaluateContextMap"), + ("MAP_SPACE", 0x03019): (183, "ScriptContextTableMap"), + ("MAP_SPACE", 0x03071): (151, "FeedbackMetadataArrayMap"), + ("MAP_SPACE", 0x030c9): (183, "ArrayListMap"), + ("MAP_SPACE", 0x03121): (130, "BigIntMap"), + ("MAP_SPACE", 0x03179): (184, "BoilerplateDescriptionMap"), + ("MAP_SPACE", 0x031d1): (137, "BytecodeArrayMap"), + ("MAP_SPACE", 0x03229): (200, "CodeDataContainerMap"), + ("MAP_SPACE", 0x03281): (1057, "ExternalMap"), + ("MAP_SPACE", 0x032d9): (150, "FixedDoubleArrayMap"), + ("MAP_SPACE", 0x03331): (186, "GlobalDictionaryMap"), + ("MAP_SPACE", 0x03389): (201, "ManyClosuresCellMap"), + ("MAP_SPACE", 0x033e1): (1072, "JSMessageObjectMap"), + ("MAP_SPACE", 0x03439): (183, "ModuleInfoMap"), + ("MAP_SPACE", 0x03491): (134, "MutableHeapNumberMap"), + ("MAP_SPACE", 0x034e9): (186, "NameDictionaryMap"), + ("MAP_SPACE", 0x03541): (201, "NoClosuresCellMap"), + ("MAP_SPACE", 0x03599): (186, "NumberDictionaryMap"), + ("MAP_SPACE", 0x035f1): (201, "OneClosureCellMap"), + ("MAP_SPACE", 0x03649): (186, "OrderedHashMapMap"), + ("MAP_SPACE", 0x036a1): (186, "OrderedHashSetMap"), + ("MAP_SPACE", 0x036f9): (204, "PropertyArrayMap"), + ("MAP_SPACE", 0x03751): (198, "SideEffectCallHandlerInfoMap"), + ("MAP_SPACE", 0x037a9): (198, "SideEffectFreeCallHandlerInfoMap"), + ("MAP_SPACE", 0x03801): (186, "SimpleNumberDictionaryMap"), + ("MAP_SPACE", 0x03859): (183, "SloppyArgumentsElementsMap"), + ("MAP_SPACE", 0x038b1): (207, "SmallOrderedHashMapMap"), + ("MAP_SPACE", 0x03909): (208, "SmallOrderedHashSetMap"), + ("MAP_SPACE", 0x03961): (186, "StringTableMap"), + ("MAP_SPACE", 0x039b9): (211, "WeakFixedArrayMap"), + ("MAP_SPACE", 0x03a11): (106, "NativeSourceStringMap"), + ("MAP_SPACE", 0x03a69): (64, "StringMap"), + ("MAP_SPACE", 0x03ac1): (73, "ConsOneByteStringMap"), + ("MAP_SPACE", 0x03b19): (65, "ConsStringMap"), + ("MAP_SPACE", 0x03b71): (77, "ThinOneByteStringMap"), + ("MAP_SPACE", 0x03bc9): (69, "ThinStringMap"), + ("MAP_SPACE", 0x03c21): (67, "SlicedStringMap"), + ("MAP_SPACE", 0x03c79): (75, "SlicedOneByteStringMap"), + ("MAP_SPACE", 0x03cd1): (66, "ExternalStringMap"), + ("MAP_SPACE", 0x03d29): (82, "ExternalStringWithOneByteDataMap"), + ("MAP_SPACE", 0x03d81): (74, "ExternalOneByteStringMap"), + ("MAP_SPACE", 0x03dd9): (98, "ShortExternalStringMap"), + ("MAP_SPACE", 0x03e31): (114, "ShortExternalStringWithOneByteDataMap"), + ("MAP_SPACE", 0x03e89): (0, "InternalizedStringMap"), + ("MAP_SPACE", 0x03ee1): (2, "ExternalInternalizedStringMap"), + ("MAP_SPACE", 0x03f39): (18, "ExternalInternalizedStringWithOneByteDataMap"), + ("MAP_SPACE", 0x03f91): (10, "ExternalOneByteInternalizedStringMap"), + ("MAP_SPACE", 0x03fe9): (34, "ShortExternalInternalizedStringMap"), + ("MAP_SPACE", 0x04041): (50, "ShortExternalInternalizedStringWithOneByteDataMap"), + ("MAP_SPACE", 0x04099): (42, "ShortExternalOneByteInternalizedStringMap"), + ("MAP_SPACE", 0x040f1): (106, "ShortExternalOneByteStringMap"), + ("MAP_SPACE", 0x04149): (140, "FixedUint8ArrayMap"), + ("MAP_SPACE", 0x041a1): (139, "FixedInt8ArrayMap"), + ("MAP_SPACE", 0x041f9): (142, "FixedUint16ArrayMap"), + ("MAP_SPACE", 0x04251): (141, "FixedInt16ArrayMap"), + ("MAP_SPACE", 0x042a9): (144, "FixedUint32ArrayMap"), + ("MAP_SPACE", 0x04301): (143, "FixedInt32ArrayMap"), + ("MAP_SPACE", 0x04359): (145, "FixedFloat32ArrayMap"), + ("MAP_SPACE", 0x043b1): (146, "FixedFloat64ArrayMap"), + ("MAP_SPACE", 0x04409): (147, "FixedUint8ClampedArrayMap"), + ("MAP_SPACE", 0x04461): (149, "FixedBigUint64ArrayMap"), + ("MAP_SPACE", 0x044b9): (148, "FixedBigInt64ArrayMap"), + ("MAP_SPACE", 0x04511): (173, "Tuple2Map"), + ("MAP_SPACE", 0x04569): (171, "ScriptMap"), + ("MAP_SPACE", 0x045c1): (163, "InterceptorInfoMap"), + ("MAP_SPACE", 0x04619): (154, "AccessorInfoMap"), + ("MAP_SPACE", 0x04671): (153, "AccessCheckInfoMap"), + ("MAP_SPACE", 0x046c9): (155, "AccessorPairMap"), + ("MAP_SPACE", 0x04721): (156, "AliasedArgumentsEntryMap"), + ("MAP_SPACE", 0x04779): (157, "AllocationMementoMap"), + ("MAP_SPACE", 0x047d1): (158, "AllocationSiteMap"), + ("MAP_SPACE", 0x04829): (159, "AsyncGeneratorRequestMap"), + ("MAP_SPACE", 0x04881): (160, "ContextExtensionMap"), + ("MAP_SPACE", 0x048d9): (161, "DebugInfoMap"), + ("MAP_SPACE", 0x04931): (162, "FunctionTemplateInfoMap"), + ("MAP_SPACE", 0x04989): (164, "InterpreterDataMap"), + ("MAP_SPACE", 0x049e1): (165, "ModuleInfoEntryMap"), + ("MAP_SPACE", 0x04a39): (166, "ModuleMap"), + ("MAP_SPACE", 0x04a91): (167, "ObjectTemplateInfoMap"), + ("MAP_SPACE", 0x04ae9): (168, "PromiseCapabilityMap"), + ("MAP_SPACE", 0x04b41): (169, "PromiseReactionMap"), + ("MAP_SPACE", 0x04b99): (170, "PrototypeInfoMap"), + ("MAP_SPACE", 0x04bf1): (172, "StackFrameInfoMap"), + ("MAP_SPACE", 0x04c49): (174, "Tuple3Map"), + ("MAP_SPACE", 0x04ca1): (175, "WasmCompiledModuleMap"), + ("MAP_SPACE", 0x04cf9): (176, "WasmDebugInfoMap"), + ("MAP_SPACE", 0x04d51): (177, "WasmSharedModuleDataMap"), + ("MAP_SPACE", 0x04da9): (178, "CallableTaskMap"), + ("MAP_SPACE", 0x04e01): (179, "CallbackTaskMap"), + ("MAP_SPACE", 0x04e59): (180, "PromiseFulfillReactionJobTaskMap"), + ("MAP_SPACE", 0x04eb1): (181, "PromiseRejectReactionJobTaskMap"), + ("MAP_SPACE", 0x04f09): (182, "PromiseResolveThenableJobTaskMap"), } # List of known V8 objects. @@ -322,34 +311,35 @@ ("OLD_SPACE", 0x02519): "TerminationException", ("OLD_SPACE", 0x02579): "OptimizedOut", ("OLD_SPACE", 0x025d1): "StaleRegister", - ("OLD_SPACE", 0x02651): "EmptyByteArray", - ("OLD_SPACE", 0x02661): "EmptyFixedUint8Array", - ("OLD_SPACE", 0x02681): "EmptyFixedInt8Array", - ("OLD_SPACE", 0x026a1): "EmptyFixedUint16Array", - ("OLD_SPACE", 0x026c1): "EmptyFixedInt16Array", - ("OLD_SPACE", 0x026e1): "EmptyFixedUint32Array", - ("OLD_SPACE", 0x02701): "EmptyFixedInt32Array", - ("OLD_SPACE", 0x02721): "EmptyFixedFloat32Array", - ("OLD_SPACE", 0x02741): "EmptyFixedFloat64Array", - ("OLD_SPACE", 0x02761): "EmptyFixedUint8ClampedArray", - ("OLD_SPACE", 0x027c1): "EmptyScript", - ("OLD_SPACE", 0x02849): "ManyClosuresCell", - ("OLD_SPACE", 0x02859): "EmptySloppyArgumentsElements", - ("OLD_SPACE", 0x02879): "EmptySlowElementDictionary", - ("OLD_SPACE", 0x028c1): "EmptyOrderedHashMap", - ("OLD_SPACE", 0x028e9): "EmptyOrderedHashSet", - ("OLD_SPACE", 0x02911): "EmptyPropertyCell", - ("OLD_SPACE", 0x02939): "EmptyWeakCell", - ("OLD_SPACE", 0x029a9): "NoElementsProtector", - ("OLD_SPACE", 0x029d1): "IsConcatSpreadableProtector", - ("OLD_SPACE", 0x029e1): "SpeciesProtector", - ("OLD_SPACE", 0x02a09): "StringLengthProtector", - ("OLD_SPACE", 0x02a19): "FastArrayIterationProtector", - ("OLD_SPACE", 0x02a29): "ArrayIteratorProtector", - ("OLD_SPACE", 0x02a51): "ArrayBufferNeuteringProtector", - ("OLD_SPACE", 0x02ac9): "InfinityValue", - ("OLD_SPACE", 0x02ad9): "MinusZeroValue", - ("OLD_SPACE", 0x02ae9): "MinusInfinityValue", + ("OLD_SPACE", 0x02661): "EmptyByteArray", + ("OLD_SPACE", 0x02681): "EmptyFixedUint8Array", + ("OLD_SPACE", 0x026a1): "EmptyFixedInt8Array", + ("OLD_SPACE", 0x026c1): "EmptyFixedUint16Array", + ("OLD_SPACE", 0x026e1): "EmptyFixedInt16Array", + ("OLD_SPACE", 0x02701): "EmptyFixedUint32Array", + ("OLD_SPACE", 0x02721): "EmptyFixedInt32Array", + ("OLD_SPACE", 0x02741): "EmptyFixedFloat32Array", + ("OLD_SPACE", 0x02761): "EmptyFixedFloat64Array", + ("OLD_SPACE", 0x02781): "EmptyFixedUint8ClampedArray", + ("OLD_SPACE", 0x027e1): "EmptyScript", + ("OLD_SPACE", 0x02879): "ManyClosuresCell", + ("OLD_SPACE", 0x02889): "EmptySloppyArgumentsElements", + ("OLD_SPACE", 0x028a9): "EmptySlowElementDictionary", + ("OLD_SPACE", 0x028f1): "EmptyOrderedHashMap", + ("OLD_SPACE", 0x02919): "EmptyOrderedHashSet", + ("OLD_SPACE", 0x02951): "EmptyPropertyCell", + ("OLD_SPACE", 0x02979): "EmptyWeakCell", + ("OLD_SPACE", 0x029e9): "NoElementsProtector", + ("OLD_SPACE", 0x02a11): "IsConcatSpreadableProtector", + ("OLD_SPACE", 0x02a21): "ArraySpeciesProtector", + ("OLD_SPACE", 0x02a49): "TypedArraySpeciesProtector", + ("OLD_SPACE", 0x02a71): "PromiseSpeciesProtector", + ("OLD_SPACE", 0x02a99): "StringLengthProtector", + ("OLD_SPACE", 0x02aa9): "ArrayIteratorProtector", + ("OLD_SPACE", 0x02ad1): "ArrayBufferNeuteringProtector", + ("OLD_SPACE", 0x02b59): "InfinityValue", + ("OLD_SPACE", 0x02b69): "MinusZeroValue", + ("OLD_SPACE", 0x02b79): "MinusInfinityValue", } # List of known V8 Frame Markers. @@ -360,7 +350,6 @@ "OPTIMIZED", "WASM_COMPILED", "WASM_TO_JS", - "WASM_TO_WASM", "JS_TO_WASM", "WASM_INTERPRETER_ENTRY", "C_WASM_ENTRY", @@ -368,6 +357,7 @@ "STUB", "BUILTIN_CONTINUATION", "JAVA_SCRIPT_BUILTIN_CONTINUATION", + "JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH", "INTERNAL", "CONSTRUCT", "ARGUMENTS_ADAPTOR", diff --git a/deps/v8/tools/valgrind/asan/dummy b/deps/v8/tools/valgrind/asan/dummy new file mode 100644 index 00000000000000..0e89814954ce81 --- /dev/null +++ b/deps/v8/tools/valgrind/asan/dummy @@ -0,0 +1,2 @@ +# src/base has some more tools in this folder, which we don't use. But we need +# to have the folder so that the data deps we inherit doesn't error out. \ No newline at end of file diff --git a/deps/v8/tools/whitespace.txt b/deps/v8/tools/whitespace.txt index 2367b2ccc89323..ed5e51f96a63e8 100644 --- a/deps/v8/tools/whitespace.txt +++ b/deps/v8/tools/whitespace.txt @@ -7,6 +7,6 @@ A Smi balks into a war and says: The doubles heard this and started to unbox. The Smi looked at them when a crazy v8-autoroll account showed up... The autoroller bought a round of Himbeerbrause. Suddenly... -The bartender starts to shake the bottles........ +The bartender starts to shake the bottles....................... . . From bad3c921243984fdad1915a5a5a53b35f8a752be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Thu, 31 May 2018 11:12:11 +0200 Subject: [PATCH 27/93] build: reset embedder string to "-node.0" PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- common.gypi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.gypi b/common.gypi index 31196e22535393..a4a5ae80b095a3 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.9', + 'v8_embedder_string': '-node.0', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, From fed1d18054b251b298955050d90115b6e14d7eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Tue, 13 Mar 2018 13:57:26 +0100 Subject: [PATCH 28/93] deps: update v8.gyp Synchronize source files list with upstream's BUILD.gn. PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- common.gypi | 2 +- deps/v8/gypfiles/v8.gyp | 35 ++++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/common.gypi b/common.gypi index a4a5ae80b095a3..9148252d519b94 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.0', + 'v8_embedder_string': '-node.1', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/gypfiles/v8.gyp b/deps/v8/gypfiles/v8.gyp index 601b8403cc4378..80ce748d1fecab 100644 --- a/deps/v8/gypfiles/v8.gyp +++ b/deps/v8/gypfiles/v8.gyp @@ -541,7 +541,6 @@ '../src/api.cc', '../src/api.h', '../src/api-arguments-inl.h', - '../src/api-arguments.cc', '../src/api-arguments.h', '../src/api-natives.cc', '../src/api-natives.h', @@ -657,8 +656,6 @@ '../src/compilation-cache.h', '../src/compilation-dependencies.cc', '../src/compilation-dependencies.h', - '../src/compilation-info.cc', - '../src/compilation-info.h', '../src/compilation-statistics.cc', '../src/compilation-statistics.h', '../src/compiler/access-builder.cc', @@ -941,9 +938,8 @@ '../src/extensions/trigger-failure-extension.h', '../src/external-reference-table.cc', '../src/external-reference-table.h', - '../src/factory-inl.h', - '../src/factory.cc', - '../src/factory.h', + '../src/external-reference.cc', + '../src/external-reference.h', '../src/fast-dtoa.cc', '../src/fast-dtoa.h', '../src/feedback-vector-inl.h', @@ -987,6 +983,9 @@ '../src/heap/concurrent-marking.h', '../src/heap/embedder-tracing.cc', '../src/heap/embedder-tracing.h', + '../src/heap/factory-inl.h', + '../src/heap/factory.cc', + '../src/heap/factory.h', '../src/heap/memory-reducer.cc', '../src/heap/memory-reducer.h', '../src/heap/gc-idle-time-handler.cc', @@ -1174,11 +1173,15 @@ '../src/objects/js-promise.h', '../src/objects/js-regexp-inl.h', '../src/objects/js-regexp.h', + '../src/objects/js-regexp-string-iterator-inl.h', + '../src/objects/js-regexp-string-iterator.h', '../src/objects/literal-objects.cc', '../src/objects/literal-objects-inl.h', '../src/objects/literal-objects.h', '../src/objects/map-inl.h', '../src/objects/map.h', + '../src/objects/maybe-object-inl.h', + '../src/objects/maybe-object.h', '../src/objects/microtask-inl.h', '../src/objects/microtask.h', '../src/objects/module-inl.h', @@ -1204,6 +1207,8 @@ '../src/objects/string-table.h', '../src/objects/template-objects.cc', '../src/objects/template-objects.h', + '../src/optimized-compilation-info.cc', + '../src/optimized-compilation-info.h', '../src/ostreams.cc', '../src/ostreams.h', '../src/parsing/duplicate-finder.h', @@ -1415,13 +1420,15 @@ '../src/trap-handler/trap-handler-internal.h', '../src/type-hints.cc', '../src/type-hints.h', - '../src/unicode-inl.h', - '../src/unicode.cc', - '../src/unicode.h', '../src/unicode-cache-inl.h', '../src/unicode-cache.h', '../src/unicode-decoder.cc', '../src/unicode-decoder.h', + '../src/unicode-inl.h', + '../src/unicode.cc', + '../src/unicode.h', + '../src/unoptimized-compilation-info.cc', + '../src/unoptimized-compilation-info.h', '../src/uri.cc', '../src/uri.h', '../src/utils-inl.h', @@ -1471,8 +1478,6 @@ '../src/wasm/wasm-code-manager.h', '../src/wasm/wasm-code-specialization.cc', '../src/wasm/wasm-code-specialization.h', - '../src/wasm/wasm-code-wrapper.cc', - '../src/wasm/wasm-code-wrapper.h', '../src/wasm/wasm-constants.h', '../src/wasm/wasm-debug.cc', '../src/wasm/wasm-engine.cc', @@ -2201,12 +2206,12 @@ '../include//libplatform/libplatform.h', '../include//libplatform/libplatform-export.h', '../include//libplatform/v8-tracing.h', - '../src/libplatform/default-background-task-runner.cc', - '../src/libplatform/default-background-task-runner.h', '../src/libplatform/default-foreground-task-runner.cc', '../src/libplatform/default-foreground-task-runner.h', '../src/libplatform/default-platform.cc', '../src/libplatform/default-platform.h', + '../src/libplatform/default-worker-threads-task-runner.cc', + '../src/libplatform/default-worker-threads-task-runner.h', '../src/libplatform/task-queue.cc', '../src/libplatform/task-queue.h', '../src/libplatform/tracing/trace-buffer.cc', @@ -2342,8 +2347,6 @@ '../src/js/prologue.js', '../src/js/array.js', '../src/js/typedarray.js', - '../src/js/messages.js', - '../src/js/spread.js', '../src/debug/mirrors.js', '../src/debug/debug.js', '../src/debug/liveedit.js', @@ -2473,6 +2476,8 @@ '../src/objects/js-array-inl.h', '../src/objects/js-regexp.h', '../src/objects/js-regexp-inl.h', + '../src/objects/js-regexp-string-iterator-inl.h', + '../src/objects/js-regexp-string-iterator.h', '../src/objects/map.h', '../src/objects/map-inl.h', '../src/objects/script.h', From a7aff77a97e62a9fbc1a2dccb7cf2f4e131f5328 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 13 Apr 2018 11:49:41 -0700 Subject: [PATCH 29/93] deps: cherry-pick 39d546a from upstream V8 Original commit message: [api] introduce v8::Value::IsModuleNamespaceObject This allows an embedder to check if a Value is a module namespace object. Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: Idffceff451dd5f5c6a53d4cb3ce02c1c2c5b653c Reviewed-on: https://chromium-review.googlesource.com/1011762 Reviewed-by: Georg Neis Commit-Queue: Georg Neis Cr-Commit-Position: refs/heads/master@{#52597} Refs: https://github.com/v8/v8/commit/39d546a24022b62b00aedf7b556ac6c9e2306aab PR-URL: https://github.com/nodejs/node/pull/20016 Reviewed-By: Ben Noordhuis Reviewed-By: Guy Bedford Reviewed-By: Colin Ihrig --- common.gypi | 2 +- deps/v8/AUTHORS | 1 + deps/v8/include/v8.h | 5 +++++ deps/v8/src/api.cc | 4 ++++ deps/v8/test/cctest/test-api.cc | 29 +++++++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/common.gypi b/common.gypi index 9148252d519b94..08e4f36cec4d24 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.1', + 'v8_embedder_string': '-node.2', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index 3251716f2a55f5..4b5163961d282e 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -70,6 +70,7 @@ Felix Geisendörfer Filipe David Manana Franziska Hinkelmann Geoffrey Garside +Gus Caplan Gwang Yoon Hwang Henrique Ferreiro Hirofumi Mako diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index d520c866042a7a..c6e9250e4e938b 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -2378,6 +2378,11 @@ class V8_EXPORT Value : public Data { bool IsWebAssemblyCompiledModule() const; + /** + * Returns true if the value is a Module Namespace Object. + */ + bool IsModuleNamespaceObject() const; + V8_WARN_UNUSED_RESULT MaybeLocal ToBigInt( Local context) const; V8_WARN_UNUSED_RESULT MaybeLocal ToBoolean( diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 8b177d041d447f..6dd669ee1133bf 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -3583,6 +3583,10 @@ bool Value::IsSetIterator() const { bool Value::IsPromise() const { return Utils::OpenHandle(this)->IsJSPromise(); } +bool Value::IsModuleNamespaceObject() const { + return Utils::OpenHandle(this)->IsJSModuleNamespace(); +} + MaybeLocal Value::ToString(Local context) const { auto obj = Utils::OpenHandle(this); if (obj->IsString()) return ToApiHandle(obj); diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index f126433578e336..261ada0f2bb308 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -27274,6 +27274,35 @@ TEST(ImportMeta) { CHECK(result->StrictEquals(Local::Cast(v8::Utils::ToLocal(meta)))); } +TEST(GetModuleNamespace) { + LocalContext context; + v8::Isolate* isolate = context->GetIsolate(); + v8::HandleScope scope(isolate); + + Local url = v8_str("www.google.com"); + Local source_text = v8_str("export default 5; export const a = 10;"); + v8::ScriptOrigin origin(url, Local(), Local(), + Local(), Local(), + Local(), Local(), + Local(), True(isolate)); + v8::ScriptCompiler::Source source(source_text, origin); + Local module = + v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked(); + module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback) + .ToChecked(); + module->Evaluate(context.local()).ToLocalChecked(); + + Local ns_val = module->GetModuleNamespace(); + CHECK(ns_val->IsModuleNamespaceObject()); + Local ns = ns_val.As(); + CHECK(ns->Get(context.local(), v8_str("default")) + .ToLocalChecked() + ->StrictEquals(v8::Number::New(isolate, 5))); + CHECK(ns->Get(context.local(), v8_str("a")) + .ToLocalChecked() + ->StrictEquals(v8::Number::New(isolate, 10))); +} + TEST(GlobalTemplateWithDoubleProperty) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope handle_scope(isolate); From ec058193a8c63540e37a12b6f3b53fc876e4a7b1 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Mon, 7 May 2018 08:36:43 -0500 Subject: [PATCH 30/93] v8: backport 9fb02b526f1cd3b859a530a01adb08bc0d089f4f Refs: https://github.com/v8/v8/commit/9fb02b526f1cd3b859a530a01adb08bc0d089f4f Original commit message: Allow function callbacks to have Proxy as receiver. R=verwaest@chromium.org Bug: v8:5773 Change-Id: Ifd29a1116ee8c86b8d8d24485bbfd19e260ab66b Reviewed-on: chromium-review.googlesource.com/1046088 Commit-Queue: Yang Guo Reviewed-by: Camillo Bruni Cr-Commit-Position: refs/heads/master@{#53015} PR-URL: https://github.com/nodejs/node/pull/20575 Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis --- common.gypi | 2 +- deps/v8/src/builtins/builtins-api.cc | 41 ++++++++++++++-------------- deps/v8/test/cctest/test-api.cc | 28 +++++++++++++++++++ 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/common.gypi b/common.gypi index 08e4f36cec4d24..04a729e93b7021 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.2', + 'v8_embedder_string': '-node.3', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/src/builtins/builtins-api.cc b/deps/v8/src/builtins/builtins-api.cc index ce19bf86624ec5..cba404676a9420 100644 --- a/deps/v8/src/builtins/builtins-api.cc +++ b/deps/v8/src/builtins/builtins-api.cc @@ -21,17 +21,21 @@ namespace { // Returns the holder JSObject if the function can legally be called with this // receiver. Returns nullptr if the call is illegal. // TODO(dcarney): CallOptimization duplicates this logic, merge. -JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info, - JSObject* receiver) { +JSReceiver* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info, + JSReceiver* receiver) { Object* recv_type = info->signature(); // No signature, return holder. if (!recv_type->IsFunctionTemplateInfo()) return receiver; + // A Proxy cannot have been created from the signature template. + if (!receiver->IsJSObject()) return nullptr; + + JSObject* js_obj_receiver = JSObject::cast(receiver); FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type); // Check the receiver. Fast path for receivers with no hidden prototypes. - if (signature->IsTemplateFor(receiver)) return receiver; - if (!receiver->map()->has_hidden_prototype()) return nullptr; - for (PrototypeIterator iter(isolate, receiver, kStartAtPrototype, + if (signature->IsTemplateFor(js_obj_receiver)) return receiver; + if (!js_obj_receiver->map()->has_hidden_prototype()) return nullptr; + for (PrototypeIterator iter(isolate, js_obj_receiver, kStartAtPrototype, PrototypeIterator::END_AT_NON_HIDDEN); !iter.IsAtEnd(); iter.Advance()) { JSObject* current = iter.GetCurrent(); @@ -45,8 +49,8 @@ V8_WARN_UNUSED_RESULT MaybeHandle HandleApiCallHelper( Isolate* isolate, Handle function, Handle new_target, Handle fun_data, Handle receiver, BuiltinArguments args) { - Handle js_receiver; - JSObject* raw_holder; + Handle js_receiver; + JSReceiver* raw_holder; if (is_construct) { DCHECK(args.receiver()->IsTheHole(isolate)); if (fun_data->instance_template()->IsUndefined(isolate)) { @@ -68,21 +72,18 @@ V8_WARN_UNUSED_RESULT MaybeHandle HandleApiCallHelper( raw_holder = *js_receiver; } else { DCHECK(receiver->IsJSReceiver()); - - if (!receiver->IsJSObject()) { - // This function cannot be called with the given receiver. Abort! - THROW_NEW_ERROR( - isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object); - } - - js_receiver = Handle::cast(receiver); + js_receiver = Handle::cast(receiver); if (!fun_data->accept_any_receiver() && - js_receiver->IsAccessCheckNeeded() && - !isolate->MayAccess(handle(isolate->context()), js_receiver)) { - isolate->ReportFailedAccessCheck(js_receiver); - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); - return isolate->factory()->undefined_value(); + js_receiver->IsAccessCheckNeeded()) { + // Proxies never need access checks. + DCHECK(js_receiver->IsJSObject()); + Handle js_obj_receiver = Handle::cast(js_receiver); + if (!isolate->MayAccess(handle(isolate->context()), js_obj_receiver)) { + isolate->ReportFailedAccessCheck(js_obj_receiver); + RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); + return isolate->factory()->undefined_value(); + } } raw_holder = GetCompatibleReceiver(isolate, *fun_data, *js_receiver); diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 261ada0f2bb308..2f552a9d9d9f6a 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -1088,6 +1088,34 @@ THREADED_PROFILED_TEST(FunctionTemplate) { TestFunctionTemplateAccessor(construct_callback, Return239Callback); } +static void FunctionCallbackForProxyTest( + const v8::FunctionCallbackInfo& info) { + info.GetReturnValue().Set(info.This()); +} + +THREADED_TEST(FunctionTemplateWithProxy) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + + v8::Local function_template = + v8::FunctionTemplate::New(isolate, FunctionCallbackForProxyTest); + v8::Local function = + function_template->GetFunction(env.local()).ToLocalChecked(); + CHECK((*env)->Global()->Set(env.local(), v8_str("f"), function).FromJust()); + v8::Local proxy = + CompileRun("var proxy = new Proxy({}, {}); proxy"); + CHECK(proxy->IsProxy()); + + v8::Local result = CompileRun("f(proxy)"); + CHECK(result->Equals(env.local(), (*env)->Global()).FromJust()); + + result = CompileRun("f.call(proxy)"); + CHECK(result->Equals(env.local(), proxy).FromJust()); + + result = CompileRun("Reflect.apply(f, proxy, [1])"); + CHECK(result->Equals(env.local(), proxy).FromJust()); +} static void SimpleCallback(const v8::FunctionCallbackInfo& info) { ApiTestFuzzer::Fuzz(); From 40c8bbececfed14346c42524bdc23244ccbab4bc Mon Sep 17 00:00:00 2001 From: Eugene Ostroukhov Date: Wed, 16 May 2018 09:43:17 -0700 Subject: [PATCH 31/93] deps: cherry-pick 23652c5f from upstream V8 Original commit message: Custom tag for the traceEvents array This API will be used by Node.js to provide output compatible with Chrome devtools. Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: I265495f8af39bfc78d7fdbe43ac308f0920e817d Reviewed-on: https://chromium-review.googlesource.com/1044491 Reviewed-by: Aleksey Kozyatinskiy Reviewed-by: Ulan Degenbaev Commit-Queue: Eugene Ostroukhov Cr-Commit-Position: refs/heads/master@{#53041} PR-URL: https://github.com/nodejs/node/pull/20608 Reviewed-By: James M Snell Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Matteo Collina --- common.gypi | 2 +- deps/v8/include/libplatform/v8-tracing.h | 2 + .../src/libplatform/tracing/trace-writer.cc | 13 ++- .../v8/src/libplatform/tracing/trace-writer.h | 1 + .../test/cctest/libplatform/test-tracing.cc | 83 +++++++++++-------- 5 files changed, 63 insertions(+), 38 deletions(-) diff --git a/common.gypi b/common.gypi index 04a729e93b7021..dff0f092ebe451 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.3', + 'v8_embedder_string': '-node.4', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/include/libplatform/v8-tracing.h b/deps/v8/include/libplatform/v8-tracing.h index 9dcf3d7bca760a..e430e7c3502741 100644 --- a/deps/v8/include/libplatform/v8-tracing.h +++ b/deps/v8/include/libplatform/v8-tracing.h @@ -112,6 +112,8 @@ class V8_PLATFORM_EXPORT TraceWriter { virtual void Flush() = 0; static TraceWriter* CreateJSONTraceWriter(std::ostream& stream); + static TraceWriter* CreateJSONTraceWriter(std::ostream& stream, + const std::string& tag); private: // Disallow copy and assign diff --git a/deps/v8/src/libplatform/tracing/trace-writer.cc b/deps/v8/src/libplatform/tracing/trace-writer.cc index 36a8783499d140..7bfc7664694f8d 100644 --- a/deps/v8/src/libplatform/tracing/trace-writer.cc +++ b/deps/v8/src/libplatform/tracing/trace-writer.cc @@ -119,8 +119,12 @@ void JSONTraceWriter::AppendArgValue(ConvertableToTraceFormat* value) { stream_ << arg_stringified; } -JSONTraceWriter::JSONTraceWriter(std::ostream& stream) : stream_(stream) { - stream_ << "{\"traceEvents\":["; +JSONTraceWriter::JSONTraceWriter(std::ostream& stream) + : JSONTraceWriter(stream, "traceEvents") {} + +JSONTraceWriter::JSONTraceWriter(std::ostream& stream, const std::string& tag) + : stream_(stream) { + stream_ << "{\"" << tag << "\":["; } JSONTraceWriter::~JSONTraceWriter() { stream_ << "]}"; } @@ -171,6 +175,11 @@ TraceWriter* TraceWriter::CreateJSONTraceWriter(std::ostream& stream) { return new JSONTraceWriter(stream); } +TraceWriter* TraceWriter::CreateJSONTraceWriter(std::ostream& stream, + const std::string& tag) { + return new JSONTraceWriter(stream, tag); +} + } // namespace tracing } // namespace platform } // namespace v8 diff --git a/deps/v8/src/libplatform/tracing/trace-writer.h b/deps/v8/src/libplatform/tracing/trace-writer.h index 7e1bdc24d687ae..d81135138992f7 100644 --- a/deps/v8/src/libplatform/tracing/trace-writer.h +++ b/deps/v8/src/libplatform/tracing/trace-writer.h @@ -14,6 +14,7 @@ namespace tracing { class JSONTraceWriter : public TraceWriter { public: explicit JSONTraceWriter(std::ostream& stream); + JSONTraceWriter(std::ostream& stream, const std::string& tag); ~JSONTraceWriter(); void AppendTraceEvent(TraceObject* trace_event) override; void Flush() override; diff --git a/deps/v8/test/cctest/libplatform/test-tracing.cc b/deps/v8/test/cctest/libplatform/test-tracing.cc index da202057de312c..b949785bcfacbe 100644 --- a/deps/v8/test/cctest/libplatform/test-tracing.cc +++ b/deps/v8/test/cctest/libplatform/test-tracing.cc @@ -128,44 +128,42 @@ TEST(TestTraceBufferRingBuffer) { delete ring_buffer; } -TEST(TestJSONTraceWriter) { - std::ostringstream stream; - // Create a scope for the tracing controller to terminate the trace writer. - { - v8::Platform* old_platform = i::V8::GetCurrentPlatform(); - std::unique_ptr default_platform( - v8::platform::NewDefaultPlatform()); - i::V8::SetPlatformForTesting(default_platform.get()); - auto tracing = - base::make_unique(); - v8::platform::tracing::TracingController* tracing_controller = - tracing.get(); - static_cast(default_platform.get()) - ->SetTracingController(std::move(tracing)); - TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream); +void PopulateJSONWriter(TraceWriter* writer) { + v8::Platform* old_platform = i::V8::GetCurrentPlatform(); + std::unique_ptr default_platform( + v8::platform::NewDefaultPlatform()); + i::V8::SetPlatformForTesting(default_platform.get()); + auto tracing = base::make_unique(); + v8::platform::tracing::TracingController* tracing_controller = tracing.get(); + static_cast(default_platform.get()) + ->SetTracingController(std::move(tracing)); - TraceBuffer* ring_buffer = - TraceBuffer::CreateTraceBufferRingBuffer(1, writer); - tracing_controller->Initialize(ring_buffer); - TraceConfig* trace_config = new TraceConfig(); - trace_config->AddIncludedCategory("v8-cat"); - tracing_controller->StartTracing(trace_config); + TraceBuffer* ring_buffer = + TraceBuffer::CreateTraceBufferRingBuffer(1, writer); + tracing_controller->Initialize(ring_buffer); + TraceConfig* trace_config = new TraceConfig(); + trace_config->AddIncludedCategory("v8-cat"); + tracing_controller->StartTracing(trace_config); - TraceObject trace_object; - trace_object.InitializeForTesting( - 'X', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test0", - v8::internal::tracing::kGlobalScope, 42, 123, 0, nullptr, nullptr, - nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID, 11, 22, 100, 50, 33, 44); - writer->AppendTraceEvent(&trace_object); - trace_object.InitializeForTesting( - 'Y', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test1", - v8::internal::tracing::kGlobalScope, 43, 456, 0, nullptr, nullptr, - nullptr, nullptr, 0, 55, 66, 110, 55, 77, 88); - writer->AppendTraceEvent(&trace_object); - tracing_controller->StopTracing(); - i::V8::SetPlatformForTesting(old_platform); - } + TraceObject trace_object; + trace_object.InitializeForTesting( + 'X', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test0", + v8::internal::tracing::kGlobalScope, 42, 123, 0, nullptr, nullptr, + nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID, 11, 22, 100, 50, 33, 44); + writer->AppendTraceEvent(&trace_object); + trace_object.InitializeForTesting( + 'Y', tracing_controller->GetCategoryGroupEnabled("v8-cat"), "Test1", + v8::internal::tracing::kGlobalScope, 43, 456, 0, nullptr, nullptr, + nullptr, nullptr, 0, 55, 66, 110, 55, 77, 88); + writer->AppendTraceEvent(&trace_object); + tracing_controller->StopTracing(); + i::V8::SetPlatformForTesting(old_platform); +} +TEST(TestJSONTraceWriter) { + std::ostringstream stream; + TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream); + PopulateJSONWriter(writer); std::string trace_str = stream.str(); std::string expected_trace_str = "{\"traceEvents\":[{\"pid\":11,\"tid\":22,\"ts\":100,\"tts\":50," @@ -177,6 +175,21 @@ TEST(TestJSONTraceWriter) { CHECK_EQ(expected_trace_str, trace_str); } +TEST(TestJSONTraceWriterWithCustomtag) { + std::ostringstream stream; + TraceWriter* writer = TraceWriter::CreateJSONTraceWriter(stream, "customTag"); + PopulateJSONWriter(writer); + std::string trace_str = stream.str(); + std::string expected_trace_str = + "{\"customTag\":[{\"pid\":11,\"tid\":22,\"ts\":100,\"tts\":50," + "\"ph\":\"X\",\"cat\":\"v8-cat\",\"name\":\"Test0\",\"dur\":33," + "\"tdur\":44,\"id\":\"0x2a\",\"args\":{}},{\"pid\":55,\"tid\":66," + "\"ts\":110,\"tts\":55,\"ph\":\"Y\",\"cat\":\"v8-cat\",\"name\":" + "\"Test1\",\"dur\":77,\"tdur\":88,\"args\":{}}]}"; + + CHECK_EQ(expected_trace_str, trace_str); +} + TEST(TestTracingController) { v8::Platform* old_platform = i::V8::GetCurrentPlatform(); std::unique_ptr default_platform( From fb2686148e167cd630ba403f9ade40faeea496ae Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 18 May 2018 18:49:41 +0200 Subject: [PATCH 32/93] deps: cherry-pick ff0a9793334 from upstream V8 Original commit message: [api] Expose PreviewEntries as public API Turn `debug::EntriesPreview` into a public API. This is a straightforward approach to addressing nodejs/node#20409 (not relying on functionality behind `--allow-natives-syntax`) in Node.js. Refs: https://github.com/v8/v8/commit/ff0a979333408f544f081489411814b84df6e2d9 PR-URL: https://github.com/nodejs/node/pull/20719 Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Gus Caplan Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater --- common.gypi | 2 +- deps/v8/include/v8.h | 11 +++++++++++ deps/v8/src/api.cc | 19 +++++++++---------- deps/v8/src/debug/debug-interface.h | 4 ---- deps/v8/src/inspector/v8-debugger.cc | 4 +++- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/common.gypi b/common.gypi index dff0f092ebe451..abad5d003c85f4 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.4', + 'v8_embedder_string': '-node.5', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index c6e9250e4e938b..ed1a6d4af1ac02 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -3549,6 +3549,17 @@ class V8_EXPORT Object : public Value { */ Isolate* GetIsolate(); + /** + * If this object is a Set, Map, WeakSet or WeakMap, this returns a + * representation of the elements of this object as an array. + * If this object is a SetIterator or MapIterator, this returns all + * elements of the underlying collection, starting at the iterator's current + * position. + * For other types, this will return an empty MaybeLocal (without + * scheduling an exception). + */ + MaybeLocal PreviewEntries(bool* is_key_value); + static Local New(Isolate* isolate); V8_INLINE static Object* Cast(Value* obj); diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 6dd669ee1133bf..25506d3930868d 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -9635,21 +9635,20 @@ int debug::EstimatedValueSize(Isolate* v8_isolate, v8::Local value) { return i::Handle::cast(object)->Size(); } -v8::MaybeLocal debug::EntriesPreview(Isolate* v8_isolate, - v8::Local value, - bool* is_key_value) { - i::Isolate* isolate = reinterpret_cast(v8_isolate); - ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); - if (value->IsMap()) { +v8::MaybeLocal v8::Object::PreviewEntries(bool* is_key_value) { + if (IsMap()) { *is_key_value = true; - return value.As()->AsArray(); + return Map::Cast(this)->AsArray(); } - if (value->IsSet()) { + if (IsSet()) { *is_key_value = false; - return value.As()->AsArray(); + return Set::Cast(this)->AsArray(); } - i::Handle object = Utils::OpenHandle(*value); + i::Handle object = Utils::OpenHandle(this); + i::Isolate* isolate = object->GetIsolate(); + Isolate* v8_isolate = reinterpret_cast(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); if (object->IsJSWeakCollection()) { *is_key_value = object->IsJSWeakMap(); return Utils::ToLocal(i::JSWeakCollection::GetEntries( diff --git a/deps/v8/src/debug/debug-interface.h b/deps/v8/src/debug/debug-interface.h index b3f3ad917c16f6..ec1a693550237a 100644 --- a/deps/v8/src/debug/debug-interface.h +++ b/deps/v8/src/debug/debug-interface.h @@ -212,10 +212,6 @@ void ResetBlackboxedStateCache(Isolate* isolate, int EstimatedValueSize(Isolate* isolate, v8::Local value); -v8::MaybeLocal EntriesPreview(Isolate* isolate, - v8::Local value, - bool* is_key_value); - enum Builtin { kObjectKeys, kObjectGetPrototypeOf, diff --git a/deps/v8/src/inspector/v8-debugger.cc b/deps/v8/src/inspector/v8-debugger.cc index 1cdbce27e63e0e..01e9acd9c9e6bd 100644 --- a/deps/v8/src/inspector/v8-debugger.cc +++ b/deps/v8/src/inspector/v8-debugger.cc @@ -29,8 +29,10 @@ v8::MaybeLocal collectionsEntries(v8::Local context, v8::Isolate* isolate = context->GetIsolate(); v8::Local entries; bool isKeyValue = false; - if (!v8::debug::EntriesPreview(isolate, value, &isKeyValue).ToLocal(&entries)) + if (!value->IsObject() || + !value.As()->PreviewEntries(&isKeyValue).ToLocal(&entries)) { return v8::MaybeLocal(); + } v8::Local wrappedEntries = v8::Array::New(isolate); CHECK(!isKeyValue || wrappedEntries->Length() % 2 == 0); From 4e788dc2f5113d44508af89cbb6f4b2be91cdc13 Mon Sep 17 00:00:00 2001 From: Maya Lekova Date: Mon, 14 May 2018 10:55:07 +0200 Subject: [PATCH 33/93] deps: backport 91ddb65d from upstream V8 Original commit message: Revert promises optimizations due to regressions in async hooks Revert "[async-await] Eliminate throwaway promise in async functions." This reverts commit a840f1f8f7e6c9ab32dec456a954612619855093. Revert "[async-generators] Also avoid throwaway promise here." This reverts commit feb545ceba5cb477ba883b46b60142f441ad5a3d. Revert "[async-await] Turn await closures into intrinsics." This reverts commit d97bb317386506a6798386b74647cbe0502fce35. Revert "[async-generators] Add fast-path for primitives in AsyncGeneratorYield." This reverts commit e57b500eb26dc595609613963468910eb4bcae2e. Revert "[async-generators] Add fast-path to skip "then" lookup in AsyncGeneratorResolve." This reverts commit c15802e11e30976528d1b711a9b9e6ff6b490117. Revert "[promises] Correctly run before/after hooks for await." This reverts commit ca7639239fc13e992e857710cbf7dbaac87163bf. Bug: v8:7253, v8:7745 Change-Id: I25ad0d2df3cfbc84dbb431aa25b268bce8a39e89 Reviewed-on: https://chromium-review.googlesource.com/1049975 Commit-Queue: Maya Lekova Reviewed-by: Benedikt Meurer Cr-Commit-Position: refs/heads/master@{#53139} Refs: https://github.com/v8/v8/commit/91ddb65d3b34c07c5026727de84dc91b5e0a43cd Fixes: https://github.com/nodejs/node/issues/20516 Co-authored-by: Matteo Collina PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- common.gypi | 2 +- deps/v8/src/bootstrapper.cc | 72 ++++++ .../builtins/builtins-async-function-gen.cc | 96 +++++--- deps/v8/src/builtins/builtins-async-gen.cc | 207 ++++++++++++----- deps/v8/src/builtins/builtins-async-gen.h | 43 +++- .../builtins/builtins-async-generator-gen.cc | 209 ++++++++---------- deps/v8/src/builtins/builtins-definitions.h | 38 ++-- deps/v8/src/builtins/builtins-internal-gen.cc | 38 ++-- deps/v8/src/builtins/builtins-promise-gen.cc | 125 +++++------ deps/v8/src/builtins/builtins-promise-gen.h | 11 +- deps/v8/src/builtins/builtins.cc | 11 +- deps/v8/src/compiler/js-intrinsic-lowering.cc | 35 --- deps/v8/src/compiler/js-intrinsic-lowering.h | 4 - deps/v8/src/contexts.h | 85 ++++--- deps/v8/src/heap-symbols.h | 1 - deps/v8/src/interface-descriptors.h | 8 - deps/v8/src/interpreter/bytecode-generator.cc | 18 +- .../interpreter-intrinsics-generator.cc | 24 -- .../src/interpreter/interpreter-intrinsics.h | 4 - deps/v8/src/isolate.cc | 41 ++-- deps/v8/src/isolate.h | 5 +- deps/v8/src/lookup.cc | 7 - deps/v8/src/objects-debug.cc | 29 +-- deps/v8/src/objects-inl.h | 2 +- deps/v8/src/objects-printer.cc | 6 +- deps/v8/src/objects.cc | 29 +-- deps/v8/src/objects/js-promise.h | 6 - deps/v8/src/objects/promise-inl.h | 6 +- deps/v8/src/objects/promise.h | 26 +-- deps/v8/src/runtime/runtime-generator.cc | 24 -- deps/v8/src/runtime/runtime-promise.cc | 30 ++- deps/v8/src/runtime/runtime.h | 4 - .../AsyncGenerators.golden | 12 +- .../bytecode_expectations/ForAwaitOf.golden | 18 +- .../bytecode_expectations/ForOfLoop.golden | 2 +- .../StandardForLoop.golden | 2 +- deps/v8/test/cctest/test-api.cc | 6 - deps/v8/tools/v8heapconst.py | 14 +- 38 files changed, 688 insertions(+), 612 deletions(-) diff --git a/common.gypi b/common.gypi index abad5d003c85f4..077fd57f507e93 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.5', + 'v8_embedder_string': '-node.6', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index 43c7527de9892a..2138b9c73d7db7 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -1584,6 +1584,50 @@ void Genesis::InitializeGlobal(Handle global_object, native_context()->set_async_iterator_value_unwrap_shared_fun(*info); } + { // --- A s y n c G e n e r a t o r --- + Handle await_caught = + SimpleCreateFunction(isolate, factory->empty_string(), + Builtins::kAsyncGeneratorAwaitCaught, 1, false); + native_context()->set_async_generator_await_caught(*await_caught); + + Handle await_uncaught = + SimpleCreateFunction(isolate, factory->empty_string(), + Builtins::kAsyncGeneratorAwaitUncaught, 1, false); + native_context()->set_async_generator_await_uncaught(*await_uncaught); + + Handle info = SimpleCreateSharedFunctionInfo( + isolate, Builtins::kAsyncGeneratorAwaitResolveClosure, + factory->empty_string(), 1); + native_context()->set_async_generator_await_resolve_shared_fun(*info); + + info = SimpleCreateSharedFunctionInfo( + isolate, Builtins::kAsyncGeneratorAwaitRejectClosure, + factory->empty_string(), 1); + native_context()->set_async_generator_await_reject_shared_fun(*info); + + info = SimpleCreateSharedFunctionInfo( + isolate, Builtins::kAsyncGeneratorYieldResolveClosure, + factory->empty_string(), 1); + native_context()->set_async_generator_yield_resolve_shared_fun(*info); + + info = SimpleCreateSharedFunctionInfo( + isolate, Builtins::kAsyncGeneratorReturnResolveClosure, + factory->empty_string(), 1); + native_context()->set_async_generator_return_resolve_shared_fun(*info); + + info = SimpleCreateSharedFunctionInfo( + isolate, Builtins::kAsyncGeneratorReturnClosedResolveClosure, + factory->empty_string(), 1); + native_context()->set_async_generator_return_closed_resolve_shared_fun( + *info); + + info = SimpleCreateSharedFunctionInfo( + isolate, Builtins::kAsyncGeneratorReturnClosedRejectClosure, + factory->empty_string(), 1); + native_context()->set_async_generator_return_closed_reject_shared_fun( + *info); + } + { // --- A r r a y --- Handle array_function = InstallFunction( global, "Array", JS_ARRAY_TYPE, JSArray::kSize, 0, @@ -3998,6 +4042,34 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate, JSFunction::SetPrototype(async_function_constructor, async_function_prototype); + { + Handle function = + SimpleCreateFunction(isolate, factory->empty_string(), + Builtins::kAsyncFunctionAwaitCaught, 2, false); + native_context->set_async_function_await_caught(*function); + } + + { + Handle function = + SimpleCreateFunction(isolate, factory->empty_string(), + Builtins::kAsyncFunctionAwaitUncaught, 2, false); + native_context->set_async_function_await_uncaught(*function); + } + + { + Handle info = SimpleCreateSharedFunctionInfo( + isolate, Builtins::kAsyncFunctionAwaitRejectClosure, + factory->empty_string(), 1); + native_context->set_async_function_await_reject_shared_fun(*info); + } + + { + Handle info = SimpleCreateSharedFunctionInfo( + isolate, Builtins::kAsyncFunctionAwaitResolveClosure, + factory->empty_string(), 1); + native_context->set_async_function_await_resolve_shared_fun(*info); + } + { Handle function = SimpleCreateFunction(isolate, factory->empty_string(), diff --git a/deps/v8/src/builtins/builtins-async-function-gen.cc b/deps/v8/src/builtins/builtins-async-function-gen.cc index 0db53c687e6210..0d0e34ee0da93a 100644 --- a/deps/v8/src/builtins/builtins-async-function-gen.cc +++ b/deps/v8/src/builtins/builtins-async-function-gen.cc @@ -21,18 +21,37 @@ class AsyncFunctionBuiltinsAssembler : public AsyncBuiltinsAssembler { Node* const awaited, Node* const outer_promise, const bool is_predicted_as_caught); - void AsyncFunctionAwaitResume(Node* const context, Node* const argument, - Node* const generator, - JSGeneratorObject::ResumeMode resume_mode); + void AsyncFunctionAwaitResumeClosure( + Node* const context, Node* const sent_value, + JSGeneratorObject::ResumeMode resume_mode); }; -void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResume( - Node* const context, Node* const argument, Node* const generator, +namespace { + +// Describe fields of Context associated with AsyncFunctionAwait resume +// closures. +// TODO(jgruber): Refactor to reuse code for upcoming async-generators. +class AwaitContext { + public: + enum Fields { kGeneratorSlot = Context::MIN_CONTEXT_SLOTS, kLength }; +}; + +} // anonymous namespace + +void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResumeClosure( + Node* context, Node* sent_value, JSGeneratorObject::ResumeMode resume_mode) { - CSA_ASSERT(this, IsJSGeneratorObject(generator)); DCHECK(resume_mode == JSGeneratorObject::kNext || resume_mode == JSGeneratorObject::kThrow); + Node* const generator = + LoadContextElement(context, AwaitContext::kGeneratorSlot); + CSA_SLOW_ASSERT(this, HasInstanceType(generator, JS_GENERATOR_OBJECT_TYPE)); + + // Inline version of GeneratorPrototypeNext / GeneratorPrototypeReturn with + // unnecessary runtime checks removed. + // TODO(jgruber): Refactor to reuse code from builtins-generator.cc. + // Ensure that the generator is neither closed nor running. CSA_SLOW_ASSERT( this, @@ -47,23 +66,31 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResume( // Resume the {receiver} using our trampoline. Callable callable = CodeFactory::ResumeGenerator(isolate()); - TailCallStub(callable, context, argument, generator); + CallStub(callable, context, sent_value, generator); + + // The resulting Promise is a throwaway, so it doesn't matter what it + // resolves to. What is important is that we don't end up keeping the + // whole chain of intermediate Promises alive by returning the return value + // of ResumeGenerator, as that would create a memory leak. } -TF_BUILTIN(AsyncFunctionAwaitFulfill, AsyncFunctionBuiltinsAssembler) { - Node* const argument = Parameter(Descriptor::kArgument); - Node* const generator = Parameter(Descriptor::kGenerator); +TF_BUILTIN(AsyncFunctionAwaitRejectClosure, AsyncFunctionBuiltinsAssembler) { + CSA_ASSERT_JS_ARGC_EQ(this, 1); + Node* const sentError = Parameter(Descriptor::kSentError); Node* const context = Parameter(Descriptor::kContext); - AsyncFunctionAwaitResume(context, argument, generator, - JSGeneratorObject::kNext); + + AsyncFunctionAwaitResumeClosure(context, sentError, + JSGeneratorObject::kThrow); + Return(UndefinedConstant()); } -TF_BUILTIN(AsyncFunctionAwaitReject, AsyncFunctionBuiltinsAssembler) { - Node* const argument = Parameter(Descriptor::kArgument); - Node* const generator = Parameter(Descriptor::kGenerator); +TF_BUILTIN(AsyncFunctionAwaitResolveClosure, AsyncFunctionBuiltinsAssembler) { + CSA_ASSERT_JS_ARGC_EQ(this, 1); + Node* const sentValue = Parameter(Descriptor::kSentValue); Node* const context = Parameter(Descriptor::kContext); - AsyncFunctionAwaitResume(context, argument, generator, - JSGeneratorObject::kThrow); + + AsyncFunctionAwaitResumeClosure(context, sentValue, JSGeneratorObject::kNext); + Return(UndefinedConstant()); } // ES#abstract-ops-async-function-await @@ -78,12 +105,25 @@ TF_BUILTIN(AsyncFunctionAwaitReject, AsyncFunctionBuiltinsAssembler) { void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait( Node* const context, Node* const generator, Node* const awaited, Node* const outer_promise, const bool is_predicted_as_caught) { - CSA_SLOW_ASSERT(this, IsJSGeneratorObject(generator)); - CSA_SLOW_ASSERT(this, IsJSPromise(outer_promise)); - - Await(context, generator, awaited, outer_promise, - Builtins::kAsyncFunctionAwaitFulfill, - Builtins::kAsyncFunctionAwaitReject, is_predicted_as_caught); + CSA_SLOW_ASSERT(this, HasInstanceType(generator, JS_GENERATOR_OBJECT_TYPE)); + CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE)); + + ContextInitializer init_closure_context = [&](Node* context) { + StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot, + generator); + }; + + // TODO(jgruber): AsyncBuiltinsAssembler::Await currently does not reuse + // the awaited promise if it is already a promise. Reuse is non-spec compliant + // but part of our old behavior gives us a couple of percent + // performance boost. + // TODO(jgruber): Use a faster specialized version of + // InternalPerformPromiseThen. + + Await(context, generator, awaited, outer_promise, AwaitContext::kLength, + init_closure_context, Context::ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN, + Context::ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN, + is_predicted_as_caught); // Return outer promise to avoid adding an load of the outer promise before // suspending in BytecodeGenerator. @@ -93,28 +133,30 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait( // Called by the parser from the desugaring of 'await' when catch // prediction indicates that there is a locally surrounding catch block. TF_BUILTIN(AsyncFunctionAwaitCaught, AsyncFunctionBuiltinsAssembler) { + CSA_ASSERT_JS_ARGC_EQ(this, 3); Node* const generator = Parameter(Descriptor::kGenerator); - Node* const value = Parameter(Descriptor::kValue); + Node* const awaited = Parameter(Descriptor::kAwaited); Node* const outer_promise = Parameter(Descriptor::kOuterPromise); Node* const context = Parameter(Descriptor::kContext); static const bool kIsPredictedAsCaught = true; - AsyncFunctionAwait(context, generator, value, outer_promise, + AsyncFunctionAwait(context, generator, awaited, outer_promise, kIsPredictedAsCaught); } // Called by the parser from the desugaring of 'await' when catch // prediction indicates no locally surrounding catch block. TF_BUILTIN(AsyncFunctionAwaitUncaught, AsyncFunctionBuiltinsAssembler) { + CSA_ASSERT_JS_ARGC_EQ(this, 3); Node* const generator = Parameter(Descriptor::kGenerator); - Node* const value = Parameter(Descriptor::kValue); + Node* const awaited = Parameter(Descriptor::kAwaited); Node* const outer_promise = Parameter(Descriptor::kOuterPromise); Node* const context = Parameter(Descriptor::kContext); static const bool kIsPredictedAsCaught = false; - AsyncFunctionAwait(context, generator, value, outer_promise, + AsyncFunctionAwait(context, generator, awaited, outer_promise, kIsPredictedAsCaught); } diff --git a/deps/v8/src/builtins/builtins-async-gen.cc b/deps/v8/src/builtins/builtins-async-gen.cc index 073c96a2e09948..ba0226d7b3a42a 100644 --- a/deps/v8/src/builtins/builtins-async-gen.cc +++ b/deps/v8/src/builtins/builtins-async-gen.cc @@ -13,58 +13,6 @@ namespace internal { using compiler::Node; -void AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value, - Node* outer_promise, - Builtins::Name fulfill_builtin, - Builtins::Name reject_builtin, - Node* is_predicted_as_caught) { - CSA_SLOW_ASSERT(this, Word32Or(IsJSAsyncGeneratorObject(generator), - IsJSGeneratorObject(generator))); - CSA_SLOW_ASSERT(this, IsJSPromise(outer_promise)); - CSA_SLOW_ASSERT(this, IsBoolean(is_predicted_as_caught)); - - Node* const native_context = LoadNativeContext(context); - - // TODO(bmeurer): This could be optimized and folded into a single allocation. - Node* const promise = AllocateAndInitJSPromise(native_context); - Node* const promise_reactions = - LoadObjectField(promise, JSPromise::kReactionsOrResultOffset); - Node* const fulfill_handler = - HeapConstant(Builtins::CallableFor(isolate(), fulfill_builtin).code()); - Node* const reject_handler = - HeapConstant(Builtins::CallableFor(isolate(), reject_builtin).code()); - Node* const reaction = AllocatePromiseReaction( - promise_reactions, generator, fulfill_handler, reject_handler); - StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, reaction); - PromiseSetHasHandler(promise); - - // Perform ! Call(promiseCapability.[[Resolve]], undefined, « value »). - CallBuiltin(Builtins::kResolvePromise, native_context, promise, value); - - // When debugging, we need to link from the {generator} to the - // {outer_promise} of the async function/generator. - Label done(this); - GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &done); - CallRuntime(Runtime::kSetProperty, native_context, generator, - LoadRoot(Heap::kgenerator_outer_promise_symbolRootIndex), - outer_promise, SmiConstant(LanguageMode::kStrict)); - GotoIf(IsFalse(is_predicted_as_caught), &done); - GotoIf(TaggedIsSmi(value), &done); - GotoIfNot(IsJSPromise(value), &done); - PromiseSetHandledHint(value); - Goto(&done); - BIND(&done); -} - -void AsyncBuiltinsAssembler::Await(Node* context, Node* generator, Node* value, - Node* outer_promise, - Builtins::Name fulfill_builtin, - Builtins::Name reject_builtin, - bool is_predicted_as_caught) { - return Await(context, generator, value, outer_promise, fulfill_builtin, - reject_builtin, BooleanConstant(is_predicted_as_caught)); -} - namespace { // Describe fields of Context associated with the AsyncIterator unwrap closure. class ValueUnwrapContext { @@ -74,6 +22,161 @@ class ValueUnwrapContext { } // namespace +Node* AsyncBuiltinsAssembler::Await( + Node* context, Node* generator, Node* value, Node* outer_promise, + int context_length, const ContextInitializer& init_closure_context, + Node* on_resolve_context_index, Node* on_reject_context_index, + Node* is_predicted_as_caught) { + DCHECK_GE(context_length, Context::MIN_CONTEXT_SLOTS); + + Node* const native_context = LoadNativeContext(context); + + static const int kWrappedPromiseOffset = FixedArray::SizeFor(context_length); + static const int kThrowawayPromiseOffset = + kWrappedPromiseOffset + JSPromise::kSizeWithEmbedderFields; + static const int kResolveClosureOffset = + kThrowawayPromiseOffset + JSPromise::kSizeWithEmbedderFields; + static const int kRejectClosureOffset = + kResolveClosureOffset + JSFunction::kSizeWithoutPrototype; + static const int kTotalSize = + kRejectClosureOffset + JSFunction::kSizeWithoutPrototype; + + Node* const base = AllocateInNewSpace(kTotalSize); + Node* const closure_context = base; + { + // Initialize closure context + InitializeFunctionContext(native_context, closure_context, context_length); + init_closure_context(closure_context); + } + + // Let promiseCapability be ! NewPromiseCapability(%Promise%). + Node* const promise_fun = + LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); + CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun))); + Node* const promise_map = + LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset); + // Assert that the JSPromise map has an instance size is + // JSPromise::kSizeWithEmbedderFields. + CSA_ASSERT(this, WordEqual(LoadMapInstanceSizeInWords(promise_map), + IntPtrConstant(JSPromise::kSizeWithEmbedderFields / + kPointerSize))); + Node* const wrapped_value = InnerAllocate(base, kWrappedPromiseOffset); + { + // Initialize Promise + StoreMapNoWriteBarrier(wrapped_value, promise_map); + InitializeJSObjectFromMap( + wrapped_value, promise_map, + IntPtrConstant(JSPromise::kSizeWithEmbedderFields)); + PromiseInit(wrapped_value); + } + + Node* const throwaway = InnerAllocate(base, kThrowawayPromiseOffset); + { + // Initialize throwawayPromise + StoreMapNoWriteBarrier(throwaway, promise_map); + InitializeJSObjectFromMap( + throwaway, promise_map, + IntPtrConstant(JSPromise::kSizeWithEmbedderFields)); + PromiseInit(throwaway); + } + + Node* const on_resolve = InnerAllocate(base, kResolveClosureOffset); + { + // Initialize resolve handler + InitializeNativeClosure(closure_context, native_context, on_resolve, + on_resolve_context_index); + } + + Node* const on_reject = InnerAllocate(base, kRejectClosureOffset); + { + // Initialize reject handler + InitializeNativeClosure(closure_context, native_context, on_reject, + on_reject_context_index); + } + + { + // Add PromiseHooks if needed + Label next(this); + GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &next); + CallRuntime(Runtime::kPromiseHookInit, context, wrapped_value, + outer_promise); + CallRuntime(Runtime::kPromiseHookInit, context, throwaway, wrapped_value); + Goto(&next); + BIND(&next); + } + + // Perform ! Call(promiseCapability.[[Resolve]], undefined, « promise »). + CallBuiltin(Builtins::kResolvePromise, context, wrapped_value, value); + + // The Promise will be thrown away and not handled, but it shouldn't trigger + // unhandled reject events as its work is done + PromiseSetHasHandler(throwaway); + + Label do_perform_promise_then(this); + GotoIfNot(IsDebugActive(), &do_perform_promise_then); + { + Label common(this); + GotoIf(TaggedIsSmi(value), &common); + GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &common); + { + // Mark the reject handler callback to be a forwarding edge, rather + // than a meaningful catch handler + Node* const key = + HeapConstant(factory()->promise_forwarding_handler_symbol()); + CallRuntime(Runtime::kSetProperty, context, on_reject, key, + TrueConstant(), SmiConstant(LanguageMode::kStrict)); + + GotoIf(IsFalse(is_predicted_as_caught), &common); + PromiseSetHandledHint(value); + } + + Goto(&common); + BIND(&common); + // Mark the dependency to outer Promise in case the throwaway Promise is + // found on the Promise stack + CSA_SLOW_ASSERT(this, HasInstanceType(outer_promise, JS_PROMISE_TYPE)); + + Node* const key = HeapConstant(factory()->promise_handled_by_symbol()); + CallRuntime(Runtime::kSetProperty, context, throwaway, key, outer_promise, + SmiConstant(LanguageMode::kStrict)); + } + + Goto(&do_perform_promise_then); + BIND(&do_perform_promise_then); + return CallBuiltin(Builtins::kPerformPromiseThen, context, wrapped_value, + on_resolve, on_reject, throwaway); +} + +void AsyncBuiltinsAssembler::InitializeNativeClosure(Node* context, + Node* native_context, + Node* function, + Node* context_index) { + Node* const function_map = LoadContextElement( + native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); + // Ensure that we don't have to initialize prototype_or_initial_map field of + // JSFunction. + CSA_ASSERT(this, WordEqual(LoadMapInstanceSizeInWords(function_map), + IntPtrConstant(JSFunction::kSizeWithoutPrototype / + kPointerSize))); + STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize); + StoreMapNoWriteBarrier(function, function_map); + StoreObjectFieldRoot(function, JSObject::kPropertiesOrHashOffset, + Heap::kEmptyFixedArrayRootIndex); + StoreObjectFieldRoot(function, JSObject::kElementsOffset, + Heap::kEmptyFixedArrayRootIndex); + StoreObjectFieldRoot(function, JSFunction::kFeedbackCellOffset, + Heap::kManyClosuresCellRootIndex); + + Node* shared_info = LoadContextElement(native_context, context_index); + CSA_ASSERT(this, IsSharedFunctionInfo(shared_info)); + StoreObjectFieldNoWriteBarrier( + function, JSFunction::kSharedFunctionInfoOffset, shared_info); + StoreObjectFieldNoWriteBarrier(function, JSFunction::kContextOffset, context); + + Node* const code = GetSharedFunctionInfoCode(shared_info); + StoreObjectFieldNoWriteBarrier(function, JSFunction::kCodeOffset, code); +} + Node* AsyncBuiltinsAssembler::CreateUnwrapClosure(Node* native_context, Node* done) { Node* const map = LoadContextElement( diff --git a/deps/v8/src/builtins/builtins-async-gen.h b/deps/v8/src/builtins/builtins-async-gen.h index 70f68a498b7922..45d7c8689a902a 100644 --- a/deps/v8/src/builtins/builtins-async-gen.h +++ b/deps/v8/src/builtins/builtins-async-gen.h @@ -16,23 +16,48 @@ class AsyncBuiltinsAssembler : public PromiseBuiltinsAssembler { : PromiseBuiltinsAssembler(state) {} protected: - void Await(Node* context, Node* generator, Node* value, Node* outer_promise, - Builtins::Name fulfill_builtin, Builtins::Name reject_builtin, - Node* is_predicted_as_caught); - void Await(Node* context, Node* generator, Node* value, Node* outer_promise, - Builtins::Name fulfill_builtin, Builtins::Name reject_builtin, - bool is_predicted_as_caught); + typedef std::function ContextInitializer; + + // Perform steps to resume generator after `value` is resolved. + // `on_reject_context_index` is an index into the Native Context, which should + // point to a SharedFunctioninfo instance used to create the closure. The + // value following the reject index should be a similar value for the resolve + // closure. Returns the Promise-wrapped `value`. + Node* Await(Node* context, Node* generator, Node* value, Node* outer_promise, + int context_length, + const ContextInitializer& init_closure_context, + Node* on_resolve_context_index, Node* on_reject_context_index, + Node* is_predicted_as_caught); + Node* Await(Node* context, Node* generator, Node* value, Node* outer_promise, + int context_length, + const ContextInitializer& init_closure_context, + int on_resolve_context_index, int on_reject_context_index, + Node* is_predicted_as_caught) { + return Await(context, generator, value, outer_promise, context_length, + init_closure_context, IntPtrConstant(on_resolve_context_index), + IntPtrConstant(on_reject_context_index), + is_predicted_as_caught); + } + Node* Await(Node* context, Node* generator, Node* value, Node* outer_promise, + int context_length, + const ContextInitializer& init_closure_context, + int on_resolve_context_index, int on_reject_context_index, + bool is_predicted_as_caught) { + return Await(context, generator, value, outer_promise, context_length, + init_closure_context, on_resolve_context_index, + on_reject_context_index, + BooleanConstant(is_predicted_as_caught)); + } // Return a new built-in function object as defined in // Async Iterator Value Unwrap Functions Node* CreateUnwrapClosure(Node* const native_context, Node* const done); private: + void InitializeNativeClosure(Node* context, Node* native_context, + Node* function, Node* context_index); Node* AllocateAsyncIteratorValueUnwrapContext(Node* native_context, Node* done); - Node* AllocateAwaitPromiseJobTask(Node* generator, Node* fulfill_handler, - Node* reject_handler, Node* promise, - Node* context); }; } // namespace internal diff --git a/deps/v8/src/builtins/builtins-async-generator-gen.cc b/deps/v8/src/builtins/builtins-async-generator-gen.cc index 290252da624940..dd6c644196451f 100644 --- a/deps/v8/src/builtins/builtins-async-generator-gen.cc +++ b/deps/v8/src/builtins/builtins-async-generator-gen.cc @@ -140,8 +140,8 @@ class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler { // for AsyncGenerators. template void AsyncGeneratorAwait(bool is_catchable); - void AsyncGeneratorAwaitResume( - Node* context, Node* generator, Node* argument, + void AsyncGeneratorAwaitResumeClosure( + Node* context, Node* value, JSAsyncGeneratorObject::ResumeMode resume_mode); }; @@ -219,9 +219,11 @@ Node* AsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest( return request; } -void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResume( - Node* context, Node* generator, Node* argument, +void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure( + Node* context, Node* value, JSAsyncGeneratorObject::ResumeMode resume_mode) { + Node* const generator = + LoadContextElement(context, AwaitContext::kGeneratorSlot); CSA_SLOW_ASSERT(this, TaggedIsAsyncGenerator(generator)); SetGeneratorNotAwaiting(generator); @@ -233,30 +235,36 @@ void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResume( JSGeneratorObject::kResumeModeOffset, SmiConstant(resume_mode)); - CallStub(CodeFactory::ResumeGenerator(isolate()), context, argument, - generator); + CallStub(CodeFactory::ResumeGenerator(isolate()), context, value, generator); TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator); } template void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwait(bool is_catchable) { - Node* const generator = Parameter(Descriptor::kGenerator); - Node* const value = Parameter(Descriptor::kValue); - Node* const context = Parameter(Descriptor::kContext); + Node* generator = Parameter(Descriptor::kGenerator); + Node* value = Parameter(Descriptor::kAwaited); + Node* context = Parameter(Descriptor::kContext); CSA_SLOW_ASSERT(this, TaggedIsAsyncGenerator(generator)); Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator); CSA_ASSERT(this, IsNotUndefined(request)); + ContextInitializer init_closure_context = [&](Node* context) { + StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot, + generator); + }; + Node* outer_promise = LoadObjectField(request, AsyncGeneratorRequest::kPromiseOffset); + const int resolve_index = Context::ASYNC_GENERATOR_AWAIT_RESOLVE_SHARED_FUN; + const int reject_index = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN; + SetGeneratorAwaiting(generator); - Await(context, generator, value, outer_promise, - Builtins::kAsyncGeneratorAwaitFulfill, - Builtins::kAsyncGeneratorAwaitReject, is_catchable); + Await(context, generator, value, outer_promise, AwaitContext::kLength, + init_closure_context, resolve_index, reject_index, is_catchable); Return(UndefinedConstant()); } @@ -367,20 +375,18 @@ TF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) { "[AsyncGenerator].prototype.throw"); } -TF_BUILTIN(AsyncGeneratorAwaitFulfill, AsyncGeneratorBuiltinsAssembler) { - Node* const generator = Parameter(Descriptor::kGenerator); - Node* const argument = Parameter(Descriptor::kArgument); - Node* const context = Parameter(Descriptor::kContext); - AsyncGeneratorAwaitResume(context, generator, argument, - JSAsyncGeneratorObject::kNext); +TF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) { + Node* value = Parameter(Descriptor::kValue); + Node* context = Parameter(Descriptor::kContext); + AsyncGeneratorAwaitResumeClosure(context, value, + JSAsyncGeneratorObject::kNext); } -TF_BUILTIN(AsyncGeneratorAwaitReject, AsyncGeneratorBuiltinsAssembler) { - Node* const generator = Parameter(Descriptor::kGenerator); - Node* const argument = Parameter(Descriptor::kArgument); - Node* const context = Parameter(Descriptor::kContext); - AsyncGeneratorAwaitResume(context, generator, argument, - JSAsyncGeneratorObject::kThrow); +TF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) { + Node* value = Parameter(Descriptor::kValue); + Node* context = Parameter(Descriptor::kContext); + AsyncGeneratorAwaitResumeClosure(context, value, + JSAsyncGeneratorObject::kThrow); } TF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) { @@ -518,34 +524,11 @@ TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) { done); } - // We know that {iter_result} itself doesn't have any "then" property and - // we also know that the [[Prototype]] of {iter_result} is the intrinsic - // %ObjectPrototype%. So we can skip the [[Resolve]] logic here completely - // and directly call into the FulfillPromise operation if we can prove - // that the %ObjectPrototype% also doesn't have any "then" property. This - // is guarded by the Promise#then protector. - Label if_fast(this), if_slow(this, Label::kDeferred), return_promise(this); - GotoIfForceSlowPath(&if_slow); - Branch(IsPromiseThenProtectorCellInvalid(), &if_slow, &if_fast); - - BIND(&if_fast); - { - // Skip the "then" on {iter_result} and directly fulfill the {promise} - // with the {iter_result}. - CallBuiltin(Builtins::kFulfillPromise, context, promise, iter_result); - Goto(&return_promise); - } - - BIND(&if_slow); - { - // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»). - CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result); - Goto(&return_promise); - } + // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»). + CallBuiltin(Builtins::kResolvePromise, context, promise, iter_result); // Per spec, AsyncGeneratorResolve() returns undefined. However, for the // benefit of %TraceExit(), return the Promise. - BIND(&return_promise); Return(promise); } @@ -571,54 +554,31 @@ TF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) { Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator); Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(request); - // Mark the generator as "awaiting". - SetGeneratorAwaiting(generator); + ContextInitializer init_closure_context = [&](Node* context) { + StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot, + generator); + }; - // We can skip the creation of a temporary promise and the whole - // [[Resolve]] logic if we already know that the {value} that's - // being yielded is a primitive, as in that case we would immediately - // fulfill the temporary promise anyways and schedule a fulfill - // reaction job. This gives a nice performance boost for async - // generators that yield only primitives, e.g. numbers or strings. - Label if_primitive(this), if_generic(this); - GotoIfForceSlowPath(&if_generic); - GotoIf(IsPromiseHookEnabledOrDebugIsActive(), &if_generic); - GotoIf(TaggedIsSmi(value), &if_primitive); - Branch(IsJSReceiver(value), &if_generic, &if_primitive); - - BIND(&if_generic); - { - Await(context, generator, value, outer_promise, - Builtins::kAsyncGeneratorYieldFulfill, - Builtins::kAsyncGeneratorAwaitReject, is_caught); - Return(UndefinedConstant()); - } + const int on_resolve = Context::ASYNC_GENERATOR_YIELD_RESOLVE_SHARED_FUN; + const int on_reject = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN; - BIND(&if_primitive); - { - // For primitive {value}s we can skip the allocation of the temporary - // promise and the resolution of that, and directly allocate the fulfill - // reaction job. - Node* const microtask = AllocatePromiseReactionJobTask( - Heap::kPromiseFulfillReactionJobTaskMapRootIndex, context, value, - HeapConstant(Builtins::CallableFor( - isolate(), Builtins::kAsyncGeneratorYieldFulfill) - .code()), - generator); - TailCallBuiltin(Builtins::kEnqueueMicrotask, context, microtask); - } + SetGeneratorAwaiting(generator); + Await(context, generator, value, outer_promise, AwaitContext::kLength, + init_closure_context, on_resolve, on_reject, is_caught); + Return(UndefinedConstant()); } -TF_BUILTIN(AsyncGeneratorYieldFulfill, AsyncGeneratorBuiltinsAssembler) { +TF_BUILTIN(AsyncGeneratorYieldResolveClosure, AsyncGeneratorBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); - Node* const generator = Parameter(Descriptor::kGenerator); - Node* const argument = Parameter(Descriptor::kArgument); + Node* const value = Parameter(Descriptor::kValue); + Node* const generator = + LoadContextElement(context, AwaitContext::kGeneratorSlot); SetGeneratorNotAwaiting(generator); // Per proposal-async-iteration/#sec-asyncgeneratoryield step 9 // Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *false*). - CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, argument, + CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, value, FalseConstant()); TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator); @@ -644,33 +604,39 @@ TF_BUILTIN(AsyncGeneratorReturn, AsyncGeneratorBuiltinsAssembler) { Node* const generator = Parameter(Descriptor::kGenerator); Node* const value = Parameter(Descriptor::kValue); Node* const is_caught = Parameter(Descriptor::kIsCaught); - Node* const context = Parameter(Descriptor::kContext); Node* const req = LoadFirstAsyncGeneratorRequestFromQueue(generator); - Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(req); CSA_ASSERT(this, IsNotUndefined(req)); - Label if_closed(this, Label::kDeferred), if_not_closed(this), done(this); + Label perform_await(this); + VARIABLE(var_on_resolve, MachineType::PointerRepresentation(), + IntPtrConstant( + Context::ASYNC_GENERATOR_RETURN_CLOSED_RESOLVE_SHARED_FUN)); + VARIABLE( + var_on_reject, MachineType::PointerRepresentation(), + IntPtrConstant(Context::ASYNC_GENERATOR_RETURN_CLOSED_REJECT_SHARED_FUN)); + Node* const state = LoadGeneratorState(generator); - SetGeneratorAwaiting(generator); - Branch(IsGeneratorStateClosed(state), &if_closed, &if_not_closed); + GotoIf(IsGeneratorStateClosed(state), &perform_await); + var_on_resolve.Bind( + IntPtrConstant(Context::ASYNC_GENERATOR_RETURN_RESOLVE_SHARED_FUN)); + var_on_reject.Bind( + IntPtrConstant(Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN)); + Goto(&perform_await); - BIND(&if_closed); - { - Await(context, generator, value, outer_promise, - Builtins::kAsyncGeneratorReturnClosedFulfill, - Builtins::kAsyncGeneratorReturnClosedReject, is_caught); - Goto(&done); - } + BIND(&perform_await); - BIND(&if_not_closed); - { - Await(context, generator, value, outer_promise, - Builtins::kAsyncGeneratorReturnFulfill, - Builtins::kAsyncGeneratorAwaitReject, is_caught); - Goto(&done); - } + ContextInitializer init_closure_context = [&](Node* context) { + StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot, + generator); + }; + + SetGeneratorAwaiting(generator); + Node* const context = Parameter(Descriptor::kContext); + Node* const outer_promise = LoadPromiseFromAsyncGeneratorRequest(req); + Await(context, generator, value, outer_promise, AwaitContext::kLength, + init_closure_context, var_on_resolve.value(), var_on_reject.value(), + is_caught); - BIND(&done); Return(UndefinedConstant()); } @@ -678,44 +644,47 @@ TF_BUILTIN(AsyncGeneratorReturn, AsyncGeneratorBuiltinsAssembler) { // Resume the generator with "return" resume_mode, and finally perform // AsyncGeneratorResumeNext. Per // proposal-async-iteration/#sec-asyncgeneratoryield step 8.e -TF_BUILTIN(AsyncGeneratorReturnFulfill, AsyncGeneratorBuiltinsAssembler) { - Node* const generator = Parameter(Descriptor::kGenerator); - Node* const argument = Parameter(Descriptor::kArgument); +TF_BUILTIN(AsyncGeneratorReturnResolveClosure, + AsyncGeneratorBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); - AsyncGeneratorAwaitResume(context, generator, argument, - JSGeneratorObject::kReturn); + Node* const value = Parameter(Descriptor::kValue); + AsyncGeneratorAwaitResumeClosure(context, value, JSGeneratorObject::kReturn); } // On-resolve closure for Await in AsyncGeneratorReturn // Perform AsyncGeneratorResolve({awaited_value}, true) and finally perform // AsyncGeneratorResumeNext. -TF_BUILTIN(AsyncGeneratorReturnClosedFulfill, AsyncGeneratorBuiltinsAssembler) { - Node* const generator = Parameter(Descriptor::kGenerator); - Node* const argument = Parameter(Descriptor::kArgument); +TF_BUILTIN(AsyncGeneratorReturnClosedResolveClosure, + AsyncGeneratorBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); + Node* const value = Parameter(Descriptor::kValue); + Node* const generator = + LoadContextElement(context, AwaitContext::kGeneratorSlot); SetGeneratorNotAwaiting(generator); // https://tc39.github.io/proposal-async-iteration/ // #async-generator-resume-next-return-processor-fulfilled step 2: // Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *true*). - CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, argument, + CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator, value, TrueConstant()); TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator); } -TF_BUILTIN(AsyncGeneratorReturnClosedReject, AsyncGeneratorBuiltinsAssembler) { - Node* const generator = Parameter(Descriptor::kGenerator); - Node* const argument = Parameter(Descriptor::kArgument); +TF_BUILTIN(AsyncGeneratorReturnClosedRejectClosure, + AsyncGeneratorBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); + Node* const value = Parameter(Descriptor::kValue); + Node* const generator = + LoadContextElement(context, AwaitContext::kGeneratorSlot); SetGeneratorNotAwaiting(generator); // https://tc39.github.io/proposal-async-iteration/ // #async-generator-resume-next-return-processor-rejected step 2: // Return ! AsyncGeneratorReject(_F_.[[Generator]], _reason_). - CallBuiltin(Builtins::kAsyncGeneratorReject, context, generator, argument); + CallBuiltin(Builtins::kAsyncGeneratorReject, context, generator, value); TailCallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator); } diff --git a/deps/v8/src/builtins/builtins-definitions.h b/deps/v8/src/builtins/builtins-definitions.h index 0f60dfd97e8888..5f06abeceb0d76 100644 --- a/deps/v8/src/builtins/builtins-definitions.h +++ b/deps/v8/src/builtins/builtins-definitions.h @@ -381,10 +381,10 @@ namespace internal { CPP(ArrayBufferPrototypeSlice) \ \ /* AsyncFunction */ \ - TFC(AsyncFunctionAwaitFulfill, PromiseReactionHandler, 1) \ - TFC(AsyncFunctionAwaitReject, PromiseReactionHandler, 1) \ - TFS(AsyncFunctionAwaitCaught, kGenerator, kValue, kOuterPromise) \ - TFS(AsyncFunctionAwaitUncaught, kGenerator, kValue, kOuterPromise) \ + TFJ(AsyncFunctionAwaitCaught, 3, kGenerator, kAwaited, kOuterPromise) \ + TFJ(AsyncFunctionAwaitUncaught, 3, kGenerator, kAwaited, kOuterPromise) \ + TFJ(AsyncFunctionAwaitRejectClosure, 1, kSentError) \ + TFJ(AsyncFunctionAwaitResolveClosure, 1, kSentValue) \ TFJ(AsyncFunctionPromiseCreate, 0) \ TFJ(AsyncFunctionPromiseRelease, 1, kPromise) \ \ @@ -838,8 +838,8 @@ namespace internal { /* ES #sec-promise.prototype.catch */ \ TFJ(PromisePrototypeCatch, 1, kOnRejected) \ /* ES #sec-promisereactionjob */ \ - TFS(PromiseRejectReactionJob, kReason, kHandler, kPayload) \ - TFS(PromiseFulfillReactionJob, kValue, kHandler, kPayload) \ + TFS(PromiseRejectReactionJob, kReason, kHandler, kPromiseOrCapability) \ + TFS(PromiseFulfillReactionJob, kValue, kHandler, kPromiseOrCapability) \ /* ES #sec-promiseresolvethenablejob */ \ TFS(PromiseResolveThenableJob, kPromiseToResolve, kThenable, kThen) \ /* ES #sec-promise.resolve */ \ @@ -1203,17 +1203,6 @@ namespace internal { \ /* AsyncGenerator */ \ \ - /* Await (proposal-async-iteration/#await), with resume behaviour */ \ - /* specific to Async Generators. Internal / Not exposed to JS code. */ \ - TFS(AsyncGeneratorAwaitCaught, kGenerator, kValue) \ - TFS(AsyncGeneratorAwaitUncaught, kGenerator, kValue) \ - TFC(AsyncGeneratorAwaitFulfill, PromiseReactionHandler, 1) \ - TFC(AsyncGeneratorAwaitReject, PromiseReactionHandler, 1) \ - TFC(AsyncGeneratorYieldFulfill, PromiseReactionHandler, 1) \ - TFC(AsyncGeneratorReturnClosedFulfill, PromiseReactionHandler, 1) \ - TFC(AsyncGeneratorReturnClosedReject, PromiseReactionHandler, 1) \ - TFC(AsyncGeneratorReturnFulfill, PromiseReactionHandler, 1) \ - \ TFS(AsyncGeneratorResolve, kGenerator, kValue, kDone) \ TFS(AsyncGeneratorReject, kGenerator, kValue) \ TFS(AsyncGeneratorYield, kGenerator, kValue, kIsCaught) \ @@ -1236,6 +1225,17 @@ namespace internal { TFJ(AsyncGeneratorPrototypeThrow, \ SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ \ + /* Await (proposal-async-iteration/#await), with resume behaviour */ \ + /* specific to Async Generators. Internal / Not exposed to JS code. */ \ + TFJ(AsyncGeneratorAwaitCaught, 2, kGenerator, kAwaited) \ + TFJ(AsyncGeneratorAwaitUncaught, 2, kGenerator, kAwaited) \ + TFJ(AsyncGeneratorAwaitResolveClosure, 1, kValue) \ + TFJ(AsyncGeneratorAwaitRejectClosure, 1, kValue) \ + TFJ(AsyncGeneratorYieldResolveClosure, 1, kValue) \ + TFJ(AsyncGeneratorReturnClosedResolveClosure, 1, kValue) \ + TFJ(AsyncGeneratorReturnClosedRejectClosure, 1, kValue) \ + TFJ(AsyncGeneratorReturnResolveClosure, 1, kValue) \ + \ /* Async-from-Sync Iterator */ \ \ /* %AsyncFromSyncIteratorPrototype% */ \ @@ -1284,7 +1284,11 @@ namespace internal { V(AsyncFromSyncIteratorPrototypeNext) \ V(AsyncFromSyncIteratorPrototypeReturn) \ V(AsyncFromSyncIteratorPrototypeThrow) \ + V(AsyncFunctionAwaitCaught) \ + V(AsyncFunctionAwaitUncaught) \ V(AsyncGeneratorResolve) \ + V(AsyncGeneratorAwaitCaught) \ + V(AsyncGeneratorAwaitUncaught) \ V(PromiseAll) \ V(PromiseConstructor) \ V(PromiseConstructorLazyDeoptContinuation) \ diff --git a/deps/v8/src/builtins/builtins-internal-gen.cc b/deps/v8/src/builtins/builtins-internal-gen.cc index e1f4aea4052549..4e533ad1c4c503 100644 --- a/deps/v8/src/builtins/builtins-internal-gen.cc +++ b/deps/v8/src/builtins/builtins-internal-gen.cc @@ -669,7 +669,7 @@ class InternalBuiltinsAssembler : public CodeStubAssembler { void LeaveMicrotaskContext(); void RunPromiseHook(Runtime::FunctionId id, TNode context, - SloppyTNode payload); + SloppyTNode promise_or_capability); TNode GetPendingException() { auto ref = ExternalReference(kPendingExceptionAddress, isolate()); @@ -790,12 +790,20 @@ void InternalBuiltinsAssembler::LeaveMicrotaskContext() { void InternalBuiltinsAssembler::RunPromiseHook( Runtime::FunctionId id, TNode context, - SloppyTNode payload) { + SloppyTNode promise_or_capability) { Label hook(this, Label::kDeferred), done_hook(this); Branch(IsPromiseHookEnabledOrDebugIsActive(), &hook, &done_hook); BIND(&hook); { - CallRuntime(id, context, payload); + // Get to the underlying JSPromise instance. + Node* const promise = Select( + IsJSPromise(promise_or_capability), + [=] { return promise_or_capability; }, + [=] { + return CAST(LoadObjectField(promise_or_capability, + PromiseCapability::kPromiseOffset)); + }); + CallRuntime(id, context, promise); Goto(&done_hook); } BIND(&done_hook); @@ -1008,19 +1016,21 @@ TF_BUILTIN(RunMicrotasks, InternalBuiltinsAssembler) { LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset); Node* const handler = LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset); - Node* const payload = - LoadObjectField(microtask, PromiseReactionJobTask::kPayloadOffset); + Node* const promise_or_capability = LoadObjectField( + microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset); // Run the promise before/debug hook if enabled. - RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, payload); + RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, + promise_or_capability); Node* const result = CallBuiltin(Builtins::kPromiseFulfillReactionJob, microtask_context, - argument, handler, payload); + argument, handler, promise_or_capability); GotoIfException(result, &if_exception, &var_exception); // Run the promise after/debug hook if enabled. - RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, payload); + RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, + promise_or_capability); LeaveMicrotaskContext(); SetCurrentContext(current_context); @@ -1041,19 +1051,21 @@ TF_BUILTIN(RunMicrotasks, InternalBuiltinsAssembler) { LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset); Node* const handler = LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset); - Node* const payload = - LoadObjectField(microtask, PromiseReactionJobTask::kPayloadOffset); + Node* const promise_or_capability = LoadObjectField( + microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset); // Run the promise before/debug hook if enabled. - RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, payload); + RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, + promise_or_capability); Node* const result = CallBuiltin(Builtins::kPromiseRejectReactionJob, microtask_context, - argument, handler, payload); + argument, handler, promise_or_capability); GotoIfException(result, &if_exception, &var_exception); // Run the promise after/debug hook if enabled. - RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, payload); + RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, + promise_or_capability); LeaveMicrotaskContext(); SetCurrentContext(current_context); diff --git a/deps/v8/src/builtins/builtins-promise-gen.cc b/deps/v8/src/builtins/builtins-promise-gen.cc index dd38dbc5435cab..868b45a8316ff5 100644 --- a/deps/v8/src/builtins/builtins-promise-gen.cc +++ b/deps/v8/src/builtins/builtins-promise-gen.cc @@ -391,15 +391,15 @@ TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) { Return(result_promise); } -Node* PromiseBuiltinsAssembler::AllocatePromiseReaction(Node* next, - Node* payload, - Node* fulfill_handler, - Node* reject_handler) { +Node* PromiseBuiltinsAssembler::AllocatePromiseReaction( + Node* next, Node* promise_or_capability, Node* fulfill_handler, + Node* reject_handler) { Node* const reaction = Allocate(PromiseReaction::kSize); StoreMapNoWriteBarrier(reaction, Heap::kPromiseReactionMapRootIndex); StoreObjectFieldNoWriteBarrier(reaction, PromiseReaction::kNextOffset, next); - StoreObjectFieldNoWriteBarrier(reaction, PromiseReaction::kPayloadOffset, - payload); + StoreObjectFieldNoWriteBarrier(reaction, + PromiseReaction::kPromiseOrCapabilityOffset, + promise_or_capability); StoreObjectFieldNoWriteBarrier( reaction, PromiseReaction::kFulfillHandlerOffset, fulfill_handler); StoreObjectFieldNoWriteBarrier( @@ -408,7 +408,8 @@ Node* PromiseBuiltinsAssembler::AllocatePromiseReaction(Node* next, } Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask( - Node* map, Node* context, Node* argument, Node* handler, Node* payload) { + Node* map, Node* context, Node* argument, Node* handler, + Node* promise_or_capability) { Node* const microtask = Allocate(PromiseReactionJobTask::kSize); StoreMapNoWriteBarrier(microtask, map); StoreObjectFieldNoWriteBarrier( @@ -418,18 +419,19 @@ Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask( StoreObjectFieldNoWriteBarrier( microtask, PromiseReactionJobTask::kHandlerOffset, handler); StoreObjectFieldNoWriteBarrier( - microtask, PromiseReactionJobTask::kPayloadOffset, payload); + microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset, + promise_or_capability); return microtask; } Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask( Heap::RootListIndex map_root_index, Node* context, Node* argument, - Node* handler, Node* payload) { + Node* handler, Node* promise_or_capability) { DCHECK(map_root_index == Heap::kPromiseFulfillReactionJobTaskMapRootIndex || map_root_index == Heap::kPromiseRejectReactionJobTaskMapRootIndex); Node* const map = LoadRoot(map_root_index); return AllocatePromiseReactionJobTask(map, context, argument, handler, - payload); + promise_or_capability); } Node* PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobTask( @@ -502,8 +504,8 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( context); STATIC_ASSERT(PromiseReaction::kFulfillHandlerOffset == PromiseReactionJobTask::kHandlerOffset); - STATIC_ASSERT(PromiseReaction::kPayloadOffset == - PromiseReactionJobTask::kPayloadOffset); + STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset == + PromiseReactionJobTask::kPromiseOrCapabilityOffset); } else { Node* handler = LoadObjectField(current, PromiseReaction::kRejectHandlerOffset); @@ -515,8 +517,8 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( context); StoreObjectField(current, PromiseReactionJobTask::kHandlerOffset, handler); - STATIC_ASSERT(PromiseReaction::kPayloadOffset == - PromiseReactionJobTask::kPayloadOffset); + STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset == + PromiseReactionJobTask::kPromiseOrCapabilityOffset); } CallBuiltin(Builtins::kEnqueueMicrotask, NoContextConstant(), current); Goto(&loop); @@ -1118,28 +1120,20 @@ TF_BUILTIN(PromiseResolveThenableJob, PromiseBuiltinsAssembler) { // ES #sec-promisereactionjob void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument, - Node* handler, Node* payload, + Node* handler, + Node* promise_or_capability, PromiseReaction::Type type) { CSA_ASSERT(this, TaggedIsNotSmi(handler)); - CSA_ASSERT(this, Word32Or(IsCallable(handler), - Word32Or(IsCode(handler), IsUndefined(handler)))); - CSA_ASSERT(this, TaggedIsNotSmi(payload)); + CSA_ASSERT(this, Word32Or(IsUndefined(handler), IsCallable(handler))); + CSA_ASSERT(this, TaggedIsNotSmi(promise_or_capability)); + CSA_ASSERT(this, Word32Or(IsJSPromise(promise_or_capability), + IsPromiseCapability(promise_or_capability))); VARIABLE(var_handler_result, MachineRepresentation::kTagged, argument); - Label if_handler_callable(this), if_fulfill(this), if_reject(this), - if_code_handler(this); - - GotoIf(IsUndefined(handler), - type == PromiseReaction::kFulfill ? &if_fulfill : &if_reject); - Branch(IsCode(handler), &if_code_handler, &if_handler_callable); - - BIND(&if_code_handler); - { - // The {handler} is a Code object that knows how to deal with - // the {payload} and the {argument}. - PromiseReactionHandlerDescriptor descriptor(isolate()); - TailCallStub(descriptor, handler, context, argument, payload); - } + Label if_handler_callable(this), if_fulfill(this), if_reject(this); + Branch(IsUndefined(handler), + type == PromiseReaction::kFulfill ? &if_fulfill : &if_reject, + &if_handler_callable); BIND(&if_handler_callable); { @@ -1155,22 +1149,24 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument, { Label if_promise(this), if_promise_capability(this, Label::kDeferred); Node* const value = var_handler_result.value(); - Branch(IsPromiseCapability(payload), &if_promise_capability, &if_promise); + Branch(IsPromiseCapability(promise_or_capability), &if_promise_capability, + &if_promise); BIND(&if_promise); { // For fast native promises we can skip the indirection // via the promiseCapability.[[Resolve]] function and // run the resolve logic directly from here. - TailCallBuiltin(Builtins::kResolvePromise, context, payload, value); + TailCallBuiltin(Builtins::kResolvePromise, context, promise_or_capability, + value); } BIND(&if_promise_capability); { // In the general case we need to call the (user provided) // promiseCapability.[[Resolve]] function. - Node* const resolve = - LoadObjectField(payload, PromiseCapability::kResolveOffset); + Node* const resolve = LoadObjectField(promise_or_capability, + PromiseCapability::kResolveOffset); Node* const result = CallJS( CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), context, resolve, UndefinedConstant(), value); @@ -1183,15 +1179,16 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument, if (type == PromiseReaction::kReject) { Label if_promise(this), if_promise_capability(this, Label::kDeferred); Node* const reason = var_handler_result.value(); - Branch(IsPromiseCapability(payload), &if_promise_capability, &if_promise); + Branch(IsPromiseCapability(promise_or_capability), &if_promise_capability, + &if_promise); BIND(&if_promise); { // For fast native promises we can skip the indirection // via the promiseCapability.[[Reject]] function and // run the resolve logic directly from here. - TailCallBuiltin(Builtins::kRejectPromise, context, payload, reason, - FalseConstant()); + TailCallBuiltin(Builtins::kRejectPromise, context, promise_or_capability, + reason, FalseConstant()); } BIND(&if_promise_capability); @@ -1201,8 +1198,8 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument, Label if_exception(this, Label::kDeferred); VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant()); - Node* const reject = - LoadObjectField(payload, PromiseCapability::kRejectOffset); + Node* const reject = LoadObjectField(promise_or_capability, + PromiseCapability::kRejectOffset); Node* const result = CallJS( CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), context, reject, UndefinedConstant(), reason); @@ -1219,7 +1216,8 @@ void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument, // predictions in the debugger will be wrong, which just walks the stack // and checks for certain builtins. TailCallBuiltin(Builtins::kPromiseRejectReactionJob, context, - var_handler_result.value(), UndefinedConstant(), payload); + var_handler_result.value(), UndefinedConstant(), + promise_or_capability); } } @@ -1228,9 +1226,10 @@ TF_BUILTIN(PromiseFulfillReactionJob, PromiseBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); Node* const value = Parameter(Descriptor::kValue); Node* const handler = Parameter(Descriptor::kHandler); - Node* const payload = Parameter(Descriptor::kPayload); + Node* const promise_or_capability = + Parameter(Descriptor::kPromiseOrCapability); - PromiseReactionJob(context, value, handler, payload, + PromiseReactionJob(context, value, handler, promise_or_capability, PromiseReaction::kFulfill); } @@ -1239,9 +1238,10 @@ TF_BUILTIN(PromiseRejectReactionJob, PromiseBuiltinsAssembler) { Node* const context = Parameter(Descriptor::kContext); Node* const reason = Parameter(Descriptor::kReason); Node* const handler = Parameter(Descriptor::kHandler); - Node* const payload = Parameter(Descriptor::kPayload); + Node* const promise_or_capability = + Parameter(Descriptor::kPromiseOrCapability); - PromiseReactionJob(context, reason, handler, payload, + PromiseReactionJob(context, reason, handler, promise_or_capability, PromiseReaction::kReject); } @@ -1717,23 +1717,21 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { // 7. If Type(resolution) is not Object, then GotoIf(TaggedIsSmi(resolution), &if_fulfill); - Node* const resolution_map = LoadMap(resolution); - GotoIfNot(IsJSReceiverMap(resolution_map), &if_fulfill); + Node* const result_map = LoadMap(resolution); + GotoIfNot(IsJSReceiverMap(result_map), &if_fulfill); // We can skip the "then" lookup on {resolution} if its [[Prototype]] // is the (initial) Promise.prototype and the Promise#then protector // is intact, as that guards the lookup path for the "then" property // on JSPromise instances which have the (initial) %PromisePrototype%. - Label if_fast(this), if_generic(this), if_slow(this, Label::kDeferred); + Label if_fast(this), if_slow(this, Label::kDeferred); Node* const native_context = LoadNativeContext(context); - GotoIfForceSlowPath(&if_slow); - GotoIf(IsPromiseThenProtectorCellInvalid(), &if_slow); - GotoIfNot(IsJSPromiseMap(resolution_map), &if_generic); - Node* const promise_prototype = - LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX); - Branch(WordEqual(LoadMapPrototype(resolution_map), promise_prototype), - &if_fast, &if_slow); + BranchIfPromiseThenLookupChainIntact(native_context, result_map, &if_fast, + &if_slow); + // Resolution is a native promise and if it's already resolved or + // rejected, shortcircuit the resolution procedure by directly + // reusing the value from the promise. BIND(&if_fast); { Node* const then = @@ -1742,21 +1740,6 @@ TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) { Goto(&do_enqueue); } - BIND(&if_generic); - { - // We can skip the lookup of "then" if the {resolution} is a (newly - // created) IterResultObject, as the Promise#then protector also - // ensures that the intrinsic %ObjectPrototype% doesn't contain any - // "then" property. This helps to avoid negative lookups on iterator - // results from async generators. - CSA_ASSERT(this, IsJSReceiverMap(resolution_map)); - CSA_ASSERT(this, Word32BinaryNot(IsPromiseThenProtectorCellInvalid())); - Node* const iterator_result_map = - LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX); - Branch(WordEqual(resolution_map, iterator_result_map), &if_fulfill, - &if_slow); - } - BIND(&if_slow); { // 8. Let then be Get(resolution, "then"). diff --git a/deps/v8/src/builtins/builtins-promise-gen.h b/deps/v8/src/builtins/builtins-promise-gen.h index f21d86a141a28d..694cea28c06b5a 100644 --- a/deps/v8/src/builtins/builtins-promise-gen.h +++ b/deps/v8/src/builtins/builtins-promise-gen.h @@ -85,14 +85,16 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler { Node* AllocateAndSetJSPromise(Node* context, v8::Promise::PromiseState status, Node* result); - Node* AllocatePromiseReaction(Node* next, Node* payload, + Node* AllocatePromiseReaction(Node* next, Node* promise_or_capability, Node* fulfill_handler, Node* reject_handler); Node* AllocatePromiseReactionJobTask(Heap::RootListIndex map_root_index, Node* context, Node* argument, - Node* handler, Node* payload); + Node* handler, + Node* promise_or_capability); Node* AllocatePromiseReactionJobTask(Node* map, Node* context, Node* argument, - Node* handler, Node* payload); + Node* handler, + Node* promise_or_capability); Node* AllocatePromiseResolveThenableJobTask(Node* promise_to_resolve, Node* then, Node* thenable, Node* context); @@ -192,7 +194,8 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler { Node* PromiseStatus(Node* promise); void PromiseReactionJob(Node* context, Node* argument, Node* handler, - Node* payload, PromiseReaction::Type type); + Node* promise_or_capability, + PromiseReaction::Type type); Node* IsPromiseStatus(Node* actual, v8::Promise::PromiseState expected); void PromiseSetStatus(Node* promise, v8::Promise::PromiseState status); diff --git a/deps/v8/src/builtins/builtins.cc b/deps/v8/src/builtins/builtins.cc index c348248fffb0d9..7e6a0459a7da90 100644 --- a/deps/v8/src/builtins/builtins.cc +++ b/deps/v8/src/builtins/builtins.cc @@ -364,17 +364,12 @@ bool Builtins::IsIsolateIndependent(int index) { case kAsyncFromSyncIteratorPrototypeNext: case kAsyncFromSyncIteratorPrototypeReturn: case kAsyncFromSyncIteratorPrototypeThrow: - case kAsyncFunctionAwaitFulfill: - case kAsyncFunctionAwaitReject: + case kAsyncFunctionAwaitCaught: case kAsyncFunctionPromiseCreate: case kAsyncFunctionPromiseRelease: - case kAsyncGeneratorAwaitFulfill: - case kAsyncGeneratorAwaitReject: case kAsyncGeneratorResumeNext: - case kAsyncGeneratorReturnClosedFulfill: - case kAsyncGeneratorReturnClosedReject: - case kAsyncGeneratorReturnFulfill: - case kAsyncGeneratorYieldFulfill: + case kAsyncGeneratorReturnClosedRejectClosure: + case kAsyncGeneratorReturn: case kAsyncIteratorValueUnwrap: case kBitwiseNot: case kBooleanPrototypeToString: diff --git a/deps/v8/src/compiler/js-intrinsic-lowering.cc b/deps/v8/src/compiler/js-intrinsic-lowering.cc index c570a1f8ddce3f..d9742e47d9fd2f 100644 --- a/deps/v8/src/compiler/js-intrinsic-lowering.cc +++ b/deps/v8/src/compiler/js-intrinsic-lowering.cc @@ -41,14 +41,6 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) { return ReduceCreateJSGeneratorObject(node); case Runtime::kInlineGeneratorGetInputOrDebugPos: return ReduceGeneratorGetInputOrDebugPos(node); - case Runtime::kInlineAsyncFunctionAwaitCaught: - return ReduceAsyncFunctionAwaitCaught(node); - case Runtime::kInlineAsyncFunctionAwaitUncaught: - return ReduceAsyncFunctionAwaitUncaught(node); - case Runtime::kInlineAsyncGeneratorAwaitCaught: - return ReduceAsyncGeneratorAwaitCaught(node); - case Runtime::kInlineAsyncGeneratorAwaitUncaught: - return ReduceAsyncGeneratorAwaitUncaught(node); case Runtime::kInlineAsyncGeneratorReject: return ReduceAsyncGeneratorReject(node); case Runtime::kInlineAsyncGeneratorResolve: @@ -185,33 +177,6 @@ Reduction JSIntrinsicLowering::ReduceGeneratorGetInputOrDebugPos(Node* node) { return Change(node, op, generator, effect, control); } -Reduction JSIntrinsicLowering::ReduceAsyncFunctionAwaitCaught(Node* node) { - return Change( - node, - Builtins::CallableFor(isolate(), Builtins::kAsyncFunctionAwaitCaught), 0); -} - -Reduction JSIntrinsicLowering::ReduceAsyncFunctionAwaitUncaught(Node* node) { - return Change( - node, - Builtins::CallableFor(isolate(), Builtins::kAsyncFunctionAwaitUncaught), - 0); -} - -Reduction JSIntrinsicLowering::ReduceAsyncGeneratorAwaitCaught(Node* node) { - return Change( - node, - Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorAwaitCaught), - 0); -} - -Reduction JSIntrinsicLowering::ReduceAsyncGeneratorAwaitUncaught(Node* node) { - return Change( - node, - Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorAwaitUncaught), - 0); -} - Reduction JSIntrinsicLowering::ReduceAsyncGeneratorReject(Node* node) { return Change( node, Builtins::CallableFor(isolate(), Builtins::kAsyncGeneratorReject), diff --git a/deps/v8/src/compiler/js-intrinsic-lowering.h b/deps/v8/src/compiler/js-intrinsic-lowering.h index fb745986a60155..18fe1248c7aa52 100644 --- a/deps/v8/src/compiler/js-intrinsic-lowering.h +++ b/deps/v8/src/compiler/js-intrinsic-lowering.h @@ -45,10 +45,6 @@ class V8_EXPORT_PRIVATE JSIntrinsicLowering final Reduction ReduceCreateJSGeneratorObject(Node* node); Reduction ReduceGeneratorClose(Node* node); Reduction ReduceGeneratorGetInputOrDebugPos(Node* node); - Reduction ReduceAsyncFunctionAwaitCaught(Node* node); - Reduction ReduceAsyncFunctionAwaitUncaught(Node* node); - Reduction ReduceAsyncGeneratorAwaitCaught(Node* node); - Reduction ReduceAsyncGeneratorAwaitUncaught(Node* node); Reduction ReduceAsyncGeneratorReject(Node* node); Reduction ReduceAsyncGeneratorResolve(Node* node); Reduction ReduceAsyncGeneratorYield(Node* node); diff --git a/deps/v8/src/contexts.h b/deps/v8/src/contexts.h index 6fc6f2d1c32ca5..fcfeccdc44e08f 100644 --- a/deps/v8/src/contexts.h +++ b/deps/v8/src/contexts.h @@ -32,37 +32,44 @@ enum ContextLookupFlags { // must always be allocated via Heap::AllocateContext() or // Factory::NewContext. -#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \ - V(ASYNC_FUNCTION_PROMISE_CREATE_INDEX, JSFunction, \ - async_function_promise_create) \ - V(ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, JSFunction, \ - async_function_promise_release) \ - V(IS_ARRAYLIKE, JSFunction, is_arraylike) \ - V(GENERATOR_NEXT_INTERNAL, JSFunction, generator_next_internal) \ - V(MAKE_ERROR_INDEX, JSFunction, make_error) \ - V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error) \ - V(MAKE_SYNTAX_ERROR_INDEX, JSFunction, make_syntax_error) \ - V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error) \ - V(MAKE_URI_ERROR_INDEX, JSFunction, make_uri_error) \ - V(OBJECT_CREATE, JSFunction, object_create) \ - V(OBJECT_DEFINE_PROPERTIES, JSFunction, object_define_properties) \ - V(OBJECT_DEFINE_PROPERTY, JSFunction, object_define_property) \ - V(OBJECT_GET_PROTOTYPE_OF, JSFunction, object_get_prototype_of) \ - V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible) \ - V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen) \ - V(OBJECT_IS_SEALED, JSFunction, object_is_sealed) \ - V(OBJECT_KEYS, JSFunction, object_keys) \ - V(REGEXP_INTERNAL_MATCH, JSFunction, regexp_internal_match) \ - V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply) \ - V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \ - V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \ - V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \ - V(MATH_FLOOR_INDEX, JSFunction, math_floor) \ - V(MATH_POW_INDEX, JSFunction, math_pow) \ - V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \ - promise_internal_constructor) \ - V(IS_PROMISE_INDEX, JSFunction, is_promise) \ - V(PROMISE_THEN_INDEX, JSFunction, promise_then) +#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \ + V(ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX, JSFunction, \ + async_function_await_caught) \ + V(ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX, JSFunction, \ + async_function_await_uncaught) \ + V(ASYNC_FUNCTION_PROMISE_CREATE_INDEX, JSFunction, \ + async_function_promise_create) \ + V(ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, JSFunction, \ + async_function_promise_release) \ + V(IS_ARRAYLIKE, JSFunction, is_arraylike) \ + V(GENERATOR_NEXT_INTERNAL, JSFunction, generator_next_internal) \ + V(MAKE_ERROR_INDEX, JSFunction, make_error) \ + V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error) \ + V(MAKE_SYNTAX_ERROR_INDEX, JSFunction, make_syntax_error) \ + V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error) \ + V(MAKE_URI_ERROR_INDEX, JSFunction, make_uri_error) \ + V(OBJECT_CREATE, JSFunction, object_create) \ + V(OBJECT_DEFINE_PROPERTIES, JSFunction, object_define_properties) \ + V(OBJECT_DEFINE_PROPERTY, JSFunction, object_define_property) \ + V(OBJECT_GET_PROTOTYPE_OF, JSFunction, object_get_prototype_of) \ + V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible) \ + V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen) \ + V(OBJECT_IS_SEALED, JSFunction, object_is_sealed) \ + V(OBJECT_KEYS, JSFunction, object_keys) \ + V(REGEXP_INTERNAL_MATCH, JSFunction, regexp_internal_match) \ + V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply) \ + V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \ + V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \ + V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \ + V(MATH_FLOOR_INDEX, JSFunction, math_floor) \ + V(MATH_POW_INDEX, JSFunction, math_pow) \ + V(NEW_PROMISE_CAPABILITY_INDEX, JSFunction, new_promise_capability) \ + V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \ + promise_internal_constructor) \ + V(IS_PROMISE_INDEX, JSFunction, is_promise) \ + V(PROMISE_THEN_INDEX, JSFunction, promise_then) \ + V(ASYNC_GENERATOR_AWAIT_CAUGHT, JSFunction, async_generator_await_caught) \ + V(ASYNC_GENERATOR_AWAIT_UNCAUGHT, JSFunction, async_generator_await_uncaught) #define NATIVE_CONTEXT_IMPORTED_FIELDS(V) \ V(ARRAY_POP_INDEX, JSFunction, array_pop) \ @@ -116,11 +123,27 @@ enum ContextLookupFlags { V(ARRAY_BUFFER_NOINIT_FUN_INDEX, JSFunction, array_buffer_noinit_fun) \ V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \ V(ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX, Map, async_from_sync_iterator_map) \ + V(ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN, SharedFunctionInfo, \ + async_function_await_reject_shared_fun) \ + V(ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN, SharedFunctionInfo, \ + async_function_await_resolve_shared_fun) \ V(ASYNC_FUNCTION_FUNCTION_INDEX, JSFunction, async_function_constructor) \ V(ASYNC_GENERATOR_FUNCTION_FUNCTION_INDEX, JSFunction, \ async_generator_function_function) \ V(ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN, SharedFunctionInfo, \ async_iterator_value_unwrap_shared_fun) \ + V(ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN, SharedFunctionInfo, \ + async_generator_await_reject_shared_fun) \ + V(ASYNC_GENERATOR_AWAIT_RESOLVE_SHARED_FUN, SharedFunctionInfo, \ + async_generator_await_resolve_shared_fun) \ + V(ASYNC_GENERATOR_YIELD_RESOLVE_SHARED_FUN, SharedFunctionInfo, \ + async_generator_yield_resolve_shared_fun) \ + V(ASYNC_GENERATOR_RETURN_RESOLVE_SHARED_FUN, SharedFunctionInfo, \ + async_generator_return_resolve_shared_fun) \ + V(ASYNC_GENERATOR_RETURN_CLOSED_RESOLVE_SHARED_FUN, SharedFunctionInfo, \ + async_generator_return_closed_resolve_shared_fun) \ + V(ASYNC_GENERATOR_RETURN_CLOSED_REJECT_SHARED_FUN, SharedFunctionInfo, \ + async_generator_return_closed_reject_shared_fun) \ V(ATOMICS_OBJECT, JSObject, atomics_object) \ V(BIGINT_FUNCTION_INDEX, JSFunction, bigint_function) \ V(BIGINT64_ARRAY_FUN_INDEX, JSFunction, bigint64_array_fun) \ diff --git a/deps/v8/src/heap-symbols.h b/deps/v8/src/heap-symbols.h index 82ecd7665750ff..c15aa9ba1380db 100644 --- a/deps/v8/src/heap-symbols.h +++ b/deps/v8/src/heap-symbols.h @@ -237,7 +237,6 @@ V(error_script_symbol) \ V(error_start_pos_symbol) \ V(frozen_symbol) \ - V(generator_outer_promise_symbol) \ V(generic_symbol) \ V(home_object_symbol) \ V(intl_initialized_marker_symbol) \ diff --git a/deps/v8/src/interface-descriptors.h b/deps/v8/src/interface-descriptors.h index 61da0c3f4ea45a..8375ea11971ac4 100644 --- a/deps/v8/src/interface-descriptors.h +++ b/deps/v8/src/interface-descriptors.h @@ -81,7 +81,6 @@ class PlatformInterfaceDescriptor; V(FrameDropperTrampoline) \ V(WasmRuntimeCall) \ V(RunMicrotasks) \ - V(PromiseReactionHandler) \ BUILTIN_LIST_TFS(V) class V8_EXPORT_PRIVATE CallInterfaceDescriptorData { @@ -889,13 +888,6 @@ class RunMicrotasksDescriptor final : public CallInterfaceDescriptor { 0) }; -class PromiseReactionHandlerDescriptor final : public CallInterfaceDescriptor { - public: - DEFINE_PARAMETERS(kArgument, kGenerator) - DECLARE_DEFAULT_DESCRIPTOR(PromiseReactionHandlerDescriptor, - CallInterfaceDescriptor, 2) -}; - #define DEFINE_TFS_BUILTIN_DESCRIPTOR(Name, ...) \ class Name##Descriptor : public CallInterfaceDescriptor { \ public: \ diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc index 29ad2c2a82f033..744c6614f7a2ec 100644 --- a/deps/v8/src/interpreter/bytecode-generator.cc +++ b/deps/v8/src/interpreter/bytecode-generator.cc @@ -3239,20 +3239,22 @@ void BytecodeGenerator::BuildAwait(Expression* await_expr) { // Await(operand) and suspend. RegisterAllocationScope register_scope(this); - Runtime::FunctionId id; + int await_builtin_context_index; RegisterList args; if (IsAsyncGeneratorFunction(function_kind())) { - id = catch_prediction() == HandlerTable::ASYNC_AWAIT - ? Runtime::kInlineAsyncGeneratorAwaitUncaught - : Runtime::kInlineAsyncGeneratorAwaitCaught; + await_builtin_context_index = + catch_prediction() == HandlerTable::ASYNC_AWAIT + ? Context::ASYNC_GENERATOR_AWAIT_UNCAUGHT + : Context::ASYNC_GENERATOR_AWAIT_CAUGHT; args = register_allocator()->NewRegisterList(2); builder() ->MoveRegister(generator_object(), args[0]) .StoreAccumulatorInRegister(args[1]); } else { - id = catch_prediction() == HandlerTable::ASYNC_AWAIT - ? Runtime::kInlineAsyncFunctionAwaitUncaught - : Runtime::kInlineAsyncFunctionAwaitCaught; + await_builtin_context_index = + catch_prediction() == HandlerTable::ASYNC_AWAIT + ? Context::ASYNC_FUNCTION_AWAIT_UNCAUGHT_INDEX + : Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX; args = register_allocator()->NewRegisterList(3); builder() ->MoveRegister(generator_object(), args[0]) @@ -3265,7 +3267,7 @@ void BytecodeGenerator::BuildAwait(Expression* await_expr) { builder()->StoreAccumulatorInRegister(args[2]); } - builder()->CallRuntime(id, args); + builder()->CallJSRuntime(await_builtin_context_index, args); } BuildSuspendPoint(await_expr); diff --git a/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc b/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc index 675a8bcccc7c0a..0480dec6cc6516 100644 --- a/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc +++ b/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc @@ -402,30 +402,6 @@ Node* IntrinsicsGenerator::GetImportMetaObject( return return_value.value(); } -Node* IntrinsicsGenerator::AsyncFunctionAwaitCaught( - const InterpreterAssembler::RegListNodePair& args, Node* context) { - return IntrinsicAsBuiltinCall(args, context, - Builtins::kAsyncFunctionAwaitCaught); -} - -Node* IntrinsicsGenerator::AsyncFunctionAwaitUncaught( - const InterpreterAssembler::RegListNodePair& args, Node* context) { - return IntrinsicAsBuiltinCall(args, context, - Builtins::kAsyncFunctionAwaitUncaught); -} - -Node* IntrinsicsGenerator::AsyncGeneratorAwaitCaught( - const InterpreterAssembler::RegListNodePair& args, Node* context) { - return IntrinsicAsBuiltinCall(args, context, - Builtins::kAsyncGeneratorAwaitCaught); -} - -Node* IntrinsicsGenerator::AsyncGeneratorAwaitUncaught( - const InterpreterAssembler::RegListNodePair& args, Node* context) { - return IntrinsicAsBuiltinCall(args, context, - Builtins::kAsyncGeneratorAwaitUncaught); -} - Node* IntrinsicsGenerator::AsyncGeneratorReject( const InterpreterAssembler::RegListNodePair& args, Node* context) { return IntrinsicAsBuiltinCall(args, context, Builtins::kAsyncGeneratorReject); diff --git a/deps/v8/src/interpreter/interpreter-intrinsics.h b/deps/v8/src/interpreter/interpreter-intrinsics.h index 6cdfec2d04f1fb..3016183c0b96d7 100644 --- a/deps/v8/src/interpreter/interpreter-intrinsics.h +++ b/deps/v8/src/interpreter/interpreter-intrinsics.h @@ -14,10 +14,6 @@ namespace interpreter { // List of supported intrisics, with upper case name, lower case name and // expected number of arguments (-1 denoting argument count is variable). #define INTRINSICS_LIST(V) \ - V(AsyncFunctionAwaitCaught, async_function_await_caught, 3) \ - V(AsyncFunctionAwaitUncaught, async_function_await_uncaught, 3) \ - V(AsyncGeneratorAwaitCaught, async_generator_await_caught, 2) \ - V(AsyncGeneratorAwaitUncaught, async_generator_await_uncaught, 2) \ V(AsyncGeneratorReject, async_generator_reject, 2) \ V(AsyncGeneratorResolve, async_generator_resolve, 3) \ V(AsyncGeneratorYield, async_generator_yield, 3) \ diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index adb30b12acece3..2c4e22726d7301 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -2048,7 +2048,6 @@ void Isolate::PopPromise() { } namespace { - bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate, Handle promise); @@ -2095,27 +2094,29 @@ bool InternalPromiseHasUserDefinedRejectHandler(Isolate* isolate, } if (promise->status() == Promise::kPending) { - Handle current(promise->reactions(), isolate); - while (!current->IsSmi()) { - Handle current_reaction = - Handle::cast(current); - Handle payload(current_reaction->payload(), isolate); - Handle current_promise; - if (JSPromise::From(payload).ToHandle(¤t_promise)) { - if (current_reaction->reject_handler()->IsCallable()) { - Handle current_handler( - JSReceiver::cast(current_reaction->reject_handler()), isolate); - if (PromiseHandlerCheck(isolate, current_handler, current_promise)) { - return true; - } - } else { - if (InternalPromiseHasUserDefinedRejectHandler(isolate, - current_promise)) { - return true; - } + for (Handle current(promise->reactions(), isolate); + !current->IsSmi();) { + Handle reaction = Handle::cast(current); + Handle promise_or_capability( + reaction->promise_or_capability(), isolate); + Handle promise = Handle::cast( + promise_or_capability->IsJSPromise() + ? promise_or_capability + : handle(Handle::cast(promise_or_capability) + ->promise(), + isolate)); + if (reaction->reject_handler()->IsUndefined(isolate)) { + if (InternalPromiseHasUserDefinedRejectHandler(isolate, promise)) { + return true; + } + } else { + Handle current_handler( + JSReceiver::cast(reaction->reject_handler()), isolate); + if (PromiseHandlerCheck(isolate, current_handler, promise)) { + return true; } } - current = handle(current_reaction->next(), isolate); + current = handle(reaction->next(), isolate); } } diff --git a/deps/v8/src/isolate.h b/deps/v8/src/isolate.h index 75b447f1629bb5..82d33033737c36 100644 --- a/deps/v8/src/isolate.h +++ b/deps/v8/src/isolate.h @@ -1096,10 +1096,7 @@ class Isolate { bool IsPromiseResolveLookupChainIntact(); // Make sure a lookup of "then" on any JSPromise whose [[Prototype]] is the - // initial %PromisePrototype% yields the initial method. In addition this - // protector also guards the negative lookup of "then" on the intrinsic - // %ObjectPrototype%, meaning that such lookups are guaranteed to yield - // undefined without triggering any side-effects. + // initial %PromisePrototype% yields the initial method. bool IsPromiseThenLookupChainIntact(); bool IsPromiseThenLookupChainIntact(Handle receiver); diff --git a/deps/v8/src/lookup.cc b/deps/v8/src/lookup.cc index 205011499470ca..a4cca33d6c3e8a 100644 --- a/deps/v8/src/lookup.cc +++ b/deps/v8/src/lookup.cc @@ -364,14 +364,7 @@ void LookupIterator::InternalUpdateProtector() { if (!isolate_->IsPromiseThenLookupChainIntact()) return; // Setting the "then" property on any JSPromise instance or on the // initial %PromisePrototype% invalidates the Promise#then protector. - // Also setting the "then" property on the initial %ObjectPrototype% - // invalidates the Promise#then protector, since we use this protector - // to guard the fast-path in AsyncGeneratorResolve, where we can skip - // the ResolvePromise step and go directly to FulfillPromise if we - // know that the Object.prototype doesn't contain a "then" method. if (holder_->IsJSPromise() || - isolate_->IsInAnyContext(*holder_, - Context::INITIAL_OBJECT_PROTOTYPE_INDEX) || isolate_->IsInAnyContext(*holder_, Context::PROMISE_PROTOTYPE_INDEX)) { isolate_->InvalidatePromiseThenProtector(); } diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc index c735cc0813caaa..086078bb251dc4 100644 --- a/deps/v8/src/objects-debug.cc +++ b/deps/v8/src/objects-debug.cc @@ -1172,13 +1172,10 @@ void PromiseReactionJobTask::PromiseReactionJobTaskVerify() { VerifyHeapPointer(context()); CHECK(context()->IsContext()); VerifyHeapPointer(handler()); - VerifyHeapPointer(payload()); - if (handler()->IsCode()) { - CHECK(payload()->IsJSReceiver()); - } else { - CHECK(handler()->IsUndefined(isolate) || handler()->IsCallable()); - CHECK(payload()->IsJSPromise() || payload()->IsPromiseCapability()); - } + CHECK(handler()->IsUndefined(isolate) || handler()->IsCallable()); + VerifyHeapPointer(promise_or_capability()); + CHECK(promise_or_capability()->IsJSPromise() || + promise_or_capability()->IsPromiseCapability()); } void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskVerify() { @@ -1220,18 +1217,14 @@ void PromiseReaction::PromiseReactionVerify() { VerifyPointer(next()); CHECK(next()->IsSmi() || next()->IsPromiseReaction()); VerifyHeapPointer(reject_handler()); + CHECK(reject_handler()->IsUndefined(isolate) || + reject_handler()->IsCallable()); VerifyHeapPointer(fulfill_handler()); - VerifyHeapPointer(payload()); - if (reject_handler()->IsCode()) { - CHECK(fulfill_handler()->IsCode()); - CHECK(payload()->IsJSReceiver()); - } else { - CHECK(reject_handler()->IsUndefined(isolate) || - reject_handler()->IsCallable()); - CHECK(fulfill_handler()->IsUndefined(isolate) || - fulfill_handler()->IsCallable()); - CHECK(payload()->IsJSPromise() || payload()->IsPromiseCapability()); - } + CHECK(fulfill_handler()->IsUndefined(isolate) || + fulfill_handler()->IsCallable()); + VerifyHeapPointer(promise_or_capability()); + CHECK(promise_or_capability()->IsJSPromise() || + promise_or_capability()->IsPromiseCapability()); } void JSPromise::JSPromiseVerify() { diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index bda031e0637776..297e9fc836d490 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -2278,7 +2278,7 @@ ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) ACCESSORS(AccessorInfo, name, Name, kNameOffset) SMI_ACCESSORS(AccessorInfo, flags, kFlagsOffset) ACCESSORS(AccessorInfo, expected_receiver_type, Object, - kExpectedReceiverTypeOffset) + kExpectedReceiverTypeOffset) ACCESSORS_CHECKED2(AccessorInfo, getter, Object, kGetterOffset, true, Foreign::IsNormalized(value)) diff --git a/deps/v8/src/objects-printer.cc b/deps/v8/src/objects-printer.cc index 942b9de0ba2779..8d20279b2f1f20 100644 --- a/deps/v8/src/objects-printer.cc +++ b/deps/v8/src/objects-printer.cc @@ -1441,7 +1441,7 @@ void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskPrint( os << "\n - argument: " << Brief(argument()); os << "\n - context: " << Brief(context()); os << "\n - handler: " << Brief(handler()); - os << "\n - payload: " << Brief(payload()); + os << "\n - promise_or_capability: " << Brief(promise_or_capability()); os << "\n"; } @@ -1451,7 +1451,7 @@ void PromiseRejectReactionJobTask::PromiseRejectReactionJobTaskPrint( os << "\n - argument: " << Brief(argument()); os << "\n - context: " << Brief(context()); os << "\n - handler: " << Brief(handler()); - os << "\n - payload: " << Brief(payload()); + os << "\n - promise_or_capability: " << Brief(promise_or_capability()); os << "\n"; } @@ -1478,7 +1478,7 @@ void PromiseReaction::PromiseReactionPrint(std::ostream& os) { // NOLINT os << "\n - next: " << Brief(next()); os << "\n - reject_handler: " << Brief(reject_handler()); os << "\n - fulfill_handler: " << Brief(fulfill_handler()); - os << "\n - payload: " << Brief(payload()); + os << "\n - promise_or_capability: " << Brief(promise_or_capability()); os << "\n"; } diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 8057cb837b186d..6565910fd3faea 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -16054,27 +16054,6 @@ MaybeHandle JSPromise::Resolve(Handle promise, return isolate->factory()->undefined_value(); } -// static -MaybeHandle JSPromise::From(Handle object) { - Isolate* const isolate = object->GetIsolate(); - if (object->IsJSPromise()) { - return Handle::cast(object); - } else if (object->IsPromiseCapability()) { - Handle capability = - Handle::cast(object); - if (capability->promise()->IsJSPromise()) { - return handle(JSPromise::cast(capability->promise()), isolate); - } - } else if (object->IsJSGeneratorObject()) { - Handle generator = - Handle::cast(object); - Handle handled_by = JSObject::GetDataProperty( - generator, isolate->factory()->generator_outer_promise_symbol()); - if (handled_by->IsJSPromise()) return Handle::cast(handled_by); - } - return MaybeHandle(); -} - // static Handle JSPromise::TriggerPromiseReactions(Isolate* isolate, Handle reactions, @@ -16114,8 +16093,8 @@ Handle JSPromise::TriggerPromiseReactions(Isolate* isolate, *isolate->native_context()); STATIC_ASSERT(PromiseReaction::kFulfillHandlerOffset == PromiseFulfillReactionJobTask::kHandlerOffset); - STATIC_ASSERT(PromiseReaction::kPayloadOffset == - PromiseFulfillReactionJobTask::kPayloadOffset); + STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset == + PromiseFulfillReactionJobTask::kPromiseOrCapabilityOffset); } else { DisallowHeapAllocation no_gc; HeapObject* handler = reaction->reject_handler(); @@ -16125,8 +16104,8 @@ Handle JSPromise::TriggerPromiseReactions(Isolate* isolate, Handle::cast(task)->set_context( *isolate->native_context()); Handle::cast(task)->set_handler(handler); - STATIC_ASSERT(PromiseReaction::kPayloadOffset == - PromiseRejectReactionJobTask::kPayloadOffset); + STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset == + PromiseRejectReactionJobTask::kPromiseOrCapabilityOffset); } isolate->EnqueueMicrotask(Handle::cast(task)); diff --git a/deps/v8/src/objects/js-promise.h b/deps/v8/src/objects/js-promise.h index 20a0a90131a06f..434bae893380d5 100644 --- a/deps/v8/src/objects/js-promise.h +++ b/deps/v8/src/objects/js-promise.h @@ -59,12 +59,6 @@ class JSPromise : public JSObject { V8_WARN_UNUSED_RESULT static MaybeHandle Resolve( Handle promise, Handle resolution); - // This is a helper that extracts the JSPromise from the input - // {object}, which is used as a payload for PromiseReaction and - // PromiseReactionJobTask. - V8_WARN_UNUSED_RESULT static MaybeHandle From( - Handle object); - DECL_CAST(JSPromise) // Dispatched behavior. diff --git a/deps/v8/src/objects/promise-inl.h b/deps/v8/src/objects/promise-inl.h index 4283f0aa19483e..f9fb6110f346c1 100644 --- a/deps/v8/src/objects/promise-inl.h +++ b/deps/v8/src/objects/promise-inl.h @@ -23,7 +23,8 @@ CAST_ACCESSOR(PromiseResolveThenableJobTask) ACCESSORS(PromiseReaction, next, Object, kNextOffset) ACCESSORS(PromiseReaction, reject_handler, HeapObject, kRejectHandlerOffset) ACCESSORS(PromiseReaction, fulfill_handler, HeapObject, kFulfillHandlerOffset) -ACCESSORS(PromiseReaction, payload, HeapObject, kPayloadOffset) +ACCESSORS(PromiseReaction, promise_or_capability, HeapObject, + kPromiseOrCapabilityOffset) ACCESSORS(PromiseResolveThenableJobTask, context, Context, kContextOffset) ACCESSORS(PromiseResolveThenableJobTask, promise_to_resolve, JSPromise, @@ -34,7 +35,8 @@ ACCESSORS(PromiseResolveThenableJobTask, thenable, JSReceiver, kThenableOffset) ACCESSORS(PromiseReactionJobTask, context, Context, kContextOffset) ACCESSORS(PromiseReactionJobTask, argument, Object, kArgumentOffset); ACCESSORS(PromiseReactionJobTask, handler, HeapObject, kHandlerOffset); -ACCESSORS(PromiseReactionJobTask, payload, HeapObject, kPayloadOffset); +ACCESSORS(PromiseReactionJobTask, promise_or_capability, HeapObject, + kPromiseOrCapabilityOffset); ACCESSORS(PromiseCapability, promise, HeapObject, kPromiseOffset) ACCESSORS(PromiseCapability, resolve, Object, kResolveOffset) diff --git a/deps/v8/src/objects/promise.h b/deps/v8/src/objects/promise.h index 36ef4afe1d6e68..5ff5dac6f372ea 100644 --- a/deps/v8/src/objects/promise.h +++ b/deps/v8/src/objects/promise.h @@ -26,16 +26,15 @@ class PromiseReactionJobTask : public Microtask { public: DECL_ACCESSORS(argument, Object) DECL_ACCESSORS(context, Context) - // [handler]: This is either a Code object, a Callable or Undefined. DECL_ACCESSORS(handler, HeapObject) - // [payload]: Usually a JSPromise or a PromiseCapability. - DECL_ACCESSORS(payload, HeapObject) + // [promise_or_capability]: Either a JSPromise or a PromiseCapability. + DECL_ACCESSORS(promise_or_capability, HeapObject) static const int kArgumentOffset = Microtask::kHeaderSize; static const int kContextOffset = kArgumentOffset + kPointerSize; static const int kHandlerOffset = kContextOffset + kPointerSize; - static const int kPayloadOffset = kHandlerOffset + kPointerSize; - static const int kSize = kPayloadOffset + kPointerSize; + static const int kPromiseOrCapabilityOffset = kHandlerOffset + kPointerSize; + static const int kSize = kPromiseOrCapabilityOffset + kPointerSize; // Dispatched behavior. DECL_CAST(PromiseReactionJobTask) @@ -121,10 +120,9 @@ class PromiseCapability : public Struct { // of microtasks. So the size of PromiseReaction and the size of the // PromiseReactionJobTask has to be same for this to work. // -// The PromiseReaction::payload field usually holds a JSPromise -// instance (in the fast case of a native promise) or a PromiseCapability -// in case of a custom promise. For await we store the JSGeneratorObject -// here and use custom Code handlers. +// The PromiseReaction::promise_or_capability field can either hold a JSPromise +// instance (in the fast case of a native promise) or a PromiseCapability in +// case of a Promise subclass. // // We need to keep the context in the PromiseReaction so that we can run // the default handlers (in case they are undefined) in the proper context. @@ -138,18 +136,16 @@ class PromiseReaction : public Struct { enum Type { kFulfill, kReject }; DECL_ACCESSORS(next, Object) - // [reject_handler]: This is either a Code object, a Callable or Undefined. DECL_ACCESSORS(reject_handler, HeapObject) - // [fulfill_handler]: This is either a Code object, a Callable or Undefined. DECL_ACCESSORS(fulfill_handler, HeapObject) - // [payload]: Usually a JSPromise or a PromiseCapability. - DECL_ACCESSORS(payload, HeapObject) + DECL_ACCESSORS(promise_or_capability, HeapObject) static const int kNextOffset = Struct::kHeaderSize; static const int kRejectHandlerOffset = kNextOffset + kPointerSize; static const int kFulfillHandlerOffset = kRejectHandlerOffset + kPointerSize; - static const int kPayloadOffset = kFulfillHandlerOffset + kPointerSize; - static const int kSize = kPayloadOffset + kPointerSize; + static const int kPromiseOrCapabilityOffset = + kFulfillHandlerOffset + kPointerSize; + static const int kSize = kPromiseOrCapabilityOffset + kPointerSize; // Dispatched behavior. DECL_CAST(PromiseReaction) diff --git a/deps/v8/src/runtime/runtime-generator.cc b/deps/v8/src/runtime/runtime-generator.cc index e69d334042681c..3c7c808c30b66a 100644 --- a/deps/v8/src/runtime/runtime-generator.cc +++ b/deps/v8/src/runtime/runtime-generator.cc @@ -70,30 +70,6 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetInputOrDebugPos) { UNREACHABLE(); } -RUNTIME_FUNCTION(Runtime_AsyncFunctionAwaitCaught) { - // Runtime call is implemented in InterpreterIntrinsics and lowered in - // JSIntrinsicLowering - UNREACHABLE(); -} - -RUNTIME_FUNCTION(Runtime_AsyncFunctionAwaitUncaught) { - // Runtime call is implemented in InterpreterIntrinsics and lowered in - // JSIntrinsicLowering - UNREACHABLE(); -} - -RUNTIME_FUNCTION(Runtime_AsyncGeneratorAwaitCaught) { - // Runtime call is implemented in InterpreterIntrinsics and lowered in - // JSIntrinsicLowering - UNREACHABLE(); -} - -RUNTIME_FUNCTION(Runtime_AsyncGeneratorAwaitUncaught) { - // Runtime call is implemented in InterpreterIntrinsics and lowered in - // JSIntrinsicLowering - UNREACHABLE(); -} - RUNTIME_FUNCTION(Runtime_AsyncGeneratorResolve) { // Runtime call is implemented in InterpreterIntrinsics and lowered in // JSIntrinsicLowering diff --git a/deps/v8/src/runtime/runtime-promise.cc b/deps/v8/src/runtime/runtime-promise.cc index b2a7e8bae1b701..f5b9db3c028b0e 100644 --- a/deps/v8/src/runtime/runtime-promise.cc +++ b/deps/v8/src/runtime/runtime-promise.cc @@ -114,14 +114,13 @@ RUNTIME_FUNCTION(Runtime_PromiseHookInit) { RUNTIME_FUNCTION(Runtime_PromiseHookBefore) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); - CONVERT_ARG_HANDLE_CHECKED(HeapObject, payload, 0); - Handle promise; - if (JSPromise::From(payload).ToHandle(&promise)) { - if (isolate->debug()->is_active()) isolate->PushPromise(promise); - if (promise->IsJSPromise()) { - isolate->RunPromiseHook(PromiseHookType::kBefore, promise, - isolate->factory()->undefined_value()); - } + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0); + if (!maybe_promise->IsJSPromise()) return isolate->heap()->undefined_value(); + Handle promise = Handle::cast(maybe_promise); + if (isolate->debug()->is_active()) isolate->PushPromise(promise); + if (promise->IsJSPromise()) { + isolate->RunPromiseHook(PromiseHookType::kBefore, promise, + isolate->factory()->undefined_value()); } return isolate->heap()->undefined_value(); } @@ -129,14 +128,13 @@ RUNTIME_FUNCTION(Runtime_PromiseHookBefore) { RUNTIME_FUNCTION(Runtime_PromiseHookAfter) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); - CONVERT_ARG_HANDLE_CHECKED(HeapObject, payload, 0); - Handle promise; - if (JSPromise::From(payload).ToHandle(&promise)) { - if (isolate->debug()->is_active()) isolate->PopPromise(); - if (promise->IsJSPromise()) { - isolate->RunPromiseHook(PromiseHookType::kAfter, promise, - isolate->factory()->undefined_value()); - } + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, maybe_promise, 0); + if (!maybe_promise->IsJSPromise()) return isolate->heap()->undefined_value(); + Handle promise = Handle::cast(maybe_promise); + if (isolate->debug()->is_active()) isolate->PopPromise(); + if (promise->IsJSPromise()) { + isolate->RunPromiseHook(PromiseHookType::kAfter, promise, + isolate->factory()->undefined_value()); } return isolate->heap()->undefined_value(); } diff --git a/deps/v8/src/runtime/runtime.h b/deps/v8/src/runtime/runtime.h index 48a63d500da527..37ce74e8250f2c 100644 --- a/deps/v8/src/runtime/runtime.h +++ b/deps/v8/src/runtime/runtime.h @@ -222,10 +222,6 @@ namespace internal { F(SetNativeFlag, 1, 1) #define FOR_EACH_INTRINSIC_GENERATOR(F) \ - F(AsyncFunctionAwaitCaught, 3, 1) \ - F(AsyncFunctionAwaitUncaught, 3, 1) \ - F(AsyncGeneratorAwaitCaught, 2, 1) \ - F(AsyncGeneratorAwaitUncaught, 2, 1) \ F(AsyncGeneratorHasCatchHandlerForPC, 1, 1) \ F(AsyncGeneratorReject, 2, 1) \ F(AsyncGeneratorResolve, 3, 1) \ diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden index df6b3723586533..2b4eb6b2cc5674 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden @@ -39,7 +39,7 @@ bytecodes: [ B(LdaUndefined), B(Star), R(6), B(Mov), R(0), R(5), - B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(5), U8(2), + B(CallJSRuntime), U8(%async_generator_await_uncaught), R(5), U8(2), B(SuspendGenerator), R(0), R(0), U8(5), U8(1), B(ResumeGenerator), R(0), R(0), U8(5), B(Star), R(5), @@ -166,7 +166,7 @@ bytecodes: [ B(LdaUndefined), B(Star), R(6), B(Mov), R(0), R(5), - B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(5), U8(2), + B(CallJSRuntime), U8(%async_generator_await_uncaught), R(5), U8(2), B(SuspendGenerator), R(0), R(0), U8(5), U8(2), B(ResumeGenerator), R(0), R(0), U8(5), B(Star), R(5), @@ -404,7 +404,7 @@ bytecodes: [ B(LdaUndefined), B(Star), R(16), B(Mov), R(2), R(15), - B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(15), U8(2), + B(CallJSRuntime), U8(%async_generator_await_uncaught), R(15), U8(2), B(SuspendGenerator), R(2), R(0), U8(15), U8(2), B(ResumeGenerator), R(2), R(0), U8(15), B(Star), R(15), @@ -580,7 +580,7 @@ bytecodes: [ B(Jump), U8(2), B(Star), R(13), B(Mov), R(0), R(12), - B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(12), U8(2), + B(CallJSRuntime), U8(%async_generator_await_uncaught), R(12), U8(2), /* 49 E> */ B(SuspendGenerator), R(0), R(0), U8(12), U8(1), B(ResumeGenerator), R(0), R(0), U8(12), B(Star), R(12), @@ -598,7 +598,7 @@ bytecodes: [ B(CallRuntime), U16(Runtime::kThrowThrowMethodMissing), R(0), U8(0), B(Star), R(13), B(Mov), R(0), R(12), - B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(12), U8(2), + B(CallJSRuntime), U8(%async_generator_await_uncaught), R(12), U8(2), /* 49 E> */ B(SuspendGenerator), R(0), R(0), U8(12), U8(2), B(ResumeGenerator), R(0), R(0), U8(12), B(Star), R(12), @@ -639,7 +639,7 @@ bytecodes: [ B(LdaUndefined), B(Star), R(6), B(Mov), R(0), R(5), - B(InvokeIntrinsic), U8(Runtime::k_AsyncGeneratorAwaitUncaught), R(5), U8(2), + B(CallJSRuntime), U8(%async_generator_await_uncaught), R(5), U8(2), B(SuspendGenerator), R(0), R(0), U8(5), U8(4), B(ResumeGenerator), R(0), R(0), U8(5), B(Star), R(5), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden index 95400dacf803ac..4d36315f027988 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden @@ -53,7 +53,7 @@ bytecodes: [ B(Star), R(21), B(Mov), R(2), R(20), B(Mov), R(11), R(22), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(20), U8(3), + B(CallJSRuntime), U8(%async_function_await_uncaught), R(20), U8(3), /* 40 E> */ B(SuspendGenerator), R(2), R(0), U8(20), U8(0), B(ResumeGenerator), R(2), R(0), U8(20), B(Star), R(20), @@ -137,7 +137,7 @@ bytecodes: [ B(Star), R(21), B(Mov), R(2), R(20), B(Mov), R(11), R(22), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitCaught), R(20), U8(3), + B(CallJSRuntime), U8(%async_function_await_caught), R(20), U8(3), B(SuspendGenerator), R(2), R(0), U8(20), U8(1), B(ResumeGenerator), R(2), R(0), U8(20), B(Star), R(20), @@ -160,7 +160,7 @@ bytecodes: [ B(Star), R(20), B(Mov), R(2), R(19), B(Mov), R(11), R(21), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(19), U8(3), + B(CallJSRuntime), U8(%async_function_await_uncaught), R(19), U8(3), B(SuspendGenerator), R(2), R(0), U8(19), U8(2), B(ResumeGenerator), R(2), R(0), U8(19), B(Star), R(19), @@ -306,7 +306,7 @@ bytecodes: [ B(Star), R(21), B(Mov), R(2), R(20), B(Mov), R(11), R(22), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(20), U8(3), + B(CallJSRuntime), U8(%async_function_await_uncaught), R(20), U8(3), /* 40 E> */ B(SuspendGenerator), R(2), R(0), U8(20), U8(0), B(ResumeGenerator), R(2), R(0), U8(20), B(Star), R(20), @@ -391,7 +391,7 @@ bytecodes: [ B(Star), R(21), B(Mov), R(2), R(20), B(Mov), R(11), R(22), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitCaught), R(20), U8(3), + B(CallJSRuntime), U8(%async_function_await_caught), R(20), U8(3), B(SuspendGenerator), R(2), R(0), U8(20), U8(1), B(ResumeGenerator), R(2), R(0), U8(20), B(Star), R(20), @@ -414,7 +414,7 @@ bytecodes: [ B(Star), R(20), B(Mov), R(2), R(19), B(Mov), R(11), R(21), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(19), U8(3), + B(CallJSRuntime), U8(%async_function_await_uncaught), R(19), U8(3), B(SuspendGenerator), R(2), R(0), U8(19), U8(2), B(ResumeGenerator), R(2), R(0), U8(19), B(Star), R(19), @@ -575,7 +575,7 @@ bytecodes: [ B(Star), R(21), B(Mov), R(2), R(20), B(Mov), R(11), R(22), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(20), U8(3), + B(CallJSRuntime), U8(%async_function_await_uncaught), R(20), U8(3), /* 40 E> */ B(SuspendGenerator), R(2), R(0), U8(20), U8(0), B(ResumeGenerator), R(2), R(0), U8(20), B(Star), R(20), @@ -667,7 +667,7 @@ bytecodes: [ B(Star), R(21), B(Mov), R(2), R(20), B(Mov), R(11), R(22), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitCaught), R(20), U8(3), + B(CallJSRuntime), U8(%async_function_await_caught), R(20), U8(3), B(SuspendGenerator), R(2), R(0), U8(20), U8(1), B(ResumeGenerator), R(2), R(0), U8(20), B(Star), R(20), @@ -690,7 +690,7 @@ bytecodes: [ B(Star), R(20), B(Mov), R(2), R(19), B(Mov), R(11), R(21), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(19), U8(3), + B(CallJSRuntime), U8(%async_function_await_uncaught), R(19), U8(3), B(SuspendGenerator), R(2), R(0), U8(19), U8(2), B(ResumeGenerator), R(2), R(0), U8(19), B(Star), R(19), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden index 1a0155da79c809..f92076e6e65ebe 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden @@ -1196,7 +1196,7 @@ bytecodes: [ /* 45 S> */ B(Mov), R(2), R(21), B(Mov), R(0), R(22), B(Mov), R(11), R(23), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(21), U8(3), + B(CallJSRuntime), U8(%async_function_await_uncaught), R(21), U8(3), /* 45 E> */ B(SuspendGenerator), R(2), R(0), U8(21), U8(0), B(ResumeGenerator), R(2), R(0), U8(21), B(Star), R(21), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden index 80609db7b80b5b..7edf446ce33d53 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden @@ -493,7 +493,7 @@ bytecodes: [ /* 52 S> */ B(Mov), R(1), R(7), B(Mov), R(0), R(8), B(Mov), R(2), R(9), - B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(7), U8(3), + B(CallJSRuntime), U8(%async_function_await_uncaught), R(7), U8(3), /* 52 E> */ B(SuspendGenerator), R(1), R(0), U8(7), U8(0), B(ResumeGenerator), R(1), R(0), U8(7), B(Star), R(7), diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 2f552a9d9d9f6a..8b93944d93363f 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -18358,12 +18358,6 @@ TEST(PromiseHook) { CHECK_EQ(v8::Promise::kFulfilled, GetPromise("p")->State()); CHECK_EQ(9, promise_hook_data->promise_hook_count); - promise_hook_data->Reset(); - source = "(async() => await p)();\n"; - - CompileRun(source); - CHECK_EQ(11, promise_hook_data->promise_hook_count); - delete promise_hook_data; isolate->SetPromiseHook(nullptr); } diff --git a/deps/v8/tools/v8heapconst.py b/deps/v8/tools/v8heapconst.py index 1e57ce64a9e297..e3b29f820423b0 100644 --- a/deps/v8/tools/v8heapconst.py +++ b/deps/v8/tools/v8heapconst.py @@ -263,12 +263,12 @@ ("MAP_SPACE", 0x04511): (173, "Tuple2Map"), ("MAP_SPACE", 0x04569): (171, "ScriptMap"), ("MAP_SPACE", 0x045c1): (163, "InterceptorInfoMap"), - ("MAP_SPACE", 0x04619): (154, "AccessorInfoMap"), - ("MAP_SPACE", 0x04671): (153, "AccessCheckInfoMap"), - ("MAP_SPACE", 0x046c9): (155, "AccessorPairMap"), - ("MAP_SPACE", 0x04721): (156, "AliasedArgumentsEntryMap"), - ("MAP_SPACE", 0x04779): (157, "AllocationMementoMap"), - ("MAP_SPACE", 0x047d1): (158, "AllocationSiteMap"), + ("MAP_SPACE", 0x04619): (158, "AllocationSiteMap"), + ("MAP_SPACE", 0x04671): (154, "AccessorInfoMap"), + ("MAP_SPACE", 0x046c9): (153, "AccessCheckInfoMap"), + ("MAP_SPACE", 0x04721): (155, "AccessorPairMap"), + ("MAP_SPACE", 0x04779): (156, "AliasedArgumentsEntryMap"), + ("MAP_SPACE", 0x047d1): (157, "AllocationMementoMap"), ("MAP_SPACE", 0x04829): (159, "AsyncGeneratorRequestMap"), ("MAP_SPACE", 0x04881): (160, "ContextExtensionMap"), ("MAP_SPACE", 0x048d9): (161, "DebugInfoMap"), @@ -366,4 +366,4 @@ "NATIVE", ) -# This set of constants is generated from a shipping build. +# This set of constants is generated from a non-shipping build. From 35d66619735063e40e30da9a1dd2f67e9f9f21a8 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Fri, 18 May 2018 11:36:50 -0700 Subject: [PATCH 34/93] deps: cherry-pick 6989b3f6d7 from V8 upstream Original commit message: Fix default Intl language tag handling With certain ICU data bundles (such as the Node.js "small-icu"), %GetDefaultICULocale() may return a more specific language tag (e.g. "en-US") than what's available (e.g. "en"). In those cases, consider the more specific language tag supported. This CL also resolves the following Node.js issue: https://github.com/nodejs/node/issues/15223 Bug: v8:7024 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ifda0776b3418734d5caa8af4e50c17cda95add73 Reviewed-on: https://chromium-review.googlesource.com/668350 Commit-Queue: Daniel Ehrenberg Reviewed-by: Daniel Ehrenberg Cr-Commit-Position: refs/heads/master@{#52716} PR-URL: https://github.com/nodejs/node/pull/20826 Fixes: https://github.com/nodejs/node/issues/15223 Refs: https://github.com/v8/v8/commit/6989b3f6d7d6a5e68127332296723317917821eb Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski Reviewed-By: Ben Noordhuis --- common.gypi | 2 +- deps/v8/src/js/intl.js | 89 ++++++++++++------- deps/v8/test/intl/assert.js | 41 +++++++++ .../intl/break-iterator/default-locale.js | 4 +- .../wellformed-unsupported-locale.js | 2 +- deps/v8/test/intl/collator/default-locale.js | 11 ++- .../collator/wellformed-unsupported-locale.js | 2 +- .../test/intl/date-format/default-locale.js | 4 +- .../wellformed-unsupported-locale.js | 2 +- .../test/intl/number-format/default-locale.js | 4 +- .../wellformed-unsupported-locale.js | 2 +- deps/v8/test/mjsunit/regress/regress-6288.js | 2 +- 12 files changed, 119 insertions(+), 46 deletions(-) diff --git a/common.gypi b/common.gypi index 077fd57f507e93..641aa90b17c1d3 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.6', + 'v8_embedder_string': '-node.7', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/src/js/intl.js b/deps/v8/src/js/intl.js index 53fbe1f9473267..3c7112716c30cc 100644 --- a/deps/v8/src/js/intl.js +++ b/deps/v8/src/js/intl.js @@ -152,18 +152,11 @@ var AVAILABLE_LOCALES = { */ var DEFAULT_ICU_LOCALE = UNDEFINED; -function GetDefaultICULocaleJS(service) { +function GetDefaultICULocaleJS() { if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) { DEFAULT_ICU_LOCALE = %GetDefaultICULocale(); } - // Check that this is a valid default for this service, - // otherwise fall back to "und" - // TODO(littledan,jshin): AvailableLocalesOf sometimes excludes locales - // which don't require tailoring, but work fine with root data. Look into - // exposing this fact in ICU or the way Chrome bundles data. - return (IS_UNDEFINED(service) || - HAS_OWN_PROPERTY(getAvailableLocalesOf(service), DEFAULT_ICU_LOCALE)) - ? DEFAULT_ICU_LOCALE : "und"; + return DEFAULT_ICU_LOCALE; } /** @@ -434,6 +427,48 @@ function resolveLocale(service, requestedLocales, options) { } +/** + * Look up the longest non-empty prefix of |locale| that is an element of + * |availableLocales|. Returns undefined when the |locale| is completely + * unsupported by |availableLocales|. + */ +function bestAvailableLocale(availableLocales, locale) { + do { + if (!IS_UNDEFINED(availableLocales[locale])) { + return locale; + } + // Truncate locale if possible. + var pos = %StringLastIndexOf(locale, '-'); + if (pos === -1) { + break; + } + locale = %_Call(StringSubstring, locale, 0, pos); + } while (true); + + return UNDEFINED; +} + + +/** + * Try to match any mutation of |requestedLocale| against |availableLocales|. + */ +function attemptSingleLookup(availableLocales, requestedLocale) { + // Remove all extensions. + var noExtensionsLocale = %RegExpInternalReplace( + GetAnyExtensionRE(), requestedLocale, ''); + var availableLocale = bestAvailableLocale( + availableLocales, requestedLocale); + if (!IS_UNDEFINED(availableLocale)) { + // Return the resolved locale and extension. + var extensionMatch = %regexp_internal_match( + GetUnicodeExtensionRE(), requestedLocale); + var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; + return {locale: availableLocale, extension: extension}; + } + return UNDEFINED; +} + + /** * Returns best matched supported locale and extension info using basic * lookup algorithm. @@ -446,31 +481,25 @@ function lookupMatcher(service, requestedLocales) { var availableLocales = getAvailableLocalesOf(service); for (var i = 0; i < requestedLocales.length; ++i) { - // Remove all extensions. - var locale = %RegExpInternalReplace( - GetAnyExtensionRE(), requestedLocales[i], ''); - do { - if (!IS_UNDEFINED(availableLocales[locale])) { - // Return the resolved locale and extension. - var extensionMatch = %regexp_internal_match( - GetUnicodeExtensionRE(), requestedLocales[i]); - var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; - return {locale: locale, extension: extension, position: i}; - } - // Truncate locale if possible. - var pos = %StringLastIndexOf(locale, '-'); - if (pos === -1) { - break; - } - locale = %_Call(StringSubstring, locale, 0, pos); - } while (true); + var result = attemptSingleLookup(availableLocales, requestedLocales[i]); + if (!IS_UNDEFINED(result)) { + return result; + } + } + + var defLocale = GetDefaultICULocaleJS(); + + // While ECMA-402 returns defLocale directly, we have to check if it is + // supported, as such support is not guaranteed. + var result = attemptSingleLookup(availableLocales, defLocale); + if (!IS_UNDEFINED(result)) { + return result; } // Didn't find a match, return default. return { - locale: GetDefaultICULocaleJS(service), - extension: '', - position: -1 + locale: 'und', + extension: '' }; } diff --git a/deps/v8/test/intl/assert.js b/deps/v8/test/intl/assert.js index d8cc85849f463a..c11e7c0bbf8914 100644 --- a/deps/v8/test/intl/assert.js +++ b/deps/v8/test/intl/assert.js @@ -132,6 +132,16 @@ function assertFalse(value, user_message = '') { } +/** + * Throws if value is null. + */ +function assertNotNull(value, user_message = '') { + if (value === null) { + fail("not null", value, user_message); + } +} + + /** * Runs code() and asserts that it throws the specified exception. */ @@ -189,3 +199,34 @@ function assertInstanceof(obj, type) { (actualTypeName ? ' but of < ' + actualTypeName + '>' : '')); } } + + +/** + * Split a BCP 47 language tag into locale and extension. + */ +function splitLanguageTag(tag) { + var extRe = /(-[0-9A-Za-z](-[0-9A-Za-z]{2,8})+)+$/; + var match = %regexp_internal_match(extRe, tag); + if (match) { + return { locale: tag.slice(0, match.index), extension: match[0] }; + } + + return { locale: tag, extension: '' }; +} + + +/** + * Throw if |parent| is not a more general language tag of |child|, nor |child| + * itself, per BCP 47 rules. + */ +function assertLanguageTag(child, parent) { + var childSplit = splitLanguageTag(child); + var parentSplit = splitLanguageTag(parent); + + // Do not compare extensions at this moment, as %GetDefaultICULocale() + // doesn't always output something we support. + if (childSplit.locale !== parentSplit.locale && + !childSplit.locale.startsWith(parentSplit.locale + '-')) { + fail(child, parent, 'language tag comparison'); + } +} diff --git a/deps/v8/test/intl/break-iterator/default-locale.js b/deps/v8/test/intl/break-iterator/default-locale.js index d8d5aeadb27510..e1a42a100a6b0f 100644 --- a/deps/v8/test/intl/break-iterator/default-locale.js +++ b/deps/v8/test/intl/break-iterator/default-locale.js @@ -37,8 +37,8 @@ assertFalse(options.locale === 'und'); assertFalse(options.locale === ''); assertFalse(options.locale === undefined); -// Then check for equality. -assertEquals(options.locale, %GetDefaultICULocale()); +// Then check for legitimacy. +assertLanguageTag(%GetDefaultICULocale(), options.locale); var iteratorNone = new Intl.v8BreakIterator(); assertEquals(options.locale, iteratorNone.resolvedOptions().locale); diff --git a/deps/v8/test/intl/break-iterator/wellformed-unsupported-locale.js b/deps/v8/test/intl/break-iterator/wellformed-unsupported-locale.js index 5ac8fbcd41583f..ffa44aef081eaf 100644 --- a/deps/v8/test/intl/break-iterator/wellformed-unsupported-locale.js +++ b/deps/v8/test/intl/break-iterator/wellformed-unsupported-locale.js @@ -29,4 +29,4 @@ var iterator = Intl.v8BreakIterator(['xx']); -assertEquals(iterator.resolvedOptions().locale, %GetDefaultICULocale()); +assertLanguageTag(%GetDefaultICULocale(), iterator.resolvedOptions().locale); diff --git a/deps/v8/test/intl/collator/default-locale.js b/deps/v8/test/intl/collator/default-locale.js index db9b1e73304114..5fc6ff4665c903 100644 --- a/deps/v8/test/intl/collator/default-locale.js +++ b/deps/v8/test/intl/collator/default-locale.js @@ -37,8 +37,8 @@ assertFalse(options.locale === 'und'); assertFalse(options.locale === ''); assertFalse(options.locale === undefined); -// Then check for equality. -assertEquals(options.locale, %GetDefaultICULocale()); +// Then check for legitimacy. +assertLanguageTag(%GetDefaultICULocale(), options.locale); var collatorNone = new Intl.Collator(); assertEquals(options.locale, collatorNone.resolvedOptions().locale); @@ -48,5 +48,8 @@ var collatorBraket = new Intl.Collator({}); assertEquals(options.locale, collatorBraket.resolvedOptions().locale); var collatorWithOptions = new Intl.Collator(undefined, {usage: 'search'}); -assertEquals(%GetDefaultICULocale() + '-u-co-search', - collatorWithOptions.resolvedOptions().locale); +assertLanguageTag(%GetDefaultICULocale(), + collatorWithOptions.resolvedOptions().locale); +assertNotNull( + %regexp_internal_match(/-u(-[a-zA-Z]+-[a-zA-Z]+)*-co-search/, + collatorWithOptions.resolvedOptions().locale)); diff --git a/deps/v8/test/intl/collator/wellformed-unsupported-locale.js b/deps/v8/test/intl/collator/wellformed-unsupported-locale.js index 3963d47a61ff85..ad89e3e2203e31 100644 --- a/deps/v8/test/intl/collator/wellformed-unsupported-locale.js +++ b/deps/v8/test/intl/collator/wellformed-unsupported-locale.js @@ -29,4 +29,4 @@ var collator = Intl.Collator(['xx']); -assertEquals(collator.resolvedOptions().locale, %GetDefaultICULocale()); +assertLanguageTag(%GetDefaultICULocale(), collator.resolvedOptions().locale); diff --git a/deps/v8/test/intl/date-format/default-locale.js b/deps/v8/test/intl/date-format/default-locale.js index 8e9b7fcec3e16e..2d79e895b54c38 100644 --- a/deps/v8/test/intl/date-format/default-locale.js +++ b/deps/v8/test/intl/date-format/default-locale.js @@ -37,8 +37,8 @@ assertFalse(options.locale === 'und'); assertFalse(options.locale === ''); assertFalse(options.locale === undefined); -// Then check for equality. -assertEquals(options.locale, %GetDefaultICULocale()); +// Then check for legitimacy. +assertLanguageTag(%GetDefaultICULocale(), options.locale); var dtfNone = new Intl.DateTimeFormat(); assertEquals(options.locale, dtfNone.resolvedOptions().locale); diff --git a/deps/v8/test/intl/date-format/wellformed-unsupported-locale.js b/deps/v8/test/intl/date-format/wellformed-unsupported-locale.js index 6f063abbd1a07c..b81216483250af 100644 --- a/deps/v8/test/intl/date-format/wellformed-unsupported-locale.js +++ b/deps/v8/test/intl/date-format/wellformed-unsupported-locale.js @@ -29,4 +29,4 @@ var dtf = Intl.DateTimeFormat(['xx']); -assertEquals(dtf.resolvedOptions().locale, %GetDefaultICULocale()); +assertLanguageTag(%GetDefaultICULocale(), dtf.resolvedOptions().locale); diff --git a/deps/v8/test/intl/number-format/default-locale.js b/deps/v8/test/intl/number-format/default-locale.js index cd67ba724f140f..a24aec23332786 100644 --- a/deps/v8/test/intl/number-format/default-locale.js +++ b/deps/v8/test/intl/number-format/default-locale.js @@ -37,8 +37,8 @@ assertFalse(options.locale === 'und'); assertFalse(options.locale === ''); assertFalse(options.locale === undefined); -// Then check for equality. -assertEquals(options.locale, %GetDefaultICULocale()); +// Then check for legitimacy. +assertLanguageTag(%GetDefaultICULocale(), options.locale); var nfNone = new Intl.NumberFormat(); assertEquals(options.locale, nfNone.resolvedOptions().locale); diff --git a/deps/v8/test/intl/number-format/wellformed-unsupported-locale.js b/deps/v8/test/intl/number-format/wellformed-unsupported-locale.js index 195eba4c19e09b..c51753928eeb87 100644 --- a/deps/v8/test/intl/number-format/wellformed-unsupported-locale.js +++ b/deps/v8/test/intl/number-format/wellformed-unsupported-locale.js @@ -29,4 +29,4 @@ var nf = Intl.NumberFormat(['xx']); -assertEquals(nf.resolvedOptions().locale, %GetDefaultICULocale()); +assertLanguageTag(%GetDefaultICULocale(), nf.resolvedOptions().locale); diff --git a/deps/v8/test/mjsunit/regress/regress-6288.js b/deps/v8/test/mjsunit/regress/regress-6288.js index 337af54c1a8303..5f550c31c8b72d 100644 --- a/deps/v8/test/mjsunit/regress/regress-6288.js +++ b/deps/v8/test/mjsunit/regress/regress-6288.js @@ -8,6 +8,6 @@ // DateTimeFormat but not Collation if (this.Intl) { - assertEquals('und', Intl.Collator().resolvedOptions().locale); + assertEquals('pt', Intl.Collator().resolvedOptions().locale); assertEquals('pt-BR', Intl.DateTimeFormat().resolvedOptions().locale); } From 4c48b69e90c60ded5dc7da0dc1ae5237b78499ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Tue, 13 Mar 2018 15:08:31 +0100 Subject: [PATCH 35/93] util: add type check function for BigIntObject PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- src/node_types.cc | 1 + test/.eslintrc.yaml | 1 + test/parallel/test-util-types.js | 1 + 3 files changed, 3 insertions(+) diff --git a/src/node_types.cc b/src/node_types.cc index bd7ea9cf23fff7..5dac1f6d275b63 100644 --- a/src/node_types.cc +++ b/src/node_types.cc @@ -13,6 +13,7 @@ namespace { V(External) \ V(Date) \ V(ArgumentsObject) \ + V(BigIntObject) \ V(BooleanObject) \ V(NumberObject) \ V(StringObject) \ diff --git a/test/.eslintrc.yaml b/test/.eslintrc.yaml index 7f67df154a9b35..c57d7505c984ff 100644 --- a/test/.eslintrc.yaml +++ b/test/.eslintrc.yaml @@ -49,6 +49,7 @@ rules: # Global scoped methods and vars globals: WebAssembly: false + BigInt: false BigInt64Array: false BigUint64Array: false SharedArrayBuffer: false diff --git a/test/parallel/test-util-types.js b/test/parallel/test-util-types.js index 24f613cc0b25ad..de5a89ab4abc80 100644 --- a/test/parallel/test-util-types.js +++ b/test/parallel/test-util-types.js @@ -20,6 +20,7 @@ for (const [ value, _method ] of [ [ new Number(), 'isNumberObject' ], [ new String(), 'isStringObject' ], [ Object(Symbol()), 'isSymbolObject' ], + [ Object(BigInt(0)), 'isBigIntObject' ], [ new Error(), 'isNativeError' ], [ new RegExp() ], [ async function() {}, 'isAsyncFunction' ], From af62a16ff60f7788853b9835c1783c41ba380d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Thu, 12 Apr 2018 09:13:06 +0200 Subject: [PATCH 36/93] Revert "src: fix GetCpuProfiler() deprecation warning" This reverts commit f02b74dfdb364e1ccfa59ba7ee22790fe65548c3. PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- src/env.cc | 14 +++----------- src/env.h | 4 ---- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/env.cc b/src/env.cc index f6303e6011f54c..a37efe08832f45 100644 --- a/src/env.cc +++ b/src/env.cc @@ -1,5 +1,6 @@ #include "node_internals.h" #include "async_wrap.h" +#include "v8-profiler.h" #include "node_buffer.h" #include "node_platform.h" #include "node_file.h" @@ -73,15 +74,6 @@ IsolateData::IsolateData(Isolate* isolate, IsolateData::~IsolateData() { if (platform_ != nullptr) platform_->UnregisterIsolate(this); - if (cpu_profiler_ != nullptr) - cpu_profiler_->Dispose(); -} - -v8::CpuProfiler* IsolateData::GetCpuProfiler() { - if (cpu_profiler_ != nullptr) return cpu_profiler_; - cpu_profiler_ = v8::CpuProfiler::New(isolate()); - CHECK_NOT_NULL(cpu_profiler_); - return cpu_profiler_; } @@ -260,12 +252,12 @@ void Environment::CleanupHandles() { void Environment::StartProfilerIdleNotifier() { uv_prepare_start(&idle_prepare_handle_, [](uv_prepare_t* handle) { Environment* env = ContainerOf(&Environment::idle_prepare_handle_, handle); - env->isolate_data()->GetCpuProfiler()->SetIdle(true); + env->isolate()->GetCpuProfiler()->SetIdle(true); }); uv_check_start(&idle_check_handle_, [](uv_check_t* handle) { Environment* env = ContainerOf(&Environment::idle_check_handle_, handle); - env->isolate_data()->GetCpuProfiler()->SetIdle(false); + env->isolate()->GetCpuProfiler()->SetIdle(false); }); } diff --git a/src/env.h b/src/env.h index c17cc59b5b5ccd..96252fa12a1397 100644 --- a/src/env.h +++ b/src/env.h @@ -32,7 +32,6 @@ #include "req_wrap.h" #include "util.h" #include "uv.h" -#include "v8-profiler.h" #include "v8.h" #include "node.h" #include "node_http2_state.h" @@ -369,8 +368,6 @@ class IsolateData { std::unordered_map> http2_static_strs; inline v8::Isolate* isolate() const; - v8::CpuProfiler* GetCpuProfiler(); - private: #define VP(PropertyName, StringValue) V(v8::Private, PropertyName) #define VS(PropertyName, StringValue) V(v8::String, PropertyName) @@ -386,7 +383,6 @@ class IsolateData { uv_loop_t* const event_loop_; uint32_t* const zero_fill_field_; MultiIsolatePlatform* platform_; - v8::CpuProfiler* cpu_profiler_ = nullptr; DISALLOW_COPY_AND_ASSIGN(IsolateData); }; From 2d3137c5a9b9e7301a1df8638687949b2215c654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Fri, 23 Mar 2018 18:28:30 +0100 Subject: [PATCH 37/93] src: fix GetCpuProfiler() deprecation warning Refs: https://github.com/nodejs/node-v8/issues/46 PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- src/env.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/env.cc b/src/env.cc index a37efe08832f45..32ffd402da049a 100644 --- a/src/env.cc +++ b/src/env.cc @@ -252,12 +252,12 @@ void Environment::CleanupHandles() { void Environment::StartProfilerIdleNotifier() { uv_prepare_start(&idle_prepare_handle_, [](uv_prepare_t* handle) { Environment* env = ContainerOf(&Environment::idle_prepare_handle_, handle); - env->isolate()->GetCpuProfiler()->SetIdle(true); + env->isolate()->SetIdle(true); }); uv_check_start(&idle_check_handle_, [](uv_check_t* handle) { Environment* env = ContainerOf(&Environment::idle_check_handle_, handle); - env->isolate()->GetCpuProfiler()->SetIdle(false); + env->isolate()->SetIdle(false); }); } From aa08f6464ced0d7ed8a9daaadda46d83cf353b2b Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 27 Mar 2018 11:17:33 -0400 Subject: [PATCH 38/93] test: add read_only_space heap space v8.getHeapSpaceStatistics() now includes read_only_space in its results. Update test-v8-stats.js to account for this. Fixes: https://github.com/nodejs/node-v8/issues/44 PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- test/parallel/test-v8-stats.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-v8-stats.js b/test/parallel/test-v8-stats.js index 02182e2816bbc7..83689afc974e12 100644 --- a/test/parallel/test-v8-stats.js +++ b/test/parallel/test-v8-stats.js @@ -25,7 +25,8 @@ const expectedHeapSpaces = [ 'old_space', 'code_space', 'map_space', - 'large_object_space' + 'large_object_space', + 'read_only_space' ]; const heapSpaceStatistics = v8.getHeapSpaceStatistics(); const actualHeapSpaceNames = heapSpaceStatistics.map((s) => s.space_name); From df9779144781e0a2efa2cf3c9a082468b0633634 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 27 Mar 2018 12:16:51 -0400 Subject: [PATCH 39/93] test: update postmortem metadata test This commit updates the following postmortem metadata constants: - v8dbg_class_SharedFunctionInfo__code__Code - This is now combined with SharedFunctionInfo's function_data. - Renamed: v8dbg_class_SharedFunctionInfo__function_data__Object - V8 commit: https://github.com/v8/v8/commit/51ded9d3c0dc430217253595027c6ed207d8cc2d - v8dbg_class_SharedFunctionInfo__raw_name__Object and - v8dbg_class_SharedFunctionInfo__scope_info__ScopeInfo - These are now combined as name_or_scope_info. - Renamed: v8dbg_class_SharedFunctionInfo__name_or_scope_info__Object - V8 commit: https://github.com/v8/v8/commit/74a663be675924944a343f2aed71bbe60ef55764 - v8dbg_class_SharedFunctionInfo__compiler_hints__int - Renamed: v8dbg_class_SharedFunctionInfo__flags__int - V8 commit: https://github.com/v8/v8/commit/071b01b6406e8884b040cc54e763d4c3b4b18c39#diff-f3f182b0510ba2ee39ae87e421ff110b Fixes: https://github.com/nodejs/node-v8/issues/44 Fixes: https://github.com/nodejs/node-v8/issues/48 PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- test/parallel/test-postmortem-metadata.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/parallel/test-postmortem-metadata.js b/test/parallel/test-postmortem-metadata.js index 1f4cc7e6056df7..82dfb2c9a9fb07 100644 --- a/test/parallel/test-postmortem-metadata.js +++ b/test/parallel/test-postmortem-metadata.js @@ -93,13 +93,12 @@ function getExpectedSymbols() { 'v8dbg_class_Script__source__Object', 'v8dbg_class_SeqOneByteString__chars__char', 'v8dbg_class_SeqTwoByteString__chars__char', - 'v8dbg_class_SharedFunctionInfo__code__Code', - 'v8dbg_class_SharedFunctionInfo__compiler_hints__int', + 'v8dbg_class_SharedFunctionInfo__function_data__Object', + 'v8dbg_class_SharedFunctionInfo__flags__int', 'v8dbg_class_SharedFunctionInfo__end_position__int', 'v8dbg_class_SharedFunctionInfo__function_identifier__Object', 'v8dbg_class_SharedFunctionInfo__internal_formal_parameter_count__int', - 'v8dbg_class_SharedFunctionInfo__raw_name__Object', - 'v8dbg_class_SharedFunctionInfo__scope_info__ScopeInfo', + 'v8dbg_class_SharedFunctionInfo__name_or_scope_info__Object', 'v8dbg_class_SharedFunctionInfo__script__Object', 'v8dbg_class_SharedFunctionInfo__start_position_and_type__int', 'v8dbg_class_SlicedString__offset__SMI', From 7c0c61bde1f7ef2adf3167915fff6b2f2b09bcae Mon Sep 17 00:00:00 2001 From: cjihrig Date: Wed, 4 Apr 2018 02:51:07 +0000 Subject: [PATCH 40/93] src: update postmortem constant name This commit renames V8DBG_CLASS_SHAREDFUNCTIONINFO__RAW_NAME__OBJECT to V8DBG_CLASS_SHAREDFUNCTIONINFO__NAME_OR_SCOPE_INFO__OBJECT following an upstream change. PR-URL: https://github.com/nodejs/node/pull/19989 Reviewed-By: James M Snell Reviewed-By: Matheus Marchini Reviewed-By: Gus Caplan Reviewed-By: Myles Borins --- src/v8abbr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v8abbr.h b/src/v8abbr.h index c4b244b5637bc7..9e8920204a386a 100644 --- a/src/v8abbr.h +++ b/src/v8abbr.h @@ -86,7 +86,7 @@ #define V8_OFF_FUNC_SHARED \ V8_OFF_HEAP(V8DBG_CLASS_JSFUNCTION__SHARED__SHAREDFUNCTIONINFO) #define V8_OFF_RAW_NAME \ - V8_OFF_HEAP(V8DBG_CLASS_SHAREDFUNCTIONINFO__RAW_NAME__OBJECT) + V8_OFF_HEAP(V8DBG_CLASS_SHAREDFUNCTIONINFO__NAME_OR_SCOPE_INFO__OBJECT) #define V8_OFF_SHARED_IDENT \ V8_OFF_HEAP(V8DBG_CLASS_SHAREDFUNCTIONINFO__FUNCTION_IDENTIFIER__OBJECT) #define V8_OFF_SHARED_SCRIPT \ From f2c9e5af09de17470ff40a0abcfb276bc995c3d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Tue, 5 Jun 2018 16:18:06 +0200 Subject: [PATCH 41/93] lib: introduce internal/validators Create a file to centralize argument validators that are used in multiple internal modules. Move validateInt32 and validateUint32 to this file. PR-URL: https://github.com/nodejs/node/pull/21149 Reviewed-By: Joyee Cheung Reviewed-By: Myles Borins --- lib/fs.js | 16 +++++----- lib/internal/fs/promises.js | 12 ++++---- lib/internal/fs/utils.js | 45 +--------------------------- lib/internal/validators.js | 58 +++++++++++++++++++++++++++++++++++++ node.gyp | 1 + 5 files changed, 76 insertions(+), 56 deletions(-) create mode 100644 lib/internal/validators.js diff --git a/lib/fs.js b/lib/fs.js index 646772a813e127..7b05750307c118 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -65,7 +65,6 @@ const internalUtil = require('internal/util'); const { copyObject, getOptions, - isUint32, modeNum, nullCheck, preprocessSymlinkDestination, @@ -76,16 +75,19 @@ const { stringToSymlinkType, toUnixTimestamp, validateBuffer, - validateLen, validateOffsetLengthRead, validateOffsetLengthWrite, - validatePath, - validateUint32 + validatePath } = internalFS; const { CHAR_FORWARD_SLASH, CHAR_BACKWARD_SLASH, } = require('internal/constants'); +const { + isUint32, + validateInt32, + validateUint32 +} = require('internal/validators'); // Lazy loaded let promises; @@ -787,8 +789,8 @@ fs.ftruncate = function(fd, len = 0, callback) { // TODO(BridgeAR): This does not seem right. // There does not seem to be any validation before and if there is any, it // should work similar to validateUint32 or not have a upper cap at all. - // This applies to all usage of `validateLen`. - validateLen(len); + // This applies to all usage of `validateInt32(len, 'len')`. + validateInt32(len, 'len'); len = Math.max(0, len); const req = new FSReqWrap(); req.oncomplete = makeCallback(callback); @@ -797,7 +799,7 @@ fs.ftruncate = function(fd, len = 0, callback) { fs.ftruncateSync = function(fd, len = 0) { validateUint32(fd, 'fd'); - validateLen(len); + validateInt32(len, 'len'); len = Math.max(0, len); const ctx = {}; binding.ftruncate(fd, len, undefined, ctx); diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 97ac4c6c495b3d..4c0a256f5ad66c 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -21,7 +21,6 @@ const { copyObject, getOptions, getStatsFromBinding, - isUint32, modeNum, nullCheck, preprocessSymlinkDestination, @@ -29,12 +28,15 @@ const { stringToSymlinkType, toUnixTimestamp, validateBuffer, - validateLen, validateOffsetLengthRead, validateOffsetLengthWrite, - validatePath, - validateUint32 + validatePath } = require('internal/fs/utils'); +const { + isUint32, + validateInt32, + validateUint32 +} = require('internal/validators'); const pathModule = require('path'); const kHandle = Symbol('handle'); @@ -263,7 +265,7 @@ async function truncate(path, len = 0) { async function ftruncate(handle, len = 0) { validateFileHandle(handle); - validateLen(len); + validateInt32(len, 'len'); len = Math.max(0, len); return binding.ftruncate(handle.fd, len, kUsePromises); } diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 0cfb89a9d3d084..2f7a8d8ced176e 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -70,9 +70,6 @@ function getOptions(options, defaultOptions) { return options; } -function isInt32(n) { return n === (n | 0); } -function isUint32(n) { return n === (n >>> 0); } - function modeNum(m, def) { if (typeof m === 'number') return m; @@ -341,26 +338,6 @@ function validateBuffer(buffer) { } } -function validateLen(len) { - let err; - - if (!isInt32(len)) { - if (typeof len !== 'number') { - err = new ERR_INVALID_ARG_TYPE('len', 'number', len); - } else if (!Number.isInteger(len)) { - err = new ERR_OUT_OF_RANGE('len', 'an integer', len); - } else { - // 2 ** 31 === 2147483648 - err = new ERR_OUT_OF_RANGE('len', '> -2147483649 && < 2147483648', len); - } - } - - if (err !== undefined) { - Error.captureStackTrace(err, validateLen); - throw err; - } -} - function validateOffsetLengthRead(offset, length, bufferLength) { let err; @@ -410,28 +387,10 @@ function validatePath(path, propName = 'path') { } } -function validateUint32(value, propName) { - if (!isUint32(value)) { - let err; - if (typeof value !== 'number') { - err = new ERR_INVALID_ARG_TYPE(propName, 'number', value); - } else if (!Number.isInteger(value)) { - err = new ERR_OUT_OF_RANGE(propName, 'an integer', value); - } else { - // 2 ** 32 === 4294967296 - err = new ERR_OUT_OF_RANGE(propName, '>= 0 && < 4294967296', value); - } - Error.captureStackTrace(err, validateUint32); - throw err; - } -} - module.exports = { assertEncoding, copyObject, getOptions, - isInt32, - isUint32, modeNum, nullCheck, preprocessSymlinkDestination, @@ -443,9 +402,7 @@ module.exports = { SyncWriteStream, toUnixTimestamp, validateBuffer, - validateLen, validateOffsetLengthRead, validateOffsetLengthWrite, - validatePath, - validateUint32 + validatePath }; diff --git a/lib/internal/validators.js b/lib/internal/validators.js new file mode 100644 index 00000000000000..556bfb2dc08f5f --- /dev/null +++ b/lib/internal/validators.js @@ -0,0 +1,58 @@ +'use strict'; + +const { + ERR_INVALID_ARG_TYPE, + ERR_OUT_OF_RANGE +} = require('internal/errors').codes; + +function isInt32(value) { + return value === (value | 0); +} + +function isUint32(value) { + return value === (value >>> 0); +} + +function validateInt32(value, name) { + if (!isInt32(value)) { + let err; + if (typeof value !== 'number') { + err = new ERR_INVALID_ARG_TYPE(name, 'number', value); + } else if (!Number.isInteger(value)) { + err = new ERR_OUT_OF_RANGE(name, 'an integer', value); + } else { + // 2 ** 31 === 2147483648 + err = new ERR_OUT_OF_RANGE(name, '> -2147483649 && < 2147483648', value); + } + Error.captureStackTrace(err, validateInt32); + throw err; + } +} + +function validateUint32(value, name, positive) { + if (!isUint32(value)) { + let err; + if (typeof value !== 'number') { + err = new ERR_INVALID_ARG_TYPE(name, 'number', value); + } else if (!Number.isInteger(value)) { + err = new ERR_OUT_OF_RANGE(name, 'an integer', value); + } else { + const min = positive ? 1 : 0; + // 2 ** 32 === 4294967296 + err = new ERR_OUT_OF_RANGE(name, `>= ${min} && < 4294967296`, value); + } + Error.captureStackTrace(err, validateUint32); + throw err; + } else if (positive && value === 0) { + const err = new ERR_OUT_OF_RANGE(name, '>= 1 && < 4294967296', value); + Error.captureStackTrace(err, validateUint32); + throw err; + } +} + +module.exports = { + isInt32, + isUint32, + validateInt32, + validateUint32 +}; diff --git a/node.gyp b/node.gyp index 10b818e683f1fc..19367d9bd9517d 100644 --- a/node.gyp +++ b/node.gyp @@ -147,6 +147,7 @@ 'lib/internal/http2/util.js', 'lib/internal/v8_prof_polyfill.js', 'lib/internal/v8_prof_processor.js', + 'lib/internal/validators.js', 'lib/internal/stream_base_commons.js', 'lib/internal/vm/module.js', 'lib/internal/streams/lazy_transform.js', From e4224fd793bbab8cde2f3ea5e17cc5cef59721f2 Mon Sep 17 00:00:00 2001 From: Shivang Date: Fri, 25 May 2018 14:12:36 -0400 Subject: [PATCH 42/93] test: improve path tests Replaced deepStrictEqual with strictEqual when asserting that the path is equal to the win32 or posix equivalent, since it is a more strict check than deepStrictCheck. Also removed third argument in the check so that if there is an assertion error the properties that are different will be displayed. PR-URL: https://github.com/nodejs/node/pull/20967 Reviewed-By: Colin Ihrig Reviewed-By: Rich Trott Reviewed-By: Luigi Pinca Reviewed-By: Ujjwal Sharma Reviewed-By: Ruben Bridgewater Reviewed-By: Trivikram Kamat Reviewed-By: James M Snell --- test/parallel/test-path.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-path.js b/test/parallel/test-path.js index a3f10eccdf1d7e..ca10665b26ffc1 100644 --- a/test/parallel/test-path.js +++ b/test/parallel/test-path.js @@ -68,6 +68,6 @@ assert.strictEqual(path.win32.delimiter, ';'); assert.strictEqual(path.posix.delimiter, ':'); if (common.isWindows) - assert.deepStrictEqual(path, path.win32, 'should be win32 path module'); + assert.strictEqual(path, path.win32); else - assert.deepStrictEqual(path, path.posix, 'should be posix path module'); + assert.strictEqual(path, path.posix); From d84aa51dc7138f522c579fdf633d4bc89e59633f Mon Sep 17 00:00:00 2001 From: Lucas Liepert Date: Sat, 26 May 2018 14:50:48 -0400 Subject: [PATCH 43/93] test: removed message from strictEqual By removing the message from strictEqual, it will now print out the actual values of a and b, which will be more helpful in debugging. The old message has been added as a comment above the test. PR-URL: https://github.com/nodejs/node/pull/20983 Reviewed-By: Ruben Bridgewater Reviewed-By: Richard Lau Reviewed-By: Trivikram Kamat Reviewed-By: Rich Trott Reviewed-By: Benjamin Gruenbaum Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/parallel/test-require-dot.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-require-dot.js b/test/parallel/test-require-dot.js index 002a7ac988f2a1..423441cfcde435 100644 --- a/test/parallel/test-require-dot.js +++ b/test/parallel/test-require-dot.js @@ -8,7 +8,8 @@ const a = require(fixtures.path('module-require', 'relative', 'dot.js')); const b = require(fixtures.path('module-require', 'relative', 'dot-slash.js')); assert.strictEqual(a.value, 42); -assert.strictEqual(a, b, 'require(".") should resolve like require("./")'); +// require(".") should resolve like require("./") +assert.strictEqual(a, b); process.env.NODE_PATH = fixtures.path('module-require', 'relative'); m._initPaths(); From f79096a3f257aff8d03f60ad1fcd7ce616ba947e Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 26 May 2018 00:34:38 +0200 Subject: [PATCH 44/93] src: do not cache `NumberOfHeapSpaces()` globally While `NumberOfHeapSpaces()` currently returns a constant value, that is not strictly guaranteed by the V8 API as far as I can tell. Therefore, caching it globally does not seem appropriate. (The motivation here is that this squelches warnings which are produced by concurrency debugging tooling due to the apparent race conditions when accessing the global variable.) PR-URL: https://github.com/nodejs/node/pull/20971 Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Minwoo Jung Reviewed-By: Ben Noordhuis Reviewed-By: Joyee Cheung Reviewed-By: James M Snell --- src/node_v8.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/node_v8.cc b/src/node_v8.cc index bb41b569e6f796..d546eeba93f4d9 100644 --- a/src/node_v8.cc +++ b/src/node_v8.cc @@ -71,9 +71,6 @@ static const size_t kHeapSpaceStatisticsPropertiesCount = HEAP_SPACE_STATISTICS_PROPERTIES(V); #undef V -// Will be populated in InitializeV8Bindings. -static size_t number_of_heap_spaces = 0; - void CachedDataVersionTag(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -100,6 +97,7 @@ void UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo& args) { HeapSpaceStatistics s; Isolate* const isolate = env->isolate(); double* buffer = env->heap_space_statistics_buffer(); + size_t number_of_heap_spaces = env->isolate()->NumberOfHeapSpaces(); for (size_t i = 0; i < number_of_heap_spaces; i++) { isolate->GetHeapSpaceStatistics(&s, i); @@ -153,7 +151,7 @@ void Initialize(Local target, Uint32::NewFromUnsigned(env->isolate(), kHeapSpaceStatisticsPropertiesCount)); - number_of_heap_spaces = env->isolate()->NumberOfHeapSpaces(); + size_t number_of_heap_spaces = env->isolate()->NumberOfHeapSpaces(); // Heap space names are extracted once and exposed to JavaScript to // avoid excessive creation of heap space name Strings. From 4cd44203def7ab6e8a8f3125807928147012f684 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 26 May 2018 23:05:45 +0100 Subject: [PATCH 45/93] doc: remove invalid `vm.Script` arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/20984 Fixes: https://github.com/nodejs/node/issues/20982 Reviewed-By: Gus Caplan Reviewed-By: Michaël Zasso Reviewed-By: Ruben Bridgewater Reviewed-By: Trivikram Kamat Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Luigi Pinca Reviewed-By: Tobias Nießen Reviewed-By: James M Snell --- doc/api/vm.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/api/vm.md b/doc/api/vm.md index cc9b3135381dad..ff2f8c4ad0a41d 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -421,12 +421,6 @@ changes: in stack traces produced by this script. * `columnOffset` {number} Specifies the column number offset that is displayed in stack traces produced by this script. - * `displayErrors` {boolean} When `true`, if an [`Error`][] error occurs - while compiling the `code`, the line of code causing the error is attached - to the stack trace. - * `timeout` {number} Specifies the number of milliseconds to execute `code` - before terminating execution. If execution is terminated, an [`Error`][] - will be thrown. * `cachedData` {Buffer} Provides an optional `Buffer` with V8's code cache data for the supplied source. When supplied, the `cachedDataRejected` value will be set to either `true` or `false` depending on acceptance of the data From fd201e0d3271b95de27fd25d1a574370f8481ddc Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Mon, 28 May 2018 00:59:28 +0800 Subject: [PATCH 46/93] doc: add guides on writing tests involving promises Mention `common.crashOnUnhandledRejection()` and wrapping the handlers in `common.mustCall()` or `common.mustNotCall()`. PR-URL: https://github.com/nodejs/node/pull/20988 Reviewed-By: Vse Mozhet Byt Reviewed-By: Daniel Bevenius Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater Reviewed-By: Trivikram Kamat Reviewed-By: James M Snell --- doc/guides/writing-tests.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/guides/writing-tests.md b/doc/guides/writing-tests.md index 340d527dd20080..ac2844ebf43d5b 100644 --- a/doc/guides/writing-tests.md +++ b/doc/guides/writing-tests.md @@ -223,6 +223,37 @@ countdown.dec(); countdown.dec(); // The countdown callback will be invoked now. ``` +#### Testing promises + +When writing tests involving promises, either make sure that the +`onFulfilled` or the `onRejected` handler is wrapped in +`common.mustCall()` or `common.mustNotCall()` accordingly, or +call `common.crashOnUnhandledRejection()` in the top level of the +test to make sure that unhandled rejections would result in a test +failure. For example: + +```javascript +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs').promises; + +// Use `common.crashOnUnhandledRejection()` to make sure unhandled rejections +// will fail the test. +common.crashOnUnhandledRejection(); + +// Or, wrap the `onRejected` handler in `common.mustNotCall()`. +fs.writeFile('test-file', 'test').catch(common.mustNotCall()); + +// Or, wrap the `onFulfilled` handler in `common.mustCall()`. +// If there are assertions in the `onFulfilled` handler, wrap +// the next `onRejected` handler in `common.mustNotCall()` +// to handle potential failures. +fs.readFile('test-file').then( + common.mustCall( + (content) => assert.strictEqual(content.toString(), 'test2') + )) + .catch(common.mustNotCall()); +``` ### Flags From 09aec436cb8b69bb98cc3eea6dc6f5d0b15eb646 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 29 May 2018 19:59:28 -0700 Subject: [PATCH 47/93] doc: remove vestigial onboarding section The onboarding-extras doc includes a section with a single bullet point instructing the new Collaborator to write good pull request descriptions. This material is likely superfluous and is in the wrong document if it is not. (It more properly belongs in pull-requests.md as it is information that is not specific to new Collaborators.) I am not putting it in pullrequests.md because that document is already plenty long and detailed, and includes advice on writing good commit messages, which tend to become the pull request descriptions anyway. PR-URL: https://github.com/nodejs/node/pull/21028 Reviewed-By: Jon Moss Reviewed-By: Vse Mozhet Byt Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- doc/onboarding-extras.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/onboarding-extras.md b/doc/onboarding-extras.md index 62a7f7bb6b2837..74317c7e2bc962 100644 --- a/doc/onboarding-extras.md +++ b/doc/onboarding-extras.md @@ -93,7 +93,3 @@ to update from nodejs/node: * `git checkout master` * `git remote update -p` OR `git fetch --all` * `git merge --ff-only upstream/master` (or `REMOTENAME/BRANCH`) - -## Best practices - -* When making PRs, spend time writing a thorough description. From f5bf2c8d0859225ab4f267ac9369b78bf4c2a661 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 29 May 2018 20:15:41 -0700 Subject: [PATCH 48/93] doc: move upstream information to onboarding doc Move information about setting `upstream` remote and updating from `upstream` out of `onboarding-extras` and into `onboarding`. Previously, a link was provided in `onboarding` to the section. This puts all the git setup information for Collaborator onboardings in one place. PR-URL: https://github.com/nodejs/node/pull/21029 Reviewed-By: Jon Moss Reviewed-By: Vse Mozhet Byt Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- doc/onboarding-extras.md | 10 ---------- doc/onboarding.md | 8 ++++++-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/doc/onboarding-extras.md b/doc/onboarding-extras.md index 74317c7e2bc962..c9fbc56ad0210b 100644 --- a/doc/onboarding-extras.md +++ b/doc/onboarding-extras.md @@ -83,13 +83,3 @@ need to be attached anymore, as only important bugfixes will be included. * Architecture labels * `arm`, `mips`, `s390`, `ppc` * No x86{_64}, since that is the implied default - -## Updating Node.js from Upstream - -* `git remote add upstream git://github.com/nodejs/node.git` - -to update from nodejs/node: - -* `git checkout master` -* `git remote update -p` OR `git fetch --all` -* `git merge --ff-only upstream/master` (or `REMOTENAME/BRANCH`) diff --git a/doc/onboarding.md b/doc/onboarding.md index af4e2bb256b967..39c517e1f593c7 100644 --- a/doc/onboarding.md +++ b/doc/onboarding.md @@ -38,7 +38,12 @@ onboarding session. apply.whitespace fix` * Always continue to PR from your own GitHub fork * Branches in the `nodejs/node` repository are only for release lines - * See [Updating Node.js from Upstream][] + * Add the canonical nodejs repository as `upstream` remote: + * `git remote add upstream git://github.com/nodejs/node.git` + * To update from `upstream`: + * `git checkout master` + * `git remote update -p` OR `git fetch --all` + * `git merge --ff-only upstream/master` (or `REMOTENAME/BRANCH`) * Make a new branch for each PR you submit. * Membership: Consider making your membership in the Node.js GitHub organization public. This makes it easier to identify Collaborators. @@ -251,6 +256,5 @@ needs to be pointed out separately during the onboarding. [Publicizing or hiding organization membership]: https://help.github.com/articles/publicizing-or-hiding-organization-membership/ [set up the credentials]: https://github.com/nodejs/node-core-utils#setting-up-credentials [two-factor authentication]: https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/ -[Updating Node.js from Upstream]: ./onboarding-extras.md#updating-nodejs-from-upstream [using a TOTP mobile app]: https://help.github.com/articles/configuring-two-factor-authentication-via-a-totp-mobile-app/ [who-to-cc]: ../COLLABORATOR_GUIDE.md#who-to-cc-in-the-issue-tracker From b1f0907416a0816d8f95e95b53293bdd4362e429 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 14:56:41 +0200 Subject: [PATCH 49/93] doc: use "is" rather than "has been" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In deprecations.md, there are many uses of "has been" that are mildly awkward. This changes several instances of things like "fhqwhgads() has been deprecated" to "fhqwhgads() is deprecated". Especially for non-native speakers, present tense is generally easier to read and understand than past participles. (Or at least that's my experience reading things in languages other than English.) PR-URL: https://github.com/nodejs/node/pull/21043 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: Tobias Nießen Reviewed-By: Vse Mozhet Byt Reviewed-By: Trivikram Kamat Reviewed-By: Michaël Zasso Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- doc/api/deprecations.md | 76 ++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 2f20bc5d891fd8..49631d2fca9d46 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4,8 +4,8 @@ Node.js may deprecate APIs when either: (a) use of the API is considered to be -unsafe, (b) an improved alternative API has been made available, or (c) -breaking changes to the API are expected in a future major release. +unsafe, (b) an improved alternative API is available, or (c) breaking changes to +the API are expected in a future major release. Node.js utilizes three kinds of Deprecations: @@ -27,8 +27,8 @@ be printed to `stderr` the first time the deprecated API is used. When the `--throw-deprecation` command-line flag is used, a Runtime deprecation will cause an error to be thrown. -An End-of-Life deprecation is used to identify code that either has been -removed or will soon be removed from Node.js. +An End-of-Life deprecation is used when functionality is or will soon be removed +from Node.js. ## Revoking deprecations @@ -123,7 +123,7 @@ precisely describe the actual semantics and was unnecessarily emotion-laden. Type: Documentation-only -The `constants` module has been deprecated. When requiring access to constants +The `constants` module is deprecated. When requiring access to constants relevant to specific Node.js builtin modules, developers should instead refer to the `constants` property exposed by the relevant module. For instance, `require('fs').constants` and `require('os').constants`. @@ -303,7 +303,7 @@ instead. Type: Documentation-only -The [`SlowBuffer`][] class has been deprecated. Please use +The [`SlowBuffer`][] class is deprecated. Please use [`Buffer.allocUnsafeSlow(size)`][] instead. @@ -326,7 +326,7 @@ The [`domain`][] module is deprecated and should not be used. Type: Documentation-only -The [`EventEmitter.listenerCount(emitter, eventName)`][] API has been +The [`EventEmitter.listenerCount(emitter, eventName)`][] API is deprecated. Please use [`emitter.listenerCount(eventName)`][] instead. @@ -334,7 +334,7 @@ deprecated. Please use [`emitter.listenerCount(eventName)`][] instead. Type: Documentation-only -The [`fs.exists(path, callback)`][] API has been deprecated. Please use +The [`fs.exists(path, callback)`][] API is deprecated. Please use [`fs.stat()`][] or [`fs.access()`][] instead. @@ -342,42 +342,42 @@ The [`fs.exists(path, callback)`][] API has been deprecated. Please use Type: Documentation-only -The [`fs.lchmod(path, mode, callback)`][] API has been deprecated. +The [`fs.lchmod(path, mode, callback)`][] API is deprecated. ### DEP0036: fs.lchmodSync(path, mode) Type: Documentation-only -The [`fs.lchmodSync(path, mode)`][] API has been deprecated. +The [`fs.lchmodSync(path, mode)`][] API is deprecated. ### DEP0037: fs.lchown(path, uid, gid, callback) Type: Documentation-only -The [`fs.lchown(path, uid, gid, callback)`][] API has been deprecated. +The [`fs.lchown(path, uid, gid, callback)`][] API is deprecated. ### DEP0038: fs.lchownSync(path, uid, gid) Type: Documentation-only -The [`fs.lchownSync(path, uid, gid)`][] API has been deprecated. +The [`fs.lchownSync(path, uid, gid)`][] API is deprecated. ### DEP0039: require.extensions Type: Documentation-only -The [`require.extensions`][] property has been deprecated. +The [`require.extensions`][] property is deprecated. ### DEP0040: punycode module Type: Documentation-only -The [`punycode`][] module has been deprecated. Please use a userland alternative +The [`punycode`][] module is deprecated. Please use a userland alternative instead. @@ -393,7 +393,7 @@ The `NODE_REPL_HISTORY_FILE` environment variable was removed. Please use Type: Documentation-only -The [`tls.CryptoStream`][] class has been deprecated. Please use +The [`tls.CryptoStream`][] class is deprecated. Please use [`tls.TLSSocket`][] instead. @@ -401,7 +401,7 @@ The [`tls.CryptoStream`][] class has been deprecated. Please use Type: Documentation-only -The [`tls.SecurePair`][] class has been deprecated. Please use +The [`tls.SecurePair`][] class is deprecated. Please use [`tls.TLSSocket`][] instead. @@ -409,7 +409,7 @@ The [`tls.SecurePair`][] class has been deprecated. Please use Type: Documentation-only -The [`util.isArray()`][] API has been deprecated. Please use `Array.isArray()` +The [`util.isArray()`][] API is deprecated. Please use `Array.isArray()` instead. @@ -417,14 +417,14 @@ instead. Type: Documentation-only -The [`util.isBoolean()`][] API has been deprecated. +The [`util.isBoolean()`][] API is deprecated. ### DEP0046: util.isBuffer() Type: Documentation-only -The [`util.isBuffer()`][] API has been deprecated. Please use +The [`util.isBuffer()`][] API is deprecated. Please use [`Buffer.isBuffer()`][] instead. @@ -432,98 +432,98 @@ The [`util.isBuffer()`][] API has been deprecated. Please use Type: Documentation-only -The [`util.isDate()`][] API has been deprecated. +The [`util.isDate()`][] API is deprecated. ### DEP0048: util.isError() Type: Documentation-only -The [`util.isError()`][] API has been deprecated. +The [`util.isError()`][] API is deprecated. ### DEP0049: util.isFunction() Type: Documentation-only -The [`util.isFunction()`][] API has been deprecated. +The [`util.isFunction()`][] API is deprecated. ### DEP0050: util.isNull() Type: Documentation-only -The [`util.isNull()`][] API has been deprecated. +The [`util.isNull()`][] API is deprecated. ### DEP0051: util.isNullOrUndefined() Type: Documentation-only -The [`util.isNullOrUndefined()`][] API has been deprecated. +The [`util.isNullOrUndefined()`][] API is deprecated. ### DEP0052: util.isNumber() Type: Documentation-only -The [`util.isNumber()`][] API has been deprecated. +The [`util.isNumber()`][] API is deprecated. ### DEP0053 util.isObject() Type: Documentation-only -The [`util.isObject()`][] API has been deprecated. +The [`util.isObject()`][] API is deprecated. ### DEP0054: util.isPrimitive() Type: Documentation-only -The [`util.isPrimitive()`][] API has been deprecated. +The [`util.isPrimitive()`][] API is deprecated. ### DEP0055: util.isRegExp() Type: Documentation-only -The [`util.isRegExp()`][] API has been deprecated. +The [`util.isRegExp()`][] API is deprecated. ### DEP0056: util.isString() Type: Documentation-only -The [`util.isString()`][] API has been deprecated. +The [`util.isString()`][] API is deprecated. ### DEP0057: util.isSymbol() Type: Documentation-only -The [`util.isSymbol()`][] API has been deprecated. +The [`util.isSymbol()`][] API is deprecated. ### DEP0058: util.isUndefined() Type: Documentation-only -The [`util.isUndefined()`][] API has been deprecated. +The [`util.isUndefined()`][] API is deprecated. ### DEP0059: util.log() Type: Documentation-only -The [`util.log()`][] API has been deprecated. +The [`util.log()`][] API is deprecated. ### DEP0060: util.\_extend() Type: Documentation-only -The [`util._extend()`][] API has been deprecated. +The [`util._extend()`][] API is deprecated. ### DEP0061: fs.SyncWriteStream @@ -538,7 +538,7 @@ API. No alternative API is available. Please use a userland alternative. Type: Runtime -`--debug` activates the legacy V8 debugger interface, which has been removed as +`--debug` activates the legacy V8 debugger interface, which was removed as of V8 5.8. It is replaced by Inspector which is activated with `--inspect` instead. @@ -547,7 +547,7 @@ instead. Type: Documentation-only -The `http` module `ServerResponse.prototype.writeHeader()` API has been +The `http` module `ServerResponse.prototype.writeHeader()` API is deprecated. Please use `ServerResponse.prototype.writeHead()` instead. The `ServerResponse.prototype.writeHeader()` method was never documented as an @@ -595,7 +595,7 @@ were never documented as officially supported properties. Type: Documentation-only -The `http` module `OutgoingMessage.prototype._renderHeaders()` API has been +The `http` module `OutgoingMessage.prototype._renderHeaders()` API is deprecated. The `OutgoingMessage.prototype._renderHeaders` property was never documented as @@ -654,7 +654,7 @@ This change was made while `async_hooks` was an experimental API. Type: End-of-Life Accessing several internal, undocumented properties of `net.Server` instances -with inappropriate names has been deprecated. +with inappropriate names is deprecated. As the original API was undocumented and not generally useful for non-internal code, no replacement API is provided. @@ -702,7 +702,7 @@ difference is that `querystring.parse()` does url decoding: Type: Runtime -`Module._debug()` has been deprecated. +`Module._debug()` is deprecated. The `Module._debug()` function was never documented as an officially supported API. From c74c83a4c1d766eb7341f0bd10039db2f34f1e78 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 15:15:25 +0200 Subject: [PATCH 50/93] test: avoid empty fixture in fs test Refactor test-fs-error-messages to use tmpdir for its empty directory rather than using a not-actually-empty directory called "empty" in fixtures. PR-URL: https://github.com/nodejs/node/pull/21044 Reviewed-By: Anatoli Papirovski Reviewed-By: Trivikram Kamat Reviewed-By: Richard Lau Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- test/parallel/test-fs-error-messages.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-fs-error-messages.js b/test/parallel/test-fs-error-messages.js index 28141f33f62965..f406e8743ed120 100644 --- a/test/parallel/test-fs-error-messages.js +++ b/test/parallel/test-fs-error-messages.js @@ -22,13 +22,17 @@ 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); const assert = require('assert'); const fs = require('fs'); + +tmpdir.refresh(); + const nonexistentFile = fixtures.path('non-existent'); const nonexistentDir = fixtures.path('non-existent', 'foo', 'bar'); const existingFile = fixtures.path('exit.js'); const existingFile2 = fixtures.path('create-file.js'); -const existingDir = fixtures.path('empty'); +const existingDir = tmpdir.path; const existingDir2 = fixtures.path('keys'); const { COPYFILE_EXCL } = fs.constants; const uv = process.binding('uv'); From f7886ab8ad4e177404e67c8450b2616a9ef6dd58 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 15:19:33 +0200 Subject: [PATCH 51/93] test: avoid empty fixture in module test Refactor test-module-loading to use tmpdir for its empty directory rather than using a not-actually-empty directory called "empty" in fixtures. PR-URL: https://github.com/nodejs/node/pull/21044 Reviewed-By: Anatoli Papirovski Reviewed-By: Trivikram Kamat Reviewed-By: Richard Lau Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- test/sequential/test-module-loading.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index 7bc8428fac5939..abea73c4aa616c 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -21,9 +21,11 @@ 'use strict'; const common = require('../common'); +const tmpdir = require('../common/tmpdir'); + const assert = require('assert'); -const path = require('path'); const fs = require('fs'); +const path = require('path'); const backslash = /\\/g; @@ -168,9 +170,10 @@ assert.strictEqual(require('../fixtures/foo').foo, 'ok', // Should not attempt to load a directory try { - require('../fixtures/empty'); + tmpdir.refresh(); + require(tmpdir.path); } catch (err) { - assert.strictEqual(err.message, 'Cannot find module \'../fixtures/empty\''); + assert.strictEqual(err.message, `Cannot find module '${tmpdir.path}'`); } { @@ -284,7 +287,6 @@ try { 'fixtures/registerExt.test': {}, 'fixtures/registerExt.hello.world': {}, 'fixtures/registerExt2.test': {}, - 'fixtures/empty.js': {}, 'fixtures/module-load-order/file1': {}, 'fixtures/module-load-order/file2.js': {}, 'fixtures/module-load-order/file3.node': {}, From 60abd08c7f45f934607403fb2027dde75effd258 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 15:19:48 +0200 Subject: [PATCH 52/93] test: remove unused empty fixture The not-quite-empty directory called "empty" in fixtures was replaced in tests with `tmpdir.path` (after calling `tmpdir.refresh()` to ensure that it is empty). The fixture is removed in this commit. PR-URL: https://github.com/nodejs/node/pull/21044 Reviewed-By: Anatoli Papirovski Reviewed-By: Trivikram Kamat Reviewed-By: Richard Lau Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- test/fixtures/empty/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/fixtures/empty/.gitkeep diff --git a/test/fixtures/empty/.gitkeep b/test/fixtures/empty/.gitkeep deleted file mode 100644 index e69de29bb2d1d6..00000000000000 From 2edf1728a0ec9722fe60038239846ee9e6107b39 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 15:24:19 +0200 Subject: [PATCH 53/93] doc: fix typos on `e.g.` abbreviations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `eg.` was used in two places where `e.g.` was intended. Replace one instance with `e.g.` and rewrite the other instance to not require the abbreviation at all. PR-URL: https://github.com/nodejs/node/pull/21045 Reviewed-By: Anna Henningsen Reviewed-By: Vse Mozhet Byt Reviewed-By: Trivikram Kamat Reviewed-By: Weijia Wang Reviewed-By: Tobias Nießen Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Michaël Zasso Reviewed-By: Benjamin Gruenbaum Reviewed-By: Yuta Hiroto --- doc/api/dns.md | 2 +- doc/api/fs.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/dns.md b/doc/api/dns.md index 74504910c24107..93f91a6e351c65 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -508,7 +508,7 @@ will be present on the object: | `'PTR'` | `value` | | `'SOA'` | Refer to [`dns.resolveSoa()`][] | | `'SRV'` | Refer to [`dns.resolveSrv()`][] | -| `'TXT'` | This type of record contains an array property called `entries` which refers to [`dns.resolveTxt()`][], eg. `{ entries: ['...'], type: 'TXT' }` | +| `'TXT'` | This type of record contains an array property called `entries` which refers to [`dns.resolveTxt()`][], e.g. `{ entries: ['...'], type: 'TXT' }` | Here is an example of the `ret` object passed to the callback: diff --git a/doc/api/fs.md b/doc/api/fs.md index 435cc56d18dffe..c2daa8d71a5055 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -2136,7 +2136,7 @@ by [Naming Files, Paths, and Namespaces][]. Under NTFS, if the filename contains a colon, Node.js will open a file system stream, as described by [this MSDN page][MSDN-Using-Streams]. -Functions based on `fs.open()` exhibit this behavior as well. eg. +Functions based on `fs.open()` exhibit this behavior as well: `fs.writeFile()`, `fs.readFile()`, etc. ## fs.openSync(path, flags[, mode]) From 261ef1d2428bd38a63b0d366483e5286af862e69 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 14:37:40 +0200 Subject: [PATCH 54/93] doc: remove POST_STATUS_TO_PR from onboarding.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POST_STATUS_TO_PR is checked/enabled by default so there is no longer a need to mention that it should be checked in onboarding.md. There is almost never a situation when it should be unchecked. PR-URL: https://github.com/nodejs/node/pull/21042 Reviewed-By: Refael Ackermann Reviewed-By: Jon Moss Reviewed-By: Vse Mozhet Byt Reviewed-By: Trivikram Kamat Reviewed-By: Tobias Nießen Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- doc/onboarding.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/onboarding.md b/doc/onboarding.md index 39c517e1f593c7..1474d24f1d6b05 100644 --- a/doc/onboarding.md +++ b/doc/onboarding.md @@ -185,9 +185,7 @@ onboarding session. request containing the code you wish to test. For example, if the URL for the pull request is `https://github.com/nodejs/node/issues/7006`, then put `7006` in the `PR_ID`. - * The remaining elements on the form are typically unchanged with the - exception of `POST_STATUS_TO_PR`. Check that if you want a CI status - indicator to be automatically inserted into the PR. + * The remaining elements on the form are typically unchanged. * If you need help with something CI-related: * Use #node-dev (IRC) to talk to other Collaborators. * Use #node-build (IRC) to talk to the Build WG members who maintain the CI From a30bf55e69433bf5fea0f75f93fd28c5c2e96c52 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 14:31:23 +0200 Subject: [PATCH 55/93] lib: use focused ESLint disabling in util.js Instead of disabling all ESLint rules for two lines that require a violation of no-control-regex, disable only the no-control-regex rule. PR-URL: https://github.com/nodejs/node/pull/21041 Reviewed-By: Gus Caplan Reviewed-By: Vse Mozhet Byt Reviewed-By: Trivikram Kamat Reviewed-By: Weijia Wang Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- lib/util.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index 900ced1b46133f..5a4e52b62676b2 100644 --- a/lib/util.js +++ b/lib/util.js @@ -87,10 +87,11 @@ const errorToString = Error.prototype.toString; let CIRCULAR_ERROR_MESSAGE; let internalDeepEqual; -/* eslint-disable */ +/* eslint-disable no-control-regex */ const strEscapeSequencesRegExp = /[\x00-\x1f\x27\x5c]/; const strEscapeSequencesReplacer = /[\x00-\x1f\x27\x5c]/g; -/* eslint-enable */ +/* eslint-enable no-control-regex */ + const keyStrRegExp = /^[a-zA-Z_][a-zA-Z_0-9]*$/; const numberRegExp = /^(0|[1-9][0-9]*)$/; From 29c35bd0deba068a0bdd02a63adfb56020216491 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 07:56:48 +0000 Subject: [PATCH 56/93] doc: remove link prediction from STYLE_GUIDE.md Remove promise to eventually link an example document to show level-one heading. The style guide has been fine without the example doc for a long time. The statement is already clear. And the style guide itself is an example. We don't link to examples of wrapping at 80 characters, for example. There's no need to link just to show what a level-one heading is. (And if level-one heading is unclear, then it may be preferable to improve the terminology rather than to link to an example.) PR-URL: https://github.com/nodejs/node/pull/21031 Reviewed-By: Richard Lau Reviewed-By: Vse Mozhet Byt Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- doc/STYLE_GUIDE.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/STYLE_GUIDE.md b/doc/STYLE_GUIDE.md index a875a31b83d14a..610b012dda5570 100644 --- a/doc/STYLE_GUIDE.md +++ b/doc/STYLE_GUIDE.md @@ -26,8 +26,7 @@ fragment of a clause. * Place end-of-sentence punctuation inside wrapping elements — periods go inside parentheses and quotes, not after. -* Documents must start with a level-one heading. An example document will be - linked here eventually. +* Documents must start with a level-one heading. * Prefer affixing links to inlining links — prefer `[a link][]` to `[a link](http://example.com)`. * When documenting APIs, note the version the API was introduced in at From be249d9eb5972ab08b09733d9a3608dcd27ef86d Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Sat, 2 Jun 2018 00:30:17 +0900 Subject: [PATCH 57/93] benchmark: fix "comparisons"' typo PR-URL: https://github.com/nodejs/node/pull/21085 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Lance Ball Reviewed-By: Luigi Pinca Reviewed-By: Rich Trott Reviewed-By: Richard Lau --- benchmark/compare.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark/compare.R b/benchmark/compare.R index 1527d680c38182..7a0c89af3de4c5 100644 --- a/benchmark/compare.R +++ b/benchmark/compare.R @@ -107,8 +107,8 @@ options(width = 200); print(statistics); cat("\n") cat(sprintf( -"Be aware that when doing many comparisions the risk of a false-positive -result increases. In this case there are %d comparisions, you can thus +"Be aware that when doing many comparisons the risk of a false-positive +result increases. In this case there are %d comparisons, you can thus expect the following amount of false-positive results: %.2f false positives, when considering a 5%% risk acceptance (*, **, ***), %.2f false positives, when considering a 1%% risk acceptance (**, ***), From 15aa3c10461647d27a8cee7d134267e1fe45ec9b Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 14:23:32 +0200 Subject: [PATCH 58/93] doc: add notable-change to onboarding.md exercise Pull requests that add new Collaborators should be labeled `notable-change`. Make a note of this in onboarding.md. PR-URL: https://github.com/nodejs/node/pull/21040 Reviewed-By: Vse Mozhet Byt Reviewed-By: Trivikram Kamat Reviewed-By: Refael Ackermann Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- doc/onboarding.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/onboarding.md b/doc/onboarding.md index 1474d24f1d6b05..0748c1be7dbb44 100644 --- a/doc/onboarding.md +++ b/doc/onboarding.md @@ -211,7 +211,7 @@ needs to be pointed out separately during the onboarding. -1` * Collaborators are in alphabetical order by GitHub username. * Optionally, include your personal pronouns. -* Label your pull request with the `doc` subsystem label. +* Label your pull request with the `doc` and `notable-change` labels. * Run CI on the PR. Because the PR does not affect any code, use the `node-test-pull-request-lite` CI task. Alternatively, use the usual `node-test-pull-request` CI task and cancel it after the linter and one other From a3fdd2e4c5ff3ed9cc4390a216c1a38a1d51d647 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 08:39:25 +0000 Subject: [PATCH 59/93] test: add option to test-benchmark-timers Add option to test-benchmark-timers such that all benchmark files return only a single set of results. (This helps prevent benchmark tests from taking a long time to run.) Alphabetize options in the file. PR-URL: https://github.com/nodejs/node/pull/21032 Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski --- test/parallel/test-benchmark-timers.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-benchmark-timers.js b/test/parallel/test-benchmark-timers.js index 433a12e8258c64..af3c49bd714742 100644 --- a/test/parallel/test-benchmark-timers.js +++ b/test/parallel/test-benchmark-timers.js @@ -6,7 +6,8 @@ const runBenchmark = require('../common/benchmark'); runBenchmark('timers', [ + 'direction=start', + 'n=1', 'type=depth', - 'n=1' ], { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); From c8ee379d8582e4fbe446b98897932faa82519102 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 08:46:38 +0000 Subject: [PATCH 60/93] test: run crypto benchmark only once in tests Prevent crypto benchmark files from running more than one benchmark during tests. PR-URL: https://github.com/nodejs/node/pull/21032 Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski --- benchmark/crypto/aes-gcm-throughput.js | 3 +++ benchmark/crypto/cipher-stream.js | 3 +++ test/parallel/test-benchmark-crypto.js | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/benchmark/crypto/aes-gcm-throughput.js b/benchmark/crypto/aes-gcm-throughput.js index 5c1e71e7280575..cd8f29c8c7d7b2 100644 --- a/benchmark/crypto/aes-gcm-throughput.js +++ b/benchmark/crypto/aes-gcm-throughput.js @@ -9,6 +9,9 @@ const bench = common.createBenchmark(main, { }); function main({ n, len, cipher }) { + // Default cipher for tests. + if (cipher === '') + cipher = 'aes-128-gcm'; const message = Buffer.alloc(len, 'b'); const key = crypto.randomBytes(keylen[cipher]); const iv = crypto.randomBytes(12); diff --git a/benchmark/crypto/cipher-stream.js b/benchmark/crypto/cipher-stream.js index 64f6ff7b7292be..9f986dfb36b60d 100644 --- a/benchmark/crypto/cipher-stream.js +++ b/benchmark/crypto/cipher-stream.js @@ -10,6 +10,9 @@ const bench = common.createBenchmark(main, { }); function main({ api, cipher, type, len, writes }) { + // Default cipher for tests. + if (cipher === '') + cipher = 'AES192'; 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. diff --git a/test/parallel/test-benchmark-crypto.js b/test/parallel/test-benchmark-crypto.js index 2e78d78bc93985..f24edf675f92f0 100644 --- a/test/parallel/test-benchmark-crypto.js +++ b/test/parallel/test-benchmark-crypto.js @@ -12,14 +12,15 @@ const runBenchmark = require('../common/benchmark'); runBenchmark('crypto', [ - 'n=1', 'algo=sha256', 'api=stream', + 'cipher=', 'keylen=1024', 'len=1', + 'n=1', 'out=buffer', 'type=buf', 'v=crypto', - 'writes=1' + 'writes=1', ], { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); From 90d86586d2a3b83a35ad083896d6b3790a71cfea Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 03:32:42 +0000 Subject: [PATCH 61/93] benchmark: refactor deepequal-buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a minor refactor of benchmark/assert/deepequal-buffer.js to reduce exceptions that need to be made for lint compliance. PR-URL: https://github.com/nodejs/node/pull/21030 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- benchmark/assert/deepequal-buffer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/benchmark/assert/deepequal-buffer.js b/benchmark/assert/deepequal-buffer.js index 9556a81ec3b151..fe3f6f9754c3a0 100644 --- a/benchmark/assert/deepequal-buffer.js +++ b/benchmark/assert/deepequal-buffer.js @@ -14,6 +14,8 @@ const bench = common.createBenchmark(main, { }); function main({ len, n, method }) { + if (!method) + method = 'deepEqual'; const data = Buffer.allocUnsafe(len + 1); const actual = Buffer.alloc(len); const expected = Buffer.alloc(len); @@ -22,8 +24,7 @@ function main({ len, n, method }) { data.copy(expected); data.copy(expectedWrong); - // eslint-disable-next-line no-restricted-properties - const fn = method !== '' ? assert[method] : assert.deepEqual; + const fn = assert[method]; const value2 = method.includes('not') ? expectedWrong : expected; bench.start(); From 9b0fc59723819d879d14445866f71deb30829792 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 03:38:35 +0000 Subject: [PATCH 62/93] benchmark: refactor deepequal-map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a minor refactor of benchmark/assert/deepequal-map.js to reduce exceptions that need to be made for lint compliance. PR-URL: https://github.com/nodejs/node/pull/21030 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- benchmark/assert/deepequal-map.js | 33 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/benchmark/assert/deepequal-map.js b/benchmark/assert/deepequal-map.js index bdd3c5c6b8c514..c6c7173fe8ed6d 100644 --- a/benchmark/assert/deepequal-map.js +++ b/benchmark/assert/deepequal-map.js @@ -1,9 +1,8 @@ 'use strict'; -/* eslint-disable no-restricted-properties */ - const common = require('../common.js'); -const assert = require('assert'); +const { deepEqual, deepStrictEqual, notDeepEqual, notDeepStrictEqual } = + require('assert'); const bench = common.createBenchmark(main, { n: [5e2], @@ -47,74 +46,74 @@ function main({ n, len, method }) { // Empty string falls through to next line as default, mostly for tests. case 'deepEqual_primitiveOnly': values = array.map((_, i) => [`str_${i}`, 123]); - benchmark(assert.deepEqual, n, values); + benchmark(deepEqual, n, values); break; case 'deepStrictEqual_primitiveOnly': values = array.map((_, i) => [`str_${i}`, 123]); - benchmark(assert.deepStrictEqual, n, values); + benchmark(deepStrictEqual, n, values); break; case 'deepEqual_objectOnly': values = array.map((_, i) => [[`str_${i}`, 1], 123]); - benchmark(assert.deepEqual, n, values); + benchmark(deepEqual, n, values); break; case 'deepStrictEqual_objectOnly': values = array.map((_, i) => [[`str_${i}`, 1], 123]); - benchmark(assert.deepStrictEqual, n, values); + benchmark(deepStrictEqual, n, values); break; case 'deepEqual_mixed': values = array.map((_, i) => [i % 2 ? [`str_${i}`, 1] : `str_${i}`, 123]); - benchmark(assert.deepEqual, n, values); + benchmark(deepEqual, n, values); break; case 'deepStrictEqual_mixed': values = array.map((_, i) => [i % 2 ? [`str_${i}`, 1] : `str_${i}`, 123]); - benchmark(assert.deepStrictEqual, n, values); + benchmark(deepStrictEqual, n, values); break; case 'deepEqual_looseMatches': values = array.map((_, i) => [i, i]); values2 = values.slice().map((v) => [String(v[0]), String(v[1])]); - benchmark(assert.deepEqual, n, values, values2); + benchmark(deepEqual, n, values, values2); break; case 'notDeepEqual_primitiveOnly': values = array.map((_, i) => [`str_${i}`, 123]); values2 = values.slice(0); values2[Math.floor(len / 2)] = ['w00t', 123]; - benchmark(assert.notDeepEqual, n, values, values2); + benchmark(notDeepEqual, n, values, values2); break; case 'notDeepStrictEqual_primitiveOnly': values = array.map((_, i) => [`str_${i}`, 123]); values2 = values.slice(0); values2[Math.floor(len / 2)] = ['w00t', 123]; - benchmark(assert.notDeepStrictEqual, n, values, values2); + benchmark(notDeepStrictEqual, n, values, values2); break; case 'notDeepEqual_objectOnly': values = array.map((_, i) => [[`str_${i}`, 1], 123]); values2 = values.slice(0); values2[Math.floor(len / 2)] = [['w00t'], 123]; - benchmark(assert.notDeepEqual, n, values, values2); + benchmark(notDeepEqual, n, values, values2); break; case 'notDeepStrictEqual_objectOnly': values = array.map((_, i) => [[`str_${i}`, 1], 123]); values2 = values.slice(0); values2[Math.floor(len / 2)] = [['w00t'], 123]; - benchmark(assert.notDeepStrictEqual, n, values, values2); + benchmark(notDeepStrictEqual, n, values, values2); break; case 'notDeepEqual_mixed': values = array.map((_, i) => [i % 2 ? [`str_${i}`, 1] : `str_${i}`, 123]); values2 = values.slice(0); values2[0] = ['w00t', 123]; - benchmark(assert.notDeepEqual, n, values, values2); + benchmark(notDeepEqual, n, values, values2); break; case 'notDeepStrictEqual_mixed': values = array.map((_, i) => [i % 2 ? [`str_${i}`, 1] : `str_${i}`, 123]); values2 = values.slice(0); values2[0] = ['w00t', 123]; - benchmark(assert.notDeepStrictEqual, n, values, values2); + benchmark(notDeepStrictEqual, n, values, values2); break; case 'notDeepEqual_looseMatches': values = array.map((_, i) => [i, i]); values2 = values.slice().map((v) => [String(v[0]), String(v[1])]); values2[len - 1] = [String(len + 1), String(len + 1)]; - benchmark(assert.notDeepEqual, n, values, values2); + benchmark(notDeepEqual, n, values, values2); break; default: throw new Error(`Unsupported method ${method}`); From 4d714421e9abc2a4c92fac831331e21bc615856e Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 03:41:57 +0000 Subject: [PATCH 63/93] benchmark: refactor deepequal-object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a minor refactor of benchmark/assert/deepequal-object.js to reduce exceptions that need to be made for lint compliance. PR-URL: https://github.com/nodejs/node/pull/21030 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- benchmark/assert/deepequal-object.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/benchmark/assert/deepequal-object.js b/benchmark/assert/deepequal-object.js index 4c95006b3b8bc7..124943b19ec761 100644 --- a/benchmark/assert/deepequal-object.js +++ b/benchmark/assert/deepequal-object.js @@ -29,13 +29,15 @@ function main({ size, n, method }) { // TODO: Fix this "hack". `n` should not be manipulated. n = n / size; + if (!method) + method = 'deepEqual'; + const source = Array.apply(null, Array(size)); const actual = createObj(source); const expected = createObj(source); const expectedWrong = createObj(source, '4'); - // eslint-disable-next-line no-restricted-properties - const fn = method !== '' ? assert[method] : assert.deepEqual; + const fn = assert[method]; const value2 = method.includes('not') ? expectedWrong : expected; bench.start(); From 6fbb00e8873f7985784a0c8287504a52735a5ea6 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 03:45:24 +0000 Subject: [PATCH 64/93] benchmark: refactor prims-and-objs-big-array-set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a minor refactor of benchmark/assert/deepequal-prims-and-objs-big-array-set.js to reduce exceptions that need to be made for lint compliance. PR-URL: https://github.com/nodejs/node/pull/21030 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- .../deepequal-prims-and-objs-big-array-set.js | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) 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 90dbf1059361a5..4578e5a250f392 100644 --- a/benchmark/assert/deepequal-prims-and-objs-big-array-set.js +++ b/benchmark/assert/deepequal-prims-and-objs-big-array-set.js @@ -1,7 +1,8 @@ 'use strict'; const common = require('../common.js'); -const assert = require('assert'); +const { deepEqual, deepStrictEqual, notDeepEqual, notDeepStrictEqual } = + require('assert'); const primValues = { 'null': null, @@ -61,32 +62,28 @@ function main({ n, len, primitive, method }) { // Empty string falls through to next line as default, mostly for tests. case '': case 'deepEqual_Array': - // eslint-disable-next-line no-restricted-properties - run(assert.deepEqual, n, actual, expected); + run(deepEqual, n, actual, expected); break; case 'deepStrictEqual_Array': - run(assert.deepStrictEqual, n, actual, expected); + run(deepStrictEqual, n, actual, expected); break; case 'notDeepEqual_Array': - // eslint-disable-next-line no-restricted-properties - run(assert.notDeepEqual, n, actual, expectedWrong); + run(notDeepEqual, n, actual, expectedWrong); break; case 'notDeepStrictEqual_Array': - run(assert.notDeepStrictEqual, n, actual, expectedWrong); + run(notDeepStrictEqual, n, actual, expectedWrong); break; case 'deepEqual_Set': - // eslint-disable-next-line no-restricted-properties - run(assert.deepEqual, n, actualSet, expectedSet); + run(deepEqual, n, actualSet, expectedSet); break; case 'deepStrictEqual_Set': - run(assert.deepStrictEqual, n, actualSet, expectedSet); + run(deepStrictEqual, n, actualSet, expectedSet); break; case 'notDeepEqual_Set': - // eslint-disable-next-line no-restricted-properties - run(assert.notDeepEqual, n, actualSet, expectedWrongSet); + run(notDeepEqual, n, actualSet, expectedWrongSet); break; case 'notDeepStrictEqual_Set': - run(assert.notDeepStrictEqual, n, actualSet, expectedWrongSet); + run(notDeepStrictEqual, n, actualSet, expectedWrongSet); break; default: throw new Error(`Unsupported method "${method}"`); From 56c67595db5d22d9868050c80bf03d11e9cb0ce3 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 03:47:41 +0000 Subject: [PATCH 65/93] benchmark: refactor prims-and-objs-big-loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a minor refactor of benchmark/assert/deepequal-prims-and-objs-big-loop.js to reduce exceptions that need to be made for lint compliance. PR-URL: https://github.com/nodejs/node/pull/21030 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- benchmark/assert/deepequal-prims-and-objs-big-loop.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/benchmark/assert/deepequal-prims-and-objs-big-loop.js b/benchmark/assert/deepequal-prims-and-objs-big-loop.js index ec51201d51839d..f1183dab32a3fb 100644 --- a/benchmark/assert/deepequal-prims-and-objs-big-loop.js +++ b/benchmark/assert/deepequal-prims-and-objs-big-loop.js @@ -25,13 +25,14 @@ const bench = common.createBenchmark(main, { }); function main({ n, primitive, method }) { + if (!method) + method = 'deepEqual'; const prim = primValues[primitive]; const actual = prim; const expected = prim; const expectedWrong = 'b'; - // eslint-disable-next-line no-restricted-properties - const fn = method !== '' ? assert[method] : assert.deepEqual; + const fn = assert[method]; const value2 = method.includes('not') ? expectedWrong : expected; bench.start(); From 686587ba1af9a983f86863fcdeb3c9c651d80233 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 03:50:31 +0000 Subject: [PATCH 66/93] benchmark: refactor deepequal-set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a minor refactor of benchmark/assert/deepequal-set.js to reduce exceptions that need to be made for lint compliance. PR-URL: https://github.com/nodejs/node/pull/21030 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- benchmark/assert/deepequal-set.js | 33 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/benchmark/assert/deepequal-set.js b/benchmark/assert/deepequal-set.js index e70ddf10e93626..6769e5e37fafb7 100644 --- a/benchmark/assert/deepequal-set.js +++ b/benchmark/assert/deepequal-set.js @@ -1,9 +1,8 @@ 'use strict'; -/* eslint-disable no-restricted-properties */ - const common = require('../common.js'); -const assert = require('assert'); +const { deepEqual, deepStrictEqual, notDeepEqual, notDeepStrictEqual } = + require('assert'); const bench = common.createBenchmark(main, { n: [5e2], @@ -48,60 +47,60 @@ function main({ n, len, method }) { // Empty string falls through to next line as default, mostly for tests. case 'deepEqual_primitiveOnly': values = array.map((_, i) => `str_${i}`); - benchmark(assert.deepEqual, n, values); + benchmark(deepEqual, n, values); break; case 'deepStrictEqual_primitiveOnly': values = array.map((_, i) => `str_${i}`); - benchmark(assert.deepStrictEqual, n, values); + benchmark(deepStrictEqual, n, values); break; case 'deepEqual_objectOnly': values = array.map((_, i) => [`str_${i}`, null]); - benchmark(assert.deepEqual, n, values); + benchmark(deepEqual, n, values); break; case 'deepStrictEqual_objectOnly': values = array.map((_, i) => [`str_${i}`, null]); - benchmark(assert.deepStrictEqual, n, values); + benchmark(deepStrictEqual, n, values); break; case 'deepEqual_mixed': values = array.map((_, i) => { return i % 2 ? [`str_${i}`, null] : `str_${i}`; }); - benchmark(assert.deepEqual, n, values); + benchmark(deepEqual, n, values); break; case 'deepStrictEqual_mixed': values = array.map((_, i) => { return i % 2 ? [`str_${i}`, null] : `str_${i}`; }); - benchmark(assert.deepStrictEqual, n, values); + benchmark(deepStrictEqual, n, values); break; case 'deepEqual_looseMatches': values = array.map((_, i) => i); values2 = values.slice().map((v) => String(v)); - benchmark(assert.deepEqual, n, values, values2); + benchmark(deepEqual, n, values, values2); break; case 'notDeepEqual_primitiveOnly': values = array.map((_, i) => `str_${i}`); values2 = values.slice(0); values2[Math.floor(len / 2)] = 'w00t'; - benchmark(assert.notDeepEqual, n, values, values2); + benchmark(notDeepEqual, n, values, values2); break; case 'notDeepStrictEqual_primitiveOnly': values = array.map((_, i) => `str_${i}`); values2 = values.slice(0); values2[Math.floor(len / 2)] = 'w00t'; - benchmark(assert.notDeepStrictEqual, n, values, values2); + benchmark(notDeepStrictEqual, n, values, values2); break; case 'notDeepEqual_objectOnly': values = array.map((_, i) => [`str_${i}`, null]); values2 = values.slice(0); values2[Math.floor(len / 2)] = ['w00t']; - benchmark(assert.notDeepEqual, n, values, values2); + benchmark(notDeepEqual, n, values, values2); break; case 'notDeepStrictEqual_objectOnly': values = array.map((_, i) => [`str_${i}`, null]); values2 = values.slice(0); values2[Math.floor(len / 2)] = ['w00t']; - benchmark(assert.notDeepStrictEqual, n, values, values2); + benchmark(notDeepStrictEqual, n, values, values2); break; case 'notDeepEqual_mixed': values = array.map((_, i) => { @@ -109,7 +108,7 @@ function main({ n, len, method }) { }); values2 = values.slice(); values2[0] = 'w00t'; - benchmark(assert.notDeepEqual, n, values, values2); + benchmark(notDeepEqual, n, values, values2); break; case 'notDeepStrictEqual_mixed': values = array.map((_, i) => { @@ -117,13 +116,13 @@ function main({ n, len, method }) { }); values2 = values.slice(); values2[0] = 'w00t'; - benchmark(assert.notDeepStrictEqual, n, values, values2); + benchmark(notDeepStrictEqual, n, values, values2); break; case 'notDeepEqual_looseMatches': values = array.map((_, i) => i); values2 = values.slice().map((v) => String(v)); values2[len - 1] = String(len + 1); - benchmark(assert.notDeepEqual, n, values, values2); + benchmark(notDeepEqual, n, values, values2); break; default: throw new Error(`Unsupported method "${method}"`); From b8470b929f55396ad1b8813acab2002717651bf7 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 03:53:11 +0000 Subject: [PATCH 67/93] benchmark: refactor deepequal-typedarrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a minor refactor of benchmark/assert/deepequal-typedarrays.js to reduce exceptions that need to be made for lint compliance. PR-URL: https://github.com/nodejs/node/pull/21030 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- benchmark/assert/deepequal-typedarrays.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/benchmark/assert/deepequal-typedarrays.js b/benchmark/assert/deepequal-typedarrays.js index 50e6e525b20a0c..c4d8f434bf4e8a 100644 --- a/benchmark/assert/deepequal-typedarrays.js +++ b/benchmark/assert/deepequal-typedarrays.js @@ -25,6 +25,8 @@ const bench = common.createBenchmark(main, { }); function main({ type, n, len, method }) { + if (!method) + method = 'deepEqual'; const clazz = global[type]; const actual = new clazz(len); const expected = new clazz(len); @@ -32,8 +34,7 @@ function main({ type, n, len, method }) { const wrongIndex = Math.floor(len / 2); expectedWrong[wrongIndex] = 123; - // eslint-disable-next-line no-restricted-properties - const fn = method !== '' ? assert[method] : assert.deepEqual; + const fn = assert[method]; const value2 = method.includes('not') ? expectedWrong : expected; bench.start(); From 9ada68b1868afe351093d80c60b1b16371a8049f Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 30 May 2018 04:03:52 +0000 Subject: [PATCH 68/93] benchmark: refactor benchmark/assert/throws.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a minor refactor of benchmark/assert/throws.js to reduce exceptions that need to be made for lint compliance. PR-URL: https://github.com/nodejs/node/pull/21030 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- benchmark/assert/throws.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/benchmark/assert/throws.js b/benchmark/assert/throws.js index 2409d19206e353..a8a7bd4509e1ca 100644 --- a/benchmark/assert/throws.js +++ b/benchmark/assert/throws.js @@ -1,7 +1,7 @@ 'use strict'; const common = require('../common.js'); -const assert = require('assert'); +const { throws, doesNotThrow } = require('assert'); const bench = common.createBenchmark(main, { n: [1e6], @@ -14,8 +14,8 @@ const bench = common.createBenchmark(main, { }); function main({ n, method }) { - const throws = () => { throw new TypeError('foobar'); }; - const doesNotThrow = () => { return 'foobar'; }; + const throwError = () => { throw new TypeError('foobar'); }; + const doNotThrowError = () => { return 'foobar'; }; const regExp = /foobar/; const message = 'failure'; var i; @@ -26,30 +26,28 @@ function main({ n, method }) { case 'doesNotThrow': bench.start(); for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-syntax - assert.doesNotThrow(doesNotThrow); + doesNotThrow(doNotThrowError); } bench.end(n); break; case 'throws': bench.start(); for (i = 0; i < n; ++i) { - // eslint-disable-next-line no-restricted-syntax - assert.throws(throws); + throws(throwError); } bench.end(n); break; case 'throws_TypeError': bench.start(); for (i = 0; i < n; ++i) { - assert.throws(throws, TypeError, message); + throws(throwError, TypeError, message); } bench.end(n); break; case 'throws_RegExp': bench.start(); for (i = 0; i < n; ++i) { - assert.throws(throws, regExp, message); + throws(throwError, regExp, message); } bench.end(n); break; From 44fe78b09a7d2ce122bacdca68e2d89264e2a6a2 Mon Sep 17 00:00:00 2001 From: Miklos Suveges Date: Tue, 29 May 2018 01:47:27 +0200 Subject: [PATCH 69/93] stream: inline needMoreData function Inline the needMoreData function since it has only one call place. Update the related comment. Add a test for the edge case where HWM=0 and state.length=0. Add a test for ReadableStream.read(n) method's edge case where n, HWM and state.length are all zero. This proves that there is no easy way to simplify the check at https://github.com/nodejs/node/blob/master/lib/_stream_readable.js#L440 Fixes: https://github.com/nodejs/node/issues/19893 Refs: https://github.com/nodejs/node/pull/19896 PR-URL: https://github.com/nodejs/node/pull/21009 Reviewed-By: Matteo Collina Reviewed-By: James M Snell Reviewed-By: Lance Ball Reviewed-By: Trivikram Kamat --- lib/_stream_readable.js | 19 ++---- test/parallel/test-streams-highwatermark.js | 73 ++++++++++++++------- 2 files changed, 55 insertions(+), 37 deletions(-) diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index a8e52f5f1d6c5b..31b129facd3a38 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -270,7 +270,11 @@ function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { } } - return needMoreData(state); + // We can push more data if we are below the highWaterMark. + // Also, if we have no data yet, we can stand some more bytes. + // This is to work around cases where hwm=0, such as the repl. + return !state.ended && + (state.length < state.highWaterMark || state.length === 0); } function addChunk(stream, state, chunk, addToFront) { @@ -304,19 +308,6 @@ function chunkInvalid(state, chunk) { } -// We can push more data if we are below the highWaterMark. -// Also, if we have no data yet, we can stand some -// more bytes. This is to work around cases where hwm=0, -// such as the repl. Also, if the push() triggered a -// readable event, and the user called read(largeNumber) such that -// needReadable was set, then we ought to push more, so that another -// 'readable' event will be triggered. -function needMoreData(state) { - return !state.ended && - (state.length < state.highWaterMark || - state.length === 0); -} - Readable.prototype.isPaused = function() { return this._readableState.flowing === false; }; diff --git a/test/parallel/test-streams-highwatermark.js b/test/parallel/test-streams-highwatermark.js index 377fe08e90d3f8..4dd9694a464272 100644 --- a/test/parallel/test-streams-highwatermark.js +++ b/test/parallel/test-streams-highwatermark.js @@ -1,31 +1,58 @@ 'use strict'; const common = require('../common'); -// This test ensures that the stream implementation correctly handles values -// for highWaterMark which exceed the range of signed 32 bit integers and -// rejects invalid values. - const assert = require('assert'); const stream = require('stream'); -// This number exceeds the range of 32 bit integer arithmetic but should still -// be handled correctly. -const ovfl = Number.MAX_SAFE_INTEGER; - -const readable = stream.Readable({ highWaterMark: ovfl }); -assert.strictEqual(readable._readableState.highWaterMark, ovfl); - -const writable = stream.Writable({ highWaterMark: ovfl }); -assert.strictEqual(writable._writableState.highWaterMark, ovfl); - -for (const invalidHwm of [true, false, '5', {}, -5, NaN]) { - for (const type of [stream.Readable, stream.Writable]) { - common.expectsError(() => { - type({ highWaterMark: invalidHwm }); - }, { - type: TypeError, - code: 'ERR_INVALID_OPT_VALUE', - message: `The value "${invalidHwm}" is invalid for option "highWaterMark"` - }); +{ + // This test ensures that the stream implementation correctly handles values + // for highWaterMark which exceed the range of signed 32 bit integers and + // rejects invalid values. + + // This number exceeds the range of 32 bit integer arithmetic but should still + // be handled correctly. + const ovfl = Number.MAX_SAFE_INTEGER; + + const readable = stream.Readable({ highWaterMark: ovfl }); + assert.strictEqual(readable._readableState.highWaterMark, ovfl); + + const writable = stream.Writable({ highWaterMark: ovfl }); + assert.strictEqual(writable._writableState.highWaterMark, ovfl); + + for (const invalidHwm of [true, false, '5', {}, -5, NaN]) { + for (const type of [stream.Readable, stream.Writable]) { + common.expectsError(() => { + type({ highWaterMark: invalidHwm }); + }, { + type: TypeError, + code: 'ERR_INVALID_OPT_VALUE', + message: + `The value "${invalidHwm}" is invalid for option "highWaterMark"` + }); + } + } +} + +{ + // This test ensures that the push method's implementation + // correctly handles the edge case where the highWaterMark and + // the state.length are both zero + + const readable = stream.Readable({ highWaterMark: 0 }); + + for (let i = 0; i < 3; i++) { + const needMoreData = readable.push(); + assert.strictEqual(needMoreData, true); } } + +{ + // This test ensures that the read(n) method's implementation + // correctly handles the edge case where the highWaterMark, state.length + // and n are all zero + + const readable = stream.Readable({ highWaterMark: 0 }); + + readable._read = common.mustCall(); + readable.read(0); +} From c4fc1ff29588956f20bb672ff54af92d06423647 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 1 Jun 2018 09:57:05 +0200 Subject: [PATCH 70/93] test: fix flaky async-hooks/test-zlib.zlib-binding.deflate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the typed arrays used in this test would not automatically be kept alive by the native handle when it’s using them, so the V8 garbage collector could collect them while they are still in use by the zlib module, leading to memory corruption. Fixes: https://github.com/nodejs/node/issues/20907 PR-URL: https://github.com/nodejs/node/pull/21077 Reviewed-By: Anatoli Papirovski Reviewed-By: Jeremiah Senkpiel Reviewed-By: Matteo Collina Reviewed-By: Ruben Bridgewater Reviewed-By: Joyee Cheung Reviewed-By: Rich Trott Reviewed-By: Yang Guo Reviewed-By: James M Snell --- .../test-zlib.zlib-binding.deflate.js | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/test/async-hooks/test-zlib.zlib-binding.deflate.js b/test/async-hooks/test-zlib.zlib-binding.deflate.js index e5e6a14bbbfffc..ddcba9d89630f7 100644 --- a/test/async-hooks/test-zlib.zlib-binding.deflate.js +++ b/test/async-hooks/test-zlib.zlib-binding.deflate.js @@ -21,23 +21,29 @@ assert.strictEqual(typeof hdl.uid, 'number'); assert.strictEqual(typeof hdl.triggerAsyncId, 'number'); checkInvocations(hdl, { init: 1 }, 'when created handle'); +// Store all buffers together so that they do not get +// garbage collected. +const buffers = { + writeResult: new Uint32Array(2), + dictionary: new Uint8Array(0), + inBuf: new Uint8Array([0x78]), + outBuf: new Uint8Array(1) +}; + handle.init( constants.Z_DEFAULT_WINDOWBITS, constants.Z_MIN_LEVEL, constants.Z_DEFAULT_MEMLEVEL, constants.Z_DEFAULT_STRATEGY, - new Uint32Array(2), + buffers.writeResult, function processCallback() { this.cb(); }, - Buffer.from('') + buffers.dictionary ); checkInvocations(hdl, { init: 1 }, 'when initialized handle'); -const inBuf = Buffer.from('x'); -const outBuf = Buffer.allocUnsafe(1); - let count = 2; handle.cb = common.mustCall(onwritten, 2); -handle.write(true, inBuf, 0, 1, outBuf, 0, 1); +handle.write(true, buffers.inBuf, 0, 1, buffers.outBuf, 0, 1); checkInvocations(hdl, { init: 1 }, 'when invoked write() on handle'); function onwritten() { @@ -45,7 +51,7 @@ function onwritten() { // first write checkInvocations(hdl, { init: 1, before: 1 }, 'when wrote to handle the first time'); - handle.write(true, inBuf, 0, 1, outBuf, 0, 1); + handle.write(true, buffers.inBuf, 0, 1, buffers.outBuf, 0, 1); } else { // second write checkInvocations(hdl, { init: 1, before: 2, after: 1 }, @@ -61,4 +67,7 @@ function onexit() { // TODO: destroy never called here even with large amounts of ticks // is that correct? checkInvocations(hdl, { init: 1, before: 2, after: 2 }, 'when process exits'); + + // Do something with `buffers` to keep them alive until here. + buffers.buffers = buffers; } From bd0d19dae76d3ebecccb8c16a3ee13059f994011 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 2 Jun 2018 16:01:58 +0200 Subject: [PATCH 71/93] test: minor adjustments to test-http2-respond-file PR-URL: https://github.com/nodejs/node/pull/21098 Reviewed-By: Anatoli Papirovski Reviewed-By: Rich Trott Reviewed-By: Jon Moss Reviewed-By: Richard Lau --- test/parallel/test-http2-respond-file.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/parallel/test-http2-respond-file.js b/test/parallel/test-http2-respond-file.js index 9ad8e7a69648dc..1c10ceb4350723 100644 --- a/test/parallel/test-http2-respond-file.js +++ b/test/parallel/test-http2-respond-file.js @@ -19,7 +19,7 @@ const data = fs.readFileSync(fname); const stat = fs.statSync(fname); const server = http2.createServer(); -server.on('stream', (stream) => { +server.on('stream', common.mustCall((stream) => { stream.respondWithFile(fname, { [HTTP2_HEADER_CONTENT_TYPE]: 'text/plain' }, { @@ -28,9 +28,9 @@ server.on('stream', (stream) => { headers[HTTP2_HEADER_CONTENT_LENGTH] = stat.size; } }); -}); -server.listen(0, () => { +})); +server.listen(0, common.mustCall(() => { const client = http2.connect(`http://localhost:${server.address().port}`); const req = client.request(); @@ -49,4 +49,4 @@ server.listen(0, () => { server.close(); })); req.end(); -}); +})); From 8e3e18ef7d3f48c4f852c6bf14624d14f6de00dd Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Sun, 3 Jun 2018 13:19:39 +0200 Subject: [PATCH 72/93] test: unmark test-zlib.zlib-binding.deflate flaky MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/21109 Reviewed-By: Anna Henningsen Reviewed-By: Tobias Nießen Reviewed-By: Rich Trott --- test/async-hooks/async-hooks.status | 1 - 1 file changed, 1 deletion(-) diff --git a/test/async-hooks/async-hooks.status b/test/async-hooks/async-hooks.status index f70b5c5fe5e488..7f36d5a78a6e2b 100644 --- a/test/async-hooks/async-hooks.status +++ b/test/async-hooks/async-hooks.status @@ -9,7 +9,6 @@ prefix async-hooks [$system==win32] [$system==linux] -test-zlib.zlib-binding.deflate: PASS,FLAKY [$system==macos] From 341b2c21f3df1efa01da40da31bcad1cdf3b9ae5 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Thu, 31 May 2018 10:39:19 +0200 Subject: [PATCH 73/93] http2: fix premature destroy Check stream._writableState.finished instead of stream.writable as the latter can lead to premature calls to destroy and dropped writes on busy processes. PR-URL: https://github.com/nodejs/node/pull/21051 Fixes: https://github.com/nodejs/node/issues/20750 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- lib/internal/http2/core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 97a6a5b4f1f89c..bbbc3c21300a74 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -1896,7 +1896,7 @@ class Http2Stream extends Duplex { } // TODO(mcollina): remove usage of _*State properties - if (!this.writable) { + if (this._writableState.finished) { if (!this.readable && this.closed) { this.destroy(); return; From fda8654161b7ed2247c161ae64f6f3f3efc29beb Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 1 Jun 2018 13:12:21 +0200 Subject: [PATCH 74/93] test: log before and after RSS in memory leak test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs: https://github.com/nodejs/node/issues/21076 PR-URL: https://github.com/nodejs/node/pull/21080 Reviewed-By: Tobias Nießen Reviewed-By: Rich Trott Reviewed-By: Anatoli Papirovski Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Yuta Hiroto Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Luigi Pinca --- test/parallel/test-crypto-dh-leak.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-crypto-dh-leak.js b/test/parallel/test-crypto-dh-leak.js index e57c65b8b1fceb..bcca210503299b 100644 --- a/test/parallel/test-crypto-dh-leak.js +++ b/test/parallel/test-crypto-dh-leak.js @@ -23,4 +23,4 @@ const after = process.memoryUsage().rss; // RSS should stay the same, ceteris paribus, but allow for // some slop because V8 mallocs memory during execution. -assert(after - before < 5 << 20); +assert(after - before < 5 << 20, `before=${before} after=${after}`); From c60810a85371227519dbf6ce0bd3d532b2bffc19 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 2 Jun 2018 10:03:25 +0200 Subject: [PATCH 75/93] test: increase slop limit in memory leak test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It transpires that the extra bookkeeping in debug builds sometimes makes the increase in RSS go _just_ over the 5 MB limit, by fewer than 100 kB. Double the limit so we hopefully don't run into it any time again soon. The memory leak it tests for was one where RSS grew by hundreds of megabytes over the lifetime of the test; 5 vs. 10 MB is insignificant. Fixes: https://github.com/nodejs/node/issues/21076 PR-URL: https://github.com/nodejs/node/pull/21080 Refs: https://github.com/nodejs/node/issues/21076 Reviewed-By: Tobias Nießen Reviewed-By: Rich Trott Reviewed-By: Anatoli Papirovski Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Yuta Hiroto Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Luigi Pinca --- test/parallel/test-crypto-dh-leak.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-crypto-dh-leak.js b/test/parallel/test-crypto-dh-leak.js index bcca210503299b..9ba8d29e155dc6 100644 --- a/test/parallel/test-crypto-dh-leak.js +++ b/test/parallel/test-crypto-dh-leak.js @@ -23,4 +23,4 @@ const after = process.memoryUsage().rss; // RSS should stay the same, ceteris paribus, but allow for // some slop because V8 mallocs memory during execution. -assert(after - before < 5 << 20, `before=${before} after=${after}`); +assert(after - before < 10 << 20, `before=${before} after=${after}`); From 66f4c7bdec8cee1a53deacc18cfa5bdabf810d01 Mon Sep 17 00:00:00 2001 From: Masashi Hirano Date: Mon, 4 Jun 2018 00:59:21 +0900 Subject: [PATCH 76/93] src: fix typo string_search.h comment PR-URL: https://github.com/nodejs/node/pull/21115 Reviewed-By: Anna Henningsen Reviewed-By: Vse Mozhet Byt Reviewed-By: Richard Lau Reviewed-By: Jon Moss Reviewed-By: Trivikram Kamat --- src/string_search.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string_search.h b/src/string_search.h index 9c090da247aec8..358a4c1b024e67 100644 --- a/src/string_search.h +++ b/src/string_search.h @@ -559,7 +559,7 @@ size_t StringSearch::InitialSearch( return subject.length(); } -// Perform a a single stand-alone search. +// Perform a single stand-alone search. // If searching multiple times for the same pattern, a search // object should be constructed once and the Search function then called // for each search. From 28f2dcb22a2dd4c3d7f28c7b4fb02b89600ccaea Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 3 Jun 2018 23:01:02 +0200 Subject: [PATCH 77/93] test: update test-dns error message test-dns is in the internet suite and therefore is rarely run. (That will change soon. We will run internet tests nightly in CI.) Because it is infrequently run, it was not noticed that it no longer passes. (An error message has changed to provide more information.) This change fixes the test so it passes. PR-URL: https://github.com/nodejs/node/pull/21116 Reviewed-By: Anatoli Papirovski Reviewed-By: Richard Lau Reviewed-By: Trivikram Kamat --- test/internet/test-dns.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/internet/test-dns.js b/test/internet/test-dns.js index f1b7b4ff056833..56fa370fce01cf 100644 --- a/test/internet/test-dns.js +++ b/test/internet/test-dns.js @@ -70,7 +70,7 @@ function checkWrap(req) { TEST(function test_reverse_bogus(done) { assert.throws(() => { dns.reverse('bogus ip', common.mustNotCall()); - }, /^Error: getHostByAddr EINVAL$/); + }, /^Error: getHostByAddr EINVAL bogus ip$/); done(); }); From 1e607d09103451ae607fece82e50bcee6330313a Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Fri, 1 Jun 2018 14:53:51 +0200 Subject: [PATCH 78/93] test: add source for test.wasm The original commit 74e7a4a041fe83f106bc50ebe99c961afb28a0cd ("test: add basic WebAssembly test") references the source for test.wasm and while there are tools to go from wasm to wat but having the source viewable is helpful I think. PR-URL: https://github.com/nodejs/node/pull/21082 Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Lance Ball Reviewed-By: Luigi Pinca Reviewed-By: Gus Caplan Reviewed-By: Trivikram Kamat Reviewed-By: John-David Dalton --- test/fixtures/test.wasm | Bin 44 -> 50 bytes test/fixtures/test.wat | 10 ++++++++++ 2 files changed, 10 insertions(+) create mode 100644 test/fixtures/test.wat diff --git a/test/fixtures/test.wasm b/test/fixtures/test.wasm index 8b19588df228b76c6747d04aee091cbe268592d0..da1b0330069de60ad944216d8fd1ba403dd3f761 100644 GIT binary patch delta 33 mcmdNfnjj`4z{H%GlET2i1|&nu^BEYpI2qX)6c`j3v$z3lBL$fN delta 27 icmXrgnII;{#mJVJk`hv$&%nUN$;i&2z@WgG#SH*Qu>@cM diff --git a/test/fixtures/test.wat b/test/fixtures/test.wat new file mode 100644 index 00000000000000..fa90b17cce0155 --- /dev/null +++ b/test/fixtures/test.wat @@ -0,0 +1,10 @@ +;; Compiled using the WebAssembly Tootkit (https://github.com/WebAssembly/wabt) +;; $ wat2wasm test.wat -o test.wasm +(module + (func $add (export "add") (param $first i32) (param $second i32) (result i32) + get_local $first + get_local $second + (i32.add) + ) + (export "addTwo" (func $add)) +) From ba71fe8bd306a562d4888e5737caeca975a12a07 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Thu, 31 May 2018 12:10:07 +0200 Subject: [PATCH 79/93] timers: check can_call_into_js in Immediates Prevent an infinite loop if it's not possible to call into JS. PR-URL: https://github.com/nodejs/node/pull/21057 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel --- src/env.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/env.cc b/src/env.cc index 32ffd402da049a..7865ba95404df5 100644 --- a/src/env.cc +++ b/src/env.cc @@ -457,6 +457,9 @@ void Environment::CheckImmediate(uv_check_t* handle) { env->RunAndClearNativeImmediates(); + if (!env->can_call_into_js()) + return; + do { MakeCallback(env->isolate(), env->process_object(), @@ -464,7 +467,7 @@ void Environment::CheckImmediate(uv_check_t* handle) { 0, nullptr, {0, 0}).ToLocalChecked(); - } while (env->immediate_info()->has_outstanding()); + } while (env->immediate_info()->has_outstanding() && env->can_call_into_js()); if (env->immediate_info()->ref_count() == 0) env->ToggleImmediateRef(false); From 1733ef9decb6a64cc97c4246acc8c81b14685972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Thu, 31 May 2018 17:21:59 +0200 Subject: [PATCH 80/93] test: make handling of noWarnCode stricter This change requires all expected warnings to be specified along with their respective code and will raise an error if the code does not match. This also kind of fixes the behavior when the expected warning code was noWarnCode and there is an actual warning code. PR-URL: https://github.com/nodejs/node/pull/21075 Reviewed-By: Daniel Bevenius Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- test/common/index.js | 11 ++--------- .../test-promises-unhandled-symbol-rejections.js | 2 +- test/parallel/test-util.js | 8 ++++---- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/test/common/index.js b/test/common/index.js index 85d11ec093414c..f76e1cd38cf460 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -589,7 +589,7 @@ exports.isAlive = function isAlive(pid) { } }; -exports.noWarnCode = 'no_expected_warning_code'; +exports.noWarnCode = undefined; function expectWarning(name, expected) { const map = new Map(expected); @@ -598,14 +598,7 @@ function expectWarning(name, expected) { assert.ok(map.has(warning.message), `unexpected error message: "${warning.message}"`); const code = map.get(warning.message); - if (code === undefined) { - throw new Error('An error code must be specified or use ' + - 'common.noWarnCode if there is no error code. The error ' + - `code for this warning was ${warning.code}`); - } - if (code !== exports.noWarnCode) { - assert.strictEqual(warning.code, code); - } + assert.strictEqual(warning.code, code); // Remove a warning message after it is seen so that we guarantee that we // get each message only once. map.delete(expected); diff --git a/test/parallel/test-promises-unhandled-symbol-rejections.js b/test/parallel/test-promises-unhandled-symbol-rejections.js index 5c028a74c24e90..e5084b50c189fd 100644 --- a/test/parallel/test-promises-unhandled-symbol-rejections.js +++ b/test/parallel/test-promises-unhandled-symbol-rejections.js @@ -6,7 +6,7 @@ const expectedDeprecationWarning = ['Unhandled promise rejections are ' + 'deprecated. In the future, promise ' + 'rejections that are not handled will ' + 'terminate the Node.js process with a ' + - 'non-zero exit code.', common.noWarnCode]; + 'non-zero exit code.', 'DEP0018']; const expectedPromiseWarning = ['Unhandled promise rejection. ' + 'This error originated either by throwing ' + 'inside of an async function without a catch ' + diff --git a/test/parallel/test-util.js b/test/parallel/test-util.js index ee2fe917f3e510..337cb789f73656 100644 --- a/test/parallel/test-util.js +++ b/test/parallel/test-util.js @@ -142,10 +142,10 @@ assert.strictEqual(util.isFunction(), false); assert.strictEqual(util.isFunction('string'), false); common.expectWarning('DeprecationWarning', [ - ['util.print is deprecated. Use console.log instead.', common.noWarnCode], - ['util.puts is deprecated. Use console.log instead.', common.noWarnCode], - ['util.debug is deprecated. Use console.error instead.', common.noWarnCode], - ['util.error is deprecated. Use console.error instead.', common.noWarnCode] + ['util.print is deprecated. Use console.log instead.', 'DEP0026'], + ['util.puts is deprecated. Use console.log instead.', 'DEP0027'], + ['util.debug is deprecated. Use console.error instead.', 'DEP0028'], + ['util.error is deprecated. Use console.error instead.', 'DEP0029'] ]); util.print('test'); From 2d36150852622429e19409fdcdef448f418b2d3a Mon Sep 17 00:00:00 2001 From: Masashi Hirano Date: Fri, 1 Jun 2018 23:02:13 +0900 Subject: [PATCH 81/93] test: string-decorater.lastChar Added test for string-decorater.lastChar to improve coverage. PR-URL: https://github.com/nodejs/node/pull/21084 Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Lance Ball Reviewed-By: Trivikram Kamat --- test/parallel/test-string-decoder.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js index 0e7ea8ffdd56a6..fafab97b2d3888 100644 --- a/test/parallel/test-string-decoder.js +++ b/test/parallel/test-string-decoder.js @@ -90,7 +90,8 @@ test('utf16le', Buffer.from('3DD84DDC', 'hex'), '\ud83d\udc4d'); // thumbs up decoder = new StringDecoder('utf8'); assert.strictEqual(decoder.write(Buffer.from('E1', 'hex')), ''); -// A quick test for lastNeed & lastTotal which are undocumented. +// A quick test for lastChar, lastNeed & lastTotal which are undocumented. +assert(decoder.lastChar.equals(new Uint8Array([0xe1, 0, 0, 0]))); assert.strictEqual(decoder.lastNeed, 2); assert.strictEqual(decoder.lastTotal, 3); From 820236fd0d423a86beb5ae980324f6808b5a8f29 Mon Sep 17 00:00:00 2001 From: Matheus Marchini Date: Wed, 30 May 2018 14:59:09 -0300 Subject: [PATCH 82/93] test: mark test-trace-events-fs-sync as flaky test-trace-events-fs-sync has been failing ocasinally on FreeBSD. While we don't have a fix, it should be marked as flaky. Ref: https://github.com/nodejs/node/issues/21038 PR-URL: https://github.com/nodejs/node/pull/21039 Refs: https://github.com/nodejs/node/issues/21038 Reviewed-By: James M Snell Reviewed-By: Refael Ackermann Reviewed-By: Trivikram Kamat Reviewed-By: Rich Trott Reviewed-By: Anatoli Papirovski Reviewed-By: Lance Ball --- test/parallel/parallel.status | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index e4b757bbd3dac9..3a48bd7cf4069c 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -20,5 +20,7 @@ test-child-process-fork-net: PASS,FLAKY [$system==solaris] # Also applies to SmartOS [$system==freebsd] +# https://github.com/nodejs/node/issues/21038 +test-trace-events-fs-sync: PASS,FLAKY [$system==aix] From 9d41ab466bbd4e6252f48ea270cbac7415630bfc Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sat, 2 Jun 2018 12:34:06 +0200 Subject: [PATCH 83/93] test: refactor child-process-fork-net MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split test-child-process-fork-net into test-child-process-fork-net-server and test-child-process-fork-net-socket. Rename test-child-process-fork-net2.js to test-child-process-fork-net.js. Refs: https://github.com/nodejs/node/pull/21012 PR-URL: https://github.com/nodejs/node/pull/21095 Reviewed-By: Michaël Zasso Reviewed-By: Joyee Cheung Reviewed-By: Trivikram Kamat --- test/parallel/parallel.status | 2 +- .../test-child-process-fork-net-server.js | 145 ++++++++++ .../test-child-process-fork-net-socket.js | 87 ++++++ test/parallel/test-child-process-fork-net.js | 251 ++++++++---------- test/parallel/test-child-process-fork-net2.js | 164 ------------ 5 files changed, 338 insertions(+), 311 deletions(-) create mode 100644 test/parallel/test-child-process-fork-net-server.js create mode 100644 test/parallel/test-child-process-fork-net-socket.js delete mode 100644 test/parallel/test-child-process-fork-net2.js diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 3a48bd7cf4069c..acc0c95b6a953b 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -9,7 +9,7 @@ prefix parallel test-postmortem-metadata: PASS,FLAKY [$system==win32] -test-child-process-fork-net: PASS,FLAKY +test-child-process-fork-net-socket: PASS,FLAKY [$system==linux] diff --git a/test/parallel/test-child-process-fork-net-server.js b/test/parallel/test-child-process-fork-net-server.js new file mode 100644 index 00000000000000..340b3075f9622a --- /dev/null +++ b/test/parallel/test-child-process-fork-net-server.js @@ -0,0 +1,145 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const fork = require('child_process').fork; +const net = require('net'); + +function ProgressTracker(missing, callback) { + this.missing = missing; + this.callback = callback; +} +ProgressTracker.prototype.done = function() { + this.missing -= 1; + this.check(); +}; +ProgressTracker.prototype.check = function() { + if (this.missing === 0) this.callback(); +}; + +if (process.argv[2] === 'child') { + + let serverScope; + + process.on('message', function onServer(msg, server) { + if (msg.what !== 'server') return; + process.removeListener('message', onServer); + + serverScope = server; + + server.on('connection', function(socket) { + console.log('CHILD: got connection'); + process.send({ what: 'connection' }); + socket.destroy(); + }); + + // Start making connection from parent. + console.log('CHILD: server listening'); + process.send({ what: 'listening' }); + }); + + process.on('message', function onClose(msg) { + if (msg.what !== 'close') return; + process.removeListener('message', onClose); + + serverScope.on('close', function() { + process.send({ what: 'close' }); + }); + serverScope.close(); + }); + + process.send({ what: 'ready' }); +} else { + + const child = fork(process.argv[1], ['child']); + + child.on('exit', common.mustCall(function(code, signal) { + const message = `CHILD: died with ${code}, ${signal}`; + assert.strictEqual(code, 0, message); + })); + + // Send net.Server to child and test by connecting. + function testServer(callback) { + + // Destroy server execute callback when done. + const progress = new ProgressTracker(2, function() { + server.on('close', function() { + console.log('PARENT: server closed'); + child.send({ what: 'close' }); + }); + server.close(); + }); + + // We expect 4 connections and close events. + const connections = new ProgressTracker(4, progress.done.bind(progress)); + const closed = new ProgressTracker(4, progress.done.bind(progress)); + + // Create server and send it to child. + const server = net.createServer(); + server.on('connection', function(socket) { + console.log('PARENT: got connection'); + socket.destroy(); + connections.done(); + }); + server.on('listening', function() { + console.log('PARENT: server listening'); + child.send({ what: 'server' }, server); + }); + server.listen(0); + + // Handle client messages. + function messageHandlers(msg) { + + if (msg.what === 'listening') { + // Make connections. + let socket; + for (let i = 0; i < 4; i++) { + socket = net.connect(server.address().port, function() { + console.log('CLIENT: connected'); + }); + socket.on('close', function() { + closed.done(); + console.log('CLIENT: closed'); + }); + } + + } else if (msg.what === 'connection') { + // child got connection + connections.done(); + } else if (msg.what === 'close') { + child.removeListener('message', messageHandlers); + callback(); + } + } + + child.on('message', messageHandlers); + } + + // Create server and send it to child. + child.on('message', function onReady(msg) { + if (msg.what !== 'ready') return; + child.removeListener('message', onReady); + + testServer(common.mustCall()); + }); +} diff --git a/test/parallel/test-child-process-fork-net-socket.js b/test/parallel/test-child-process-fork-net-socket.js new file mode 100644 index 00000000000000..8e3d9ee16e2e56 --- /dev/null +++ b/test/parallel/test-child-process-fork-net-socket.js @@ -0,0 +1,87 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const fork = require('child_process').fork; +const net = require('net'); + +if (process.argv[2] === 'child') { + + process.on('message', function onSocket(msg, socket) { + if (msg.what !== 'socket') return; + process.removeListener('message', onSocket); + socket.end('echo'); + console.log('CHILD: got socket'); + }); + + process.send({ what: 'ready' }); +} else { + + const child = fork(process.argv[1], ['child']); + + child.on('exit', common.mustCall(function(code, signal) { + const message = `CHILD: died with ${code}, ${signal}`; + assert.strictEqual(code, 0, message); + })); + + // Send net.Socket to child. + function testSocket(callback) { + + // Create a new server and connect to it, + // but the socket will be handled by the child. + const server = net.createServer(); + server.on('connection', function(socket) { + socket.on('close', function() { + console.log('CLIENT: socket closed'); + }); + child.send({ what: 'socket' }, socket); + }); + server.on('close', function() { + console.log('PARENT: server closed'); + callback(); + }); + + server.listen(0, function() { + console.log('testSocket, listening'); + const connect = net.connect(server.address().port); + let store = ''; + connect.on('data', function(chunk) { + store += chunk; + console.log('CLIENT: got data'); + }); + connect.on('close', function() { + console.log('CLIENT: closed'); + assert.strictEqual(store, 'echo'); + server.close(); + }); + }); + } + + // Create socket and send it to child. + child.on('message', function onReady(msg) { + if (msg.what !== 'ready') return; + child.removeListener('message', onReady); + + testSocket(common.mustCall()); + }); +} diff --git a/test/parallel/test-child-process-fork-net.js b/test/parallel/test-child-process-fork-net.js index cfc8f564d2a03a..babde351d3f05a 100644 --- a/test/parallel/test-child-process-fork-net.js +++ b/test/parallel/test-child-process-fork-net.js @@ -24,182 +24,141 @@ const common = require('../common'); const assert = require('assert'); const fork = require('child_process').fork; const net = require('net'); - -function ProgressTracker(missing, callback) { - this.missing = missing; - this.callback = callback; -} -ProgressTracker.prototype.done = function() { - this.missing -= 1; - this.check(); -}; -ProgressTracker.prototype.check = function() { - if (this.missing === 0) this.callback(); -}; +const count = 12; if (process.argv[2] === 'child') { + const needEnd = []; + const id = process.argv[3]; + + process.on('message', function(m, socket) { + if (!socket) return; - let serverScope; + console.error(`[${id}] got socket ${m}`); - process.on('message', function onServer(msg, server) { - if (msg.what !== 'server') return; - process.removeListener('message', onServer); + // will call .end('end') or .write('write'); + socket[m](m); - serverScope = server; + socket.resume(); - server.on('connection', function(socket) { - console.log('CHILD: got connection'); - process.send({ what: 'connection' }); - socket.destroy(); + socket.on('data', function() { + console.error(`[${id}] socket.data ${m}`); }); - // Start making connection from parent. - console.log('CHILD: server listening'); - process.send({ what: 'listening' }); - }); + socket.on('end', function() { + console.error(`[${id}] socket.end ${m}`); + }); - process.on('message', function onClose(msg) { - if (msg.what !== 'close') return; - process.removeListener('message', onClose); + // store the unfinished socket + if (m === 'write') { + needEnd.push(socket); + } - serverScope.on('close', function() { - process.send({ what: 'close' }); + socket.on('close', function(had_error) { + console.error(`[${id}] socket.close ${had_error} ${m}`); }); - serverScope.close(); - }); - process.on('message', function onSocket(msg, socket) { - if (msg.what !== 'socket') return; - process.removeListener('message', onSocket); - socket.end('echo'); - console.log('CHILD: got socket'); + socket.on('finish', function() { + console.error(`[${id}] socket finished ${m}`); + }); }); - process.send({ what: 'ready' }); -} else { + process.on('message', function(m) { + if (m !== 'close') return; + console.error(`[${id}] got close message`); + needEnd.forEach(function(endMe, i) { + console.error(`[${id}] ending ${i}/${needEnd.length}`); + endMe.end('end'); + }); + }); - const child = fork(process.argv[1], ['child']); + process.on('disconnect', function() { + console.error(`[${id}] process disconnect, ending`); + needEnd.forEach(function(endMe, i) { + console.error(`[${id}] ending ${i}/${needEnd.length}`); + endMe.end('end'); + }); + }); - child.on('exit', common.mustCall(function(code, signal) { - const message = `CHILD: died with ${code}, ${signal}`; - assert.strictEqual(code, 0, message); - })); +} else { - // Send net.Server to child and test by connecting. - function testServer(callback) { + const child1 = fork(process.argv[1], ['child', '1']); + const child2 = fork(process.argv[1], ['child', '2']); + const child3 = fork(process.argv[1], ['child', '3']); + + const server = net.createServer(); + + let connected = 0; + let closed = 0; + server.on('connection', function(socket) { + switch (connected % 6) { + case 0: + child1.send('end', socket); break; + case 1: + child1.send('write', socket); break; + case 2: + child2.send('end', socket); break; + case 3: + child2.send('write', socket); break; + case 4: + child3.send('end', socket); break; + case 5: + child3.send('write', socket); break; + } + connected += 1; - // Destroy server execute callback when done. - const progress = new ProgressTracker(2, function() { - server.on('close', function() { - console.log('PARENT: server closed'); - child.send({ what: 'close' }); - }); - server.close(); + socket.once('close', function() { + console.log(`[m] socket closed, total ${++closed}`); }); - // We expect 4 connections and close events. - const connections = new ProgressTracker(4, progress.done.bind(progress)); - const closed = new ProgressTracker(4, progress.done.bind(progress)); - - // Create server and send it to child. - const server = net.createServer(); - server.on('connection', function(socket) { - console.log('PARENT: got connection'); - socket.destroy(); - connections.done(); - }); - server.on('listening', function() { - console.log('PARENT: server listening'); - child.send({ what: 'server' }, server); - }); - server.listen(0); - - // Handle client messages. - function messageHandlers(msg) { - - if (msg.what === 'listening') { - // Make connections. - let socket; - for (let i = 0; i < 4; i++) { - socket = net.connect(server.address().port, function() { - console.log('CLIENT: connected'); - }); - socket.on('close', function() { - closed.done(); - console.log('CLIENT: closed'); - }); - } - - } else if (msg.what === 'connection') { - // child got connection - connections.done(); - } else if (msg.what === 'close') { - child.removeListener('message', messageHandlers); - callback(); - } + if (connected === count) { + closeServer(); } + }); - child.on('message', messageHandlers); - } - - // Send net.Socket to child. - function testSocket(callback) { + let disconnected = 0; + server.on('listening', function() { - // Create a new server and connect to it, - // but the socket will be handled by the child. - const server = net.createServer(); - server.on('connection', function(socket) { - socket.on('close', function() { - console.log('CLIENT: socket closed'); + let j = count; + while (j--) { + const client = net.connect(this.address().port, '127.0.0.1'); + client.on('error', function() { + // This can happen if we kill the child too early. + // The client should still get a close event afterwards. + console.error('[m] CLIENT: error event'); }); - child.send({ what: 'socket' }, socket); - }); - server.on('close', function() { - console.log('PARENT: server closed'); - callback(); - }); - // Don't listen on the same port, because SmartOS sometimes says - // that the server's fd is closed, but it still cannot listen - // on the same port again. - // - // An isolated test for this would be lovely, but for now, this - // will have to do. - server.listen(0, function() { - console.log('testSocket, listening'); - const connect = net.connect(server.address().port); - let store = ''; - connect.on('data', function(chunk) { - store += chunk; - console.log('CLIENT: got data'); - }); - connect.on('close', function() { - console.log('CLIENT: closed'); - assert.strictEqual(store, 'echo'); - server.close(); + client.on('close', function() { + console.error('[m] CLIENT: close event'); + disconnected += 1; }); - }); - } + client.resume(); + } + }); - // Create server and send it to child. - let serverSuccess = false; - let socketSuccess = false; - child.on('message', function onReady(msg) { - if (msg.what !== 'ready') return; - child.removeListener('message', onReady); + let closeEmitted = false; + server.on('close', common.mustCall(function() { + closeEmitted = true; - testServer(function() { - serverSuccess = true; + child1.kill(); + child2.kill(); + child3.kill(); + })); - testSocket(function() { - socketSuccess = true; - }); - }); + server.listen(0, '127.0.0.1'); - }); + function closeServer() { + server.close(); + + setTimeout(function() { + assert(!closeEmitted); + child1.send('close'); + child2.send('close'); + child3.disconnect(); + }, 200); + } process.on('exit', function() { - assert.ok(serverSuccess); - assert.ok(socketSuccess); + assert.strictEqual(server._workers.length, 0); + assert.strictEqual(disconnected, count); + assert.strictEqual(connected, count); }); - } diff --git a/test/parallel/test-child-process-fork-net2.js b/test/parallel/test-child-process-fork-net2.js deleted file mode 100644 index babde351d3f05a..00000000000000 --- a/test/parallel/test-child-process-fork-net2.js +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; -const common = require('../common'); -const assert = require('assert'); -const fork = require('child_process').fork; -const net = require('net'); -const count = 12; - -if (process.argv[2] === 'child') { - const needEnd = []; - const id = process.argv[3]; - - process.on('message', function(m, socket) { - if (!socket) return; - - console.error(`[${id}] got socket ${m}`); - - // will call .end('end') or .write('write'); - socket[m](m); - - socket.resume(); - - socket.on('data', function() { - console.error(`[${id}] socket.data ${m}`); - }); - - socket.on('end', function() { - console.error(`[${id}] socket.end ${m}`); - }); - - // store the unfinished socket - if (m === 'write') { - needEnd.push(socket); - } - - socket.on('close', function(had_error) { - console.error(`[${id}] socket.close ${had_error} ${m}`); - }); - - socket.on('finish', function() { - console.error(`[${id}] socket finished ${m}`); - }); - }); - - process.on('message', function(m) { - if (m !== 'close') return; - console.error(`[${id}] got close message`); - needEnd.forEach(function(endMe, i) { - console.error(`[${id}] ending ${i}/${needEnd.length}`); - endMe.end('end'); - }); - }); - - process.on('disconnect', function() { - console.error(`[${id}] process disconnect, ending`); - needEnd.forEach(function(endMe, i) { - console.error(`[${id}] ending ${i}/${needEnd.length}`); - endMe.end('end'); - }); - }); - -} else { - - const child1 = fork(process.argv[1], ['child', '1']); - const child2 = fork(process.argv[1], ['child', '2']); - const child3 = fork(process.argv[1], ['child', '3']); - - const server = net.createServer(); - - let connected = 0; - let closed = 0; - server.on('connection', function(socket) { - switch (connected % 6) { - case 0: - child1.send('end', socket); break; - case 1: - child1.send('write', socket); break; - case 2: - child2.send('end', socket); break; - case 3: - child2.send('write', socket); break; - case 4: - child3.send('end', socket); break; - case 5: - child3.send('write', socket); break; - } - connected += 1; - - socket.once('close', function() { - console.log(`[m] socket closed, total ${++closed}`); - }); - - if (connected === count) { - closeServer(); - } - }); - - let disconnected = 0; - server.on('listening', function() { - - let j = count; - while (j--) { - const client = net.connect(this.address().port, '127.0.0.1'); - client.on('error', function() { - // This can happen if we kill the child too early. - // The client should still get a close event afterwards. - console.error('[m] CLIENT: error event'); - }); - client.on('close', function() { - console.error('[m] CLIENT: close event'); - disconnected += 1; - }); - client.resume(); - } - }); - - let closeEmitted = false; - server.on('close', common.mustCall(function() { - closeEmitted = true; - - child1.kill(); - child2.kill(); - child3.kill(); - })); - - server.listen(0, '127.0.0.1'); - - function closeServer() { - server.close(); - - setTimeout(function() { - assert(!closeEmitted); - child1.send('close'); - child2.send('close'); - child3.disconnect(); - }, 200); - } - - process.on('exit', function() { - assert.strictEqual(server._workers.length, 0); - assert.strictEqual(disconnected, count); - assert.strictEqual(connected, count); - }); -} From 8862f0a613c3da77b6cffa24a4374df83d30c300 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Sat, 2 Jun 2018 18:10:34 +0200 Subject: [PATCH 84/93] src: store pointer to Environment on DestroyParam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid a potential segfault when inside WeakCallback, store a reference to Environment inside DestroyParam. PR-URL: https://github.com/nodejs/node/pull/21099 Reviewed-By: Yang Guo Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Tiancheng "Timothy" Gu Co-authored-by: Yang Guo Co-authored-by: Michaël Zasso --- src/async_wrap.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/async_wrap.cc b/src/async_wrap.cc index 11ce5a387a950c..87c50950faadcc 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -398,6 +398,7 @@ static void DisablePromiseHook(const FunctionCallbackInfo& args) { class DestroyParam { public: double asyncId; + Environment* env; Persistent target; Persistent propBag; }; @@ -406,13 +407,12 @@ class DestroyParam { void AsyncWrap::WeakCallback(const v8::WeakCallbackInfo& info) { HandleScope scope(info.GetIsolate()); - Environment* env = Environment::GetCurrent(info.GetIsolate()); std::unique_ptr p{info.GetParameter()}; Local prop_bag = PersistentToLocal(info.GetIsolate(), p->propBag); - Local val = prop_bag->Get(env->destroyed_string()); + Local val = prop_bag->Get(p->env->destroyed_string()); if (val->IsFalse()) { - AsyncWrap::EmitDestroy(env, p->asyncId); + AsyncWrap::EmitDestroy(p->env, p->asyncId); } // unique_ptr goes out of scope here and pointer is deleted. } @@ -426,6 +426,7 @@ static void RegisterDestroyHook(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); DestroyParam* p = new DestroyParam(); p->asyncId = args[1].As()->Value(); + p->env = Environment::GetCurrent(args); p->target.Reset(isolate, args[0].As()); p->propBag.Reset(isolate, args[2].As()); p->target.SetWeak( From 1c211ec90162088008228ed983ecb476a2cb2cbe Mon Sep 17 00:00:00 2001 From: Eugene Ostroukhov Date: Thu, 31 May 2018 14:24:21 -0700 Subject: [PATCH 85/93] inspector: code cleanup Remove some unused code from the WS server implementation and switch to smart pointers where possible. PR-URL: https://github.com/nodejs/node/pull/21070 Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis --- src/inspector_io.cc | 38 +-- src/inspector_io.h | 3 +- src/inspector_socket.cc | 23 +- src/inspector_socket.h | 5 +- src/inspector_socket_server.cc | 146 +++------ src/inspector_socket_server.h | 28 +- test/cctest/test_inspector_socket_server.cc | 323 +++++++++----------- 7 files changed, 229 insertions(+), 337 deletions(-) diff --git a/src/inspector_io.cc b/src/inspector_io.cc index 4db26bee273b9a..615fc975922fd9 100644 --- a/src/inspector_io.cc +++ b/src/inspector_io.cc @@ -109,8 +109,12 @@ class IoSessionDelegate : public InspectorSessionDelegate { // mostly session start, message received, and session end. class InspectorIoDelegate: public node::inspector::SocketServerDelegate { public: - InspectorIoDelegate(InspectorIo* io, const std::string& script_path, + InspectorIoDelegate(InspectorIo* io, const std::string& target_id, + const std::string& script_path, const std::string& script_name, bool wait); + ~InspectorIoDelegate() { + io_->ServerDone(); + } // Calls PostIncomingMessage() with appropriate InspectorAction: // kStartSession void StartSession(int session_id, const std::string& target_id) override; @@ -122,11 +126,8 @@ class InspectorIoDelegate: public node::inspector::SocketServerDelegate { std::vector GetTargetIds() override; std::string GetTargetTitle(const std::string& id) override; std::string GetTargetUrl(const std::string& id) override; - void ServerDone() override { - io_->ServerDone(); - } - void AssignTransport(InspectorSocketServer* server) { + void AssignServer(InspectorSocketServer* server) override { server_ = server; } @@ -163,11 +164,11 @@ class DispatchMessagesTask : public v8::Task { InspectorIo::InspectorIo(Environment* env, v8::Platform* platform, const std::string& path, const DebugOptions& options, bool wait_for_connect) - : options_(options), thread_(), delegate_(nullptr), - state_(State::kNew), parent_env_(env), - thread_req_(), platform_(platform), + : options_(options), thread_(), state_(State::kNew), + parent_env_(env), thread_req_(), platform_(platform), dispatching_messages_(false), script_name_(path), - wait_for_connect_(wait_for_connect), port_(-1) { + wait_for_connect_(wait_for_connect), port_(-1), + id_(GenerateID()) { main_thread_req_ = new AsyncAndAgent({uv_async_t(), env->inspector_agent()}); CHECK_EQ(0, uv_async_init(env->event_loop(), &main_thread_req_->first, InspectorIo::MainThreadReqAsyncCb)); @@ -244,7 +245,7 @@ void InspectorIo::IoThreadAsyncCb(uv_async_t* async) { transport->TerminateConnections(); // Fallthrough case TransportAction::kStop: - transport->Stop(nullptr); + transport->Stop(); break; case TransportAction::kSendMessage: transport->Send(session_id, @@ -271,11 +272,11 @@ void InspectorIo::ThreadMain() { err = uv_async_init(&loop, &thread_req_, IoThreadAsyncCb); CHECK_EQ(err, 0); std::string script_path = ScriptPath(&loop, script_name_); - InspectorIoDelegate delegate(this, script_path, script_name_, - wait_for_connect_); - delegate_ = &delegate; - Transport server(&delegate, &loop, options_.host_name(), options_.port()); - delegate.AssignTransport(&server); + auto delegate = std::unique_ptr( + new InspectorIoDelegate(this, id_, script_path, script_name_, + wait_for_connect_)); + Transport server(std::move(delegate), &loop, options_.host_name(), + options_.port()); TransportAndIo queue_transport(&server, this); thread_req_.data = &queue_transport; if (!server.Start()) { @@ -291,8 +292,6 @@ void InspectorIo::ThreadMain() { uv_run(&loop, UV_RUN_DEFAULT); thread_req_.data = nullptr; CHECK_EQ(uv_loop_close(&loop), 0); - delegate.AssignTransport(nullptr); - delegate_ = nullptr; } template @@ -328,7 +327,7 @@ void InspectorIo::PostIncomingMessage(InspectorAction action, int session_id, } std::vector InspectorIo::GetTargetIds() const { - return delegate_ ? delegate_->GetTargetIds() : std::vector(); + return { id_ }; } TransportAction InspectorIo::Attach(int session_id) { @@ -416,6 +415,7 @@ bool InspectorIo::WaitForFrontendEvent() { } InspectorIoDelegate::InspectorIoDelegate(InspectorIo* io, + const std::string& target_id, const std::string& script_path, const std::string& script_name, bool wait) @@ -423,7 +423,7 @@ InspectorIoDelegate::InspectorIoDelegate(InspectorIo* io, session_id_(0), script_name_(script_name), script_path_(script_path), - target_id_(GenerateID()), + target_id_(target_id), waiting_(wait), server_(nullptr) { } diff --git a/src/inspector_io.h b/src/inspector_io.h index 05de2d17cd3bad..9d27fc557b7b25 100644 --- a/src/inspector_io.h +++ b/src/inspector_io.h @@ -134,7 +134,6 @@ class InspectorIo { // and receive a connection if wait_for_connect was requested. uv_sem_t thread_start_sem_; - InspectorIoDelegate* delegate_; State state_; node::Environment* parent_env_; @@ -161,6 +160,8 @@ class InspectorIo { const bool wait_for_connect_; int port_; std::unordered_map> sessions_; + // May be accessed from any thread + const std::string id_; friend class DispatchMessagesTask; friend class IoSessionDelegate; diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc index 1350269cf2c4b0..dc36359b5c927c 100644 --- a/src/inspector_socket.cc +++ b/src/inspector_socket.cc @@ -22,7 +22,8 @@ namespace inspector { class TcpHolder { public: - using Pointer = std::unique_ptr; + static void DisconnectAndDispose(TcpHolder* holder); + using Pointer = DeleteFnPtr; static Pointer Accept(uv_stream_t* server, InspectorSocket::DelegatePointer delegate); @@ -41,7 +42,6 @@ class TcpHolder { static void OnClosed(uv_handle_t* handle); static void OnDataReceivedCb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); - static void DisconnectAndDispose(TcpHolder* holder); explicit TcpHolder(InspectorSocket::DelegatePointer delegate); ~TcpHolder() = default; void ReclaimUvBuf(const uv_buf_t* buf, ssize_t read); @@ -68,14 +68,10 @@ class ProtocolHandler { InspectorSocket* inspector() { return inspector_; } - - static void Shutdown(ProtocolHandler* handler) { - handler->Shutdown(); - } + virtual void Shutdown() = 0; protected: virtual ~ProtocolHandler() = default; - virtual void Shutdown() = 0; int WriteRaw(const std::vector& buffer, uv_write_cb write_cb); InspectorSocket::Delegate* delegate(); @@ -653,10 +649,10 @@ TcpHolder::Pointer TcpHolder::Accept( err = uv_read_start(tcp, allocate_buffer, OnDataReceivedCb); } if (err == 0) { - return { result, DisconnectAndDispose }; + return TcpHolder::Pointer(result); } else { delete result; - return { nullptr, nullptr }; + return nullptr; } } @@ -721,12 +717,13 @@ void TcpHolder::ReclaimUvBuf(const uv_buf_t* buf, ssize_t read) { delete[] buf->base; } -// Public interface -InspectorSocket::InspectorSocket() - : protocol_handler_(nullptr, ProtocolHandler::Shutdown) { } - InspectorSocket::~InspectorSocket() = default; +// static +void InspectorSocket::Shutdown(ProtocolHandler* handler) { + handler->Shutdown(); +} + // static InspectorSocket::Pointer InspectorSocket::Accept(uv_stream_t* server, DelegatePointer delegate) { diff --git a/src/inspector_socket.h b/src/inspector_socket.h index 81b894f95cb88f..ae49d78ff3452a 100644 --- a/src/inspector_socket.h +++ b/src/inspector_socket.h @@ -40,9 +40,10 @@ class InspectorSocket { std::string GetHost(); private: - InspectorSocket(); + static void Shutdown(ProtocolHandler*); + InspectorSocket() = default; - std::unique_ptr protocol_handler_; + DeleteFnPtr protocol_handler_; DISALLOW_COPY_AND_ASSIGN(InspectorSocket); }; diff --git a/src/inspector_socket_server.cc b/src/inspector_socket_server.cc index 42082c9c8495ed..d5eb1b75c81ae0 100644 --- a/src/inspector_socket_server.cc +++ b/src/inspector_socket_server.cc @@ -156,43 +156,6 @@ std::string FormatWsAddress(const std::string& host, int port, return FormatAddress(FormatHostPort(host, port), target_id, include_protocol); } -class Closer { - public: - explicit Closer(InspectorSocketServer* server) : server_(server), - close_count_(0) { } - - void AddCallback(InspectorSocketServer::ServerCallback callback) { - if (callback == nullptr) - return; - callbacks_.insert(callback); - } - - void DecreaseExpectedCount() { - --close_count_; - NotifyIfDone(); - } - - void IncreaseExpectedCount() { - ++close_count_; - } - - void NotifyIfDone() { - if (close_count_ == 0) { - for (auto callback : callbacks_) { - callback(server_); - } - InspectorSocketServer* server = server_; - delete server->closer_; - server->closer_ = nullptr; - } - } - - private: - InspectorSocketServer* server_; - std::set callbacks_; - int close_count_; -}; - class SocketSession { public: SocketSession(InspectorSocketServer* server, int id, int server_port); @@ -250,45 +213,38 @@ class SocketSession { class ServerSocket { public: - static int Listen(InspectorSocketServer* inspector_server, - sockaddr* addr, uv_loop_t* loop); + explicit ServerSocket(InspectorSocketServer* server) + : tcp_socket_(uv_tcp_t()), server_(server) {} + int Listen(sockaddr* addr, uv_loop_t* loop); void Close() { - uv_close(reinterpret_cast(&tcp_socket_), - SocketClosedCallback); + uv_close(reinterpret_cast(&tcp_socket_), FreeOnCloseCallback); } int port() const { return port_; } private: - explicit ServerSocket(InspectorSocketServer* server) - : tcp_socket_(uv_tcp_t()), server_(server), port_(-1) {} template static ServerSocket* FromTcpSocket(UvHandle* socket) { return node::ContainerOf(&ServerSocket::tcp_socket_, reinterpret_cast(socket)); } static void SocketConnectedCallback(uv_stream_t* tcp_socket, int status); - static void SocketClosedCallback(uv_handle_t* tcp_socket); static void FreeOnCloseCallback(uv_handle_t* tcp_socket_) { delete FromTcpSocket(tcp_socket_); } int DetectPort(); + ~ServerSocket() = default; uv_tcp_t tcp_socket_; InspectorSocketServer* server_; - int port_; + int port_ = -1; }; -InspectorSocketServer::InspectorSocketServer(SocketServerDelegate* delegate, - uv_loop_t* loop, - const std::string& host, - int port, - FILE* out) : loop_(loop), - delegate_(delegate), - host_(host), - port_(port), - closer_(nullptr), - next_session_id_(0), - out_(out) { +InspectorSocketServer::InspectorSocketServer( + std::unique_ptr delegate, uv_loop_t* loop, + const std::string& host, int port, FILE* out) + : loop_(loop), delegate_(std::move(delegate)), host_(host), port_(port), + next_session_id_(0), out_(out) { + delegate_->AssignServer(this); state_ = ServerState::kNew; } @@ -328,7 +284,7 @@ void InspectorSocketServer::SessionTerminated(int session_id) { delegate_->GetTargetIds(), out_); } if (state_ == ServerState::kStopped) { - delegate_->ServerDone(); + delegate_.reset(); } } } @@ -389,7 +345,11 @@ void InspectorSocketServer::SendListResponse(InspectorSocket* socket, } bool InspectorSocketServer::Start() { + CHECK_NE(delegate_, nullptr); CHECK_EQ(state_, ServerState::kNew); + std::unique_ptr delegate_holder; + // We will return it if startup is successful + delegate_.swap(delegate_holder); struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICSERV; @@ -407,13 +367,13 @@ bool InspectorSocketServer::Start() { } for (addrinfo* address = req.addrinfo; address != nullptr; address = address->ai_next) { - err = ServerSocket::Listen(this, address->ai_addr, loop_); + auto server_socket = ServerSocketPtr(new ServerSocket(this)); + err = server_socket->Listen(address->ai_addr, loop_); + if (err == 0) + server_sockets_.push_back(std::move(server_socket)); } uv_freeaddrinfo(req.addrinfo); - if (!connected_sessions_.empty()) { - return true; - } // We only show error if we failed to start server on all addresses. We only // show one error, for the last address. if (server_sockets_.empty()) { @@ -424,6 +384,7 @@ bool InspectorSocketServer::Start() { } return false; } + delegate_.swap(delegate_holder); state_ = ServerState::kRunning; // getaddrinfo sorts the addresses, so the first port is most relevant. PrintDebuggerReadyMessage(host_, server_sockets_[0]->port(), @@ -431,17 +392,12 @@ bool InspectorSocketServer::Start() { return true; } -void InspectorSocketServer::Stop(ServerCallback cb) { +void InspectorSocketServer::Stop() { CHECK_EQ(state_, ServerState::kRunning); - if (closer_ == nullptr) { - closer_ = new Closer(this); - } - closer_->AddCallback(cb); - closer_->IncreaseExpectedCount(); - state_ = ServerState::kStopping; - for (ServerSocket* server_socket : server_sockets_) - server_socket->Close(); - closer_->NotifyIfDone(); + state_ = ServerState::kStopped; + server_sockets_.clear(); + if (done()) + delegate_.reset(); } void InspectorSocketServer::TerminateConnections() { @@ -455,28 +411,6 @@ bool InspectorSocketServer::TargetExists(const std::string& id) { return found != target_ids.end(); } -void InspectorSocketServer::ServerSocketListening(ServerSocket* server_socket) { - server_sockets_.push_back(server_socket); -} - -void InspectorSocketServer::ServerSocketClosed(ServerSocket* server_socket) { - CHECK_EQ(state_, ServerState::kStopping); - - server_sockets_.erase(std::remove(server_sockets_.begin(), - server_sockets_.end(), server_socket), - server_sockets_.end()); - if (!server_sockets_.empty()) - return; - - if (closer_ != nullptr) { - closer_->DecreaseExpectedCount(); - } - if (connected_sessions_.empty()) { - delegate_->ServerDone(); - } - state_ = ServerState::kStopped; -} - int InspectorSocketServer::Port() const { if (!server_sockets_.empty()) { return server_sockets_[0]->port(); @@ -525,6 +459,10 @@ void InspectorSocketServer::Send(int session_id, const std::string& message) { } } +void InspectorSocketServer::CloseServerSocket(ServerSocket* server) { + server->Close(); +} + // InspectorSession tracking SocketSession::SocketSession(InspectorSocketServer* server, int id, int server_port) @@ -569,11 +507,8 @@ int ServerSocket::DetectPort() { return err; } -// static -int ServerSocket::Listen(InspectorSocketServer* inspector_server, - sockaddr* addr, uv_loop_t* loop) { - ServerSocket* server_socket = new ServerSocket(inspector_server); - uv_tcp_t* server = &server_socket->tcp_socket_; +int ServerSocket::Listen(sockaddr* addr, uv_loop_t* loop) { + uv_tcp_t* server = &tcp_socket_; CHECK_EQ(0, uv_tcp_init(loop, server)); int err = uv_tcp_bind(server, addr, 0); if (err == 0) { @@ -582,12 +517,7 @@ int ServerSocket::Listen(InspectorSocketServer* inspector_server, ServerSocket::SocketConnectedCallback); } if (err == 0) { - err = server_socket->DetectPort(); - } - if (err == 0) { - inspector_server->ServerSocketListening(server_socket); - } else { - uv_close(reinterpret_cast(server), FreeOnCloseCallback); + err = DetectPort(); } return err; } @@ -601,13 +531,5 @@ void ServerSocket::SocketConnectedCallback(uv_stream_t* tcp_socket, server_socket->server_->Accept(server_socket->port_, tcp_socket); } } - -// static -void ServerSocket::SocketClosedCallback(uv_handle_t* tcp_socket) { - ServerSocket* server_socket = ServerSocket::FromTcpSocket(tcp_socket); - server_socket->server_->ServerSocketClosed(server_socket); - delete server_socket; -} - } // namespace inspector } // namespace node diff --git a/src/inspector_socket_server.h b/src/inspector_socket_server.h index f6003c4c4b4d70..b8d98e13a26b62 100644 --- a/src/inspector_socket_server.h +++ b/src/inspector_socket_server.h @@ -16,19 +16,20 @@ namespace node { namespace inspector { -class Closer; +class InspectorSocketServer; class SocketSession; class ServerSocket; class SocketServerDelegate { public: + virtual void AssignServer(InspectorSocketServer* server) = 0; virtual void StartSession(int session_id, const std::string& target_id) = 0; virtual void EndSession(int session_id) = 0; virtual void MessageReceived(int session_id, const std::string& message) = 0; virtual std::vector GetTargetIds() = 0; virtual std::string GetTargetTitle(const std::string& id) = 0; virtual std::string GetTargetUrl(const std::string& id) = 0; - virtual void ServerDone() = 0; + virtual ~SocketServerDelegate() {} }; // HTTP Server, writes messages requested as TransportActions, and responds @@ -36,8 +37,7 @@ class SocketServerDelegate { class InspectorSocketServer { public: - using ServerCallback = void (*)(InspectorSocketServer*); - InspectorSocketServer(SocketServerDelegate* delegate, + InspectorSocketServer(std::unique_ptr delegate, uv_loop_t* loop, const std::string& host, int port, @@ -49,7 +49,7 @@ class InspectorSocketServer { // Called by the TransportAction sent with InspectorIo::Write(): // kKill and kStop - void Stop(ServerCallback callback); + void Stop(); // kSendMessage void Send(int session_id, const std::string& message); // kKill @@ -58,13 +58,8 @@ class InspectorSocketServer { void AcceptSession(int session_id); // kDeclineSession void DeclineSession(int session_id); - int Port() const; - // Server socket lifecycle. There may be multiple sockets - void ServerSocketListening(ServerSocket* server_socket); - void ServerSocketClosed(ServerSocket* server_socket); - // Session connection lifecycle void Accept(int server_port, uv_stream_t* server_socket); bool HandleGetRequest(int session_id, const std::string& host, @@ -76,27 +71,30 @@ class InspectorSocketServer { delegate_->MessageReceived(session_id, message); } SocketSession* Session(int session_id); + bool done() const { + return server_sockets_.empty() && connected_sessions_.empty(); + } private: + static void CloseServerSocket(ServerSocket*); + using ServerSocketPtr = DeleteFnPtr; + void SendListResponse(InspectorSocket* socket, const std::string& host, SocketSession* session); bool TargetExists(const std::string& id); enum class ServerState {kNew, kRunning, kStopping, kStopped}; uv_loop_t* loop_; - SocketServerDelegate* const delegate_; + std::unique_ptr delegate_; const std::string host_; int port_; std::string path_; - std::vector server_sockets_; - Closer* closer_; + std::vector server_sockets_; std::map>> connected_sessions_; int next_session_id_; FILE* out_; ServerState state_; - - friend class Closer; }; } // namespace inspector diff --git a/test/cctest/test_inspector_socket_server.cc b/test/cctest/test_inspector_socket_server.cc index 9023ad43c1c75c..60b7eefc5e997f 100644 --- a/test/cctest/test_inspector_socket_server.cc +++ b/test/cctest/test_inspector_socket_server.cc @@ -84,78 +84,6 @@ class InspectorSocketServerTest : public ::testing::Test { } }; -class TestInspectorServerDelegate : public SocketServerDelegate { - public: - TestInspectorServerDelegate() : connected(0), disconnected(0), done(false), - targets_({ MAIN_TARGET_ID, - UNCONNECTABLE_TARGET_ID }), - session_id_(0) {} - - void Connect(InspectorSocketServer* server) { - server_ = server; - } - - void StartSession(int session_id, const std::string& target_id) override { - buffer_.clear(); - CHECK_NE(targets_.end(), - std::find(targets_.begin(), targets_.end(), target_id)); - if (target_id == UNCONNECTABLE_TARGET_ID) { - server_->DeclineSession(session_id); - return; - } - connected++; - session_id_ = session_id; - server_->AcceptSession(session_id); - } - - void MessageReceived(int session_id, const std::string& message) override { - CHECK_EQ(session_id_, session_id); - buffer_.insert(buffer_.end(), message.begin(), message.end()); - } - - void EndSession(int session_id) override { - CHECK_EQ(session_id_, session_id); - disconnected++; - } - - std::vector GetTargetIds() override { - return targets_; - } - - std::string GetTargetTitle(const std::string& id) override { - return id + " Target Title"; - } - - std::string GetTargetUrl(const std::string& id) override { - return "file://" + id + "/script.js"; - } - - void Expect(const std::string& expects) { - SPIN_WHILE(buffer_.size() < expects.length()); - ASSERT_STREQ(std::string(buffer_.data(), expects.length()).c_str(), - expects.c_str()); - buffer_.erase(buffer_.begin(), buffer_.begin() + expects.length()); - } - - void Write(const std::string& message) { - server_->Send(session_id_, message); - } - - void ServerDone() override { - done = true; - } - - int connected; - int disconnected; - bool done; - - private: - const std::vector targets_; - InspectorSocketServer* server_; - int session_id_; - std::vector buffer_; -}; - class SocketWrapper { public: explicit SocketWrapper(uv_loop_t* loop) : closed_(false), @@ -312,76 +240,136 @@ class SocketWrapper { class ServerHolder { public: - template - ServerHolder(Delegate* delegate, uv_loop_t* loop, int port) - : ServerHolder(delegate, loop, HOST, port, nullptr) { } + ServerHolder(bool has_targets, uv_loop_t* loop, int port) + : ServerHolder(has_targets, loop, HOST, port, nullptr) { } - template - ServerHolder(Delegate* delegate, uv_loop_t* loop, const std::string host, - int port, FILE* out) - : closed(false), paused(false), - server_(delegate, loop, host, port, out) { - delegate->Connect(&server_); - } + ServerHolder(bool has_targets, uv_loop_t* loop, + const std::string host, int port, FILE* out); InspectorSocketServer* operator->() { - return &server_; + return server_.get(); } int port() { - return server_.Port(); + return server_->Port(); } - static void CloseCallback(InspectorSocketServer* server) { - ServerHolder* holder = node::ContainerOf(&ServerHolder::server_, server); - holder->closed = true; + bool done() { + return server_->done(); } - static void PausedCallback(InspectorSocketServer* server) { - ServerHolder* holder = node::ContainerOf(&ServerHolder::server_, server); - holder->paused = true; + void Connected() { + connected++; + } + + void Disconnected() { + disconnected++; + } + + void Done() { + delegate_done = true; + } + + void PrepareSession(int id) { + buffer_.clear(); + session_id_ = id; + } + + void Received(const std::string& message) { + buffer_.insert(buffer_.end(), message.begin(), message.end()); } - bool closed; - bool paused; + void Write(const std::string& message) { + server_->Send(session_id_, message); + } + + void Expect(const std::string& expects) { + SPIN_WHILE(buffer_.size() < expects.length()); + ASSERT_STREQ(std::string(buffer_.data(), expects.length()).c_str(), + expects.c_str()); + buffer_.erase(buffer_.begin(), buffer_.begin() + expects.length()); + } + + int connected = 0; + int disconnected = 0; + bool delegate_done = false; private: - InspectorSocketServer server_; + std::unique_ptr server_; + std::vector buffer_; + int session_id_; }; -class ServerDelegateNoTargets : public SocketServerDelegate { +class TestSocketServerDelegate : public SocketServerDelegate { public: - ServerDelegateNoTargets() : server_(nullptr) { } - void Connect(InspectorSocketServer* server) { } - void MessageReceived(int session_id, const std::string& message) override { } - void EndSession(int session_id) override { } + explicit TestSocketServerDelegate( + ServerHolder* server, + const std::vector& target_ids) + : harness_(server), + targets_(target_ids), + session_id_(0) {} + + ~TestSocketServerDelegate() { + harness_->Done(); + } + + void AssignServer(InspectorSocketServer* server) override { + server_ = server; + } void StartSession(int session_id, const std::string& target_id) override { - server_->DeclineSession(session_id); + session_id_ = session_id; + harness_->PrepareSession(session_id_); + CHECK_NE(targets_.end(), + std::find(targets_.begin(), targets_.end(), target_id)); + if (target_id == UNCONNECTABLE_TARGET_ID) { + server_->DeclineSession(session_id); + return; + } + harness_->Connected(); + server_->AcceptSession(session_id); } - std::vector GetTargetIds() override { - return std::vector(); + void MessageReceived(int session_id, const std::string& message) override { + CHECK_EQ(session_id_, session_id); + harness_->Received(message); } - std::string GetTargetTitle(const std::string& id) override { - return ""; + void EndSession(int session_id) override { + CHECK_EQ(session_id_, session_id); + harness_->Disconnected(); } - std::string GetTargetUrl(const std::string& id) override { - return ""; + std::vector GetTargetIds() override { + return targets_; } - void ServerDone() override { - done = true; + std::string GetTargetTitle(const std::string& id) override { + return id + " Target Title"; } - bool done = false; + std::string GetTargetUrl(const std::string& id) override { + return "file://" + id + "/script.js"; + } private: + ServerHolder* harness_; + const std::vector targets_; InspectorSocketServer* server_; + int session_id_; }; +ServerHolder::ServerHolder(bool has_targets, uv_loop_t* loop, + const std::string host, int port, FILE* out) { + std::vector targets; + if (has_targets) + targets = { MAIN_TARGET_ID, UNCONNECTABLE_TARGET_ID }; + std::unique_ptr delegate( + new TestSocketServerDelegate(this, targets)); + server_.reset( + new InspectorSocketServer(std::move(delegate), loop, host, port, out)); +} + static void TestHttpRequest(int port, const std::string& path, const std::string& expected_body) { SocketWrapper socket(&loop); @@ -402,8 +390,7 @@ static const std::string WsHandshakeRequest(const std::string& target_id) { TEST_F(InspectorSocketServerTest, InspectorSessions) { - TestInspectorServerDelegate delegate; - ServerHolder server(&delegate, &loop, 0); + ServerHolder server(true, &loop, 0); ASSERT_TRUE(server->Start()); SocketWrapper well_behaved_socket(&loop); @@ -412,18 +399,18 @@ TEST_F(InspectorSocketServerTest, InspectorSessions) { well_behaved_socket.Write(WsHandshakeRequest(MAIN_TARGET_ID)); well_behaved_socket.Expect(WS_HANDSHAKE_RESPONSE); - EXPECT_EQ(1, delegate.connected); + EXPECT_EQ(1, server.connected); well_behaved_socket.Write("\x81\x84\x7F\xC2\x66\x31\x4E\xF0\x55\x05"); - delegate.Expect("1234"); - delegate.Write("5678"); + server.Expect("1234"); + server.Write("5678"); well_behaved_socket.Expect("\x81\x4" "5678"); well_behaved_socket.Write(CLIENT_CLOSE_FRAME); well_behaved_socket.Expect(SERVER_CLOSE_FRAME); - EXPECT_EQ(1, delegate.disconnected); + EXPECT_EQ(1, server.disconnected); well_behaved_socket.Close(); @@ -433,8 +420,8 @@ TEST_F(InspectorSocketServerTest, InspectorSessions) { declined_target_socket.Write(WsHandshakeRequest(UNCONNECTABLE_TARGET_ID)); declined_target_socket.Expect("HTTP/1.0 400 Bad Request"); declined_target_socket.ExpectEOF(); - EXPECT_EQ(1, delegate.connected); - EXPECT_EQ(1, delegate.disconnected); + EXPECT_EQ(1, server.connected); + EXPECT_EQ(1, server.disconnected); // Bogus target - start session callback should not even be invoked SocketWrapper bogus_target_socket(&loop); @@ -442,8 +429,8 @@ TEST_F(InspectorSocketServerTest, InspectorSessions) { bogus_target_socket.Write(WsHandshakeRequest("bogus_target")); bogus_target_socket.Expect("HTTP/1.0 400 Bad Request"); bogus_target_socket.ExpectEOF(); - EXPECT_EQ(1, delegate.connected); - EXPECT_EQ(1, delegate.disconnected); + EXPECT_EQ(1, server.connected); + EXPECT_EQ(1, server.disconnected); // Drop connection (no proper close frames) SocketWrapper dropped_connection_socket(&loop); @@ -451,13 +438,13 @@ TEST_F(InspectorSocketServerTest, InspectorSessions) { dropped_connection_socket.Write(WsHandshakeRequest(MAIN_TARGET_ID)); dropped_connection_socket.Expect(WS_HANDSHAKE_RESPONSE); - EXPECT_EQ(2, delegate.connected); + EXPECT_EQ(2, server.connected); - delegate.Write("5678"); + server.Write("5678"); dropped_connection_socket.Expect("\x81\x4" "5678"); dropped_connection_socket.Close(); - SPIN_WHILE(delegate.disconnected < 2); + SPIN_WHILE(server.disconnected < 2); // Reconnect regular connection SocketWrapper stays_till_termination_socket(&loop); @@ -465,41 +452,38 @@ TEST_F(InspectorSocketServerTest, InspectorSessions) { stays_till_termination_socket.Write(WsHandshakeRequest(MAIN_TARGET_ID)); stays_till_termination_socket.Expect(WS_HANDSHAKE_RESPONSE); - SPIN_WHILE(3 != delegate.connected); + SPIN_WHILE(3 != server.connected); - delegate.Write("5678"); + server.Write("5678"); stays_till_termination_socket.Expect("\x81\x4" "5678"); stays_till_termination_socket .Write("\x81\x84\x7F\xC2\x66\x31\x4E\xF0\x55\x05"); - delegate.Expect("1234"); + server.Expect("1234"); - server->Stop(ServerHolder::CloseCallback); + server->Stop(); server->TerminateConnections(); stays_till_termination_socket.Write(CLIENT_CLOSE_FRAME); stays_till_termination_socket.Expect(SERVER_CLOSE_FRAME); - SPIN_WHILE(3 != delegate.disconnected); - - SPIN_WHILE(!server.closed); + SPIN_WHILE(3 != server.disconnected); + SPIN_WHILE(!server.done()); stays_till_termination_socket.ExpectEOF(); } TEST_F(InspectorSocketServerTest, ServerDoesNothing) { - TestInspectorServerDelegate delegate; - ServerHolder server(&delegate, &loop, 0); + ServerHolder server(true, &loop, 0); ASSERT_TRUE(server->Start()); - - server->Stop(ServerHolder::CloseCallback); + server->Stop(); server->TerminateConnections(); - SPIN_WHILE(!server.closed); - ASSERT_TRUE(delegate.done); + SPIN_WHILE(!server.done()); + ASSERT_TRUE(server.delegate_done); + SPIN_WHILE(uv_loop_alive(&loop)); } TEST_F(InspectorSocketServerTest, ServerWithoutTargets) { - ServerDelegateNoTargets delegate; - ServerHolder server(&delegate, &loop, 0); + ServerHolder server(false, &loop, 0); ASSERT_TRUE(server->Start()); TestHttpRequest(server.port(), "/json/list", "[ ]"); TestHttpRequest(server.port(), "/json", "[ ]"); @@ -510,89 +494,81 @@ TEST_F(InspectorSocketServerTest, ServerWithoutTargets) { socket.Write(WsHandshakeRequest(UNCONNECTABLE_TARGET_ID)); socket.Expect("HTTP/1.0 400 Bad Request"); socket.ExpectEOF(); - server->Stop(ServerHolder::CloseCallback); + server->Stop(); server->TerminateConnections(); - SPIN_WHILE(!server.closed); + SPIN_WHILE(!server.done()); + SPIN_WHILE(uv_loop_alive(&loop)); } TEST_F(InspectorSocketServerTest, ServerCannotStart) { - ServerDelegateNoTargets delegate1, delegate2; - ServerHolder server1(&delegate1, &loop, 0); + ServerHolder server1(false, &loop, 0); ASSERT_TRUE(server1->Start()); - ServerHolder server2(&delegate2, &loop, server1.port()); + ServerHolder server2(false, &loop, server1.port()); ASSERT_FALSE(server2->Start()); - server1->Stop(ServerHolder::CloseCallback); + server1->Stop(); server1->TerminateConnections(); - SPIN_WHILE(!server1.closed); - ASSERT_TRUE(delegate1.done); + SPIN_WHILE(!server1.done()); + ASSERT_TRUE(server1.delegate_done); + SPIN_WHILE(uv_loop_alive(&loop)); } TEST_F(InspectorSocketServerTest, StoppingServerDoesNotKillConnections) { - ServerDelegateNoTargets delegate; - ServerHolder server(&delegate, &loop, 0); + ServerHolder server(false, &loop, 0); ASSERT_TRUE(server->Start()); SocketWrapper socket1(&loop); socket1.Connect(HOST, server.port()); socket1.TestHttpRequest("/json/list", "[ ]"); - server->Stop(ServerHolder::CloseCallback); - SPIN_WHILE(!server.closed); + server->Stop(); socket1.TestHttpRequest("/json/list", "[ ]"); socket1.Close(); uv_run(&loop, UV_RUN_DEFAULT); - ASSERT_TRUE(delegate.done); + ASSERT_TRUE(server.delegate_done); } TEST_F(InspectorSocketServerTest, ClosingConnectionReportsDone) { - ServerDelegateNoTargets delegate; - ServerHolder server(&delegate, &loop, 0); + ServerHolder server(false, &loop, 0); ASSERT_TRUE(server->Start()); SocketWrapper socket1(&loop); socket1.Connect(HOST, server.port()); socket1.TestHttpRequest("/json/list", "[ ]"); - server->Stop(ServerHolder::CloseCallback); - SPIN_WHILE(!server.closed); + server->Stop(); socket1.TestHttpRequest("/json/list", "[ ]"); socket1.Close(); uv_run(&loop, UV_RUN_DEFAULT); - ASSERT_TRUE(delegate.done); + ASSERT_TRUE(server.delegate_done); } TEST_F(InspectorSocketServerTest, ClosingSocketReportsDone) { - TestInspectorServerDelegate delegate; - ServerHolder server(&delegate, &loop, 0); + ServerHolder server(true, &loop, 0); ASSERT_TRUE(server->Start()); SocketWrapper socket1(&loop); socket1.Connect(HOST, server.port()); socket1.Write(WsHandshakeRequest(MAIN_TARGET_ID)); socket1.Expect(WS_HANDSHAKE_RESPONSE); - server->Stop(ServerHolder::CloseCallback); - SPIN_WHILE(!server.closed); - ASSERT_FALSE(delegate.done); + server->Stop(); + ASSERT_FALSE(server.delegate_done); socket1.Close(); - SPIN_WHILE(!delegate.done); + SPIN_WHILE(!server.delegate_done); } TEST_F(InspectorSocketServerTest, TerminatingSessionReportsDone) { - TestInspectorServerDelegate delegate; - ServerHolder server(&delegate, &loop, 0); + ServerHolder server(true, &loop, 0); ASSERT_TRUE(server->Start()); SocketWrapper socket1(&loop); socket1.Connect(HOST, server.port()); socket1.Write(WsHandshakeRequest(MAIN_TARGET_ID)); socket1.Expect(WS_HANDSHAKE_RESPONSE); - server->Stop(ServerHolder::CloseCallback); - SPIN_WHILE(!server.closed); - ASSERT_FALSE(delegate.done); + server->Stop(); + ASSERT_FALSE(server.delegate_done); server->TerminateConnections(); socket1.Expect(SERVER_CLOSE_FRAME); socket1.Write(CLIENT_CLOSE_FRAME); socket1.ExpectEOF(); - SPIN_WHILE(!delegate.done); + SPIN_WHILE(!server.delegate_done); } TEST_F(InspectorSocketServerTest, FailsToBindToNodejsHost) { - TestInspectorServerDelegate delegate; - ServerHolder server(&delegate, &loop, "nodejs.org", 80, nullptr); + ServerHolder server(true, &loop, "nodejs.org", 80, nullptr); ASSERT_FALSE(server->Start()); SPIN_WHILE(uv_loop_alive(&loop)); } @@ -619,17 +595,14 @@ TEST_F(InspectorSocketServerTest, BindsToIpV6) { fprintf(stderr, "No IPv6 network detected\n"); return; } - TestInspectorServerDelegate delegate; - ServerHolder server(&delegate, &loop, "::", 0, nullptr); + ServerHolder server(true, &loop, "::", 0, nullptr); ASSERT_TRUE(server->Start()); - SocketWrapper socket1(&loop); socket1.Connect("::1", server.port(), true); socket1.Write(WsHandshakeRequest(MAIN_TARGET_ID)); socket1.Expect(WS_HANDSHAKE_RESPONSE); - server->Stop(ServerHolder::CloseCallback); - SPIN_WHILE(!server.closed); - ASSERT_FALSE(delegate.done); + server->Stop(); + ASSERT_FALSE(server.delegate_done); socket1.Close(); - SPIN_WHILE(!delegate.done); + SPIN_WHILE(!server.delegate_done); } From e2a792866ca0d5342adccad8ddc515259428bec0 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sat, 2 Jun 2018 23:24:23 +0200 Subject: [PATCH 86/93] doc: add offboarding doc Add minimal document for what to do when a Collaborator moves to Collaborator Emeritus or leaves the project. PR-URL: https://github.com/nodejs/node/pull/21103 Reviewed-By: Richard Lau Reviewed-By: Vse Mozhet Byt Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Lance Ball Reviewed-By: Matheus Marchini --- doc/offboarding.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 doc/offboarding.md diff --git a/doc/offboarding.md b/doc/offboarding.md new file mode 100644 index 00000000000000..5b7a1e1231e8d7 --- /dev/null +++ b/doc/offboarding.md @@ -0,0 +1,16 @@ +# Offboarding + +This document is a checklist of things to do when a Collaborator becomes +Emeritus or leaves the project. + +* Remove the Collaborator from the @nodejs/collaborators team. +* Open a fast-track pull request to move the Collaborator to Collaborator + Emeriti in README.md. +* Email the TSC mailing list to notify TSC members that the Collaborator is + moving to Collaborator Emeritus. +* Determine what GitHub teams the Collaborator belongs to. In consultation with + the Collaborator, determine which of those teams they should be removed from. + * Some teams may also require a pull request to remove the Collaborator from + a team listing. For example, if someone is removed from @nodejs/build, + they should also be removed from the Build WG README.md file in the + https://github.com/nodejs/build repository. From 8161287b4042e757773a00464f8da43b8e109aad Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Mon, 4 Jun 2018 15:08:16 +0200 Subject: [PATCH 87/93] test: move benchmark-dgram to sequential MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This test uses hardcoded ports, it should not be located in parallel. PR-URL: https://github.com/nodejs/node/pull/21144 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: Joyee Cheung Reviewed-By: Trivikram Kamat Reviewed-By: Rich Trott --- test/{parallel => sequential}/test-benchmark-dgram.js | 4 ++++ 1 file changed, 4 insertions(+) rename test/{parallel => sequential}/test-benchmark-dgram.js (63%) diff --git a/test/parallel/test-benchmark-dgram.js b/test/sequential/test-benchmark-dgram.js similarity index 63% rename from test/parallel/test-benchmark-dgram.js rename to test/sequential/test-benchmark-dgram.js index 69eafbcb13b46b..8c93cd5a0c9239 100644 --- a/test/parallel/test-benchmark-dgram.js +++ b/test/sequential/test-benchmark-dgram.js @@ -4,6 +4,10 @@ require('../common'); const runBenchmark = require('../common/benchmark'); +// Because the dgram 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. + runBenchmark('dgram', ['address=true', 'chunks=2', 'dur=0.1', From 1d22254c4db33e3362eacfc79fdad881bb922731 Mon Sep 17 00:00:00 2001 From: ErnestoSalazar Date: Thu, 31 May 2018 14:26:31 -0700 Subject: [PATCH 88/93] https: removed extra _http_server require PR-URL: https://github.com/nodejs/node/pull/21069 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Kyle Farnung Reviewed-By: Trivikram Kamat Reviewed-By: Rich Trott Reviewed-By: Daniel Bevenius Reviewed-By: Jon Moss Reviewed-By: Luigi Pinca --- lib/https.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/https.js b/lib/https.js index 2237a909e999c3..94d9bf8dcf0a7a 100644 --- a/lib/https.js +++ b/lib/https.js @@ -29,7 +29,8 @@ const util = require('util'); const { Agent: HttpAgent } = require('_http_agent'); const { Server: HttpServer, - _connectionListener + _connectionListener, + kServerResponse } = require('_http_server'); const { ClientRequest } = require('_http_client'); const { inherits } = util; @@ -38,7 +39,6 @@ const { urlToOptions, searchParamsSymbol } = require('internal/url'); const { ERR_INVALID_DOMAIN_NAME } = require('internal/errors').codes; 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); From 48aa4c32d000078edc94c7aac88e7ac54af16bd8 Mon Sep 17 00:00:00 2001 From: ErnestoSalazar Date: Thu, 31 May 2018 14:27:22 -0700 Subject: [PATCH 89/93] zlib: removed extra util require PR-URL: https://github.com/nodejs/node/pull/21069 Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Kyle Farnung Reviewed-By: Trivikram Kamat Reviewed-By: Rich Trott Reviewed-By: Daniel Bevenius Reviewed-By: Jon Moss Reviewed-By: Luigi Pinca --- lib/zlib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zlib.js b/lib/zlib.js index 5ce8637a50f04f..d8a1cb57c5a892 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -30,6 +30,7 @@ const { const Transform = require('_stream_transform'); const { _extend, + inherits, types: { isAnyArrayBuffer, isArrayBufferView @@ -50,7 +51,6 @@ const { Z_DEFAULT_STRATEGY, Z_DEFAULT_WINDOWBITS, Z_DEFAULT_MEMLEVEL, Z_FIXED, DEFLATE, DEFLATERAW, INFLATE, INFLATERAW, GZIP, GUNZIP, UNZIP } = constants; -const { inherits } = require('util'); // translation table for return codes. const codes = { From 2c671ab2fde3f42efa8c88ce74e5b1c7b77ead4e Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 4 Jun 2018 12:07:08 -0700 Subject: [PATCH 90/93] doc: fix typo in addons.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "across version of Node.js" -> "across versions of Node.js" PR-URL: https://github.com/nodejs/node/pull/21137 Reviewed-By: Vse Mozhet Byt Reviewed-By: Trivikram Kamat Reviewed-By: Michaël Zasso Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- doc/api/addons.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/addons.md b/doc/api/addons.md index afbbdd843cb223..a0e16cff3521d4 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -224,7 +224,7 @@ illustration of how it can be used. N-API is an API for building native Addons. It is independent from the underlying JavaScript runtime (e.g. V8) and is maintained as part of Node.js itself. This API will be Application Binary Interface (ABI) stable -across version of Node.js. It is intended to insulate Addons from +across versions of Node.js. It is intended to insulate Addons from changes in the underlying JavaScript engine and allow modules compiled for one version to run on later versions of Node.js without recompilation. Addons are built/packaged with the same approach/tools From afc811cc1cc166cad28e2516a4f7862a2e3202fe Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 18 May 2018 16:59:37 +0200 Subject: [PATCH 91/93] src: break out of timers loop if `!can_call_into_js()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, this turns into an infinite loop when the flag is set, because it makes `MakeCallback()` return immediately. Backport-PR-URL: https://github.com/nodejs/node/pull/21168 PR-URL: https://github.com/nodejs/node/pull/20884 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Tobias Nießen --- src/timer_wrap.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc index 88377a3e1b88cc..50541acc9b8a0d 100644 --- a/src/timer_wrap.cc +++ b/src/timer_wrap.cc @@ -148,6 +148,7 @@ class TimerWrap : public HandleWrap { .ToLocalChecked(); } while (ret->IsUndefined() && !env->tick_info()->has_thrown() && + env->can_call_into_js() && wrap->object()->Get(env->context(), env->owner_string()).ToLocalChecked() ->IsUndefined()); From 440e899d948277146e90960eab45755c0938d975 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Tue, 29 May 2018 17:12:52 +0200 Subject: [PATCH 92/93] tools: ensure doc-only doesn't update package-lock Currently `make doc-only` is updating the package-lock.json which is breaking our release build. This adds the flags `--no-package-lock` when running `npm install` to ensure the package-lock.json is not changed unintentionally by running make PR-URL: https://github.com/nodejs/node/pull/21015 Reviewed-By: Gus Caplan Reviewed-By: Refael Ackermann Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Trivikram Kamat --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a7099947c72a78..b11168aaa456af 100644 --- a/Makefile +++ b/Makefile @@ -643,7 +643,7 @@ available-node = \ exit 1; \ fi; -run-npm-install = $(PWD)/$(NPM) install --production +run-npm-install = $(PWD)/$(NPM) install --production --no-package-lock tools/doc/node_modules/js-yaml/package.json: cd tools/doc && $(call available-node,$(run-npm-install)) From 1e88953977430db46c9928b4b1984b6275a74729 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 6 Jun 2018 11:12:48 +0200 Subject: [PATCH 93/93] 2018-06-06, Version 10.4.0 (Current) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notable Changes: * **deps**: - update V8 to 6.7.288.43 (Michaël Zasso) https://github.com/nodejs/node/pull/19989 * **stream**: - ensure Stream.pipeline re-throws errors without callback (Blaine Bublitz) https://github.com/nodejs/node/pull/20437 PR-URL: https://github.com/nodejs/node/pull/21167 --- CHANGELOG.md | 3 +- doc/changelogs/CHANGELOG_V10.md | 106 ++++++++++++++++++++++++++++++++ src/node_version.h | 6 +- 3 files changed, 111 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ab73471c87b8a..e3c26a907b67f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,8 @@ release. -10.3.0
+10.4.0
+10.3.0
10.2.1
10.2.0
10.1.0
diff --git a/doc/changelogs/CHANGELOG_V10.md b/doc/changelogs/CHANGELOG_V10.md index d01b2901301ce3..5487e7b30db707 100644 --- a/doc/changelogs/CHANGELOG_V10.md +++ b/doc/changelogs/CHANGELOG_V10.md @@ -9,6 +9,7 @@ +10.4.0
10.3.0
10.2.1
10.2.0
@@ -30,6 +31,111 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2018-06-06, Version 10.4.0 (Current), @MylesBorins + +### Notable Changes + +* **deps**: + - update V8 to 6.7.288.43 (Michaël Zasso) [#19989](https://github.com/nodejs/node/pull/19989) +* **stream**: + - ensure Stream.pipeline re-throws errors without callback (Blaine Bublitz) [#20437](https://github.com/nodejs/node/pull/20437) + +### Commits + +* [[`9ada68b186`](https://github.com/nodejs/node/commit/9ada68b186)] - **benchmark**: refactor benchmark/assert/throws.js (Rich Trott) [#21030](https://github.com/nodejs/node/pull/21030) +* [[`b8470b929f`](https://github.com/nodejs/node/commit/b8470b929f)] - **benchmark**: refactor deepequal-typedarrays (Rich Trott) [#21030](https://github.com/nodejs/node/pull/21030) +* [[`686587ba1a`](https://github.com/nodejs/node/commit/686587ba1a)] - **benchmark**: refactor deepequal-set (Rich Trott) [#21030](https://github.com/nodejs/node/pull/21030) +* [[`56c67595db`](https://github.com/nodejs/node/commit/56c67595db)] - **benchmark**: refactor prims-and-objs-big-loop (Rich Trott) [#21030](https://github.com/nodejs/node/pull/21030) +* [[`6fbb00e887`](https://github.com/nodejs/node/commit/6fbb00e887)] - **benchmark**: refactor prims-and-objs-big-array-set (Rich Trott) [#21030](https://github.com/nodejs/node/pull/21030) +* [[`4d714421e9`](https://github.com/nodejs/node/commit/4d714421e9)] - **benchmark**: refactor deepequal-object (Rich Trott) [#21030](https://github.com/nodejs/node/pull/21030) +* [[`9b0fc59723`](https://github.com/nodejs/node/commit/9b0fc59723)] - **benchmark**: refactor deepequal-map (Rich Trott) [#21030](https://github.com/nodejs/node/pull/21030) +* [[`90d86586d2`](https://github.com/nodejs/node/commit/90d86586d2)] - **benchmark**: refactor deepequal-buffer (Rich Trott) [#21030](https://github.com/nodejs/node/pull/21030) +* [[`be249d9eb5`](https://github.com/nodejs/node/commit/be249d9eb5)] - **benchmark**: fix "comparisons"' typo (Yuta Hiroto) [#21085](https://github.com/nodejs/node/pull/21085) +* [[`bad3c92124`](https://github.com/nodejs/node/commit/bad3c92124)] - **(SEMVER-MINOR)** **build**: reset embedder string to "-node.0" (Michaël Zasso) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`35d6661973`](https://github.com/nodejs/node/commit/35d6661973)] - **deps**: cherry-pick 6989b3f6d7 from V8 upstream (Timothy Gu) [#20826](https://github.com/nodejs/node/pull/20826) +* [[`4e788dc2f5`](https://github.com/nodejs/node/commit/4e788dc2f5)] - **(SEMVER-MINOR)** **deps**: backport 91ddb65d from upstream V8 (Maya Lekova) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`fb2686148e`](https://github.com/nodejs/node/commit/fb2686148e)] - **deps**: cherry-pick ff0a9793334 from upstream V8 (Anna Henningsen) [#20719](https://github.com/nodejs/node/pull/20719) +* [[`40c8bbecec`](https://github.com/nodejs/node/commit/40c8bbecec)] - **deps**: cherry-pick 23652c5f from upstream V8 (Eugene Ostroukhov) [#20608](https://github.com/nodejs/node/pull/20608) +* [[`a7aff77a97`](https://github.com/nodejs/node/commit/a7aff77a97)] - **(SEMVER-MINOR)** **deps**: cherry-pick 39d546a from upstream V8 (Gus Caplan) [#20016](https://github.com/nodejs/node/pull/20016) +* [[`fed1d18054`](https://github.com/nodejs/node/commit/fed1d18054)] - **(SEMVER-MINOR)** **deps**: update v8.gyp (Michaël Zasso) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`da8ad4aba9`](https://github.com/nodejs/node/commit/da8ad4aba9)] - **(SEMVER-MINOR)** **deps**: update V8 to 6.7.288.43 (Michaël Zasso) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`2c671ab2fd`](https://github.com/nodejs/node/commit/2c671ab2fd)] - **doc**: fix typo in addons.md (Rich Trott) [#21137](https://github.com/nodejs/node/pull/21137) +* [[`e2a792866c`](https://github.com/nodejs/node/commit/e2a792866c)] - **doc**: add offboarding doc (Rich Trott) [#21103](https://github.com/nodejs/node/pull/21103) +* [[`15aa3c1046`](https://github.com/nodejs/node/commit/15aa3c1046)] - **doc**: add notable-change to onboarding.md exercise (Rich Trott) [#21040](https://github.com/nodejs/node/pull/21040) +* [[`29c35bd0de`](https://github.com/nodejs/node/commit/29c35bd0de)] - **doc**: remove link prediction from STYLE\_GUIDE.md (Rich Trott) [#21031](https://github.com/nodejs/node/pull/21031) +* [[`261ef1d242`](https://github.com/nodejs/node/commit/261ef1d242)] - **doc**: remove POST\_STATUS\_TO\_PR from onboarding.md (Rich Trott) [#21042](https://github.com/nodejs/node/pull/21042) +* [[`2edf1728a0`](https://github.com/nodejs/node/commit/2edf1728a0)] - **doc**: fix typos on `e.g.` abbreviations (Rich Trott) [#21045](https://github.com/nodejs/node/pull/21045) +* [[`b1f0907416`](https://github.com/nodejs/node/commit/b1f0907416)] - **doc**: use "is" rather than "has been" (Rich Trott) [#21043](https://github.com/nodejs/node/pull/21043) +* [[`f5bf2c8d08`](https://github.com/nodejs/node/commit/f5bf2c8d08)] - **doc**: move upstream information to onboarding doc (Rich Trott) [#21029](https://github.com/nodejs/node/pull/21029) +* [[`09aec436cb`](https://github.com/nodejs/node/commit/09aec436cb)] - **doc**: remove vestigial onboarding section (Rich Trott) [#21028](https://github.com/nodejs/node/pull/21028) +* [[`fd201e0d32`](https://github.com/nodejs/node/commit/fd201e0d32)] - **doc**: add guides on writing tests involving promises (Joyee Cheung) [#20988](https://github.com/nodejs/node/pull/20988) +* [[`4cd44203de`](https://github.com/nodejs/node/commit/4cd44203de)] - **doc**: remove invalid `vm.Script` arguments (Simen Bekkhus) [#20984](https://github.com/nodejs/node/pull/20984) +* [[`4012e0550a`](https://github.com/nodejs/node/commit/4012e0550a)] - **doc**: fix typo in n-api.md (ohbarye) [#21060](https://github.com/nodejs/node/pull/21060) +* [[`bb8d341714`](https://github.com/nodejs/node/commit/bb8d341714)] - **doc**: better font stack for monospace in docs (Roman Reiss) [#21036](https://github.com/nodejs/node/pull/21036) +* [[`1b8e8e90af`](https://github.com/nodejs/node/commit/1b8e8e90af)] - **doc**: make minor improvements to fs.realpath() docs (Rich Trott) [#20953](https://github.com/nodejs/node/pull/20953) +* [[`c2ae93db63`](https://github.com/nodejs/node/commit/c2ae93db63)] - **doc**: add missing link for 10.3.0 changelog (Myles Borins) [#21017](https://github.com/nodejs/node/pull/21017) +* [[`8dc7c883a7`](https://github.com/nodejs/node/commit/8dc7c883a7)] - **doc**: improve note on zlib APIs threadpool usage (Luigi Pinca) [#20380](https://github.com/nodejs/node/pull/20380) +* [[`ab43581f15`](https://github.com/nodejs/node/commit/ab43581f15)] - **doc**: make constants enumeration consistent (Diego Rodríguez Baquero) [#20991](https://github.com/nodejs/node/pull/20991) +* [[`44ef458d9c`](https://github.com/nodejs/node/commit/44ef458d9c)] - **fs**: ensure options.flag defaults to 'r' in readFile (Unknown) [#20268](https://github.com/nodejs/node/pull/20268) +* [[`341b2c21f3`](https://github.com/nodejs/node/commit/341b2c21f3)] - **http2**: fix premature destroy (Anatoli Papirovski) [#21051](https://github.com/nodejs/node/pull/21051) +* [[`d4787cfd61`](https://github.com/nodejs/node/commit/d4787cfd61)] - **http2**: force through RST\_STREAM in destroy (Anatoli Papirovski) [#21016](https://github.com/nodejs/node/pull/21016) +* [[`2a9912c0df`](https://github.com/nodejs/node/commit/2a9912c0df)] - **http2**: delay closing stream (Anatoli Papirovski) [#20997](https://github.com/nodejs/node/pull/20997) +* [[`182c73bf7f`](https://github.com/nodejs/node/commit/182c73bf7f)] - **http2**: switch to new runtime-controlled debugging system (Anna Henningsen) [#20987](https://github.com/nodejs/node/pull/20987) +* [[`1d22254c4d`](https://github.com/nodejs/node/commit/1d22254c4d)] - **https**: removed extra \_http\_server require (ErnestoSalazar) [#21069](https://github.com/nodejs/node/pull/21069) +* [[`1c211ec901`](https://github.com/nodejs/node/commit/1c211ec901)] - **inspector**: code cleanup (Eugene Ostroukhov) [#21070](https://github.com/nodejs/node/pull/21070) +* [[`a30bf55e69`](https://github.com/nodejs/node/commit/a30bf55e69)] - **lib**: use focused ESLint disabling in util.js (Rich Trott) [#21041](https://github.com/nodejs/node/pull/21041) +* [[`f2c9e5af09`](https://github.com/nodejs/node/commit/f2c9e5af09)] - **lib**: introduce internal/validators (Michaël Zasso) [#21149](https://github.com/nodejs/node/pull/21149) +* [[`46d1025add`](https://github.com/nodejs/node/commit/46d1025add)] - **net**: use object destructuring (starkewang) [#20959](https://github.com/nodejs/node/pull/20959) +* [[`afc811cc1c`](https://github.com/nodejs/node/commit/afc811cc1c)] - **src**: break out of timers loop if `!can\_call\_into\_js()` (Anna Henningsen) [#20884](https://github.com/nodejs/node/pull/20884) +* [[`8862f0a613`](https://github.com/nodejs/node/commit/8862f0a613)] - **src**: store pointer to Environment on DestroyParam (Anatoli Papirovski) [#21099](https://github.com/nodejs/node/pull/21099) +* [[`66f4c7bdec`](https://github.com/nodejs/node/commit/66f4c7bdec)] - **src**: fix typo string\_search.h comment (Masashi Hirano) [#21115](https://github.com/nodejs/node/pull/21115) +* [[`f79096a3f2`](https://github.com/nodejs/node/commit/f79096a3f2)] - **src**: do not cache `NumberOfHeapSpaces()` globally (Anna Henningsen) [#20971](https://github.com/nodejs/node/pull/20971) +* [[`7c0c61bde1`](https://github.com/nodejs/node/commit/7c0c61bde1)] - **(SEMVER-MINOR)** **src**: update postmortem constant name (cjihrig) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`2d3137c5a9`](https://github.com/nodejs/node/commit/2d3137c5a9)] - **(SEMVER-MINOR)** **src**: fix GetCpuProfiler() deprecation warning (Michaël Zasso) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`af62a16ff6`](https://github.com/nodejs/node/commit/af62a16ff6)] - **(SEMVER-MINOR)** ***Revert*** "**src**: fix GetCpuProfiler() deprecation warning" (Michaël Zasso) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`af06581b84`](https://github.com/nodejs/node/commit/af06581b84)] - **src**: restore stdio on program exit (Ben Noordhuis) [#20592](https://github.com/nodejs/node/pull/20592) +* [[`45eeea4330`](https://github.com/nodejs/node/commit/45eeea4330)] - **src**: implement debug output utilities (Anna Henningsen) [#20987](https://github.com/nodejs/node/pull/20987) +* [[`ebbd036d0b`](https://github.com/nodejs/node/commit/ebbd036d0b)] - **src**: remove unused private data member (Ben Noordhuis) [#20974](https://github.com/nodejs/node/pull/20974) +* [[`d4f507b23b`](https://github.com/nodejs/node/commit/d4f507b23b)] - **src**: remove unused req\_wrap-inl.h (Daniel Bevenius) [#20996](https://github.com/nodejs/node/pull/20996) +* [[`44fe78b09a`](https://github.com/nodejs/node/commit/44fe78b09a)] - **stream**: inline needMoreData function (Miklos Suveges) [#21009](https://github.com/nodejs/node/pull/21009) +* [[`d1e81b0f17`](https://github.com/nodejs/node/commit/d1e81b0f17)] - **stream**: ensure Stream.pipeline re-throws errors without callback (Blaine Bublitz) [#20437](https://github.com/nodejs/node/pull/20437) +* [[`8161287b40`](https://github.com/nodejs/node/commit/8161287b40)] - **test**: move benchmark-dgram to sequential (Anatoli Papirovski) [#21144](https://github.com/nodejs/node/pull/21144) +* [[`9d41ab466b`](https://github.com/nodejs/node/commit/9d41ab466b)] - **test**: refactor child-process-fork-net (Rich Trott) [#21095](https://github.com/nodejs/node/pull/21095) +* [[`820236fd0d`](https://github.com/nodejs/node/commit/820236fd0d)] - **test**: mark test-trace-events-fs-sync as flaky (Matheus Marchini) [#21039](https://github.com/nodejs/node/pull/21039) +* [[`2d36150852`](https://github.com/nodejs/node/commit/2d36150852)] - **test**: string-decorater.lastChar (Masashi Hirano) [#21084](https://github.com/nodejs/node/pull/21084) +* [[`1733ef9dec`](https://github.com/nodejs/node/commit/1733ef9dec)] - **test**: make handling of noWarnCode stricter (Tobias Nießen) [#21075](https://github.com/nodejs/node/pull/21075) +* [[`1e607d0910`](https://github.com/nodejs/node/commit/1e607d0910)] - **test**: add source for test.wasm (Daniel Bevenius) [#21082](https://github.com/nodejs/node/pull/21082) +* [[`28f2dcb22a`](https://github.com/nodejs/node/commit/28f2dcb22a)] - **test**: update test-dns error message (Rich Trott) [#21116](https://github.com/nodejs/node/pull/21116) +* [[`c60810a853`](https://github.com/nodejs/node/commit/c60810a853)] - **test**: increase slop limit in memory leak test (Ben Noordhuis) [#21080](https://github.com/nodejs/node/pull/21080) +* [[`fda8654161`](https://github.com/nodejs/node/commit/fda8654161)] - **test**: log before and after RSS in memory leak test (Ben Noordhuis) [#21080](https://github.com/nodejs/node/pull/21080) +* [[`8e3e18ef7d`](https://github.com/nodejs/node/commit/8e3e18ef7d)] - **test**: unmark test-zlib.zlib-binding.deflate flaky (Anatoli Papirovski) [#21109](https://github.com/nodejs/node/pull/21109) +* [[`bd0d19dae7`](https://github.com/nodejs/node/commit/bd0d19dae7)] - **test**: minor adjustments to test-http2-respond-file (Anna Henningsen) [#21098](https://github.com/nodejs/node/pull/21098) +* [[`c4fc1ff295`](https://github.com/nodejs/node/commit/c4fc1ff295)] - **test**: fix flaky async-hooks/test-zlib.zlib-binding.deflate (Anna Henningsen) [#21077](https://github.com/nodejs/node/pull/21077) +* [[`c8ee379d85`](https://github.com/nodejs/node/commit/c8ee379d85)] - **test**: run crypto benchmark only once in tests (Rich Trott) [#21032](https://github.com/nodejs/node/pull/21032) +* [[`a3fdd2e4c5`](https://github.com/nodejs/node/commit/a3fdd2e4c5)] - **test**: add option to test-benchmark-timers (Rich Trott) [#21032](https://github.com/nodejs/node/pull/21032) +* [[`60abd08c7f`](https://github.com/nodejs/node/commit/60abd08c7f)] - **test**: remove unused empty fixture (Rich Trott) [#21044](https://github.com/nodejs/node/pull/21044) +* [[`f7886ab8ad`](https://github.com/nodejs/node/commit/f7886ab8ad)] - **test**: avoid empty fixture in module test (Rich Trott) [#21044](https://github.com/nodejs/node/pull/21044) +* [[`c74c83a4c1`](https://github.com/nodejs/node/commit/c74c83a4c1)] - **test**: avoid empty fixture in fs test (Rich Trott) [#21044](https://github.com/nodejs/node/pull/21044) +* [[`d84aa51dc7`](https://github.com/nodejs/node/commit/d84aa51dc7)] - **test**: removed message from strictEqual (Lucas Liepert) [#20983](https://github.com/nodejs/node/pull/20983) +* [[`e4224fd793`](https://github.com/nodejs/node/commit/e4224fd793)] - **test**: improve path tests (Shivang) [#20967](https://github.com/nodejs/node/pull/20967) +* [[`df97791447`](https://github.com/nodejs/node/commit/df97791447)] - **(SEMVER-MINOR)** **test**: update postmortem metadata test (cjihrig) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`aa08f6464c`](https://github.com/nodejs/node/commit/aa08f6464c)] - **(SEMVER-MINOR)** **test**: add read\_only\_space heap space (cjihrig) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`ea81d42ddc`](https://github.com/nodejs/node/commit/ea81d42ddc)] - **test**: show actual error in next-tick-when-exiting (Shailesh Shekhawat) [#20956](https://github.com/nodejs/node/pull/20956) +* [[`7e1f61070e`](https://github.com/nodejs/node/commit/7e1f61070e)] - **test**: fix flaky test-domain-timers (Anatoli Papirovski) [#21019](https://github.com/nodejs/node/pull/21019) +* [[`2bbd99c7b2`](https://github.com/nodejs/node/commit/2bbd99c7b2)] - **test**: check TTY mode reset on exit (Anna Henningsen) [#21027](https://github.com/nodejs/node/pull/21027) +* [[`adbbf0d625`](https://github.com/nodejs/node/commit/adbbf0d625)] - **test**: mark test-fs-readfile-tostring-fail as flaky (Matheus Marchini) [#21013](https://github.com/nodejs/node/pull/21013) +* [[`ff5f20fc7b`](https://github.com/nodejs/node/commit/ff5f20fc7b)] - **test**: add test for fs.promises.lchmod (Masashi Hirano) [#20584](https://github.com/nodejs/node/pull/20584) +* [[`04af69750c`](https://github.com/nodejs/node/commit/04af69750c)] - **test**: mark test-child-process-fork-net as flaky (Matheus Marchini) [#21018](https://github.com/nodejs/node/pull/21018) +* [[`edf42985d7`](https://github.com/nodejs/node/commit/edf42985d7)] - **test**: fix worker send error (Gireesh Punathil) [#20973](https://github.com/nodejs/node/pull/20973) +* [[`ba71fe8bd3`](https://github.com/nodejs/node/commit/ba71fe8bd3)] - **timers**: check can\_call\_into\_js in Immediates (Anatoli Papirovski) [#21057](https://github.com/nodejs/node/pull/21057) +* [[`440e899d94`](https://github.com/nodejs/node/commit/440e899d94)] - **tools**: ensure doc-only doesn't update package-lock (Myles Borins) [#21015](https://github.com/nodejs/node/pull/21015) +* [[`b5b7459e5c`](https://github.com/nodejs/node/commit/b5b7459e5c)] - **trace_events**: add version metadata (James M Snell) [#20852](https://github.com/nodejs/node/pull/20852) +* [[`4c48b69e90`](https://github.com/nodejs/node/commit/4c48b69e90)] - **(SEMVER-MINOR)** **util**: add type check function for BigIntObject (Michaël Zasso) [#19989](https://github.com/nodejs/node/pull/19989) +* [[`b2808ed929`](https://github.com/nodejs/node/commit/b2808ed929)] - **util**: fix inspection of module namespaces (Gus Caplan) [#20962](https://github.com/nodejs/node/pull/20962) +* [[`ec058193a8`](https://github.com/nodejs/node/commit/ec058193a8)] - **v8**: backport 9fb02b526f1cd3b859a530a01adb08bc0d089f4f (Gus Caplan) [#20575](https://github.com/nodejs/node/pull/20575) +* [[`48aa4c32d0`](https://github.com/nodejs/node/commit/48aa4c32d0)] - **zlib**: removed extra util require (ErnestoSalazar) [#21069](https://github.com/nodejs/node/pull/21069) + ## 2018-05-29, Version 10.3.0 (Current), @MylesBorins diff --git a/src/node_version.h b/src/node_version.h index 88681ac0ae9704..0e0f325d07a63c 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -23,13 +23,13 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 10 -#define NODE_MINOR_VERSION 3 -#define NODE_PATCH_VERSION 1 +#define NODE_MINOR_VERSION 4 +#define NODE_PATCH_VERSION 0 #define NODE_VERSION_IS_LTS 0 #define NODE_VERSION_LTS_CODENAME "" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)