Browse Source

src: add /json/protocol endpoint to inspector

Embed the compressed and minified protocol.json from the bundled
v8_inspector and make it available through the /json/protocol endpoint.

Refs: https://github.com/nodejs/diagnostics/issues/52
PR-URL: https://github.com/nodejs/node/pull/7491
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
v6
Ben Noordhuis 9 years ago
parent
commit
782620f03f
  1. 4
      deps/zlib/zlib.gyp
  2. 29
      node.gyp
  3. 28
      src/inspector_agent.cc
  4. 1
      test/common.js
  5. 22
      test/parallel/test-v8-inspector-json-protocol.js
  6. 5
      test/testpy/__init__.py
  7. 25
      tools/compress_json.py

4
deps/zlib/zlib.gyp

@ -12,6 +12,7 @@
{
'target_name': 'zlib',
'type': 'static_library',
'defines': [ 'ZLIB_CONST' ],
'sources': [
'adler32.c',
'compress.c',
@ -44,6 +45,7 @@
'.',
],
'direct_dependent_settings': {
'defines': [ 'ZLIB_CONST' ],
'include_dirs': [
'.',
],
@ -72,10 +74,12 @@
'direct_dependent_settings': {
'defines': [
'USE_SYSTEM_ZLIB',
'ZLIB_CONST',
],
},
'defines': [
'USE_SYSTEM_ZLIB',
'ZLIB_CONST',
],
'link_settings': {
'libraries': [

29
node.gyp

@ -323,6 +323,7 @@
'dependencies': [
'deps/v8_inspector/third_party/v8_inspector/platform/'
'v8_inspector/v8_inspector.gyp:v8_inspector_stl',
'v8_inspector_compress_protocol_json#host',
],
'include_dirs': [
'deps/v8_inspector/third_party/v8_inspector',
@ -651,6 +652,34 @@
} ]
]
},
{
'target_name': 'v8_inspector_compress_protocol_json',
'type': 'none',
'toolsets': ['host'],
'conditions': [
[ 'v8_inspector=="true"', {
'actions': [
{
'action_name': 'v8_inspector_compress_protocol_json',
'process_outputs_as_sources': 1,
'inputs': [
'deps/v8_inspector/third_party/'
'v8_inspector/platform/v8_inspector/js_protocol.json',
],
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/v8_inspector_protocol_json.h',
],
'action': [
'python',
'tools/compress_json.py',
'<@(_inputs)',
'<@(_outputs)',
],
},
],
}],
],
},
{
'target_name': 'node_js2c',
'type': 'none',

28
src/inspector_agent.cc

@ -8,6 +8,7 @@
#include "node_version.h"
#include "v8-platform.h"
#include "util.h"
#include "zlib.h"
#include "platform/v8_inspector/public/InspectorVersion.h"
#include "platform/v8_inspector/public/V8Inspector.h"
@ -41,6 +42,10 @@ const char TAG_DISCONNECT[] = "#disconnect";
const char DEVTOOLS_PATH[] = "/node";
const char DEVTOOLS_HASH[] = V8_INSPECTOR_REVISION;
static const uint8_t PROTOCOL_JSON[] = {
#include "v8_inspector_protocol_json.h" // NOLINT(build/include_order)
};
void PrintDebuggerReadyMessage(int port) {
fprintf(stderr, "Debugger listening on port %d.\n"
"Warning: This is an experimental feature and could change at any time.\n"
@ -161,6 +166,27 @@ void SendTargentsListResponse(InspectorSocket* socket,
SendHttpResponse(socket, buffer.data(), len);
}
void SendProtocolJson(InspectorSocket* socket) {
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
CHECK_EQ(Z_OK, inflateInit(&strm));
static const size_t kDecompressedSize =
PROTOCOL_JSON[0] * 0x10000u +
PROTOCOL_JSON[1] * 0x100u +
PROTOCOL_JSON[2];
strm.next_in = PROTOCOL_JSON + 3;
strm.avail_in = sizeof(PROTOCOL_JSON) - 3;
std::vector<char> data(kDecompressedSize);
strm.next_out = reinterpret_cast<Byte*>(&data[0]);
strm.avail_out = data.size();
CHECK_EQ(Z_STREAM_END, inflate(&strm, Z_FINISH));
CHECK_EQ(0, strm.avail_out);
CHECK_EQ(Z_OK, inflateEnd(&strm));
SendHttpResponse(socket, &data[0], data.size());
}
const char* match_path_segment(const char* path, const char* expected) {
size_t len = strlen(expected);
if (StringEqualNoCaseN(path, expected, len)) {
@ -179,6 +205,8 @@ bool RespondToGet(InspectorSocket* socket, const std::string& script_name_,
if (match_path_segment(command, "list") || command[0] == '\0') {
SendTargentsListResponse(socket, script_name_, script_path_, port);
} else if (match_path_segment(command, "protocol")) {
SendProtocolJson(socket);
} else if (match_path_segment(command, "version")) {
SendVersionResponse(socket);
} else {

1
test/common.js

@ -16,6 +16,7 @@ exports.testDir = __dirname;
exports.fixturesDir = path.join(exports.testDir, 'fixtures');
exports.libDir = path.join(exports.testDir, '../lib');
exports.tmpDirName = 'tmp';
// PORT should match the definition in test/testpy/__init__.py.
exports.PORT = +process.env.NODE_COMMON_PORT || 12346;
exports.isWindows = process.platform === 'win32';
exports.isWOW64 = exports.isWindows &&

22
test/parallel/test-v8-inspector-json-protocol.js

@ -0,0 +1,22 @@
// Flags: --inspect={PORT}
'use strict';
const common = require('../common');
const assert = require('assert');
const http = require('http');
const options = {
path: '/json/protocol',
port: common.PORT,
host: common.localhostIPv4,
};
http.get(options, common.mustCall((res) => {
let body = '';
res.setEncoding('utf8');
res.on('data', (data) => body += data);
res.on('end', common.mustCall(() => {
assert(body.length > 0);
assert.deepStrictEqual(JSON.stringify(JSON.parse(body)), body);
}));
}));

5
test/testpy/__init__.py

@ -61,7 +61,10 @@ class SimpleTestCase(test.TestCase):
source = open(self.file).read()
flags_match = FLAGS_PATTERN.search(source)
if flags_match:
result += flags_match.group(1).strip().split()
# PORT should match the definition in test/common.js.
env = { 'PORT': int(os.getenv('NODE_COMMON_PORT', '12346')) }
env['PORT'] += self.thread_id * 100
result += flags_match.group(1).strip().format(**env).split()
files_match = FILES_PATTERN.search(source);
additional_files = []
if files_match:

25
tools/compress_json.py

@ -0,0 +1,25 @@
#!/usr/bin/env python
import json
import struct
import sys
import zlib
if __name__ == '__main__':
fp = open(sys.argv[1])
obj = json.load(fp)
text = json.dumps(obj, separators=(',', ':'))
data = zlib.compress(text, zlib.Z_BEST_COMPRESSION)
# To make decompression a little easier, we prepend the compressed data
# with the size of the uncompressed data as a 24 bits BE unsigned integer.
assert len(text) < 1 << 24, 'Uncompressed JSON must be < 16 MB.'
data = struct.pack('>I', len(text))[1:4] + data
step = 20
slices = (data[i:i+step] for i in xrange(0, len(data), step))
slices = map(lambda s: ','.join(str(ord(c)) for c in s), slices)
text = ',\n'.join(slices)
fp = open(sys.argv[2], 'w')
fp.write(text)
Loading…
Cancel
Save