diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-02-14 11:27:26 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-02-22 15:55:42 +0100 |
commit | 7a77daf24344db7942e34c962b0f1ee729ab7af5 (patch) | |
tree | e7cbe7bf4e2f4b802a8f5bc18336c546cd6a0d7f /deps/v8/third_party/inspector_protocol | |
parent | 5f08871ee93ea739148cc49e0f7679e33c70295a (diff) | |
download | android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.gz android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.bz2 android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.zip |
deps: update V8 to 5.6.326.55
PR-URL: https://github.com/nodejs/node/pull/10992
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/third_party/inspector_protocol')
30 files changed, 4236 insertions, 0 deletions
diff --git a/deps/v8/third_party/inspector_protocol/CheckProtocolCompatibility.py b/deps/v8/third_party/inspector_protocol/CheckProtocolCompatibility.py new file mode 100755 index 0000000000..dd9acad898 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/CheckProtocolCompatibility.py @@ -0,0 +1,479 @@ +#!/usr/bin/env python +# Copyright (c) 2011 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Inspector protocol validator. +# +# Tests that subsequent protocol changes are not breaking backwards compatibility. +# Following violations are reported: +# +# - Domain has been removed +# - Command has been removed +# - Required command parameter was added or changed from optional +# - Required response parameter was removed or changed to optional +# - Event has been removed +# - Required event parameter was removed or changed to optional +# - Parameter type has changed. +# +# For the parameters with composite types the above checks are also applied +# recursively to every property of the type. +# +# Adding --show_changes to the command line prints out a list of valid public API changes. + +import copy +import os.path +import optparse +import sys + +try: + import json +except ImportError: + import simplejson as json + + +def list_to_map(items, key): + result = {} + for item in items: + if "experimental" not in item and "hidden" not in item: + result[item[key]] = item + return result + + +def named_list_to_map(container, name, key): + if name in container: + return list_to_map(container[name], key) + return {} + + +def removed(reverse): + if reverse: + return "added" + return "removed" + + +def required(reverse): + if reverse: + return "optional" + return "required" + + +def compare_schemas(d_1, d_2, reverse): + errors = [] + domains_1 = copy.deepcopy(d_1) + domains_2 = copy.deepcopy(d_2) + types_1 = normalize_types_in_schema(domains_1) + types_2 = normalize_types_in_schema(domains_2) + + domains_by_name_1 = list_to_map(domains_1, "domain") + domains_by_name_2 = list_to_map(domains_2, "domain") + + for name in domains_by_name_1: + domain_1 = domains_by_name_1[name] + if name not in domains_by_name_2: + errors.append("%s: domain has been %s" % (name, removed(reverse))) + continue + compare_domains(domain_1, domains_by_name_2[name], types_1, types_2, errors, reverse) + return errors + + +def compare_domains(domain_1, domain_2, types_map_1, types_map_2, errors, reverse): + domain_name = domain_1["domain"] + commands_1 = named_list_to_map(domain_1, "commands", "name") + commands_2 = named_list_to_map(domain_2, "commands", "name") + for name in commands_1: + command_1 = commands_1[name] + if name not in commands_2: + errors.append("%s.%s: command has been %s" % (domain_1["domain"], name, removed(reverse))) + continue + compare_commands(domain_name, command_1, commands_2[name], types_map_1, types_map_2, errors, reverse) + + events_1 = named_list_to_map(domain_1, "events", "name") + events_2 = named_list_to_map(domain_2, "events", "name") + for name in events_1: + event_1 = events_1[name] + if name not in events_2: + errors.append("%s.%s: event has been %s" % (domain_1["domain"], name, removed(reverse))) + continue + compare_events(domain_name, event_1, events_2[name], types_map_1, types_map_2, errors, reverse) + + +def compare_commands(domain_name, command_1, command_2, types_map_1, types_map_2, errors, reverse): + context = domain_name + "." + command_1["name"] + + params_1 = named_list_to_map(command_1, "parameters", "name") + params_2 = named_list_to_map(command_2, "parameters", "name") + # Note the reversed order: we allow removing but forbid adding parameters. + compare_params_list(context, "parameter", params_2, params_1, types_map_2, types_map_1, 0, errors, not reverse) + + returns_1 = named_list_to_map(command_1, "returns", "name") + returns_2 = named_list_to_map(command_2, "returns", "name") + compare_params_list(context, "response parameter", returns_1, returns_2, types_map_1, types_map_2, 0, errors, reverse) + + +def compare_events(domain_name, event_1, event_2, types_map_1, types_map_2, errors, reverse): + context = domain_name + "." + event_1["name"] + params_1 = named_list_to_map(event_1, "parameters", "name") + params_2 = named_list_to_map(event_2, "parameters", "name") + compare_params_list(context, "parameter", params_1, params_2, types_map_1, types_map_2, 0, errors, reverse) + + +def compare_params_list(context, kind, params_1, params_2, types_map_1, types_map_2, depth, errors, reverse): + for name in params_1: + param_1 = params_1[name] + if name not in params_2: + if "optional" not in param_1: + errors.append("%s.%s: required %s has been %s" % (context, name, kind, removed(reverse))) + continue + + param_2 = params_2[name] + if param_2 and "optional" in param_2 and "optional" not in param_1: + errors.append("%s.%s: %s %s is now %s" % (context, name, required(reverse), kind, required(not reverse))) + continue + type_1 = extract_type(param_1, types_map_1, errors) + type_2 = extract_type(param_2, types_map_2, errors) + compare_types(context + "." + name, kind, type_1, type_2, types_map_1, types_map_2, depth, errors, reverse) + + +def compare_types(context, kind, type_1, type_2, types_map_1, types_map_2, depth, errors, reverse): + if depth > 10: + return + + base_type_1 = type_1["type"] + base_type_2 = type_2["type"] + + if base_type_1 != base_type_2: + errors.append("%s: %s base type mismatch, '%s' vs '%s'" % (context, kind, base_type_1, base_type_2)) + elif base_type_1 == "object": + params_1 = named_list_to_map(type_1, "properties", "name") + params_2 = named_list_to_map(type_2, "properties", "name") + # If both parameters have the same named type use it in the context. + if "id" in type_1 and "id" in type_2 and type_1["id"] == type_2["id"]: + type_name = type_1["id"] + else: + type_name = "<object>" + context += " %s->%s" % (kind, type_name) + compare_params_list(context, "property", params_1, params_2, types_map_1, types_map_2, depth + 1, errors, reverse) + elif base_type_1 == "array": + item_type_1 = extract_type(type_1["items"], types_map_1, errors) + item_type_2 = extract_type(type_2["items"], types_map_2, errors) + compare_types(context, kind, item_type_1, item_type_2, types_map_1, types_map_2, depth + 1, errors, reverse) + + +def extract_type(typed_object, types_map, errors): + if "type" in typed_object: + result = {"id": "<transient>", "type": typed_object["type"]} + if typed_object["type"] == "object": + result["properties"] = [] + elif typed_object["type"] == "array": + result["items"] = typed_object["items"] + return result + elif "$ref" in typed_object: + ref = typed_object["$ref"] + if ref not in types_map: + errors.append("Can not resolve type: %s" % ref) + types_map[ref] = {"id": "<transient>", "type": "object"} + return types_map[ref] + + +def normalize_types_in_schema(domains): + types = {} + for domain in domains: + domain_name = domain["domain"] + normalize_types(domain, domain_name, types) + return types + + +def normalize_types(obj, domain_name, types): + if isinstance(obj, list): + for item in obj: + normalize_types(item, domain_name, types) + elif isinstance(obj, dict): + for key, value in obj.items(): + if key == "$ref" and value.find(".") == -1: + obj[key] = "%s.%s" % (domain_name, value) + elif key == "id": + obj[key] = "%s.%s" % (domain_name, value) + types[obj[key]] = obj + else: + normalize_types(value, domain_name, types) + + +def load_schema(file_name, domains): + # pylint: disable=W0613 + if not os.path.isfile(file_name): + return + input_file = open(file_name, "r") + json_string = input_file.read() + parsed_json = json.loads(json_string) + domains += parsed_json["domains"] + return parsed_json["version"] + + +def self_test(): + def create_test_schema_1(): + return [ + { + "domain": "Network", + "types": [ + { + "id": "LoaderId", + "type": "string" + }, + { + "id": "Headers", + "type": "object" + }, + { + "id": "Request", + "type": "object", + "properties": [ + {"name": "url", "type": "string"}, + {"name": "method", "type": "string"}, + {"name": "headers", "$ref": "Headers"}, + {"name": "becameOptionalField", "type": "string"}, + {"name": "removedField", "type": "string"}, + ] + } + ], + "commands": [ + { + "name": "removedCommand", + }, + { + "name": "setExtraHTTPHeaders", + "parameters": [ + {"name": "headers", "$ref": "Headers"}, + {"name": "mismatched", "type": "string"}, + {"name": "becameOptional", "$ref": "Headers"}, + {"name": "removedRequired", "$ref": "Headers"}, + {"name": "becameRequired", "$ref": "Headers", "optional": True}, + {"name": "removedOptional", "$ref": "Headers", "optional": True}, + ], + "returns": [ + {"name": "mimeType", "type": "string"}, + {"name": "becameOptional", "type": "string"}, + {"name": "removedRequired", "type": "string"}, + {"name": "becameRequired", "type": "string", "optional": True}, + {"name": "removedOptional", "type": "string", "optional": True}, + ] + } + ], + "events": [ + { + "name": "requestWillBeSent", + "parameters": [ + {"name": "frameId", "type": "string", "experimental": True}, + {"name": "request", "$ref": "Request"}, + {"name": "becameOptional", "type": "string"}, + {"name": "removedRequired", "type": "string"}, + {"name": "becameRequired", "type": "string", "optional": True}, + {"name": "removedOptional", "type": "string", "optional": True}, + ] + }, + { + "name": "removedEvent", + "parameters": [ + {"name": "errorText", "type": "string"}, + {"name": "canceled", "type": "boolean", "optional": True} + ] + } + ] + }, + { + "domain": "removedDomain" + } + ] + + def create_test_schema_2(): + return [ + { + "domain": "Network", + "types": [ + { + "id": "LoaderId", + "type": "string" + }, + { + "id": "Request", + "type": "object", + "properties": [ + {"name": "url", "type": "string"}, + {"name": "method", "type": "string"}, + {"name": "headers", "type": "object"}, + {"name": "becameOptionalField", "type": "string", "optional": True}, + ] + } + ], + "commands": [ + { + "name": "addedCommand", + }, + { + "name": "setExtraHTTPHeaders", + "parameters": [ + {"name": "headers", "type": "object"}, + {"name": "mismatched", "type": "object"}, + {"name": "becameOptional", "type": "object", "optional": True}, + {"name": "addedRequired", "type": "object"}, + {"name": "becameRequired", "type": "object"}, + {"name": "addedOptional", "type": "object", "optional": True}, + ], + "returns": [ + {"name": "mimeType", "type": "string"}, + {"name": "becameOptional", "type": "string", "optional": True}, + {"name": "addedRequired", "type": "string"}, + {"name": "becameRequired", "type": "string"}, + {"name": "addedOptional", "type": "string", "optional": True}, + ] + } + ], + "events": [ + { + "name": "requestWillBeSent", + "parameters": [ + {"name": "request", "$ref": "Request"}, + {"name": "becameOptional", "type": "string", "optional": True}, + {"name": "addedRequired", "type": "string"}, + {"name": "becameRequired", "type": "string"}, + {"name": "addedOptional", "type": "string", "optional": True}, + ] + }, + { + "name": "addedEvent" + } + ] + }, + { + "domain": "addedDomain" + } + ] + + expected_errors = [ + "removedDomain: domain has been removed", + "Network.removedCommand: command has been removed", + "Network.removedEvent: event has been removed", + "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'object' vs 'string'", + "Network.setExtraHTTPHeaders.addedRequired: required parameter has been added", + "Network.setExtraHTTPHeaders.becameRequired: optional parameter is now required", + "Network.setExtraHTTPHeaders.removedRequired: required response parameter has been removed", + "Network.setExtraHTTPHeaders.becameOptional: required response parameter is now optional", + "Network.requestWillBeSent.removedRequired: required parameter has been removed", + "Network.requestWillBeSent.becameOptional: required parameter is now optional", + "Network.requestWillBeSent.request parameter->Network.Request.removedField: required property has been removed", + "Network.requestWillBeSent.request parameter->Network.Request.becameOptionalField: required property is now optional", + ] + + expected_errors_reverse = [ + "addedDomain: domain has been added", + "Network.addedEvent: event has been added", + "Network.addedCommand: command has been added", + "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'string' vs 'object'", + "Network.setExtraHTTPHeaders.removedRequired: required parameter has been removed", + "Network.setExtraHTTPHeaders.becameOptional: required parameter is now optional", + "Network.setExtraHTTPHeaders.addedRequired: required response parameter has been added", + "Network.setExtraHTTPHeaders.becameRequired: optional response parameter is now required", + "Network.requestWillBeSent.becameRequired: optional parameter is now required", + "Network.requestWillBeSent.addedRequired: required parameter has been added", + ] + + def is_subset(subset, superset, message): + for i in range(len(subset)): + if subset[i] not in superset: + sys.stderr.write("%s error: %s\n" % (message, subset[i])) + return False + return True + + def errors_match(expected, actual): + return (is_subset(actual, expected, "Unexpected") and + is_subset(expected, actual, "Missing")) + + return (errors_match(expected_errors, + compare_schemas(create_test_schema_1(), create_test_schema_2(), False)) and + errors_match(expected_errors_reverse, + compare_schemas(create_test_schema_2(), create_test_schema_1(), True))) + + +def load_domains_and_baselines(file_name, domains, baseline_domains): + version = load_schema(os.path.normpath(file_name), domains) + suffix = "-%s.%s.json" % (version["major"], version["minor"]) + baseline_file = file_name.replace(".json", suffix) + load_schema(os.path.normpath(baseline_file), baseline_domains) + return version + + +def main(): + if not self_test(): + sys.stderr.write("Self-test failed") + return 1 + + cmdline_parser = optparse.OptionParser() + cmdline_parser.add_option("--show_changes") + cmdline_parser.add_option("--expected_errors") + cmdline_parser.add_option("--stamp") + arg_options, arg_values = cmdline_parser.parse_args() + + if len(arg_values) < 1: + sys.stderr.write("Usage: %s [--show_changes] <protocol-1> [, <protocol-2>...]\n" % sys.argv[0]) + return 1 + + domains = [] + baseline_domains = [] + version = load_domains_and_baselines(arg_values[0], domains, baseline_domains) + for dependency in arg_values[1:]: + load_domains_and_baselines(dependency, domains, baseline_domains) + + expected_errors = [] + if arg_options.expected_errors: + expected_errors_file = open(arg_options.expected_errors, "r") + expected_errors = json.loads(expected_errors_file.read())["errors"] + expected_errors_file.close() + + errors = compare_schemas(baseline_domains, domains, False) + unexpected_errors = [] + for i in range(len(errors)): + if errors[i] not in expected_errors: + unexpected_errors.append(errors[i]) + if len(unexpected_errors) > 0: + sys.stderr.write(" Compatibility checks FAILED\n") + for error in unexpected_errors: + sys.stderr.write(" %s\n" % error) + return 1 + + if arg_options.show_changes: + changes = compare_schemas(domains, baseline_domains, True) + if len(changes) > 0: + print " Public changes since %s:" % version + for change in changes: + print " %s" % change + + if arg_options.stamp: + with open(arg_options.stamp, 'a') as _: + pass + +if __name__ == '__main__': + sys.exit(main()) diff --git a/deps/v8/third_party/inspector_protocol/CodeGenerator.py b/deps/v8/third_party/inspector_protocol/CodeGenerator.py new file mode 100644 index 0000000000..de1029e801 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/CodeGenerator.py @@ -0,0 +1,498 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os.path +import sys +import optparse +import collections +import functools +try: + import json +except ImportError: + import simplejson as json + +# Path handling for libraries and templates +# Paths have to be normalized because Jinja uses the exact template path to +# determine the hash used in the cache filename, and we need a pre-caching step +# to be concurrency-safe. Use absolute path because __file__ is absolute if +# module is imported, and relative if executed directly. +# If paths differ between pre-caching and individual file compilation, the cache +# is regenerated, which causes a race condition and breaks concurrent build, +# since some compile processes will try to read the partially written cache. +module_path, module_filename = os.path.split(os.path.realpath(__file__)) + +def read_config(): + # pylint: disable=W0703 + def json_to_object(data, output_base, config_base): + def json_object_hook(object_dict): + items = [(k, os.path.join(config_base, v) if k == "path" else v) for (k, v) in object_dict.items()] + items = [(k, os.path.join(output_base, v) if k == "output" else v) for (k, v) in items] + keys, values = zip(*items) + return collections.namedtuple('X', keys)(*values) + return json.loads(data, object_hook=json_object_hook) + + def init_defaults(config_tuple, path, defaults): + keys = list(config_tuple._fields) # pylint: disable=E1101 + values = [getattr(config_tuple, k) for k in keys] + for i in xrange(len(keys)): + if hasattr(values[i], "_fields"): + values[i] = init_defaults(values[i], path + "." + keys[i], defaults) + for optional in defaults: + if optional.find(path + ".") != 0: + continue + optional_key = optional[len(path) + 1:] + if optional_key.find(".") == -1 and optional_key not in keys: + keys.append(optional_key) + values.append(defaults[optional]) + return collections.namedtuple('X', keys)(*values) + + try: + cmdline_parser = optparse.OptionParser() + cmdline_parser.add_option("--output_base") + cmdline_parser.add_option("--jinja_dir") + cmdline_parser.add_option("--config") + arg_options, _ = cmdline_parser.parse_args() + jinja_dir = arg_options.jinja_dir + if not jinja_dir: + raise Exception("jinja directory must be specified") + output_base = arg_options.output_base + if not output_base: + raise Exception("Base output directory must be specified") + config_file = arg_options.config + if not config_file: + raise Exception("Config file name must be specified") + config_base = os.path.dirname(config_file) + except Exception: + # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html + exc = sys.exc_info()[1] + sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) + exit(1) + + try: + config_json_file = open(config_file, "r") + config_json_string = config_json_file.read() + config_partial = json_to_object(config_json_string, output_base, config_base) + config_json_file.close() + defaults = { + ".imported": False, + ".imported.export_macro": "", + ".imported.export_header": False, + ".imported.header": False, + ".imported.package": False, + ".protocol.export_macro": "", + ".protocol.export_header": False, + ".exported": False, + ".exported.export_macro": "", + ".exported.export_header": False, + ".lib": False, + ".lib.export_macro": "", + ".lib.export_header": False, + } + return (jinja_dir, config_file, init_defaults(config_partial, "", defaults)) + except Exception: + # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html + exc = sys.exc_info()[1] + sys.stderr.write("Failed to parse config file: %s\n\n" % exc) + exit(1) + + +def to_title_case(name): + return name[:1].upper() + name[1:] + + +def dash_to_camelcase(word): + prefix = "" + if word[0] == "-": + prefix = "Negative" + word = word[1:] + return prefix + "".join(to_title_case(x) or "-" for x in word.split("-")) + + +def initialize_jinja_env(jinja_dir, cache_dir): + # pylint: disable=F0401 + sys.path.insert(1, os.path.abspath(jinja_dir)) + import jinja2 + + jinja_env = jinja2.Environment( + loader=jinja2.FileSystemLoader(module_path), + # Bytecode cache is not concurrency-safe unless pre-cached: + # if pre-cached this is read-only, but writing creates a race condition. + bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir), + keep_trailing_newline=True, # newline-terminate generated files + lstrip_blocks=True, # so can indent control flow tags + trim_blocks=True) + jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase": dash_to_camelcase}) + jinja_env.add_extension("jinja2.ext.loopcontrols") + return jinja_env + + +def patch_full_qualified_refs(protocol): + def patch_full_qualified_refs_in_domain(json, domain_name): + if isinstance(json, list): + for item in json: + patch_full_qualified_refs_in_domain(item, domain_name) + + if not isinstance(json, dict): + return + for key in json: + if key == "type" and json[key] == "string": + json[key] = domain_name + ".string" + if key != "$ref": + patch_full_qualified_refs_in_domain(json[key], domain_name) + continue + if json["$ref"].find(".") == -1: + json["$ref"] = domain_name + "." + json["$ref"] + return + + for domain in protocol.json_api["domains"]: + patch_full_qualified_refs_in_domain(domain, domain["domain"]) + + +def calculate_exports(protocol): + def calculate_exports_in_json(json_value): + has_exports = False + if isinstance(json_value, list): + for item in json_value: + has_exports = calculate_exports_in_json(item) or has_exports + if isinstance(json_value, dict): + has_exports = ("exported" in json_value and json_value["exported"]) or has_exports + for key in json_value: + has_exports = calculate_exports_in_json(json_value[key]) or has_exports + return has_exports + + protocol.json_api["has_exports"] = False + for domain_json in protocol.json_api["domains"]: + domain_json["has_exports"] = calculate_exports_in_json(domain_json) + if domain_json["has_exports"] and domain_json["domain"] in protocol.generate_domains: + protocol.json_api["has_exports"] = True + + +def create_imported_type_definition(domain_name, type, imported_namespace): + # pylint: disable=W0622 + return { + "return_type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace, domain_name, type["id"]), + "pass_type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace, domain_name, type["id"]), + "to_raw_type": "%s.get()", + "to_pass_type": "std::move(%s)", + "to_rvalue": "std::move(%s)", + "type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace, domain_name, type["id"]), + "raw_type": "%s::%s::API::%s" % (imported_namespace, domain_name, type["id"]), + "raw_pass_type": "%s::%s::API::%s*" % (imported_namespace, domain_name, type["id"]), + "raw_return_type": "%s::%s::API::%s*" % (imported_namespace, domain_name, type["id"]), + } + + +def create_user_type_definition(domain_name, type): + # pylint: disable=W0622 + return { + "return_type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]), + "pass_type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]), + "to_raw_type": "%s.get()", + "to_pass_type": "std::move(%s)", + "to_rvalue": "std::move(%s)", + "type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]), + "raw_type": "protocol::%s::%s" % (domain_name, type["id"]), + "raw_pass_type": "protocol::%s::%s*" % (domain_name, type["id"]), + "raw_return_type": "protocol::%s::%s*" % (domain_name, type["id"]), + } + + +def create_object_type_definition(): + # pylint: disable=W0622 + return { + "return_type": "std::unique_ptr<protocol::DictionaryValue>", + "pass_type": "std::unique_ptr<protocol::DictionaryValue>", + "to_raw_type": "%s.get()", + "to_pass_type": "std::move(%s)", + "to_rvalue": "std::move(%s)", + "type": "std::unique_ptr<protocol::DictionaryValue>", + "raw_type": "protocol::DictionaryValue", + "raw_pass_type": "protocol::DictionaryValue*", + "raw_return_type": "protocol::DictionaryValue*", + } + + +def create_any_type_definition(): + # pylint: disable=W0622 + return { + "return_type": "std::unique_ptr<protocol::Value>", + "pass_type": "std::unique_ptr<protocol::Value>", + "to_raw_type": "%s.get()", + "to_pass_type": "std::move(%s)", + "to_rvalue": "std::move(%s)", + "type": "std::unique_ptr<protocol::Value>", + "raw_type": "protocol::Value", + "raw_pass_type": "protocol::Value*", + "raw_return_type": "protocol::Value*", + } + + +def create_string_type_definition(): + # pylint: disable=W0622 + return { + "return_type": "String", + "pass_type": "const String&", + "to_pass_type": "%s", + "to_raw_type": "%s", + "to_rvalue": "%s", + "type": "String", + "raw_type": "String", + "raw_pass_type": "const String&", + "raw_return_type": "String", + } + + +def create_primitive_type_definition(type): + # pylint: disable=W0622 + typedefs = { + "number": "double", + "integer": "int", + "boolean": "bool" + } + defaults = { + "number": "0", + "integer": "0", + "boolean": "false" + } + jsontypes = { + "number": "TypeDouble", + "integer": "TypeInteger", + "boolean": "TypeBoolean", + } + return { + "return_type": typedefs[type], + "pass_type": typedefs[type], + "to_pass_type": "%s", + "to_raw_type": "%s", + "to_rvalue": "%s", + "type": typedefs[type], + "raw_type": typedefs[type], + "raw_pass_type": typedefs[type], + "raw_return_type": typedefs[type], + "default_value": defaults[type] + } + + +def wrap_array_definition(type): + # pylint: disable=W0622 + return { + "return_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"], + "pass_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"], + "to_raw_type": "%s.get()", + "to_pass_type": "std::move(%s)", + "to_rvalue": "std::move(%s)", + "type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"], + "raw_type": "protocol::Array<%s>" % type["raw_type"], + "raw_pass_type": "protocol::Array<%s>*" % type["raw_type"], + "raw_return_type": "protocol::Array<%s>*" % type["raw_type"], + "create_type": "wrapUnique(new protocol::Array<%s>())" % type["raw_type"], + "out_type": "protocol::Array<%s>&" % type["raw_type"], + } + + +def create_type_definitions(protocol, imported_namespace): + protocol.type_definitions = {} + protocol.type_definitions["number"] = create_primitive_type_definition("number") + protocol.type_definitions["integer"] = create_primitive_type_definition("integer") + protocol.type_definitions["boolean"] = create_primitive_type_definition("boolean") + protocol.type_definitions["object"] = create_object_type_definition() + protocol.type_definitions["any"] = create_any_type_definition() + for domain in protocol.json_api["domains"]: + protocol.type_definitions[domain["domain"] + ".string"] = create_string_type_definition() + if not ("types" in domain): + continue + for type in domain["types"]: + type_name = domain["domain"] + "." + type["id"] + if type["type"] == "object" and domain["domain"] in protocol.imported_domains: + protocol.type_definitions[type_name] = create_imported_type_definition(domain["domain"], type, imported_namespace) + elif type["type"] == "object": + protocol.type_definitions[type_name] = create_user_type_definition(domain["domain"], type) + elif type["type"] == "array": + items_type = type["items"]["type"] + protocol.type_definitions[type_name] = wrap_array_definition(protocol.type_definitions[items_type]) + elif type["type"] == domain["domain"] + ".string": + protocol.type_definitions[type_name] = create_string_type_definition() + else: + protocol.type_definitions[type_name] = create_primitive_type_definition(type["type"]) + + +def type_definition(protocol, name): + return protocol.type_definitions[name] + + +def resolve_type(protocol, prop): + if "$ref" in prop: + return protocol.type_definitions[prop["$ref"]] + if prop["type"] == "array": + return wrap_array_definition(resolve_type(protocol, prop["items"])) + return protocol.type_definitions[prop["type"]] + + +def join_arrays(dict, keys): + result = [] + for key in keys: + if key in dict: + result += dict[key] + return result + + +def has_disable(commands): + for command in commands: + if command["name"] == "disable" and (not ("handlers" in command) or "renderer" in command["handlers"]): + return True + return False + + +def format_include(header): + return "\"" + header + "\"" if header[0] not in "<\"" else header + + +def read_protocol_file(file_name, json_api): + input_file = open(file_name, "r") + json_string = input_file.read() + input_file.close() + parsed_json = json.loads(json_string) + version = parsed_json["version"]["major"] + "." + parsed_json["version"]["minor"] + domains = [] + for domain in parsed_json["domains"]: + domains.append(domain["domain"]) + domain["version"] = version + json_api["domains"] += parsed_json["domains"] + return domains + + +class Protocol(object): + def __init__(self): + self.json_api = {} + self.generate_domains = [] + self.imported_domains = [] + + +def main(): + jinja_dir, config_file, config = read_config() + + protocol = Protocol() + protocol.json_api = {"domains": []} + protocol.generate_domains = read_protocol_file(config.protocol.path, protocol.json_api) + protocol.imported_domains = read_protocol_file(config.imported.path, protocol.json_api) if config.imported else [] + patch_full_qualified_refs(protocol) + calculate_exports(protocol) + create_type_definitions(protocol, "::".join(config.imported.namespace) if config.imported else "") + + if not config.exported: + for domain_json in protocol.json_api["domains"]: + if domain_json["has_exports"] and domain_json["domain"] in protocol.generate_domains: + sys.stderr.write("Domain %s is exported, but config is missing export entry\n\n" % domain_json["domain"]) + exit(1) + + if not os.path.exists(config.protocol.output): + os.mkdir(config.protocol.output) + if protocol.json_api["has_exports"] and not os.path.exists(config.exported.output): + os.mkdir(config.exported.output) + jinja_env = initialize_jinja_env(jinja_dir, config.protocol.output) + + inputs = [] + inputs.append(__file__) + inputs.append(config_file) + inputs.append(config.protocol.path) + if config.imported: + inputs.append(config.imported.path) + templates_dir = os.path.join(module_path, "templates") + inputs.append(os.path.join(templates_dir, "TypeBuilder_h.template")) + inputs.append(os.path.join(templates_dir, "TypeBuilder_cpp.template")) + inputs.append(os.path.join(templates_dir, "Exported_h.template")) + inputs.append(os.path.join(templates_dir, "Imported_h.template")) + + h_template = jinja_env.get_template("templates/TypeBuilder_h.template") + cpp_template = jinja_env.get_template("templates/TypeBuilder_cpp.template") + exported_template = jinja_env.get_template("templates/Exported_h.template") + imported_template = jinja_env.get_template("templates/Imported_h.template") + + outputs = dict() + + for domain in protocol.json_api["domains"]: + class_name = domain["domain"] + template_context = { + "config": config, + "domain": domain, + "join_arrays": join_arrays, + "resolve_type": functools.partial(resolve_type, protocol), + "type_definition": functools.partial(type_definition, protocol), + "has_disable": has_disable, + "format_include": format_include + } + + if domain["domain"] in protocol.generate_domains: + outputs[os.path.join(config.protocol.output, class_name + ".h")] = h_template.render(template_context) + outputs[os.path.join(config.protocol.output, class_name + ".cpp")] = cpp_template.render(template_context) + if domain["has_exports"]: + outputs[os.path.join(config.exported.output, class_name + ".h")] = exported_template.render(template_context) + if domain["domain"] in protocol.imported_domains and domain["has_exports"]: + outputs[os.path.join(config.protocol.output, class_name + ".h")] = imported_template.render(template_context) + + if config.lib: + template_context = { + "config": config, + "format_include": format_include, + } + + lib_templates_dir = os.path.join(module_path, "lib") + # Note these should be sorted in the right order. + # TODO(dgozman): sort them programmatically based on commented includes. + lib_h_templates = [ + "Collections_h.template", + "ErrorSupport_h.template", + "Values_h.template", + "Object_h.template", + "ValueConversions_h.template", + "Maybe_h.template", + "Array_h.template", + "DispatcherBase_h.template", + "Parser_h.template", + ] + + lib_cpp_templates = [ + "Protocol_cpp.template", + "ErrorSupport_cpp.template", + "Values_cpp.template", + "Object_cpp.template", + "DispatcherBase_cpp.template", + "Parser_cpp.template", + ] + + forward_h_templates = [ + "Forward_h.template", + "Allocator_h.template", + "FrontendChannel_h.template", + ] + + def generate_lib_file(file_name, template_files): + parts = [] + for template_file in template_files: + inputs.append(os.path.join(lib_templates_dir, template_file)) + template = jinja_env.get_template("lib/" + template_file) + parts.append(template.render(template_context)) + outputs[file_name] = "\n\n".join(parts) + + generate_lib_file(os.path.join(config.lib.output, "Forward.h"), forward_h_templates) + generate_lib_file(os.path.join(config.lib.output, "Protocol.h"), lib_h_templates) + generate_lib_file(os.path.join(config.lib.output, "Protocol.cpp"), lib_cpp_templates) + + # Make gyp / make generatos happy, otherwise make rebuilds world. + inputs_ts = max(map(os.path.getmtime, inputs)) + up_to_date = True + for output_file in outputs.iterkeys(): + if not os.path.exists(output_file) or os.path.getmtime(output_file) < inputs_ts: + up_to_date = False + break + if up_to_date: + sys.exit() + + for file_name, content in outputs.iteritems(): + out_file = open(file_name, "w") + out_file.write(content) + out_file.close() + + +main() diff --git a/deps/v8/third_party/inspector_protocol/ConcatenateProtocols.py b/deps/v8/third_party/inspector_protocol/ConcatenateProtocols.py new file mode 100755 index 0000000000..a7cbc992c7 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/ConcatenateProtocols.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os.path +import sys + +try: + import json +except ImportError: + import simplejson as json + + +def main(argv): + if len(argv) < 1: + sys.stderr.write("Usage: %s <protocol-1> [<protocol-2> [, <protocol-3>...]] <output-file>\n" % sys.argv[0]) + return 1 + + domains = [] + version = None + for protocol in argv[:-1]: + file_name = os.path.normpath(protocol) + if not os.path.isfile(file_name): + sys.stderr.write("Cannot find %s\n" % file_name) + return 1 + input_file = open(file_name, "r") + json_string = input_file.read() + parsed_json = json.loads(json_string) + domains += parsed_json["domains"] + version = parsed_json["version"] + + 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__': + sys.exit(main(sys.argv[1:])) diff --git a/deps/v8/third_party/inspector_protocol/LICENSE b/deps/v8/third_party/inspector_protocol/LICENSE new file mode 100644 index 0000000000..800468e576 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/deps/v8/third_party/inspector_protocol/OWNERS b/deps/v8/third_party/inspector_protocol/OWNERS new file mode 100644 index 0000000000..ff8888ace3 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/OWNERS @@ -0,0 +1,9 @@ +set noparent + +alph@chromium.org +caseq@chromium.org +dgozman@chromium.org +jochen@chromium.org +kozyatinskiy@chromium.org +pfeldman@chromium.org +yangguo@chromium.org
\ No newline at end of file diff --git a/deps/v8/third_party/inspector_protocol/README.v8 b/deps/v8/third_party/inspector_protocol/README.v8 new file mode 100644 index 0000000000..d95b61eaaf --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/README.v8 @@ -0,0 +1,16 @@ +Name: inspector protocol +Short Name: inspector_protocol +URL: https://chromium.googlesource.com/deps/inspector_protocol/ +Version: 0 +Revision: ebda02bf94a742a2e26e4f818df1fc77517ac44c +License: BSD +License File: LICENSE +Security Critical: no + +Description: +src/inspector uses these scripts to generate handlers from protocol +description. + +Local modifications: +- This only includes the lib/ and templates/ directories, scripts, build + and the LICENSE files. diff --git a/deps/v8/third_party/inspector_protocol/inspector_protocol.gni b/deps/v8/third_party/inspector_protocol/inspector_protocol.gni new file mode 100644 index 0000000000..34bc0de208 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/inspector_protocol.gni @@ -0,0 +1,80 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This template will generate inspector protocol source code. The code will +# not be compiled, use get_target_outputs(<name>) to compile them. +# +# Inputs +# +# config_file (required) +# Path to json file specifying inspector protocol configuration. +# +# out_dir (required) +# Path to put the generated files in. It must be inside output or +# generated file directory. +# +# outputs (required) +# Files generated. Relative to out_dir. +# +# inputs (optional) +# Extra inputs specified by the config file. +template("inspector_protocol_generate") { + assert(defined(invoker.config_file)) + assert(defined(invoker.out_dir)) + assert(defined(invoker.outputs)) + assert(defined(invoker.inspector_protocol_dir)) + inspector_protocol_dir = invoker.inspector_protocol_dir + + action(target_name) { + script = "$inspector_protocol_dir/CodeGenerator.py" + + inputs = [ + invoker.config_file, + "$inspector_protocol_dir/lib/Allocator_h.template", + "$inspector_protocol_dir/lib/Array_h.template", + "$inspector_protocol_dir/lib/Collections_h.template", + "$inspector_protocol_dir/lib/DispatcherBase_cpp.template", + "$inspector_protocol_dir/lib/DispatcherBase_h.template", + "$inspector_protocol_dir/lib/ErrorSupport_cpp.template", + "$inspector_protocol_dir/lib/ErrorSupport_h.template", + "$inspector_protocol_dir/lib/Forward_h.template", + "$inspector_protocol_dir/lib/FrontendChannel_h.template", + "$inspector_protocol_dir/lib/Maybe_h.template", + "$inspector_protocol_dir/lib/Object_cpp.template", + "$inspector_protocol_dir/lib/Object_h.template", + "$inspector_protocol_dir/lib/Parser_cpp.template", + "$inspector_protocol_dir/lib/Parser_h.template", + "$inspector_protocol_dir/lib/Protocol_cpp.template", + "$inspector_protocol_dir/lib/ValueConversions_h.template", + "$inspector_protocol_dir/lib/Values_cpp.template", + "$inspector_protocol_dir/lib/Values_h.template", + "$inspector_protocol_dir/templates/Exported_h.template", + "$inspector_protocol_dir/templates/Imported_h.template", + "$inspector_protocol_dir/templates/TypeBuilder_cpp.template", + "$inspector_protocol_dir/templates/TypeBuilder_h.template", + ] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + + args = [ + "--jinja_dir", + rebase_path("//third_party/", root_build_dir), # jinja is in chromium's third_party + "--output_base", + rebase_path(invoker.out_dir, root_build_dir), + "--config", + rebase_path(invoker.config_file, root_build_dir), + ] + + outputs = get_path_info(rebase_path(invoker.outputs, ".", invoker.out_dir), + "abspath") + + forward_variables_from(invoker, + [ + "visibility", + "deps", + "public_deps", + ]) + } +} diff --git a/deps/v8/third_party/inspector_protocol/inspector_protocol.gypi b/deps/v8/third_party/inspector_protocol/inspector_protocol.gypi new file mode 100644 index 0000000000..1fb7119b5f --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/inspector_protocol.gypi @@ -0,0 +1,33 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'inspector_protocol_files': [ + 'lib/Allocator_h.template', + 'lib/Array_h.template', + 'lib/Collections_h.template', + 'lib/DispatcherBase_cpp.template', + 'lib/DispatcherBase_h.template', + 'lib/ErrorSupport_cpp.template', + 'lib/ErrorSupport_h.template', + 'lib/Forward_h.template', + 'lib/FrontendChannel_h.template', + 'lib/Maybe_h.template', + 'lib/Object_cpp.template', + 'lib/Object_h.template', + 'lib/Parser_cpp.template', + 'lib/Parser_h.template', + 'lib/Protocol_cpp.template', + 'lib/ValueConversions_h.template', + 'lib/Values_cpp.template', + 'lib/Values_h.template', + 'templates/Exported_h.template', + 'templates/Imported_h.template', + 'templates/TypeBuilder_cpp.template', + 'templates/TypeBuilder_h.template', + 'CodeGenerator.py', + ] + } +} diff --git a/deps/v8/third_party/inspector_protocol/lib/Allocator_h.template b/deps/v8/third_party/inspector_protocol/lib/Allocator_h.template new file mode 100644 index 0000000000..8f8109d695 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Allocator_h.template @@ -0,0 +1,30 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Allocator_h +#define {{"_".join(config.protocol.namespace)}}_Allocator_h + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +enum NotNullTagEnum { NotNullLiteral }; + +#define PROTOCOL_DISALLOW_NEW() \ + private: \ + void* operator new(size_t) = delete; \ + void* operator new(size_t, NotNullTagEnum, void*) = delete; \ + void* operator new(size_t, void*) = delete; \ + public: + +#define PROTOCOL_DISALLOW_COPY(ClassName) \ + private: \ + ClassName(const ClassName&) = delete; \ + ClassName& operator=(const ClassName&) = delete + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Allocator_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/Array_h.template b/deps/v8/third_party/inspector_protocol/lib/Array_h.template new file mode 100644 index 0000000000..9555e302a9 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Array_h.template @@ -0,0 +1,136 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Array_h +#define {{"_".join(config.protocol.namespace)}}_Array_h + +//#include "ErrorSupport.h" +//#include "Forward.h" +//#include "ValueConversions.h" +//#include "Values.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template<typename T> +class Array { +public: + static std::unique_ptr<Array<T>> create() + { + return wrapUnique(new Array<T>()); + } + + static std::unique_ptr<Array<T>> parse(protocol::Value* value, ErrorSupport* errors) + { + protocol::ListValue* array = ListValue::cast(value); + if (!array) { + errors->addError("array expected"); + return nullptr; + } + std::unique_ptr<Array<T>> result(new Array<T>()); + errors->push(); + for (size_t i = 0; i < array->size(); ++i) { + errors->setName(StringUtil::fromInteger(i)); + std::unique_ptr<T> item = ValueConversions<T>::parse(array->at(i), errors); + result->m_vector.push_back(std::move(item)); + } + errors->pop(); + if (errors->hasErrors()) + return nullptr; + return result; + } + + void addItem(std::unique_ptr<T> value) + { + m_vector.push_back(std::move(value)); + } + + size_t length() + { + return m_vector.size(); + } + + T* get(size_t index) + { + return m_vector[index].get(); + } + + std::unique_ptr<protocol::ListValue> serialize() + { + std::unique_ptr<protocol::ListValue> result = ListValue::create(); + for (auto& item : m_vector) + result->pushValue(ValueConversions<T>::serialize(item)); + return result; + } + +private: + std::vector<std::unique_ptr<T>> m_vector; +}; + +template<typename T> +class ArrayBase { +public: + static std::unique_ptr<Array<T>> create() + { + return wrapUnique(new Array<T>()); + } + + static std::unique_ptr<Array<T>> parse(protocol::Value* value, ErrorSupport* errors) + { + protocol::ListValue* array = ListValue::cast(value); + if (!array) { + errors->addError("array expected"); + return nullptr; + } + errors->push(); + std::unique_ptr<Array<T>> result(new Array<T>()); + for (size_t i = 0; i < array->size(); ++i) { + errors->setName(StringUtil::fromInteger(i)); + T item = ValueConversions<T>::parse(array->at(i), errors); + result->m_vector.push_back(item); + } + errors->pop(); + if (errors->hasErrors()) + return nullptr; + return result; + } + + void addItem(const T& value) + { + m_vector.push_back(value); + } + + size_t length() + { + return m_vector.size(); + } + + T get(size_t index) + { + return m_vector[index]; + } + + std::unique_ptr<protocol::ListValue> serialize() + { + std::unique_ptr<protocol::ListValue> result = ListValue::create(); + for (auto& item : m_vector) + result->pushValue(ValueConversions<T>::serialize(item)); + return result; + } + +private: + std::vector<T> m_vector; +}; + +template<> class Array<String> : public ArrayBase<String> {}; +template<> class Array<int> : public ArrayBase<int> {}; +template<> class Array<double> : public ArrayBase<double> {}; +template<> class Array<bool> : public ArrayBase<bool> {}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Array_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/Collections_h.template b/deps/v8/third_party/inspector_protocol/lib/Collections_h.template new file mode 100644 index 0000000000..3f760287b5 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Collections_h.template @@ -0,0 +1,43 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Collections_h +#define {{"_".join(config.protocol.namespace)}}_Collections_h + +#include "{{config.protocol.package}}/Forward.h" +#include <cstddef> + +#if defined(__APPLE__) && !defined(_LIBCPP_VERSION) +#include <map> +#include <set> + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template <class Key, class T> using HashMap = std::map<Key, T>; +template <class Key> using HashSet = std::set<Key>; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#else +#include <unordered_map> +#include <unordered_set> + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template <class Key, class T> using HashMap = std::unordered_map<Key, T>; +template <class Key> using HashSet = std::unordered_set<Key>; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // defined(__APPLE__) && !defined(_LIBCPP_VERSION) + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Collections_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/DispatcherBase_cpp.template b/deps/v8/third_party/inspector_protocol/lib/DispatcherBase_cpp.template new file mode 100644 index 0000000000..c4f36a5fd3 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/DispatcherBase_cpp.template @@ -0,0 +1,225 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//#include "DispatcherBase.h" +//#include "Parser.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +// static +DispatchResponse DispatchResponse::OK() +{ + DispatchResponse result; + result.m_status = kSuccess; + result.m_errorCode = kParseError; + return result; +} + +// static +DispatchResponse DispatchResponse::Error(const String& error) +{ + DispatchResponse result; + result.m_status = kError; + result.m_errorCode = kServerError; + result.m_errorMessage = error; + return result; +} + +// static +DispatchResponse DispatchResponse::InternalError() +{ + DispatchResponse result; + result.m_status = kError; + result.m_errorCode = kInternalError; + result.m_errorMessage = "Internal error"; + return result; +} + +// static +DispatchResponse DispatchResponse::FallThrough() +{ + DispatchResponse result; + result.m_status = kFallThrough; + result.m_errorCode = kParseError; + return result; +} + +// static +const char DispatcherBase::kInvalidParamsString[] = "Invalid parameters"; + +DispatcherBase::WeakPtr::WeakPtr(DispatcherBase* dispatcher) : m_dispatcher(dispatcher) { } + +DispatcherBase::WeakPtr::~WeakPtr() +{ + if (m_dispatcher) + m_dispatcher->m_weakPtrs.erase(this); +} + +DispatcherBase::Callback::Callback(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId) + : m_backendImpl(std::move(backendImpl)) + , m_callId(callId) { } + +DispatcherBase::Callback::~Callback() = default; + +void DispatcherBase::Callback::dispose() +{ + m_backendImpl = nullptr; +} + +void DispatcherBase::Callback::sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const DispatchResponse& response) +{ + if (!m_backendImpl || !m_backendImpl->get()) + return; + m_backendImpl->get()->sendResponse(m_callId, response, std::move(partialMessage)); + m_backendImpl = nullptr; +} + +DispatcherBase::DispatcherBase(FrontendChannel* frontendChannel) + : m_frontendChannel(frontendChannel) { } + +DispatcherBase::~DispatcherBase() +{ + clearFrontend(); +} + +// static +bool DispatcherBase::getCommandName(const String& message, String* result) +{ + std::unique_ptr<protocol::Value> value = parseJSON(message); + if (!value) + return false; + + protocol::DictionaryValue* object = DictionaryValue::cast(value.get()); + if (!object) + return false; + + if (!object->getString("method", result)) + return false; + + return true; +} + +void DispatcherBase::sendResponse(int callId, const DispatchResponse& response, std::unique_ptr<protocol::DictionaryValue> result) +{ + if (response.status() == DispatchResponse::kError) { + reportProtocolError(callId, response.errorCode(), response.errorMessage(), nullptr); + return; + } + + std::unique_ptr<protocol::DictionaryValue> responseMessage = DictionaryValue::create(); + responseMessage->setInteger("id", callId); + responseMessage->setObject("result", std::move(result)); + if (m_frontendChannel) + m_frontendChannel->sendProtocolResponse(callId, responseMessage->toJSONString()); +} + +void DispatcherBase::sendResponse(int callId, const DispatchResponse& response) +{ + sendResponse(callId, response, DictionaryValue::create()); +} + +static void reportProtocolErrorTo(FrontendChannel* frontendChannel, int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors) +{ + if (!frontendChannel) + return; + std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create(); + error->setInteger("code", code); + error->setString("message", errorMessage); + if (errors && errors->hasErrors()) + error->setString("data", errors->errors()); + std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create(); + message->setObject("error", std::move(error)); + message->setInteger("id", callId); + frontendChannel->sendProtocolResponse(callId, message->toJSONString()); +} + +static void reportProtocolErrorTo(FrontendChannel* frontendChannel, DispatchResponse::ErrorCode code, const String& errorMessage) +{ + if (!frontendChannel) + return; + std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create(); + error->setInteger("code", code); + error->setString("message", errorMessage); + std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create(); + message->setObject("error", std::move(error)); + frontendChannel->sendProtocolNotification(message->toJSONString()); +} + +void DispatcherBase::reportProtocolError(int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors) +{ + reportProtocolErrorTo(m_frontendChannel, callId, code, errorMessage, errors); +} + +void DispatcherBase::clearFrontend() +{ + m_frontendChannel = nullptr; + for (auto& weak : m_weakPtrs) + weak->dispose(); + m_weakPtrs.clear(); +} + +std::unique_ptr<DispatcherBase::WeakPtr> DispatcherBase::weakPtr() +{ + std::unique_ptr<DispatcherBase::WeakPtr> weak(new DispatcherBase::WeakPtr(this)); + m_weakPtrs.insert(weak.get()); + return weak; +} + +UberDispatcher::UberDispatcher(FrontendChannel* frontendChannel) + : m_frontendChannel(frontendChannel) { } + +void UberDispatcher::registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase> dispatcher) +{ + m_dispatchers[name] = std::move(dispatcher); +} + +DispatchResponse::Status UberDispatcher::dispatch(std::unique_ptr<Value> parsedMessage) +{ + if (!parsedMessage) { + reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kParseError, "Message must be a valid JSON"); + return DispatchResponse::kError; + } + std::unique_ptr<protocol::DictionaryValue> messageObject = DictionaryValue::cast(std::move(parsedMessage)); + if (!messageObject) { + reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kInvalidRequest, "Message must be an object"); + return DispatchResponse::kError; + } + + int callId = 0; + protocol::Value* callIdValue = messageObject->get("id"); + bool success = callIdValue && callIdValue->asInteger(&callId); + if (!success) { + reportProtocolErrorTo(m_frontendChannel, DispatchResponse::kInvalidRequest, "Message must have integer 'id' porperty"); + return DispatchResponse::kError; + } + + protocol::Value* methodValue = messageObject->get("method"); + String method; + success = methodValue && methodValue->asString(&method); + if (!success) { + reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kInvalidRequest, "Message must have string 'method' porperty", nullptr); + return DispatchResponse::kError; + } + + size_t dotIndex = method.find("."); + if (dotIndex == StringUtil::kNotFound) { + reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kMethodNotFound, "'" + method + "' wasn't found", nullptr); + return DispatchResponse::kError; + } + String domain = StringUtil::substring(method, 0, dotIndex); + auto it = m_dispatchers.find(domain); + if (it == m_dispatchers.end()) { + reportProtocolErrorTo(m_frontendChannel, callId, DispatchResponse::kMethodNotFound, "'" + method + "' wasn't found", nullptr); + return DispatchResponse::kError; + } + return it->second->dispatch(callId, method, std::move(messageObject)); +} + +UberDispatcher::~UberDispatcher() = default; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8/third_party/inspector_protocol/lib/DispatcherBase_h.template b/deps/v8/third_party/inspector_protocol/lib/DispatcherBase_h.template new file mode 100644 index 0000000000..4fb89efafe --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/DispatcherBase_h.template @@ -0,0 +1,120 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_DispatcherBase_h +#define {{"_".join(config.protocol.namespace)}}_DispatcherBase_h + +//#include "Collections.h" +//#include "ErrorSupport.h" +//#include "Forward.h" +//#include "Values.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +class WeakPtr; + +class {{config.lib.export_macro}} DispatchResponse { +public: + enum Status { + kSuccess = 0, + kError = 1, + kFallThrough = 2, + kAsync = 3 + }; + + enum ErrorCode { + kParseError = -32700, + kInvalidRequest = -32600, + kMethodNotFound = -32601, + kInvalidParams = -32602, + kInternalError = -32603, + kServerError = -32000, + }; + + Status status() const { return m_status; } + const String& errorMessage() const { return m_errorMessage; } + ErrorCode errorCode() const { return m_errorCode; } + bool isSuccess() const { return m_status == kSuccess; } + + static DispatchResponse OK(); + static DispatchResponse Error(const String&); + static DispatchResponse InternalError(); + static DispatchResponse FallThrough(); + +private: + Status m_status; + String m_errorMessage; + ErrorCode m_errorCode; +}; + +class {{config.lib.export_macro}} DispatcherBase { + PROTOCOL_DISALLOW_COPY(DispatcherBase); +public: + static const char kInvalidParamsString[]; + class {{config.lib.export_macro}} WeakPtr { + public: + explicit WeakPtr(DispatcherBase*); + ~WeakPtr(); + DispatcherBase* get() { return m_dispatcher; } + void dispose() { m_dispatcher = nullptr; } + + private: + DispatcherBase* m_dispatcher; + }; + + class {{config.lib.export_macro}} Callback { + public: + Callback(std::unique_ptr<WeakPtr> backendImpl, int callId); + virtual ~Callback(); + void dispose(); + + protected: + void sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const DispatchResponse& response); + + private: + std::unique_ptr<WeakPtr> m_backendImpl; + int m_callId; + }; + + explicit DispatcherBase(FrontendChannel*); + virtual ~DispatcherBase(); + + static bool getCommandName(const String& message, String* result); + + virtual DispatchResponse::Status dispatch(int callId, const String& method, std::unique_ptr<protocol::DictionaryValue> messageObject) = 0; + + void sendResponse(int callId, const DispatchResponse&, std::unique_ptr<protocol::DictionaryValue> result); + void sendResponse(int callId, const DispatchResponse&); + + void reportProtocolError(int callId, DispatchResponse::ErrorCode, const String& errorMessage, ErrorSupport* errors); + void clearFrontend(); + + std::unique_ptr<WeakPtr> weakPtr(); + +private: + FrontendChannel* m_frontendChannel; + protocol::HashSet<WeakPtr*> m_weakPtrs; +}; + +class {{config.lib.export_macro}} UberDispatcher { + PROTOCOL_DISALLOW_COPY(UberDispatcher); +public: + explicit UberDispatcher(FrontendChannel*); + void registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase>); + DispatchResponse::Status dispatch(std::unique_ptr<Value> message); + FrontendChannel* channel() { return m_frontendChannel; } + virtual ~UberDispatcher(); + +private: + FrontendChannel* m_frontendChannel; + protocol::HashMap<String, std::unique_ptr<protocol::DispatcherBase>> m_dispatchers; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_DispatcherBase_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/ErrorSupport_cpp.template b/deps/v8/third_party/inspector_protocol/lib/ErrorSupport_cpp.template new file mode 100644 index 0000000000..1d107f697a --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/ErrorSupport_cpp.template @@ -0,0 +1,61 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//#include "ErrorSupport.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +ErrorSupport::ErrorSupport() { } +ErrorSupport::~ErrorSupport() { } + +void ErrorSupport::setName(const String& name) +{ + DCHECK(m_path.size()); + m_path[m_path.size() - 1] = name; +} + +void ErrorSupport::push() +{ + m_path.push_back(String()); +} + +void ErrorSupport::pop() +{ + m_path.pop_back(); +} + +void ErrorSupport::addError(const String& error) +{ + StringBuilder builder; + for (size_t i = 0; i < m_path.size(); ++i) { + if (i) + builder.append('.'); + builder.append(m_path[i]); + } + builder.append(": "); + builder.append(error); + m_errors.push_back(builder.toString()); +} + +bool ErrorSupport::hasErrors() +{ + return m_errors.size(); +} + +String ErrorSupport::errors() +{ + StringBuilder builder; + for (size_t i = 0; i < m_errors.size(); ++i) { + if (i) + builder.append("; "); + builder.append(m_errors[i]); + } + return builder.toString(); +} + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8/third_party/inspector_protocol/lib/ErrorSupport_h.template b/deps/v8/third_party/inspector_protocol/lib/ErrorSupport_h.template new file mode 100644 index 0000000000..0c98e3e0eb --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/ErrorSupport_h.template @@ -0,0 +1,35 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_ErrorSupport_h +#define {{"_".join(config.protocol.namespace)}}_ErrorSupport_h + +//#include "Forward.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +class {{config.lib.export_macro}} ErrorSupport { +public: + ErrorSupport(); + ~ErrorSupport(); + + void push(); + void setName(const String&); + void pop(); + void addError(const String&); + bool hasErrors(); + String errors(); + +private: + std::vector<String> m_path; + std::vector<String> m_errors; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_ErrorSupport_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/Forward_h.template b/deps/v8/third_party/inspector_protocol/lib/Forward_h.template new file mode 100644 index 0000000000..04868b707f --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Forward_h.template @@ -0,0 +1,38 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Forward_h +#define {{"_".join(config.protocol.namespace)}}_Forward_h + +{% if config.lib.export_header %} +#include {{format_include(config.lib.export_header)}} +{% endif %} +#include {{format_include(config.lib.platform_header)}} +#include {{format_include(config.lib.string_header)}} + +#include <vector> + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template<typename T> class Array; +class DictionaryValue; +class DispatchResponse; +class ErrorSupport; +class FundamentalValue; +class ListValue; +template<typename T> class Maybe; +class Object; +using Response = DispatchResponse; +class SerializedValue; +class StringValue; +class UberDispatcher; +class Value; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Forward_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/FrontendChannel_h.template b/deps/v8/third_party/inspector_protocol/lib/FrontendChannel_h.template new file mode 100644 index 0000000000..8b653b5821 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/FrontendChannel_h.template @@ -0,0 +1,24 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_FrontendChannel_h +#define {{"_".join(config.protocol.namespace)}}_FrontendChannel_h + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +class {{config.lib.export_macro}} FrontendChannel { +public: + virtual ~FrontendChannel() { } + virtual void sendProtocolResponse(int callId, const String& message) = 0; + virtual void sendProtocolNotification(const String& message) = 0; + virtual void flushProtocolNotifications() = 0; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_FrontendChannel_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/Maybe_h.template b/deps/v8/third_party/inspector_protocol/lib/Maybe_h.template new file mode 100644 index 0000000000..cd0dfbdf2e --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Maybe_h.template @@ -0,0 +1,86 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Maybe_h +#define {{"_".join(config.protocol.namespace)}}_Maybe_h + +//#include "Forward.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template<typename T> +class Maybe { +public: + Maybe() : m_value() { } + Maybe(std::unique_ptr<T> value) : m_value(std::move(value)) { } + Maybe(Maybe&& other) : m_value(std::move(other.m_value)) { } + void operator=(std::unique_ptr<T> value) { m_value = std::move(value); } + T* fromJust() const { DCHECK(m_value); return m_value.get(); } + T* fromMaybe(T* defaultValue) const { return m_value ? m_value.get() : defaultValue; } + bool isJust() const { return !!m_value; } + std::unique_ptr<T> takeJust() { DCHECK(m_value); return m_value.release(); } +private: + std::unique_ptr<T> m_value; +}; + +template<typename T> +class MaybeBase { +public: + MaybeBase() : m_isJust(false) { } + MaybeBase(T value) : m_isJust(true), m_value(value) { } + MaybeBase(MaybeBase&& other) : m_isJust(other.m_isJust), m_value(std::move(other.m_value)) { } + void operator=(T value) { m_value = value; m_isJust = true; } + T fromJust() const { DCHECK(m_isJust); return m_value; } + T fromMaybe(const T& defaultValue) const { return m_isJust ? m_value : defaultValue; } + bool isJust() const { return m_isJust; } + T takeJust() { DCHECK(m_isJust); return m_value; } + +protected: + bool m_isJust; + T m_value; +}; + +template<> +class Maybe<bool> : public MaybeBase<bool> { +public: + Maybe() { } + Maybe(bool value) : MaybeBase(value) { } + Maybe(Maybe&& other) : MaybeBase(std::move(other)) { } + using MaybeBase::operator=; +}; + +template<> +class Maybe<int> : public MaybeBase<int> { +public: + Maybe() { } + Maybe(int value) : MaybeBase(value) { } + Maybe(Maybe&& other) : MaybeBase(std::move(other)) { } + using MaybeBase::operator=; +}; + +template<> +class Maybe<double> : public MaybeBase<double> { +public: + Maybe() { } + Maybe(double value) : MaybeBase(value) { } + Maybe(Maybe&& other) : MaybeBase(std::move(other)) { } + using MaybeBase::operator=; +}; + +template<> +class Maybe<String> : public MaybeBase<String> { +public: + Maybe() { } + Maybe(const String& value) : MaybeBase(value) { } + Maybe(Maybe&& other) : MaybeBase(std::move(other)) { } + using MaybeBase::operator=; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Maybe_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/Object_cpp.template b/deps/v8/third_party/inspector_protocol/lib/Object_cpp.template new file mode 100644 index 0000000000..e3f18c3500 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Object_cpp.template @@ -0,0 +1,37 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//#include "Object.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +std::unique_ptr<Object> Object::parse(protocol::Value* value, ErrorSupport* errors) +{ + protocol::DictionaryValue* object = DictionaryValue::cast(value); + if (!object) { + errors->addError("object expected"); + return nullptr; + } + return wrapUnique(new Object(wrapUnique(static_cast<DictionaryValue*>(object->clone().release())))); +} + +std::unique_ptr<protocol::DictionaryValue> Object::serialize() const +{ + return DictionaryValue::cast(m_object->clone()); +} + +std::unique_ptr<Object> Object::clone() const +{ + return wrapUnique(new Object(DictionaryValue::cast(m_object->clone()))); +} + +Object::Object(std::unique_ptr<protocol::DictionaryValue> object) : m_object(std::move(object)) { } + +Object::~Object() { } + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8/third_party/inspector_protocol/lib/Object_h.template b/deps/v8/third_party/inspector_protocol/lib/Object_h.template new file mode 100644 index 0000000000..4ccd88bdab --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Object_h.template @@ -0,0 +1,32 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Object_h +#define {{"_".join(config.protocol.namespace)}}_Object_h + +//#include "ErrorSupport.h" +//#include "Forward.h" +//#include "Values.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +class {{config.lib.export_macro}} Object { +public: + static std::unique_ptr<Object> parse(protocol::Value*, ErrorSupport*); + ~Object(); + + std::unique_ptr<protocol::DictionaryValue> serialize() const; + std::unique_ptr<Object> clone() const; +private: + explicit Object(std::unique_ptr<protocol::DictionaryValue>); + std::unique_ptr<protocol::DictionaryValue> m_object; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Object_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/Parser_cpp.template b/deps/v8/third_party/inspector_protocol/lib/Parser_cpp.template new file mode 100644 index 0000000000..a103b8228e --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Parser_cpp.template @@ -0,0 +1,553 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +namespace { + +const int stackLimit = 1000; + +enum Token { + ObjectBegin, + ObjectEnd, + ArrayBegin, + ArrayEnd, + StringLiteral, + Number, + BoolTrue, + BoolFalse, + NullToken, + ListSeparator, + ObjectPairSeparator, + InvalidToken, +}; + +const char* const nullString = "null"; +const char* const trueString = "true"; +const char* const falseString = "false"; + +bool isASCII(uint16_t c) +{ + return !(c & ~0x7F); +} + +bool isSpaceOrNewLine(uint16_t c) +{ + return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); +} + +double charactersToDouble(const uint16_t* characters, size_t length, bool* ok) +{ + std::vector<char> buffer; + buffer.reserve(length + 1); + for (size_t i = 0; i < length; ++i) { + if (!isASCII(characters[i])) { + *ok = false; + return 0; + } + buffer.push_back(static_cast<char>(characters[i])); + } + buffer.push_back('\0'); + char* endptr; + double result = std::strtod(buffer.data(), &endptr); + *ok = !(*endptr); + return result; +} + +double charactersToDouble(const uint8_t* characters, size_t length, bool* ok) +{ + std::string buffer(reinterpret_cast<const char*>(characters), length); + char* endptr; + double result = std::strtod(buffer.data(), &endptr); + *ok = !(*endptr); + return result; +} + +template<typename Char> +bool parseConstToken(const Char* start, const Char* end, const Char** tokenEnd, const char* token) +{ + while (start < end && *token != '\0' && *start++ == *token++) { } + if (*token != '\0') + return false; + *tokenEnd = start; + return true; +} + +template<typename Char> +bool readInt(const Char* start, const Char* end, const Char** tokenEnd, bool canHaveLeadingZeros) +{ + if (start == end) + return false; + bool haveLeadingZero = '0' == *start; + int length = 0; + while (start < end && '0' <= *start && *start <= '9') { + ++start; + ++length; + } + if (!length) + return false; + if (!canHaveLeadingZeros && length > 1 && haveLeadingZero) + return false; + *tokenEnd = start; + return true; +} + +template<typename Char> +bool parseNumberToken(const Char* start, const Char* end, const Char** tokenEnd) +{ + // We just grab the number here. We validate the size in DecodeNumber. + // According to RFC4627, a valid number is: [minus] int [frac] [exp] + if (start == end) + return false; + Char c = *start; + if ('-' == c) + ++start; + + if (!readInt(start, end, &start, false)) + return false; + if (start == end) { + *tokenEnd = start; + return true; + } + + // Optional fraction part + c = *start; + if ('.' == c) { + ++start; + if (!readInt(start, end, &start, true)) + return false; + if (start == end) { + *tokenEnd = start; + return true; + } + c = *start; + } + + // Optional exponent part + if ('e' == c || 'E' == c) { + ++start; + if (start == end) + return false; + c = *start; + if ('-' == c || '+' == c) { + ++start; + if (start == end) + return false; + } + if (!readInt(start, end, &start, true)) + return false; + } + + *tokenEnd = start; + return true; +} + +template<typename Char> +bool readHexDigits(const Char* start, const Char* end, const Char** tokenEnd, int digits) +{ + if (end - start < digits) + return false; + for (int i = 0; i < digits; ++i) { + Char c = *start++; + if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))) + return false; + } + *tokenEnd = start; + return true; +} + +template<typename Char> +bool parseStringToken(const Char* start, const Char* end, const Char** tokenEnd) +{ + while (start < end) { + Char c = *start++; + if ('\\' == c) { + if (start == end) + return false; + c = *start++; + // Make sure the escaped char is valid. + switch (c) { + case 'x': + if (!readHexDigits(start, end, &start, 2)) + return false; + break; + case 'u': + if (!readHexDigits(start, end, &start, 4)) + return false; + break; + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': + case '"': + break; + default: + return false; + } + } else if ('"' == c) { + *tokenEnd = start; + return true; + } + } + return false; +} + +template<typename Char> +bool skipComment(const Char* start, const Char* end, const Char** commentEnd) +{ + if (start == end) + return false; + + if (*start != '/' || start + 1 >= end) + return false; + ++start; + + if (*start == '/') { + // Single line comment, read to newline. + for (++start; start < end; ++start) { + if (*start == '\n' || *start == '\r') { + *commentEnd = start + 1; + return true; + } + } + *commentEnd = end; + // Comment reaches end-of-input, which is fine. + return true; + } + + if (*start == '*') { + Char previous = '\0'; + // Block comment, read until end marker. + for (++start; start < end; previous = *start++) { + if (previous == '*' && *start == '/') { + *commentEnd = start + 1; + return true; + } + } + // Block comment must close before end-of-input. + return false; + } + + return false; +} + +template<typename Char> +void skipWhitespaceAndComments(const Char* start, const Char* end, const Char** whitespaceEnd) +{ + while (start < end) { + if (isSpaceOrNewLine(*start)) { + ++start; + } else if (*start == '/') { + const Char* commentEnd; + if (!skipComment(start, end, &commentEnd)) + break; + start = commentEnd; + } else { + break; + } + } + *whitespaceEnd = start; +} + +template<typename Char> +Token parseToken(const Char* start, const Char* end, const Char** tokenStart, const Char** tokenEnd) +{ + skipWhitespaceAndComments(start, end, tokenStart); + start = *tokenStart; + + if (start == end) + return InvalidToken; + + switch (*start) { + case 'n': + if (parseConstToken(start, end, tokenEnd, nullString)) + return NullToken; + break; + case 't': + if (parseConstToken(start, end, tokenEnd, trueString)) + return BoolTrue; + break; + case 'f': + if (parseConstToken(start, end, tokenEnd, falseString)) + return BoolFalse; + break; + case '[': + *tokenEnd = start + 1; + return ArrayBegin; + case ']': + *tokenEnd = start + 1; + return ArrayEnd; + case ',': + *tokenEnd = start + 1; + return ListSeparator; + case '{': + *tokenEnd = start + 1; + return ObjectBegin; + case '}': + *tokenEnd = start + 1; + return ObjectEnd; + case ':': + *tokenEnd = start + 1; + return ObjectPairSeparator; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + if (parseNumberToken(start, end, tokenEnd)) + return Number; + break; + case '"': + if (parseStringToken(start + 1, end, tokenEnd)) + return StringLiteral; + break; + } + return InvalidToken; +} + +template<typename Char> +int hexToInt(Char c) +{ + if ('0' <= c && c <= '9') + return c - '0'; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + DCHECK(false); + return 0; +} + +template<typename Char> +bool decodeString(const Char* start, const Char* end, StringBuilder* output) +{ + while (start < end) { + uint16_t c = *start++; + if ('\\' != c) { + output->append(c); + continue; + } + if (start == end) + return false; + c = *start++; + + if (c == 'x') { + // \x is not supported. + return false; + } + + switch (c) { + case '"': + case '/': + case '\\': + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = '\v'; + break; + case 'u': + c = (hexToInt(*start) << 12) + + (hexToInt(*(start + 1)) << 8) + + (hexToInt(*(start + 2)) << 4) + + hexToInt(*(start + 3)); + start += 4; + break; + default: + return false; + } + output->append(c); + } + return true; +} + +template<typename Char> +bool decodeString(const Char* start, const Char* end, String* output) +{ + if (start == end) { + *output = ""; + return true; + } + if (start > end) + return false; + StringBuilder buffer; + StringUtil::builderReserve(buffer, end - start); + if (!decodeString(start, end, &buffer)) + return false; + *output = buffer.toString(); + return true; +} + +template<typename Char> +std::unique_ptr<Value> buildValue(const Char* start, const Char* end, const Char** valueTokenEnd, int depth) +{ + if (depth > stackLimit) + return nullptr; + + std::unique_ptr<Value> result; + const Char* tokenStart; + const Char* tokenEnd; + Token token = parseToken(start, end, &tokenStart, &tokenEnd); + switch (token) { + case InvalidToken: + return nullptr; + case NullToken: + result = Value::null(); + break; + case BoolTrue: + result = FundamentalValue::create(true); + break; + case BoolFalse: + result = FundamentalValue::create(false); + break; + case Number: { + bool ok; + double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok); + if (!ok) + return nullptr; + int number = static_cast<int>(value); + if (number == value) + result = FundamentalValue::create(number); + else + result = FundamentalValue::create(value); + break; + } + case StringLiteral: { + String value; + bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); + if (!ok) + return nullptr; + result = StringValue::create(value); + break; + } + case ArrayBegin: { + std::unique_ptr<ListValue> array = ListValue::create(); + start = tokenEnd; + token = parseToken(start, end, &tokenStart, &tokenEnd); + while (token != ArrayEnd) { + std::unique_ptr<Value> arrayNode = buildValue(start, end, &tokenEnd, depth + 1); + if (!arrayNode) + return nullptr; + array->pushValue(std::move(arrayNode)); + + // After a list value, we expect a comma or the end of the list. + start = tokenEnd; + token = parseToken(start, end, &tokenStart, &tokenEnd); + if (token == ListSeparator) { + start = tokenEnd; + token = parseToken(start, end, &tokenStart, &tokenEnd); + if (token == ArrayEnd) + return nullptr; + } else if (token != ArrayEnd) { + // Unexpected value after list value. Bail out. + return nullptr; + } + } + if (token != ArrayEnd) + return nullptr; + result = std::move(array); + break; + } + case ObjectBegin: { + std::unique_ptr<DictionaryValue> object = DictionaryValue::create(); + start = tokenEnd; + token = parseToken(start, end, &tokenStart, &tokenEnd); + while (token != ObjectEnd) { + if (token != StringLiteral) + return nullptr; + String key; + if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) + return nullptr; + start = tokenEnd; + + token = parseToken(start, end, &tokenStart, &tokenEnd); + if (token != ObjectPairSeparator) + return nullptr; + start = tokenEnd; + + std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, depth + 1); + if (!value) + return nullptr; + object->setValue(key, std::move(value)); + start = tokenEnd; + + // After a key/value pair, we expect a comma or the end of the + // object. + token = parseToken(start, end, &tokenStart, &tokenEnd); + if (token == ListSeparator) { + start = tokenEnd; + token = parseToken(start, end, &tokenStart, &tokenEnd); + if (token == ObjectEnd) + return nullptr; + } else if (token != ObjectEnd) { + // Unexpected value after last object value. Bail out. + return nullptr; + } + } + if (token != ObjectEnd) + return nullptr; + result = std::move(object); + break; + } + + default: + // We got a token that's not a value. + return nullptr; + } + + skipWhitespaceAndComments(tokenEnd, end, valueTokenEnd); + return result; +} + +template<typename Char> +std::unique_ptr<Value> parseJSONInternal(const Char* start, unsigned length) +{ + const Char* end = start + length; + const Char *tokenEnd; + std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, 0); + if (!value || tokenEnd != end) + return nullptr; + return value; +} + +} // anonymous namespace + +std::unique_ptr<Value> parseJSON(const uint16_t* characters, unsigned length) +{ + return parseJSONInternal<uint16_t>(characters, length); +} + +std::unique_ptr<Value> parseJSON(const uint8_t* characters, unsigned length) +{ + return parseJSONInternal<uint8_t>(characters, length); +} + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8/third_party/inspector_protocol/lib/Parser_h.template b/deps/v8/third_party/inspector_protocol/lib/Parser_h.template new file mode 100644 index 0000000000..7b2a29b6c9 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Parser_h.template @@ -0,0 +1,22 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Parser_h +#define {{"_".join(config.protocol.namespace)}}_Parser_h + +//#include "Forward.h" +//#include "Values.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +{{config.lib.export_macro}} std::unique_ptr<Value> parseJSON(const uint8_t*, unsigned); +{{config.lib.export_macro}} std::unique_ptr<Value> parseJSON(const uint16_t*, unsigned); + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Parser_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/Protocol_cpp.template b/deps/v8/third_party/inspector_protocol/lib/Protocol_cpp.template new file mode 100644 index 0000000000..8e35fa74fc --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Protocol_cpp.template @@ -0,0 +1,12 @@ +// This file is generated. + +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "{{config.protocol.package}}/Protocol.h" + +#include <algorithm> +#include <cmath> + +#include <cstring> diff --git a/deps/v8/third_party/inspector_protocol/lib/ValueConversions_h.template b/deps/v8/third_party/inspector_protocol/lib/ValueConversions_h.template new file mode 100644 index 0000000000..5384c7bb1e --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/ValueConversions_h.template @@ -0,0 +1,171 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_ValueConversions_h +#define {{"_".join(config.protocol.namespace)}}_ValueConversions_h + +//#include "ErrorSupport.h" +//#include "Forward.h" +//#include "Values.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template<typename T> +struct ValueConversions { + static std::unique_ptr<T> parse(protocol::Value* value, ErrorSupport* errors) + { + return T::parse(value, errors); + } + + static std::unique_ptr<protocol::Value> serialize(T* value) + { + return value->serialize(); + } + + static std::unique_ptr<protocol::Value> serialize(const std::unique_ptr<T>& value) + { + return value->serialize(); + } +}; + +template<> +struct ValueConversions<bool> { + static bool parse(protocol::Value* value, ErrorSupport* errors) + { + bool result = false; + bool success = value ? value->asBoolean(&result) : false; + if (!success) + errors->addError("boolean value expected"); + return result; + } + + static std::unique_ptr<protocol::Value> serialize(bool value) + { + return FundamentalValue::create(value); + } +}; + +template<> +struct ValueConversions<int> { + static int parse(protocol::Value* value, ErrorSupport* errors) + { + int result = 0; + bool success = value ? value->asInteger(&result) : false; + if (!success) + errors->addError("integer value expected"); + return result; + } + + static std::unique_ptr<protocol::Value> serialize(int value) + { + return FundamentalValue::create(value); + } +}; + +template<> +struct ValueConversions<double> { + static double parse(protocol::Value* value, ErrorSupport* errors) + { + double result = 0; + bool success = value ? value->asDouble(&result) : false; + if (!success) + errors->addError("double value expected"); + return result; + } + + static std::unique_ptr<protocol::Value> serialize(double value) + { + return FundamentalValue::create(value); + } +}; + +template<> +struct ValueConversions<String> { + static String parse(protocol::Value* value, ErrorSupport* errors) + { + String result; + bool success = value ? value->asString(&result) : false; + if (!success) + errors->addError("string value expected"); + return result; + } + + static std::unique_ptr<protocol::Value> serialize(const String& value) + { + return StringValue::create(value); + } +}; + +template<> +struct ValueConversions<Value> { + static std::unique_ptr<Value> parse(protocol::Value* value, ErrorSupport* errors) + { + bool success = !!value; + if (!success) { + errors->addError("value expected"); + return nullptr; + } + return value->clone(); + } + + static std::unique_ptr<protocol::Value> serialize(Value* value) + { + return value->clone(); + } + + static std::unique_ptr<protocol::Value> serialize(const std::unique_ptr<Value>& value) + { + return value->clone(); + } +}; + +template<> +struct ValueConversions<DictionaryValue> { + static std::unique_ptr<DictionaryValue> parse(protocol::Value* value, ErrorSupport* errors) + { + bool success = value && value->type() == protocol::Value::TypeObject; + if (!success) + errors->addError("object expected"); + return DictionaryValue::cast(value->clone()); + } + + static std::unique_ptr<protocol::Value> serialize(DictionaryValue* value) + { + return value->clone(); + } + + static std::unique_ptr<protocol::Value> serialize(const std::unique_ptr<DictionaryValue>& value) + { + return value->clone(); + } +}; + +template<> +struct ValueConversions<ListValue> { + static std::unique_ptr<ListValue> parse(protocol::Value* value, ErrorSupport* errors) + { + bool success = value && value->type() == protocol::Value::TypeArray; + if (!success) + errors->addError("list expected"); + return ListValue::cast(value->clone()); + } + + static std::unique_ptr<protocol::Value> serialize(ListValue* value) + { + return value->clone(); + } + + static std::unique_ptr<protocol::Value> serialize(const std::unique_ptr<ListValue>& value) + { + return value->clone(); + } +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_ValueConversions_h) diff --git a/deps/v8/third_party/inspector_protocol/lib/Values_cpp.template b/deps/v8/third_party/inspector_protocol/lib/Values_cpp.template new file mode 100644 index 0000000000..1b5cdfee22 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Values_cpp.template @@ -0,0 +1,407 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//#include "Values.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +namespace { + +const char* const nullValueString = "null"; +const char* const trueValueString = "true"; +const char* const falseValueString = "false"; + +inline bool escapeChar(uint16_t c, StringBuilder* dst) +{ + switch (c) { + case '\b': dst->append("\\b"); break; + case '\f': dst->append("\\f"); break; + case '\n': dst->append("\\n"); break; + case '\r': dst->append("\\r"); break; + case '\t': dst->append("\\t"); break; + case '\\': dst->append("\\\\"); break; + case '"': dst->append("\\\""); break; + default: + return false; + } + return true; +} + +const char hexDigits[17] = "0123456789ABCDEF"; + +void appendUnsignedAsHex(uint16_t number, StringBuilder* dst) +{ + dst->append("\\u"); + for (size_t i = 0; i < 4; ++i) { + uint16_t c = hexDigits[(number & 0xF000) >> 12]; + dst->append(c); + number <<= 4; + } +} + +void escapeStringForJSON(const String& str, StringBuilder* dst) +{ + for (unsigned i = 0; i < str.length(); ++i) { + uint16_t c = str[i]; + if (!escapeChar(c, dst)) { + if (c < 32 || c > 126 || c == '<' || c == '>') { + // 1. Escaping <, > to prevent script execution. + // 2. Technically, we could also pass through c > 126 as UTF8, but this + // is also optional. It would also be a pain to implement here. + appendUnsignedAsHex(c, dst); + } else { + dst->append(c); + } + } + } +} + +void doubleQuoteStringForJSON(const String& str, StringBuilder* dst) +{ + dst->append('"'); + escapeStringForJSON(str, dst); + dst->append('"'); +} + +} // anonymous namespace + +bool Value::asBoolean(bool*) const +{ + return false; +} + +bool Value::asDouble(double*) const +{ + return false; +} + +bool Value::asInteger(int*) const +{ + return false; +} + +bool Value::asString(String*) const +{ + return false; +} + +bool Value::asSerialized(String*) const +{ + return false; +} + +String Value::toJSONString() const +{ + StringBuilder result; + StringUtil::builderReserve(result, 512); + writeJSON(&result); + return result.toString(); +} + +void Value::writeJSON(StringBuilder* output) const +{ + DCHECK(m_type == TypeNull); + output->append(nullValueString, 4); +} + +std::unique_ptr<Value> Value::clone() const +{ + return Value::null(); +} + +bool FundamentalValue::asBoolean(bool* output) const +{ + if (type() != TypeBoolean) + return false; + *output = m_boolValue; + return true; +} + +bool FundamentalValue::asDouble(double* output) const +{ + if (type() == TypeDouble) { + *output = m_doubleValue; + return true; + } + if (type() == TypeInteger) { + *output = m_integerValue; + return true; + } + return false; +} + +bool FundamentalValue::asInteger(int* output) const +{ + if (type() != TypeInteger) + return false; + *output = m_integerValue; + return true; +} + +void FundamentalValue::writeJSON(StringBuilder* output) const +{ + DCHECK(type() == TypeBoolean || type() == TypeInteger || type() == TypeDouble); + if (type() == TypeBoolean) { + if (m_boolValue) + output->append(trueValueString, 4); + else + output->append(falseValueString, 5); + } else if (type() == TypeDouble) { + if (!std::isfinite(m_doubleValue)) { + output->append(nullValueString, 4); + return; + } + output->append(StringUtil::fromDouble(m_doubleValue)); + } else if (type() == TypeInteger) { + output->append(StringUtil::fromInteger(m_integerValue)); + } +} + +std::unique_ptr<Value> FundamentalValue::clone() const +{ + switch (type()) { + case TypeDouble: return FundamentalValue::create(m_doubleValue); + case TypeInteger: return FundamentalValue::create(m_integerValue); + case TypeBoolean: return FundamentalValue::create(m_boolValue); + default: + DCHECK(false); + } + return nullptr; +} + +bool StringValue::asString(String* output) const +{ + *output = m_stringValue; + return true; +} + +void StringValue::writeJSON(StringBuilder* output) const +{ + DCHECK(type() == TypeString); + doubleQuoteStringForJSON(m_stringValue, output); +} + +std::unique_ptr<Value> StringValue::clone() const +{ + return StringValue::create(m_stringValue); +} + +bool SerializedValue::asSerialized(String* output) const +{ + *output = m_serializedValue; + return true; +} + +void SerializedValue::writeJSON(StringBuilder* output) const +{ + DCHECK(type() == TypeSerialized); + output->append(m_serializedValue); +} + +std::unique_ptr<Value> SerializedValue::clone() const +{ + return SerializedValue::create(m_serializedValue); +} + +DictionaryValue::~DictionaryValue() +{ +} + +void DictionaryValue::setBoolean(const String& name, bool value) +{ + setValue(name, FundamentalValue::create(value)); +} + +void DictionaryValue::setInteger(const String& name, int value) +{ + setValue(name, FundamentalValue::create(value)); +} + +void DictionaryValue::setDouble(const String& name, double value) +{ + setValue(name, FundamentalValue::create(value)); +} + +void DictionaryValue::setString(const String& name, const String& value) +{ + setValue(name, StringValue::create(value)); +} + +void DictionaryValue::setValue(const String& name, std::unique_ptr<Value> value) +{ + set(name, value); +} + +void DictionaryValue::setObject(const String& name, std::unique_ptr<DictionaryValue> value) +{ + set(name, value); +} + +void DictionaryValue::setArray(const String& name, std::unique_ptr<ListValue> value) +{ + set(name, value); +} + +bool DictionaryValue::getBoolean(const String& name, bool* output) const +{ + protocol::Value* value = get(name); + if (!value) + return false; + return value->asBoolean(output); +} + +bool DictionaryValue::getInteger(const String& name, int* output) const +{ + Value* value = get(name); + if (!value) + return false; + return value->asInteger(output); +} + +bool DictionaryValue::getDouble(const String& name, double* output) const +{ + Value* value = get(name); + if (!value) + return false; + return value->asDouble(output); +} + +bool DictionaryValue::getString(const String& name, String* output) const +{ + protocol::Value* value = get(name); + if (!value) + return false; + return value->asString(output); +} + +DictionaryValue* DictionaryValue::getObject(const String& name) const +{ + return DictionaryValue::cast(get(name)); +} + +protocol::ListValue* DictionaryValue::getArray(const String& name) const +{ + return ListValue::cast(get(name)); +} + +protocol::Value* DictionaryValue::get(const String& name) const +{ + Dictionary::const_iterator it = m_data.find(name); + if (it == m_data.end()) + return nullptr; + return it->second.get(); +} + +DictionaryValue::Entry DictionaryValue::at(size_t index) const +{ + const String key = m_order[index]; + return std::make_pair(key, m_data.find(key)->second.get()); +} + +bool DictionaryValue::booleanProperty(const String& name, bool defaultValue) const +{ + bool result = defaultValue; + getBoolean(name, &result); + return result; +} + +int DictionaryValue::integerProperty(const String& name, int defaultValue) const +{ + int result = defaultValue; + getInteger(name, &result); + return result; +} + +double DictionaryValue::doubleProperty(const String& name, double defaultValue) const +{ + double result = defaultValue; + getDouble(name, &result); + return result; +} + +void DictionaryValue::remove(const String& name) +{ + m_data.erase(name); + m_order.erase(std::remove(m_order.begin(), m_order.end(), name), m_order.end()); +} + +void DictionaryValue::writeJSON(StringBuilder* output) const +{ + output->append('{'); + for (size_t i = 0; i < m_order.size(); ++i) { + Dictionary::const_iterator it = m_data.find(m_order[i]); + CHECK(it != m_data.end()); + if (i) + output->append(','); + doubleQuoteStringForJSON(it->first, output); + output->append(':'); + it->second->writeJSON(output); + } + output->append('}'); +} + +std::unique_ptr<Value> DictionaryValue::clone() const +{ + std::unique_ptr<DictionaryValue> result = DictionaryValue::create(); + for (size_t i = 0; i < m_order.size(); ++i) { + String key = m_order[i]; + Dictionary::const_iterator value = m_data.find(key); + DCHECK(value != m_data.cend() && value->second); + result->setValue(key, value->second->clone()); + } + return std::move(result); +} + +DictionaryValue::DictionaryValue() + : Value(TypeObject) +{ +} + +ListValue::~ListValue() +{ +} + +void ListValue::writeJSON(StringBuilder* output) const +{ + output->append('['); + bool first = true; + for (const std::unique_ptr<protocol::Value>& value : m_data) { + if (!first) + output->append(','); + value->writeJSON(output); + first = false; + } + output->append(']'); +} + +std::unique_ptr<Value> ListValue::clone() const +{ + std::unique_ptr<ListValue> result = ListValue::create(); + for (const std::unique_ptr<protocol::Value>& value : m_data) + result->pushValue(value->clone()); + return std::move(result); +} + +ListValue::ListValue() + : Value(TypeArray) +{ +} + +void ListValue::pushValue(std::unique_ptr<protocol::Value> value) +{ + DCHECK(value); + m_data.push_back(std::move(value)); +} + +protocol::Value* ListValue::at(size_t index) +{ + DCHECK_LT(index, m_data.size()); + return m_data[index].get(); +} + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8/third_party/inspector_protocol/lib/Values_h.template b/deps/v8/third_party/inspector_protocol/lib/Values_h.template new file mode 100644 index 0000000000..8f75ef2220 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/lib/Values_h.template @@ -0,0 +1,246 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Values_h +#define {{"_".join(config.protocol.namespace)}}_Values_h + +//#include "Allocator.h" +//#include "Collections.h" +//#include "Forward.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +class ListValue; +class DictionaryValue; +class Value; + +class {{config.lib.export_macro}} Value { + PROTOCOL_DISALLOW_COPY(Value); +public: + virtual ~Value() { } + + static std::unique_ptr<Value> null() + { + return wrapUnique(new Value()); + } + + enum ValueType { + TypeNull = 0, + TypeBoolean, + TypeInteger, + TypeDouble, + TypeString, + TypeObject, + TypeArray, + TypeSerialized + }; + + ValueType type() const { return m_type; } + + bool isNull() const { return m_type == TypeNull; } + + virtual bool asBoolean(bool* output) const; + virtual bool asDouble(double* output) const; + virtual bool asInteger(int* output) const; + virtual bool asString(String* output) const; + virtual bool asSerialized(String* output) const; + + String toJSONString() const; + virtual void writeJSON(StringBuilder* output) const; + virtual std::unique_ptr<Value> clone() const; + +protected: + Value() : m_type(TypeNull) { } + explicit Value(ValueType type) : m_type(type) { } + +private: + friend class DictionaryValue; + friend class ListValue; + + ValueType m_type; +}; + +class {{config.lib.export_macro}} FundamentalValue : public Value { +public: + static std::unique_ptr<FundamentalValue> create(bool value) + { + return wrapUnique(new FundamentalValue(value)); + } + + static std::unique_ptr<FundamentalValue> create(int value) + { + return wrapUnique(new FundamentalValue(value)); + } + + static std::unique_ptr<FundamentalValue> create(double value) + { + return wrapUnique(new FundamentalValue(value)); + } + + bool asBoolean(bool* output) const override; + bool asDouble(double* output) const override; + bool asInteger(int* output) const override; + void writeJSON(StringBuilder* output) const override; + std::unique_ptr<Value> clone() const override; + +private: + explicit FundamentalValue(bool value) : Value(TypeBoolean), m_boolValue(value) { } + explicit FundamentalValue(int value) : Value(TypeInteger), m_integerValue(value) { } + explicit FundamentalValue(double value) : Value(TypeDouble), m_doubleValue(value) { } + + union { + bool m_boolValue; + double m_doubleValue; + int m_integerValue; + }; +}; + +class {{config.lib.export_macro}} StringValue : public Value { +public: + static std::unique_ptr<StringValue> create(const String& value) + { + return wrapUnique(new StringValue(value)); + } + + static std::unique_ptr<StringValue> create(const char* value) + { + return wrapUnique(new StringValue(value)); + } + + bool asString(String* output) const override; + void writeJSON(StringBuilder* output) const override; + std::unique_ptr<Value> clone() const override; + +private: + explicit StringValue(const String& value) : Value(TypeString), m_stringValue(value) { } + explicit StringValue(const char* value) : Value(TypeString), m_stringValue(value) { } + + String m_stringValue; +}; + +class {{config.lib.export_macro}} SerializedValue : public Value { +public: + static std::unique_ptr<SerializedValue> create(const String& value) + { + return wrapUnique(new SerializedValue(value)); + } + + bool asSerialized(String* output) const override; + void writeJSON(StringBuilder* output) const override; + std::unique_ptr<Value> clone() const override; + +private: + explicit SerializedValue(const String& value) : Value(TypeSerialized), m_serializedValue(value) { } + + String m_serializedValue; +}; + +class {{config.lib.export_macro}} DictionaryValue : public Value { +public: + using Entry = std::pair<String, Value*>; + static std::unique_ptr<DictionaryValue> create() + { + return wrapUnique(new DictionaryValue()); + } + + static DictionaryValue* cast(Value* value) + { + if (!value || value->type() != TypeObject) + return nullptr; + return static_cast<DictionaryValue*>(value); + } + + static std::unique_ptr<DictionaryValue> cast(std::unique_ptr<Value> value) + { + return wrapUnique(DictionaryValue::cast(value.release())); + } + + void writeJSON(StringBuilder* output) const override; + std::unique_ptr<Value> clone() const override; + + size_t size() const { return m_data.size(); } + + void setBoolean(const String& name, bool); + void setInteger(const String& name, int); + void setDouble(const String& name, double); + void setString(const String& name, const String&); + void setValue(const String& name, std::unique_ptr<Value>); + void setObject(const String& name, std::unique_ptr<DictionaryValue>); + void setArray(const String& name, std::unique_ptr<ListValue>); + + bool getBoolean(const String& name, bool* output) const; + bool getInteger(const String& name, int* output) const; + bool getDouble(const String& name, double* output) const; + bool getString(const String& name, String* output) const; + + DictionaryValue* getObject(const String& name) const; + ListValue* getArray(const String& name) const; + Value* get(const String& name) const; + Entry at(size_t index) const; + + bool booleanProperty(const String& name, bool defaultValue) const; + int integerProperty(const String& name, int defaultValue) const; + double doubleProperty(const String& name, double defaultValue) const; + void remove(const String& name); + + ~DictionaryValue() override; + +private: + DictionaryValue(); + template<typename T> + void set(const String& key, std::unique_ptr<T>& value) + { + DCHECK(value); + bool isNew = m_data.find(key) == m_data.end(); + m_data[key] = std::move(value); + if (isNew) + m_order.push_back(key); + } + + using Dictionary = protocol::HashMap<String, std::unique_ptr<Value>>; + Dictionary m_data; + std::vector<String> m_order; +}; + +class {{config.lib.export_macro}} ListValue : public Value { +public: + static std::unique_ptr<ListValue> create() + { + return wrapUnique(new ListValue()); + } + + static ListValue* cast(Value* value) + { + if (!value || value->type() != TypeArray) + return nullptr; + return static_cast<ListValue*>(value); + } + + static std::unique_ptr<ListValue> cast(std::unique_ptr<Value> value) + { + return wrapUnique(ListValue::cast(value.release())); + } + + ~ListValue() override; + + void writeJSON(StringBuilder* output) const override; + std::unique_ptr<Value> clone() const override; + + void pushValue(std::unique_ptr<Value>); + + Value* at(size_t index); + size_t size() const { return m_data.size(); } + +private: + ListValue(); + std::vector<std::unique_ptr<Value>> m_data; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // {{"_".join(config.protocol.namespace)}}_Values_h diff --git a/deps/v8/third_party/inspector_protocol/templates/Exported_h.template b/deps/v8/third_party/inspector_protocol/templates/Exported_h.template new file mode 100644 index 0000000000..3357f95b5e --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/templates/Exported_h.template @@ -0,0 +1,65 @@ +// This file is generated + +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_api_h +#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_api_h + +{% if config.exported.export_header %} +#include {{format_include(config.exported.export_header)}} +{% endif %} +#include {{format_include(config.exported.string_header)}} + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} +namespace {{domain.domain}} { +namespace API { + +// ------------- Enums. + {% for type in domain.types %} + {% if ("enum" in type) and type.exported %} + +namespace {{type.id}}Enum { + {% for literal in type.enum %} +{{config.exported.export_macro}} extern const char* {{ literal | dash_to_camelcase}}; + {% endfor %} +} // {{type.id}}Enum + {% endif %} + {% endfor %} + {% for command in join_arrays(domain, ["commands", "events"]) %} + {% for param in join_arrays(command, ["parameters", "returns"]) %} + {% if ("enum" in param) and (param.exported) %} + +namespace {{command.name | to_title_case}} { +namespace {{param.name | to_title_case}}Enum { + {% for literal in param.enum %} +{{config.exported.export_macro}} extern const char* {{ literal | dash_to_camelcase}}; + {% endfor %} +} // {{param.name | to_title_case}}Enum +} // {{command.name | to_title_case }} + {% endif %} + {% endfor %} + {% endfor %} + +// ------------- Types. + {% for type in domain.types %} + {% if not (type.type == "object") or not ("properties" in type) or not (type.exported) %}{% continue %}{% endif %} + +class {{config.exported.export_macro}} {{type.id}} { +public: + virtual {{config.exported.string_out}} toJSONString() const = 0; + virtual ~{{type.id}}() { } + static std::unique_ptr<protocol::{{domain.domain}}::API::{{type.id}}> fromJSONString(const {{config.exported.string_in}}& json); +}; + {% endfor %} + +} // namespace API +} // namespace {{domain.domain}} +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_api_h) diff --git a/deps/v8/third_party/inspector_protocol/templates/Imported_h.template b/deps/v8/third_party/inspector_protocol/templates/Imported_h.template new file mode 100644 index 0000000000..c23b8fe87c --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/templates/Imported_h.template @@ -0,0 +1,51 @@ +// This file is generated + +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h +#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h + +#include "{{config.protocol.package}}/Protocol.h" +#include {{format_include(config.imported.header if config.imported.header else "\"%s/%s.h\"" % (config.imported.package, domain.domain))}} + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + {% for type in domain.types %} + {% if not (type.type == "object") or not ("properties" in type) or not (type.exported) %}{% continue %}{% endif %} + +template<> +struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> { + static std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> parse(protocol::Value* value, ErrorSupport* errors) + { + if (!value) { + errors->addError("value expected"); + return nullptr; + } + String json = value->toJSONString(); + auto result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromJSONString({{config.imported.to_imported_string % "json"}}); + if (!result) + errors->addError("cannot parse"); + return result; + } + + static std::unique_ptr<protocol::Value> serialize(const {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}* value) + { + auto json = value->toJSONString(); + return SerializedValue::create({{config.imported.from_imported_string % "std::move(json)"}}); + } + + static std::unique_ptr<protocol::Value> serialize(const std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}>& value) + { + return serialize(value.get()); + } +}; + {% endfor %} + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h) diff --git a/deps/v8/third_party/inspector_protocol/templates/TypeBuilder_cpp.template b/deps/v8/third_party/inspector_protocol/templates/TypeBuilder_cpp.template new file mode 100644 index 0000000000..16f1ae516a --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/templates/TypeBuilder_cpp.template @@ -0,0 +1,364 @@ +// This file is generated + +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "{{config.protocol.package}}/{{domain.domain}}.h" + +#include "{{config.protocol.package}}/Protocol.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} +namespace {{domain.domain}} { + +// ------------- Enum values from types. + +const char Metainfo::domainName[] = "{{domain.domain}}"; +const char Metainfo::commandPrefix[] = "{{domain.domain}}."; +const char Metainfo::version[] = "{{domain.version}}"; + {% for type in domain.types %} + {% if "enum" in type %} + +namespace {{type.id}}Enum { + {% for literal in type.enum %} +const char* {{ literal | dash_to_camelcase}} = "{{literal}}"; + {% endfor %} +} // namespace {{type.id}}Enum + {% if type.exported %} + +namespace API { +namespace {{type.id}}Enum { + {% for literal in type.enum %} +const char* {{ literal | dash_to_camelcase}} = "{{literal}}"; + {% endfor %} +} // namespace {{type.id}}Enum +} // namespace API + {% endif %} + {% endif %} + {% for property in type.properties %} + {% if "enum" in property %} + + {% for literal in property.enum %} +const char* {{type.id}}::{{property.name | to_title_case}}Enum::{{literal | dash_to_camelcase}} = "{{literal}}"; + {% endfor %} + {% endif %} + {% endfor %} + {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %} + +std::unique_ptr<{{type.id}}> {{type.id}}::parse(protocol::Value* value, ErrorSupport* errors) +{ + if (!value || value->type() != protocol::Value::TypeObject) { + errors->addError("object expected"); + return nullptr; + } + + std::unique_ptr<{{type.id}}> result(new {{type.id}}()); + protocol::DictionaryValue* object = DictionaryValue::cast(value); + errors->push(); + {% for property in type.properties %} + protocol::Value* {{property.name}}Value = object->get("{{property.name}}"); + {% if property.optional %} + if ({{property.name}}Value) { + errors->setName("{{property.name}}"); + result->m_{{property.name}} = ValueConversions<{{resolve_type(property).raw_type}}>::parse({{property.name}}Value, errors); + } + {% else %} + errors->setName("{{property.name}}"); + result->m_{{property.name}} = ValueConversions<{{resolve_type(property).raw_type}}>::parse({{property.name}}Value, errors); + {% endif %} + {% endfor %} + errors->pop(); + if (errors->hasErrors()) + return nullptr; + return result; +} + +std::unique_ptr<protocol::DictionaryValue> {{type.id}}::serialize() const +{ + std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create(); + {% for property in type.properties %} + {% if property.optional %} + if (m_{{property.name}}.isJust()) + result->setValue("{{property.name}}", ValueConversions<{{resolve_type(property).raw_type}}>::serialize(m_{{property.name}}.fromJust())); + {% else %} + result->setValue("{{property.name}}", ValueConversions<{{resolve_type(property).raw_type}}>::serialize({{resolve_type(property).to_raw_type % ("m_" + property.name)}})); + {% endif %} + {% endfor %} + return result; +} + +std::unique_ptr<{{type.id}}> {{type.id}}::clone() const +{ + ErrorSupport errors; + return parse(serialize().get(), &errors); +} + {% if type.exported %} + +{{config.exported.string_out}} {{type.id}}::toJSONString() const +{ + String json = serialize()->toJSONString(); + return {{config.exported.to_string_out % "json"}}; +} + +// static +std::unique_ptr<API::{{type.id}}> API::{{type.id}}::fromJSONString(const {{config.exported.string_in}}& json) +{ + ErrorSupport errors; + std::unique_ptr<Value> value = parseJSON(json); + if (!value) + return nullptr; + return protocol::{{domain.domain}}::{{type.id}}::parse(value.get(), &errors); +} + {% endif %} + {% endfor %} + +// ------------- Enum values from params. + + {% for command in join_arrays(domain, ["commands", "events"]) %} + {% for param in join_arrays(command, ["parameters", "returns"]) %} + {% if "enum" in param %} + +namespace {{command.name | to_title_case}} { +namespace {{param.name | to_title_case}}Enum { + {% for literal in param.enum %} +const char* {{ literal | to_title_case}} = "{{literal}}"; + {% endfor %} +} // namespace {{param.name | to_title_case}}Enum +} // namespace {{command.name | to_title_case }} + {% if param.exported %} + +namespace API { +namespace {{command.name | to_title_case}} { +namespace {{param.name | to_title_case}}Enum { + {% for literal in param.enum %} +const char* {{ literal | to_title_case}} = "{{literal}}"; + {% endfor %} +} // namespace {{param.name | to_title_case}}Enum +} // namespace {{command.name | to_title_case }} +} // namespace API + {% endif %} + {% endif %} + {% endfor %} + {% endfor %} + +// ------------- Frontend notifications. + {% for event in domain.events %} + {% if "handlers" in event and not ("renderer" in event["handlers"]) %}{% continue %}{% endif %} + +void Frontend::{{event.name}}( + {%- for parameter in event.parameters %} + {% if "optional" in parameter -%} + Maybe<{{resolve_type(parameter).raw_type}}> + {%- else -%} + {{resolve_type(parameter).pass_type}} + {%- endif %} {{parameter.name}}{%- if not loop.last -%}, {% endif -%} + {% endfor -%}) +{ + std::unique_ptr<protocol::DictionaryValue> jsonMessage = DictionaryValue::create(); + jsonMessage->setString("method", "{{domain.domain}}.{{event.name}}"); + std::unique_ptr<protocol::DictionaryValue> paramsObject = DictionaryValue::create(); + {% for parameter in event.parameters %} + {% if "optional" in parameter %} + if ({{parameter.name}}.isJust()) + paramsObject->setValue("{{parameter.name}}", ValueConversions<{{resolve_type(parameter).raw_type}}>::serialize({{parameter.name}}.fromJust())); + {% else %} + paramsObject->setValue("{{parameter.name}}", ValueConversions<{{resolve_type(parameter).raw_type}}>::serialize({{resolve_type(parameter).to_raw_type % parameter.name}})); + {% endif %} + {% endfor %} + jsonMessage->setObject("params", std::move(paramsObject)); + if (m_frontendChannel) + m_frontendChannel->sendProtocolNotification(jsonMessage->toJSONString()); +} + {% endfor %} + +void Frontend::flush() +{ + m_frontendChannel->flushProtocolNotifications(); +} + +// --------------------- Dispatcher. + +class DispatcherImpl : public protocol::DispatcherBase { +public: + DispatcherImpl(FrontendChannel* frontendChannel, Backend* backend) + : DispatcherBase(frontendChannel) + , m_backend(backend) { + {% for command in domain.commands %} + {% if "redirect" in command %}{% continue %}{% endif %} + {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %} + m_dispatchMap["{{domain.domain}}.{{command.name}}"] = &DispatcherImpl::{{command.name}}; + {% endfor %} + } + ~DispatcherImpl() override { } + DispatchResponse::Status dispatch(int callId, const String& method, std::unique_ptr<protocol::DictionaryValue> messageObject) override; + +protected: + using CallHandler = DispatchResponse::Status (DispatcherImpl::*)(int callId, std::unique_ptr<DictionaryValue> messageObject, ErrorSupport* errors); + using DispatchMap = protocol::HashMap<String, CallHandler>; + DispatchMap m_dispatchMap; + + {% for command in domain.commands %} + {% if "redirect" in command %}{% continue %}{% endif %} + {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %} + DispatchResponse::Status {{command.name}}(int callId, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport*); + {% endfor %} + + Backend* m_backend; +}; + +DispatchResponse::Status DispatcherImpl::dispatch(int callId, const String& method, std::unique_ptr<protocol::DictionaryValue> messageObject) +{ + protocol::HashMap<String, CallHandler>::iterator it = m_dispatchMap.find(method); + if (it == m_dispatchMap.end()) { + reportProtocolError(callId, DispatchResponse::kMethodNotFound, "'" + method + "' wasn't found", nullptr); + return DispatchResponse::kError; + } + + protocol::ErrorSupport errors; + return (this->*(it->second))(callId, std::move(messageObject), &errors); +} + + {% for command in domain.commands %} + {% if "redirect" in command %}{% continue %}{% endif %} + {% if "handlers" in command and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %} + {% if "async" in command %} + +class {{command.name | to_title_case}}CallbackImpl : public Backend::{{command.name | to_title_case}}Callback, public DispatcherBase::Callback { +public: + {{command.name | to_title_case}}CallbackImpl(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId) + : DispatcherBase::Callback(std::move(backendImpl), callId) { } + + void sendSuccess( + {%- for parameter in command.returns -%} + {%- if "optional" in parameter -%} + Maybe<{{resolve_type(parameter).raw_type}}> {{parameter.name}} + {%- else -%} + {{resolve_type(parameter).pass_type}} {{parameter.name}} + {%- endif -%} + {%- if not loop.last -%}, {% endif -%} + {%- endfor -%}) override + { + std::unique_ptr<protocol::DictionaryValue> resultObject = DictionaryValue::create(); + {% for parameter in command.returns %} + {% if "optional" in parameter %} + if ({{parameter.name}}.isJust()) + resultObject->setValue("{{parameter.name}}", ValueConversions<{{resolve_type(parameter).raw_type}}>::serialize({{parameter.name}}.fromJust())); + {% else %} + resultObject->setValue("{{parameter.name}}", ValueConversions<{{resolve_type(parameter).raw_type}}>::serialize({{resolve_type(parameter).to_raw_type % parameter.name}})); + {% endif %} + {% endfor %} + sendIfActive(std::move(resultObject), DispatchResponse::OK()); + } + + void sendFailure(const DispatchResponse& response) override + { + DCHECK(response.status() == DispatchResponse::kError); + sendIfActive(nullptr, response); + } +}; + {% endif %} + +DispatchResponse::Status DispatcherImpl::{{command.name}}(int callId, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport* errors) +{ + {% if "parameters" in command %} + // Prepare input parameters. + protocol::DictionaryValue* object = DictionaryValue::cast(requestMessageObject->get("params")); + errors->push(); + {% for property in command.parameters %} + protocol::Value* {{property.name}}Value = object ? object->get("{{property.name}}") : nullptr; + {% if property.optional %} + Maybe<{{resolve_type(property).raw_type}}> in_{{property.name}}; + if ({{property.name}}Value) { + errors->setName("{{property.name}}"); + in_{{property.name}} = ValueConversions<{{resolve_type(property).raw_type}}>::parse({{property.name}}Value, errors); + } + {% else %} + errors->setName("{{property.name}}"); + {{resolve_type(property).type}} in_{{property.name}} = ValueConversions<{{resolve_type(property).raw_type}}>::parse({{property.name}}Value, errors); + {% endif %} + {% endfor %} + errors->pop(); + if (errors->hasErrors()) { + reportProtocolError(callId, DispatchResponse::kInvalidParams, kInvalidParamsString, errors); + return DispatchResponse::kError; + } + {% endif %} + {% if "returns" in command and not ("async" in command) %} + // Declare output parameters. + {% for property in command.returns %} + {% if "optional" in property %} + Maybe<{{resolve_type(property).raw_type}}> out_{{property.name}}; + {% else %} + {{resolve_type(property).type}} out_{{property.name}}; + {% endif %} + {% endfor %} + {% endif %} + + {% if not("async" in command) %} + std::unique_ptr<DispatcherBase::WeakPtr> weak = weakPtr(); + DispatchResponse response = m_backend->{{command.name}}( + {%- for property in command.parameters -%} + {%- if not loop.first -%}, {% endif -%} + {%- if "optional" in property -%} + std::move(in_{{property.name}}) + {%- else -%} + {{resolve_type(property).to_pass_type % ("in_" + property.name)}} + {%- endif -%} + {%- endfor %} + {%- if "returns" in command %} + {%- for property in command.returns -%} + {%- if not loop.first or command.parameters -%}, {% endif -%} + &out_{{property.name}} + {%- endfor %} + {% endif %}); + {% if "returns" in command %} + if (response.status() == DispatchResponse::kFallThrough) + return response.status(); + std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create(); + if (response.status() == DispatchResponse::kSuccess) { + {% for parameter in command.returns %} + {% if "optional" in parameter %} + if (out_{{parameter.name}}.isJust()) + result->setValue("{{parameter.name}}", ValueConversions<{{resolve_type(parameter).raw_type}}>::serialize(out_{{parameter.name}}.fromJust())); + {% else %} + result->setValue("{{parameter.name}}", ValueConversions<{{resolve_type(parameter).raw_type}}>::serialize({{resolve_type(parameter).to_raw_type % ("out_" + parameter.name)}})); + {% endif %} + {% endfor %} + } + if (weak->get()) + weak->get()->sendResponse(callId, response, std::move(result)); + {% else %} + if (weak->get()) + weak->get()->sendResponse(callId, response); + {% endif %} + return response.status(); + {% else %} + std::unique_ptr<{{command.name | to_title_case}}CallbackImpl> callback(new {{command.name | to_title_case}}CallbackImpl(weakPtr(), callId)); + m_backend->{{command.name}}( + {%- for property in command.parameters -%} + {%- if not loop.first -%}, {% endif -%} + {%- if "optional" in property -%} + std::move(in_{{property.name}}) + {%- else -%} + {{resolve_type(property).to_pass_type % ("in_" + property.name)}} + {%- endif -%} + {%- endfor -%} + {%- if command.parameters -%}, {% endif -%} + std::move(callback)); + return DispatchResponse::kAsync; + {% endif %} +} + {% endfor %} + +// static +void Dispatcher::wire(UberDispatcher* dispatcher, Backend* backend) +{ + dispatcher->registerBackend("{{domain.domain}}", wrapUnique(new DispatcherImpl(dispatcher->channel(), backend))); +} + +} // {{domain.domain}} +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8/third_party/inspector_protocol/templates/TypeBuilder_h.template b/deps/v8/third_party/inspector_protocol/templates/TypeBuilder_h.template new file mode 100644 index 0000000000..f665039dd7 --- /dev/null +++ b/deps/v8/third_party/inspector_protocol/templates/TypeBuilder_h.template @@ -0,0 +1,297 @@ +// This file is generated + +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h +#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h + +{% if config.protocol.export_header %} +#include {{format_include(config.protocol.export_header)}} +{% endif %} +#include "{{config.protocol.package}}/Protocol.h" +// For each imported domain we generate a ValueConversions struct instead of a full domain definition +// and include Domain::API version from there. +{% for name in domain.dependencies %} +#include "{{config.protocol.package}}/{{name}}.h" +{% endfor %} +{% if domain["has_exports"] %} +#include "{{config.exported.package}}/{{domain.domain}}.h" +{% endif %} + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} +namespace {{domain.domain}} { + +// ------------- Forward and enum declarations. + {% for type in domain.types %} + {% if type.type == "object" %} + {% if "properties" in type %} +// {{type.description}} +class {{type.id}}; + {% else %} +// {{type.description}} +using {{type.id}} = Object; + {% endif %} + {% elif type.type != "array" %} +// {{type.description}} +using {{type.id}} = {{resolve_type(type).type}}; + {% endif %} + {% endfor %} + {% for type in domain.types %} + {% if "enum" in type %} + +namespace {{type.id}}Enum { + {% for literal in type.enum %} +{{config.protocol.export_macro}} extern const char* {{ literal | dash_to_camelcase}}; + {% endfor %} +} // namespace {{type.id}}Enum + {% endif %} + {% endfor %} + {% for command in join_arrays(domain, ["commands", "events"]) %} + {% for param in join_arrays(command, ["parameters", "returns"]) %} + {% if "enum" in param %} + +namespace {{command.name | to_title_case}} { +namespace {{param.name | to_title_case}}Enum { + {% for literal in param.enum %} +{{config.protocol.export_macro}} extern const char* {{literal | dash_to_camelcase}}; + {% endfor %} +} // {{param.name | to_title_case}}Enum +} // {{command.name | to_title_case }} + {% endif %} + {% endfor %} + {% endfor %} + +// ------------- Type and builder declarations. + {% for type in domain.types %} + {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %} + {% set type_def = type_definition(domain.domain + "." + type.id)%} + +// {{type.description}} +class {{config.protocol.export_macro}} {{type.id}} {% if type.exported %}: public API::{{type.id}} {% endif %}{ + PROTOCOL_DISALLOW_COPY({{type.id}}); +public: + static std::unique_ptr<{{type.id}}> parse(protocol::Value* value, ErrorSupport* errors); + + ~{{type.id}}() { } + {% for property in type.properties %} + {% if "enum" in property %} + + struct {{config.protocol.export_macro}} {{property.name | to_title_case}}Enum { + {% for literal in property.enum %} + static const char* {{literal | dash_to_camelcase}}; + {% endfor %} + }; // {{property.name | to_title_case}}Enum + {% endif %} + + {% if property.optional %} + bool has{{property.name | to_title_case}}() { return m_{{property.name}}.isJust(); } + {{resolve_type(property).raw_return_type}} get{{property.name | to_title_case}}({{resolve_type(property).raw_pass_type}} defaultValue) { return m_{{property.name}}.isJust() ? m_{{property.name}}.fromJust() : defaultValue; } + {% else %} + {{resolve_type(property).raw_return_type}} get{{property.name | to_title_case}}() { return {{resolve_type(property).to_raw_type % ("m_" + property.name)}}; } + {% endif %} + void set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) { m_{{property.name}} = {{resolve_type(property).to_rvalue % "value"}}; } + {% endfor %} + + std::unique_ptr<protocol::DictionaryValue> serialize() const; + std::unique_ptr<{{type.id}}> clone() const; + {% if type.exported %} + {{config.exported.string_out}} toJSONString() const override; + {% endif %} + + template<int STATE> + class {{type.id}}Builder { + public: + enum { + NoFieldsSet = 0, + {% set count = 0 %} + {% for property in type.properties %} + {% if not(property.optional) %} + {% set count = count + 1 %} + {{property.name | to_title_case}}Set = 1 << {{count}}, + {% endif %} + {% endfor %} + AllFieldsSet = ( + {%- for property in type.properties %} + {% if not(property.optional) %}{{property.name | to_title_case}}Set | {%endif %} + {% endfor %}0)}; + + {% for property in type.properties %} + + {% if property.optional %} + {{type.id}}Builder<STATE>& set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) + { + m_result->set{{property.name | to_title_case}}({{resolve_type(property).to_rvalue % "value"}}); + return *this; + } + {% else %} + {{type.id}}Builder<STATE | {{property.name | to_title_case}}Set>& set{{property.name | to_title_case}}({{resolve_type(property).pass_type}} value) + { + static_assert(!(STATE & {{property.name | to_title_case}}Set), "property {{property.name}} should not be set yet"); + m_result->set{{property.name | to_title_case}}({{resolve_type(property).to_rvalue % "value"}}); + return castState<{{property.name | to_title_case}}Set>(); + } + {% endif %} + {% endfor %} + + std::unique_ptr<{{type.id}}> build() + { + static_assert(STATE == AllFieldsSet, "state should be AllFieldsSet"); + return std::move(m_result); + } + + private: + friend class {{type.id}}; + {{type.id}}Builder() : m_result(new {{type.id}}()) { } + + template<int STEP> {{type.id}}Builder<STATE | STEP>& castState() + { + return *reinterpret_cast<{{type.id}}Builder<STATE | STEP>*>(this); + } + + {{type_def.type}} m_result; + }; + + static {{type.id}}Builder<0> create() + { + return {{type.id}}Builder<0>(); + } + +private: + {{type.id}}() + { + {% for property in type.properties %} + {% if not(property.optional) and "default_value" in resolve_type(property) %} + m_{{property.name}} = {{resolve_type(property).default_value}}; + {%endif %} + {% endfor %} + } + + {% for property in type.properties %} + {% if property.optional %} + Maybe<{{resolve_type(property).raw_type}}> m_{{property.name}}; + {% else %} + {{resolve_type(property).type}} m_{{property.name}}; + {% endif %} + {% endfor %} +}; + + {% endfor %} + +// ------------- Backend interface. + +class {{config.protocol.export_macro}} Backend { +public: + virtual ~Backend() { } + + {% for command in domain.commands %} + {% if "redirect" in command %}{% continue %}{% endif %} + {% if ("handlers" in command) and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %} + {% if "async" in command %} + class {{config.protocol.export_macro}} {{command.name | to_title_case}}Callback { + public: + virtual void sendSuccess( + {%- for parameter in command.returns -%} + {%- if "optional" in parameter -%} + Maybe<{{resolve_type(parameter).raw_type}}> {{parameter.name}} + {%- else -%} + {{resolve_type(parameter).pass_type}} {{parameter.name}} + {%- endif -%} + {%- if not loop.last -%}, {% endif -%} + {%- endfor -%} + ) = 0; + virtual void sendFailure(const DispatchResponse&) = 0; + virtual ~{{command.name | to_title_case}}Callback() { } + }; + {% endif %} + {%- if not("async" in command) %} + virtual DispatchResponse {{command.name}}( + {%- else %} + virtual void {{command.name}}( + {%- endif %} + {%- for parameter in command.parameters -%} + {%- if not loop.first -%}, {% endif -%} + {%- if "optional" in parameter -%} + Maybe<{{resolve_type(parameter).raw_type}}> in_{{parameter.name}} + {%- else -%} + {{resolve_type(parameter).pass_type}} in_{{parameter.name}} + {%- endif -%} + {%- endfor -%} + {%- if "async" in command -%} + {%- if command.parameters -%}, {% endif -%} + std::unique_ptr<{{command.name | to_title_case}}Callback> callback + {%- else -%} + {%- for parameter in command.returns -%} + {%- if (not loop.first) or command.parameters -%}, {% endif -%} + {%- if "optional" in parameter -%} + Maybe<{{resolve_type(parameter).raw_type}}>* out_{{parameter.name}} + {%- else -%} + {{resolve_type(parameter).type}}* out_{{parameter.name}} + {%- endif -%} + {%- endfor -%} + {%- endif -%} + ) = 0; + {% endfor %} + + {% if not has_disable(domain.commands) %} + virtual DispatchResponse disable() + { + return DispatchResponse::OK(); + } + {% endif %} +}; + +// ------------- Frontend interface. + +class {{config.protocol.export_macro}} Frontend { +public: + Frontend(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { } + {% for event in domain.events %} + {% if "handlers" in event and not ("renderer" in event["handlers"]) %}{% continue %}{% endif %} + void {{event.name}}( + {%- for parameter in event.parameters -%} + {%- if "optional" in parameter -%} + Maybe<{{resolve_type(parameter).raw_type}}> {{parameter.name}} = Maybe<{{resolve_type(parameter).raw_type}}>() + {%- else -%} + {{resolve_type(parameter).pass_type}} {{parameter.name}} + {%- endif -%}{%- if not loop.last -%}, {% endif -%} + {%- endfor -%} + ); + {% endfor %} + + void flush(); +private: + FrontendChannel* m_frontendChannel; +}; + +// ------------- Dispatcher. + +class {{config.protocol.export_macro}} Dispatcher { +public: + static void wire(UberDispatcher*, Backend*); + +private: + Dispatcher() { } +}; + +// ------------- Metainfo. + +class {{config.protocol.export_macro}} Metainfo { +public: + using BackendClass = Backend; + using FrontendClass = Frontend; + using DispatcherClass = Dispatcher; + static const char domainName[]; + static const char commandPrefix[]; + static const char version[]; +}; + +} // namespace {{domain.domain}} +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h) |