Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock X-Debbugs-Cc: secur...@debian.org
Please unblock package nodejs [ Reason ] Debian security team plans to upload nodejs security updates "as-is", at least while upstream still maintain nodejs 12.x. This is what was done in Buster. Latest security update is 12.22.4 (severity high). I did not try to get nodejs > 12.21.0 into bullseye up until now because upstream changes were essentially not concerning the debian package. However the 12.22.4 release has many v8 fixes, and a security fix (high). [ Impact ] If not in Bullseye, it will require users to download nodejs a second time just after installation, through security updates. So it will postpone any issue post-release. [ Tests ] Usual thorough upstream test suite + all dependents packages tests. [ Risks ] Low, but when considering the regressions i saw false positives: - node-chokidar seems to have a flaky test - node-esquery, node-caniuse-api, node-browserslist suites fail on their own, for an unrelated problem - node-websocket-driver was already broken, probably for a long time. I opened #991700 and will ask its removal from testing. Also an undocumented internal api has been deprecated, and old modules trying accessing it will now print a warning (process.binding('http_parser')). Only node-websocket-driver is actually using it... A code search shows node-http-signature, node-fastcgi are using it in their test suites, but it doesn't pose any problem. https://codesearch.debian.net/search?q=process%5C.binding%5C%28%5B%27%22%5Dhttp_parser%5B%27%22%5D%5C%29&literal=0 [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] debdiff is without deps/cares (not used), deps/openssl (not used), test/*, benchmark/*, tools/msvs/*. Still waiting for armhf test results when writing this request. unblock nodejs/12.22.4~dfsg-1
diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/common.gypi nodejs-12.22.4~dfsg/common.gypi --- nodejs-12.21.0~dfsg/common.gypi 2021-02-23 03:58:04.000000000 +0100 +++ nodejs-12.22.4~dfsg/common.gypi 2021-07-29 12:35:21.000000000 +0200 @@ -34,7 +34,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.45', + 'v8_embedder_string': '-node.56', ##### V8 defaults for Node.js ##### diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/debian/changelog nodejs-12.22.4~dfsg/debian/changelog --- nodejs-12.21.0~dfsg/debian/changelog 2021-07-03 20:50:29.000000000 +0200 +++ nodejs-12.22.4~dfsg/debian/changelog 2021-07-30 01:02:46.000000000 +0200 @@ -1,3 +1,12 @@ +nodejs (12.22.4~dfsg-1) unstable; urgency=medium + + * New upstream version 12.22.4~dfsg + Fixed vulnerabilities: + + CVE-2021-22930: Use after free on close http2 + on stream canceling (High) + + -- Jérémy Lal <kapo...@melix.org> Fri, 30 Jul 2021 01:02:46 +0200 + nodejs (12.21.0~dfsg-5) unstable; urgency=medium * Patch uvwasi.gyp to honour --shared-libuv. Closes: #990569. diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/cjs-module-lexer/lexer.js nodejs-12.22.4~dfsg/deps/cjs-module-lexer/lexer.js --- nodejs-12.21.0~dfsg/deps/cjs-module-lexer/lexer.js 2021-02-23 03:58:04.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/cjs-module-lexer/lexer.js 2021-07-29 12:35:21.000000000 +0200 @@ -37,8 +37,6 @@ const ExportAssign = 1; const ExportStar = 2; -const strictReserved = new Set(['implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'yield', 'enum']); - function parseCJS (source, name = '@') { resetState(); try { @@ -49,14 +47,39 @@ e.loc = pos; throw e; } - const result = { exports: [..._exports].filter(expt => !unsafeGetters.has(expt)), reexports: [...reexports] }; + const result = { exports: [..._exports].filter(expt => expt !== undefined && !unsafeGetters.has(expt)), reexports: [...reexports].filter(reexpt => reexpt !== undefined) }; resetState(); return result; } -function addExport (name) { - if (!strictReserved.has(name)) - _exports.add(name); +function decode (str) { + if (str[0] === '"' || str[0] === '\'') { + try { + const decoded = (0, eval)(str); + // Filter to exclude non-matching UTF-16 surrogate strings + for (let i = 0; i < decoded.length; i++) { + const surrogatePrefix = decoded.charCodeAt(i) & 0xFC00; + if (surrogatePrefix < 0xD800) { + // Not a surrogate + continue; + } + else if (surrogatePrefix === 0xD800) { + // Validate surrogate pair + if ((decoded.charCodeAt(++i) & 0xFC00) !== 0xDC00) + return; + } + else { + // Out-of-range surrogate code (above 0xD800) + return; + } + } + return decoded; + } + catch {} + } + else { + return str; + } } function parseSource (cjsSource) { @@ -97,7 +120,18 @@ lastTokenPos = pos; continue; case 95/*_*/: - if (source.startsWith('_export', pos + 1) && (keywordStart(pos) || source.charCodeAt(pos - 1) === 46/*.*/)) { + if (source.startsWith('interopRequireWildcard', pos + 1) && (keywordStart(pos) || source.charCodeAt(pos - 1) === 46/*.*/)) { + const startPos = pos; + pos += 23; + if (source.charCodeAt(pos) === 40/*(*/) { + pos++; + openTokenPosStack[openTokenDepth++] = lastTokenPos; + if (tryParseRequire(Import) && keywordStart(startPos)) { + tryBacktrackAddStarExportBinding(startPos - 1); + } + } + } + else if (source.startsWith('_export', pos + 1) && (keywordStart(pos) || source.charCodeAt(pos - 1) === 46/*.*/)) { pos += 8; if (source.startsWith('Star', pos)) pos += 4; @@ -162,10 +196,8 @@ // TODO: <!-- XML comment support break; case 39/*'*/: - singleQuoteString(); - break; case 34/*"*/: - doubleQuoteString(); + stringLiteral(ch); break; case 47/*/*/: { const next_ch = source.charCodeAt(pos + 1); @@ -254,6 +286,48 @@ } } +// `Object.` `prototype.`? hasOwnProperty.call(` IDENTIFIER `, ` IDENTIFIER$2 `)` +function tryParseObjectHasOwnProperty (it_id) { + ch = commentWhitespace(); + if (ch !== 79/*O*/ || !source.startsWith('bject', pos + 1)) return false; + pos += 6; + ch = commentWhitespace(); + if (ch !== 46/*.*/) return false; + pos++; + ch = commentWhitespace(); + if (ch === 112/*p*/) { + if (!source.startsWith('rototype', pos + 1)) return false; + pos += 9; + ch = commentWhitespace(); + if (ch !== 46/*.*/) return false; + pos++; + ch = commentWhitespace(); + } + if (ch !== 104/*h*/ || !source.startsWith('asOwnProperty', pos + 1)) return false; + pos += 14; + ch = commentWhitespace(); + if (ch !== 46/*.*/) return false; + pos++; + ch = commentWhitespace(); + if (ch !== 99/*c*/ || !source.startsWith('all', pos + 1)) return false; + pos += 4; + ch = commentWhitespace(); + if (ch !== 40/*(*/) return false; + pos++; + ch = commentWhitespace(); + if (!identifier()) return false; + ch = commentWhitespace(); + if (ch !== 44/*,*/) return false; + pos++; + ch = commentWhitespace(); + if (!source.startsWith(it_id, pos)) return false; + pos += it_id.length; + ch = commentWhitespace(); + if (ch !== 41/*)*/) return false; + pos++; + return true; +} + function tryParseObjectDefineOrKeys (keys) { pos += 6; let revertPos = pos - 1; @@ -276,11 +350,9 @@ pos++; ch = commentWhitespace(); if (ch !== 39/*'*/ && ch !== 34/*"*/) break; - let quot = ch; - const exportPos = ++pos; - if (!identifier() || source.charCodeAt(pos) !== quot) break; - expt = source.slice(exportPos, pos); - pos++; + const exportPos = pos; + stringLiteral(ch); + expt = source.slice(exportPos, ++pos); ch = commentWhitespace(); if (ch !== 44/*,*/) break; pos++; @@ -307,7 +379,7 @@ pos += 5; ch = commentWhitespace(); if (ch !== 58/*:*/) break; - addExport(expt); + _exports.add(decode(expt)); pos = revertPos; return; } @@ -350,8 +422,7 @@ else if (ch === 91/*[*/) { pos++; ch = commentWhitespace(); - if (ch === 39/*'*/) singleQuoteString(); - else if (ch === 34/*"*/) doubleQuoteString(); + if (ch === 39/*'*/ || ch === 34/*"*/) stringLiteral(ch); else break; pos++; ch = commentWhitespace(); @@ -366,17 +437,21 @@ if (ch !== 125/*}*/) break; pos++; ch = commentWhitespace(); + if (ch === 44/*,*/) { + pos++; + ch = commentWhitespace(); + } if (ch !== 125/*}*/) break; pos++; ch = commentWhitespace(); if (ch !== 41/*)*/) break; - addExport(expt); + _exports.add(decode(expt)); return; } break; } if (expt) { - unsafeGetters.add(expt); + unsafeGetters.add(decode(expt)); } } else if (keys && ch === 107/*k*/ && source.startsWith('eys', pos + 1)) { @@ -469,8 +544,94 @@ if (ch === 59/*;*/) pos++; ch = commentWhitespace(); + + // `if (` + if (ch === 105/*i*/ && source.charCodeAt(pos + 1) === 102/*f*/) { + let inIf = true; + pos += 2; + ch = commentWhitespace(); + if (ch !== 40/*(*/) break; + pos++; + const ifInnerPos = pos; + // `Object.prototype.hasOwnProperty.call(` IDENTIFIER `, ` IDENTIFIER$2 `)) return` `;`? + if (tryParseObjectHasOwnProperty(it_id)) { + ch = commentWhitespace(); + if (ch !== 41/*)*/) break; + pos++; + ch = commentWhitespace(); + if (ch !== 114/*r*/ || !source.startsWith('eturn', pos + 1)) break; + pos += 6; + ch = commentWhitespace(); + if (ch === 59/*;*/) + pos++; + ch = commentWhitespace(); + // match next if + if (ch === 105/*i*/ && source.charCodeAt(pos + 1) === 102/*f*/) { + pos += 2; + ch = commentWhitespace(); + if (ch !== 40/*(*/) break; + pos++; + } + else { + inIf = false; + } + } + else { + pos = ifInnerPos; + } + + // IDENTIFIER$2 `in` EXPORTS_IDENTIFIER `&&` EXPORTS_IDENTIFIER `[` IDENTIFIER$2 `] ===` IDENTIFIER$1 `[` IDENTIFIER$2 `]) return` `;`? + if (inIf) { + if (!source.startsWith(it_id, pos)) break; + pos += it_id.length; + ch = commentWhitespace(); + if (ch !== 105/*i*/ || !source.startsWith('n ', pos + 1)) break; + pos += 3; + ch = commentWhitespace(); + if (!readExportsOrModuleDotExports(ch)) break; + ch = commentWhitespace(); + if (ch !== 38/*&*/ || source.charCodeAt(pos + 1) !== 38/*&*/) break; + pos += 2; + ch = commentWhitespace(); + if (!readExportsOrModuleDotExports(ch)) break; + ch = commentWhitespace(); + if (ch !== 91/*[*/) break; + pos++; + ch = commentWhitespace(); + if (!source.startsWith(it_id, pos)) break; + pos += it_id.length; + ch = commentWhitespace(); + if (ch !== 93/*]*/) break; + pos++; + ch = commentWhitespace(); + if (ch !== 61/*=*/ || !source.startsWith('==', pos + 1)) break; + pos += 3; + ch = commentWhitespace(); + if (!source.startsWith(id, pos)) break; + pos += id.length; + ch = commentWhitespace(); + if (ch !== 91/*[*/) break; + pos++; + ch = commentWhitespace(); + if (!source.startsWith(it_id, pos)) break; + pos += it_id.length; + ch = commentWhitespace(); + if (ch !== 93/*]*/) break; + pos++; + ch = commentWhitespace(); + if (ch !== 41/*)*/) break; + pos++; + ch = commentWhitespace(); + if (ch !== 114/*r*/ || !source.startsWith('eturn', pos + 1)) break; + pos += 6; + ch = commentWhitespace(); + if (ch === 59/*;*/) + pos++; + ch = commentWhitespace(); + } + } } - // `if (` IDENTIFIER$2 `!==` ( `'default'` | `"default"` ) `)` + // `if (` IDENTIFIER$2 `!==` ( `'default'` | `"default"` ) (`&& !` IDENTIFIER `.hasOwnProperty(` IDENTIFIER$2 `)` )? `)` else if (ch === 33/*!*/) { if (!source.startsWith('==', pos + 1)) break; pos += 3; @@ -483,67 +644,40 @@ if (ch !== quot) break; pos += 1; ch = commentWhitespace(); + if (ch === 38/*&*/) { + if (source.charCodeAt(pos + 1) !== 38/*&*/) break; + pos += 2; + ch = commentWhitespace(); + if (ch !== 33/*!*/) break; + pos += 1; + ch = commentWhitespace(); + if (source.startsWith(id, pos)) { + pos += id.length; + ch = commentWhitespace(); + if (ch !== 46/*.*/) break; + pos++; + ch = commentWhitespace(); + if (ch !== 104/*h*/ || !source.startsWith('asOwnProperty', pos + 1)) break; + pos += 14; + ch = commentWhitespace(); + if (ch !== 40/*(*/) break; + pos += 1; + ch = commentWhitespace(); + if (!source.startsWith(it_id, pos)) break; + pos += it_id.length; + ch = commentWhitespace(); + if (ch !== 41/*)*/) break; + pos += 1; + } + else if (!tryParseObjectHasOwnProperty(it_id)) break; + ch = commentWhitespace(); + } if (ch !== 41/*)*/) break; pos += 1; ch = commentWhitespace(); } else break; - // `if (` IDENTIFIER$2 `in` EXPORTS_IDENTIFIER `&&` EXPORTS_IDENTIFIER `[` IDENTIFIER$2 `] ===` IDENTIFIER$1 `[` IDENTIFIER$2 `]) return` `;`? - if (ch === 105/*i*/ && source.charCodeAt(pos + 1) === 102/*f*/) { - pos += 2; - ch = commentWhitespace(); - if (ch !== 40/*(*/) break; - pos++; - ch = commentWhitespace(); - if (!source.startsWith(it_id, pos)) break; - pos += it_id.length; - ch = commentWhitespace(); - if (ch !== 105/*i*/ || !source.startsWith('n ', pos + 1)) break; - pos += 3; - ch = commentWhitespace(); - if (!readExportsOrModuleDotExports(ch)) break; - ch = commentWhitespace(); - if (ch !== 38/*&*/ || source.charCodeAt(pos + 1) !== 38/*&*/) break; - pos += 2; - ch = commentWhitespace(); - if (!readExportsOrModuleDotExports(ch)) break; - ch = commentWhitespace(); - if (ch !== 91/*[*/) break; - pos++; - ch = commentWhitespace(); - if (!source.startsWith(it_id, pos)) break; - pos += it_id.length; - ch = commentWhitespace(); - if (ch !== 93/*]*/) break; - pos++; - ch = commentWhitespace(); - if (ch !== 61/*=*/ || !source.startsWith('==', pos + 1)) break; - pos += 3; - ch = commentWhitespace(); - if (!source.startsWith(id, pos)) break; - pos += id.length; - ch = commentWhitespace(); - if (ch !== 91/*[*/) break; - pos++; - ch = commentWhitespace(); - if (!source.startsWith(it_id, pos)) break; - pos += it_id.length; - ch = commentWhitespace(); - if (ch !== 93/*]*/) break; - pos++; - ch = commentWhitespace(); - if (ch !== 41/*)*/) break; - pos++; - ch = commentWhitespace(); - if (ch !== 114/*r*/ || !source.startsWith('eturn', pos + 1)) break; - pos += 6; - ch = commentWhitespace(); - if (ch === 59/*;*/) - pos++; - ch = commentWhitespace(); - } - // EXPORTS_IDENTIFIER `[` IDENTIFIER$2 `] =` IDENTIFIER$1 `[` IDENTIFIER$2 `]` if (readExportsOrModuleDotExports(ch)) { ch = commentWhitespace(); @@ -619,12 +753,17 @@ if (ch !== 103/*g*/ || !source.startsWith('et', pos + 1)) break; pos += 3; ch = commentWhitespace(); - if (ch !== 58/*:*/) break; - pos++; - ch = commentWhitespace(); - if (ch !== 102/*f*/ || !source.startsWith('unction', pos + 1)) break; - pos += 8; - ch = commentWhitespace(); + if (ch === 58/*:*/) { + pos++; + ch = commentWhitespace(); + if (ch !== 102/*f*/) break; + if (!source.startsWith('unction', pos + 1)) break; + pos += 8; + let lastPos = pos; + ch = commentWhitespace(); + if (ch !== 40 && (lastPos === pos || !identifier())) break; + ch = commentWhitespace(); + } if (ch !== 40/*(*/) break; pos++; ch = commentWhitespace(); @@ -656,6 +795,10 @@ if (ch !== 125/*}*/) break; pos++; ch = commentWhitespace(); + if (ch === 44/*,*/) { + pos++; + ch = commentWhitespace(); + } if (ch !== 125/*}*/) break; pos++; ch = commentWhitespace(); @@ -676,7 +819,7 @@ const starExportSpecifier = starExportMap[id]; if (starExportSpecifier) { - reexports.add(starExportSpecifier); + reexports.add(decode(starExportSpecifier)); pos = revertPos; return; } @@ -738,7 +881,7 @@ const endPos = pos; ch = commentWhitespace(); if (ch === 61/*=*/) { - addExport(source.slice(startPos, endPos)); + _exports.add(decode(source.slice(startPos, endPos))); return; } } @@ -749,19 +892,15 @@ pos++; ch = commentWhitespace(); if (ch === 39/*'*/ || ch === 34/*"*/) { - pos++; const startPos = pos; - if (identifier() && source.charCodeAt(pos) === ch) { - const endPos = pos++; - ch = commentWhitespace(); - if (ch !== 93/*]*/) - break; - pos++; - ch = commentWhitespace(); - if (ch !== 61/*=*/) - break; - addExport(source.slice(startPos, endPos)); - } + stringLiteral(ch); + const endPos = ++pos; + ch = commentWhitespace(); + if (ch !== 93/*]*/) break; + pos++; + ch = commentWhitespace(); + if (ch !== 61/*=*/) break; + _exports.add(decode(source.slice(startPos, endPos))); } break; } @@ -796,39 +935,21 @@ if (ch === 40/*(*/) { pos++; ch = commentWhitespace(); - const reexportStart = pos + 1; - if (ch === 39/*'*/) { - singleQuoteString(); - const reexportEnd = pos++; - ch = commentWhitespace(); - if (ch === 41/*)*/) { - switch (requireType) { - case ExportAssign: - reexports.add(source.slice(reexportStart, reexportEnd)); - return true; - case ExportStar: - reexports.add(source.slice(reexportStart, reexportEnd)); - return true; - default: - lastStarExportSpecifier = source.slice(reexportStart, reexportEnd); - return true; - } - } - } - else if (ch === 34/*"*/) { - doubleQuoteString(); - const reexportEnd = pos++; + const reexportStart = pos; + if (ch === 39/*'*/ || ch === 34/*"*/) { + stringLiteral(ch); + const reexportEnd = ++pos; ch = commentWhitespace(); if (ch === 41/*)*/) { switch (requireType) { case ExportAssign: - reexports.add(source.slice(reexportStart, reexportEnd)); + reexports.add(decode(source.slice(reexportStart, reexportEnd))); return true; case ExportStar: - reexports.add(source.slice(reexportStart, reexportEnd)); + reexports.add(decode(source.slice(reexportStart, reexportEnd))); return true; default: - lastStarExportSpecifier = source.slice(reexportStart, reexportEnd); + lastStarExportSpecifier = decode(source.slice(reexportStart, reexportEnd)); return true; } } @@ -857,7 +978,7 @@ } ch = source.charCodeAt(pos); } - addExport(source.slice(startPos, endPos)); + _exports.add(decode(source.slice(startPos, endPos))); } else if (ch === 46/*.*/ && source.startsWith('..', pos + 1)) { pos += 3; @@ -871,21 +992,20 @@ ch = commentWhitespace(); } else if (ch === 39/*'*/ || ch === 34/*"*/) { - const startPos = ++pos; - if (identifier() && source.charCodeAt(pos) === ch) { - const endPos = pos++; + const startPos = pos; + stringLiteral(ch); + const endPos = ++pos; + ch = commentWhitespace(); + if (ch === 58/*:*/) { + pos++; ch = commentWhitespace(); - if (ch === 58/*:*/) { - pos++; - ch = commentWhitespace(); - // nothing more complex than identifier expressions for now - if (!identifier()) { - pos = revertPos; - return; - } - ch = source.charCodeAt(pos); - addExport(source.slice(startPos, endPos)); + // nothing more complex than identifier expressions for now + if (!identifier()) { + pos = revertPos; + return; } + ch = source.charCodeAt(pos); + _exports.add(decode(source.slice(startPos, endPos))); } } else { @@ -1039,7 +1159,6 @@ // import.meta case 46/*.*/: throw new Error('Unexpected import.meta in CJS module.'); - return; default: // no space after "import" -> not an import keyword @@ -1124,26 +1243,10 @@ } } -function singleQuoteString () { - while (pos++ < end) { - let ch = source.charCodeAt(pos); - if (ch === 39/*'*/) - return; - if (ch === 92/*\*/) { - ch = source.charCodeAt(++pos); - if (ch === 13/*\r*/ && source.charCodeAt(pos + 1) === 10/*\n*/) - pos++; - } - else if (isBr(ch)) - break; - } - throw new Error('Unterminated string.'); -} - -function doubleQuoteString () { +function stringLiteral (quote) { while (pos++ < end) { let ch = source.charCodeAt(pos); - if (ch === 34/*"*/) + if (ch === quote) return; if (ch === 92/*\*/) { ch = source.charCodeAt(++pos); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/BUILD.gn nodejs-12.22.4~dfsg/deps/v8/BUILD.gn --- nodejs-12.21.0~dfsg/deps/v8/BUILD.gn 2021-02-23 03:58:05.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/BUILD.gn 2021-07-29 12:35:23.000000000 +0200 @@ -6,7 +6,6 @@ import("//build/config/arm.gni") import("//build/config/dcheck_always_on.gni") import("//build/config/host_byteorder.gni") -import("//build/config/jumbo.gni") import("//build/config/mips.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build_overrides/build.gni") @@ -266,7 +265,8 @@ # config("internal_config_base") { - visibility = [ ":*" ] # Only targets in this file can depend on this. + # Only targets in this file and its subdirs can depend on this. + visibility = [ "./*" ] include_dirs = [ ".", @@ -276,7 +276,8 @@ config("internal_config") { defines = [] - visibility = [ ":*" ] # Only targets in this file can depend on this. + # Only targets in this file and its subdirs can depend on this. + visibility = [ "./*" ] configs = [ "//build/config/compiler:wexit_time_destructors", @@ -362,7 +363,8 @@ # Put defines here that are only used in our internal files and NEVER in # external headers that embedders (such as chromium and node) might include. config("features") { - visibility = [ ":*" ] # Only targets in this file can depend on this. + # Only targets in this file and its subdirs can depend on this. + visibility = [ "./*" ] defines = [] @@ -479,7 +481,8 @@ } config("toolchain") { - visibility = [ ":*" ] # Only targets in this file can depend on this. + # Only targets in this file and its subdirs can depend on this. + visibility = [ "./*" ] defines = [] cflags = [] @@ -1470,17 +1473,12 @@ if (v8_use_multi_snapshots) { deps += [ ":asm_to_inline_asm_trusted" ] sources += [ "$target_gen_dir/embedded_trusted.cc" ] - jumbo_excluded_sources = [ "$target_gen_dir/embedded_trusted.cc" ] } } else if (v8_enable_embedded_builtins) { sources += [ "$target_gen_dir/embedded.S" ] if (v8_use_multi_snapshots) { sources += [ "$target_gen_dir/embedded_trusted.S" ] - jumbo_excluded_sources = [ - # Duplicated symbols with embedded.S - "$target_gen_dir/embedded_trusted.S", - ] } } else { sources += [ "src/snapshot/embedded/embedded-empty.cc" ] @@ -1577,17 +1575,6 @@ "src/interpreter/interpreter-intrinsics-generator.h", ] - jumbo_excluded_sources = [ - # TODO(most...@vewd.com): don't exclude these http://crbug.com/752428 - "src/builtins/builtins-async-iterator-gen.cc", - "src/builtins/builtins-async-generator-gen.cc", - - # These source files take an unusually large amount of time to - # compile. Build them separately to avoid bottlenecks. - "src/builtins/builtins-regexp-gen.cc", - "src/codegen/code-stub-assembler.cc", - ] - if (v8_current_cpu == "x86") { sources += [ ### gcmole(arch:ia32) ### @@ -2996,19 +2983,6 @@ sources += check_header_includes_sources } - jumbo_excluded_sources = [ - # TODO(most...@vewd.com): don't exclude these http://crbug.com/752428 - "src/profiler/heap-snapshot-generator.cc", # Macro clash in mman-linux.h - - # These source files take an unusually large amount of time to - # compile. Build them separately to avoid bottlenecks. - "src/api/api.cc", - "src/heap/heap.cc", - "src/objects/elements.cc", - "src/objects/objects.cc", - "src/parsing/parser.cc", - ] - if (v8_current_cpu == "x86") { sources += [ ### gcmole(arch:ia32) ### "src/codegen/ia32/assembler-ia32-inl.h", @@ -3162,11 +3136,6 @@ "src/diagnostics/unwinding-info-win64.h", ] } - jumbo_excluded_sources += [ - # TODO(most...@vewd.com): fix this code so it doesn't need - # to be excluded, see the comments inside. - "src/codegen/arm64/instructions-arm64-constants.cc", - ] } else if (v8_current_cpu == "mips" || v8_current_cpu == "mipsel") { sources += [ ### gcmole(arch:mipsel) ### "src/codegen/mips/assembler-mips-inl.h", diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/DEPS nodejs-12.22.4~dfsg/deps/v8/DEPS --- nodejs-12.21.0~dfsg/deps/v8/DEPS 2021-02-23 03:58:05.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/DEPS 2021-07-29 12:35:23.000000000 +0200 @@ -2,7 +2,15 @@ # directory and assume that the root of the checkout is in ./v8/, so # all paths in here must match this assumption. +gclient_gn_args_file = 'v8/build/config/gclient_args.gni' +gclient_gn_args = [ + 'checkout_aemu' +] + vars = { + # By Default, do not checkout AEMU, as it is too big, as is done in Chromium. + 'checkout_aemu': False, + # Fetches only the SDK boot images which match at least one of the whitelist # entries in a comma-separated list. # @@ -72,15 +80,15 @@ deps = { 'v8/build': - Var('chromium_url') + '/chromium/src/build.git' + '@' + '693faeda4ee025796c7e473d953a5a7b6ad64c93', + Var('chromium_url') + '/chromium/src/build.git' + '@' + 'c854b8178a7e0a20b168ffded4f2d2cb1e136e42', 'v8/third_party/depot_tools': - Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + 'f38bc1796282c61087dcf15abc61b8fd18a68402', + Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + 'd4e6fb6573e0955110a2c69be29557f6626d9ae6', 'v8/third_party/icu': Var('chromium_url') + '/chromium/deps/icu.git' + '@' + '53f6b233a41ec982d8445996247093f7aaf41639', 'v8/third_party/instrumented_libraries': Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + 'b1c3ca20848c117eb935b02c25d441f03e6fbc5e', 'v8/buildtools': - Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '74cfb57006f83cfe050817526db359d5c8a11628', + Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '6302c1175607a436e18947a5abe9df2209e845fc', 'v8/buildtools/clang_format/script': Var('chromium_url') + '/chromium/llvm-project/cfe/tools/clang-format.git' + '@' + '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'v8/buildtools/linux64': { @@ -104,11 +112,11 @@ 'condition': 'host_os == "mac"', }, 'v8/buildtools/third_party/libc++/trunk': - Var('chromium_url') + '/chromium/llvm-project/libcxx.git' + '@' + '5938e0582bac570a41edb3d6a2217c299adc1bc6', + Var('chromium_url') + '/chromium/llvm-project/libcxx.git' + '@' + '78d6a7767ed57b50122a161b91f59f19c9bd0d19', 'v8/buildtools/third_party/libc++abi/trunk': - Var('chromium_url') + '/chromium/llvm-project/libcxxabi.git' + '@' + '0d529660e32d77d9111912d73f2c74fc5fa2a858', + Var('chromium_url') + '/chromium/llvm-project/libcxxabi.git' + '@' + 'ce3db128f9e4d6d19d1cdbe39bb45fcc64a5adb0', 'v8/buildtools/third_party/libunwind/trunk': - Var('chromium_url') + '/external/llvm.org/libunwind.git' + '@' + '69d9b84cca8354117b9fe9705a4430d789ee599b', + Var('chromium_url') + '/external/llvm.org/libunwind.git' + '@' + '3e6ec2ae9afaa3683269b690612f84d907943ea2', 'v8/buildtools/win': { 'packages': [ { @@ -168,7 +176,7 @@ 'dep_type': 'cipd', }, 'v8/third_party/catapult': { - 'url': Var('chromium_url') + '/catapult.git' + '@' + 'e7c719c3e85f76938bf4fef0ba37c27f89246f71', + 'url': Var('chromium_url') + '/catapult.git' + '@' + 'f92a7636da65f28dad15bc524e6b681d1c311de0', 'condition': 'checkout_android', }, 'v8/third_party/colorama/src': { @@ -216,7 +224,7 @@ 'dep_type': 'cipd', }, 'v8/tools/clang': - Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + '2fef805e5b05b26a8c87c47865590b5f43218611', + Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + 'c72342ce992ebd9cc02c0d65f0af5941d29eb217', 'v8/tools/luci-go': { 'packages': [ { @@ -246,7 +254,7 @@ 'dep_type': 'cipd', }, 'v8/third_party/perfetto': - Var('android_url') + '/platform/external/perfetto.git' + '@' + '01615892494a9a8dc84414962d0a817bf97de2c2', + Var('android_url') + '/platform/external/perfetto.git' + '@' + '7cdc44f903d3bcfd1d0f67188bfa797a24756868', 'v8/third_party/protobuf': Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + 'b68a347f56137b4b1a746e8c7438495a6ac1bd91', } diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/gni/proto_library.gni nodejs-12.22.4~dfsg/deps/v8/gni/proto_library.gni --- nodejs-12.21.0~dfsg/deps/v8/gni/proto_library.gni 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/gni/proto_library.gni 2021-07-29 12:35:23.000000000 +0200 @@ -11,8 +11,6 @@ assert(defined(invoker.sources)) proto_sources = invoker.sources - set_sources_assignment_filter([]) - if (host_os == "win") { host_executable_suffix = ".exe" } else { @@ -137,6 +135,12 @@ ] } + if (defined(invoker.import_dirs)) { + foreach(path, invoker.import_dirs) { + args += [ "--import-dir=" + rebase_path(path, root_build_dir) ] + } + } + if (generate_with_plugin) { plugin_path_rebased = rebase_path(plugin_path, root_build_dir) plugin_out_args = "" @@ -187,10 +191,7 @@ "visibility", ]) - # Exclude the config.descriptor file which is an output for some reason. - set_sources_assignment_filter([ "*.descriptor" ]) sources = get_target_outputs(":$action_name") - set_sources_assignment_filter(sources_assignment_filter) # configs -= [ "//gn/standalone:extra_warnings" ] if (defined(invoker.extra_configs)) { diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/gni/split_static_library.gni nodejs-12.22.4~dfsg/deps/v8/gni/split_static_library.gni --- nodejs-12.21.0~dfsg/deps/v8/gni/split_static_library.gni 1970-01-01 01:00:00.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/gni/split_static_library.gni 2021-07-29 12:35:23.000000000 +0200 @@ -0,0 +1,78 @@ +# Copyright 2019 the V8 project authors. All rights reserved. +# Copyright 2016 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. + +import("//build/config/compiler/compiler.gni") + +template("split_static_library") { + assert(defined(invoker.split_count), + "Must define split_count for split_static_library") + + # In many conditions the number of inputs will be 1 (because the + # count will be conditional on platform or configuration) and for + # some build configurations it's unnecessary to split libraries + # since the tooling will never create files of a problematic size. + if (invoker.split_count == 1 || use_lld) { + static_library(target_name) { + forward_variables_from(invoker, "*") + } + } else { + group_name = target_name + + generated_static_libraries = [] + current_library_index = 0 + foreach(current_sources, split_list(invoker.sources, invoker.split_count)) { + current_name = "${target_name}_$current_library_index" + assert( + current_sources != [], + "Your values for splitting a static library generate one that has no sources.") + generated_static_libraries += [ ":$current_name" ] + + static_library(current_name) { + # Generated static library shard gets everything but sources (which + # we're redefining) and visibility (which is set to be the group + # below). + forward_variables_from(invoker, + "*", + [ + "check_includes", + "sources", + "visibility", + ]) + sources = current_sources + visibility = [ ":$group_name" ] + + # When splitting a target's sources up into a series of static + # libraries, those targets will naturally include headers from each + # other arbitrarily. We could theoretically generate a web of + # dependencies and allow_circular_includes_from between all pairs of + # targets, but that's very cumbersome. Typical usage in Chrome is that + # only official Windows builds use split static libraries due to the + # Visual Studio size limits, and this means we'll still get header + # checking coverage for the other configurations. + check_includes = false + + # Uniquify the output name if one is specified. + if (defined(invoker.output_name)) { + output_name = "${invoker.output_name}_$current_library_index" + } + } + + current_library_index = current_library_index + 1 + } + + group(group_name) { + public_deps = generated_static_libraries + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + } + } +} + +set_defaults("split_static_library") { + configs = default_compiler_configs +} diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/gni/v8.gni nodejs-12.22.4~dfsg/deps/v8/gni/v8.gni --- nodejs-12.21.0~dfsg/deps/v8/gni/v8.gni 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/gni/v8.gni 2021-07-29 12:35:23.000000000 +0200 @@ -2,10 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/jumbo.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build/config/v8_target_cpu.gni") -import("//build/split_static_library.gni") +import("split_static_library.gni") declare_args() { # Set flags for tracking code coverage. Uses gcov with gcc and sanitizer @@ -80,7 +79,7 @@ # build configuration. This allows us to set v8_use_multi_snapshots=true on # all bots, and e.g. no-snapshot bots will automatically do the right thing. v8_use_multi_snapshots = - v8_use_external_startup_data && !build_with_chromium && !use_jumbo_build + v8_use_external_startup_data && !build_with_chromium } if (v8_enable_backtrace == "") { @@ -149,9 +148,9 @@ defined(v8_static_library) && v8_static_library && is_win) { link_target_type = "jumbo_split_static_library" } else if (defined(v8_static_library) && v8_static_library) { - link_target_type = "jumbo_static_library" + link_target_type = "static_library" } else { - link_target_type = "jumbo_source_set" + link_target_type = "source_set" } target(link_target_type, target_name) { forward_variables_from(invoker, @@ -170,7 +169,7 @@ } template("v8_header_set") { - jumbo_source_set(target_name) { + source_set(target_name) { forward_variables_from(invoker, "*", [ "configs" ]) configs -= v8_remove_configs configs += v8_add_configs diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/infra/mb/mb_config.pyl nodejs-12.22.4~dfsg/deps/v8/infra/mb/mb_config.pyl --- nodejs-12.21.0~dfsg/deps/v8/infra/mb/mb_config.pyl 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/infra/mb/mb_config.pyl 2021-07-29 12:35:23.000000000 +0200 @@ -64,11 +64,6 @@ 'V8 Linux64 - debug - header includes': 'debug_x64_header_includes', 'V8 Linux64 - shared': 'release_x64_shared_verify_heap', 'V8 Linux64 - verify csa': 'release_x64_verify_csa', - # Jumbo. - 'V8 Linux64 Jumbo': 'release_x64_jumbo', - 'V8 Linux64 Jumbo - debug': 'debug_x64_jumbo', - 'V8 Linux64 Jumbo - limited': 'release_x64_jumbo_limited', - 'V8 Linux64 Jumbo - limited - debug': 'debug_x64_jumbo_limited', # Windows. 'V8 Win32 - builder': 'release_x86_minimal_symbols', 'V8 Win32 - debug builder': 'debug_x86_minimal_symbols', @@ -230,8 +225,6 @@ 'v8_linux64_msan_rel': 'release_simulate_arm64_msan_minimal_symbols', 'v8_linux64_sanitizer_coverage_rel': 'release_x64_asan_minimal_symbols_coverage', - 'v8_linux64_jumbo_compile_rel': 'release_x64_jumbo_trybot', - 'v8_linux64_jumbo_limited_compile_rel': 'release_x64_jumbo_limited_trybot', 'v8_linux64_tsan_rel': 'release_x64_tsan_minimal_symbols', 'v8_linux64_tsan_isolates_rel_ng': 'release_x64_tsan_minimal_symbols', @@ -448,14 +441,6 @@ 'release_bot', 'x64', 'ios_simulator'], 'release_x64_internal': [ 'release_bot', 'x64', 'v8_snapshot_internal'], - 'release_x64_jumbo': [ - 'release_bot', 'x64', 'jumbo'], - 'release_x64_jumbo_trybot': [ - 'release_trybot', 'x64', 'jumbo'], - 'release_x64_jumbo_limited': [ - 'release_bot', 'x64', 'jumbo_limited'], - 'release_x64_jumbo_limited_trybot': [ - 'release_trybot', 'x64', 'jumbo_limited'], 'release_x64_minimal_symbols': [ 'release_bot', 'x64', 'minimal_symbols'], 'release_x64_pointer_compression': [ @@ -499,10 +484,6 @@ 'debug_bot', 'x64', 'gcc', 'v8_check_header_includes'], 'debug_x64_header_includes': [ 'debug_bot', 'x64', 'v8_check_header_includes'], - 'debug_x64_jumbo': [ - 'debug_bot', 'x64', 'jumbo'], - 'debug_x64_jumbo_limited': [ - 'debug_bot', 'x64', 'jumbo_limited'], 'debug_x64_minimal_symbols': [ 'debug_bot', 'x64', 'minimal_symbols'], 'debug_x64_perfetto': [ @@ -668,14 +649,6 @@ 'gn_args': 'target_cpu="x64" target_os="ios"', }, - 'jumbo': { - 'gn_args': 'use_jumbo_build=true', - }, - - 'jumbo_limited': { - 'gn_args': 'use_jumbo_build=true jumbo_file_merge_limit=50', - }, - 'lsan': { 'mixins': ['v8_enable_test_features'], 'gn_args': 'is_lsan=true', diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/src/base/cpu.cc nodejs-12.22.4~dfsg/deps/v8/src/base/cpu.cc --- nodejs-12.21.0~dfsg/deps/v8/src/base/cpu.cc 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/src/base/cpu.cc 2021-07-29 12:35:23.000000000 +0200 @@ -27,6 +27,9 @@ #ifndef POWER_9 #define POWER_9 0x20000 #endif +#ifndef POWER_10 +#define POWER_10 0x40000 +#endif #endif #if V8_OS_POSIX #include <unistd.h> // sysconf() @@ -639,7 +642,10 @@ part_ = -1; if (auxv_cpu_type) { - if (strcmp(auxv_cpu_type, "power9") == 0) { + if (strcmp(auxv_cpu_type, "power10") == 0) { + part_ = PPC_POWER10; + } + else if (strcmp(auxv_cpu_type, "power9") == 0) { part_ = PPC_POWER9; } else if (strcmp(auxv_cpu_type, "power8") == 0) { part_ = PPC_POWER8; @@ -660,6 +666,9 @@ #elif V8_OS_AIX switch (_system_configuration.implementation) { + case POWER_10: + part_ = PPC_POWER10; + break; case POWER_9: part_ = PPC_POWER9; break; diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/src/base/cpu.h nodejs-12.22.4~dfsg/deps/v8/src/base/cpu.h --- nodejs-12.21.0~dfsg/deps/v8/src/base/cpu.h 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/src/base/cpu.h 2021-07-29 12:35:23.000000000 +0200 @@ -70,6 +70,7 @@ PPC_POWER7, PPC_POWER8, PPC_POWER9, + PPC_POWER10, PPC_G4, PPC_G5, PPC_PA6T diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/src/base/macros.h nodejs-12.22.4~dfsg/deps/v8/src/base/macros.h --- nodejs-12.21.0~dfsg/deps/v8/src/base/macros.h 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/src/base/macros.h 2021-07-29 12:35:23.000000000 +0200 @@ -357,14 +357,14 @@ STATIC_ASSERT(std::is_integral<T>::value); // m must be a power of two. DCHECK(m != 0 && ((m & (m - 1)) == 0)); - return x & -m; + return x & static_cast<T>(-m); } template <intptr_t m, typename T> constexpr inline T RoundDown(T x) { STATIC_ASSERT(std::is_integral<T>::value); // m must be a power of two. STATIC_ASSERT(m != 0 && ((m & (m - 1)) == 0)); - return x & -m; + return x & static_cast<T>(-m); } // Return the smallest multiple of m which is >= x. diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/src/codegen/ppc/assembler-ppc.cc nodejs-12.22.4~dfsg/deps/v8/src/codegen/ppc/assembler-ppc.cc --- nodejs-12.21.0~dfsg/deps/v8/src/codegen/ppc/assembler-ppc.cc 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/src/codegen/ppc/assembler-ppc.cc 2021-07-29 12:35:23.000000000 +0200 @@ -67,21 +67,28 @@ #ifndef USE_SIMULATOR // Probe for additional features at runtime. base::CPU cpu; - if (cpu.part() == base::CPU::PPC_POWER9) { + if (cpu.part() == base::CPU::PPC_POWER9 || + cpu.part() == base::CPU::PPC_POWER10) { supported_ |= (1u << MODULO); } #if V8_TARGET_ARCH_PPC64 - if (cpu.part() == base::CPU::PPC_POWER8) { + if (cpu.part() == base::CPU::PPC_POWER8 || + cpu.part() == base::CPU::PPC_POWER9 || + cpu.part() == base::CPU::PPC_POWER10) { supported_ |= (1u << FPR_GPR_MOV); } #endif if (cpu.part() == base::CPU::PPC_POWER6 || cpu.part() == base::CPU::PPC_POWER7 || - cpu.part() == base::CPU::PPC_POWER8) { + cpu.part() == base::CPU::PPC_POWER8 || + cpu.part() == base::CPU::PPC_POWER9 || + cpu.part() == base::CPU::PPC_POWER10) { supported_ |= (1u << LWSYNC); } if (cpu.part() == base::CPU::PPC_POWER7 || - cpu.part() == base::CPU::PPC_POWER8) { + cpu.part() == base::CPU::PPC_POWER8 || + cpu.part() == base::CPU::PPC_POWER9 || + cpu.part() == base::CPU::PPC_POWER10) { supported_ |= (1u << ISELECT); supported_ |= (1u << VSX); } diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/src/objects/js-list-format.cc nodejs-12.22.4~dfsg/deps/v8/src/objects/js-list-format.cc --- nodejs-12.21.0~dfsg/deps/v8/src/objects/js-list-format.cc 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/src/objects/js-list-format.cc 2021-07-29 12:35:23.000000000 +0200 @@ -24,11 +24,14 @@ #include "unicode/fpositer.h" #include "unicode/listformatter.h" #include "unicode/ulistformatter.h" +#include "unicode/uvernum.h" namespace v8 { namespace internal { namespace { + +#if U_ICU_VERSION_MAJOR_NUM < 67 const char* kStandard = "standard"; const char* kOr = "or"; const char* kUnit = "unit"; @@ -72,6 +75,31 @@ } UNREACHABLE(); } +#else +UListFormatterWidth GetIcuWidth(JSListFormat::Style style) { + switch (style) { + case JSListFormat::Style::LONG: + return ULISTFMT_WIDTH_WIDE; + case JSListFormat::Style::SHORT: + return ULISTFMT_WIDTH_SHORT; + case JSListFormat::Style::NARROW: + return ULISTFMT_WIDTH_NARROW; + } + UNREACHABLE(); +} + +UListFormatterType GetIcuType(JSListFormat::Type type) { + switch (type) { + case JSListFormat::Type::CONJUNCTION: + return ULISTFMT_TYPE_AND; + case JSListFormat::Type::DISJUNCTION: + return ULISTFMT_TYPE_OR; + case JSListFormat::Type::UNIT: + return ULISTFMT_TYPE_UNITS; + } + UNREACHABLE(); +} +#endif } // namespace @@ -170,7 +198,11 @@ icu::Locale icu_locale = r.icu_locale; UErrorCode status = U_ZERO_ERROR; icu::ListFormatter* formatter = icu::ListFormatter::createInstance( +#if U_ICU_VERSION_MAJOR_NUM < 67 icu_locale, GetIcuStyleString(style_enum, type_enum), status); +#else + icu_locale, GetIcuType(type_enum), GetIcuWidth(style_enum), status); +#endif if (U_FAILURE(status)) { delete formatter; FATAL("Failed to create ICU list formatter, are ICU data files missing?"); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/src/profiler/profiler-listener.cc nodejs-12.22.4~dfsg/deps/v8/src/profiler/profiler-listener.cc --- nodejs-12.21.0~dfsg/deps/v8/src/profiler/profiler-listener.cc 2021-02-23 03:58:06.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/src/profiler/profiler-listener.cc 2021-07-29 12:35:23.000000000 +0200 @@ -120,7 +120,8 @@ // profiler as is stored on the code object, except that we transform source // positions to line numbers here, because we only care about attributing // ticks to a given line. - for (SourcePositionTableIterator it(abstract_code.source_position_table()); + for (SourcePositionTableIterator it( + handle(abstract_code.source_position_table(), isolate_)); !it.done(); it.Advance()) { int position = it.source_position().ScriptOffset(); int inlining_id = it.source_position().InliningId(); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/deps/v8/testing/gtest/BUILD.gn nodejs-12.22.4~dfsg/deps/v8/testing/gtest/BUILD.gn --- nodejs-12.21.0~dfsg/deps/v8/testing/gtest/BUILD.gn 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/deps/v8/testing/gtest/BUILD.gn 2021-07-29 12:35:25.000000000 +0200 @@ -4,9 +4,9 @@ import("//build_overrides/gtest.gni") if (is_ios) { + import("//build/buildflag_header.gni") import("//build/config/coverage/coverage.gni") import("//build/config/ios/ios_sdk.gni") - import("//build/buildflag_header.gni") } config("gtest_direct_config") { @@ -40,9 +40,7 @@ # Android. https://codereview.chromium.org/2852613002/#ps20001 "empty.cc", ] - public_deps = [ - "//third_party/googletest:gtest", - ] + public_deps = [ "//third_party/googletest:gtest" ] public_configs = [ ":gtest_direct_config" ] @@ -58,9 +56,6 @@ } if ((is_mac || is_ios) && gtest_include_objc_support) { - if (is_ios) { - set_sources_assignment_filter([]) - } sources += [ "../gtest_mac.h", "../gtest_mac.mm", @@ -68,7 +63,6 @@ if (gtest_include_platform_test) { sources += [ "../platform_test_mac.mm" ] } - set_sources_assignment_filter(sources_assignment_filter) } if (is_ios && gtest_include_ios_coverage) { @@ -76,9 +70,7 @@ "../coverage_util_ios.h", "../coverage_util_ios.mm", ] - deps = [ - ":ios_enable_coverage", - ] + deps = [ ":ios_enable_coverage" ] } } @@ -87,9 +79,7 @@ # into //third_party/googletest. source_set("gtest_main") { testonly = true - deps = [ - "//third_party/googletest:gtest_main", - ] + deps = [ "//third_party/googletest:gtest_main" ] } if (is_ios) { diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/lib/internal/modules/esm/get_source.js nodejs-12.22.4~dfsg/lib/internal/modules/esm/get_source.js --- nodejs-12.21.0~dfsg/lib/internal/modules/esm/get_source.js 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/lib/internal/modules/esm/get_source.js 2021-07-29 12:35:25.000000000 +0200 @@ -1,5 +1,8 @@ 'use strict'; +const { + decodeURIComponent, +} = primordials; const { getOptionValue } = require('internal/options'); const manifest = getOptionValue('--experimental-policy') ? require('internal/process/policy').manifest : @@ -28,8 +31,8 @@ if (!match) { throw new ERR_INVALID_URL(url); } - const [ , base64, body ] = match; - source = Buffer.from(body, base64 ? 'base64' : 'utf8'); + const { 1: base64, 2: body } = match; + source = Buffer.from(decodeURIComponent(body), base64 ? 'base64' : 'utf8'); } else { throw new ERR_INVALID_URL_SCHEME(['file', 'data']); } diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/lib/internal/modules/esm/resolve.js nodejs-12.22.4~dfsg/lib/internal/modules/esm/resolve.js --- nodejs-12.21.0~dfsg/lib/internal/modules/esm/resolve.js 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/lib/internal/modules/esm/resolve.js 2021-07-29 12:35:25.000000000 +0200 @@ -30,7 +30,7 @@ Stats, } = require('fs'); const { getOptionValue } = require('internal/options'); -const { sep, relative } = require('path'); +const { sep, relative, resolve } = require('path'); const preserveSymlinks = getOptionValue('--preserve-symlinks'); const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); const typeFlag = getOptionValue('--input-type'); @@ -160,16 +160,18 @@ return packageConfig; } -/* +/** * Legacy CommonJS main resolution: * 1. let M = pkg_url + (json main field) * 2. TRY(M, M.js, M.json, M.node) * 3. TRY(M/index.js, M/index.json, M/index.node) * 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node) * 5. NOT_FOUND + * @param {string | URL} url + * @returns {boolean} */ function fileExists(url) { - return tryStatSync(fileURLToPath(url)).isFile(); + return tryStatSync(url).isFile(); } function legacyMainResolve(packageJSONUrl, packageConfig, base) { @@ -236,7 +238,19 @@ return undefined; } -function resolveIndex(search) { +function resolveDirectoryEntry(search) { + const dirPath = fileURLToPath(search); + const pkgJsonPath = resolve(dirPath, 'package.json'); + if (fileExists(pkgJsonPath)) { + const pkgJson = packageJsonReader.read(pkgJsonPath); + if (pkgJson.containsKeys) { + const { main } = JSONParse(pkgJson.string); + if (main != null) { + const mainUrl = pathToFileURL(resolve(dirPath, main)); + return resolveExtensionsWithTryExactName(mainUrl); + } + } + } return resolveExtensions(new URL('index', search)); } @@ -252,10 +266,10 @@ let file = resolveExtensionsWithTryExactName(resolved); if (file !== undefined) return file; if (!StringPrototypeEndsWith(path, '/')) { - file = resolveIndex(new URL(`${resolved}/`)); + file = resolveDirectoryEntry(new URL(`${resolved}/`)); if (file !== undefined) return file; } else { - return resolveIndex(resolved) || resolved; + return resolveDirectoryEntry(resolved) || resolved; } throw new ERR_MODULE_NOT_FOUND( resolved.pathname, fileURLToPath(base), 'module'); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/lib/internal/per_context/primordials.js nodejs-12.22.4~dfsg/lib/internal/per_context/primordials.js --- nodejs-12.21.0~dfsg/lib/internal/per_context/primordials.js 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/lib/internal/per_context/primordials.js 2021-07-29 12:35:25.000000000 +0200 @@ -106,6 +106,16 @@ class SafePromise extends Promise {} ); +// Create copies of URI handling functions +[ + decodeURI, + decodeURIComponent, + encodeURI, + encodeURIComponent, +].forEach((fn) => { + primordials[fn.name] = fn; +}); + // Create copies of the namespace objects [ 'JSON', diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/lib/internal/url.js nodejs-12.22.4~dfsg/lib/internal/url.js --- nodejs-12.21.0~dfsg/lib/internal/url.js 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/lib/internal/url.js 2021-07-29 12:35:25.000000000 +0200 @@ -14,6 +14,7 @@ Symbol, SymbolIterator, SymbolToStringTag, + decodeURIComponent, } = primordials; const { inspect } = require('internal/util/inspect'); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/lib/internal/worker.js nodejs-12.22.4~dfsg/lib/internal/worker.js --- nodejs-12.21.0~dfsg/lib/internal/worker.js 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/lib/internal/worker.js 2021-07-29 12:35:25.000000000 +0200 @@ -17,6 +17,7 @@ const EventEmitter = require('events'); const assert = require('internal/assert'); const path = require('path'); +const { timeOrigin } = internalBinding('performance'); const errorCodes = require('internal/errors').codes; const { @@ -67,6 +68,8 @@ const kOnCouldNotSerializeErr = Symbol('kOnCouldNotSerializeErr'); const kOnErrorMessage = Symbol('kOnErrorMessage'); const kParentSideStdio = Symbol('kParentSideStdio'); +const kLoopStartTime = Symbol('kLoopStartTime'); +const kIsOnline = Symbol('kIsOnline'); const SHARE_ENV = SymbolFor('nodejs.worker_threads.SHARE_ENV'); let debug = require('internal/util/debuglog').debuglog('worker', (fn) => { @@ -214,6 +217,12 @@ null, hasStdin: !!options.stdin }, transferList); + // Use this to cache the Worker's loopStart value once available. + this[kLoopStartTime] = -1; + this[kIsOnline] = false; + this.performance = { + eventLoopUtilization: eventLoopUtilization.bind(this), + }; // Actually start the new thread now that everything is in place. this[kHandle].startThread(); } @@ -245,6 +254,7 @@ [kOnMessage](message) { switch (message.type) { case messageTypes.UP_AND_RUNNING: + this[kIsOnline] = true; return this.emit('online'); case messageTypes.COULD_NOT_SERIALIZE_ERROR: return this[kOnCouldNotSerializeErr](); @@ -406,6 +416,52 @@ }; } +function eventLoopUtilization(util1, util2) { + // TODO(trevnorris): Works to solve the thread-safe read/write issue of + // loopTime, but has the drawback that it can't be set until the event loop + // has had a chance to turn. So it will be impossible to read the ELU of + // a worker thread immediately after it's been created. + if (!this[kIsOnline] || !this[kHandle]) { + return { idle: 0, active: 0, utilization: 0 }; + } + + // Cache loopStart, since it's only written to once. + if (this[kLoopStartTime] === -1) { + this[kLoopStartTime] = this[kHandle].loopStartTime(); + if (this[kLoopStartTime] === -1) + return { idle: 0, active: 0, utilization: 0 }; + } + + if (util2) { + const idle = util1.idle - util2.idle; + const active = util1.active - util2.active; + return { idle, active, utilization: active / (idle + active) }; + } + + const idle = this[kHandle].loopIdleTime(); + + // Using performance.now() here is fine since it's always the time from + // the beginning of the process, and is why it needs to be offset by the + // loopStart time (which is also calculated from the beginning of the + // process). + const active = now() - this[kLoopStartTime] - idle; + + if (!util1) { + return { idle, active, utilization: active / (idle + active) }; + } + + const idle_delta = idle - util1.idle; + const active_delta = active - util1.active; + const utilization = active_delta / (idle_delta + active_delta); + return { idle: idle_delta, active: active_delta, utilization }; +} + +// Duplicate code from performance.now() so don't need to require perf_hooks. +function now() { + const hr = process.hrtime(); + return (hr[0] * 1000 + hr[1] / 1e6) - timeOrigin; +} + module.exports = { ownsProcessState, isMainThread, diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/lib/querystring.js nodejs-12.22.4~dfsg/lib/querystring.js --- nodejs-12.21.0~dfsg/lib/querystring.js 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/lib/querystring.js 2021-07-29 12:35:25.000000000 +0200 @@ -29,6 +29,7 @@ MathAbs, ObjectCreate, ObjectKeys, + decodeURIComponent, } = primordials; const { Buffer } = require('buffer'); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/lib/url.js nodejs-12.22.4~dfsg/lib/url.js --- nodejs-12.21.0~dfsg/lib/url.js 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/lib/url.js 2021-07-29 12:35:25.000000000 +0200 @@ -25,6 +25,7 @@ ObjectCreate, ObjectKeys, SafeSet, + decodeURIComponent, } = primordials; const { toASCII } = require('internal/idna'); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/lib/v8.js nodejs-12.22.4~dfsg/lib/v8.js --- nodejs-12.21.0~dfsg/lib/v8.js 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/lib/v8.js 2021-07-29 12:35:25.000000000 +0200 @@ -37,6 +37,12 @@ Serializer: _Serializer, Deserializer: _Deserializer } = internalBinding('serdes'); + +let profiler = {}; +if (internalBinding('config').hasInspector) { + profiler = internalBinding('profiler'); +} + const assert = require('internal/assert'); const { copy } = internalBinding('buffer'); const { inspect } = require('internal/util/inspect'); @@ -286,6 +292,8 @@ DefaultSerializer, DefaultDeserializer, deserialize, + takeCoverage: profiler.takeCoverage, + stopCoverage: profiler.stopCoverage, serialize, writeHeapSnapshot, }; diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/api/environment.cc nodejs-12.22.4~dfsg/src/api/environment.cc --- nodejs-12.21.0~dfsg/src/api/environment.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/api/environment.cc 2021-07-29 12:35:25.000000000 +0200 @@ -712,7 +712,8 @@ } void DefaultProcessExitHandler(Environment* env, int exit_code) { - Stop(env); + env->set_can_call_into_js(false); + env->stop_sub_worker_contexts(); DisposePlatform(); uv_library_shutdown(); exit(exit_code); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/cares_wrap.cc nodejs-12.22.4~dfsg/src/cares_wrap.cc --- nodejs-12.21.0~dfsg/src/cares_wrap.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/cares_wrap.cc 2021-07-29 12:35:25.000000000 +0200 @@ -49,7 +49,11 @@ # include <arpa/nameser.h> #endif -#if defined(__OpenBSD__) +// OpenBSD does not define these +#ifndef AI_ALL +# define AI_ALL 0 +#endif +#ifndef AI_V4MAPPED # define AI_V4MAPPED 0 #endif diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/env.cc nodejs-12.22.4~dfsg/src/env.cc --- nodejs-12.21.0~dfsg/src/env.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/env.cc 2021-07-29 12:35:25.000000000 +0200 @@ -550,10 +550,9 @@ } } -void Environment::Stop() { +void Environment::ExitEnv() { set_can_call_into_js(false); set_stopping(true); - stop_sub_worker_contexts(); isolate_->TerminateExecution(); SetImmediateThreadsafe([](Environment* env) { uv_stop(env->event_loop()); }); } @@ -1039,6 +1038,8 @@ } void Environment::stop_sub_worker_contexts() { + DCHECK_EQ(Isolate::GetCurrent(), isolate()); + while (!sub_worker_contexts_.empty()) { Worker* w = *sub_worker_contexts_.begin(); remove_sub_worker_context(w); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/env.h nodejs-12.22.4~dfsg/src/env.h --- nodejs-12.21.0~dfsg/src/env.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/env.h 2021-07-29 12:35:25.000000000 +0200 @@ -253,6 +253,7 @@ V(fd_string, "fd") \ V(fields_string, "fields") \ V(file_string, "file") \ + V(filename_string, "filename") \ V(fingerprint256_string, "fingerprint256") \ V(fingerprint_string, "fingerprint") \ V(flags_string, "flags") \ @@ -926,7 +927,7 @@ void RegisterHandleCleanups(); void CleanupHandles(); void Exit(int code); - void Stop(); + void ExitEnv(); // Register clean-up cb to be called on environment destruction. inline void RegisterHandleCleanup(uv_handle_t* handle, diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/inspector_profiler.cc nodejs-12.22.4~dfsg/src/inspector_profiler.cc --- nodejs-12.21.0~dfsg/src/inspector_profiler.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/inspector_profiler.cc 2021-07-29 12:35:25.000000000 +0200 @@ -9,6 +9,7 @@ #include "util-inl.h" #include "v8-inspector.h" +#include <cinttypes> #include <sstream> namespace node { @@ -36,10 +37,11 @@ false)), env_(env) {} -size_t V8ProfilerConnection::DispatchMessage(const char* method, - const char* params) { +uint32_t V8ProfilerConnection::DispatchMessage(const char* method, + const char* params, + bool is_profile_request) { std::stringstream ss; - size_t id = next_id(); + uint32_t id = next_id(); ss << R"({ "id": )" << id; DCHECK(method != nullptr); ss << R"(, "method": ")" << method << '"'; @@ -50,12 +52,15 @@ std::string message = ss.str(); const uint8_t* message_data = reinterpret_cast<const uint8_t*>(message.c_str()); + // Save the id of the profile request to identify its response. + if (is_profile_request) { + profile_ids_.insert(id); + } Debug(env(), DebugCategory::INSPECTOR_PROFILER, "Dispatching message %s\n", message.c_str()); session_->Dispatch(StringView(message_data, message.length())); - // TODO(joyeecheung): use this to identify the ending message. return id; } @@ -77,21 +82,10 @@ Environment* env = connection_->env(); Isolate* isolate = env->isolate(); HandleScope handle_scope(isolate); - Context::Scope context_scope(env->context()); + Local<Context> context = env->context(); + Context::Scope context_scope(context); - // TODO(joyeecheung): always parse the message so that we can use the id to - // identify ending messages as well as printing the message in the debug - // output when there is an error. const char* type = connection_->type(); - Debug(env, - DebugCategory::INSPECTOR_PROFILER, - "Receive %s profile message, ending = %s\n", - type, - connection_->ending() ? "true" : "false"); - if (!connection_->ending()) { - return; - } - // Convert StringView to a Local<String>. Local<String> message_str; if (!String::NewFromTwoByte(isolate, @@ -99,11 +93,62 @@ NewStringType::kNormal, message.length()) .ToLocal(&message_str)) { - fprintf(stderr, "Failed to convert %s profile message\n", type); + fprintf( + stderr, "Failed to convert %s profile message to V8 string\n", type); + return; + } + + Debug(env, + DebugCategory::INSPECTOR_PROFILER, + "Receive %s profile message\n", + type); + + Local<Value> parsed; + if (!v8::JSON::Parse(context, message_str).ToLocal(&parsed) || + !parsed->IsObject()) { + fprintf(stderr, "Failed to parse %s profile result as JSON object\n", type); + return; + } + + Local<Object> response = parsed.As<Object>(); + Local<Value> id_v; + if (!response->Get(context, FIXED_ONE_BYTE_STRING(isolate, "id")) + .ToLocal(&id_v) || + !id_v->IsUint32()) { + Utf8Value str(isolate, message_str); + fprintf( + stderr, "Cannot retrieve id from the response message:\n%s\n", *str); return; } + uint32_t id = id_v.As<v8::Uint32>()->Value(); - connection_->WriteProfile(message_str); + if (!connection_->HasProfileId(id)) { + Utf8Value str(isolate, message_str); + Debug(env, DebugCategory::INSPECTOR_PROFILER, "%s\n", *str); + return; + } else { + Debug(env, + DebugCategory::INSPECTOR_PROFILER, + "Writing profile response (id = %" PRIu64 ")\n", + static_cast<uint64_t>(id)); + } + + // Get message.result from the response. + Local<Value> result_v; + if (!response->Get(context, FIXED_ONE_BYTE_STRING(isolate, "result")) + .ToLocal(&result_v)) { + fprintf(stderr, "Failed to get 'result' from %s profile response\n", type); + return; + } + + if (!result_v->IsObject()) { + fprintf( + stderr, "'result' from %s profile response is not an object\n", type); + return; + } + + connection_->WriteProfile(result_v.As<Object>()); + connection_->RemoveProfileId(id); } static bool EnsureDirectory(const std::string& directory, const char* type) { @@ -138,45 +183,9 @@ return filename; } -static MaybeLocal<Object> ParseProfile(Environment* env, - Local<String> message, - const char* type) { - Local<Context> context = env->context(); - Isolate* isolate = env->isolate(); - - // Get message.result from the response - Local<Value> parsed; - if (!v8::JSON::Parse(context, message).ToLocal(&parsed) || - !parsed->IsObject()) { - fprintf(stderr, "Failed to parse %s profile result as JSON object\n", type); - return MaybeLocal<Object>(); - } - - Local<Value> result_v; - if (!parsed.As<Object>() - ->Get(context, FIXED_ONE_BYTE_STRING(isolate, "result")) - .ToLocal(&result_v)) { - fprintf(stderr, "Failed to get 'result' from %s profile message\n", type); - return MaybeLocal<Object>(); - } - - if (!result_v->IsObject()) { - fprintf( - stderr, "'result' from %s profile message is not an object\n", type); - return MaybeLocal<Object>(); - } - - return result_v.As<Object>(); -} - -void V8ProfilerConnection::WriteProfile(Local<String> message) { +void V8ProfilerConnection::WriteProfile(Local<Object> result) { Local<Context> context = env_->context(); - // Get message.result from the response. - Local<Object> result; - if (!ParseProfile(env_, message, type()).ToLocal(&result)) { - return; - } // Generate the profile output from the subclass. Local<Object> profile; if (!GetProfile(result).ToLocal(&profile)) { @@ -203,7 +212,7 @@ WriteResult(env_, path.c_str(), result_s); } -void V8CoverageConnection::WriteProfile(Local<String> message) { +void V8CoverageConnection::WriteProfile(Local<Object> result) { Isolate* isolate = env_->isolate(); Local<Context> context = env_->context(); HandleScope handle_scope(isolate); @@ -219,11 +228,6 @@ return; } - // Get message.result from the response. - Local<Object> result; - if (!ParseProfile(env_, message, type()).ToLocal(&result)) { - return; - } // Generate the profile output from the subclass. Local<Object> profile; if (!GetProfile(result).ToLocal(&profile)) { @@ -287,10 +291,23 @@ R"({ "callCount": true, "detailed": true })"); } +void V8CoverageConnection::TakeCoverage() { + DispatchMessage("Profiler.takePreciseCoverage", nullptr, true); +} + +void V8CoverageConnection::StopCoverage() { + DispatchMessage("Profiler.stopPreciseCoverage"); +} + void V8CoverageConnection::End() { - CHECK_EQ(ending_, false); + Debug(env_, + DebugCategory::INSPECTOR_PROFILER, + "V8CoverageConnection::End(), ending = %d\n", ending_); + if (ending_) { + return; + } ending_ = true; - DispatchMessage("Profiler.takePreciseCoverage"); + TakeCoverage(); } std::string V8CpuProfilerConnection::GetDirectory() const { @@ -327,9 +344,14 @@ } void V8CpuProfilerConnection::End() { - CHECK_EQ(ending_, false); + Debug(env_, + DebugCategory::INSPECTOR_PROFILER, + "V8CpuProfilerConnection::End(), ending = %d\n", ending_); + if (ending_) { + return; + } ending_ = true; - DispatchMessage("Profiler.stop"); + DispatchMessage("Profiler.stop", nullptr, true); } std::string V8HeapProfilerConnection::GetDirectory() const { @@ -365,31 +387,33 @@ } void V8HeapProfilerConnection::End() { - CHECK_EQ(ending_, false); + Debug(env_, + DebugCategory::INSPECTOR_PROFILER, + "V8HeapProfilerConnection::End(), ending = %d\n", ending_); + if (ending_) { + return; + } ending_ = true; - DispatchMessage("HeapProfiler.stopSampling"); + DispatchMessage("HeapProfiler.stopSampling", nullptr, true); } // For now, we only support coverage profiling, but we may add more // in the future. static void EndStartedProfilers(Environment* env) { + // TODO(joyeechueng): merge these connections and use one session per env. Debug(env, DebugCategory::INSPECTOR_PROFILER, "EndStartedProfilers\n"); V8ProfilerConnection* connection = env->cpu_profiler_connection(); - if (connection != nullptr && !connection->ending()) { - Debug(env, DebugCategory::INSPECTOR_PROFILER, "Ending cpu profiling\n"); + if (connection != nullptr) { connection->End(); } connection = env->heap_profiler_connection(); - if (connection != nullptr && !connection->ending()) { - Debug(env, DebugCategory::INSPECTOR_PROFILER, "Ending heap profiling\n"); + if (connection != nullptr) { connection->End(); } connection = env->coverage_connection(); - if (connection != nullptr && !connection->ending()) { - Debug( - env, DebugCategory::INSPECTOR_PROFILER, "Ending coverage collection\n"); + if (connection != nullptr) { connection->End(); } } @@ -469,6 +493,37 @@ env->set_source_map_cache_getter(args[0].As<Function>()); } +static void TakeCoverage(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + V8CoverageConnection* connection = env->coverage_connection(); + + Debug( + env, + DebugCategory::INSPECTOR_PROFILER, + "TakeCoverage, connection %s nullptr\n", + connection == nullptr ? "==" : "!="); + + if (connection != nullptr) { + Debug(env, DebugCategory::INSPECTOR_PROFILER, "taking coverage\n"); + connection->TakeCoverage(); + } +} + +static void StopCoverage(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + V8CoverageConnection* connection = env->coverage_connection(); + + Debug(env, + DebugCategory::INSPECTOR_PROFILER, + "StopCoverage, connection %s nullptr\n", + connection == nullptr ? "==" : "!="); + + if (connection != nullptr) { + Debug(env, DebugCategory::INSPECTOR_PROFILER, "Stopping coverage\n"); + connection->StopCoverage(); + } +} + static void Initialize(Local<Object> target, Local<Value> unused, Local<Context> context, @@ -476,6 +531,8 @@ Environment* env = Environment::GetCurrent(context); env->SetMethod(target, "setCoverageDirectory", SetCoverageDirectory); env->SetMethod(target, "setSourceMapCacheGetter", SetSourceMapCacheGetter); + env->SetMethod(target, "takeCoverage", TakeCoverage); + env->SetMethod(target, "stopCoverage", StopCoverage); } } // namespace profiler diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/inspector_profiler.h nodejs-12.22.4~dfsg/src/inspector_profiler.h --- nodejs-12.21.0~dfsg/src/inspector_profiler.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/inspector_profiler.h 2021-07-29 12:35:25.000000000 +0200 @@ -7,6 +7,7 @@ #error("This header can only be used when inspector is enabled") #endif +#include <unordered_set> #include "inspector_agent.h" namespace node { @@ -39,7 +40,9 @@ // The optional `params` should be formatted in JSON. // The strings should be in one byte characters - which is enough for // the commands we use here. - size_t DispatchMessage(const char* method, const char* params = nullptr); + uint32_t DispatchMessage(const char* method, + const char* params = nullptr, + bool is_profile_request = false); // Use DispatchMessage() to dispatch necessary inspector messages // to start and end the profiling. @@ -58,12 +61,19 @@ // which will be then written as a JSON. virtual v8::MaybeLocal<v8::Object> GetProfile( v8::Local<v8::Object> result) = 0; - virtual void WriteProfile(v8::Local<v8::String> message); + virtual void WriteProfile(v8::Local<v8::Object> result); + + bool HasProfileId(uint32_t id) const { + return profile_ids_.find(id) != profile_ids_.end(); + } + + void RemoveProfileId(uint32_t id) { profile_ids_.erase(id); } private: - size_t next_id() { return id_++; } + uint32_t next_id() { return id_++; } std::unique_ptr<inspector::InspectorSession> session_; - size_t id_ = 1; + uint32_t id_ = 1; + std::unordered_set<uint32_t> profile_ids_; protected: Environment* env_ = nullptr; @@ -82,8 +92,10 @@ std::string GetDirectory() const override; std::string GetFilename() const override; v8::MaybeLocal<v8::Object> GetProfile(v8::Local<v8::Object> result) override; - void WriteProfile(v8::Local<v8::String> message) override; + void WriteProfile(v8::Local<v8::Object> result) override; void WriteSourceMapCache(); + void TakeCoverage(); + void StopCoverage(); private: std::unique_ptr<inspector::InspectorSession> session_; diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/js_native_api.h nodejs-12.22.4~dfsg/src/js_native_api.h --- nodejs-12.21.0~dfsg/src/js_native_api.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/js_native_api.h 2021-07-29 12:35:25.000000000 +0200 @@ -17,7 +17,7 @@ // functions available in a new version of N-API that is not yet ported in all // LTS versions, they can set NAPI_VERSION knowing that they have specifically // depended on that version. -#define NAPI_VERSION 7 +#define NAPI_VERSION 8 #endif #endif @@ -539,7 +539,7 @@ bool* result); #endif // NAPI_VERSION >= 7 -#ifdef NAPI_EXPERIMENTAL +#if NAPI_VERSION >= 8 // Type tagging NAPI_EXTERN napi_status napi_type_tag_object(napi_env env, napi_value value, @@ -554,7 +554,7 @@ napi_value object); NAPI_EXTERN napi_status napi_object_seal(napi_env env, napi_value object); -#endif // NAPI_EXPERIMENTAL +#endif // NAPI_VERSION >= 8 EXTERN_C_END diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/js_native_api_types.h nodejs-12.22.4~dfsg/src/js_native_api_types.h --- nodejs-12.21.0~dfsg/src/js_native_api_types.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/js_native_api_types.h 2021-07-29 12:35:25.000000000 +0200 @@ -31,7 +31,7 @@ // from instance properties. Ignored by napi_define_properties. napi_static = 1 << 10, -#ifdef NAPI_EXPERIMENTAL +#if NAPI_VERSION >= 8 // Default for class methods. napi_default_method = napi_writable | napi_configurable, @@ -39,7 +39,7 @@ napi_default_jsproperty = napi_writable | napi_enumerable | napi_configurable, -#endif // NAPI_EXPERIMENTAL +#endif // NAPI_VERSION >= 8 } napi_property_attributes; typedef enum { @@ -146,11 +146,11 @@ } napi_key_conversion; #endif // NAPI_VERSION >= 6 -#ifdef NAPI_EXPERIMENTAL +#if NAPI_VERSION >= 8 typedef struct { uint64_t lower; uint64_t upper; } napi_type_tag; -#endif // NAPI_EXPERIMENTAL +#endif // NAPI_VERSION >= 8 #endif // SRC_JS_NATIVE_API_TYPES_H_ diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_api.cc nodejs-12.22.4~dfsg/src/node_api.cc --- nodejs-12.21.0~dfsg/src/node_api.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_api.cc 2021-07-29 12:35:25.000000000 +0200 @@ -12,8 +12,9 @@ #include <memory> struct node_napi_env__ : public napi_env__ { - explicit node_napi_env__(v8::Local<v8::Context> context): - napi_env__(context) { + explicit node_napi_env__(v8::Local<v8::Context> context, + const std::string& module_filename): + napi_env__(context), filename(module_filename) { CHECK_NOT_NULL(node_env()); } @@ -43,6 +44,10 @@ }); }); } + + const char* GetFilename() const { return filename.c_str(); } + + std::string filename; }; typedef node_napi_env__* node_napi_env; @@ -84,10 +89,11 @@ }; }; -static inline napi_env NewEnv(v8::Local<v8::Context> context) { +static inline napi_env +NewEnv(v8::Local<v8::Context> context, const std::string& module_filename) { node_napi_env result; - result = new node_napi_env__(context); + result = new node_napi_env__(context, module_filename); // TODO(addaleax): There was previously code that tried to delete the // napi_env when its v8::Context was garbage collected; // However, as long as N-API addons using this napi_env are in place, @@ -454,16 +460,35 @@ v8::Local<v8::Value> module, v8::Local<v8::Context> context, napi_addon_register_func init) { + node::Environment* node_env = node::Environment::GetCurrent(context); + std::string module_filename = ""; if (init == nullptr) { - node::Environment* node_env = node::Environment::GetCurrent(context); CHECK_NOT_NULL(node_env); node_env->ThrowError( "Module has no declared entry point."); return; } + // We set `env->filename` from `module.filename` here, but we could just as + // easily add a private property to `exports` in `process.dlopen`, which + // receives the file name from JS, and retrieve *that* here. Thus, we are not + // endorsing commonjs here by making use of `module.filename`. + v8::Local<v8::Value> filename_js; + v8::Local<v8::Object> modobj; + if (module->ToObject(context).ToLocal(&modobj) && + modobj->Get(context, node_env->filename_string()).ToLocal(&filename_js) && + filename_js->IsString()) { + node::Utf8Value filename(node_env->isolate(), filename_js); // Cast + + // Turn the absolute path into a URL. Currently the absolute path is always + // a file system path. + // TODO(gabrielschulhof): Pass the `filename` through unchanged if/when we + // receive it as a URL already. + module_filename = std::string("file://") + (*filename); + } + // Create a new napi_env for this specific module. - napi_env env = v8impl::NewEnv(context); + napi_env env = v8impl::NewEnv(context, module_filename); napi_value _exports; env->CallIntoModule([&](napi_env env) { @@ -1154,3 +1179,11 @@ CHECK_NOT_NULL(func); return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Ref(); } + +napi_status node_api_get_module_file_name(napi_env env, const char** result) { + CHECK_ENV(env); + CHECK_ARG(env, result); + + *result = static_cast<node_napi_env>(env)->GetFilename(); + return napi_clear_last_error(env); +} diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_api.h nodejs-12.22.4~dfsg/src/node_api.h --- nodejs-12.21.0~dfsg/src/node_api.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_api.h 2021-07-29 12:35:25.000000000 +0200 @@ -250,7 +250,7 @@ #endif // NAPI_VERSION >= 4 -#ifdef NAPI_EXPERIMENTAL +#if NAPI_VERSION >= 8 NAPI_EXTERN napi_status napi_add_async_cleanup_hook( napi_env env, @@ -261,6 +261,13 @@ NAPI_EXTERN napi_status napi_remove_async_cleanup_hook( napi_async_cleanup_hook_handle remove_handle); +#endif // NAPI_VERSION >= 8 + +#ifdef NAPI_EXPERIMENTAL + +NAPI_EXTERN napi_status +node_api_get_module_file_name(napi_env env, const char** result); + #endif // NAPI_EXPERIMENTAL EXTERN_C_END diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_api_types.h nodejs-12.22.4~dfsg/src/node_api_types.h --- nodejs-12.21.0~dfsg/src/node_api_types.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_api_types.h 2021-07-29 12:35:25.000000000 +0200 @@ -41,10 +41,10 @@ const char* release; } napi_node_version; -#ifdef NAPI_EXPERIMENTAL +#if NAPI_VERSION >= 8 typedef struct napi_async_cleanup_hook_handle__* napi_async_cleanup_hook_handle; typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle, void* data); -#endif // NAPI_EXPERIMENTAL +#endif // NAPI_VERSION >= 8 #endif // SRC_NODE_API_TYPES_H_ diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node.cc nodejs-12.22.4~dfsg/src/node.cc --- nodejs-12.21.0~dfsg/src/node.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node.cc 2021-07-29 12:35:25.000000000 +0200 @@ -1035,7 +1035,7 @@ } int Stop(Environment* env) { - env->Stop(); + env->ExitEnv(); return 0; } diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node.h nodejs-12.22.4~dfsg/src/node.h --- nodejs-12.21.0~dfsg/src/node.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node.h 2021-07-29 12:35:25.000000000 +0200 @@ -218,8 +218,7 @@ NODE_EXTERN int Start(int argc, char* argv[]); // Tear down Node.js while it is running (there are active handles -// in the loop and / or actively executing JavaScript code). This also stops -// all Workers that may have been started earlier. +// in the loop and / or actively executing JavaScript code). NODE_EXTERN int Stop(Environment* env); // TODO(addaleax): Officially deprecate this and replace it with something @@ -469,8 +468,8 @@ // It receives the Environment* instance and the exit code as arguments. // This could e.g. call Stop(env); in order to terminate execution and stop // the event loop. -// The default handler calls Stop(), disposes of the global V8 platform -// instance, if one is being used, and calls exit(). +// The default handler disposes of the global V8 platform instance, if one is +// being used, and calls exit(). NODE_EXTERN void SetProcessExitHandler( Environment* env, std::function<void(Environment*, int)>&& handler); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_http2.cc nodejs-12.22.4~dfsg/src/node_http2.cc --- nodejs-12.21.0~dfsg/src/node_http2.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_http2.cc 2021-07-29 12:35:25.000000000 +0200 @@ -2150,6 +2150,23 @@ void Http2Stream::SubmitRstStream(const uint32_t code) { CHECK(!this->IsDestroyed()); code_ = code; + + // If RST_STREAM frame is received and stream is not writable + // because it is busy reading data, don't try force purging it. + // Instead add the stream to pending stream list and process + // the pending data when it is safe to do so. This is to avoid + // double free error due to unwanted behavior of nghttp2. + // Ref:https://github.com/nodejs/node/issues/38964 + + // Add stream to the pending list if it is received with scope + // below in the stack. The pending list may not get processed + // if RST_STREAM received is not in scope and added to the list + // causing endpoint to hang. + if (session_->is_in_scope() && IsReading()) { + session_->AddPendingRstStream(id_); + return; + } + // If possible, force a purge of any currently pending data here to make sure // it is sent before closing the stream. If it returns non-zero then we need // to wait until the current write finishes and try again to avoid nghttp2 diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_http2.h nodejs-12.22.4~dfsg/src/node_http2.h --- nodejs-12.21.0~dfsg/src/node_http2.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_http2.h 2021-07-29 12:35:25.000000000 +0200 @@ -764,6 +764,22 @@ return (flags_ & SESSION_STATE_CLOSED) || session_ == nullptr; } + + // The changes are backported and exposes APIs to check the + // status flag of `Http2Session` +#define IS_FLAG(name, flag) \ + bool is_##name() const { return flags_ & flag; } + + IS_FLAG(in_scope, SESSION_STATE_HAS_SCOPE) + IS_FLAG(write_scheduled, SESSION_STATE_WRITE_SCHEDULED) + IS_FLAG(closing, SESSION_STATE_CLOSING) + IS_FLAG(sending, SESSION_STATE_SENDING) + IS_FLAG(write_in_progress, SESSION_STATE_WRITE_IN_PROGRESS) + IS_FLAG(reading_stopped, SESSION_STATE_READING_STOPPED) + IS_FLAG(receive_paused, SESSION_STATE_NGHTTP2_RECV_PAUSED) + +#undef IS_FLAG + // Schedule a write if nghttp2 indicates it wants to write to the socket. void MaybeScheduleWrite(); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_http_parser_impl.h nodejs-12.22.4~dfsg/src/node_http_parser_impl.h --- nodejs-12.21.0~dfsg/src/node_http_parser_impl.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_http_parser_impl.h 2021-07-29 12:35:25.000000000 +0200 @@ -26,6 +26,9 @@ #include "node.h" #include "node_buffer.h" +#ifndef NODE_EXPERIMENTAL_HTTP +#include "node_process.h" +#endif /* NODE_EXPERIMENTAL_HTTP */ #include "util.h" #include "async_wrap-inl.h" @@ -1021,6 +1024,10 @@ #ifndef NODE_EXPERIMENTAL_HTTP static uv_once_t init_once = UV_ONCE_INIT; uv_once(&init_once, InitMaxHttpHeaderSizeOnce); + ProcessEmitDeprecationWarning( + env, + "The legacy HTTP parser is deprecated.", + "DEP0131").IsNothing(); #endif /* NODE_EXPERIMENTAL_HTTP */ } diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_platform.cc nodejs-12.22.4~dfsg/src/node_platform.cc --- nodejs-12.21.0~dfsg/src/node_platform.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_platform.cc 2021-07-29 12:35:25.000000000 +0200 @@ -359,10 +359,10 @@ Mutex::ScopedLock lock(per_isolate_mutex_); auto it = per_isolate_.find(isolate); if (it == per_isolate_.end()) { - CHECK(it->second); cb(data); return; } + CHECK(it->second); it->second->AddShutdownCallback(cb, data); } diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_version.h nodejs-12.22.4~dfsg/src/node_version.h --- nodejs-12.21.0~dfsg/src/node_version.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_version.h 2021-07-29 12:35:25.000000000 +0200 @@ -23,8 +23,8 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 12 -#define NODE_MINOR_VERSION 21 -#define NODE_PATCH_VERSION 0 +#define NODE_MINOR_VERSION 22 +#define NODE_PATCH_VERSION 4 #define NODE_VERSION_IS_LTS 1 #define NODE_VERSION_LTS_CODENAME "Erbium" @@ -93,6 +93,6 @@ // The NAPI_VERSION provided by this version of the runtime. This is the version // which the Node binary being built supports. -#define NAPI_VERSION 7 +#define NAPI_VERSION 8 #endif // SRC_NODE_VERSION_H_ diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_worker.cc nodejs-12.22.4~dfsg/src/node_worker.cc --- nodejs-12.21.0~dfsg/src/node_worker.cc 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_worker.cc 2021-07-29 12:35:25.000000000 +0200 @@ -765,6 +765,39 @@ args.GetReturnValue().Set(scheduled ? taker->object() : Local<Object>()); } +void Worker::LoopIdleTime(const FunctionCallbackInfo<Value>& args) { + Worker* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.This()); + + Mutex::ScopedLock lock(w->mutex_); + // Using w->is_stopped() here leads to a deadlock, and checking is_stopped() + // before locking the mutex is a race condition. So manually do the same + // check. + if (w->stopped_ || w->env_ == nullptr) + return args.GetReturnValue().Set(-1); + + uint64_t idle_time = uv_metrics_idle_time(w->env_->event_loop()); + args.GetReturnValue().Set(1.0 * idle_time / 1e6); +} + +void Worker::LoopStartTime(const FunctionCallbackInfo<Value>& args) { + Worker* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.This()); + + Mutex::ScopedLock lock(w->mutex_); + // Using w->is_stopped() here leads to a deadlock, and checking is_stopped() + // before locking the mutex is a race condition. So manually do the same + // check. + if (w->stopped_ || w->env_ == nullptr) + return args.GetReturnValue().Set(-1); + + double loop_start_time = w->env_->performance_state()->milestones[ + node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START]; + CHECK_GE(loop_start_time, 0); + args.GetReturnValue().Set( + (loop_start_time - node::performance::timeOrigin) / 1e6); +} + namespace { // Return the MessagePort that is global for this Environment and communicates @@ -798,6 +831,8 @@ env->SetProtoMethod(w, "unref", Worker::Unref); env->SetProtoMethod(w, "getResourceLimits", Worker::GetResourceLimits); env->SetProtoMethod(w, "takeHeapSnapshot", Worker::TakeHeapSnapshot); + env->SetProtoMethod(w, "loopIdleTime", Worker::LoopIdleTime); + env->SetProtoMethod(w, "loopStartTime", Worker::LoopStartTime); Local<String> workerString = FIXED_ONE_BYTE_STRING(env->isolate(), "Worker"); diff -Nru --exclude '*.md' --exclude '*.html' --exclude '*.json' --exclude '*.ts' nodejs-12.21.0~dfsg/src/node_worker.h nodejs-12.22.4~dfsg/src/node_worker.h --- nodejs-12.21.0~dfsg/src/node_worker.h 2021-02-23 03:58:07.000000000 +0100 +++ nodejs-12.22.4~dfsg/src/node_worker.h 2021-07-29 12:35:25.000000000 +0200 @@ -66,6 +66,8 @@ const v8::FunctionCallbackInfo<v8::Value>& args); v8::Local<v8::Float64Array> GetResourceLimits(v8::Isolate* isolate) const; static void TakeHeapSnapshot(const v8::FunctionCallbackInfo<v8::Value>& args); + static void LoopIdleTime(const v8::FunctionCallbackInfo<v8::Value>& args); + static void LoopStartTime(const v8::FunctionCallbackInfo<v8::Value>& args); private: void CreateEnvMessagePort(Environment* env);