From 05948d8e4e3fefb757ea8b8aa5160cacd07e0cf4 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 24 Nov 2017 00:13:44 +0100 Subject: [PATCH 1/2] lib: remove use of Debug.MakeMirror() This paves the way for removing `vm.runInDebugContext()`. Inspection of Map and Set iterators is now done through V8 instrinsics. Fixes: https://github.com/nodejs/node/issues/11875 PR-URL: https://github.com/nodejs/node/pull/13295 Reviewed-By: Anna Henningsen Reviewed-By: Franziska Hinkelmann Reviewed-By: James M Snell Reviewed-By: Robert Jefe Lindstaedt Reviewed-By: Ruben Bridgewater Reviewed-By: Timothy Gu --- .eslintignore | 1 + lib/internal/bootstrap_node.js | 15 +++++++++++++ lib/internal/v8.js | 21 ++++++++++++++++++ lib/util.js | 39 +++++++++++++++++----------------- node.gyp | 1 + src/node.cc | 6 ++++++ 6 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 lib/internal/v8.js diff --git a/.eslintignore b/.eslintignore index 4b6e6b5e0fa94a..9b1d8b3f35da9a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ +lib/internal/v8.js lib/internal/v8_prof_polyfill.js lib/punycode.js test/addons/??_* diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index fb8bc762286467..a565916193000f 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -27,6 +27,7 @@ // do this good and early, since it handles errors. setupProcessFatal(); + setupV8(); setupProcessICUVersions(); setupGlobalVariables(); @@ -414,6 +415,20 @@ }; } + function setupV8() { + // Warm up the map and set iterator preview functions. V8 compiles + // functions lazily (unless --nolazy is set) so we need to do this + // before we turn off --allow_natives_syntax again. + const v8 = NativeModule.require('internal/v8'); + v8.previewMapIterator(new Map().entries(), 1); + v8.previewSetIterator(new Set().entries(), 1); + // Disable --allow_natives_syntax again unless it was explicitly + // specified on the command line. + const re = /^--allow[-_]natives[-_]syntax$/; + if (!process.execArgv.some((s) => re.test(s))) + process.binding('v8').setFlagsFromString('--noallow_natives_syntax'); + } + function setupProcessICUVersions() { const icu = process.binding('config').hasIntl ? process.binding('icu') : undefined; diff --git a/lib/internal/v8.js b/lib/internal/v8.js new file mode 100644 index 00000000000000..b80e3de33d6155 --- /dev/null +++ b/lib/internal/v8.js @@ -0,0 +1,21 @@ +'use strict'; + +function take(it, n) { + const result = []; + for (const e of it) { + if (--n < 0) + break; + result.push(e); + } + return result; +} + +function previewMapIterator(it, n) { + return take(%MapIteratorClone(it), n); +} + +function previewSetIterator(it, n) { + return take(%SetIteratorClone(it), n); +} + +module.exports = { previewMapIterator, previewSetIterator }; diff --git a/lib/util.js b/lib/util.js index 3ea3fa0dc8d2a0..058b5ed6bde145 100644 --- a/lib/util.js +++ b/lib/util.js @@ -26,6 +26,7 @@ const { TextDecoder, TextEncoder } = require('internal/encoding'); const { isBuffer } = require('buffer').Buffer; const { errname } = process.binding('uv'); +const { previewMapIterator, previewSetIterator } = require('internal/v8'); const { getPromiseDetails, @@ -77,7 +78,6 @@ const dateToISOString = Date.prototype.toISOString; const errorToString = Error.prototype.toString; var CIRCULAR_ERROR_MESSAGE; -var Debug; /* eslint-disable */ const strEscapeSequencesRegExp = /[\x00-\x1f\x27\x5c]/; @@ -356,17 +356,6 @@ function stylizeNoColor(str, styleType) { return str; } -function ensureDebugIsInitialized() { - if (Debug === undefined) { - const runInDebugContext = require('vm').runInDebugContext; - // a workaround till this entire method is removed - const originalValue = process.noDeprecation; - process.noDeprecation = true; - Debug = runInDebugContext('Debug'); - process.noDeprecation = originalValue; - } -} - function formatValue(ctx, value, recurseTimes, ln) { // Primitive types cannot have properties if (typeof value !== 'object' && typeof value !== 'function') { @@ -474,10 +463,10 @@ function formatValue(ctx, value, recurseTimes, ln) { formatter = formatTypedArray; } else if (isMapIterator(value)) { braces = ['MapIterator {', '}']; - formatter = formatCollectionIterator; + formatter = formatMapIterator; } else if (isSetIterator(value)) { braces = ['SetIterator {', '}']; - formatter = formatCollectionIterator; + formatter = formatSetIterator; } else { // Check for boxed strings with valueOf() // The .valueOf() call can fail for a multitude of reasons @@ -782,17 +771,27 @@ function formatMap(ctx, value, recurseTimes, keys) { return output; } -function formatCollectionIterator(ctx, value, recurseTimes, keys) { - ensureDebugIsInitialized(); - const mirror = Debug.MakeMirror(value, true); - const vals = mirror.preview(); - const output = []; +function formatCollectionIterator(preview, ctx, value, recurseTimes, + visibleKeys, keys) { + var nextRecurseTimes = recurseTimes === null ? null : recurseTimes - 1; + var vals = preview(value, 100); + var output = []; for (const o of vals) { - output.push(formatValue(ctx, o, recurseTimes)); + output.push(formatValue(ctx, o, nextRecurseTimes)); } return output; } +function formatMapIterator(ctx, value, recurseTimes, visibleKeys, keys) { + return formatCollectionIterator(previewMapIterator, ctx, value, recurseTimes, + visibleKeys, keys); +} + +function formatSetIterator(ctx, value, recurseTimes, visibleKeys, keys) { + return formatCollectionIterator(previewSetIterator, ctx, value, recurseTimes, + visibleKeys, keys); +} + function formatPromise(ctx, value, recurseTimes, keys) { var output; const [state, result] = getPromiseDetails(value); diff --git a/node.gyp b/node.gyp index c32adc37206526..ed28b4a6ce198a 100644 --- a/node.gyp +++ b/node.gyp @@ -132,6 +132,7 @@ 'lib/internal/http2/core.js', 'lib/internal/http2/compat.js', 'lib/internal/http2/util.js', + 'lib/internal/v8.js', 'lib/internal/v8_prof_polyfill.js', 'lib/internal/v8_prof_processor.js', 'lib/internal/streams/lazy_transform.js', diff --git a/src/node.cc b/src/node.cc index 111f3b80f2d4f1..57c1a4cc8a7f1e 100644 --- a/src/node.cc +++ b/src/node.cc @@ -4288,6 +4288,12 @@ void Init(int* argc, const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0"; V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1); + // Needed for access to V8 intrinsics. Disabled again during bootstrapping, + // see lib/internal/bootstrap_node.js. + const char allow_natives_syntax[] = "--allow_natives_syntax"; + V8::SetFlagsFromString(allow_natives_syntax, + sizeof(allow_natives_syntax) - 1); + // We should set node_is_initialized here instead of in node::Start, // otherwise embedders using node::Init to initialize everything will not be // able to set it and native modules will not load for them. From 6f724e1563159fb332ed43068649958e99e7be28 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 24 Nov 2017 00:13:44 +0100 Subject: [PATCH 2/2] lib,src: remove vm.runInDebugContext() The V8 API it is based on is deprecated and scheduled for removal later this year. Remove it. PR-URL: https://github.com/nodejs/node/pull/13295 Reviewed-By: Anna Henningsen Reviewed-By: Franziska Hinkelmann Reviewed-By: James M Snell Reviewed-By: Robert Jefe Lindstaedt Reviewed-By: Ruben Bridgewater Reviewed-By: Timothy Gu --- doc/api/deprecations.md | 5 +- doc/api/vm.md | 31 ----- lib/module.js | 4 - lib/vm.js | 15 --- src/node_contextify.cc | 33 ----- test/fixtures/vm-run-in-debug-context.js | 4 - test/parallel/test-util-inspect.js | 6 +- test/parallel/test-vm-debug-context.js | 123 ------------------ .../test-tick-processor-cpp-core.js | 4 +- .../test-tick-processor-preprocess-flag.js | 2 +- 10 files changed, 8 insertions(+), 219 deletions(-) delete mode 100644 test/fixtures/vm-run-in-debug-context.js delete mode 100644 test/parallel/test-vm-debug-context.js diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 93baba97991c29..1353272439366d 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -600,10 +600,9 @@ a V8-inspector based CLI debugger available through `node inspect`. ### DEP0069: vm.runInDebugContext(string) -Type: Runtime +Type: End-of-Life -The DebugContext will be removed in V8 soon and will not be available in Node -10+. +DebugContext has been removed in V8 and is not available in Node 10+. *Note*: DebugContext was an experimental API. diff --git a/doc/api/vm.md b/doc/api/vm.md index 209302b450bc09..001e7b0a2387ff 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -334,36 +334,6 @@ console.log(util.inspect(sandbox)); // { globalVar: 1024 } ``` -## vm.runInDebugContext(code) - - -> Stability: 0 - Deprecated. An alternative is in development. - -* `code` {string} The JavaScript code to compile and run. - -The `vm.runInDebugContext()` method compiles and executes `code` inside the V8 -debug context. The primary use case is to gain access to the V8 `Debug` object: - -```js -const vm = require('vm'); -const Debug = vm.runInDebugContext('Debug'); -console.log(Debug.findScript(process.emit).name); // 'events.js' -console.log(Debug.findScript(process.exit).name); // 'internal/process.js' -``` - -*Note*: The debug context and object are intrinsically tied to V8's debugger -implementation and may change (or even be removed) without prior warning. - -The `Debug` object can also be made available using the V8-specific -`--expose_debug_as=` [command line option][]. - ## vm.runInNewContext(code[, sandbox][, options])