summaryrefslogtreecommitdiff
path: root/deps/node/deps/node-inspect/lib/internal/inspect_repl.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/node/deps/node-inspect/lib/internal/inspect_repl.js')
-rw-r--r--deps/node/deps/node-inspect/lib/internal/inspect_repl.js1089
1 files changed, 0 insertions, 1089 deletions
diff --git a/deps/node/deps/node-inspect/lib/internal/inspect_repl.js b/deps/node/deps/node-inspect/lib/internal/inspect_repl.js
deleted file mode 100644
index 38fe4684..00000000
--- a/deps/node/deps/node-inspect/lib/internal/inspect_repl.js
+++ /dev/null
@@ -1,1089 +0,0 @@
-/*
- * Copyright Node.js contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-'use strict';
-const FS = require('fs');
-const Path = require('path');
-const Repl = require('repl');
-const util = require('util');
-const vm = require('vm');
-
-const debuglog = util.debuglog('inspect');
-
-const SHORTCUTS = {
- cont: 'c',
- next: 'n',
- step: 's',
- out: 'o',
- backtrace: 'bt',
- setBreakpoint: 'sb',
- clearBreakpoint: 'cb',
- run: 'r',
-};
-
-const HELP = `
-run, restart, r Run the application or reconnect
-kill Kill a running application or disconnect
-
-cont, c Resume execution
-next, n Continue to next line in current file
-step, s Step into, potentially entering a function
-out, o Step out, leaving the current function
-backtrace, bt Print the current backtrace
-list Print the source around the current line where execution
- is currently paused
-
-setBreakpoint, sb Set a breakpoint
-clearBreakpoint, cb Clear a breakpoint
-breakpoints List all known breakpoints
-breakOnException Pause execution whenever an exception is thrown
-breakOnUncaught Pause execution whenever an exception isn't caught
-breakOnNone Don't pause on exceptions (this is the default)
-
-watch(expr) Start watching the given expression
-unwatch(expr) Stop watching an expression
-watchers Print all watched expressions and their current values
-
-exec(expr) Evaluate the expression and print the value
-repl Enter a debug repl that works like exec
-
-scripts List application scripts that are currently loaded
-scripts(true) List all scripts (including node-internals)
-
-profile Start CPU profiling session.
-profileEnd Stop current CPU profiling session.
-profiles Array of completed CPU profiling sessions.
-profiles[n].save(filepath = 'node.cpuprofile')
- Save CPU profiling session to disk as JSON.
-
-takeHeapSnapshot(filepath = 'node.heapsnapshot')
- Take a heap snapshot and save to disk as JSON.
-`.trim();
-
-const FUNCTION_NAME_PATTERN = /^(?:function\*? )?([^(\s]+)\(/;
-function extractFunctionName(description) {
- const fnNameMatch = description.match(FUNCTION_NAME_PATTERN);
- return fnNameMatch ? `: ${fnNameMatch[1]}` : '';
-}
-
-const NATIVES = process.binding('natives');
-function isNativeUrl(url) {
- return url.replace('.js', '') in NATIVES || url === 'bootstrap_node.js';
-}
-
-function getRelativePath(filename) {
- const dir = Path.join(Path.resolve(), 'x').slice(0, -1);
-
- // Change path to relative, if possible
- if (filename.indexOf(dir) === 0) {
- return filename.slice(dir.length);
- }
- return filename;
-}
-
-function toCallback(promise, callback) {
- function forward(...args) {
- process.nextTick(() => callback(...args));
- }
- promise.then(forward.bind(null, null), forward);
-}
-
-// Adds spaces and prefix to number
-// maxN is a maximum number we should have space for
-function leftPad(n, prefix, maxN) {
- const s = n.toString();
- const nchars = Math.max(2, String(maxN).length) + 1;
- const nspaces = nchars - s.length - 1;
-
- return prefix + ' '.repeat(nspaces) + s;
-}
-
-function markSourceColumn(sourceText, position, useColors) {
- if (!sourceText) return '';
-
- const head = sourceText.slice(0, position);
- let tail = sourceText.slice(position);
-
- // Colourize char if stdout supports colours
- if (useColors) {
- tail = tail.replace(/(.+?)([^\w]|$)/, '\u001b[32m$1\u001b[39m$2');
- }
-
- // Return source line with coloured char at `position`
- return [head, tail].join('');
-}
-
-function extractErrorMessage(stack) {
- if (!stack) return '<unknown>';
- const m = stack.match(/^\w+: ([^\n]+)/);
- return m ? m[1] : stack;
-}
-
-function convertResultToError(result) {
- const { className, description } = result;
- const err = new Error(extractErrorMessage(description));
- err.stack = description;
- Object.defineProperty(err, 'name', { value: className });
- return err;
-}
-
-class RemoteObject {
- constructor(attributes) {
- Object.assign(this, attributes);
- if (this.type === 'number') {
- this.value =
- this.unserializableValue ? +this.unserializableValue : +this.value;
- }
- }
-
- [util.inspect.custom](depth, opts) {
- function formatProperty(prop) {
- switch (prop.type) {
- case 'string':
- case 'undefined':
- return util.inspect(prop.value, opts);
-
- case 'number':
- case 'boolean':
- return opts.stylize(prop.value, prop.type);
-
- case 'object':
- case 'symbol':
- if (prop.subtype === 'date') {
- return util.inspect(new Date(prop.value), opts);
- }
- if (prop.subtype === 'array') {
- return opts.stylize(prop.value, 'special');
- }
- return opts.stylize(prop.value, prop.subtype || 'special');
-
- default:
- return prop.value;
- }
- }
- switch (this.type) {
- case 'boolean':
- case 'number':
- case 'string':
- case 'undefined':
- return util.inspect(this.value, opts);
-
- case 'symbol':
- return opts.stylize(this.description, 'special');
-
- case 'function': {
- const fnName = extractFunctionName(this.description);
- const formatted = `[${this.className}${fnName}]`;
- return opts.stylize(formatted, 'special');
- }
-
- case 'object':
- switch (this.subtype) {
- case 'date':
- return util.inspect(new Date(this.description), opts);
-
- case 'null':
- return util.inspect(null, opts);
-
- case 'regexp':
- return opts.stylize(this.description, 'regexp');
-
- default:
- break;
- }
- if (this.preview) {
- const props = this.preview.properties
- .map((prop, idx) => {
- const value = formatProperty(prop);
- if (prop.name === `${idx}`) return value;
- return `${prop.name}: ${value}`;
- });
- if (this.preview.overflow) {
- props.push('...');
- }
- const singleLine = props.join(', ');
- const propString =
- singleLine.length > 60 ? props.join(',\n ') : singleLine;
-
- return this.subtype === 'array' ?
- `[ ${propString} ]` : `{ ${propString} }`;
- }
- return this.description;
-
- default:
- return this.description;
- }
- }
-
- static fromEvalResult({ result, wasThrown }) {
- if (wasThrown) return convertResultToError(result);
- return new RemoteObject(result);
- }
-}
-
-class ScopeSnapshot {
- constructor(scope, properties) {
- Object.assign(this, scope);
- this.properties = new Map(properties.map((prop) => {
- const value = new RemoteObject(prop.value);
- return [prop.name, value];
- }));
- this.completionGroup = properties.map((prop) => prop.name);
- }
-
- [util.inspect.custom](depth, opts) {
- const type = `${this.type[0].toUpperCase()}${this.type.slice(1)}`;
- const name = this.name ? `<${this.name}>` : '';
- const prefix = `${type}${name} `;
- return util.inspect(this.properties, opts)
- .replace(/^Map /, prefix);
- }
-}
-
-function copyOwnProperties(target, source) {
- Object.getOwnPropertyNames(source).forEach((prop) => {
- const descriptor = Object.getOwnPropertyDescriptor(source, prop);
- Object.defineProperty(target, prop, descriptor);
- });
-}
-
-function aliasProperties(target, mapping) {
- Object.keys(mapping).forEach((key) => {
- const descriptor = Object.getOwnPropertyDescriptor(target, key);
- Object.defineProperty(target, mapping[key], descriptor);
- });
-}
-
-function createRepl(inspector) {
- const { Debugger, HeapProfiler, Profiler, Runtime } = inspector;
-
- let repl; // eslint-disable-line prefer-const
-
- // Things we want to keep around
- const history = { control: [], debug: [] };
- const watchedExpressions = [];
- const knownBreakpoints = [];
- let pauseOnExceptionState = 'none';
- let lastCommand;
-
- // Things we need to reset when the app restarts
- let knownScripts;
- let currentBacktrace;
- let selectedFrame;
- let exitDebugRepl;
-
- function resetOnStart() {
- knownScripts = {};
- currentBacktrace = null;
- selectedFrame = null;
-
- if (exitDebugRepl) exitDebugRepl();
- exitDebugRepl = null;
- }
- resetOnStart();
-
- const INSPECT_OPTIONS = { colors: inspector.stdout.isTTY };
- function inspect(value) {
- return util.inspect(value, INSPECT_OPTIONS);
- }
-
- function print(value, oneline = false) {
- const text = typeof value === 'string' ? value : inspect(value);
- return inspector.print(text, oneline);
- }
-
- function getCurrentLocation() {
- if (!selectedFrame) {
- throw new Error('Requires execution to be paused');
- }
- return selectedFrame.location;
- }
-
- function isCurrentScript(script) {
- return selectedFrame && getCurrentLocation().scriptId === script.scriptId;
- }
-
- function formatScripts(displayNatives = false) {
- function isVisible(script) {
- if (displayNatives) return true;
- return !script.isNative || isCurrentScript(script);
- }
-
- return Object.keys(knownScripts)
- .map((scriptId) => knownScripts[scriptId])
- .filter(isVisible)
- .map((script) => {
- const isCurrent = isCurrentScript(script);
- const { isNative, url } = script;
- const name = `${getRelativePath(url)}${isNative ? ' <native>' : ''}`;
- return `${isCurrent ? '*' : ' '} ${script.scriptId}: ${name}`;
- })
- .join('\n');
- }
- function listScripts(displayNatives = false) {
- print(formatScripts(displayNatives));
- }
- listScripts[util.inspect.custom] = function listWithoutInternal() {
- return formatScripts();
- };
-
- const profiles = [];
- class Profile {
- constructor(data) {
- this.data = data;
- }
-
- static createAndRegister({ profile }) {
- const p = new Profile(profile);
- profiles.push(p);
- return p;
- }
-
- [util.inspect.custom](depth, { stylize }) {
- const { startTime, endTime } = this.data;
- return stylize(`[Profile ${endTime - startTime}μs]`, 'special');
- }
-
- save(filename = 'node.cpuprofile') {
- const absoluteFile = Path.resolve(filename);
- const json = JSON.stringify(this.data);
- FS.writeFileSync(absoluteFile, json);
- print('Saved profile to ' + absoluteFile);
- }
- }
-
- class SourceSnippet {
- constructor(location, delta, scriptSource) {
- Object.assign(this, location);
- this.scriptSource = scriptSource;
- this.delta = delta;
- }
-
- [util.inspect.custom](depth, options) {
- const { scriptId, lineNumber, columnNumber, delta, scriptSource } = this;
- const start = Math.max(1, lineNumber - delta + 1);
- const end = lineNumber + delta + 1;
-
- const lines = scriptSource.split('\n');
- return lines.slice(start - 1, end).map((lineText, offset) => {
- const i = start + offset;
- const isCurrent = i === (lineNumber + 1);
-
- const markedLine = isCurrent
- ? markSourceColumn(lineText, columnNumber, options.colors)
- : lineText;
-
- let isBreakpoint = false;
- knownBreakpoints.forEach(({ location }) => {
- if (!location) return;
- if (scriptId === location.scriptId &&
- i === (location.lineNumber + 1)) {
- isBreakpoint = true;
- }
- });
-
- let prefixChar = ' ';
- if (isCurrent) {
- prefixChar = '>';
- } else if (isBreakpoint) {
- prefixChar = '*';
- }
- return `${leftPad(i, prefixChar, end)} ${markedLine}`;
- }).join('\n');
- }
- }
-
- function getSourceSnippet(location, delta = 5) {
- const { scriptId } = location;
- return Debugger.getScriptSource({ scriptId })
- .then(({ scriptSource }) =>
- new SourceSnippet(location, delta, scriptSource));
- }
-
- class CallFrame {
- constructor(callFrame) {
- Object.assign(this, callFrame);
- }
-
- loadScopes() {
- return Promise.all(
- this.scopeChain
- .filter((scope) => scope.type !== 'global')
- .map((scope) => {
- const { objectId } = scope.object;
- return Runtime.getProperties({
- objectId,
- generatePreview: true,
- }).then(({ result }) => new ScopeSnapshot(scope, result));
- })
- );
- }
-
- list(delta = 5) {
- return getSourceSnippet(this.location, delta);
- }
- }
-
- class Backtrace extends Array {
- [util.inspect.custom]() {
- return this.map((callFrame, idx) => {
- const {
- location: { scriptId, lineNumber, columnNumber },
- functionName
- } = callFrame;
- const name = functionName || '(anonymous)';
-
- const script = knownScripts[scriptId];
- const relativeUrl =
- (script && getRelativePath(script.url)) || '<unknown>';
- const frameLocation =
- `${relativeUrl}:${lineNumber + 1}:${columnNumber}`;
-
- return `#${idx} ${name} ${frameLocation}`;
- }).join('\n');
- }
-
- static from(callFrames) {
- return super.from(Array.from(callFrames).map((callFrame) => {
- if (callFrame instanceof CallFrame) {
- return callFrame;
- }
- return new CallFrame(callFrame);
- }));
- }
- }
-
- function prepareControlCode(input) {
- if (input === '\n') return lastCommand;
- // exec process.title => exec("process.title");
- const match = input.match(/^\s*exec\s+([^\n]*)/);
- if (match) {
- lastCommand = `exec(${JSON.stringify(match[1])})`;
- } else {
- lastCommand = input;
- }
- return lastCommand;
- }
-
- function evalInCurrentContext(code) {
- // Repl asked for scope variables
- if (code === '.scope') {
- if (!selectedFrame) {
- return Promise.reject(new Error('Requires execution to be paused'));
- }
- return selectedFrame.loadScopes().then((scopes) => {
- return scopes.map((scope) => scope.completionGroup);
- });
- }
-
- if (selectedFrame) {
- return Debugger.evaluateOnCallFrame({
- callFrameId: selectedFrame.callFrameId,
- expression: code,
- objectGroup: 'node-inspect',
- generatePreview: true,
- }).then(RemoteObject.fromEvalResult);
- }
- return Runtime.evaluate({
- expression: code,
- objectGroup: 'node-inspect',
- generatePreview: true,
- }).then(RemoteObject.fromEvalResult);
- }
-
- function controlEval(input, context, filename, callback) {
- debuglog('eval:', input);
- function returnToCallback(error, result) {
- debuglog('end-eval:', input, error);
- callback(error, result);
- }
-
- try {
- const code = prepareControlCode(input);
- const result = vm.runInContext(code, context, filename);
-
- if (result && typeof result.then === 'function') {
- toCallback(result, returnToCallback);
- return;
- }
- returnToCallback(null, result);
- } catch (e) {
- returnToCallback(e);
- }
- }
-
- function debugEval(input, context, filename, callback) {
- debuglog('eval:', input);
- function returnToCallback(error, result) {
- debuglog('end-eval:', input, error);
- callback(error, result);
- }
-
- try {
- const result = evalInCurrentContext(input);
-
- if (result && typeof result.then === 'function') {
- toCallback(result, returnToCallback);
- return;
- }
- returnToCallback(null, result);
- } catch (e) {
- returnToCallback(e);
- }
- }
-
- function formatWatchers(verbose = false) {
- if (!watchedExpressions.length) {
- return Promise.resolve('');
- }
-
- const inspectValue = (expr) =>
- evalInCurrentContext(expr)
- // .then(formatValue)
- .catch((error) => `<${error.message}>`);
- const lastIndex = watchedExpressions.length - 1;
-
- return Promise.all(watchedExpressions.map(inspectValue))
- .then((values) => {
- const lines = watchedExpressions
- .map((expr, idx) => {
- const prefix = `${leftPad(idx, ' ', lastIndex)}: ${expr} =`;
- const value = inspect(values[idx], { colors: true });
- if (value.indexOf('\n') === -1) {
- return `${prefix} ${value}`;
- }
- return `${prefix}\n ${value.split('\n').join('\n ')}`;
- });
- return lines.join('\n');
- })
- .then((valueList) => {
- return verbose ? `Watchers:\n${valueList}\n` : valueList;
- });
- }
-
- function watchers(verbose = false) {
- return formatWatchers(verbose).then(print);
- }
-
- // List source code
- function list(delta = 5) {
- return selectedFrame.list(delta)
- .then(null, (error) => {
- print('You can\'t list source code right now');
- throw error;
- });
- }
-
- function handleBreakpointResolved({ breakpointId, location }) {
- const script = knownScripts[location.scriptId];
- const scriptUrl = script && script.url;
- if (scriptUrl) {
- Object.assign(location, { scriptUrl });
- }
- const isExisting = knownBreakpoints.some((bp) => {
- if (bp.breakpointId === breakpointId) {
- Object.assign(bp, { location });
- return true;
- }
- return false;
- });
- if (!isExisting) {
- knownBreakpoints.push({ breakpointId, location });
- }
- }
-
- function listBreakpoints() {
- if (!knownBreakpoints.length) {
- print('No breakpoints yet');
- return;
- }
-
- function formatLocation(location) {
- if (!location) return '<unknown location>';
- const script = knownScripts[location.scriptId];
- const scriptUrl = script ? script.url : location.scriptUrl;
- return `${getRelativePath(scriptUrl)}:${location.lineNumber + 1}`;
- }
- const breaklist = knownBreakpoints
- .map((bp, idx) => `#${idx} ${formatLocation(bp.location)}`)
- .join('\n');
- print(breaklist);
- }
-
- function setBreakpoint(script, line, condition, silent) {
- function registerBreakpoint({ breakpointId, actualLocation }) {
- handleBreakpointResolved({ breakpointId, location: actualLocation });
- if (actualLocation && actualLocation.scriptId) {
- if (!silent) return getSourceSnippet(actualLocation, 5);
- } else {
- print(`Warning: script '${script}' was not loaded yet.`);
- }
- return undefined;
- }
-
- // setBreakpoint(): set breakpoint at current location
- if (script === undefined) {
- return Debugger
- .setBreakpoint({ location: getCurrentLocation(), condition })
- .then(registerBreakpoint);
- }
-
- // setBreakpoint(line): set breakpoint in current script at specific line
- if (line === undefined && typeof script === 'number') {
- const location = {
- scriptId: getCurrentLocation().scriptId,
- lineNumber: script - 1,
- };
- return Debugger.setBreakpoint({ location, condition })
- .then(registerBreakpoint);
- }
-
- if (typeof script !== 'string') {
- throw new TypeError(`setBreakpoint() expects a string, got ${script}`);
- }
-
- // setBreakpoint('fn()'): Break when a function is called
- if (script.endsWith('()')) {
- const debugExpr = `debug(${script.slice(0, -2)})`;
- const debugCall = selectedFrame
- ? Debugger.evaluateOnCallFrame({
- callFrameId: selectedFrame.callFrameId,
- expression: debugExpr,
- includeCommandLineAPI: true,
- })
- : Runtime.evaluate({
- expression: debugExpr,
- includeCommandLineAPI: true,
- });
- return debugCall.then(({ result, wasThrown }) => {
- if (wasThrown) return convertResultToError(result);
- return undefined; // This breakpoint can't be removed the same way
- });
- }
-
- // setBreakpoint('scriptname')
- let scriptId = null;
- let ambiguous = false;
- if (knownScripts[script]) {
- scriptId = script;
- } else {
- for (const id of Object.keys(knownScripts)) {
- const scriptUrl = knownScripts[id].url;
- if (scriptUrl && scriptUrl.indexOf(script) !== -1) {
- if (scriptId !== null) {
- ambiguous = true;
- }
- scriptId = id;
- }
- }
- }
-
- if (ambiguous) {
- print('Script name is ambiguous');
- return undefined;
- }
- if (line <= 0) {
- print('Line should be a positive value');
- return undefined;
- }
-
- if (scriptId !== null) {
- const location = { scriptId, lineNumber: line - 1 };
- return Debugger.setBreakpoint({ location, condition })
- .then(registerBreakpoint);
- }
-
- const escapedPath = script.replace(/([/\\.?*()^${}|[\]])/g, '\\$1');
- const urlRegex = `^(.*[\\/\\\\])?${escapedPath}$`;
-
- return Debugger
- .setBreakpointByUrl({ urlRegex, lineNumber: line - 1, condition })
- .then((bp) => {
- // TODO: handle bp.locations in case the regex matches existing files
- if (!bp.location) { // Fake it for now.
- Object.assign(bp, {
- actualLocation: {
- scriptUrl: `.*/${script}$`,
- lineNumber: line - 1,
- },
- });
- }
- return registerBreakpoint(bp);
- });
- }
-
- function clearBreakpoint(url, line) {
- const breakpoint = knownBreakpoints.find(({ location }) => {
- if (!location) return false;
- const script = knownScripts[location.scriptId];
- if (!script) return false;
- return (
- script.url.indexOf(url) !== -1 && (location.lineNumber + 1) === line
- );
- });
- if (!breakpoint) {
- print(`Could not find breakpoint at ${url}:${line}`);
- return Promise.resolve();
- }
- return Debugger.removeBreakpoint({ breakpointId: breakpoint.breakpointId })
- .then(() => {
- const idx = knownBreakpoints.indexOf(breakpoint);
- knownBreakpoints.splice(idx, 1);
- });
- }
-
- function restoreBreakpoints() {
- const lastBreakpoints = knownBreakpoints.slice();
- knownBreakpoints.length = 0;
- const newBreakpoints = lastBreakpoints
- .filter(({ location }) => !!location.scriptUrl)
- .map(({ location }) =>
- setBreakpoint(location.scriptUrl, location.lineNumber + 1));
- if (!newBreakpoints.length) return Promise.resolve();
- return Promise.all(newBreakpoints).then((results) => {
- print(`${results.length} breakpoints restored.`);
- });
- }
-
- function setPauseOnExceptions(state) {
- return Debugger.setPauseOnExceptions({ state })
- .then(() => {
- pauseOnExceptionState = state;
- });
- }
-
- Debugger.on('paused', ({ callFrames, reason /* , hitBreakpoints */ }) => {
- // Save execution context's data
- currentBacktrace = Backtrace.from(callFrames);
- selectedFrame = currentBacktrace[0];
- const { scriptId, lineNumber } = selectedFrame.location;
-
- const breakType = reason === 'other' ? 'break' : reason;
- const script = knownScripts[scriptId];
- const scriptUrl = script ? getRelativePath(script.url) : '[unknown]';
-
- const header = `${breakType} in ${scriptUrl}:${lineNumber + 1}`;
-
- inspector.suspendReplWhile(() =>
- Promise.all([formatWatchers(true), selectedFrame.list(2)])
- .then(([watcherList, context]) => {
- if (watcherList) {
- return `${watcherList}\n${inspect(context)}`;
- }
- return inspect(context);
- }).then((breakContext) => {
- print(`${header}\n${breakContext}`);
- }));
- });
-
- function handleResumed() {
- currentBacktrace = null;
- selectedFrame = null;
- }
-
- Debugger.on('resumed', handleResumed);
-
- Debugger.on('breakpointResolved', handleBreakpointResolved);
-
- Debugger.on('scriptParsed', (script) => {
- const { scriptId, url } = script;
- if (url) {
- knownScripts[scriptId] = Object.assign({
- isNative: isNativeUrl(url),
- }, script);
- }
- });
-
- Profiler.on('consoleProfileFinished', ({ profile }) => {
- Profile.createAndRegister({ profile });
- print([
- 'Captured new CPU profile.',
- `Access it with profiles[${profiles.length - 1}]`
- ].join('\n'));
- });
-
- function initializeContext(context) {
- inspector.domainNames.forEach((domain) => {
- Object.defineProperty(context, domain, {
- value: inspector[domain],
- enumerable: true,
- configurable: true,
- writeable: false,
- });
- });
-
- copyOwnProperties(context, {
- get help() {
- print(HELP);
- },
-
- get run() {
- return inspector.run();
- },
-
- get kill() {
- return inspector.killChild();
- },
-
- get restart() {
- return inspector.run();
- },
-
- get cont() {
- handleResumed();
- return Debugger.resume();
- },
-
- get next() {
- handleResumed();
- return Debugger.stepOver();
- },
-
- get step() {
- handleResumed();
- return Debugger.stepInto();
- },
-
- get out() {
- handleResumed();
- return Debugger.stepOut();
- },
-
- get pause() {
- return Debugger.pause();
- },
-
- get backtrace() {
- return currentBacktrace;
- },
-
- get breakpoints() {
- return listBreakpoints();
- },
-
- exec(expr) {
- return evalInCurrentContext(expr);
- },
-
- get profile() {
- return Profiler.start();
- },
-
- get profileEnd() {
- return Profiler.stop()
- .then(Profile.createAndRegister);
- },
-
- get profiles() {
- return profiles;
- },
-
- takeHeapSnapshot(filename = 'node.heapsnapshot') {
- return new Promise((resolve, reject) => {
- const absoluteFile = Path.resolve(filename);
- const writer = FS.createWriteStream(absoluteFile);
- let sizeWritten = 0;
- function onProgress({ done, total, finished }) {
- if (finished) {
- print('Heap snaphost prepared.');
- } else {
- print(`Heap snapshot: ${done}/${total}`, true);
- }
- }
- function onChunk({ chunk }) {
- sizeWritten += chunk.length;
- writer.write(chunk);
- print(`Writing snapshot: ${sizeWritten}`, true);
- }
- function onResolve() {
- writer.end(() => {
- teardown();
- print(`Wrote snapshot: ${absoluteFile}`);
- resolve();
- });
- }
- function onReject(error) {
- teardown();
- reject(error);
- }
- function teardown() {
- HeapProfiler.removeListener(
- 'reportHeapSnapshotProgress', onProgress);
- HeapProfiler.removeListener('addHeapSnapshotChunk', onChunk);
- }
-
- HeapProfiler.on('reportHeapSnapshotProgress', onProgress);
- HeapProfiler.on('addHeapSnapshotChunk', onChunk);
-
- print('Heap snapshot: 0/0', true);
- HeapProfiler.takeHeapSnapshot({ reportProgress: true })
- .then(onResolve, onReject);
- });
- },
-
- get watchers() {
- return watchers();
- },
-
- watch(expr) {
- watchedExpressions.push(expr);
- },
-
- unwatch(expr) {
- const index = watchedExpressions.indexOf(expr);
-
- // Unwatch by expression
- // or
- // Unwatch by watcher number
- watchedExpressions.splice(index !== -1 ? index : +expr, 1);
- },
-
- get repl() {
- // Don't display any default messages
- const listeners = repl.rli.listeners('SIGINT').slice(0);
- repl.rli.removeAllListeners('SIGINT');
-
- const oldContext = repl.context;
-
- exitDebugRepl = () => {
- // Restore all listeners
- process.nextTick(() => {
- listeners.forEach((listener) => {
- repl.rli.on('SIGINT', listener);
- });
- });
-
- // Exit debug repl
- repl.eval = controlEval;
-
- // Swap history
- history.debug = repl.rli.history;
- repl.rli.history = history.control;
-
- repl.context = oldContext;
- repl.rli.setPrompt('debug> ');
- repl.displayPrompt();
-
- repl.rli.removeListener('SIGINT', exitDebugRepl);
- repl.removeListener('exit', exitDebugRepl);
-
- exitDebugRepl = null;
- };
-
- // Exit debug repl on SIGINT
- repl.rli.on('SIGINT', exitDebugRepl);
-
- // Exit debug repl on repl exit
- repl.on('exit', exitDebugRepl);
-
- // Set new
- repl.eval = debugEval;
- repl.context = {};
-
- // Swap history
- history.control = repl.rli.history;
- repl.rli.history = history.debug;
-
- repl.rli.setPrompt('> ');
-
- print('Press Ctrl + C to leave debug repl');
- repl.displayPrompt();
- },
-
- get version() {
- return Runtime.evaluate({
- expression: 'process.versions.v8',
- contextId: 1,
- returnByValue: true,
- }).then(({ result }) => {
- print(result.value);
- });
- },
-
- scripts: listScripts,
-
- setBreakpoint,
- clearBreakpoint,
- setPauseOnExceptions,
- get breakOnException() {
- return setPauseOnExceptions('all');
- },
- get breakOnUncaught() {
- return setPauseOnExceptions('uncaught');
- },
- get breakOnNone() {
- return setPauseOnExceptions('none');
- },
-
- list,
- });
- aliasProperties(context, SHORTCUTS);
- }
-
- function initAfterStart() {
- const setupTasks = [
- Runtime.enable(),
- Profiler.enable(),
- Profiler.setSamplingInterval({ interval: 100 }),
- Debugger.enable(),
- Debugger.setPauseOnExceptions({ state: 'none' }),
- Debugger.setAsyncCallStackDepth({ maxDepth: 0 }),
- Debugger.setBlackboxPatterns({ patterns: [] }),
- Debugger.setPauseOnExceptions({ state: pauseOnExceptionState }),
- restoreBreakpoints(),
- Runtime.runIfWaitingForDebugger(),
- ];
- return Promise.all(setupTasks);
- }
-
- return function startRepl() {
- inspector.client.on('close', () => {
- resetOnStart();
- });
- inspector.client.on('ready', () => {
- initAfterStart();
- });
-
- const replOptions = {
- prompt: 'debug> ',
- input: inspector.stdin,
- output: inspector.stdout,
- eval: controlEval,
- useGlobal: false,
- ignoreUndefined: true,
- };
-
- repl = Repl.start(replOptions); // eslint-disable-line prefer-const
- initializeContext(repl.context);
- repl.on('reset', initializeContext);
-
- repl.defineCommand('interrupt', () => {
- // We want this for testing purposes where sending CTRL-C can be tricky.
- repl.rli.emit('SIGINT');
- });
-
- // Init once for the initial connection
- initAfterStart();
-
- return repl;
- };
-}
-module.exports = createRepl;