0
0
mirror of https://github.com/nodejs/node.git synced 2024-11-29 23:16:30 +01:00
nodejs/lib/inspector.js
Anna Henningsen 0df031acad
worker: initial implementation
Implement multi-threading support for most of the API.

Thanks to Stephen Belanger for reviewing this change in its
original form, to Olivia Hugger for reviewing the
documentation and some of the tests coming along with it,
and to Alexey Orlenko and Timothy Gu for reviewing other
parts of the tests.

Refs: https://github.com/ayojs/ayo/pull/110
Refs: https://github.com/ayojs/ayo/pull/114
Refs: https://github.com/ayojs/ayo/pull/117

PR-URL: https://github.com/nodejs/node/pull/20876
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Shingo Inoue <leko.noor@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
2018-06-06 19:43:52 +02:00

108 lines
3.0 KiB
JavaScript

'use strict';
const EventEmitter = require('events');
const {
ERR_INSPECTOR_ALREADY_CONNECTED,
ERR_INSPECTOR_CLOSED,
ERR_INSPECTOR_NOT_AVAILABLE,
ERR_INSPECTOR_NOT_CONNECTED,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_CALLBACK
} = require('internal/errors').codes;
const util = require('util');
const { Connection, open, url } = process.binding('inspector');
if (!Connection || !require('internal/worker').isMainThread)
throw new ERR_INSPECTOR_NOT_AVAILABLE();
const connectionSymbol = Symbol('connectionProperty');
const messageCallbacksSymbol = Symbol('messageCallbacks');
const nextIdSymbol = Symbol('nextId');
const onMessageSymbol = Symbol('onMessage');
class Session extends EventEmitter {
constructor() {
super();
this[connectionSymbol] = null;
this[nextIdSymbol] = 1;
this[messageCallbacksSymbol] = new Map();
}
connect() {
if (this[connectionSymbol])
throw new ERR_INSPECTOR_ALREADY_CONNECTED('The inspector session');
const connection =
new Connection((message) => this[onMessageSymbol](message));
if (connection.sessionAttached) {
throw new ERR_INSPECTOR_ALREADY_CONNECTED('Another inspector session');
}
this[connectionSymbol] = connection;
}
[onMessageSymbol](message) {
const parsed = JSON.parse(message);
try {
if (parsed.id) {
const callback = this[messageCallbacksSymbol].get(parsed.id);
this[messageCallbacksSymbol].delete(parsed.id);
if (callback)
callback(parsed.error || null, parsed.result || null);
} else {
this.emit(parsed.method, parsed);
this.emit('inspectorNotification', parsed);
}
} catch (error) {
process.emitWarning(error);
}
}
post(method, params, callback) {
if (typeof method !== 'string') {
throw new ERR_INVALID_ARG_TYPE('method', 'string', method);
}
if (!callback && util.isFunction(params)) {
callback = params;
params = null;
}
if (params && typeof params !== 'object') {
throw new ERR_INVALID_ARG_TYPE('params', 'Object', params);
}
if (callback && typeof callback !== 'function') {
throw new ERR_INVALID_CALLBACK();
}
if (!this[connectionSymbol]) {
throw new ERR_INSPECTOR_NOT_CONNECTED();
}
const id = this[nextIdSymbol]++;
const message = { id, method };
if (params) {
message.params = params;
}
if (callback) {
this[messageCallbacksSymbol].set(id, callback);
}
this[connectionSymbol].dispatch(JSON.stringify(message));
}
disconnect() {
if (!this[connectionSymbol])
return;
this[connectionSymbol].disconnect();
this[connectionSymbol] = null;
const remainingCallbacks = this[messageCallbacksSymbol].values();
for (const callback of remainingCallbacks) {
process.nextTick(callback, new ERR_INSPECTOR_CLOSED());
}
this[messageCallbacksSymbol].clear();
this[nextIdSymbol] = 1;
}
}
module.exports = {
open: (port, host, wait) => open(port, host, !!wait),
close: process._debugEnd,
url: url,
Session
};