1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 |
|
7 | var _stringify = require('babel-runtime/core-js/json/stringify');
|
8 |
|
9 | var _stringify2 = _interopRequireDefault(_stringify);
|
10 |
|
11 | var _assign = require('babel-runtime/core-js/object/assign');
|
12 |
|
13 | var _assign2 = _interopRequireDefault(_assign);
|
14 |
|
15 | var _regenerator = require('babel-runtime/regenerator');
|
16 |
|
17 | var _regenerator2 = _interopRequireDefault(_regenerator);
|
18 |
|
19 | var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
|
20 |
|
21 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
|
22 |
|
23 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
24 |
|
25 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
26 |
|
27 | var _createClass2 = require('babel-runtime/helpers/createClass');
|
28 |
|
29 | var _createClass3 = _interopRequireDefault(_createClass2);
|
30 |
|
31 | var _pinkie = require('pinkie');
|
32 |
|
33 | var _pinkie2 = _interopRequireDefault(_pinkie);
|
34 |
|
35 | var _net = require('net');
|
36 |
|
37 | var _promisifyEvent = require('promisify-event');
|
38 |
|
39 | var _promisifyEvent2 = _interopRequireDefault(_promisifyEvent);
|
40 |
|
41 | var _events = require('events');
|
42 |
|
43 | var _events2 = _interopRequireDefault(_events);
|
44 |
|
45 | var _delay = require('./utils/delay');
|
46 |
|
47 | var _delay2 = _interopRequireDefault(_delay);
|
48 |
|
49 | var _constants = require('./constants');
|
50 |
|
51 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
52 |
|
53 | var HEADER_SEPARATOR = '\r\n\r\n';
|
54 | var HEADER_LINE_RE = /^([^:]+):\s+(.*)$/;
|
55 |
|
56 | var NodeDebug = function () {
|
57 | function NodeDebug() {
|
58 | var port = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 5858;
|
59 | var host = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '127.0.0.1';
|
60 | (0, _classCallCheck3.default)(this, NodeDebug);
|
61 |
|
62 | this.currentPacketNumber = 1;
|
63 | this.events = new _events2.default();
|
64 | this.port = port;
|
65 | this.host = host;
|
66 | this.socket = new _net.Socket();
|
67 | this.buffer = Buffer.alloc(0);
|
68 | this.getPacketPromise = _pinkie2.default.resolve();
|
69 | this.sendPacketPromise = _pinkie2.default.resolve();
|
70 |
|
71 | this.nodeInfo = {
|
72 | v8Version: '',
|
73 | protocolVersion: '',
|
74 | embeddingHost: ''
|
75 | };
|
76 | }
|
77 |
|
78 | (0, _createClass3.default)(NodeDebug, [{
|
79 | key: '_attemptToConnect',
|
80 | value: function () {
|
81 | var _ref = (0, _asyncToGenerator3.default)( _regenerator2.default.mark(function _callee(port, host) {
|
82 | var _this = this;
|
83 |
|
84 | var connectionPromise;
|
85 | return _regenerator2.default.wrap(function _callee$(_context) {
|
86 | while (1) {
|
87 | switch (_context.prev = _context.next) {
|
88 | case 0:
|
89 | this.socket.connect(port, host);
|
90 |
|
91 | connectionPromise = _pinkie2.default.race([(0, _promisifyEvent2.default)(this.socket, 'connect'), (0, _promisifyEvent2.default)(this.socket, 'error')]);
|
92 | _context.next = 4;
|
93 | return connectionPromise.then(function () {
|
94 | return true;
|
95 | }).catch(function () {
|
96 | _this.socket.removeAllListeners('connect');
|
97 | return (0, _delay2.default)(_constants.connectionRetryDelay);
|
98 | });
|
99 |
|
100 | case 4:
|
101 | return _context.abrupt('return', _context.sent);
|
102 |
|
103 | case 5:
|
104 | case 'end':
|
105 | return _context.stop();
|
106 | }
|
107 | }
|
108 | }, _callee, this);
|
109 | }));
|
110 |
|
111 | function _attemptToConnect(_x3, _x4) {
|
112 | return _ref.apply(this, arguments);
|
113 | }
|
114 |
|
115 | return _attemptToConnect;
|
116 | }()
|
117 | }, {
|
118 | key: '_connectSocket',
|
119 | value: function () {
|
120 | var _ref2 = (0, _asyncToGenerator3.default)( _regenerator2.default.mark(function _callee2(port, host) {
|
121 | var _this2 = this;
|
122 |
|
123 | var connected, i;
|
124 | return _regenerator2.default.wrap(function _callee2$(_context2) {
|
125 | while (1) {
|
126 | switch (_context2.prev = _context2.next) {
|
127 | case 0:
|
128 | _context2.next = 2;
|
129 | return this._attemptToConnect(port, host);
|
130 |
|
131 | case 2:
|
132 | connected = _context2.sent;
|
133 | i = 0;
|
134 |
|
135 | case 4:
|
136 | if (!(!connected && i < _constants.maxConnectionRetryCount)) {
|
137 | _context2.next = 11;
|
138 | break;
|
139 | }
|
140 |
|
141 | _context2.next = 7;
|
142 | return this._attemptToConnect(port, host);
|
143 |
|
144 | case 7:
|
145 | connected = _context2.sent;
|
146 |
|
147 | case 8:
|
148 | i++;
|
149 | _context2.next = 4;
|
150 | break;
|
151 |
|
152 | case 11:
|
153 | if (connected) {
|
154 | _context2.next = 13;
|
155 | break;
|
156 | }
|
157 |
|
158 | throw new Error('Unable to connect');
|
159 |
|
160 | case 13:
|
161 |
|
162 | this.socket.on('data', function (data) {
|
163 | return _this2._handleNewData(data);
|
164 | });
|
165 |
|
166 | case 14:
|
167 | case 'end':
|
168 | return _context2.stop();
|
169 | }
|
170 | }
|
171 | }, _callee2, this);
|
172 | }));
|
173 |
|
174 | function _connectSocket(_x5, _x6) {
|
175 | return _ref2.apply(this, arguments);
|
176 | }
|
177 |
|
178 | return _connectSocket;
|
179 | }()
|
180 | }, {
|
181 | key: '_writeSocket',
|
182 | value: function () {
|
183 | var _ref3 = (0, _asyncToGenerator3.default)( _regenerator2.default.mark(function _callee3(message) {
|
184 | return _regenerator2.default.wrap(function _callee3$(_context3) {
|
185 | while (1) {
|
186 | switch (_context3.prev = _context3.next) {
|
187 | case 0:
|
188 | if (this.socket.write(message)) {
|
189 | _context3.next = 3;
|
190 | break;
|
191 | }
|
192 |
|
193 | _context3.next = 3;
|
194 | return (0, _promisifyEvent2.default)(this.socket, 'drain');
|
195 |
|
196 | case 3:
|
197 | case 'end':
|
198 | return _context3.stop();
|
199 | }
|
200 | }
|
201 | }, _callee3, this);
|
202 | }));
|
203 |
|
204 | function _writeSocket(_x7) {
|
205 | return _ref3.apply(this, arguments);
|
206 | }
|
207 |
|
208 | return _writeSocket;
|
209 | }()
|
210 | }, {
|
211 | key: '_handleNewData',
|
212 | value: function _handleNewData(data) {
|
213 | if (!data) return;
|
214 |
|
215 | this.buffer = Buffer.concat([this.buffer, data]);
|
216 |
|
217 | this.events.emit('new-data');
|
218 | }
|
219 | }, {
|
220 | key: '_getPacket',
|
221 | value: function _getPacket() {
|
222 | var _this3 = this;
|
223 |
|
224 | this.getPacketPromise = this.getPacketPromise.then((0, _asyncToGenerator3.default)( _regenerator2.default.mark(function _callee4() {
|
225 | var headerEndIndex, packet, contentLengthHeader, contentLength, bodyStartIndex, bodyEndIndex;
|
226 | return _regenerator2.default.wrap(function _callee4$(_context4) {
|
227 | while (1) {
|
228 | switch (_context4.prev = _context4.next) {
|
229 | case 0:
|
230 | headerEndIndex = _this3.buffer.indexOf(HEADER_SEPARATOR);
|
231 |
|
232 | case 1:
|
233 | if (!(headerEndIndex < 0)) {
|
234 | _context4.next = 7;
|
235 | break;
|
236 | }
|
237 |
|
238 | _context4.next = 4;
|
239 | return (0, _promisifyEvent2.default)(_this3.events, 'new-data');
|
240 |
|
241 | case 4:
|
242 |
|
243 | headerEndIndex = _this3.buffer.indexOf('\r\n\r\n');
|
244 | _context4.next = 1;
|
245 | break;
|
246 |
|
247 | case 7:
|
248 | packet = {
|
249 | headers: null,
|
250 | body: null
|
251 | };
|
252 |
|
253 |
|
254 | packet.headers = _this3.buffer.toString('utf8', 0, headerEndIndex).split('\r\n').map(function (line) {
|
255 | return line.match(HEADER_LINE_RE);
|
256 | }).reduce(function (obj, match) {
|
257 | obj[match[1].toLowerCase()] = match[2];
|
258 |
|
259 | return obj;
|
260 | }, {});
|
261 |
|
262 | contentLengthHeader = packet.headers['content-length'];
|
263 | contentLength = contentLengthHeader && parseInt(contentLengthHeader, 10) || 0;
|
264 | bodyStartIndex = headerEndIndex + HEADER_SEPARATOR.length;
|
265 | bodyEndIndex = bodyStartIndex + contentLength;
|
266 |
|
267 | if (!contentLength) {
|
268 | _context4.next = 20;
|
269 | break;
|
270 | }
|
271 |
|
272 | case 14:
|
273 | if (!(_this3.buffer.length < bodyEndIndex)) {
|
274 | _context4.next = 19;
|
275 | break;
|
276 | }
|
277 |
|
278 | _context4.next = 17;
|
279 | return (0, _promisifyEvent2.default)(_this3.events, 'new-data');
|
280 |
|
281 | case 17:
|
282 | _context4.next = 14;
|
283 | break;
|
284 |
|
285 | case 19:
|
286 |
|
287 | packet.body = JSON.parse(_this3.buffer.toString('utf8', bodyStartIndex, bodyEndIndex));
|
288 |
|
289 | case 20:
|
290 |
|
291 | _this3.buffer = _this3.buffer.slice(bodyEndIndex);
|
292 |
|
293 | return _context4.abrupt('return', packet);
|
294 |
|
295 | case 22:
|
296 | case 'end':
|
297 | return _context4.stop();
|
298 | }
|
299 | }
|
300 | }, _callee4, _this3);
|
301 | })));
|
302 |
|
303 | return this.getPacketPromise;
|
304 | }
|
305 | }, {
|
306 | key: '_sendPacket',
|
307 | value: function _sendPacket(payload) {
|
308 | var _this4 = this;
|
309 |
|
310 | this.sendPacketPromise = this.sendPacketPromise.then((0, _asyncToGenerator3.default)( _regenerator2.default.mark(function _callee5() {
|
311 | var body, serialized, message;
|
312 | return _regenerator2.default.wrap(function _callee5$(_context5) {
|
313 | while (1) {
|
314 | switch (_context5.prev = _context5.next) {
|
315 | case 0:
|
316 | body = (0, _assign2.default)({}, payload, { seq: _this4.currentPacketNumber++, type: 'request' });
|
317 | serialized = (0, _stringify2.default)(body);
|
318 | message = 'Content-Length: ' + Buffer.byteLength(serialized, 'utf8') + HEADER_SEPARATOR + serialized;
|
319 |
|
320 |
|
321 | _this4._writeSocket(message);
|
322 |
|
323 | case 4:
|
324 | case 'end':
|
325 | return _context5.stop();
|
326 | }
|
327 | }
|
328 | }, _callee5, _this4);
|
329 | })));
|
330 |
|
331 | return this.sendPacketPromise;
|
332 | }
|
333 | }, {
|
334 | key: 'connect',
|
335 | value: function () {
|
336 | var _ref6 = (0, _asyncToGenerator3.default)( _regenerator2.default.mark(function _callee6() {
|
337 | var infoPacket;
|
338 | return _regenerator2.default.wrap(function _callee6$(_context6) {
|
339 | while (1) {
|
340 | switch (_context6.prev = _context6.next) {
|
341 | case 0:
|
342 | _context6.next = 2;
|
343 | return this._connectSocket(this.port, this.host);
|
344 |
|
345 | case 2:
|
346 | _context6.next = 4;
|
347 | return this._getPacket();
|
348 |
|
349 | case 4:
|
350 | infoPacket = _context6.sent;
|
351 |
|
352 |
|
353 | this.nodeInfo = {
|
354 | v8Version: infoPacket.headers['v8-version'],
|
355 | protocolVersion: infoPacket.headers['protocol-version'],
|
356 | embeddingHost: infoPacket.headers['embedding-host']
|
357 | };
|
358 |
|
359 | case 6:
|
360 | case 'end':
|
361 | return _context6.stop();
|
362 | }
|
363 | }
|
364 | }, _callee6, this);
|
365 | }));
|
366 |
|
367 | function connect() {
|
368 | return _ref6.apply(this, arguments);
|
369 | }
|
370 |
|
371 | return connect;
|
372 | }()
|
373 | }, {
|
374 | key: 'dispose',
|
375 | value: function dispose() {
|
376 | this.socket.end();
|
377 | this.buffer = null;
|
378 | }
|
379 | }, {
|
380 | key: 'evaluate',
|
381 | value: function () {
|
382 | var _ref7 = (0, _asyncToGenerator3.default)( _regenerator2.default.mark(function _callee7(expression) {
|
383 | var packetNumber, responsePacket;
|
384 | return _regenerator2.default.wrap(function _callee7$(_context7) {
|
385 | while (1) {
|
386 | switch (_context7.prev = _context7.next) {
|
387 | case 0:
|
388 | packetNumber = this.currentPacketNumber;
|
389 | _context7.next = 3;
|
390 | return this._sendPacket({ command: 'evaluate', arguments: { expression: expression, 'disable_break': true } });
|
391 |
|
392 | case 3:
|
393 | _context7.next = 5;
|
394 | return this._getPacket();
|
395 |
|
396 | case 5:
|
397 | responsePacket = _context7.sent;
|
398 |
|
399 | case 6:
|
400 | if (!(!responsePacket.body || responsePacket.body['request_seq'] !== packetNumber)) {
|
401 | _context7.next = 12;
|
402 | break;
|
403 | }
|
404 |
|
405 | _context7.next = 9;
|
406 | return this._getPacket();
|
407 |
|
408 | case 9:
|
409 | responsePacket = _context7.sent;
|
410 | _context7.next = 6;
|
411 | break;
|
412 |
|
413 | case 12:
|
414 | return _context7.abrupt('return', responsePacket);
|
415 |
|
416 | case 13:
|
417 | case 'end':
|
418 | return _context7.stop();
|
419 | }
|
420 | }
|
421 | }, _callee7, this);
|
422 | }));
|
423 |
|
424 | function evaluate(_x8) {
|
425 | return _ref7.apply(this, arguments);
|
426 | }
|
427 |
|
428 | return evaluate;
|
429 | }()
|
430 | }]);
|
431 | return NodeDebug;
|
432 | }();
|
433 |
|
434 | exports.default = NodeDebug;
|
435 | module.exports = exports['default']; |
\ | No newline at end of file |