Commit e350e84a authored by Johannes Henkel's avatar Johannes Henkel Committed by Commit Bot

[DevTools] Roll inspector_protocol (V8).

New Revision: d48ba2079ffcdaf2d99f4153127aab6dbe32a954

Change-Id: Idde7388b4f92492609c1714fc003ec3234c8bf82
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1686451
Auto-Submit: Johannes Henkel <johannes@chromium.org>
Reviewed-by: 's avatarAlexei Filippov <alph@chromium.org>
Commit-Queue: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62503}
parent 39eab44d
...@@ -15,8 +15,8 @@ https://cs.chromium.org/chromium/src/v8/third_party/inspector_protocol/ ...@@ -15,8 +15,8 @@ https://cs.chromium.org/chromium/src/v8/third_party/inspector_protocol/
See also [Contributing to Chrome Devtools Protocol](https://docs.google.com/document/d/1c-COD2kaK__5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit). See also [Contributing to Chrome Devtools Protocol](https://docs.google.com/document/d/1c-COD2kaK__5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit).
We're working on enabling standalone builds for parts of this package for We're working on enabling standalone builds for parts of this package for
testing and development, please feel free to ignore this for now. testing and development.
But, if you're familiar with If you're familiar with
[Chromium's development process](https://www.chromium.org/developers/contributing-code) [Chromium's development process](https://www.chromium.org/developers/contributing-code)
and have the depot_tools installed, you may use these commands and have the depot_tools installed, you may use these commands
to fetch the package (and dependencies) and build and run the tests: to fetch the package (and dependencies) and build and run the tests:
...@@ -24,8 +24,9 @@ to fetch the package (and dependencies) and build and run the tests: ...@@ -24,8 +24,9 @@ to fetch the package (and dependencies) and build and run the tests:
fetch inspector_protocol fetch inspector_protocol
cd src cd src
gn gen out/Release gn gen out/Release
ninja -C out/Release json_parser_test ninja -C out/Release encoding_test bindings_test
out/Release/json_parser_test out/Release/encoding_test
out/Release/bindings_test
You'll probably also need to install g++, since Clang uses this to find the You'll probably also need to install g++, since Clang uses this to find the
standard C++ headers. E.g., standard C++ headers. E.g.,
......
...@@ -2,7 +2,7 @@ Name: inspector protocol ...@@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/ URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0 Version: 0
Revision: aec57d43b6a2c41c37fb0a2507108e89a9342177 Revision: 373efb7fe33a7ae84038868ed08b9f1bd328b55d
License: BSD License: BSD
License File: LICENSE License File: LICENSE
Security Critical: no Security Critical: no
......
...@@ -7,33 +7,36 @@ import os.path ...@@ -7,33 +7,36 @@ import os.path
import sys import sys
try: try:
import json import json
except ImportError: except ImportError:
import simplejson as json import simplejson as json
import pdl import pdl
def main(argv): def main(argv):
if len(argv) < 1: if len(argv) < 1:
sys.stderr.write("Usage: %s <protocol-1> [<protocol-2> [, <protocol-3>...]] <output-file>\n" % sys.argv[0]) sys.stderr.write(
return 1 "Usage: %s <protocol-1> [<protocol-2> [, <protocol-3>...]] "
"<output-file>\n" % sys.argv[0])
domains = [] return 1
version = None
for protocol in argv[:-1]: domains = []
file_name = os.path.normpath(protocol) version = None
if not os.path.isfile(file_name): for protocol in argv[:-1]:
sys.stderr.write("Cannot find %s\n" % file_name) file_name = os.path.normpath(protocol)
return 1 if not os.path.isfile(file_name):
input_file = open(file_name, "r") sys.stderr.write("Cannot find %s\n" % file_name)
parsed_json = pdl.loads(input_file.read(), file_name) return 1
domains += parsed_json["domains"] input_file = open(file_name, "r")
version = parsed_json["version"] parsed_json = pdl.loads(input_file.read(), file_name)
domains += parsed_json["domains"]
output_file = open(argv[-1], "w") version = parsed_json["version"]
json.dump({"version": version, "domains": domains}, output_file, indent=4, sort_keys=False, separators=(',', ': '))
output_file.close() output_file = open(argv[-1], "w")
json.dump({"version": version, "domains": domains}, output_file,
indent=4, sort_keys=False, separators=(',', ': '))
output_file.close()
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main(sys.argv[1:])) sys.exit(main(sys.argv[1:]))
...@@ -1370,7 +1370,7 @@ class JSONEncoder : public StreamingParserHandler { ...@@ -1370,7 +1370,7 @@ class JSONEncoder : public StreamingParserHandler {
// If we have enough bytes in our input, decode the remaining ones // If we have enough bytes in our input, decode the remaining ones
// belonging to this Unicode character into |codepoint|. // belonging to this Unicode character into |codepoint|.
if (ii + num_bytes_left > chars.size()) if (ii + num_bytes_left >= chars.size())
continue; continue;
while (num_bytes_left > 0) { while (num_bytes_left > 0) {
c = chars[++ii]; c = chars[++ii];
......
...@@ -1366,6 +1366,32 @@ TEST(JsonEncoder, OverlongEncodings) { ...@@ -1366,6 +1366,32 @@ TEST(JsonEncoder, OverlongEncodings) {
EXPECT_EQ("\"\"", out); // Empty string means that 0x7f was rejected (good). EXPECT_EQ("\"\"", out); // Empty string means that 0x7f was rejected (good).
} }
TEST(JsonEncoder, IncompleteUtf8Sequence) {
std::string out;
Status status;
std::unique_ptr<StreamingParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleArrayBegin(); // This emits [, which starts an array.
{ // 🌎 takes four bytes to encode in UTF-8. We test with the first three;
// This means we're trying to emit a string that consists solely of an
// incomplete UTF-8 sequence. So the string in the JSON output is emtpy.
std::string world_utf8 = "🌎";
ASSERT_EQ(4u, world_utf8.size());
std::vector<uint8_t> chars(world_utf8.begin(), world_utf8.begin() + 3);
writer->HandleString8(SpanFrom(chars));
EXPECT_EQ("[\"\"", out); // Incomplete sequence rejected: empty string.
}
{ // This time, the incomplete sequence is at the end of the string.
std::string msg = "Hello, \xF0\x9F\x8C";
std::vector<uint8_t> chars(msg.begin(), msg.end());
writer->HandleString8(SpanFrom(chars));
EXPECT_EQ("[\"\",\"Hello, \"", out); // Incomplete sequence dropped at end.
}
}
TEST(JsonStdStringWriterTest, HelloWorld) { TEST(JsonStdStringWriterTest, HelloWorld) {
std::string out; std::string out;
Status status; Status status;
......
...@@ -12,160 +12,167 @@ import sys ...@@ -12,160 +12,167 @@ import sys
description = '' description = ''
primitiveTypes = ['integer', 'number', 'boolean', 'string', 'object', 'any', 'array', 'binary'] primitiveTypes = ['integer', 'number', 'boolean', 'string', 'object',
'any', 'array', 'binary']
def assignType(item, type, is_array=False, map_binary_to_string=False): def assignType(item, type, is_array=False, map_binary_to_string=False):
if is_array: if is_array:
item['type'] = 'array' item['type'] = 'array'
item['items'] = collections.OrderedDict() item['items'] = collections.OrderedDict()
assignType(item['items'], type, False, map_binary_to_string) assignType(item['items'], type, False, map_binary_to_string)
return return
if type == 'enum': if type == 'enum':
type = 'string' type = 'string'
if map_binary_to_string and type == 'binary': if map_binary_to_string and type == 'binary':
type = 'string' type = 'string'
if type in primitiveTypes: if type in primitiveTypes:
item['type'] = type item['type'] = type
else: else:
item['$ref'] = type item['$ref'] = type
def createItem(d, experimental, deprecated, name=None): def createItem(d, experimental, deprecated, name=None):
result = collections.OrderedDict(d) result = collections.OrderedDict(d)
if name: if name:
result['name'] = name result['name'] = name
global description global description
if description: if description:
result['description'] = description.strip() result['description'] = description.strip()
if experimental: if experimental:
result['experimental'] = True result['experimental'] = True
if deprecated: if deprecated:
result['deprecated'] = True result['deprecated'] = True
return result return result
def parse(data, file_name, map_binary_to_string=False): def parse(data, file_name, map_binary_to_string=False):
protocol = collections.OrderedDict() protocol = collections.OrderedDict()
protocol['version'] = collections.OrderedDict() protocol['version'] = collections.OrderedDict()
protocol['domains'] = [] protocol['domains'] = []
domain = None domain = None
item = None item = None
subitems = None subitems = None
nukeDescription = False nukeDescription = False
global description global description
lines = data.split('\n') lines = data.split('\n')
for i in range(0, len(lines)): for i in range(0, len(lines)):
if nukeDescription: if nukeDescription:
description = '' description = ''
nukeDescription = False nukeDescription = False
line = lines[i] line = lines[i]
trimLine = line.strip() trimLine = line.strip()
if trimLine.startswith('#'): if trimLine.startswith('#'):
if len(description): if len(description):
description += '\n' description += '\n'
description += trimLine[2:] description += trimLine[2:]
continue continue
else:
nukeDescription = True
if len(trimLine) == 0:
continue
match = re.compile(
r'^(experimental )?(deprecated )?domain (.*)').match(line)
if match:
domain = createItem({'domain' : match.group(3)}, match.group(1),
match.group(2))
protocol['domains'].append(domain)
continue
match = re.compile(r'^ depends on ([^\s]+)').match(line)
if match:
if 'dependencies' not in domain:
domain['dependencies'] = []
domain['dependencies'].append(match.group(1))
continue
match = re.compile(r'^ (experimental )?(deprecated )?type (.*) '
r'extends (array of )?([^\s]+)').match(line)
if match:
if 'types' not in domain:
domain['types'] = []
item = createItem({'id': match.group(3)}, match.group(1), match.group(2))
assignType(item, match.group(5), match.group(4), map_binary_to_string)
domain['types'].append(item)
continue
match = re.compile(
r'^ (experimental )?(deprecated )?(command|event) (.*)').match(line)
if match:
list = []
if match.group(3) == 'command':
if 'commands' in domain:
list = domain['commands']
else:
list = domain['commands'] = []
else:
if 'events' in domain:
list = domain['events']
else: else:
nukeDescription = True list = domain['events'] = []
if len(trimLine) == 0: item = createItem({}, match.group(1), match.group(2), match.group(4))
continue list.append(item)
continue
match = re.compile(r'^(experimental )?(deprecated )?domain (.*)').match(line)
if match: match = re.compile(
domain = createItem({'domain' : match.group(3)}, match.group(1), match.group(2)) r'^ (experimental )?(deprecated )?(optional )?'
protocol['domains'].append(domain) r'(array of )?([^\s]+) ([^\s]+)').match(line)
continue if match:
param = createItem({}, match.group(1), match.group(2), match.group(6))
match = re.compile(r'^ depends on ([^\s]+)').match(line) if match.group(3):
if match: param['optional'] = True
if 'dependencies' not in domain: assignType(param, match.group(5), match.group(4), map_binary_to_string)
domain['dependencies'] = [] if match.group(5) == 'enum':
domain['dependencies'].append(match.group(1)) enumliterals = param['enum'] = []
continue subitems.append(param)
continue
match = re.compile(r'^ (experimental )?(deprecated )?type (.*) extends (array of )?([^\s]+)').match(line)
if match: match = re.compile(r'^ (parameters|returns|properties)').match(line)
if 'types' not in domain: if match:
domain['types'] = [] subitems = item[match.group(1)] = []
item = createItem({'id': match.group(3)}, match.group(1), match.group(2)) continue
assignType(item, match.group(5), match.group(4), map_binary_to_string)
domain['types'].append(item) match = re.compile(r'^ enum').match(line)
continue if match:
enumliterals = item['enum'] = []
match = re.compile(r'^ (experimental )?(deprecated )?(command|event) (.*)').match(line) continue
if match:
list = [] match = re.compile(r'^version').match(line)
if match.group(3) == 'command': if match:
if 'commands' in domain: continue
list = domain['commands']
else: match = re.compile(r'^ major (\d+)').match(line)
list = domain['commands'] = [] if match:
else: protocol['version']['major'] = match.group(1)
if 'events' in domain: continue
list = domain['events']
else: match = re.compile(r'^ minor (\d+)').match(line)
list = domain['events'] = [] if match:
protocol['version']['minor'] = match.group(1)
item = createItem({}, match.group(1), match.group(2), match.group(4)) continue
list.append(item)
continue match = re.compile(r'^ redirect ([^\s]+)').match(line)
if match:
match = re.compile(r'^ (experimental )?(deprecated )?(optional )?(array of )?([^\s]+) ([^\s]+)').match(line) item['redirect'] = match.group(1)
if match: continue
param = createItem({}, match.group(1), match.group(2), match.group(6))
if match.group(3): match = re.compile(r'^ ( )?[^\s]+$').match(line)
param['optional'] = True if match:
assignType(param, match.group(5), match.group(4), map_binary_to_string) # enum literal
if match.group(5) == 'enum': enumliterals.append(trimLine)
enumliterals = param['enum'] = [] continue
subitems.append(param)
continue print('Error in %s:%s, illegal token: \t%s' % (file_name, i, line))
sys.exit(1)
match = re.compile(r'^ (parameters|returns|properties)').match(line) return protocol
if match:
subitems = item[match.group(1)] = []
continue
match = re.compile(r'^ enum').match(line)
if match:
enumliterals = item['enum'] = []
continue
match = re.compile(r'^version').match(line)
if match:
continue
match = re.compile(r'^ major (\d+)').match(line)
if match:
protocol['version']['major'] = match.group(1)
continue
match = re.compile(r'^ minor (\d+)').match(line)
if match:
protocol['version']['minor'] = match.group(1)
continue
match = re.compile(r'^ redirect ([^\s]+)').match(line)
if match:
item['redirect'] = match.group(1)
continue
match = re.compile(r'^ ( )?[^\s]+$').match(line)
if match:
# enum literal
enumliterals.append(trimLine)
continue
print('Error in %s:%s, illegal token: \t%s' % (file_name, i, line))
sys.exit(1)
return protocol
def loads(data, file_name, map_binary_to_string=False): def loads(data, file_name, map_binary_to_string=False):
if file_name.endswith(".pdl"): if file_name.endswith(".pdl"):
return parse(data, file_name, map_binary_to_string) return parse(data, file_name, map_binary_to_string)
return json.loads(data) return json.loads(data)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment