Import Cobalt 13.102542

Change-Id: I6bda7b03a2e33edfd735efcb981e2a731696b90d
diff --git a/src/v8/third_party/inspector_protocol/CheckProtocolCompatibility.py b/src/v8/third_party/inspector_protocol/CheckProtocolCompatibility.py
new file mode 100755
index 0000000..dd9acad
--- /dev/null
+++ b/src/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/src/v8/third_party/inspector_protocol/CodeGenerator.py b/src/v8/third_party/inspector_protocol/CodeGenerator.py
new file mode 100644
index 0000000..8b28d13
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/CodeGenerator.py
@@ -0,0 +1,592 @@
+# 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
+import re
+import copy
+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")
+        cmdline_parser.add_option("--config_value", action="append", type="string")
+        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)
+        config_values = arg_options.config_value
+        if not config_values:
+            config_values = []
+    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 = {
+            ".use_snake_file_names": False,
+            ".use_title_case_methods": False,
+            ".imported": False,
+            ".imported.export_macro": "",
+            ".imported.export_header": False,
+            ".imported.header": False,
+            ".imported.package": False,
+            ".imported.options": False,
+            ".protocol.export_macro": "",
+            ".protocol.export_header": False,
+            ".protocol.options": False,
+            ".exported": False,
+            ".exported.export_macro": "",
+            ".exported.export_header": False,
+            ".lib": False,
+            ".lib.export_macro": "",
+            ".lib.export_header": False,
+        }
+        for key_value in config_values:
+            parts = key_value.split("=")
+            if len(parts) == 2:
+                defaults["." + parts[0]] = parts[1]
+        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)
+
+
+# ---- Begin of utilities exposed to generator ----
+
+
+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 to_snake_case(name):
+    return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", name, sys.maxint).lower()
+
+
+def to_method_case(config, name):
+    if config.use_title_case_methods:
+        return to_title_case(name)
+    return name
+
+
+def join_arrays(dict, keys):
+    result = []
+    for key in keys:
+        if key in dict:
+            result += dict[key]
+    return result
+
+
+def format_include(config, header, file_name=None):
+    if file_name is not None:
+        header = header + "/" + file_name + ".h"
+    header = "\"" + header + "\"" if header[0] not in "<\"" else header
+    if config.use_snake_file_names:
+        header = to_snake_case(header)
+    return header
+
+
+def to_file_name(config, file_name):
+    if config.use_snake_file_names:
+        return to_snake_case(file_name).replace(".cpp", ".cc")
+    return file_name
+
+
+# ---- End of utilities exposed to generator ----
+
+
+def initialize_jinja_env(jinja_dir, cache_dir, config):
+    # 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, "to_method_case": functools.partial(to_method_case, config)})
+    jinja_env.add_extension("jinja2.ext.loopcontrols")
+    return jinja_env
+
+
+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"],
+        "out_type": "protocol::Array<%s>&" % type["raw_type"],
+    }
+
+
+class Protocol(object):
+    def __init__(self, config):
+        self.config = config
+        self.json_api = {"domains": []}
+        self.imported_domains = []
+        self.exported_domains = []
+        self.generate_domains = self.read_protocol_file(config.protocol.path)
+
+        if config.protocol.options:
+            self.generate_domains = [rule.domain for rule in config.protocol.options]
+            self.exported_domains = [rule.domain for rule in config.protocol.options if hasattr(rule, "exported")]
+
+        if config.imported:
+            self.imported_domains = self.read_protocol_file(config.imported.path)
+            if config.imported.options:
+                self.imported_domains = [rule.domain for rule in config.imported.options]
+
+        self.patch_full_qualified_refs()
+        self.create_notification_types()
+        self.create_type_definitions()
+
+
+    def read_protocol_file(self, file_name):
+        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
+        self.json_api["domains"] += parsed_json["domains"]
+        return domains
+
+
+    def patch_full_qualified_refs(self):
+        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 self.json_api["domains"]:
+            patch_full_qualified_refs_in_domain(domain, domain["domain"])
+
+
+    def create_notification_types(self):
+        for domain in self.json_api["domains"]:
+            if "events" in domain:
+                for event in domain["events"]:
+                    event_type = dict()
+                    event_type["description"] = "Wrapper for notification params"
+                    event_type["type"] = "object"
+                    event_type["id"] = to_title_case(event["name"]) + "Notification"
+                    if "parameters" in event:
+                        event_type["properties"] = copy.deepcopy(event["parameters"])
+                    if "types" not in domain:
+                        domain["types"] = list()
+                    domain["types"].append(event_type)
+
+
+    def create_type_definitions(self):
+        imported_namespace = "::".join(self.config.imported.namespace) if self.config.imported else ""
+        self.type_definitions = {}
+        self.type_definitions["number"] = create_primitive_type_definition("number")
+        self.type_definitions["integer"] = create_primitive_type_definition("integer")
+        self.type_definitions["boolean"] = create_primitive_type_definition("boolean")
+        self.type_definitions["object"] = create_object_type_definition()
+        self.type_definitions["any"] = create_any_type_definition()
+        for domain in self.json_api["domains"]:
+            self.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 self.imported_domains:
+                    self.type_definitions[type_name] = create_imported_type_definition(domain["domain"], type, imported_namespace)
+                elif type["type"] == "object":
+                    self.type_definitions[type_name] = create_user_type_definition(domain["domain"], type)
+                elif type["type"] == "array":
+                    items_type = type["items"]["type"]
+                    self.type_definitions[type_name] = wrap_array_definition(self.type_definitions[items_type])
+                elif type["type"] == domain["domain"] + ".string":
+                    self.type_definitions[type_name] = create_string_type_definition()
+                else:
+                    self.type_definitions[type_name] = create_primitive_type_definition(type["type"])
+
+
+    def check_options(self, options, domain, name, include_attr, exclude_attr, default):
+        for rule in options:
+            if rule.domain != domain:
+                continue
+            if include_attr and hasattr(rule, include_attr):
+                return name in getattr(rule, include_attr)
+            if exclude_attr and hasattr(rule, exclude_attr):
+                return name not in getattr(rule, exclude_attr)
+            return default
+        return False
+
+
+    # ---- Begin of methods exposed to generator
+
+
+    def type_definition(self, name):
+        return self.type_definitions[name]
+
+
+    def resolve_type(self, prop):
+        if "$ref" in prop:
+            return self.type_definitions[prop["$ref"]]
+        if prop["type"] == "array":
+            return wrap_array_definition(self.resolve_type(prop["items"]))
+        return self.type_definitions[prop["type"]]
+
+
+    def generate_command(self, domain, command):
+        if not self.config.protocol.options:
+            return domain in self.generate_domains
+        return self.check_options(self.config.protocol.options, domain, command, "include", "exclude", True)
+
+
+    def generate_event(self, domain, event):
+        if not self.config.protocol.options:
+            return domain in self.generate_domains
+        return self.check_options(self.config.protocol.options, domain, event, "include_events", "exclude_events", True)
+
+
+    def is_async_command(self, domain, command):
+        if not self.config.protocol.options:
+            return False
+        return self.check_options(self.config.protocol.options, domain, command, "async", None, False)
+
+
+    def is_exported(self, domain, name):
+        if not self.config.protocol.options:
+            return False
+        return self.check_options(self.config.protocol.options, domain, name, "exported", None, False)
+
+
+    def is_imported(self, domain, name):
+        if not self.config.imported:
+            return False
+        if not self.config.imported.options:
+            return domain in self.imported_domains
+        return self.check_options(self.config.imported.options, domain, name, "imported", None, False)
+
+
+    def is_exported_domain(self, domain):
+        return domain in self.exported_domains
+
+
+    def generate_disable(self, domain):
+        if "commands" not in domain:
+            return True
+        for command in domain["commands"]:
+            if command["name"] == "disable" and self.generate_command(domain["domain"], "disable"):
+                return False
+        return True
+
+
+def main():
+    jinja_dir, config_file, config = read_config()
+
+    protocol = Protocol(config)
+
+    if not config.exported and len(protocol.exported_domains):
+        sys.stderr.write("Domains [%s] are exported, but config is missing export entry\n\n" % ", ".join(protocol.exported_domains))
+        exit(1)
+
+    if not os.path.exists(config.protocol.output):
+        os.mkdir(config.protocol.output)
+    if len(protocol.exported_domains) and not os.path.exists(config.exported.output):
+        os.mkdir(config.exported.output)
+    jinja_env = initialize_jinja_env(jinja_dir, config.protocol.output, config)
+
+    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 = {
+            "protocol": protocol,
+            "config": config,
+            "domain": domain,
+            "join_arrays": join_arrays,
+            "format_include": functools.partial(format_include, config),
+        }
+
+        if domain["domain"] in protocol.generate_domains:
+            outputs[os.path.join(config.protocol.output, to_file_name(config, class_name + ".h"))] = h_template.render(template_context)
+            outputs[os.path.join(config.protocol.output, to_file_name(config, class_name + ".cpp"))] = cpp_template.render(template_context)
+            if domain["domain"] in protocol.exported_domains:
+                outputs[os.path.join(config.exported.output, to_file_name(config, class_name + ".h"))] = exported_template.render(template_context)
+        if domain["domain"] in protocol.imported_domains:
+            outputs[os.path.join(config.protocol.output, to_file_name(config, class_name + ".h"))] = imported_template.render(template_context)
+
+    if config.lib:
+        template_context = {
+            "config": config,
+            "format_include": functools.partial(format_include, config),
+        }
+
+        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, to_file_name(config, "Forward.h")), forward_h_templates)
+        generate_lib_file(os.path.join(config.lib.output, to_file_name(config, "Protocol.h")), lib_h_templates)
+        generate_lib_file(os.path.join(config.lib.output, to_file_name(config, "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/src/v8/third_party/inspector_protocol/ConcatenateProtocols.py b/src/v8/third_party/inspector_protocol/ConcatenateProtocols.py
new file mode 100755
index 0000000..a7cbc99
--- /dev/null
+++ b/src/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/src/v8/third_party/inspector_protocol/LICENSE b/src/v8/third_party/inspector_protocol/LICENSE
new file mode 100644
index 0000000..800468e
--- /dev/null
+++ b/src/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/src/v8/third_party/inspector_protocol/README.v8 b/src/v8/third_party/inspector_protocol/README.v8
new file mode 100644
index 0000000..b13c906
--- /dev/null
+++ b/src/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: 1a7cbe8ba8fa0d622586f549a97c73d9b52efbea
+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/src/v8/third_party/inspector_protocol/inspector_protocol.gni b/src/v8/third_party/inspector_protocol/inspector_protocol.gni
new file mode 100644
index 0000000..5dcc1f5
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/inspector_protocol.gni
@@ -0,0 +1,89 @@
+# 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),
+    ]
+
+    if (defined(invoker.config_values)) {
+      foreach(value, invoker.config_values) {
+        args += [
+          "--config_value",
+          value,
+        ]
+      }
+    }
+
+    outputs = get_path_info(rebase_path(invoker.outputs, ".", invoker.out_dir),
+                            "abspath")
+
+    forward_variables_from(invoker,
+                           [
+                             "visibility",
+                             "deps",
+                             "public_deps",
+                           ])
+  }
+}
diff --git a/src/v8/third_party/inspector_protocol/inspector_protocol.gypi b/src/v8/third_party/inspector_protocol/inspector_protocol.gypi
new file mode 100644
index 0000000..1fb7119
--- /dev/null
+++ b/src/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/src/v8/third_party/inspector_protocol/lib/Allocator_h.template b/src/v8/third_party/inspector_protocol/lib/Allocator_h.template
new file mode 100644
index 0000000..8f8109d
--- /dev/null
+++ b/src/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/src/v8/third_party/inspector_protocol/lib/Array_h.template b/src/v8/third_party/inspector_protocol/lib/Array_h.template
new file mode 100644
index 0000000..3854f6e
--- /dev/null
+++ b/src/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 std::unique_ptr<Array<T>>(new Array<T>());
+    }
+
+    static std::unique_ptr<Array<T>> fromValue(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>::fromValue(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> toValue()
+    {
+        std::unique_ptr<protocol::ListValue> result = ListValue::create();
+        for (auto& item : m_vector)
+            result->pushValue(ValueConversions<T>::toValue(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 std::unique_ptr<Array<T>>(new Array<T>());
+    }
+
+    static std::unique_ptr<Array<T>> fromValue(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>::fromValue(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> toValue()
+    {
+        std::unique_ptr<protocol::ListValue> result = ListValue::create();
+        for (auto& item : m_vector)
+            result->pushValue(ValueConversions<T>::toValue(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/src/v8/third_party/inspector_protocol/lib/Collections_h.template b/src/v8/third_party/inspector_protocol/lib/Collections_h.template
new file mode 100644
index 0000000..7505a17
--- /dev/null
+++ b/src/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 {{format_include(config.protocol.package, "Forward")}}
+#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/src/v8/third_party/inspector_protocol/lib/DispatcherBase_cpp.template b/src/v8/third_party/inspector_protocol/lib/DispatcherBase_cpp.template
new file mode 100644
index 0000000..fac5553
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/lib/DispatcherBase_cpp.template
@@ -0,0 +1,334 @@
+// 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::InvalidParams(const String& error)
+{
+    DispatchResponse result;
+    result.m_status = kError;
+    result.m_errorCode = kInvalidParams;
+    result.m_errorMessage = 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, int callbackId)
+    : m_backendImpl(std::move(backendImpl))
+    , m_callId(callId)
+    , m_callbackId(callbackId) { }
+
+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;
+}
+
+void DispatcherBase::Callback::fallThroughIfActive()
+{
+    if (!m_backendImpl || !m_backendImpl->get())
+        return;
+    m_backendImpl->get()->markFallThrough(m_callbackId);
+    m_backendImpl = nullptr;
+}
+
+DispatcherBase::DispatcherBase(FrontendChannel* frontendChannel)
+    : m_frontendChannel(frontendChannel)
+    , m_lastCallbackId(0)
+    , m_lastCallbackFallThrough(false) { }
+
+DispatcherBase::~DispatcherBase()
+{
+    clearFrontend();
+}
+
+int DispatcherBase::nextCallbackId()
+{
+    m_lastCallbackFallThrough = false;
+    return ++m_lastCallbackId;
+}
+
+void DispatcherBase::markFallThrough(int callbackId)
+{
+    DCHECK(callbackId == m_lastCallbackId);
+    m_lastCallbackFallThrough = true;
+}
+
+// static
+bool DispatcherBase::getCommandName(const String& message, String* result)
+{
+    std::unique_ptr<protocol::Value> value = StringUtil::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 (!m_frontendChannel)
+        return;
+    if (response.status() == DispatchResponse::kError) {
+        reportProtocolError(callId, response.errorCode(), response.errorMessage(), nullptr);
+        return;
+    }
+    m_frontendChannel->sendProtocolResponse(callId, InternalResponse::createResponse(callId, std::move(result)));
+}
+
+void DispatcherBase::sendResponse(int callId, const DispatchResponse& response)
+{
+    sendResponse(callId, response, DictionaryValue::create());
+}
+
+namespace {
+
+class ProtocolError : public Serializable {
+public:
+    static std::unique_ptr<ProtocolError> createErrorResponse(int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors)
+    {
+        std::unique_ptr<ProtocolError> protocolError(new ProtocolError(code, errorMessage));
+        protocolError->m_callId = callId;
+        protocolError->m_hasCallId = true;
+        if (errors && errors->hasErrors())
+            protocolError->m_data = errors->errors();
+        return protocolError;
+    }
+
+    static std::unique_ptr<ProtocolError> createErrorNotification(DispatchResponse::ErrorCode code, const String& errorMessage)
+    {
+        return std::unique_ptr<ProtocolError>(new ProtocolError(code, errorMessage));
+    }
+
+    String serialize() override
+    {
+        std::unique_ptr<protocol::DictionaryValue> error = DictionaryValue::create();
+        error->setInteger("code", m_code);
+        error->setString("message", m_errorMessage);
+        if (m_data.length())
+            error->setString("data", m_data);
+        std::unique_ptr<protocol::DictionaryValue> message = DictionaryValue::create();
+        message->setObject("error", std::move(error));
+        if (m_hasCallId)
+            message->setInteger("id", m_callId);
+        return message->serialize();
+    }
+
+    ~ProtocolError() override {}
+
+private:
+    ProtocolError(DispatchResponse::ErrorCode code, const String& errorMessage)
+        : m_code(code)
+        , m_errorMessage(errorMessage)
+    {
+    }
+
+    DispatchResponse::ErrorCode m_code;
+    String m_errorMessage;
+    String m_data;
+    int m_callId = 0;
+    bool m_hasCallId = false;
+};
+
+} // namespace
+
+static void reportProtocolErrorTo(FrontendChannel* frontendChannel, int callId, DispatchResponse::ErrorCode code, const String& errorMessage, ErrorSupport* errors)
+{
+    if (frontendChannel)
+        frontendChannel->sendProtocolResponse(callId, ProtocolError::createErrorResponse(callId, code, errorMessage, errors));
+}
+
+static void reportProtocolErrorTo(FrontendChannel* frontendChannel, DispatchResponse::ErrorCode code, const String& errorMessage)
+{
+    if (frontendChannel)
+        frontendChannel->sendProtocolNotification(ProtocolError::createErrorNotification(code, errorMessage));
+}
+
+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)
+    , m_fallThroughForNotFound(false) { }
+
+void UberDispatcher::setFallThroughForNotFound(bool fallThroughForNotFound)
+{
+    m_fallThroughForNotFound = fallThroughForNotFound;
+}
+
+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 = StringUtil::find(method, ".");
+    if (dotIndex == StringUtil::kNotFound) {
+        if (m_fallThroughForNotFound)
+            return DispatchResponse::kFallThrough;
+        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()) {
+        if (m_fallThroughForNotFound)
+            return DispatchResponse::kFallThrough;
+        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;
+
+// static
+std::unique_ptr<InternalResponse> InternalResponse::createResponse(int callId, std::unique_ptr<Serializable> params)
+{
+    return std::unique_ptr<InternalResponse>(new InternalResponse(callId, String(), std::move(params)));
+}
+
+// static
+std::unique_ptr<InternalResponse> InternalResponse::createNotification(const String& notification, std::unique_ptr<Serializable> params)
+{
+    return std::unique_ptr<InternalResponse>(new InternalResponse(0, notification, std::move(params)));
+}
+
+String InternalResponse::serialize()
+{
+    std::unique_ptr<DictionaryValue> result = DictionaryValue::create();
+    std::unique_ptr<Serializable> params(m_params ? std::move(m_params) : DictionaryValue::create());
+    if (m_notification.length()) {
+        result->setString("method", m_notification);
+        result->setValue("params", SerializedValue::create(params->serialize()));
+    } else {
+        result->setInteger("id", m_callId);
+        result->setValue("result", SerializedValue::create(params->serialize()));
+    }
+    return result->serialize();
+}
+
+InternalResponse::InternalResponse(int callId, const String& notification, std::unique_ptr<Serializable> params)
+    : m_callId(callId)
+    , m_notification(notification)
+    , m_params(params ? std::move(params) : nullptr)
+{
+}
+
+{% for namespace in config.protocol.namespace %}
+} // namespace {{namespace}}
+{% endfor %}
diff --git a/src/v8/third_party/inspector_protocol/lib/DispatcherBase_h.template b/src/v8/third_party/inspector_protocol/lib/DispatcherBase_h.template
new file mode 100644
index 0000000..3a6069b
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/lib/DispatcherBase_h.template
@@ -0,0 +1,172 @@
+// 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 InvalidParams(const String&);
+    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, int callbackId);
+        virtual ~Callback();
+        void dispose();
+
+    protected:
+        void sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const DispatchResponse& response);
+        void fallThroughIfActive();
+
+    private:
+        std::unique_ptr<WeakPtr> m_backendImpl;
+        int m_callId;
+        int m_callbackId;
+    };
+
+    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();
+
+    int nextCallbackId();
+    void markFallThrough(int callbackId);
+    bool lastCallbackFallThrough() { return m_lastCallbackFallThrough; }
+
+private:
+    FrontendChannel* m_frontendChannel;
+    protocol::HashSet<WeakPtr*> m_weakPtrs;
+    int m_lastCallbackId;
+    bool m_lastCallbackFallThrough;
+};
+
+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; }
+    bool fallThroughForNotFound() { return m_fallThroughForNotFound; }
+    void setFallThroughForNotFound(bool);
+    virtual ~UberDispatcher();
+
+private:
+    FrontendChannel* m_frontendChannel;
+    bool m_fallThroughForNotFound;
+    protocol::HashMap<String, std::unique_ptr<protocol::DispatcherBase>> m_dispatchers;
+};
+
+class InternalResponse : public Serializable {
+    PROTOCOL_DISALLOW_COPY(InternalResponse);
+public:
+    static std::unique_ptr<InternalResponse> createResponse(int callId, std::unique_ptr<Serializable> params);
+    static std::unique_ptr<InternalResponse> createNotification(const String& notification, std::unique_ptr<Serializable> params = nullptr);
+
+    String serialize() override;
+
+    ~InternalResponse() override {}
+
+private:
+    InternalResponse(int callId, const String& notification, std::unique_ptr<Serializable> params);
+
+    int m_callId;
+    String m_notification;
+    std::unique_ptr<Serializable> m_params;
+};
+
+class InternalRawNotification : public Serializable {
+public:
+    static std::unique_ptr<InternalRawNotification> create(const String& notification)
+    {
+        return std::unique_ptr<InternalRawNotification>(new InternalRawNotification(notification));
+    }
+    ~InternalRawNotification() override {}
+
+    String serialize() override
+    {
+        return m_notification;
+    }
+
+private:
+  explicit InternalRawNotification(const String& notification)
+    : m_notification(notification)
+  {
+  }
+
+  String m_notification;
+};
+
+{% for namespace in config.protocol.namespace %}
+} // namespace {{namespace}}
+{% endfor %}
+
+#endif // !defined({{"_".join(config.protocol.namespace)}}_DispatcherBase_h)
diff --git a/src/v8/third_party/inspector_protocol/lib/ErrorSupport_cpp.template b/src/v8/third_party/inspector_protocol/lib/ErrorSupport_cpp.template
new file mode 100644
index 0000000..2108262
--- /dev/null
+++ b/src/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)
+            StringUtil::builderAppend(builder, '.');
+        StringUtil::builderAppend(builder, m_path[i]);
+    }
+    StringUtil::builderAppend(builder, ": ");
+    StringUtil::builderAppend(builder, error);
+    m_errors.push_back(StringUtil::builderToString(builder));
+}
+
+bool ErrorSupport::hasErrors()
+{
+    return !!m_errors.size();
+}
+
+String ErrorSupport::errors()
+{
+    StringBuilder builder;
+    for (size_t i = 0; i < m_errors.size(); ++i) {
+        if (i)
+            StringUtil::builderAppend(builder, "; ");
+        StringUtil::builderAppend(builder, m_errors[i]);
+    }
+    return StringUtil::builderToString(builder);
+}
+
+{% for namespace in config.protocol.namespace %}
+} // namespace {{namespace}}
+{% endfor %}
diff --git a/src/v8/third_party/inspector_protocol/lib/ErrorSupport_h.template b/src/v8/third_party/inspector_protocol/lib/ErrorSupport_h.template
new file mode 100644
index 0000000..0c98e3e
--- /dev/null
+++ b/src/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/src/v8/third_party/inspector_protocol/lib/Forward_h.template b/src/v8/third_party/inspector_protocol/lib/Forward_h.template
new file mode 100644
index 0000000..34d1c0d
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/lib/Forward_h.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.
+
+#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.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/src/v8/third_party/inspector_protocol/lib/FrontendChannel_h.template b/src/v8/third_party/inspector_protocol/lib/FrontendChannel_h.template
new file mode 100644
index 0000000..0454978
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/lib/FrontendChannel_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)}}_FrontendChannel_h
+#define {{"_".join(config.protocol.namespace)}}_FrontendChannel_h
+
+{% for namespace in config.protocol.namespace %}
+namespace {{namespace}} {
+{% endfor %}
+
+class {{config.lib.export_macro}} Serializable {
+public:
+    virtual String serialize() = 0;
+    virtual ~Serializable() = default;
+};
+
+class {{config.lib.export_macro}} FrontendChannel {
+public:
+    virtual ~FrontendChannel() { }
+    virtual void sendProtocolResponse(int callId, std::unique_ptr<Serializable> message) = 0;
+    virtual void sendProtocolNotification(std::unique_ptr<Serializable> 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/src/v8/third_party/inspector_protocol/lib/Maybe_h.template b/src/v8/third_party/inspector_protocol/lib/Maybe_h.template
new file mode 100644
index 0000000..71593ac
--- /dev/null
+++ b/src/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 std::move(m_value); }
+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/src/v8/third_party/inspector_protocol/lib/Object_cpp.template b/src/v8/third_party/inspector_protocol/lib/Object_cpp.template
new file mode 100644
index 0000000..91723a7
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/lib/Object_cpp.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.
+
+//#include "Object.h"
+
+{% for namespace in config.protocol.namespace %}
+namespace {{namespace}} {
+{% endfor %}
+
+std::unique_ptr<Object> Object::fromValue(protocol::Value* value, ErrorSupport* errors)
+{
+    protocol::DictionaryValue* dictionary = DictionaryValue::cast(value);
+    if (!dictionary) {
+        errors->addError("object expected");
+        return nullptr;
+    }
+    dictionary = static_cast<protocol::DictionaryValue*>(dictionary->clone().release());
+    return std::unique_ptr<Object>(new Object(std::unique_ptr<DictionaryValue>(dictionary)));
+}
+
+std::unique_ptr<protocol::DictionaryValue> Object::toValue() const
+{
+    return DictionaryValue::cast(m_object->clone());
+}
+
+std::unique_ptr<Object> Object::clone() const
+{
+    return std::unique_ptr<Object>(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/src/v8/third_party/inspector_protocol/lib/Object_h.template b/src/v8/third_party/inspector_protocol/lib/Object_h.template
new file mode 100644
index 0000000..f6ffc57
--- /dev/null
+++ b/src/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> fromValue(protocol::Value*, ErrorSupport*);
+    ~Object();
+
+    std::unique_ptr<protocol::DictionaryValue> toValue() 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/src/v8/third_party/inspector_protocol/lib/Parser_cpp.template b/src/v8/third_party/inspector_protocol/lib/Parser_cpp.template
new file mode 100644
index 0000000..f3dde5a
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/lib/Parser_cpp.template
@@ -0,0 +1,547 @@
+// 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');
+    return StringUtil::toDouble(buffer.data(), length, ok);
+}
+
+double charactersToDouble(const uint8_t* characters, size_t length, bool* ok)
+{
+    std::string buffer(reinterpret_cast<const char*>(characters), length);
+    return StringUtil::toDouble(buffer.data(), length, ok);
+}
+
+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) {
+            StringUtil::builderAppend(*output, 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;
+        }
+        StringUtil::builderAppend(*output, 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 = StringUtil::builderToString(buffer);
+    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> parseJSONCharacters(const uint16_t* characters, unsigned length)
+{
+    return parseJSONInternal<uint16_t>(characters, length);
+}
+
+std::unique_ptr<Value> parseJSONCharacters(const uint8_t* characters, unsigned length)
+{
+    return parseJSONInternal<uint8_t>(characters, length);
+}
+
+{% for namespace in config.protocol.namespace %}
+} // namespace {{namespace}}
+{% endfor %}
diff --git a/src/v8/third_party/inspector_protocol/lib/Parser_h.template b/src/v8/third_party/inspector_protocol/lib/Parser_h.template
new file mode 100644
index 0000000..8397d3f
--- /dev/null
+++ b/src/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> parseJSONCharacters(const uint8_t*, unsigned);
+{{config.lib.export_macro}} std::unique_ptr<Value> parseJSONCharacters(const uint16_t*, unsigned);
+
+{% for namespace in config.protocol.namespace %}
+} // namespace {{namespace}}
+{% endfor %}
+
+#endif // !defined({{"_".join(config.protocol.namespace)}}_Parser_h)
diff --git a/src/v8/third_party/inspector_protocol/lib/Protocol_cpp.template b/src/v8/third_party/inspector_protocol/lib/Protocol_cpp.template
new file mode 100644
index 0000000..9016563
--- /dev/null
+++ b/src/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 {{format_include(config.protocol.package, "Protocol")}}
+
+#include <algorithm>
+#include <cmath>
+
+#include <cstring>
diff --git a/src/v8/third_party/inspector_protocol/lib/ValueConversions_h.template b/src/v8/third_party/inspector_protocol/lib/ValueConversions_h.template
new file mode 100644
index 0000000..4d64ec9
--- /dev/null
+++ b/src/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> fromValue(protocol::Value* value, ErrorSupport* errors)
+    {
+        return T::fromValue(value, errors);
+    }
+
+    static std::unique_ptr<protocol::Value> toValue(T* value)
+    {
+        return value->toValue();
+    }
+
+    static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<T>& value)
+    {
+        return value->toValue();
+    }
+};
+
+template<>
+struct ValueConversions<bool> {
+    static bool fromValue(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> toValue(bool value)
+    {
+        return FundamentalValue::create(value);
+    }
+};
+
+template<>
+struct ValueConversions<int> {
+    static int fromValue(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> toValue(int value)
+    {
+        return FundamentalValue::create(value);
+    }
+};
+
+template<>
+struct ValueConversions<double> {
+    static double fromValue(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> toValue(double value)
+    {
+        return FundamentalValue::create(value);
+    }
+};
+
+template<>
+struct ValueConversions<String> {
+    static String fromValue(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> toValue(const String& value)
+    {
+        return StringValue::create(value);
+    }
+};
+
+template<>
+struct ValueConversions<Value> {
+    static std::unique_ptr<Value> fromValue(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> toValue(Value* value)
+    {
+        return value->clone();
+    }
+
+    static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<Value>& value)
+    {
+        return value->clone();
+    }
+};
+
+template<>
+struct ValueConversions<DictionaryValue> {
+    static std::unique_ptr<DictionaryValue> fromValue(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> toValue(DictionaryValue* value)
+    {
+        return value->clone();
+    }
+
+    static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<DictionaryValue>& value)
+    {
+        return value->clone();
+    }
+};
+
+template<>
+struct ValueConversions<ListValue> {
+    static std::unique_ptr<ListValue> fromValue(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> toValue(ListValue* value)
+    {
+        return value->clone();
+    }
+
+    static std::unique_ptr<protocol::Value> toValue(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/src/v8/third_party/inspector_protocol/lib/Values_cpp.template b/src/v8/third_party/inspector_protocol/lib/Values_cpp.template
new file mode 100644
index 0000000..6f8b14c
--- /dev/null
+++ b/src/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': StringUtil::builderAppend(*dst, "\\b"); break;
+    case '\f': StringUtil::builderAppend(*dst, "\\f"); break;
+    case '\n': StringUtil::builderAppend(*dst, "\\n"); break;
+    case '\r': StringUtil::builderAppend(*dst, "\\r"); break;
+    case '\t': StringUtil::builderAppend(*dst, "\\t"); break;
+    case '\\': StringUtil::builderAppend(*dst, "\\\\"); break;
+    case '"': StringUtil::builderAppend(*dst, "\\\""); break;
+    default:
+        return false;
+    }
+    return true;
+}
+
+const char hexDigits[17] = "0123456789ABCDEF";
+
+void appendUnsignedAsHex(uint16_t number, StringBuilder* dst)
+{
+    StringUtil::builderAppend(*dst, "\\u");
+    for (size_t i = 0; i < 4; ++i) {
+        uint16_t c = hexDigits[(number & 0xF000) >> 12];
+        StringUtil::builderAppend(*dst, 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 {
+                StringUtil::builderAppend(*dst, c);
+            }
+        }
+    }
+}
+
+void doubleQuoteStringForJSON(const String& str, StringBuilder* dst)
+{
+    StringUtil::builderAppend(*dst, '"');
+    escapeStringForJSON(str, dst);
+    StringUtil::builderAppend(*dst, '"');
+}
+
+} // 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;
+}
+
+void Value::writeJSON(StringBuilder* output) const
+{
+    DCHECK(m_type == TypeNull);
+    StringUtil::builderAppend(*output, nullValueString, 4);
+}
+
+std::unique_ptr<Value> Value::clone() const
+{
+    return Value::null();
+}
+
+String Value::serialize()
+{
+    StringBuilder result;
+    StringUtil::builderReserve(result, 512);
+    writeJSON(&result);
+    return StringUtil::builderToString(result);
+}
+
+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)
+            StringUtil::builderAppend(*output, trueValueString, 4);
+        else
+            StringUtil::builderAppend(*output, falseValueString, 5);
+    } else if (type() == TypeDouble) {
+        if (!std::isfinite(m_doubleValue)) {
+            StringUtil::builderAppend(*output, nullValueString, 4);
+            return;
+        }
+        StringUtil::builderAppend(*output, StringUtil::fromDouble(m_doubleValue));
+    } else if (type() == TypeInteger) {
+        StringUtil::builderAppend(*output, 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);
+    StringUtil::builderAppend(*output, 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
+{
+    StringUtil::builderAppend(*output, '{');
+    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)
+            StringUtil::builderAppend(*output, ',');
+        doubleQuoteStringForJSON(it->first, output);
+        StringUtil::builderAppend(*output, ':');
+        it->second->writeJSON(output);
+    }
+    StringUtil::builderAppend(*output, '}');
+}
+
+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
+{
+    StringUtil::builderAppend(*output, '[');
+    bool first = true;
+    for (const std::unique_ptr<protocol::Value>& value : m_data) {
+        if (!first)
+            StringUtil::builderAppend(*output, ',');
+        value->writeJSON(output);
+        first = false;
+    }
+    StringUtil::builderAppend(*output, ']');
+}
+
+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/src/v8/third_party/inspector_protocol/lib/Values_h.template b/src/v8/third_party/inspector_protocol/lib/Values_h.template
new file mode 100644
index 0000000..646543a
--- /dev/null
+++ b/src/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 : public Serializable {
+    PROTOCOL_DISALLOW_COPY(Value);
+public:
+    virtual ~Value() override { }
+
+    static std::unique_ptr<Value> null()
+    {
+        return std::unique_ptr<Value>(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;
+
+    virtual void writeJSON(StringBuilder* output) const;
+    virtual std::unique_ptr<Value> clone() const;
+    String serialize() override;
+
+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 std::unique_ptr<FundamentalValue>(new FundamentalValue(value));
+    }
+
+    static std::unique_ptr<FundamentalValue> create(int value)
+    {
+        return std::unique_ptr<FundamentalValue>(new FundamentalValue(value));
+    }
+
+    static std::unique_ptr<FundamentalValue> create(double value)
+    {
+        return std::unique_ptr<FundamentalValue>(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 std::unique_ptr<StringValue>(new StringValue(value));
+    }
+
+    static std::unique_ptr<StringValue> create(const char* value)
+    {
+        return std::unique_ptr<StringValue>(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 std::unique_ptr<SerializedValue>(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 std::unique_ptr<DictionaryValue>(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 std::unique_ptr<DictionaryValue>(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 std::unique_ptr<ListValue>(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 std::unique_ptr<ListValue>(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/src/v8/third_party/inspector_protocol/templates/Exported_h.template b/src/v8/third_party/inspector_protocol/templates/Exported_h.template
new file mode 100644
index 0000000..3d36ecf
--- /dev/null
+++ b/src/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 protocol.is_exported(domain.domain, type.id) %}
+
+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 protocol.is_exported(domain.domain, command.name + "." + param.name) %}
+
+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 protocol.is_exported(domain.domain, type.id) %}{% 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/src/v8/third_party/inspector_protocol/templates/Imported_h.template b/src/v8/third_party/inspector_protocol/templates/Imported_h.template
new file mode 100644
index 0000000..4c9d24b
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/templates/Imported_h.template
@@ -0,0 +1,55 @@
+// 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 {{format_include(config.protocol.package, "Protocol")}}
+{% if config.imported.header %}
+#include {{format_include(config.imported.header)}}
+{% else %}
+#include {{format_include(config.imported.package, domain.domain)}}
+{% endif %}
+
+{% 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 protocol.is_imported(domain.domain, type.id) %}{% 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}}> fromValue(protocol::Value* value, ErrorSupport* errors)
+    {
+        if (!value) {
+            errors->addError("value expected");
+            return nullptr;
+        }
+        String json = value->serialize();
+        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> toValue(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> toValue(const std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}>& value)
+    {
+        return toValue(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/src/v8/third_party/inspector_protocol/templates/TypeBuilder_cpp.template b/src/v8/third_party/inspector_protocol/templates/TypeBuilder_cpp.template
new file mode 100644
index 0000000..14b55b9
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/templates/TypeBuilder_cpp.template
@@ -0,0 +1,389 @@
+// 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 {{format_include(config.protocol.package, domain.domain)}}
+
+#include {{format_include(config.protocol.package, "Protocol")}}
+
+{% 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 protocol.is_exported(domain.domain, type.id) %}
+
+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}}::fromValue(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<{{protocol.resolve_type(property).raw_type}}>::fromValue({{property.name}}Value, errors);
+    }
+      {% else %}
+    errors->setName("{{property.name}}");
+    result->m_{{property.name}} = ValueConversions<{{protocol.resolve_type(property).raw_type}}>::fromValue({{property.name}}Value, errors);
+      {% endif %}
+    {% endfor %}
+    errors->pop();
+    if (errors->hasErrors())
+        return nullptr;
+    return result;
+}
+
+std::unique_ptr<protocol::DictionaryValue> {{type.id}}::toValue() const
+{
+    std::unique_ptr<protocol::DictionaryValue> result = DictionaryValue::create();
+    {% for property in type.properties %}
+      {% set property_type = protocol.resolve_type(property) %}
+      {% set property_field = "m_" + property.name %}
+      {% if property.optional %}
+    if ({{property_field}}.isJust())
+        result->setValue("{{property.name}}", ValueConversions<{{property_type.raw_type}}>::toValue({{property_field}}.fromJust()));
+      {% else %}
+    result->setValue("{{property.name}}", ValueConversions<{{property_type.raw_type}}>::toValue({{property_type.to_raw_type % property_field}}));
+      {% endif %}
+    {% endfor %}
+    return result;
+}
+
+std::unique_ptr<{{type.id}}> {{type.id}}::clone() const
+{
+    ErrorSupport errors;
+    return fromValue(toValue().get(), &errors);
+}
+    {% if protocol.is_exported(domain.domain, type.id) %}
+
+{{config.exported.string_out}} {{type.id}}::toJSONString() const
+{
+    String json = toValue()->serialize();
+    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 = StringUtil::parseJSON(json);
+    if (!value)
+        return nullptr;
+    return protocol::{{domain.domain}}::{{type.id}}::fromValue(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 protocol.is_exported(domain.domain, command.name + "." + param.name) %}
+
+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 not protocol.generate_event(domain.domain, event.name) %}{% continue %}{% endif %}
+
+void Frontend::{{event.name | to_method_case}}(
+    {%- for parameter in event.parameters %}
+      {% if "optional" in parameter -%}
+        Maybe<{{protocol.resolve_type(parameter).raw_type}}>
+      {%- else -%}
+        {{protocol.resolve_type(parameter).pass_type}}
+      {%- endif %} {{parameter.name}}{%- if not loop.last -%}, {% endif -%}
+    {% endfor -%})
+{
+    if (!m_frontendChannel)
+        return;
+      {% if event.parameters %}
+    std::unique_ptr<{{event.name | to_title_case}}Notification> messageData = {{event.name | to_title_case}}Notification::{{"create" | to_method_case}}()
+        {% for parameter in event.parameters %}
+          {% if not "optional" in parameter %}
+        .{{"set" | to_method_case}}{{parameter.name | to_title_case}}({{protocol.resolve_type(parameter).to_pass_type % parameter.name}})
+          {% endif %}
+        {% endfor %}
+        .{{ "build" | to_method_case }}();
+        {% for parameter in event.parameters %}
+          {% if "optional" in parameter %}
+    if ({{parameter.name}}.isJust())
+        messageData->{{"set" | to_method_case}}{{parameter.name | to_title_case}}(std::move({{parameter.name}}).takeJust());
+          {% endif %}
+        {% endfor %}
+    m_frontendChannel->sendProtocolNotification(InternalResponse::createNotification("{{domain.domain}}.{{event.name}}", std::move(messageData)));
+      {% else %}
+    m_frontendChannel->sendProtocolNotification(InternalResponse::createNotification("{{domain.domain}}.{{event.name}}"));
+      {% endif %}
+}
+  {% endfor %}
+
+void Frontend::flush()
+{
+    m_frontendChannel->flushProtocolNotifications();
+}
+
+void Frontend::sendRawNotification(const String& notification)
+{
+    m_frontendChannel->sendProtocolNotification(InternalRawNotification::create(notification));
+}
+
+// --------------------- Dispatcher.
+
+class DispatcherImpl : public protocol::DispatcherBase {
+public:
+    DispatcherImpl(FrontendChannel* frontendChannel, Backend* backend, bool fallThroughForNotFound)
+        : DispatcherBase(frontendChannel)
+        , m_backend(backend)
+        , m_fallThroughForNotFound(fallThroughForNotFound) {
+  {% for command in domain.commands %}
+    {% if "redirect" in command %}{% continue %}{% endif %}
+    {% if not protocol.generate_command(domain.domain, command.name) %}{% 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 not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
+    DispatchResponse::Status {{command.name}}(int callId, std::unique_ptr<DictionaryValue> requestMessageObject, ErrorSupport*);
+  {% endfor %}
+
+    Backend* m_backend;
+    bool m_fallThroughForNotFound;
+};
+
+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()) {
+        if (m_fallThroughForNotFound)
+            return DispatchResponse::kFallThrough;
+        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 %}
+    {% set command_name_title = command.name | to_title_case %}
+    {% if "redirect" in command %}{% continue %}{% endif %}
+    {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
+    {% if protocol.is_async_command(domain.domain, command.name) %}
+
+class {{command_name_title}}CallbackImpl : public Backend::{{command_name_title}}Callback, public DispatcherBase::Callback {
+public:
+    {{command_name_title}}CallbackImpl(std::unique_ptr<DispatcherBase::WeakPtr> backendImpl, int callId, int callbackId)
+        : DispatcherBase::Callback(std::move(backendImpl), callId, callbackId) { }
+
+    void sendSuccess(
+      {%- for parameter in command.returns -%}
+        {%- if "optional" in parameter -%}
+        Maybe<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}}
+        {%- else -%}
+        {{protocol.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<{{protocol.resolve_type(parameter).raw_type}}>::toValue({{parameter.name}}.fromJust()));
+           {% else %}
+        resultObject->setValue("{{parameter.name}}", ValueConversions<{{protocol.resolve_type(parameter).raw_type}}>::toValue({{protocol.resolve_type(parameter).to_raw_type % parameter.name}}));
+            {% endif %}
+          {% endfor %}
+        sendIfActive(std::move(resultObject), DispatchResponse::OK());
+    }
+
+    void fallThrough() override
+    {
+        fallThroughIfActive();
+    }
+
+    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 parameter in command.parameters %}
+        {% set parameter_type = protocol.resolve_type(parameter) %}
+    protocol::Value* {{parameter.name}}Value = object ? object->get("{{parameter.name}}") : nullptr;
+        {% if parameter.optional %}
+    Maybe<{{parameter_type.raw_type}}> in_{{parameter.name}};
+    if ({{parameter.name}}Value) {
+        errors->setName("{{parameter.name}}");
+        in_{{parameter.name}} = ValueConversions<{{parameter_type.raw_type}}>::fromValue({{parameter.name}}Value, errors);
+    }
+        {% else %}
+    errors->setName("{{parameter.name}}");
+    {{parameter_type.type}} in_{{parameter.name}} = ValueConversions<{{parameter_type.raw_type}}>::fromValue({{parameter.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 protocol.is_async_command(domain.domain, command.name) %}
+    // Declare output parameters.
+      {% for parameter in command.returns %}
+        {% if "optional" in parameter %}
+    Maybe<{{protocol.resolve_type(parameter).raw_type}}> out_{{parameter.name}};
+        {% else %}
+    {{protocol.resolve_type(parameter).type}} out_{{parameter.name}};
+        {% endif %}
+      {% endfor %}
+    {% endif %}
+
+    {% if not protocol.is_async_command(domain.domain, command.name) %}
+    std::unique_ptr<DispatcherBase::WeakPtr> weak = weakPtr();
+    DispatchResponse response = m_backend->{{command.name | to_method_case}}(
+      {%- for parameter in command.parameters -%}
+        {%- if not loop.first -%}, {% endif -%}
+        {%- if "optional" in parameter -%}
+        std::move(in_{{parameter.name}})
+        {%- else -%}
+        {{protocol.resolve_type(parameter).to_pass_type % ("in_" + parameter.name)}}
+        {%- endif -%}
+      {%- endfor %}
+      {%- if "returns" in command %}
+        {%- for parameter in command.returns -%}
+          {%- if not loop.first or command.parameters -%}, {% endif -%}
+          &out_{{parameter.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<{{protocol.resolve_type(parameter).raw_type}}>::toValue(out_{{parameter.name}}.fromJust()));
+          {% else %}
+        result->setValue("{{parameter.name}}", ValueConversions<{{protocol.resolve_type(parameter).raw_type}}>::toValue({{protocol.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<DispatcherBase::WeakPtr> weak = weakPtr();
+    std::unique_ptr<{{command_name_title}}CallbackImpl> callback(new {{command.name | to_title_case}}CallbackImpl(weakPtr(), callId, nextCallbackId()));
+    m_backend->{{command.name | to_method_case}}(
+      {%- for property in command.parameters -%}
+        {%- if not loop.first -%}, {% endif -%}
+        {%- if "optional" in property -%}
+        std::move(in_{{property.name}})
+        {%- else -%}
+        {{protocol.resolve_type(property).to_pass_type % ("in_" + property.name)}}
+        {%- endif -%}
+      {%- endfor -%}
+        {%- if command.parameters -%}, {% endif -%}
+        std::move(callback));
+    return (weak->get() && weak->get()->lastCallbackFallThrough()) ? DispatchResponse::kFallThrough : DispatchResponse::kAsync;
+    {% endif %}
+}
+  {% endfor %}
+
+// static
+void Dispatcher::wire(UberDispatcher* dispatcher, Backend* backend)
+{
+    dispatcher->registerBackend("{{domain.domain}}", std::unique_ptr<protocol::DispatcherBase>(new DispatcherImpl(dispatcher->channel(), backend, dispatcher->fallThroughForNotFound())));
+}
+
+} // {{domain.domain}}
+{% for namespace in config.protocol.namespace %}
+} // namespace {{namespace}}
+{% endfor %}
diff --git a/src/v8/third_party/inspector_protocol/templates/TypeBuilder_h.template b/src/v8/third_party/inspector_protocol/templates/TypeBuilder_h.template
new file mode 100644
index 0000000..81dd7f2
--- /dev/null
+++ b/src/v8/third_party/inspector_protocol/templates/TypeBuilder_h.template
@@ -0,0 +1,304 @@
+// 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 {{format_include(config.protocol.package, "Protocol")}}
+// 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 {{format_include(config.protocol.package, name)}}
+{% endfor %}
+{% if protocol.is_exported_domain(domain.domain) %}
+#include {{format_include(config.exported.package, domain.domain)}}
+{% 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}} = {{protocol.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 %}
+
+// {{type.description}}
+class {{config.protocol.export_macro}} {{type.id}} : public Serializable{% if protocol.is_exported(domain.domain, type.id) %}, public API::{{type.id}}{% endif %}{
+    PROTOCOL_DISALLOW_COPY({{type.id}});
+public:
+    static std::unique_ptr<{{type.id}}> fromValue(protocol::Value* value, ErrorSupport* errors);
+
+    ~{{type.id}}() override { }
+    {% for property in type.properties %}
+      {% set property_type = protocol.resolve_type(property) %}
+      {% set property_name = property.name | to_title_case %}
+      {% set property_field = "m_" + property.name %}
+      {% if "enum" in property %}
+
+    struct {{config.protocol.export_macro}} {{property_name}}Enum {
+        {% for literal in property.enum %}
+        static const char* {{literal | dash_to_camelcase}};
+        {% endfor %}
+    }; // {{property_name}}Enum
+      {% endif %}
+
+      {% if property.optional %}
+    bool {{"has" | to_method_case}}{{property_name}}() { return {{property_field}}.isJust(); }
+    {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}({{property_type.raw_pass_type}} defaultValue) { return {{property_field}}.isJust() ? {{property_field}}.fromJust() : defaultValue; }
+      {% else %}
+    {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}() { return {{property_type.to_raw_type % property_field}}; }
+      {% endif %}
+    void {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value) { {{property_field}} = {{property_type.to_rvalue % "value"}}; }
+    {% endfor %}
+
+    std::unique_ptr<protocol::DictionaryValue> toValue() const;
+    String serialize() override { return toValue()->serialize(); }
+    std::unique_ptr<{{type.id}}> clone() const;
+    {% if protocol.is_exported(domain.domain, type.id) %}
+    {{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 %}
+      {% set property_type = protocol.resolve_type(property) %}
+      {% set property_name = property.name | to_title_case %}
+
+      {% if property.optional %}
+        {{type.id}}Builder<STATE>& {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value)
+        {
+            m_result->{{"set" | to_method_case}}{{property_name}}({{property_type.to_rvalue % "value"}});
+            return *this;
+        }
+      {% else %}
+        {{type.id}}Builder<STATE | {{property_name}}Set>& {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value)
+        {
+            static_assert(!(STATE & {{property_name}}Set), "property {{property.name}} should not be set yet");
+            m_result->{{"set" | to_method_case}}{{property_name}}({{property_type.to_rvalue % "value"}});
+            return castState<{{property_name}}Set>();
+        }
+      {% endif %}
+    {% endfor %}
+
+        std::unique_ptr<{{type.id}}> {{"build" | to_method_case}}()
+        {
+            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);
+        }
+
+        {{protocol.type_definition(domain.domain + "." + type.id).type}} m_result;
+    };
+
+    static {{type.id}}Builder<0> {{"create" | to_method_case}}()
+    {
+        return {{type.id}}Builder<0>();
+    }
+
+private:
+    {{type.id}}()
+    {
+    {% for property in type.properties %}
+      {% if not(property.optional) and "default_value" in protocol.resolve_type(property) %}
+          m_{{property.name}} = {{protocol.resolve_type(property).default_value}};
+      {%endif %}
+    {% endfor %}
+    }
+
+    {% for property in type.properties %}
+      {% if property.optional %}
+    Maybe<{{protocol.resolve_type(property).raw_type}}> m_{{property.name}};
+      {% else %}
+    {{protocol.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 not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
+    {% if protocol.is_async_command(domain.domain, command.name) %}
+    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<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}}
+        {%- else -%}
+                {{protocol.resolve_type(parameter).pass_type}} {{parameter.name}}
+        {%- endif -%}
+        {%- if not loop.last -%}, {% endif -%}
+      {%- endfor -%}
+        ) = 0;
+        virtual void sendFailure(const DispatchResponse&) = 0;
+        virtual void fallThrough() = 0;
+        virtual ~{{command.name | to_title_case}}Callback() { }
+    };
+    {% endif %}
+    {%- if not protocol.is_async_command(domain.domain, command.name) %}
+    virtual DispatchResponse {{command.name | to_method_case}}(
+    {%- else %}
+    virtual void {{command.name | to_method_case}}(
+    {%- endif %}
+    {%- for parameter in command.parameters -%}
+      {%- if not loop.first -%}, {% endif -%}
+      {%- if "optional" in parameter -%}
+        Maybe<{{protocol.resolve_type(parameter).raw_type}}> in_{{parameter.name}}
+      {%- else -%}
+        {{protocol.resolve_type(parameter).pass_type}} in_{{parameter.name}}
+      {%- endif -%}
+    {%- endfor -%}
+    {%- if protocol.is_async_command(domain.domain, command.name) -%}
+      {%- 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<{{protocol.resolve_type(parameter).raw_type}}>* out_{{parameter.name}}
+        {%- else -%}
+        {{protocol.resolve_type(parameter).type}}* out_{{parameter.name}}
+        {%- endif -%}
+      {%- endfor -%}
+    {%- endif -%}
+    ) = 0;
+  {% endfor %}
+
+  {% if protocol.generate_disable(domain) %}
+    virtual DispatchResponse {{"disable" | to_method_case}}()
+    {
+        return DispatchResponse::OK();
+    }
+  {% endif %}
+};
+
+// ------------- Frontend interface.
+
+class {{config.protocol.export_macro}} Frontend {
+public:
+    explicit Frontend(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { }
+  {% for event in domain.events %}
+    {% if not protocol.generate_event(domain.domain, event.name) %}{% continue %}{% endif %}
+    void {{event.name | to_method_case}}(
+    {%- for parameter in event.parameters -%}
+      {%- if "optional" in parameter -%}
+        Maybe<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}} = Maybe<{{protocol.resolve_type(parameter).raw_type}}>()
+      {%- else -%}
+        {{protocol.resolve_type(parameter).pass_type}} {{parameter.name}}
+      {%- endif -%}{%- if not loop.last -%}, {% endif -%}
+    {%- endfor -%}
+    );
+  {% endfor %}
+
+    void flush();
+    void sendRawNotification(const String&);
+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)