mirror of
https://github.com/nodejs/node.git
synced 2025-05-07 23:52:40 +00:00
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>
This commit is contained in:
parent
a8d2c9d775
commit
782620f03f
4
deps/zlib/zlib.gyp
vendored
4
deps/zlib/zlib.gyp
vendored
@ -12,6 +12,7 @@
|
|||||||
{
|
{
|
||||||
'target_name': 'zlib',
|
'target_name': 'zlib',
|
||||||
'type': 'static_library',
|
'type': 'static_library',
|
||||||
|
'defines': [ 'ZLIB_CONST' ],
|
||||||
'sources': [
|
'sources': [
|
||||||
'adler32.c',
|
'adler32.c',
|
||||||
'compress.c',
|
'compress.c',
|
||||||
@ -44,6 +45,7 @@
|
|||||||
'.',
|
'.',
|
||||||
],
|
],
|
||||||
'direct_dependent_settings': {
|
'direct_dependent_settings': {
|
||||||
|
'defines': [ 'ZLIB_CONST' ],
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'.',
|
'.',
|
||||||
],
|
],
|
||||||
@ -72,10 +74,12 @@
|
|||||||
'direct_dependent_settings': {
|
'direct_dependent_settings': {
|
||||||
'defines': [
|
'defines': [
|
||||||
'USE_SYSTEM_ZLIB',
|
'USE_SYSTEM_ZLIB',
|
||||||
|
'ZLIB_CONST',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'defines': [
|
'defines': [
|
||||||
'USE_SYSTEM_ZLIB',
|
'USE_SYSTEM_ZLIB',
|
||||||
|
'ZLIB_CONST',
|
||||||
],
|
],
|
||||||
'link_settings': {
|
'link_settings': {
|
||||||
'libraries': [
|
'libraries': [
|
||||||
|
29
node.gyp
29
node.gyp
@ -323,6 +323,7 @@
|
|||||||
'dependencies': [
|
'dependencies': [
|
||||||
'deps/v8_inspector/third_party/v8_inspector/platform/'
|
'deps/v8_inspector/third_party/v8_inspector/platform/'
|
||||||
'v8_inspector/v8_inspector.gyp:v8_inspector_stl',
|
'v8_inspector/v8_inspector.gyp:v8_inspector_stl',
|
||||||
|
'v8_inspector_compress_protocol_json#host',
|
||||||
],
|
],
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'deps/v8_inspector/third_party/v8_inspector',
|
'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',
|
'target_name': 'node_js2c',
|
||||||
'type': 'none',
|
'type': 'none',
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "node_version.h"
|
#include "node_version.h"
|
||||||
#include "v8-platform.h"
|
#include "v8-platform.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "zlib.h"
|
||||||
|
|
||||||
#include "platform/v8_inspector/public/InspectorVersion.h"
|
#include "platform/v8_inspector/public/InspectorVersion.h"
|
||||||
#include "platform/v8_inspector/public/V8Inspector.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_PATH[] = "/node";
|
||||||
const char DEVTOOLS_HASH[] = V8_INSPECTOR_REVISION;
|
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) {
|
void PrintDebuggerReadyMessage(int port) {
|
||||||
fprintf(stderr, "Debugger listening on port %d.\n"
|
fprintf(stderr, "Debugger listening on port %d.\n"
|
||||||
"Warning: This is an experimental feature and could change at any time.\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);
|
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) {
|
const char* match_path_segment(const char* path, const char* expected) {
|
||||||
size_t len = strlen(expected);
|
size_t len = strlen(expected);
|
||||||
if (StringEqualNoCaseN(path, expected, len)) {
|
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') {
|
if (match_path_segment(command, "list") || command[0] == '\0') {
|
||||||
SendTargentsListResponse(socket, script_name_, script_path_, port);
|
SendTargentsListResponse(socket, script_name_, script_path_, port);
|
||||||
|
} else if (match_path_segment(command, "protocol")) {
|
||||||
|
SendProtocolJson(socket);
|
||||||
} else if (match_path_segment(command, "version")) {
|
} else if (match_path_segment(command, "version")) {
|
||||||
SendVersionResponse(socket);
|
SendVersionResponse(socket);
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,6 +16,7 @@ exports.testDir = __dirname;
|
|||||||
exports.fixturesDir = path.join(exports.testDir, 'fixtures');
|
exports.fixturesDir = path.join(exports.testDir, 'fixtures');
|
||||||
exports.libDir = path.join(exports.testDir, '../lib');
|
exports.libDir = path.join(exports.testDir, '../lib');
|
||||||
exports.tmpDirName = 'tmp';
|
exports.tmpDirName = 'tmp';
|
||||||
|
// PORT should match the definition in test/testpy/__init__.py.
|
||||||
exports.PORT = +process.env.NODE_COMMON_PORT || 12346;
|
exports.PORT = +process.env.NODE_COMMON_PORT || 12346;
|
||||||
exports.isWindows = process.platform === 'win32';
|
exports.isWindows = process.platform === 'win32';
|
||||||
exports.isWOW64 = exports.isWindows &&
|
exports.isWOW64 = exports.isWindows &&
|
||||||
|
22
test/parallel/test-v8-inspector-json-protocol.js
Normal file
22
test/parallel/test-v8-inspector-json-protocol.js
Normal file
@ -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);
|
||||||
|
}));
|
||||||
|
}));
|
@ -61,7 +61,10 @@ class SimpleTestCase(test.TestCase):
|
|||||||
source = open(self.file).read()
|
source = open(self.file).read()
|
||||||
flags_match = FLAGS_PATTERN.search(source)
|
flags_match = FLAGS_PATTERN.search(source)
|
||||||
if flags_match:
|
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);
|
files_match = FILES_PATTERN.search(source);
|
||||||
additional_files = []
|
additional_files = []
|
||||||
if files_match:
|
if files_match:
|
||||||
|
25
tools/compress_json.py
Normal file
25
tools/compress_json.py
Normal file
@ -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…
Reference in New Issue
Block a user