diff --git a/configure b/configure index 9b4fa94521a7f4..20975831ff3794 100755 --- a/configure +++ b/configure @@ -852,7 +852,6 @@ def configure_node(o): o['variables']['library_files'] = options.linked_module o['variables']['asan'] = int(options.enable_asan or 0) - o['variables']['v8_inspector'] = b(not options.without_inspector) o['variables']['debug_devtools'] = 'node' if options.use_xcode and options.use_ninja: @@ -1220,6 +1219,12 @@ def configure_intl(o): pprint.pformat(icu_config, indent=2) + '\n') return # end of configure_intl +def configure_inspector(o): + disable_inspector = (options.without_inspector or + options.with_intl in (None, 'none') or + options.without_ssl) + o['variables']['v8_inspector'] = b(not disable_inspector) + output = { 'variables': {}, 'include_dirs': [], @@ -1250,6 +1255,7 @@ configure_v8(output) configure_openssl(output) configure_intl(output) configure_static(output) +configure_inspector(output) # variables should be a root level element, # move everything else to target_defaults diff --git a/deps/v8_inspector/README.md b/deps/v8_inspector/README.md index 60578c90324ed0..2ea180ca63a906 100644 --- a/deps/v8_inspector/README.md +++ b/deps/v8_inspector/README.md @@ -4,8 +4,9 @@ V8 Inspector support for Node.js This repository is an intermediate repository that gathers the dependencies for Node.js support for the [Chrome Debug Protocol][https://developer.chrome.com/devtools/docs/debugger-protocol]. -* third_party/v8_inspector/platform/v8_inspector: vendored from https://chromium.googlesource.com/chromium/src/third_party/WebKit/Source/platform/v8_inspector -* third_party/v8_inspector/platform/inspector_protocol: vendored from https://chromium.googlesource.com/chromium/src/third_party/WebKit/Source/platform/inspector_protocol +* include: vendored from v8/include +* src/inspector: vendored from v8/src/inspector +* third_party/WebKit/platform/inspector_protocol: vendored from https://chromium.googlesource.com/chromium/src/third_party/WebKit/Source/platform/inspector_protocol * third_party/jinja2: vendored from https://github.com/mitsuhiko/jinja2 * The `tests/` directory `ext/jinja.el` file have been deleted. * third_party/markupsafe: vendored from https://github.com/mitsuhiko/markupsafe diff --git a/deps/v8_inspector/include/v8-inspector-protocol.h b/deps/v8_inspector/include/v8-inspector-protocol.h new file mode 100644 index 00000000000000..612a2ebc3911f5 --- /dev/null +++ b/deps/v8_inspector/include/v8-inspector-protocol.h @@ -0,0 +1,13 @@ +// Copyright 2016 the V8 project 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 V8_V8_INSPECTOR_PROTOCOL_H_ +#define V8_V8_INSPECTOR_PROTOCOL_H_ + +#include "inspector/Debugger.h" // NOLINT(build/include) +#include "inspector/Runtime.h" // NOLINT(build/include) +#include "inspector/Schema.h" // NOLINT(build/include) +#include "v8-inspector.h" // NOLINT(build/include) + +#endif // V8_V8_INSPECTOR_PROTOCOL_H_ diff --git a/deps/v8_inspector/include/v8-inspector.h b/deps/v8_inspector/include/v8-inspector.h new file mode 100644 index 00000000000000..0855ac101b74ef --- /dev/null +++ b/deps/v8_inspector/include/v8-inspector.h @@ -0,0 +1,267 @@ +// Copyright 2016 the V8 project 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 V8_V8_INSPECTOR_H_ +#define V8_V8_INSPECTOR_H_ + +#include +#include + +#include + +#include "v8.h" // NOLINT(build/include) + +namespace v8_inspector { + +namespace protocol { +namespace Debugger { +namespace API { +class SearchMatch; +} +} +namespace Runtime { +namespace API { +class RemoteObject; +class StackTrace; +} +} +namespace Schema { +namespace API { +class Domain; +} +} +} // namespace protocol + +class V8_EXPORT StringView { + public: + StringView() : m_is8Bit(true), m_length(0), m_characters8(nullptr) {} + + StringView(const uint8_t* characters, size_t length) + : m_is8Bit(true), m_length(length), m_characters8(characters) {} + + StringView(const uint16_t* characters, size_t length) + : m_is8Bit(false), m_length(length), m_characters16(characters) {} + + bool is8Bit() const { return m_is8Bit; } + size_t length() const { return m_length; } + + // TODO(dgozman): add DCHECK(m_is8Bit) to accessors once platform can be used + // here. + const uint8_t* characters8() const { return m_characters8; } + const uint16_t* characters16() const { return m_characters16; } + + private: + bool m_is8Bit; + size_t m_length; + union { + const uint8_t* m_characters8; + const uint16_t* m_characters16; + }; +}; + +class V8_EXPORT StringBuffer { + public: + virtual ~StringBuffer() {} + virtual const StringView& string() = 0; + // This method copies contents. + static std::unique_ptr create(const StringView&); +}; + +class V8_EXPORT V8ContextInfo { + public: + V8ContextInfo(v8::Local context, int contextGroupId, + const StringView& humanReadableName) + : context(context), + contextGroupId(contextGroupId), + humanReadableName(humanReadableName), + hasMemoryOnConsole(false) {} + + v8::Local context; + // Each v8::Context is a part of a group. The group id must be non-zero. + int contextGroupId; + StringView humanReadableName; + StringView origin; + StringView auxData; + bool hasMemoryOnConsole; + + private: + // Disallow copying and allocating this one. + enum NotNullTagEnum { NotNullLiteral }; + void* operator new(size_t) = delete; + void* operator new(size_t, NotNullTagEnum, void*) = delete; + void* operator new(size_t, void*) = delete; + V8ContextInfo(const V8ContextInfo&) = delete; + V8ContextInfo& operator=(const V8ContextInfo&) = delete; +}; + +class V8_EXPORT V8StackTrace { + public: + virtual bool isEmpty() const = 0; + virtual StringView topSourceURL() const = 0; + virtual int topLineNumber() const = 0; + virtual int topColumnNumber() const = 0; + virtual StringView topScriptId() const = 0; + virtual StringView topFunctionName() const = 0; + + virtual ~V8StackTrace() {} + virtual std::unique_ptr + buildInspectorObject() const = 0; + virtual std::unique_ptr toString() const = 0; + + // Safe to pass between threads, drops async chain. + virtual std::unique_ptr clone() = 0; +}; + +class V8_EXPORT V8InspectorSession { + public: + virtual ~V8InspectorSession() {} + + // Cross-context inspectable values (DOM nodes in different worlds, etc.). + class V8_EXPORT Inspectable { + public: + virtual v8::Local get(v8::Local) = 0; + virtual ~Inspectable() {} + }; + virtual void addInspectedObject(std::unique_ptr) = 0; + + // Dispatching protocol messages. + static bool canDispatchMethod(const StringView& method); + virtual void dispatchProtocolMessage(const StringView& message) = 0; + virtual std::unique_ptr stateJSON() = 0; + virtual std::vector> + supportedDomains() = 0; + + // Debugger actions. + virtual void schedulePauseOnNextStatement(const StringView& breakReason, + const StringView& breakDetails) = 0; + virtual void cancelPauseOnNextStatement() = 0; + virtual void breakProgram(const StringView& breakReason, + const StringView& breakDetails) = 0; + virtual void setSkipAllPauses(bool) = 0; + virtual void resume() = 0; + virtual void stepOver() = 0; + virtual std::vector> + searchInTextByLines(const StringView& text, const StringView& query, + bool caseSensitive, bool isRegex) = 0; + + // Remote objects. + virtual std::unique_ptr wrapObject( + v8::Local, v8::Local, + const StringView& groupName) = 0; + virtual bool unwrapObject(std::unique_ptr* error, + const StringView& objectId, v8::Local*, + v8::Local*, + std::unique_ptr* objectGroup) = 0; + virtual void releaseObjectGroup(const StringView&) = 0; +}; + +enum class V8ConsoleAPIType { kClear, kDebug, kLog, kInfo, kWarning, kError }; + +class V8_EXPORT V8InspectorClient { + public: + virtual ~V8InspectorClient() {} + + virtual void runMessageLoopOnPause(int contextGroupId) {} + virtual void quitMessageLoopOnPause() {} + virtual void runIfWaitingForDebugger(int contextGroupId) {} + + virtual void muteMetrics(int contextGroupId) {} + virtual void unmuteMetrics(int contextGroupId) {} + + virtual void beginUserGesture() {} + virtual void endUserGesture() {} + + virtual std::unique_ptr valueSubtype(v8::Local) { + return nullptr; + } + virtual bool formatAccessorsAsProperties(v8::Local) { + return false; + } + virtual bool isInspectableHeapObject(v8::Local) { return true; } + + virtual v8::Local ensureDefaultContextInGroup( + int contextGroupId) { + return v8::Local(); + } + virtual void beginEnsureAllContextsInGroup(int contextGroupId) {} + virtual void endEnsureAllContextsInGroup(int contextGroupId) {} + + virtual void installAdditionalCommandLineAPI(v8::Local, + v8::Local) {} + virtual void consoleAPIMessage(int contextGroupId, V8ConsoleAPIType, + const StringView& message, + const StringView& url, unsigned lineNumber, + unsigned columnNumber, V8StackTrace*) {} + virtual v8::MaybeLocal memoryInfo(v8::Isolate*, + v8::Local) { + return v8::MaybeLocal(); + } + + virtual void consoleTime(const StringView& title) {} + virtual void consoleTimeEnd(const StringView& title) {} + virtual void consoleTimeStamp(const StringView& title) {} + virtual double currentTimeMS() { return 0; } + typedef void (*TimerCallback)(void*); + virtual void startRepeatingTimer(double, TimerCallback, void* data) {} + virtual void cancelTimer(void* data) {} + + // TODO(dgozman): this was added to support service worker shadow page. We + // should not connect at all. + virtual bool canExecuteScripts(int contextGroupId) { return true; } +}; + +class V8_EXPORT V8Inspector { + public: + static std::unique_ptr create(v8::Isolate*, V8InspectorClient*); + virtual ~V8Inspector() {} + + // Contexts instrumentation. + virtual void contextCreated(const V8ContextInfo&) = 0; + virtual void contextDestroyed(v8::Local) = 0; + virtual void resetContextGroup(int contextGroupId) = 0; + + // Various instrumentation. + virtual void willExecuteScript(v8::Local, int scriptId) = 0; + virtual void didExecuteScript(v8::Local) = 0; + virtual void idleStarted() = 0; + virtual void idleFinished() = 0; + + // Async stack traces instrumentation. + virtual void asyncTaskScheduled(const StringView& taskName, void* task, + bool recurring) = 0; + virtual void asyncTaskCanceled(void* task) = 0; + virtual void asyncTaskStarted(void* task) = 0; + virtual void asyncTaskFinished(void* task) = 0; + virtual void allAsyncTasksCanceled() = 0; + + // Exceptions instrumentation. + virtual unsigned exceptionThrown( + v8::Local, const StringView& message, + v8::Local exception, const StringView& detailedMessage, + const StringView& url, unsigned lineNumber, unsigned columnNumber, + std::unique_ptr, int scriptId) = 0; + virtual void exceptionRevoked(v8::Local, unsigned exceptionId, + const StringView& message) = 0; + + // Connection. + class V8_EXPORT Channel { + public: + virtual ~Channel() {} + virtual void sendProtocolResponse(int callId, + const StringView& message) = 0; + virtual void sendProtocolNotification(const StringView& message) = 0; + virtual void flushProtocolNotifications() = 0; + }; + virtual std::unique_ptr connect( + int contextGroupId, Channel*, const StringView& state) = 0; + + // API methods. + virtual std::unique_ptr createStackTrace( + v8::Local) = 0; + virtual std::unique_ptr captureStackTrace(bool fullStack) = 0; +}; + +} // namespace v8_inspector + +#endif // V8_V8_INSPECTOR_H_ diff --git a/deps/v8_inspector/src/inspector/BUILD.gn b/deps/v8_inspector/src/inspector/BUILD.gn new file mode 100644 index 00000000000000..15c090ff2218b5 --- /dev/null +++ b/deps/v8_inspector/src/inspector/BUILD.gn @@ -0,0 +1,189 @@ +# Copyright 2016 the V8 project 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("../../gni/v8.gni") + +_inspector_protocol = "//third_party/WebKit/Source/platform/inspector_protocol" +import("$_inspector_protocol/inspector_protocol.gni") + +_protocol_generated = [ + "protocol/Forward.h", + "protocol/Protocol.cpp", + "protocol/Protocol.h", + "protocol/Console.cpp", + "protocol/Console.h", + "protocol/Debugger.cpp", + "protocol/Debugger.h", + "protocol/HeapProfiler.cpp", + "protocol/HeapProfiler.h", + "protocol/Profiler.cpp", + "protocol/Profiler.h", + "protocol/Runtime.cpp", + "protocol/Runtime.h", + "protocol/Schema.cpp", + "protocol/Schema.h", + "../../include/inspector/Debugger.h", + "../../include/inspector/Runtime.h", + "../../include/inspector/Schema.h", +] + +action("protocol_compatibility") { + visibility = [ ":*" ] # Only targets in this file can depend on this. + script = "$_inspector_protocol/CheckProtocolCompatibility.py" + inputs = [ + "js_protocol.json", + ] + _stamp = "$target_gen_dir/js_protocol.stamp" + outputs = [ + _stamp, + ] + args = [ + "--stamp", + rebase_path(_stamp, root_build_dir), + rebase_path("js_protocol.json", root_build_dir), + ] +} + +inspector_protocol_generate("protocol_generated_sources") { + visibility = [ ":*" ] # Only targets in this file can depend on this. + deps = [ + ":protocol_compatibility", + ] + + out_dir = target_gen_dir + config_file = "inspector_protocol_config.json" + inputs = [ + "js_protocol.json", + "inspector_protocol_config.json", + ] + outputs = _protocol_generated +} + +action("inspector_injected_script") { + visibility = [ ":*" ] # Only targets in this file can depend on this. + script = "build/xxd.py" + inputs = [ + "injected-script-source.js", + ] + outputs = [ + "$target_gen_dir/injected-script-source.h", + ] + args = [ + "InjectedScriptSource_js", + rebase_path("injected-script-source.js", root_build_dir), + rebase_path("$target_gen_dir/injected-script-source.h", root_build_dir), + ] +} + +action("inspector_debugger_script") { + visibility = [ ":*" ] # Only targets in this file can depend on this. + script = "build/xxd.py" + inputs = [ + "debugger-script.js", + ] + outputs = [ + "$target_gen_dir/debugger-script.h", + ] + args = [ + "DebuggerScript_js", + rebase_path("debugger-script.js", root_build_dir), + rebase_path("$target_gen_dir/debugger-script.h", root_build_dir), + ] +} + +config("inspector_config") { + visibility = [ ":*" ] # Only targets in this file can depend on this. + cflags = [] + if (is_win) { + cflags += [ + "/wd4267", # Truncation from size_t to int. + "/wd4305", # Truncation from 'type1' to 'type2'. + "/wd4324", # Struct padded due to declspec(align). + "/wd4714", # Function marked forceinline not inlined. + "/wd4800", # Value forced to bool. + "/wd4996", # Deprecated function call. + ] + } + if (is_component_build) { + defines = [ "BUILDING_V8_SHARED" ] + } +} + +v8_source_set("inspector") { + deps = [ + ":inspector_debugger_script", + ":inspector_injected_script", + ":protocol_generated_sources", + ] + configs = [ ":inspector_config" ] + include_dirs = [ + "../..", + "../../include", + "$target_gen_dir/../..", + "$target_gen_dir/../../include", + ] + sources = rebase_path(_protocol_generated, ".", target_gen_dir) + sources += [ + "../../include/v8-inspector-protocol.h", + "../../include/v8-inspector.h", + ] + sources += get_target_outputs(":inspector_injected_script") + sources += get_target_outputs(":inspector_debugger_script") + sources += [ + "injected-script-native.cc", + "injected-script-native.h", + "injected-script.cc", + "injected-script.h", + "inspected-context.cc", + "inspected-context.h", + "java-script-call-frame.cc", + "java-script-call-frame.h", + "protocol-platform.h", + "remote-object-id.cc", + "remote-object-id.h", + "script-breakpoint.h", + "search-util.cc", + "search-util.h", + "string-16.cc", + "string-16.h", + "string-util.cc", + "string-util.h", + "v8-console-agent-impl.cc", + "v8-console-agent-impl.h", + "v8-console-message.cc", + "v8-console-message.h", + "v8-console.cc", + "v8-console.h", + "v8-debugger-agent-impl.cc", + "v8-debugger-agent-impl.h", + "v8-debugger-script.cc", + "v8-debugger-script.h", + "v8-debugger.cc", + "v8-debugger.h", + "v8-function-call.cc", + "v8-function-call.h", + "v8-heap-profiler-agent-impl.cc", + "v8-heap-profiler-agent-impl.h", + "v8-injected-script-host.cc", + "v8-injected-script-host.h", + "v8-inspector-impl.cc", + "v8-inspector-impl.h", + "v8-inspector-session-impl.cc", + "v8-inspector-session-impl.h", + "v8-internal-value-type.cc", + "v8-internal-value-type.h", + "v8-profiler-agent-impl.cc", + "v8-profiler-agent-impl.h", + "v8-regex.cc", + "v8-regex.h", + "v8-runtime-agent-impl.cc", + "v8-runtime-agent-impl.h", + "v8-schema-agent-impl.cc", + "v8-schema-agent-impl.h", + "v8-stack-trace-impl.cc", + "v8-stack-trace-impl.h", + "v8-value-copier.cc", + "v8-value-copier.h", + ] +} diff --git a/deps/v8_inspector/src/inspector/DEPS b/deps/v8_inspector/src/inspector/DEPS new file mode 100644 index 00000000000000..4486204d74ec76 --- /dev/null +++ b/deps/v8_inspector/src/inspector/DEPS @@ -0,0 +1,8 @@ +include_rules = [ + "-src", + "+src/inspector", + "+src/base/atomicops.h", + "+src/base/macros.h", + "+src/base/logging.h", + "+src/base/platform/platform.h", +] diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/OWNERS b/deps/v8_inspector/src/inspector/OWNERS similarity index 87% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/OWNERS rename to deps/v8_inspector/src/inspector/OWNERS index 8787a9d384ab32..2c4bd8d24bc92a 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/OWNERS +++ b/deps/v8_inspector/src/inspector/OWNERS @@ -1,8 +1,12 @@ +set noparent + alph@chromium.org caseq@chromium.org dgozman@chromium.org +jochen@chromium.org kozyatinskiy@chromium.org pfeldman@chromium.org +yangguo@chromium.org # Changes to remote debugging protocol require devtools review to # ensure backwards compatibility and committment to maintain. diff --git a/deps/v8_inspector/src/inspector/PRESUBMIT.py b/deps/v8_inspector/src/inspector/PRESUBMIT.py new file mode 100644 index 00000000000000..491564b2d9fc68 --- /dev/null +++ b/deps/v8_inspector/src/inspector/PRESUBMIT.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# Copyright 2016 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""v8_inspect presubmit script + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into gcl. +""" + +compile_note = "Be sure to run your patch by the compile-scripts.py script prior to committing!" + + +def _CompileScripts(input_api, output_api): + local_paths = [f.LocalPath() for f in input_api.AffectedFiles()] + + compilation_related_files = [ + "js_protocol.json" + "compile-scripts.js", + "injected-script-source.js", + "debugger_script_externs.js", + "injected_script_externs.js", + "check_injected_script_source.js", + "debugger-script.js" + ] + + for file in compilation_related_files: + if (any(file in path for path in local_paths)): + script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), + "build", "compile-scripts.py") + proc = input_api.subprocess.Popen( + [input_api.python_executable, script_path], + stdout=input_api.subprocess.PIPE, + stderr=input_api.subprocess.STDOUT) + out, _ = proc.communicate() + if "ERROR" in out or "WARNING" in out or proc.returncode: + return [output_api.PresubmitError(out)] + if "NOTE" in out: + return [output_api.PresubmitPromptWarning(out + compile_note)] + return [] + return [] + + +def CheckChangeOnUpload(input_api, output_api): + results = [] + results.extend(_CompileScripts(input_api, output_api)) + return results + + +def CheckChangeOnCommit(input_api, output_api): + results = [] + results.extend(_CompileScripts(input_api, output_api)) + return results diff --git a/deps/v8_inspector/src/inspector/build/check_injected_script_source.py b/deps/v8_inspector/src/inspector/build/check_injected_script_source.py new file mode 100644 index 00000000000000..0f2509cd8c5cac --- /dev/null +++ b/deps/v8_inspector/src/inspector/build/check_injected_script_source.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# Copyright (c) 2014 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. +# +# Copied from blink: +# WebKit/Source/devtools/scripts/check_injected_script_source.py +# + +import re +import sys +import os + + +def validate_injected_script(fileName): + f = open(fileName, "r") + lines = f.readlines() + f.close() + + proto_functions = "|".join([ + # Array.prototype.* + "concat", "every", "filter", "forEach", "indexOf", "join", "lastIndexOf", "map", "pop", + "push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toString", "unshift", + # Function.prototype.* + "apply", "bind", "call", "isGenerator", "toSource", + # Object.prototype.* + "toString", + ]) + + global_functions = "|".join([ + "eval", "uneval", "isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent", + "encodeURI", "encodeURIComponent", "escape", "unescape", "Map", "Set" + ]) + + # Black list: + # - instanceof, since e.g. "obj instanceof Error" may throw if Error is overridden and is not a function + # - Object.prototype.toString() + # - Array.prototype.* + # - Function.prototype.* + # - Math.* + # - Global functions + black_list_call_regex = re.compile(r"\sinstanceof\s+\w*|\bMath\.\w+\(|(?= java_required_major and minor >= java_required_minor + if is_ok: + exec_command = [java_path, '-Xms1024m', '-server', + '-XX:+TieredCompilation'] + check_server_proc = popen(exec_command + ['-version']) + check_server_proc.communicate() + if check_server_proc.returncode != 0: + # Not all Java installs have server JVMs. + exec_command = exec_command.remove('-server') + has_server_jvm = False + + if not is_ok: + print 'NOTE: Java executable version %d.%d or above not found in $PATH.' % (java_required_major, java_required_minor) + sys.exit(0) + print 'Java executable: %s%s' % (java_path, '' if has_server_jvm else ' (no server JVM)') + return exec_command + +java_exec = find_java() + +spawned_compiler_command = java_exec + [ + '-jar', + closure_compiler_jar +] + common_closure_args + +print 'Compiling injected-script-source.js...' + +command = spawned_compiler_command + [ + '--externs', injected_script_externs_file, + '--externs', protocol_externs_file, + '--js', injected_script_source_name +] + +injected_script_compile_proc = popen(command) + +print 'Compiling debugger-script.js...' + +command = spawned_compiler_command + [ + '--externs', debugger_script_externs_file, + '--js', debugger_script_source_name, + '--new_type_inf' +] + +debugger_script_compile_proc = popen(command) + +print 'Validating injected-script-source.js...' +injectedscript_check_script_path = path.join(v8_inspector_path, 'build', + 'check_injected_script_source.py') +validate_injected_script_proc = popen([sys.executable, + injectedscript_check_script_path, injected_script_source_name]) + +print + +(injected_script_compile_out, _) = injected_script_compile_proc.communicate() +print 'injected-script-source.js compilation output:%s' % os.linesep +print injected_script_compile_out +errors_found |= has_errors(injected_script_compile_out) + +(debugger_script_compiler_out, _) = debugger_script_compile_proc.communicate() +print 'debugger-script.js compilation output:%s' % os.linesep +print debugger_script_compiler_out +errors_found |= has_errors(debugger_script_compiler_out) + +(validate_injected_script_out, _) = validate_injected_script_proc.communicate() +print 'Validate injected-script-source.js output:%s' % os.linesep +print validate_injected_script_out if validate_injected_script_out else '' +errors_found |= has_errors(validate_injected_script_out) + +os.remove(protocol_externs_file) + +if errors_found: + print 'ERRORS DETECTED' + sys.exit(1) diff --git a/deps/v8_inspector/src/inspector/build/generate_protocol_externs.py b/deps/v8_inspector/src/inspector/build/generate_protocol_externs.py new file mode 100755 index 00000000000000..c2ba2c5b84e5d6 --- /dev/null +++ b/deps/v8_inspector/src/inspector/build/generate_protocol_externs.py @@ -0,0 +1,246 @@ +#!/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. + +import os +import re +import json + +type_traits = { + "any": "*", + "string": "string", + "integer": "number", + "number": "number", + "boolean": "boolean", + "array": "!Array.<*>", + "object": "!Object", +} + +promisified_domains = { + "Accessibility", + "Animation", + "CSS", + "Emulation", + "Profiler" +} + +ref_types = {} + +def full_qualified_type_id(domain_name, type_id): + if type_id.find(".") == -1: + return "%s.%s" % (domain_name, type_id) + return type_id + + +def fix_camel_case(name): + prefix = "" + if name[0] == "-": + prefix = "Negative" + name = name[1:] + refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name) + refined = to_title_case(refined) + return prefix + re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined) + + +def to_title_case(name): + return name[:1].upper() + name[1:] + + +def generate_enum(name, json): + enum_members = [] + for member in json["enum"]: + enum_members.append(" %s: \"%s\"" % (fix_camel_case(member), member)) + return "\n/** @enum {string} */\n%s = {\n%s\n};\n" % (name, (",\n".join(enum_members))) + + +def param_type(domain_name, param): + if "type" in param: + if param["type"] == "array": + items = param["items"] + return "!Array.<%s>" % param_type(domain_name, items) + else: + return type_traits[param["type"]] + if "$ref" in param: + type_id = full_qualified_type_id(domain_name, param["$ref"]) + if type_id in ref_types: + return ref_types[type_id] + else: + print "Type not found: " + type_id + return "!! Type not found: " + type_id + + +def load_schema(file, domains): + input_file = open(file, "r") + json_string = input_file.read() + parsed_json = json.loads(json_string) + domains.extend(parsed_json["domains"]) + + +def generate_protocol_externs(output_path, file1): + domains = [] + load_schema(file1, domains) + output_file = open(output_path, "w") + + output_file.write( +""" +var InspectorBackend = {} + +var Protocol = {}; +/** @typedef {string}*/ +Protocol.Error; +""") + + for domain in domains: + domain_name = domain["domain"] + if "types" in domain: + for type in domain["types"]: + type_id = full_qualified_type_id(domain_name, type["id"]) + ref_types[type_id] = "%sAgent.%s" % (domain_name, type["id"]) + + for domain in domains: + domain_name = domain["domain"] + promisified = domain_name in promisified_domains + + output_file.write("\n\n/**\n * @constructor\n*/\n") + output_file.write("Protocol.%sAgent = function(){};\n" % domain_name) + + if "commands" in domain: + for command in domain["commands"]: + output_file.write("\n/**\n") + params = [] + has_return_value = "returns" in command + explicit_parameters = promisified and has_return_value + if ("parameters" in command): + for in_param in command["parameters"]: + # All parameters are not optional in case of promisified domain with return value. + if (not explicit_parameters and "optional" in in_param): + params.append("opt_%s" % in_param["name"]) + output_file.write(" * @param {%s=} opt_%s\n" % (param_type(domain_name, in_param), in_param["name"])) + else: + params.append(in_param["name"]) + output_file.write(" * @param {%s} %s\n" % (param_type(domain_name, in_param), in_param["name"])) + returns = [] + returns.append("?Protocol.Error") + if ("error" in command): + returns.append("%s=" % param_type(domain_name, command["error"])) + if (has_return_value): + for out_param in command["returns"]: + if ("optional" in out_param): + returns.append("%s=" % param_type(domain_name, out_param)) + else: + returns.append("%s" % param_type(domain_name, out_param)) + callback_return_type = "void=" + if explicit_parameters: + callback_return_type = "T" + elif promisified: + callback_return_type = "T=" + output_file.write(" * @param {function(%s):%s} opt_callback\n" % (", ".join(returns), callback_return_type)) + if (promisified): + output_file.write(" * @return {!Promise.}\n") + output_file.write(" * @template T\n") + params.append("opt_callback") + + output_file.write(" */\n") + output_file.write("Protocol.%sAgent.prototype.%s = function(%s) {}\n" % (domain_name, command["name"], ", ".join(params))) + output_file.write("/** @param {function(%s):void=} opt_callback */\n" % ", ".join(returns)) + output_file.write("Protocol.%sAgent.prototype.invoke_%s = function(obj, opt_callback) {}\n" % (domain_name, command["name"])) + + output_file.write("\n\n\nvar %sAgent = function(){};\n" % domain_name) + + if "types" in domain: + for type in domain["types"]: + if type["type"] == "object": + typedef_args = [] + if "properties" in type: + for property in type["properties"]: + suffix = "" + if ("optional" in property): + suffix = "|undefined" + if "enum" in property: + enum_name = "%sAgent.%s%s" % (domain_name, type["id"], to_title_case(property["name"])) + output_file.write(generate_enum(enum_name, property)) + typedef_args.append("%s:(%s%s)" % (property["name"], enum_name, suffix)) + else: + typedef_args.append("%s:(%s%s)" % (property["name"], param_type(domain_name, property), suffix)) + if (typedef_args): + output_file.write("\n/** @typedef {!{%s}} */\n%sAgent.%s;\n" % (", ".join(typedef_args), domain_name, type["id"])) + else: + output_file.write("\n/** @typedef {!Object} */\n%sAgent.%s;\n" % (domain_name, type["id"])) + elif type["type"] == "string" and "enum" in type: + output_file.write(generate_enum("%sAgent.%s" % (domain_name, type["id"]), type)) + elif type["type"] == "array": + output_file.write("\n/** @typedef {!Array.} */\n%sAgent.%s;\n" % (param_type(domain_name, type["items"]), domain_name, type["id"])) + else: + output_file.write("\n/** @typedef {%s} */\n%sAgent.%s;\n" % (type_traits[type["type"]], domain_name, type["id"])) + + output_file.write("/** @interface */\n") + output_file.write("%sAgent.Dispatcher = function() {};\n" % domain_name) + if "events" in domain: + for event in domain["events"]: + params = [] + if ("parameters" in event): + output_file.write("/**\n") + for param in event["parameters"]: + if ("optional" in param): + params.append("opt_%s" % param["name"]) + output_file.write(" * @param {%s=} opt_%s\n" % (param_type(domain_name, param), param["name"])) + else: + params.append(param["name"]) + output_file.write(" * @param {%s} %s\n" % (param_type(domain_name, param), param["name"])) + output_file.write(" */\n") + output_file.write("%sAgent.Dispatcher.prototype.%s = function(%s) {};\n" % (domain_name, event["name"], ", ".join(params))) + + output_file.write("\n/** @constructor\n * @param {!Object.} agentsMap\n */\n") + output_file.write("Protocol.Agents = function(agentsMap){this._agentsMap;};\n") + output_file.write("/**\n * @param {string} domain\n * @param {!Object} dispatcher\n */\n") + output_file.write("Protocol.Agents.prototype.registerDispatcher = function(domain, dispatcher){};\n") + for domain in domains: + domain_name = domain["domain"] + uppercase_length = 0 + while uppercase_length < len(domain_name) and domain_name[uppercase_length].isupper(): + uppercase_length += 1 + + output_file.write("/** @return {!Protocol.%sAgent}*/\n" % domain_name) + output_file.write("Protocol.Agents.prototype.%s = function(){};\n" % (domain_name[:uppercase_length].lower() + domain_name[uppercase_length:] + "Agent")) + + output_file.write("/**\n * @param {!%sAgent.Dispatcher} dispatcher\n */\n" % domain_name) + output_file.write("Protocol.Agents.prototype.register%sDispatcher = function(dispatcher) {}\n" % domain_name) + + + output_file.close() + +if __name__ == "__main__": + import sys + import os.path + program_name = os.path.basename(__file__) + if len(sys.argv) < 4 or sys.argv[1] != "-o": + sys.stderr.write("Usage: %s -o OUTPUT_FILE INPUT_FILE\n" % program_name) + exit(1) + output_path = sys.argv[2] + input_path = sys.argv[3] + generate_protocol_externs(output_path, input_path) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/build/rjsmin.py b/deps/v8_inspector/src/inspector/build/rjsmin.py similarity index 100% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/build/rjsmin.py rename to deps/v8_inspector/src/inspector/build/rjsmin.py diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/build/xxd.py b/deps/v8_inspector/src/inspector/build/xxd.py similarity index 92% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/build/xxd.py rename to deps/v8_inspector/src/inspector/build/xxd.py index 635d80c7d47509..5a63a7cb8d0381 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/build/xxd.py +++ b/deps/v8_inspector/src/inspector/build/xxd.py @@ -1,4 +1,4 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. +# Copyright 2016 the V8 project authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/DebuggerScript.js b/deps/v8_inspector/src/inspector/debugger-script.js similarity index 99% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/DebuggerScript.js rename to deps/v8_inspector/src/inspector/debugger-script.js index 18beac0e03ceea..98910d69df7167 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/DebuggerScript.js +++ b/deps/v8_inspector/src/inspector/debugger-script.js @@ -34,11 +34,12 @@ var DebuggerScript = {}; /** @enum */ -DebuggerScript.PauseOnExceptionsState = { +const PauseOnExceptionsState = { DontPauseOnExceptions: 0, PauseOnAllExceptions: 1, PauseOnUncaughtExceptions: 2 }; +DebuggerScript.PauseOnExceptionsState = PauseOnExceptionsState; DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions; Debug.clearBreakOnException(); @@ -422,7 +423,7 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror) var returnValue = isAtReturn ? frameDetails.returnValue() : undefined; var scopeMirrors = frameMirror.allScopes(false); - /** @type {!Array} */ + /** @type {!Array} */ var scopeTypes = new Array(scopeMirrors.length); /** @type {?Array} */ var scopeObjects = new Array(scopeMirrors.length); diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/debugger_script_externs.js b/deps/v8_inspector/src/inspector/debugger_script_externs.js similarity index 74% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/debugger_script_externs.js rename to deps/v8_inspector/src/inspector/debugger_script_externs.js index 7e80895ed587d0..c7df61f3f49550 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/debugger_script_externs.js +++ b/deps/v8_inspector/src/inspector/debugger_script_externs.js @@ -1,4 +1,4 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -56,27 +56,28 @@ var JavaScriptCallFrameDetails; }} */ var JavaScriptCallFrame; -/** @interface */ -function DebugClass() -{ - /** @type {!LiveEditClass} */ - this.LiveEdit; -} +/** + * @const + */ +var Debug = {}; -DebugClass.prototype.setBreakOnException = function() {} +Debug.setBreakOnException = function() {} -DebugClass.prototype.clearBreakOnException = function() {} +Debug.clearBreakOnException = function() {} -DebugClass.prototype.setBreakOnUncaughtException = function() {} +Debug.setBreakOnUncaughtException = function() {} -DebugClass.prototype.clearBreakOnUncaughtException = function() {} +/** + * @return {undefined} + */ +Debug.clearBreakOnUncaughtException = function() {} -DebugClass.prototype.clearStepping = function() {} +Debug.clearStepping = function() {} -DebugClass.prototype.clearAllBreakPoints = function() {} +Debug.clearAllBreakPoints = function() {} /** @return {!Array} */ -DebugClass.prototype.scripts = function() {} +Debug.scripts = function() {} /** * @param {number} scriptId @@ -86,33 +87,31 @@ DebugClass.prototype.scripts = function() {} * @param {string=} groupId * @param {Debug.BreakPositionAlignment=} positionAlignment */ -DebugClass.prototype.setScriptBreakPointById = function(scriptId, line, column, condition, groupId, positionAlignment) {} +Debug.setScriptBreakPointById = function(scriptId, line, column, condition, groupId, positionAlignment) {} /** * @param {number} breakId * @return {!Array} */ -DebugClass.prototype.findBreakPointActualLocations = function(breakId) {} +Debug.findBreakPointActualLocations = function(breakId) {} /** * @param {number} breakId * @param {boolean} remove * @return {!BreakPoint|undefined} */ -DebugClass.prototype.findBreakPoint = function(breakId, remove) {} +Debug.findBreakPoint = function(breakId, remove) {} /** @return {!DebuggerFlags} */ -DebugClass.prototype.debuggerFlags = function() {} - -/** @type {!DebugClass} */ -var Debug; +Debug.debuggerFlags = function() {} /** @enum */ -Debug.BreakPositionAlignment = { +const BreakPositionAlignment = { Statement: 0, BreakPosition: 1 }; +Debug.BreakPositionAlignment = BreakPositionAlignment; /** @enum */ Debug.StepAction = { StepOut: 0, @@ -121,9 +120,10 @@ Debug.StepAction = { StepOut: 0, StepFrame: 3 }; /** @enum */ -Debug.ScriptCompilationType = { Host: 0, - Eval: 1, - JSON: 2 }; +const ScriptCompilationType = { Host: 0, + Eval: 1, + JSON: 2 }; +Debug.ScriptCompilationType = ScriptCompilationType; /** @interface */ @@ -133,16 +133,14 @@ function DebuggerFlag() {} DebuggerFlag.prototype.setValue = function(value) {} -/** @interface */ -function DebuggerFlags() -{ - /** @type {!DebuggerFlag} */ - this.breakPointsActive; -} - +/** @typedef {{ + * breakPointsActive: !DebuggerFlag + * }} + */ +var DebuggerFlags; -/** @interface */ -function LiveEditClass() {} +/** @const */ +var LiveEdit = {} /** * @param {!Script} script @@ -150,35 +148,32 @@ function LiveEditClass() {} * @param {boolean} previewOnly * @return {!{stack_modified: (boolean|undefined)}} */ -LiveEditClass.prototype.SetScriptSource = function(script, newSource, previewOnly, change_log) {} +LiveEdit.SetScriptSource = function(script, newSource, previewOnly, change_log) {} +/** @constructor */ +function Failure() {} +LiveEdit.Failure = Failure; -/** @interface */ -function LiveEditErrorDetails() -{ - /** @type {string} */ - this.syntaxErrorMessage; - /** @type {!{start: !{line: number, column: number}}} */ - this.position; -} +Debug.LiveEdit = LiveEdit; +/** @typedef {{ + * type: string, + * syntaxErrorMessage: string, + * position: !{start: !{line: number, column: number}}, + * }} + */ +var LiveEditErrorDetails; -/** @interface */ -function BreakpointInfo() -{ - /** @type {number} */ - this.breakpointId; - /** @type {number} */ - this.sourceID; - /** @type {number|undefined} */ - this.lineNumber; - /** @type {number|undefined} */ - this.columnNumber; - /** @type {string|undefined} */ - this.condition; - /** @type {boolean|undefined} */ - this.interstatementLocation; -} +/** @typedef {{ + * breakpointId: number, + * sourceID: number, + * lineNumber: (number|undefined), + * columnNumber: (number|undefined), + * condition: (string|undefined), + * interstatementLocation: (boolean|undefined), + * }} + */ +var BreakpointInfo; /** @interface */ @@ -244,53 +239,32 @@ var ScopeType = { Global: 0, Script: 6 }; -/** @interface */ -function SourceLocation() -{ - /** @type {number} */ - this.script; - /** @type {number} */ - this.position; - /** @type {number} */ - this.line; - /** @type {number} */ - this.column; - /** @type {number} */ - this.start; - /** @type {number} */ - this.end; -} - - -/** @interface */ -function Script() -{ - /** @type {number} */ - this.id; - /** @type {string|undefined} */ - this.context_data; - /** @type {string|undefined} */ - this.source_url; - /** @type {string|undefined} */ - this.source_mapping_url; - /** @type {boolean} */ - this.is_debugger_script; - /** @type {string} */ - this.source; - /** @type {!Array} */ - this.line_ends; - /** @type {number} */ - this.line_offset; - /** @type {number} */ - this.column_offset; -} - -/** @return {string} */ -Script.prototype.nameOrSourceURL = function() {} - -/** @return {!Debug.ScriptCompilationType} */ -Script.prototype.compilationType = function() {} - +/** @typedef {{ + * script: number, + * position: number, + * line: number, + * column:number, + * start: number, + * end: number, + * }} + */ +var SourceLocation; + +/** @typedef{{ + * id: number, + * context_data: (string|undefined), + * source_url: (string|undefined), + * source_mapping_url: (string|undefined), + * is_debugger_script: boolean, + * source: string, + * line_ends: !Array, + * line_offset: number, + * column_offset: number, + * nameOrSourceURL: function():string, + * compilationType: function():!ScriptCompilationType, + * }} + */ +var Script; /** @interface */ function ScopeDetails() {} @@ -301,6 +275,9 @@ ScopeDetails.prototype.object = function() {} /** @return {string|undefined} */ ScopeDetails.prototype.name = function() {} +/** @return {number} */ +ScopeDetails.prototype.type = function() {} + /** @interface */ function FrameDetails() {} @@ -463,11 +440,7 @@ GeneratorMirror.prototype.func = function() {} * @interface * @extends {Mirror} */ -function PropertyMirror() -{ - /** @type {*} */ - this.value_; -} +function PropertyMirror() {} /** @return {!Mirror} */ PropertyMirror.prototype.value = function() {} @@ -475,6 +448,8 @@ PropertyMirror.prototype.value = function() {} /** @return {string} */ PropertyMirror.prototype.name = function() {} +/** @type {*} */ +PropertyMirror.prototype.value_; /** * @interface diff --git a/deps/v8_inspector/src/inspector/injected-script-native.cc b/deps/v8_inspector/src/inspector/injected-script-native.cc new file mode 100644 index 00000000000000..fcf2ead94b3faa --- /dev/null +++ b/deps/v8_inspector/src/inspector/injected-script-native.cc @@ -0,0 +1,89 @@ +// Copyright 2015 the V8 project 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 "src/inspector/injected-script-native.h" + +namespace v8_inspector { + +InjectedScriptNative::InjectedScriptNative(v8::Isolate* isolate) + : m_lastBoundObjectId(1), m_isolate(isolate) {} + +static const char privateKeyName[] = "v8-inspector#injectedScript"; + +InjectedScriptNative::~InjectedScriptNative() {} + +void InjectedScriptNative::setOnInjectedScriptHost( + v8::Local injectedScriptHost) { + v8::HandleScope handleScope(m_isolate); + v8::Local external = v8::External::New(m_isolate, this); + v8::Local privateKey = v8::Private::ForApi( + m_isolate, v8::String::NewFromUtf8(m_isolate, privateKeyName, + v8::NewStringType::kInternalized) + .ToLocalChecked()); + injectedScriptHost->SetPrivate(m_isolate->GetCurrentContext(), privateKey, + external); +} + +InjectedScriptNative* InjectedScriptNative::fromInjectedScriptHost( + v8::Isolate* isolate, v8::Local injectedScriptObject) { + v8::HandleScope handleScope(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Local privateKey = v8::Private::ForApi( + isolate, v8::String::NewFromUtf8(isolate, privateKeyName, + v8::NewStringType::kInternalized) + .ToLocalChecked()); + v8::Local value = + injectedScriptObject->GetPrivate(context, privateKey).ToLocalChecked(); + DCHECK(value->IsExternal()); + v8::Local external = value.As(); + return static_cast(external->Value()); +} + +int InjectedScriptNative::bind(v8::Local value, + const String16& groupName) { + if (m_lastBoundObjectId <= 0) m_lastBoundObjectId = 1; + int id = m_lastBoundObjectId++; + m_idToWrappedObject[id] = + wrapUnique(new v8::Global(m_isolate, value)); + addObjectToGroup(id, groupName); + return id; +} + +void InjectedScriptNative::unbind(int id) { + m_idToWrappedObject.erase(id); + m_idToObjectGroupName.erase(id); +} + +v8::Local InjectedScriptNative::objectForId(int id) { + auto iter = m_idToWrappedObject.find(id); + return iter != m_idToWrappedObject.end() ? iter->second->Get(m_isolate) + : v8::Local(); +} + +void InjectedScriptNative::addObjectToGroup(int objectId, + const String16& groupName) { + if (groupName.isEmpty()) return; + if (objectId <= 0) return; + m_idToObjectGroupName[objectId] = groupName; + m_nameToObjectGroup[groupName].push_back( + objectId); // Creates an empty vector if key is not there +} + +void InjectedScriptNative::releaseObjectGroup(const String16& groupName) { + if (groupName.isEmpty()) return; + NameToObjectGroup::iterator groupIt = m_nameToObjectGroup.find(groupName); + if (groupIt == m_nameToObjectGroup.end()) return; + for (int id : groupIt->second) unbind(id); + m_nameToObjectGroup.erase(groupIt); +} + +String16 InjectedScriptNative::groupName(int objectId) const { + if (objectId <= 0) return String16(); + IdToObjectGroupName::const_iterator iterator = + m_idToObjectGroupName.find(objectId); + return iterator != m_idToObjectGroupName.end() ? iterator->second + : String16(); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/injected-script-native.h b/deps/v8_inspector/src/inspector/injected-script-native.h new file mode 100644 index 00000000000000..3bdf24709dcd2a --- /dev/null +++ b/deps/v8_inspector/src/inspector/injected-script-native.h @@ -0,0 +1,47 @@ +// Copyright 2015 the V8 project 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 V8_INSPECTOR_INJECTEDSCRIPTNATIVE_H_ +#define V8_INSPECTOR_INJECTEDSCRIPTNATIVE_H_ + +#include + +#include "src/inspector/protocol/Protocol.h" + +#include "include/v8.h" + +namespace v8_inspector { + +class InjectedScriptNative final { + public: + explicit InjectedScriptNative(v8::Isolate*); + ~InjectedScriptNative(); + + void setOnInjectedScriptHost(v8::Local); + static InjectedScriptNative* fromInjectedScriptHost(v8::Isolate* isolate, + v8::Local); + + int bind(v8::Local, const String16& groupName); + void unbind(int id); + v8::Local objectForId(int id); + + void releaseObjectGroup(const String16& groupName); + String16 groupName(int objectId) const; + + private: + void addObjectToGroup(int objectId, const String16& groupName); + + int m_lastBoundObjectId; + v8::Isolate* m_isolate; + protocol::HashMap>> + m_idToWrappedObject; + typedef protocol::HashMap IdToObjectGroupName; + IdToObjectGroupName m_idToObjectGroupName; + typedef protocol::HashMap> NameToObjectGroup; + NameToObjectGroup m_nameToObjectGroup; +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_INJECTEDSCRIPTNATIVE_H_ diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptSource.js b/deps/v8_inspector/src/inspector/injected-script-source.js similarity index 99% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptSource.js rename to deps/v8_inspector/src/inspector/injected-script-source.js index 92457fdfbdc068..39c6c9c1e84b0d 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptSource.js +++ b/deps/v8_inspector/src/inspector/injected-script-source.js @@ -33,6 +33,7 @@ * @param {!InjectedScriptHostClass} InjectedScriptHost * @param {!Window|!WorkerGlobalScope} inspectedGlobalObject * @param {number} injectedScriptId + * @suppress {uselessCode} */ (function (InjectedScriptHost, inspectedGlobalObject, injectedScriptId) { @@ -799,7 +800,6 @@ InjectedScript.RemoteObject.prototype = { } /** - * @suppressReceiverCheck * @param {*} object * @param {*=} customObjectConfig * @return {*} diff --git a/deps/v8_inspector/src/inspector/injected-script.cc b/deps/v8_inspector/src/inspector/injected-script.cc new file mode 100644 index 00000000000000..d379a50c7378bf --- /dev/null +++ b/deps/v8_inspector/src/inspector/injected-script.cc @@ -0,0 +1,575 @@ +/* + * Copyright (C) 2012 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. + */ + +#include "src/inspector/injected-script.h" + +#include "src/inspector/injected-script-native.h" +#include "src/inspector/injected-script-source.h" +#include "src/inspector/inspected-context.h" +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/remote-object-id.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-console.h" +#include "src/inspector/v8-function-call.h" +#include "src/inspector/v8-injected-script-host.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-stack-trace-impl.h" +#include "src/inspector/v8-value-copier.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +using protocol::Array; +using protocol::Runtime::PropertyDescriptor; +using protocol::Runtime::InternalPropertyDescriptor; +using protocol::Runtime::RemoteObject; +using protocol::Maybe; + +static bool hasInternalError(ErrorString* errorString, bool hasError) { + if (hasError) *errorString = "Internal error"; + return hasError; +} + +std::unique_ptr InjectedScript::create( + InspectedContext* inspectedContext) { + v8::Isolate* isolate = inspectedContext->isolate(); + v8::HandleScope handles(isolate); + v8::Local context = inspectedContext->context(); + v8::Context::Scope scope(context); + + std::unique_ptr injectedScriptNative( + new InjectedScriptNative(isolate)); + v8::Local scriptHostWrapper = + V8InjectedScriptHost::create(context, inspectedContext->inspector()); + injectedScriptNative->setOnInjectedScriptHost(scriptHostWrapper); + + // Inject javascript into the context. The compiled script is supposed to + // evaluate into + // a single anonymous function(it's anonymous to avoid cluttering the global + // object with + // inspector's stuff) the function is called a few lines below with + // InjectedScriptHost wrapper, + // injected script id and explicit reference to the inspected global object. + // The function is expected + // to create and configure InjectedScript instance that is going to be used by + // the inspector. + String16 injectedScriptSource( + reinterpret_cast(InjectedScriptSource_js), + sizeof(InjectedScriptSource_js)); + v8::Local value; + if (!inspectedContext->inspector() + ->compileAndRunInternalScript( + context, toV8String(isolate, injectedScriptSource)) + .ToLocal(&value)) + return nullptr; + DCHECK(value->IsFunction()); + v8::Local function = v8::Local::Cast(value); + v8::Local windowGlobal = context->Global(); + v8::Local info[] = { + scriptHostWrapper, windowGlobal, + v8::Number::New(isolate, inspectedContext->contextId())}; + v8::MicrotasksScope microtasksScope(isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::Local injectedScriptValue; + if (!function->Call(context, windowGlobal, arraysize(info), info) + .ToLocal(&injectedScriptValue)) + return nullptr; + if (!injectedScriptValue->IsObject()) return nullptr; + return wrapUnique(new InjectedScript(inspectedContext, + injectedScriptValue.As(), + std::move(injectedScriptNative))); +} + +InjectedScript::InjectedScript( + InspectedContext* context, v8::Local object, + std::unique_ptr injectedScriptNative) + : m_context(context), + m_value(context->isolate(), object), + m_native(std::move(injectedScriptNative)) {} + +InjectedScript::~InjectedScript() {} + +void InjectedScript::getProperties( + ErrorString* errorString, v8::Local object, + const String16& groupName, bool ownProperties, bool accessorPropertiesOnly, + bool generatePreview, + std::unique_ptr>* properties, + Maybe* exceptionDetails) { + v8::HandleScope handles(m_context->isolate()); + v8::Local context = m_context->context(); + V8FunctionCall function(m_context->inspector(), m_context->context(), + v8Value(), "getProperties"); + function.appendArgument(object); + function.appendArgument(groupName); + function.appendArgument(ownProperties); + function.appendArgument(accessorPropertiesOnly); + function.appendArgument(generatePreview); + + v8::TryCatch tryCatch(m_context->isolate()); + v8::Local resultValue = function.callWithoutExceptionHandling(); + if (tryCatch.HasCaught()) { + *exceptionDetails = createExceptionDetails(errorString, tryCatch, groupName, + generatePreview); + // FIXME: make properties optional + *properties = Array::create(); + return; + } + if (hasInternalError(errorString, resultValue.IsEmpty())) return; + std::unique_ptr protocolValue = + toProtocolValue(errorString, context, resultValue); + if (!protocolValue) return; + protocol::ErrorSupport errors(errorString); + std::unique_ptr> result = + Array::parse(protocolValue.get(), &errors); + if (!hasInternalError(errorString, errors.hasErrors())) + *properties = std::move(result); +} + +void InjectedScript::releaseObject(const String16& objectId) { + std::unique_ptr parsedObjectId = + protocol::parseJSON(objectId); + if (!parsedObjectId) return; + protocol::DictionaryValue* object = + protocol::DictionaryValue::cast(parsedObjectId.get()); + if (!object) return; + int boundId = 0; + if (!object->getInteger("id", &boundId)) return; + m_native->unbind(boundId); +} + +std::unique_ptr InjectedScript::wrapObject( + ErrorString* errorString, v8::Local value, + const String16& groupName, bool forceValueType, + bool generatePreview) const { + v8::HandleScope handles(m_context->isolate()); + v8::Local wrappedObject; + v8::Local context = m_context->context(); + if (!wrapValue(errorString, value, groupName, forceValueType, generatePreview) + .ToLocal(&wrappedObject)) + return nullptr; + protocol::ErrorSupport errors; + std::unique_ptr protocolValue = + toProtocolValue(errorString, context, wrappedObject); + if (!protocolValue) return nullptr; + std::unique_ptr remoteObject = + protocol::Runtime::RemoteObject::parse(protocolValue.get(), &errors); + if (!remoteObject) *errorString = errors.errors(); + return remoteObject; +} + +bool InjectedScript::wrapObjectProperty(ErrorString* errorString, + v8::Local object, + v8::Local key, + const String16& groupName, + bool forceValueType, + bool generatePreview) const { + v8::Local property; + v8::Local context = m_context->context(); + if (hasInternalError(errorString, + !object->Get(context, key).ToLocal(&property))) + return false; + v8::Local wrappedProperty; + if (!wrapValue(errorString, property, groupName, forceValueType, + generatePreview) + .ToLocal(&wrappedProperty)) + return false; + v8::Maybe success = + createDataProperty(context, object, key, wrappedProperty); + if (hasInternalError(errorString, success.IsNothing() || !success.FromJust())) + return false; + return true; +} + +bool InjectedScript::wrapPropertyInArray(ErrorString* errorString, + v8::Local array, + v8::Local property, + const String16& groupName, + bool forceValueType, + bool generatePreview) const { + V8FunctionCall function(m_context->inspector(), m_context->context(), + v8Value(), "wrapPropertyInArray"); + function.appendArgument(array); + function.appendArgument(property); + function.appendArgument(groupName); + function.appendArgument(forceValueType); + function.appendArgument(generatePreview); + bool hadException = false; + function.call(hadException); + return !hasInternalError(errorString, hadException); +} + +bool InjectedScript::wrapObjectsInArray(ErrorString* errorString, + v8::Local array, + const String16& groupName, + bool forceValueType, + bool generatePreview) const { + V8FunctionCall function(m_context->inspector(), m_context->context(), + v8Value(), "wrapObjectsInArray"); + function.appendArgument(array); + function.appendArgument(groupName); + function.appendArgument(forceValueType); + function.appendArgument(generatePreview); + bool hadException = false; + function.call(hadException); + return !hasInternalError(errorString, hadException); +} + +v8::MaybeLocal InjectedScript::wrapValue( + ErrorString* errorString, v8::Local value, + const String16& groupName, bool forceValueType, + bool generatePreview) const { + V8FunctionCall function(m_context->inspector(), m_context->context(), + v8Value(), "wrapObject"); + function.appendArgument(value); + function.appendArgument(groupName); + function.appendArgument(forceValueType); + function.appendArgument(generatePreview); + bool hadException = false; + v8::Local r = function.call(hadException); + if (hasInternalError(errorString, hadException || r.IsEmpty())) + return v8::MaybeLocal(); + return r; +} + +std::unique_ptr InjectedScript::wrapTable( + v8::Local table, v8::Local columns) const { + v8::HandleScope handles(m_context->isolate()); + v8::Local context = m_context->context(); + V8FunctionCall function(m_context->inspector(), context, v8Value(), + "wrapTable"); + function.appendArgument(table); + if (columns.IsEmpty()) + function.appendArgument(false); + else + function.appendArgument(columns); + bool hadException = false; + v8::Local r = function.call(hadException); + if (hadException || r.IsEmpty()) return nullptr; + protocol::ErrorString errorString; + std::unique_ptr protocolValue = + toProtocolValue(&errorString, context, r); + if (!protocolValue) return nullptr; + protocol::ErrorSupport errors; + return protocol::Runtime::RemoteObject::parse(protocolValue.get(), &errors); +} + +bool InjectedScript::findObject(ErrorString* errorString, + const RemoteObjectId& objectId, + v8::Local* outObject) const { + *outObject = m_native->objectForId(objectId.id()); + if (outObject->IsEmpty()) + *errorString = "Could not find object with given id"; + return !outObject->IsEmpty(); +} + +String16 InjectedScript::objectGroupName(const RemoteObjectId& objectId) const { + return m_native->groupName(objectId.id()); +} + +void InjectedScript::releaseObjectGroup(const String16& objectGroup) { + m_native->releaseObjectGroup(objectGroup); + if (objectGroup == "console") m_lastEvaluationResult.Reset(); +} + +void InjectedScript::setCustomObjectFormatterEnabled(bool enabled) { + v8::HandleScope handles(m_context->isolate()); + V8FunctionCall function(m_context->inspector(), m_context->context(), + v8Value(), "setCustomObjectFormatterEnabled"); + function.appendArgument(enabled); + bool hadException = false; + function.call(hadException); + DCHECK(!hadException); +} + +v8::Local InjectedScript::v8Value() const { + return m_value.Get(m_context->isolate()); +} + +v8::Local InjectedScript::lastEvaluationResult() const { + if (m_lastEvaluationResult.IsEmpty()) + return v8::Undefined(m_context->isolate()); + return m_lastEvaluationResult.Get(m_context->isolate()); +} + +v8::MaybeLocal InjectedScript::resolveCallArgument( + ErrorString* errorString, protocol::Runtime::CallArgument* callArgument) { + if (callArgument->hasObjectId()) { + std::unique_ptr remoteObjectId = + RemoteObjectId::parse(errorString, callArgument->getObjectId("")); + if (!remoteObjectId) return v8::MaybeLocal(); + if (remoteObjectId->contextId() != m_context->contextId()) { + *errorString = + "Argument should belong to the same JavaScript world as target " + "object"; + return v8::MaybeLocal(); + } + v8::Local object; + if (!findObject(errorString, *remoteObjectId, &object)) + return v8::MaybeLocal(); + return object; + } + if (callArgument->hasValue() || callArgument->hasUnserializableValue()) { + String16 value = + callArgument->hasValue() + ? callArgument->getValue(nullptr)->toJSONString() + : "Number(\"" + callArgument->getUnserializableValue("") + "\")"; + v8::Local object; + if (!m_context->inspector() + ->compileAndRunInternalScript( + m_context->context(), toV8String(m_context->isolate(), value)) + .ToLocal(&object)) { + *errorString = "Couldn't parse value object in call argument"; + return v8::MaybeLocal(); + } + return object; + } + return v8::Undefined(m_context->isolate()); +} + +std::unique_ptr +InjectedScript::createExceptionDetails(ErrorString* errorString, + const v8::TryCatch& tryCatch, + const String16& objectGroup, + bool generatePreview) { + if (!tryCatch.HasCaught()) return nullptr; + v8::Local message = tryCatch.Message(); + v8::Local exception = tryCatch.Exception(); + String16 messageText = + message.IsEmpty() ? String16() : toProtocolString(message->Get()); + std::unique_ptr exceptionDetails = + protocol::Runtime::ExceptionDetails::create() + .setExceptionId(m_context->inspector()->nextExceptionId()) + .setText(exception.IsEmpty() ? messageText : String16("Uncaught")) + .setLineNumber( + message.IsEmpty() + ? 0 + : message->GetLineNumber(m_context->context()).FromMaybe(1) - + 1) + .setColumnNumber( + message.IsEmpty() + ? 0 + : message->GetStartColumn(m_context->context()).FromMaybe(0)) + .build(); + if (!message.IsEmpty()) { + exceptionDetails->setScriptId(String16::fromInteger( + static_cast(message->GetScriptOrigin().ScriptID()->Value()))); + v8::Local stackTrace = message->GetStackTrace(); + if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) + exceptionDetails->setStackTrace(m_context->inspector() + ->debugger() + ->createStackTrace(stackTrace) + ->buildInspectorObjectImpl()); + } + if (!exception.IsEmpty()) { + std::unique_ptr wrapped = wrapObject( + errorString, exception, objectGroup, false /* forceValueType */, + generatePreview && !exception->IsNativeError()); + if (!wrapped) return nullptr; + exceptionDetails->setException(std::move(wrapped)); + } + return exceptionDetails; +} + +void InjectedScript::wrapEvaluateResult( + ErrorString* errorString, v8::MaybeLocal maybeResultValue, + const v8::TryCatch& tryCatch, const String16& objectGroup, + bool returnByValue, bool generatePreview, + std::unique_ptr* result, + Maybe* exceptionDetails) { + v8::Local resultValue; + if (!tryCatch.HasCaught()) { + if (hasInternalError(errorString, !maybeResultValue.ToLocal(&resultValue))) + return; + std::unique_ptr remoteObject = wrapObject( + errorString, resultValue, objectGroup, returnByValue, generatePreview); + if (!remoteObject) return; + if (objectGroup == "console") + m_lastEvaluationResult.Reset(m_context->isolate(), resultValue); + *result = std::move(remoteObject); + } else { + v8::Local exception = tryCatch.Exception(); + std::unique_ptr remoteObject = + wrapObject(errorString, exception, objectGroup, false, + generatePreview && !exception->IsNativeError()); + if (!remoteObject) return; + // We send exception in result for compatibility reasons, even though it's + // accessible through exceptionDetails.exception. + *result = std::move(remoteObject); + *exceptionDetails = createExceptionDetails(errorString, tryCatch, + objectGroup, generatePreview); + } +} + +v8::Local InjectedScript::commandLineAPI() { + if (m_commandLineAPI.IsEmpty()) + m_commandLineAPI.Reset(m_context->isolate(), + V8Console::createCommandLineAPI(m_context)); + return m_commandLineAPI.Get(m_context->isolate()); +} + +InjectedScript::Scope::Scope(ErrorString* errorString, + V8InspectorImpl* inspector, int contextGroupId) + : m_errorString(errorString), + m_inspector(inspector), + m_contextGroupId(contextGroupId), + m_injectedScript(nullptr), + m_handleScope(inspector->isolate()), + m_tryCatch(inspector->isolate()), + m_ignoreExceptionsAndMuteConsole(false), + m_previousPauseOnExceptionsState(V8Debugger::DontPauseOnExceptions), + m_userGesture(false) {} + +bool InjectedScript::Scope::initialize() { + cleanup(); + // TODO(dgozman): what if we reattach to the same context group during + // evaluate? Introduce a session id? + V8InspectorSessionImpl* session = + m_inspector->sessionForContextGroup(m_contextGroupId); + if (!session) { + *m_errorString = "Internal error"; + return false; + } + findInjectedScript(session); + if (!m_injectedScript) return false; + m_context = m_injectedScript->context()->context(); + m_context->Enter(); + return true; +} + +bool InjectedScript::Scope::installCommandLineAPI() { + DCHECK(m_injectedScript && !m_context.IsEmpty() && + !m_commandLineAPIScope.get()); + m_commandLineAPIScope.reset(new V8Console::CommandLineAPIScope( + m_context, m_injectedScript->commandLineAPI(), m_context->Global())); + return true; +} + +void InjectedScript::Scope::ignoreExceptionsAndMuteConsole() { + DCHECK(!m_ignoreExceptionsAndMuteConsole); + m_ignoreExceptionsAndMuteConsole = true; + m_inspector->client()->muteMetrics(m_contextGroupId); + m_inspector->muteExceptions(m_contextGroupId); + m_previousPauseOnExceptionsState = + setPauseOnExceptionsState(V8Debugger::DontPauseOnExceptions); +} + +V8Debugger::PauseOnExceptionsState +InjectedScript::Scope::setPauseOnExceptionsState( + V8Debugger::PauseOnExceptionsState newState) { + if (!m_inspector->debugger()->enabled()) return newState; + V8Debugger::PauseOnExceptionsState presentState = + m_inspector->debugger()->getPauseOnExceptionsState(); + if (presentState != newState) + m_inspector->debugger()->setPauseOnExceptionsState(newState); + return presentState; +} + +void InjectedScript::Scope::pretendUserGesture() { + DCHECK(!m_userGesture); + m_userGesture = true; + m_inspector->client()->beginUserGesture(); +} + +void InjectedScript::Scope::cleanup() { + m_commandLineAPIScope.reset(); + if (!m_context.IsEmpty()) { + m_context->Exit(); + m_context.Clear(); + } +} + +InjectedScript::Scope::~Scope() { + if (m_ignoreExceptionsAndMuteConsole) { + setPauseOnExceptionsState(m_previousPauseOnExceptionsState); + m_inspector->client()->unmuteMetrics(m_contextGroupId); + m_inspector->unmuteExceptions(m_contextGroupId); + } + if (m_userGesture) m_inspector->client()->endUserGesture(); + cleanup(); +} + +InjectedScript::ContextScope::ContextScope(ErrorString* errorString, + V8InspectorImpl* inspector, + int contextGroupId, + int executionContextId) + : InjectedScript::Scope(errorString, inspector, contextGroupId), + m_executionContextId(executionContextId) {} + +InjectedScript::ContextScope::~ContextScope() {} + +void InjectedScript::ContextScope::findInjectedScript( + V8InspectorSessionImpl* session) { + m_injectedScript = + session->findInjectedScript(m_errorString, m_executionContextId); +} + +InjectedScript::ObjectScope::ObjectScope(ErrorString* errorString, + V8InspectorImpl* inspector, + int contextGroupId, + const String16& remoteObjectId) + : InjectedScript::Scope(errorString, inspector, contextGroupId), + m_remoteObjectId(remoteObjectId) {} + +InjectedScript::ObjectScope::~ObjectScope() {} + +void InjectedScript::ObjectScope::findInjectedScript( + V8InspectorSessionImpl* session) { + std::unique_ptr remoteId = + RemoteObjectId::parse(m_errorString, m_remoteObjectId); + if (!remoteId) return; + InjectedScript* injectedScript = + session->findInjectedScript(m_errorString, remoteId.get()); + if (!injectedScript) return; + m_objectGroupName = injectedScript->objectGroupName(*remoteId); + if (!injectedScript->findObject(m_errorString, *remoteId, &m_object)) return; + m_injectedScript = injectedScript; +} + +InjectedScript::CallFrameScope::CallFrameScope(ErrorString* errorString, + V8InspectorImpl* inspector, + int contextGroupId, + const String16& remoteObjectId) + : InjectedScript::Scope(errorString, inspector, contextGroupId), + m_remoteCallFrameId(remoteObjectId) {} + +InjectedScript::CallFrameScope::~CallFrameScope() {} + +void InjectedScript::CallFrameScope::findInjectedScript( + V8InspectorSessionImpl* session) { + std::unique_ptr remoteId = + RemoteCallFrameId::parse(m_errorString, m_remoteCallFrameId); + if (!remoteId) return; + m_frameOrdinal = static_cast(remoteId->frameOrdinal()); + m_injectedScript = session->findInjectedScript(m_errorString, remoteId.get()); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/injected-script.h b/deps/v8_inspector/src/inspector/injected-script.h new file mode 100644 index 00000000000000..9b324c948d4f59 --- /dev/null +++ b/deps/v8_inspector/src/inspector/injected-script.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2012 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. + */ + +#ifndef V8_INSPECTOR_INJECTEDSCRIPT_H_ +#define V8_INSPECTOR_INJECTEDSCRIPT_H_ + +#include "src/base/macros.h" +#include "src/inspector/injected-script-native.h" +#include "src/inspector/inspected-context.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/Runtime.h" +#include "src/inspector/v8-console.h" +#include "src/inspector/v8-debugger.h" + +#include "include/v8.h" + +namespace v8_inspector { + +class RemoteObjectId; +class V8FunctionCall; +class V8InspectorImpl; +class V8InspectorSessionImpl; + +using protocol::ErrorString; +using protocol::Maybe; + +class InjectedScript final { + public: + static std::unique_ptr create(InspectedContext*); + ~InjectedScript(); + + InspectedContext* context() const { return m_context; } + + void getProperties( + ErrorString*, v8::Local, const String16& groupName, + bool ownProperties, bool accessorPropertiesOnly, bool generatePreview, + std::unique_ptr>* + result, + Maybe*); + void releaseObject(const String16& objectId); + + std::unique_ptr wrapObject( + ErrorString*, v8::Local, const String16& groupName, + bool forceValueType = false, bool generatePreview = false) const; + bool wrapObjectProperty(ErrorString*, v8::Local, + v8::Local key, const String16& groupName, + bool forceValueType = false, + bool generatePreview = false) const; + bool wrapPropertyInArray(ErrorString*, v8::Local, + v8::Local property, + const String16& groupName, + bool forceValueType = false, + bool generatePreview = false) const; + bool wrapObjectsInArray(ErrorString*, v8::Local, + const String16& groupName, + bool forceValueType = false, + bool generatePreview = false) const; + std::unique_ptr wrapTable( + v8::Local table, v8::Local columns) const; + + bool findObject(ErrorString*, const RemoteObjectId&, + v8::Local*) const; + String16 objectGroupName(const RemoteObjectId&) const; + void releaseObjectGroup(const String16&); + void setCustomObjectFormatterEnabled(bool); + v8::MaybeLocal resolveCallArgument( + ErrorString*, protocol::Runtime::CallArgument*); + + std::unique_ptr createExceptionDetails( + ErrorString*, const v8::TryCatch&, const String16& groupName, + bool generatePreview); + void wrapEvaluateResult( + ErrorString*, v8::MaybeLocal maybeResultValue, + const v8::TryCatch&, const String16& objectGroup, bool returnByValue, + bool generatePreview, + std::unique_ptr* result, + Maybe*); + v8::Local lastEvaluationResult() const; + + class Scope { + public: + bool initialize(); + bool installCommandLineAPI(); + void ignoreExceptionsAndMuteConsole(); + void pretendUserGesture(); + v8::Local context() const { return m_context; } + InjectedScript* injectedScript() const { return m_injectedScript; } + const v8::TryCatch& tryCatch() const { return m_tryCatch; } + + protected: + Scope(ErrorString*, V8InspectorImpl*, int contextGroupId); + virtual ~Scope(); + virtual void findInjectedScript(V8InspectorSessionImpl*) = 0; + + ErrorString* m_errorString; + V8InspectorImpl* m_inspector; + int m_contextGroupId; + InjectedScript* m_injectedScript; + + private: + void cleanup(); + V8Debugger::PauseOnExceptionsState setPauseOnExceptionsState( + V8Debugger::PauseOnExceptionsState); + + v8::HandleScope m_handleScope; + v8::TryCatch m_tryCatch; + v8::Local m_context; + std::unique_ptr m_commandLineAPIScope; + bool m_ignoreExceptionsAndMuteConsole; + V8Debugger::PauseOnExceptionsState m_previousPauseOnExceptionsState; + bool m_userGesture; + }; + + class ContextScope : public Scope { + public: + ContextScope(ErrorString*, V8InspectorImpl*, int contextGroupId, + int executionContextId); + ~ContextScope(); + + private: + void findInjectedScript(V8InspectorSessionImpl*) override; + int m_executionContextId; + + DISALLOW_COPY_AND_ASSIGN(ContextScope); + }; + + class ObjectScope : public Scope { + public: + ObjectScope(ErrorString*, V8InspectorImpl*, int contextGroupId, + const String16& remoteObjectId); + ~ObjectScope(); + const String16& objectGroupName() const { return m_objectGroupName; } + v8::Local object() const { return m_object; } + + private: + void findInjectedScript(V8InspectorSessionImpl*) override; + String16 m_remoteObjectId; + String16 m_objectGroupName; + v8::Local m_object; + + DISALLOW_COPY_AND_ASSIGN(ObjectScope); + }; + + class CallFrameScope : public Scope { + public: + CallFrameScope(ErrorString*, V8InspectorImpl*, int contextGroupId, + const String16& remoteCallFrameId); + ~CallFrameScope(); + size_t frameOrdinal() const { return m_frameOrdinal; } + + private: + void findInjectedScript(V8InspectorSessionImpl*) override; + String16 m_remoteCallFrameId; + size_t m_frameOrdinal; + + DISALLOW_COPY_AND_ASSIGN(CallFrameScope); + }; + + private: + InjectedScript(InspectedContext*, v8::Local, + std::unique_ptr); + v8::Local v8Value() const; + v8::MaybeLocal wrapValue(ErrorString*, v8::Local, + const String16& groupName, + bool forceValueType, + bool generatePreview) const; + v8::Local commandLineAPI(); + + InspectedContext* m_context; + v8::Global m_value; + v8::Global m_lastEvaluationResult; + std::unique_ptr m_native; + v8::Global m_commandLineAPI; + + DISALLOW_COPY_AND_ASSIGN(InjectedScript); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_INJECTEDSCRIPT_H_ diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/injected_script_externs.js b/deps/v8_inspector/src/inspector/injected_script_externs.js similarity index 95% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/injected_script_externs.js rename to deps/v8_inspector/src/inspector/injected_script_externs.js index 03455614f32f1f..b6339c6eb08667 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/injected_script_externs.js +++ b/deps/v8_inspector/src/inspector/injected_script_externs.js @@ -1,4 +1,4 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. +// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/deps/v8_inspector/src/inspector/inspected-context.cc b/deps/v8_inspector/src/inspector/inspected-context.cc new file mode 100644 index 00000000000000..3fdb0846f3c053 --- /dev/null +++ b/deps/v8_inspector/src/inspector/inspected-context.cc @@ -0,0 +1,84 @@ +// Copyright 2016 the V8 project 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 "src/inspector/inspected-context.h" + +#include "src/inspector/injected-script.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-console.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-value-copier.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +void InspectedContext::weakCallback( + const v8::WeakCallbackInfo& data) { + InspectedContext* context = data.GetParameter(); + if (!context->m_context.IsEmpty()) { + context->m_context.Reset(); + data.SetSecondPassCallback(&InspectedContext::weakCallback); + } else { + context->m_inspector->discardInspectedContext(context->m_contextGroupId, + context->m_contextId); + } +} + +void InspectedContext::consoleWeakCallback( + const v8::WeakCallbackInfo& data) { + data.GetParameter()->m_console.Reset(); +} + +InspectedContext::InspectedContext(V8InspectorImpl* inspector, + const V8ContextInfo& info, int contextId) + : m_inspector(inspector), + m_context(info.context->GetIsolate(), info.context), + m_contextId(contextId), + m_contextGroupId(info.contextGroupId), + m_origin(toString16(info.origin)), + m_humanReadableName(toString16(info.humanReadableName)), + m_auxData(toString16(info.auxData)), + m_reported(false) { + m_context.SetWeak(this, &InspectedContext::weakCallback, + v8::WeakCallbackType::kParameter); + + v8::Isolate* isolate = m_inspector->isolate(); + v8::Local global = info.context->Global(); + v8::Local console = + V8Console::createConsole(this, info.hasMemoryOnConsole); + if (!global + ->Set(info.context, toV8StringInternalized(isolate, "console"), + console) + .FromMaybe(false)) + return; + m_console.Reset(isolate, console); + m_console.SetWeak(this, &InspectedContext::consoleWeakCallback, + v8::WeakCallbackType::kParameter); +} + +InspectedContext::~InspectedContext() { + if (!m_context.IsEmpty() && !m_console.IsEmpty()) { + v8::HandleScope scope(isolate()); + V8Console::clearInspectedContextIfNeeded(context(), + m_console.Get(isolate())); + } +} + +v8::Local InspectedContext::context() const { + return m_context.Get(isolate()); +} + +v8::Isolate* InspectedContext::isolate() const { + return m_inspector->isolate(); +} + +void InspectedContext::createInjectedScript() { + DCHECK(!m_injectedScript); + m_injectedScript = InjectedScript::create(this); +} + +void InspectedContext::discardInjectedScript() { m_injectedScript.reset(); } + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/inspected-context.h b/deps/v8_inspector/src/inspector/inspected-context.h new file mode 100644 index 00000000000000..443f4a1425734f --- /dev/null +++ b/deps/v8_inspector/src/inspector/inspected-context.h @@ -0,0 +1,64 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_INSPECTEDCONTEXT_H_ +#define V8_INSPECTOR_INSPECTEDCONTEXT_H_ + +#include "src/base/macros.h" +#include "src/inspector/string-16.h" + +#include "include/v8.h" + +namespace v8_inspector { + +class InjectedScript; +class InjectedScriptHost; +class V8ContextInfo; +class V8InspectorImpl; + +class InspectedContext { + public: + ~InspectedContext(); + + v8::Local context() const; + int contextId() const { return m_contextId; } + int contextGroupId() const { return m_contextGroupId; } + String16 origin() const { return m_origin; } + String16 humanReadableName() const { return m_humanReadableName; } + String16 auxData() const { return m_auxData; } + + bool isReported() const { return m_reported; } + void setReported(bool reported) { m_reported = reported; } + + v8::Isolate* isolate() const; + V8InspectorImpl* inspector() const { return m_inspector; } + + InjectedScript* getInjectedScript() { return m_injectedScript.get(); } + void createInjectedScript(); + void discardInjectedScript(); + + private: + friend class V8InspectorImpl; + InspectedContext(V8InspectorImpl*, const V8ContextInfo&, int contextId); + static void weakCallback(const v8::WeakCallbackInfo&); + static void consoleWeakCallback( + const v8::WeakCallbackInfo&); + + V8InspectorImpl* m_inspector; + v8::Global m_context; + int m_contextId; + int m_contextGroupId; + const String16 m_origin; + const String16 m_humanReadableName; + const String16 m_auxData; + bool m_reported; + std::unique_ptr m_injectedScript; + v8::Global m_console; + + DISALLOW_COPY_AND_ASSIGN(InspectedContext); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_INSPECTEDCONTEXT_H_ diff --git a/deps/v8_inspector/src/inspector/inspector.gyp b/deps/v8_inspector/src/inspector/inspector.gyp new file mode 100644 index 00000000000000..231814cb31f48c --- /dev/null +++ b/deps/v8_inspector/src/inspector/inspector.gyp @@ -0,0 +1,131 @@ +# Copyright 2016 the V8 project 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': { + 'protocol_path': '../../third_party/WebKit/Source/platform/inspector_protocol', + }, + 'includes': [ + '../../../v8/gypfiles/toolchain.gypi', + '../../../v8/gypfiles/features.gypi', + 'inspector.gypi', + '../../third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gypi', + ], + 'targets': [ + { 'target_name': 'inspector_injected_script', + 'type': 'none', + 'actions': [ + { + 'action_name': 'convert_js_to_cpp_char_array', + 'inputs': [ + 'build/xxd.py', + '<(inspector_injected_script_source)', + ], + 'outputs': [ + '<(inspector_generated_injected_script)', + ], + 'action': [ + 'python', + 'build/xxd.py', + 'InjectedScriptSource_js', + 'injected-script-source.js', + '<@(_outputs)' + ], + }, + ], + # Since this target generates header files, it needs to be a hard dependency. + 'hard_dependency': 1, + }, + { 'target_name': 'inspector_debugger_script', + 'type': 'none', + 'actions': [ + { + 'action_name': 'convert_js_to_cpp_char_array', + 'inputs': [ + 'build/xxd.py', + '<(inspector_debugger_script_source)', + ], + 'outputs': [ + '<(inspector_generated_debugger_script)', + ], + 'action': [ + 'python', + 'build/xxd.py', + 'DebuggerScript_js', + 'debugger-script.js', + '<@(_outputs)' + ], + }, + ], + # Since this target generates header files, it needs to be a hard dependency. + 'hard_dependency': 1, + }, + { 'target_name': 'protocol_compatibility', + 'type': 'none', + 'actions': [ + { + 'action_name': 'protocol_compatibility', + 'inputs': [ + 'js_protocol.json', + ], + 'outputs': [ + '<@(SHARED_INTERMEDIATE_DIR)/src/js_protocol.stamp', + ], + 'action': [ + 'python', + '<(protocol_path)/CheckProtocolCompatibility.py', + '--stamp', '<@(_outputs)', + 'js_protocol.json', + ], + 'message': 'Generating inspector protocol sources from protocol json definition', + }, + ] + }, + { 'target_name': 'protocol_generated_sources', + 'type': 'none', + 'dependencies': [ 'protocol_compatibility' ], + 'actions': [ + { + 'action_name': 'protocol_generated_sources', + 'inputs': [ + 'js_protocol.json', + 'inspector_protocol_config.json', + '<@(inspector_protocol_files)', + ], + 'outputs': [ + '<@(inspector_generated_sources)', + ], + 'action': [ + 'python', + '<(protocol_path)/CodeGenerator.py', + '--jinja_dir', '../../third_party', + '--output_base', '<(SHARED_INTERMEDIATE_DIR)/src/inspector', + '--config', 'inspector_protocol_config.json', + ], + 'message': 'Generating inspector protocol sources from protocol json', + }, + ] + }, + { + 'target_name': 'standalone_inspector', + 'type': 'static_library', + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + '<(SHARED_INTERMEDIATE_DIR)/include', + '../../include', + '../..', + '../../../v8' + ], + 'sources': [ + '<@(inspector_all_sources)' + ], + 'dependencies': [ + 'protocol_generated_sources', + 'inspector_injected_script', + 'inspector_debugger_script', + '../../../v8/src/v8.gyp:v8_libplatform', + ], + }, + ], +} diff --git a/deps/v8_inspector/src/inspector/inspector.gypi b/deps/v8_inspector/src/inspector/inspector.gypi new file mode 100644 index 00000000000000..031735d7c6a610 --- /dev/null +++ b/deps/v8_inspector/src/inspector/inspector.gypi @@ -0,0 +1,95 @@ +# Copyright 2016 the V8 project 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_generated_sources': [ + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Forward.h', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Protocol.cpp', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Protocol.h', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Console.cpp', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Console.h', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Debugger.cpp', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Debugger.h', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/HeapProfiler.cpp', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/HeapProfiler.h', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Profiler.cpp', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Profiler.h', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Runtime.cpp', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Runtime.h', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Schema.cpp', + '<(SHARED_INTERMEDIATE_DIR)/src/inspector/protocol/Schema.h', + '<(SHARED_INTERMEDIATE_DIR)/include/inspector/Debugger.h', + '<(SHARED_INTERMEDIATE_DIR)/include/inspector/Runtime.h', + '<(SHARED_INTERMEDIATE_DIR)/include/inspector/Schema.h', + ], + + 'inspector_injected_script_source': 'injected-script-source.js', + 'inspector_generated_injected_script': '<(SHARED_INTERMEDIATE_DIR)/src/inspector/injected-script-source.h', + 'inspector_debugger_script_source': 'debugger-script.js', + 'inspector_generated_debugger_script': '<(SHARED_INTERMEDIATE_DIR)/src/inspector/debugger-script.h', + + 'inspector_all_sources': [ + '<@(inspector_generated_sources)', + '<(inspector_generated_injected_script)', + '<(inspector_generated_debugger_script)', + '../../include/v8-inspector.h', + '../../include/v8-inspector-protocol.h', + 'injected-script.cc', + 'injected-script.h', + 'injected-script-native.cc', + 'injected-script-native.h', + 'inspected-context.cc', + 'inspected-context.h', + 'java-script-call-frame.cc', + 'java-script-call-frame.h', + 'protocol-platform.h', + 'remote-object-id.cc', + 'remote-object-id.h', + 'script-breakpoint.h', + 'search-util.cc', + 'search-util.h', + 'string-16.cc', + 'string-16.h', + 'string-util.cc', + 'string-util.h', + 'v8-console.cc', + 'v8-console.h', + 'v8-console-agent-impl.cc', + 'v8-console-agent-impl.h', + 'v8-console-message.cc', + 'v8-console-message.h', + 'v8-debugger.cc', + 'v8-debugger.h', + 'v8-debugger-agent-impl.cc', + 'v8-debugger-agent-impl.h', + 'v8-debugger-script.cc', + 'v8-debugger-script.h', + 'v8-function-call.cc', + 'v8-function-call.h', + 'v8-heap-profiler-agent-impl.cc', + 'v8-heap-profiler-agent-impl.h', + 'v8-injected-script-host.cc', + 'v8-injected-script-host.h', + 'v8-inspector-impl.cc', + 'v8-inspector-impl.h', + 'v8-inspector-session-impl.cc', + 'v8-inspector-session-impl.h', + 'v8-internal-value-type.cc', + 'v8-internal-value-type.h', + 'v8-profiler-agent-impl.cc', + 'v8-profiler-agent-impl.h', + 'v8-regex.cc', + 'v8-regex.h', + 'v8-runtime-agent-impl.cc', + 'v8-runtime-agent-impl.h', + 'v8-schema-agent-impl.cc', + 'v8-schema-agent-impl.h', + 'v8-stack-trace-impl.cc', + 'v8-stack-trace-impl.h', + 'v8-value-copier.cc', + 'v8-value-copier.h', + ] + } +} diff --git a/deps/v8_inspector/src/inspector/inspector_protocol_config.json b/deps/v8_inspector/src/inspector/inspector_protocol_config.json new file mode 100644 index 00000000000000..cb9e6698d16609 --- /dev/null +++ b/deps/v8_inspector/src/inspector/inspector_protocol_config.json @@ -0,0 +1,25 @@ +{ + "protocol": { + "path": "js_protocol.json", + "package": "src/inspector/protocol", + "output": "protocol", + "namespace": ["v8_inspector", "protocol"] + }, + + "exported": { + "package": "include/inspector", + "output": "../../include/inspector", + "string_header": "v8-inspector.h", + "string_in": "StringView", + "string_out": "std::unique_ptr", + "to_string_out": "StringBufferImpl::adopt(%s)", + "export_macro": "V8_EXPORT" + }, + + "lib": { + "package": "src/inspector/protocol", + "output": "protocol", + "string_header": "src/inspector/string-util.h", + "platform_header": "src/inspector/protocol-platform.h" + } +} diff --git a/deps/v8_inspector/src/inspector/java-script-call-frame.cc b/deps/v8_inspector/src/inspector/java-script-call-frame.cc new file mode 100644 index 00000000000000..b70af21f8646e6 --- /dev/null +++ b/deps/v8_inspector/src/inspector/java-script-call-frame.cc @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2010, 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. + */ + +#include "src/inspector/java-script-call-frame.h" + +#include "src/inspector/string-util.h" + +#include "include/v8-debug.h" + +namespace v8_inspector { + +JavaScriptCallFrame::JavaScriptCallFrame(v8::Local debuggerContext, + v8::Local callFrame) + : m_isolate(debuggerContext->GetIsolate()), + m_debuggerContext(m_isolate, debuggerContext), + m_callFrame(m_isolate, callFrame) {} + +JavaScriptCallFrame::~JavaScriptCallFrame() {} + +int JavaScriptCallFrame::callV8FunctionReturnInt(const char* name) const { + v8::HandleScope handleScope(m_isolate); + v8::MicrotasksScope microtasks(m_isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::Local context = + v8::Local::New(m_isolate, m_debuggerContext); + v8::Local callFrame = + v8::Local::New(m_isolate, m_callFrame); + v8::Local func = v8::Local::Cast( + callFrame->Get(context, toV8StringInternalized(m_isolate, name)) + .ToLocalChecked()); + v8::Local result; + if (!func->Call(context, callFrame, 0, nullptr).ToLocal(&result) || + !result->IsInt32()) + return 0; + return result.As()->Value(); +} + +int JavaScriptCallFrame::sourceID() const { + return callV8FunctionReturnInt("sourceID"); +} + +int JavaScriptCallFrame::line() const { + return callV8FunctionReturnInt("line"); +} + +int JavaScriptCallFrame::column() const { + return callV8FunctionReturnInt("column"); +} + +int JavaScriptCallFrame::contextId() const { + return callV8FunctionReturnInt("contextId"); +} + +bool JavaScriptCallFrame::isAtReturn() const { + v8::HandleScope handleScope(m_isolate); + v8::Local context = + v8::Local::New(m_isolate, m_debuggerContext); + v8::Local callFrame = + v8::Local::New(m_isolate, m_callFrame); + v8::Local result; + if (!callFrame->Get(context, toV8StringInternalized(m_isolate, "isAtReturn")) + .ToLocal(&result) || + !result->IsBoolean()) + return false; + return result.As()->BooleanValue(context).FromMaybe(false); +} + +v8::Local JavaScriptCallFrame::details() const { + v8::MicrotasksScope microtasks(m_isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::Local context = + v8::Local::New(m_isolate, m_debuggerContext); + v8::Local callFrame = + v8::Local::New(m_isolate, m_callFrame); + v8::Local func = v8::Local::Cast( + callFrame->Get(context, toV8StringInternalized(m_isolate, "details")) + .ToLocalChecked()); + return v8::Local::Cast( + func->Call(context, callFrame, 0, nullptr).ToLocalChecked()); +} + +v8::MaybeLocal JavaScriptCallFrame::evaluate( + v8::Local expression) { + v8::MicrotasksScope microtasks(m_isolate, + v8::MicrotasksScope::kRunMicrotasks); + v8::Local context = + v8::Local::New(m_isolate, m_debuggerContext); + v8::Local callFrame = + v8::Local::New(m_isolate, m_callFrame); + v8::Local evalFunction = v8::Local::Cast( + callFrame->Get(context, toV8StringInternalized(m_isolate, "evaluate")) + .ToLocalChecked()); + return evalFunction->Call(context, callFrame, 1, &expression); +} + +v8::MaybeLocal JavaScriptCallFrame::restart() { + v8::MicrotasksScope microtasks(m_isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::Local context = + v8::Local::New(m_isolate, m_debuggerContext); + v8::Local callFrame = + v8::Local::New(m_isolate, m_callFrame); + v8::Local restartFunction = v8::Local::Cast( + callFrame->Get(context, toV8StringInternalized(m_isolate, "restart")) + .ToLocalChecked()); + v8::Debug::SetLiveEditEnabled(m_isolate, true); + v8::MaybeLocal result = restartFunction->Call( + m_debuggerContext.Get(m_isolate), callFrame, 0, nullptr); + v8::Debug::SetLiveEditEnabled(m_isolate, false); + return result; +} + +v8::MaybeLocal JavaScriptCallFrame::setVariableValue( + int scopeNumber, v8::Local variableName, + v8::Local newValue) { + v8::MicrotasksScope microtasks(m_isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::Local context = + v8::Local::New(m_isolate, m_debuggerContext); + v8::Local callFrame = + v8::Local::New(m_isolate, m_callFrame); + v8::Local setVariableValueFunction = + v8::Local::Cast( + callFrame + ->Get(context, + toV8StringInternalized(m_isolate, "setVariableValue")) + .ToLocalChecked()); + v8::Local argv[] = { + v8::Local(v8::Integer::New(m_isolate, scopeNumber)), + variableName, newValue}; + return setVariableValueFunction->Call(context, callFrame, arraysize(argv), + argv); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.h b/deps/v8_inspector/src/inspector/java-script-call-frame.h similarity index 56% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.h rename to deps/v8_inspector/src/inspector/java-script-call-frame.h index d9a3e6accd5212..5a4ce19cc20ef6 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.h +++ b/deps/v8_inspector/src/inspector/java-script-call-frame.h @@ -28,49 +28,55 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JavaScriptCallFrame_h -#define JavaScriptCallFrame_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include +#ifndef V8_INSPECTOR_JAVASCRIPTCALLFRAME_H_ +#define V8_INSPECTOR_JAVASCRIPTCALLFRAME_H_ #include -namespace v8_inspector { +#include "src/base/macros.h" +#include "src/inspector/protocol-platform.h" + +#include "include/v8.h" -namespace protocol = blink::protocol; +namespace v8_inspector { class JavaScriptCallFrame { -public: - static std::unique_ptr create(v8::Local debuggerContext, v8::Local callFrame) - { - return wrapUnique(new JavaScriptCallFrame(debuggerContext, callFrame)); - } - ~JavaScriptCallFrame(); - - int sourceID() const; - int line() const; - int column() const; - int contextId() const; - - bool isAtReturn() const; - v8::Local details() const; - - v8::MaybeLocal evaluate(v8::Local expression); - v8::MaybeLocal restart(); - v8::MaybeLocal setVariableValue(int scopeNumber, v8::Local variableName, v8::Local newValue); -private: - JavaScriptCallFrame(v8::Local debuggerContext, v8::Local callFrame); - - int callV8FunctionReturnInt(const char* name) const; - - v8::Isolate* m_isolate; - v8::Global m_debuggerContext; - v8::Global m_callFrame; + public: + static std::unique_ptr create( + v8::Local debuggerContext, v8::Local callFrame) { + return wrapUnique(new JavaScriptCallFrame(debuggerContext, callFrame)); + } + ~JavaScriptCallFrame(); + + int sourceID() const; + int line() const; + int column() const; + int contextId() const; + + bool isAtReturn() const; + v8::Local details() const; + + v8::MaybeLocal evaluate(v8::Local expression); + v8::MaybeLocal restart(); + v8::MaybeLocal setVariableValue(int scopeNumber, + v8::Local variableName, + v8::Local newValue); + + private: + JavaScriptCallFrame(v8::Local debuggerContext, + v8::Local callFrame); + + int callV8FunctionReturnInt(const char* name) const; + + v8::Isolate* m_isolate; + v8::Global m_debuggerContext; + v8::Global m_callFrame; + + DISALLOW_COPY_AND_ASSIGN(JavaScriptCallFrame); }; using JavaScriptCallFrames = std::vector>; -} // namespace v8_inspector +} // namespace v8_inspector -#endif // JavaScriptCallFrame_h +#endif // V8_INSPECTOR_JAVASCRIPTCALLFRAME_H_ diff --git a/deps/v8_inspector/src/inspector/js_protocol-1.2.json b/deps/v8_inspector/src/inspector/js_protocol-1.2.json new file mode 100644 index 00000000000000..aff68062226847 --- /dev/null +++ b/deps/v8_inspector/src/inspector/js_protocol-1.2.json @@ -0,0 +1,997 @@ +{ + "version": { "major": "1", "minor": "2" }, + "domains": [ + { + "domain": "Schema", + "description": "Provides information about the protocol schema.", + "types": [ + { + "id": "Domain", + "type": "object", + "description": "Description of the protocol domain.", + "exported": true, + "properties": [ + { "name": "name", "type": "string", "description": "Domain name." }, + { "name": "version", "type": "string", "description": "Domain version." } + ] + } + ], + "commands": [ + { + "name": "getDomains", + "description": "Returns supported domains.", + "handlers": ["browser", "renderer"], + "returns": [ + { "name": "domains", "type": "array", "items": { "$ref": "Domain" }, "description": "List of supported domains." } + ] + } + ] + }, + { + "domain": "Runtime", + "description": "Runtime domain exposes JavaScript runtime by means of remote evaluation and mirror objects. Evaluation results are returned as mirror object that expose object type, string representation and unique identifier that can be used for further object reference. Original objects are maintained in memory unless they are either explicitly released or are released along with the other objects in their object group.", + "types": [ + { + "id": "ScriptId", + "type": "string", + "description": "Unique script identifier." + }, + { + "id": "RemoteObjectId", + "type": "string", + "description": "Unique object identifier." + }, + { + "id": "UnserializableValue", + "type": "string", + "enum": ["Infinity", "NaN", "-Infinity", "-0"], + "description": "Primitive value which cannot be JSON-stringified." + }, + { + "id": "RemoteObject", + "type": "object", + "description": "Mirror object referencing original JavaScript object.", + "exported": true, + "properties": [ + { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol"], "description": "Object type." }, + { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error", "proxy", "promise", "typedarray"], "description": "Object subtype hint. Specified for object type values only." }, + { "name": "className", "type": "string", "optional": true, "description": "Object class (constructor) name. Specified for object type values only." }, + { "name": "value", "type": "any", "optional": true, "description": "Remote object value in case of primitive values or JSON values (if it was requested)." }, + { "name": "unserializableValue", "$ref": "UnserializableValue", "optional": true, "description": "Primitive value which can not be JSON-stringified does not have value, but gets this property." }, + { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." }, + { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Unique object identifier (for non-primitive values)." }, + { "name": "preview", "$ref": "ObjectPreview", "optional": true, "description": "Preview containing abbreviated property values. Specified for object type values only.", "experimental": true }, + { "name": "customPreview", "$ref": "CustomPreview", "optional": true, "experimental": true} + ] + }, + { + "id": "CustomPreview", + "type": "object", + "experimental": true, + "properties": [ + { "name": "header", "type": "string"}, + { "name": "hasBody", "type": "boolean"}, + { "name": "formatterObjectId", "$ref": "RemoteObjectId"}, + { "name": "bindRemoteObjectFunctionId", "$ref": "RemoteObjectId" }, + { "name": "configObjectId", "$ref": "RemoteObjectId", "optional": true } + ] + }, + { + "id": "ObjectPreview", + "type": "object", + "experimental": true, + "description": "Object containing abbreviated remote object value.", + "properties": [ + { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol"], "description": "Object type." }, + { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error"], "description": "Object subtype hint. Specified for object type values only." }, + { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." }, + { "name": "overflow", "type": "boolean", "description": "True iff some of the properties or entries of the original object did not fit." }, + { "name": "properties", "type": "array", "items": { "$ref": "PropertyPreview" }, "description": "List of the properties." }, + { "name": "entries", "type": "array", "items": { "$ref": "EntryPreview" }, "optional": true, "description": "List of the entries. Specified for map and set subtype values only." } + ] + }, + { + "id": "PropertyPreview", + "type": "object", + "experimental": true, + "properties": [ + { "name": "name", "type": "string", "description": "Property name." }, + { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol", "accessor"], "description": "Object type. Accessor means that the property itself is an accessor property." }, + { "name": "value", "type": "string", "optional": true, "description": "User-friendly property value string." }, + { "name": "valuePreview", "$ref": "ObjectPreview", "optional": true, "description": "Nested value preview." }, + { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error"], "description": "Object subtype hint. Specified for object type values only." } + ] + }, + { + "id": "EntryPreview", + "type": "object", + "experimental": true, + "properties": [ + { "name": "key", "$ref": "ObjectPreview", "optional": true, "description": "Preview of the key. Specified for map-like collection entries." }, + { "name": "value", "$ref": "ObjectPreview", "description": "Preview of the value." } + ] + }, + { + "id": "PropertyDescriptor", + "type": "object", + "description": "Object property descriptor.", + "properties": [ + { "name": "name", "type": "string", "description": "Property name or symbol description." }, + { "name": "value", "$ref": "RemoteObject", "optional": true, "description": "The value associated with the property." }, + { "name": "writable", "type": "boolean", "optional": true, "description": "True if the value associated with the property may be changed (data descriptors only)." }, + { "name": "get", "$ref": "RemoteObject", "optional": true, "description": "A function which serves as a getter for the property, or undefined if there is no getter (accessor descriptors only)." }, + { "name": "set", "$ref": "RemoteObject", "optional": true, "description": "A function which serves as a setter for the property, or undefined if there is no setter (accessor descriptors only)." }, + { "name": "configurable", "type": "boolean", "description": "True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object." }, + { "name": "enumerable", "type": "boolean", "description": "True if this property shows up during enumeration of the properties on the corresponding object." }, + { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }, + { "name": "isOwn", "optional": true, "type": "boolean", "description": "True if the property is owned for the object." }, + { "name": "symbol", "$ref": "RemoteObject", "optional": true, "description": "Property symbol object, if the property is of the symbol type." } + ] + }, + { + "id": "InternalPropertyDescriptor", + "type": "object", + "description": "Object internal property descriptor. This property isn't normally visible in JavaScript code.", + "properties": [ + { "name": "name", "type": "string", "description": "Conventional property name." }, + { "name": "value", "$ref": "RemoteObject", "optional": true, "description": "The value associated with the property." } + ] + }, + { + "id": "CallArgument", + "type": "object", + "description": "Represents function call argument. Either remote object id objectId, primitive value, unserializable primitive value or neither of (for undefined) them should be specified.", + "properties": [ + { "name": "value", "type": "any", "optional": true, "description": "Primitive value." }, + { "name": "unserializableValue", "$ref": "UnserializableValue", "optional": true, "description": "Primitive value which can not be JSON-stringified." }, + { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Remote object handle." } + ] + }, + { + "id": "ExecutionContextId", + "type": "integer", + "description": "Id of an execution context." + }, + { + "id": "ExecutionContextDescription", + "type": "object", + "description": "Description of an isolated world.", + "properties": [ + { "name": "id", "$ref": "ExecutionContextId", "description": "Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed." }, + { "name": "origin", "type": "string", "description": "Execution context origin." }, + { "name": "name", "type": "string", "description": "Human readable name describing given context." }, + { "name": "auxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data." } + ] + }, + { + "id": "ExceptionDetails", + "type": "object", + "description": "Detailed information about exception (or error) that was thrown during script compilation or execution.", + "properties": [ + { "name": "exceptionId", "type": "integer", "description": "Exception id." }, + { "name": "text", "type": "string", "description": "Exception text, which should be used together with exception object when available." }, + { "name": "lineNumber", "type": "integer", "description": "Line number of the exception location (0-based)." }, + { "name": "columnNumber", "type": "integer", "description": "Column number of the exception location (0-based)." }, + { "name": "scriptId", "$ref": "ScriptId", "optional": true, "description": "Script ID of the exception location." }, + { "name": "url", "type": "string", "optional": true, "description": "URL of the exception location, to be used when the script was not reported." }, + { "name": "stackTrace", "$ref": "StackTrace", "optional": true, "description": "JavaScript stack trace if available." }, + { "name": "exception", "$ref": "RemoteObject", "optional": true, "description": "Exception object if available." }, + { "name": "executionContextId", "$ref": "ExecutionContextId", "optional": true, "description": "Identifier of the context where exception happened." } + ] + }, + { + "id": "Timestamp", + "type": "number", + "description": "Number of milliseconds since epoch." + }, + { + "id": "CallFrame", + "type": "object", + "description": "Stack entry for runtime errors and assertions.", + "properties": [ + { "name": "functionName", "type": "string", "description": "JavaScript function name." }, + { "name": "scriptId", "$ref": "ScriptId", "description": "JavaScript script id." }, + { "name": "url", "type": "string", "description": "JavaScript script name or url." }, + { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number (0-based)." }, + { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number (0-based)." } + ] + }, + { + "id": "StackTrace", + "type": "object", + "description": "Call frames for assertions or error messages.", + "exported": true, + "properties": [ + { "name": "description", "type": "string", "optional": true, "description": "String label of this stack trace. For async traces this may be a name of the function that initiated the async call." }, + { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "JavaScript function name." }, + { "name": "parent", "$ref": "StackTrace", "optional": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." } + ] + } + ], + "commands": [ + { + "name": "evaluate", + "async": true, + "parameters": [ + { "name": "expression", "type": "string", "description": "Expression to evaluate." }, + { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }, + { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation." }, + { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state." }, + { "name": "contextId", "$ref": "ExecutionContextId", "optional": true, "description": "Specifies in which execution context to perform evaluation. If the parameter is omitted the evaluation will be performed in the context of the inspected page." }, + { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." }, + { "name": "generatePreview", "type": "boolean", "optional": true, "experimental": true, "description": "Whether preview should be generated for the result." }, + { "name": "userGesture", "type": "boolean", "optional": true, "experimental": true, "description": "Whether execution should be treated as initiated by user in the UI." }, + { "name": "awaitPromise", "type": "boolean", "optional":true, "description": "Whether execution should wait for promise to be resolved. If the result of evaluation is not a Promise, it's considered to be an error." } + ], + "returns": [ + { "name": "result", "$ref": "RemoteObject", "description": "Evaluation result." }, + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} + ], + "description": "Evaluates expression on global object." + }, + { + "name": "awaitPromise", + "async": true, + "parameters": [ + { "name": "promiseObjectId", "$ref": "RemoteObjectId", "description": "Identifier of the promise." }, + { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." }, + { "name": "generatePreview", "type": "boolean", "optional": true, "description": "Whether preview should be generated for the result." } + ], + "returns": [ + { "name": "result", "$ref": "RemoteObject", "description": "Promise result. Will contain rejected value if promise was rejected." }, + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details if stack strace is available."} + ], + "description": "Add handler to promise with given promise object id." + }, + { + "name": "callFunctionOn", + "async": true, + "parameters": [ + { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to call function on." }, + { "name": "functionDeclaration", "type": "string", "description": "Declaration of the function to call." }, + { "name": "arguments", "type": "array", "items": { "$ref": "CallArgument", "description": "Call argument." }, "optional": true, "description": "Call arguments. All call arguments must belong to the same JavaScript world as the target object." }, + { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state." }, + { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." }, + { "name": "generatePreview", "type": "boolean", "optional": true, "experimental": true, "description": "Whether preview should be generated for the result." }, + { "name": "userGesture", "type": "boolean", "optional": true, "experimental": true, "description": "Whether execution should be treated as initiated by user in the UI." }, + { "name": "awaitPromise", "type": "boolean", "optional":true, "description": "Whether execution should wait for promise to be resolved. If the result of evaluation is not a Promise, it's considered to be an error." } + ], + "returns": [ + { "name": "result", "$ref": "RemoteObject", "description": "Call result." }, + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} + ], + "description": "Calls function with given declaration on the given object. Object group of the result is inherited from the target object." + }, + { + "name": "getProperties", + "parameters": [ + { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to return properties for." }, + { "name": "ownProperties", "optional": true, "type": "boolean", "description": "If true, returns properties belonging only to the element itself, not to its prototype chain." }, + { "name": "accessorPropertiesOnly", "optional": true, "type": "boolean", "description": "If true, returns accessor properties (with getter/setter) only; internal properties are not returned either.", "experimental": true }, + { "name": "generatePreview", "type": "boolean", "optional": true, "experimental": true, "description": "Whether preview should be generated for the results." } + ], + "returns": [ + { "name": "result", "type": "array", "items": { "$ref": "PropertyDescriptor" }, "description": "Object properties." }, + { "name": "internalProperties", "optional": true, "type": "array", "items": { "$ref": "InternalPropertyDescriptor" }, "description": "Internal object properties (only of the element itself)." }, + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} + ], + "description": "Returns properties of a given object. Object group of the result is inherited from the target object." + }, + { + "name": "releaseObject", + "parameters": [ + { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to release." } + ], + "description": "Releases remote object with given id." + }, + { + "name": "releaseObjectGroup", + "parameters": [ + { "name": "objectGroup", "type": "string", "description": "Symbolic object group name." } + ], + "description": "Releases all remote objects that belong to a given group." + }, + { + "name": "runIfWaitingForDebugger", + "description": "Tells inspected instance to run if it was waiting for debugger to attach." + }, + { + "name": "enable", + "description": "Enables reporting of execution contexts creation by means of executionContextCreated event. When the reporting gets enabled the event will be sent immediately for each existing execution context." + }, + { + "name": "disable", + "description": "Disables reporting of execution contexts creation." + }, + { + "name": "discardConsoleEntries", + "description": "Discards collected exceptions and console API calls." + }, + { + "name": "setCustomObjectFormatterEnabled", + "parameters": [ + { + "name": "enabled", + "type": "boolean" + } + ], + "experimental": true + }, + { + "name": "compileScript", + "parameters": [ + { "name": "expression", "type": "string", "description": "Expression to compile." }, + { "name": "sourceURL", "type": "string", "description": "Source url to be set for the script." }, + { "name": "persistScript", "type": "boolean", "description": "Specifies whether the compiled script should be persisted." }, + { "name": "executionContextId", "$ref": "ExecutionContextId", "optional": true, "description": "Specifies in which execution context to perform script run. If the parameter is omitted the evaluation will be performed in the context of the inspected page." } + ], + "returns": [ + { "name": "scriptId", "$ref": "ScriptId", "optional": true, "description": "Id of the script." }, + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} + ], + "description": "Compiles expression." + }, + { + "name": "runScript", + "async": true, + "parameters": [ + { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to run." }, + { "name": "executionContextId", "$ref": "ExecutionContextId", "optional": true, "description": "Specifies in which execution context to perform script run. If the parameter is omitted the evaluation will be performed in the context of the inspected page." }, + { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }, + { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state." }, + { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation." }, + { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." }, + { "name": "generatePreview", "type": "boolean", "optional": true, "description": "Whether preview should be generated for the result." }, + { "name": "awaitPromise", "type": "boolean", "optional": true, "description": "Whether execution should wait for promise to be resolved. If the result of evaluation is not a Promise, it's considered to be an error." } + ], + "returns": [ + { "name": "result", "$ref": "RemoteObject", "description": "Run result." }, + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} + ], + "description": "Runs script with given id in a given context." + } + ], + "events": [ + { + "name": "executionContextCreated", + "parameters": [ + { "name": "context", "$ref": "ExecutionContextDescription", "description": "A newly created execution contex." } + ], + "description": "Issued when new execution context is created." + }, + { + "name": "executionContextDestroyed", + "parameters": [ + { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Id of the destroyed context" } + ], + "description": "Issued when execution context is destroyed." + }, + { + "name": "executionContextsCleared", + "description": "Issued when all executionContexts were cleared in browser" + }, + { + "name": "exceptionThrown", + "description": "Issued when exception was thrown and unhandled.", + "parameters": [ + { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp of the exception." }, + { "name": "exceptionDetails", "$ref": "ExceptionDetails" } + ] + }, + { + "name": "exceptionRevoked", + "description": "Issued when unhandled exception was revoked.", + "parameters": [ + { "name": "reason", "type": "string", "description": "Reason describing why exception was revoked." }, + { "name": "exceptionId", "type": "integer", "description": "The id of revoked exception, as reported in exceptionUnhandled." } + ] + }, + { + "name": "consoleAPICalled", + "description": "Issued when console API was called.", + "parameters": [ + { "name": "type", "type": "string", "enum": ["log", "debug", "info", "error", "warning", "dir", "dirxml", "table", "trace", "clear", "startGroup", "startGroupCollapsed", "endGroup", "assert", "profile", "profileEnd"], "description": "Type of the call." }, + { "name": "args", "type": "array", "items": { "$ref": "RemoteObject" }, "description": "Call arguments." }, + { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Identifier of the context where the call was made." }, + { "name": "timestamp", "$ref": "Timestamp", "description": "Call timestamp." }, + { "name": "stackTrace", "$ref": "StackTrace", "optional": true, "description": "Stack trace captured when the call was made." } + ] + }, + { + "name": "inspectRequested", + "description": "Issued when object should be inspected (for example, as a result of inspect() command line API call).", + "parameters": [ + { "name": "object", "$ref": "RemoteObject" }, + { "name": "hints", "type": "object" } + ] + } + ] + }, + { + "domain": "Debugger", + "description": "Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing breakpoints, stepping through execution, exploring stack traces, etc.", + "dependencies": ["Runtime"], + "types": [ + { + "id": "BreakpointId", + "type": "string", + "description": "Breakpoint identifier." + }, + { + "id": "CallFrameId", + "type": "string", + "description": "Call frame identifier." + }, + { + "id": "Location", + "type": "object", + "properties": [ + { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Script identifier as reported in the Debugger.scriptParsed." }, + { "name": "lineNumber", "type": "integer", "description": "Line number in the script (0-based)." }, + { "name": "columnNumber", "type": "integer", "optional": true, "description": "Column number in the script (0-based)." } + ], + "description": "Location in the source code." + }, + { + "id": "ScriptPosition", + "experimental": true, + "type": "object", + "properties": [ + { "name": "lineNumber", "type": "integer" }, + { "name": "columnNumber", "type": "integer" } + ], + "description": "Location in the source code." + }, + { + "id": "CallFrame", + "type": "object", + "properties": [ + { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier. This identifier is only valid while the virtual machine is paused." }, + { "name": "functionName", "type": "string", "description": "Name of the JavaScript function called on this call frame." }, + { "name": "functionLocation", "$ref": "Location", "optional": true, "experimental": true, "description": "Location in the source code." }, + { "name": "location", "$ref": "Location", "description": "Location in the source code." }, + { "name": "scopeChain", "type": "array", "items": { "$ref": "Scope" }, "description": "Scope chain for this call frame." }, + { "name": "this", "$ref": "Runtime.RemoteObject", "description": "this object for this call frame." }, + { "name": "returnValue", "$ref": "Runtime.RemoteObject", "optional": true, "description": "The value being returned, if the function is at return point." } + ], + "description": "JavaScript call frame. Array of call frames form the call stack." + }, + { + "id": "Scope", + "type": "object", + "properties": [ + { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "block", "script"], "description": "Scope type." }, + { "name": "object", "$ref": "Runtime.RemoteObject", "description": "Object representing the scope. For global and with scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." }, + { "name": "name", "type": "string", "optional": true }, + { "name": "startLocation", "$ref": "Location", "optional": true, "description": "Location in the source code where scope starts" }, + { "name": "endLocation", "$ref": "Location", "optional": true, "description": "Location in the source code where scope ends" } + ], + "description": "Scope description." + }, + { + "id": "SearchMatch", + "type": "object", + "description": "Search match for resource.", + "exported": true, + "properties": [ + { "name": "lineNumber", "type": "number", "description": "Line number in resource content." }, + { "name": "lineContent", "type": "string", "description": "Line with match content." } + ], + "experimental": true + } + ], + "commands": [ + { + "name": "enable", + "description": "Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received." + }, + { + "name": "disable", + "description": "Disables debugger for given page." + }, + { + "name": "setBreakpointsActive", + "parameters": [ + { "name": "active", "type": "boolean", "description": "New value for breakpoints active state." } + ], + "description": "Activates / deactivates all breakpoints on the page." + }, + { + "name": "setSkipAllPauses", + "parameters": [ + { "name": "skip", "type": "boolean", "description": "New value for skip pauses state." } + ], + "description": "Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc)." + }, + { + "name": "setBreakpointByUrl", + "parameters": [ + { "name": "lineNumber", "type": "integer", "description": "Line number to set breakpoint at." }, + { "name": "url", "type": "string", "optional": true, "description": "URL of the resources to set breakpoint on." }, + { "name": "urlRegex", "type": "string", "optional": true, "description": "Regex pattern for the URLs of the resources to set breakpoints on. Either url or urlRegex must be specified." }, + { "name": "columnNumber", "type": "integer", "optional": true, "description": "Offset in the line to set breakpoint at." }, + { "name": "condition", "type": "string", "optional": true, "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." } + ], + "returns": [ + { "name": "breakpointId", "$ref": "BreakpointId", "description": "Id of the created breakpoint for further reference." }, + { "name": "locations", "type": "array", "items": { "$ref": "Location" }, "description": "List of the locations this breakpoint resolved into upon addition." } + ], + "description": "Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in locations property. Further matching script parsing will result in subsequent breakpointResolved events issued. This logical breakpoint will survive page reloads." + }, + { + "name": "setBreakpoint", + "parameters": [ + { "name": "location", "$ref": "Location", "description": "Location to set breakpoint in." }, + { "name": "condition", "type": "string", "optional": true, "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." } + ], + "returns": [ + { "name": "breakpointId", "$ref": "BreakpointId", "description": "Id of the created breakpoint for further reference." }, + { "name": "actualLocation", "$ref": "Location", "description": "Location this breakpoint resolved into." } + ], + "description": "Sets JavaScript breakpoint at a given location." + }, + { + "name": "removeBreakpoint", + "parameters": [ + { "name": "breakpointId", "$ref": "BreakpointId" } + ], + "description": "Removes JavaScript breakpoint." + }, + { + "name": "continueToLocation", + "parameters": [ + { "name": "location", "$ref": "Location", "description": "Location to continue to." } + ], + "description": "Continues execution until specific location is reached." + }, + { + "name": "stepOver", + "description": "Steps over the statement." + }, + { + "name": "stepInto", + "description": "Steps into the function call." + }, + { + "name": "stepOut", + "description": "Steps out of the function call." + }, + { + "name": "pause", + "description": "Stops on the next JavaScript statement." + }, + { + "name": "resume", + "description": "Resumes JavaScript execution." + }, + { + "name": "searchInContent", + "parameters": [ + { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to search in." }, + { "name": "query", "type": "string", "description": "String to search for." }, + { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." }, + { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." } + ], + "returns": [ + { "name": "result", "type": "array", "items": { "$ref": "SearchMatch" }, "description": "List of search matches." } + ], + "experimental": true, + "description": "Searches for given string in script content." + }, + { + "name": "setScriptSource", + "parameters": [ + { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to edit." }, + { "name": "scriptSource", "type": "string", "description": "New content of the script." }, + { "name": "dryRun", "type": "boolean", "optional": true, "description": " If true the change will not actually be applied. Dry run may be used to get result description without actually modifying the code." } + ], + "returns": [ + { "name": "callFrames", "type": "array", "optional": true, "items": { "$ref": "CallFrame" }, "description": "New stack trace in case editing has happened while VM was stopped." }, + { "name": "stackChanged", "type": "boolean", "optional": true, "description": "Whether current call stack was modified after applying the changes." }, + { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." }, + { "name": "exceptionDetails", "optional": true, "$ref": "Runtime.ExceptionDetails", "description": "Exception details if any." } + ], + "description": "Edits JavaScript source live." + }, + { + "name": "restartFrame", + "parameters": [ + { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier to evaluate on." } + ], + "returns": [ + { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "New stack trace." }, + { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." } + ], + "description": "Restarts particular call frame from the beginning." + }, + { + "name": "getScriptSource", + "parameters": [ + { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to get source for." } + ], + "returns": [ + { "name": "scriptSource", "type": "string", "description": "Script source." } + ], + "description": "Returns source for the script with given id." + }, + { + "name": "setPauseOnExceptions", + "parameters": [ + { "name": "state", "type": "string", "enum": ["none", "uncaught", "all"], "description": "Pause on exceptions mode." } + ], + "description": "Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is none." + }, + { + "name": "evaluateOnCallFrame", + "parameters": [ + { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier to evaluate on." }, + { "name": "expression", "type": "string", "description": "Expression to evaluate." }, + { "name": "objectGroup", "type": "string", "optional": true, "description": "String object group name to put result into (allows rapid releasing resulting object handles using releaseObjectGroup)." }, + { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Specifies whether command line API should be available to the evaluated expression, defaults to false." }, + { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state." }, + { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." }, + { "name": "generatePreview", "type": "boolean", "optional": true, "experimental": true, "description": "Whether preview should be generated for the result." } + ], + "returns": [ + { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Object wrapper for the evaluation result." }, + { "name": "exceptionDetails", "$ref": "Runtime.ExceptionDetails", "optional": true, "description": "Exception details."} + ], + "description": "Evaluates expression on a given call frame." + }, + { + "name": "setVariableValue", + "parameters": [ + { "name": "scopeNumber", "type": "integer", "description": "0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually." }, + { "name": "variableName", "type": "string", "description": "Variable name." }, + { "name": "newValue", "$ref": "Runtime.CallArgument", "description": "New variable value." }, + { "name": "callFrameId", "$ref": "CallFrameId", "description": "Id of callframe that holds variable." } + ], + "description": "Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually." + }, + { + "name": "setAsyncCallStackDepth", + "parameters": [ + { "name": "maxDepth", "type": "integer", "description": "Maximum depth of async call stacks. Setting to 0 will effectively disable collecting async call stacks (default)." } + ], + "description": "Enables or disables async call stacks tracking." + }, + { + "name": "setBlackboxPatterns", + "parameters": [ + { "name": "patterns", "type": "array", "items": { "type": "string" }, "description": "Array of regexps that will be used to check script url for blackbox state." } + ], + "experimental": true, + "description": "Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by performing 'step in' several times, finally resorting to 'step out' if unsuccessful." + }, + { + "name": "setBlackboxedRanges", + "parameters": [ + { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script." }, + { "name": "positions", "type": "array", "items": { "$ref": "ScriptPosition" } } + ], + "experimental": true, + "description": "Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. Positions array contains positions where blackbox state is changed. First interval isn't blackboxed. Array should be sorted." + } + ], + "events": [ + { + "name": "scriptParsed", + "parameters": [ + { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Identifier of the script parsed." }, + { "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." }, + { "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." }, + { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." }, + { "name": "endLine", "type": "integer", "description": "Last line of the script." }, + { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." }, + { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies script creation context." }, + { "name": "hash", "type": "string", "description": "Content hash of the script."}, + { "name": "executionContextAuxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data." }, + { "name": "isLiveEdit", "type": "boolean", "optional": true, "description": "True, if this script is generated as a result of the live edit operation.", "experimental": true }, + { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." }, + { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL.", "experimental": true } + ], + "description": "Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger." + }, + { + "name": "scriptFailedToParse", + "parameters": [ + { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Identifier of the script parsed." }, + { "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." }, + { "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." }, + { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." }, + { "name": "endLine", "type": "integer", "description": "Last line of the script." }, + { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." }, + { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies script creation context." }, + { "name": "hash", "type": "string", "description": "Content hash of the script."}, + { "name": "executionContextAuxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data." }, + { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." }, + { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL.", "experimental": true } + ], + "description": "Fired when virtual machine fails to parse the script." + }, + { + "name": "breakpointResolved", + "parameters": [ + { "name": "breakpointId", "$ref": "BreakpointId", "description": "Breakpoint unique identifier." }, + { "name": "location", "$ref": "Location", "description": "Actual breakpoint location." } + ], + "description": "Fired when breakpoint is resolved to an actual script and location." + }, + { + "name": "paused", + "parameters": [ + { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." }, + { "name": "reason", "type": "string", "enum": [ "XHR", "DOM", "EventListener", "exception", "assert", "debugCommand", "promiseRejection", "other" ], "description": "Pause reason.", "exported": true }, + { "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." }, + { "name": "hitBreakpoints", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Hit breakpoints IDs" }, + { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." } + ], + "description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria." + }, + { + "name": "resumed", + "description": "Fired when the virtual machine resumed execution." + } + ] + }, + { + "domain": "Console", + "description": "This domain is deprecated - use Runtime or Log instead.", + "dependencies": ["Runtime"], + "deprecated": true, + "types": [ + { + "id": "ConsoleMessage", + "type": "object", + "description": "Console message.", + "properties": [ + { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "console-api", "storage", "appcache", "rendering", "security", "other", "deprecation", "worker"], "description": "Message source." }, + { "name": "level", "type": "string", "enum": ["log", "warning", "error", "debug", "info"], "description": "Message severity." }, + { "name": "text", "type": "string", "description": "Message text." }, + { "name": "url", "type": "string", "optional": true, "description": "URL of the message origin." }, + { "name": "line", "type": "integer", "optional": true, "description": "Line number in the resource that generated this message (1-based)." }, + { "name": "column", "type": "integer", "optional": true, "description": "Column number in the resource that generated this message (1-based)." } + ] + } + ], + "commands": [ + { + "name": "enable", + "description": "Enables console domain, sends the messages collected so far to the client by means of the messageAdded notification." + }, + { + "name": "disable", + "description": "Disables console domain, prevents further console messages from being reported to the client." + }, + { + "name": "clearMessages", + "description": "Does nothing." + } + ], + "events": [ + { + "name": "messageAdded", + "parameters": [ + { "name": "message", "$ref": "ConsoleMessage", "description": "Console message that has been added." } + ], + "description": "Issued when new console message is added." + } + ] + }, + { + "domain": "Profiler", + "dependencies": ["Runtime", "Debugger"], + "types": [ + { + "id": "ProfileNode", + "type": "object", + "description": "Profile node. Holds callsite information, execution statistics and child nodes.", + "properties": [ + { "name": "id", "type": "integer", "description": "Unique id of the node." }, + { "name": "callFrame", "$ref": "Runtime.CallFrame", "description": "Function location." }, + { "name": "hitCount", "type": "integer", "optional": true, "experimental": true, "description": "Number of samples where this node was on top of the call stack." }, + { "name": "children", "type": "array", "items": { "type": "integer" }, "optional": true, "description": "Child node ids." }, + { "name": "deoptReason", "type": "string", "optional": true, "description": "The reason of being not optimized. The function may be deoptimized or marked as don't optimize."}, + { "name": "positionTicks", "type": "array", "items": { "$ref": "PositionTickInfo" }, "optional": true, "experimental": true, "description": "An array of source position ticks." } + ] + }, + { + "id": "Profile", + "type": "object", + "description": "Profile.", + "properties": [ + { "name": "nodes", "type": "array", "items": { "$ref": "ProfileNode" }, "description": "The list of profile nodes. First item is the root node." }, + { "name": "startTime", "type": "number", "description": "Profiling start timestamp in microseconds." }, + { "name": "endTime", "type": "number", "description": "Profiling end timestamp in microseconds." }, + { "name": "samples", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Ids of samples top nodes." }, + { "name": "timeDeltas", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Time intervals between adjacent samples in microseconds. The first delta is relative to the profile startTime." } + ] + }, + { + "id": "PositionTickInfo", + "type": "object", + "experimental": true, + "description": "Specifies a number of samples attributed to a certain source position.", + "properties": [ + { "name": "line", "type": "integer", "description": "Source line number (1-based)." }, + { "name": "ticks", "type": "integer", "description": "Number of samples attributed to the source line." } + ] + } + ], + "commands": [ + { + "name": "enable" + }, + { + "name": "disable" + }, + { + "name": "setSamplingInterval", + "parameters": [ + { "name": "interval", "type": "integer", "description": "New sampling interval in microseconds." } + ], + "description": "Changes CPU profiler sampling interval. Must be called before CPU profiles recording started." + }, + { + "name": "start" + }, + { + "name": "stop", + "returns": [ + { "name": "profile", "$ref": "Profile", "description": "Recorded profile." } + ] + } + ], + "events": [ + { + "name": "consoleProfileStarted", + "parameters": [ + { "name": "id", "type": "string" }, + { "name": "location", "$ref": "Debugger.Location", "description": "Location of console.profile()." }, + { "name": "title", "type": "string", "optional": true, "description": "Profile title passed as an argument to console.profile()." } + ], + "description": "Sent when new profile recodring is started using console.profile() call." + }, + { + "name": "consoleProfileFinished", + "parameters": [ + { "name": "id", "type": "string" }, + { "name": "location", "$ref": "Debugger.Location", "description": "Location of console.profileEnd()." }, + { "name": "profile", "$ref": "Profile" }, + { "name": "title", "type": "string", "optional": true, "description": "Profile title passed as an argument to console.profile()." } + ] + } + ] + }, + { + "domain": "HeapProfiler", + "dependencies": ["Runtime"], + "experimental": true, + "types": [ + { + "id": "HeapSnapshotObjectId", + "type": "string", + "description": "Heap snapshot object id." + }, + { + "id": "SamplingHeapProfileNode", + "type": "object", + "description": "Sampling Heap Profile node. Holds callsite information, allocation statistics and child nodes.", + "properties": [ + { "name": "callFrame", "$ref": "Runtime.CallFrame", "description": "Function location." }, + { "name": "selfSize", "type": "number", "description": "Allocations size in bytes for the node excluding children." }, + { "name": "children", "type": "array", "items": { "$ref": "SamplingHeapProfileNode" }, "description": "Child nodes." } + ] + }, + { + "id": "SamplingHeapProfile", + "type": "object", + "description": "Profile.", + "properties": [ + { "name": "head", "$ref": "SamplingHeapProfileNode" } + ] + } + ], + "commands": [ + { + "name": "enable" + }, + { + "name": "disable" + }, + { + "name": "startTrackingHeapObjects", + "parameters": [ + { "name": "trackAllocations", "type": "boolean", "optional": true } + ] + }, + { + "name": "stopTrackingHeapObjects", + "parameters": [ + { "name": "reportProgress", "type": "boolean", "optional": true, "description": "If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken when the tracking is stopped." } + ] + }, + { + "name": "takeHeapSnapshot", + "parameters": [ + { "name": "reportProgress", "type": "boolean", "optional": true, "description": "If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken." } + ] + }, + { + "name": "collectGarbage" + }, + { + "name": "getObjectByHeapObjectId", + "parameters": [ + { "name": "objectId", "$ref": "HeapSnapshotObjectId" }, + { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." } + ], + "returns": [ + { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Evaluation result." } + ] + }, + { + "name": "addInspectedHeapObject", + "parameters": [ + { "name": "heapObjectId", "$ref": "HeapSnapshotObjectId", "description": "Heap snapshot object id to be accessible by means of $x command line API." } + ], + "description": "Enables console to refer to the node with given id via $x (see Command Line API for more details $x functions)." + }, + { + "name": "getHeapObjectId", + "parameters": [ + { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Identifier of the object to get heap object id for." } + ], + "returns": [ + { "name": "heapSnapshotObjectId", "$ref": "HeapSnapshotObjectId", "description": "Id of the heap snapshot object corresponding to the passed remote object id." } + ] + }, + { + "name": "startSampling", + "parameters": [ + { "name": "samplingInterval", "type": "number", "optional": true, "description": "Average sample interval in bytes. Poisson distribution is used for the intervals. The default value is 32768 bytes." } + ] + }, + { + "name": "stopSampling", + "returns": [ + { "name": "profile", "$ref": "SamplingHeapProfile", "description": "Recorded sampling heap profile." } + ] + } + ], + "events": [ + { + "name": "addHeapSnapshotChunk", + "parameters": [ + { "name": "chunk", "type": "string" } + ] + }, + { + "name": "resetProfiles" + }, + { + "name": "reportHeapSnapshotProgress", + "parameters": [ + { "name": "done", "type": "integer" }, + { "name": "total", "type": "integer" }, + { "name": "finished", "type": "boolean", "optional": true } + ] + }, + { + "name": "lastSeenObjectId", + "description": "If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.", + "parameters": [ + { "name": "lastSeenObjectId", "type": "integer" }, + { "name": "timestamp", "type": "number" } + ] + }, + { + "name": "heapStatsUpdate", + "description": "If heap objects tracking has been started then backend may send update for one or more fragments", + "parameters": [ + { "name": "statsUpdate", "type": "array", "items": { "type": "integer" }, "description": "An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment."} + ] + } + ] + }] +} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/js_protocol.json b/deps/v8_inspector/src/inspector/js_protocol.json similarity index 93% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/js_protocol.json rename to deps/v8_inspector/src/inspector/js_protocol.json index 43b788d5b16ee8..aff68062226847 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/js_protocol.json +++ b/deps/v8_inspector/src/inspector/js_protocol.json @@ -1,10 +1,9 @@ { - "version": { "major": "1", "minor": "1" }, + "version": { "major": "1", "minor": "2" }, "domains": [ { "domain": "Schema", "description": "Provides information about the protocol schema.", - "experimental": true, "types": [ { "id": "Domain", @@ -58,7 +57,7 @@ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "map", "set", "iterator", "generator", "error", "proxy", "promise", "typedarray"], "description": "Object subtype hint. Specified for object type values only." }, { "name": "className", "type": "string", "optional": true, "description": "Object class (constructor) name. Specified for object type values only." }, { "name": "value", "type": "any", "optional": true, "description": "Remote object value in case of primitive values or JSON values (if it was requested)." }, - { "name": "unserializableValue", "$ref": "UnserializableValue", "optional": true, "experimental": true, "description": "Primitive value which can not be JSON-stringified does not have value, but gets this property." }, + { "name": "unserializableValue", "$ref": "UnserializableValue", "optional": true, "description": "Primitive value which can not be JSON-stringified does not have value, but gets this property." }, { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." }, { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Unique object identifier (for non-primitive values)." }, { "name": "preview", "$ref": "ObjectPreview", "optional": true, "description": "Preview containing abbreviated property values. Specified for object type values only.", "experimental": true }, @@ -125,8 +124,8 @@ { "name": "configurable", "type": "boolean", "description": "True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object." }, { "name": "enumerable", "type": "boolean", "description": "True if this property shows up during enumeration of the properties on the corresponding object." }, { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }, - { "name": "isOwn", "optional": true, "type": "boolean", "description": "True if the property is owned for the object.", "experimental": true }, - { "name": "symbol", "$ref": "RemoteObject", "optional": true, "description": "Property symbol object, if the property is of the symbol type.", "experimental": true } + { "name": "isOwn", "optional": true, "type": "boolean", "description": "True if the property is owned for the object." }, + { "name": "symbol", "$ref": "RemoteObject", "optional": true, "description": "Property symbol object, if the property is of the symbol type." } ] }, { @@ -136,8 +135,7 @@ "properties": [ { "name": "name", "type": "string", "description": "Conventional property name." }, { "name": "value", "$ref": "RemoteObject", "optional": true, "description": "The value associated with the property." } - ], - "experimental": true + ] }, { "id": "CallArgument", @@ -145,7 +143,7 @@ "description": "Represents function call argument. Either remote object id objectId, primitive value, unserializable primitive value or neither of (for undefined) them should be specified.", "properties": [ { "name": "value", "type": "any", "optional": true, "description": "Primitive value." }, - { "name": "unserializableValue", "$ref": "UnserializableValue", "optional": true, "experimental": true, "description": "Primitive value which can not be JSON-stringified." }, + { "name": "unserializableValue", "$ref": "UnserializableValue", "optional": true, "description": "Primitive value which can not be JSON-stringified." }, { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Remote object handle." } ] }, @@ -160,15 +158,14 @@ "description": "Description of an isolated world.", "properties": [ { "name": "id", "$ref": "ExecutionContextId", "description": "Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed." }, - { "name": "origin", "type": "string", "description": "Execution context origin.", "experimental": true }, - { "name": "name", "type": "string", "description": "Human readable name describing given context.", "experimental": true }, - { "name": "auxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data.", "experimental": true } + { "name": "origin", "type": "string", "description": "Execution context origin." }, + { "name": "name", "type": "string", "description": "Human readable name describing given context." }, + { "name": "auxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data." } ] }, { "id": "ExceptionDetails", "type": "object", - "experimental": true, "description": "Detailed information about exception (or error) that was thrown during script compilation or execution.", "properties": [ { "name": "exceptionId", "type": "integer", "description": "Exception id." }, @@ -185,8 +182,7 @@ { "id": "Timestamp", "type": "number", - "description": "Number of milliseconds since epoch.", - "experimental": true + "description": "Number of milliseconds since epoch." }, { "id": "CallFrame", @@ -208,7 +204,7 @@ "properties": [ { "name": "description", "type": "string", "optional": true, "description": "String label of this stack trace. For async traces this may be a name of the function that initiated the async call." }, { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "JavaScript function name." }, - { "name": "parent", "$ref": "StackTrace", "optional": true, "experimental": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." } + { "name": "parent", "$ref": "StackTrace", "optional": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." } ] } ], @@ -219,23 +215,22 @@ "parameters": [ { "name": "expression", "type": "string", "description": "Expression to evaluate." }, { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }, - { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation.", "experimental": true }, - { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state.", "experimental": true }, + { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation." }, + { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state." }, { "name": "contextId", "$ref": "ExecutionContextId", "optional": true, "description": "Specifies in which execution context to perform evaluation. If the parameter is omitted the evaluation will be performed in the context of the inspected page." }, { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." }, { "name": "generatePreview", "type": "boolean", "optional": true, "experimental": true, "description": "Whether preview should be generated for the result." }, { "name": "userGesture", "type": "boolean", "optional": true, "experimental": true, "description": "Whether execution should be treated as initiated by user in the UI." }, - { "name": "awaitPromise", "type": "boolean", "optional":true, "experimental": true, "description": "Whether execution should wait for promise to be resolved. If the result of evaluation is not a Promise, it's considered to be an error." } + { "name": "awaitPromise", "type": "boolean", "optional":true, "description": "Whether execution should wait for promise to be resolved. If the result of evaluation is not a Promise, it's considered to be an error." } ], "returns": [ { "name": "result", "$ref": "RemoteObject", "description": "Evaluation result." }, - { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "experimental": true, "description": "Exception details."} + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} ], "description": "Evaluates expression on global object." }, { "name": "awaitPromise", - "experimental": true, "async": true, "parameters": [ { "name": "promiseObjectId", "$ref": "RemoteObjectId", "description": "Identifier of the promise." }, @@ -255,15 +250,15 @@ { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to call function on." }, { "name": "functionDeclaration", "type": "string", "description": "Declaration of the function to call." }, { "name": "arguments", "type": "array", "items": { "$ref": "CallArgument", "description": "Call argument." }, "optional": true, "description": "Call arguments. All call arguments must belong to the same JavaScript world as the target object." }, - { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state.", "experimental": true }, + { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state." }, { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." }, { "name": "generatePreview", "type": "boolean", "optional": true, "experimental": true, "description": "Whether preview should be generated for the result." }, { "name": "userGesture", "type": "boolean", "optional": true, "experimental": true, "description": "Whether execution should be treated as initiated by user in the UI." }, - { "name": "awaitPromise", "type": "boolean", "optional":true, "experimental": true, "description": "Whether execution should wait for promise to be resolved. If the result of evaluation is not a Promise, it's considered to be an error." } + { "name": "awaitPromise", "type": "boolean", "optional":true, "description": "Whether execution should wait for promise to be resolved. If the result of evaluation is not a Promise, it's considered to be an error." } ], "returns": [ { "name": "result", "$ref": "RemoteObject", "description": "Call result." }, - { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "experimental": true, "description": "Exception details."} + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} ], "description": "Calls function with given declaration on the given object. Object group of the result is inherited from the target object." }, @@ -277,8 +272,8 @@ ], "returns": [ { "name": "result", "type": "array", "items": { "$ref": "PropertyDescriptor" }, "description": "Object properties." }, - { "name": "internalProperties", "optional": true, "type": "array", "items": { "$ref": "InternalPropertyDescriptor" }, "description": "Internal object properties (only of the element itself).", "experimental": true }, - { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "experimental": true, "description": "Exception details."} + { "name": "internalProperties", "optional": true, "type": "array", "items": { "$ref": "InternalPropertyDescriptor" }, "description": "Internal object properties (only of the element itself)." }, + { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."} ], "description": "Returns properties of a given object. Object group of the result is inherited from the target object." }, @@ -298,7 +293,6 @@ }, { "name": "runIfWaitingForDebugger", - "experimental": true, "description": "Tells inspected instance to run if it was waiting for debugger to attach." }, { @@ -307,12 +301,10 @@ }, { "name": "disable", - "experimental": true, "description": "Disables reporting of execution contexts creation." }, { "name": "discardConsoleEntries", - "experimental": true, "description": "Discards collected exceptions and console API calls." }, { @@ -327,7 +319,6 @@ }, { "name": "compileScript", - "experimental": true, "parameters": [ { "name": "expression", "type": "string", "description": "Expression to compile." }, { "name": "sourceURL", "type": "string", "description": "Source url to be set for the script." }, @@ -342,13 +333,12 @@ }, { "name": "runScript", - "experimental": true, "async": true, "parameters": [ { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to run." }, { "name": "executionContextId", "$ref": "ExecutionContextId", "optional": true, "description": "Specifies in which execution context to perform script run. If the parameter is omitted the evaluation will be performed in the context of the inspected page." }, { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." }, - { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state.", "experimental": true }, + { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state." }, { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation." }, { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." }, { "name": "generatePreview", "type": "boolean", "optional": true, "description": "Whether preview should be generated for the result." }, @@ -386,8 +376,7 @@ "parameters": [ { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp of the exception." }, { "name": "exceptionDetails", "$ref": "ExceptionDetails" } - ], - "experimental": true + ] }, { "name": "exceptionRevoked", @@ -395,8 +384,7 @@ "parameters": [ { "name": "reason", "type": "string", "description": "Reason describing why exception was revoked." }, { "name": "exceptionId", "type": "integer", "description": "The id of revoked exception, as reported in exceptionUnhandled." } - ], - "experimental": true + ] }, { "name": "consoleAPICalled", @@ -407,8 +395,7 @@ { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Identifier of the context where the call was made." }, { "name": "timestamp", "$ref": "Timestamp", "description": "Call timestamp." }, { "name": "stackTrace", "$ref": "StackTrace", "optional": true, "description": "Stack trace captured when the call was made." } - ], - "experimental": true + ] }, { "name": "inspectRequested", @@ -416,8 +403,7 @@ "parameters": [ { "name": "object", "$ref": "RemoteObject" }, { "name": "hints", "type": "object" } - ], - "experimental": true + ] } ] }, @@ -466,7 +452,7 @@ { "name": "location", "$ref": "Location", "description": "Location in the source code." }, { "name": "scopeChain", "type": "array", "items": { "$ref": "Scope" }, "description": "Scope chain for this call frame." }, { "name": "this", "$ref": "Runtime.RemoteObject", "description": "this object for this call frame." }, - { "name": "returnValue", "$ref": "Runtime.RemoteObject", "optional": true, "experimental": true, "description": "The value being returned, if the function is at return point." } + { "name": "returnValue", "$ref": "Runtime.RemoteObject", "optional": true, "description": "The value being returned, if the function is at return point." } ], "description": "JavaScript call frame. Array of call frames form the call stack." }, @@ -476,9 +462,9 @@ "properties": [ { "name": "type", "type": "string", "enum": ["global", "local", "with", "closure", "catch", "block", "script"], "description": "Scope type." }, { "name": "object", "$ref": "Runtime.RemoteObject", "description": "Object representing the scope. For global and with scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." }, - { "name": "name", "type": "string", "optional": true, "experimental": true }, - { "name": "startLocation", "$ref": "Location", "optional": true, "experimental": true, "description": "Location in the source code where scope starts" }, - { "name": "endLocation", "$ref": "Location", "optional": true, "experimental": true, "description": "Location in the source code where scope ends" } + { "name": "name", "type": "string", "optional": true }, + { "name": "startLocation", "$ref": "Location", "optional": true, "description": "Location in the source code where scope starts" }, + { "name": "endLocation", "$ref": "Location", "optional": true, "description": "Location in the source code where scope ends" } ], "description": "Scope description." }, @@ -512,7 +498,6 @@ }, { "name": "setSkipAllPauses", - "experimental": true, "parameters": [ { "name": "skip", "type": "boolean", "description": "New value for skip pauses state." } ], @@ -590,6 +575,7 @@ "returns": [ { "name": "result", "type": "array", "items": { "$ref": "SearchMatch" }, "description": "List of search matches." } ], + "experimental": true, "description": "Searches for given string in script content." }, { @@ -597,12 +583,12 @@ "parameters": [ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to edit." }, { "name": "scriptSource", "type": "string", "description": "New content of the script." }, - { "name": "dryRun", "type": "boolean", "optional": true, "description": " If true the change will not actually be applied. Dry run may be used to get result description without actually modifying the code.", "experimental": true } + { "name": "dryRun", "type": "boolean", "optional": true, "description": " If true the change will not actually be applied. Dry run may be used to get result description without actually modifying the code." } ], "returns": [ { "name": "callFrames", "type": "array", "optional": true, "items": { "$ref": "CallFrame" }, "description": "New stack trace in case editing has happened while VM was stopped." }, - { "name": "stackChanged", "type": "boolean", "optional": true, "description": "Whether current call stack was modified after applying the changes.", "experimental": true }, - { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any.", "experimental": true }, + { "name": "stackChanged", "type": "boolean", "optional": true, "description": "Whether current call stack was modified after applying the changes." }, + { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." }, { "name": "exceptionDetails", "optional": true, "$ref": "Runtime.ExceptionDetails", "description": "Exception details if any." } ], "description": "Edits JavaScript source live." @@ -616,7 +602,6 @@ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "New stack trace." }, { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." } ], - "experimental": true, "description": "Restarts particular call frame from the beginning." }, { @@ -642,14 +627,14 @@ { "name": "callFrameId", "$ref": "CallFrameId", "description": "Call frame identifier to evaluate on." }, { "name": "expression", "type": "string", "description": "Expression to evaluate." }, { "name": "objectGroup", "type": "string", "optional": true, "description": "String object group name to put result into (allows rapid releasing resulting object handles using releaseObjectGroup)." }, - { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Specifies whether command line API should be available to the evaluated expression, defaults to false.", "experimental": true }, - { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state.", "experimental": true }, + { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Specifies whether command line API should be available to the evaluated expression, defaults to false." }, + { "name": "silent", "type": "boolean", "optional": true, "description": "In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state." }, { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." }, { "name": "generatePreview", "type": "boolean", "optional": true, "experimental": true, "description": "Whether preview should be generated for the result." } ], "returns": [ { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Object wrapper for the evaluation result." }, - { "name": "exceptionDetails", "$ref": "Runtime.ExceptionDetails", "optional": true, "experimental": true, "description": "Exception details."} + { "name": "exceptionDetails", "$ref": "Runtime.ExceptionDetails", "optional": true, "description": "Exception details."} ], "description": "Evaluates expression on a given call frame." }, @@ -661,7 +646,6 @@ { "name": "newValue", "$ref": "Runtime.CallArgument", "description": "New variable value." }, { "name": "callFrameId", "$ref": "CallFrameId", "description": "Id of callframe that holds variable." } ], - "experimental": true, "description": "Changes value of variable in a callframe. Object-based scopes are not supported and must be mutated manually." }, { @@ -669,7 +653,6 @@ "parameters": [ { "name": "maxDepth", "type": "integer", "description": "Maximum depth of async call stacks. Setting to 0 will effectively disable collecting async call stacks (default)." } ], - "experimental": true, "description": "Enables or disables async call stacks tracking." }, { @@ -700,9 +683,9 @@ { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." }, { "name": "endLine", "type": "integer", "description": "Last line of the script." }, { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." }, - { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies script creation context.", "experimental": true }, - { "name": "hash", "type": "string", "experimental": true, "description": "Content hash of the script."}, - { "name": "executionContextAuxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data.", "experimental": true }, + { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies script creation context." }, + { "name": "hash", "type": "string", "description": "Content hash of the script."}, + { "name": "executionContextAuxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data." }, { "name": "isLiveEdit", "type": "boolean", "optional": true, "description": "True, if this script is generated as a result of the live edit operation.", "experimental": true }, { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." }, { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL.", "experimental": true } @@ -718,9 +701,9 @@ { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." }, { "name": "endLine", "type": "integer", "description": "Last line of the script." }, { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." }, - { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies script creation context.", "experimental": true }, - { "name": "hash", "type": "string", "experimental": true, "description": "Content hash of the script."}, - { "name": "executionContextAuxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data.", "experimental": true }, + { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies script creation context." }, + { "name": "hash", "type": "string", "description": "Content hash of the script."}, + { "name": "executionContextAuxData", "type": "object", "optional": true, "description": "Embedder-specific auxiliary data." }, { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." }, { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL.", "experimental": true } ], @@ -740,8 +723,8 @@ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." }, { "name": "reason", "type": "string", "enum": [ "XHR", "DOM", "EventListener", "exception", "assert", "debugCommand", "promiseRejection", "other" ], "description": "Pause reason.", "exported": true }, { "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." }, - { "name": "hitBreakpoints", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Hit breakpoints IDs", "experimental": true }, - { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any.", "experimental": true } + { "name": "hitBreakpoints", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Hit breakpoints IDs" }, + { "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." } ], "description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria." }, @@ -798,31 +781,30 @@ { "domain": "Profiler", "dependencies": ["Runtime", "Debugger"], - "experimental": true, "types": [ { - "id": "CPUProfileNode", + "id": "ProfileNode", "type": "object", - "description": "CPU Profile node. Holds callsite information, execution statistics and child nodes.", + "description": "Profile node. Holds callsite information, execution statistics and child nodes.", "properties": [ { "name": "id", "type": "integer", "description": "Unique id of the node." }, { "name": "callFrame", "$ref": "Runtime.CallFrame", "description": "Function location." }, - { "name": "hitCount", "type": "integer", "description": "Number of samples where this node was on top of the call stack." }, + { "name": "hitCount", "type": "integer", "optional": true, "experimental": true, "description": "Number of samples where this node was on top of the call stack." }, { "name": "children", "type": "array", "items": { "type": "integer" }, "optional": true, "description": "Child node ids." }, { "name": "deoptReason", "type": "string", "optional": true, "description": "The reason of being not optimized. The function may be deoptimized or marked as don't optimize."}, { "name": "positionTicks", "type": "array", "items": { "$ref": "PositionTickInfo" }, "optional": true, "experimental": true, "description": "An array of source position ticks." } ] }, { - "id": "CPUProfile", + "id": "Profile", "type": "object", "description": "Profile.", "properties": [ - { "name": "nodes", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "The list of profile nodes. First item is the root node." }, + { "name": "nodes", "type": "array", "items": { "$ref": "ProfileNode" }, "description": "The list of profile nodes. First item is the root node." }, { "name": "startTime", "type": "number", "description": "Profiling start timestamp in microseconds." }, { "name": "endTime", "type": "number", "description": "Profiling end timestamp in microseconds." }, { "name": "samples", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Ids of samples top nodes." }, - { "name": "timestampDeltas", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Deltas between adjacent sample timestamps in microseconds. The first delta is relative to the profile startTime." } + { "name": "timeDeltas", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Time intervals between adjacent samples in microseconds. The first delta is relative to the profile startTime." } ] }, { @@ -856,7 +838,7 @@ { "name": "stop", "returns": [ - { "name": "profile", "$ref": "CPUProfile", "description": "Recorded profile." } + { "name": "profile", "$ref": "Profile", "description": "Recorded profile." } ] } ], @@ -875,7 +857,7 @@ "parameters": [ { "name": "id", "type": "string" }, { "name": "location", "$ref": "Debugger.Location", "description": "Location of console.profileEnd()." }, - { "name": "profile", "$ref": "CPUProfile" }, + { "name": "profile", "$ref": "Profile" }, { "name": "title", "type": "string", "optional": true, "description": "Profile title passed as an argument to console.profile()." } ] } diff --git a/deps/v8_inspector/src/inspector/protocol-platform.h b/deps/v8_inspector/src/inspector/protocol-platform.h new file mode 100644 index 00000000000000..c7723932b42465 --- /dev/null +++ b/deps/v8_inspector/src/inspector/protocol-platform.h @@ -0,0 +1,21 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_PROTOCOLPLATFORM_H_ +#define V8_INSPECTOR_PROTOCOLPLATFORM_H_ + +#include + +#include "src/base/logging.h" + +namespace v8_inspector { + +template +std::unique_ptr wrapUnique(T* ptr) { + return std::unique_ptr(ptr); +} + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_PROTOCOLPLATFORM_H_ diff --git a/deps/v8_inspector/src/inspector/remote-object-id.cc b/deps/v8_inspector/src/inspector/remote-object-id.cc new file mode 100644 index 00000000000000..d83020c6f20208 --- /dev/null +++ b/deps/v8_inspector/src/inspector/remote-object-id.cc @@ -0,0 +1,76 @@ +// Copyright 2015 the V8 project 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 "src/inspector/remote-object-id.h" + +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/string-util.h" + +namespace v8_inspector { + +RemoteObjectIdBase::RemoteObjectIdBase() : m_injectedScriptId(0) {} + +std::unique_ptr +RemoteObjectIdBase::parseInjectedScriptId(const String16& objectId) { + std::unique_ptr parsedValue = protocol::parseJSON(objectId); + if (!parsedValue || parsedValue->type() != protocol::Value::TypeObject) + return nullptr; + + std::unique_ptr parsedObjectId( + protocol::DictionaryValue::cast(parsedValue.release())); + bool success = + parsedObjectId->getInteger("injectedScriptId", &m_injectedScriptId); + if (success) return parsedObjectId; + return nullptr; +} + +RemoteObjectId::RemoteObjectId() : RemoteObjectIdBase(), m_id(0) {} + +std::unique_ptr RemoteObjectId::parse( + ErrorString* errorString, const String16& objectId) { + std::unique_ptr result(new RemoteObjectId()); + std::unique_ptr parsedObjectId = + result->parseInjectedScriptId(objectId); + if (!parsedObjectId) { + *errorString = "Invalid remote object id"; + return nullptr; + } + + bool success = parsedObjectId->getInteger("id", &result->m_id); + if (!success) { + *errorString = "Invalid remote object id"; + return nullptr; + } + return result; +} + +RemoteCallFrameId::RemoteCallFrameId() + : RemoteObjectIdBase(), m_frameOrdinal(0) {} + +std::unique_ptr RemoteCallFrameId::parse( + ErrorString* errorString, const String16& objectId) { + std::unique_ptr result(new RemoteCallFrameId()); + std::unique_ptr parsedObjectId = + result->parseInjectedScriptId(objectId); + if (!parsedObjectId) { + *errorString = "Invalid call frame id"; + return nullptr; + } + + bool success = parsedObjectId->getInteger("ordinal", &result->m_frameOrdinal); + if (!success) { + *errorString = "Invalid call frame id"; + return nullptr; + } + + return result; +} + +String16 RemoteCallFrameId::serialize(int injectedScriptId, int frameOrdinal) { + return "{\"ordinal\":" + String16::fromInteger(frameOrdinal) + + ",\"injectedScriptId\":" + String16::fromInteger(injectedScriptId) + + "}"; +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/remote-object-id.h b/deps/v8_inspector/src/inspector/remote-object-id.h new file mode 100644 index 00000000000000..a32f568fb8ac0e --- /dev/null +++ b/deps/v8_inspector/src/inspector/remote-object-id.h @@ -0,0 +1,58 @@ +// Copyright 2015 the V8 project 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 V8_INSPECTOR_REMOTEOBJECTID_H_ +#define V8_INSPECTOR_REMOTEOBJECTID_H_ + +#include "src/inspector/protocol/Forward.h" + +namespace v8_inspector { + +using protocol::ErrorString; + +class RemoteObjectIdBase { + public: + int contextId() const { return m_injectedScriptId; } + + protected: + RemoteObjectIdBase(); + ~RemoteObjectIdBase() {} + + std::unique_ptr parseInjectedScriptId( + const String16&); + + int m_injectedScriptId; +}; + +class RemoteObjectId final : public RemoteObjectIdBase { + public: + static std::unique_ptr parse(ErrorString*, const String16&); + ~RemoteObjectId() {} + int id() const { return m_id; } + + private: + RemoteObjectId(); + + int m_id; +}; + +class RemoteCallFrameId final : public RemoteObjectIdBase { + public: + static std::unique_ptr parse(ErrorString*, + const String16&); + ~RemoteCallFrameId() {} + + int frameOrdinal() const { return m_frameOrdinal; } + + static String16 serialize(int injectedScriptId, int frameOrdinal); + + private: + RemoteCallFrameId(); + + int m_frameOrdinal; +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_REMOTEOBJECTID_H_ diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/ScriptBreakpoint.h b/deps/v8_inspector/src/inspector/script-breakpoint.h similarity index 75% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/ScriptBreakpoint.h rename to deps/v8_inspector/src/inspector/script-breakpoint.h index 52e8f995aa7fb2..025233dd19e802 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/ScriptBreakpoint.h +++ b/deps/v8_inspector/src/inspector/script-breakpoint.h @@ -27,30 +27,26 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptBreakpoint_h -#define ScriptBreakpoint_h +#ifndef V8_INSPECTOR_SCRIPTBREAKPOINT_H_ +#define V8_INSPECTOR_SCRIPTBREAKPOINT_H_ -#include "platform/inspector_protocol/InspectorProtocol.h" +#include "src/inspector/string-16.h" namespace v8_inspector { -namespace protocol = blink::protocol; - struct ScriptBreakpoint { - ScriptBreakpoint() : ScriptBreakpoint(0, 0, String16()) { } - - ScriptBreakpoint(int lineNumber, int columnNumber, const String16& condition) - : lineNumber(lineNumber) - , columnNumber(columnNumber) - , condition(condition) - { - } - - int lineNumber; - int columnNumber; - String16 condition; + ScriptBreakpoint() : ScriptBreakpoint(0, 0, String16()) {} + + ScriptBreakpoint(int lineNumber, int columnNumber, const String16& condition) + : lineNumber(lineNumber), + columnNumber(columnNumber), + condition(condition) {} + + int lineNumber; + int columnNumber; + String16 condition; }; -} // namespace v8_inspector +} // namespace v8_inspector -#endif // !defined(ScriptBreakpoint_h) +#endif // V8_INSPECTOR_SCRIPTBREAKPOINT_H_ diff --git a/deps/v8_inspector/src/inspector/search-util.cc b/deps/v8_inspector/src/inspector/search-util.cc new file mode 100644 index 00000000000000..a6fba06c115b72 --- /dev/null +++ b/deps/v8_inspector/src/inspector/search-util.cc @@ -0,0 +1,164 @@ +// Copyright 2016 the V8 project 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 "src/inspector/search-util.h" + +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-regex.h" + +namespace v8_inspector { + +namespace { + +String16 findMagicComment(const String16& content, const String16& name, + bool multiline) { + DCHECK(name.find("=") == String16::kNotFound); + size_t length = content.length(); + size_t nameLength = name.length(); + + size_t pos = length; + size_t equalSignPos = 0; + size_t closingCommentPos = 0; + while (true) { + pos = content.reverseFind(name, pos); + if (pos == String16::kNotFound) return String16(); + + // Check for a /\/[\/*][@#][ \t]/ regexp (length of 4) before found name. + if (pos < 4) return String16(); + pos -= 4; + if (content[pos] != '/') continue; + if ((content[pos + 1] != '/' || multiline) && + (content[pos + 1] != '*' || !multiline)) + continue; + if (content[pos + 2] != '#' && content[pos + 2] != '@') continue; + if (content[pos + 3] != ' ' && content[pos + 3] != '\t') continue; + equalSignPos = pos + 4 + nameLength; + if (equalSignPos < length && content[equalSignPos] != '=') continue; + if (multiline) { + closingCommentPos = content.find("*/", equalSignPos + 1); + if (closingCommentPos == String16::kNotFound) return String16(); + } + + break; + } + + DCHECK(equalSignPos); + DCHECK(!multiline || closingCommentPos); + size_t urlPos = equalSignPos + 1; + String16 match = multiline + ? content.substring(urlPos, closingCommentPos - urlPos) + : content.substring(urlPos); + + size_t newLine = match.find("\n"); + if (newLine != String16::kNotFound) match = match.substring(0, newLine); + match = match.stripWhiteSpace(); + + for (size_t i = 0; i < match.length(); ++i) { + UChar c = match[i]; + if (c == '"' || c == '\'' || c == ' ' || c == '\t') return ""; + } + + return match; +} + +String16 createSearchRegexSource(const String16& text) { + String16Builder result; + + for (size_t i = 0; i < text.length(); i++) { + UChar c = text[i]; + if (c == '[' || c == ']' || c == '(' || c == ')' || c == '{' || c == '}' || + c == '+' || c == '-' || c == '*' || c == '.' || c == ',' || c == '?' || + c == '\\' || c == '^' || c == '$' || c == '|') { + result.append('\\'); + } + result.append(c); + } + + return result.toString(); +} + +std::unique_ptr> lineEndings(const String16& text) { + std::unique_ptr> result(new std::vector()); + + const String16 lineEndString = "\n"; + size_t start = 0; + while (start < text.length()) { + size_t lineEnd = text.find(lineEndString, start); + if (lineEnd == String16::kNotFound) break; + + result->push_back(lineEnd); + start = lineEnd + 1; + } + result->push_back(text.length()); + + return result; +} + +std::vector> scriptRegexpMatchesByLines( + const V8Regex& regex, const String16& text) { + std::vector> result; + if (text.isEmpty()) return result; + + std::unique_ptr> endings(lineEndings(text)); + size_t size = endings->size(); + size_t start = 0; + for (size_t lineNumber = 0; lineNumber < size; ++lineNumber) { + size_t lineEnd = endings->at(lineNumber); + String16 line = text.substring(start, lineEnd - start); + if (line.length() && line[line.length() - 1] == '\r') + line = line.substring(0, line.length() - 1); + + int matchLength; + if (regex.match(line, 0, &matchLength) != -1) + result.push_back(std::pair(lineNumber, line)); + + start = lineEnd + 1; + } + return result; +} + +std::unique_ptr buildObjectForSearchMatch( + int lineNumber, const String16& lineContent) { + return protocol::Debugger::SearchMatch::create() + .setLineNumber(lineNumber) + .setLineContent(lineContent) + .build(); +} + +std::unique_ptr createSearchRegex(V8InspectorImpl* inspector, + const String16& query, + bool caseSensitive, bool isRegex) { + String16 regexSource = isRegex ? query : createSearchRegexSource(query); + return wrapUnique(new V8Regex(inspector, regexSource, caseSensitive)); +} + +} // namespace + +std::vector> +searchInTextByLinesImpl(V8InspectorSession* session, const String16& text, + const String16& query, const bool caseSensitive, + const bool isRegex) { + std::unique_ptr regex = createSearchRegex( + static_cast(session)->inspector(), query, + caseSensitive, isRegex); + std::vector> matches = + scriptRegexpMatchesByLines(*regex.get(), text); + + std::vector> result; + for (const auto& match : matches) + result.push_back(buildObjectForSearchMatch(match.first, match.second)); + return result; +} + +String16 findSourceURL(const String16& content, bool multiline) { + return findMagicComment(content, "sourceURL", multiline); +} + +String16 findSourceMapURL(const String16& content, bool multiline) { + return findMagicComment(content, "sourceMappingURL", multiline); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/search-util.h b/deps/v8_inspector/src/inspector/search-util.h new file mode 100644 index 00000000000000..8f5753b6202c1d --- /dev/null +++ b/deps/v8_inspector/src/inspector/search-util.h @@ -0,0 +1,24 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_SEARCHUTIL_H_ +#define V8_INSPECTOR_SEARCHUTIL_H_ + +#include "src/inspector/protocol/Debugger.h" +#include "src/inspector/string-util.h" + +namespace v8_inspector { + +class V8InspectorSession; + +String16 findSourceURL(const String16& content, bool multiline); +String16 findSourceMapURL(const String16& content, bool multiline); +std::vector> +searchInTextByLinesImpl(V8InspectorSession*, const String16& text, + const String16& query, bool caseSensitive, + bool isRegex); + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_SEARCHUTIL_H_ diff --git a/deps/v8_inspector/src/inspector/string-16.cc b/deps/v8_inspector/src/inspector/string-16.cc new file mode 100644 index 00000000000000..e39b87c17f8f03 --- /dev/null +++ b/deps/v8_inspector/src/inspector/string-16.cc @@ -0,0 +1,523 @@ +// Copyright 2016 the V8 project 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 "src/inspector/string-16.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "src/base/platform/platform.h" +#include "src/inspector/protocol-platform.h" + +namespace v8_inspector { + +namespace { + +bool isASCII(UChar c) { return !(c & ~0x7F); } + +bool isSpaceOrNewLine(UChar c) { + return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); +} + +int charactersToInteger(const UChar* characters, size_t length, + bool* ok = nullptr) { + std::vector buffer; + buffer.reserve(length + 1); + for (size_t i = 0; i < length; ++i) { + if (!isASCII(characters[i])) { + if (ok) *ok = false; + return 0; + } + buffer.push_back(static_cast(characters[i])); + } + buffer.push_back('\0'); + + char* endptr; + int64_t result = + static_cast(std::strtol(buffer.data(), &endptr, 10)); + if (ok) { + *ok = !(*endptr) && result <= std::numeric_limits::max() && + result >= std::numeric_limits::min(); + } + return static_cast(result); +} + +const UChar replacementCharacter = 0xFFFD; +using UChar32 = uint32_t; + +inline int inlineUTF8SequenceLengthNonASCII(char b0) { + if ((b0 & 0xC0) != 0xC0) return 0; + if ((b0 & 0xE0) == 0xC0) return 2; + if ((b0 & 0xF0) == 0xE0) return 3; + if ((b0 & 0xF8) == 0xF0) return 4; + return 0; +} + +inline int inlineUTF8SequenceLength(char b0) { + return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); +} + +// Once the bits are split out into bytes of UTF-8, this is a mask OR-ed +// into the first byte, depending on how many bytes follow. There are +// as many entries in this table as there are UTF-8 sequence types. +// (I.e., one byte sequence, two byte... etc.). Remember that sequences +// for *legal* UTF-8 will be 4 or fewer bytes total. +static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, + 0xF0, 0xF8, 0xFC}; + +typedef enum { + conversionOK, // conversion successful + sourceExhausted, // partial character in source, but hit end + targetExhausted, // insuff. room in target for conversion + sourceIllegal // source sequence is illegal/malformed +} ConversionResult; + +ConversionResult convertUTF16ToUTF8(const UChar** sourceStart, + const UChar* sourceEnd, char** targetStart, + char* targetEnd, bool strict) { + ConversionResult result = conversionOK; + const UChar* source = *sourceStart; + char* target = *targetStart; + while (source < sourceEnd) { + UChar32 ch; + uint32_t bytesToWrite = 0; + const UChar32 byteMask = 0xBF; + const UChar32 byteMark = 0x80; + const UChar* oldSource = + source; // In case we have to back up because of target overflow. + ch = static_cast(*source++); + // If we have a surrogate pair, convert to UChar32 first. + if (ch >= 0xD800 && ch <= 0xDBFF) { + // If the 16 bits following the high surrogate are in the source buffer... + if (source < sourceEnd) { + UChar32 ch2 = static_cast(*source); + // If it's a low surrogate, convert to UChar32. + if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) { + ch = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x0010000; + ++source; + } else if (strict) { // it's an unpaired high surrogate + --source; // return to the illegal value itself + result = sourceIllegal; + break; + } + } else { // We don't have the 16 bits following the high surrogate. + --source; // return to the high surrogate + result = sourceExhausted; + break; + } + } else if (strict) { + // UTF-16 surrogate values are illegal in UTF-32 + if (ch >= 0xDC00 && ch <= 0xDFFF) { + --source; // return to the illegal value itself + result = sourceIllegal; + break; + } + } + // Figure out how many bytes the result will require + if (ch < (UChar32)0x80) { + bytesToWrite = 1; + } else if (ch < (UChar32)0x800) { + bytesToWrite = 2; + } else if (ch < (UChar32)0x10000) { + bytesToWrite = 3; + } else if (ch < (UChar32)0x110000) { + bytesToWrite = 4; + } else { + bytesToWrite = 3; + ch = replacementCharacter; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; // Back up source pointer! + target -= bytesToWrite; + result = targetExhausted; + break; + } + switch (bytesToWrite) { // note: everything falls through. + case 4: + *--target = static_cast((ch | byteMark) & byteMask); + ch >>= 6; + case 3: + *--target = static_cast((ch | byteMark) & byteMask); + ch >>= 6; + case 2: + *--target = static_cast((ch | byteMark) & byteMask); + ch >>= 6; + case 1: + *--target = static_cast(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/** + * Is this code point a BMP code point (U+0000..U+ffff)? + * @param c 32-bit code point + * @return TRUE or FALSE + * @stable ICU 2.8 + */ +#define U_IS_BMP(c) ((uint32_t)(c) <= 0xffff) + +/** + * Is this code point a supplementary code point (U+10000..U+10ffff)? + * @param c 32-bit code point + * @return TRUE or FALSE + * @stable ICU 2.8 + */ +#define U_IS_SUPPLEMENTARY(c) ((uint32_t)((c)-0x10000) <= 0xfffff) + +/** + * Is this code point a surrogate (U+d800..U+dfff)? + * @param c 32-bit code point + * @return TRUE or FALSE + * @stable ICU 2.4 + */ +#define U_IS_SURROGATE(c) (((c)&0xfffff800) == 0xd800) + +/** + * Get the lead surrogate (0xd800..0xdbff) for a + * supplementary code point (0x10000..0x10ffff). + * @param supplementary 32-bit code point (U+10000..U+10ffff) + * @return lead surrogate (U+d800..U+dbff) for supplementary + * @stable ICU 2.4 + */ +#define U16_LEAD(supplementary) (UChar)(((supplementary) >> 10) + 0xd7c0) + +/** + * Get the trail surrogate (0xdc00..0xdfff) for a + * supplementary code point (0x10000..0x10ffff). + * @param supplementary 32-bit code point (U+10000..U+10ffff) + * @return trail surrogate (U+dc00..U+dfff) for supplementary + * @stable ICU 2.4 + */ +#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff) | 0xdc00) + +// This must be called with the length pre-determined by the first byte. +// If presented with a length > 4, this returns false. The Unicode +// definition of UTF-8 goes up to 4-byte sequences. +static bool isLegalUTF8(const unsigned char* source, int length) { + unsigned char a; + const unsigned char* srcptr = source + length; + switch (length) { + default: + return false; + // Everything else falls through when "true"... + case 4: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: + if ((a = (*--srcptr)) > 0xBF) return false; + + // no fall-through in this inner switch + switch (*source) { + case 0xE0: + if (a < 0xA0) return false; + break; + case 0xED: + if (a > 0x9F) return false; + break; + case 0xF0: + if (a < 0x90) return false; + break; + case 0xF4: + if (a > 0x8F) return false; + break; + default: + if (a < 0x80) return false; + } + + case 1: + if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +// Magic values subtracted from a buffer value during UTF8 conversion. +// This table contains as many values as there might be trailing bytes +// in a UTF-8 sequence. +static const UChar32 offsetsFromUTF8[6] = {0x00000000UL, + 0x00003080UL, + 0x000E2080UL, + 0x03C82080UL, + static_cast(0xFA082080UL), + static_cast(0x82082080UL)}; + +static inline UChar32 readUTF8Sequence(const char*& sequence, size_t length) { + UChar32 character = 0; + + // The cases all fall through. + switch (length) { + case 6: + character += static_cast(*sequence++); + character <<= 6; + case 5: + character += static_cast(*sequence++); + character <<= 6; + case 4: + character += static_cast(*sequence++); + character <<= 6; + case 3: + character += static_cast(*sequence++); + character <<= 6; + case 2: + character += static_cast(*sequence++); + character <<= 6; + case 1: + character += static_cast(*sequence++); + } + + return character - offsetsFromUTF8[length - 1]; +} + +ConversionResult convertUTF8ToUTF16(const char** sourceStart, + const char* sourceEnd, UChar** targetStart, + UChar* targetEnd, bool* sourceAllASCII, + bool strict) { + ConversionResult result = conversionOK; + const char* source = *sourceStart; + UChar* target = *targetStart; + UChar orAllData = 0; + while (source < sourceEnd) { + int utf8SequenceLength = inlineUTF8SequenceLength(*source); + if (sourceEnd - source < utf8SequenceLength) { + result = sourceExhausted; + break; + } + // Do this check whether lenient or strict + if (!isLegalUTF8(reinterpret_cast(source), + utf8SequenceLength)) { + result = sourceIllegal; + break; + } + + UChar32 character = readUTF8Sequence(source, utf8SequenceLength); + + if (target >= targetEnd) { + source -= utf8SequenceLength; // Back up source pointer! + result = targetExhausted; + break; + } + + if (U_IS_BMP(character)) { + // UTF-16 surrogate values are illegal in UTF-32 + if (U_IS_SURROGATE(character)) { + if (strict) { + source -= utf8SequenceLength; // return to the illegal value itself + result = sourceIllegal; + break; + } + *target++ = replacementCharacter; + orAllData |= replacementCharacter; + } else { + *target++ = static_cast(character); // normal case + orAllData |= character; + } + } else if (U_IS_SUPPLEMENTARY(character)) { + // target is a character in range 0xFFFF - 0x10FFFF + if (target + 1 >= targetEnd) { + source -= utf8SequenceLength; // Back up source pointer! + result = targetExhausted; + break; + } + *target++ = U16_LEAD(character); + *target++ = U16_TRAIL(character); + orAllData = 0xffff; + } else { + if (strict) { + source -= utf8SequenceLength; // return to the start + result = sourceIllegal; + break; // Bail out; shouldn't continue + } else { + *target++ = replacementCharacter; + orAllData |= replacementCharacter; + } + } + } + *sourceStart = source; + *targetStart = target; + + if (sourceAllASCII) *sourceAllASCII = !(orAllData & ~0x7f); + + return result; +} + +// Helper to write a three-byte UTF-8 code point to the buffer, caller must +// check room is available. +static inline void putUTF8Triple(char*& buffer, UChar ch) { + *buffer++ = static_cast(((ch >> 12) & 0x0F) | 0xE0); + *buffer++ = static_cast(((ch >> 6) & 0x3F) | 0x80); + *buffer++ = static_cast((ch & 0x3F) | 0x80); +} + +} // namespace + +// static +String16 String16::fromInteger(int number) { + const size_t kBufferSize = 50; + char buffer[kBufferSize]; + v8::base::OS::SNPrintF(buffer, kBufferSize, "%d", number); + return String16(buffer); +} + +// static +String16 String16::fromInteger(size_t number) { + const size_t kBufferSize = 50; + char buffer[kBufferSize]; + v8::base::OS::SNPrintF(buffer, kBufferSize, "%zu", number); + return String16(buffer); +} + +// static +String16 String16::fromDouble(double number) { + const size_t kBufferSize = 100; + char buffer[kBufferSize]; + v8::base::OS::SNPrintF(buffer, kBufferSize, "%f", number); + return String16(buffer); +} + +// static +String16 String16::fromDoublePrecision3(double number) { + const size_t kBufferSize = 100; + char buffer[kBufferSize]; + v8::base::OS::SNPrintF(buffer, kBufferSize, "%.3g", number); + return String16(buffer); +} + +// static +String16 String16::fromDoublePrecision6(double number) { + const size_t kBufferSize = 100; + char buffer[kBufferSize]; + v8::base::OS::SNPrintF(buffer, kBufferSize, "%.6g", number); + return String16(buffer); +} + +int String16::toInteger(bool* ok) const { + return charactersToInteger(characters16(), length(), ok); +} + +String16 String16::stripWhiteSpace() const { + if (!length()) return String16(); + + size_t start = 0; + size_t end = length() - 1; + + // skip white space from start + while (start <= end && isSpaceOrNewLine(characters16()[start])) ++start; + + // only white space + if (start > end) return String16(); + + // skip white space from end + while (end && isSpaceOrNewLine(characters16()[end])) --end; + + if (!start && end == length() - 1) return *this; + return String16(characters16() + start, end + 1 - start); +} + +String16Builder::String16Builder() {} + +void String16Builder::append(const String16& s) { + m_buffer.insert(m_buffer.end(), s.characters16(), + s.characters16() + s.length()); +} + +void String16Builder::append(UChar c) { m_buffer.push_back(c); } + +void String16Builder::append(char c) { + UChar u = c; + m_buffer.push_back(u); +} + +void String16Builder::append(const UChar* characters, size_t length) { + m_buffer.insert(m_buffer.end(), characters, characters + length); +} + +void String16Builder::append(const char* characters, size_t length) { + m_buffer.insert(m_buffer.end(), characters, characters + length); +} + +String16 String16Builder::toString() { + return String16(m_buffer.data(), m_buffer.size()); +} + +void String16Builder::reserveCapacity(size_t capacity) { + m_buffer.reserve(capacity); +} + +String16 String16::fromUTF8(const char* stringStart, size_t length) { + if (!stringStart || !length) return String16(); + + std::vector buffer(length); + UChar* bufferStart = buffer.data(); + + UChar* bufferCurrent = bufferStart; + const char* stringCurrent = stringStart; + if (convertUTF8ToUTF16(&stringCurrent, stringStart + length, &bufferCurrent, + bufferCurrent + buffer.size(), 0, + true) != conversionOK) + return String16(); + + size_t utf16Length = bufferCurrent - bufferStart; + return String16(bufferStart, utf16Length); +} + +std::string String16::utf8() const { + size_t length = this->length(); + + if (!length) return std::string(""); + + // Allocate a buffer big enough to hold all the characters + // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes). + // Optimization ideas, if we find this function is hot: + // * We could speculatively create a CStringBuffer to contain 'length' + // characters, and resize if necessary (i.e. if the buffer contains + // non-ascii characters). (Alternatively, scan the buffer first for + // ascii characters, so we know this will be sufficient). + // * We could allocate a CStringBuffer with an appropriate size to + // have a good chance of being able to write the string into the + // buffer without reallocing (say, 1.5 x length). + if (length > std::numeric_limits::max() / 3) return std::string(); + std::vector bufferVector(length * 3); + char* buffer = bufferVector.data(); + const UChar* characters = m_impl.data(); + + ConversionResult result = + convertUTF16ToUTF8(&characters, characters + length, &buffer, + buffer + bufferVector.size(), false); + DCHECK( + result != + targetExhausted); // (length * 3) should be sufficient for any conversion + + // Only produced from strict conversion. + DCHECK(result != sourceIllegal); + + // Check for an unconverted high surrogate. + if (result == sourceExhausted) { + // This should be one unpaired high surrogate. Treat it the same + // was as an unpaired high surrogate would have been handled in + // the middle of a string with non-strict conversion - which is + // to say, simply encode it to UTF-8. + DCHECK((characters + 1) == (m_impl.data() + length)); + DCHECK((*characters >= 0xD800) && (*characters <= 0xDBFF)); + // There should be room left, since one UChar hasn't been + // converted. + DCHECK((buffer + 3) <= (buffer + bufferVector.size())); + putUTF8Triple(buffer, *characters); + } + + return std::string(bufferVector.data(), buffer - bufferVector.data()); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/string-16.h b/deps/v8_inspector/src/inspector/string-16.h new file mode 100644 index 00000000000000..94069479579faf --- /dev/null +++ b/deps/v8_inspector/src/inspector/string-16.h @@ -0,0 +1,134 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_STRING16_H_ +#define V8_INSPECTOR_STRING16_H_ + +#include +#include +#include +#include +#include +#include + +namespace v8_inspector { + +using UChar = uint16_t; + +class String16 { + public: + static const size_t kNotFound = static_cast(-1); + + String16() {} + String16(const String16& other) : m_impl(other.m_impl) {} + String16(const UChar* characters, size_t size) : m_impl(characters, size) {} + String16(const UChar* characters) // NOLINT(runtime/explicit) + : m_impl(characters) {} + String16(const char* characters) // NOLINT(runtime/explicit) + : String16(characters, std::strlen(characters)) {} + String16(const char* characters, size_t size) { + m_impl.resize(size); + for (size_t i = 0; i < size; ++i) m_impl[i] = characters[i]; + } + + static String16 fromInteger(int); + static String16 fromInteger(size_t); + static String16 fromDouble(double); + static String16 fromDoublePrecision3(double); + static String16 fromDoublePrecision6(double); + + int toInteger(bool* ok = nullptr) const; + String16 stripWhiteSpace() const; + const UChar* characters16() const { return m_impl.c_str(); } + size_t length() const { return m_impl.length(); } + bool isEmpty() const { return !m_impl.length(); } + UChar operator[](size_t index) const { return m_impl[index]; } + String16 substring(size_t pos, size_t len = UINT_MAX) const { + return String16(m_impl.substr(pos, len)); + } + size_t find(const String16& str, size_t start = 0) const { + return m_impl.find(str.m_impl, start); + } + size_t reverseFind(const String16& str, size_t start = UINT_MAX) const { + return m_impl.rfind(str.m_impl, start); + } + void swap(String16& other) { m_impl.swap(other.m_impl); } + + // Convenience methods. + std::string utf8() const; + static String16 fromUTF8(const char* stringStart, size_t length); + + const std::basic_string& impl() const { return m_impl; } + explicit String16(const std::basic_string& impl) : m_impl(impl) {} + + std::size_t hash() const { + if (!has_hash) { + size_t hash = 0; + for (size_t i = 0; i < length(); ++i) hash = 31 * hash + m_impl[i]; + hash_code = hash; + has_hash = true; + } + return hash_code; + } + + private: + std::basic_string m_impl; + mutable bool has_hash = false; + mutable std::size_t hash_code = 0; +}; + +inline bool operator==(const String16& a, const String16& b) { + return a.impl() == b.impl(); +} +inline bool operator<(const String16& a, const String16& b) { + return a.impl() < b.impl(); +} +inline bool operator!=(const String16& a, const String16& b) { + return a.impl() != b.impl(); +} +inline bool operator==(const String16& a, const char* b) { + return a.impl() == String16(b).impl(); +} +inline String16 operator+(const String16& a, const char* b) { + return String16(a.impl() + String16(b).impl()); +} +inline String16 operator+(const char* a, const String16& b) { + return String16(String16(a).impl() + b.impl()); +} +inline String16 operator+(const String16& a, const String16& b) { + return String16(a.impl() + b.impl()); +} + +class String16Builder { + public: + String16Builder(); + void append(const String16&); + void append(UChar); + void append(char); + void append(const UChar*, size_t); + void append(const char*, size_t); + String16 toString(); + void reserveCapacity(size_t); + + private: + std::vector m_buffer; +}; + +} // namespace v8_inspector + +#if !defined(__APPLE__) || defined(_LIBCPP_VERSION) + +namespace std { +template <> +struct hash { + std::size_t operator()(const v8_inspector::String16& string) const { + return string.hash(); + } +}; + +} // namespace std + +#endif // !defined(__APPLE__) || defined(_LIBCPP_VERSION) + +#endif // V8_INSPECTOR_STRING16_H_ diff --git a/deps/v8_inspector/src/inspector/string-util.cc b/deps/v8_inspector/src/inspector/string-util.cc new file mode 100644 index 00000000000000..e6b83a5d7db6f8 --- /dev/null +++ b/deps/v8_inspector/src/inspector/string-util.cc @@ -0,0 +1,218 @@ +// Copyright 2016 the V8 project 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 "src/inspector/string-util.h" + +#include "src/inspector/protocol/Protocol.h" + +namespace v8_inspector { + +v8::Local toV8String(v8::Isolate* isolate, const String16& string) { + if (string.isEmpty()) return v8::String::Empty(isolate); + DCHECK(string.length() < v8::String::kMaxLength); + return v8::String::NewFromTwoByte( + isolate, reinterpret_cast(string.characters16()), + v8::NewStringType::kNormal, static_cast(string.length())) + .ToLocalChecked(); +} + +v8::Local toV8StringInternalized(v8::Isolate* isolate, + const String16& string) { + if (string.isEmpty()) return v8::String::Empty(isolate); + DCHECK(string.length() < v8::String::kMaxLength); + return v8::String::NewFromTwoByte( + isolate, reinterpret_cast(string.characters16()), + v8::NewStringType::kInternalized, + static_cast(string.length())) + .ToLocalChecked(); +} + +v8::Local toV8StringInternalized(v8::Isolate* isolate, + const char* str) { + return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kInternalized) + .ToLocalChecked(); +} + +v8::Local toV8String(v8::Isolate* isolate, + const StringView& string) { + if (!string.length()) return v8::String::Empty(isolate); + DCHECK(string.length() < v8::String::kMaxLength); + if (string.is8Bit()) + return v8::String::NewFromOneByte( + isolate, reinterpret_cast(string.characters8()), + v8::NewStringType::kNormal, static_cast(string.length())) + .ToLocalChecked(); + return v8::String::NewFromTwoByte( + isolate, reinterpret_cast(string.characters16()), + v8::NewStringType::kNormal, static_cast(string.length())) + .ToLocalChecked(); +} + +String16 toProtocolString(v8::Local value) { + if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) + return String16(); + std::unique_ptr buffer(new UChar[value->Length()]); + value->Write(reinterpret_cast(buffer.get()), 0, value->Length()); + return String16(buffer.get(), value->Length()); +} + +String16 toProtocolStringWithTypeCheck(v8::Local value) { + if (value.IsEmpty() || !value->IsString()) return String16(); + return toProtocolString(value.As()); +} + +String16 toString16(const StringView& string) { + if (!string.length()) return String16(); + if (string.is8Bit()) + return String16(reinterpret_cast(string.characters8()), + string.length()); + return String16(reinterpret_cast(string.characters16()), + string.length()); +} + +StringView toStringView(const String16& string) { + if (string.isEmpty()) return StringView(); + return StringView(reinterpret_cast(string.characters16()), + string.length()); +} + +bool stringViewStartsWith(const StringView& string, const char* prefix) { + if (!string.length()) return !(*prefix); + if (string.is8Bit()) { + for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) { + if (string.characters8()[i] != prefix[j]) return false; + } + } else { + for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) { + if (string.characters16()[i] != prefix[j]) return false; + } + } + return true; +} + +namespace protocol { + +std::unique_ptr parseJSON(const StringView& string) { + if (!string.length()) return nullptr; + if (string.is8Bit()) { + return protocol::parseJSON(string.characters8(), + static_cast(string.length())); + } + return protocol::parseJSON(string.characters16(), + static_cast(string.length())); +} + +std::unique_ptr parseJSON(const String16& string) { + if (!string.length()) return nullptr; + return protocol::parseJSON(string.characters16(), + static_cast(string.length())); +} + +} // namespace protocol + +std::unique_ptr toProtocolValue(protocol::String* errorString, + v8::Local context, + v8::Local value, + int maxDepth) { + if (value.IsEmpty()) { + UNREACHABLE(); + return nullptr; + } + + if (!maxDepth) { + *errorString = "Object reference chain is too long"; + return nullptr; + } + maxDepth--; + + if (value->IsNull() || value->IsUndefined()) return protocol::Value::null(); + if (value->IsBoolean()) + return protocol::FundamentalValue::create(value.As()->Value()); + if (value->IsNumber()) { + double doubleValue = value.As()->Value(); + int intValue = static_cast(doubleValue); + if (intValue == doubleValue) + return protocol::FundamentalValue::create(intValue); + return protocol::FundamentalValue::create(doubleValue); + } + if (value->IsString()) + return protocol::StringValue::create( + toProtocolString(value.As())); + if (value->IsArray()) { + v8::Local array = value.As(); + std::unique_ptr inspectorArray = + protocol::ListValue::create(); + uint32_t length = array->Length(); + for (uint32_t i = 0; i < length; i++) { + v8::Local value; + if (!array->Get(context, i).ToLocal(&value)) { + *errorString = "Internal error"; + return nullptr; + } + std::unique_ptr element = + toProtocolValue(errorString, context, value, maxDepth); + if (!element) return nullptr; + inspectorArray->pushValue(std::move(element)); + } + return std::move(inspectorArray); + } + if (value->IsObject()) { + std::unique_ptr jsonObject = + protocol::DictionaryValue::create(); + v8::Local object = v8::Local::Cast(value); + v8::Local propertyNames; + if (!object->GetPropertyNames(context).ToLocal(&propertyNames)) { + *errorString = "Internal error"; + return nullptr; + } + uint32_t length = propertyNames->Length(); + for (uint32_t i = 0; i < length; i++) { + v8::Local name; + if (!propertyNames->Get(context, i).ToLocal(&name)) { + *errorString = "Internal error"; + return nullptr; + } + // FIXME(yurys): v8::Object should support GetOwnPropertyNames + if (name->IsString()) { + v8::Maybe hasRealNamedProperty = object->HasRealNamedProperty( + context, v8::Local::Cast(name)); + if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust()) + continue; + } + v8::Local propertyName; + if (!name->ToString(context).ToLocal(&propertyName)) continue; + v8::Local property; + if (!object->Get(context, name).ToLocal(&property)) { + *errorString = "Internal error"; + return nullptr; + } + std::unique_ptr propertyValue = + toProtocolValue(errorString, context, property, maxDepth); + if (!propertyValue) return nullptr; + jsonObject->setValue(toProtocolString(propertyName), + std::move(propertyValue)); + } + return std::move(jsonObject); + } + *errorString = "Object couldn't be returned by value"; + return nullptr; +} + +// static +std::unique_ptr StringBuffer::create(const StringView& string) { + String16 owner = toString16(string); + return StringBufferImpl::adopt(owner); +} + +// static +std::unique_ptr StringBufferImpl::adopt(String16& string) { + return wrapUnique(new StringBufferImpl(string)); +} + +StringBufferImpl::StringBufferImpl(String16& string) { + m_owner.swap(string); + m_string = toStringView(m_owner); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/string-util.h b/deps/v8_inspector/src/inspector/string-util.h new file mode 100644 index 00000000000000..30137b8b786f97 --- /dev/null +++ b/deps/v8_inspector/src/inspector/string-util.h @@ -0,0 +1,75 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_STRINGUTIL_H_ +#define V8_INSPECTOR_STRINGUTIL_H_ + +#include "src/base/macros.h" +#include "src/inspector/string-16.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +namespace protocol { + +class Value; + +using String = v8_inspector::String16; +using StringBuilder = v8_inspector::String16Builder; + +class StringUtil { + public: + static String substring(const String& s, size_t pos, size_t len) { + return s.substring(pos, len); + } + static String fromInteger(int number) { return String::fromInteger(number); } + static String fromInteger(size_t number) { + return String::fromInteger(number); + } + static String fromDouble(double number) { return String::fromDouble(number); } + static const size_t kNotFound = String::kNotFound; + static void builderReserve(StringBuilder& builder, size_t capacity) { + builder.reserveCapacity(capacity); + } +}; + +std::unique_ptr parseJSON(const StringView& json); +std::unique_ptr parseJSON(const String16& json); + +} // namespace protocol + +std::unique_ptr toProtocolValue(protocol::String* errorString, + v8::Local, + v8::Local, + int maxDepth = 1000); + +v8::Local toV8String(v8::Isolate*, const String16&); +v8::Local toV8StringInternalized(v8::Isolate*, const String16&); +v8::Local toV8StringInternalized(v8::Isolate*, const char*); +v8::Local toV8String(v8::Isolate*, const StringView&); +// TODO(dgozman): rename to toString16. +String16 toProtocolString(v8::Local); +String16 toProtocolStringWithTypeCheck(v8::Local); +String16 toString16(const StringView&); +StringView toStringView(const String16&); +bool stringViewStartsWith(const StringView&, const char*); + +class StringBufferImpl : public StringBuffer { + public: + // Destroys string's content. + static std::unique_ptr adopt(String16&); + const StringView& string() override { return m_string; } + + private: + explicit StringBufferImpl(String16&); + String16 m_owner; + StringView m_string; + + DISALLOW_COPY_AND_ASSIGN(StringBufferImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_STRINGUTIL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-console-agent-impl.cc b/deps/v8_inspector/src/inspector/v8-console-agent-impl.cc new file mode 100644 index 00000000000000..8eb883cb754c44 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-console-agent-impl.cc @@ -0,0 +1,79 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-console-agent-impl.h" + +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/v8-console-message.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-stack-trace-impl.h" + +namespace v8_inspector { + +namespace ConsoleAgentState { +static const char consoleEnabled[] = "consoleEnabled"; +} + +V8ConsoleAgentImpl::V8ConsoleAgentImpl( + V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, + protocol::DictionaryValue* state) + : m_session(session), + m_state(state), + m_frontend(frontendChannel), + m_enabled(false) {} + +V8ConsoleAgentImpl::~V8ConsoleAgentImpl() {} + +void V8ConsoleAgentImpl::enable(ErrorString* errorString) { + if (m_enabled) return; + m_state->setBoolean(ConsoleAgentState::consoleEnabled, true); + m_enabled = true; + m_session->inspector()->enableStackCapturingIfNeeded(); + reportAllMessages(); +} + +void V8ConsoleAgentImpl::disable(ErrorString* errorString) { + if (!m_enabled) return; + m_session->inspector()->disableStackCapturingIfNeeded(); + m_state->setBoolean(ConsoleAgentState::consoleEnabled, false); + m_enabled = false; +} + +void V8ConsoleAgentImpl::clearMessages(ErrorString* errorString) {} + +void V8ConsoleAgentImpl::restore() { + if (!m_state->booleanProperty(ConsoleAgentState::consoleEnabled, false)) + return; + ErrorString ignored; + enable(&ignored); +} + +void V8ConsoleAgentImpl::messageAdded(V8ConsoleMessage* message) { + if (m_enabled) reportMessage(message, true); +} + +bool V8ConsoleAgentImpl::enabled() { return m_enabled; } + +void V8ConsoleAgentImpl::reportAllMessages() { + V8ConsoleMessageStorage* storage = + m_session->inspector()->ensureConsoleMessageStorage( + m_session->contextGroupId()); + for (const auto& message : storage->messages()) { + if (message->origin() == V8MessageOrigin::kConsole) { + if (!reportMessage(message.get(), false)) return; + } + } +} + +bool V8ConsoleAgentImpl::reportMessage(V8ConsoleMessage* message, + bool generatePreview) { + DCHECK(message->origin() == V8MessageOrigin::kConsole); + message->reportToFrontend(&m_frontend); + m_frontend.flush(); + return m_session->inspector()->hasConsoleMessageStorage( + m_session->contextGroupId()); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-console-agent-impl.h b/deps/v8_inspector/src/inspector/v8-console-agent-impl.h new file mode 100644 index 00000000000000..f3d598bb3494fb --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-console-agent-impl.h @@ -0,0 +1,48 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8CONSOLEAGENTIMPL_H_ +#define V8_INSPECTOR_V8CONSOLEAGENTIMPL_H_ + +#include "src/base/macros.h" +#include "src/inspector/protocol/Console.h" +#include "src/inspector/protocol/Forward.h" + +namespace v8_inspector { + +class V8ConsoleMessage; +class V8InspectorSessionImpl; + +using protocol::ErrorString; + +class V8ConsoleAgentImpl : public protocol::Console::Backend { + public: + V8ConsoleAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, + protocol::DictionaryValue* state); + ~V8ConsoleAgentImpl() override; + + void enable(ErrorString*) override; + void disable(ErrorString*) override; + void clearMessages(ErrorString*) override; + + void restore(); + void messageAdded(V8ConsoleMessage*); + void reset(); + bool enabled(); + + private: + void reportAllMessages(); + bool reportMessage(V8ConsoleMessage*, bool generatePreview); + + V8InspectorSessionImpl* m_session; + protocol::DictionaryValue* m_state; + protocol::Console::Frontend m_frontend; + bool m_enabled; + + DISALLOW_COPY_AND_ASSIGN(V8ConsoleAgentImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8CONSOLEAGENTIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-console-message.cc b/deps/v8_inspector/src/inspector/v8-console-message.cc new file mode 100644 index 00000000000000..87c9d68d9b3514 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-console-message.cc @@ -0,0 +1,473 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-console-message.h" + +#include "src/inspector/inspected-context.h" +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-console-agent-impl.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-runtime-agent-impl.h" +#include "src/inspector/v8-stack-trace-impl.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +namespace { + +String16 consoleAPITypeValue(ConsoleAPIType type) { + switch (type) { + case ConsoleAPIType::kLog: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log; + case ConsoleAPIType::kDebug: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug; + case ConsoleAPIType::kInfo: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Info; + case ConsoleAPIType::kError: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Error; + case ConsoleAPIType::kWarning: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Warning; + case ConsoleAPIType::kClear: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Clear; + case ConsoleAPIType::kDir: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dir; + case ConsoleAPIType::kDirXML: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dirxml; + case ConsoleAPIType::kTable: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Table; + case ConsoleAPIType::kTrace: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Trace; + case ConsoleAPIType::kStartGroup: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroup; + case ConsoleAPIType::kStartGroupCollapsed: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroupCollapsed; + case ConsoleAPIType::kEndGroup: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::EndGroup; + case ConsoleAPIType::kAssert: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Assert; + case ConsoleAPIType::kTimeEnd: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug; + case ConsoleAPIType::kCount: + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug; + } + return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log; +} + +const unsigned maxConsoleMessageCount = 1000; +const unsigned maxArrayItemsLimit = 10000; +const unsigned maxStackDepthLimit = 32; + +class V8ValueStringBuilder { + public: + static String16 toString(v8::Local value, + v8::Local context) { + V8ValueStringBuilder builder(context); + if (!builder.append(value)) return String16(); + return builder.toString(); + } + + private: + enum { + IgnoreNull = 1 << 0, + IgnoreUndefined = 1 << 1, + }; + + explicit V8ValueStringBuilder(v8::Local context) + : m_arrayLimit(maxArrayItemsLimit), + m_isolate(context->GetIsolate()), + m_tryCatch(context->GetIsolate()), + m_context(context) {} + + bool append(v8::Local value, unsigned ignoreOptions = 0) { + if (value.IsEmpty()) return true; + if ((ignoreOptions & IgnoreNull) && value->IsNull()) return true; + if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined()) return true; + if (value->IsString()) return append(v8::Local::Cast(value)); + if (value->IsStringObject()) + return append(v8::Local::Cast(value)->ValueOf()); + if (value->IsSymbol()) return append(v8::Local::Cast(value)); + if (value->IsSymbolObject()) + return append(v8::Local::Cast(value)->ValueOf()); + if (value->IsNumberObject()) { + m_builder.append(String16::fromDoublePrecision6( + v8::Local::Cast(value)->ValueOf())); + return true; + } + if (value->IsBooleanObject()) { + m_builder.append(v8::Local::Cast(value)->ValueOf() + ? "true" + : "false"); + return true; + } + if (value->IsArray()) return append(v8::Local::Cast(value)); + if (value->IsProxy()) { + m_builder.append("[object Proxy]"); + return true; + } + if (value->IsObject() && !value->IsDate() && !value->IsFunction() && + !value->IsNativeError() && !value->IsRegExp()) { + v8::Local object = v8::Local::Cast(value); + v8::Local stringValue; + if (object->ObjectProtoToString(m_isolate->GetCurrentContext()) + .ToLocal(&stringValue)) + return append(stringValue); + } + v8::Local stringValue; + if (!value->ToString(m_isolate->GetCurrentContext()).ToLocal(&stringValue)) + return false; + return append(stringValue); + } + + bool append(v8::Local array) { + for (const auto& it : m_visitedArrays) { + if (it == array) return true; + } + uint32_t length = array->Length(); + if (length > m_arrayLimit) return false; + if (m_visitedArrays.size() > maxStackDepthLimit) return false; + + bool result = true; + m_arrayLimit -= length; + m_visitedArrays.push_back(array); + for (uint32_t i = 0; i < length; ++i) { + if (i) m_builder.append(','); + v8::Local value; + if (!array->Get(m_context, i).ToLocal(&value)) continue; + if (!append(value, IgnoreNull | IgnoreUndefined)) { + result = false; + break; + } + } + m_visitedArrays.pop_back(); + return result; + } + + bool append(v8::Local symbol) { + m_builder.append("Symbol("); + bool result = append(symbol->Name(), IgnoreUndefined); + m_builder.append(')'); + return result; + } + + bool append(v8::Local string) { + if (m_tryCatch.HasCaught()) return false; + if (!string.IsEmpty()) m_builder.append(toProtocolString(string)); + return true; + } + + String16 toString() { + if (m_tryCatch.HasCaught()) return String16(); + return m_builder.toString(); + } + + uint32_t m_arrayLimit; + v8::Isolate* m_isolate; + String16Builder m_builder; + std::vector> m_visitedArrays; + v8::TryCatch m_tryCatch; + v8::Local m_context; +}; + +} // namespace + +V8ConsoleMessage::V8ConsoleMessage(V8MessageOrigin origin, double timestamp, + const String16& message) + : m_origin(origin), + m_timestamp(timestamp), + m_message(message), + m_lineNumber(0), + m_columnNumber(0), + m_scriptId(0), + m_contextId(0), + m_type(ConsoleAPIType::kLog), + m_exceptionId(0), + m_revokedExceptionId(0) {} + +V8ConsoleMessage::~V8ConsoleMessage() {} + +void V8ConsoleMessage::setLocation(const String16& url, unsigned lineNumber, + unsigned columnNumber, + std::unique_ptr stackTrace, + int scriptId) { + m_url = url; + m_lineNumber = lineNumber; + m_columnNumber = columnNumber; + m_stackTrace = std::move(stackTrace); + m_scriptId = scriptId; +} + +void V8ConsoleMessage::reportToFrontend( + protocol::Console::Frontend* frontend) const { + DCHECK(m_origin == V8MessageOrigin::kConsole); + String16 level = protocol::Console::ConsoleMessage::LevelEnum::Log; + if (m_type == ConsoleAPIType::kDebug || m_type == ConsoleAPIType::kCount || + m_type == ConsoleAPIType::kTimeEnd) + level = protocol::Console::ConsoleMessage::LevelEnum::Debug; + else if (m_type == ConsoleAPIType::kError || + m_type == ConsoleAPIType::kAssert) + level = protocol::Console::ConsoleMessage::LevelEnum::Error; + else if (m_type == ConsoleAPIType::kWarning) + level = protocol::Console::ConsoleMessage::LevelEnum::Warning; + else if (m_type == ConsoleAPIType::kInfo) + level = protocol::Console::ConsoleMessage::LevelEnum::Info; + std::unique_ptr result = + protocol::Console::ConsoleMessage::create() + .setSource(protocol::Console::ConsoleMessage::SourceEnum::ConsoleApi) + .setLevel(level) + .setText(m_message) + .build(); + result->setLine(static_cast(m_lineNumber)); + result->setColumn(static_cast(m_columnNumber)); + result->setUrl(m_url); + frontend->messageAdded(std::move(result)); +} + +std::unique_ptr> +V8ConsoleMessage::wrapArguments(V8InspectorSessionImpl* session, + bool generatePreview) const { + if (!m_arguments.size() || !m_contextId) return nullptr; + InspectedContext* inspectedContext = + session->inspector()->getContext(session->contextGroupId(), m_contextId); + if (!inspectedContext) return nullptr; + + v8::Isolate* isolate = inspectedContext->isolate(); + v8::HandleScope handles(isolate); + v8::Local context = inspectedContext->context(); + + std::unique_ptr> args = + protocol::Array::create(); + if (m_type == ConsoleAPIType::kTable && generatePreview) { + v8::Local table = m_arguments[0]->Get(isolate); + v8::Local columns = m_arguments.size() > 1 + ? m_arguments[1]->Get(isolate) + : v8::Local(); + std::unique_ptr wrapped = + session->wrapTable(context, table, columns); + if (wrapped) + args->addItem(std::move(wrapped)); + else + args = nullptr; + } else { + for (size_t i = 0; i < m_arguments.size(); ++i) { + std::unique_ptr wrapped = + session->wrapObject(context, m_arguments[i]->Get(isolate), "console", + generatePreview); + if (!wrapped) { + args = nullptr; + break; + } + args->addItem(std::move(wrapped)); + } + } + return args; +} + +void V8ConsoleMessage::reportToFrontend(protocol::Runtime::Frontend* frontend, + V8InspectorSessionImpl* session, + bool generatePreview) const { + if (m_origin == V8MessageOrigin::kException) { + std::unique_ptr exception = + wrapException(session, generatePreview); + std::unique_ptr exceptionDetails = + protocol::Runtime::ExceptionDetails::create() + .setExceptionId(m_exceptionId) + .setText(exception ? m_message : m_detailedMessage) + .setLineNumber(m_lineNumber ? m_lineNumber - 1 : 0) + .setColumnNumber(m_columnNumber ? m_columnNumber - 1 : 0) + .build(); + if (m_scriptId) + exceptionDetails->setScriptId(String16::fromInteger(m_scriptId)); + if (!m_url.isEmpty()) exceptionDetails->setUrl(m_url); + if (m_stackTrace) + exceptionDetails->setStackTrace(m_stackTrace->buildInspectorObjectImpl()); + if (m_contextId) exceptionDetails->setExecutionContextId(m_contextId); + if (exception) exceptionDetails->setException(std::move(exception)); + frontend->exceptionThrown(m_timestamp, std::move(exceptionDetails)); + return; + } + if (m_origin == V8MessageOrigin::kRevokedException) { + frontend->exceptionRevoked(m_message, m_revokedExceptionId); + return; + } + if (m_origin == V8MessageOrigin::kConsole) { + std::unique_ptr> + arguments = wrapArguments(session, generatePreview); + if (!arguments) { + arguments = protocol::Array::create(); + if (!m_message.isEmpty()) { + std::unique_ptr messageArg = + protocol::Runtime::RemoteObject::create() + .setType(protocol::Runtime::RemoteObject::TypeEnum::String) + .build(); + messageArg->setValue(protocol::StringValue::create(m_message)); + arguments->addItem(std::move(messageArg)); + } + } + frontend->consoleAPICalled( + consoleAPITypeValue(m_type), std::move(arguments), m_contextId, + m_timestamp, + m_stackTrace ? m_stackTrace->buildInspectorObjectImpl() : nullptr); + return; + } + UNREACHABLE(); +} + +std::unique_ptr +V8ConsoleMessage::wrapException(V8InspectorSessionImpl* session, + bool generatePreview) const { + if (!m_arguments.size() || !m_contextId) return nullptr; + DCHECK_EQ(1u, m_arguments.size()); + InspectedContext* inspectedContext = + session->inspector()->getContext(session->contextGroupId(), m_contextId); + if (!inspectedContext) return nullptr; + + v8::Isolate* isolate = inspectedContext->isolate(); + v8::HandleScope handles(isolate); + // TODO(dgozman): should we use different object group? + return session->wrapObject(inspectedContext->context(), + m_arguments[0]->Get(isolate), "console", + generatePreview); +} + +V8MessageOrigin V8ConsoleMessage::origin() const { return m_origin; } + +ConsoleAPIType V8ConsoleMessage::type() const { return m_type; } + +// static +std::unique_ptr V8ConsoleMessage::createForConsoleAPI( + double timestamp, ConsoleAPIType type, + const std::vector>& arguments, + std::unique_ptr stackTrace, + InspectedContext* inspectedContext) { + v8::Isolate* isolate = inspectedContext->isolate(); + int contextId = inspectedContext->contextId(); + int contextGroupId = inspectedContext->contextGroupId(); + V8InspectorImpl* inspector = inspectedContext->inspector(); + v8::Local context = inspectedContext->context(); + + std::unique_ptr message = wrapUnique( + new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, String16())); + if (stackTrace && !stackTrace->isEmpty()) { + message->m_url = toString16(stackTrace->topSourceURL()); + message->m_lineNumber = stackTrace->topLineNumber(); + message->m_columnNumber = stackTrace->topColumnNumber(); + } + message->m_stackTrace = std::move(stackTrace); + message->m_type = type; + message->m_contextId = contextId; + for (size_t i = 0; i < arguments.size(); ++i) + message->m_arguments.push_back( + wrapUnique(new v8::Global(isolate, arguments.at(i)))); + if (arguments.size()) + message->m_message = V8ValueStringBuilder::toString(arguments[0], context); + + V8ConsoleAPIType clientType = V8ConsoleAPIType::kLog; + if (type == ConsoleAPIType::kDebug || type == ConsoleAPIType::kCount || + type == ConsoleAPIType::kTimeEnd) + clientType = V8ConsoleAPIType::kDebug; + else if (type == ConsoleAPIType::kError || type == ConsoleAPIType::kAssert) + clientType = V8ConsoleAPIType::kError; + else if (type == ConsoleAPIType::kWarning) + clientType = V8ConsoleAPIType::kWarning; + else if (type == ConsoleAPIType::kInfo) + clientType = V8ConsoleAPIType::kInfo; + else if (type == ConsoleAPIType::kClear) + clientType = V8ConsoleAPIType::kClear; + inspector->client()->consoleAPIMessage( + contextGroupId, clientType, toStringView(message->m_message), + toStringView(message->m_url), message->m_lineNumber, + message->m_columnNumber, message->m_stackTrace.get()); + + return message; +} + +// static +std::unique_ptr V8ConsoleMessage::createForException( + double timestamp, const String16& detailedMessage, const String16& url, + unsigned lineNumber, unsigned columnNumber, + std::unique_ptr stackTrace, int scriptId, + v8::Isolate* isolate, const String16& message, int contextId, + v8::Local exception, unsigned exceptionId) { + std::unique_ptr consoleMessage = wrapUnique( + new V8ConsoleMessage(V8MessageOrigin::kException, timestamp, message)); + consoleMessage->setLocation(url, lineNumber, columnNumber, + std::move(stackTrace), scriptId); + consoleMessage->m_exceptionId = exceptionId; + consoleMessage->m_detailedMessage = detailedMessage; + if (contextId && !exception.IsEmpty()) { + consoleMessage->m_contextId = contextId; + consoleMessage->m_arguments.push_back( + wrapUnique(new v8::Global(isolate, exception))); + } + return consoleMessage; +} + +// static +std::unique_ptr V8ConsoleMessage::createForRevokedException( + double timestamp, const String16& messageText, + unsigned revokedExceptionId) { + std::unique_ptr message = wrapUnique(new V8ConsoleMessage( + V8MessageOrigin::kRevokedException, timestamp, messageText)); + message->m_revokedExceptionId = revokedExceptionId; + return message; +} + +void V8ConsoleMessage::contextDestroyed(int contextId) { + if (contextId != m_contextId) return; + m_contextId = 0; + if (m_message.isEmpty()) m_message = ""; + Arguments empty; + m_arguments.swap(empty); +} + +// ------------------------ V8ConsoleMessageStorage ---------------------------- + +V8ConsoleMessageStorage::V8ConsoleMessageStorage(V8InspectorImpl* inspector, + int contextGroupId) + : m_inspector(inspector), + m_contextGroupId(contextGroupId), + m_expiredCount(0) {} + +V8ConsoleMessageStorage::~V8ConsoleMessageStorage() { clear(); } + +void V8ConsoleMessageStorage::addMessage( + std::unique_ptr message) { + int contextGroupId = m_contextGroupId; + V8InspectorImpl* inspector = m_inspector; + if (message->type() == ConsoleAPIType::kClear) clear(); + + V8InspectorSessionImpl* session = + inspector->sessionForContextGroup(contextGroupId); + if (session) { + if (message->origin() == V8MessageOrigin::kConsole) + session->consoleAgent()->messageAdded(message.get()); + session->runtimeAgent()->messageAdded(message.get()); + } + if (!inspector->hasConsoleMessageStorage(contextGroupId)) return; + + DCHECK(m_messages.size() <= maxConsoleMessageCount); + if (m_messages.size() == maxConsoleMessageCount) { + ++m_expiredCount; + m_messages.pop_front(); + } + m_messages.push_back(std::move(message)); +} + +void V8ConsoleMessageStorage::clear() { + m_messages.clear(); + m_expiredCount = 0; + if (V8InspectorSessionImpl* session = + m_inspector->sessionForContextGroup(m_contextGroupId)) + session->releaseObjectGroup("console"); +} + +void V8ConsoleMessageStorage::contextDestroyed(int contextId) { + for (size_t i = 0; i < m_messages.size(); ++i) + m_messages[i]->contextDestroyed(contextId); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-console-message.h b/deps/v8_inspector/src/inspector/v8-console-message.h new file mode 100644 index 00000000000000..a6e9eafe2d983c --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-console-message.h @@ -0,0 +1,120 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8CONSOLEMESSAGE_H_ +#define V8_INSPECTOR_V8CONSOLEMESSAGE_H_ + +#include +#include "include/v8.h" +#include "src/inspector/protocol/Console.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/Runtime.h" + +namespace v8_inspector { + +class InspectedContext; +class V8InspectorImpl; +class V8InspectorSessionImpl; +class V8StackTraceImpl; + +enum class V8MessageOrigin { kConsole, kException, kRevokedException }; + +enum class ConsoleAPIType { + kLog, + kDebug, + kInfo, + kError, + kWarning, + kDir, + kDirXML, + kTable, + kTrace, + kStartGroup, + kStartGroupCollapsed, + kEndGroup, + kClear, + kAssert, + kTimeEnd, + kCount +}; + +class V8ConsoleMessage { + public: + ~V8ConsoleMessage(); + + static std::unique_ptr createForConsoleAPI( + double timestamp, ConsoleAPIType, + const std::vector>& arguments, + std::unique_ptr, InspectedContext*); + + static std::unique_ptr createForException( + double timestamp, const String16& detailedMessage, const String16& url, + unsigned lineNumber, unsigned columnNumber, + std::unique_ptr, int scriptId, v8::Isolate*, + const String16& message, int contextId, v8::Local exception, + unsigned exceptionId); + + static std::unique_ptr createForRevokedException( + double timestamp, const String16& message, unsigned revokedExceptionId); + + V8MessageOrigin origin() const; + void reportToFrontend(protocol::Console::Frontend*) const; + void reportToFrontend(protocol::Runtime::Frontend*, V8InspectorSessionImpl*, + bool generatePreview) const; + ConsoleAPIType type() const; + void contextDestroyed(int contextId); + + private: + V8ConsoleMessage(V8MessageOrigin, double timestamp, const String16& message); + + using Arguments = std::vector>>; + std::unique_ptr> + wrapArguments(V8InspectorSessionImpl*, bool generatePreview) const; + std::unique_ptr wrapException( + V8InspectorSessionImpl*, bool generatePreview) const; + void setLocation(const String16& url, unsigned lineNumber, + unsigned columnNumber, std::unique_ptr, + int scriptId); + + V8MessageOrigin m_origin; + double m_timestamp; + String16 m_message; + String16 m_url; + unsigned m_lineNumber; + unsigned m_columnNumber; + std::unique_ptr m_stackTrace; + int m_scriptId; + int m_contextId; + ConsoleAPIType m_type; + unsigned m_exceptionId; + unsigned m_revokedExceptionId; + Arguments m_arguments; + String16 m_detailedMessage; +}; + +class V8ConsoleMessageStorage { + public: + V8ConsoleMessageStorage(V8InspectorImpl*, int contextGroupId); + ~V8ConsoleMessageStorage(); + + int contextGroupId() { return m_contextGroupId; } + int expiredCount() { return m_expiredCount; } + const std::deque>& messages() const { + return m_messages; + } + + void addMessage(std::unique_ptr); + void contextDestroyed(int contextId); + void clear(); + + private: + V8InspectorImpl* m_inspector; + int m_contextGroupId; + int m_expiredCount; + std::deque> m_messages; +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8CONSOLEMESSAGE_H_ diff --git a/deps/v8_inspector/src/inspector/v8-console.cc b/deps/v8_inspector/src/inspector/v8-console.cc new file mode 100644 index 00000000000000..b094de10b0469f --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-console.cc @@ -0,0 +1,919 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-console.h" + +#include "src/base/macros.h" +#include "src/inspector/injected-script.h" +#include "src/inspector/inspected-context.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-console-message.h" +#include "src/inspector/v8-debugger-agent-impl.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-profiler-agent-impl.h" +#include "src/inspector/v8-runtime-agent-impl.h" +#include "src/inspector/v8-stack-trace-impl.h" +#include "src/inspector/v8-value-copier.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +namespace { + +v8::Local inspectedContextPrivateKey(v8::Isolate* isolate) { + return v8::Private::ForApi( + isolate, toV8StringInternalized(isolate, "V8Console#InspectedContext")); +} + +class ConsoleHelper { + public: + explicit ConsoleHelper(const v8::FunctionCallbackInfo& info) + : m_info(info), + m_isolate(info.GetIsolate()), + m_context(info.GetIsolate()->GetCurrentContext()), + m_inspectedContext(nullptr), + m_inspectorClient(nullptr) {} + + v8::Local ensureConsole() { + if (m_console.IsEmpty()) { + DCHECK(!m_info.Data().IsEmpty()); + DCHECK(!m_info.Data()->IsUndefined()); + m_console = m_info.Data().As(); + } + return m_console; + } + + InspectedContext* ensureInspectedContext() { + if (m_inspectedContext) return m_inspectedContext; + v8::Local console = ensureConsole(); + + v8::Local key = inspectedContextPrivateKey(m_isolate); + v8::Local inspectedContextValue; + if (!console->GetPrivate(m_context, key).ToLocal(&inspectedContextValue)) + return nullptr; + DCHECK(inspectedContextValue->IsExternal()); + m_inspectedContext = static_cast( + inspectedContextValue.As()->Value()); + return m_inspectedContext; + } + + V8InspectorClient* ensureDebuggerClient() { + if (m_inspectorClient) return m_inspectorClient; + InspectedContext* inspectedContext = ensureInspectedContext(); + if (!inspectedContext) return nullptr; + m_inspectorClient = inspectedContext->inspector()->client(); + return m_inspectorClient; + } + + void reportCall(ConsoleAPIType type) { + if (!m_info.Length()) return; + std::vector> arguments; + for (int i = 0; i < m_info.Length(); ++i) arguments.push_back(m_info[i]); + reportCall(type, arguments); + } + + void reportCallWithDefaultArgument(ConsoleAPIType type, + const String16& message) { + std::vector> arguments; + for (int i = 0; i < m_info.Length(); ++i) arguments.push_back(m_info[i]); + if (!m_info.Length()) arguments.push_back(toV8String(m_isolate, message)); + reportCall(type, arguments); + } + + void reportCallWithArgument(ConsoleAPIType type, const String16& message) { + std::vector> arguments(1, + toV8String(m_isolate, message)); + reportCall(type, arguments); + } + + void reportCall(ConsoleAPIType type, + const std::vector>& arguments) { + InspectedContext* inspectedContext = ensureInspectedContext(); + if (!inspectedContext) return; + int contextGroupId = inspectedContext->contextGroupId(); + V8InspectorImpl* inspector = inspectedContext->inspector(); + std::unique_ptr message = + V8ConsoleMessage::createForConsoleAPI( + inspector->client()->currentTimeMS(), type, arguments, + inspector->debugger()->captureStackTrace(false), inspectedContext); + inspector->ensureConsoleMessageStorage(contextGroupId) + ->addMessage(std::move(message)); + } + + void reportDeprecatedCall(const char* id, const String16& message) { + if (checkAndSetPrivateFlagOnConsole(id, false)) return; + std::vector> arguments(1, + toV8String(m_isolate, message)); + reportCall(ConsoleAPIType::kWarning, arguments); + } + + bool firstArgToBoolean(bool defaultValue) { + if (m_info.Length() < 1) return defaultValue; + if (m_info[0]->IsBoolean()) return m_info[0].As()->Value(); + return m_info[0]->BooleanValue(m_context).FromMaybe(defaultValue); + } + + String16 firstArgToString(const String16& defaultValue) { + if (m_info.Length() < 1) return defaultValue; + v8::Local titleValue; + if (m_info[0]->IsObject()) { + if (!m_info[0].As()->ObjectProtoToString(m_context).ToLocal( + &titleValue)) + return defaultValue; + } else { + if (!m_info[0]->ToString(m_context).ToLocal(&titleValue)) + return defaultValue; + } + return toProtocolString(titleValue); + } + + v8::MaybeLocal firstArgAsObject() { + if (m_info.Length() < 1 || !m_info[0]->IsObject()) + return v8::MaybeLocal(); + return m_info[0].As(); + } + + v8::MaybeLocal firstArgAsFunction() { + if (m_info.Length() < 1 || !m_info[0]->IsFunction()) + return v8::MaybeLocal(); + return m_info[0].As(); + } + + v8::MaybeLocal privateMap(const char* name) { + v8::Local console = ensureConsole(); + v8::Local privateKey = + v8::Private::ForApi(m_isolate, toV8StringInternalized(m_isolate, name)); + v8::Local mapValue; + if (!console->GetPrivate(m_context, privateKey).ToLocal(&mapValue)) + return v8::MaybeLocal(); + if (mapValue->IsUndefined()) { + v8::Local map = v8::Map::New(m_isolate); + if (!console->SetPrivate(m_context, privateKey, map).FromMaybe(false)) + return v8::MaybeLocal(); + return map; + } + return mapValue->IsMap() ? mapValue.As() + : v8::MaybeLocal(); + } + + int32_t getIntFromMap(v8::Local map, const String16& key, + int32_t defaultValue) { + v8::Local v8Key = toV8String(m_isolate, key); + if (!map->Has(m_context, v8Key).FromMaybe(false)) return defaultValue; + v8::Local intValue; + if (!map->Get(m_context, v8Key).ToLocal(&intValue)) return defaultValue; + return static_cast(intValue.As()->Value()); + } + + void setIntOnMap(v8::Local map, const String16& key, int32_t value) { + v8::Local v8Key = toV8String(m_isolate, key); + if (!map->Set(m_context, v8Key, v8::Integer::New(m_isolate, value)) + .ToLocal(&map)) + return; + } + + double getDoubleFromMap(v8::Local map, const String16& key, + double defaultValue) { + v8::Local v8Key = toV8String(m_isolate, key); + if (!map->Has(m_context, v8Key).FromMaybe(false)) return defaultValue; + v8::Local intValue; + if (!map->Get(m_context, v8Key).ToLocal(&intValue)) return defaultValue; + return intValue.As()->Value(); + } + + void setDoubleOnMap(v8::Local map, const String16& key, + double value) { + v8::Local v8Key = toV8String(m_isolate, key); + if (!map->Set(m_context, v8Key, v8::Number::New(m_isolate, value)) + .ToLocal(&map)) + return; + } + + V8ProfilerAgentImpl* profilerAgent() { + if (V8InspectorSessionImpl* session = currentSession()) { + if (session && session->profilerAgent()->enabled()) + return session->profilerAgent(); + } + return nullptr; + } + + V8DebuggerAgentImpl* debuggerAgent() { + if (V8InspectorSessionImpl* session = currentSession()) { + if (session && session->debuggerAgent()->enabled()) + return session->debuggerAgent(); + } + return nullptr; + } + + V8InspectorSessionImpl* currentSession() { + InspectedContext* inspectedContext = ensureInspectedContext(); + if (!inspectedContext) return nullptr; + return inspectedContext->inspector()->sessionForContextGroup( + inspectedContext->contextGroupId()); + } + + private: + const v8::FunctionCallbackInfo& m_info; + v8::Isolate* m_isolate; + v8::Local m_context; + v8::Local m_console; + InspectedContext* m_inspectedContext; + V8InspectorClient* m_inspectorClient; + + bool checkAndSetPrivateFlagOnConsole(const char* name, bool defaultValue) { + v8::Local console = ensureConsole(); + v8::Local key = + v8::Private::ForApi(m_isolate, toV8StringInternalized(m_isolate, name)); + v8::Local flagValue; + if (!console->GetPrivate(m_context, key).ToLocal(&flagValue)) + return defaultValue; + DCHECK(flagValue->IsUndefined() || flagValue->IsBoolean()); + if (flagValue->IsBoolean()) { + DCHECK(flagValue.As()->Value()); + return true; + } + if (!console->SetPrivate(m_context, key, v8::True(m_isolate)) + .FromMaybe(false)) + return defaultValue; + return false; + } + + DISALLOW_COPY_AND_ASSIGN(ConsoleHelper); +}; + +void returnDataCallback(const v8::FunctionCallbackInfo& info) { + info.GetReturnValue().Set(info.Data()); +} + +void createBoundFunctionProperty(v8::Local context, + v8::Local console, + const char* name, + v8::FunctionCallback callback, + const char* description = nullptr) { + v8::Local funcName = + toV8StringInternalized(context->GetIsolate(), name); + v8::Local func; + if (!v8::Function::New(context, callback, console, 0, + v8::ConstructorBehavior::kThrow) + .ToLocal(&func)) + return; + func->SetName(funcName); + if (description) { + v8::Local returnValue = + toV8String(context->GetIsolate(), description); + v8::Local toStringFunction; + if (v8::Function::New(context, returnDataCallback, returnValue, 0, + v8::ConstructorBehavior::kThrow) + .ToLocal(&toStringFunction)) + createDataProperty(context, func, toV8StringInternalized( + context->GetIsolate(), "toString"), + toStringFunction); + } + createDataProperty(context, console, funcName, func); +} + +} // namespace + +void V8Console::debugCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCall(ConsoleAPIType::kDebug); +} + +void V8Console::errorCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCall(ConsoleAPIType::kError); +} + +void V8Console::infoCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCall(ConsoleAPIType::kInfo); +} + +void V8Console::logCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCall(ConsoleAPIType::kLog); +} + +void V8Console::warnCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCall(ConsoleAPIType::kWarning); +} + +void V8Console::dirCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCall(ConsoleAPIType::kDir); +} + +void V8Console::dirxmlCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCall(ConsoleAPIType::kDirXML); +} + +void V8Console::tableCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCall(ConsoleAPIType::kTable); +} + +void V8Console::traceCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCallWithDefaultArgument(ConsoleAPIType::kTrace, + String16("console.trace")); +} + +void V8Console::groupCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCallWithDefaultArgument(ConsoleAPIType::kStartGroup, + String16("console.group")); +} + +void V8Console::groupCollapsedCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCallWithDefaultArgument( + ConsoleAPIType::kStartGroupCollapsed, String16("console.groupCollapsed")); +} + +void V8Console::groupEndCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCallWithDefaultArgument( + ConsoleAPIType::kEndGroup, String16("console.groupEnd")); +} + +void V8Console::clearCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportCallWithDefaultArgument(ConsoleAPIType::kClear, + String16("console.clear")); +} + +void V8Console::countCallback(const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + + String16 title = helper.firstArgToString(String16()); + String16 identifier; + if (title.isEmpty()) { + std::unique_ptr stackTrace = + V8StackTraceImpl::capture(nullptr, 0, 1); + if (stackTrace && !stackTrace->isEmpty()) { + identifier = toString16(stackTrace->topSourceURL()) + ":" + + String16::fromInteger(stackTrace->topLineNumber()); + } + } else { + identifier = title + "@"; + } + + v8::Local countMap; + if (!helper.privateMap("V8Console#countMap").ToLocal(&countMap)) return; + int32_t count = helper.getIntFromMap(countMap, identifier, 0) + 1; + helper.setIntOnMap(countMap, identifier, count); + helper.reportCallWithArgument(ConsoleAPIType::kCount, + title + ": " + String16::fromInteger(count)); +} + +void V8Console::assertCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + if (helper.firstArgToBoolean(false)) return; + + std::vector> arguments; + for (int i = 1; i < info.Length(); ++i) arguments.push_back(info[i]); + if (info.Length() < 2) + arguments.push_back( + toV8String(info.GetIsolate(), String16("console.assert"))); + helper.reportCall(ConsoleAPIType::kAssert, arguments); + + if (V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent()) + debuggerAgent->breakProgramOnException( + protocol::Debugger::Paused::ReasonEnum::Assert, nullptr); +} + +void V8Console::markTimelineCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportDeprecatedCall("V8Console#markTimelineDeprecated", + "'console.markTimeline' is " + "deprecated. Please use " + "'console.timeStamp' instead."); + timeStampCallback(info); +} + +void V8Console::profileCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + if (V8ProfilerAgentImpl* profilerAgent = helper.profilerAgent()) + profilerAgent->consoleProfile(helper.firstArgToString(String16())); +} + +void V8Console::profileEndCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + if (V8ProfilerAgentImpl* profilerAgent = helper.profilerAgent()) + profilerAgent->consoleProfileEnd(helper.firstArgToString(String16())); +} + +static void timeFunction(const v8::FunctionCallbackInfo& info, + bool timelinePrefix) { + ConsoleHelper helper(info); + if (V8InspectorClient* client = helper.ensureDebuggerClient()) { + String16 protocolTitle = helper.firstArgToString("default"); + if (timelinePrefix) protocolTitle = "Timeline '" + protocolTitle + "'"; + client->consoleTime(toStringView(protocolTitle)); + + v8::Local timeMap; + if (!helper.privateMap("V8Console#timeMap").ToLocal(&timeMap)) return; + helper.setDoubleOnMap(timeMap, protocolTitle, client->currentTimeMS()); + } +} + +static void timeEndFunction(const v8::FunctionCallbackInfo& info, + bool timelinePrefix) { + ConsoleHelper helper(info); + if (V8InspectorClient* client = helper.ensureDebuggerClient()) { + String16 protocolTitle = helper.firstArgToString("default"); + if (timelinePrefix) protocolTitle = "Timeline '" + protocolTitle + "'"; + client->consoleTimeEnd(toStringView(protocolTitle)); + + v8::Local timeMap; + if (!helper.privateMap("V8Console#timeMap").ToLocal(&timeMap)) return; + double elapsed = client->currentTimeMS() - + helper.getDoubleFromMap(timeMap, protocolTitle, 0.0); + String16 message = + protocolTitle + ": " + String16::fromDoublePrecision3(elapsed) + "ms"; + helper.reportCallWithArgument(ConsoleAPIType::kTimeEnd, message); + } +} + +void V8Console::timelineCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportDeprecatedCall( + "V8Console#timeline", + "'console.timeline' is deprecated. Please use 'console.time' instead."); + timeFunction(info, true); +} + +void V8Console::timelineEndCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper(info).reportDeprecatedCall("V8Console#timelineEnd", + "'console.timelineEnd' is " + "deprecated. Please use " + "'console.timeEnd' instead."); + timeEndFunction(info, true); +} + +void V8Console::timeCallback(const v8::FunctionCallbackInfo& info) { + timeFunction(info, false); +} + +void V8Console::timeEndCallback( + const v8::FunctionCallbackInfo& info) { + timeEndFunction(info, false); +} + +void V8Console::timeStampCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + if (V8InspectorClient* client = helper.ensureDebuggerClient()) { + String16 title = helper.firstArgToString(String16()); + client->consoleTimeStamp(toStringView(title)); + } +} + +void V8Console::memoryGetterCallback( + const v8::FunctionCallbackInfo& info) { + if (V8InspectorClient* client = ConsoleHelper(info).ensureDebuggerClient()) { + v8::Local memoryValue; + if (!client + ->memoryInfo(info.GetIsolate(), + info.GetIsolate()->GetCurrentContext()) + .ToLocal(&memoryValue)) + return; + info.GetReturnValue().Set(memoryValue); + } +} + +void V8Console::memorySetterCallback( + const v8::FunctionCallbackInfo& info) { + // We can't make the attribute readonly as it breaks existing code that relies + // on being able to assign to console.memory in strict mode. Instead, the + // setter just ignores the passed value. http://crbug.com/468611 +} + +void V8Console::keysCallback(const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + info.GetReturnValue().Set(v8::Array::New(isolate)); + + ConsoleHelper helper(info); + v8::Local obj; + if (!helper.firstArgAsObject().ToLocal(&obj)) return; + v8::Local names; + if (!obj->GetOwnPropertyNames(isolate->GetCurrentContext()).ToLocal(&names)) + return; + info.GetReturnValue().Set(names); +} + +void V8Console::valuesCallback( + const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + info.GetReturnValue().Set(v8::Array::New(isolate)); + + ConsoleHelper helper(info); + v8::Local obj; + if (!helper.firstArgAsObject().ToLocal(&obj)) return; + v8::Local names; + v8::Local context = isolate->GetCurrentContext(); + if (!obj->GetOwnPropertyNames(context).ToLocal(&names)) return; + v8::Local values = v8::Array::New(isolate, names->Length()); + for (uint32_t i = 0; i < names->Length(); ++i) { + v8::Local key; + if (!names->Get(context, i).ToLocal(&key)) continue; + v8::Local value; + if (!obj->Get(context, key).ToLocal(&value)) continue; + createDataProperty(context, values, i, value); + } + info.GetReturnValue().Set(values); +} + +static void setFunctionBreakpoint(ConsoleHelper& helper, + v8::Local function, + V8DebuggerAgentImpl::BreakpointSource source, + const String16& condition, bool enable) { + V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent(); + if (!debuggerAgent) return; + String16 scriptId = String16::fromInteger(function->ScriptId()); + int lineNumber = function->GetScriptLineNumber(); + int columnNumber = function->GetScriptColumnNumber(); + if (lineNumber == v8::Function::kLineOffsetNotFound || + columnNumber == v8::Function::kLineOffsetNotFound) + return; + if (enable) + debuggerAgent->setBreakpointAt(scriptId, lineNumber, columnNumber, source, + condition); + else + debuggerAgent->removeBreakpointAt(scriptId, lineNumber, columnNumber, + source); +} + +void V8Console::debugFunctionCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + v8::Local function; + if (!helper.firstArgAsFunction().ToLocal(&function)) return; + setFunctionBreakpoint(helper, function, + V8DebuggerAgentImpl::DebugCommandBreakpointSource, + String16(), true); +} + +void V8Console::undebugFunctionCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + v8::Local function; + if (!helper.firstArgAsFunction().ToLocal(&function)) return; + setFunctionBreakpoint(helper, function, + V8DebuggerAgentImpl::DebugCommandBreakpointSource, + String16(), false); +} + +void V8Console::monitorFunctionCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + v8::Local function; + if (!helper.firstArgAsFunction().ToLocal(&function)) return; + v8::Local name = function->GetName(); + if (!name->IsString() || !v8::Local::Cast(name)->Length()) + name = function->GetInferredName(); + String16 functionName = toProtocolStringWithTypeCheck(name); + String16Builder builder; + builder.append("console.log(\"function "); + if (functionName.isEmpty()) + builder.append("(anonymous function)"); + else + builder.append(functionName); + builder.append( + " called\" + (arguments.length > 0 ? \" with arguments: \" + " + "Array.prototype.join.call(arguments, \", \") : \"\")) && false"); + setFunctionBreakpoint(helper, function, + V8DebuggerAgentImpl::MonitorCommandBreakpointSource, + builder.toString(), true); +} + +void V8Console::unmonitorFunctionCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + v8::Local function; + if (!helper.firstArgAsFunction().ToLocal(&function)) return; + setFunctionBreakpoint(helper, function, + V8DebuggerAgentImpl::MonitorCommandBreakpointSource, + String16(), false); +} + +void V8Console::lastEvaluationResultCallback( + const v8::FunctionCallbackInfo& info) { + ConsoleHelper helper(info); + InspectedContext* context = helper.ensureInspectedContext(); + if (!context) return; + if (InjectedScript* injectedScript = context->getInjectedScript()) + info.GetReturnValue().Set(injectedScript->lastEvaluationResult()); +} + +static void inspectImpl(const v8::FunctionCallbackInfo& info, + bool copyToClipboard) { + if (info.Length() < 1) return; + if (!copyToClipboard) info.GetReturnValue().Set(info[0]); + + ConsoleHelper helper(info); + InspectedContext* context = helper.ensureInspectedContext(); + if (!context) return; + InjectedScript* injectedScript = context->getInjectedScript(); + if (!injectedScript) return; + ErrorString errorString; + std::unique_ptr wrappedObject = + injectedScript->wrapObject(&errorString, info[0], "", + false /** forceValueType */, + false /** generatePreview */); + if (!wrappedObject || !errorString.isEmpty()) return; + + std::unique_ptr hints = + protocol::DictionaryValue::create(); + if (copyToClipboard) hints->setBoolean("copyToClipboard", true); + if (V8InspectorSessionImpl* session = helper.currentSession()) + session->runtimeAgent()->inspect(std::move(wrappedObject), + std::move(hints)); +} + +void V8Console::inspectCallback( + const v8::FunctionCallbackInfo& info) { + inspectImpl(info, false); +} + +void V8Console::copyCallback(const v8::FunctionCallbackInfo& info) { + inspectImpl(info, true); +} + +void V8Console::inspectedObject(const v8::FunctionCallbackInfo& info, + unsigned num) { + DCHECK(num < V8InspectorSessionImpl::kInspectedObjectBufferSize); + ConsoleHelper helper(info); + if (V8InspectorSessionImpl* session = helper.currentSession()) { + V8InspectorSession::Inspectable* object = session->inspectedObject(num); + v8::Isolate* isolate = info.GetIsolate(); + if (object) + info.GetReturnValue().Set(object->get(isolate->GetCurrentContext())); + else + info.GetReturnValue().Set(v8::Undefined(isolate)); + } +} + +v8::Local V8Console::createConsole( + InspectedContext* inspectedContext, bool hasMemoryAttribute) { + v8::Local context = inspectedContext->context(); + v8::Context::Scope contextScope(context); + v8::Isolate* isolate = context->GetIsolate(); + v8::MicrotasksScope microtasksScope(isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + + v8::Local console = v8::Object::New(isolate); + bool success = + console->SetPrototype(context, v8::Object::New(isolate)).FromMaybe(false); + DCHECK(success); + USE(success); + + createBoundFunctionProperty(context, console, "debug", + V8Console::debugCallback); + createBoundFunctionProperty(context, console, "error", + V8Console::errorCallback); + createBoundFunctionProperty(context, console, "info", + V8Console::infoCallback); + createBoundFunctionProperty(context, console, "log", V8Console::logCallback); + createBoundFunctionProperty(context, console, "warn", + V8Console::warnCallback); + createBoundFunctionProperty(context, console, "dir", V8Console::dirCallback); + createBoundFunctionProperty(context, console, "dirxml", + V8Console::dirxmlCallback); + createBoundFunctionProperty(context, console, "table", + V8Console::tableCallback); + createBoundFunctionProperty(context, console, "trace", + V8Console::traceCallback); + createBoundFunctionProperty(context, console, "group", + V8Console::groupCallback); + createBoundFunctionProperty(context, console, "groupCollapsed", + V8Console::groupCollapsedCallback); + createBoundFunctionProperty(context, console, "groupEnd", + V8Console::groupEndCallback); + createBoundFunctionProperty(context, console, "clear", + V8Console::clearCallback); + createBoundFunctionProperty(context, console, "count", + V8Console::countCallback); + createBoundFunctionProperty(context, console, "assert", + V8Console::assertCallback); + createBoundFunctionProperty(context, console, "markTimeline", + V8Console::markTimelineCallback); + createBoundFunctionProperty(context, console, "profile", + V8Console::profileCallback); + createBoundFunctionProperty(context, console, "profileEnd", + V8Console::profileEndCallback); + createBoundFunctionProperty(context, console, "timeline", + V8Console::timelineCallback); + createBoundFunctionProperty(context, console, "timelineEnd", + V8Console::timelineEndCallback); + createBoundFunctionProperty(context, console, "time", + V8Console::timeCallback); + createBoundFunctionProperty(context, console, "timeEnd", + V8Console::timeEndCallback); + createBoundFunctionProperty(context, console, "timeStamp", + V8Console::timeStampCallback); + + if (hasMemoryAttribute) + console->SetAccessorProperty( + toV8StringInternalized(isolate, "memory"), + v8::Function::New(context, V8Console::memoryGetterCallback, console, 0, + v8::ConstructorBehavior::kThrow) + .ToLocalChecked(), + v8::Function::New(context, V8Console::memorySetterCallback, + v8::Local(), 0, + v8::ConstructorBehavior::kThrow) + .ToLocalChecked(), + static_cast(v8::None), v8::DEFAULT); + + console->SetPrivate(context, inspectedContextPrivateKey(isolate), + v8::External::New(isolate, inspectedContext)); + return console; +} + +void V8Console::clearInspectedContextIfNeeded(v8::Local context, + v8::Local console) { + v8::Isolate* isolate = context->GetIsolate(); + console->SetPrivate(context, inspectedContextPrivateKey(isolate), + v8::External::New(isolate, nullptr)); +} + +v8::Local V8Console::createCommandLineAPI( + InspectedContext* inspectedContext) { + v8::Local context = inspectedContext->context(); + v8::Isolate* isolate = context->GetIsolate(); + v8::MicrotasksScope microtasksScope(isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + + v8::Local commandLineAPI = v8::Object::New(isolate); + bool success = + commandLineAPI->SetPrototype(context, v8::Null(isolate)).FromMaybe(false); + DCHECK(success); + USE(success); + + createBoundFunctionProperty(context, commandLineAPI, "dir", + V8Console::dirCallback, + "function dir(value) { [Command Line API] }"); + createBoundFunctionProperty(context, commandLineAPI, "dirxml", + V8Console::dirxmlCallback, + "function dirxml(value) { [Command Line API] }"); + createBoundFunctionProperty(context, commandLineAPI, "profile", + V8Console::profileCallback, + "function profile(title) { [Command Line API] }"); + createBoundFunctionProperty( + context, commandLineAPI, "profileEnd", V8Console::profileEndCallback, + "function profileEnd(title) { [Command Line API] }"); + createBoundFunctionProperty(context, commandLineAPI, "clear", + V8Console::clearCallback, + "function clear() { [Command Line API] }"); + createBoundFunctionProperty( + context, commandLineAPI, "table", V8Console::tableCallback, + "function table(data, [columns]) { [Command Line API] }"); + + createBoundFunctionProperty(context, commandLineAPI, "keys", + V8Console::keysCallback, + "function keys(object) { [Command Line API] }"); + createBoundFunctionProperty(context, commandLineAPI, "values", + V8Console::valuesCallback, + "function values(object) { [Command Line API] }"); + createBoundFunctionProperty( + context, commandLineAPI, "debug", V8Console::debugFunctionCallback, + "function debug(function) { [Command Line API] }"); + createBoundFunctionProperty( + context, commandLineAPI, "undebug", V8Console::undebugFunctionCallback, + "function undebug(function) { [Command Line API] }"); + createBoundFunctionProperty( + context, commandLineAPI, "monitor", V8Console::monitorFunctionCallback, + "function monitor(function) { [Command Line API] }"); + createBoundFunctionProperty( + context, commandLineAPI, "unmonitor", + V8Console::unmonitorFunctionCallback, + "function unmonitor(function) { [Command Line API] }"); + createBoundFunctionProperty( + context, commandLineAPI, "inspect", V8Console::inspectCallback, + "function inspect(object) { [Command Line API] }"); + createBoundFunctionProperty(context, commandLineAPI, "copy", + V8Console::copyCallback, + "function copy(value) { [Command Line API] }"); + createBoundFunctionProperty(context, commandLineAPI, "$_", + V8Console::lastEvaluationResultCallback); + createBoundFunctionProperty(context, commandLineAPI, "$0", + V8Console::inspectedObject0); + createBoundFunctionProperty(context, commandLineAPI, "$1", + V8Console::inspectedObject1); + createBoundFunctionProperty(context, commandLineAPI, "$2", + V8Console::inspectedObject2); + createBoundFunctionProperty(context, commandLineAPI, "$3", + V8Console::inspectedObject3); + createBoundFunctionProperty(context, commandLineAPI, "$4", + V8Console::inspectedObject4); + + inspectedContext->inspector()->client()->installAdditionalCommandLineAPI( + context, commandLineAPI); + + commandLineAPI->SetPrivate(context, inspectedContextPrivateKey(isolate), + v8::External::New(isolate, inspectedContext)); + return commandLineAPI; +} + +static bool isCommandLineAPIGetter(const String16& name) { + if (name.length() != 2) return false; + // $0 ... $4, $_ + return name[0] == '$' && + ((name[1] >= '0' && name[1] <= '4') || name[1] == '_'); +} + +void V8Console::CommandLineAPIScope::accessorGetterCallback( + v8::Local name, const v8::PropertyCallbackInfo& info) { + CommandLineAPIScope* scope = static_cast( + info.Data().As()->Value()); + DCHECK(scope); + + v8::Local context = info.GetIsolate()->GetCurrentContext(); + if (scope->m_cleanup) { + bool removed = info.Holder()->Delete(context, name).FromMaybe(false); + DCHECK(removed); + USE(removed); + return; + } + v8::Local commandLineAPI = scope->m_commandLineAPI; + + v8::Local value; + if (!commandLineAPI->Get(context, name).ToLocal(&value)) return; + if (isCommandLineAPIGetter(toProtocolStringWithTypeCheck(name))) { + DCHECK(value->IsFunction()); + v8::MicrotasksScope microtasks(info.GetIsolate(), + v8::MicrotasksScope::kDoNotRunMicrotasks); + if (value.As() + ->Call(context, commandLineAPI, 0, nullptr) + .ToLocal(&value)) + info.GetReturnValue().Set(value); + } else { + info.GetReturnValue().Set(value); + } +} + +void V8Console::CommandLineAPIScope::accessorSetterCallback( + v8::Local name, v8::Local value, + const v8::PropertyCallbackInfo& info) { + CommandLineAPIScope* scope = static_cast( + info.Data().As()->Value()); + v8::Local context = info.GetIsolate()->GetCurrentContext(); + if (!info.Holder()->Delete(context, name).FromMaybe(false)) return; + if (!info.Holder()->CreateDataProperty(context, name, value).FromMaybe(false)) + return; + bool removed = + scope->m_installedMethods->Delete(context, name).FromMaybe(false); + DCHECK(removed); + USE(removed); +} + +V8Console::CommandLineAPIScope::CommandLineAPIScope( + v8::Local context, v8::Local commandLineAPI, + v8::Local global) + : m_context(context), + m_commandLineAPI(commandLineAPI), + m_global(global), + m_installedMethods(v8::Set::New(context->GetIsolate())), + m_cleanup(false) { + v8::Local names; + if (!m_commandLineAPI->GetOwnPropertyNames(context).ToLocal(&names)) return; + v8::Local externalThis = + v8::External::New(context->GetIsolate(), this); + for (uint32_t i = 0; i < names->Length(); ++i) { + v8::Local name; + if (!names->Get(context, i).ToLocal(&name) || !name->IsName()) continue; + if (m_global->Has(context, name).FromMaybe(true)) continue; + if (!m_installedMethods->Add(context, name).ToLocal(&m_installedMethods)) + continue; + if (!m_global + ->SetAccessor(context, v8::Local::Cast(name), + CommandLineAPIScope::accessorGetterCallback, + CommandLineAPIScope::accessorSetterCallback, + externalThis, v8::DEFAULT, v8::DontEnum) + .FromMaybe(false)) { + bool removed = m_installedMethods->Delete(context, name).FromMaybe(false); + DCHECK(removed); + USE(removed); + continue; + } + } +} + +V8Console::CommandLineAPIScope::~CommandLineAPIScope() { + m_cleanup = true; + v8::Local names = m_installedMethods->AsArray(); + for (uint32_t i = 0; i < names->Length(); ++i) { + v8::Local name; + if (!names->Get(m_context, i).ToLocal(&name) || !name->IsName()) continue; + if (name->IsString()) { + v8::Local descriptor; + bool success = m_global + ->GetOwnPropertyDescriptor( + m_context, v8::Local::Cast(name)) + .ToLocal(&descriptor); + DCHECK(success); + USE(success); + } + } +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-console.h b/deps/v8_inspector/src/inspector/v8-console.h new file mode 100644 index 00000000000000..c643d49a4154a4 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-console.h @@ -0,0 +1,119 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8CONSOLE_H_ +#define V8_INSPECTOR_V8CONSOLE_H_ + +#include "src/base/macros.h" + +#include "include/v8.h" + +namespace v8_inspector { + +class InspectedContext; + +// Console API +// https://console.spec.whatwg.org/#console-interface +class V8Console { + public: + static v8::Local createConsole(InspectedContext*, + bool hasMemoryAttribute); + static void clearInspectedContextIfNeeded(v8::Local, + v8::Local console); + static v8::Local createCommandLineAPI(InspectedContext*); + + class CommandLineAPIScope { + public: + CommandLineAPIScope(v8::Local, + v8::Local commandLineAPI, + v8::Local global); + ~CommandLineAPIScope(); + + private: + static void accessorGetterCallback( + v8::Local, const v8::PropertyCallbackInfo&); + static void accessorSetterCallback(v8::Local, + v8::Local, + const v8::PropertyCallbackInfo&); + + v8::Local m_context; + v8::Local m_commandLineAPI; + v8::Local m_global; + v8::Local m_installedMethods; + bool m_cleanup; + + DISALLOW_COPY_AND_ASSIGN(CommandLineAPIScope); + }; + + private: + static void debugCallback(const v8::FunctionCallbackInfo&); + static void errorCallback(const v8::FunctionCallbackInfo&); + static void infoCallback(const v8::FunctionCallbackInfo&); + static void logCallback(const v8::FunctionCallbackInfo&); + static void warnCallback(const v8::FunctionCallbackInfo&); + static void dirCallback(const v8::FunctionCallbackInfo&); + static void dirxmlCallback(const v8::FunctionCallbackInfo&); + static void tableCallback(const v8::FunctionCallbackInfo&); + static void traceCallback(const v8::FunctionCallbackInfo&); + static void groupCallback(const v8::FunctionCallbackInfo&); + static void groupCollapsedCallback( + const v8::FunctionCallbackInfo&); + static void groupEndCallback(const v8::FunctionCallbackInfo&); + static void clearCallback(const v8::FunctionCallbackInfo&); + static void countCallback(const v8::FunctionCallbackInfo&); + static void assertCallback(const v8::FunctionCallbackInfo&); + static void markTimelineCallback(const v8::FunctionCallbackInfo&); + static void profileCallback(const v8::FunctionCallbackInfo&); + static void profileEndCallback(const v8::FunctionCallbackInfo&); + static void timelineCallback(const v8::FunctionCallbackInfo&); + static void timelineEndCallback(const v8::FunctionCallbackInfo&); + static void timeCallback(const v8::FunctionCallbackInfo&); + static void timeEndCallback(const v8::FunctionCallbackInfo&); + static void timeStampCallback(const v8::FunctionCallbackInfo&); + // TODO(foolip): There is no spec for the Memory Info API, see blink-dev: + // https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ + static void memoryGetterCallback(const v8::FunctionCallbackInfo&); + static void memorySetterCallback(const v8::FunctionCallbackInfo&); + + // CommandLineAPI + static void keysCallback(const v8::FunctionCallbackInfo&); + static void valuesCallback(const v8::FunctionCallbackInfo&); + static void debugFunctionCallback(const v8::FunctionCallbackInfo&); + static void undebugFunctionCallback( + const v8::FunctionCallbackInfo&); + static void monitorFunctionCallback( + const v8::FunctionCallbackInfo&); + static void unmonitorFunctionCallback( + const v8::FunctionCallbackInfo&); + static void lastEvaluationResultCallback( + const v8::FunctionCallbackInfo&); + static void inspectCallback(const v8::FunctionCallbackInfo&); + static void copyCallback(const v8::FunctionCallbackInfo&); + static void inspectedObject(const v8::FunctionCallbackInfo&, + unsigned num); + static void inspectedObject0( + const v8::FunctionCallbackInfo& info) { + inspectedObject(info, 0); + } + static void inspectedObject1( + const v8::FunctionCallbackInfo& info) { + inspectedObject(info, 1); + } + static void inspectedObject2( + const v8::FunctionCallbackInfo& info) { + inspectedObject(info, 2); + } + static void inspectedObject3( + const v8::FunctionCallbackInfo& info) { + inspectedObject(info, 3); + } + static void inspectedObject4( + const v8::FunctionCallbackInfo& info) { + inspectedObject(info, 4); + } +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8CONSOLE_H_ diff --git a/deps/v8_inspector/src/inspector/v8-debugger-agent-impl.cc b/deps/v8_inspector/src/inspector/v8-debugger-agent-impl.cc new file mode 100644 index 00000000000000..80e261119e8dad --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-debugger-agent-impl.cc @@ -0,0 +1,1255 @@ +// Copyright 2015 the V8 project 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 "src/inspector/v8-debugger-agent-impl.h" + +#include + +#include "src/inspector/injected-script.h" +#include "src/inspector/inspected-context.h" +#include "src/inspector/java-script-call-frame.h" +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/remote-object-id.h" +#include "src/inspector/script-breakpoint.h" +#include "src/inspector/search-util.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-debugger-script.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-regex.h" +#include "src/inspector/v8-runtime-agent-impl.h" +#include "src/inspector/v8-stack-trace-impl.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +using protocol::Array; +using protocol::Maybe; +using protocol::Debugger::BreakpointId; +using protocol::Debugger::CallFrame; +using protocol::Runtime::ExceptionDetails; +using protocol::Runtime::ScriptId; +using protocol::Runtime::StackTrace; +using protocol::Runtime::RemoteObject; + +namespace DebuggerAgentState { +static const char javaScriptBreakpoints[] = "javaScriptBreakopints"; +static const char pauseOnExceptionsState[] = "pauseOnExceptionsState"; +static const char asyncCallStackDepth[] = "asyncCallStackDepth"; +static const char blackboxPattern[] = "blackboxPattern"; +static const char debuggerEnabled[] = "debuggerEnabled"; + +// Breakpoint properties. +static const char url[] = "url"; +static const char isRegex[] = "isRegex"; +static const char lineNumber[] = "lineNumber"; +static const char columnNumber[] = "columnNumber"; +static const char condition[] = "condition"; +static const char skipAllPauses[] = "skipAllPauses"; + +} // namespace DebuggerAgentState + +static const int maxSkipStepFrameCount = 128; +static const char backtraceObjectGroup[] = "backtrace"; + +static String16 breakpointIdSuffix( + V8DebuggerAgentImpl::BreakpointSource source) { + switch (source) { + case V8DebuggerAgentImpl::UserBreakpointSource: + break; + case V8DebuggerAgentImpl::DebugCommandBreakpointSource: + return ":debug"; + case V8DebuggerAgentImpl::MonitorCommandBreakpointSource: + return ":monitor"; + } + return String16(); +} + +static String16 generateBreakpointId( + const String16& scriptId, int lineNumber, int columnNumber, + V8DebuggerAgentImpl::BreakpointSource source) { + return scriptId + ":" + String16::fromInteger(lineNumber) + ":" + + String16::fromInteger(columnNumber) + breakpointIdSuffix(source); +} + +static bool positionComparator(const std::pair& a, + const std::pair& b) { + if (a.first != b.first) return a.first < b.first; + return a.second < b.second; +} + +static bool hasInternalError(ErrorString* errorString, bool hasError) { + if (hasError) *errorString = "Internal error"; + return hasError; +} + +static std::unique_ptr buildProtocolLocation( + const String16& scriptId, int lineNumber, int columnNumber) { + return protocol::Debugger::Location::create() + .setScriptId(scriptId) + .setLineNumber(lineNumber) + .setColumnNumber(columnNumber) + .build(); +} + +V8DebuggerAgentImpl::V8DebuggerAgentImpl( + V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, + protocol::DictionaryValue* state) + : m_inspector(session->inspector()), + m_debugger(m_inspector->debugger()), + m_session(session), + m_enabled(false), + m_state(state), + m_frontend(frontendChannel), + m_isolate(m_inspector->isolate()), + m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other), + m_scheduledDebuggerStep(NoStep), + m_skipNextDebuggerStepOut(false), + m_javaScriptPauseScheduled(false), + m_steppingFromFramework(false), + m_pausingOnNativeEvent(false), + m_skippedStepFrameCount(0), + m_recursionLevelForStepOut(0), + m_recursionLevelForStepFrame(0), + m_skipAllPauses(false) { + clearBreakDetails(); +} + +V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} + +bool V8DebuggerAgentImpl::checkEnabled(ErrorString* errorString) { + if (enabled()) return true; + *errorString = "Debugger agent is not enabled"; + return false; +} + +void V8DebuggerAgentImpl::enable() { + // m_inspector->addListener may result in reporting all parsed scripts to + // the agent so it should already be in enabled state by then. + m_enabled = true; + m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); + m_debugger->enable(); + + std::vector> compiledScripts; + m_debugger->getCompiledScripts(m_session->contextGroupId(), compiledScripts); + for (size_t i = 0; i < compiledScripts.size(); i++) + didParseSource(std::move(compiledScripts[i]), true); + + // FIXME(WK44513): breakpoints activated flag should be synchronized between + // all front-ends + m_debugger->setBreakpointsActivated(true); +} + +bool V8DebuggerAgentImpl::enabled() { return m_enabled; } + +void V8DebuggerAgentImpl::enable(ErrorString* errorString) { + if (enabled()) return; + + if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) { + *errorString = "Script execution is prohibited"; + return; + } + + enable(); +} + +void V8DebuggerAgentImpl::disable(ErrorString*) { + if (!enabled()) return; + + m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, + protocol::DictionaryValue::create()); + m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, + V8Debugger::DontPauseOnExceptions); + m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); + + if (!m_pausedContext.IsEmpty()) m_debugger->continueProgram(); + m_debugger->disable(); + m_pausedContext.Reset(); + JavaScriptCallFrames emptyCallFrames; + m_pausedCallFrames.swap(emptyCallFrames); + m_scripts.clear(); + m_blackboxedPositions.clear(); + m_breakpointIdToDebuggerBreakpointIds.clear(); + m_debugger->setAsyncCallStackDepth(this, 0); + m_continueToLocationBreakpointId = String16(); + clearBreakDetails(); + m_scheduledDebuggerStep = NoStep; + m_skipNextDebuggerStepOut = false; + m_javaScriptPauseScheduled = false; + m_steppingFromFramework = false; + m_pausingOnNativeEvent = false; + m_skippedStepFrameCount = 0; + m_recursionLevelForStepFrame = 0; + m_skipAllPauses = false; + m_blackboxPattern = nullptr; + m_state->remove(DebuggerAgentState::blackboxPattern); + m_enabled = false; + m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); +} + +void V8DebuggerAgentImpl::restore() { + DCHECK(!m_enabled); + if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) + return; + if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) + return; + + enable(); + ErrorString error; + + int pauseState = V8Debugger::DontPauseOnExceptions; + m_state->getInteger(DebuggerAgentState::pauseOnExceptionsState, &pauseState); + setPauseOnExceptionsImpl(&error, pauseState); + DCHECK(error.isEmpty()); + + m_skipAllPauses = + m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false); + + int asyncCallStackDepth = 0; + m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, + &asyncCallStackDepth); + m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); + + String16 blackboxPattern; + if (m_state->getString(DebuggerAgentState::blackboxPattern, + &blackboxPattern)) { + if (!setBlackboxPattern(&error, blackboxPattern)) UNREACHABLE(); + } +} + +void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, + bool active) { + if (!checkEnabled(errorString)) return; + m_debugger->setBreakpointsActivated(active); +} + +void V8DebuggerAgentImpl::setSkipAllPauses(ErrorString*, bool skip) { + m_skipAllPauses = skip; + m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses); +} + +static std::unique_ptr +buildObjectForBreakpointCookie(const String16& url, int lineNumber, + int columnNumber, const String16& condition, + bool isRegex) { + std::unique_ptr breakpointObject = + protocol::DictionaryValue::create(); + breakpointObject->setString(DebuggerAgentState::url, url); + breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); + breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); + breakpointObject->setString(DebuggerAgentState::condition, condition); + breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex); + return breakpointObject; +} + +static bool matches(V8InspectorImpl* inspector, const String16& url, + const String16& pattern, bool isRegex) { + if (isRegex) { + V8Regex regex(inspector, pattern, true); + return regex.match(url) != -1; + } + return url == pattern; +} + +void V8DebuggerAgentImpl::setBreakpointByUrl( + ErrorString* errorString, int lineNumber, + const Maybe& optionalURL, const Maybe& optionalURLRegex, + const Maybe& optionalColumnNumber, + const Maybe& optionalCondition, String16* outBreakpointId, + std::unique_ptr>* locations) { + *locations = Array::create(); + if (optionalURL.isJust() == optionalURLRegex.isJust()) { + *errorString = "Either url or urlRegex must be specified."; + return; + } + + String16 url = optionalURL.isJust() ? optionalURL.fromJust() + : optionalURLRegex.fromJust(); + int columnNumber = 0; + if (optionalColumnNumber.isJust()) { + columnNumber = optionalColumnNumber.fromJust(); + if (columnNumber < 0) { + *errorString = "Incorrect column number"; + return; + } + } + String16 condition = optionalCondition.fromMaybe(""); + bool isRegex = optionalURLRegex.isJust(); + + String16 breakpointId = (isRegex ? "/" + url + "/" : url) + ":" + + String16::fromInteger(lineNumber) + ":" + + String16::fromInteger(columnNumber); + protocol::DictionaryValue* breakpointsCookie = + m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); + if (!breakpointsCookie) { + std::unique_ptr newValue = + protocol::DictionaryValue::create(); + breakpointsCookie = newValue.get(); + m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, + std::move(newValue)); + } + if (breakpointsCookie->get(breakpointId)) { + *errorString = "Breakpoint at specified location already exists."; + return; + } + + breakpointsCookie->setObject( + breakpointId, buildObjectForBreakpointCookie( + url, lineNumber, columnNumber, condition, isRegex)); + + ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); + for (const auto& script : m_scripts) { + if (!matches(m_inspector, script.second->sourceURL(), url, isRegex)) + continue; + std::unique_ptr location = resolveBreakpoint( + breakpointId, script.first, breakpoint, UserBreakpointSource); + if (location) (*locations)->addItem(std::move(location)); + } + + *outBreakpointId = breakpointId; +} + +static bool parseLocation( + ErrorString* errorString, + std::unique_ptr location, String16* scriptId, + int* lineNumber, int* columnNumber) { + *scriptId = location->getScriptId(); + *lineNumber = location->getLineNumber(); + *columnNumber = location->getColumnNumber(0); + return true; +} + +void V8DebuggerAgentImpl::setBreakpoint( + ErrorString* errorString, + std::unique_ptr location, + const Maybe& optionalCondition, String16* outBreakpointId, + std::unique_ptr* actualLocation) { + String16 scriptId; + int lineNumber; + int columnNumber; + + if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, + &columnNumber)) + return; + + String16 condition = optionalCondition.fromMaybe(""); + + String16 breakpointId = generateBreakpointId( + scriptId, lineNumber, columnNumber, UserBreakpointSource); + if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != + m_breakpointIdToDebuggerBreakpointIds.end()) { + *errorString = "Breakpoint at specified location already exists."; + return; + } + ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); + *actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, + UserBreakpointSource); + if (*actualLocation) + *outBreakpointId = breakpointId; + else + *errorString = "Could not resolve breakpoint"; +} + +void V8DebuggerAgentImpl::removeBreakpoint(ErrorString* errorString, + const String16& breakpointId) { + if (!checkEnabled(errorString)) return; + protocol::DictionaryValue* breakpointsCookie = + m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); + if (breakpointsCookie) breakpointsCookie->remove(breakpointId); + removeBreakpoint(breakpointId); +} + +void V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { + DCHECK(enabled()); + BreakpointIdToDebuggerBreakpointIdsMap::iterator + debuggerBreakpointIdsIterator = + m_breakpointIdToDebuggerBreakpointIds.find(breakpointId); + if (debuggerBreakpointIdsIterator == + m_breakpointIdToDebuggerBreakpointIds.end()) + return; + const std::vector& ids = debuggerBreakpointIdsIterator->second; + for (size_t i = 0; i < ids.size(); ++i) { + const String16& debuggerBreakpointId = ids[i]; + + m_debugger->removeBreakpoint(debuggerBreakpointId); + m_serverBreakpoints.erase(debuggerBreakpointId); + } + m_breakpointIdToDebuggerBreakpointIds.erase(breakpointId); +} + +void V8DebuggerAgentImpl::continueToLocation( + ErrorString* errorString, + std::unique_ptr location) { + if (!checkEnabled(errorString)) return; + if (!m_continueToLocationBreakpointId.isEmpty()) { + m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); + m_continueToLocationBreakpointId = ""; + } + + String16 scriptId; + int lineNumber; + int columnNumber; + + if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, + &columnNumber)) + return; + + ScriptBreakpoint breakpoint(lineNumber, columnNumber, ""); + m_continueToLocationBreakpointId = m_debugger->setBreakpoint( + scriptId, breakpoint, &lineNumber, &columnNumber); + resume(errorString); +} + +bool V8DebuggerAgentImpl::isCurrentCallStackEmptyOrBlackboxed() { + DCHECK(enabled()); + JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(); + for (size_t index = 0; index < callFrames.size(); ++index) { + if (!isCallFrameWithUnknownScriptOrBlackboxed(callFrames[index].get())) + return false; + } + return true; +} + +bool V8DebuggerAgentImpl::isTopPausedCallFrameBlackboxed() { + DCHECK(enabled()); + JavaScriptCallFrame* frame = + m_pausedCallFrames.size() ? m_pausedCallFrames[0].get() : nullptr; + return isCallFrameWithUnknownScriptOrBlackboxed(frame); +} + +bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed( + JavaScriptCallFrame* frame) { + if (!frame) return true; + ScriptsMap::iterator it = + m_scripts.find(String16::fromInteger(frame->sourceID())); + if (it == m_scripts.end()) { + // Unknown scripts are blackboxed. + return true; + } + if (m_blackboxPattern) { + const String16& scriptSourceURL = it->second->sourceURL(); + if (!scriptSourceURL.isEmpty() && + m_blackboxPattern->match(scriptSourceURL) != -1) + return true; + } + auto itBlackboxedPositions = + m_blackboxedPositions.find(String16::fromInteger(frame->sourceID())); + if (itBlackboxedPositions == m_blackboxedPositions.end()) return false; + + const std::vector>& ranges = + itBlackboxedPositions->second; + auto itRange = std::lower_bound( + ranges.begin(), ranges.end(), + std::make_pair(frame->line(), frame->column()), positionComparator); + // Ranges array contains positions in script where blackbox state is changed. + // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is + // blackboxed... + return std::distance(ranges.begin(), itRange) % 2; +} + +V8DebuggerAgentImpl::SkipPauseRequest +V8DebuggerAgentImpl::shouldSkipExceptionPause( + JavaScriptCallFrame* topCallFrame) { + if (m_steppingFromFramework) return RequestNoSkip; + if (isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) + return RequestContinue; + return RequestNoSkip; +} + +V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipStepPause( + JavaScriptCallFrame* topCallFrame) { + if (m_steppingFromFramework) return RequestNoSkip; + + if (m_skipNextDebuggerStepOut) { + m_skipNextDebuggerStepOut = false; + if (m_scheduledDebuggerStep == StepOut) return RequestStepOut; + } + + if (!isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) + return RequestNoSkip; + + if (m_skippedStepFrameCount >= maxSkipStepFrameCount) return RequestStepOut; + + if (!m_skippedStepFrameCount) m_recursionLevelForStepFrame = 1; + + ++m_skippedStepFrameCount; + return RequestStepFrame; +} + +std::unique_ptr +V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, + const String16& scriptId, + const ScriptBreakpoint& breakpoint, + BreakpointSource source) { + DCHECK(enabled()); + // FIXME: remove these checks once crbug.com/520702 is resolved. + CHECK(!breakpointId.isEmpty()); + CHECK(!scriptId.isEmpty()); + ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); + if (scriptIterator == m_scripts.end()) return nullptr; + if (breakpoint.lineNumber < scriptIterator->second->startLine() || + scriptIterator->second->endLine() < breakpoint.lineNumber) + return nullptr; + + int actualLineNumber; + int actualColumnNumber; + String16 debuggerBreakpointId = m_debugger->setBreakpoint( + scriptId, breakpoint, &actualLineNumber, &actualColumnNumber); + if (debuggerBreakpointId.isEmpty()) return nullptr; + + m_serverBreakpoints[debuggerBreakpointId] = + std::make_pair(breakpointId, source); + CHECK(!breakpointId.isEmpty()); + + m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( + debuggerBreakpointId); + return buildProtocolLocation(scriptId, actualLineNumber, actualColumnNumber); +} + +void V8DebuggerAgentImpl::searchInContent( + ErrorString* error, const String16& scriptId, const String16& query, + const Maybe& optionalCaseSensitive, + const Maybe& optionalIsRegex, + std::unique_ptr>* results) { + v8::HandleScope handles(m_isolate); + ScriptsMap::iterator it = m_scripts.find(scriptId); + if (it == m_scripts.end()) { + *error = String16("No script for id: " + scriptId); + return; + } + + std::vector> matches = + searchInTextByLinesImpl(m_session, + toProtocolString(it->second->source(m_isolate)), + query, optionalCaseSensitive.fromMaybe(false), + optionalIsRegex.fromMaybe(false)); + *results = protocol::Array::create(); + for (size_t i = 0; i < matches.size(); ++i) + (*results)->addItem(std::move(matches[i])); +} + +void V8DebuggerAgentImpl::setScriptSource( + ErrorString* errorString, const String16& scriptId, + const String16& newContent, const Maybe& dryRun, + Maybe>* newCallFrames, + Maybe* stackChanged, Maybe* asyncStackTrace, + Maybe* optOutCompileError) { + if (!checkEnabled(errorString)) return; + + v8::HandleScope handles(m_isolate); + v8::Local newSource = toV8String(m_isolate, newContent); + if (!m_debugger->setScriptSource(scriptId, newSource, dryRun.fromMaybe(false), + errorString, optOutCompileError, + &m_pausedCallFrames, stackChanged)) + return; + + ScriptsMap::iterator it = m_scripts.find(scriptId); + if (it != m_scripts.end()) it->second->setSource(m_isolate, newSource); + + std::unique_ptr> callFrames = currentCallFrames(errorString); + if (!callFrames) return; + *newCallFrames = std::move(callFrames); + *asyncStackTrace = currentAsyncStackTrace(); +} + +void V8DebuggerAgentImpl::restartFrame( + ErrorString* errorString, const String16& callFrameId, + std::unique_ptr>* newCallFrames, + Maybe* asyncStackTrace) { + if (!assertPaused(errorString)) return; + InjectedScript::CallFrameScope scope( + errorString, m_inspector, m_session->contextGroupId(), callFrameId); + if (!scope.initialize()) return; + if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { + *errorString = "Could not find call frame with given id"; + return; + } + + v8::Local resultValue; + v8::Local result; + if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal( + &resultValue) || + scope.tryCatch().HasCaught() || + !resultValue->ToBoolean(scope.context()).ToLocal(&result) || + !result->Value()) { + *errorString = "Internal error"; + return; + } + JavaScriptCallFrames frames = m_debugger->currentCallFrames(); + m_pausedCallFrames.swap(frames); + + *newCallFrames = currentCallFrames(errorString); + if (!*newCallFrames) return; + *asyncStackTrace = currentAsyncStackTrace(); +} + +void V8DebuggerAgentImpl::getScriptSource(ErrorString* error, + const String16& scriptId, + String16* scriptSource) { + if (!checkEnabled(error)) return; + ScriptsMap::iterator it = m_scripts.find(scriptId); + if (it == m_scripts.end()) { + *error = "No script for id: " + scriptId; + return; + } + v8::HandleScope handles(m_isolate); + *scriptSource = toProtocolString(it->second->source(m_isolate)); +} + +void V8DebuggerAgentImpl::schedulePauseOnNextStatement( + const String16& breakReason, + std::unique_ptr data) { + if (!enabled() || m_scheduledDebuggerStep == StepInto || + m_javaScriptPauseScheduled || m_debugger->isPaused() || + !m_debugger->breakpointsActivated()) + return; + m_breakReason = breakReason; + m_breakAuxData = std::move(data); + m_pausingOnNativeEvent = true; + m_skipNextDebuggerStepOut = false; + m_debugger->setPauseOnNextStatement(true); +} + +void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() { + DCHECK(enabled()); + if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || + m_debugger->isPaused()) + return; + clearBreakDetails(); + m_pausingOnNativeEvent = false; + m_skippedStepFrameCount = 0; + m_recursionLevelForStepFrame = 0; + m_debugger->setPauseOnNextStatement(true); +} + +void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { + if (m_javaScriptPauseScheduled || m_debugger->isPaused()) return; + clearBreakDetails(); + m_pausingOnNativeEvent = false; + m_debugger->setPauseOnNextStatement(false); +} + +void V8DebuggerAgentImpl::pause(ErrorString* errorString) { + if (!checkEnabled(errorString)) return; + if (m_javaScriptPauseScheduled || m_debugger->isPaused()) return; + clearBreakDetails(); + m_javaScriptPauseScheduled = true; + m_scheduledDebuggerStep = NoStep; + m_skippedStepFrameCount = 0; + m_steppingFromFramework = false; + m_debugger->setPauseOnNextStatement(true); +} + +void V8DebuggerAgentImpl::resume(ErrorString* errorString) { + if (!assertPaused(errorString)) return; + m_scheduledDebuggerStep = NoStep; + m_steppingFromFramework = false; + m_session->releaseObjectGroup(backtraceObjectGroup); + m_debugger->continueProgram(); +} + +void V8DebuggerAgentImpl::stepOver(ErrorString* errorString) { + if (!assertPaused(errorString)) return; + // StepOver at function return point should fallback to StepInto. + JavaScriptCallFrame* frame = + !m_pausedCallFrames.empty() ? m_pausedCallFrames[0].get() : nullptr; + if (frame && frame->isAtReturn()) { + stepInto(errorString); + return; + } + m_scheduledDebuggerStep = StepOver; + m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); + m_session->releaseObjectGroup(backtraceObjectGroup); + m_debugger->stepOverStatement(); +} + +void V8DebuggerAgentImpl::stepInto(ErrorString* errorString) { + if (!assertPaused(errorString)) return; + m_scheduledDebuggerStep = StepInto; + m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); + m_session->releaseObjectGroup(backtraceObjectGroup); + m_debugger->stepIntoStatement(); +} + +void V8DebuggerAgentImpl::stepOut(ErrorString* errorString) { + if (!assertPaused(errorString)) return; + m_scheduledDebuggerStep = StepOut; + m_skipNextDebuggerStepOut = false; + m_recursionLevelForStepOut = 1; + m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); + m_session->releaseObjectGroup(backtraceObjectGroup); + m_debugger->stepOutOfFunction(); +} + +void V8DebuggerAgentImpl::setPauseOnExceptions( + ErrorString* errorString, const String16& stringPauseState) { + if (!checkEnabled(errorString)) return; + V8Debugger::PauseOnExceptionsState pauseState; + if (stringPauseState == "none") { + pauseState = V8Debugger::DontPauseOnExceptions; + } else if (stringPauseState == "all") { + pauseState = V8Debugger::PauseOnAllExceptions; + } else if (stringPauseState == "uncaught") { + pauseState = V8Debugger::PauseOnUncaughtExceptions; + } else { + *errorString = "Unknown pause on exceptions mode: " + stringPauseState; + return; + } + setPauseOnExceptionsImpl(errorString, pauseState); +} + +void V8DebuggerAgentImpl::setPauseOnExceptionsImpl(ErrorString* errorString, + int pauseState) { + m_debugger->setPauseOnExceptionsState( + static_cast(pauseState)); + if (m_debugger->getPauseOnExceptionsState() != pauseState) + *errorString = "Internal error. Could not change pause on exceptions state"; + else + m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); +} + +void V8DebuggerAgentImpl::evaluateOnCallFrame( + ErrorString* errorString, const String16& callFrameId, + const String16& expression, const Maybe& objectGroup, + const Maybe& includeCommandLineAPI, const Maybe& silent, + const Maybe& returnByValue, const Maybe& generatePreview, + std::unique_ptr* result, + Maybe* exceptionDetails) { + if (!assertPaused(errorString)) return; + InjectedScript::CallFrameScope scope( + errorString, m_inspector, m_session->contextGroupId(), callFrameId); + if (!scope.initialize()) return; + if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { + *errorString = "Could not find call frame with given id"; + return; + } + + if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI()) + return; + if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); + + v8::MaybeLocal maybeResultValue = + m_pausedCallFrames[scope.frameOrdinal()]->evaluate( + toV8String(m_isolate, expression)); + + // Re-initialize after running client's code, as it could have destroyed + // context or session. + if (!scope.initialize()) return; + scope.injectedScript()->wrapEvaluateResult( + errorString, maybeResultValue, scope.tryCatch(), + objectGroup.fromMaybe(""), returnByValue.fromMaybe(false), + generatePreview.fromMaybe(false), result, exceptionDetails); +} + +void V8DebuggerAgentImpl::setVariableValue( + ErrorString* errorString, int scopeNumber, const String16& variableName, + std::unique_ptr newValueArgument, + const String16& callFrameId) { + if (!checkEnabled(errorString)) return; + if (!assertPaused(errorString)) return; + InjectedScript::CallFrameScope scope( + errorString, m_inspector, m_session->contextGroupId(), callFrameId); + if (!scope.initialize()) return; + + v8::Local newValue; + if (!scope.injectedScript() + ->resolveCallArgument(errorString, newValueArgument.get()) + .ToLocal(&newValue)) + return; + + if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { + *errorString = "Could not find call frame with given id"; + return; + } + v8::MaybeLocal result = + m_pausedCallFrames[scope.frameOrdinal()]->setVariableValue( + scopeNumber, toV8String(m_isolate, variableName), newValue); + if (scope.tryCatch().HasCaught() || result.IsEmpty()) { + *errorString = "Internal error"; + return; + } +} + +void V8DebuggerAgentImpl::setAsyncCallStackDepth(ErrorString* errorString, + int depth) { + if (!checkEnabled(errorString)) return; + m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, depth); + m_debugger->setAsyncCallStackDepth(this, depth); +} + +void V8DebuggerAgentImpl::setBlackboxPatterns( + ErrorString* errorString, + std::unique_ptr> patterns) { + if (!patterns->length()) { + m_blackboxPattern = nullptr; + m_state->remove(DebuggerAgentState::blackboxPattern); + return; + } + + String16Builder patternBuilder; + patternBuilder.append('('); + for (size_t i = 0; i < patterns->length() - 1; ++i) { + patternBuilder.append(patterns->get(i)); + patternBuilder.append("|"); + } + patternBuilder.append(patterns->get(patterns->length() - 1)); + patternBuilder.append(')'); + String16 pattern = patternBuilder.toString(); + if (!setBlackboxPattern(errorString, pattern)) return; + m_state->setString(DebuggerAgentState::blackboxPattern, pattern); +} + +bool V8DebuggerAgentImpl::setBlackboxPattern(ErrorString* errorString, + const String16& pattern) { + std::unique_ptr regex(new V8Regex( + m_inspector, pattern, true /** caseSensitive */, false /** multiline */)); + if (!regex->isValid()) { + *errorString = "Pattern parser error: " + regex->errorMessage(); + return false; + } + m_blackboxPattern = std::move(regex); + return true; +} + +void V8DebuggerAgentImpl::setBlackboxedRanges( + ErrorString* error, const String16& scriptId, + std::unique_ptr> + inPositions) { + if (m_scripts.find(scriptId) == m_scripts.end()) { + *error = "No script with passed id."; + return; + } + + if (!inPositions->length()) { + m_blackboxedPositions.erase(scriptId); + return; + } + + std::vector> positions; + positions.reserve(inPositions->length()); + for (size_t i = 0; i < inPositions->length(); ++i) { + protocol::Debugger::ScriptPosition* position = inPositions->get(i); + if (position->getLineNumber() < 0) { + *error = "Position missing 'line' or 'line' < 0."; + return; + } + if (position->getColumnNumber() < 0) { + *error = "Position missing 'column' or 'column' < 0."; + return; + } + positions.push_back( + std::make_pair(position->getLineNumber(), position->getColumnNumber())); + } + + for (size_t i = 1; i < positions.size(); ++i) { + if (positions[i - 1].first < positions[i].first) continue; + if (positions[i - 1].first == positions[i].first && + positions[i - 1].second < positions[i].second) + continue; + *error = + "Input positions array is not sorted or contains duplicate values."; + return; + } + + m_blackboxedPositions[scriptId] = positions; +} + +void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { + changeJavaScriptRecursionLevel(+1); + // Fast return. + if (m_scheduledDebuggerStep != StepInto) return; + schedulePauseOnNextStatementIfSteppingInto(); +} + +void V8DebuggerAgentImpl::didExecuteScript() { + changeJavaScriptRecursionLevel(-1); +} + +void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { + if (m_javaScriptPauseScheduled && !m_skipAllPauses && + !m_debugger->isPaused()) { + // Do not ever loose user's pause request until we have actually paused. + m_debugger->setPauseOnNextStatement(true); + } + if (m_scheduledDebuggerStep == StepOut) { + m_recursionLevelForStepOut += step; + if (!m_recursionLevelForStepOut) { + // When StepOut crosses a task boundary (i.e. js -> c++) from where it was + // requested, + // switch stepping to step into a next JS task, as if we exited to a + // blackboxed framework. + m_scheduledDebuggerStep = StepInto; + m_skipNextDebuggerStepOut = false; + } + } + if (m_recursionLevelForStepFrame) { + m_recursionLevelForStepFrame += step; + if (!m_recursionLevelForStepFrame) { + // We have walked through a blackboxed framework and got back to where we + // started. + // If there was no stepping scheduled, we should cancel the stepping + // explicitly, + // since there may be a scheduled StepFrame left. + // Otherwise, if we were stepping in/over, the StepFrame will stop at the + // right location, + // whereas if we were stepping out, we should continue doing so after + // debugger pauses + // from the old StepFrame. + m_skippedStepFrameCount = 0; + if (m_scheduledDebuggerStep == NoStep) + m_debugger->clearStepping(); + else if (m_scheduledDebuggerStep == StepOut) + m_skipNextDebuggerStepOut = true; + } + } +} + +std::unique_ptr> V8DebuggerAgentImpl::currentCallFrames( + ErrorString* errorString) { + if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) + return Array::create(); + ErrorString ignored; + v8::HandleScope handles(m_isolate); + v8::Local debuggerContext = + v8::Debug::GetDebugContext(m_isolate); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local objects = v8::Array::New(m_isolate); + + for (size_t frameOrdinal = 0; frameOrdinal < m_pausedCallFrames.size(); + ++frameOrdinal) { + const std::unique_ptr& currentCallFrame = + m_pausedCallFrames[frameOrdinal]; + + v8::Local details = currentCallFrame->details(); + if (hasInternalError(errorString, details.IsEmpty())) + return Array::create(); + + int contextId = currentCallFrame->contextId(); + InjectedScript* injectedScript = + contextId ? m_session->findInjectedScript(&ignored, contextId) + : nullptr; + + String16 callFrameId = + RemoteCallFrameId::serialize(contextId, static_cast(frameOrdinal)); + if (hasInternalError( + errorString, + !details + ->Set(debuggerContext, + toV8StringInternalized(m_isolate, "callFrameId"), + toV8String(m_isolate, callFrameId)) + .FromMaybe(false))) + return Array::create(); + + if (injectedScript) { + v8::Local scopeChain; + if (hasInternalError( + errorString, + !details->Get(debuggerContext, + toV8StringInternalized(m_isolate, "scopeChain")) + .ToLocal(&scopeChain) || + !scopeChain->IsArray())) + return Array::create(); + v8::Local scopeChainArray = scopeChain.As(); + if (!injectedScript->wrapPropertyInArray( + errorString, scopeChainArray, + toV8StringInternalized(m_isolate, "object"), + backtraceObjectGroup)) + return Array::create(); + if (!injectedScript->wrapObjectProperty( + errorString, details, toV8StringInternalized(m_isolate, "this"), + backtraceObjectGroup)) + return Array::create(); + if (details + ->Has(debuggerContext, + toV8StringInternalized(m_isolate, "returnValue")) + .FromMaybe(false)) { + if (!injectedScript->wrapObjectProperty( + errorString, details, + toV8StringInternalized(m_isolate, "returnValue"), + backtraceObjectGroup)) + return Array::create(); + } + } else { + if (hasInternalError(errorString, !details + ->Set(debuggerContext, + toV8StringInternalized( + m_isolate, "scopeChain"), + v8::Array::New(m_isolate, 0)) + .FromMaybe(false))) + return Array::create(); + v8::Local remoteObject = v8::Object::New(m_isolate); + if (hasInternalError( + errorString, + !remoteObject + ->Set(debuggerContext, + toV8StringInternalized(m_isolate, "type"), + toV8StringInternalized(m_isolate, "undefined")) + .FromMaybe(false))) + return Array::create(); + if (hasInternalError(errorString, + !details + ->Set(debuggerContext, + toV8StringInternalized(m_isolate, "this"), + remoteObject) + .FromMaybe(false))) + return Array::create(); + if (hasInternalError( + errorString, + !details + ->Delete(debuggerContext, + toV8StringInternalized(m_isolate, "returnValue")) + .FromMaybe(false))) + return Array::create(); + } + + if (hasInternalError( + errorString, + !objects + ->Set(debuggerContext, static_cast(frameOrdinal), details) + .FromMaybe(false))) + return Array::create(); + } + + std::unique_ptr protocolValue = + toProtocolValue(errorString, debuggerContext, objects); + if (!protocolValue) return Array::create(); + protocol::ErrorSupport errorSupport; + std::unique_ptr> callFrames = + Array::parse(protocolValue.get(), &errorSupport); + if (hasInternalError(errorString, !callFrames)) + return Array::create(); + return callFrames; +} + +std::unique_ptr V8DebuggerAgentImpl::currentAsyncStackTrace() { + if (m_pausedContext.IsEmpty()) return nullptr; + V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); + return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) + : nullptr; +} + +void V8DebuggerAgentImpl::didParseSource( + std::unique_ptr script, bool success) { + v8::HandleScope handles(m_isolate); + String16 scriptSource = toProtocolString(script->source(m_isolate)); + if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); + if (!success) + script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); + + std::unique_ptr executionContextAuxData; + if (!script->executionContextAuxData().isEmpty()) + executionContextAuxData = protocol::DictionaryValue::cast( + protocol::parseJSON(script->executionContextAuxData())); + bool isLiveEdit = script->isLiveEdit(); + bool hasSourceURL = script->hasSourceURL(); + String16 scriptId = script->scriptId(); + String16 scriptURL = script->sourceURL(); + + const Maybe& sourceMapURLParam = script->sourceMappingURL(); + const Maybe& executionContextAuxDataParam( + std::move(executionContextAuxData)); + const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; + const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; + if (success) + m_frontend.scriptParsed( + scriptId, scriptURL, script->startLine(), script->startColumn(), + script->endLine(), script->endColumn(), script->executionContextId(), + script->hash(), executionContextAuxDataParam, isLiveEditParam, + sourceMapURLParam, hasSourceURLParam); + else + m_frontend.scriptFailedToParse( + scriptId, scriptURL, script->startLine(), script->startColumn(), + script->endLine(), script->endColumn(), script->executionContextId(), + script->hash(), executionContextAuxDataParam, sourceMapURLParam, + hasSourceURLParam); + + m_scripts[scriptId] = std::move(script); + + if (scriptURL.isEmpty() || !success) return; + + protocol::DictionaryValue* breakpointsCookie = + m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); + if (!breakpointsCookie) return; + + for (size_t i = 0; i < breakpointsCookie->size(); ++i) { + auto cookie = breakpointsCookie->at(i); + protocol::DictionaryValue* breakpointObject = + protocol::DictionaryValue::cast(cookie.second); + bool isRegex; + breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex); + String16 url; + breakpointObject->getString(DebuggerAgentState::url, &url); + if (!matches(m_inspector, scriptURL, url, isRegex)) continue; + ScriptBreakpoint breakpoint; + breakpointObject->getInteger(DebuggerAgentState::lineNumber, + &breakpoint.lineNumber); + breakpointObject->getInteger(DebuggerAgentState::columnNumber, + &breakpoint.columnNumber); + breakpointObject->getString(DebuggerAgentState::condition, + &breakpoint.condition); + std::unique_ptr location = resolveBreakpoint( + cookie.first, scriptId, breakpoint, UserBreakpointSource); + if (location) + m_frontend.breakpointResolved(cookie.first, std::move(location)); + } +} + +V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause( + v8::Local context, v8::Local exception, + const std::vector& hitBreakpoints, bool isPromiseRejection) { + JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(1); + JavaScriptCallFrame* topCallFrame = + !callFrames.empty() ? callFrames.begin()->get() : nullptr; + + V8DebuggerAgentImpl::SkipPauseRequest result; + if (m_skipAllPauses) + result = RequestContinue; + else if (!hitBreakpoints.empty()) + result = RequestNoSkip; // Don't skip explicit breakpoints even if set in + // frameworks. + else if (!exception.IsEmpty()) + result = shouldSkipExceptionPause(topCallFrame); + else if (m_scheduledDebuggerStep != NoStep || m_javaScriptPauseScheduled || + m_pausingOnNativeEvent) + result = shouldSkipStepPause(topCallFrame); + else + result = RequestNoSkip; + + m_skipNextDebuggerStepOut = false; + if (result != RequestNoSkip) return result; + // Skip pauses inside V8 internal scripts and on syntax errors. + if (!topCallFrame) return RequestContinue; + + DCHECK(m_pausedContext.IsEmpty()); + JavaScriptCallFrames frames = m_debugger->currentCallFrames(); + m_pausedCallFrames.swap(frames); + m_pausedContext.Reset(m_isolate, context); + v8::HandleScope handles(m_isolate); + + if (!exception.IsEmpty()) { + ErrorString ignored; + InjectedScript* injectedScript = + m_session->findInjectedScript(&ignored, V8Debugger::contextId(context)); + if (injectedScript) { + m_breakReason = + isPromiseRejection + ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection + : protocol::Debugger::Paused::ReasonEnum::Exception; + ErrorString errorString; + auto obj = injectedScript->wrapObject(&errorString, exception, + backtraceObjectGroup); + m_breakAuxData = obj ? obj->serialize() : nullptr; + // m_breakAuxData might be null after this. + } + } + + std::unique_ptr> hitBreakpointIds = Array::create(); + + for (const auto& point : hitBreakpoints) { + DebugServerBreakpointToBreakpointIdAndSourceMap::iterator + breakpointIterator = m_serverBreakpoints.find(point); + if (breakpointIterator != m_serverBreakpoints.end()) { + const String16& localId = breakpointIterator->second.first; + hitBreakpointIds->addItem(localId); + + BreakpointSource source = breakpointIterator->second.second; + if (m_breakReason == protocol::Debugger::Paused::ReasonEnum::Other && + source == DebugCommandBreakpointSource) + m_breakReason = protocol::Debugger::Paused::ReasonEnum::DebugCommand; + } + } + + ErrorString errorString; + m_frontend.paused(currentCallFrames(&errorString), m_breakReason, + std::move(m_breakAuxData), std::move(hitBreakpointIds), + currentAsyncStackTrace()); + m_scheduledDebuggerStep = NoStep; + m_javaScriptPauseScheduled = false; + m_steppingFromFramework = false; + m_pausingOnNativeEvent = false; + m_skippedStepFrameCount = 0; + m_recursionLevelForStepFrame = 0; + + if (!m_continueToLocationBreakpointId.isEmpty()) { + m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); + m_continueToLocationBreakpointId = ""; + } + return result; +} + +void V8DebuggerAgentImpl::didContinue() { + m_pausedContext.Reset(); + JavaScriptCallFrames emptyCallFrames; + m_pausedCallFrames.swap(emptyCallFrames); + clearBreakDetails(); + m_frontend.resumed(); +} + +void V8DebuggerAgentImpl::breakProgram( + const String16& breakReason, + std::unique_ptr data) { + if (!enabled() || m_skipAllPauses || !m_pausedContext.IsEmpty() || + isCurrentCallStackEmptyOrBlackboxed() || + !m_debugger->breakpointsActivated()) + return; + m_breakReason = breakReason; + m_breakAuxData = std::move(data); + m_scheduledDebuggerStep = NoStep; + m_steppingFromFramework = false; + m_pausingOnNativeEvent = false; + m_debugger->breakProgram(); +} + +void V8DebuggerAgentImpl::breakProgramOnException( + const String16& breakReason, + std::unique_ptr data) { + if (!enabled() || + m_debugger->getPauseOnExceptionsState() == + V8Debugger::DontPauseOnExceptions) + return; + breakProgram(breakReason, std::move(data)); +} + +bool V8DebuggerAgentImpl::assertPaused(ErrorString* errorString) { + if (m_pausedContext.IsEmpty()) { + *errorString = "Can only perform operation while paused."; + return false; + } + return true; +} + +void V8DebuggerAgentImpl::clearBreakDetails() { + m_breakReason = protocol::Debugger::Paused::ReasonEnum::Other; + m_breakAuxData = nullptr; +} + +void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, + int lineNumber, int columnNumber, + BreakpointSource source, + const String16& condition) { + String16 breakpointId = + generateBreakpointId(scriptId, lineNumber, columnNumber, source); + ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); + resolveBreakpoint(breakpointId, scriptId, breakpoint, source); +} + +void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, + int lineNumber, int columnNumber, + BreakpointSource source) { + removeBreakpoint( + generateBreakpointId(scriptId, lineNumber, columnNumber, source)); +} + +void V8DebuggerAgentImpl::reset() { + if (!enabled()) return; + m_scheduledDebuggerStep = NoStep; + m_scripts.clear(); + m_blackboxedPositions.clear(); + m_breakpointIdToDebuggerBreakpointIds.clear(); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-debugger-agent-impl.h b/deps/v8_inspector/src/inspector/v8-debugger-agent-impl.h new file mode 100644 index 00000000000000..62aa67b64bb33a --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-debugger-agent-impl.h @@ -0,0 +1,224 @@ +// Copyright 2015 the V8 project 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 V8_INSPECTOR_V8DEBUGGERAGENTIMPL_H_ +#define V8_INSPECTOR_V8DEBUGGERAGENTIMPL_H_ + +#include + +#include "src/base/macros.h" +#include "src/inspector/java-script-call-frame.h" +#include "src/inspector/protocol/Debugger.h" +#include "src/inspector/protocol/Forward.h" + +namespace v8_inspector { + +struct ScriptBreakpoint; +class JavaScriptCallFrame; +class PromiseTracker; +class V8Debugger; +class V8DebuggerScript; +class V8InspectorImpl; +class V8InspectorSessionImpl; +class V8Regex; +class V8StackTraceImpl; + +using protocol::ErrorString; +using protocol::Maybe; + +class V8DebuggerAgentImpl : public protocol::Debugger::Backend { + public: + enum SkipPauseRequest { + RequestNoSkip, + RequestContinue, + RequestStepInto, + RequestStepOut, + RequestStepFrame + }; + + enum BreakpointSource { + UserBreakpointSource, + DebugCommandBreakpointSource, + MonitorCommandBreakpointSource + }; + + V8DebuggerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, + protocol::DictionaryValue* state); + ~V8DebuggerAgentImpl() override; + void restore(); + + // Part of the protocol. + void enable(ErrorString*) override; + void disable(ErrorString*) override; + void setBreakpointsActive(ErrorString*, bool active) override; + void setSkipAllPauses(ErrorString*, bool skip) override; + void setBreakpointByUrl( + ErrorString*, int lineNumber, const Maybe& optionalURL, + const Maybe& optionalURLRegex, + const Maybe& optionalColumnNumber, + const Maybe& optionalCondition, String16*, + std::unique_ptr>* locations) + override; + void setBreakpoint( + ErrorString*, std::unique_ptr, + const Maybe& optionalCondition, String16*, + std::unique_ptr* actualLocation) override; + void removeBreakpoint(ErrorString*, const String16& breakpointId) override; + void continueToLocation( + ErrorString*, std::unique_ptr) override; + void searchInContent( + ErrorString*, const String16& scriptId, const String16& query, + const Maybe& optionalCaseSensitive, + const Maybe& optionalIsRegex, + std::unique_ptr>*) + override; + void setScriptSource( + ErrorString*, const String16& inScriptId, const String16& inScriptSource, + const Maybe& dryRun, + Maybe>* optOutCallFrames, + Maybe* optOutStackChanged, + Maybe* optOutAsyncStackTrace, + Maybe* optOutCompileError) override; + void restartFrame( + ErrorString*, const String16& callFrameId, + std::unique_ptr>* + newCallFrames, + Maybe* asyncStackTrace) override; + void getScriptSource(ErrorString*, const String16& scriptId, + String16* scriptSource) override; + void pause(ErrorString*) override; + void resume(ErrorString*) override; + void stepOver(ErrorString*) override; + void stepInto(ErrorString*) override; + void stepOut(ErrorString*) override; + void setPauseOnExceptions(ErrorString*, const String16& pauseState) override; + void evaluateOnCallFrame( + ErrorString*, const String16& callFrameId, const String16& expression, + const Maybe& objectGroup, + const Maybe& includeCommandLineAPI, const Maybe& silent, + const Maybe& returnByValue, const Maybe& generatePreview, + std::unique_ptr* result, + Maybe*) override; + void setVariableValue( + ErrorString*, int scopeNumber, const String16& variableName, + std::unique_ptr newValue, + const String16& callFrame) override; + void setAsyncCallStackDepth(ErrorString*, int depth) override; + void setBlackboxPatterns( + ErrorString*, + std::unique_ptr> patterns) override; + void setBlackboxedRanges( + ErrorString*, const String16& scriptId, + std::unique_ptr> + positions) override; + + bool enabled(); + + void setBreakpointAt(const String16& scriptId, int lineNumber, + int columnNumber, BreakpointSource, + const String16& condition = String16()); + void removeBreakpointAt(const String16& scriptId, int lineNumber, + int columnNumber, BreakpointSource); + void schedulePauseOnNextStatement( + const String16& breakReason, + std::unique_ptr data); + void cancelPauseOnNextStatement(); + void breakProgram(const String16& breakReason, + std::unique_ptr data); + void breakProgramOnException(const String16& breakReason, + std::unique_ptr data); + + void reset(); + + // Interface for V8InspectorImpl + SkipPauseRequest didPause(v8::Local, + v8::Local exception, + const std::vector& hitBreakpoints, + bool isPromiseRejection); + void didContinue(); + void didParseSource(std::unique_ptr, bool success); + void willExecuteScript(int scriptId); + void didExecuteScript(); + + v8::Isolate* isolate() { return m_isolate; } + + private: + bool checkEnabled(ErrorString*); + void enable(); + + SkipPauseRequest shouldSkipExceptionPause(JavaScriptCallFrame* topCallFrame); + SkipPauseRequest shouldSkipStepPause(JavaScriptCallFrame* topCallFrame); + + void schedulePauseOnNextStatementIfSteppingInto(); + + std::unique_ptr> + currentCallFrames(ErrorString*); + std::unique_ptr currentAsyncStackTrace(); + + void changeJavaScriptRecursionLevel(int step); + + void setPauseOnExceptionsImpl(ErrorString*, int); + + std::unique_ptr resolveBreakpoint( + const String16& breakpointId, const String16& scriptId, + const ScriptBreakpoint&, BreakpointSource); + void removeBreakpoint(const String16& breakpointId); + bool assertPaused(ErrorString*); + void clearBreakDetails(); + + bool isCurrentCallStackEmptyOrBlackboxed(); + bool isTopPausedCallFrameBlackboxed(); + bool isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCallFrame*); + + void internalSetAsyncCallStackDepth(int); + void increaseCachedSkipStackGeneration(); + + bool setBlackboxPattern(ErrorString*, const String16& pattern); + + using ScriptsMap = + protocol::HashMap>; + using BreakpointIdToDebuggerBreakpointIdsMap = + protocol::HashMap>; + using DebugServerBreakpointToBreakpointIdAndSourceMap = + protocol::HashMap>; + using MuteBreakpoins = protocol::HashMap>; + + enum DebuggerStep { NoStep = 0, StepInto, StepOver, StepOut }; + + V8InspectorImpl* m_inspector; + V8Debugger* m_debugger; + V8InspectorSessionImpl* m_session; + bool m_enabled; + protocol::DictionaryValue* m_state; + protocol::Debugger::Frontend m_frontend; + v8::Isolate* m_isolate; + v8::Global m_pausedContext; + JavaScriptCallFrames m_pausedCallFrames; + ScriptsMap m_scripts; + BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds; + DebugServerBreakpointToBreakpointIdAndSourceMap m_serverBreakpoints; + String16 m_continueToLocationBreakpointId; + String16 m_breakReason; + std::unique_ptr m_breakAuxData; + DebuggerStep m_scheduledDebuggerStep; + bool m_skipNextDebuggerStepOut; + bool m_javaScriptPauseScheduled; + bool m_steppingFromFramework; + bool m_pausingOnNativeEvent; + + int m_skippedStepFrameCount; + int m_recursionLevelForStepOut; + int m_recursionLevelForStepFrame; + bool m_skipAllPauses; + + std::unique_ptr m_blackboxPattern; + protocol::HashMap>> + m_blackboxedPositions; + + DISALLOW_COPY_AND_ASSIGN(V8DebuggerAgentImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8DEBUGGERAGENTIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-debugger-script.cc b/deps/v8_inspector/src/inspector/v8-debugger-script.cc new file mode 100644 index 00000000000000..485188a48f4eac --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-debugger-script.cc @@ -0,0 +1,140 @@ +// Copyright 2014 the V8 project 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 "src/inspector/v8-debugger-script.h" + +#include "src/inspector/protocol-platform.h" +#include "src/inspector/string-util.h" + +namespace v8_inspector { + +static const char hexDigits[17] = "0123456789ABCDEF"; + +static void appendUnsignedAsHex(uint64_t number, String16Builder* destination) { + for (size_t i = 0; i < 8; ++i) { + UChar c = hexDigits[number & 0xF]; + destination->append(c); + number >>= 4; + } +} + +// Hash algorithm for substrings is described in "Über die Komplexität der +// Multiplikation in +// eingeschränkten Branchingprogrammmodellen" by Woelfe. +// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000 +static String16 calculateHash(const String16& str) { + static uint64_t prime[] = {0x3FB75161, 0xAB1F4E4F, 0x82675BC5, 0xCD924D35, + 0x81ABE279}; + static uint64_t random[] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, + 0xC3D2E1F0}; + static uint32_t randomOdd[] = {0xB4663807, 0xCC322BF5, 0xD4F91BBD, 0xA7BEA11D, + 0x8F462907}; + + uint64_t hashes[] = {0, 0, 0, 0, 0}; + uint64_t zi[] = {1, 1, 1, 1, 1}; + + const size_t hashesSize = arraysize(hashes); + + size_t current = 0; + const uint32_t* data = nullptr; + size_t sizeInBytes = sizeof(UChar) * str.length(); + data = reinterpret_cast(str.characters16()); + for (size_t i = 0; i < sizeInBytes / 4; i += 4) { + uint32_t v = data[i]; + uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF; + hashes[current] = (hashes[current] + zi[current] * xi) % prime[current]; + zi[current] = (zi[current] * random[current]) % prime[current]; + current = current == hashesSize - 1 ? 0 : current + 1; + } + if (sizeInBytes % 4) { + uint32_t v = 0; + for (size_t i = sizeInBytes - sizeInBytes % 4; i < sizeInBytes; ++i) { + v <<= 8; + v |= reinterpret_cast(data)[i]; + } + uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF; + hashes[current] = (hashes[current] + zi[current] * xi) % prime[current]; + zi[current] = (zi[current] * random[current]) % prime[current]; + current = current == hashesSize - 1 ? 0 : current + 1; + } + + for (size_t i = 0; i < hashesSize; ++i) + hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i]; + + String16Builder hash; + for (size_t i = 0; i < hashesSize; ++i) appendUnsignedAsHex(hashes[i], &hash); + return hash.toString(); +} + +static v8::Local GetChecked(v8::Local context, + v8::Local object, + const char* name) { + return object + ->Get(context, toV8StringInternalized(context->GetIsolate(), name)) + .ToLocalChecked(); +} + +static int GetCheckedInt(v8::Local context, + v8::Local object, const char* name) { + return static_cast(GetChecked(context, object, name) + ->ToInteger(context) + .ToLocalChecked() + ->Value()); +} + +V8DebuggerScript::V8DebuggerScript(v8::Local context, + v8::Local object, + bool isLiveEdit) { + v8::Isolate* isolate = context->GetIsolate(); + v8::Local idValue = GetChecked(context, object, "id"); + DCHECK(!idValue.IsEmpty() && idValue->IsInt32()); + m_id = String16::fromInteger(idValue->Int32Value(context).FromJust()); + + m_url = toProtocolStringWithTypeCheck(GetChecked(context, object, "name")); + m_sourceURL = + toProtocolStringWithTypeCheck(GetChecked(context, object, "sourceURL")); + m_sourceMappingURL = toProtocolStringWithTypeCheck( + GetChecked(context, object, "sourceMappingURL")); + m_startLine = GetCheckedInt(context, object, "startLine"); + m_startColumn = GetCheckedInt(context, object, "startColumn"); + m_endLine = GetCheckedInt(context, object, "endLine"); + m_endColumn = GetCheckedInt(context, object, "endColumn"); + m_executionContextAuxData = toProtocolStringWithTypeCheck( + GetChecked(context, object, "executionContextAuxData")); + m_executionContextId = GetCheckedInt(context, object, "executionContextId"); + m_isLiveEdit = isLiveEdit; + + v8::Local sourceValue; + if (!object->Get(context, toV8StringInternalized(isolate, "source")) + .ToLocal(&sourceValue) || + !sourceValue->IsString()) + return; + setSource(isolate, sourceValue.As()); +} + +V8DebuggerScript::~V8DebuggerScript() {} + +const String16& V8DebuggerScript::sourceURL() const { + return m_sourceURL.isEmpty() ? m_url : m_sourceURL; +} + +v8::Local V8DebuggerScript::source(v8::Isolate* isolate) const { + return m_source.Get(isolate); +} + +void V8DebuggerScript::setSourceURL(const String16& sourceURL) { + m_sourceURL = sourceURL; +} + +void V8DebuggerScript::setSourceMappingURL(const String16& sourceMappingURL) { + m_sourceMappingURL = sourceMappingURL; +} + +void V8DebuggerScript::setSource(v8::Isolate* isolate, + v8::Local source) { + m_source.Reset(isolate, source); + m_hash = calculateHash(toProtocolString(source)); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerScript.h b/deps/v8_inspector/src/inspector/v8-debugger-script.h similarity index 50% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerScript.h rename to deps/v8_inspector/src/inspector/v8-debugger-script.h index 8af67ffa08db46..78c44b5eb97cb4 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerScript.h +++ b/deps/v8_inspector/src/inspector/v8-debugger-script.h @@ -27,58 +27,61 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef V8DebuggerScript_h -#define V8DebuggerScript_h +#ifndef V8_INSPECTOR_V8DEBUGGERSCRIPT_H_ +#define V8_INSPECTOR_V8DEBUGGERSCRIPT_H_ -#include "platform/inspector_protocol/InspectorProtocol.h" -#include +#include "src/base/macros.h" +#include "src/inspector/string-16.h" -namespace v8_inspector { +#include "include/v8.h" -namespace protocol = blink::protocol; +namespace v8_inspector { class V8DebuggerScript { - PROTOCOL_DISALLOW_COPY(V8DebuggerScript); -public: - V8DebuggerScript(v8::Isolate*, v8::Local, bool isLiveEdit); - ~V8DebuggerScript(); + public: + V8DebuggerScript(v8::Local, v8::Local, + bool isLiveEdit); + ~V8DebuggerScript(); - const String16& scriptId() const { return m_id; } - const String16& url() const { return m_url; } - bool hasSourceURL() const { return !m_sourceURL.isEmpty(); } - const String16& sourceURL() const; - const String16& sourceMappingURL() const { return m_sourceMappingURL; } - v8::Local source(v8::Isolate*) const; - const String16& hash() const { return m_hash; } - int startLine() const { return m_startLine; } - int startColumn() const { return m_startColumn; } - int endLine() const { return m_endLine; } - int endColumn() const { return m_endColumn; } - int executionContextId() const { return m_executionContextId; } - const String16& executionContextAuxData() const { return m_executionContextAuxData; } - bool isLiveEdit() const { return m_isLiveEdit; } + const String16& scriptId() const { return m_id; } + const String16& url() const { return m_url; } + bool hasSourceURL() const { return !m_sourceURL.isEmpty(); } + const String16& sourceURL() const; + const String16& sourceMappingURL() const { return m_sourceMappingURL; } + v8::Local source(v8::Isolate*) const; + const String16& hash() const { return m_hash; } + int startLine() const { return m_startLine; } + int startColumn() const { return m_startColumn; } + int endLine() const { return m_endLine; } + int endColumn() const { return m_endColumn; } + int executionContextId() const { return m_executionContextId; } + const String16& executionContextAuxData() const { + return m_executionContextAuxData; + } + bool isLiveEdit() const { return m_isLiveEdit; } - void setSourceURL(const String16&); - void setSourceMappingURL(const String16&); - void setSource(v8::Isolate*, v8::Local); + void setSourceURL(const String16&); + void setSourceMappingURL(const String16&); + void setSource(v8::Isolate*, v8::Local); -private: - String16 m_id; - String16 m_url; - String16 m_sourceURL; - String16 m_sourceMappingURL; - v8::Global m_source; - String16 m_hash; - int m_startLine; - int m_startColumn; - int m_endLine; - int m_endColumn; - int m_executionContextId; - String16 m_executionContextAuxData; - bool m_isLiveEdit; -}; + private: + String16 m_id; + String16 m_url; + String16 m_sourceURL; + String16 m_sourceMappingURL; + v8::Global m_source; + String16 m_hash; + int m_startLine; + int m_startColumn; + int m_endLine; + int m_endColumn; + int m_executionContextId; + String16 m_executionContextAuxData; + bool m_isLiveEdit; -} // namespace v8_inspector + DISALLOW_COPY_AND_ASSIGN(V8DebuggerScript); +}; +} // namespace v8_inspector -#endif // V8DebuggerScript_h +#endif // V8_INSPECTOR_V8DEBUGGERSCRIPT_H_ diff --git a/deps/v8_inspector/src/inspector/v8-debugger.cc b/deps/v8_inspector/src/inspector/v8-debugger.cc new file mode 100644 index 00000000000000..d393f81ad4a38a --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-debugger.cc @@ -0,0 +1,1002 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-debugger.h" + +#include "src/inspector/debugger-script.h" +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/script-breakpoint.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-debugger-agent-impl.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-internal-value-type.h" +#include "src/inspector/v8-stack-trace-impl.h" +#include "src/inspector/v8-value-copier.h" + +namespace v8_inspector { + +namespace { +const char stepIntoV8MethodName[] = "stepIntoStatement"; +const char stepOutV8MethodName[] = "stepOutOfFunction"; +static const char v8AsyncTaskEventEnqueue[] = "enqueue"; +static const char v8AsyncTaskEventEnqueueRecurring[] = "enqueueRecurring"; +static const char v8AsyncTaskEventWillHandle[] = "willHandle"; +static const char v8AsyncTaskEventDidHandle[] = "didHandle"; +static const char v8AsyncTaskEventCancel[] = "cancel"; + +inline v8::Local v8Boolean(bool value, v8::Isolate* isolate) { + return value ? v8::True(isolate) : v8::False(isolate); +} + +} // namespace + +static bool inLiveEditScope = false; + +v8::MaybeLocal V8Debugger::callDebuggerMethod( + const char* functionName, int argc, v8::Local argv[]) { + v8::MicrotasksScope microtasks(m_isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + DCHECK(m_isolate->InContext()); + v8::Local context = m_isolate->GetCurrentContext(); + v8::Local debuggerScript = m_debuggerScript.Get(m_isolate); + v8::Local function = v8::Local::Cast( + debuggerScript + ->Get(context, toV8StringInternalized(m_isolate, functionName)) + .ToLocalChecked()); + return function->Call(context, debuggerScript, argc, argv); +} + +V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) + : m_isolate(isolate), + m_inspector(inspector), + m_lastContextId(0), + m_enableCount(0), + m_breakpointsActivated(true), + m_runningNestedMessageLoop(false), + m_ignoreScriptParsedEventsCounter(0), + m_maxAsyncCallStackDepth(0) {} + +V8Debugger::~V8Debugger() {} + +void V8Debugger::enable() { + if (m_enableCount++) return; + DCHECK(!enabled()); + v8::HandleScope scope(m_isolate); + v8::Debug::SetDebugEventListener(m_isolate, &V8Debugger::v8DebugEventCallback, + v8::External::New(m_isolate, this)); + m_debuggerContext.Reset(m_isolate, v8::Debug::GetDebugContext(m_isolate)); + compileDebuggerScript(); +} + +void V8Debugger::disable() { + if (--m_enableCount) return; + DCHECK(enabled()); + clearBreakpoints(); + m_debuggerScript.Reset(); + m_debuggerContext.Reset(); + allAsyncTasksCanceled(); + v8::Debug::SetDebugEventListener(m_isolate, nullptr); +} + +bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } + +// static +int V8Debugger::contextId(v8::Local context) { + v8::Local data = + context->GetEmbedderData(static_cast(v8::Context::kDebugIdIndex)); + if (data.IsEmpty() || !data->IsString()) return 0; + String16 dataString = toProtocolString(data.As()); + if (dataString.isEmpty()) return 0; + size_t commaPos = dataString.find(","); + if (commaPos == String16::kNotFound) return 0; + size_t commaPos2 = dataString.find(",", commaPos + 1); + if (commaPos2 == String16::kNotFound) return 0; + return dataString.substring(commaPos + 1, commaPos2 - commaPos - 1) + .toInteger(); +} + +// static +int V8Debugger::getGroupId(v8::Local context) { + v8::Local data = + context->GetEmbedderData(static_cast(v8::Context::kDebugIdIndex)); + if (data.IsEmpty() || !data->IsString()) return 0; + String16 dataString = toProtocolString(data.As()); + if (dataString.isEmpty()) return 0; + size_t commaPos = dataString.find(","); + if (commaPos == String16::kNotFound) return 0; + return dataString.substring(0, commaPos).toInteger(); +} + +void V8Debugger::getCompiledScripts( + int contextGroupId, + std::vector>& result) { + v8::HandleScope scope(m_isolate); + v8::MicrotasksScope microtasks(m_isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::Local context = debuggerContext(); + v8::Local debuggerScript = m_debuggerScript.Get(m_isolate); + DCHECK(!debuggerScript->IsUndefined()); + v8::Local getScriptsFunction = v8::Local::Cast( + debuggerScript + ->Get(context, toV8StringInternalized(m_isolate, "getScripts")) + .ToLocalChecked()); + v8::Local argv[] = {v8::Integer::New(m_isolate, contextGroupId)}; + v8::Local value; + if (!getScriptsFunction->Call(context, debuggerScript, arraysize(argv), argv) + .ToLocal(&value)) + return; + DCHECK(value->IsArray()); + v8::Local scriptsArray = v8::Local::Cast(value); + result.reserve(scriptsArray->Length()); + for (unsigned i = 0; i < scriptsArray->Length(); ++i) { + v8::Local scriptObject = v8::Local::Cast( + scriptsArray->Get(context, v8::Integer::New(m_isolate, i)) + .ToLocalChecked()); + result.push_back(wrapUnique( + new V8DebuggerScript(context, scriptObject, inLiveEditScope))); + } +} + +String16 V8Debugger::setBreakpoint(const String16& sourceID, + const ScriptBreakpoint& scriptBreakpoint, + int* actualLineNumber, + int* actualColumnNumber) { + v8::HandleScope scope(m_isolate); + v8::Local context = debuggerContext(); + v8::Context::Scope contextScope(context); + + v8::Local info = v8::Object::New(m_isolate); + bool success = false; + success = info->Set(context, toV8StringInternalized(m_isolate, "sourceID"), + toV8String(m_isolate, sourceID)) + .FromMaybe(false); + DCHECK(success); + success = info->Set(context, toV8StringInternalized(m_isolate, "lineNumber"), + v8::Integer::New(m_isolate, scriptBreakpoint.lineNumber)) + .FromMaybe(false); + DCHECK(success); + success = + info->Set(context, toV8StringInternalized(m_isolate, "columnNumber"), + v8::Integer::New(m_isolate, scriptBreakpoint.columnNumber)) + .FromMaybe(false); + DCHECK(success); + success = info->Set(context, toV8StringInternalized(m_isolate, "condition"), + toV8String(m_isolate, scriptBreakpoint.condition)) + .FromMaybe(false); + DCHECK(success); + + v8::Local setBreakpointFunction = v8::Local::Cast( + m_debuggerScript.Get(m_isolate) + ->Get(context, toV8StringInternalized(m_isolate, "setBreakpoint")) + .ToLocalChecked()); + v8::Local breakpointId = + v8::Debug::Call(debuggerContext(), setBreakpointFunction, info) + .ToLocalChecked(); + if (!breakpointId->IsString()) return ""; + *actualLineNumber = + info->Get(context, toV8StringInternalized(m_isolate, "lineNumber")) + .ToLocalChecked() + ->Int32Value(context) + .FromJust(); + *actualColumnNumber = + info->Get(context, toV8StringInternalized(m_isolate, "columnNumber")) + .ToLocalChecked() + ->Int32Value(context) + .FromJust(); + return toProtocolString(breakpointId.As()); +} + +void V8Debugger::removeBreakpoint(const String16& breakpointId) { + v8::HandleScope scope(m_isolate); + v8::Local context = debuggerContext(); + v8::Context::Scope contextScope(context); + + v8::Local info = v8::Object::New(m_isolate); + bool success = false; + success = + info->Set(context, toV8StringInternalized(m_isolate, "breakpointId"), + toV8String(m_isolate, breakpointId)) + .FromMaybe(false); + DCHECK(success); + + v8::Local removeBreakpointFunction = + v8::Local::Cast( + m_debuggerScript.Get(m_isolate) + ->Get(context, + toV8StringInternalized(m_isolate, "removeBreakpoint")) + .ToLocalChecked()); + v8::Debug::Call(debuggerContext(), removeBreakpointFunction, info) + .ToLocalChecked(); +} + +void V8Debugger::clearBreakpoints() { + v8::HandleScope scope(m_isolate); + v8::Local context = debuggerContext(); + v8::Context::Scope contextScope(context); + + v8::Local clearBreakpoints = v8::Local::Cast( + m_debuggerScript.Get(m_isolate) + ->Get(context, toV8StringInternalized(m_isolate, "clearBreakpoints")) + .ToLocalChecked()); + v8::Debug::Call(debuggerContext(), clearBreakpoints).ToLocalChecked(); +} + +void V8Debugger::setBreakpointsActivated(bool activated) { + if (!enabled()) { + UNREACHABLE(); + return; + } + v8::HandleScope scope(m_isolate); + v8::Local context = debuggerContext(); + v8::Context::Scope contextScope(context); + + v8::Local info = v8::Object::New(m_isolate); + bool success = false; + success = info->Set(context, toV8StringInternalized(m_isolate, "enabled"), + v8::Boolean::New(m_isolate, activated)) + .FromMaybe(false); + DCHECK(success); + v8::Local setBreakpointsActivated = + v8::Local::Cast( + m_debuggerScript.Get(m_isolate) + ->Get(context, toV8StringInternalized(m_isolate, + "setBreakpointsActivated")) + .ToLocalChecked()); + v8::Debug::Call(debuggerContext(), setBreakpointsActivated, info) + .ToLocalChecked(); + + m_breakpointsActivated = activated; +} + +V8Debugger::PauseOnExceptionsState V8Debugger::getPauseOnExceptionsState() { + DCHECK(enabled()); + v8::HandleScope scope(m_isolate); + v8::Local context = debuggerContext(); + v8::Context::Scope contextScope(context); + + v8::Local argv[] = {v8::Undefined(m_isolate)}; + v8::Local result = + callDebuggerMethod("pauseOnExceptionsState", 0, argv).ToLocalChecked(); + return static_cast( + result->Int32Value(context).FromJust()); +} + +void V8Debugger::setPauseOnExceptionsState( + PauseOnExceptionsState pauseOnExceptionsState) { + DCHECK(enabled()); + v8::HandleScope scope(m_isolate); + v8::Context::Scope contextScope(debuggerContext()); + + v8::Local argv[] = { + v8::Int32::New(m_isolate, pauseOnExceptionsState)}; + callDebuggerMethod("setPauseOnExceptionsState", 1, argv); +} + +void V8Debugger::setPauseOnNextStatement(bool pause) { + if (m_runningNestedMessageLoop) return; + if (pause) + v8::Debug::DebugBreak(m_isolate); + else + v8::Debug::CancelDebugBreak(m_isolate); +} + +bool V8Debugger::canBreakProgram() { + if (!m_breakpointsActivated) return false; + return m_isolate->InContext(); +} + +void V8Debugger::breakProgram() { + if (isPaused()) { + DCHECK(!m_runningNestedMessageLoop); + v8::Local exception; + v8::Local hitBreakpoints; + handleProgramBreak(m_pausedContext, m_executionState, exception, + hitBreakpoints); + return; + } + + if (!canBreakProgram()) return; + + v8::HandleScope scope(m_isolate); + v8::Local breakFunction; + if (!v8::Function::New(m_isolate->GetCurrentContext(), + &V8Debugger::breakProgramCallback, + v8::External::New(m_isolate, this), 0, + v8::ConstructorBehavior::kThrow) + .ToLocal(&breakFunction)) + return; + v8::Debug::Call(debuggerContext(), breakFunction).ToLocalChecked(); +} + +void V8Debugger::continueProgram() { + if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); + m_pausedContext.Clear(); + m_executionState.Clear(); +} + +void V8Debugger::stepIntoStatement() { + DCHECK(isPaused()); + DCHECK(!m_executionState.IsEmpty()); + v8::HandleScope handleScope(m_isolate); + v8::Local argv[] = {m_executionState}; + callDebuggerMethod(stepIntoV8MethodName, 1, argv); + continueProgram(); +} + +void V8Debugger::stepOverStatement() { + DCHECK(isPaused()); + DCHECK(!m_executionState.IsEmpty()); + v8::HandleScope handleScope(m_isolate); + v8::Local argv[] = {m_executionState}; + callDebuggerMethod("stepOverStatement", 1, argv); + continueProgram(); +} + +void V8Debugger::stepOutOfFunction() { + DCHECK(isPaused()); + DCHECK(!m_executionState.IsEmpty()); + v8::HandleScope handleScope(m_isolate); + v8::Local argv[] = {m_executionState}; + callDebuggerMethod(stepOutV8MethodName, 1, argv); + continueProgram(); +} + +void V8Debugger::clearStepping() { + DCHECK(enabled()); + v8::HandleScope scope(m_isolate); + v8::Context::Scope contextScope(debuggerContext()); + + v8::Local argv[] = {v8::Undefined(m_isolate)}; + callDebuggerMethod("clearStepping", 0, argv); +} + +bool V8Debugger::setScriptSource( + const String16& sourceID, v8::Local newSource, bool dryRun, + ErrorString* error, + Maybe* exceptionDetails, + JavaScriptCallFrames* newCallFrames, Maybe* stackChanged) { + class EnableLiveEditScope { + public: + explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { + v8::Debug::SetLiveEditEnabled(m_isolate, true); + inLiveEditScope = true; + } + ~EnableLiveEditScope() { + v8::Debug::SetLiveEditEnabled(m_isolate, false); + inLiveEditScope = false; + } + + private: + v8::Isolate* m_isolate; + }; + + DCHECK(enabled()); + v8::HandleScope scope(m_isolate); + + std::unique_ptr contextScope; + if (!isPaused()) + contextScope = wrapUnique(new v8::Context::Scope(debuggerContext())); + + v8::Local argv[] = {toV8String(m_isolate, sourceID), newSource, + v8Boolean(dryRun, m_isolate)}; + + v8::Local v8result; + { + EnableLiveEditScope enableLiveEditScope(m_isolate); + v8::TryCatch tryCatch(m_isolate); + tryCatch.SetVerbose(false); + v8::MaybeLocal maybeResult = + callDebuggerMethod("liveEditScriptSource", 3, argv); + if (tryCatch.HasCaught()) { + v8::Local message = tryCatch.Message(); + if (!message.IsEmpty()) + *error = toProtocolStringWithTypeCheck(message->Get()); + else + *error = "Unknown error."; + return false; + } + v8result = maybeResult.ToLocalChecked(); + } + DCHECK(!v8result.IsEmpty()); + v8::Local context = m_isolate->GetCurrentContext(); + v8::Local resultTuple = + v8result->ToObject(context).ToLocalChecked(); + int code = static_cast(resultTuple->Get(context, 0) + .ToLocalChecked() + ->ToInteger(context) + .ToLocalChecked() + ->Value()); + switch (code) { + case 0: { + *stackChanged = resultTuple->Get(context, 1) + .ToLocalChecked() + ->BooleanValue(context) + .FromJust(); + // Call stack may have changed after if the edited function was on the + // stack. + if (!dryRun && isPaused()) { + JavaScriptCallFrames frames = currentCallFrames(); + newCallFrames->swap(frames); + } + return true; + } + // Compile error. + case 1: { + *exceptionDetails = + protocol::Runtime::ExceptionDetails::create() + .setExceptionId(m_inspector->nextExceptionId()) + .setText(toProtocolStringWithTypeCheck( + resultTuple->Get(context, 2).ToLocalChecked())) + .setLineNumber(static_cast(resultTuple->Get(context, 3) + .ToLocalChecked() + ->ToInteger(context) + .ToLocalChecked() + ->Value()) - + 1) + .setColumnNumber(static_cast(resultTuple->Get(context, 4) + .ToLocalChecked() + ->ToInteger(context) + .ToLocalChecked() + ->Value()) - + 1) + .build(); + return false; + } + } + *error = "Unknown error."; + return false; +} + +JavaScriptCallFrames V8Debugger::currentCallFrames(int limit) { + if (!m_isolate->InContext()) return JavaScriptCallFrames(); + v8::Local currentCallFramesV8; + if (m_executionState.IsEmpty()) { + v8::Local currentCallFramesFunction = + v8::Local::Cast( + m_debuggerScript.Get(m_isolate) + ->Get(debuggerContext(), + toV8StringInternalized(m_isolate, "currentCallFrames")) + .ToLocalChecked()); + currentCallFramesV8 = + v8::Debug::Call(debuggerContext(), currentCallFramesFunction, + v8::Integer::New(m_isolate, limit)) + .ToLocalChecked(); + } else { + v8::Local argv[] = {m_executionState, + v8::Integer::New(m_isolate, limit)}; + currentCallFramesV8 = + callDebuggerMethod("currentCallFrames", arraysize(argv), argv) + .ToLocalChecked(); + } + DCHECK(!currentCallFramesV8.IsEmpty()); + if (!currentCallFramesV8->IsArray()) return JavaScriptCallFrames(); + v8::Local callFramesArray = currentCallFramesV8.As(); + JavaScriptCallFrames callFrames; + for (uint32_t i = 0; i < callFramesArray->Length(); ++i) { + v8::Local callFrameValue; + if (!callFramesArray->Get(debuggerContext(), i).ToLocal(&callFrameValue)) + return JavaScriptCallFrames(); + if (!callFrameValue->IsObject()) return JavaScriptCallFrames(); + v8::Local callFrameObject = callFrameValue.As(); + callFrames.push_back(JavaScriptCallFrame::create( + debuggerContext(), v8::Local::Cast(callFrameObject))); + } + return callFrames; +} + +static V8Debugger* toV8Debugger(v8::Local data) { + void* p = v8::Local::Cast(data)->Value(); + return static_cast(p); +} + +void V8Debugger::breakProgramCallback( + const v8::FunctionCallbackInfo& info) { + DCHECK_EQ(info.Length(), 2); + V8Debugger* thisPtr = toV8Debugger(info.Data()); + if (!thisPtr->enabled()) return; + v8::Local pausedContext = + thisPtr->m_isolate->GetCurrentContext(); + v8::Local exception; + v8::Local hitBreakpoints; + thisPtr->handleProgramBreak(pausedContext, + v8::Local::Cast(info[0]), exception, + hitBreakpoints); +} + +void V8Debugger::handleProgramBreak(v8::Local pausedContext, + v8::Local executionState, + v8::Local exception, + v8::Local hitBreakpointNumbers, + bool isPromiseRejection) { + // Don't allow nested breaks. + if (m_runningNestedMessageLoop) return; + + V8DebuggerAgentImpl* agent = + m_inspector->enabledDebuggerAgentForGroup(getGroupId(pausedContext)); + if (!agent) return; + + std::vector breakpointIds; + if (!hitBreakpointNumbers.IsEmpty()) { + breakpointIds.reserve(hitBreakpointNumbers->Length()); + for (uint32_t i = 0; i < hitBreakpointNumbers->Length(); i++) { + v8::Local hitBreakpointNumber = + hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); + DCHECK(hitBreakpointNumber->IsInt32()); + breakpointIds.push_back(String16::fromInteger( + hitBreakpointNumber->Int32Value(debuggerContext()).FromJust())); + } + } + + m_pausedContext = pausedContext; + m_executionState = executionState; + V8DebuggerAgentImpl::SkipPauseRequest result = agent->didPause( + pausedContext, exception, breakpointIds, isPromiseRejection); + if (result == V8DebuggerAgentImpl::RequestNoSkip) { + m_runningNestedMessageLoop = true; + int groupId = getGroupId(pausedContext); + DCHECK(groupId); + m_inspector->client()->runMessageLoopOnPause(groupId); + // The agent may have been removed in the nested loop. + agent = + m_inspector->enabledDebuggerAgentForGroup(getGroupId(pausedContext)); + if (agent) agent->didContinue(); + m_runningNestedMessageLoop = false; + } + m_pausedContext.Clear(); + m_executionState.Clear(); + + if (result == V8DebuggerAgentImpl::RequestStepFrame) { + v8::Local argv[] = {executionState}; + callDebuggerMethod("stepFrameStatement", 1, argv); + } else if (result == V8DebuggerAgentImpl::RequestStepInto) { + v8::Local argv[] = {executionState}; + callDebuggerMethod(stepIntoV8MethodName, 1, argv); + } else if (result == V8DebuggerAgentImpl::RequestStepOut) { + v8::Local argv[] = {executionState}; + callDebuggerMethod(stepOutV8MethodName, 1, argv); + } +} + +void V8Debugger::v8DebugEventCallback( + const v8::Debug::EventDetails& eventDetails) { + V8Debugger* thisPtr = toV8Debugger(eventDetails.GetCallbackData()); + thisPtr->handleV8DebugEvent(eventDetails); +} + +v8::Local V8Debugger::callInternalGetterFunction( + v8::Local object, const char* functionName) { + v8::MicrotasksScope microtasks(m_isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::Local getterValue = + object + ->Get(m_isolate->GetCurrentContext(), + toV8StringInternalized(m_isolate, functionName)) + .ToLocalChecked(); + DCHECK(!getterValue.IsEmpty() && getterValue->IsFunction()); + return v8::Local::Cast(getterValue) + ->Call(m_isolate->GetCurrentContext(), object, 0, 0) + .ToLocalChecked(); +} + +void V8Debugger::handleV8DebugEvent( + const v8::Debug::EventDetails& eventDetails) { + if (!enabled()) return; + v8::DebugEvent event = eventDetails.GetEvent(); + if (event != v8::AsyncTaskEvent && event != v8::Break && + event != v8::Exception && event != v8::AfterCompile && + event != v8::BeforeCompile && event != v8::CompileError) + return; + + v8::Local eventContext = eventDetails.GetEventContext(); + DCHECK(!eventContext.IsEmpty()); + + if (event == v8::AsyncTaskEvent) { + v8::HandleScope scope(m_isolate); + handleV8AsyncTaskEvent(eventContext, eventDetails.GetExecutionState(), + eventDetails.GetEventData()); + return; + } + + V8DebuggerAgentImpl* agent = + m_inspector->enabledDebuggerAgentForGroup(getGroupId(eventContext)); + if (agent) { + v8::HandleScope scope(m_isolate); + if (m_ignoreScriptParsedEventsCounter == 0 && + (event == v8::AfterCompile || event == v8::CompileError)) { + v8::Context::Scope contextScope(debuggerContext()); + v8::Local argv[] = {eventDetails.GetEventData()}; + v8::Local value = + callDebuggerMethod("getAfterCompileScript", 1, argv).ToLocalChecked(); + if (value->IsNull()) return; + DCHECK(value->IsObject()); + v8::Local scriptObject = v8::Local::Cast(value); + agent->didParseSource( + wrapUnique(new V8DebuggerScript(debuggerContext(), scriptObject, + inLiveEditScope)), + event == v8::AfterCompile); + } else if (event == v8::Exception) { + v8::Local eventData = eventDetails.GetEventData(); + v8::Local exception = + callInternalGetterFunction(eventData, "exception"); + v8::Local promise = + callInternalGetterFunction(eventData, "promise"); + bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); + handleProgramBreak(eventContext, eventDetails.GetExecutionState(), + exception, v8::Local(), isPromiseRejection); + } else if (event == v8::Break) { + v8::Local argv[] = {eventDetails.GetEventData()}; + v8::Local hitBreakpoints = + callDebuggerMethod("getBreakpointNumbers", 1, argv).ToLocalChecked(); + DCHECK(hitBreakpoints->IsArray()); + handleProgramBreak(eventContext, eventDetails.GetExecutionState(), + v8::Local(), + hitBreakpoints.As()); + } + } +} + +void V8Debugger::handleV8AsyncTaskEvent(v8::Local context, + v8::Local executionState, + v8::Local eventData) { + if (!m_maxAsyncCallStackDepth) return; + + String16 type = toProtocolStringWithTypeCheck( + callInternalGetterFunction(eventData, "type")); + String16 name = toProtocolStringWithTypeCheck( + callInternalGetterFunction(eventData, "name")); + int id = static_cast(callInternalGetterFunction(eventData, "id") + ->ToInteger(context) + .ToLocalChecked() + ->Value()); + // Async task events from Promises are given misaligned pointers to prevent + // from overlapping with other Blink task identifiers. There is a single + // namespace of such ids, managed by src/js/promise.js. + void* ptr = reinterpret_cast(id * 2 + 1); + if (type == v8AsyncTaskEventEnqueue) + asyncTaskScheduled(name, ptr, false); + else if (type == v8AsyncTaskEventEnqueueRecurring) + asyncTaskScheduled(name, ptr, true); + else if (type == v8AsyncTaskEventWillHandle) + asyncTaskStarted(ptr); + else if (type == v8AsyncTaskEventDidHandle) + asyncTaskFinished(ptr); + else if (type == v8AsyncTaskEventCancel) + asyncTaskCanceled(ptr); + else + UNREACHABLE(); +} + +V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { + if (!m_currentStacks.size()) return nullptr; + return m_currentStacks.back().get(); +} + +void V8Debugger::compileDebuggerScript() { + if (!m_debuggerScript.IsEmpty()) { + UNREACHABLE(); + return; + } + + v8::HandleScope scope(m_isolate); + v8::Context::Scope contextScope(debuggerContext()); + + v8::Local scriptValue = + v8::String::NewFromUtf8(m_isolate, DebuggerScript_js, + v8::NewStringType::kInternalized, + sizeof(DebuggerScript_js)) + .ToLocalChecked(); + v8::Local value; + if (!m_inspector->compileAndRunInternalScript(debuggerContext(), scriptValue) + .ToLocal(&value)) { + UNREACHABLE(); + return; + } + DCHECK(value->IsObject()); + m_debuggerScript.Reset(m_isolate, value.As()); +} + +v8::Local V8Debugger::debuggerContext() const { + DCHECK(!m_debuggerContext.IsEmpty()); + return m_debuggerContext.Get(m_isolate); +} + +v8::MaybeLocal V8Debugger::functionScopes( + v8::Local context, v8::Local function) { + if (!enabled()) { + UNREACHABLE(); + return v8::Local::New(m_isolate, v8::Undefined(m_isolate)); + } + v8::Local argv[] = {function}; + v8::Local scopesValue; + if (!callDebuggerMethod("getFunctionScopes", 1, argv).ToLocal(&scopesValue)) + return v8::MaybeLocal(); + v8::Local copied; + if (!copyValueFromDebuggerContext(m_isolate, debuggerContext(), context, + scopesValue) + .ToLocal(&copied) || + !copied->IsArray()) + return v8::MaybeLocal(); + if (!markAsInternal(context, v8::Local::Cast(copied), + V8InternalValueType::kScopeList)) + return v8::MaybeLocal(); + if (!markArrayEntriesAsInternal(context, v8::Local::Cast(copied), + V8InternalValueType::kScope)) + return v8::MaybeLocal(); + return copied; +} + +v8::MaybeLocal V8Debugger::internalProperties( + v8::Local context, v8::Local value) { + v8::Local properties; + if (!v8::Debug::GetInternalProperties(m_isolate, value).ToLocal(&properties)) + return v8::MaybeLocal(); + if (value->IsFunction()) { + v8::Local function = value.As(); + v8::Local location = functionLocation(context, function); + if (location->IsObject()) { + createDataProperty( + context, properties, properties->Length(), + toV8StringInternalized(m_isolate, "[[FunctionLocation]]")); + createDataProperty(context, properties, properties->Length(), location); + } + if (function->IsGeneratorFunction()) { + createDataProperty(context, properties, properties->Length(), + toV8StringInternalized(m_isolate, "[[IsGenerator]]")); + createDataProperty(context, properties, properties->Length(), + v8::True(m_isolate)); + } + } + if (!enabled()) return properties; + if (value->IsMap() || value->IsWeakMap() || value->IsSet() || + value->IsWeakSet() || value->IsSetIterator() || value->IsMapIterator()) { + v8::Local entries = + collectionEntries(context, v8::Local::Cast(value)); + if (entries->IsArray()) { + createDataProperty(context, properties, properties->Length(), + toV8StringInternalized(m_isolate, "[[Entries]]")); + createDataProperty(context, properties, properties->Length(), entries); + } + } + if (value->IsGeneratorObject()) { + v8::Local location = + generatorObjectLocation(context, v8::Local::Cast(value)); + if (location->IsObject()) { + createDataProperty( + context, properties, properties->Length(), + toV8StringInternalized(m_isolate, "[[GeneratorLocation]]")); + createDataProperty(context, properties, properties->Length(), location); + } + } + if (value->IsFunction()) { + v8::Local function = value.As(); + v8::Local boundFunction = function->GetBoundFunction(); + v8::Local scopes; + if (boundFunction->IsUndefined() && + functionScopes(context, function).ToLocal(&scopes)) { + createDataProperty(context, properties, properties->Length(), + toV8StringInternalized(m_isolate, "[[Scopes]]")); + createDataProperty(context, properties, properties->Length(), scopes); + } + } + return properties; +} + +v8::Local V8Debugger::collectionEntries( + v8::Local context, v8::Local object) { + if (!enabled()) { + UNREACHABLE(); + return v8::Undefined(m_isolate); + } + v8::Local argv[] = {object}; + v8::Local entriesValue = + callDebuggerMethod("getCollectionEntries", 1, argv).ToLocalChecked(); + if (!entriesValue->IsArray()) return v8::Undefined(m_isolate); + + v8::Local entries = entriesValue.As(); + v8::Local copiedArray = + v8::Array::New(m_isolate, entries->Length()); + if (!copiedArray->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false)) + return v8::Undefined(m_isolate); + for (uint32_t i = 0; i < entries->Length(); ++i) { + v8::Local item; + if (!entries->Get(debuggerContext(), i).ToLocal(&item)) + return v8::Undefined(m_isolate); + v8::Local copied; + if (!copyValueFromDebuggerContext(m_isolate, debuggerContext(), context, + item) + .ToLocal(&copied)) + return v8::Undefined(m_isolate); + if (!createDataProperty(context, copiedArray, i, copied).FromMaybe(false)) + return v8::Undefined(m_isolate); + } + if (!markArrayEntriesAsInternal(context, + v8::Local::Cast(copiedArray), + V8InternalValueType::kEntry)) + return v8::Undefined(m_isolate); + return copiedArray; +} + +v8::Local V8Debugger::generatorObjectLocation( + v8::Local context, v8::Local object) { + if (!enabled()) { + UNREACHABLE(); + return v8::Null(m_isolate); + } + v8::Local argv[] = {object}; + v8::Local location = + callDebuggerMethod("getGeneratorObjectLocation", 1, argv) + .ToLocalChecked(); + v8::Local copied; + if (!copyValueFromDebuggerContext(m_isolate, debuggerContext(), context, + location) + .ToLocal(&copied) || + !copied->IsObject()) + return v8::Null(m_isolate); + if (!markAsInternal(context, v8::Local::Cast(copied), + V8InternalValueType::kLocation)) + return v8::Null(m_isolate); + return copied; +} + +v8::Local V8Debugger::functionLocation( + v8::Local context, v8::Local function) { + int scriptId = function->ScriptId(); + if (scriptId == v8::UnboundScript::kNoScriptId) return v8::Null(m_isolate); + int lineNumber = function->GetScriptLineNumber(); + int columnNumber = function->GetScriptColumnNumber(); + if (lineNumber == v8::Function::kLineOffsetNotFound || + columnNumber == v8::Function::kLineOffsetNotFound) + return v8::Null(m_isolate); + v8::Local location = v8::Object::New(m_isolate); + if (!location->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false)) + return v8::Null(m_isolate); + if (!createDataProperty( + context, location, toV8StringInternalized(m_isolate, "scriptId"), + toV8String(m_isolate, String16::fromInteger(scriptId))) + .FromMaybe(false)) + return v8::Null(m_isolate); + if (!createDataProperty(context, location, + toV8StringInternalized(m_isolate, "lineNumber"), + v8::Integer::New(m_isolate, lineNumber)) + .FromMaybe(false)) + return v8::Null(m_isolate); + if (!createDataProperty(context, location, + toV8StringInternalized(m_isolate, "columnNumber"), + v8::Integer::New(m_isolate, columnNumber)) + .FromMaybe(false)) + return v8::Null(m_isolate); + if (!markAsInternal(context, location, V8InternalValueType::kLocation)) + return v8::Null(m_isolate); + return location; +} + +bool V8Debugger::isPaused() { return !m_pausedContext.IsEmpty(); } + +std::unique_ptr V8Debugger::createStackTrace( + v8::Local stackTrace) { + int contextGroupId = + m_isolate->InContext() ? getGroupId(m_isolate->GetCurrentContext()) : 0; + return V8StackTraceImpl::create(this, contextGroupId, stackTrace, + V8StackTraceImpl::maxCallStackSizeToCapture); +} + +int V8Debugger::markContext(const V8ContextInfo& info) { + DCHECK(info.context->GetIsolate() == m_isolate); + int contextId = ++m_lastContextId; + String16 debugData = String16::fromInteger(info.contextGroupId) + "," + + String16::fromInteger(contextId) + "," + + toString16(info.auxData); + v8::Context::Scope contextScope(info.context); + info.context->SetEmbedderData(static_cast(v8::Context::kDebugIdIndex), + toV8String(m_isolate, debugData)); + return contextId; +} + +void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { + if (depth <= 0) + m_maxAsyncCallStackDepthMap.erase(agent); + else + m_maxAsyncCallStackDepthMap[agent] = depth; + + int maxAsyncCallStackDepth = 0; + for (const auto& pair : m_maxAsyncCallStackDepthMap) { + if (pair.second > maxAsyncCallStackDepth) + maxAsyncCallStackDepth = pair.second; + } + + if (m_maxAsyncCallStackDepth == maxAsyncCallStackDepth) return; + m_maxAsyncCallStackDepth = maxAsyncCallStackDepth; + if (!maxAsyncCallStackDepth) allAsyncTasksCanceled(); +} + +void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, + bool recurring) { + if (!m_maxAsyncCallStackDepth) return; + asyncTaskScheduled(toString16(taskName), task, recurring); +} + +void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, + bool recurring) { + if (!m_maxAsyncCallStackDepth) return; + v8::HandleScope scope(m_isolate); + int contextGroupId = + m_isolate->InContext() ? getGroupId(m_isolate->GetCurrentContext()) : 0; + std::unique_ptr chain = V8StackTraceImpl::capture( + this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, + taskName); + if (chain) { + m_asyncTaskStacks[task] = std::move(chain); + if (recurring) m_recurringTasks.insert(task); + } +} + +void V8Debugger::asyncTaskCanceled(void* task) { + if (!m_maxAsyncCallStackDepth) return; + m_asyncTaskStacks.erase(task); + m_recurringTasks.erase(task); +} + +void V8Debugger::asyncTaskStarted(void* task) { + if (!m_maxAsyncCallStackDepth) return; + m_currentTasks.push_back(task); + AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find(task); + // Needs to support following order of events: + // - asyncTaskScheduled + // <-- attached here --> + // - asyncTaskStarted + // - asyncTaskCanceled <-- canceled before finished + // <-- async stack requested here --> + // - asyncTaskFinished + std::unique_ptr stack; + if (stackIt != m_asyncTaskStacks.end() && stackIt->second) + stack = stackIt->second->cloneImpl(); + m_currentStacks.push_back(std::move(stack)); +} + +void V8Debugger::asyncTaskFinished(void* task) { + if (!m_maxAsyncCallStackDepth) return; + // We could start instrumenting half way and the stack is empty. + if (!m_currentStacks.size()) return; + + DCHECK(m_currentTasks.back() == task); + m_currentTasks.pop_back(); + + m_currentStacks.pop_back(); + if (m_recurringTasks.find(task) == m_recurringTasks.end()) + m_asyncTaskStacks.erase(task); +} + +void V8Debugger::allAsyncTasksCanceled() { + m_asyncTaskStacks.clear(); + m_recurringTasks.clear(); + m_currentStacks.clear(); + m_currentTasks.clear(); +} + +void V8Debugger::muteScriptParsedEvents() { + ++m_ignoreScriptParsedEventsCounter; +} + +void V8Debugger::unmuteScriptParsedEvents() { + --m_ignoreScriptParsedEventsCounter; + DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); +} + +std::unique_ptr V8Debugger::captureStackTrace( + bool fullStack) { + if (!m_isolate->InContext()) return nullptr; + + v8::HandleScope handles(m_isolate); + int contextGroupId = getGroupId(m_isolate->GetCurrentContext()); + if (!contextGroupId) return nullptr; + + size_t stackSize = + fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; + if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) + stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; + + return V8StackTraceImpl::capture(this, contextGroupId, stackSize); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-debugger.h b/deps/v8_inspector/src/inspector/v8-debugger.h new file mode 100644 index 00000000000000..83c1b21b02a712 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-debugger.h @@ -0,0 +1,160 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8DEBUGGER_H_ +#define V8_INSPECTOR_V8DEBUGGER_H_ + +#include + +#include "src/base/macros.h" +#include "src/inspector/java-script-call-frame.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/Runtime.h" +#include "src/inspector/v8-debugger-script.h" + +#include "include/v8-debug.h" +#include "include/v8-inspector.h" + +namespace v8_inspector { + +struct ScriptBreakpoint; +class V8DebuggerAgentImpl; +class V8InspectorImpl; +class V8StackTraceImpl; + +using protocol::ErrorString; + +class V8Debugger { + public: + V8Debugger(v8::Isolate*, V8InspectorImpl*); + ~V8Debugger(); + + static int contextId(v8::Local); + static int getGroupId(v8::Local); + int markContext(const V8ContextInfo&); + + bool enabled() const; + + String16 setBreakpoint(const String16& sourceID, const ScriptBreakpoint&, + int* actualLineNumber, int* actualColumnNumber); + void removeBreakpoint(const String16& breakpointId); + void setBreakpointsActivated(bool); + bool breakpointsActivated() const { return m_breakpointsActivated; } + + enum PauseOnExceptionsState { + DontPauseOnExceptions, + PauseOnAllExceptions, + PauseOnUncaughtExceptions + }; + PauseOnExceptionsState getPauseOnExceptionsState(); + void setPauseOnExceptionsState(PauseOnExceptionsState); + void setPauseOnNextStatement(bool); + bool canBreakProgram(); + void breakProgram(); + void continueProgram(); + void stepIntoStatement(); + void stepOverStatement(); + void stepOutOfFunction(); + void clearStepping(); + + bool setScriptSource(const String16& sourceID, + v8::Local newSource, bool dryRun, + ErrorString*, + protocol::Maybe*, + JavaScriptCallFrames* newCallFrames, + protocol::Maybe* stackChanged); + JavaScriptCallFrames currentCallFrames(int limit = 0); + + // Each script inherits debug data from v8::Context where it has been + // compiled. + // Only scripts whose debug data matches |contextGroupId| will be reported. + // Passing 0 will result in reporting all scripts. + void getCompiledScripts(int contextGroupId, + std::vector>&); + void enable(); + void disable(); + + bool isPaused(); + v8::Local pausedContext() { return m_pausedContext; } + + int maxAsyncCallChainDepth() { return m_maxAsyncCallStackDepth; } + V8StackTraceImpl* currentAsyncCallChain(); + void setAsyncCallStackDepth(V8DebuggerAgentImpl*, int); + std::unique_ptr createStackTrace(v8::Local); + std::unique_ptr captureStackTrace(bool fullStack); + + v8::MaybeLocal internalProperties(v8::Local, + v8::Local); + + void asyncTaskScheduled(const StringView& taskName, void* task, + bool recurring); + void asyncTaskScheduled(const String16& taskName, void* task, bool recurring); + void asyncTaskCanceled(void* task); + void asyncTaskStarted(void* task); + void asyncTaskFinished(void* task); + void allAsyncTasksCanceled(); + + void muteScriptParsedEvents(); + void unmuteScriptParsedEvents(); + + V8InspectorImpl* inspector() { return m_inspector; } + + private: + void compileDebuggerScript(); + v8::MaybeLocal callDebuggerMethod(const char* functionName, + int argc, + v8::Local argv[]); + v8::Local debuggerContext() const; + void clearBreakpoints(); + + static void breakProgramCallback(const v8::FunctionCallbackInfo&); + void handleProgramBreak(v8::Local pausedContext, + v8::Local executionState, + v8::Local exception, + v8::Local hitBreakpoints, + bool isPromiseRejection = false); + static void v8DebugEventCallback(const v8::Debug::EventDetails&); + v8::Local callInternalGetterFunction(v8::Local, + const char* functionName); + void handleV8DebugEvent(const v8::Debug::EventDetails&); + void handleV8AsyncTaskEvent(v8::Local, + v8::Local executionState, + v8::Local eventData); + + v8::Local collectionEntries(v8::Local, + v8::Local); + v8::Local generatorObjectLocation(v8::Local, + v8::Local); + v8::Local functionLocation(v8::Local, + v8::Local); + v8::MaybeLocal functionScopes(v8::Local, + v8::Local); + + v8::Isolate* m_isolate; + V8InspectorImpl* m_inspector; + int m_lastContextId; + int m_enableCount; + bool m_breakpointsActivated; + v8::Global m_debuggerScript; + v8::Global m_debuggerContext; + v8::Local m_executionState; + v8::Local m_pausedContext; + bool m_runningNestedMessageLoop; + int m_ignoreScriptParsedEventsCounter; + + using AsyncTaskToStackTrace = + protocol::HashMap>; + AsyncTaskToStackTrace m_asyncTaskStacks; + protocol::HashSet m_recurringTasks; + int m_maxAsyncCallStackDepth; + std::vector m_currentTasks; + std::vector> m_currentStacks; + protocol::HashMap m_maxAsyncCallStackDepthMap; + + DISALLOW_COPY_AND_ASSIGN(V8Debugger); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8DEBUGGER_H_ diff --git a/deps/v8_inspector/src/inspector/v8-function-call.cc b/deps/v8_inspector/src/inspector/v8-function-call.cc new file mode 100644 index 00000000000000..3880e3100e497e --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-function-call.cc @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009 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. + */ + +#include "src/inspector/v8-function-call.h" + +#include "src/inspector/string-util.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-impl.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +V8FunctionCall::V8FunctionCall(V8InspectorImpl* inspector, + v8::Local context, + v8::Local value, const String16& name) + : m_inspector(inspector), + m_context(context), + m_name(toV8String(context->GetIsolate(), name)), + m_value(value) {} + +void V8FunctionCall::appendArgument(v8::Local value) { + m_arguments.push_back(value); +} + +void V8FunctionCall::appendArgument(const String16& argument) { + m_arguments.push_back(toV8String(m_context->GetIsolate(), argument)); +} + +void V8FunctionCall::appendArgument(int argument) { + m_arguments.push_back(v8::Number::New(m_context->GetIsolate(), argument)); +} + +void V8FunctionCall::appendArgument(bool argument) { + m_arguments.push_back(argument ? v8::True(m_context->GetIsolate()) + : v8::False(m_context->GetIsolate())); +} + +v8::Local V8FunctionCall::call(bool& hadException, + bool reportExceptions) { + v8::TryCatch tryCatch(m_context->GetIsolate()); + tryCatch.SetVerbose(reportExceptions); + + v8::Local result = callWithoutExceptionHandling(); + hadException = tryCatch.HasCaught(); + return result; +} + +v8::Local V8FunctionCall::callWithoutExceptionHandling() { + v8::Local thisObject = v8::Local::Cast(m_value); + v8::Local value; + if (!thisObject->Get(m_context, m_name).ToLocal(&value)) + return v8::Local(); + + DCHECK(value->IsFunction()); + + v8::Local function = v8::Local::Cast(value); + std::unique_ptr[]> info( + new v8::Local[m_arguments.size()]); + for (size_t i = 0; i < m_arguments.size(); ++i) { + info[i] = m_arguments[i]; + DCHECK(!info[i].IsEmpty()); + } + + int contextGroupId = V8Debugger::getGroupId(m_context); + if (contextGroupId) { + m_inspector->client()->muteMetrics(contextGroupId); + m_inspector->muteExceptions(contextGroupId); + } + v8::MicrotasksScope microtasksScope(m_context->GetIsolate(), + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::MaybeLocal maybeResult = function->Call( + m_context, thisObject, static_cast(m_arguments.size()), info.get()); + if (contextGroupId) { + m_inspector->client()->unmuteMetrics(contextGroupId); + m_inspector->unmuteExceptions(contextGroupId); + } + + v8::Local result; + if (!maybeResult.ToLocal(&result)) return v8::Local(); + return result; +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8FunctionCall.h b/deps/v8_inspector/src/inspector/v8-function-call.h similarity index 66% rename from deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8FunctionCall.h rename to deps/v8_inspector/src/inspector/v8-function-call.h index d853644888c5fc..0337caa339e202 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8FunctionCall.h +++ b/deps/v8_inspector/src/inspector/v8-function-call.h @@ -28,39 +28,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef V8FunctionCall_h -#define V8FunctionCall_h +#ifndef V8_INSPECTOR_V8FUNCTIONCALL_H_ +#define V8_INSPECTOR_V8FUNCTIONCALL_H_ -#include "platform/inspector_protocol/InspectorProtocol.h" +#include "src/inspector/string-16.h" -#include +#include "include/v8.h" namespace v8_inspector { class V8InspectorImpl; -namespace protocol = blink::protocol; - class V8FunctionCall { -public: - V8FunctionCall(V8InspectorImpl*, v8::Local, v8::Local, const String16& name); + public: + V8FunctionCall(V8InspectorImpl*, v8::Local, v8::Local, + const String16& name); - void appendArgument(v8::Local); - void appendArgument(const String16&); - void appendArgument(int); - void appendArgument(bool); + void appendArgument(v8::Local); + void appendArgument(const String16&); + void appendArgument(int); + void appendArgument(bool); - v8::Local call(bool& hadException, bool reportExceptions = true); - v8::Local callWithoutExceptionHandling(); + v8::Local call(bool& hadException, bool reportExceptions = true); + v8::Local callWithoutExceptionHandling(); -protected: - V8InspectorImpl* m_inspector; - v8::Local m_context; - std::vector> m_arguments; - v8::Local m_name; - v8::Local m_value; + protected: + V8InspectorImpl* m_inspector; + v8::Local m_context; + std::vector> m_arguments; + v8::Local m_name; + v8::Local m_value; }; -} // namespace v8_inspector +} // namespace v8_inspector -#endif // V8FunctionCall +#endif // V8_INSPECTOR_V8FUNCTIONCALL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-heap-profiler-agent-impl.cc b/deps/v8_inspector/src/inspector/v8-heap-profiler-agent-impl.cc new file mode 100644 index 00000000000000..84c890bf3f72bf --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-heap-profiler-agent-impl.cc @@ -0,0 +1,407 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-heap-profiler-agent-impl.h" + +#include "src/inspector/injected-script.h" +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" + +#include "include/v8-inspector.h" +#include "include/v8-profiler.h" +#include "include/v8-version.h" + +namespace v8_inspector { + +namespace { + +namespace HeapProfilerAgentState { +static const char heapProfilerEnabled[] = "heapProfilerEnabled"; +static const char heapObjectsTrackingEnabled[] = "heapObjectsTrackingEnabled"; +static const char allocationTrackingEnabled[] = "allocationTrackingEnabled"; +static const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled"; +static const char samplingHeapProfilerInterval[] = + "samplingHeapProfilerInterval"; +} + +class HeapSnapshotProgress final : public v8::ActivityControl { + public: + explicit HeapSnapshotProgress(protocol::HeapProfiler::Frontend* frontend) + : m_frontend(frontend) {} + ControlOption ReportProgressValue(int done, int total) override { + m_frontend->reportHeapSnapshotProgress(done, total, + protocol::Maybe()); + if (done >= total) { + m_frontend->reportHeapSnapshotProgress(total, total, true); + } + m_frontend->flush(); + return kContinue; + } + + private: + protocol::HeapProfiler::Frontend* m_frontend; +}; + +class GlobalObjectNameResolver final + : public v8::HeapProfiler::ObjectNameResolver { + public: + explicit GlobalObjectNameResolver(V8InspectorSessionImpl* session) + : m_offset(0), m_strings(10000), m_session(session) {} + + const char* GetName(v8::Local object) override { + InspectedContext* context = m_session->inspector()->getContext( + m_session->contextGroupId(), + V8Debugger::contextId(object->CreationContext())); + if (!context) return ""; + String16 name = context->origin(); + size_t length = name.length(); + if (m_offset + length + 1 >= m_strings.size()) return ""; + for (size_t i = 0; i < length; ++i) { + UChar ch = name[i]; + m_strings[m_offset + i] = ch > 0xff ? '?' : static_cast(ch); + } + m_strings[m_offset + length] = '\0'; + char* result = &*m_strings.begin() + m_offset; + m_offset += length + 1; + return result; + } + + private: + size_t m_offset; + std::vector m_strings; + V8InspectorSessionImpl* m_session; +}; + +class HeapSnapshotOutputStream final : public v8::OutputStream { + public: + explicit HeapSnapshotOutputStream(protocol::HeapProfiler::Frontend* frontend) + : m_frontend(frontend) {} + void EndOfStream() override {} + int GetChunkSize() override { return 102400; } + WriteResult WriteAsciiChunk(char* data, int size) override { + m_frontend->addHeapSnapshotChunk(String16(data, size)); + m_frontend->flush(); + return kContinue; + } + + private: + protocol::HeapProfiler::Frontend* m_frontend; +}; + +v8::Local objectByHeapObjectId(v8::Isolate* isolate, int id) { + v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); + v8::Local value = profiler->FindObjectById(id); + if (value.IsEmpty() || !value->IsObject()) return v8::Local(); + return value.As(); +} + +class InspectableHeapObject final : public V8InspectorSession::Inspectable { + public: + explicit InspectableHeapObject(int heapObjectId) + : m_heapObjectId(heapObjectId) {} + v8::Local get(v8::Local context) override { + return objectByHeapObjectId(context->GetIsolate(), m_heapObjectId); + } + + private: + int m_heapObjectId; +}; + +class HeapStatsStream final : public v8::OutputStream { + public: + explicit HeapStatsStream(protocol::HeapProfiler::Frontend* frontend) + : m_frontend(frontend) {} + + void EndOfStream() override {} + + WriteResult WriteAsciiChunk(char* data, int size) override { + DCHECK(false); + return kAbort; + } + + WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData, + int count) override { + DCHECK_GT(count, 0); + std::unique_ptr> statsDiff = + protocol::Array::create(); + for (int i = 0; i < count; ++i) { + statsDiff->addItem(updateData[i].index); + statsDiff->addItem(updateData[i].count); + statsDiff->addItem(updateData[i].size); + } + m_frontend->heapStatsUpdate(std::move(statsDiff)); + return kContinue; + } + + private: + protocol::HeapProfiler::Frontend* m_frontend; +}; + +} // namespace + +V8HeapProfilerAgentImpl::V8HeapProfilerAgentImpl( + V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, + protocol::DictionaryValue* state) + : m_session(session), + m_isolate(session->inspector()->isolate()), + m_frontend(frontendChannel), + m_state(state), + m_hasTimer(false) {} + +V8HeapProfilerAgentImpl::~V8HeapProfilerAgentImpl() {} + +void V8HeapProfilerAgentImpl::restore() { + if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled, + false)) + m_frontend.resetProfiles(); + if (m_state->booleanProperty( + HeapProfilerAgentState::heapObjectsTrackingEnabled, false)) + startTrackingHeapObjectsInternal(m_state->booleanProperty( + HeapProfilerAgentState::allocationTrackingEnabled, false)); + if (m_state->booleanProperty( + HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { + ErrorString error; + double samplingInterval = m_state->doubleProperty( + HeapProfilerAgentState::samplingHeapProfilerInterval, -1); + DCHECK_GE(samplingInterval, 0); + startSampling(&error, Maybe(samplingInterval)); + } +} + +void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*) { + m_isolate->LowMemoryNotification(); +} + +void V8HeapProfilerAgentImpl::startTrackingHeapObjects( + ErrorString*, const protocol::Maybe& trackAllocations) { + m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true); + bool allocationTrackingEnabled = trackAllocations.fromMaybe(false); + m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, + allocationTrackingEnabled); + startTrackingHeapObjectsInternal(allocationTrackingEnabled); +} + +void V8HeapProfilerAgentImpl::stopTrackingHeapObjects( + ErrorString* error, const protocol::Maybe& reportProgress) { + requestHeapStatsUpdate(); + takeHeapSnapshot(error, reportProgress); + stopTrackingHeapObjectsInternal(); +} + +void V8HeapProfilerAgentImpl::enable(ErrorString*) { + m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true); +} + +void V8HeapProfilerAgentImpl::disable(ErrorString* error) { + stopTrackingHeapObjectsInternal(); + if (m_state->booleanProperty( + HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { + v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); + if (profiler) profiler->StopSamplingHeapProfiler(); + } + m_isolate->GetHeapProfiler()->ClearObjectIds(); + m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false); +} + +void V8HeapProfilerAgentImpl::takeHeapSnapshot( + ErrorString* errorString, const protocol::Maybe& reportProgress) { + v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); + if (!profiler) { + *errorString = "Cannot access v8 heap profiler"; + return; + } + std::unique_ptr progress; + if (reportProgress.fromMaybe(false)) + progress = wrapUnique(new HeapSnapshotProgress(&m_frontend)); + + GlobalObjectNameResolver resolver(m_session); + const v8::HeapSnapshot* snapshot = + profiler->TakeHeapSnapshot(progress.get(), &resolver); + if (!snapshot) { + *errorString = "Failed to take heap snapshot"; + return; + } + HeapSnapshotOutputStream stream(&m_frontend); + snapshot->Serialize(&stream); + const_cast(snapshot)->Delete(); +} + +void V8HeapProfilerAgentImpl::getObjectByHeapObjectId( + ErrorString* error, const String16& heapSnapshotObjectId, + const protocol::Maybe& objectGroup, + std::unique_ptr* result) { + bool ok; + int id = heapSnapshotObjectId.toInteger(&ok); + if (!ok) { + *error = "Invalid heap snapshot object id"; + return; + } + + v8::HandleScope handles(m_isolate); + v8::Local heapObject = objectByHeapObjectId(m_isolate, id); + if (heapObject.IsEmpty()) { + *error = "Object is not available"; + return; + } + + if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) { + *error = "Object is not available"; + return; + } + + *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, + objectGroup.fromMaybe(""), false); + if (!result) *error = "Object is not available"; +} + +void V8HeapProfilerAgentImpl::addInspectedHeapObject( + ErrorString* errorString, const String16& inspectedHeapObjectId) { + bool ok; + int id = inspectedHeapObjectId.toInteger(&ok); + if (!ok) { + *errorString = "Invalid heap snapshot object id"; + return; + } + + v8::HandleScope handles(m_isolate); + v8::Local heapObject = objectByHeapObjectId(m_isolate, id); + if (heapObject.IsEmpty()) { + *errorString = "Object is not available"; + return; + } + + if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) { + *errorString = "Object is not available"; + return; + } + + m_session->addInspectedObject(wrapUnique(new InspectableHeapObject(id))); +} + +void V8HeapProfilerAgentImpl::getHeapObjectId(ErrorString* errorString, + const String16& objectId, + String16* heapSnapshotObjectId) { + v8::HandleScope handles(m_isolate); + v8::Local value; + v8::Local context; + if (!m_session->unwrapObject(errorString, objectId, &value, &context, + nullptr) || + value->IsUndefined()) + return; + + v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value); + *heapSnapshotObjectId = String16::fromInteger(static_cast(id)); +} + +void V8HeapProfilerAgentImpl::requestHeapStatsUpdate() { + HeapStatsStream stream(&m_frontend); + v8::SnapshotObjectId lastSeenObjectId = + m_isolate->GetHeapProfiler()->GetHeapStats(&stream); + m_frontend.lastSeenObjectId( + lastSeenObjectId, m_session->inspector()->client()->currentTimeMS()); +} + +// static +void V8HeapProfilerAgentImpl::onTimer(void* data) { + reinterpret_cast(data)->requestHeapStatsUpdate(); +} + +void V8HeapProfilerAgentImpl::startTrackingHeapObjectsInternal( + bool trackAllocations) { + m_isolate->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations); + if (!m_hasTimer) { + m_hasTimer = true; + m_session->inspector()->client()->startRepeatingTimer( + 0.05, &V8HeapProfilerAgentImpl::onTimer, reinterpret_cast(this)); + } +} + +void V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal() { + if (m_hasTimer) { + m_session->inspector()->client()->cancelTimer( + reinterpret_cast(this)); + m_hasTimer = false; + } + m_isolate->GetHeapProfiler()->StopTrackingHeapObjects(); + m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, + false); + m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false); +} + +void V8HeapProfilerAgentImpl::startSampling( + ErrorString* errorString, const Maybe& samplingInterval) { + v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); + if (!profiler) { + *errorString = "Cannot access v8 heap profiler"; + return; + } + const unsigned defaultSamplingInterval = 1 << 15; + double samplingIntervalValue = + samplingInterval.fromMaybe(defaultSamplingInterval); + m_state->setDouble(HeapProfilerAgentState::samplingHeapProfilerInterval, + samplingIntervalValue); + m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, + true); + profiler->StartSamplingHeapProfiler( + static_cast(samplingIntervalValue), 128, + v8::HeapProfiler::kSamplingForceGC); +} + +namespace { +std::unique_ptr +buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node) { + auto children = protocol::Array< + protocol::HeapProfiler::SamplingHeapProfileNode>::create(); + for (const auto* child : node->children) + children->addItem(buildSampingHeapProfileNode(child)); + size_t selfSize = 0; + for (const auto& allocation : node->allocations) + selfSize += allocation.size * allocation.count; + std::unique_ptr callFrame = + protocol::Runtime::CallFrame::create() + .setFunctionName(toProtocolString(node->name)) + .setScriptId(String16::fromInteger(node->script_id)) + .setUrl(toProtocolString(node->script_name)) + .setLineNumber(node->line_number - 1) + .setColumnNumber(node->column_number - 1) + .build(); + std::unique_ptr result = + protocol::HeapProfiler::SamplingHeapProfileNode::create() + .setCallFrame(std::move(callFrame)) + .setSelfSize(selfSize) + .setChildren(std::move(children)) + .build(); + return result; +} +} // namespace + +void V8HeapProfilerAgentImpl::stopSampling( + ErrorString* errorString, + std::unique_ptr* profile) { + v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); + if (!profiler) { + *errorString = "Cannot access v8 heap profiler"; + return; + } + v8::HandleScope scope( + m_isolate); // Allocation profile contains Local handles. + std::unique_ptr v8Profile( + profiler->GetAllocationProfile()); + profiler->StopSamplingHeapProfiler(); + m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, + false); + if (!v8Profile) { + *errorString = "Cannot access v8 sampled heap profile."; + return; + } + v8::AllocationProfile::Node* root = v8Profile->GetRootNode(); + *profile = protocol::HeapProfiler::SamplingHeapProfile::create() + .setHead(buildSampingHeapProfileNode(root)) + .build(); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-heap-profiler-agent-impl.h b/deps/v8_inspector/src/inspector/v8-heap-profiler-agent-impl.h new file mode 100644 index 00000000000000..caa969870bacc5 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-heap-profiler-agent-impl.h @@ -0,0 +1,73 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8HEAPPROFILERAGENTIMPL_H_ +#define V8_INSPECTOR_V8HEAPPROFILERAGENTIMPL_H_ + +#include "src/base/macros.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/HeapProfiler.h" + +#include "include/v8.h" + +namespace v8_inspector { + +class V8InspectorSessionImpl; + +using protocol::ErrorString; +using protocol::Maybe; + +class V8HeapProfilerAgentImpl : public protocol::HeapProfiler::Backend { + public: + V8HeapProfilerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, + protocol::DictionaryValue* state); + ~V8HeapProfilerAgentImpl() override; + void restore(); + + void collectGarbage(ErrorString*) override; + + void enable(ErrorString*) override; + void startTrackingHeapObjects(ErrorString*, + const Maybe& trackAllocations) override; + void stopTrackingHeapObjects(ErrorString*, + const Maybe& reportProgress) override; + + void disable(ErrorString*) override; + + void takeHeapSnapshot(ErrorString*, + const Maybe& reportProgress) override; + + void getObjectByHeapObjectId( + ErrorString*, const String16& heapSnapshotObjectId, + const Maybe& objectGroup, + std::unique_ptr* result) override; + void addInspectedHeapObject(ErrorString*, + const String16& inspectedHeapObjectId) override; + void getHeapObjectId(ErrorString*, const String16& objectId, + String16* heapSnapshotObjectId) override; + + void startSampling(ErrorString*, + const Maybe& samplingInterval) override; + void stopSampling( + ErrorString*, + std::unique_ptr*) override; + + private: + void startTrackingHeapObjectsInternal(bool trackAllocations); + void stopTrackingHeapObjectsInternal(); + void requestHeapStatsUpdate(); + static void onTimer(void*); + + V8InspectorSessionImpl* m_session; + v8::Isolate* m_isolate; + protocol::HeapProfiler::Frontend m_frontend; + protocol::DictionaryValue* m_state; + bool m_hasTimer; + + DISALLOW_COPY_AND_ASSIGN(V8HeapProfilerAgentImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8HEAPPROFILERAGENTIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-injected-script-host.cc b/deps/v8_inspector/src/inspector/v8-injected-script-host.cc new file mode 100644 index 00000000000000..dc41ef8631febe --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-injected-script-host.cc @@ -0,0 +1,216 @@ +// Copyright 2015 the V8 project 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 "src/inspector/v8-injected-script-host.h" + +#include "src/base/macros.h" +#include "src/inspector/injected-script-native.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-internal-value-type.h" +#include "src/inspector/v8-value-copier.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +namespace { + +void setFunctionProperty(v8::Local context, + v8::Local obj, const char* name, + v8::FunctionCallback callback, + v8::Local external) { + v8::Local funcName = + toV8StringInternalized(context->GetIsolate(), name); + v8::Local func; + if (!v8::Function::New(context, callback, external, 0, + v8::ConstructorBehavior::kThrow) + .ToLocal(&func)) + return; + func->SetName(funcName); + createDataProperty(context, obj, funcName, func); +} + +V8InspectorImpl* unwrapInspector( + const v8::FunctionCallbackInfo& info) { + DCHECK(!info.Data().IsEmpty()); + DCHECK(info.Data()->IsExternal()); + V8InspectorImpl* inspector = + static_cast(info.Data().As()->Value()); + DCHECK(inspector); + return inspector; +} + +} // namespace + +v8::Local V8InjectedScriptHost::create( + v8::Local context, V8InspectorImpl* inspector) { + v8::Isolate* isolate = inspector->isolate(); + v8::Local injectedScriptHost = v8::Object::New(isolate); + bool success = injectedScriptHost->SetPrototype(context, v8::Null(isolate)) + .FromMaybe(false); + DCHECK(success); + USE(success); + v8::Local debuggerExternal = + v8::External::New(isolate, inspector); + setFunctionProperty(context, injectedScriptHost, "internalConstructorName", + V8InjectedScriptHost::internalConstructorNameCallback, + debuggerExternal); + setFunctionProperty( + context, injectedScriptHost, "formatAccessorsAsProperties", + V8InjectedScriptHost::formatAccessorsAsProperties, debuggerExternal); + setFunctionProperty(context, injectedScriptHost, "subtype", + V8InjectedScriptHost::subtypeCallback, debuggerExternal); + setFunctionProperty(context, injectedScriptHost, "getInternalProperties", + V8InjectedScriptHost::getInternalPropertiesCallback, + debuggerExternal); + setFunctionProperty(context, injectedScriptHost, "objectHasOwnProperty", + V8InjectedScriptHost::objectHasOwnPropertyCallback, + debuggerExternal); + setFunctionProperty(context, injectedScriptHost, "bind", + V8InjectedScriptHost::bindCallback, debuggerExternal); + setFunctionProperty(context, injectedScriptHost, "proxyTargetValue", + V8InjectedScriptHost::proxyTargetValueCallback, + debuggerExternal); + return injectedScriptHost; +} + +void V8InjectedScriptHost::internalConstructorNameCallback( + const v8::FunctionCallbackInfo& info) { + if (info.Length() < 1 || !info[0]->IsObject()) return; + + v8::Local object = info[0].As(); + info.GetReturnValue().Set(object->GetConstructorName()); +} + +void V8InjectedScriptHost::formatAccessorsAsProperties( + const v8::FunctionCallbackInfo& info) { + DCHECK_EQ(info.Length(), 2); + info.GetReturnValue().Set(false); + if (!info[1]->IsFunction()) return; + // Check that function is user-defined. + if (info[1].As()->ScriptId() != v8::UnboundScript::kNoScriptId) + return; + info.GetReturnValue().Set( + unwrapInspector(info)->client()->formatAccessorsAsProperties(info[0])); +} + +void V8InjectedScriptHost::subtypeCallback( + const v8::FunctionCallbackInfo& info) { + if (info.Length() < 1) return; + + v8::Isolate* isolate = info.GetIsolate(); + v8::Local value = info[0]; + if (value->IsObject()) { + v8::Local internalType = v8InternalValueTypeFrom( + isolate->GetCurrentContext(), v8::Local::Cast(value)); + if (internalType->IsString()) { + info.GetReturnValue().Set(internalType); + return; + } + } + if (value->IsArray() || value->IsArgumentsObject()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "array")); + return; + } + if (value->IsTypedArray()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "typedarray")); + return; + } + if (value->IsDate()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "date")); + return; + } + if (value->IsRegExp()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "regexp")); + return; + } + if (value->IsMap() || value->IsWeakMap()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "map")); + return; + } + if (value->IsSet() || value->IsWeakSet()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "set")); + return; + } + if (value->IsMapIterator() || value->IsSetIterator()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "iterator")); + return; + } + if (value->IsGeneratorObject()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "generator")); + return; + } + if (value->IsNativeError()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "error")); + return; + } + if (value->IsProxy()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "proxy")); + return; + } + if (value->IsPromise()) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "promise")); + return; + } + std::unique_ptr subtype = + unwrapInspector(info)->client()->valueSubtype(value); + if (subtype) { + info.GetReturnValue().Set(toV8String(isolate, subtype->string())); + return; + } +} + +void V8InjectedScriptHost::getInternalPropertiesCallback( + const v8::FunctionCallbackInfo& info) { + if (info.Length() < 1) return; + v8::Local properties; + if (unwrapInspector(info) + ->debugger() + ->internalProperties(info.GetIsolate()->GetCurrentContext(), info[0]) + .ToLocal(&properties)) + info.GetReturnValue().Set(properties); +} + +void V8InjectedScriptHost::objectHasOwnPropertyCallback( + const v8::FunctionCallbackInfo& info) { + if (info.Length() < 2 || !info[0]->IsObject() || !info[1]->IsString()) return; + bool result = info[0] + .As() + ->HasOwnProperty(info.GetIsolate()->GetCurrentContext(), + v8::Local::Cast(info[1])) + .FromMaybe(false); + info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), result)); +} + +void V8InjectedScriptHost::bindCallback( + const v8::FunctionCallbackInfo& info) { + if (info.Length() < 2 || !info[1]->IsString()) return; + InjectedScriptNative* injectedScriptNative = + InjectedScriptNative::fromInjectedScriptHost(info.GetIsolate(), + info.Holder()); + if (!injectedScriptNative) return; + + v8::Local context = info.GetIsolate()->GetCurrentContext(); + v8::Local v8groupName = + info[1]->ToString(context).ToLocalChecked(); + String16 groupName = toProtocolStringWithTypeCheck(v8groupName); + int id = injectedScriptNative->bind(info[0], groupName); + info.GetReturnValue().Set(id); +} + +void V8InjectedScriptHost::proxyTargetValueCallback( + const v8::FunctionCallbackInfo& info) { + if (info.Length() != 1 || !info[0]->IsProxy()) { + UNREACHABLE(); + return; + } + v8::Local target = info[0].As(); + while (target->IsProxy()) + target = v8::Local::Cast(target)->GetTarget(); + info.GetReturnValue().Set(target); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-injected-script-host.h b/deps/v8_inspector/src/inspector/v8-injected-script-host.h new file mode 100644 index 00000000000000..7d293af5a754d8 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-injected-script-host.h @@ -0,0 +1,46 @@ +// Copyright 2015 the V8 project 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 V8_INSPECTOR_V8INJECTEDSCRIPTHOST_H_ +#define V8_INSPECTOR_V8INJECTEDSCRIPTHOST_H_ + +#include "include/v8.h" + +namespace v8_inspector { + +class V8InspectorImpl; + +// SECURITY NOTE: Although the InjectedScriptHost is intended for use solely by +// the inspector, +// a reference to the InjectedScriptHost may be leaked to the page being +// inspected. Thus, the +// InjectedScriptHost must never implemment methods that have more power over +// the page than the +// page already has itself (e.g. origin restriction bypasses). + +class V8InjectedScriptHost { + public: + // We expect that debugger outlives any JS context and thus + // V8InjectedScriptHost (owned by JS) + // is destroyed before inspector. + static v8::Local create(v8::Local, V8InspectorImpl*); + + private: + static void internalConstructorNameCallback( + const v8::FunctionCallbackInfo&); + static void formatAccessorsAsProperties( + const v8::FunctionCallbackInfo&); + static void subtypeCallback(const v8::FunctionCallbackInfo&); + static void getInternalPropertiesCallback( + const v8::FunctionCallbackInfo&); + static void objectHasOwnPropertyCallback( + const v8::FunctionCallbackInfo&); + static void bindCallback(const v8::FunctionCallbackInfo&); + static void proxyTargetValueCallback( + const v8::FunctionCallbackInfo&); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8INJECTEDSCRIPTHOST_H_ diff --git a/deps/v8_inspector/src/inspector/v8-inspector-impl.cc b/deps/v8_inspector/src/inspector/v8-inspector-impl.cc new file mode 100644 index 00000000000000..bd68548fbf9f82 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-inspector-impl.cc @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2010-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. + */ + +#include "src/inspector/v8-inspector-impl.h" + +#include "src/inspector/inspected-context.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-console-agent-impl.h" +#include "src/inspector/v8-console-message.h" +#include "src/inspector/v8-debugger-agent-impl.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-profiler-agent-impl.h" +#include "src/inspector/v8-runtime-agent-impl.h" +#include "src/inspector/v8-stack-trace-impl.h" + +namespace v8_inspector { + +std::unique_ptr V8Inspector::create(v8::Isolate* isolate, + V8InspectorClient* client) { + return wrapUnique(new V8InspectorImpl(isolate, client)); +} + +V8InspectorImpl::V8InspectorImpl(v8::Isolate* isolate, + V8InspectorClient* client) + : m_isolate(isolate), + m_client(client), + m_debugger(new V8Debugger(isolate, this)), + m_capturingStackTracesCount(0), + m_lastExceptionId(0) {} + +V8InspectorImpl::~V8InspectorImpl() {} + +V8DebuggerAgentImpl* V8InspectorImpl::enabledDebuggerAgentForGroup( + int contextGroupId) { + V8InspectorSessionImpl* session = sessionForContextGroup(contextGroupId); + V8DebuggerAgentImpl* agent = session ? session->debuggerAgent() : nullptr; + return agent && agent->enabled() ? agent : nullptr; +} + +V8RuntimeAgentImpl* V8InspectorImpl::enabledRuntimeAgentForGroup( + int contextGroupId) { + V8InspectorSessionImpl* session = sessionForContextGroup(contextGroupId); + V8RuntimeAgentImpl* agent = session ? session->runtimeAgent() : nullptr; + return agent && agent->enabled() ? agent : nullptr; +} + +V8ProfilerAgentImpl* V8InspectorImpl::enabledProfilerAgentForGroup( + int contextGroupId) { + V8InspectorSessionImpl* session = sessionForContextGroup(contextGroupId); + V8ProfilerAgentImpl* agent = session ? session->profilerAgent() : nullptr; + return agent && agent->enabled() ? agent : nullptr; +} + +v8::MaybeLocal V8InspectorImpl::runCompiledScript( + v8::Local context, v8::Local script) { + v8::MicrotasksScope microtasksScope(m_isolate, + v8::MicrotasksScope::kRunMicrotasks); + int groupId = V8Debugger::getGroupId(context); + if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) + agent->willExecuteScript(script->GetUnboundScript()->GetId()); + v8::MaybeLocal result = script->Run(context); + // Get agent from the map again, since it could have detached during script + // execution. + if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) + agent->didExecuteScript(); + return result; +} + +v8::MaybeLocal V8InspectorImpl::callFunction( + v8::Local function, v8::Local context, + v8::Local receiver, int argc, v8::Local info[]) { + v8::MicrotasksScope microtasksScope(m_isolate, + v8::MicrotasksScope::kRunMicrotasks); + int groupId = V8Debugger::getGroupId(context); + if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) + agent->willExecuteScript(function->ScriptId()); + v8::MaybeLocal result = + function->Call(context, receiver, argc, info); + // Get agent from the map again, since it could have detached during script + // execution. + if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) + agent->didExecuteScript(); + return result; +} + +v8::MaybeLocal V8InspectorImpl::compileAndRunInternalScript( + v8::Local context, v8::Local source) { + v8::Local script = + compileScript(context, source, String16(), true); + if (script.IsEmpty()) return v8::MaybeLocal(); + v8::MicrotasksScope microtasksScope(m_isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + return script->Run(context); +} + +v8::Local V8InspectorImpl::compileScript( + v8::Local context, v8::Local code, + const String16& fileName, bool markAsInternal) { + v8::ScriptOrigin origin( + toV8String(m_isolate, fileName), v8::Integer::New(m_isolate, 0), + v8::Integer::New(m_isolate, 0), + v8::False(m_isolate), // sharable + v8::Local(), + v8::Boolean::New(m_isolate, markAsInternal), // internal + toV8String(m_isolate, String16()), // sourceMap + v8::True(m_isolate)); // opaqueresource + v8::ScriptCompiler::Source source(code, origin); + v8::Local script; + if (!v8::ScriptCompiler::Compile(context, &source, + v8::ScriptCompiler::kNoCompileOptions) + .ToLocal(&script)) + return v8::Local(); + return script; +} + +void V8InspectorImpl::enableStackCapturingIfNeeded() { + if (!m_capturingStackTracesCount) + V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(m_isolate, + true); + ++m_capturingStackTracesCount; +} + +void V8InspectorImpl::disableStackCapturingIfNeeded() { + if (!(--m_capturingStackTracesCount)) + V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(m_isolate, + false); +} + +void V8InspectorImpl::muteExceptions(int contextGroupId) { + m_muteExceptionsMap[contextGroupId]++; +} + +void V8InspectorImpl::unmuteExceptions(int contextGroupId) { + m_muteExceptionsMap[contextGroupId]--; +} + +V8ConsoleMessageStorage* V8InspectorImpl::ensureConsoleMessageStorage( + int contextGroupId) { + ConsoleStorageMap::iterator storageIt = + m_consoleStorageMap.find(contextGroupId); + if (storageIt == m_consoleStorageMap.end()) + storageIt = + m_consoleStorageMap + .insert(std::make_pair( + contextGroupId, + wrapUnique(new V8ConsoleMessageStorage(this, contextGroupId)))) + .first; + return storageIt->second.get(); +} + +bool V8InspectorImpl::hasConsoleMessageStorage(int contextGroupId) { + ConsoleStorageMap::iterator storageIt = + m_consoleStorageMap.find(contextGroupId); + return storageIt != m_consoleStorageMap.end(); +} + +std::unique_ptr V8InspectorImpl::createStackTrace( + v8::Local stackTrace) { + return m_debugger->createStackTrace(stackTrace); +} + +std::unique_ptr V8InspectorImpl::connect( + int contextGroupId, V8Inspector::Channel* channel, + const StringView& state) { + DCHECK(m_sessions.find(contextGroupId) == m_sessions.cend()); + std::unique_ptr session = + V8InspectorSessionImpl::create(this, contextGroupId, channel, state); + m_sessions[contextGroupId] = session.get(); + return std::move(session); +} + +void V8InspectorImpl::disconnect(V8InspectorSessionImpl* session) { + DCHECK(m_sessions.find(session->contextGroupId()) != m_sessions.end()); + m_sessions.erase(session->contextGroupId()); +} + +InspectedContext* V8InspectorImpl::getContext(int groupId, + int contextId) const { + if (!groupId || !contextId) return nullptr; + + ContextsByGroupMap::const_iterator contextGroupIt = m_contexts.find(groupId); + if (contextGroupIt == m_contexts.end()) return nullptr; + + ContextByIdMap::iterator contextIt = contextGroupIt->second->find(contextId); + if (contextIt == contextGroupIt->second->end()) return nullptr; + + return contextIt->second.get(); +} + +void V8InspectorImpl::contextCreated(const V8ContextInfo& info) { + int contextId = m_debugger->markContext(info); + + ContextsByGroupMap::iterator contextIt = m_contexts.find(info.contextGroupId); + if (contextIt == m_contexts.end()) + contextIt = m_contexts + .insert(std::make_pair(info.contextGroupId, + wrapUnique(new ContextByIdMap()))) + .first; + + const auto& contextById = contextIt->second; + + DCHECK(contextById->find(contextId) == contextById->cend()); + InspectedContext* context = new InspectedContext(this, info, contextId); + (*contextById)[contextId] = wrapUnique(context); + SessionMap::iterator sessionIt = m_sessions.find(info.contextGroupId); + if (sessionIt != m_sessions.end()) + sessionIt->second->runtimeAgent()->reportExecutionContextCreated(context); +} + +void V8InspectorImpl::contextDestroyed(v8::Local context) { + int contextId = V8Debugger::contextId(context); + int contextGroupId = V8Debugger::getGroupId(context); + + ConsoleStorageMap::iterator storageIt = + m_consoleStorageMap.find(contextGroupId); + if (storageIt != m_consoleStorageMap.end()) + storageIt->second->contextDestroyed(contextId); + + InspectedContext* inspectedContext = getContext(contextGroupId, contextId); + if (!inspectedContext) return; + + SessionMap::iterator iter = m_sessions.find(contextGroupId); + if (iter != m_sessions.end()) + iter->second->runtimeAgent()->reportExecutionContextDestroyed( + inspectedContext); + discardInspectedContext(contextGroupId, contextId); +} + +void V8InspectorImpl::resetContextGroup(int contextGroupId) { + m_consoleStorageMap.erase(contextGroupId); + m_muteExceptionsMap.erase(contextGroupId); + SessionMap::iterator session = m_sessions.find(contextGroupId); + if (session != m_sessions.end()) session->second->reset(); + m_contexts.erase(contextGroupId); +} + +void V8InspectorImpl::willExecuteScript(v8::Local context, + int scriptId) { + if (V8DebuggerAgentImpl* agent = + enabledDebuggerAgentForGroup(V8Debugger::getGroupId(context))) + agent->willExecuteScript(scriptId); +} + +void V8InspectorImpl::didExecuteScript(v8::Local context) { + if (V8DebuggerAgentImpl* agent = + enabledDebuggerAgentForGroup(V8Debugger::getGroupId(context))) + agent->didExecuteScript(); +} + +void V8InspectorImpl::idleStarted() { + for (auto it = m_sessions.begin(); it != m_sessions.end(); ++it) { + if (it->second->profilerAgent()->idleStarted()) return; + } +} + +void V8InspectorImpl::idleFinished() { + for (auto it = m_sessions.begin(); it != m_sessions.end(); ++it) { + if (it->second->profilerAgent()->idleFinished()) return; + } +} + +unsigned V8InspectorImpl::exceptionThrown( + v8::Local context, const StringView& message, + v8::Local exception, const StringView& detailedMessage, + const StringView& url, unsigned lineNumber, unsigned columnNumber, + std::unique_ptr stackTrace, int scriptId) { + int contextGroupId = V8Debugger::getGroupId(context); + if (!contextGroupId || m_muteExceptionsMap[contextGroupId]) return 0; + std::unique_ptr stackTraceImpl = + wrapUnique(static_cast(stackTrace.release())); + unsigned exceptionId = nextExceptionId(); + std::unique_ptr consoleMessage = + V8ConsoleMessage::createForException( + m_client->currentTimeMS(), toString16(detailedMessage), + toString16(url), lineNumber, columnNumber, std::move(stackTraceImpl), + scriptId, m_isolate, toString16(message), + V8Debugger::contextId(context), exception, exceptionId); + ensureConsoleMessageStorage(contextGroupId) + ->addMessage(std::move(consoleMessage)); + return exceptionId; +} + +void V8InspectorImpl::exceptionRevoked(v8::Local context, + unsigned exceptionId, + const StringView& message) { + int contextGroupId = V8Debugger::getGroupId(context); + if (!contextGroupId) return; + + std::unique_ptr consoleMessage = + V8ConsoleMessage::createForRevokedException( + m_client->currentTimeMS(), toString16(message), exceptionId); + ensureConsoleMessageStorage(contextGroupId) + ->addMessage(std::move(consoleMessage)); +} + +std::unique_ptr V8InspectorImpl::captureStackTrace( + bool fullStack) { + return m_debugger->captureStackTrace(fullStack); +} + +void V8InspectorImpl::asyncTaskScheduled(const StringView& taskName, void* task, + bool recurring) { + m_debugger->asyncTaskScheduled(taskName, task, recurring); +} + +void V8InspectorImpl::asyncTaskCanceled(void* task) { + m_debugger->asyncTaskCanceled(task); +} + +void V8InspectorImpl::asyncTaskStarted(void* task) { + m_debugger->asyncTaskStarted(task); +} + +void V8InspectorImpl::asyncTaskFinished(void* task) { + m_debugger->asyncTaskFinished(task); +} + +void V8InspectorImpl::allAsyncTasksCanceled() { + m_debugger->allAsyncTasksCanceled(); +} + +v8::Local V8InspectorImpl::regexContext() { + if (m_regexContext.IsEmpty()) + m_regexContext.Reset(m_isolate, v8::Context::New(m_isolate)); + return m_regexContext.Get(m_isolate); +} + +void V8InspectorImpl::discardInspectedContext(int contextGroupId, + int contextId) { + if (!getContext(contextGroupId, contextId)) return; + m_contexts[contextGroupId]->erase(contextId); + if (m_contexts[contextGroupId]->empty()) m_contexts.erase(contextGroupId); +} + +const V8InspectorImpl::ContextByIdMap* V8InspectorImpl::contextGroup( + int contextGroupId) { + ContextsByGroupMap::iterator iter = m_contexts.find(contextGroupId); + return iter == m_contexts.end() ? nullptr : iter->second.get(); +} + +V8InspectorSessionImpl* V8InspectorImpl::sessionForContextGroup( + int contextGroupId) { + if (!contextGroupId) return nullptr; + SessionMap::iterator iter = m_sessions.find(contextGroupId); + return iter == m_sessions.end() ? nullptr : iter->second; +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-inspector-impl.h b/deps/v8_inspector/src/inspector/v8-inspector-impl.h new file mode 100644 index 00000000000000..0ca1a6a7297b02 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-inspector-impl.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2010, 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. + */ + +#ifndef V8_INSPECTOR_V8INSPECTORIMPL_H_ +#define V8_INSPECTOR_V8INSPECTORIMPL_H_ + +#include + +#include "src/base/macros.h" +#include "src/inspector/protocol/Protocol.h" + +#include "include/v8-debug.h" +#include "include/v8-inspector.h" + +namespace v8_inspector { + +class InspectedContext; +class V8ConsoleMessageStorage; +class V8Debugger; +class V8DebuggerAgentImpl; +class V8InspectorSessionImpl; +class V8ProfilerAgentImpl; +class V8RuntimeAgentImpl; +class V8StackTraceImpl; + +class V8InspectorImpl : public V8Inspector { + public: + V8InspectorImpl(v8::Isolate*, V8InspectorClient*); + ~V8InspectorImpl() override; + + v8::Isolate* isolate() const { return m_isolate; } + V8InspectorClient* client() { return m_client; } + V8Debugger* debugger() { return m_debugger.get(); } + + v8::MaybeLocal runCompiledScript(v8::Local, + v8::Local); + v8::MaybeLocal callFunction(v8::Local, + v8::Local, + v8::Local receiver, + int argc, v8::Local info[]); + v8::MaybeLocal compileAndRunInternalScript(v8::Local, + v8::Local); + v8::Local compileScript(v8::Local, + v8::Local, + const String16& fileName, + bool markAsInternal); + v8::Local regexContext(); + + // V8Inspector implementation. + std::unique_ptr connect(int contextGroupId, + V8Inspector::Channel*, + const StringView& state) override; + void contextCreated(const V8ContextInfo&) override; + void contextDestroyed(v8::Local) override; + void resetContextGroup(int contextGroupId) override; + void willExecuteScript(v8::Local, int scriptId) override; + void didExecuteScript(v8::Local) override; + void idleStarted() override; + void idleFinished() override; + unsigned exceptionThrown(v8::Local, const StringView& message, + v8::Local exception, + const StringView& detailedMessage, + const StringView& url, unsigned lineNumber, + unsigned columnNumber, std::unique_ptr, + int scriptId) override; + void exceptionRevoked(v8::Local, unsigned exceptionId, + const StringView& message) override; + std::unique_ptr createStackTrace( + v8::Local) override; + std::unique_ptr captureStackTrace(bool fullStack) override; + void asyncTaskScheduled(const StringView& taskName, void* task, + bool recurring) override; + void asyncTaskCanceled(void* task) override; + void asyncTaskStarted(void* task) override; + void asyncTaskFinished(void* task) override; + void allAsyncTasksCanceled() override; + + unsigned nextExceptionId() { return ++m_lastExceptionId; } + void enableStackCapturingIfNeeded(); + void disableStackCapturingIfNeeded(); + void muteExceptions(int contextGroupId); + void unmuteExceptions(int contextGroupId); + V8ConsoleMessageStorage* ensureConsoleMessageStorage(int contextGroupId); + bool hasConsoleMessageStorage(int contextGroupId); + using ContextByIdMap = + protocol::HashMap>; + void discardInspectedContext(int contextGroupId, int contextId); + const ContextByIdMap* contextGroup(int contextGroupId); + void disconnect(V8InspectorSessionImpl*); + V8InspectorSessionImpl* sessionForContextGroup(int contextGroupId); + InspectedContext* getContext(int groupId, int contextId) const; + V8DebuggerAgentImpl* enabledDebuggerAgentForGroup(int contextGroupId); + V8RuntimeAgentImpl* enabledRuntimeAgentForGroup(int contextGroupId); + V8ProfilerAgentImpl* enabledProfilerAgentForGroup(int contextGroupId); + + private: + v8::Isolate* m_isolate; + V8InspectorClient* m_client; + std::unique_ptr m_debugger; + v8::Global m_regexContext; + int m_capturingStackTracesCount; + unsigned m_lastExceptionId; + + using MuteExceptionsMap = protocol::HashMap; + MuteExceptionsMap m_muteExceptionsMap; + + using ContextsByGroupMap = + protocol::HashMap>; + ContextsByGroupMap m_contexts; + + using SessionMap = protocol::HashMap; + SessionMap m_sessions; + + using ConsoleStorageMap = + protocol::HashMap>; + ConsoleStorageMap m_consoleStorageMap; + + DISALLOW_COPY_AND_ASSIGN(V8InspectorImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8INSPECTORIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-inspector-session-impl.cc b/deps/v8_inspector/src/inspector/v8-inspector-session-impl.cc new file mode 100644 index 00000000000000..9a0f652c4ca4ae --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-inspector-session-impl.cc @@ -0,0 +1,418 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-inspector-session-impl.h" + +#include "src/inspector/injected-script.h" +#include "src/inspector/inspected-context.h" +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/remote-object-id.h" +#include "src/inspector/search-util.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-console-agent-impl.h" +#include "src/inspector/v8-debugger-agent-impl.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-heap-profiler-agent-impl.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-profiler-agent-impl.h" +#include "src/inspector/v8-runtime-agent-impl.h" +#include "src/inspector/v8-schema-agent-impl.h" + +namespace v8_inspector { + +// static +bool V8InspectorSession::canDispatchMethod(const StringView& method) { + return stringViewStartsWith(method, + protocol::Runtime::Metainfo::commandPrefix) || + stringViewStartsWith(method, + protocol::Debugger::Metainfo::commandPrefix) || + stringViewStartsWith(method, + protocol::Profiler::Metainfo::commandPrefix) || + stringViewStartsWith( + method, protocol::HeapProfiler::Metainfo::commandPrefix) || + stringViewStartsWith(method, + protocol::Console::Metainfo::commandPrefix) || + stringViewStartsWith(method, + protocol::Schema::Metainfo::commandPrefix); +} + +std::unique_ptr V8InspectorSessionImpl::create( + V8InspectorImpl* inspector, int contextGroupId, + V8Inspector::Channel* channel, const StringView& state) { + return wrapUnique( + new V8InspectorSessionImpl(inspector, contextGroupId, channel, state)); +} + +V8InspectorSessionImpl::V8InspectorSessionImpl(V8InspectorImpl* inspector, + int contextGroupId, + V8Inspector::Channel* channel, + const StringView& savedState) + : m_contextGroupId(contextGroupId), + m_inspector(inspector), + m_channel(channel), + m_customObjectFormatterEnabled(false), + m_dispatcher(this), + m_state(nullptr), + m_runtimeAgent(nullptr), + m_debuggerAgent(nullptr), + m_heapProfilerAgent(nullptr), + m_profilerAgent(nullptr), + m_consoleAgent(nullptr), + m_schemaAgent(nullptr) { + if (savedState.length()) { + std::unique_ptr state = + protocol::parseJSON(toString16(savedState)); + if (state) m_state = protocol::DictionaryValue::cast(std::move(state)); + if (!m_state) m_state = protocol::DictionaryValue::create(); + } else { + m_state = protocol::DictionaryValue::create(); + } + + m_runtimeAgent = wrapUnique(new V8RuntimeAgentImpl( + this, this, agentState(protocol::Runtime::Metainfo::domainName))); + protocol::Runtime::Dispatcher::wire(&m_dispatcher, m_runtimeAgent.get()); + + m_debuggerAgent = wrapUnique(new V8DebuggerAgentImpl( + this, this, agentState(protocol::Debugger::Metainfo::domainName))); + protocol::Debugger::Dispatcher::wire(&m_dispatcher, m_debuggerAgent.get()); + + m_profilerAgent = wrapUnique(new V8ProfilerAgentImpl( + this, this, agentState(protocol::Profiler::Metainfo::domainName))); + protocol::Profiler::Dispatcher::wire(&m_dispatcher, m_profilerAgent.get()); + + m_heapProfilerAgent = wrapUnique(new V8HeapProfilerAgentImpl( + this, this, agentState(protocol::HeapProfiler::Metainfo::domainName))); + protocol::HeapProfiler::Dispatcher::wire(&m_dispatcher, + m_heapProfilerAgent.get()); + + m_consoleAgent = wrapUnique(new V8ConsoleAgentImpl( + this, this, agentState(protocol::Console::Metainfo::domainName))); + protocol::Console::Dispatcher::wire(&m_dispatcher, m_consoleAgent.get()); + + m_schemaAgent = wrapUnique(new V8SchemaAgentImpl( + this, this, agentState(protocol::Schema::Metainfo::domainName))); + protocol::Schema::Dispatcher::wire(&m_dispatcher, m_schemaAgent.get()); + + if (savedState.length()) { + m_runtimeAgent->restore(); + m_debuggerAgent->restore(); + m_heapProfilerAgent->restore(); + m_profilerAgent->restore(); + m_consoleAgent->restore(); + } +} + +V8InspectorSessionImpl::~V8InspectorSessionImpl() { + ErrorString errorString; + m_consoleAgent->disable(&errorString); + m_profilerAgent->disable(&errorString); + m_heapProfilerAgent->disable(&errorString); + m_debuggerAgent->disable(&errorString); + m_runtimeAgent->disable(&errorString); + + discardInjectedScripts(); + m_inspector->disconnect(this); +} + +protocol::DictionaryValue* V8InspectorSessionImpl::agentState( + const String16& name) { + protocol::DictionaryValue* state = m_state->getObject(name); + if (!state) { + std::unique_ptr newState = + protocol::DictionaryValue::create(); + state = newState.get(); + m_state->setObject(name, std::move(newState)); + } + return state; +} + +void V8InspectorSessionImpl::sendProtocolResponse(int callId, + const String16& message) { + m_channel->sendProtocolResponse(callId, toStringView(message)); +} + +void V8InspectorSessionImpl::sendProtocolNotification(const String16& message) { + m_channel->sendProtocolNotification(toStringView(message)); +} + +void V8InspectorSessionImpl::flushProtocolNotifications() { + m_channel->flushProtocolNotifications(); +} + +void V8InspectorSessionImpl::reset() { + m_debuggerAgent->reset(); + m_runtimeAgent->reset(); + discardInjectedScripts(); +} + +void V8InspectorSessionImpl::discardInjectedScripts() { + m_inspectedObjects.clear(); + const V8InspectorImpl::ContextByIdMap* contexts = + m_inspector->contextGroup(m_contextGroupId); + if (!contexts) return; + + std::vector keys; + keys.reserve(contexts->size()); + for (auto& idContext : *contexts) keys.push_back(idContext.first); + for (auto& key : keys) { + contexts = m_inspector->contextGroup(m_contextGroupId); + if (!contexts) continue; + auto contextIt = contexts->find(key); + if (contextIt != contexts->end()) + contextIt->second + ->discardInjectedScript(); // This may destroy some contexts. + } +} + +InjectedScript* V8InspectorSessionImpl::findInjectedScript( + ErrorString* errorString, int contextId) { + if (!contextId) { + *errorString = "Cannot find context with specified id"; + return nullptr; + } + + const V8InspectorImpl::ContextByIdMap* contexts = + m_inspector->contextGroup(m_contextGroupId); + if (!contexts) { + *errorString = "Cannot find context with specified id"; + return nullptr; + } + + auto contextsIt = contexts->find(contextId); + if (contextsIt == contexts->end()) { + *errorString = "Cannot find context with specified id"; + return nullptr; + } + + const std::unique_ptr& context = contextsIt->second; + if (!context->getInjectedScript()) { + context->createInjectedScript(); + if (!context->getInjectedScript()) { + *errorString = "Cannot access specified execution context"; + return nullptr; + } + if (m_customObjectFormatterEnabled) + context->getInjectedScript()->setCustomObjectFormatterEnabled(true); + } + return context->getInjectedScript(); +} + +InjectedScript* V8InspectorSessionImpl::findInjectedScript( + ErrorString* errorString, RemoteObjectIdBase* objectId) { + return objectId ? findInjectedScript(errorString, objectId->contextId()) + : nullptr; +} + +void V8InspectorSessionImpl::releaseObjectGroup(const StringView& objectGroup) { + releaseObjectGroup(toString16(objectGroup)); +} + +void V8InspectorSessionImpl::releaseObjectGroup(const String16& objectGroup) { + const V8InspectorImpl::ContextByIdMap* contexts = + m_inspector->contextGroup(m_contextGroupId); + if (!contexts) return; + + std::vector keys; + for (auto& idContext : *contexts) keys.push_back(idContext.first); + for (auto& key : keys) { + contexts = m_inspector->contextGroup(m_contextGroupId); + if (!contexts) continue; + auto contextsIt = contexts->find(key); + if (contextsIt == contexts->end()) continue; + InjectedScript* injectedScript = contextsIt->second->getInjectedScript(); + if (injectedScript) + injectedScript->releaseObjectGroup( + objectGroup); // This may destroy some contexts. + } +} + +bool V8InspectorSessionImpl::unwrapObject( + std::unique_ptr* error, const StringView& objectId, + v8::Local* object, v8::Local* context, + std::unique_ptr* objectGroup) { + ErrorString errorString; + String16 objectGroupString; + bool result = + unwrapObject(&errorString, toString16(objectId), object, context, + objectGroup ? &objectGroupString : nullptr); + if (error) *error = StringBufferImpl::adopt(errorString); + if (objectGroup) *objectGroup = StringBufferImpl::adopt(objectGroupString); + return result; +} + +bool V8InspectorSessionImpl::unwrapObject(ErrorString* errorString, + const String16& objectId, + v8::Local* object, + v8::Local* context, + String16* objectGroup) { + std::unique_ptr remoteId = + RemoteObjectId::parse(errorString, objectId); + if (!remoteId) return false; + InjectedScript* injectedScript = + findInjectedScript(errorString, remoteId.get()); + if (!injectedScript) return false; + if (!injectedScript->findObject(errorString, *remoteId, object)) return false; + *context = injectedScript->context()->context(); + if (objectGroup) *objectGroup = injectedScript->objectGroupName(*remoteId); + return true; +} + +std::unique_ptr +V8InspectorSessionImpl::wrapObject(v8::Local context, + v8::Local value, + const StringView& groupName) { + return wrapObject(context, value, toString16(groupName), false); +} + +std::unique_ptr +V8InspectorSessionImpl::wrapObject(v8::Local context, + v8::Local value, + const String16& groupName, + bool generatePreview) { + ErrorString errorString; + InjectedScript* injectedScript = + findInjectedScript(&errorString, V8Debugger::contextId(context)); + if (!injectedScript) return nullptr; + return injectedScript->wrapObject(&errorString, value, groupName, false, + generatePreview); +} + +std::unique_ptr +V8InspectorSessionImpl::wrapTable(v8::Local context, + v8::Local table, + v8::Local columns) { + ErrorString errorString; + InjectedScript* injectedScript = + findInjectedScript(&errorString, V8Debugger::contextId(context)); + if (!injectedScript) return nullptr; + return injectedScript->wrapTable(table, columns); +} + +void V8InspectorSessionImpl::setCustomObjectFormatterEnabled(bool enabled) { + m_customObjectFormatterEnabled = enabled; + const V8InspectorImpl::ContextByIdMap* contexts = + m_inspector->contextGroup(m_contextGroupId); + if (!contexts) return; + for (auto& idContext : *contexts) { + InjectedScript* injectedScript = idContext.second->getInjectedScript(); + if (injectedScript) + injectedScript->setCustomObjectFormatterEnabled(enabled); + } +} + +void V8InspectorSessionImpl::reportAllContexts(V8RuntimeAgentImpl* agent) { + const V8InspectorImpl::ContextByIdMap* contexts = + m_inspector->contextGroup(m_contextGroupId); + if (!contexts) return; + for (auto& idContext : *contexts) + agent->reportExecutionContextCreated(idContext.second.get()); +} + +void V8InspectorSessionImpl::dispatchProtocolMessage( + const StringView& message) { + m_dispatcher.dispatch(protocol::parseJSON(message)); +} + +std::unique_ptr V8InspectorSessionImpl::stateJSON() { + String16 json = m_state->toJSONString(); + return StringBufferImpl::adopt(json); +} + +std::vector> +V8InspectorSessionImpl::supportedDomains() { + std::vector> domains = + supportedDomainsImpl(); + std::vector> result; + for (size_t i = 0; i < domains.size(); ++i) + result.push_back(std::move(domains[i])); + return result; +} + +std::vector> +V8InspectorSessionImpl::supportedDomainsImpl() { + std::vector> result; + result.push_back(protocol::Schema::Domain::create() + .setName(protocol::Runtime::Metainfo::domainName) + .setVersion(protocol::Runtime::Metainfo::version) + .build()); + result.push_back(protocol::Schema::Domain::create() + .setName(protocol::Debugger::Metainfo::domainName) + .setVersion(protocol::Debugger::Metainfo::version) + .build()); + result.push_back(protocol::Schema::Domain::create() + .setName(protocol::Profiler::Metainfo::domainName) + .setVersion(protocol::Profiler::Metainfo::version) + .build()); + result.push_back(protocol::Schema::Domain::create() + .setName(protocol::HeapProfiler::Metainfo::domainName) + .setVersion(protocol::HeapProfiler::Metainfo::version) + .build()); + result.push_back(protocol::Schema::Domain::create() + .setName(protocol::Schema::Metainfo::domainName) + .setVersion(protocol::Schema::Metainfo::version) + .build()); + return result; +} + +void V8InspectorSessionImpl::addInspectedObject( + std::unique_ptr inspectable) { + m_inspectedObjects.insert(m_inspectedObjects.begin(), std::move(inspectable)); + if (m_inspectedObjects.size() > kInspectedObjectBufferSize) + m_inspectedObjects.resize(kInspectedObjectBufferSize); +} + +V8InspectorSession::Inspectable* V8InspectorSessionImpl::inspectedObject( + unsigned num) { + if (num >= m_inspectedObjects.size()) return nullptr; + return m_inspectedObjects[num].get(); +} + +void V8InspectorSessionImpl::schedulePauseOnNextStatement( + const StringView& breakReason, const StringView& breakDetails) { + m_debuggerAgent->schedulePauseOnNextStatement( + toString16(breakReason), + protocol::DictionaryValue::cast(protocol::parseJSON(breakDetails))); +} + +void V8InspectorSessionImpl::cancelPauseOnNextStatement() { + m_debuggerAgent->cancelPauseOnNextStatement(); +} + +void V8InspectorSessionImpl::breakProgram(const StringView& breakReason, + const StringView& breakDetails) { + m_debuggerAgent->breakProgram( + toString16(breakReason), + protocol::DictionaryValue::cast(protocol::parseJSON(breakDetails))); +} + +void V8InspectorSessionImpl::setSkipAllPauses(bool skip) { + ErrorString errorString; + m_debuggerAgent->setSkipAllPauses(&errorString, skip); +} + +void V8InspectorSessionImpl::resume() { + ErrorString errorString; + m_debuggerAgent->resume(&errorString); +} + +void V8InspectorSessionImpl::stepOver() { + ErrorString errorString; + m_debuggerAgent->stepOver(&errorString); +} + +std::vector> +V8InspectorSessionImpl::searchInTextByLines(const StringView& text, + const StringView& query, + bool caseSensitive, bool isRegex) { + // TODO(dgozman): search may operate on StringView and avoid copying |text|. + std::vector> matches = + searchInTextByLinesImpl(this, toString16(text), toString16(query), + caseSensitive, isRegex); + std::vector> result; + for (size_t i = 0; i < matches.size(); ++i) + result.push_back(std::move(matches[i])); + return result; +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-inspector-session-impl.h b/deps/v8_inspector/src/inspector/v8-inspector-session-impl.h new file mode 100644 index 00000000000000..e84e8c99a77c3f --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-inspector-session-impl.h @@ -0,0 +1,126 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8INSPECTORSESSIONIMPL_H_ +#define V8_INSPECTOR_V8INSPECTORSESSIONIMPL_H_ + +#include + +#include "src/base/macros.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/Runtime.h" +#include "src/inspector/protocol/Schema.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +class InjectedScript; +class RemoteObjectIdBase; +class V8ConsoleAgentImpl; +class V8DebuggerAgentImpl; +class V8InspectorImpl; +class V8HeapProfilerAgentImpl; +class V8ProfilerAgentImpl; +class V8RuntimeAgentImpl; +class V8SchemaAgentImpl; + +using protocol::ErrorString; + +class V8InspectorSessionImpl : public V8InspectorSession, + public protocol::FrontendChannel { + public: + static std::unique_ptr create( + V8InspectorImpl*, int contextGroupId, V8Inspector::Channel*, + const StringView& state); + ~V8InspectorSessionImpl(); + + V8InspectorImpl* inspector() const { return m_inspector; } + V8ConsoleAgentImpl* consoleAgent() { return m_consoleAgent.get(); } + V8DebuggerAgentImpl* debuggerAgent() { return m_debuggerAgent.get(); } + V8SchemaAgentImpl* schemaAgent() { return m_schemaAgent.get(); } + V8ProfilerAgentImpl* profilerAgent() { return m_profilerAgent.get(); } + V8RuntimeAgentImpl* runtimeAgent() { return m_runtimeAgent.get(); } + int contextGroupId() const { return m_contextGroupId; } + + InjectedScript* findInjectedScript(ErrorString*, int contextId); + InjectedScript* findInjectedScript(ErrorString*, RemoteObjectIdBase*); + void reset(); + void discardInjectedScripts(); + void reportAllContexts(V8RuntimeAgentImpl*); + void setCustomObjectFormatterEnabled(bool); + std::unique_ptr wrapObject( + v8::Local, v8::Local, const String16& groupName, + bool generatePreview); + std::unique_ptr wrapTable( + v8::Local, v8::Local table, + v8::Local columns); + std::vector> supportedDomainsImpl(); + bool unwrapObject(ErrorString*, const String16& objectId, + v8::Local*, v8::Local*, + String16* objectGroup); + void releaseObjectGroup(const String16& objectGroup); + + // V8InspectorSession implementation. + void dispatchProtocolMessage(const StringView& message) override; + std::unique_ptr stateJSON() override; + std::vector> supportedDomains() + override; + void addInspectedObject( + std::unique_ptr) override; + void schedulePauseOnNextStatement(const StringView& breakReason, + const StringView& breakDetails) override; + void cancelPauseOnNextStatement() override; + void breakProgram(const StringView& breakReason, + const StringView& breakDetails) override; + void setSkipAllPauses(bool) override; + void resume() override; + void stepOver() override; + std::vector> + searchInTextByLines(const StringView& text, const StringView& query, + bool caseSensitive, bool isRegex) override; + void releaseObjectGroup(const StringView& objectGroup) override; + bool unwrapObject(std::unique_ptr*, const StringView& objectId, + v8::Local*, v8::Local*, + std::unique_ptr* objectGroup) override; + std::unique_ptr wrapObject( + v8::Local, v8::Local, + const StringView& groupName) override; + + V8InspectorSession::Inspectable* inspectedObject(unsigned num); + static const unsigned kInspectedObjectBufferSize = 5; + + private: + V8InspectorSessionImpl(V8InspectorImpl*, int contextGroupId, + V8Inspector::Channel*, const StringView& state); + protocol::DictionaryValue* agentState(const String16& name); + + // protocol::FrontendChannel implementation. + void sendProtocolResponse(int callId, const String16& message) override; + void sendProtocolNotification(const String16& message) override; + void flushProtocolNotifications() override; + + int m_contextGroupId; + V8InspectorImpl* m_inspector; + V8Inspector::Channel* m_channel; + bool m_customObjectFormatterEnabled; + + protocol::UberDispatcher m_dispatcher; + std::unique_ptr m_state; + + std::unique_ptr m_runtimeAgent; + std::unique_ptr m_debuggerAgent; + std::unique_ptr m_heapProfilerAgent; + std::unique_ptr m_profilerAgent; + std::unique_ptr m_consoleAgent; + std::unique_ptr m_schemaAgent; + std::vector> + m_inspectedObjects; + + DISALLOW_COPY_AND_ASSIGN(V8InspectorSessionImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8INSPECTORSESSIONIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-internal-value-type.cc b/deps/v8_inspector/src/inspector/v8-internal-value-type.cc new file mode 100644 index 00000000000000..cde8bc9f7f9957 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-internal-value-type.cc @@ -0,0 +1,77 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-internal-value-type.h" + +#include "src/inspector/protocol-platform.h" +#include "src/inspector/string-util.h" + +namespace v8_inspector { + +namespace { + +v8::Local internalSubtypePrivate(v8::Isolate* isolate) { + return v8::Private::ForApi( + isolate, + toV8StringInternalized(isolate, "V8InternalType#internalSubtype")); +} + +v8::Local subtypeForInternalType(v8::Isolate* isolate, + V8InternalValueType type) { + switch (type) { + case V8InternalValueType::kEntry: + return toV8StringInternalized(isolate, "internal#entry"); + case V8InternalValueType::kLocation: + return toV8StringInternalized(isolate, "internal#location"); + case V8InternalValueType::kScope: + return toV8StringInternalized(isolate, "internal#scope"); + case V8InternalValueType::kScopeList: + return toV8StringInternalized(isolate, "internal#scopeList"); + } + UNREACHABLE(); + return v8::Local(); +} + +} // namespace + +bool markAsInternal(v8::Local context, + v8::Local object, V8InternalValueType type) { + v8::Isolate* isolate = context->GetIsolate(); + v8::Local privateValue = internalSubtypePrivate(isolate); + v8::Local subtype = subtypeForInternalType(isolate, type); + return object->SetPrivate(context, privateValue, subtype).FromMaybe(false); +} + +bool markArrayEntriesAsInternal(v8::Local context, + v8::Local array, + V8InternalValueType type) { + v8::Isolate* isolate = context->GetIsolate(); + v8::Local privateValue = internalSubtypePrivate(isolate); + v8::Local subtype = subtypeForInternalType(isolate, type); + for (uint32_t i = 0; i < array->Length(); ++i) { + v8::Local entry; + if (!array->Get(context, i).ToLocal(&entry) || !entry->IsObject()) + return false; + if (!entry.As() + ->SetPrivate(context, privateValue, subtype) + .FromMaybe(false)) + return false; + } + return true; +} + +v8::Local v8InternalValueTypeFrom(v8::Local context, + v8::Local object) { + v8::Isolate* isolate = context->GetIsolate(); + v8::Local privateValue = internalSubtypePrivate(isolate); + if (!object->HasPrivate(context, privateValue).FromMaybe(false)) + return v8::Null(isolate); + v8::Local subtypeValue; + if (!object->GetPrivate(context, privateValue).ToLocal(&subtypeValue) || + !subtypeValue->IsString()) + return v8::Null(isolate); + return subtypeValue; +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-internal-value-type.h b/deps/v8_inspector/src/inspector/v8-internal-value-type.h new file mode 100644 index 00000000000000..e648a0d4a3ec7d --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-internal-value-type.h @@ -0,0 +1,23 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8INTERNALVALUETYPE_H_ +#define V8_INSPECTOR_V8INTERNALVALUETYPE_H_ + +#include "include/v8.h" + +namespace v8_inspector { + +enum class V8InternalValueType { kEntry, kLocation, kScope, kScopeList }; + +bool markAsInternal(v8::Local, v8::Local, + V8InternalValueType); +bool markArrayEntriesAsInternal(v8::Local, v8::Local, + V8InternalValueType); +v8::Local v8InternalValueTypeFrom(v8::Local, + v8::Local); + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8INTERNALVALUETYPE_H_ diff --git a/deps/v8_inspector/src/inspector/v8-profiler-agent-impl.cc b/deps/v8_inspector/src/inspector/v8-profiler-agent-impl.cc new file mode 100644 index 00000000000000..0511ca39b55ca1 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-profiler-agent-impl.cc @@ -0,0 +1,321 @@ +// Copyright 2015 the V8 project 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 "src/inspector/v8-profiler-agent-impl.h" + +#include + +#include "src/base/atomicops.h" +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-stack-trace-impl.h" + +#include "include/v8-profiler.h" + +namespace v8_inspector { + +namespace ProfilerAgentState { +static const char samplingInterval[] = "samplingInterval"; +static const char userInitiatedProfiling[] = "userInitiatedProfiling"; +static const char profilerEnabled[] = "profilerEnabled"; +} + +namespace { + +std::unique_ptr> +buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) { + unsigned lineCount = node->GetHitLineCount(); + if (!lineCount) return nullptr; + auto array = protocol::Array::create(); + std::vector entries(lineCount); + if (node->GetLineTicks(&entries[0], lineCount)) { + for (unsigned i = 0; i < lineCount; i++) { + std::unique_ptr line = + protocol::Profiler::PositionTickInfo::create() + .setLine(entries[i].line) + .setTicks(entries[i].hit_count) + .build(); + array->addItem(std::move(line)); + } + } + return array; +} + +std::unique_ptr buildInspectorObjectFor( + v8::Isolate* isolate, const v8::CpuProfileNode* node) { + v8::HandleScope handleScope(isolate); + auto callFrame = + protocol::Runtime::CallFrame::create() + .setFunctionName(toProtocolString(node->GetFunctionName())) + .setScriptId(String16::fromInteger(node->GetScriptId())) + .setUrl(toProtocolString(node->GetScriptResourceName())) + .setLineNumber(node->GetLineNumber() - 1) + .setColumnNumber(node->GetColumnNumber() - 1) + .build(); + auto result = protocol::Profiler::ProfileNode::create() + .setCallFrame(std::move(callFrame)) + .setHitCount(node->GetHitCount()) + .setId(node->GetNodeId()) + .build(); + + const int childrenCount = node->GetChildrenCount(); + if (childrenCount) { + auto children = protocol::Array::create(); + for (int i = 0; i < childrenCount; i++) + children->addItem(node->GetChild(i)->GetNodeId()); + result->setChildren(std::move(children)); + } + + const char* deoptReason = node->GetBailoutReason(); + if (deoptReason && deoptReason[0] && strcmp(deoptReason, "no reason")) + result->setDeoptReason(deoptReason); + + auto positionTicks = buildInspectorObjectForPositionTicks(node); + if (positionTicks) result->setPositionTicks(std::move(positionTicks)); + + return result; +} + +std::unique_ptr> buildInspectorObjectForSamples( + v8::CpuProfile* v8profile) { + auto array = protocol::Array::create(); + int count = v8profile->GetSamplesCount(); + for (int i = 0; i < count; i++) + array->addItem(v8profile->GetSample(i)->GetNodeId()); + return array; +} + +std::unique_ptr> buildInspectorObjectForTimestamps( + v8::CpuProfile* v8profile) { + auto array = protocol::Array::create(); + int count = v8profile->GetSamplesCount(); + uint64_t lastTime = v8profile->GetStartTime(); + for (int i = 0; i < count; i++) { + uint64_t ts = v8profile->GetSampleTimestamp(i); + array->addItem(static_cast(ts - lastTime)); + lastTime = ts; + } + return array; +} + +void flattenNodesTree(v8::Isolate* isolate, const v8::CpuProfileNode* node, + protocol::Array* list) { + list->addItem(buildInspectorObjectFor(isolate, node)); + const int childrenCount = node->GetChildrenCount(); + for (int i = 0; i < childrenCount; i++) + flattenNodesTree(isolate, node->GetChild(i), list); +} + +std::unique_ptr createCPUProfile( + v8::Isolate* isolate, v8::CpuProfile* v8profile) { + auto nodes = protocol::Array::create(); + flattenNodesTree(isolate, v8profile->GetTopDownRoot(), nodes.get()); + return protocol::Profiler::Profile::create() + .setNodes(std::move(nodes)) + .setStartTime(static_cast(v8profile->GetStartTime())) + .setEndTime(static_cast(v8profile->GetEndTime())) + .setSamples(buildInspectorObjectForSamples(v8profile)) + .setTimeDeltas(buildInspectorObjectForTimestamps(v8profile)) + .build(); +} + +std::unique_ptr currentDebugLocation( + V8InspectorImpl* inspector) { + std::unique_ptr callStack = + inspector->debugger()->captureStackTrace(false /* fullStack */); + auto location = protocol::Debugger::Location::create() + .setScriptId(toString16(callStack->topScriptId())) + .setLineNumber(callStack->topLineNumber()) + .build(); + location->setColumnNumber(callStack->topColumnNumber()); + return location; +} + +volatile int s_lastProfileId = 0; + +} // namespace + +class V8ProfilerAgentImpl::ProfileDescriptor { + public: + ProfileDescriptor(const String16& id, const String16& title) + : m_id(id), m_title(title) {} + String16 m_id; + String16 m_title; +}; + +V8ProfilerAgentImpl::V8ProfilerAgentImpl( + V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, + protocol::DictionaryValue* state) + : m_session(session), + m_isolate(m_session->inspector()->isolate()), + m_profiler(nullptr), + m_state(state), + m_frontend(frontendChannel), + m_enabled(false), + m_recordingCPUProfile(false) {} + +V8ProfilerAgentImpl::~V8ProfilerAgentImpl() { + if (m_profiler) m_profiler->Dispose(); +} + +void V8ProfilerAgentImpl::consoleProfile(const String16& title) { + if (!m_enabled) return; + String16 id = nextProfileId(); + m_startedProfiles.push_back(ProfileDescriptor(id, title)); + startProfiling(id); + m_frontend.consoleProfileStarted( + id, currentDebugLocation(m_session->inspector()), title); +} + +void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) { + if (!m_enabled) return; + String16 id; + String16 resolvedTitle; + // Take last started profile if no title was passed. + if (title.isEmpty()) { + if (m_startedProfiles.empty()) return; + id = m_startedProfiles.back().m_id; + resolvedTitle = m_startedProfiles.back().m_title; + m_startedProfiles.pop_back(); + } else { + for (size_t i = 0; i < m_startedProfiles.size(); i++) { + if (m_startedProfiles[i].m_title == title) { + resolvedTitle = title; + id = m_startedProfiles[i].m_id; + m_startedProfiles.erase(m_startedProfiles.begin() + i); + break; + } + } + if (id.isEmpty()) return; + } + std::unique_ptr profile = + stopProfiling(id, true); + if (!profile) return; + std::unique_ptr location = + currentDebugLocation(m_session->inspector()); + m_frontend.consoleProfileFinished(id, std::move(location), std::move(profile), + resolvedTitle); +} + +void V8ProfilerAgentImpl::enable(ErrorString*) { + if (m_enabled) return; + m_enabled = true; + DCHECK(!m_profiler); + m_profiler = v8::CpuProfiler::New(m_isolate); + m_state->setBoolean(ProfilerAgentState::profilerEnabled, true); +} + +void V8ProfilerAgentImpl::disable(ErrorString* errorString) { + if (!m_enabled) return; + for (size_t i = m_startedProfiles.size(); i > 0; --i) + stopProfiling(m_startedProfiles[i - 1].m_id, false); + m_startedProfiles.clear(); + stop(nullptr, nullptr); + m_profiler->Dispose(); + m_profiler = nullptr; + m_enabled = false; + m_state->setBoolean(ProfilerAgentState::profilerEnabled, false); +} + +void V8ProfilerAgentImpl::setSamplingInterval(ErrorString* error, + int interval) { + if (m_recordingCPUProfile) { + *error = "Cannot change sampling interval when profiling."; + return; + } + m_state->setInteger(ProfilerAgentState::samplingInterval, interval); + m_profiler->SetSamplingInterval(interval); +} + +void V8ProfilerAgentImpl::restore() { + DCHECK(!m_enabled); + if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false)) + return; + m_enabled = true; + DCHECK(!m_profiler); + m_profiler = v8::CpuProfiler::New(m_isolate); + int interval = 0; + m_state->getInteger(ProfilerAgentState::samplingInterval, &interval); + if (interval) m_profiler->SetSamplingInterval(interval); + if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, + false)) { + ErrorString error; + start(&error); + } +} + +void V8ProfilerAgentImpl::start(ErrorString* error) { + if (m_recordingCPUProfile) return; + if (!m_enabled) { + *error = "Profiler is not enabled"; + return; + } + m_recordingCPUProfile = true; + m_frontendInitiatedProfileId = nextProfileId(); + startProfiling(m_frontendInitiatedProfileId); + m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true); +} + +void V8ProfilerAgentImpl::stop( + ErrorString* errorString, + std::unique_ptr* profile) { + if (!m_recordingCPUProfile) { + if (errorString) *errorString = "No recording profiles found"; + return; + } + m_recordingCPUProfile = false; + std::unique_ptr cpuProfile = + stopProfiling(m_frontendInitiatedProfileId, !!profile); + if (profile) { + *profile = std::move(cpuProfile); + if (!profile->get() && errorString) *errorString = "Profile is not found"; + } + m_frontendInitiatedProfileId = String16(); + m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false); +} + +String16 V8ProfilerAgentImpl::nextProfileId() { + return String16::fromInteger( + v8::base::NoBarrier_AtomicIncrement(&s_lastProfileId, 1)); +} + +void V8ProfilerAgentImpl::startProfiling(const String16& title) { + v8::HandleScope handleScope(m_isolate); + m_profiler->StartProfiling(toV8String(m_isolate, title), true); +} + +std::unique_ptr V8ProfilerAgentImpl::stopProfiling( + const String16& title, bool serialize) { + v8::HandleScope handleScope(m_isolate); + v8::CpuProfile* profile = + m_profiler->StopProfiling(toV8String(m_isolate, title)); + if (!profile) return nullptr; + std::unique_ptr result; + if (serialize) result = createCPUProfile(m_isolate, profile); + profile->Delete(); + return result; +} + +bool V8ProfilerAgentImpl::isRecording() const { + return m_recordingCPUProfile || !m_startedProfiles.empty(); +} + +bool V8ProfilerAgentImpl::idleStarted() { + if (m_profiler) m_profiler->SetIdle(true); + return m_profiler; +} + +bool V8ProfilerAgentImpl::idleFinished() { + if (m_profiler) m_profiler->SetIdle(false); + return m_profiler; +} + +void V8ProfilerAgentImpl::collectSample() { + if (m_profiler) m_profiler->CollectSample(); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-profiler-agent-impl.h b/deps/v8_inspector/src/inspector/v8-profiler-agent-impl.h new file mode 100644 index 00000000000000..ee8997653af518 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-profiler-agent-impl.h @@ -0,0 +1,74 @@ +// Copyright 2015 the V8 project 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 V8_INSPECTOR_V8PROFILERAGENTIMPL_H_ +#define V8_INSPECTOR_V8PROFILERAGENTIMPL_H_ + +#include + +#include "src/base/macros.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/Profiler.h" + +namespace v8 { +class CpuProfiler; +class Isolate; +} + +namespace v8_inspector { + +class V8InspectorSessionImpl; + +using protocol::ErrorString; + +class V8ProfilerAgentImpl : public protocol::Profiler::Backend { + public: + V8ProfilerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, + protocol::DictionaryValue* state); + ~V8ProfilerAgentImpl() override; + + bool enabled() const { return m_enabled; } + void restore(); + + void enable(ErrorString*) override; + void disable(ErrorString*) override; + void setSamplingInterval(ErrorString*, int) override; + void start(ErrorString*) override; + void stop(ErrorString*, + std::unique_ptr*) override; + + void consoleProfile(const String16& title); + void consoleProfileEnd(const String16& title); + + bool idleStarted(); + bool idleFinished(); + + void collectSample(); + + private: + String16 nextProfileId(); + + void startProfiling(const String16& title); + std::unique_ptr stopProfiling( + const String16& title, bool serialize); + + bool isRecording() const; + + V8InspectorSessionImpl* m_session; + v8::Isolate* m_isolate; + v8::CpuProfiler* m_profiler; + protocol::DictionaryValue* m_state; + protocol::Profiler::Frontend m_frontend; + bool m_enabled; + bool m_recordingCPUProfile; + class ProfileDescriptor; + std::vector m_startedProfiles; + String16 m_frontendInitiatedProfileId; + + DISALLOW_COPY_AND_ASSIGN(V8ProfilerAgentImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8PROFILERAGENTIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-regex.cc b/deps/v8_inspector/src/inspector/v8-regex.cc new file mode 100644 index 00000000000000..47af70d3604ae1 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-regex.cc @@ -0,0 +1,93 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-regex.h" + +#include + +#include "src/inspector/string-util.h" +#include "src/inspector/v8-inspector-impl.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +V8Regex::V8Regex(V8InspectorImpl* inspector, const String16& pattern, + bool caseSensitive, bool multiline) + : m_inspector(inspector) { + v8::Isolate* isolate = m_inspector->isolate(); + v8::HandleScope handleScope(isolate); + v8::Local context = m_inspector->regexContext(); + v8::Context::Scope contextScope(context); + v8::TryCatch tryCatch(isolate); + + unsigned flags = v8::RegExp::kNone; + if (!caseSensitive) flags |= v8::RegExp::kIgnoreCase; + if (multiline) flags |= v8::RegExp::kMultiline; + + v8::Local regex; + if (v8::RegExp::New(context, toV8String(isolate, pattern), + static_cast(flags)) + .ToLocal(®ex)) + m_regex.Reset(isolate, regex); + else if (tryCatch.HasCaught()) + m_errorMessage = toProtocolString(tryCatch.Message()->Get()); + else + m_errorMessage = "Internal error"; +} + +int V8Regex::match(const String16& string, int startFrom, + int* matchLength) const { + if (matchLength) *matchLength = 0; + + if (m_regex.IsEmpty() || string.isEmpty()) return -1; + + // v8 strings are limited to int. + if (string.length() > INT_MAX) return -1; + + v8::Isolate* isolate = m_inspector->isolate(); + v8::HandleScope handleScope(isolate); + v8::Local context = m_inspector->regexContext(); + v8::MicrotasksScope microtasks(isolate, + v8::MicrotasksScope::kDoNotRunMicrotasks); + v8::TryCatch tryCatch(isolate); + + v8::Local regex = m_regex.Get(isolate); + v8::Local exec; + if (!regex->Get(context, toV8StringInternalized(isolate, "exec")) + .ToLocal(&exec)) + return -1; + v8::Local argv[] = { + toV8String(isolate, string.substring(startFrom))}; + v8::Local returnValue; + if (!exec.As() + ->Call(context, regex, arraysize(argv), argv) + .ToLocal(&returnValue)) + return -1; + + // RegExp#exec returns null if there's no match, otherwise it returns an + // Array of strings with the first being the whole match string and others + // being subgroups. The Array also has some random properties tacked on like + // "index" which is the offset of the match. + // + // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec + + DCHECK(!returnValue.IsEmpty()); + if (!returnValue->IsArray()) return -1; + + v8::Local result = returnValue.As(); + v8::Local matchOffset; + if (!result->Get(context, toV8StringInternalized(isolate, "index")) + .ToLocal(&matchOffset)) + return -1; + if (matchLength) { + v8::Local match; + if (!result->Get(context, 0).ToLocal(&match)) return -1; + *matchLength = match.As()->Length(); + } + + return matchOffset.As()->Value() + startFrom; +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-regex.h b/deps/v8_inspector/src/inspector/v8-regex.h new file mode 100644 index 00000000000000..b4b1f8ce13517a --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-regex.h @@ -0,0 +1,37 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8REGEX_H_ +#define V8_INSPECTOR_V8REGEX_H_ + +#include "src/base/macros.h" +#include "src/inspector/string-16.h" + +#include "include/v8.h" + +namespace v8_inspector { + +class V8InspectorImpl; + +enum MultilineMode { MultilineDisabled, MultilineEnabled }; + +class V8Regex { + public: + V8Regex(V8InspectorImpl*, const String16&, bool caseSensitive, + bool multiline = false); + int match(const String16&, int startFrom = 0, int* matchLength = 0) const; + bool isValid() const { return !m_regex.IsEmpty(); } + const String16& errorMessage() const { return m_errorMessage; } + + private: + V8InspectorImpl* m_inspector; + v8::Global m_regex; + String16 m_errorMessage; + + DISALLOW_COPY_AND_ASSIGN(V8Regex); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8REGEX_H_ diff --git a/deps/v8_inspector/src/inspector/v8-runtime-agent-impl.cc b/deps/v8_inspector/src/inspector/v8-runtime-agent-impl.cc new file mode 100644 index 00000000000000..640ec317d23752 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-runtime-agent-impl.cc @@ -0,0 +1,738 @@ +/* + * 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. + */ + +#include "src/inspector/v8-runtime-agent-impl.h" + +#include "src/inspector/injected-script.h" +#include "src/inspector/inspected-context.h" +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/remote-object-id.h" +#include "src/inspector/string-util.h" +#include "src/inspector/v8-console-message.h" +#include "src/inspector/v8-debugger-agent-impl.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-inspector-session-impl.h" +#include "src/inspector/v8-stack-trace-impl.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +namespace V8RuntimeAgentImplState { +static const char customObjectFormatterEnabled[] = + "customObjectFormatterEnabled"; +static const char runtimeEnabled[] = "runtimeEnabled"; +}; + +using protocol::Runtime::RemoteObject; + +static bool hasInternalError(ErrorString* errorString, bool hasError) { + if (hasError) *errorString = "Internal error"; + return hasError; +} + +namespace { + +template +class ProtocolPromiseHandler { + public: + static void add(V8InspectorImpl* inspector, v8::Local context, + v8::MaybeLocal value, + const String16& notPromiseError, int contextGroupId, + int executionContextId, const String16& objectGroup, + bool returnByValue, bool generatePreview, + std::unique_ptr callback) { + if (value.IsEmpty()) { + callback->sendFailure("Internal error"); + return; + } + if (!value.ToLocalChecked()->IsPromise()) { + callback->sendFailure(notPromiseError); + return; + } + v8::MicrotasksScope microtasks_scope(inspector->isolate(), + v8::MicrotasksScope::kRunMicrotasks); + v8::Local promise = + v8::Local::Cast(value.ToLocalChecked()); + Callback* rawCallback = callback.get(); + ProtocolPromiseHandler* handler = new ProtocolPromiseHandler( + inspector, contextGroupId, executionContextId, objectGroup, + returnByValue, generatePreview, std::move(callback)); + v8::Local wrapper = handler->m_wrapper.Get(inspector->isolate()); + + v8::Local thenCallbackFunction = + v8::Function::New(context, thenCallback, wrapper, 0, + v8::ConstructorBehavior::kThrow) + .ToLocalChecked(); + if (promise->Then(context, thenCallbackFunction).IsEmpty()) { + rawCallback->sendFailure("Internal error"); + return; + } + v8::Local catchCallbackFunction = + v8::Function::New(context, catchCallback, wrapper, 0, + v8::ConstructorBehavior::kThrow) + .ToLocalChecked(); + if (promise->Catch(context, catchCallbackFunction).IsEmpty()) { + rawCallback->sendFailure("Internal error"); + return; + } + } + + private: + static void thenCallback(const v8::FunctionCallbackInfo& info) { + ProtocolPromiseHandler* handler = + static_cast*>( + info.Data().As()->Value()); + DCHECK(handler); + v8::Local value = + info.Length() > 0 + ? info[0] + : v8::Local::Cast(v8::Undefined(info.GetIsolate())); + std::unique_ptr wrappedValue( + handler->wrapObject(value)); + if (!wrappedValue) return; + handler->m_callback->sendSuccess( + std::move(wrappedValue), Maybe()); + } + + static void catchCallback(const v8::FunctionCallbackInfo& info) { + ProtocolPromiseHandler* handler = + static_cast*>( + info.Data().As()->Value()); + DCHECK(handler); + v8::Local value = + info.Length() > 0 + ? info[0] + : v8::Local::Cast(v8::Undefined(info.GetIsolate())); + + std::unique_ptr wrappedValue( + handler->wrapObject(value)); + if (!wrappedValue) return; + + std::unique_ptr stack = + handler->m_inspector->debugger()->captureStackTrace(true); + std::unique_ptr exceptionDetails = + protocol::Runtime::ExceptionDetails::create() + .setExceptionId(handler->m_inspector->nextExceptionId()) + .setText("Uncaught (in promise)") + .setLineNumber(stack && !stack->isEmpty() ? stack->topLineNumber() + : 0) + .setColumnNumber( + stack && !stack->isEmpty() ? stack->topColumnNumber() : 0) + .setException(wrappedValue->clone()) + .build(); + if (stack) + exceptionDetails->setStackTrace(stack->buildInspectorObjectImpl()); + if (stack && !stack->isEmpty()) + exceptionDetails->setScriptId(toString16(stack->topScriptId())); + handler->m_callback->sendSuccess(std::move(wrappedValue), + std::move(exceptionDetails)); + } + + ProtocolPromiseHandler(V8InspectorImpl* inspector, int contextGroupId, + int executionContextId, const String16& objectGroup, + bool returnByValue, bool generatePreview, + std::unique_ptr callback) + : m_inspector(inspector), + m_contextGroupId(contextGroupId), + m_executionContextId(executionContextId), + m_objectGroup(objectGroup), + m_returnByValue(returnByValue), + m_generatePreview(generatePreview), + m_callback(std::move(callback)), + m_wrapper(inspector->isolate(), + v8::External::New(inspector->isolate(), this)) { + m_wrapper.SetWeak(this, cleanup, v8::WeakCallbackType::kParameter); + } + + static void cleanup( + const v8::WeakCallbackInfo>& data) { + if (!data.GetParameter()->m_wrapper.IsEmpty()) { + data.GetParameter()->m_wrapper.Reset(); + data.SetSecondPassCallback(cleanup); + } else { + data.GetParameter()->m_callback->sendFailure("Promise was collected"); + delete data.GetParameter(); + } + } + + std::unique_ptr wrapObject( + v8::Local value) { + ErrorString errorString; + InjectedScript::ContextScope scope(&errorString, m_inspector, + m_contextGroupId, m_executionContextId); + if (!scope.initialize()) { + m_callback->sendFailure(errorString); + return nullptr; + } + std::unique_ptr wrappedValue = + scope.injectedScript()->wrapObject(&errorString, value, m_objectGroup, + m_returnByValue, m_generatePreview); + if (!wrappedValue) { + m_callback->sendFailure(errorString); + return nullptr; + } + return wrappedValue; + } + + V8InspectorImpl* m_inspector; + int m_contextGroupId; + int m_executionContextId; + String16 m_objectGroup; + bool m_returnByValue; + bool m_generatePreview; + std::unique_ptr m_callback; + v8::Global m_wrapper; +}; + +template +bool wrapEvaluateResultAsync(InjectedScript* injectedScript, + v8::MaybeLocal maybeResultValue, + const v8::TryCatch& tryCatch, + const String16& objectGroup, bool returnByValue, + bool generatePreview, Callback* callback) { + std::unique_ptr result; + Maybe exceptionDetails; + + ErrorString errorString; + injectedScript->wrapEvaluateResult( + &errorString, maybeResultValue, tryCatch, objectGroup, returnByValue, + generatePreview, &result, &exceptionDetails); + if (errorString.isEmpty()) { + callback->sendSuccess(std::move(result), exceptionDetails); + return true; + } + callback->sendFailure(errorString); + return false; +} + +int ensureContext(ErrorString* errorString, V8InspectorImpl* inspector, + int contextGroupId, const Maybe& executionContextId) { + int contextId; + if (executionContextId.isJust()) { + contextId = executionContextId.fromJust(); + } else { + v8::HandleScope handles(inspector->isolate()); + v8::Local defaultContext = + inspector->client()->ensureDefaultContextInGroup(contextGroupId); + if (defaultContext.IsEmpty()) { + *errorString = "Cannot find default execution context"; + return 0; + } + contextId = V8Debugger::contextId(defaultContext); + } + return contextId; +} + +} // namespace + +V8RuntimeAgentImpl::V8RuntimeAgentImpl( + V8InspectorSessionImpl* session, protocol::FrontendChannel* FrontendChannel, + protocol::DictionaryValue* state) + : m_session(session), + m_state(state), + m_frontend(FrontendChannel), + m_inspector(session->inspector()), + m_enabled(false) {} + +V8RuntimeAgentImpl::~V8RuntimeAgentImpl() {} + +void V8RuntimeAgentImpl::evaluate( + const String16& expression, const Maybe& objectGroup, + const Maybe& includeCommandLineAPI, const Maybe& silent, + const Maybe& executionContextId, const Maybe& returnByValue, + const Maybe& generatePreview, const Maybe& userGesture, + const Maybe& awaitPromise, + std::unique_ptr callback) { + ErrorString errorString; + int contextId = + ensureContext(&errorString, m_inspector, m_session->contextGroupId(), + executionContextId); + if (!errorString.isEmpty()) { + callback->sendFailure(errorString); + return; + } + + InjectedScript::ContextScope scope(&errorString, m_inspector, + m_session->contextGroupId(), contextId); + if (!scope.initialize()) { + callback->sendFailure(errorString); + return; + } + + if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); + if (userGesture.fromMaybe(false)) scope.pretendUserGesture(); + + if (includeCommandLineAPI.fromMaybe(false) && + !scope.installCommandLineAPI()) { + callback->sendFailure(errorString); + return; + } + + bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed(); + // Temporarily enable allow evals for inspector. + if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(true); + + v8::MaybeLocal maybeResultValue; + v8::Local script = m_inspector->compileScript( + scope.context(), toV8String(m_inspector->isolate(), expression), + String16(), false); + if (!script.IsEmpty()) + maybeResultValue = m_inspector->runCompiledScript(scope.context(), script); + + if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(false); + + // Re-initialize after running client's code, as it could have destroyed + // context or session. + if (!scope.initialize()) { + callback->sendFailure(errorString); + return; + } + + if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) { + wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue, + scope.tryCatch(), objectGroup.fromMaybe(""), + returnByValue.fromMaybe(false), + generatePreview.fromMaybe(false), callback.get()); + return; + } + ProtocolPromiseHandler::add( + m_inspector, scope.context(), maybeResultValue, + "Result of the evaluation is not a promise", m_session->contextGroupId(), + scope.injectedScript()->context()->contextId(), objectGroup.fromMaybe(""), + returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), + std::move(callback)); +} + +void V8RuntimeAgentImpl::awaitPromise( + const String16& promiseObjectId, const Maybe& returnByValue, + const Maybe& generatePreview, + std::unique_ptr callback) { + ErrorString errorString; + InjectedScript::ObjectScope scope( + &errorString, m_inspector, m_session->contextGroupId(), promiseObjectId); + if (!scope.initialize()) { + callback->sendFailure(errorString); + return; + } + ProtocolPromiseHandler::add( + m_inspector, scope.context(), scope.object(), + "Could not find promise with given id", m_session->contextGroupId(), + scope.injectedScript()->context()->contextId(), scope.objectGroupName(), + returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), + std::move(callback)); +} + +void V8RuntimeAgentImpl::callFunctionOn( + const String16& objectId, const String16& expression, + const Maybe>& + optionalArguments, + const Maybe& silent, const Maybe& returnByValue, + const Maybe& generatePreview, const Maybe& userGesture, + const Maybe& awaitPromise, + std::unique_ptr callback) { + ErrorString errorString; + InjectedScript::ObjectScope scope(&errorString, m_inspector, + m_session->contextGroupId(), objectId); + if (!scope.initialize()) { + callback->sendFailure(errorString); + return; + } + + std::unique_ptr[]> argv = nullptr; + int argc = 0; + if (optionalArguments.isJust()) { + protocol::Array* arguments = + optionalArguments.fromJust(); + argc = static_cast(arguments->length()); + argv.reset(new v8::Local[argc]); + for (int i = 0; i < argc; ++i) { + v8::Local argumentValue; + if (!scope.injectedScript() + ->resolveCallArgument(&errorString, arguments->get(i)) + .ToLocal(&argumentValue)) { + callback->sendFailure(errorString); + return; + } + argv[i] = argumentValue; + } + } + + if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); + if (userGesture.fromMaybe(false)) scope.pretendUserGesture(); + + v8::MaybeLocal maybeFunctionValue = + m_inspector->compileAndRunInternalScript( + scope.context(), + toV8String(m_inspector->isolate(), "(" + expression + ")")); + // Re-initialize after running client's code, as it could have destroyed + // context or session. + if (!scope.initialize()) { + callback->sendFailure(errorString); + return; + } + + if (scope.tryCatch().HasCaught()) { + wrapEvaluateResultAsync(scope.injectedScript(), maybeFunctionValue, + scope.tryCatch(), scope.objectGroupName(), false, + false, callback.get()); + return; + } + + v8::Local functionValue; + if (!maybeFunctionValue.ToLocal(&functionValue) || + !functionValue->IsFunction()) { + callback->sendFailure("Given expression does not evaluate to a function"); + return; + } + + v8::MaybeLocal maybeResultValue = m_inspector->callFunction( + functionValue.As(), scope.context(), scope.object(), argc, + argv.get()); + // Re-initialize after running client's code, as it could have destroyed + // context or session. + if (!scope.initialize()) { + callback->sendFailure(errorString); + return; + } + + if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) { + wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue, + scope.tryCatch(), scope.objectGroupName(), + returnByValue.fromMaybe(false), + generatePreview.fromMaybe(false), callback.get()); + return; + } + + ProtocolPromiseHandler::add( + m_inspector, scope.context(), maybeResultValue, + "Result of the function call is not a promise", + m_session->contextGroupId(), + scope.injectedScript()->context()->contextId(), scope.objectGroupName(), + returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), + std::move(callback)); +} + +void V8RuntimeAgentImpl::getProperties( + ErrorString* errorString, const String16& objectId, + const Maybe& ownProperties, const Maybe& accessorPropertiesOnly, + const Maybe& generatePreview, + std::unique_ptr>* + result, + Maybe>* + internalProperties, + Maybe* exceptionDetails) { + using protocol::Runtime::InternalPropertyDescriptor; + + InjectedScript::ObjectScope scope(errorString, m_inspector, + m_session->contextGroupId(), objectId); + if (!scope.initialize()) return; + + scope.ignoreExceptionsAndMuteConsole(); + if (!scope.object()->IsObject()) { + *errorString = "Value with given id is not an object"; + return; + } + + v8::Local object = scope.object().As(); + scope.injectedScript()->getProperties( + errorString, object, scope.objectGroupName(), + ownProperties.fromMaybe(false), accessorPropertiesOnly.fromMaybe(false), + generatePreview.fromMaybe(false), result, exceptionDetails); + if (!errorString->isEmpty() || exceptionDetails->isJust() || + accessorPropertiesOnly.fromMaybe(false)) + return; + v8::Local propertiesArray; + if (hasInternalError(errorString, !m_inspector->debugger() + ->internalProperties(scope.context(), + scope.object()) + .ToLocal(&propertiesArray))) + return; + std::unique_ptr> + propertiesProtocolArray = + protocol::Array::create(); + for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) { + v8::Local name; + if (hasInternalError( + errorString, + !propertiesArray->Get(scope.context(), i).ToLocal(&name)) || + !name->IsString()) + return; + v8::Local value; + if (hasInternalError( + errorString, + !propertiesArray->Get(scope.context(), i + 1).ToLocal(&value))) + return; + std::unique_ptr wrappedValue = + scope.injectedScript()->wrapObject(errorString, value, + scope.objectGroupName()); + if (!wrappedValue) return; + propertiesProtocolArray->addItem( + InternalPropertyDescriptor::create() + .setName(toProtocolString(name.As())) + .setValue(std::move(wrappedValue)) + .build()); + } + if (!propertiesProtocolArray->length()) return; + *internalProperties = std::move(propertiesProtocolArray); +} + +void V8RuntimeAgentImpl::releaseObject(ErrorString* errorString, + const String16& objectId) { + InjectedScript::ObjectScope scope(errorString, m_inspector, + m_session->contextGroupId(), objectId); + if (!scope.initialize()) return; + scope.injectedScript()->releaseObject(objectId); +} + +void V8RuntimeAgentImpl::releaseObjectGroup(ErrorString*, + const String16& objectGroup) { + m_session->releaseObjectGroup(objectGroup); +} + +void V8RuntimeAgentImpl::runIfWaitingForDebugger(ErrorString* errorString) { + m_inspector->client()->runIfWaitingForDebugger(m_session->contextGroupId()); +} + +void V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(ErrorString*, + bool enabled) { + m_state->setBoolean(V8RuntimeAgentImplState::customObjectFormatterEnabled, + enabled); + m_session->setCustomObjectFormatterEnabled(enabled); +} + +void V8RuntimeAgentImpl::discardConsoleEntries(ErrorString*) { + V8ConsoleMessageStorage* storage = + m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId()); + storage->clear(); +} + +void V8RuntimeAgentImpl::compileScript( + ErrorString* errorString, const String16& expression, + const String16& sourceURL, bool persistScript, + const Maybe& executionContextId, Maybe* scriptId, + Maybe* exceptionDetails) { + if (!m_enabled) { + *errorString = "Runtime agent is not enabled"; + return; + } + int contextId = + ensureContext(errorString, m_inspector, m_session->contextGroupId(), + executionContextId); + if (!errorString->isEmpty()) return; + InjectedScript::ContextScope scope(errorString, m_inspector, + m_session->contextGroupId(), contextId); + if (!scope.initialize()) return; + + if (!persistScript) m_inspector->debugger()->muteScriptParsedEvents(); + v8::Local script = m_inspector->compileScript( + scope.context(), toV8String(m_inspector->isolate(), expression), + sourceURL, false); + if (!persistScript) m_inspector->debugger()->unmuteScriptParsedEvents(); + if (script.IsEmpty()) { + if (scope.tryCatch().HasCaught()) + *exceptionDetails = scope.injectedScript()->createExceptionDetails( + errorString, scope.tryCatch(), String16(), false); + else + *errorString = "Script compilation failed"; + return; + } + + if (!persistScript) return; + + String16 scriptValueId = + String16::fromInteger(script->GetUnboundScript()->GetId()); + std::unique_ptr> global( + new v8::Global(m_inspector->isolate(), script)); + m_compiledScripts[scriptValueId] = std::move(global); + *scriptId = scriptValueId; +} + +void V8RuntimeAgentImpl::runScript( + const String16& scriptId, const Maybe& executionContextId, + const Maybe& objectGroup, const Maybe& silent, + const Maybe& includeCommandLineAPI, const Maybe& returnByValue, + const Maybe& generatePreview, const Maybe& awaitPromise, + std::unique_ptr callback) { + if (!m_enabled) { + callback->sendFailure("Runtime agent is not enabled"); + return; + } + + auto it = m_compiledScripts.find(scriptId); + if (it == m_compiledScripts.end()) { + callback->sendFailure("No script with given id"); + return; + } + + ErrorString errorString; + int contextId = + ensureContext(&errorString, m_inspector, m_session->contextGroupId(), + executionContextId); + if (!errorString.isEmpty()) { + callback->sendFailure(errorString); + return; + } + + InjectedScript::ContextScope scope(&errorString, m_inspector, + m_session->contextGroupId(), contextId); + if (!scope.initialize()) { + callback->sendFailure(errorString); + return; + } + + if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); + + std::unique_ptr> scriptWrapper = std::move(it->second); + m_compiledScripts.erase(it); + v8::Local script = scriptWrapper->Get(m_inspector->isolate()); + if (script.IsEmpty()) { + callback->sendFailure("Script execution failed"); + return; + } + + if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI()) + return; + + v8::MaybeLocal maybeResultValue = + m_inspector->runCompiledScript(scope.context(), script); + + // Re-initialize after running client's code, as it could have destroyed + // context or session. + if (!scope.initialize()) return; + + if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) { + wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue, + scope.tryCatch(), objectGroup.fromMaybe(""), + returnByValue.fromMaybe(false), + generatePreview.fromMaybe(false), callback.get()); + return; + } + ProtocolPromiseHandler::add( + m_inspector, scope.context(), maybeResultValue.ToLocalChecked(), + "Result of the script execution is not a promise", + m_session->contextGroupId(), + scope.injectedScript()->context()->contextId(), objectGroup.fromMaybe(""), + returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), + std::move(callback)); +} + +void V8RuntimeAgentImpl::restore() { + if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false)) + return; + m_frontend.executionContextsCleared(); + ErrorString error; + enable(&error); + if (m_state->booleanProperty( + V8RuntimeAgentImplState::customObjectFormatterEnabled, false)) + m_session->setCustomObjectFormatterEnabled(true); +} + +void V8RuntimeAgentImpl::enable(ErrorString* errorString) { + if (m_enabled) return; + m_inspector->client()->beginEnsureAllContextsInGroup( + m_session->contextGroupId()); + m_enabled = true; + m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, true); + m_inspector->enableStackCapturingIfNeeded(); + m_session->reportAllContexts(this); + V8ConsoleMessageStorage* storage = + m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId()); + for (const auto& message : storage->messages()) { + if (!reportMessage(message.get(), false)) return; + } +} + +void V8RuntimeAgentImpl::disable(ErrorString* errorString) { + if (!m_enabled) return; + m_enabled = false; + m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, false); + m_inspector->disableStackCapturingIfNeeded(); + m_session->discardInjectedScripts(); + reset(); + m_inspector->client()->endEnsureAllContextsInGroup( + m_session->contextGroupId()); +} + +void V8RuntimeAgentImpl::reset() { + m_compiledScripts.clear(); + if (m_enabled) { + if (const V8InspectorImpl::ContextByIdMap* contexts = + m_inspector->contextGroup(m_session->contextGroupId())) { + for (auto& idContext : *contexts) idContext.second->setReported(false); + } + m_frontend.executionContextsCleared(); + } +} + +void V8RuntimeAgentImpl::reportExecutionContextCreated( + InspectedContext* context) { + if (!m_enabled) return; + context->setReported(true); + std::unique_ptr description = + protocol::Runtime::ExecutionContextDescription::create() + .setId(context->contextId()) + .setName(context->humanReadableName()) + .setOrigin(context->origin()) + .build(); + if (!context->auxData().isEmpty()) + description->setAuxData(protocol::DictionaryValue::cast( + protocol::parseJSON(context->auxData()))); + m_frontend.executionContextCreated(std::move(description)); +} + +void V8RuntimeAgentImpl::reportExecutionContextDestroyed( + InspectedContext* context) { + if (m_enabled && context->isReported()) { + context->setReported(false); + m_frontend.executionContextDestroyed(context->contextId()); + } +} + +void V8RuntimeAgentImpl::inspect( + std::unique_ptr objectToInspect, + std::unique_ptr hints) { + if (m_enabled) + m_frontend.inspectRequested(std::move(objectToInspect), std::move(hints)); +} + +void V8RuntimeAgentImpl::messageAdded(V8ConsoleMessage* message) { + if (m_enabled) reportMessage(message, true); +} + +bool V8RuntimeAgentImpl::reportMessage(V8ConsoleMessage* message, + bool generatePreview) { + message->reportToFrontend(&m_frontend, m_session, generatePreview); + m_frontend.flush(); + return m_inspector->hasConsoleMessageStorage(m_session->contextGroupId()); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-runtime-agent-impl.h b/deps/v8_inspector/src/inspector/v8-runtime-agent-impl.h new file mode 100644 index 00000000000000..edeeed47ed455c --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-runtime-agent-impl.h @@ -0,0 +1,131 @@ +/* + * 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. + */ + +#ifndef V8_INSPECTOR_V8RUNTIMEAGENTIMPL_H_ +#define V8_INSPECTOR_V8RUNTIMEAGENTIMPL_H_ + +#include "src/base/macros.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/Runtime.h" + +#include "include/v8.h" + +namespace v8_inspector { + +class InjectedScript; +class InspectedContext; +class RemoteObjectIdBase; +class V8ConsoleMessage; +class V8InspectorImpl; +class V8InspectorSessionImpl; + +using protocol::ErrorString; +using protocol::Maybe; + +class V8RuntimeAgentImpl : public protocol::Runtime::Backend { + public: + V8RuntimeAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, + protocol::DictionaryValue* state); + ~V8RuntimeAgentImpl() override; + void restore(); + + // Part of the protocol. + void enable(ErrorString*) override; + void disable(ErrorString*) override; + void evaluate(const String16& expression, const Maybe& objectGroup, + const Maybe& includeCommandLineAPI, + const Maybe& silent, const Maybe& executionContextId, + const Maybe& returnByValue, + const Maybe& generatePreview, + const Maybe& userGesture, const Maybe& awaitPromise, + std::unique_ptr) override; + void awaitPromise(const String16& promiseObjectId, + const Maybe& returnByValue, + const Maybe& generatePreview, + std::unique_ptr) override; + void callFunctionOn( + const String16& objectId, const String16& expression, + const Maybe>& + optionalArguments, + const Maybe& silent, const Maybe& returnByValue, + const Maybe& generatePreview, const Maybe& userGesture, + const Maybe& awaitPromise, + std::unique_ptr) override; + void releaseObject(ErrorString*, const String16& objectId) override; + void getProperties( + ErrorString*, const String16& objectId, const Maybe& ownProperties, + const Maybe& accessorPropertiesOnly, + const Maybe& generatePreview, + std::unique_ptr>* + result, + Maybe>* + internalProperties, + Maybe*) override; + void releaseObjectGroup(ErrorString*, const String16& objectGroup) override; + void runIfWaitingForDebugger(ErrorString*) override; + void setCustomObjectFormatterEnabled(ErrorString*, bool) override; + void discardConsoleEntries(ErrorString*) override; + void compileScript(ErrorString*, const String16& expression, + const String16& sourceURL, bool persistScript, + const Maybe& executionContextId, Maybe*, + Maybe*) override; + void runScript(const String16&, const Maybe& executionContextId, + const Maybe& objectGroup, const Maybe& silent, + const Maybe& includeCommandLineAPI, + const Maybe& returnByValue, + const Maybe& generatePreview, + const Maybe& awaitPromise, + std::unique_ptr) override; + + void reset(); + void reportExecutionContextCreated(InspectedContext*); + void reportExecutionContextDestroyed(InspectedContext*); + void inspect(std::unique_ptr objectToInspect, + std::unique_ptr hints); + void messageAdded(V8ConsoleMessage*); + bool enabled() const { return m_enabled; } + + private: + bool reportMessage(V8ConsoleMessage*, bool generatePreview); + + V8InspectorSessionImpl* m_session; + protocol::DictionaryValue* m_state; + protocol::Runtime::Frontend m_frontend; + V8InspectorImpl* m_inspector; + bool m_enabled; + protocol::HashMap>> + m_compiledScripts; + + DISALLOW_COPY_AND_ASSIGN(V8RuntimeAgentImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8RUNTIMEAGENTIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-schema-agent-impl.cc b/deps/v8_inspector/src/inspector/v8-schema-agent-impl.cc new file mode 100644 index 00000000000000..9eed5bdf813710 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-schema-agent-impl.cc @@ -0,0 +1,29 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-schema-agent-impl.h" + +#include "src/inspector/protocol/Protocol.h" +#include "src/inspector/v8-inspector-session-impl.h" + +namespace v8_inspector { + +V8SchemaAgentImpl::V8SchemaAgentImpl(V8InspectorSessionImpl* session, + protocol::FrontendChannel* frontendChannel, + protocol::DictionaryValue* state) + : m_session(session), m_frontend(frontendChannel) {} + +V8SchemaAgentImpl::~V8SchemaAgentImpl() {} + +void V8SchemaAgentImpl::getDomains( + ErrorString*, + std::unique_ptr>* result) { + std::vector> domains = + m_session->supportedDomainsImpl(); + *result = protocol::Array::create(); + for (size_t i = 0; i < domains.size(); ++i) + (*result)->addItem(std::move(domains[i])); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-schema-agent-impl.h b/deps/v8_inspector/src/inspector/v8-schema-agent-impl.h new file mode 100644 index 00000000000000..6150201f8bdace --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-schema-agent-impl.h @@ -0,0 +1,37 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8SCHEMAAGENTIMPL_H_ +#define V8_INSPECTOR_V8SCHEMAAGENTIMPL_H_ + +#include "src/base/macros.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/Schema.h" + +namespace v8_inspector { + +class V8InspectorSessionImpl; + +using protocol::ErrorString; + +class V8SchemaAgentImpl : public protocol::Schema::Backend { + public: + V8SchemaAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, + protocol::DictionaryValue* state); + ~V8SchemaAgentImpl() override; + + void getDomains( + ErrorString*, + std::unique_ptr>*) override; + + private: + V8InspectorSessionImpl* m_session; + protocol::Schema::Frontend m_frontend; + + DISALLOW_COPY_AND_ASSIGN(V8SchemaAgentImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8SCHEMAAGENTIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-stack-trace-impl.cc b/deps/v8_inspector/src/inspector/v8-stack-trace-impl.cc new file mode 100644 index 00000000000000..1a38c6dd82a002 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-stack-trace-impl.cc @@ -0,0 +1,281 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-stack-trace-impl.h" + +#include "src/inspector/string-util.h" +#include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-impl.h" +#include "src/inspector/v8-profiler-agent-impl.h" + +#include "include/v8-debug.h" +#include "include/v8-profiler.h" +#include "include/v8-version.h" + +namespace v8_inspector { + +namespace { + +static const v8::StackTrace::StackTraceOptions stackTraceOptions = + static_cast( + v8::StackTrace::kLineNumber | v8::StackTrace::kColumnOffset | + v8::StackTrace::kScriptId | v8::StackTrace::kScriptNameOrSourceURL | + v8::StackTrace::kFunctionName); + +V8StackTraceImpl::Frame toFrame(v8::Local frame) { + String16 scriptId = String16::fromInteger(frame->GetScriptId()); + String16 sourceName; + v8::Local sourceNameValue(frame->GetScriptNameOrSourceURL()); + if (!sourceNameValue.IsEmpty()) + sourceName = toProtocolString(sourceNameValue); + + String16 functionName; + v8::Local functionNameValue(frame->GetFunctionName()); + if (!functionNameValue.IsEmpty()) + functionName = toProtocolString(functionNameValue); + + int sourceLineNumber = frame->GetLineNumber(); + int sourceColumn = frame->GetColumn(); + return V8StackTraceImpl::Frame(functionName, scriptId, sourceName, + sourceLineNumber, sourceColumn); +} + +void toFramesVector(v8::Local stackTrace, + std::vector& frames, + size_t maxStackSize, v8::Isolate* isolate) { + DCHECK(isolate->InContext()); + int frameCount = stackTrace->GetFrameCount(); + if (frameCount > static_cast(maxStackSize)) + frameCount = static_cast(maxStackSize); + for (int i = 0; i < frameCount; i++) { + v8::Local stackFrame = stackTrace->GetFrame(i); + frames.push_back(toFrame(stackFrame)); + } +} + +} // namespace + +V8StackTraceImpl::Frame::Frame() + : m_functionName("undefined"), + m_scriptId(""), + m_scriptName("undefined"), + m_lineNumber(0), + m_columnNumber(0) {} + +V8StackTraceImpl::Frame::Frame(const String16& functionName, + const String16& scriptId, + const String16& scriptName, int lineNumber, + int column) + : m_functionName(functionName), + m_scriptId(scriptId), + m_scriptName(scriptName), + m_lineNumber(lineNumber), + m_columnNumber(column) { + DCHECK(m_lineNumber != v8::Message::kNoLineNumberInfo); + DCHECK(m_columnNumber != v8::Message::kNoColumnInfo); +} + +V8StackTraceImpl::Frame::~Frame() {} + +// buildInspectorObject() and SourceLocation's toTracedValue() should set the +// same fields. +// If either of them is modified, the other should be also modified. +std::unique_ptr +V8StackTraceImpl::Frame::buildInspectorObject() const { + return protocol::Runtime::CallFrame::create() + .setFunctionName(m_functionName) + .setScriptId(m_scriptId) + .setUrl(m_scriptName) + .setLineNumber(m_lineNumber - 1) + .setColumnNumber(m_columnNumber - 1) + .build(); +} + +V8StackTraceImpl::Frame V8StackTraceImpl::Frame::clone() const { + return Frame(m_functionName, m_scriptId, m_scriptName, m_lineNumber, + m_columnNumber); +} + +// static +void V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions( + v8::Isolate* isolate, bool capture) { + isolate->SetCaptureStackTraceForUncaughtExceptions( + capture, V8StackTraceImpl::maxCallStackSizeToCapture, stackTraceOptions); +} + +// static +std::unique_ptr V8StackTraceImpl::create( + V8Debugger* debugger, int contextGroupId, + v8::Local stackTrace, size_t maxStackSize, + const String16& description) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + std::vector frames; + if (!stackTrace.IsEmpty()) + toFramesVector(stackTrace, frames, maxStackSize, isolate); + + int maxAsyncCallChainDepth = 1; + V8StackTraceImpl* asyncCallChain = nullptr; + if (debugger && maxStackSize > 1) { + asyncCallChain = debugger->currentAsyncCallChain(); + maxAsyncCallChainDepth = debugger->maxAsyncCallChainDepth(); + } + // Do not accidentally append async call chain from another group. This should + // not + // happen if we have proper instrumentation, but let's double-check to be + // safe. + if (contextGroupId && asyncCallChain && asyncCallChain->m_contextGroupId && + asyncCallChain->m_contextGroupId != contextGroupId) { + asyncCallChain = nullptr; + maxAsyncCallChainDepth = 1; + } + + // Only the top stack in the chain may be empty, so ensure that second stack + // is non-empty (it's the top of appended chain). + if (asyncCallChain && asyncCallChain->isEmpty()) + asyncCallChain = asyncCallChain->m_parent.get(); + + if (stackTrace.IsEmpty() && !asyncCallChain) return nullptr; + + std::unique_ptr result(new V8StackTraceImpl( + contextGroupId, description, frames, + asyncCallChain ? asyncCallChain->cloneImpl() : nullptr)); + + // Crop to not exceed maxAsyncCallChainDepth. + V8StackTraceImpl* deepest = result.get(); + while (deepest && maxAsyncCallChainDepth) { + deepest = deepest->m_parent.get(); + maxAsyncCallChainDepth--; + } + if (deepest) deepest->m_parent.reset(); + + return result; +} + +// static +std::unique_ptr V8StackTraceImpl::capture( + V8Debugger* debugger, int contextGroupId, size_t maxStackSize, + const String16& description) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handleScope(isolate); + v8::Local stackTrace; + if (isolate->InContext()) { + if (debugger) { + V8InspectorImpl* inspector = debugger->inspector(); + V8ProfilerAgentImpl* profilerAgent = + inspector->enabledProfilerAgentForGroup(contextGroupId); + if (profilerAgent) profilerAgent->collectSample(); + } + stackTrace = v8::StackTrace::CurrentStackTrace( + isolate, static_cast(maxStackSize), stackTraceOptions); + } + return V8StackTraceImpl::create(debugger, contextGroupId, stackTrace, + maxStackSize, description); +} + +std::unique_ptr V8StackTraceImpl::cloneImpl() { + std::vector framesCopy(m_frames); + return wrapUnique( + new V8StackTraceImpl(m_contextGroupId, m_description, framesCopy, + m_parent ? m_parent->cloneImpl() : nullptr)); +} + +std::unique_ptr V8StackTraceImpl::clone() { + std::vector frames; + for (size_t i = 0; i < m_frames.size(); i++) + frames.push_back(m_frames.at(i).clone()); + return wrapUnique( + new V8StackTraceImpl(m_contextGroupId, m_description, frames, nullptr)); +} + +V8StackTraceImpl::V8StackTraceImpl(int contextGroupId, + const String16& description, + std::vector& frames, + std::unique_ptr parent) + : m_contextGroupId(contextGroupId), + m_description(description), + m_parent(std::move(parent)) { + m_frames.swap(frames); +} + +V8StackTraceImpl::~V8StackTraceImpl() {} + +StringView V8StackTraceImpl::topSourceURL() const { + DCHECK(m_frames.size()); + return toStringView(m_frames[0].m_scriptName); +} + +int V8StackTraceImpl::topLineNumber() const { + DCHECK(m_frames.size()); + return m_frames[0].m_lineNumber; +} + +int V8StackTraceImpl::topColumnNumber() const { + DCHECK(m_frames.size()); + return m_frames[0].m_columnNumber; +} + +StringView V8StackTraceImpl::topFunctionName() const { + DCHECK(m_frames.size()); + return toStringView(m_frames[0].m_functionName); +} + +StringView V8StackTraceImpl::topScriptId() const { + DCHECK(m_frames.size()); + return toStringView(m_frames[0].m_scriptId); +} + +std::unique_ptr +V8StackTraceImpl::buildInspectorObjectImpl() const { + std::unique_ptr> frames = + protocol::Array::create(); + for (size_t i = 0; i < m_frames.size(); i++) + frames->addItem(m_frames.at(i).buildInspectorObject()); + + std::unique_ptr stackTrace = + protocol::Runtime::StackTrace::create() + .setCallFrames(std::move(frames)) + .build(); + if (!m_description.isEmpty()) stackTrace->setDescription(m_description); + if (m_parent) stackTrace->setParent(m_parent->buildInspectorObjectImpl()); + return stackTrace; +} + +std::unique_ptr +V8StackTraceImpl::buildInspectorObjectForTail(V8Debugger* debugger) const { + v8::HandleScope handleScope(v8::Isolate::GetCurrent()); + // Next call collapses possible empty stack and ensures + // maxAsyncCallChainDepth. + std::unique_ptr fullChain = V8StackTraceImpl::create( + debugger, m_contextGroupId, v8::Local(), + V8StackTraceImpl::maxCallStackSizeToCapture); + if (!fullChain || !fullChain->m_parent) return nullptr; + return fullChain->m_parent->buildInspectorObjectImpl(); +} + +std::unique_ptr +V8StackTraceImpl::buildInspectorObject() const { + return buildInspectorObjectImpl(); +} + +std::unique_ptr V8StackTraceImpl::toString() const { + String16Builder stackTrace; + for (size_t i = 0; i < m_frames.size(); ++i) { + const Frame& frame = m_frames[i]; + stackTrace.append("\n at " + (frame.functionName().length() + ? frame.functionName() + : "(anonymous function)")); + stackTrace.append(" ("); + stackTrace.append(frame.sourceURL()); + stackTrace.append(':'); + stackTrace.append(String16::fromInteger(frame.lineNumber())); + stackTrace.append(':'); + stackTrace.append(String16::fromInteger(frame.columnNumber())); + stackTrace.append(')'); + } + String16 string = stackTrace.toString(); + return StringBufferImpl::adopt(string); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-stack-trace-impl.h b/deps/v8_inspector/src/inspector/v8-stack-trace-impl.h new file mode 100644 index 00000000000000..f0a452e9390dd8 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-stack-trace-impl.h @@ -0,0 +1,99 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8STACKTRACEIMPL_H_ +#define V8_INSPECTOR_V8STACKTRACEIMPL_H_ + +#include + +#include "src/base/macros.h" +#include "src/inspector/protocol/Forward.h" +#include "src/inspector/protocol/Runtime.h" + +#include "include/v8-inspector.h" + +namespace v8_inspector { + +class TracedValue; +class V8Debugger; + +// Note: async stack trace may have empty top stack with non-empty tail to +// indicate +// that current native-only state had some async story. +// On the other hand, any non-top async stack is guaranteed to be non-empty. +class V8StackTraceImpl final : public V8StackTrace { + public: + static const size_t maxCallStackSizeToCapture = 200; + + class Frame { + public: + Frame(); + Frame(const String16& functionName, const String16& scriptId, + const String16& scriptName, int lineNumber, int column = 0); + ~Frame(); + + const String16& functionName() const { return m_functionName; } + const String16& scriptId() const { return m_scriptId; } + const String16& sourceURL() const { return m_scriptName; } + int lineNumber() const { return m_lineNumber; } + int columnNumber() const { return m_columnNumber; } + Frame clone() const; + + private: + friend class V8StackTraceImpl; + std::unique_ptr buildInspectorObject() const; + void toTracedValue(TracedValue*) const; + + String16 m_functionName; + String16 m_scriptId; + String16 m_scriptName; + int m_lineNumber; + int m_columnNumber; + }; + + static void setCaptureStackTraceForUncaughtExceptions(v8::Isolate*, + bool capture); + static std::unique_ptr create( + V8Debugger*, int contextGroupId, v8::Local, + size_t maxStackSize, const String16& description = String16()); + static std::unique_ptr capture( + V8Debugger*, int contextGroupId, size_t maxStackSize, + const String16& description = String16()); + + // This method drops the async chain. Use cloneImpl() instead. + std::unique_ptr clone() override; + std::unique_ptr cloneImpl(); + std::unique_ptr buildInspectorObjectForTail( + V8Debugger*) const; + std::unique_ptr buildInspectorObjectImpl() + const; + ~V8StackTraceImpl() override; + + // V8StackTrace implementation. + bool isEmpty() const override { return !m_frames.size(); }; + StringView topSourceURL() const override; + int topLineNumber() const override; + int topColumnNumber() const override; + StringView topScriptId() const override; + StringView topFunctionName() const override; + std::unique_ptr buildInspectorObject() + const override; + std::unique_ptr toString() const override; + + private: + V8StackTraceImpl(int contextGroupId, const String16& description, + std::vector& frames, + std::unique_ptr parent); + + int m_contextGroupId; + String16 m_description; + std::vector m_frames; + std::unique_ptr m_parent; + + DISALLOW_COPY_AND_ASSIGN(V8StackTraceImpl); +}; + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8STACKTRACEIMPL_H_ diff --git a/deps/v8_inspector/src/inspector/v8-value-copier.cc b/deps/v8_inspector/src/inspector/v8-value-copier.cc new file mode 100644 index 00000000000000..09d86b7b985016 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-value-copier.cc @@ -0,0 +1,110 @@ +// Copyright 2016 the V8 project 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 "src/inspector/v8-value-copier.h" + +namespace v8_inspector { + +namespace { + +static int kMaxDepth = 20; +static int kMaxCalls = 1000; + +class V8ValueCopier { + public: + v8::MaybeLocal copy(v8::Local value, int depth) { + if (++m_calls > kMaxCalls || depth > kMaxDepth) + return v8::MaybeLocal(); + + if (value.IsEmpty()) return v8::MaybeLocal(); + if (value->IsNull() || value->IsUndefined() || value->IsBoolean() || + value->IsString() || value->IsNumber()) + return value; + if (!value->IsObject()) return v8::MaybeLocal(); + v8::Local object = value.As(); + if (object->CreationContext() != m_from) return value; + + if (object->IsArray()) { + v8::Local array = object.As(); + v8::Local result = v8::Array::New(m_isolate, array->Length()); + if (!result->SetPrototype(m_to, v8::Null(m_isolate)).FromMaybe(false)) + return v8::MaybeLocal(); + for (uint32_t i = 0; i < array->Length(); ++i) { + v8::Local item; + if (!array->Get(m_from, i).ToLocal(&item)) + return v8::MaybeLocal(); + v8::Local copied; + if (!copy(item, depth + 1).ToLocal(&copied)) + return v8::MaybeLocal(); + if (!createDataProperty(m_to, result, i, copied).FromMaybe(false)) + return v8::MaybeLocal(); + } + return result; + } + + v8::Local result = v8::Object::New(m_isolate); + if (!result->SetPrototype(m_to, v8::Null(m_isolate)).FromMaybe(false)) + return v8::MaybeLocal(); + v8::Local properties; + if (!object->GetOwnPropertyNames(m_from).ToLocal(&properties)) + return v8::MaybeLocal(); + for (uint32_t i = 0; i < properties->Length(); ++i) { + v8::Local name; + if (!properties->Get(m_from, i).ToLocal(&name) || !name->IsString()) + return v8::MaybeLocal(); + v8::Local property; + if (!object->Get(m_from, name).ToLocal(&property)) + return v8::MaybeLocal(); + v8::Local copied; + if (!copy(property, depth + 1).ToLocal(&copied)) + return v8::MaybeLocal(); + if (!createDataProperty(m_to, result, v8::Local::Cast(name), + copied) + .FromMaybe(false)) + return v8::MaybeLocal(); + } + return result; + } + + v8::Isolate* m_isolate; + v8::Local m_from; + v8::Local m_to; + int m_calls; +}; + +} // namespace + +v8::MaybeLocal copyValueFromDebuggerContext( + v8::Isolate* isolate, v8::Local debuggerContext, + v8::Local toContext, v8::Local value) { + V8ValueCopier copier; + copier.m_isolate = isolate; + copier.m_from = debuggerContext; + copier.m_to = toContext; + copier.m_calls = 0; + return copier.copy(value, 0); +} + +v8::Maybe createDataProperty(v8::Local context, + v8::Local object, + v8::Local key, + v8::Local value) { + v8::TryCatch tryCatch(context->GetIsolate()); + v8::Isolate::DisallowJavascriptExecutionScope throwJs( + context->GetIsolate(), + v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE); + return object->CreateDataProperty(context, key, value); +} + +v8::Maybe createDataProperty(v8::Local context, + v8::Local array, int index, + v8::Local value) { + v8::TryCatch tryCatch(context->GetIsolate()); + v8::Isolate::DisallowJavascriptExecutionScope throwJs( + context->GetIsolate(), + v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE); + return array->CreateDataProperty(context, index, value); +} + +} // namespace v8_inspector diff --git a/deps/v8_inspector/src/inspector/v8-value-copier.h b/deps/v8_inspector/src/inspector/v8-value-copier.h new file mode 100644 index 00000000000000..c24a5648a21642 --- /dev/null +++ b/deps/v8_inspector/src/inspector/v8-value-copier.h @@ -0,0 +1,24 @@ +// Copyright 2016 the V8 project 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 V8_INSPECTOR_V8VALUECOPIER_H_ +#define V8_INSPECTOR_V8VALUECOPIER_H_ + +#include "include/v8.h" + +namespace v8_inspector { + +v8::MaybeLocal copyValueFromDebuggerContext( + v8::Isolate*, v8::Local debuggerContext, + v8::Local toContext, v8::Local); +v8::Maybe createDataProperty(v8::Local, + v8::Local, + v8::Local key, + v8::Local); +v8::Maybe createDataProperty(v8::Local, v8::Local, + int index, v8::Local); + +} // namespace v8_inspector + +#endif // V8_INSPECTOR_V8VALUECOPIER_H_ diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/generate-inspector-protocol-version b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/CheckProtocolCompatibility.py similarity index 59% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/generate-inspector-protocol-version rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/CheckProtocolCompatibility.py index 8c13092541378d..dd9acad898b43e 100755 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/generate-inspector-protocol-version +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/CheckProtocolCompatibility.py @@ -45,11 +45,9 @@ # # Adding --show_changes to the command line prints out a list of valid public API changes. -import collections import copy import os.path import optparse -import re import sys try: @@ -57,10 +55,11 @@ except ImportError: import simplejson as json + def list_to_map(items, key): result = {} for item in items: - if not "experimental" in item and not "hidden" in item: + if "experimental" not in item and "hidden" not in item: result[item[key]] = item return result @@ -95,7 +94,7 @@ def compare_schemas(d_1, d_2, reverse): for name in domains_by_name_1: domain_1 = domains_by_name_1[name] - if not name in domains_by_name_2: + 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) @@ -108,7 +107,7 @@ def compare_domains(domain_1, domain_2, types_map_1, types_map_2, errors, revers commands_2 = named_list_to_map(domain_2, "commands", "name") for name in commands_1: command_1 = commands_1[name] - if not name in commands_2: + 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) @@ -117,7 +116,7 @@ def compare_domains(domain_1, domain_2, types_map_1, types_map_2, errors, revers events_2 = named_list_to_map(domain_2, "events", "name") for name in events_1: event_1 = events_1[name] - if not name in events_2: + 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) @@ -146,13 +145,13 @@ def compare_events(domain_name, event_1, event_2, types_map_1, types_map_2, erro 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 not name in params_2: - if not "optional" in param_1: + 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 not "optional" in param_1: + 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) @@ -187,7 +186,7 @@ def compare_types(context, kind, type_1, type_2, types_map_1, types_map_2, depth def extract_type(typed_object, types_map, errors): if "type" in typed_object: - result = { "id": "", "type": typed_object["type"] } + result = {"id": "", "type": typed_object["type"]} if typed_object["type"] == "object": result["properties"] = [] elif typed_object["type"] == "array": @@ -195,9 +194,9 @@ def extract_type(typed_object, types_map, errors): return result elif "$ref" in typed_object: ref = typed_object["$ref"] - if not ref in types_map: + if ref not in types_map: errors.append("Can not resolve type: %s" % ref) - types_map[ref] = { "id": "", "type": "object" } + types_map[ref] = {"id": "", "type": "object"} return types_map[ref] @@ -224,10 +223,11 @@ def normalize_types(obj, domain_name, types): normalize_types(value, domain_name, types) -def load_schema(file, domains): - if not os.path.isfile(file): +def load_schema(file_name, domains): + # pylint: disable=W0613 + if not os.path.isfile(file_name): return - input_file = open(file, "r") + input_file = open(file_name, "r") json_string = input_file.read() parsed_json = json.loads(json_string) domains += parsed_json["domains"] @@ -237,141 +237,141 @@ def load_schema(file, domains): 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 }, + { + "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"}, ] - }, - { - "name": "removedEvent", - "parameters": [ - { "name": "errorText", "type": "string" }, - { "name": "canceled", "type": "boolean", "optional": True } - ] - } - ] - }, - { - "domain": "removedDomain" - } - ] + } + ], + "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" - } - ] + { + "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", @@ -389,16 +389,16 @@ def create_test_schema_2(): ] 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", + "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): @@ -418,11 +418,10 @@ def errors_match(expected, actual): compare_schemas(create_test_schema_2(), create_test_schema_1(), True))) - -def load_domains_and_baselines(file, domains, baseline_domains): - version = load_schema(os.path.normpath(file), domains) +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.replace(".json", suffix) + baseline_file = file_name.replace(".json", suffix) load_schema(os.path.normpath(baseline_file), baseline_domains) return version @@ -434,29 +433,25 @@ def main(): cmdline_parser = optparse.OptionParser() cmdline_parser.add_option("--show_changes") - cmdline_parser.add_option("--o") + cmdline_parser.add_option("--expected_errors") + cmdline_parser.add_option("--stamp") arg_options, arg_values = cmdline_parser.parse_args() - if len(arg_values) < 1 or not arg_options.o: - sys.stderr.write("Usage: %s --o OUTPUT_FILE [--show_changes] PROTOCOL_FOLDER1 ?PROTOCOL_FOLDER2 \n" % sys.argv[0]) + if len(arg_values) < 1: + sys.stderr.write("Usage: %s [--show_changes] [, ...]\n" % sys.argv[0]) return 1 - output_path = arg_options.o - output_file = open(output_path, "w") - domains = [] baseline_domains = [] version = load_domains_and_baselines(arg_values[0], domains, baseline_domains) - if len(arg_values) > 1: - load_domains_and_baselines(arg_values[1], domains, baseline_domains) + for dependency in arg_values[1:]: + load_domains_and_baselines(dependency, domains, baseline_domains) - expected_errors = [ - "Debugger.globalObjectCleared: event has been removed", - "Runtime.executionContextCreated.context parameter->Runtime.ExecutionContextDescription.frameId: required property has been removed", - "Debugger.canSetScriptSource: command has been removed", - "Console.messageRepeatCountUpdated: event has been removed", - "Console.messagesCleared: event has been removed" - ] + 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 = [] @@ -466,7 +461,7 @@ def main(): if len(unexpected_errors) > 0: sys.stderr.write(" Compatibility checks FAILED\n") for error in unexpected_errors: - sys.stderr.write( " %s\n" % error) + sys.stderr.write(" %s\n" % error) return 1 if arg_options.show_changes: @@ -476,8 +471,9 @@ def main(): for change in changes: print " %s" % change - json.dump({"version": version, "domains": domains}, output_file, indent=4, sort_keys=False, separators=(',', ': ')) - output_file.close() + if arg_options.stamp: + with open(arg_options.stamp, 'a') as _: + pass if __name__ == '__main__': sys.exit(main()) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/CodeGenerator.py b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/CodeGenerator.py similarity index 78% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/CodeGenerator.py rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/CodeGenerator.py index 985236821316c6..e57e3a23898f88 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/CodeGenerator.py +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/CodeGenerator.py @@ -21,34 +21,6 @@ # 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__)) -templates_dir = module_path - -# In Blink, jinja2 is in chromium's third_party directory. -# Insert at 1 so at front to override system libraries, and -# after path[0] == invoking script dir -blink_third_party_dir = os.path.normpath(os.path.join( - module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, - "third_party")) -if os.path.isdir(blink_third_party_dir): - sys.path.insert(1, blink_third_party_dir) - -# In V8, it is in third_party folder -v8_third_party_dir = os.path.normpath(os.path.join( - module_path, os.pardir, os.pardir, "third_party")) - -if os.path.isdir(v8_third_party_dir): - sys.path.insert(1, v8_third_party_dir) - -# In Node, it is in deps folder -deps_dir = os.path.normpath(os.path.join( - module_path, os.pardir, os.pardir, os.pardir, os.pardir, "third_party")) - -if os.path.isdir(deps_dir): - sys.path.insert(1, os.path.join(deps_dir, "jinja2")) - sys.path.insert(1, os.path.join(deps_dir, "markupsafe")) - -import jinja2 - def read_config(): # pylint: disable=W0703 @@ -60,11 +32,30 @@ def json_object_hook(object_dict): return collections.namedtuple('X', keys)(*values) return json.loads(data, object_hook=json_object_hook) + def init_defaults(config_tuple, path, defaults): + keys = list(config_tuple._fields) # pylint: disable=E1101 + values = [getattr(config_tuple, k) for k in keys] + for i in xrange(len(keys)): + if hasattr(values[i], "_fields"): + values[i] = init_defaults(values[i], path + "." + keys[i], defaults) + for optional in defaults: + if optional.find(path + ".") != 0: + continue + optional_key = optional[len(path) + 1:] + if optional_key.find(".") == -1 and optional_key not in keys: + keys.append(optional_key) + values.append(defaults[optional]) + return collections.namedtuple('X', keys)(*values) + try: cmdline_parser = optparse.OptionParser() cmdline_parser.add_option("--output_base") + cmdline_parser.add_option("--jinja_dir") cmdline_parser.add_option("--config") arg_options, _ = cmdline_parser.parse_args() + jinja_dir = arg_options.jinja_dir + if not jinja_dir: + raise Exception("jinja directory must be specified") output_base = arg_options.output_base if not output_base: raise Exception("Base output directory must be specified") @@ -82,14 +73,23 @@ def json_object_hook(object_dict): 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) - keys = list(config_partial._fields) # pylint: disable=E1101 - values = [getattr(config_partial, k) for k in keys] - for optional in ["imported", "exported", "lib"]: - if optional not in keys: - keys.append(optional) - values.append(False) config_json_file.close() - return (config_file, collections.namedtuple('X', keys)(*values)) + defaults = { + ".imported": False, + ".imported.export_macro": "", + ".imported.export_header": False, + ".imported.header": False, + ".imported.package": False, + ".protocol.export_macro": "", + ".protocol.export_header": False, + ".exported": False, + ".exported.export_macro": "", + ".exported.export_header": False, + ".lib": False, + ".lib.export_macro": "", + ".lib.export_header": False, + } + return (jinja_dir, config_file, init_defaults(config_partial, "", defaults)) except Exception: # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html exc = sys.exc_info()[1] @@ -109,9 +109,15 @@ def dash_to_camelcase(word): return prefix + "".join(to_title_case(x) or "-" for x in word.split("-")) -def initialize_jinja_env(cache_dir): +def initialize_jinja_env(jinja_dir, cache_dir): + dir = os.path.abspath(jinja_dir) + # pylint: disable=F0401 + sys.path.insert(1, os.path.join(dir, "jinja2")) + sys.path.insert(1, os.path.join(dir, "markupsafe")) + import jinja2 + jinja_env = jinja2.Environment( - loader=jinja2.FileSystemLoader(templates_dir), + 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), @@ -164,18 +170,18 @@ def calculate_exports_in_json(json_value): protocol.json_api["has_exports"] = True -def create_imported_type_definition(domain_name, type): +def create_imported_type_definition(domain_name, type, imported_namespace): # pylint: disable=W0622 return { - "return_type": "std::unique_ptr" % (domain_name, type["id"]), - "pass_type": "std::unique_ptr" % (domain_name, type["id"]), + "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" % (domain_name, type["id"]), - "raw_type": "protocol::%s::API::%s" % (domain_name, type["id"]), - "raw_pass_type": "protocol::%s::API::%s*" % (domain_name, type["id"]), - "raw_return_type": "protocol::%s::API::%s*" % (domain_name, type["id"]), + "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"]), } @@ -224,18 +230,18 @@ def create_any_type_definition(): } -def create_string_type_definition(string_type): +def create_string_type_definition(): # pylint: disable=W0622 return { - "return_type": string_type, - "pass_type": ("const %s&" % string_type), + "return_type": "String", + "pass_type": "const String&", "to_pass_type": "%s", "to_raw_type": "%s", "to_rvalue": "%s", - "type": string_type, - "raw_type": string_type, - "raw_pass_type": ("const %s&" % string_type), - "raw_return_type": string_type, + "type": "String", + "raw_type": "String", + "raw_pass_type": "const String&", + "raw_return_type": "String", } @@ -287,7 +293,7 @@ def wrap_array_definition(type): } -def create_type_definitions(protocol, string_type): +def create_type_definitions(protocol, imported_namespace): protocol.type_definitions = {} protocol.type_definitions["number"] = create_primitive_type_definition("number") protocol.type_definitions["integer"] = create_primitive_type_definition("integer") @@ -295,20 +301,20 @@ def create_type_definitions(protocol, string_type): protocol.type_definitions["object"] = create_object_type_definition() protocol.type_definitions["any"] = create_any_type_definition() for domain in protocol.json_api["domains"]: - protocol.type_definitions[domain["domain"] + ".string"] = create_string_type_definition(string_type) + protocol.type_definitions[domain["domain"] + ".string"] = create_string_type_definition() if not ("types" in domain): continue for type in domain["types"]: type_name = domain["domain"] + "." + type["id"] if type["type"] == "object" and domain["domain"] in protocol.imported_domains: - protocol.type_definitions[type_name] = create_imported_type_definition(domain["domain"], type) + protocol.type_definitions[type_name] = create_imported_type_definition(domain["domain"], type, imported_namespace) elif type["type"] == "object": protocol.type_definitions[type_name] = create_user_type_definition(domain["domain"], type) elif type["type"] == "array": items_type = type["items"]["type"] protocol.type_definitions[type_name] = wrap_array_definition(protocol.type_definitions[items_type]) elif type["type"] == domain["domain"] + ".string": - protocol.type_definitions[type_name] = create_string_type_definition(string_type) + protocol.type_definitions[type_name] = create_string_type_definition() else: protocol.type_definitions[type_name] = create_primitive_type_definition(type["type"]) @@ -340,6 +346,10 @@ def has_disable(commands): return False +def format_include(header): + return "\"" + header + "\"" if header[0] not in "<\"" else header + + def read_protocol_file(file_name, json_api): input_file = open(file_name, "r") json_string = input_file.read() @@ -362,7 +372,7 @@ def __init__(self): def main(): - config_file, config = read_config() + jinja_dir, config_file, config = read_config() protocol = Protocol() protocol.json_api = {"domains": []} @@ -370,7 +380,7 @@ def main(): protocol.imported_domains = read_protocol_file(config.imported.path, protocol.json_api) if config.imported else [] patch_full_qualified_refs(protocol) calculate_exports(protocol) - create_type_definitions(protocol, config.string.class_name) + create_type_definitions(protocol, "::".join(config.imported.namespace) if config.imported else "") if not config.exported: for domain_json in protocol.json_api["domains"]: @@ -382,7 +392,7 @@ def main(): os.mkdir(config.protocol.output) if protocol.json_api["has_exports"] and not os.path.exists(config.exported.output): os.mkdir(config.exported.output) - jinja_env = initialize_jinja_env(config.protocol.output) + jinja_env = initialize_jinja_env(jinja_dir, config.protocol.output) inputs = [] inputs.append(__file__) @@ -390,15 +400,16 @@ def main(): 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("TypeBuilder_h.template") - cpp_template = jinja_env.get_template("TypeBuilder_cpp.template") - exported_template = jinja_env.get_template("Exported_h.template") - imported_template = jinja_env.get_template("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() @@ -410,7 +421,8 @@ def main(): "join_arrays": join_arrays, "resolve_type": functools.partial(resolve_type, protocol), "type_definition": functools.partial(type_definition, protocol), - "has_disable": has_disable + "has_disable": has_disable, + "format_include": format_include, } if domain["domain"] in protocol.generate_domains: @@ -423,31 +435,28 @@ def main(): if config.lib: template_context = { - "config": config + "config": config, + "format_include": format_include, } + lib_templates_dir = os.path.join(module_path, "lib") # Note these should be sorted in the right order. # TODO(dgozman): sort them programmatically based on commented includes. lib_h_templates = [ - "Allocator_h.template", - "Platform_h.template", "Collections_h.template", - "String16_h.template", "ErrorSupport_h.template", "Values_h.template", "Object_h.template", "ValueConversions_h.template", "Maybe_h.template", "Array_h.template", - "FrontendChannel_h.template", "BackendCallback_h.template", "DispatcherBase_h.template", "Parser_h.template", ] lib_cpp_templates = [ - "InspectorProtocol_cpp.template", - "String16_cpp.template", + "Protocol_cpp.template", "ErrorSupport_cpp.template", "Values_cpp.template", "Object_cpp.template", @@ -455,16 +464,23 @@ def main(): "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(templates_dir, template_file)) - template = jinja_env.get_template(template_file) + 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, "InspectorProtocol.h"), lib_h_templates) - generate_lib_file(os.path.join(config.lib.output, "InspectorProtocol.cpp"), lib_cpp_templates) + generate_lib_file(os.path.join(config.lib.output, "Forward.h"), forward_h_templates) + generate_lib_file(os.path.join(config.lib.output, "Protocol.h"), lib_h_templates) + generate_lib_file(os.path.join(config.lib.output, "Protocol.cpp"), lib_cpp_templates) # Make gyp / make generatos happy, otherwise make rebuilds world. inputs_ts = max(map(os.path.getmtime, inputs)) diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/ConcatenateProtocols.py b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/ConcatenateProtocols.py new file mode 100755 index 00000000000000..a7cbc992c76e40 --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/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 [ [, ...]] \n" % sys.argv[0]) + return 1 + + domains = [] + version = None + for protocol in argv[:-1]: + file_name = os.path.normpath(protocol) + if not os.path.isfile(file_name): + sys.stderr.write("Cannot find %s\n" % file_name) + return 1 + input_file = open(file_name, "r") + json_string = input_file.read() + parsed_json = json.loads(json_string) + domains += parsed_json["domains"] + version = parsed_json["version"] + + output_file = open(argv[-1], "w") + json.dump({"version": version, "domains": domains}, output_file, indent=4, sort_keys=False, separators=(',', ': ')) + output_file.close() + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/OWNERS b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/OWNERS similarity index 100% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/OWNERS rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/OWNERS diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gni b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gni new file mode 100644 index 00000000000000..4b161a0981529b --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gni @@ -0,0 +1,82 @@ +# 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() 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)) + + inspector_protocol_dir = + "//third_party/WebKit/Source/platform/inspector_protocol" + + 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/BackendCallback_h.template", + "$inspector_protocol_dir/lib/Collections_h.template", + "$inspector_protocol_dir/lib/DispatcherBase_cpp.template", + "$inspector_protocol_dir/lib/DispatcherBase_h.template", + "$inspector_protocol_dir/lib/ErrorSupport_cpp.template", + "$inspector_protocol_dir/lib/ErrorSupport_h.template", + "$inspector_protocol_dir/lib/Forward_h.template", + "$inspector_protocol_dir/lib/FrontendChannel_h.template", + "$inspector_protocol_dir/lib/Maybe_h.template", + "$inspector_protocol_dir/lib/Object_cpp.template", + "$inspector_protocol_dir/lib/Object_h.template", + "$inspector_protocol_dir/lib/Parser_cpp.template", + "$inspector_protocol_dir/lib/Parser_h.template", + "$inspector_protocol_dir/lib/Protocol_cpp.template", + "$inspector_protocol_dir/lib/ValueConversions_h.template", + "$inspector_protocol_dir/lib/Values_cpp.template", + "$inspector_protocol_dir/lib/Values_h.template", + "$inspector_protocol_dir/templates/Exported_h.template", + "$inspector_protocol_dir/templates/Imported_h.template", + "$inspector_protocol_dir/templates/TypeBuilder_cpp.template", + "$inspector_protocol_dir/templates/TypeBuilder_h.template", + ] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + + args = [ + "--jinja_dir", + rebase_path("//third_party/", root_build_dir), # jinja is in chromium's third_party + "--output_base", + rebase_path(invoker.out_dir, root_build_dir), + "--config", + rebase_path(invoker.config_file, root_build_dir), + ] + + outputs = get_path_info(rebase_path(invoker.outputs, ".", invoker.out_dir), + "abspath") + + forward_variables_from(invoker, + [ + "visibility", + "deps", + "public_deps", + ]) + } +} diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gypi b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gypi new file mode 100644 index 00000000000000..aa43821b9aecca --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gypi @@ -0,0 +1,36 @@ +# 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. + +# Note: do not remove this file, it's used by v8's gyp. +# It will be moved out from platform/ soon. +{ + 'variables': { + 'inspector_protocol_files': [ + 'lib/Allocator_h.template', + 'lib/Array_h.template', + 'lib/BackendCallback_h.template', + 'lib/Collections_h.template', + 'lib/DispatcherBase_cpp.template', + 'lib/DispatcherBase_h.template', + 'lib/ErrorSupport_cpp.template', + 'lib/ErrorSupport_h.template', + 'lib/Forward_h.template', + 'lib/FrontendChannel_h.template', + 'lib/Maybe_h.template', + 'lib/Object_cpp.template', + 'lib/Object_h.template', + 'lib/Parser_cpp.template', + 'lib/Parser_h.template', + 'lib/Protocol_cpp.template', + 'lib/ValueConversions_h.template', + 'lib/Values_cpp.template', + 'lib/Values_h.template', + 'templates/Exported_h.template', + 'templates/Imported_h.template', + 'templates/TypeBuilder_cpp.template', + 'templates/TypeBuilder_h.template', + 'CodeGenerator.py', + ] + } +} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Allocator_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Allocator_h.template similarity index 65% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Allocator_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Allocator_h.template index e38b76cd62b7d3..8f8109d695c597 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Allocator_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Allocator_h.template @@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef Allocator_h -#define Allocator_h +#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 }; @@ -19,4 +23,8 @@ enum NotNullTagEnum { NotNullLiteral }; ClassName(const ClassName&) = delete; \ ClassName& operator=(const ClassName&) = delete -#endif /* Allocator_h */ +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Allocator_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Array_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Array_h.template similarity index 84% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Array_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Array_h.template index 40abb2d467c161..9555e302a933d0 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Array_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Array_h.template @@ -2,19 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef Array_h -#define Array_h +#ifndef {{"_".join(config.protocol.namespace)}}_Array_h +#define {{"_".join(config.protocol.namespace)}}_Array_h //#include "ErrorSupport.h" -//#include "Platform.h" -//#include "String16.h" +//#include "Forward.h" //#include "ValueConversions.h" //#include "Values.h" -#include - -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} template class Array { @@ -34,7 +32,7 @@ public: std::unique_ptr> result(new Array()); errors->push(); for (size_t i = 0; i < array->size(); ++i) { - errors->setName(String16::fromInteger(i)); + errors->setName(StringUtil::fromInteger(i)); std::unique_ptr item = ValueConversions::parse(array->at(i), errors); result->m_vector.push_back(std::move(item)); } @@ -89,7 +87,7 @@ public: errors->push(); std::unique_ptr> result(new Array()); for (size_t i = 0; i < array->size(); ++i) { - errors->setName(String16::fromInteger(i)); + errors->setName(StringUtil::fromInteger(i)); T item = ValueConversions::parse(array->at(i), errors); result->m_vector.push_back(item); } @@ -126,13 +124,13 @@ private: std::vector m_vector; }; -template<> class Array : public ArrayBase {}; -template<> class Array : public ArrayBase {}; +template<> class Array : public ArrayBase {}; template<> class Array : public ArrayBase {}; template<> class Array : public ArrayBase {}; template<> class Array : public ArrayBase {}; -} // namespace platform -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} -#endif // !defined(Array_h) +#endif // !defined({{"_".join(config.protocol.namespace)}}_Array_h) diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/BackendCallback_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/BackendCallback_h.template new file mode 100644 index 00000000000000..3c8fc15b3216e5 --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/BackendCallback_h.template @@ -0,0 +1,24 @@ +// 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)}}_BackendCallback_h +#define {{"_".join(config.protocol.namespace)}}_BackendCallback_h + +//#include "Forward.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +class {{config.lib.export_macro}} BackendCallback { +public: + virtual ~BackendCallback() { } + virtual void sendFailure(const ErrorString&) = 0; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_BackendCallback_h) diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Collections_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Collections_h.template new file mode 100644 index 00000000000000..3f760287b58f0e --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Collections_h.template @@ -0,0 +1,43 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_Collections_h +#define {{"_".join(config.protocol.namespace)}}_Collections_h + +#include "{{config.protocol.package}}/Forward.h" +#include + +#if defined(__APPLE__) && !defined(_LIBCPP_VERSION) +#include +#include + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template using HashMap = std::map; +template using HashSet = std::set; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#else +#include +#include + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template using HashMap = std::unordered_map; +template using HashSet = std::unordered_set; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // defined(__APPLE__) && !defined(_LIBCPP_VERSION) + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Collections_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/DispatcherBase_cpp.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/DispatcherBase_cpp.template similarity index 77% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/DispatcherBase_cpp.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/DispatcherBase_cpp.template index 2f842e7fa1177c..76f77aae7ece78 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/DispatcherBase_cpp.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/DispatcherBase_cpp.template @@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -namespace blink { -namespace protocol { +//#include "DispatcherBase.h" +//#include "Parser.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} // static const char DispatcherBase::kInvalidRequest[] = "Invalid request"; @@ -44,7 +48,7 @@ DispatcherBase::~DispatcherBase() } // static -bool DispatcherBase::getCommandName(const String16& message, String16* result) +bool DispatcherBase::getCommandName(const String& message, String* result) { std::unique_ptr value = parseJSON(message); if (!value) @@ -84,8 +88,10 @@ void DispatcherBase::sendResponse(int callId, const ErrorString& invocationError sendResponse(callId, invocationError, nullptr, DictionaryValue::create()); } -static void reportProtocolError(FrontendChannel* frontendChannel, int callId, DispatcherBase::CommonErrorCode code, const String16& errorMessage, ErrorSupport* errors) +static void reportProtocolErrorTo(FrontendChannel* frontendChannel, int callId, DispatcherBase::CommonErrorCode code, const String& errorMessage, ErrorSupport* errors) { + if (!frontendChannel) + return; std::unique_ptr error = DictionaryValue::create(); error->setInteger("code", code); error->setString("message", errorMessage); @@ -98,10 +104,9 @@ static void reportProtocolError(FrontendChannel* frontendChannel, int callId, Di frontendChannel->sendProtocolResponse(callId, message->toJSONString()); } -void DispatcherBase::reportProtocolError(int callId, CommonErrorCode code, const String16& errorMessage, ErrorSupport* errors) +void DispatcherBase::reportProtocolError(int callId, CommonErrorCode code, const String& errorMessage, ErrorSupport* errors) { - if (m_frontendChannel) - ::blink::protocol::reportProtocolError(m_frontendChannel, callId, code, errorMessage, errors); + reportProtocolErrorTo(m_frontendChannel, callId, code, errorMessage, errors); } void DispatcherBase::clearFrontend() @@ -122,14 +127,13 @@ std::unique_ptr DispatcherBase::weakPtr() UberDispatcher::UberDispatcher(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { } -void UberDispatcher::registerBackend(const String16& name, std::unique_ptr dispatcher) +void UberDispatcher::registerBackend(const String& name, std::unique_ptr dispatcher) { m_dispatchers[name] = std::move(dispatcher); } -void UberDispatcher::dispatch(const String16& message) +void UberDispatcher::dispatch(std::unique_ptr parsedMessage) { - std::unique_ptr parsedMessage = parseJSON(message); if (!parsedMessage) return; std::unique_ptr messageObject = DictionaryValue::cast(std::move(parsedMessage)); @@ -138,25 +142,25 @@ void UberDispatcher::dispatch(const String16& message) int callId = 0; protocol::Value* callIdValue = messageObject->get("id"); - bool success = callIdValue->asInteger(&callId); + bool success = callIdValue && callIdValue->asInteger(&callId); if (!success) return; protocol::Value* methodValue = messageObject->get("method"); - String16 method; + String method; success = methodValue && methodValue->asString(&method); if (!success) return; size_t dotIndex = method.find("."); - if (dotIndex == String16::kNotFound) { - reportProtocolError(m_frontendChannel, callId, DispatcherBase::MethodNotFound, "'" + method + "' wasn't found", nullptr); + if (dotIndex == StringUtil::kNotFound) { + reportProtocolErrorTo(m_frontendChannel, callId, DispatcherBase::MethodNotFound, "'" + method + "' wasn't found", nullptr); return; } - String16 domain = method.substring(0, dotIndex); + String domain = StringUtil::substring(method, 0, dotIndex); auto it = m_dispatchers.find(domain); if (it == m_dispatchers.end()) { - reportProtocolError(m_frontendChannel, callId, DispatcherBase::MethodNotFound, "'" + method + "' wasn't found", nullptr); + reportProtocolErrorTo(m_frontendChannel, callId, DispatcherBase::MethodNotFound, "'" + method + "' wasn't found", nullptr); return; } it->second->dispatch(callId, method, std::move(messageObject)); @@ -164,5 +168,6 @@ void UberDispatcher::dispatch(const String16& message) UberDispatcher::~UberDispatcher() = default; -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/DispatcherBase_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/DispatcherBase_h.template similarity index 64% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/DispatcherBase_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/DispatcherBase_h.template index 4402d9674ab246..17fd8708abdb76 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/DispatcherBase_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/DispatcherBase_h.template @@ -2,28 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DispatcherBase_h -#define DispatcherBase_h +#ifndef {{"_".join(config.protocol.namespace)}}_DispatcherBase_h +#define {{"_".join(config.protocol.namespace)}}_DispatcherBase_h //#include "BackendCallback.h" //#include "Collections.h" //#include "ErrorSupport.h" -//#include "Platform.h" -//#include "String16.h" +//#include "Forward.h" //#include "Values.h" -#include "{{config.class_export.header}}" -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} -class FrontendChannel; class WeakPtr; -class {{config.class_export.macro}} DispatcherBase { +class {{config.lib.export_macro}} DispatcherBase { PROTOCOL_DISALLOW_COPY(DispatcherBase); public: static const char kInvalidRequest[]; - class {{config.class_export.macro}} WeakPtr { + class {{config.lib.export_macro}} WeakPtr { public: explicit WeakPtr(DispatcherBase*); ~WeakPtr(); @@ -34,7 +32,7 @@ public: DispatcherBase* m_dispatcher; }; - class {{config.class_export.macro}} Callback : public protocol::BackendCallback { + class {{config.lib.export_macro}} Callback : public protocol::BackendCallback { public: Callback(std::unique_ptr backendImpl, int callId); virtual ~Callback(); @@ -60,15 +58,15 @@ public: ServerError = -32000, }; - static bool getCommandName(const String16& message, String16* result); + static bool getCommandName(const String& message, String* result); - virtual void dispatch(int callId, const String16& method, std::unique_ptr messageObject) = 0; + virtual void dispatch(int callId, const String& method, std::unique_ptr messageObject) = 0; void sendResponse(int callId, const ErrorString&, ErrorSupport*, std::unique_ptr result); void sendResponse(int callId, const ErrorString&, std::unique_ptr result); void sendResponse(int callId, const ErrorString&); - void reportProtocolError(int callId, CommonErrorCode, const String16& errorMessage, ErrorSupport* errors); + void reportProtocolError(int callId, CommonErrorCode, const String& errorMessage, ErrorSupport* errors); void clearFrontend(); std::unique_ptr weakPtr(); @@ -78,21 +76,22 @@ private: protocol::HashSet m_weakPtrs; }; -class {{config.class_export.macro}} UberDispatcher { +class {{config.lib.export_macro}} UberDispatcher { PROTOCOL_DISALLOW_COPY(UberDispatcher); public: explicit UberDispatcher(FrontendChannel*); - void registerBackend(const String16& name, std::unique_ptr); - void dispatch(const String16& message); + void registerBackend(const String& name, std::unique_ptr); + void dispatch(std::unique_ptr message); FrontendChannel* channel() { return m_frontendChannel; } virtual ~UberDispatcher(); private: FrontendChannel* m_frontendChannel; - protocol::HashMap> m_dispatchers; + protocol::HashMap> m_dispatchers; }; -} // namespace platform -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} -#endif // !defined(DispatcherBase_h) +#endif // !defined({{"_".join(config.protocol.namespace)}}_DispatcherBase_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ErrorSupport_cpp.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ErrorSupport_cpp.template similarity index 66% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ErrorSupport_cpp.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ErrorSupport_cpp.template index 695cb58dc3867f..34593ec13de84d 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ErrorSupport_cpp.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ErrorSupport_cpp.template @@ -2,22 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -namespace blink { -namespace protocol { +//#include "ErrorSupport.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} ErrorSupport::ErrorSupport() : m_errorString(nullptr) { } -ErrorSupport::ErrorSupport(String16* errorString) : m_errorString(errorString) { } +ErrorSupport::ErrorSupport(String* errorString) : m_errorString(errorString) { } ErrorSupport::~ErrorSupport() { if (m_errorString && hasErrors()) { - String16Builder builder; + StringBuilder builder; builder.append("Internal error(s): "); builder.append(errors()); *m_errorString = builder.toString(); } } -void ErrorSupport::setName(const String16& name) +void ErrorSupport::setName(const String& name) { DCHECK(m_path.size()); m_path[m_path.size() - 1] = name; @@ -25,7 +28,7 @@ void ErrorSupport::setName(const String16& name) void ErrorSupport::push() { - m_path.push_back(String16()); + m_path.push_back(String()); } void ErrorSupport::pop() @@ -33,9 +36,9 @@ void ErrorSupport::pop() m_path.pop_back(); } -void ErrorSupport::addError(const String16& error) +void ErrorSupport::addError(const String& error) { - String16Builder builder; + StringBuilder builder; for (size_t i = 0; i < m_path.size(); ++i) { if (i) builder.append('.'); @@ -51,9 +54,9 @@ bool ErrorSupport::hasErrors() return m_errors.size(); } -String16 ErrorSupport::errors() +String ErrorSupport::errors() { - String16Builder builder; + StringBuilder builder; for (size_t i = 0; i < m_errors.size(); ++i) { if (i) builder.append("; "); @@ -62,5 +65,6 @@ String16 ErrorSupport::errors() return builder.toString(); } -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ErrorSupport_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ErrorSupport_h.template new file mode 100644 index 00000000000000..9d2a19260305e6 --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ErrorSupport_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)}}_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(String* errorString); + ~ErrorSupport(); + + void push(); + void setName(const String&); + void pop(); + void addError(const String&); + bool hasErrors(); + String errors(); + +private: + std::vector m_path; + std::vector m_errors; + String* m_errorString; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_ErrorSupport_h) diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Forward_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Forward_h.template new file mode 100644 index 00000000000000..2ad3897ba9d3e4 --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/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.platform_header)}} +#include {{format_include(config.lib.string_header)}} + +#include + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +template class Array; +class DictionaryValue; +using ErrorString = String; +class ErrorSupport; +class FundamentalValue; +class ListValue; +template class Maybe; +class Object; +class SerializedValue; +class StringValue; +class UberDispatcher; +class Value; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Forward_h) diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/FrontendChannel_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/FrontendChannel_h.template new file mode 100644 index 00000000000000..8b653b58214b80 --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/FrontendChannel_h.template @@ -0,0 +1,24 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_FrontendChannel_h +#define {{"_".join(config.protocol.namespace)}}_FrontendChannel_h + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + +class {{config.lib.export_macro}} FrontendChannel { +public: + virtual ~FrontendChannel() { } + virtual void sendProtocolResponse(int callId, const String& message) = 0; + virtual void sendProtocolNotification(const String& message) = 0; + virtual void flushProtocolNotifications() = 0; +}; + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_FrontendChannel_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Maybe_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Maybe_h.template similarity index 75% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Maybe_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Maybe_h.template index e15ac070da1287..2096572ba7ba60 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Maybe_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Maybe_h.template @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef Maybe_h -#define Maybe_h +#ifndef {{"_".join(config.protocol.namespace)}}_Maybe_h +#define {{"_".join(config.protocol.namespace)}}_Maybe_h -//#include "Platform.h" -//#include "String16.h" +//#include "Forward.h" -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} template class Maybe { @@ -66,22 +66,15 @@ public: }; template<> -class Maybe : public MaybeBase { +class Maybe : public MaybeBase { public: Maybe() { } - Maybe(const InspectorProtocolConvenienceStringType& value) : MaybeBase(value) { } + Maybe(const String& value) : MaybeBase(value) { } using MaybeBase::operator=; }; -template<> -class Maybe : public MaybeBase { -public: - Maybe() { } - Maybe(const String16& value) : MaybeBase(value) { } - using MaybeBase::operator=; -}; - -} // namespace platform -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} -#endif // !defined(Maybe_h) +#endif // !defined({{"_".join(config.protocol.namespace)}}_Maybe_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Object_cpp.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Object_cpp.template similarity index 81% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Object_cpp.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Object_cpp.template index 4480d853ef0184..e3f18c3500e2b2 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Object_cpp.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Object_cpp.template @@ -2,8 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -namespace blink { -namespace protocol { +//#include "Object.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} std::unique_ptr Object::parse(protocol::Value* value, ErrorSupport* errors) { @@ -29,5 +32,6 @@ Object::Object(std::unique_ptr object) : m_object(std Object::~Object() { } -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Object_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Object_h.template similarity index 56% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Object_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Object_h.template index dc7f44b6b335d6..4ccd88bdab0a73 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Object_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Object_h.template @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef Object_h -#define Object_h +#ifndef {{"_".join(config.protocol.namespace)}}_Object_h +#define {{"_".join(config.protocol.namespace)}}_Object_h //#include "ErrorSupport.h" -//#include "Platform.h" +//#include "Forward.h" //#include "Values.h" -#include "{{config.class_export.header}}" -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} -class {{config.class_export.macro}} Object { +class {{config.lib.export_macro}} Object { public: static std::unique_ptr parse(protocol::Value*, ErrorSupport*); ~Object(); @@ -25,7 +25,8 @@ private: std::unique_ptr m_object; }; -} // namespace platform -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} -#endif // !defined(Object_h) +#endif // !defined({{"_".join(config.protocol.namespace)}}_Object_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Parser_cpp.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Parser_cpp.template similarity index 76% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Parser_cpp.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Parser_cpp.template index 34d8ff0720d046..a103b8228e066e 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Parser_cpp.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Parser_cpp.template @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} namespace { @@ -28,7 +29,45 @@ const char* const nullString = "null"; const char* const trueString = "true"; const char* const falseString = "false"; -bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token) +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 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(characters[i])); + } + buffer.push_back('\0'); + char* endptr; + double result = std::strtod(buffer.data(), &endptr); + *ok = !(*endptr); + return result; +} + +double charactersToDouble(const uint8_t* characters, size_t length, bool* ok) +{ + std::string buffer(reinterpret_cast(characters), length); + char* endptr; + double result = std::strtod(buffer.data(), &endptr); + *ok = !(*endptr); + return result; +} + +template +bool parseConstToken(const Char* start, const Char* end, const Char** tokenEnd, const char* token) { while (start < end && *token != '\0' && *start++ == *token++) { } if (*token != '\0') @@ -37,7 +76,8 @@ bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEn return true; } -bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros) +template +bool readInt(const Char* start, const Char* end, const Char** tokenEnd, bool canHaveLeadingZeros) { if (start == end) return false; @@ -55,13 +95,14 @@ bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool return true; } -bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd) +template +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; - UChar c = *start; + Char c = *start; if ('-' == c) ++start; @@ -104,12 +145,13 @@ bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenE return true; } -bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits) +template +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) { - UChar c = *start++; + Char c = *start++; if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))) return false; } @@ -117,11 +159,14 @@ bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, return true; } -bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd) +template +bool parseStringToken(const Char* start, const Char* end, const Char** tokenEnd) { while (start < end) { - UChar c = *start++; + Char c = *start++; if ('\\' == c) { + if (start == end) + return false; c = *start++; // Make sure the escaped char is valid. switch (c) { @@ -154,7 +199,8 @@ bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenE return false; } -bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd) +template +bool skipComment(const Char* start, const Char* end, const Char** commentEnd) { if (start == end) return false; @@ -177,7 +223,7 @@ bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd) } if (*start == '*') { - UChar previous = '\0'; + Char previous = '\0'; // Block comment, read until end marker. for (++start; start < end; previous = *start++) { if (previous == '*' && *start == '/') { @@ -192,13 +238,14 @@ bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd) return false; } -void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar** whitespaceEnd) +template +void skipWhitespaceAndComments(const Char* start, const Char* end, const Char** whitespaceEnd) { while (start < end) { - if (String16::isSpaceOrNewLine(*start)) { + if (isSpaceOrNewLine(*start)) { ++start; } else if (*start == '/') { - const UChar* commentEnd; + const Char* commentEnd; if (!skipComment(start, end, &commentEnd)) break; start = commentEnd; @@ -209,7 +256,8 @@ void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar *whitespaceEnd = start; } -Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd) +template +Token parseToken(const Char* start, const Char* end, const Char** tokenStart, const Char** tokenEnd) { skipWhitespaceAndComments(start, end, tokenStart); start = *tokenStart; @@ -270,7 +318,8 @@ Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, return InvalidToken; } -inline int hexToInt(UChar c) +template +int hexToInt(Char c) { if ('0' <= c && c <= '9') return c - '0'; @@ -278,18 +327,21 @@ inline int hexToInt(UChar c) return c - 'A' + 10; if ('a' <= c && c <= 'f') return c - 'a' + 10; - NOTREACHED(); + DCHECK(false); return 0; } -bool decodeString(const UChar* start, const UChar* end, String16Builder* output) +template +bool decodeString(const Char* start, const Char* end, StringBuilder* output) { while (start < end) { - UChar c = *start++; + uint16_t c = *start++; if ('\\' != c) { output->append(c); continue; } + if (start == end) + return false; c = *start++; if (c == 'x') { @@ -335,7 +387,8 @@ bool decodeString(const UChar* start, const UChar* end, String16Builder* output) return true; } -bool decodeString(const UChar* start, const UChar* end, String16* output) +template +bool decodeString(const Char* start, const Char* end, String* output) { if (start == end) { *output = ""; @@ -343,22 +396,23 @@ bool decodeString(const UChar* start, const UChar* end, String16* output) } if (start > end) return false; - String16Builder buffer; - buffer.reserveCapacity(end - start); + StringBuilder buffer; + StringUtil::builderReserve(buffer, end - start); if (!decodeString(start, end, &buffer)) return false; *output = buffer.toString(); return true; } -std::unique_ptr buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth) +template +std::unique_ptr buildValue(const Char* start, const Char* end, const Char** valueTokenEnd, int depth) { if (depth > stackLimit) return nullptr; std::unique_ptr result; - const UChar* tokenStart; - const UChar* tokenEnd; + const Char* tokenStart; + const Char* tokenEnd; Token token = parseToken(start, end, &tokenStart, &tokenEnd); switch (token) { case InvalidToken: @@ -374,7 +428,7 @@ std::unique_ptr buildValue(const UChar* start, const UChar* end, const UC break; case Number: { bool ok; - double value = String16::charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok); + double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok); if (!ok) return nullptr; int number = static_cast(value); @@ -385,7 +439,7 @@ std::unique_ptr buildValue(const UChar* start, const UChar* end, const UC break; } case StringLiteral: { - String16 value; + String value; bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); if (!ok) return nullptr; @@ -427,7 +481,7 @@ std::unique_ptr buildValue(const UChar* start, const UChar* end, const UC while (token != ObjectEnd) { if (token != StringLiteral) return nullptr; - String16 key; + String key; if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) return nullptr; start = tokenEnd; @@ -471,10 +525,11 @@ std::unique_ptr buildValue(const UChar* start, const UChar* end, const UC return result; } -std::unique_ptr parseJSONInternal(const UChar* start, unsigned length) +template +std::unique_ptr parseJSONInternal(const Char* start, unsigned length) { - const UChar* end = start + length; - const UChar *tokenEnd; + const Char* end = start + length; + const Char *tokenEnd; std::unique_ptr value = buildValue(start, end, &tokenEnd, 0); if (!value || tokenEnd != end) return nullptr; @@ -483,12 +538,16 @@ std::unique_ptr parseJSONInternal(const UChar* start, unsigned length) } // anonymous namespace -std::unique_ptr parseJSON(const String16& json) +std::unique_ptr parseJSON(const uint16_t* characters, unsigned length) { - if (json.isEmpty()) - return nullptr; - return parseJSONInternal(json.characters16(), json.length()); + return parseJSONInternal(characters, length); +} + +std::unique_ptr parseJSON(const uint8_t* characters, unsigned length) +{ + return parseJSONInternal(characters, length); } -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Parser_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Parser_h.template new file mode 100644 index 00000000000000..7b2a29b6c9bef3 --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/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 parseJSON(const uint8_t*, unsigned); +{{config.lib.export_macro}} std::unique_ptr parseJSON(const uint16_t*, unsigned); + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_Parser_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Platform_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Protocol_cpp.template similarity index 54% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Platform_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Protocol_cpp.template index 41b8ef2140cc14..8e35fa74fc34db 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Platform_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Protocol_cpp.template @@ -1,10 +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. -#ifndef protocol_Platform_h -#define protocol_Platform_h +#include "{{config.protocol.package}}/Protocol.h" -#include "{{config.lib.platform_header}}" +#include +#include -#endif // !defined(protocol_Platform_h) +#include diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ValueConversions_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ValueConversions_h.template similarity index 81% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ValueConversions_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ValueConversions_h.template index 3b7eaa4f79d58f..5384c7bb1e29f8 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ValueConversions_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/ValueConversions_h.template @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ValueConversions_h -#define ValueConversions_h +#ifndef {{"_".join(config.protocol.namespace)}}_ValueConversions_h +#define {{"_".join(config.protocol.namespace)}}_ValueConversions_h //#include "ErrorSupport.h" -//#include "Platform.h" -//#include "String16.h" +//#include "Forward.h" //#include "Values.h" -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} template struct ValueConversions { @@ -83,34 +83,17 @@ struct ValueConversions { }; template<> -struct ValueConversions { - static InspectorProtocolConvenienceStringType parse(protocol::Value* value, ErrorSupport* errors) +struct ValueConversions { + static String parse(protocol::Value* value, ErrorSupport* errors) { - String16 result; + String result; bool success = value ? value->asString(&result) : false; if (!success) errors->addError("string value expected"); return result; } - static std::unique_ptr serialize(const InspectorProtocolConvenienceStringType& value) - { - return StringValue::create(value); - } -}; - -template<> -struct ValueConversions { - static String16 parse(protocol::Value* value, ErrorSupport* errors) - { - String16 result; - bool success = value ? value->asString(&result) : false; - if (!success) - errors->addError("string value expected"); - return result; - } - - static std::unique_ptr serialize(const String16& value) + static std::unique_ptr serialize(const String& value) { return StringValue::create(value); } @@ -181,7 +164,8 @@ struct ValueConversions { } }; -} // namespace platform -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} -#endif // !defined(ValueConversions_h) +#endif // !defined({{"_".join(config.protocol.namespace)}}_ValueConversions_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Values_cpp.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Values_cpp.template similarity index 72% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Values_cpp.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Values_cpp.template index 482ec46ab44af7..1b5cdfee227b08 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Values_cpp.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Values_cpp.template @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include -#include +//#include "Values.h" -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} namespace { @@ -14,7 +14,7 @@ const char* const nullValueString = "null"; const char* const trueValueString = "true"; const char* const falseValueString = "false"; -inline bool escapeChar(UChar c, String16Builder* dst) +inline bool escapeChar(uint16_t c, StringBuilder* dst) { switch (c) { case '\b': dst->append("\\b"); break; @@ -32,20 +32,20 @@ inline bool escapeChar(UChar c, String16Builder* dst) const char hexDigits[17] = "0123456789ABCDEF"; -void appendUnsignedAsHex(UChar number, String16Builder* dst) +void appendUnsignedAsHex(uint16_t number, StringBuilder* dst) { dst->append("\\u"); for (size_t i = 0; i < 4; ++i) { - UChar c = hexDigits[(number & 0xF000) >> 12]; + uint16_t c = hexDigits[(number & 0xF000) >> 12]; dst->append(c); number <<= 4; } } -void escapeStringForJSON(const String16& str, String16Builder* dst) +void escapeStringForJSON(const String& str, StringBuilder* dst) { for (unsigned i = 0; i < str.length(); ++i) { - UChar c = str[i]; + uint16_t c = str[i]; if (!escapeChar(c, dst)) { if (c < 32 || c > 126 || c == '<' || c == '>') { // 1. Escaping <, > to prevent script execution. @@ -59,7 +59,7 @@ void escapeStringForJSON(const String16& str, String16Builder* dst) } } -void doubleQuoteStringForJSON(const String16& str, String16Builder* dst) +void doubleQuoteStringForJSON(const String& str, StringBuilder* dst) { dst->append('"'); escapeStringForJSON(str, dst); @@ -83,25 +83,25 @@ bool Value::asInteger(int*) const return false; } -bool Value::asString(String16*) const +bool Value::asString(String*) const { return false; } -bool Value::asSerialized(String16*) const +bool Value::asSerialized(String*) const { return false; } -String16 Value::toJSONString() const +String Value::toJSONString() const { - String16Builder result; - result.reserveCapacity(512); + StringBuilder result; + StringUtil::builderReserve(result, 512); writeJSON(&result); return result.toString(); } -void Value::writeJSON(String16Builder* output) const +void Value::writeJSON(StringBuilder* output) const { DCHECK(m_type == TypeNull); output->append(nullValueString, 4); @@ -141,7 +141,7 @@ bool FundamentalValue::asInteger(int* output) const return true; } -void FundamentalValue::writeJSON(String16Builder* output) const +void FundamentalValue::writeJSON(StringBuilder* output) const { DCHECK(type() == TypeBoolean || type() == TypeInteger || type() == TypeDouble); if (type() == TypeBoolean) { @@ -154,9 +154,9 @@ void FundamentalValue::writeJSON(String16Builder* output) const output->append(nullValueString, 4); return; } - output->append(String16::fromDouble(m_doubleValue)); + output->append(StringUtil::fromDouble(m_doubleValue)); } else if (type() == TypeInteger) { - output->append(String16::fromInteger(m_integerValue)); + output->append(StringUtil::fromInteger(m_integerValue)); } } @@ -167,18 +167,18 @@ std::unique_ptr FundamentalValue::clone() const case TypeInteger: return FundamentalValue::create(m_integerValue); case TypeBoolean: return FundamentalValue::create(m_boolValue); default: - NOTREACHED(); + DCHECK(false); } return nullptr; } -bool StringValue::asString(String16* output) const +bool StringValue::asString(String* output) const { *output = m_stringValue; return true; } -void StringValue::writeJSON(String16Builder* output) const +void StringValue::writeJSON(StringBuilder* output) const { DCHECK(type() == TypeString); doubleQuoteStringForJSON(m_stringValue, output); @@ -189,13 +189,13 @@ std::unique_ptr StringValue::clone() const return StringValue::create(m_stringValue); } -bool SerializedValue::asSerialized(String16* output) const +bool SerializedValue::asSerialized(String* output) const { *output = m_serializedValue; return true; } -void SerializedValue::writeJSON(String16Builder* output) const +void SerializedValue::writeJSON(StringBuilder* output) const { DCHECK(type() == TypeSerialized); output->append(m_serializedValue); @@ -210,42 +210,42 @@ DictionaryValue::~DictionaryValue() { } -void DictionaryValue::setBoolean(const String16& name, bool value) +void DictionaryValue::setBoolean(const String& name, bool value) { setValue(name, FundamentalValue::create(value)); } -void DictionaryValue::setInteger(const String16& name, int value) +void DictionaryValue::setInteger(const String& name, int value) { setValue(name, FundamentalValue::create(value)); } -void DictionaryValue::setDouble(const String16& name, double value) +void DictionaryValue::setDouble(const String& name, double value) { setValue(name, FundamentalValue::create(value)); } -void DictionaryValue::setString(const String16& name, const String16& value) +void DictionaryValue::setString(const String& name, const String& value) { setValue(name, StringValue::create(value)); } -void DictionaryValue::setValue(const String16& name, std::unique_ptr value) +void DictionaryValue::setValue(const String& name, std::unique_ptr value) { set(name, value); } -void DictionaryValue::setObject(const String16& name, std::unique_ptr value) +void DictionaryValue::setObject(const String& name, std::unique_ptr value) { set(name, value); } -void DictionaryValue::setArray(const String16& name, std::unique_ptr value) +void DictionaryValue::setArray(const String& name, std::unique_ptr value) { set(name, value); } -bool DictionaryValue::getBoolean(const String16& name, bool* output) const +bool DictionaryValue::getBoolean(const String& name, bool* output) const { protocol::Value* value = get(name); if (!value) @@ -253,7 +253,7 @@ bool DictionaryValue::getBoolean(const String16& name, bool* output) const return value->asBoolean(output); } -bool DictionaryValue::getInteger(const String16& name, int* output) const +bool DictionaryValue::getInteger(const String& name, int* output) const { Value* value = get(name); if (!value) @@ -261,7 +261,7 @@ bool DictionaryValue::getInteger(const String16& name, int* output) const return value->asInteger(output); } -bool DictionaryValue::getDouble(const String16& name, double* output) const +bool DictionaryValue::getDouble(const String& name, double* output) const { Value* value = get(name); if (!value) @@ -269,7 +269,7 @@ bool DictionaryValue::getDouble(const String16& name, double* output) const return value->asDouble(output); } -bool DictionaryValue::getString(const String16& name, String16* output) const +bool DictionaryValue::getString(const String& name, String* output) const { protocol::Value* value = get(name); if (!value) @@ -277,17 +277,17 @@ bool DictionaryValue::getString(const String16& name, String16* output) const return value->asString(output); } -DictionaryValue* DictionaryValue::getObject(const String16& name) const +DictionaryValue* DictionaryValue::getObject(const String& name) const { return DictionaryValue::cast(get(name)); } -protocol::ListValue* DictionaryValue::getArray(const String16& name) const +protocol::ListValue* DictionaryValue::getArray(const String& name) const { return ListValue::cast(get(name)); } -protocol::Value* DictionaryValue::get(const String16& name) const +protocol::Value* DictionaryValue::get(const String& name) const { Dictionary::const_iterator it = m_data.find(name); if (it == m_data.end()) @@ -297,38 +297,38 @@ protocol::Value* DictionaryValue::get(const String16& name) const DictionaryValue::Entry DictionaryValue::at(size_t index) const { - const String16 key = m_order[index]; + const String key = m_order[index]; return std::make_pair(key, m_data.find(key)->second.get()); } -bool DictionaryValue::booleanProperty(const String16& name, bool defaultValue) const +bool DictionaryValue::booleanProperty(const String& name, bool defaultValue) const { bool result = defaultValue; getBoolean(name, &result); return result; } -int DictionaryValue::integerProperty(const String16& name, int defaultValue) const +int DictionaryValue::integerProperty(const String& name, int defaultValue) const { int result = defaultValue; getInteger(name, &result); return result; } -double DictionaryValue::doubleProperty(const String16& name, double defaultValue) const +double DictionaryValue::doubleProperty(const String& name, double defaultValue) const { double result = defaultValue; getDouble(name, &result); return result; } -void DictionaryValue::remove(const String16& name) +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(String16Builder* output) const +void DictionaryValue::writeJSON(StringBuilder* output) const { output->append('{'); for (size_t i = 0; i < m_order.size(); ++i) { @@ -347,7 +347,7 @@ std::unique_ptr DictionaryValue::clone() const { std::unique_ptr result = DictionaryValue::create(); for (size_t i = 0; i < m_order.size(); ++i) { - String16 key = m_order[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()); @@ -364,7 +364,7 @@ ListValue::~ListValue() { } -void ListValue::writeJSON(String16Builder* output) const +void ListValue::writeJSON(StringBuilder* output) const { output->append('['); bool first = true; @@ -402,5 +402,6 @@ protocol::Value* ListValue::at(size_t index) return m_data[index].get(); } -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Values_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Values_h.template similarity index 58% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Values_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Values_h.template index 9874183a773628..8f75ef2220e26e 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Values_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/lib/Values_h.template @@ -2,29 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef Values_h -#define Values_h +#ifndef {{"_".join(config.protocol.namespace)}}_Values_h +#define {{"_".join(config.protocol.namespace)}}_Values_h //#include "Allocator.h" //#include "Collections.h" -//#include "Platform.h" -//#include "String16.h" -#include "{{config.class_export.header}}" +//#include "Forward.h" -#include - -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} class ListValue; class DictionaryValue; class Value; -class {{config.class_export.macro}} Value { +class {{config.lib.export_macro}} Value { PROTOCOL_DISALLOW_COPY(Value); public: - static const int maxDepth = 1000; - virtual ~Value() { } static std::unique_ptr null() @@ -50,11 +45,11 @@ public: virtual bool asBoolean(bool* output) const; virtual bool asDouble(double* output) const; virtual bool asInteger(int* output) const; - virtual bool asString(String16* output) const; - virtual bool asSerialized(String16* output) const; + virtual bool asString(String* output) const; + virtual bool asSerialized(String* output) const; - String16 toJSONString() const; - virtual void writeJSON(String16Builder* output) const; + String toJSONString() const; + virtual void writeJSON(StringBuilder* output) const; virtual std::unique_ptr clone() const; protected: @@ -68,7 +63,7 @@ private: ValueType m_type; }; -class {{config.class_export.macro}} FundamentalValue : public Value { +class {{config.lib.export_macro}} FundamentalValue : public Value { public: static std::unique_ptr create(bool value) { @@ -88,7 +83,7 @@ public: bool asBoolean(bool* output) const override; bool asDouble(double* output) const override; bool asInteger(int* output) const override; - void writeJSON(String16Builder* output) const override; + void writeJSON(StringBuilder* output) const override; std::unique_ptr clone() const override; private: @@ -103,9 +98,9 @@ private: }; }; -class {{config.class_export.macro}} StringValue : public Value { +class {{config.lib.export_macro}} StringValue : public Value { public: - static std::unique_ptr create(const String16& value) + static std::unique_ptr create(const String& value) { return wrapUnique(new StringValue(value)); } @@ -115,38 +110,37 @@ public: return wrapUnique(new StringValue(value)); } - bool asString(String16* output) const override; - void writeJSON(String16Builder* output) const override; + bool asString(String* output) const override; + void writeJSON(StringBuilder* output) const override; std::unique_ptr clone() const override; private: - explicit StringValue(const String16& value) : Value(TypeString), m_stringValue(value) { } + explicit StringValue(const String& value) : Value(TypeString), m_stringValue(value) { } explicit StringValue(const char* value) : Value(TypeString), m_stringValue(value) { } - String16 m_stringValue; + String m_stringValue; }; -class {{config.class_export.macro}} SerializedValue : public Value { +class {{config.lib.export_macro}} SerializedValue : public Value { public: - static std::unique_ptr create(const String16& value) + static std::unique_ptr create(const String& value) { return wrapUnique(new SerializedValue(value)); } - bool asSerialized(String16* output) const override; - void writeJSON(String16Builder* output) const override; + bool asSerialized(String* output) const override; + void writeJSON(StringBuilder* output) const override; std::unique_ptr clone() const override; private: - explicit SerializedValue(const String16& value) : Value(TypeSerialized), m_serializedValue(value) { } - explicit SerializedValue(const char* value) : Value(TypeSerialized), m_serializedValue(value) { } + explicit SerializedValue(const String& value) : Value(TypeSerialized), m_serializedValue(value) { } - String16 m_serializedValue; + String m_serializedValue; }; -class {{config.class_export.macro}} DictionaryValue : public Value { +class {{config.lib.export_macro}} DictionaryValue : public Value { public: - using Entry = std::pair; + using Entry = std::pair; static std::unique_ptr create() { return wrapUnique(new DictionaryValue()); @@ -164,40 +158,40 @@ public: return wrapUnique(DictionaryValue::cast(value.release())); } - void writeJSON(String16Builder* output) const override; + void writeJSON(StringBuilder* output) const override; std::unique_ptr clone() const override; size_t size() const { return m_data.size(); } - void setBoolean(const String16& name, bool); - void setInteger(const String16& name, int); - void setDouble(const String16& name, double); - void setString(const String16& name, const String16&); - void setValue(const String16& name, std::unique_ptr); - void setObject(const String16& name, std::unique_ptr); - void setArray(const String16& name, std::unique_ptr); - - bool getBoolean(const String16& name, bool* output) const; - bool getInteger(const String16& name, int* output) const; - bool getDouble(const String16& name, double* output) const; - bool getString(const String16& name, String16* output) const; - - DictionaryValue* getObject(const String16& name) const; - ListValue* getArray(const String16& name) const; - Value* get(const String16& name) const; + 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); + void setObject(const String& name, std::unique_ptr); + void setArray(const String& name, std::unique_ptr); + + 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 String16& name, bool defaultValue) const; - int integerProperty(const String16& name, int defaultValue) const; - double doubleProperty(const String16& name, double defaultValue) const; - void remove(const String16& name); + 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 - void set(const String16& key, std::unique_ptr& value) + void set(const String& key, std::unique_ptr& value) { DCHECK(value); bool isNew = m_data.find(key) == m_data.end(); @@ -206,12 +200,12 @@ private: m_order.push_back(key); } - using Dictionary = protocol::HashMap>; + using Dictionary = protocol::HashMap>; Dictionary m_data; - std::vector m_order; + std::vector m_order; }; -class {{config.class_export.macro}} ListValue : public Value { +class {{config.lib.export_macro}} ListValue : public Value { public: static std::unique_ptr create() { @@ -232,7 +226,7 @@ public: ~ListValue() override; - void writeJSON(String16Builder* output) const override; + void writeJSON(StringBuilder* output) const override; std::unique_ptr clone() const override; void pushValue(std::unique_ptr); @@ -245,7 +239,8 @@ private: std::vector> m_data; }; -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} -#endif // Values_h +#endif // {{"_".join(config.protocol.namespace)}}_Values_h diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/sample_config.json b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/sample_config.json new file mode 100644 index 00000000000000..82d7845da3cbcd --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/sample_config.json @@ -0,0 +1,39 @@ +{ + "protocol": { + "path": "./relative/path/protocol/sample_protocol.json", + "package": "include/generated/files/like/this", + "output": "place/generated/files/here", + "namespace": ["sample_project", "protocol"], + "export_macro": "LIB_EXPORT", + "export_header": "lib/lib_export.h" + }, + + "exported": { + "package": "include/exported/files/like/this", + "output": "place/exported/files/here", + "string_header": "include/exported/string.h", + "string_in": "String", + "string_out": "String", + "to_string_out": "toString(%s)", + "export_macro": "LIB_EXPORT", + "export_header": "lib/lib_export.h" + }, + + "imported": { + "path": "../relative/path/imported_protocol.json", + "package": "either/include/imported/files/from/here", + "header": "or/include/them/all/together/like/this/imported_protocol.h", + "to_imported_string": "toImportedString(%s)", + "from_imported_string": "fromImportedString(%s)", + "namespace": ["imported_project", "protocol"] + }, + + "lib": { + "package": "include/lib/files/like/this", + "output": "place/generated/lib/files/here", + "string_header": "string/implementation.h", + "platform_header": "platform/implementation.h", + "export_macro": "LIB_EXPORT", + "export_header": "lib/lib_export.h" + } +} diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/sample_expected_errors.json b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/sample_expected_errors.json new file mode 100644 index 00000000000000..85fa2641db6029 --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/sample_expected_errors.json @@ -0,0 +1,7 @@ +{ + "errors": [ + "Domain.event: event has been removed", + "Domain.command: command has been removed", + "Domain.command.param parameter->Domain.TypeName.property: required property has been removed" + ] +} \ No newline at end of file diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Exported_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/Exported_h.template similarity index 58% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Exported_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/Exported_h.template index 66cf7f9018537a..3357f95b5ef159 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Exported_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/Exported_h.template @@ -4,14 +4,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef protocol_{{domain.domain}}_api_h -#define protocol_{{domain.domain}}_api_h +#ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_api_h +#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_api_h -#include "{{config.class_export.header}}" -#include "{{config.lib_package}}/InspectorProtocol.h" +{% if config.exported.export_header %} +#include {{format_include(config.exported.export_header)}} +{% endif %} +#include {{format_include(config.exported.string_header)}} -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} namespace {{domain.domain}} { namespace API { @@ -21,7 +24,7 @@ namespace API { namespace {{type.id}}Enum { {% for literal in type.enum %} -{{config.class_export.macro}} extern const char* {{ literal | dash_to_camelcase}}; +{{config.exported.export_macro}} extern const char* {{ literal | dash_to_camelcase}}; {% endfor %} } // {{type.id}}Enum {% endif %} @@ -33,7 +36,7 @@ namespace {{type.id}}Enum { namespace {{command.name | to_title_case}} { namespace {{param.name | to_title_case}}Enum { {% for literal in param.enum %} -{{config.class_export.macro}} extern const char* {{ literal | dash_to_camelcase}}; +{{config.exported.export_macro}} extern const char* {{ literal | dash_to_camelcase}}; {% endfor %} } // {{param.name | to_title_case}}Enum } // {{command.name | to_title_case }} @@ -45,17 +48,18 @@ namespace {{param.name | to_title_case}}Enum { {% for type in domain.types %} {% if not (type.type == "object") or not ("properties" in type) or not (type.exported) %}{% continue %}{% endif %} -class {{config.class_export.macro}} {{type.id}} { +class {{config.exported.export_macro}} {{type.id}} { public: - virtual String16 toJSONString() const = 0; + virtual {{config.exported.string_out}} toJSONString() const = 0; virtual ~{{type.id}}() { } - static std::unique_ptr fromJSONString(const String16& json); + static std::unique_ptr fromJSONString(const {{config.exported.string_in}}& json); }; {% endfor %} } // namespace API } // namespace {{domain.domain}} -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} -#endif // !defined(protocol_{{domain.domain}}_api_h) +#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_api_h) diff --git a/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/Imported_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/Imported_h.template new file mode 100644 index 00000000000000..c23b8fe87c9f55 --- /dev/null +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/Imported_h.template @@ -0,0 +1,51 @@ +// This file is generated + +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h +#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h + +#include "{{config.protocol.package}}/Protocol.h" +#include {{format_include(config.imported.header if config.imported.header else "\"%s/%s.h\"" % (config.imported.package, domain.domain))}} + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} + {% for type in domain.types %} + {% if not (type.type == "object") or not ("properties" in type) or not (type.exported) %}{% continue %}{% endif %} + +template<> +struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> { + static std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> parse(protocol::Value* value, ErrorSupport* errors) + { + if (!value) { + errors->addError("value expected"); + return nullptr; + } + String json = value->toJSONString(); + auto result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromJSONString({{config.imported.to_imported_string % "json"}}); + if (!result) + errors->addError("cannot parse"); + return result; + } + + static std::unique_ptr serialize(const {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}* value) + { + auto json = value->toJSONString(); + return SerializedValue::create({{config.imported.from_imported_string % "std::move(json)"}}); + } + + static std::unique_ptr serialize(const std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}>& value) + { + return serialize(value.get()); + } +}; + {% endfor %} + +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} + +#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/TypeBuilder_cpp.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/TypeBuilder_cpp.template similarity index 93% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/TypeBuilder_cpp.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/TypeBuilder_cpp.template index 84a3acf670f144..0ea21e9337d76f 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/TypeBuilder_cpp.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/TypeBuilder_cpp.template @@ -6,8 +6,11 @@ #include "{{config.protocol.package}}/{{domain.domain}}.h" -namespace blink { -namespace protocol { +#include "{{config.protocol.package}}/Protocol.h" + +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} namespace {{domain.domain}} { // ------------- Enum values from types. @@ -93,13 +96,14 @@ std::unique_ptr<{{type.id}}> {{type.id}}::clone() const } {% if type.exported %} -String16 {{type.id}}::toJSONString() const +{{config.exported.string_out}} {{type.id}}::toJSONString() const { - return serialize()->toJSONString(); + String json = serialize()->toJSONString(); + return {{config.exported.to_string_out % "json"}}; } // static -std::unique_ptr API::{{type.id}}::fromJSONString(const String16& json) +std::unique_ptr API::{{type.id}}::fromJSONString(const {{config.exported.string_in}}& json) { ErrorSupport errors; std::unique_ptr value = parseJSON(json); @@ -169,6 +173,11 @@ void Frontend::{{event.name}}( } {% endfor %} +void Frontend::flush() +{ + m_frontendChannel->flushProtocolNotifications(); +} + // --------------------- Dispatcher. class DispatcherImpl : public protocol::DispatcherBase { @@ -183,11 +192,11 @@ public: {% endfor %} } ~DispatcherImpl() override { } - void dispatch(int callId, const String16& method, std::unique_ptr messageObject) override; + void dispatch(int callId, const String& method, std::unique_ptr messageObject) override; protected: using CallHandler = void (DispatcherImpl::*)(int callId, std::unique_ptr messageObject, ErrorSupport* errors); - using DispatchMap = protocol::HashMap; + using DispatchMap = protocol::HashMap; DispatchMap m_dispatchMap; {% for command in domain.commands %} @@ -199,9 +208,9 @@ protected: Backend* m_backend; }; -void DispatcherImpl::dispatch(int callId, const String16& method, std::unique_ptr messageObject) +void DispatcherImpl::dispatch(int callId, const String& method, std::unique_ptr messageObject) { - protocol::HashMap::iterator it = m_dispatchMap.find(method); + protocol::HashMap::iterator it = m_dispatchMap.find(method); if (it == m_dispatchMap.end()) { reportProtocolError(callId, MethodNotFound, "'" + method + "' wasn't found", nullptr); return; @@ -345,5 +354,6 @@ void Dispatcher::wire(UberDispatcher* dispatcher, Backend* backend) } } // {{domain.domain}} -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/TypeBuilder_h.template b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/TypeBuilder_h.template similarity index 86% rename from deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/TypeBuilder_h.template rename to deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/TypeBuilder_h.template index b5cf09621d4b2b..553ba55f7c0de6 100644 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/TypeBuilder_h.template +++ b/deps/v8_inspector/third_party/WebKit/Source/platform/inspector_protocol/templates/TypeBuilder_h.template @@ -4,11 +4,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef protocol_{{domain.domain}}_h -#define protocol_{{domain.domain}}_h +#ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h +#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h -#include "{{config.class_export.header}}" -#include "{{config.lib_package}}/InspectorProtocol.h" +{% if config.protocol.export_header %} +#include {{format_include(config.protocol.export_header)}} +{% endif %} +#include "{{config.protocol.package}}/Protocol.h" // For each imported domain we generate a ValueConversions struct instead of a full domain definition // and include Domain::API version from there. {% for name in domain.dependencies %} @@ -18,8 +20,9 @@ #include "{{config.exported.package}}/{{domain.domain}}.h" {% endif %} -namespace blink { -namespace protocol { +{% for namespace in config.protocol.namespace %} +namespace {{namespace}} { +{% endfor %} namespace {{domain.domain}} { // ------------- Forward and enum declarations. @@ -42,7 +45,7 @@ using {{type.id}} = {{resolve_type(type).type}}; namespace {{type.id}}Enum { {% for literal in type.enum %} -{{config.class_export.macro}} extern const char* {{ literal | dash_to_camelcase}}; +{{config.protocol.export_macro}} extern const char* {{ literal | dash_to_camelcase}}; {% endfor %} } // namespace {{type.id}}Enum {% endif %} @@ -54,7 +57,7 @@ namespace {{type.id}}Enum { namespace {{command.name | to_title_case}} { namespace {{param.name | to_title_case}}Enum { {% for literal in param.enum %} -{{config.class_export.macro}} extern const char* {{literal | dash_to_camelcase}}; +{{config.protocol.export_macro}} extern const char* {{literal | dash_to_camelcase}}; {% endfor %} } // {{param.name | to_title_case}}Enum } // {{command.name | to_title_case }} @@ -68,7 +71,7 @@ namespace {{param.name | to_title_case}}Enum { {% set type_def = type_definition(domain.domain + "." + type.id)%} // {{type.description}} -class {{config.class_export.macro}} {{type.id}} {% if type.exported %}: public API::{{type.id}} {% endif %}{ +class {{config.protocol.export_macro}} {{type.id}} {% if type.exported %}: public API::{{type.id}} {% endif %}{ PROTOCOL_DISALLOW_COPY({{type.id}}); public: static std::unique_ptr<{{type.id}}> parse(protocol::Value* value, ErrorSupport* errors); @@ -77,7 +80,7 @@ public: {% for property in type.properties %} {% if "enum" in property %} - struct {{config.class_export.macro}} {{property.name | to_title_case}}Enum { + struct {{config.protocol.export_macro}} {{property.name | to_title_case}}Enum { {% for literal in property.enum %} static const char* {{literal | dash_to_camelcase}}; {% endfor %} @@ -96,7 +99,7 @@ public: std::unique_ptr serialize() const; std::unique_ptr<{{type.id}}> clone() const; {% if type.exported %} - String16 toJSONString() const override; + {{config.exported.string_out}} toJSONString() const override; {% endif %} template @@ -180,13 +183,15 @@ private: // ------------- Backend interface. -class {{config.class_export.macro}} Backend { +class {{config.protocol.export_macro}} Backend { public: + virtual ~Backend() { } + {% for command in domain.commands %} {% if "redirect" in command %}{% continue %}{% endif %} {% if ("handlers" in command) and not ("renderer" in command["handlers"]) %}{% continue %}{% endif %} {% if "async" in command %} - class {{config.class_export.macro}} {{command.name | to_title_case}}Callback : public BackendCallback { + class {{config.protocol.export_macro}} {{command.name | to_title_case}}Callback : public BackendCallback { public: virtual void sendSuccess( {%- for parameter in command.returns -%} @@ -230,14 +235,11 @@ public: {% if not has_disable(domain.commands) %} virtual void disable(ErrorString*) { } {% endif %} - -protected: - virtual ~Backend() { } }; // ------------- Frontend interface. -class {{config.class_export.macro}} Frontend { +class {{config.protocol.export_macro}} Frontend { public: Frontend(FrontendChannel* frontendChannel) : m_frontendChannel(frontendChannel) { } {% for event in domain.events %} @@ -253,16 +255,16 @@ public: ); {% endfor %} - void flush() { m_frontendChannel->flushProtocolNotifications(); } + void flush(); private: FrontendChannel* m_frontendChannel; }; // ------------- Dispatcher. -class {{config.class_export.macro}} Dispatcher { +class {{config.protocol.export_macro}} Dispatcher { public: - static void wire(UberDispatcher*, blink::protocol::{{domain.domain}}::Backend*); + static void wire(UberDispatcher*, Backend*); private: Dispatcher() { } @@ -270,7 +272,7 @@ private: // ------------- Metainfo. -class {{config.class_export.macro}} Metainfo { +class {{config.protocol.export_macro}} Metainfo { public: using BackendClass = Backend; using FrontendClass = Frontend; @@ -281,7 +283,8 @@ public: }; } // namespace {{domain.domain}} -} // namespace protocol -} // namespace blink +{% for namespace in config.protocol.namespace %} +} // namespace {{namespace}} +{% endfor %} -#endif // !defined(protocol_{{domain.domain}}_h) +#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/LICENSE b/deps/v8_inspector/third_party/v8_inspector/LICENSE deleted file mode 100644 index a32e00ce6be362..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/PlatformExport.h b/deps/v8_inspector/third_party/v8_inspector/platform/PlatformExport.h deleted file mode 100644 index 8230fbb80fe30d..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/PlatformExport.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - - -#ifndef PlatformExport_h -#define PlatformExport_h - -#if !defined(BLINK_PLATFORM_IMPLEMENTATION) -#define BLINK_PLATFORM_IMPLEMENTATION 0 -#endif - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) -#if BLINK_PLATFORM_IMPLEMENTATION -#define PLATFORM_EXPORT __declspec(dllexport) -#else -#define PLATFORM_EXPORT __declspec(dllimport) -#endif -#else // defined(WIN32) -#define PLATFORM_EXPORT __attribute__((visibility("default"))) -#endif -#else // defined(COMPONENT_BUILD) -#define PLATFORM_EXPORT -#endif - -#if defined(_MSC_VER) -// MSVC Compiler warning C4275: -// non dll-interface class 'Bar' used as base for dll-interface class 'Foo'. -// Note that this is intended to be used only when no access to the base class' -// static data is done through derived classes or inline methods. For more info, -// see http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx -// -// This pragma will allow exporting a class that inherits from a non-exported -// base class, anywhere in the Blink platform component. This is only -// a problem when using the MSVC compiler on Windows. -#pragma warning(suppress:4275) -#endif - -#endif // PlatformExport_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/BackendCallback_h.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/BackendCallback_h.template deleted file mode 100644 index 0eb44bf2fcfb67..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/BackendCallback_h.template +++ /dev/null @@ -1,24 +0,0 @@ -// 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 BackendCallback_h -#define BackendCallback_h - -//#include "ErrorSupport.h" -//#include "Platform.h" -#include "{{config.class_export.header}}" - -namespace blink { -namespace protocol { - -class {{config.class_export.macro}} BackendCallback { -public: - virtual ~BackendCallback() { } - virtual void sendFailure(const ErrorString&) = 0; -}; - -} // namespace platform -} // namespace blink - -#endif // !defined(BackendCallback_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Collections_h.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Collections_h.template deleted file mode 100644 index a89bef413811e3..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Collections_h.template +++ /dev/null @@ -1,46 +0,0 @@ -// 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 Collections_h -#define Collections_h - -#include - -#if defined(__APPLE__) && !defined(_LIBCPP_VERSION) -#include -#include - -namespace blink { -namespace protocol { - -template using HashMap = std::map; -template using HashSet = std::set; - -} // namespace protocol -} // namespace blink - -#else -#include -#include - -namespace blink { -namespace protocol { - -template using HashMap = std::unordered_map; -template using HashSet = std::unordered_set; - -} // namespace protocol -} // namespace blink - -#endif // defined(__APPLE__) && !defined(_LIBCPP_VERSION) - -// Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array. -template char (&ArrayLengthHelperFunction(T (&)[Size]))[Size]; -// GCC needs some help to deduce a 0 length array. -#if defined(__GNUC__) -template char (&ArrayLengthHelperFunction(T (&)[0]))[0]; -#endif -#define PROTOCOL_ARRAY_LENGTH(array) sizeof(::ArrayLengthHelperFunction(array)) - -#endif // !defined(Collections_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ErrorSupport_h.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ErrorSupport_h.template deleted file mode 100644 index f837bff388e154..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ErrorSupport_h.template +++ /dev/null @@ -1,43 +0,0 @@ -// 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 ErrorSupport_h -#define ErrorSupport_h - -//#include "Platform.h" -//#include "String16.h" -#include "{{config.class_export.header}}" - -#include - -namespace blink { -namespace protocol { - -using ErrorString = String16; - -class {{config.class_export.macro}} ErrorSupport { -public: - ErrorSupport(); - ErrorSupport(String16* errorString); - ~ErrorSupport(); - - void push(); - void setName(const String16&); - void pop(); - void addError(const String16&); - bool hasErrors(); - String16 errors(); - -private: - std::vector m_path; - std::vector m_errors; - String16* m_errorString; -}; - -} // namespace platform -} // namespace blink - -using blink::protocol::ErrorString; - -#endif // !defined(ErrorSupport_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/FrontendChannel_h.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/FrontendChannel_h.template deleted file mode 100644 index ead1491ed28262..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/FrontendChannel_h.template +++ /dev/null @@ -1,25 +0,0 @@ -// 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 FrontendChannel_h -#define FrontendChannel_h - -//#include "String16.h" -#include "{{config.class_export.header}}" - -namespace blink { -namespace protocol { - -class {{config.class_export.macro}} FrontendChannel { -public: - virtual ~FrontendChannel() { } - virtual void sendProtocolResponse(int callId, const String16& message) = 0; - virtual void sendProtocolNotification(const String16& message) = 0; - virtual void flushProtocolNotifications() = 0; -}; - -} // namespace protocol -} // namespace blink - -#endif // !defined(FrontendChannel_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Imported_h.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Imported_h.template deleted file mode 100644 index 2d4e11a4690807..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Imported_h.template +++ /dev/null @@ -1,47 +0,0 @@ -// 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 protocol_{{domain.domain}}_imported_h -#define protocol_{{domain.domain}}_imported_h - -#include "{{config.lib_package}}/InspectorProtocol.h" -#include "{{config.imported.package}}/{{domain.domain}}.h" - -namespace blink { -namespace protocol { - {% for type in domain.types %} - {% if not (type.type == "object") or not ("properties" in type) or not (type.exported) %}{% continue %}{% endif %} - -template<> -struct ValueConversions<{{domain.domain}}::API::{{type.id}}> { - static std::unique_ptr<{{domain.domain}}::API::{{type.id}}> parse(protocol::Value* value, ErrorSupport* errors) - { - if (!value) { - errors->addError("value expected"); - return nullptr; - } - std::unique_ptr<{{domain.domain}}::API::{{type.id}}> result = {{domain.domain}}::API::{{type.id}}::fromJSONString(value->toJSONString()); - if (!result) - errors->addError("cannot parse"); - return result; - } - - static std::unique_ptr serialize({{domain.domain}}::API::{{type.id}}* value) - { - return SerializedValue::create(value->toJSONString()); - } - - static std::unique_ptr serialize(const std::unique_ptr<{{domain.domain}}::API::{{type.id}}>& value) - { - return SerializedValue::create(value->toJSONString()); - } -}; - {% endfor %} - -} // namespace protocol -} // namespace blink - -#endif // !defined(protocol_{{domain.domain}}_imported_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/InspectorProtocol_cpp.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/InspectorProtocol_cpp.template deleted file mode 100644 index e7c49fdda189e5..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/InspectorProtocol_cpp.template +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "{{config.lib_package}}/InspectorProtocol.h" diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ParserTest.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ParserTest.cpp deleted file mode 100644 index 40c6af754cedbe..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/ParserTest.cpp +++ /dev/null @@ -1,501 +0,0 @@ -// 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 "platform/inspector_protocol/InspectorProtocol.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace blink { -namespace protocol { - -TEST(ParserTest, Reading) -{ - protocol::Value* tmpValue; - std::unique_ptr root; - std::unique_ptr root2; - String16 strVal; - int intVal = 0; - - // some whitespace checking - root = parseJSON(" null "); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeNull, root->type()); - - // Invalid JSON string - root = parseJSON("nu"); - EXPECT_FALSE(root.get()); - - // Simple bool - root = parseJSON("true "); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeBoolean, root->type()); - - // Embedded comment - root = parseJSON("40 /*/"); - EXPECT_FALSE(root.get()); - root = parseJSON("/* comment */null"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeNull, root->type()); - root = parseJSON("40 /* comment */"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeInteger, root->type()); - EXPECT_TRUE(root->asInteger(&intVal)); - EXPECT_EQ(40, intVal); - root = parseJSON("/**/ 40 /* multi-line\n comment */ // more comment"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeInteger, root->type()); - EXPECT_TRUE(root->asInteger(&intVal)); - EXPECT_EQ(40, intVal); - root = parseJSON("true // comment"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeBoolean, root->type()); - root = parseJSON("/* comment */\"sample string\""); - ASSERT_TRUE(root.get()); - EXPECT_TRUE(root->asString(&strVal)); - EXPECT_EQ("sample string", strVal); - root = parseJSON("[1, /* comment, 2 ] */ \n 3]"); - ASSERT_TRUE(root.get()); - protocol::ListValue* list = ListValue::cast(root.get()); - ASSERT_TRUE(list); - EXPECT_EQ(2u, list->size()); - tmpValue = list->at(0); - ASSERT_TRUE(tmpValue); - EXPECT_TRUE(tmpValue->asInteger(&intVal)); - EXPECT_EQ(1, intVal); - tmpValue = list->at(1); - ASSERT_TRUE(tmpValue); - EXPECT_TRUE(tmpValue->asInteger(&intVal)); - EXPECT_EQ(3, intVal); - root = parseJSON("[1, /*a*/2, 3]"); - ASSERT_TRUE(root.get()); - list = ListValue::cast(root.get()); - ASSERT_TRUE(list); - EXPECT_EQ(3u, list->size()); - root = parseJSON("/* comment **/42"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeInteger, root->type()); - EXPECT_TRUE(root->asInteger(&intVal)); - EXPECT_EQ(42, intVal); - root = parseJSON( - "/* comment **/\n" - "// */ 43\n" - "44"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeInteger, root->type()); - EXPECT_TRUE(root->asInteger(&intVal)); - EXPECT_EQ(44, intVal); - - // Test number formats - root = parseJSON("43"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeInteger, root->type()); - EXPECT_TRUE(root->asInteger(&intVal)); - EXPECT_EQ(43, intVal); - - // According to RFC4627, oct, hex, and leading zeros are invalid JSON. - root = parseJSON("043"); - EXPECT_FALSE(root.get()); - root = parseJSON("0x43"); - EXPECT_FALSE(root.get()); - root = parseJSON("00"); - EXPECT_FALSE(root.get()); - - // Test 0 (which needs to be special cased because of the leading zero - // clause). - root = parseJSON("0"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeInteger, root->type()); - intVal = 1; - EXPECT_TRUE(root->asInteger(&intVal)); - EXPECT_EQ(0, intVal); - - // Numbers that overflow ints should succeed, being internally promoted to - // storage as doubles - root = parseJSON("2147483648"); - ASSERT_TRUE(root.get()); - double doubleVal; - EXPECT_EQ(Value::TypeDouble, root->type()); - doubleVal = 0.0; - EXPECT_TRUE(root->asDouble(&doubleVal)); - EXPECT_DOUBLE_EQ(2147483648.0, doubleVal); - root = parseJSON("-2147483649"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeDouble, root->type()); - doubleVal = 0.0; - EXPECT_TRUE(root->asDouble(&doubleVal)); - EXPECT_DOUBLE_EQ(-2147483649.0, doubleVal); - - // Parse a double - root = parseJSON("43.1"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeDouble, root->type()); - doubleVal = 0.0; - EXPECT_TRUE(root->asDouble(&doubleVal)); - EXPECT_DOUBLE_EQ(43.1, doubleVal); - - root = parseJSON("4.3e-1"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeDouble, root->type()); - doubleVal = 0.0; - EXPECT_TRUE(root->asDouble(&doubleVal)); - EXPECT_DOUBLE_EQ(.43, doubleVal); - - root = parseJSON("2.1e0"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeDouble, root->type()); - doubleVal = 0.0; - EXPECT_TRUE(root->asDouble(&doubleVal)); - EXPECT_DOUBLE_EQ(2.1, doubleVal); - - root = parseJSON("2.1e+0001"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeInteger, root->type()); - doubleVal = 0.0; - EXPECT_TRUE(root->asDouble(&doubleVal)); - EXPECT_DOUBLE_EQ(21.0, doubleVal); - - root = parseJSON("0.01"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeDouble, root->type()); - doubleVal = 0.0; - EXPECT_TRUE(root->asDouble(&doubleVal)); - EXPECT_DOUBLE_EQ(0.01, doubleVal); - - root = parseJSON("1.00"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeInteger, root->type()); - doubleVal = 0.0; - EXPECT_TRUE(root->asDouble(&doubleVal)); - EXPECT_DOUBLE_EQ(1.0, doubleVal); - - // Fractional parts must have a digit before and after the decimal point. - root = parseJSON("1."); - EXPECT_FALSE(root.get()); - root = parseJSON(".1"); - EXPECT_FALSE(root.get()); - root = parseJSON("1.e10"); - EXPECT_FALSE(root.get()); - - // Exponent must have a digit following the 'e'. - root = parseJSON("1e"); - EXPECT_FALSE(root.get()); - root = parseJSON("1E"); - EXPECT_FALSE(root.get()); - root = parseJSON("1e1."); - EXPECT_FALSE(root.get()); - root = parseJSON("1e1.0"); - EXPECT_FALSE(root.get()); - - // INF/-INF/NaN are not valid - root = parseJSON("NaN"); - EXPECT_FALSE(root.get()); - root = parseJSON("nan"); - EXPECT_FALSE(root.get()); - root = parseJSON("inf"); - EXPECT_FALSE(root.get()); - - // Invalid number formats - root = parseJSON("4.3.1"); - EXPECT_FALSE(root.get()); - root = parseJSON("4e3.1"); - EXPECT_FALSE(root.get()); - - // Test string parser - root = parseJSON("\"hello world\""); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeString, root->type()); - EXPECT_TRUE(root->asString(&strVal)); - EXPECT_EQ("hello world", strVal); - - // Empty string - root = parseJSON("\"\""); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeString, root->type()); - EXPECT_TRUE(root->asString(&strVal)); - EXPECT_EQ("", strVal); - - // Test basic string escapes - root = parseJSON("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\\v\""); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeString, root->type()); - EXPECT_TRUE(root->asString(&strVal)); - EXPECT_EQ(" \"\\/\b\f\n\r\t\v", strVal); - - // Test hex and unicode escapes including the null character. - root = parseJSON("\"\\x41\\x00\\u1234\""); - EXPECT_FALSE(root.get()); - - // Test invalid strings - root = parseJSON("\"no closing quote"); - EXPECT_FALSE(root.get()); - root = parseJSON("\"\\z invalid escape char\""); - EXPECT_FALSE(root.get()); - root = parseJSON("\"not enough escape chars\\u123\""); - EXPECT_FALSE(root.get()); - root = parseJSON("\"extra backslash at end of input\\\""); - EXPECT_FALSE(root.get()); - - // Basic array - root = parseJSON("[true, false, null]"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeArray, root->type()); - list = ListValue::cast(root.get()); - ASSERT_TRUE(list); - EXPECT_EQ(3U, list->size()); - - // Empty array - root = parseJSON("[]"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeArray, root->type()); - list = ListValue::cast(root.get()); - ASSERT_TRUE(list); - EXPECT_EQ(0U, list->size()); - - // Nested arrays - root = parseJSON("[[true], [], [false, [], [null]], null]"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeArray, root->type()); - list = ListValue::cast(root.get()); - ASSERT_TRUE(list); - EXPECT_EQ(4U, list->size()); - - // Invalid, missing close brace. - root = parseJSON("[[true], [], [false, [], [null]], null"); - EXPECT_FALSE(root.get()); - - // Invalid, too many commas - root = parseJSON("[true,, null]"); - EXPECT_FALSE(root.get()); - - // Invalid, no commas - root = parseJSON("[true null]"); - EXPECT_FALSE(root.get()); - - // Invalid, trailing comma - root = parseJSON("[true,]"); - EXPECT_FALSE(root.get()); - - root = parseJSON("[true]"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeArray, root->type()); - list = ListValue::cast(root.get()); - ASSERT_TRUE(list); - EXPECT_EQ(1U, list->size()); - tmpValue = list->at(0); - ASSERT_TRUE(tmpValue); - EXPECT_EQ(Value::TypeBoolean, tmpValue->type()); - bool boolValue = false; - EXPECT_TRUE(tmpValue->asBoolean(&boolValue)); - EXPECT_TRUE(boolValue); - - // Don't allow empty elements. - root = parseJSON("[,]"); - EXPECT_FALSE(root.get()); - root = parseJSON("[true,,]"); - EXPECT_FALSE(root.get()); - root = parseJSON("[,true,]"); - EXPECT_FALSE(root.get()); - root = parseJSON("[true,,false]"); - EXPECT_FALSE(root.get()); - - // Test objects - root = parseJSON("{}"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeObject, root->type()); - - root = parseJSON("{\"number\":9.87654321, \"null\":null , \"S\" : \"str\" }"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeObject, root->type()); - protocol::DictionaryValue* objectVal = DictionaryValue::cast(root.get()); - ASSERT_TRUE(objectVal); - doubleVal = 0.0; - EXPECT_TRUE(objectVal->getDouble("number", &doubleVal)); - EXPECT_DOUBLE_EQ(9.87654321, doubleVal); - protocol::Value* nullVal = objectVal->get("null"); - ASSERT_TRUE(nullVal); - EXPECT_EQ(Value::TypeNull, nullVal->type()); - EXPECT_TRUE(objectVal->getString("S", &strVal)); - EXPECT_EQ("str", strVal); - - // Test newline equivalence. - root2 = parseJSON( - "{\n" - " \"number\":9.87654321,\n" - " \"null\":null,\n" - " \"S\":\"str\"\n" - "}\n"); - ASSERT_TRUE(root2.get()); - EXPECT_EQ(root->toJSONString(), root2->toJSONString()); - - root2 = parseJSON( - "{\r\n" - " \"number\":9.87654321,\r\n" - " \"null\":null,\r\n" - " \"S\":\"str\"\r\n" - "}\r\n"); - ASSERT_TRUE(root2.get()); - EXPECT_EQ(root->toJSONString(), root2->toJSONString()); - - // Test nesting - root = parseJSON("{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeObject, root->type()); - objectVal = DictionaryValue::cast(root.get()); - ASSERT_TRUE(objectVal); - protocol::DictionaryValue* innerObject = objectVal->getObject("inner"); - ASSERT_TRUE(innerObject); - protocol::ListValue* innerArray = innerObject->getArray("array"); - ASSERT_TRUE(innerArray); - EXPECT_EQ(1U, innerArray->size()); - boolValue = true; - EXPECT_TRUE(objectVal->getBoolean("false", &boolValue)); - EXPECT_FALSE(boolValue); - innerObject = objectVal->getObject("d"); - EXPECT_TRUE(innerObject); - - // Test keys with periods - root = parseJSON("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeObject, root->type()); - objectVal = DictionaryValue::cast(root.get()); - ASSERT_TRUE(objectVal); - int integerValue = 0; - EXPECT_TRUE(objectVal->getInteger("a.b", &integerValue)); - EXPECT_EQ(3, integerValue); - EXPECT_TRUE(objectVal->getInteger("c", &integerValue)); - EXPECT_EQ(2, integerValue); - innerObject = objectVal->getObject("d.e.f"); - ASSERT_TRUE(innerObject); - EXPECT_EQ(1U, innerObject->size()); - EXPECT_TRUE(innerObject->getInteger("g.h.i.j", &integerValue)); - EXPECT_EQ(1, integerValue); - - root = parseJSON("{\"a\":{\"b\":2},\"a.b\":1}"); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeObject, root->type()); - objectVal = DictionaryValue::cast(root.get()); - ASSERT_TRUE(objectVal); - innerObject = objectVal->getObject("a"); - ASSERT_TRUE(innerObject); - EXPECT_TRUE(innerObject->getInteger("b", &integerValue)); - EXPECT_EQ(2, integerValue); - EXPECT_TRUE(objectVal->getInteger("a.b", &integerValue)); - EXPECT_EQ(1, integerValue); - - // Invalid, no closing brace - root = parseJSON("{\"a\": true"); - EXPECT_FALSE(root.get()); - - // Invalid, keys must be quoted - root = parseJSON("{foo:true}"); - EXPECT_FALSE(root.get()); - - // Invalid, trailing comma - root = parseJSON("{\"a\":true,}"); - EXPECT_FALSE(root.get()); - - // Invalid, too many commas - root = parseJSON("{\"a\":true,,\"b\":false}"); - EXPECT_FALSE(root.get()); - - // Invalid, no separator - root = parseJSON("{\"a\" \"b\"}"); - EXPECT_FALSE(root.get()); - - // Invalid, lone comma. - root = parseJSON("{,}"); - EXPECT_FALSE(root.get()); - root = parseJSON("{\"a\":true,,}"); - EXPECT_FALSE(root.get()); - root = parseJSON("{,\"a\":true}"); - EXPECT_FALSE(root.get()); - root = parseJSON("{\"a\":true,,\"b\":false}"); - EXPECT_FALSE(root.get()); - - // Test stack overflow - String16Builder evil; - evil.reserveCapacity(2000000); - for (int i = 0; i < 1000000; ++i) - evil.append('['); - for (int i = 0; i < 1000000; ++i) - evil.append(']'); - root = parseJSON(evil.toString()); - EXPECT_FALSE(root.get()); - - // A few thousand adjacent lists is fine. - String16Builder notEvil; - notEvil.reserveCapacity(15010); - notEvil.append('['); - for (int i = 0; i < 5000; ++i) - notEvil.append("[],"); - notEvil.append("[]]"); - root = parseJSON(notEvil.toString()); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeArray, root->type()); - list = ListValue::cast(root.get()); - ASSERT_TRUE(list); - EXPECT_EQ(5001U, list->size()); - - // Test utf8 encoded input - root = parseJSON("\"\\xe7\\xbd\\x91\\xe9\\xa1\\xb5\""); - ASSERT_FALSE(root.get()); - - // Test utf16 encoded strings. - root = parseJSON("\"\\u20ac3,14\""); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeString, root->type()); - EXPECT_TRUE(root->asString(&strVal)); - UChar tmp2[] = {0x20ac, 0x33, 0x2c, 0x31, 0x34}; - EXPECT_EQ(String16(tmp2, 5), strVal); - - root = parseJSON("\"\\ud83d\\udca9\\ud83d\\udc6c\""); - ASSERT_TRUE(root.get()); - EXPECT_EQ(Value::TypeString, root->type()); - EXPECT_TRUE(root->asString(&strVal)); - UChar tmp3[] = {0xd83d, 0xdca9, 0xd83d, 0xdc6c}; - EXPECT_EQ(String16(tmp3, 4), strVal); - - // Test literal root objects. - root = parseJSON("null"); - EXPECT_EQ(Value::TypeNull, root->type()); - - root = parseJSON("true"); - ASSERT_TRUE(root.get()); - EXPECT_TRUE(root->asBoolean(&boolValue)); - EXPECT_TRUE(boolValue); - - root = parseJSON("10"); - ASSERT_TRUE(root.get()); - EXPECT_TRUE(root->asInteger(&integerValue)); - EXPECT_EQ(10, integerValue); - - root = parseJSON("\"root\""); - ASSERT_TRUE(root.get()); - EXPECT_TRUE(root->asString(&strVal)); - EXPECT_EQ("root", strVal); -} - -TEST(ParserTest, InvalidSanity) -{ - const char* const invalidJson[] = { - "/* test *", - "{\"foo\"", - "{\"foo\":", - " [", - "\"\\u123g\"", - "{\n\"eh:\n}", - "////", - "*/**/", - "/**/", - "/*/", - "//**/" - }; - - for (size_t i = 0; i < 11; ++i) { - std::unique_ptr result = parseJSON(invalidJson[i]); - EXPECT_FALSE(result.get()); - } -} - -} // namespace protocol -} // namespace blink diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Parser_h.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Parser_h.template deleted file mode 100644 index 1f3a1b65c06e40..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/Parser_h.template +++ /dev/null @@ -1,22 +0,0 @@ -// 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 Parser_h -#define Parser_h - -//#include "Platform.h" -//#include "String16.h" -#include "{{config.class_export.header}}" - -namespace blink { -namespace protocol { - -class Value; - -{{config.class_export.macro}} std::unique_ptr parseJSON(const String16& json); - -} // namespace platform -} // namespace blink - -#endif // !defined(Parser_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/String16_cpp.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/String16_cpp.template deleted file mode 100644 index d795aefa0c2f25..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/String16_cpp.template +++ /dev/null @@ -1,99 +0,0 @@ -// 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 -#include -#include - -namespace blink { -namespace protocol { - -namespace internal { - -void intToStr(int number, char* buffer, size_t length) -{ - std::snprintf(buffer, length, "%d", number); -} - -void doubleToStr(double number, char* buffer, size_t length) -{ - std::snprintf(buffer, length, "%f", number); -} - -void doubleToStr3(double number, char* buffer, size_t length) -{ - std::snprintf(buffer, length, "%.3g", number); -} - -void doubleToStr6(double number, char* buffer, size_t length) -{ - std::snprintf(buffer, length, "%.6g", number); -} - -double strToDouble(const char* buffer, bool* ok) -{ - char* endptr; - double result = std::strtod(buffer, &endptr); - if (ok) - *ok = !(*endptr); - return result; -} - -int strToInt(const char* buffer, bool* ok) -{ - char* endptr; - int result = std::strtol(buffer, &endptr, 10); - if (ok) - *ok = !(*endptr); - return result; -} - -} // namespace internal - -String16Builder::String16Builder() -{ -} - -void String16Builder::append(const String16& s) -{ - m_buffer.insert(m_buffer.end(), s.characters16(), s.characters16() + s.length()); -} - -void String16Builder::append(UChar c) -{ - m_buffer.push_back(c); -} - -void String16Builder::append(char c) -{ - UChar u = c; - m_buffer.push_back(u); -} - -void String16Builder::append(const UChar* characters, size_t length) -{ - m_buffer.insert(m_buffer.end(), characters, characters + length); -} - -void String16Builder::append(const char* characters, size_t length) -{ - m_buffer.reserve(m_buffer.size() + length); - for (size_t i = 0; i < length; ++i, ++characters) { - UChar u = *characters; - m_buffer.push_back(u); - } -} - -String16 String16Builder::toString() -{ - return String16(m_buffer.data(), m_buffer.size()); -} - -void String16Builder::reserveCapacity(size_t capacity) -{ - m_buffer.reserve(capacity); -} - -} // namespace protocol -} // namespace blink diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/String16_h.template b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/String16_h.template deleted file mode 100644 index e6f8f0c78465ae..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/String16_h.template +++ /dev/null @@ -1,181 +0,0 @@ -// 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 String16_h -#define String16_h - -//#include "Collections.h" -//#include "Platform.h" -#include "{{config.class_export.header}}" - -#include - -namespace blink { -namespace protocol { - -namespace internal { -{{config.class_export.macro}} void intToStr(int, char*, size_t); -{{config.class_export.macro}} void doubleToStr(double, char*, size_t); -{{config.class_export.macro}} void doubleToStr3(double, char*, size_t); -{{config.class_export.macro}} void doubleToStr6(double, char*, size_t); -{{config.class_export.macro}} double strToDouble(const char*, bool*); -{{config.class_export.macro}} int strToInt(const char*, bool*); -} // namespace internal - -template -class {{config.class_export.macro}} String16Base { -public: - static bool isASCII(C c) - { - return !(c & ~0x7F); - } - - static bool isSpaceOrNewLine(C c) - { - return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); - } - - static T fromInteger(int number) - { - char buffer[50]; - internal::intToStr(number, buffer, PROTOCOL_ARRAY_LENGTH(buffer)); - return T(buffer); - } - - static T fromDouble(double number) - { - char buffer[100]; - internal::doubleToStr(number, buffer, PROTOCOL_ARRAY_LENGTH(buffer)); - return T(buffer); - } - - static T fromDoublePrecision3(double number) - { - char buffer[100]; - internal::doubleToStr3(number, buffer, PROTOCOL_ARRAY_LENGTH(buffer)); - return T(buffer); - } - - static T fromDoublePrecision6(double number) - { - char buffer[100]; - internal::doubleToStr6(number, buffer, PROTOCOL_ARRAY_LENGTH(buffer)); - return T(buffer); - } - - static double charactersToDouble(const C* characters, size_t length, bool* ok = nullptr) - { - std::vector buffer; - buffer.reserve(length + 1); - for (size_t i = 0; i < length; ++i) { - if (!isASCII(characters[i])) { - if (ok) - *ok = false; - return 0; - } - buffer.push_back(static_cast(characters[i])); - } - buffer.push_back('\0'); - return internal::strToDouble(buffer.data(), ok); - } - - static int charactersToInteger(const C* characters, size_t length, bool* ok = nullptr) - { - std::vector buffer; - buffer.reserve(length + 1); - for (size_t i = 0; i < length; ++i) { - if (!isASCII(characters[i])) { - if (ok) - *ok = false; - return 0; - } - buffer.push_back(static_cast(characters[i])); - } - buffer.push_back('\0'); - return internal::strToInt(buffer.data(), ok); - } - - double toDouble(bool* ok = nullptr) const - { - const C* characters = static_cast(*this).characters16(); - size_t length = static_cast(*this).length(); - return charactersToDouble(characters, length, ok); - } - - int toInteger(bool* ok = nullptr) const - { - const C* characters = static_cast(*this).characters16(); - size_t length = static_cast(*this).length(); - return charactersToInteger(characters, length, ok); - } - - T stripWhiteSpace() const - { - size_t length = static_cast(*this).length(); - if (!length) - return T(); - - unsigned start = 0; - unsigned end = length - 1; - const C* characters = static_cast(*this).characters16(); - - // skip white space from start - while (start <= end && isSpaceOrNewLine(characters[start])) - ++start; - - // only white space - if (start > end) - return T(); - - // skip white space from end - while (end && isSpaceOrNewLine(characters[end])) - --end; - - if (!start && end == length - 1) - return T(static_cast(*this)); - return T(characters + start, end + 1 - start); - } - - bool startsWith(const char* prefix) const - { - const C* characters = static_cast(*this).characters16(); - size_t length = static_cast(*this).length(); - for (size_t i = 0, j = 0; prefix[j] && i < length; ++i, ++j) { - if (characters[i] != prefix[j]) - return false; - } - return true; - } -}; - -} // namespace protocol -} // namespace blink - -#include "{{config.lib.string16_header}}" - -namespace blink { -namespace protocol { - -class {{config.class_export.macro}} String16Builder { -public: - String16Builder(); - void append(const String16&); - void append(UChar); - void append(char); - void append(const UChar*, size_t); - void append(const char*, size_t); - String16 toString(); - void reserveCapacity(size_t); - -private: - std::vector m_buffer; -}; - -} // namespace protocol -} // namespace blink - -using String16 = blink::protocol::String16; -using String16Builder = blink::protocol::String16Builder; - -#endif // !defined(String16_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/sample_config.json b/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/sample_config.json deleted file mode 100644 index 5ad6722cb27d5c..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/inspector_protocol/sample_config.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "protocol": { - "path": "protocol/sample_protocol.json", - "package": "include/generated/files/like/this", - "output": "place/generated/files/here" - }, - - "imported": { - "path": "../relative/path/imported_protocol.json", - "package": "include/imported/files/like/this" - }, - - "exported": { - "package": "include/exported/files/like/this", - "output": "place/exported/files/here" - }, - - "string": { - "class_name": "String16" - }, - - "lib": { - "output": "place/generated/lib/files/here", - "string16_header": "sting16/implementation.h", - "platform_header": "platform/implementation.h" - }, - - "lib_package": "include/lib/files/like/this", - - "class_export": { - "macro": "LIB_EXPORT", - "header": "lib/export.h" - } -} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/Atomics.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/Atomics.h deleted file mode 100644 index 8523df6294158e..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/Atomics.h +++ /dev/null @@ -1,29 +0,0 @@ -// 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 Atomics_h -#define Atomics_h - -#include - -#if defined(_MSC_VER) -#include -#endif - -namespace v8_inspector { - -#if defined(_MSC_VER) - -inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast(addend)); } - -#else - -inline int atomicAdd(int volatile* addend, int increment) { return __sync_add_and_fetch(addend, increment); } -inline int atomicIncrement(int volatile* addend) { return atomicAdd(addend, 1); } - -#endif - -} // namespace v8_inspector - -#endif /* Atomics_h */ diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScript.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScript.cpp deleted file mode 100644 index dfe5b923be1ba9..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScript.cpp +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#include "platform/v8_inspector/InjectedScript.h" - -#include "platform/v8_inspector/InjectedScriptNative.h" -#include "platform/v8_inspector/InjectedScriptSource.h" -#include "platform/v8_inspector/InspectedContext.h" -#include "platform/v8_inspector/RemoteObjectId.h" -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8Console.h" -#include "platform/v8_inspector/V8FunctionCall.h" -#include "platform/v8_inspector/V8InjectedScriptHost.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -using blink::protocol::Array; -using blink::protocol::Debugger::CallFrame; -using blink::protocol::Runtime::PropertyDescriptor; -using blink::protocol::Runtime::InternalPropertyDescriptor; -using blink::protocol::Runtime::RemoteObject; -using blink::protocol::Maybe; - -namespace v8_inspector { - -static bool hasInternalError(ErrorString* errorString, bool hasError) -{ - if (hasError) - *errorString = "Internal error"; - return hasError; -} - -std::unique_ptr InjectedScript::create(InspectedContext* inspectedContext) -{ - v8::Isolate* isolate = inspectedContext->isolate(); - v8::HandleScope handles(isolate); - v8::Local context = inspectedContext->context(); - v8::Context::Scope scope(context); - - std::unique_ptr injectedScriptNative(new InjectedScriptNative(isolate)); - v8::Local scriptHostWrapper = V8InjectedScriptHost::create(context, inspectedContext->inspector()); - injectedScriptNative->setOnInjectedScriptHost(scriptHostWrapper); - - // Inject javascript into the context. The compiled script is supposed to evaluate into - // a single anonymous function(it's anonymous to avoid cluttering the global object with - // inspector's stuff) the function is called a few lines below with InjectedScriptHost wrapper, - // injected script id and explicit reference to the inspected global object. The function is expected - // to create and configure InjectedScript instance that is going to be used by the inspector. - String16 injectedScriptSource(reinterpret_cast(InjectedScriptSource_js), sizeof(InjectedScriptSource_js)); - v8::Local value; - if (!inspectedContext->inspector()->compileAndRunInternalScript(context, toV8String(isolate, injectedScriptSource)).ToLocal(&value)) - return nullptr; - DCHECK(value->IsFunction()); - v8::Local function = v8::Local::Cast(value); - v8::Local windowGlobal = context->Global(); - v8::Local info[] = { scriptHostWrapper, windowGlobal, v8::Number::New(isolate, inspectedContext->contextId()) }; - v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local injectedScriptValue; - if (!function->Call(context, windowGlobal, PROTOCOL_ARRAY_LENGTH(info), info).ToLocal(&injectedScriptValue)) - return nullptr; - if (!injectedScriptValue->IsObject()) - return nullptr; - return wrapUnique(new InjectedScript(inspectedContext, injectedScriptValue.As(), std::move(injectedScriptNative))); -} - -InjectedScript::InjectedScript(InspectedContext* context, v8::Local object, std::unique_ptr injectedScriptNative) - : m_context(context) - , m_value(context->isolate(), object) - , m_native(std::move(injectedScriptNative)) -{ -} - -InjectedScript::~InjectedScript() -{ -} - -void InjectedScript::getProperties(ErrorString* errorString, v8::Local object, const String16& groupName, bool ownProperties, bool accessorPropertiesOnly, bool generatePreview, std::unique_ptr>* properties, Maybe* exceptionDetails) -{ - v8::HandleScope handles(m_context->isolate()); - V8FunctionCall function(m_context->inspector(), m_context->context(), v8Value(), "getProperties"); - function.appendArgument(object); - function.appendArgument(groupName); - function.appendArgument(ownProperties); - function.appendArgument(accessorPropertiesOnly); - function.appendArgument(generatePreview); - - v8::TryCatch tryCatch(m_context->isolate()); - v8::Local resultValue = function.callWithoutExceptionHandling(); - if (tryCatch.HasCaught()) { - *exceptionDetails = createExceptionDetails(errorString, tryCatch, groupName, generatePreview); - // FIXME: make properties optional - *properties = Array::create(); - return; - } - - std::unique_ptr protocolValue = toProtocolValue(m_context->context(), resultValue); - if (hasInternalError(errorString, !protocolValue)) - return; - protocol::ErrorSupport errors(errorString); - std::unique_ptr> result = Array::parse(protocolValue.get(), &errors); - if (!hasInternalError(errorString, errors.hasErrors())) - *properties = std::move(result); -} - -void InjectedScript::releaseObject(const String16& objectId) -{ - std::unique_ptr parsedObjectId = protocol::parseJSON(objectId); - if (!parsedObjectId) - return; - protocol::DictionaryValue* object = protocol::DictionaryValue::cast(parsedObjectId.get()); - if (!object) - return; - int boundId = 0; - if (!object->getInteger("id", &boundId)) - return; - m_native->unbind(boundId); -} - -std::unique_ptr InjectedScript::wrapObject(ErrorString* errorString, v8::Local value, const String16& groupName, bool forceValueType, bool generatePreview) const -{ - v8::HandleScope handles(m_context->isolate()); - v8::Local wrappedObject; - if (!wrapValue(errorString, value, groupName, forceValueType, generatePreview).ToLocal(&wrappedObject)) - return nullptr; - protocol::ErrorSupport errors; - std::unique_ptr remoteObject = protocol::Runtime::RemoteObject::parse(toProtocolValue(m_context->context(), wrappedObject).get(), &errors); - if (!remoteObject) - *errorString = "Object has too long reference chain"; - return remoteObject; -} - -bool InjectedScript::wrapObjectProperty(ErrorString* errorString, v8::Local object, v8::Local key, const String16& groupName, bool forceValueType, bool generatePreview) const -{ - v8::Local property; - if (hasInternalError(errorString, !object->Get(m_context->context(), key).ToLocal(&property))) - return false; - v8::Local wrappedProperty; - if (!wrapValue(errorString, property, groupName, forceValueType, generatePreview).ToLocal(&wrappedProperty)) - return false; - v8::Maybe success = object->Set(m_context->context(), key, wrappedProperty); - if (hasInternalError(errorString, success.IsNothing() || !success.FromJust())) - return false; - return true; -} - -bool InjectedScript::wrapPropertyInArray(ErrorString* errorString, v8::Local array, v8::Local property, const String16& groupName, bool forceValueType, bool generatePreview) const -{ - V8FunctionCall function(m_context->inspector(), m_context->context(), v8Value(), "wrapPropertyInArray"); - function.appendArgument(array); - function.appendArgument(property); - function.appendArgument(groupName); - function.appendArgument(forceValueType); - function.appendArgument(generatePreview); - bool hadException = false; - function.call(hadException); - return !hasInternalError(errorString, hadException); -} - -bool InjectedScript::wrapObjectsInArray(ErrorString* errorString, v8::Local array, const String16& groupName, bool forceValueType, bool generatePreview) const -{ - V8FunctionCall function(m_context->inspector(), m_context->context(), v8Value(), "wrapObjectsInArray"); - function.appendArgument(array); - function.appendArgument(groupName); - function.appendArgument(forceValueType); - function.appendArgument(generatePreview); - bool hadException = false; - function.call(hadException); - return !hasInternalError(errorString, hadException); -} - -v8::MaybeLocal InjectedScript::wrapValue(ErrorString* errorString, v8::Local value, const String16& groupName, bool forceValueType, bool generatePreview) const -{ - V8FunctionCall function(m_context->inspector(), m_context->context(), v8Value(), "wrapObject"); - function.appendArgument(value); - function.appendArgument(groupName); - function.appendArgument(forceValueType); - function.appendArgument(generatePreview); - bool hadException = false; - v8::Local r = function.call(hadException); - if (hasInternalError(errorString, hadException || r.IsEmpty())) - return v8::MaybeLocal(); - return r; -} - -std::unique_ptr InjectedScript::wrapTable(v8::Local table, v8::Local columns) const -{ - v8::HandleScope handles(m_context->isolate()); - V8FunctionCall function(m_context->inspector(), m_context->context(), v8Value(), "wrapTable"); - function.appendArgument(table); - if (columns.IsEmpty()) - function.appendArgument(false); - else - function.appendArgument(columns); - bool hadException = false; - v8::Local r = function.call(hadException); - if (hadException) - return nullptr; - protocol::ErrorSupport errors; - return protocol::Runtime::RemoteObject::parse(toProtocolValue(m_context->context(), r).get(), &errors); -} - -bool InjectedScript::findObject(ErrorString* errorString, const RemoteObjectId& objectId, v8::Local* outObject) const -{ - *outObject = m_native->objectForId(objectId.id()); - if (outObject->IsEmpty()) - *errorString = "Could not find object with given id"; - return !outObject->IsEmpty(); -} - -String16 InjectedScript::objectGroupName(const RemoteObjectId& objectId) const -{ - return m_native->groupName(objectId.id()); -} - -void InjectedScript::releaseObjectGroup(const String16& objectGroup) -{ - m_native->releaseObjectGroup(objectGroup); - if (objectGroup == "console") - m_lastEvaluationResult.Reset(); -} - -void InjectedScript::setCustomObjectFormatterEnabled(bool enabled) -{ - v8::HandleScope handles(m_context->isolate()); - V8FunctionCall function(m_context->inspector(), m_context->context(), v8Value(), "setCustomObjectFormatterEnabled"); - function.appendArgument(enabled); - bool hadException = false; - function.call(hadException); - DCHECK(!hadException); -} - -v8::Local InjectedScript::v8Value() const -{ - return m_value.Get(m_context->isolate()); -} - -v8::Local InjectedScript::lastEvaluationResult() const -{ - if (m_lastEvaluationResult.IsEmpty()) - return v8::Undefined(m_context->isolate()); - return m_lastEvaluationResult.Get(m_context->isolate()); -} - -v8::MaybeLocal InjectedScript::resolveCallArgument(ErrorString* errorString, protocol::Runtime::CallArgument* callArgument) -{ - if (callArgument->hasObjectId()) { - std::unique_ptr remoteObjectId = RemoteObjectId::parse(errorString, callArgument->getObjectId("")); - if (!remoteObjectId) - return v8::MaybeLocal(); - if (remoteObjectId->contextId() != m_context->contextId()) { - *errorString = "Argument should belong to the same JavaScript world as target object"; - return v8::MaybeLocal(); - } - v8::Local object; - if (!findObject(errorString, *remoteObjectId, &object)) - return v8::MaybeLocal(); - return object; - } - if (callArgument->hasValue() || callArgument->hasUnserializableValue()) { - String16 value = callArgument->hasValue() ? - callArgument->getValue(nullptr)->toJSONString() : - "Number(\"" + callArgument->getUnserializableValue("") + "\")"; - v8::Local object; - if (!m_context->inspector()->compileAndRunInternalScript(m_context->context(), toV8String(m_context->isolate(), value)).ToLocal(&object)) { - *errorString = "Couldn't parse value object in call argument"; - return v8::MaybeLocal(); - } - return object; - } - return v8::Undefined(m_context->isolate()); -} - -std::unique_ptr InjectedScript::createExceptionDetails(ErrorString* errorString, const v8::TryCatch& tryCatch, const String16& objectGroup, bool generatePreview) -{ - if (!tryCatch.HasCaught()) - return nullptr; - v8::Local message = tryCatch.Message(); - v8::Local exception = tryCatch.Exception(); - String16 messageText = message.IsEmpty() ? String16() : toProtocolString(message->Get()); - std::unique_ptr exceptionDetails = protocol::Runtime::ExceptionDetails::create() - .setExceptionId(m_context->inspector()->nextExceptionId()) - .setText(exception.IsEmpty() ? messageText : String16("Uncaught")) - .setLineNumber(message.IsEmpty() ? 0 : message->GetLineNumber(m_context->context()).FromMaybe(1) - 1) - .setColumnNumber(message.IsEmpty() ? 0 : message->GetStartColumn(m_context->context()).FromMaybe(0)) - .build(); - if (!message.IsEmpty()) { - exceptionDetails->setScriptId(String16::fromInteger(message->GetScriptOrigin().ScriptID()->Value())); - v8::Local stackTrace = message->GetStackTrace(); - if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) - exceptionDetails->setStackTrace(m_context->inspector()->debugger()->createStackTrace(stackTrace)->buildInspectorObjectImpl()); - } - if (!exception.IsEmpty()) { - std::unique_ptr wrapped = wrapObject(errorString, exception, objectGroup, false /* forceValueType */, generatePreview && !exception->IsNativeError()); - if (!wrapped) - return nullptr; - exceptionDetails->setException(std::move(wrapped)); - } - return exceptionDetails; -} - -void InjectedScript::wrapEvaluateResult(ErrorString* errorString, v8::MaybeLocal maybeResultValue, const v8::TryCatch& tryCatch, const String16& objectGroup, bool returnByValue, bool generatePreview, std::unique_ptr* result, Maybe* exceptionDetails) -{ - v8::Local resultValue; - if (!tryCatch.HasCaught()) { - if (hasInternalError(errorString, !maybeResultValue.ToLocal(&resultValue))) - return; - std::unique_ptr remoteObject = wrapObject(errorString, resultValue, objectGroup, returnByValue, generatePreview); - if (!remoteObject) - return; - if (objectGroup == "console") - m_lastEvaluationResult.Reset(m_context->isolate(), resultValue); - *result = std::move(remoteObject); - } else { - v8::Local exception = tryCatch.Exception(); - std::unique_ptr remoteObject = wrapObject(errorString, exception, objectGroup, false, generatePreview && !exception->IsNativeError()); - if (!remoteObject) - return; - // We send exception in result for compatibility reasons, even though it's accessible through exceptionDetails.exception. - *result = std::move(remoteObject); - *exceptionDetails = createExceptionDetails(errorString, tryCatch, objectGroup, generatePreview); - } -} - -v8::Local InjectedScript::commandLineAPI() -{ - if (m_commandLineAPI.IsEmpty()) - m_commandLineAPI.Reset(m_context->isolate(), V8Console::createCommandLineAPI(m_context)); - return m_commandLineAPI.Get(m_context->isolate()); -} - -InjectedScript::Scope::Scope(ErrorString* errorString, V8InspectorImpl* inspector, int contextGroupId) - : m_errorString(errorString) - , m_inspector(inspector) - , m_contextGroupId(contextGroupId) - , m_injectedScript(nullptr) - , m_handleScope(inspector->isolate()) - , m_tryCatch(inspector->isolate()) - , m_ignoreExceptionsAndMuteConsole(false) - , m_previousPauseOnExceptionsState(V8Debugger::DontPauseOnExceptions) - , m_userGesture(false) -{ -} - -bool InjectedScript::Scope::initialize() -{ - cleanup(); - // TODO(dgozman): what if we reattach to the same context group during evaluate? Introduce a session id? - V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup(m_contextGroupId); - if (!session) { - *m_errorString = "Internal error"; - return false; - } - findInjectedScript(session); - if (!m_injectedScript) - return false; - m_context = m_injectedScript->context()->context(); - m_context->Enter(); - return true; -} - -bool InjectedScript::Scope::installCommandLineAPI() -{ - DCHECK(m_injectedScript && !m_context.IsEmpty() && !m_commandLineAPIScope.get()); - m_commandLineAPIScope.reset(new V8Console::CommandLineAPIScope(m_context, m_injectedScript->commandLineAPI(), m_context->Global())); - return true; -} - -void InjectedScript::Scope::ignoreExceptionsAndMuteConsole() -{ - DCHECK(!m_ignoreExceptionsAndMuteConsole); - m_ignoreExceptionsAndMuteConsole = true; - m_inspector->client()->muteMetrics(m_contextGroupId); - m_inspector->muteExceptions(m_contextGroupId); - m_previousPauseOnExceptionsState = setPauseOnExceptionsState(V8Debugger::DontPauseOnExceptions); -} - -V8Debugger::PauseOnExceptionsState InjectedScript::Scope::setPauseOnExceptionsState(V8Debugger::PauseOnExceptionsState newState) -{ - if (!m_inspector->debugger()->enabled()) - return newState; - V8Debugger::PauseOnExceptionsState presentState = m_inspector->debugger()->getPauseOnExceptionsState(); - if (presentState != newState) - m_inspector->debugger()->setPauseOnExceptionsState(newState); - return presentState; -} - -void InjectedScript::Scope::pretendUserGesture() -{ - DCHECK(!m_userGesture); - m_userGesture = true; - m_inspector->client()->beginUserGesture(); -} - -void InjectedScript::Scope::cleanup() -{ - m_commandLineAPIScope.reset(); - if (!m_context.IsEmpty()) { - m_context->Exit(); - m_context.Clear(); - } -} - -InjectedScript::Scope::~Scope() -{ - if (m_ignoreExceptionsAndMuteConsole) { - setPauseOnExceptionsState(m_previousPauseOnExceptionsState); - m_inspector->client()->unmuteMetrics(m_contextGroupId); - m_inspector->unmuteExceptions(m_contextGroupId); - } - if (m_userGesture) - m_inspector->client()->endUserGesture(); - cleanup(); -} - -InjectedScript::ContextScope::ContextScope(ErrorString* errorString, V8InspectorImpl* inspector, int contextGroupId, int executionContextId) - : InjectedScript::Scope(errorString, inspector, contextGroupId) - , m_executionContextId(executionContextId) -{ -} - -InjectedScript::ContextScope::~ContextScope() -{ -} - -void InjectedScript::ContextScope::findInjectedScript(V8InspectorSessionImpl* session) -{ - m_injectedScript = session->findInjectedScript(m_errorString, m_executionContextId); -} - -InjectedScript::ObjectScope::ObjectScope(ErrorString* errorString, V8InspectorImpl* inspector, int contextGroupId, const String16& remoteObjectId) - : InjectedScript::Scope(errorString, inspector, contextGroupId) - , m_remoteObjectId(remoteObjectId) -{ -} - -InjectedScript::ObjectScope::~ObjectScope() -{ -} - -void InjectedScript::ObjectScope::findInjectedScript(V8InspectorSessionImpl* session) -{ - std::unique_ptr remoteId = RemoteObjectId::parse(m_errorString, m_remoteObjectId); - if (!remoteId) - return; - InjectedScript* injectedScript = session->findInjectedScript(m_errorString, remoteId.get()); - if (!injectedScript) - return; - m_objectGroupName = injectedScript->objectGroupName(*remoteId); - if (!injectedScript->findObject(m_errorString, *remoteId, &m_object)) - return; - m_injectedScript = injectedScript; -} - -InjectedScript::CallFrameScope::CallFrameScope(ErrorString* errorString, V8InspectorImpl* inspector, int contextGroupId, const String16& remoteObjectId) - : InjectedScript::Scope(errorString, inspector, contextGroupId) - , m_remoteCallFrameId(remoteObjectId) -{ -} - -InjectedScript::CallFrameScope::~CallFrameScope() -{ -} - -void InjectedScript::CallFrameScope::findInjectedScript(V8InspectorSessionImpl* session) -{ - std::unique_ptr remoteId = RemoteCallFrameId::parse(m_errorString, m_remoteCallFrameId); - if (!remoteId) - return; - m_frameOrdinal = static_cast(remoteId->frameOrdinal()); - m_injectedScript = session->findInjectedScript(m_errorString, remoteId.get()); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScript.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScript.h deleted file mode 100644 index 9c674d313eb629..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScript.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#ifndef InjectedScript_h -#define InjectedScript_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/InjectedScriptNative.h" -#include "platform/v8_inspector/InspectedContext.h" -#include "platform/v8_inspector/V8Console.h" -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/protocol/Runtime.h" - -#include - -namespace v8_inspector { - -class RemoteObjectId; -class V8FunctionCall; -class V8InspectorImpl; -class V8InspectorSessionImpl; - -namespace protocol = blink::protocol; -using blink::protocol::Maybe; - -class InjectedScript final { - PROTOCOL_DISALLOW_COPY(InjectedScript); -public: - static std::unique_ptr create(InspectedContext*); - ~InjectedScript(); - - InspectedContext* context() const { return m_context; } - - void getProperties(ErrorString*, v8::Local, const String16& groupName, bool ownProperties, bool accessorPropertiesOnly, bool generatePreview, std::unique_ptr>* result, Maybe*); - void releaseObject(const String16& objectId); - - std::unique_ptr wrapObject(ErrorString*, v8::Local, const String16& groupName, bool forceValueType = false, bool generatePreview = false) const; - bool wrapObjectProperty(ErrorString*, v8::Local, v8::Local key, const String16& groupName, bool forceValueType = false, bool generatePreview = false) const; - bool wrapPropertyInArray(ErrorString*, v8::Local, v8::Local property, const String16& groupName, bool forceValueType = false, bool generatePreview = false) const; - bool wrapObjectsInArray(ErrorString*, v8::Local, const String16& groupName, bool forceValueType = false, bool generatePreview = false) const; - std::unique_ptr wrapTable(v8::Local table, v8::Local columns) const; - - bool findObject(ErrorString*, const RemoteObjectId&, v8::Local*) const; - String16 objectGroupName(const RemoteObjectId&) const; - void releaseObjectGroup(const String16&); - void setCustomObjectFormatterEnabled(bool); - v8::MaybeLocal resolveCallArgument(ErrorString*, protocol::Runtime::CallArgument*); - - std::unique_ptr createExceptionDetails(ErrorString*, const v8::TryCatch&, const String16& groupName, bool generatePreview); - void wrapEvaluateResult(ErrorString*, - v8::MaybeLocal maybeResultValue, - const v8::TryCatch&, - const String16& objectGroup, - bool returnByValue, - bool generatePreview, - std::unique_ptr* result, - Maybe*); - v8::Local lastEvaluationResult() const; - - class Scope { - public: - bool initialize(); - bool installCommandLineAPI(); - void ignoreExceptionsAndMuteConsole(); - void pretendUserGesture(); - v8::Local context() const { return m_context; } - InjectedScript* injectedScript() const { return m_injectedScript; } - const v8::TryCatch& tryCatch() const { return m_tryCatch; } - - protected: - Scope(ErrorString*, V8InspectorImpl*, int contextGroupId); - ~Scope(); - virtual void findInjectedScript(V8InspectorSessionImpl*) = 0; - - ErrorString* m_errorString; - V8InspectorImpl* m_inspector; - int m_contextGroupId; - InjectedScript* m_injectedScript; - - private: - void cleanup(); - V8Debugger::PauseOnExceptionsState setPauseOnExceptionsState(V8Debugger::PauseOnExceptionsState); - - v8::HandleScope m_handleScope; - v8::TryCatch m_tryCatch; - v8::Local m_context; - std::unique_ptr m_commandLineAPIScope; - bool m_ignoreExceptionsAndMuteConsole; - V8Debugger::PauseOnExceptionsState m_previousPauseOnExceptionsState; - bool m_userGesture; - }; - - class ContextScope: public Scope { - PROTOCOL_DISALLOW_COPY(ContextScope); - public: - ContextScope(ErrorString*, V8InspectorImpl*, int contextGroupId, int executionContextId); - ~ContextScope(); - private: - void findInjectedScript(V8InspectorSessionImpl*) override; - int m_executionContextId; - }; - - class ObjectScope: public Scope { - PROTOCOL_DISALLOW_COPY(ObjectScope); - public: - ObjectScope(ErrorString*, V8InspectorImpl*, int contextGroupId, const String16& remoteObjectId); - ~ObjectScope(); - const String16& objectGroupName() const { return m_objectGroupName; } - v8::Local object() const { return m_object; } - private: - void findInjectedScript(V8InspectorSessionImpl*) override; - String16 m_remoteObjectId; - String16 m_objectGroupName; - v8::Local m_object; - }; - - class CallFrameScope: public Scope { - PROTOCOL_DISALLOW_COPY(CallFrameScope); - public: - CallFrameScope(ErrorString*, V8InspectorImpl*, int contextGroupId, const String16& remoteCallFrameId); - ~CallFrameScope(); - size_t frameOrdinal() const { return m_frameOrdinal; } - private: - void findInjectedScript(V8InspectorSessionImpl*) override; - String16 m_remoteCallFrameId; - size_t m_frameOrdinal; - }; - -private: - InjectedScript(InspectedContext*, v8::Local, std::unique_ptr); - v8::Local v8Value() const; - v8::MaybeLocal wrapValue(ErrorString*, v8::Local, const String16& groupName, bool forceValueType, bool generatePreview) const; - v8::Local commandLineAPI(); - - InspectedContext* m_context; - v8::Global m_value; - v8::Global m_lastEvaluationResult; - std::unique_ptr m_native; - v8::Global m_commandLineAPI; -}; - -} // namespace v8_inspector - -#endif diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptNative.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptNative.cpp deleted file mode 100644 index 44f1c8b97d9182..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptNative.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2015 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 "platform/v8_inspector/InjectedScriptNative.h" - -namespace v8_inspector { - -InjectedScriptNative::InjectedScriptNative(v8::Isolate* isolate) - : m_lastBoundObjectId(1) - , m_isolate(isolate) -{ -} - -static const char privateKeyName[] = "v8-inspector#injectedScript"; - -InjectedScriptNative::~InjectedScriptNative() { } - -void InjectedScriptNative::setOnInjectedScriptHost(v8::Local injectedScriptHost) -{ - v8::HandleScope handleScope(m_isolate); - v8::Local external = v8::External::New(m_isolate, this); - v8::Local privateKey = v8::Private::ForApi(m_isolate, v8::String::NewFromUtf8(m_isolate, privateKeyName, v8::NewStringType::kInternalized).ToLocalChecked()); - injectedScriptHost->SetPrivate(m_isolate->GetCurrentContext(), privateKey, external); -} - -InjectedScriptNative* InjectedScriptNative::fromInjectedScriptHost(v8::Local injectedScriptObject) -{ - v8::Isolate* isolate = injectedScriptObject->GetIsolate(); - v8::HandleScope handleScope(isolate); - v8::Local context = isolate->GetCurrentContext(); - v8::Local privateKey = v8::Private::ForApi(isolate, v8::String::NewFromUtf8(isolate, privateKeyName, v8::NewStringType::kInternalized).ToLocalChecked()); - v8::Local value = injectedScriptObject->GetPrivate(context, privateKey).ToLocalChecked(); - DCHECK(value->IsExternal()); - v8::Local external = value.As(); - return static_cast(external->Value()); -} - -int InjectedScriptNative::bind(v8::Local value, const String16& groupName) -{ - if (m_lastBoundObjectId <= 0) - m_lastBoundObjectId = 1; - int id = m_lastBoundObjectId++; - m_idToWrappedObject[id] = wrapUnique(new v8::Global(m_isolate, value)); - addObjectToGroup(id, groupName); - return id; -} - -void InjectedScriptNative::unbind(int id) -{ - m_idToWrappedObject.erase(id); - m_idToObjectGroupName.erase(id); -} - -v8::Local InjectedScriptNative::objectForId(int id) -{ - auto iter = m_idToWrappedObject.find(id); - return iter != m_idToWrappedObject.end() ? iter->second->Get(m_isolate) : v8::Local(); -} - -void InjectedScriptNative::addObjectToGroup(int objectId, const String16& groupName) -{ - if (groupName.isEmpty()) - return; - if (objectId <= 0) - return; - m_idToObjectGroupName[objectId] = groupName; - m_nameToObjectGroup[groupName].push_back(objectId); // Creates an empty vector if key is not there -} - -void InjectedScriptNative::releaseObjectGroup(const String16& groupName) -{ - if (groupName.isEmpty()) - return; - NameToObjectGroup::iterator groupIt = m_nameToObjectGroup.find(groupName); - if (groupIt == m_nameToObjectGroup.end()) - return; - for (int id : groupIt->second) - unbind(id); - m_nameToObjectGroup.erase(groupIt); -} - -String16 InjectedScriptNative::groupName(int objectId) const -{ - if (objectId <= 0) - return String16(); - IdToObjectGroupName::const_iterator iterator = m_idToObjectGroupName.find(objectId); - return iterator != m_idToObjectGroupName.end() ? iterator->second : String16(); -} - -} // namespace v8_inspector - diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptNative.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptNative.h deleted file mode 100644 index 036939366e0b50..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InjectedScriptNative.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2015 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 InjectedScriptNative_h -#define InjectedScriptNative_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include - -#include - -namespace v8_inspector { - -namespace protocol = blink::protocol; - -class InjectedScriptNative final { -public: - explicit InjectedScriptNative(v8::Isolate*); - ~InjectedScriptNative(); - - void setOnInjectedScriptHost(v8::Local); - static InjectedScriptNative* fromInjectedScriptHost(v8::Local); - - int bind(v8::Local, const String16& groupName); - void unbind(int id); - v8::Local objectForId(int id); - - void releaseObjectGroup(const String16& groupName); - String16 groupName(int objectId) const; - -private: - void addObjectToGroup(int objectId, const String16& groupName); - - int m_lastBoundObjectId; - v8::Isolate* m_isolate; - protocol::HashMap>> m_idToWrappedObject; - typedef protocol::HashMap IdToObjectGroupName; - IdToObjectGroupName m_idToObjectGroupName; - typedef protocol::HashMap> NameToObjectGroup; - NameToObjectGroup m_nameToObjectGroup; -}; - -} // namespace v8_inspector - -#endif diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InspectedContext.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InspectedContext.cpp deleted file mode 100644 index f2bf9527696a53..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InspectedContext.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// 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 "platform/v8_inspector/InspectedContext.h" - -#include "platform/v8_inspector/InjectedScript.h" -#include "platform/v8_inspector/V8Console.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8ContextInfo.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -namespace v8_inspector { - -void InspectedContext::weakCallback(const v8::WeakCallbackInfo& data) -{ - InspectedContext* context = data.GetParameter(); - if (!context->m_context.IsEmpty()) { - context->m_context.Reset(); - data.SetSecondPassCallback(&InspectedContext::weakCallback); - } else { - context->m_inspector->discardInspectedContext(context->m_contextGroupId, context->m_contextId); - } -} - -void InspectedContext::consoleWeakCallback(const v8::WeakCallbackInfo& data) -{ - data.GetParameter()->m_console.Reset(); -} - -InspectedContext::InspectedContext(V8InspectorImpl* inspector, const V8ContextInfo& info, int contextId) - : m_inspector(inspector) - , m_context(info.context->GetIsolate(), info.context) - , m_contextId(contextId) - , m_contextGroupId(info.contextGroupId) - , m_origin(info.origin) - , m_humanReadableName(info.humanReadableName) - , m_auxData(info.auxData) - , m_reported(false) -{ - m_context.SetWeak(this, &InspectedContext::weakCallback, v8::WeakCallbackType::kParameter); - - v8::Isolate* isolate = m_inspector->isolate(); - v8::Local global = info.context->Global(); - v8::Local console = V8Console::createConsole(this, info.hasMemoryOnConsole); - if (!global->Set(info.context, toV8StringInternalized(isolate, "console"), console).FromMaybe(false)) - return; - m_console.Reset(isolate, console); - m_console.SetWeak(this, &InspectedContext::consoleWeakCallback, v8::WeakCallbackType::kParameter); -} - -InspectedContext::~InspectedContext() -{ - if (!m_context.IsEmpty() && !m_console.IsEmpty()) { - v8::HandleScope scope(isolate()); - V8Console::clearInspectedContextIfNeeded(context(), m_console.Get(isolate())); - } -} - -v8::Local InspectedContext::context() const -{ - return m_context.Get(isolate()); -} - -v8::Isolate* InspectedContext::isolate() const -{ - return m_inspector->isolate(); -} - -void InspectedContext::createInjectedScript() -{ - DCHECK(!m_injectedScript); - m_injectedScript = InjectedScript::create(this); -} - -void InspectedContext::discardInjectedScript() -{ - m_injectedScript.reset(); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InspectedContext.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InspectedContext.h deleted file mode 100644 index fcb8af6c01fc75..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/InspectedContext.h +++ /dev/null @@ -1,62 +0,0 @@ -// 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 InspectedContext_h -#define InspectedContext_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include - -namespace v8_inspector { - -class InjectedScript; -class InjectedScriptHost; -class V8ContextInfo; -class V8InspectorImpl; - -namespace protocol = blink::protocol; - -class InspectedContext { - PROTOCOL_DISALLOW_COPY(InspectedContext); -public: - ~InspectedContext(); - - v8::Local context() const; - int contextId() const { return m_contextId; } - int contextGroupId() const { return m_contextGroupId; } - String16 origin() const { return m_origin; } - String16 humanReadableName() const { return m_humanReadableName; } - String16 auxData() const { return m_auxData; } - - bool isReported() const { return m_reported; } - void setReported(bool reported) { m_reported = reported; } - - v8::Isolate* isolate() const; - V8InspectorImpl* inspector() const { return m_inspector; } - - InjectedScript* getInjectedScript() { return m_injectedScript.get(); } - void createInjectedScript(); - void discardInjectedScript(); - -private: - friend class V8InspectorImpl; - InspectedContext(V8InspectorImpl*, const V8ContextInfo&, int contextId); - static void weakCallback(const v8::WeakCallbackInfo&); - static void consoleWeakCallback(const v8::WeakCallbackInfo&); - - V8InspectorImpl* m_inspector; - v8::Global m_context; - int m_contextId; - int m_contextGroupId; - const String16 m_origin; - const String16 m_humanReadableName; - const String16 m_auxData; - bool m_reported; - std::unique_ptr m_injectedScript; - v8::Global m_console; -}; - -} // namespace v8_inspector - -#endif diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.cpp deleted file mode 100644 index 573b14a9e8c20b..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/JavaScriptCallFrame.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2010, 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. - */ - -#include "platform/v8_inspector/JavaScriptCallFrame.h" - -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8StringUtil.h" - -#include - -namespace v8_inspector { - -JavaScriptCallFrame::JavaScriptCallFrame(v8::Local debuggerContext, v8::Local callFrame) - : m_isolate(debuggerContext->GetIsolate()) - , m_debuggerContext(m_isolate, debuggerContext) - , m_callFrame(m_isolate, callFrame) -{ -} - -JavaScriptCallFrame::~JavaScriptCallFrame() -{ -} - -int JavaScriptCallFrame::callV8FunctionReturnInt(const char* name) const -{ - v8::HandleScope handleScope(m_isolate); - v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local context = v8::Local::New(m_isolate, m_debuggerContext); - v8::Local callFrame = v8::Local::New(m_isolate, m_callFrame); - v8::Local func = v8::Local::Cast(callFrame->Get(toV8StringInternalized(m_isolate, name))); - v8::Local result; - if (!func->Call(context, callFrame, 0, nullptr).ToLocal(&result) || !result->IsInt32()) - return 0; - return result.As()->Value(); -} - -int JavaScriptCallFrame::sourceID() const -{ - return callV8FunctionReturnInt("sourceID"); -} - -int JavaScriptCallFrame::line() const -{ - return callV8FunctionReturnInt("line"); -} - -int JavaScriptCallFrame::column() const -{ - return callV8FunctionReturnInt("column"); -} - -int JavaScriptCallFrame::contextId() const -{ - return callV8FunctionReturnInt("contextId"); -} - -bool JavaScriptCallFrame::isAtReturn() const -{ - v8::HandleScope handleScope(m_isolate); - v8::Local result = v8::Local::New(m_isolate, m_callFrame)->Get(toV8StringInternalized(m_isolate, "isAtReturn")); - if (result.IsEmpty() || !result->IsBoolean()) - return false; - return result->BooleanValue(); -} - -v8::Local JavaScriptCallFrame::details() const -{ - v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local callFrame = v8::Local::New(m_isolate, m_callFrame); - v8::Local func = v8::Local::Cast(callFrame->Get(toV8StringInternalized(m_isolate, "details"))); - return v8::Local::Cast(func->Call(m_debuggerContext.Get(m_isolate), callFrame, 0, nullptr).ToLocalChecked()); -} - -v8::MaybeLocal JavaScriptCallFrame::evaluate(v8::Local expression) -{ - v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kRunMicrotasks); - v8::Local callFrame = v8::Local::New(m_isolate, m_callFrame); - v8::Local evalFunction = v8::Local::Cast(callFrame->Get(toV8StringInternalized(m_isolate, "evaluate"))); - return evalFunction->Call(m_debuggerContext.Get(m_isolate), callFrame, 1, &expression); -} - -v8::MaybeLocal JavaScriptCallFrame::restart() -{ - v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local callFrame = v8::Local::New(m_isolate, m_callFrame); - v8::Local restartFunction = v8::Local::Cast(callFrame->Get(toV8StringInternalized(m_isolate, "restart"))); - v8::Debug::SetLiveEditEnabled(m_isolate, true); - v8::MaybeLocal result = restartFunction->Call(m_debuggerContext.Get(m_isolate), callFrame, 0, nullptr); - v8::Debug::SetLiveEditEnabled(m_isolate, false); - return result; -} - -v8::MaybeLocal JavaScriptCallFrame::setVariableValue(int scopeNumber, v8::Local variableName, v8::Local newValue) -{ - v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local callFrame = v8::Local::New(m_isolate, m_callFrame); - v8::Local setVariableValueFunction = v8::Local::Cast(callFrame->Get(toV8StringInternalized(m_isolate, "setVariableValue"))); - v8::Local argv[] = { - v8::Local(v8::Integer::New(m_isolate, scopeNumber)), - variableName, - newValue - }; - return setVariableValueFunction->Call(m_debuggerContext.Get(m_isolate), callFrame, PROTOCOL_ARRAY_LENGTH(argv), argv); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/PlatformSTL.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/PlatformSTL.h deleted file mode 100644 index bfba971e698add..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/PlatformSTL.h +++ /dev/null @@ -1,317 +0,0 @@ -// 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 PlatformSTL_h -#define PlatformSTL_h - -#include - -#define PLATFORM_EXPORT -#ifndef CHECK -#define CHECK(condition) ((void) 0) -#endif -#define DCHECK(condition) ((void) 0) -#define NOTREACHED() -#define DCHECK_EQ(i, j) DCHECK(i == j) -#define DCHECK_GE(i, j) DCHECK(i >= j) -#define DCHECK_LT(i, j) DCHECK(i < j) -#define DCHECK_GT(i, j) DCHECK(i > j) -template -inline void USE(T) { } - -#define DEFINE_STATIC_LOCAL(type, name, arguments) \ - static type name; - -#if defined(__APPLE__) && !defined(_LIBCPP_VERSION) - -namespace std { - -template -struct is_convertible { -private: - struct True_ { - char x[2]; - }; - struct False_ { - }; - - static True_ helper(T2 const &); - static False_ helper(...); - -public: - static bool const value = ( - sizeof(True_) == sizeof(is_convertible::helper(T1())) - ); -}; - -template -struct enable_if { -}; - -template -struct enable_if { - typedef T type; -}; - -template -struct remove_extent { - typedef T type; -}; - -template -struct remove_extent { - typedef T type; -}; - -template -struct remove_extent { - typedef T type; -}; - -typedef decltype(nullptr) nullptr_t; - -template -struct integral_constant { - static constexpr T value = v; - typedef T value_type; - typedef integral_constant type; - constexpr operator value_type() const noexcept { return value; } - constexpr value_type operator()() const noexcept { return value; } -}; - -typedef integral_constant true_type; -typedef integral_constant false_type; - -template -struct is_array : false_type {}; - -template -struct is_array : true_type {}; - -template -struct is_array : true_type {}; - -template -struct OwnedPtrDeleter { - static void deletePtr(T* ptr) - { - static_assert(sizeof(T) > 0, "type must be complete"); - delete ptr; - } -}; - -template -struct OwnedPtrDeleter { - static void deletePtr(T* ptr) - { - static_assert(sizeof(T) > 0, "type must be complete"); - delete[] ptr; - } -}; - -template -struct OwnedPtrDeleter { - static_assert(sizeof(T) < 0, "do not use array with size as type"); -}; - -template class unique_ptr { -public: - typedef typename remove_extent::type ValueType; - typedef ValueType* PtrType; - - unique_ptr() : m_ptr(nullptr) {} - unique_ptr(std::nullptr_t) : m_ptr(nullptr) {} - unique_ptr(const unique_ptr&); - unique_ptr(unique_ptr&&); - template ::value>::type> unique_ptr(unique_ptr&&); - - ~unique_ptr() - { - OwnedPtrDeleter::deletePtr(m_ptr); - m_ptr = nullptr; - } - - PtrType get() const { return m_ptr; } - - void reset(PtrType = nullptr); - PtrType release() - { - return this->internalRelease(); - } - - ValueType& operator*() const { DCHECK(m_ptr); return *m_ptr; } - PtrType operator->() const { DCHECK(m_ptr); return m_ptr; } - - ValueType& operator[](std::ptrdiff_t i) const; - - bool operator!() const { return !m_ptr; } - explicit operator bool() const { return m_ptr; } - - unique_ptr& operator=(std::nullptr_t) { reset(); return *this; } - - unique_ptr& operator=(const unique_ptr&); - unique_ptr& operator=(unique_ptr&&); - template unique_ptr& operator=(unique_ptr&&); - - void swap(unique_ptr& o) { std::swap(m_ptr, o.m_ptr); } - - static T* hashTableDeletedValue() { return reinterpret_cast(-1); } - - explicit unique_ptr(PtrType ptr) : m_ptr(ptr) {} // NOLINT - -private: - PtrType internalRelease() const - { - PtrType ptr = m_ptr; - m_ptr = nullptr; - return ptr; - } - - // We should never have two unique_ptrs for the same underlying object - // (otherwise we'll get double-destruction), so these equality operators - // should never be needed. - template bool operator==(const unique_ptr&) const - { - static_assert(!sizeof(U*), "unique_ptrs should never be equal"); - return false; - } - template bool operator!=(const unique_ptr&) const - { - static_assert(!sizeof(U*), "unique_ptrs should never be equal"); - return false; - } - - mutable PtrType m_ptr; -}; - - -template inline void unique_ptr::reset(PtrType ptr) -{ - PtrType p = m_ptr; - m_ptr = ptr; - DCHECK(!p || m_ptr != p); - OwnedPtrDeleter::deletePtr(p); -} - -template inline typename unique_ptr::ValueType& unique_ptr::operator[](std::ptrdiff_t i) const -{ - static_assert(is_array::value, "elements access is possible for arrays only"); - DCHECK(m_ptr); - DCHECK_GE(i, 0); - return m_ptr[i]; -} - -template inline unique_ptr::unique_ptr(const unique_ptr& o) // NOLINT - : m_ptr(o.internalRelease()) -{ -} - -template inline unique_ptr::unique_ptr(unique_ptr&& o) // NOLINT - : m_ptr(o.internalRelease()) -{ -} - -template -template inline unique_ptr::unique_ptr(unique_ptr&& o) - : m_ptr(o.release()) -{ - static_assert(!is_array::value, "pointers to array must never be converted"); -} - -template inline unique_ptr& unique_ptr::operator=(const unique_ptr& o) -{ - reset(o.internalRelease()); - return *this; -} - -template inline unique_ptr& unique_ptr::operator=(unique_ptr&& o) -{ - reset(o.internalRelease()); - return *this; -} - -template -template inline unique_ptr& unique_ptr::operator=(unique_ptr&& o) -{ - static_assert(!is_array::value, "pointers to array must never be converted"); - PtrType ptr = m_ptr; - m_ptr = o.release(); - DCHECK(!ptr || m_ptr != ptr); - OwnedPtrDeleter::deletePtr(ptr); - - return *this; -} - -template inline void swap(unique_ptr& a, unique_ptr& b) -{ - a.swap(b); -} - -template inline bool operator==(const unique_ptr& a, U* b) -{ - return a.get() == b; -} - -template inline bool operator==(T* a, const unique_ptr& b) -{ - return a == b.get(); -} - -template inline bool operator!=(const unique_ptr& a, U* b) -{ - return a.get() != b; -} - -template inline bool operator!=(T* a, const unique_ptr& b) -{ - return a != b.get(); -} - -template inline typename unique_ptr::PtrType getPtr(const unique_ptr& p) -{ - return p.get(); -} - -template -unique_ptr move(unique_ptr& ptr) -{ - return unique_ptr(ptr.release()); -} - -} - -#endif // defined(__APPLE__) && !defined(_LIBCPP_VERSION) - -template -std::unique_ptr wrapUnique(T* ptr) -{ - return std::unique_ptr(ptr); -} - -// emulate snprintf() on windows, _snprintf() doesn't zero-terminate the buffer -// on overflow... -// VS 2015 added a standard conform snprintf -#if defined(_WIN32) && defined( _MSC_VER ) && (_MSC_VER < 1900) -#include -namespace std { - -inline static int snprintf(char *buffer, size_t n, const char *format, ...) -{ - va_list argp; - va_start(argp, format); - int ret = _vscprintf(format, argp); - vsnprintf_s(buffer, n, _TRUNCATE, format, argp); - va_end(argp); - return ret; -} -} // namespace std -#endif // (_WIN32) && defined( _MSC_VER ) && (_MSC_VER < 1900) - -#ifdef __sun -namespace std { -using ::snprintf; -} // namespace std -#endif // __sun - -#endif // PlatformSTL_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/PlatformWTF.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/PlatformWTF.h deleted file mode 100644 index 3cd659e6881e54..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/PlatformWTF.h +++ /dev/null @@ -1,14 +0,0 @@ -// 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 PlatformWTF_h -#define PlatformWTF_h - -#include "platform/PlatformExport.h" -#include "wtf/Assertions.h" -#include "wtf/PtrUtil.h" - -#include - -#endif // PlatformWTF_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/RemoteObjectId.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/RemoteObjectId.cpp deleted file mode 100644 index ccdd5bef101264..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/RemoteObjectId.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2015 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 "platform/v8_inspector/RemoteObjectId.h" - -namespace v8_inspector { - -RemoteObjectIdBase::RemoteObjectIdBase() : m_injectedScriptId(0) { } - -std::unique_ptr RemoteObjectIdBase::parseInjectedScriptId(const String16& objectId) -{ - std::unique_ptr parsedValue = protocol::parseJSON(objectId); - if (!parsedValue || parsedValue->type() != protocol::Value::TypeObject) - return nullptr; - - std::unique_ptr parsedObjectId(protocol::DictionaryValue::cast(parsedValue.release())); - bool success = parsedObjectId->getInteger("injectedScriptId", &m_injectedScriptId); - if (success) - return parsedObjectId; - return nullptr; -} - -RemoteObjectId::RemoteObjectId() : RemoteObjectIdBase(), m_id(0) { } - -std::unique_ptr RemoteObjectId::parse(ErrorString* errorString, const String16& objectId) -{ - std::unique_ptr result(new RemoteObjectId()); - std::unique_ptr parsedObjectId = result->parseInjectedScriptId(objectId); - if (!parsedObjectId) { - *errorString = "Invalid remote object id"; - return nullptr; - } - - bool success = parsedObjectId->getInteger("id", &result->m_id); - if (!success) { - *errorString = "Invalid remote object id"; - return nullptr; - } - return result; -} - -RemoteCallFrameId::RemoteCallFrameId() : RemoteObjectIdBase(), m_frameOrdinal(0) { } - -std::unique_ptr RemoteCallFrameId::parse(ErrorString* errorString, const String16& objectId) -{ - std::unique_ptr result(new RemoteCallFrameId()); - std::unique_ptr parsedObjectId = result->parseInjectedScriptId(objectId); - if (!parsedObjectId) { - *errorString = "Invalid call frame id"; - return nullptr; - } - - bool success = parsedObjectId->getInteger("ordinal", &result->m_frameOrdinal); - if (!success) { - *errorString = "Invalid call frame id"; - return nullptr; - } - - return result; -} - -String16 RemoteCallFrameId::serialize(int injectedScriptId, int frameOrdinal) -{ - return "{\"ordinal\":" + String16::fromInteger(frameOrdinal) + ",\"injectedScriptId\":" + String16::fromInteger(injectedScriptId) + "}"; -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/RemoteObjectId.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/RemoteObjectId.h deleted file mode 100644 index 128326ab4bcd0e..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/RemoteObjectId.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2015 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 RemoteObjectId_h -#define RemoteObjectId_h - -#include "platform/inspector_protocol/InspectorProtocol.h" - -namespace v8_inspector { - -namespace protocol = blink::protocol; - -class RemoteObjectIdBase { -public: - int contextId() const { return m_injectedScriptId; } - -protected: - RemoteObjectIdBase(); - ~RemoteObjectIdBase() { } - - std::unique_ptr parseInjectedScriptId(const String16&); - - int m_injectedScriptId; -}; - -class RemoteObjectId final : public RemoteObjectIdBase { -public: - static std::unique_ptr parse(ErrorString*, const String16&); - ~RemoteObjectId() { } - int id() const { return m_id; } - -private: - RemoteObjectId(); - - int m_id; -}; - -class RemoteCallFrameId final : public RemoteObjectIdBase { -public: - static std::unique_ptr parse(ErrorString*, const String16&); - ~RemoteCallFrameId() { } - - int frameOrdinal() const { return m_frameOrdinal; } - - static String16 serialize(int injectedScriptId, int frameOrdinal); -private: - RemoteCallFrameId(); - - int m_frameOrdinal; -}; - -} // namespace v8_inspector - -#endif // !defined(RemoteObjectId_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16STL.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16STL.cpp deleted file mode 100644 index 990932d47f18c6..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16STL.cpp +++ /dev/null @@ -1,405 +0,0 @@ -// 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 "platform/inspector_protocol/InspectorProtocol.h" - -#include -#include -#include -#include - -namespace blink { -namespace protocol { - -const UChar replacementCharacter = 0xFFFD; -using UChar32 = uint32_t; - -inline int inlineUTF8SequenceLengthNonASCII(char b0) -{ - if ((b0 & 0xC0) != 0xC0) - return 0; - if ((b0 & 0xE0) == 0xC0) - return 2; - if ((b0 & 0xF0) == 0xE0) - return 3; - if ((b0 & 0xF8) == 0xF0) - return 4; - return 0; -} - -inline int inlineUTF8SequenceLength(char b0) -{ - return String16::isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); -} - -// Once the bits are split out into bytes of UTF-8, this is a mask OR-ed -// into the first byte, depending on how many bytes follow. There are -// as many entries in this table as there are UTF-8 sequence types. -// (I.e., one byte sequence, two byte... etc.). Remember that sequences -// for *legal* UTF-8 will be 4 or fewer bytes total. -static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -typedef enum { - conversionOK, // conversion successful - sourceExhausted, // partial character in source, but hit end - targetExhausted, // insuff. room in target for conversion - sourceIllegal // source sequence is illegal/malformed -} ConversionResult; - -ConversionResult convertUTF16ToUTF8( - const UChar** sourceStart, const UChar* sourceEnd, - char** targetStart, char* targetEnd, bool strict) -{ - ConversionResult result = conversionOK; - const UChar* source = *sourceStart; - char* target = *targetStart; - while (source < sourceEnd) { - UChar32 ch; - unsigned short bytesToWrite = 0; - const UChar32 byteMask = 0xBF; - const UChar32 byteMark = 0x80; - const UChar* oldSource = source; // In case we have to back up because of target overflow. - ch = static_cast(*source++); - // If we have a surrogate pair, convert to UChar32 first. - if (ch >= 0xD800 && ch <= 0xDBFF) { - // If the 16 bits following the high surrogate are in the source buffer... - if (source < sourceEnd) { - UChar32 ch2 = static_cast(*source); - // If it's a low surrogate, convert to UChar32. - if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) { - ch = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x0010000; - ++source; - } else if (strict) { // it's an unpaired high surrogate - --source; // return to the illegal value itself - result = sourceIllegal; - break; - } - } else { // We don't have the 16 bits following the high surrogate. - --source; // return to the high surrogate - result = sourceExhausted; - break; - } - } else if (strict) { - // UTF-16 surrogate values are illegal in UTF-32 - if (ch >= 0xDC00 && ch <= 0xDFFF) { - --source; // return to the illegal value itself - result = sourceIllegal; - break; - } - } - // Figure out how many bytes the result will require - if (ch < (UChar32)0x80) { - bytesToWrite = 1; - } else if (ch < (UChar32)0x800) { - bytesToWrite = 2; - } else if (ch < (UChar32)0x10000) { - bytesToWrite = 3; - } else if (ch < (UChar32)0x110000) { - bytesToWrite = 4; - } else { - bytesToWrite = 3; - ch = replacementCharacter; - } - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; // Back up source pointer! - target -= bytesToWrite; - result = targetExhausted; - break; - } - switch (bytesToWrite) { // note: everything falls through. - case 4: - *--target = (char)((ch | byteMark) & byteMask); - ch >>= 6; - case 3: - *--target = (char)((ch | byteMark) & byteMask); - ch >>= 6; - case 2: - *--target = (char)((ch | byteMark) & byteMask); - ch >>= 6; - case 1: - *--target = (char)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/** - * Is this code point a BMP code point (U+0000..U+ffff)? - * @param c 32-bit code point - * @return TRUE or FALSE - * @stable ICU 2.8 - */ -#define U_IS_BMP(c) ((uint32_t)(c) <= 0xffff) - -/** - * Is this code point a supplementary code point (U+10000..U+10ffff)? - * @param c 32-bit code point - * @return TRUE or FALSE - * @stable ICU 2.8 - */ -#define U_IS_SUPPLEMENTARY(c) ((uint32_t)((c) - 0x10000) <= 0xfffff) - -/** - * Is this code point a surrogate (U+d800..U+dfff)? - * @param c 32-bit code point - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define U_IS_SURROGATE(c) (((c) & 0xfffff800) == 0xd800) - -/** - * Get the lead surrogate (0xd800..0xdbff) for a - * supplementary code point (0x10000..0x10ffff). - * @param supplementary 32-bit code point (U+10000..U+10ffff) - * @return lead surrogate (U+d800..U+dbff) for supplementary - * @stable ICU 2.4 - */ -#define U16_LEAD(supplementary) (UChar)(((supplementary) >> 10) + 0xd7c0) - -/** - * Get the trail surrogate (0xdc00..0xdfff) for a - * supplementary code point (0x10000..0x10ffff). - * @param supplementary 32-bit code point (U+10000..U+10ffff) - * @return trail surrogate (U+dc00..U+dfff) for supplementary - * @stable ICU 2.4 - */ -#define U16_TRAIL(supplementary) (UChar)(((supplementary) & 0x3ff) | 0xdc00) - -// This must be called with the length pre-determined by the first byte. -// If presented with a length > 4, this returns false. The Unicode -// definition of UTF-8 goes up to 4-byte sequences. -static bool isLegalUTF8(const unsigned char* source, int length) -{ - unsigned char a; - const unsigned char* srcptr = source + length; - switch (length) { - default: - return false; - // Everything else falls through when "true"... - case 4: - if ((a = (*--srcptr)) < 0x80 || a > 0xBF) - return false; - case 3: - if ((a = (*--srcptr)) < 0x80 || a > 0xBF) - return false; - case 2: - if ((a = (*--srcptr)) > 0xBF) - return false; - - // no fall-through in this inner switch - switch (*source) { - case 0xE0: - if (a < 0xA0) - return false; - break; - case 0xED: - if (a > 0x9F) - return false; - break; - case 0xF0: - if (a < 0x90) - return false; - break; - case 0xF4: - if (a > 0x8F) - return false; - break; - default: - if (a < 0x80) - return false; - } - - case 1: - if (*source >= 0x80 && *source < 0xC2) - return false; - } - if (*source > 0xF4) - return false; - return true; -} - -// Magic values subtracted from a buffer value during UTF8 conversion. -// This table contains as many values as there might be trailing bytes -// in a UTF-8 sequence. -static const UChar32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, static_cast(0xFA082080UL), static_cast(0x82082080UL) }; - -static inline UChar32 readUTF8Sequence(const char*& sequence, unsigned length) -{ - UChar32 character = 0; - - // The cases all fall through. - switch (length) { - case 6: - character += static_cast(*sequence++); - character <<= 6; - case 5: - character += static_cast(*sequence++); - character <<= 6; - case 4: - character += static_cast(*sequence++); - character <<= 6; - case 3: - character += static_cast(*sequence++); - character <<= 6; - case 2: - character += static_cast(*sequence++); - character <<= 6; - case 1: - character += static_cast(*sequence++); - } - - return character - offsetsFromUTF8[length - 1]; -} - -ConversionResult convertUTF8ToUTF16( - const char** sourceStart, const char* sourceEnd, - UChar** targetStart, UChar* targetEnd, bool* sourceAllASCII, bool strict) -{ - ConversionResult result = conversionOK; - const char* source = *sourceStart; - UChar* target = *targetStart; - UChar orAllData = 0; - while (source < sourceEnd) { - int utf8SequenceLength = inlineUTF8SequenceLength(*source); - if (sourceEnd - source < utf8SequenceLength) { - result = sourceExhausted; - break; - } - // Do this check whether lenient or strict - if (!isLegalUTF8(reinterpret_cast(source), utf8SequenceLength)) { - result = sourceIllegal; - break; - } - - UChar32 character = readUTF8Sequence(source, utf8SequenceLength); - - if (target >= targetEnd) { - source -= utf8SequenceLength; // Back up source pointer! - result = targetExhausted; - break; - } - - if (U_IS_BMP(character)) { - // UTF-16 surrogate values are illegal in UTF-32 - if (U_IS_SURROGATE(character)) { - if (strict) { - source -= utf8SequenceLength; // return to the illegal value itself - result = sourceIllegal; - break; - } - *target++ = replacementCharacter; - orAllData |= replacementCharacter; - } else { - *target++ = static_cast(character); // normal case - orAllData |= character; - } - } else if (U_IS_SUPPLEMENTARY(character)) { - // target is a character in range 0xFFFF - 0x10FFFF - if (target + 1 >= targetEnd) { - source -= utf8SequenceLength; // Back up source pointer! - result = targetExhausted; - break; - } - *target++ = U16_LEAD(character); - *target++ = U16_TRAIL(character); - orAllData = 0xffff; - } else { - if (strict) { - source -= utf8SequenceLength; // return to the start - result = sourceIllegal; - break; // Bail out; shouldn't continue - } else { - *target++ = replacementCharacter; - orAllData |= replacementCharacter; - } - } - } - *sourceStart = source; - *targetStart = target; - - if (sourceAllASCII) - *sourceAllASCII = !(orAllData & ~0x7f); - - return result; -} - -// Helper to write a three-byte UTF-8 code point to the buffer, caller must check room is available. -static inline void putUTF8Triple(char*& buffer, UChar ch) -{ - DCHECK_GE(ch, 0x0800); - *buffer++ = static_cast(((ch >> 12) & 0x0F) | 0xE0); - *buffer++ = static_cast(((ch >> 6) & 0x3F) | 0x80); - *buffer++ = static_cast((ch & 0x3F) | 0x80); -} - -String16 String16::fromUTF8(const char* stringStart, size_t length) -{ - if (!stringStart || !length) - return String16(); - - std::vector buffer(length); - UChar* bufferStart = buffer.data(); - - UChar* bufferCurrent = bufferStart; - const char* stringCurrent = stringStart; - if (convertUTF8ToUTF16(&stringCurrent, stringStart + length, &bufferCurrent, bufferCurrent + buffer.size(), 0, true) != conversionOK) - return String16(); - - unsigned utf16Length = bufferCurrent - bufferStart; - return String16(bufferStart, utf16Length); -} - -std::string String16::utf8() const -{ - unsigned length = this->length(); - - if (!length) - return std::string(""); - - // Allocate a buffer big enough to hold all the characters - // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes). - // Optimization ideas, if we find this function is hot: - // * We could speculatively create a CStringBuffer to contain 'length' - // characters, and resize if necessary (i.e. if the buffer contains - // non-ascii characters). (Alternatively, scan the buffer first for - // ascii characters, so we know this will be sufficient). - // * We could allocate a CStringBuffer with an appropriate size to - // have a good chance of being able to write the string into the - // buffer without reallocing (say, 1.5 x length). - if (length > std::numeric_limits::max() / 3) - return std::string(); - std::vector bufferVector(length * 3); - char* buffer = bufferVector.data(); - const UChar* characters = m_impl.data(); - - ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), false); - DCHECK(result != targetExhausted); // (length * 3) should be sufficient for any conversion - - // Only produced from strict conversion. - DCHECK(result != sourceIllegal); - - // Check for an unconverted high surrogate. - if (result == sourceExhausted) { - // This should be one unpaired high surrogate. Treat it the same - // was as an unpaired high surrogate would have been handled in - // the middle of a string with non-strict conversion - which is - // to say, simply encode it to UTF-8. - DCHECK((characters + 1) == (m_impl.data() + length)); - DCHECK((*characters >= 0xD800) && (*characters <= 0xDBFF)); - // There should be room left, since one UChar hasn't been - // converted. - DCHECK((buffer + 3) <= (buffer + bufferVector.size())); - putUTF8Triple(buffer, *characters); - } - - return std::string(bufferVector.data(), buffer - bufferVector.data()); -} - -} // namespace protocol -} // namespace blink diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16STL.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16STL.h deleted file mode 100644 index ffde6c72f52afd..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16STL.h +++ /dev/null @@ -1,104 +0,0 @@ -// 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 String16STL_h -#define String16STL_h - -#include -#include -#include -#include -#include -#include -#include - -using UChar = uint16_t; - -namespace blink { -namespace protocol { - -class String16 : public String16Base { -public: - static const size_t kNotFound = static_cast(-1); - - String16() { } - String16(const String16& other) : m_impl(other.m_impl) { } - String16(const UChar* characters, size_t size) : m_impl(characters, size) { } - String16(const UChar* characters) : m_impl(characters) { } - String16(const char* characters) : String16(characters, std::strlen(characters)) { } - String16(const char* characters, size_t size) - { - m_impl.resize(size); - for (size_t i = 0; i < size; ++i) - m_impl[i] = characters[i]; - } - - String16 isolatedCopy() const { return String16(m_impl); } - const UChar* characters16() const { return m_impl.c_str(); } - size_t length() const { return m_impl.length(); } - bool isEmpty() const { return !m_impl.length(); } - UChar operator[](unsigned index) const { return m_impl[index]; } - String16 substring(unsigned pos, unsigned len = UINT_MAX) const { return String16(m_impl.substr(pos, len)); } - size_t find(const String16& str, unsigned start = 0) const { return m_impl.find(str.m_impl, start); } - size_t reverseFind(const String16& str, unsigned start = UINT_MAX) const { return m_impl.rfind(str.m_impl, start); } - - // Convenience methods. - std::string utf8() const; - static String16 fromUTF8(const char* stringStart, size_t length); - - const std::basic_string& impl() const { return m_impl; } - explicit String16(const std::basic_string& impl) : m_impl(impl) { } - - std::size_t hash() const - { - if (!has_hash) { - size_t hash = 0; - for (size_t i = 0; i < length(); ++i) - hash = 31 * hash + m_impl[i]; - hash_code = hash; - has_hash = true; - } - return hash_code; - } - -private: - std::basic_string m_impl; - mutable bool has_hash = false; - mutable std::size_t hash_code = 0; -}; - -inline bool operator==(const String16& a, const String16& b) { return a.impl() == b.impl(); } -inline bool operator<(const String16& a, const String16& b) { return a.impl() < b.impl(); } -inline bool operator!=(const String16& a, const String16& b) { return a.impl() != b.impl(); } -inline bool operator==(const String16& a, const char* b) { return a.impl() == String16(b).impl(); } -inline String16 operator+(const String16& a, const char* b) { return String16(a.impl() + String16(b).impl()); } -inline String16 operator+(const char* a, const String16& b) { return String16(String16(a).impl() + b.impl()); } -inline String16 operator+(const String16& a, const String16& b) { return String16(a.impl() + b.impl()); } - -} // namespace protocol -} // namespace blink - -#if !defined(__APPLE__) || defined(_LIBCPP_VERSION) - -namespace std { -template<> struct hash { - std::size_t operator()(const blink::protocol::String16& string) const - { - return string.hash(); - } -}; - -} // namespace std - -#endif // !defined(__APPLE__) || defined(_LIBCPP_VERSION) - -class InspectorProtocolConvenienceStringType { -public: - // This class should not be ever instantiated, so we don't implement constructors. - InspectorProtocolConvenienceStringType(); - InspectorProtocolConvenienceStringType(const blink::protocol::String16& other); - operator blink::protocol::String16() const { return blink::protocol::String16(); }; -}; - -#endif // !defined(String16STL_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16WTF.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16WTF.h deleted file mode 100644 index b65383a3cfa0b6..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/String16WTF.h +++ /dev/null @@ -1,111 +0,0 @@ -// 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 String16WTF_h -#define String16WTF_h - -#include "platform/Decimal.h" -#include "public/platform/WebString.h" -#include "wtf/text/StringBuilder.h" -#include "wtf/text/StringConcatenate.h" -#include "wtf/text/StringHash.h" -#include "wtf/text/StringToNumber.h" -#include "wtf/text/StringView.h" -#include "wtf/text/WTFString.h" - -namespace blink { -namespace protocol { - -class PLATFORM_EXPORT String16 : public String16Base { -public: - static const size_t kNotFound = WTF::kNotFound; - - String16() { } - String16(const String16& other) : m_impl(other.m_impl) { } - String16(const UChar* characters, unsigned length) : m_impl(characters, length) { } - String16(const char* characters) : String16(characters, strlen(characters)) { } - String16(const char* characters, size_t length) - { - UChar* data; - m_impl = WTF::String::createUninitialized(length, data); - for (size_t i = 0; i < length; ++i) - data[i] = characters[i]; - } - - ~String16() { } - - String16 isolatedCopy() const { return String16(m_impl.isolatedCopy()); } - const UChar* characters16() const { return m_impl.isEmpty() ? nullptr : m_impl.characters16(); } - size_t length() const { return m_impl.length(); } - bool isEmpty() const { return m_impl.isEmpty(); } - UChar operator[](unsigned index) const { return m_impl[index]; } - String16 substring(unsigned pos, unsigned len = UINT_MAX) const { return m_impl.substring(pos, len); } - size_t find(const String16& str, unsigned start = 0) const { return m_impl.find(str.impl(), start); } - size_t reverseFind(const String16& str, unsigned start = UINT_MAX) const { return m_impl.reverseFind(str.impl(), start); } - - // WTF convenience constructors and helper methods. - String16(const WebString& other) : String16(String(other)) { } - template - String16(const WTF::StringAppend& impl) : String16(String(impl)) { } - String16(const WTF::AtomicString& impl) : String16(String(impl)) { } - String16(const WTF::String& impl) : m_impl(impl) { m_impl.ensure16Bit(); } - String16(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { } - bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); } - operator WTF::String() const { return m_impl; } - operator WTF::StringView() const { return StringView(m_impl); } - operator WebString() { return m_impl; } - const WTF::String& impl() const { return m_impl; } - -private: - WTF::String m_impl; -}; - -inline bool operator==(const String16& a, const String16& b) { return a.impl() == b.impl(); } -inline bool operator!=(const String16& a, const String16& b) { return a.impl() != b.impl(); } -inline bool operator==(const String16& a, const char* b) { return a.impl() == b; } -inline String16 operator+(const String16& a, const char* b) { return String16(a.impl() + b); } -inline String16 operator+(const char* a, const String16& b) { return String16(a + b.impl()); } -inline String16 operator+(const String16& a, const String16& b) { return String16(a.impl() + b.impl()); } - -} // namespace protocol -} // namespace blink - -namespace std { -template<> struct hash { - std::size_t operator()(const blink::protocol::String16& string) const - { - return StringHash::hash(string.impl()); - } -}; -} // namespace std - -using InspectorProtocolConvenienceStringType = WTF::String; - -// WTF helpers below this line. - -namespace WTF { - -struct String16Hash { - static unsigned hash(const blink::protocol::String16& key) { return StringHash::hash(key.impl()); } - static bool equal(const blink::protocol::String16& a, const blink::protocol::String16& b) - { - return StringHash::equal(a.impl(), b.impl()); - } - static const bool safeToCompareToEmptyOrDeleted = false; -}; - -template struct DefaultHash; -template<> struct DefaultHash { - typedef String16Hash Hash; -}; - -template<> -struct HashTraits : SimpleClassHashTraits { - static const bool hasIsEmptyValueFunction = true; - static bool isEmptyValue(const blink::protocol::String16& a) { return a.impl().isNull(); } -}; - -} // namespace WTF - -#endif // !defined(String16WTF_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Compat.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Compat.h deleted file mode 100644 index d623da1a616f39..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Compat.h +++ /dev/null @@ -1,32 +0,0 @@ -// 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 V8Compat_h -#define V8Compat_h - -#include - -#if V8_MAJOR_VERSION < 5 || (V8_MAJOR_VERSION == 5 && V8_MINOR_VERSION < 1) -namespace v8 { - -// In standalone V8 inspector this is expected to be noop anyways... -class V8_EXPORT MicrotasksScope { -public: - enum Type { kRunMicrotasks, kDoNotRunMicrotasks }; - - MicrotasksScope(Isolate* isolate, Type type) - { - // No-op - } -}; - -} // namespace v8 -#define V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, callback, data, length) \ - v8::Function::New((context), (callback), (data), (length)) -#else -#define V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, callback, data, length) \ - v8::Function::New((context), (callback), (data), (length), v8::ConstructorBehavior::kThrow) -#endif // V8_MAJOR_VERSION < 5 || (V8_MAJOR_VERSION == 5 && V8_MINOR_VERSION < 1) - -#endif // V8Compat_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Console.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Console.cpp deleted file mode 100644 index 73a90e225e11ae..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Console.cpp +++ /dev/null @@ -1,831 +0,0 @@ -// 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 "platform/v8_inspector/V8Console.h" - -#include "platform/v8_inspector/InjectedScript.h" -#include "platform/v8_inspector/InspectedContext.h" -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8ConsoleMessage.h" -#include "platform/v8_inspector/V8DebuggerAgentImpl.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8ProfilerAgentImpl.h" -#include "platform/v8_inspector/V8RuntimeAgentImpl.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -namespace v8_inspector { - -namespace { - -v8::Local inspectedContextPrivateKey(v8::Isolate* isolate) -{ - return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8Console#InspectedContext")); -} - -class ConsoleHelper { - PROTOCOL_DISALLOW_COPY(ConsoleHelper); -public: - ConsoleHelper(const v8::FunctionCallbackInfo& info) - : m_info(info) - , m_isolate(info.GetIsolate()) - , m_context(info.GetIsolate()->GetCurrentContext()) - , m_inspectedContext(nullptr) - , m_inspectorClient(nullptr) - { - } - - v8::Local ensureConsole() - { - if (m_console.IsEmpty()) { - DCHECK(!m_info.Data().IsEmpty()); - DCHECK(!m_info.Data()->IsUndefined()); - m_console = m_info.Data().As(); - } - return m_console; - } - - InspectedContext* ensureInspectedContext() - { - if (m_inspectedContext) - return m_inspectedContext; - v8::Local console = ensureConsole(); - - v8::Local key = inspectedContextPrivateKey(m_isolate); - v8::Local inspectedContextValue; - if (!console->GetPrivate(m_context, key).ToLocal(&inspectedContextValue)) - return nullptr; - DCHECK(inspectedContextValue->IsExternal()); - m_inspectedContext = static_cast(inspectedContextValue.As()->Value()); - return m_inspectedContext; - } - - V8InspectorClient* ensureDebuggerClient() - { - if (m_inspectorClient) - return m_inspectorClient; - InspectedContext* inspectedContext = ensureInspectedContext(); - if (!inspectedContext) - return nullptr; - m_inspectorClient = inspectedContext->inspector()->client(); - return m_inspectorClient; - } - - void reportCall(ConsoleAPIType type) - { - if (!m_info.Length()) - return; - std::vector> arguments; - for (int i = 0; i < m_info.Length(); ++i) - arguments.push_back(m_info[i]); - reportCall(type, arguments); - } - - void reportCallWithDefaultArgument(ConsoleAPIType type, const String16& message) - { - std::vector> arguments; - for (int i = 0; i < m_info.Length(); ++i) - arguments.push_back(m_info[i]); - if (!m_info.Length()) - arguments.push_back(toV8String(m_isolate, message)); - reportCall(type, arguments); - } - - void reportCallWithArgument(ConsoleAPIType type, const String16& message) - { - std::vector> arguments(1, toV8String(m_isolate, message)); - reportCall(type, arguments); - } - - void reportCall(ConsoleAPIType type, const std::vector>& arguments) - { - InspectedContext* inspectedContext = ensureInspectedContext(); - if (!inspectedContext) - return; - V8InspectorImpl* inspector = inspectedContext->inspector(); - std::unique_ptr message = V8ConsoleMessage::createForConsoleAPI(inspector->client()->currentTimeMS(), type, arguments, inspector->debugger()->captureStackTrace(false), inspectedContext); - inspector->ensureConsoleMessageStorage(inspectedContext->contextGroupId())->addMessage(std::move(message)); - } - - void reportDeprecatedCall(const char* id, const String16& message) - { - if (checkAndSetPrivateFlagOnConsole(id, false)) - return; - std::vector> arguments(1, toV8String(m_isolate, message)); - reportCall(ConsoleAPIType::kWarning, arguments); - } - - bool firstArgToBoolean(bool defaultValue) - { - if (m_info.Length() < 1) - return defaultValue; - if (m_info[0]->IsBoolean()) - return m_info[0].As()->Value(); - return m_info[0]->BooleanValue(m_context).FromMaybe(defaultValue); - } - - String16 firstArgToString(const String16& defaultValue) - { - if (m_info.Length() < 1) - return defaultValue; - v8::Local titleValue; - if (m_info[0]->IsObject()) { - if (!m_info[0].As()->ObjectProtoToString(m_context).ToLocal(&titleValue)) - return defaultValue; - } else { - if (!m_info[0]->ToString(m_context).ToLocal(&titleValue)) - return defaultValue; - } - return toProtocolString(titleValue); - } - - v8::MaybeLocal firstArgAsObject() - { - if (m_info.Length() < 1 || !m_info[0]->IsObject()) - return v8::MaybeLocal(); - return m_info[0].As(); - } - - v8::MaybeLocal firstArgAsFunction() - { - if (m_info.Length() < 1 || !m_info[0]->IsFunction()) - return v8::MaybeLocal(); - return m_info[0].As(); - } - - v8::MaybeLocal privateMap(const char* name) - { - v8::Local console = ensureConsole(); - v8::Local privateKey = v8::Private::ForApi(m_isolate, toV8StringInternalized(m_isolate, name)); - v8::Local mapValue; - if (!console->GetPrivate(m_context, privateKey).ToLocal(&mapValue)) - return v8::MaybeLocal(); - if (mapValue->IsUndefined()) { - v8::Local map = v8::Map::New(m_isolate); - if (!console->SetPrivate(m_context, privateKey, map).FromMaybe(false)) - return v8::MaybeLocal(); - return map; - } - return mapValue->IsMap() ? mapValue.As() : v8::MaybeLocal(); - } - - int64_t getIntFromMap(v8::Local map, const String16& key, int64_t defaultValue) - { - v8::Local v8Key = toV8String(m_isolate, key); - if (!map->Has(m_context, v8Key).FromMaybe(false)) - return defaultValue; - v8::Local intValue; - if (!map->Get(m_context, v8Key).ToLocal(&intValue)) - return defaultValue; - return intValue.As()->Value(); - } - - void setIntOnMap(v8::Local map, const String16& key, int64_t value) - { - v8::Local v8Key = toV8String(m_isolate, key); - if (!map->Set(m_context, v8Key, v8::Integer::New(m_isolate, value)).ToLocal(&map)) - return; - } - - double getDoubleFromMap(v8::Local map, const String16& key, double defaultValue) - { - v8::Local v8Key = toV8String(m_isolate, key); - if (!map->Has(m_context, v8Key).FromMaybe(false)) - return defaultValue; - v8::Local intValue; - if (!map->Get(m_context, v8Key).ToLocal(&intValue)) - return defaultValue; - return intValue.As()->Value(); - } - - void setDoubleOnMap(v8::Local map, const String16& key, double value) - { - v8::Local v8Key = toV8String(m_isolate, key); - if (!map->Set(m_context, v8Key, v8::Number::New(m_isolate, value)).ToLocal(&map)) - return; - } - - V8ProfilerAgentImpl* profilerAgent() - { - if (V8InspectorSessionImpl* session = currentSession()) { - if (session && session->profilerAgent()->enabled()) - return session->profilerAgent(); - } - return nullptr; - } - - V8DebuggerAgentImpl* debuggerAgent() - { - if (V8InspectorSessionImpl* session = currentSession()) { - if (session && session->debuggerAgent()->enabled()) - return session->debuggerAgent(); - } - return nullptr; - } - - V8InspectorSessionImpl* currentSession() - { - InspectedContext* inspectedContext = ensureInspectedContext(); - if (!inspectedContext) - return nullptr; - return inspectedContext->inspector()->sessionForContextGroup(inspectedContext->contextGroupId()); - } - -private: - const v8::FunctionCallbackInfo& m_info; - v8::Isolate* m_isolate; - v8::Local m_context; - v8::Local m_console; - InspectedContext* m_inspectedContext; - V8InspectorClient* m_inspectorClient; - - bool checkAndSetPrivateFlagOnConsole(const char* name, bool defaultValue) - { - v8::Local console = ensureConsole(); - v8::Local key = v8::Private::ForApi(m_isolate, toV8StringInternalized(m_isolate, name)); - v8::Local flagValue; - if (!console->GetPrivate(m_context, key).ToLocal(&flagValue)) - return defaultValue; - DCHECK(flagValue->IsUndefined() || flagValue->IsBoolean()); - if (flagValue->IsBoolean()) { - DCHECK(flagValue.As()->Value()); - return true; - } - if (!console->SetPrivate(m_context, key, v8::True(m_isolate)).FromMaybe(false)) - return defaultValue; - return false; - } -}; - -void returnDataCallback(const v8::FunctionCallbackInfo& info) -{ - info.GetReturnValue().Set(info.Data()); -} - -void createBoundFunctionProperty(v8::Local context, v8::Local console, const char* name, v8::FunctionCallback callback, const char* description = nullptr) -{ - v8::Local funcName = toV8StringInternalized(context->GetIsolate(), name); - v8::Local func; - if (!V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, callback, console, 0).ToLocal(&func)) - return; - func->SetName(funcName); - if (description) { - v8::Local returnValue = toV8String(context->GetIsolate(), description); - v8::Local toStringFunction; - if (V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, returnDataCallback, returnValue, 0).ToLocal(&toStringFunction)) - func->Set(toV8StringInternalized(context->GetIsolate(), "toString"), toStringFunction); - } - if (!console->Set(context, funcName, func).FromMaybe(false)) - return; -} - -} // namespace - -void V8Console::debugCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCall(ConsoleAPIType::kDebug); -} - -void V8Console::errorCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCall(ConsoleAPIType::kError); -} - -void V8Console::infoCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCall(ConsoleAPIType::kInfo); -} - -void V8Console::logCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCall(ConsoleAPIType::kLog); -} - -void V8Console::warnCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCall(ConsoleAPIType::kWarning); -} - -void V8Console::dirCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCall(ConsoleAPIType::kDir); -} - -void V8Console::dirxmlCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCall(ConsoleAPIType::kDirXML); -} - -void V8Console::tableCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCall(ConsoleAPIType::kTable); -} - -void V8Console::traceCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCallWithDefaultArgument(ConsoleAPIType::kTrace, String16("console.trace")); -} - -void V8Console::groupCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCallWithDefaultArgument(ConsoleAPIType::kStartGroup, String16("console.group")); -} - -void V8Console::groupCollapsedCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCallWithDefaultArgument(ConsoleAPIType::kStartGroupCollapsed, String16("console.groupCollapsed")); -} - -void V8Console::groupEndCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCallWithDefaultArgument(ConsoleAPIType::kEndGroup, String16("console.groupEnd")); -} - -void V8Console::clearCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportCallWithDefaultArgument(ConsoleAPIType::kClear, String16("console.clear")); -} - -void V8Console::countCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - - String16 title = helper.firstArgToString(String16()); - String16 identifier; - if (title.isEmpty()) { - std::unique_ptr stackTrace = V8StackTraceImpl::capture(nullptr, 0, 1); - if (stackTrace) - identifier = stackTrace->topSourceURL() + ":" + String16::fromInteger(stackTrace->topLineNumber()); - } else { - identifier = title + "@"; - } - - v8::Local countMap; - if (!helper.privateMap("V8Console#countMap").ToLocal(&countMap)) - return; - int64_t count = helper.getIntFromMap(countMap, identifier, 0) + 1; - helper.setIntOnMap(countMap, identifier, count); - helper.reportCallWithArgument(ConsoleAPIType::kCount, title + ": " + String16::fromInteger(count)); -} - -void V8Console::assertCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - if (helper.firstArgToBoolean(false)) - return; - - std::vector> arguments; - for (int i = 1; i < info.Length(); ++i) - arguments.push_back(info[i]); - if (info.Length() < 2) - arguments.push_back(toV8String(info.GetIsolate(), String16("console.assert"))); - helper.reportCall(ConsoleAPIType::kAssert, arguments); - - if (V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent()) - debuggerAgent->breakProgramOnException(protocol::Debugger::Paused::ReasonEnum::Assert, nullptr); -} - -void V8Console::markTimelineCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportDeprecatedCall("V8Console#markTimelineDeprecated", "'console.markTimeline' is deprecated. Please use 'console.timeStamp' instead."); - timeStampCallback(info); -} - -void V8Console::profileCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - if (V8ProfilerAgentImpl* profilerAgent = helper.profilerAgent()) - profilerAgent->consoleProfile(helper.firstArgToString(String16())); -} - -void V8Console::profileEndCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - if (V8ProfilerAgentImpl* profilerAgent = helper.profilerAgent()) - profilerAgent->consoleProfileEnd(helper.firstArgToString(String16())); -} - -static void timeFunction(const v8::FunctionCallbackInfo& info, bool timelinePrefix) -{ - ConsoleHelper helper(info); - if (V8InspectorClient* client = helper.ensureDebuggerClient()) { - String16 protocolTitle = helper.firstArgToString("default"); - if (timelinePrefix) - protocolTitle = "Timeline '" + protocolTitle + "'"; - client->consoleTime(protocolTitle); - - v8::Local timeMap; - if (!helper.privateMap("V8Console#timeMap").ToLocal(&timeMap)) - return; - helper.setDoubleOnMap(timeMap, protocolTitle, client->currentTimeMS()); - } -} - -static void timeEndFunction(const v8::FunctionCallbackInfo& info, bool timelinePrefix) -{ - ConsoleHelper helper(info); - if (V8InspectorClient* client = helper.ensureDebuggerClient()) { - String16 protocolTitle = helper.firstArgToString("default"); - if (timelinePrefix) - protocolTitle = "Timeline '" + protocolTitle + "'"; - client->consoleTimeEnd(protocolTitle); - - v8::Local timeMap; - if (!helper.privateMap("V8Console#timeMap").ToLocal(&timeMap)) - return; - double elapsed = client->currentTimeMS() - helper.getDoubleFromMap(timeMap, protocolTitle, 0.0); - String16 message = protocolTitle + ": " + String16::fromDoublePrecision3(elapsed) + "ms"; - helper.reportCallWithArgument(ConsoleAPIType::kTimeEnd, message); - } -} - -void V8Console::timelineCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportDeprecatedCall("V8Console#timeline", "'console.timeline' is deprecated. Please use 'console.time' instead."); - timeFunction(info, true); -} - -void V8Console::timelineEndCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper(info).reportDeprecatedCall("V8Console#timelineEnd", "'console.timelineEnd' is deprecated. Please use 'console.timeEnd' instead."); - timeEndFunction(info, true); -} - -void V8Console::timeCallback(const v8::FunctionCallbackInfo& info) -{ - timeFunction(info, false); -} - -void V8Console::timeEndCallback(const v8::FunctionCallbackInfo& info) -{ - timeEndFunction(info, false); -} - -void V8Console::timeStampCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - if (V8InspectorClient* client = helper.ensureDebuggerClient()) - client->consoleTimeStamp(helper.firstArgToString(String16())); -} - -void V8Console::memoryGetterCallback(const v8::FunctionCallbackInfo& info) -{ - if (V8InspectorClient* client = ConsoleHelper(info).ensureDebuggerClient()) { - v8::Local memoryValue; - if (!client->memoryInfo(info.GetIsolate(), info.GetIsolate()->GetCurrentContext()).ToLocal(&memoryValue)) - return; - info.GetReturnValue().Set(memoryValue); - } -} - -void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo& info) -{ - // We can't make the attribute readonly as it breaks existing code that relies on being able to assign to console.memory in strict mode. Instead, the setter just ignores the passed value. http://crbug.com/468611 -} - -void V8Console::keysCallback(const v8::FunctionCallbackInfo& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - info.GetReturnValue().Set(v8::Array::New(isolate)); - - ConsoleHelper helper(info); - v8::Local obj; - if (!helper.firstArgAsObject().ToLocal(&obj)) - return; - v8::Local names; - if (!obj->GetOwnPropertyNames(isolate->GetCurrentContext()).ToLocal(&names)) - return; - info.GetReturnValue().Set(names); -} - -void V8Console::valuesCallback(const v8::FunctionCallbackInfo& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - info.GetReturnValue().Set(v8::Array::New(isolate)); - - ConsoleHelper helper(info); - v8::Local obj; - if (!helper.firstArgAsObject().ToLocal(&obj)) - return; - v8::Local names; - v8::Local context = isolate->GetCurrentContext(); - if (!obj->GetOwnPropertyNames(context).ToLocal(&names)) - return; - v8::Local values = v8::Array::New(isolate, names->Length()); - for (size_t i = 0; i < names->Length(); ++i) { - v8::Local key; - if (!names->Get(context, i).ToLocal(&key)) - continue; - v8::Local value; - if (!obj->Get(context, key).ToLocal(&value)) - continue; - if (!values->Set(context, i, value).FromMaybe(false)) - continue; - } - info.GetReturnValue().Set(values); -} - -static void setFunctionBreakpoint(ConsoleHelper& helper, v8::Local function, V8DebuggerAgentImpl::BreakpointSource source, const String16& condition, bool enable) -{ - V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent(); - if (!debuggerAgent) - return; - String16 scriptId = String16::fromInteger(function->ScriptId()); - int lineNumber = function->GetScriptLineNumber(); - int columnNumber = function->GetScriptColumnNumber(); - if (lineNumber == v8::Function::kLineOffsetNotFound || columnNumber == v8::Function::kLineOffsetNotFound) - return; - if (enable) - debuggerAgent->setBreakpointAt(scriptId, lineNumber, columnNumber, source, condition); - else - debuggerAgent->removeBreakpointAt(scriptId, lineNumber, columnNumber, source); -} - -void V8Console::debugFunctionCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - v8::Local function; - if (!helper.firstArgAsFunction().ToLocal(&function)) - return; - setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::DebugCommandBreakpointSource, String16(), true); -} - -void V8Console::undebugFunctionCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - v8::Local function; - if (!helper.firstArgAsFunction().ToLocal(&function)) - return; - setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::DebugCommandBreakpointSource, String16(), false); -} - -void V8Console::monitorFunctionCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - v8::Local function; - if (!helper.firstArgAsFunction().ToLocal(&function)) - return; - v8::Local name = function->GetName(); - if (!name->IsString() || !v8::Local::Cast(name)->Length()) - name = function->GetInferredName(); - String16 functionName = toProtocolStringWithTypeCheck(name); - String16Builder builder; - builder.append("console.log(\"function "); - if (functionName.isEmpty()) - builder.append("(anonymous function)"); - else - builder.append(functionName); - builder.append(" called\" + (arguments.length > 0 ? \" with arguments: \" + Array.prototype.join.call(arguments, \", \") : \"\")) && false"); - setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::MonitorCommandBreakpointSource, builder.toString(), true); -} - -void V8Console::unmonitorFunctionCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - v8::Local function; - if (!helper.firstArgAsFunction().ToLocal(&function)) - return; - setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::MonitorCommandBreakpointSource, String16(), false); -} - -void V8Console::lastEvaluationResultCallback(const v8::FunctionCallbackInfo& info) -{ - ConsoleHelper helper(info); - InspectedContext* context = helper.ensureInspectedContext(); - if (!context) - return; - if (InjectedScript* injectedScript = context->getInjectedScript()) - info.GetReturnValue().Set(injectedScript->lastEvaluationResult()); -} - -static void inspectImpl(const v8::FunctionCallbackInfo& info, bool copyToClipboard) -{ - if (info.Length() < 1) - return; - if (!copyToClipboard) - info.GetReturnValue().Set(info[0]); - - ConsoleHelper helper(info); - InspectedContext* context = helper.ensureInspectedContext(); - if (!context) - return; - InjectedScript* injectedScript = context->getInjectedScript(); - if (!injectedScript) - return; - ErrorString errorString; - std::unique_ptr wrappedObject = injectedScript->wrapObject(&errorString, info[0], "", false /** forceValueType */, false /** generatePreview */); - if (!wrappedObject || !errorString.isEmpty()) - return; - - std::unique_ptr hints = protocol::DictionaryValue::create(); - if (copyToClipboard) - hints->setBoolean("copyToClipboard", true); - if (V8InspectorSessionImpl* session = helper.currentSession()) - session->runtimeAgent()->inspect(std::move(wrappedObject), std::move(hints)); -} - -void V8Console::inspectCallback(const v8::FunctionCallbackInfo& info) -{ - inspectImpl(info, false); -} - -void V8Console::copyCallback(const v8::FunctionCallbackInfo& info) -{ - inspectImpl(info, true); -} - -void V8Console::inspectedObject(const v8::FunctionCallbackInfo& info, unsigned num) -{ - DCHECK(num < V8InspectorSessionImpl::kInspectedObjectBufferSize); - ConsoleHelper helper(info); - if (V8InspectorSessionImpl* session = helper.currentSession()) { - V8InspectorSession::Inspectable* object = session->inspectedObject(num); - v8::Isolate* isolate = info.GetIsolate(); - if (object) - info.GetReturnValue().Set(object->get(isolate->GetCurrentContext())); - else - info.GetReturnValue().Set(v8::Undefined(isolate)); - } -} - -v8::Local V8Console::createConsole(InspectedContext* inspectedContext, bool hasMemoryAttribute) -{ - v8::Local context = inspectedContext->context(); - v8::Context::Scope contextScope(context); - v8::Isolate* isolate = context->GetIsolate(); - v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - - v8::Local console = v8::Object::New(isolate); - bool success = console->SetPrototype(context, v8::Object::New(isolate)).FromMaybe(false); - DCHECK(success); - - createBoundFunctionProperty(context, console, "debug", V8Console::debugCallback); - createBoundFunctionProperty(context, console, "error", V8Console::errorCallback); - createBoundFunctionProperty(context, console, "info", V8Console::infoCallback); - createBoundFunctionProperty(context, console, "log", V8Console::logCallback); - createBoundFunctionProperty(context, console, "warn", V8Console::warnCallback); - createBoundFunctionProperty(context, console, "dir", V8Console::dirCallback); - createBoundFunctionProperty(context, console, "dirxml", V8Console::dirxmlCallback); - createBoundFunctionProperty(context, console, "table", V8Console::tableCallback); - createBoundFunctionProperty(context, console, "trace", V8Console::traceCallback); - createBoundFunctionProperty(context, console, "group", V8Console::groupCallback); - createBoundFunctionProperty(context, console, "groupCollapsed", V8Console::groupCollapsedCallback); - createBoundFunctionProperty(context, console, "groupEnd", V8Console::groupEndCallback); - createBoundFunctionProperty(context, console, "clear", V8Console::clearCallback); - createBoundFunctionProperty(context, console, "count", V8Console::countCallback); - createBoundFunctionProperty(context, console, "assert", V8Console::assertCallback); - createBoundFunctionProperty(context, console, "markTimeline", V8Console::markTimelineCallback); - createBoundFunctionProperty(context, console, "profile", V8Console::profileCallback); - createBoundFunctionProperty(context, console, "profileEnd", V8Console::profileEndCallback); - createBoundFunctionProperty(context, console, "timeline", V8Console::timelineCallback); - createBoundFunctionProperty(context, console, "timelineEnd", V8Console::timelineEndCallback); - createBoundFunctionProperty(context, console, "time", V8Console::timeCallback); - createBoundFunctionProperty(context, console, "timeEnd", V8Console::timeEndCallback); - createBoundFunctionProperty(context, console, "timeStamp", V8Console::timeStampCallback); - - if (hasMemoryAttribute) - console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"), V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, V8Console::memoryGetterCallback, console, 0).ToLocalChecked(), V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, V8Console::memorySetterCallback, v8::Local(), 0).ToLocalChecked(), static_cast(v8::None), v8::DEFAULT); - - console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::External::New(isolate, inspectedContext)); - return console; -} - -void V8Console::clearInspectedContextIfNeeded(v8::Local context, v8::Local console) -{ - v8::Isolate* isolate = context->GetIsolate(); - console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::External::New(isolate, nullptr)); -} - -v8::Local V8Console::createCommandLineAPI(InspectedContext* inspectedContext) -{ - v8::Local context = inspectedContext->context(); - v8::Isolate* isolate = context->GetIsolate(); - v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - - v8::Local commandLineAPI = v8::Object::New(isolate); - bool success = commandLineAPI->SetPrototype(context, v8::Null(isolate)).FromMaybe(false); - DCHECK(success); - - createBoundFunctionProperty(context, commandLineAPI, "dir", V8Console::dirCallback, "function dir(value) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "dirxml", V8Console::dirxmlCallback, "function dirxml(value) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "profile", V8Console::profileCallback, "function profile(title) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "profileEnd", V8Console::profileEndCallback, "function profileEnd(title) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "clear", V8Console::clearCallback, "function clear() { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "table", V8Console::tableCallback, "function table(data, [columns]) { [Command Line API] }"); - - createBoundFunctionProperty(context, commandLineAPI, "keys", V8Console::keysCallback, "function keys(object) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "values", V8Console::valuesCallback, "function values(object) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "debug", V8Console::debugFunctionCallback, "function debug(function) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "undebug", V8Console::undebugFunctionCallback, "function undebug(function) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "monitor", V8Console::monitorFunctionCallback, "function monitor(function) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "unmonitor", V8Console::unmonitorFunctionCallback, "function unmonitor(function) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "inspect", V8Console::inspectCallback, "function inspect(object) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "copy", V8Console::copyCallback, "function copy(value) { [Command Line API] }"); - createBoundFunctionProperty(context, commandLineAPI, "$_", V8Console::lastEvaluationResultCallback); - createBoundFunctionProperty(context, commandLineAPI, "$0", V8Console::inspectedObject0); - createBoundFunctionProperty(context, commandLineAPI, "$1", V8Console::inspectedObject1); - createBoundFunctionProperty(context, commandLineAPI, "$2", V8Console::inspectedObject2); - createBoundFunctionProperty(context, commandLineAPI, "$3", V8Console::inspectedObject3); - createBoundFunctionProperty(context, commandLineAPI, "$4", V8Console::inspectedObject4); - - inspectedContext->inspector()->client()->installAdditionalCommandLineAPI(context, commandLineAPI); - - commandLineAPI->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::External::New(isolate, inspectedContext)); - return commandLineAPI; -} - -static bool isCommandLineAPIGetter(const String16& name) -{ - if (name.length() != 2) - return false; - // $0 ... $4, $_ - return name[0] == '$' && ((name[1] >= '0' && name[1] <= '4') || name[1] == '_'); -} - -void V8Console::CommandLineAPIScope::accessorGetterCallback(v8::Local name, const v8::PropertyCallbackInfo& info) -{ - CommandLineAPIScope* scope = static_cast(info.Data().As()->Value()); - DCHECK(scope); - - v8::Local context = info.GetIsolate()->GetCurrentContext(); - if (scope->m_cleanup) { - bool removed = info.Holder()->Delete(context, name).FromMaybe(false); - DCHECK(removed); - return; - } - v8::Local commandLineAPI = scope->m_commandLineAPI; - - v8::Local value; - if (!commandLineAPI->Get(context, name).ToLocal(&value)) - return; - if (isCommandLineAPIGetter(toProtocolStringWithTypeCheck(name))) { - DCHECK(value->IsFunction()); - v8::MicrotasksScope microtasks(info.GetIsolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); - if (value.As()->Call(context, commandLineAPI, 0, nullptr).ToLocal(&value)) - info.GetReturnValue().Set(value); - } else { - info.GetReturnValue().Set(value); - } -} - -void V8Console::CommandLineAPIScope::accessorSetterCallback(v8::Local name, v8::Local value, const v8::PropertyCallbackInfo& info) -{ - CommandLineAPIScope* scope = static_cast(info.Data().As()->Value()); - v8::Local context = info.GetIsolate()->GetCurrentContext(); - if (!info.Holder()->Delete(context, name).FromMaybe(false)) - return; - if (!info.Holder()->CreateDataProperty(context, name, value).FromMaybe(false)) - return; - bool removed = scope->m_installedMethods->Delete(context, name).FromMaybe(false); - DCHECK(removed); -} - -V8Console::CommandLineAPIScope::CommandLineAPIScope(v8::Local context, v8::Local commandLineAPI, v8::Local global) - : m_context(context) - , m_commandLineAPI(commandLineAPI) - , m_global(global) - , m_installedMethods(v8::Set::New(context->GetIsolate())) - , m_cleanup(false) -{ - v8::Local names; - if (!m_commandLineAPI->GetOwnPropertyNames(context).ToLocal(&names)) - return; - v8::Local externalThis = v8::External::New(context->GetIsolate(), this); - for (size_t i = 0; i < names->Length(); ++i) { - v8::Local name; - if (!names->Get(context, i).ToLocal(&name) || !name->IsName()) - continue; - if (m_global->Has(context, name).FromMaybe(true)) - continue; - if (!m_installedMethods->Add(context, name).ToLocal(&m_installedMethods)) - continue; - if (!m_global->SetAccessor(context, v8::Local::Cast(name), CommandLineAPIScope::accessorGetterCallback, - CommandLineAPIScope::accessorSetterCallback, externalThis, - v8::DEFAULT, v8::DontEnum).FromMaybe(false)) { - bool removed = m_installedMethods->Delete(context, name).FromMaybe(false); - DCHECK(removed); - continue; - } - } -} - -V8Console::CommandLineAPIScope::~CommandLineAPIScope() -{ - m_cleanup = true; - v8::Local names = m_installedMethods->AsArray(); - for (size_t i = 0; i < names->Length(); ++i) { - v8::Local name; - if (!names->Get(m_context, i).ToLocal(&name) || !name->IsName()) - continue; - if (name->IsString()) { - v8::Local descriptor; - bool success = m_global->GetOwnPropertyDescriptor(m_context, v8::Local::Cast(name)).ToLocal(&descriptor); - DCHECK(success); - } - } -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Console.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Console.h deleted file mode 100644 index 757a5e43789ff2..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Console.h +++ /dev/null @@ -1,91 +0,0 @@ -// 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 V8Console_h -#define V8Console_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include - -namespace v8_inspector { - -class InspectedContext; - -namespace protocol = blink::protocol; - -// Console API -// https://console.spec.whatwg.org/#console-interface -class V8Console { -public: - static v8::Local createConsole(InspectedContext*, bool hasMemoryAttribute); - static void clearInspectedContextIfNeeded(v8::Local, v8::Local console); - static v8::Local createCommandLineAPI(InspectedContext*); - - class CommandLineAPIScope { - PROTOCOL_DISALLOW_COPY(CommandLineAPIScope); - public: - CommandLineAPIScope(v8::Local, v8::Local commandLineAPI, v8::Local global); - ~CommandLineAPIScope(); - - private: - static void accessorGetterCallback(v8::Local, const v8::PropertyCallbackInfo&); - static void accessorSetterCallback(v8::Local, v8::Local, const v8::PropertyCallbackInfo&); - - v8::Local m_context; - v8::Local m_commandLineAPI; - v8::Local m_global; - v8::Local m_installedMethods; - bool m_cleanup; - }; - -private: - static void debugCallback(const v8::FunctionCallbackInfo&); - static void errorCallback(const v8::FunctionCallbackInfo&); - static void infoCallback(const v8::FunctionCallbackInfo&); - static void logCallback(const v8::FunctionCallbackInfo&); - static void warnCallback(const v8::FunctionCallbackInfo&); - static void dirCallback(const v8::FunctionCallbackInfo&); - static void dirxmlCallback(const v8::FunctionCallbackInfo&); - static void tableCallback(const v8::FunctionCallbackInfo&); - static void traceCallback(const v8::FunctionCallbackInfo&); - static void groupCallback(const v8::FunctionCallbackInfo&); - static void groupCollapsedCallback(const v8::FunctionCallbackInfo&); - static void groupEndCallback(const v8::FunctionCallbackInfo&); - static void clearCallback(const v8::FunctionCallbackInfo&); - static void countCallback(const v8::FunctionCallbackInfo&); - static void assertCallback(const v8::FunctionCallbackInfo&); - static void markTimelineCallback(const v8::FunctionCallbackInfo&); - static void profileCallback(const v8::FunctionCallbackInfo&); - static void profileEndCallback(const v8::FunctionCallbackInfo&); - static void timelineCallback(const v8::FunctionCallbackInfo&); - static void timelineEndCallback(const v8::FunctionCallbackInfo&); - static void timeCallback(const v8::FunctionCallbackInfo&); - static void timeEndCallback(const v8::FunctionCallbackInfo&); - static void timeStampCallback(const v8::FunctionCallbackInfo&); - // TODO(foolip): There is no spec for the Memory Info API, see blink-dev: - // https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ - static void memoryGetterCallback(const v8::FunctionCallbackInfo&); - static void memorySetterCallback(const v8::FunctionCallbackInfo&); - - // CommandLineAPI - static void keysCallback(const v8::FunctionCallbackInfo&); - static void valuesCallback(const v8::FunctionCallbackInfo&); - static void debugFunctionCallback(const v8::FunctionCallbackInfo&); - static void undebugFunctionCallback(const v8::FunctionCallbackInfo&); - static void monitorFunctionCallback(const v8::FunctionCallbackInfo&); - static void unmonitorFunctionCallback(const v8::FunctionCallbackInfo&); - static void lastEvaluationResultCallback(const v8::FunctionCallbackInfo&); - static void inspectCallback(const v8::FunctionCallbackInfo&); - static void copyCallback(const v8::FunctionCallbackInfo&); - static void inspectedObject(const v8::FunctionCallbackInfo&, unsigned num); - static void inspectedObject0(const v8::FunctionCallbackInfo& info) { inspectedObject(info, 0); } - static void inspectedObject1(const v8::FunctionCallbackInfo& info) { inspectedObject(info, 1); } - static void inspectedObject2(const v8::FunctionCallbackInfo& info) { inspectedObject(info, 2); } - static void inspectedObject3(const v8::FunctionCallbackInfo& info) { inspectedObject(info, 3); } - static void inspectedObject4(const v8::FunctionCallbackInfo& info) { inspectedObject(info, 4); } -}; - -} // namespace v8_inspector - -#endif // V8Console_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleAgentImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleAgentImpl.cpp deleted file mode 100644 index 820b254c939983..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleAgentImpl.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// 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 "platform/v8_inspector/V8ConsoleAgentImpl.h" - -#include "platform/v8_inspector/V8ConsoleMessage.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" - -namespace v8_inspector { - -namespace ConsoleAgentState { -static const char consoleEnabled[] = "consoleEnabled"; -} - -V8ConsoleAgentImpl::V8ConsoleAgentImpl(V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, protocol::DictionaryValue* state) - : m_session(session) - , m_state(state) - , m_frontend(frontendChannel) - , m_enabled(false) -{ -} - -V8ConsoleAgentImpl::~V8ConsoleAgentImpl() -{ -} - -void V8ConsoleAgentImpl::enable(ErrorString* errorString) -{ - if (m_enabled) - return; - m_state->setBoolean(ConsoleAgentState::consoleEnabled, true); - m_enabled = true; - m_session->inspector()->enableStackCapturingIfNeeded(); - reportAllMessages(); -} - -void V8ConsoleAgentImpl::disable(ErrorString* errorString) -{ - if (!m_enabled) - return; - m_session->inspector()->disableStackCapturingIfNeeded(); - m_state->setBoolean(ConsoleAgentState::consoleEnabled, false); - m_enabled = false; -} - -void V8ConsoleAgentImpl::clearMessages(ErrorString* errorString) -{ -} - -void V8ConsoleAgentImpl::restore() -{ - if (!m_state->booleanProperty(ConsoleAgentState::consoleEnabled, false)) - return; - ErrorString ignored; - enable(&ignored); -} - -void V8ConsoleAgentImpl::messageAdded(V8ConsoleMessage* message) -{ - if (m_enabled) - reportMessage(message, true); -} - -bool V8ConsoleAgentImpl::enabled() -{ - return m_enabled; -} - -void V8ConsoleAgentImpl::reportAllMessages() -{ - V8ConsoleMessageStorage* storage = m_session->inspector()->ensureConsoleMessageStorage(m_session->contextGroupId()); - for (const auto& message : storage->messages()) { - if (message->origin() == V8MessageOrigin::kConsole) - reportMessage(message.get(), false); - } -} - -void V8ConsoleAgentImpl::reportMessage(V8ConsoleMessage* message, bool generatePreview) -{ - DCHECK(message->origin() == V8MessageOrigin::kConsole); - message->reportToFrontend(&m_frontend); - m_frontend.flush(); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleAgentImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleAgentImpl.h deleted file mode 100644 index 0381394ff3f776..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleAgentImpl.h +++ /dev/null @@ -1,46 +0,0 @@ -// 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 V8ConsoleAgentImpl_h -#define V8ConsoleAgentImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/Console.h" - -namespace v8_inspector { - -class V8ConsoleMessage; -class V8InspectorSessionImpl; - -namespace protocol = blink::protocol; - -class V8ConsoleAgentImpl : public protocol::Console::Backend { - PROTOCOL_DISALLOW_COPY(V8ConsoleAgentImpl); -public: - V8ConsoleAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, protocol::DictionaryValue* state); - ~V8ConsoleAgentImpl() override; - - void enable(ErrorString*) override; - void disable(ErrorString*) override; - void clearMessages(ErrorString*) override; - - void restore(); - void messageAdded(V8ConsoleMessage*); - void reset(); - bool enabled(); - -private: - void reportAllMessages(); - void reportMessage(V8ConsoleMessage*, bool generatePreview); - - V8InspectorSessionImpl* m_session; - protocol::DictionaryValue* m_state; - protocol::Console::Frontend m_frontend; - bool m_enabled; -}; - -} // namespace v8_inspector - - -#endif // !defined(V8ConsoleAgentImpl_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleMessage.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleMessage.cpp deleted file mode 100644 index 160ec7417df6b9..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleMessage.cpp +++ /dev/null @@ -1,443 +0,0 @@ -// 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 "platform/v8_inspector/V8ConsoleMessage.h" - -#include "platform/v8_inspector/InspectedContext.h" -#include "platform/v8_inspector/V8ConsoleAgentImpl.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8RuntimeAgentImpl.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -namespace v8_inspector { - -namespace { - -String16 consoleAPITypeValue(ConsoleAPIType type) -{ - switch (type) { - case ConsoleAPIType::kLog: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log; - case ConsoleAPIType::kDebug: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug; - case ConsoleAPIType::kInfo: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Info; - case ConsoleAPIType::kError: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Error; - case ConsoleAPIType::kWarning: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Warning; - case ConsoleAPIType::kClear: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Clear; - case ConsoleAPIType::kDir: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dir; - case ConsoleAPIType::kDirXML: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dirxml; - case ConsoleAPIType::kTable: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Table; - case ConsoleAPIType::kTrace: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Trace; - case ConsoleAPIType::kStartGroup: return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroup; - case ConsoleAPIType::kStartGroupCollapsed: return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroupCollapsed; - case ConsoleAPIType::kEndGroup: return protocol::Runtime::ConsoleAPICalled::TypeEnum::EndGroup; - case ConsoleAPIType::kAssert: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Assert; - case ConsoleAPIType::kTimeEnd: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug; - case ConsoleAPIType::kCount: return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug; - } - return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log; -} - -const unsigned maxConsoleMessageCount = 1000; -const unsigned maxArrayItemsLimit = 10000; -const unsigned maxStackDepthLimit = 32; - -class V8ValueStringBuilder { -public: - static String16 toString(v8::Local value, v8::Isolate* isolate) - { - V8ValueStringBuilder builder(isolate); - if (!builder.append(value)) - return String16(); - return builder.toString(); - } - -private: - enum { - IgnoreNull = 1 << 0, - IgnoreUndefined = 1 << 1, - }; - - V8ValueStringBuilder(v8::Isolate* isolate) - : m_arrayLimit(maxArrayItemsLimit) - , m_isolate(isolate) - , m_tryCatch(isolate) - { - } - - bool append(v8::Local value, unsigned ignoreOptions = 0) - { - if (value.IsEmpty()) - return true; - if ((ignoreOptions & IgnoreNull) && value->IsNull()) - return true; - if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined()) - return true; - if (value->IsString()) - return append(v8::Local::Cast(value)); - if (value->IsStringObject()) - return append(v8::Local::Cast(value)->ValueOf()); - if (value->IsSymbol()) - return append(v8::Local::Cast(value)); - if (value->IsSymbolObject()) - return append(v8::Local::Cast(value)->ValueOf()); - if (value->IsNumberObject()) { - m_builder.append(String16::fromDoublePrecision6(v8::Local::Cast(value)->ValueOf())); - return true; - } - if (value->IsBooleanObject()) { - m_builder.append(v8::Local::Cast(value)->ValueOf() ? "true" : "false"); - return true; - } - if (value->IsArray()) - return append(v8::Local::Cast(value)); - if (value->IsProxy()) { - m_builder.append("[object Proxy]"); - return true; - } - if (value->IsObject() - && !value->IsDate() - && !value->IsFunction() - && !value->IsNativeError() - && !value->IsRegExp()) { - v8::Local object = v8::Local::Cast(value); - v8::Local stringValue; - if (object->ObjectProtoToString(m_isolate->GetCurrentContext()).ToLocal(&stringValue)) - return append(stringValue); - } - v8::Local stringValue; - if (!value->ToString(m_isolate->GetCurrentContext()).ToLocal(&stringValue)) - return false; - return append(stringValue); - } - - bool append(v8::Local array) - { - for (const auto& it : m_visitedArrays) { - if (it == array) - return true; - } - uint32_t length = array->Length(); - if (length > m_arrayLimit) - return false; - if (m_visitedArrays.size() > maxStackDepthLimit) - return false; - - bool result = true; - m_arrayLimit -= length; - m_visitedArrays.push_back(array); - for (uint32_t i = 0; i < length; ++i) { - if (i) - m_builder.append(','); - if (!append(array->Get(i), IgnoreNull | IgnoreUndefined)) { - result = false; - break; - } - } - m_visitedArrays.pop_back(); - return result; - } - - bool append(v8::Local symbol) - { - m_builder.append("Symbol("); - bool result = append(symbol->Name(), IgnoreUndefined); - m_builder.append(')'); - return result; - } - - bool append(v8::Local string) - { - if (m_tryCatch.HasCaught()) - return false; - if (!string.IsEmpty()) - m_builder.append(toProtocolString(string)); - return true; - } - - String16 toString() - { - if (m_tryCatch.HasCaught()) - return String16(); - return m_builder.toString(); - } - - uint32_t m_arrayLimit; - v8::Isolate* m_isolate; - String16Builder m_builder; - std::vector> m_visitedArrays; - v8::TryCatch m_tryCatch; -}; - -} // namespace - -V8ConsoleMessage::V8ConsoleMessage(V8MessageOrigin origin, double timestamp, const String16& message) - : m_origin(origin) - , m_timestamp(timestamp) - , m_message(message) - , m_lineNumber(0) - , m_columnNumber(0) - , m_scriptId(0) - , m_contextId(0) - , m_type(ConsoleAPIType::kLog) - , m_exceptionId(0) - , m_revokedExceptionId(0) -{ -} - -V8ConsoleMessage::~V8ConsoleMessage() -{ -} - -void V8ConsoleMessage::setLocation(const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr stackTrace, int scriptId) -{ - m_url = url; - m_lineNumber = lineNumber; - m_columnNumber = columnNumber; - m_stackTrace = std::move(stackTrace); - m_scriptId = scriptId; -} - -void V8ConsoleMessage::reportToFrontend(protocol::Console::Frontend* frontend) const -{ - DCHECK(m_origin == V8MessageOrigin::kConsole); - String16 level = protocol::Console::ConsoleMessage::LevelEnum::Log; - if (m_type == ConsoleAPIType::kDebug || m_type == ConsoleAPIType::kCount || m_type == ConsoleAPIType::kTimeEnd) - level = protocol::Console::ConsoleMessage::LevelEnum::Debug; - else if (m_type == ConsoleAPIType::kError || m_type == ConsoleAPIType::kAssert) - level = protocol::Console::ConsoleMessage::LevelEnum::Error; - else if (m_type == ConsoleAPIType::kWarning) - level = protocol::Console::ConsoleMessage::LevelEnum::Warning; - else if (m_type == ConsoleAPIType::kInfo) - level = protocol::Console::ConsoleMessage::LevelEnum::Info; - std::unique_ptr result = - protocol::Console::ConsoleMessage::create() - .setSource(protocol::Console::ConsoleMessage::SourceEnum::ConsoleApi) - .setLevel(level) - .setText(m_message) - .build(); - result->setLine(static_cast(m_lineNumber)); - result->setColumn(static_cast(m_columnNumber)); - result->setUrl(m_url); - frontend->messageAdded(std::move(result)); -} - -std::unique_ptr> V8ConsoleMessage::wrapArguments(V8InspectorSessionImpl* session, bool generatePreview) const -{ - if (!m_arguments.size() || !m_contextId) - return nullptr; - InspectedContext* inspectedContext = session->inspector()->getContext(session->contextGroupId(), m_contextId); - if (!inspectedContext) - return nullptr; - - v8::Isolate* isolate = inspectedContext->isolate(); - v8::HandleScope handles(isolate); - v8::Local context = inspectedContext->context(); - - std::unique_ptr> args = protocol::Array::create(); - if (m_type == ConsoleAPIType::kTable && generatePreview) { - v8::Local table = m_arguments[0]->Get(isolate); - v8::Local columns = m_arguments.size() > 1 ? m_arguments[1]->Get(isolate) : v8::Local(); - std::unique_ptr wrapped = session->wrapTable(context, table, columns); - if (wrapped) - args->addItem(std::move(wrapped)); - else - args = nullptr; - } else { - for (size_t i = 0; i < m_arguments.size(); ++i) { - std::unique_ptr wrapped = session->wrapObject(context, m_arguments[i]->Get(isolate), "console", generatePreview); - if (!wrapped) { - args = nullptr; - break; - } - args->addItem(std::move(wrapped)); - } - } - return args; -} - -void V8ConsoleMessage::reportToFrontend(protocol::Runtime::Frontend* frontend, V8InspectorSessionImpl* session, bool generatePreview) const -{ - if (m_origin == V8MessageOrigin::kException) { - std::unique_ptr exception = wrapException(session, generatePreview); - std::unique_ptr exceptionDetails = protocol::Runtime::ExceptionDetails::create() - .setExceptionId(m_exceptionId) - .setText(exception ? m_message : m_detailedMessage) - .setLineNumber(m_lineNumber ? m_lineNumber - 1 : 0) - .setColumnNumber(m_columnNumber ? m_columnNumber - 1 : 0) - .build(); - if (m_scriptId) - exceptionDetails->setScriptId(String16::fromInteger(m_scriptId)); - if (!m_url.isEmpty()) - exceptionDetails->setUrl(m_url); - if (m_stackTrace) - exceptionDetails->setStackTrace(m_stackTrace->buildInspectorObjectImpl()); - if (m_contextId) - exceptionDetails->setExecutionContextId(m_contextId); - if (exception) - exceptionDetails->setException(std::move(exception)); - frontend->exceptionThrown(m_timestamp, std::move(exceptionDetails)); - return; - } - if (m_origin == V8MessageOrigin::kRevokedException) { - frontend->exceptionRevoked(m_message, m_revokedExceptionId); - return; - } - if (m_origin == V8MessageOrigin::kConsole) { - std::unique_ptr> arguments = wrapArguments(session, generatePreview); - if (!arguments) { - arguments = protocol::Array::create(); - if (!m_message.isEmpty()) { - std::unique_ptr messageArg = protocol::Runtime::RemoteObject::create().setType(protocol::Runtime::RemoteObject::TypeEnum::String).build(); - messageArg->setValue(protocol::StringValue::create(m_message)); - arguments->addItem(std::move(messageArg)); - } - } - frontend->consoleAPICalled(consoleAPITypeValue(m_type), std::move(arguments), m_contextId, m_timestamp, m_stackTrace ? m_stackTrace->buildInspectorObjectImpl() : nullptr); - return; - } - NOTREACHED(); -} - -std::unique_ptr V8ConsoleMessage::wrapException(V8InspectorSessionImpl* session, bool generatePreview) const -{ - if (!m_arguments.size() || !m_contextId) - return nullptr; - DCHECK_EQ(1u, m_arguments.size()); - InspectedContext* inspectedContext = session->inspector()->getContext(session->contextGroupId(), m_contextId); - if (!inspectedContext) - return nullptr; - - v8::Isolate* isolate = inspectedContext->isolate(); - v8::HandleScope handles(isolate); - // TODO(dgozman): should we use different object group? - return session->wrapObject(inspectedContext->context(), m_arguments[0]->Get(isolate), "console", generatePreview); -} - -V8MessageOrigin V8ConsoleMessage::origin() const -{ - return m_origin; -} - -ConsoleAPIType V8ConsoleMessage::type() const -{ - return m_type; -} - -// static -std::unique_ptr V8ConsoleMessage::createForConsoleAPI(double timestamp, ConsoleAPIType type, const std::vector>& arguments, std::unique_ptr stackTrace, InspectedContext* context) -{ - std::unique_ptr message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, String16())); - if (stackTrace && !stackTrace->isEmpty()) { - message->m_url = stackTrace->topSourceURL(); - message->m_lineNumber = stackTrace->topLineNumber(); - message->m_columnNumber = stackTrace->topColumnNumber(); - } - message->m_stackTrace = std::move(stackTrace); - message->m_type = type; - message->m_contextId = context->contextId(); - for (size_t i = 0; i < arguments.size(); ++i) - message->m_arguments.push_back(wrapUnique(new v8::Global(context->isolate(), arguments.at(i)))); - if (arguments.size()) - message->m_message = V8ValueStringBuilder::toString(arguments[0], context->isolate()); - - V8ConsoleAPIType clientType = V8ConsoleAPIType::kLog; - if (type == ConsoleAPIType::kDebug || type == ConsoleAPIType::kCount || type == ConsoleAPIType::kTimeEnd) - clientType = V8ConsoleAPIType::kDebug; - else if (type == ConsoleAPIType::kError || type == ConsoleAPIType::kAssert) - clientType = V8ConsoleAPIType::kError; - else if (type == ConsoleAPIType::kWarning) - clientType = V8ConsoleAPIType::kWarning; - else if (type == ConsoleAPIType::kInfo) - clientType = V8ConsoleAPIType::kInfo; - else if (type == ConsoleAPIType::kClear) - clientType = V8ConsoleAPIType::kClear; - context->inspector()->client()->consoleAPIMessage(context->contextGroupId(), clientType, message->m_message, message->m_url, message->m_lineNumber, message->m_columnNumber, message->m_stackTrace.get()); - - return message; -} - -// static -std::unique_ptr V8ConsoleMessage::createForException(double timestamp, const String16& detailedMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr stackTrace, int scriptId, v8::Isolate* isolate, const String16& message, int contextId, v8::Local exception, unsigned exceptionId) -{ - std::unique_ptr consoleMessage = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kException, timestamp, message)); - consoleMessage->setLocation(url, lineNumber, columnNumber, std::move(stackTrace), scriptId); - consoleMessage->m_exceptionId = exceptionId; - consoleMessage->m_detailedMessage = detailedMessage; - if (contextId && !exception.IsEmpty()) { - consoleMessage->m_contextId = contextId; - consoleMessage->m_arguments.push_back(wrapUnique(new v8::Global(isolate, exception))); - } - return consoleMessage; -} - -// static -std::unique_ptr V8ConsoleMessage::createForRevokedException(double timestamp, const String16& messageText, unsigned revokedExceptionId) -{ - std::unique_ptr message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kRevokedException, timestamp, messageText)); - message->m_revokedExceptionId = revokedExceptionId; - return message; -} - -void V8ConsoleMessage::contextDestroyed(int contextId) -{ - if (contextId != m_contextId) - return; - m_contextId = 0; - if (m_message.isEmpty()) - m_message = ""; - Arguments empty; - m_arguments.swap(empty); -} - -// ------------------------ V8ConsoleMessageStorage ---------------------------- - -V8ConsoleMessageStorage::V8ConsoleMessageStorage(V8InspectorImpl* inspector, int contextGroupId) - : m_inspector(inspector) - , m_contextGroupId(contextGroupId) - , m_expiredCount(0) -{ -} - -V8ConsoleMessageStorage::~V8ConsoleMessageStorage() -{ - clear(); -} - -void V8ConsoleMessageStorage::addMessage(std::unique_ptr message) -{ - if (message->type() == ConsoleAPIType::kClear) - clear(); - - V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup(m_contextGroupId); - if (session) { - if (message->origin() == V8MessageOrigin::kConsole) - session->consoleAgent()->messageAdded(message.get()); - session->runtimeAgent()->messageAdded(message.get()); - } - - DCHECK(m_messages.size() <= maxConsoleMessageCount); - if (m_messages.size() == maxConsoleMessageCount) { - ++m_expiredCount; - m_messages.pop_front(); - } - m_messages.push_back(std::move(message)); -} - -void V8ConsoleMessageStorage::clear() -{ - m_messages.clear(); - m_expiredCount = 0; - if (V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup(m_contextGroupId)) - session->releaseObjectGroup("console"); -} - -void V8ConsoleMessageStorage::contextDestroyed(int contextId) -{ - for (size_t i = 0; i < m_messages.size(); ++i) - m_messages[i]->contextDestroyed(contextId); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleMessage.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleMessage.h deleted file mode 100644 index 941b61609a1401..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ConsoleMessage.h +++ /dev/null @@ -1,109 +0,0 @@ -// 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 V8ConsoleMessage_h -#define V8ConsoleMessage_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/Console.h" -#include "platform/v8_inspector/protocol/Runtime.h" -#include -#include - -namespace v8_inspector { - -class InspectedContext; -class V8InspectorImpl; -class V8InspectorSessionImpl; -class V8StackTraceImpl; - -namespace protocol = blink::protocol; - -enum class V8MessageOrigin { kConsole, kException, kRevokedException }; - -enum class ConsoleAPIType { kLog, kDebug, kInfo, kError, kWarning, kDir, kDirXML, kTable, kTrace, kStartGroup, kStartGroupCollapsed, kEndGroup, kClear, kAssert, kTimeEnd, kCount }; - -class V8ConsoleMessage { -public: - ~V8ConsoleMessage(); - - static std::unique_ptr createForConsoleAPI( - double timestamp, - ConsoleAPIType, - const std::vector>& arguments, - std::unique_ptr, - InspectedContext*); - - static std::unique_ptr createForException( - double timestamp, - const String16& detailedMessage, - const String16& url, - unsigned lineNumber, - unsigned columnNumber, - std::unique_ptr, - int scriptId, - v8::Isolate*, - const String16& message, - int contextId, - v8::Local exception, - unsigned exceptionId); - - static std::unique_ptr createForRevokedException( - double timestamp, - const String16& message, - unsigned revokedExceptionId); - - V8MessageOrigin origin() const; - void reportToFrontend(protocol::Console::Frontend*) const; - void reportToFrontend(protocol::Runtime::Frontend*, V8InspectorSessionImpl*, bool generatePreview) const; - ConsoleAPIType type() const; - void contextDestroyed(int contextId); - -private: - V8ConsoleMessage(V8MessageOrigin, double timestamp, const String16& message); - - using Arguments = std::vector>>; - std::unique_ptr> wrapArguments(V8InspectorSessionImpl*, bool generatePreview) const; - std::unique_ptr wrapException(V8InspectorSessionImpl*, bool generatePreview) const; - void setLocation(const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr, int scriptId); - - V8MessageOrigin m_origin; - double m_timestamp; - String16 m_message; - String16 m_url; - unsigned m_lineNumber; - unsigned m_columnNumber; - std::unique_ptr m_stackTrace; - int m_scriptId; - int m_contextId; - ConsoleAPIType m_type; - unsigned m_exceptionId; - unsigned m_revokedExceptionId; - Arguments m_arguments; - String16 m_detailedMessage; -}; - -class V8ConsoleMessageStorage { -public: - V8ConsoleMessageStorage(V8InspectorImpl*, int contextGroupId); - ~V8ConsoleMessageStorage(); - - int contextGroupId() { return m_contextGroupId; } - int expiredCount() { return m_expiredCount; } - const std::deque>& messages() const { return m_messages; } - - void addMessage(std::unique_ptr); - void contextDestroyed(int contextId); - void clear(); - -private: - V8InspectorImpl* m_inspector; - int m_contextGroupId; - int m_expiredCount; - std::deque> m_messages; -}; - -} // namespace v8_inspector - -#endif // V8ConsoleMessage_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Debugger.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Debugger.cpp deleted file mode 100644 index 65fa210a14eccf..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Debugger.cpp +++ /dev/null @@ -1,839 +0,0 @@ -// 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 "platform/v8_inspector/V8Debugger.h" - -#include "platform/v8_inspector/DebuggerScript.h" -#include "platform/v8_inspector/ScriptBreakpoint.h" -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8DebuggerAgentImpl.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InternalValueType.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/V8ValueCopier.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -namespace v8_inspector { - -namespace { -const char stepIntoV8MethodName[] = "stepIntoStatement"; -const char stepOutV8MethodName[] = "stepOutOfFunction"; -static const char v8AsyncTaskEventEnqueue[] = "enqueue"; -static const char v8AsyncTaskEventWillHandle[] = "willHandle"; -static const char v8AsyncTaskEventDidHandle[] = "didHandle"; - -inline v8::Local v8Boolean(bool value, v8::Isolate* isolate) -{ - return value ? v8::True(isolate) : v8::False(isolate); -} - -} // namespace - -static bool inLiveEditScope = false; - -v8::MaybeLocal V8Debugger::callDebuggerMethod(const char* functionName, int argc, v8::Local argv[]) -{ - v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local debuggerScript = m_debuggerScript.Get(m_isolate); - v8::Local function = v8::Local::Cast(debuggerScript->Get(toV8StringInternalized(m_isolate, functionName))); - DCHECK(m_isolate->InContext()); - return function->Call(m_isolate->GetCurrentContext(), debuggerScript, argc, argv); -} - -V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) - : m_isolate(isolate) - , m_inspector(inspector) - , m_lastContextId(0) - , m_enableCount(0) - , m_breakpointsActivated(true) - , m_runningNestedMessageLoop(false) - , m_ignoreScriptParsedEventsCounter(0) - , m_maxAsyncCallStackDepth(0) -{ -} - -V8Debugger::~V8Debugger() -{ -} - -void V8Debugger::enable() -{ - if (m_enableCount++) - return; - DCHECK(!enabled()); - v8::HandleScope scope(m_isolate); - v8::Debug::SetDebugEventListener(m_isolate, &V8Debugger::v8DebugEventCallback, v8::External::New(m_isolate, this)); - m_debuggerContext.Reset(m_isolate, v8::Debug::GetDebugContext(m_isolate)); - compileDebuggerScript(); -} - -void V8Debugger::disable() -{ - if (--m_enableCount) - return; - DCHECK(enabled()); - clearBreakpoints(); - m_debuggerScript.Reset(); - m_debuggerContext.Reset(); - allAsyncTasksCanceled(); - v8::Debug::SetDebugEventListener(m_isolate, nullptr); -} - -bool V8Debugger::enabled() const -{ - return !m_debuggerScript.IsEmpty(); -} - -// static -int V8Debugger::contextId(v8::Local context) -{ - v8::Local data = context->GetEmbedderData(static_cast(v8::Context::kDebugIdIndex)); - if (data.IsEmpty() || !data->IsString()) - return 0; - String16 dataString = toProtocolString(data.As()); - if (dataString.isEmpty()) - return 0; - size_t commaPos = dataString.find(","); - if (commaPos == String16::kNotFound) - return 0; - size_t commaPos2 = dataString.find(",", commaPos + 1); - if (commaPos2 == String16::kNotFound) - return 0; - return dataString.substring(commaPos + 1, commaPos2 - commaPos - 1).toInteger(); -} - -// static -int V8Debugger::getGroupId(v8::Local context) -{ - v8::Local data = context->GetEmbedderData(static_cast(v8::Context::kDebugIdIndex)); - if (data.IsEmpty() || !data->IsString()) - return 0; - String16 dataString = toProtocolString(data.As()); - if (dataString.isEmpty()) - return 0; - size_t commaPos = dataString.find(","); - if (commaPos == String16::kNotFound) - return 0; - return dataString.substring(0, commaPos).toInteger(); -} - -void V8Debugger::getCompiledScripts(int contextGroupId, std::vector>& result) -{ - v8::HandleScope scope(m_isolate); - v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local debuggerScript = m_debuggerScript.Get(m_isolate); - DCHECK(!debuggerScript->IsUndefined()); - v8::Local getScriptsFunction = v8::Local::Cast(debuggerScript->Get(toV8StringInternalized(m_isolate, "getScripts"))); - v8::Local argv[] = { v8::Integer::New(m_isolate, contextGroupId) }; - v8::Local value; - if (!getScriptsFunction->Call(debuggerContext(), debuggerScript, PROTOCOL_ARRAY_LENGTH(argv), argv).ToLocal(&value)) - return; - DCHECK(value->IsArray()); - v8::Local scriptsArray = v8::Local::Cast(value); - result.reserve(scriptsArray->Length()); - for (unsigned i = 0; i < scriptsArray->Length(); ++i) { - v8::Local scriptObject = v8::Local::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i))); - result.push_back(wrapUnique(new V8DebuggerScript(m_isolate, scriptObject, inLiveEditScope))); - } -} - -String16 V8Debugger::setBreakpoint(const String16& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber) -{ - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local info = v8::Object::New(m_isolate); - info->Set(toV8StringInternalized(m_isolate, "sourceID"), toV8String(m_isolate, sourceID)); - info->Set(toV8StringInternalized(m_isolate, "lineNumber"), v8::Integer::New(m_isolate, scriptBreakpoint.lineNumber)); - info->Set(toV8StringInternalized(m_isolate, "columnNumber"), v8::Integer::New(m_isolate, scriptBreakpoint.columnNumber)); - info->Set(toV8StringInternalized(m_isolate, "condition"), toV8String(m_isolate, scriptBreakpoint.condition)); - - v8::Local setBreakpointFunction = v8::Local::Cast(m_debuggerScript.Get(m_isolate)->Get(toV8StringInternalized(m_isolate, "setBreakpoint"))); - v8::Local breakpointId = v8::Debug::Call(debuggerContext(), setBreakpointFunction, info).ToLocalChecked(); - if (!breakpointId->IsString()) - return ""; - *actualLineNumber = info->Get(toV8StringInternalized(m_isolate, "lineNumber"))->Int32Value(); - *actualColumnNumber = info->Get(toV8StringInternalized(m_isolate, "columnNumber"))->Int32Value(); - return toProtocolString(breakpointId.As()); -} - -void V8Debugger::removeBreakpoint(const String16& breakpointId) -{ - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local info = v8::Object::New(m_isolate); - info->Set(toV8StringInternalized(m_isolate, "breakpointId"), toV8String(m_isolate, breakpointId)); - - v8::Local removeBreakpointFunction = v8::Local::Cast(m_debuggerScript.Get(m_isolate)->Get(toV8StringInternalized(m_isolate, "removeBreakpoint"))); - v8::Debug::Call(debuggerContext(), removeBreakpointFunction, info).ToLocalChecked(); -} - -void V8Debugger::clearBreakpoints() -{ - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local clearBreakpoints = v8::Local::Cast(m_debuggerScript.Get(m_isolate)->Get(toV8StringInternalized(m_isolate, "clearBreakpoints"))); - v8::Debug::Call(debuggerContext(), clearBreakpoints).ToLocalChecked(); -} - -void V8Debugger::setBreakpointsActivated(bool activated) -{ - if (!enabled()) { - NOTREACHED(); - return; - } - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local info = v8::Object::New(m_isolate); - info->Set(toV8StringInternalized(m_isolate, "enabled"), v8::Boolean::New(m_isolate, activated)); - v8::Local setBreakpointsActivated = v8::Local::Cast(m_debuggerScript.Get(m_isolate)->Get(toV8StringInternalized(m_isolate, "setBreakpointsActivated"))); - v8::Debug::Call(debuggerContext(), setBreakpointsActivated, info).ToLocalChecked(); - - m_breakpointsActivated = activated; -} - -V8Debugger::PauseOnExceptionsState V8Debugger::getPauseOnExceptionsState() -{ - DCHECK(enabled()); - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local argv[] = { v8::Undefined(m_isolate) }; - v8::Local result = callDebuggerMethod("pauseOnExceptionsState", 0, argv).ToLocalChecked(); - return static_cast(result->Int32Value()); -} - -void V8Debugger::setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState) -{ - DCHECK(enabled()); - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local argv[] = { v8::Int32::New(m_isolate, pauseOnExceptionsState) }; - callDebuggerMethod("setPauseOnExceptionsState", 1, argv); -} - -void V8Debugger::setPauseOnNextStatement(bool pause) -{ - if (m_runningNestedMessageLoop) - return; - if (pause) - v8::Debug::DebugBreak(m_isolate); - else - v8::Debug::CancelDebugBreak(m_isolate); -} - -bool V8Debugger::canBreakProgram() -{ - if (!m_breakpointsActivated) - return false; - return m_isolate->InContext(); -} - -void V8Debugger::breakProgram() -{ - if (isPaused()) { - DCHECK(!m_runningNestedMessageLoop); - v8::Local exception; - v8::Local hitBreakpoints; - handleProgramBreak(m_pausedContext, m_executionState, exception, hitBreakpoints); - return; - } - - if (!canBreakProgram()) - return; - - v8::HandleScope scope(m_isolate); - v8::Local breakFunction; - if (!V8_FUNCTION_NEW_REMOVE_PROTOTYPE(m_isolate->GetCurrentContext(), &V8Debugger::breakProgramCallback, v8::External::New(m_isolate, this), 0).ToLocal(&breakFunction)) - return; - v8::Debug::Call(debuggerContext(), breakFunction).ToLocalChecked(); -} - -void V8Debugger::continueProgram() -{ - if (isPaused()) - m_inspector->client()->quitMessageLoopOnPause(); - m_pausedContext.Clear(); - m_executionState.Clear(); -} - -void V8Debugger::stepIntoStatement() -{ - DCHECK(isPaused()); - DCHECK(!m_executionState.IsEmpty()); - v8::HandleScope handleScope(m_isolate); - v8::Local argv[] = { m_executionState }; - callDebuggerMethod(stepIntoV8MethodName, 1, argv); - continueProgram(); -} - -void V8Debugger::stepOverStatement() -{ - DCHECK(isPaused()); - DCHECK(!m_executionState.IsEmpty()); - v8::HandleScope handleScope(m_isolate); - v8::Local argv[] = { m_executionState }; - callDebuggerMethod("stepOverStatement", 1, argv); - continueProgram(); -} - -void V8Debugger::stepOutOfFunction() -{ - DCHECK(isPaused()); - DCHECK(!m_executionState.IsEmpty()); - v8::HandleScope handleScope(m_isolate); - v8::Local argv[] = { m_executionState }; - callDebuggerMethod(stepOutV8MethodName, 1, argv); - continueProgram(); -} - -void V8Debugger::clearStepping() -{ - DCHECK(enabled()); - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local argv[] = { v8::Undefined(m_isolate) }; - callDebuggerMethod("clearStepping", 0, argv); -} - -bool V8Debugger::setScriptSource(const String16& sourceID, v8::Local newSource, bool dryRun, ErrorString* error, Maybe* exceptionDetails, JavaScriptCallFrames* newCallFrames, Maybe* stackChanged) -{ - class EnableLiveEditScope { - public: - explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) - { - v8::Debug::SetLiveEditEnabled(m_isolate, true); - inLiveEditScope = true; - } - ~EnableLiveEditScope() - { - v8::Debug::SetLiveEditEnabled(m_isolate, false); - inLiveEditScope = false; - } - private: - v8::Isolate* m_isolate; - }; - - DCHECK(enabled()); - v8::HandleScope scope(m_isolate); - - std::unique_ptr contextScope; - if (!isPaused()) - contextScope = wrapUnique(new v8::Context::Scope(debuggerContext())); - - v8::Local argv[] = { toV8String(m_isolate, sourceID), newSource, v8Boolean(dryRun, m_isolate) }; - - v8::Local v8result; - { - EnableLiveEditScope enableLiveEditScope(m_isolate); - v8::TryCatch tryCatch(m_isolate); - tryCatch.SetVerbose(false); - v8::MaybeLocal maybeResult = callDebuggerMethod("liveEditScriptSource", 3, argv); - if (tryCatch.HasCaught()) { - v8::Local message = tryCatch.Message(); - if (!message.IsEmpty()) - *error = toProtocolStringWithTypeCheck(message->Get()); - else - *error = "Unknown error."; - return false; - } - v8result = maybeResult.ToLocalChecked(); - } - DCHECK(!v8result.IsEmpty()); - v8::Local resultTuple = v8result->ToObject(m_isolate); - int code = static_cast(resultTuple->Get(0)->ToInteger(m_isolate)->Value()); - switch (code) { - case 0: - { - *stackChanged = resultTuple->Get(1)->BooleanValue(); - // Call stack may have changed after if the edited function was on the stack. - if (!dryRun && isPaused()) { - JavaScriptCallFrames frames = currentCallFrames(); - newCallFrames->swap(frames); - } - return true; - } - // Compile error. - case 1: - { - *exceptionDetails = protocol::Runtime::ExceptionDetails::create() - .setExceptionId(m_inspector->nextExceptionId()) - .setText(toProtocolStringWithTypeCheck(resultTuple->Get(2))) - .setLineNumber(resultTuple->Get(3)->ToInteger(m_isolate)->Value() - 1) - .setColumnNumber(resultTuple->Get(4)->ToInteger(m_isolate)->Value() - 1).build(); - return false; - } - } - *error = "Unknown error."; - return false; -} - -JavaScriptCallFrames V8Debugger::currentCallFrames(int limit) -{ - if (!m_isolate->InContext()) - return JavaScriptCallFrames(); - v8::Local currentCallFramesV8; - if (m_executionState.IsEmpty()) { - v8::Local currentCallFramesFunction = v8::Local::Cast(m_debuggerScript.Get(m_isolate)->Get(toV8StringInternalized(m_isolate, "currentCallFrames"))); - currentCallFramesV8 = v8::Debug::Call(debuggerContext(), currentCallFramesFunction, v8::Integer::New(m_isolate, limit)).ToLocalChecked(); - } else { - v8::Local argv[] = { m_executionState, v8::Integer::New(m_isolate, limit) }; - currentCallFramesV8 = callDebuggerMethod("currentCallFrames", PROTOCOL_ARRAY_LENGTH(argv), argv).ToLocalChecked(); - } - DCHECK(!currentCallFramesV8.IsEmpty()); - if (!currentCallFramesV8->IsArray()) - return JavaScriptCallFrames(); - v8::Local callFramesArray = currentCallFramesV8.As(); - JavaScriptCallFrames callFrames; - for (size_t i = 0; i < callFramesArray->Length(); ++i) { - v8::Local callFrameValue; - if (!callFramesArray->Get(debuggerContext(), i).ToLocal(&callFrameValue)) - return JavaScriptCallFrames(); - if (!callFrameValue->IsObject()) - return JavaScriptCallFrames(); - v8::Local callFrameObject = callFrameValue.As(); - callFrames.push_back(JavaScriptCallFrame::create(debuggerContext(), v8::Local::Cast(callFrameObject))); - } - return callFrames; -} - -static V8Debugger* toV8Debugger(v8::Local data) -{ - void* p = v8::Local::Cast(data)->Value(); - return static_cast(p); -} - -void V8Debugger::breakProgramCallback(const v8::FunctionCallbackInfo& info) -{ - DCHECK_EQ(info.Length(), 2); - V8Debugger* thisPtr = toV8Debugger(info.Data()); - if (!thisPtr->enabled()) - return; - v8::Local pausedContext = thisPtr->m_isolate->GetCurrentContext(); - v8::Local exception; - v8::Local hitBreakpoints; - thisPtr->handleProgramBreak(pausedContext, v8::Local::Cast(info[0]), exception, hitBreakpoints); -} - -void V8Debugger::handleProgramBreak(v8::Local pausedContext, v8::Local executionState, v8::Local exception, v8::Local hitBreakpointNumbers, bool isPromiseRejection) -{ - // Don't allow nested breaks. - if (m_runningNestedMessageLoop) - return; - - V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup(getGroupId(pausedContext)); - if (!agent) - return; - - std::vector breakpointIds; - if (!hitBreakpointNumbers.IsEmpty()) { - breakpointIds.reserve(hitBreakpointNumbers->Length()); - for (size_t i = 0; i < hitBreakpointNumbers->Length(); i++) { - v8::Local hitBreakpointNumber = hitBreakpointNumbers->Get(i); - DCHECK(!hitBreakpointNumber.IsEmpty() && hitBreakpointNumber->IsInt32()); - breakpointIds.push_back(String16::fromInteger(hitBreakpointNumber->Int32Value())); - } - } - - m_pausedContext = pausedContext; - m_executionState = executionState; - V8DebuggerAgentImpl::SkipPauseRequest result = agent->didPause(pausedContext, exception, breakpointIds, isPromiseRejection); - if (result == V8DebuggerAgentImpl::RequestNoSkip) { - m_runningNestedMessageLoop = true; - int groupId = getGroupId(pausedContext); - DCHECK(groupId); - m_inspector->client()->runMessageLoopOnPause(groupId); - // The agent may have been removed in the nested loop. - agent = m_inspector->enabledDebuggerAgentForGroup(getGroupId(pausedContext)); - if (agent) - agent->didContinue(); - m_runningNestedMessageLoop = false; - } - m_pausedContext.Clear(); - m_executionState.Clear(); - - if (result == V8DebuggerAgentImpl::RequestStepFrame) { - v8::Local argv[] = { executionState }; - callDebuggerMethod("stepFrameStatement", 1, argv); - } else if (result == V8DebuggerAgentImpl::RequestStepInto) { - v8::Local argv[] = { executionState }; - callDebuggerMethod(stepIntoV8MethodName, 1, argv); - } else if (result == V8DebuggerAgentImpl::RequestStepOut) { - v8::Local argv[] = { executionState }; - callDebuggerMethod(stepOutV8MethodName, 1, argv); - } -} - -void V8Debugger::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails) -{ - V8Debugger* thisPtr = toV8Debugger(eventDetails.GetCallbackData()); - thisPtr->handleV8DebugEvent(eventDetails); -} - -v8::Local V8Debugger::callInternalGetterFunction(v8::Local object, const char* functionName) -{ - v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local getterValue = object->Get(toV8StringInternalized(m_isolate, functionName)); - DCHECK(!getterValue.IsEmpty() && getterValue->IsFunction()); - return v8::Local::Cast(getterValue)->Call(m_isolate->GetCurrentContext(), object, 0, 0).ToLocalChecked(); -} - -void V8Debugger::handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails) -{ - if (!enabled()) - return; - v8::DebugEvent event = eventDetails.GetEvent(); - if (event != v8::AsyncTaskEvent && event != v8::Break && event != v8::Exception && event != v8::AfterCompile && event != v8::BeforeCompile && event != v8::CompileError) - return; - - v8::Local eventContext = eventDetails.GetEventContext(); - DCHECK(!eventContext.IsEmpty()); - - if (event == v8::AsyncTaskEvent) { - v8::HandleScope scope(m_isolate); - handleV8AsyncTaskEvent(eventContext, eventDetails.GetExecutionState(), eventDetails.GetEventData()); - return; - } - - V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup(getGroupId(eventContext)); - if (agent) { - v8::HandleScope scope(m_isolate); - if (m_ignoreScriptParsedEventsCounter == 0 && (event == v8::AfterCompile || event == v8::CompileError)) { - v8::Context::Scope contextScope(debuggerContext()); - v8::Local argv[] = { eventDetails.GetEventData() }; - v8::Local value = callDebuggerMethod("getAfterCompileScript", 1, argv).ToLocalChecked(); - if (value->IsNull()) - return; - DCHECK(value->IsObject()); - v8::Local scriptObject = v8::Local::Cast(value); - agent->didParseSource(wrapUnique(new V8DebuggerScript(m_isolate, scriptObject, inLiveEditScope)), event == v8::AfterCompile); - } else if (event == v8::Exception) { - v8::Local eventData = eventDetails.GetEventData(); - v8::Local exception = callInternalGetterFunction(eventData, "exception"); - v8::Local promise = callInternalGetterFunction(eventData, "promise"); - bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); - handleProgramBreak(eventContext, eventDetails.GetExecutionState(), exception, v8::Local(), isPromiseRejection); - } else if (event == v8::Break) { - v8::Local argv[] = { eventDetails.GetEventData() }; - v8::Local hitBreakpoints = callDebuggerMethod("getBreakpointNumbers", 1, argv).ToLocalChecked(); - DCHECK(hitBreakpoints->IsArray()); - handleProgramBreak(eventContext, eventDetails.GetExecutionState(), v8::Local(), hitBreakpoints.As()); - } - } -} - -void V8Debugger::handleV8AsyncTaskEvent(v8::Local context, v8::Local executionState, v8::Local eventData) -{ - if (!m_maxAsyncCallStackDepth) - return; - - String16 type = toProtocolStringWithTypeCheck(callInternalGetterFunction(eventData, "type")); - String16 name = toProtocolStringWithTypeCheck(callInternalGetterFunction(eventData, "name")); - int id = callInternalGetterFunction(eventData, "id")->ToInteger(m_isolate)->Value(); - // The scopes for the ids are defined by the eventData.name namespaces. There are currently two namespaces: "Object." and "Promise.". - void* ptr = reinterpret_cast(id * 4 + (name[0] == 'P' ? 2 : 0) + 1); - if (type == v8AsyncTaskEventEnqueue) - asyncTaskScheduled(name, ptr, false); - else if (type == v8AsyncTaskEventWillHandle) - asyncTaskStarted(ptr); - else if (type == v8AsyncTaskEventDidHandle) - asyncTaskFinished(ptr); - else - NOTREACHED(); -} - -V8StackTraceImpl* V8Debugger::currentAsyncCallChain() -{ - if (!m_currentStacks.size()) - return nullptr; - return m_currentStacks.back().get(); -} - -void V8Debugger::compileDebuggerScript() -{ - if (!m_debuggerScript.IsEmpty()) { - NOTREACHED(); - return; - } - - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local scriptValue = v8::String::NewFromUtf8(m_isolate, DebuggerScript_js, v8::NewStringType::kInternalized, sizeof(DebuggerScript_js)).ToLocalChecked(); - v8::Local value; - if (!m_inspector->compileAndRunInternalScript(debuggerContext(), scriptValue).ToLocal(&value)) { - NOTREACHED(); - return; - } - DCHECK(value->IsObject()); - m_debuggerScript.Reset(m_isolate, value.As()); -} - -v8::Local V8Debugger::debuggerContext() const -{ - DCHECK(!m_debuggerContext.IsEmpty()); - return m_debuggerContext.Get(m_isolate); -} - -v8::MaybeLocal V8Debugger::functionScopes(v8::Local context, v8::Local function) -{ - if (!enabled()) { - NOTREACHED(); - return v8::Local::New(m_isolate, v8::Undefined(m_isolate)); - } - v8::Local argv[] = { function }; - v8::Local scopesValue; - if (!callDebuggerMethod("getFunctionScopes", 1, argv).ToLocal(&scopesValue)) - return v8::MaybeLocal(); - v8::Local copied; - if (!copyValueFromDebuggerContext(m_isolate, debuggerContext(), context, scopesValue).ToLocal(&copied) || !copied->IsArray()) - return v8::MaybeLocal(); - if (!markAsInternal(context, v8::Local::Cast(copied), V8InternalValueType::kScopeList)) - return v8::MaybeLocal(); - if (!markArrayEntriesAsInternal(context, v8::Local::Cast(copied), V8InternalValueType::kScope)) - return v8::MaybeLocal(); - return copied; -} - -v8::MaybeLocal V8Debugger::internalProperties(v8::Local context, v8::Local value) -{ - v8::Local properties; - if (!v8::Debug::GetInternalProperties(m_isolate, value).ToLocal(&properties)) - return v8::MaybeLocal(); - if (value->IsFunction()) { - v8::Local function = value.As(); - v8::Local location = functionLocation(context, function); - if (location->IsObject()) { - properties->Set(properties->Length(), toV8StringInternalized(m_isolate, "[[FunctionLocation]]")); - properties->Set(properties->Length(), location); - } - if (function->IsGeneratorFunction()) { - properties->Set(properties->Length(), toV8StringInternalized(m_isolate, "[[IsGenerator]]")); - properties->Set(properties->Length(), v8::True(m_isolate)); - } - } - if (!enabled()) - return properties; - if (value->IsMap() || value->IsWeakMap() || value->IsSet() || value->IsWeakSet() || value->IsSetIterator() || value->IsMapIterator()) { - v8::Local entries = collectionEntries(context, v8::Local::Cast(value)); - if (entries->IsArray()) { - properties->Set(properties->Length(), toV8StringInternalized(m_isolate, "[[Entries]]")); - properties->Set(properties->Length(), entries); - } - } - if (value->IsGeneratorObject()) { - v8::Local location = generatorObjectLocation(context, v8::Local::Cast(value)); - if (location->IsObject()) { - properties->Set(properties->Length(), toV8StringInternalized(m_isolate, "[[GeneratorLocation]]")); - properties->Set(properties->Length(), location); - } - } - if (value->IsFunction()) { - v8::Local function = value.As(); - v8::Local boundFunction = function->GetBoundFunction(); - v8::Local scopes; - if (boundFunction->IsUndefined() && functionScopes(context, function).ToLocal(&scopes)) { - properties->Set(properties->Length(), toV8StringInternalized(m_isolate, "[[Scopes]]")); - properties->Set(properties->Length(), scopes); - } - } - return properties; -} - -v8::Local V8Debugger::collectionEntries(v8::Local context, v8::Local object) -{ - if (!enabled()) { - NOTREACHED(); - return v8::Undefined(m_isolate); - } - v8::Local argv[] = { object }; - v8::Local entriesValue = callDebuggerMethod("getCollectionEntries", 1, argv).ToLocalChecked(); - v8::Local copied; - if (!copyValueFromDebuggerContext(m_isolate, debuggerContext(), context, entriesValue).ToLocal(&copied) || !copied->IsArray()) - return v8::Undefined(m_isolate); - if (!markArrayEntriesAsInternal(context, v8::Local::Cast(copied), V8InternalValueType::kEntry)) - return v8::Undefined(m_isolate); - return copied; -} - -v8::Local V8Debugger::generatorObjectLocation(v8::Local context, v8::Local object) -{ - if (!enabled()) { - NOTREACHED(); - return v8::Null(m_isolate); - } - v8::Local argv[] = { object }; - v8::Local location = callDebuggerMethod("getGeneratorObjectLocation", 1, argv).ToLocalChecked(); - v8::Local copied; - if (!copyValueFromDebuggerContext(m_isolate, debuggerContext(), context, location).ToLocal(&copied) || !copied->IsObject()) - return v8::Null(m_isolate); - if (!markAsInternal(context, v8::Local::Cast(copied), V8InternalValueType::kLocation)) - return v8::Null(m_isolate); - return copied; -} - -v8::Local V8Debugger::functionLocation(v8::Local context, v8::Local function) -{ - int scriptId = function->ScriptId(); - if (scriptId == v8::UnboundScript::kNoScriptId) - return v8::Null(m_isolate); - int lineNumber = function->GetScriptLineNumber(); - int columnNumber = function->GetScriptColumnNumber(); - if (lineNumber == v8::Function::kLineOffsetNotFound || columnNumber == v8::Function::kLineOffsetNotFound) - return v8::Null(m_isolate); - v8::Local location = v8::Object::New(m_isolate); - if (!location->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false)) - return v8::Null(m_isolate); - if (!location->Set(context, toV8StringInternalized(m_isolate, "scriptId"), toV8String(m_isolate, String16::fromInteger(scriptId))).FromMaybe(false)) - return v8::Null(m_isolate); - if (!location->Set(context, toV8StringInternalized(m_isolate, "lineNumber"), v8::Integer::New(m_isolate, lineNumber)).FromMaybe(false)) - return v8::Null(m_isolate); - if (!location->Set(context, toV8StringInternalized(m_isolate, "columnNumber"), v8::Integer::New(m_isolate, columnNumber)).FromMaybe(false)) - return v8::Null(m_isolate); - if (!markAsInternal(context, location, V8InternalValueType::kLocation)) - return v8::Null(m_isolate); - return location; -} - -bool V8Debugger::isPaused() -{ - return !m_pausedContext.IsEmpty(); -} - -std::unique_ptr V8Debugger::createStackTrace(v8::Local stackTrace) -{ - int contextGroupId = m_isolate->InContext() ? getGroupId(m_isolate->GetCurrentContext()) : 0; - return V8StackTraceImpl::create(this, contextGroupId, stackTrace, V8StackTraceImpl::maxCallStackSizeToCapture); -} - -int V8Debugger::markContext(const V8ContextInfo& info) -{ - DCHECK(info.context->GetIsolate() == m_isolate); - int contextId = ++m_lastContextId; - String16 debugData = String16::fromInteger(info.contextGroupId) + "," + String16::fromInteger(contextId) + "," + info.auxData; - v8::Context::Scope contextScope(info.context); - info.context->SetEmbedderData(static_cast(v8::Context::kDebugIdIndex), toV8String(m_isolate, debugData)); - return contextId; -} - -void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) -{ - if (depth <= 0) - m_maxAsyncCallStackDepthMap.erase(agent); - else - m_maxAsyncCallStackDepthMap[agent] = depth; - - int maxAsyncCallStackDepth = 0; - for (const auto& pair : m_maxAsyncCallStackDepthMap) { - if (pair.second > maxAsyncCallStackDepth) - maxAsyncCallStackDepth = pair.second; - } - - if (m_maxAsyncCallStackDepth == maxAsyncCallStackDepth) - return; - m_maxAsyncCallStackDepth = maxAsyncCallStackDepth; - if (!maxAsyncCallStackDepth) - allAsyncTasksCanceled(); -} - -void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, bool recurring) -{ - if (!m_maxAsyncCallStackDepth) - return; - v8::HandleScope scope(m_isolate); - int contextGroupId = m_isolate->InContext() ? getGroupId(m_isolate->GetCurrentContext()) : 0; - std::unique_ptr chain = V8StackTraceImpl::capture(this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, taskName); - if (chain) { - m_asyncTaskStacks[task] = std::move(chain); - if (recurring) - m_recurringTasks.insert(task); - } -} - -void V8Debugger::asyncTaskCanceled(void* task) -{ - if (!m_maxAsyncCallStackDepth) - return; - m_asyncTaskStacks.erase(task); - m_recurringTasks.erase(task); -} - -void V8Debugger::asyncTaskStarted(void* task) -{ - if (!m_maxAsyncCallStackDepth) - return; - m_currentTasks.push_back(task); - AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find(task); - // Needs to support following order of events: - // - asyncTaskScheduled - // <-- attached here --> - // - asyncTaskStarted - // - asyncTaskCanceled <-- canceled before finished - // <-- async stack requested here --> - // - asyncTaskFinished - std::unique_ptr stack; - if (stackIt != m_asyncTaskStacks.end() && stackIt->second) - stack = stackIt->second->cloneImpl(); - m_currentStacks.push_back(std::move(stack)); -} - -void V8Debugger::asyncTaskFinished(void* task) -{ - if (!m_maxAsyncCallStackDepth) - return; - // We could start instrumenting half way and the stack is empty. - if (!m_currentStacks.size()) - return; - - DCHECK(m_currentTasks.back() == task); - m_currentTasks.pop_back(); - - m_currentStacks.pop_back(); - if (m_recurringTasks.find(task) == m_recurringTasks.end()) - m_asyncTaskStacks.erase(task); -} - -void V8Debugger::allAsyncTasksCanceled() -{ - m_asyncTaskStacks.clear(); - m_recurringTasks.clear(); - m_currentStacks.clear(); - m_currentTasks.clear(); -} - -void V8Debugger::muteScriptParsedEvents() -{ - ++m_ignoreScriptParsedEventsCounter; -} - -void V8Debugger::unmuteScriptParsedEvents() -{ - --m_ignoreScriptParsedEventsCounter; - DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); -} - -std::unique_ptr V8Debugger::captureStackTrace(bool fullStack) -{ - if (!m_isolate->InContext()) - return nullptr; - - v8::HandleScope handles(m_isolate); - int contextGroupId = getGroupId(m_isolate->GetCurrentContext()); - if (!contextGroupId) - return nullptr; - - size_t stackSize = fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; - if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) - stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; - - return V8StackTraceImpl::capture(this, contextGroupId, stackSize); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Debugger.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Debugger.h deleted file mode 100644 index 02e762eb01c420..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Debugger.h +++ /dev/null @@ -1,131 +0,0 @@ -// 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 V8Debugger_h -#define V8Debugger_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/JavaScriptCallFrame.h" -#include "platform/v8_inspector/V8DebuggerScript.h" -#include "platform/v8_inspector/protocol/Runtime.h" -#include "platform/v8_inspector/public/V8ContextInfo.h" - -#include -#include -#include - -namespace v8_inspector { - -struct ScriptBreakpoint; -class V8DebuggerAgentImpl; -class V8InspectorImpl; -class V8StackTraceImpl; - -namespace protocol = blink::protocol; - -class V8Debugger { - PROTOCOL_DISALLOW_COPY(V8Debugger); -public: - V8Debugger(v8::Isolate*, V8InspectorImpl*); - ~V8Debugger(); - - static int contextId(v8::Local); - static int getGroupId(v8::Local); - int markContext(const V8ContextInfo&); - - bool enabled() const; - - String16 setBreakpoint(const String16& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber); - void removeBreakpoint(const String16& breakpointId); - void setBreakpointsActivated(bool); - bool breakpointsActivated() const { return m_breakpointsActivated; } - - enum PauseOnExceptionsState { - DontPauseOnExceptions, - PauseOnAllExceptions, - PauseOnUncaughtExceptions - }; - PauseOnExceptionsState getPauseOnExceptionsState(); - void setPauseOnExceptionsState(PauseOnExceptionsState); - void setPauseOnNextStatement(bool); - bool canBreakProgram(); - void breakProgram(); - void continueProgram(); - void stepIntoStatement(); - void stepOverStatement(); - void stepOutOfFunction(); - void clearStepping(); - - bool setScriptSource(const String16& sourceID, v8::Local newSource, bool dryRun, ErrorString*, protocol::Maybe*, JavaScriptCallFrames* newCallFrames, protocol::Maybe* stackChanged); - JavaScriptCallFrames currentCallFrames(int limit = 0); - - // Each script inherits debug data from v8::Context where it has been compiled. - // Only scripts whose debug data matches |contextGroupId| will be reported. - // Passing 0 will result in reporting all scripts. - void getCompiledScripts(int contextGroupId, std::vector>&); - void enable(); - void disable(); - - bool isPaused(); - v8::Local pausedContext() { return m_pausedContext; } - - int maxAsyncCallChainDepth() { return m_maxAsyncCallStackDepth; } - V8StackTraceImpl* currentAsyncCallChain(); - void setAsyncCallStackDepth(V8DebuggerAgentImpl*, int); - std::unique_ptr createStackTrace(v8::Local); - std::unique_ptr captureStackTrace(bool fullStack); - - v8::MaybeLocal internalProperties(v8::Local, v8::Local); - - void asyncTaskScheduled(const String16& taskName, void* task, bool recurring); - void asyncTaskCanceled(void* task); - void asyncTaskStarted(void* task); - void asyncTaskFinished(void* task); - void allAsyncTasksCanceled(); - - void muteScriptParsedEvents(); - void unmuteScriptParsedEvents(); - -private: - void compileDebuggerScript(); - v8::MaybeLocal callDebuggerMethod(const char* functionName, int argc, v8::Local argv[]); - v8::Local debuggerContext() const; - void clearBreakpoints(); - - static void breakProgramCallback(const v8::FunctionCallbackInfo&); - void handleProgramBreak(v8::Local pausedContext, v8::Local executionState, v8::Local exception, v8::Local hitBreakpoints, bool isPromiseRejection = false); - static void v8DebugEventCallback(const v8::Debug::EventDetails&); - v8::Local callInternalGetterFunction(v8::Local, const char* functionName); - void handleV8DebugEvent(const v8::Debug::EventDetails&); - void handleV8AsyncTaskEvent(v8::Local, v8::Local executionState, v8::Local eventData); - - v8::Local collectionEntries(v8::Local, v8::Local); - v8::Local generatorObjectLocation(v8::Local, v8::Local); - v8::Local functionLocation(v8::Local, v8::Local); - v8::MaybeLocal functionScopes(v8::Local, v8::Local); - - v8::Isolate* m_isolate; - V8InspectorImpl* m_inspector; - int m_lastContextId; - int m_enableCount; - bool m_breakpointsActivated; - v8::Global m_debuggerScript; - v8::Global m_debuggerContext; - v8::Local m_executionState; - v8::Local m_pausedContext; - bool m_runningNestedMessageLoop; - int m_ignoreScriptParsedEventsCounter; - - using AsyncTaskToStackTrace = protocol::HashMap>; - AsyncTaskToStackTrace m_asyncTaskStacks; - protocol::HashSet m_recurringTasks; - int m_maxAsyncCallStackDepth; - std::vector m_currentTasks; - std::vector> m_currentStacks; - protocol::HashMap m_maxAsyncCallStackDepthMap; -}; - -} // namespace v8_inspector - -#endif // V8Debugger_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.cpp deleted file mode 100644 index 0afbd02bd569cf..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.cpp +++ /dev/null @@ -1,1167 +0,0 @@ -// Copyright 2015 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 "platform/v8_inspector/V8DebuggerAgentImpl.h" - -#include "platform/v8_inspector/InjectedScript.h" -#include "platform/v8_inspector/InspectedContext.h" -#include "platform/v8_inspector/JavaScriptCallFrame.h" -#include "platform/v8_inspector/RemoteObjectId.h" -#include "platform/v8_inspector/ScriptBreakpoint.h" -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/V8DebuggerScript.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8Regex.h" -#include "platform/v8_inspector/V8RuntimeAgentImpl.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -#include - -using blink::protocol::Array; -using blink::protocol::Maybe; -using blink::protocol::Debugger::BreakpointId; -using blink::protocol::Debugger::CallFrame; -using blink::protocol::Runtime::ExceptionDetails; -using blink::protocol::Runtime::ScriptId; -using blink::protocol::Runtime::StackTrace; -using blink::protocol::Runtime::RemoteObject; - -namespace v8_inspector { - -namespace DebuggerAgentState { -static const char javaScriptBreakpoints[] = "javaScriptBreakopints"; -static const char pauseOnExceptionsState[] = "pauseOnExceptionsState"; -static const char asyncCallStackDepth[] = "asyncCallStackDepth"; -static const char blackboxPattern[] = "blackboxPattern"; -static const char debuggerEnabled[] = "debuggerEnabled"; - -// Breakpoint properties. -static const char url[] = "url"; -static const char isRegex[] = "isRegex"; -static const char lineNumber[] = "lineNumber"; -static const char columnNumber[] = "columnNumber"; -static const char condition[] = "condition"; -static const char skipAllPauses[] = "skipAllPauses"; - -} // namespace DebuggerAgentState; - -static const int maxSkipStepFrameCount = 128; -static const char backtraceObjectGroup[] = "backtrace"; - -static String16 breakpointIdSuffix(V8DebuggerAgentImpl::BreakpointSource source) -{ - switch (source) { - case V8DebuggerAgentImpl::UserBreakpointSource: - break; - case V8DebuggerAgentImpl::DebugCommandBreakpointSource: - return ":debug"; - case V8DebuggerAgentImpl::MonitorCommandBreakpointSource: - return ":monitor"; - } - return String16(); -} - -static String16 generateBreakpointId(const String16& scriptId, int lineNumber, int columnNumber, V8DebuggerAgentImpl::BreakpointSource source) -{ - return scriptId + ":" + String16::fromInteger(lineNumber) + ":" + String16::fromInteger(columnNumber) + breakpointIdSuffix(source); -} - -static bool positionComparator(const std::pair& a, const std::pair& b) -{ - if (a.first != b.first) - return a.first < b.first; - return a.second < b.second; -} - -static bool hasInternalError(ErrorString* errorString, bool hasError) -{ - if (hasError) - *errorString = "Internal error"; - return hasError; -} - -static std::unique_ptr buildProtocolLocation(const String16& scriptId, int lineNumber, int columnNumber) -{ - return protocol::Debugger::Location::create() - .setScriptId(scriptId) - .setLineNumber(lineNumber) - .setColumnNumber(columnNumber).build(); -} - -V8DebuggerAgentImpl::V8DebuggerAgentImpl(V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, protocol::DictionaryValue* state) - : m_inspector(session->inspector()) - , m_debugger(m_inspector->debugger()) - , m_session(session) - , m_enabled(false) - , m_state(state) - , m_frontend(frontendChannel) - , m_isolate(m_inspector->isolate()) - , m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other) - , m_scheduledDebuggerStep(NoStep) - , m_skipNextDebuggerStepOut(false) - , m_javaScriptPauseScheduled(false) - , m_steppingFromFramework(false) - , m_pausingOnNativeEvent(false) - , m_skippedStepFrameCount(0) - , m_recursionLevelForStepOut(0) - , m_recursionLevelForStepFrame(0) - , m_skipAllPauses(false) -{ - clearBreakDetails(); -} - -V8DebuggerAgentImpl::~V8DebuggerAgentImpl() -{ -} - -bool V8DebuggerAgentImpl::checkEnabled(ErrorString* errorString) -{ - if (enabled()) - return true; - *errorString = "Debugger agent is not enabled"; - return false; -} - -void V8DebuggerAgentImpl::enable() -{ - // m_inspector->addListener may result in reporting all parsed scripts to - // the agent so it should already be in enabled state by then. - m_enabled = true; - m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); - m_debugger->enable(); - - std::vector> compiledScripts; - m_debugger->getCompiledScripts(m_session->contextGroupId(), compiledScripts); - for (size_t i = 0; i < compiledScripts.size(); i++) - didParseSource(std::move(compiledScripts[i]), true); - - // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends - m_debugger->setBreakpointsActivated(true); -} - -bool V8DebuggerAgentImpl::enabled() -{ - return m_enabled; -} - -void V8DebuggerAgentImpl::enable(ErrorString* errorString) -{ - if (enabled()) - return; - - if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) { - *errorString = "Script execution is prohibited"; - return; - } - - enable(); -} - -void V8DebuggerAgentImpl::disable(ErrorString*) -{ - if (!enabled()) - return; - - m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, protocol::DictionaryValue::create()); - m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, V8Debugger::DontPauseOnExceptions); - m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); - - if (!m_pausedContext.IsEmpty()) - m_debugger->continueProgram(); - m_debugger->disable(); - m_pausedContext.Reset(); - JavaScriptCallFrames emptyCallFrames; - m_pausedCallFrames.swap(emptyCallFrames); - m_scripts.clear(); - m_blackboxedPositions.clear(); - m_breakpointIdToDebuggerBreakpointIds.clear(); - m_debugger->setAsyncCallStackDepth(this, 0); - m_continueToLocationBreakpointId = String16(); - clearBreakDetails(); - m_scheduledDebuggerStep = NoStep; - m_skipNextDebuggerStepOut = false; - m_javaScriptPauseScheduled = false; - m_steppingFromFramework = false; - m_pausingOnNativeEvent = false; - m_skippedStepFrameCount = 0; - m_recursionLevelForStepFrame = 0; - m_skipAllPauses = false; - m_blackboxPattern = nullptr; - m_state->remove(DebuggerAgentState::blackboxPattern); - m_enabled = false; - m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); -} - -void V8DebuggerAgentImpl::restore() -{ - DCHECK(!m_enabled); - if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) - return; - if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) - return; - - enable(); - ErrorString error; - - int pauseState = V8Debugger::DontPauseOnExceptions; - m_state->getInteger(DebuggerAgentState::pauseOnExceptionsState, &pauseState); - setPauseOnExceptionsImpl(&error, pauseState); - DCHECK(error.isEmpty()); - - m_skipAllPauses = m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false); - - int asyncCallStackDepth = 0; - m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, &asyncCallStackDepth); - m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); - - String16 blackboxPattern; - if (m_state->getString(DebuggerAgentState::blackboxPattern, &blackboxPattern)) { - if (!setBlackboxPattern(&error, blackboxPattern)) - NOTREACHED(); - } -} - -void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, bool active) -{ - if (!checkEnabled(errorString)) - return; - m_debugger->setBreakpointsActivated(active); -} - -void V8DebuggerAgentImpl::setSkipAllPauses(ErrorString*, bool skip) -{ - m_skipAllPauses = skip; - m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses); -} - -static std::unique_ptr buildObjectForBreakpointCookie(const String16& url, int lineNumber, int columnNumber, const String16& condition, bool isRegex) -{ - std::unique_ptr breakpointObject = protocol::DictionaryValue::create(); - breakpointObject->setString(DebuggerAgentState::url, url); - breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); - breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); - breakpointObject->setString(DebuggerAgentState::condition, condition); - breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex); - return breakpointObject; -} - -static bool matches(V8InspectorImpl* inspector, const String16& url, const String16& pattern, bool isRegex) -{ - if (isRegex) { - V8Regex regex(inspector, pattern, true); - return regex.match(url) != -1; - } - return url == pattern; -} - -void V8DebuggerAgentImpl::setBreakpointByUrl(ErrorString* errorString, - int lineNumber, - const Maybe& optionalURL, - const Maybe& optionalURLRegex, - const Maybe& optionalColumnNumber, - const Maybe& optionalCondition, - String16* outBreakpointId, - std::unique_ptr>* locations) -{ - *locations = Array::create(); - if (optionalURL.isJust() == optionalURLRegex.isJust()) { - *errorString = "Either url or urlRegex must be specified."; - return; - } - - String16 url = optionalURL.isJust() ? optionalURL.fromJust() : optionalURLRegex.fromJust(); - int columnNumber = 0; - if (optionalColumnNumber.isJust()) { - columnNumber = optionalColumnNumber.fromJust(); - if (columnNumber < 0) { - *errorString = "Incorrect column number"; - return; - } - } - String16 condition = optionalCondition.fromMaybe(""); - bool isRegex = optionalURLRegex.isJust(); - - String16 breakpointId = (isRegex ? "/" + url + "/" : url) + ":" + String16::fromInteger(lineNumber) + ":" + String16::fromInteger(columnNumber); - protocol::DictionaryValue* breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); - if (!breakpointsCookie) { - std::unique_ptr newValue = protocol::DictionaryValue::create(); - breakpointsCookie = newValue.get(); - m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, std::move(newValue)); - } - if (breakpointsCookie->get(breakpointId)) { - *errorString = "Breakpoint at specified location already exists."; - return; - } - - breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, isRegex)); - - ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); - for (const auto& script : m_scripts) { - if (!matches(m_inspector, script.second->sourceURL(), url, isRegex)) - continue; - std::unique_ptr location = resolveBreakpoint(breakpointId, script.first, breakpoint, UserBreakpointSource); - if (location) - (*locations)->addItem(std::move(location)); - } - - *outBreakpointId = breakpointId; -} - -static bool parseLocation(ErrorString* errorString, std::unique_ptr location, String16* scriptId, int* lineNumber, int* columnNumber) -{ - *scriptId = location->getScriptId(); - *lineNumber = location->getLineNumber(); - *columnNumber = location->getColumnNumber(0); - return true; -} - -void V8DebuggerAgentImpl::setBreakpoint(ErrorString* errorString, - std::unique_ptr location, - const Maybe& optionalCondition, - String16* outBreakpointId, - std::unique_ptr* actualLocation) -{ - String16 scriptId; - int lineNumber; - int columnNumber; - - if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, &columnNumber)) - return; - - String16 condition = optionalCondition.fromMaybe(""); - - String16 breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, UserBreakpointSource); - if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != m_breakpointIdToDebuggerBreakpointIds.end()) { - *errorString = "Breakpoint at specified location already exists."; - return; - } - ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); - *actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, UserBreakpointSource); - if (*actualLocation) - *outBreakpointId = breakpointId; - else - *errorString = "Could not resolve breakpoint"; -} - -void V8DebuggerAgentImpl::removeBreakpoint(ErrorString* errorString, const String16& breakpointId) -{ - if (!checkEnabled(errorString)) - return; - protocol::DictionaryValue* breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); - if (breakpointsCookie) - breakpointsCookie->remove(breakpointId); - removeBreakpoint(breakpointId); -} - -void V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) -{ - DCHECK(enabled()); - BreakpointIdToDebuggerBreakpointIdsMap::iterator debuggerBreakpointIdsIterator = m_breakpointIdToDebuggerBreakpointIds.find(breakpointId); - if (debuggerBreakpointIdsIterator == m_breakpointIdToDebuggerBreakpointIds.end()) - return; - const std::vector& ids = debuggerBreakpointIdsIterator->second; - for (size_t i = 0; i < ids.size(); ++i) { - const String16& debuggerBreakpointId = ids[i]; - - m_debugger->removeBreakpoint(debuggerBreakpointId); - m_serverBreakpoints.erase(debuggerBreakpointId); - } - m_breakpointIdToDebuggerBreakpointIds.erase(breakpointId); -} - -void V8DebuggerAgentImpl::continueToLocation(ErrorString* errorString, std::unique_ptr location) -{ - if (!checkEnabled(errorString)) - return; - if (!m_continueToLocationBreakpointId.isEmpty()) { - m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); - m_continueToLocationBreakpointId = ""; - } - - String16 scriptId; - int lineNumber; - int columnNumber; - - if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, &columnNumber)) - return; - - ScriptBreakpoint breakpoint(lineNumber, columnNumber, ""); - m_continueToLocationBreakpointId = m_debugger->setBreakpoint(scriptId, breakpoint, &lineNumber, &columnNumber); - resume(errorString); -} - -bool V8DebuggerAgentImpl::isCurrentCallStackEmptyOrBlackboxed() -{ - DCHECK(enabled()); - JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(); - for (size_t index = 0; index < callFrames.size(); ++index) { - if (!isCallFrameWithUnknownScriptOrBlackboxed(callFrames[index].get())) - return false; - } - return true; -} - -bool V8DebuggerAgentImpl::isTopPausedCallFrameBlackboxed() -{ - DCHECK(enabled()); - JavaScriptCallFrame* frame = m_pausedCallFrames.size() ? m_pausedCallFrames[0].get() : nullptr; - return isCallFrameWithUnknownScriptOrBlackboxed(frame); -} - -bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCallFrame* frame) -{ - if (!frame) - return true; - ScriptsMap::iterator it = m_scripts.find(String16::fromInteger(frame->sourceID())); - if (it == m_scripts.end()) { - // Unknown scripts are blackboxed. - return true; - } - if (m_blackboxPattern) { - const String16& scriptSourceURL = it->second->sourceURL(); - if (!scriptSourceURL.isEmpty() && m_blackboxPattern->match(scriptSourceURL) != -1) - return true; - } - auto itBlackboxedPositions = m_blackboxedPositions.find(String16::fromInteger(frame->sourceID())); - if (itBlackboxedPositions == m_blackboxedPositions.end()) - return false; - - const std::vector>& ranges = itBlackboxedPositions->second; - auto itRange = std::lower_bound(ranges.begin(), ranges.end(), - std::make_pair(frame->line(), frame->column()), positionComparator); - // Ranges array contains positions in script where blackbox state is changed. - // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is blackboxed... - return std::distance(ranges.begin(), itRange) % 2; -} - -V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipExceptionPause(JavaScriptCallFrame* topCallFrame) -{ - if (m_steppingFromFramework) - return RequestNoSkip; - if (isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) - return RequestContinue; - return RequestNoSkip; -} - -V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipStepPause(JavaScriptCallFrame* topCallFrame) -{ - if (m_steppingFromFramework) - return RequestNoSkip; - - if (m_skipNextDebuggerStepOut) { - m_skipNextDebuggerStepOut = false; - if (m_scheduledDebuggerStep == StepOut) - return RequestStepOut; - } - - if (!isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) - return RequestNoSkip; - - if (m_skippedStepFrameCount >= maxSkipStepFrameCount) - return RequestStepOut; - - if (!m_skippedStepFrameCount) - m_recursionLevelForStepFrame = 1; - - ++m_skippedStepFrameCount; - return RequestStepFrame; -} - -std::unique_ptr V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, const String16& scriptId, const ScriptBreakpoint& breakpoint, BreakpointSource source) -{ - DCHECK(enabled()); - // FIXME: remove these checks once crbug.com/520702 is resolved. - CHECK(!breakpointId.isEmpty()); - CHECK(!scriptId.isEmpty()); - ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); - if (scriptIterator == m_scripts.end()) - return nullptr; - if (breakpoint.lineNumber < scriptIterator->second->startLine() || scriptIterator->second->endLine() < breakpoint.lineNumber) - return nullptr; - - int actualLineNumber; - int actualColumnNumber; - String16 debuggerBreakpointId = m_debugger->setBreakpoint(scriptId, breakpoint, &actualLineNumber, &actualColumnNumber); - if (debuggerBreakpointId.isEmpty()) - return nullptr; - - m_serverBreakpoints[debuggerBreakpointId] = std::make_pair(breakpointId, source); - CHECK(!breakpointId.isEmpty()); - - m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back(debuggerBreakpointId); - return buildProtocolLocation(scriptId, actualLineNumber, actualColumnNumber); -} - -void V8DebuggerAgentImpl::searchInContent(ErrorString* error, const String16& scriptId, const String16& query, - const Maybe& optionalCaseSensitive, - const Maybe& optionalIsRegex, - std::unique_ptr>* results) -{ - v8::HandleScope handles(m_isolate); - ScriptsMap::iterator it = m_scripts.find(scriptId); - if (it == m_scripts.end()) { - *error = String16("No script for id: " + scriptId); - return; - } - - std::vector> matches = searchInTextByLinesImpl(m_session, toProtocolString(it->second->source(m_isolate)), query, optionalCaseSensitive.fromMaybe(false), optionalIsRegex.fromMaybe(false)); - *results = protocol::Array::create(); - for (size_t i = 0; i < matches.size(); ++i) - (*results)->addItem(std::move(matches[i])); -} - -void V8DebuggerAgentImpl::setScriptSource(ErrorString* errorString, - const String16& scriptId, - const String16& newContent, - const Maybe& dryRun, - Maybe>* newCallFrames, - Maybe* stackChanged, - Maybe* asyncStackTrace, - Maybe* optOutCompileError) -{ - if (!checkEnabled(errorString)) - return; - - v8::HandleScope handles(m_isolate); - v8::Local newSource = toV8String(m_isolate, newContent); - if (!m_debugger->setScriptSource(scriptId, newSource, dryRun.fromMaybe(false), errorString, optOutCompileError, &m_pausedCallFrames, stackChanged)) - return; - - ScriptsMap::iterator it = m_scripts.find(scriptId); - if (it != m_scripts.end()) - it->second->setSource(m_isolate, newSource); - - std::unique_ptr> callFrames = currentCallFrames(errorString); - if (!callFrames) - return; - *newCallFrames = std::move(callFrames); - *asyncStackTrace = currentAsyncStackTrace(); -} - -void V8DebuggerAgentImpl::restartFrame(ErrorString* errorString, - const String16& callFrameId, - std::unique_ptr>* newCallFrames, - Maybe* asyncStackTrace) -{ - if (!assertPaused(errorString)) - return; - InjectedScript::CallFrameScope scope(errorString, m_inspector, m_session->contextGroupId(), callFrameId); - if (!scope.initialize()) - return; - if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { - *errorString = "Could not find call frame with given id"; - return; - } - - v8::Local resultValue; - v8::Local result; - if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal(&resultValue) || scope.tryCatch().HasCaught() || !resultValue->ToBoolean(scope.context()).ToLocal(&result) || !result->Value()) { - *errorString = "Internal error"; - return; - } - JavaScriptCallFrames frames = m_debugger->currentCallFrames(); - m_pausedCallFrames.swap(frames); - - *newCallFrames = currentCallFrames(errorString); - if (!*newCallFrames) - return; - *asyncStackTrace = currentAsyncStackTrace(); -} - -void V8DebuggerAgentImpl::getScriptSource(ErrorString* error, const String16& scriptId, String16* scriptSource) -{ - if (!checkEnabled(error)) - return; - ScriptsMap::iterator it = m_scripts.find(scriptId); - if (it == m_scripts.end()) { - *error = "No script for id: " + scriptId; - return; - } - v8::HandleScope handles(m_isolate); - *scriptSource = toProtocolString(it->second->source(m_isolate)); -} - -void V8DebuggerAgentImpl::schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr data) -{ - if (!enabled() || m_scheduledDebuggerStep == StepInto || m_javaScriptPauseScheduled || m_debugger->isPaused() || !m_debugger->breakpointsActivated()) - return; - m_breakReason = breakReason; - m_breakAuxData = std::move(data); - m_pausingOnNativeEvent = true; - m_skipNextDebuggerStepOut = false; - m_debugger->setPauseOnNextStatement(true); -} - -void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() -{ - DCHECK(enabled()); - if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || m_debugger->isPaused()) - return; - clearBreakDetails(); - m_pausingOnNativeEvent = false; - m_skippedStepFrameCount = 0; - m_recursionLevelForStepFrame = 0; - m_debugger->setPauseOnNextStatement(true); -} - -void V8DebuggerAgentImpl::cancelPauseOnNextStatement() -{ - if (m_javaScriptPauseScheduled || m_debugger->isPaused()) - return; - clearBreakDetails(); - m_pausingOnNativeEvent = false; - m_debugger->setPauseOnNextStatement(false); -} - -void V8DebuggerAgentImpl::pause(ErrorString* errorString) -{ - if (!checkEnabled(errorString)) - return; - if (m_javaScriptPauseScheduled || m_debugger->isPaused()) - return; - clearBreakDetails(); - m_javaScriptPauseScheduled = true; - m_scheduledDebuggerStep = NoStep; - m_skippedStepFrameCount = 0; - m_steppingFromFramework = false; - m_debugger->setPauseOnNextStatement(true); -} - -void V8DebuggerAgentImpl::resume(ErrorString* errorString) -{ - if (!assertPaused(errorString)) - return; - m_scheduledDebuggerStep = NoStep; - m_steppingFromFramework = false; - m_session->releaseObjectGroup(backtraceObjectGroup); - m_debugger->continueProgram(); -} - -void V8DebuggerAgentImpl::stepOver(ErrorString* errorString) -{ - if (!assertPaused(errorString)) - return; - // StepOver at function return point should fallback to StepInto. - JavaScriptCallFrame* frame = !m_pausedCallFrames.empty() ? m_pausedCallFrames[0].get() : nullptr; - if (frame && frame->isAtReturn()) { - stepInto(errorString); - return; - } - m_scheduledDebuggerStep = StepOver; - m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); - m_session->releaseObjectGroup(backtraceObjectGroup); - m_debugger->stepOverStatement(); -} - -void V8DebuggerAgentImpl::stepInto(ErrorString* errorString) -{ - if (!assertPaused(errorString)) - return; - m_scheduledDebuggerStep = StepInto; - m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); - m_session->releaseObjectGroup(backtraceObjectGroup); - m_debugger->stepIntoStatement(); -} - -void V8DebuggerAgentImpl::stepOut(ErrorString* errorString) -{ - if (!assertPaused(errorString)) - return; - m_scheduledDebuggerStep = StepOut; - m_skipNextDebuggerStepOut = false; - m_recursionLevelForStepOut = 1; - m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); - m_session->releaseObjectGroup(backtraceObjectGroup); - m_debugger->stepOutOfFunction(); -} - -void V8DebuggerAgentImpl::setPauseOnExceptions(ErrorString* errorString, const String16& stringPauseState) -{ - if (!checkEnabled(errorString)) - return; - V8Debugger::PauseOnExceptionsState pauseState; - if (stringPauseState == "none") { - pauseState = V8Debugger::DontPauseOnExceptions; - } else if (stringPauseState == "all") { - pauseState = V8Debugger::PauseOnAllExceptions; - } else if (stringPauseState == "uncaught") { - pauseState = V8Debugger::PauseOnUncaughtExceptions; - } else { - *errorString = "Unknown pause on exceptions mode: " + stringPauseState; - return; - } - setPauseOnExceptionsImpl(errorString, pauseState); -} - -void V8DebuggerAgentImpl::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState) -{ - m_debugger->setPauseOnExceptionsState(static_cast(pauseState)); - if (m_debugger->getPauseOnExceptionsState() != pauseState) - *errorString = "Internal error. Could not change pause on exceptions state"; - else - m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); -} - -void V8DebuggerAgentImpl::evaluateOnCallFrame(ErrorString* errorString, - const String16& callFrameId, - const String16& expression, - const Maybe& objectGroup, - const Maybe& includeCommandLineAPI, - const Maybe& silent, - const Maybe& returnByValue, - const Maybe& generatePreview, - std::unique_ptr* result, - Maybe* exceptionDetails) -{ - if (!assertPaused(errorString)) - return; - InjectedScript::CallFrameScope scope(errorString, m_inspector, m_session->contextGroupId(), callFrameId); - if (!scope.initialize()) - return; - if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { - *errorString = "Could not find call frame with given id"; - return; - } - - if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI()) - return; - if (silent.fromMaybe(false)) - scope.ignoreExceptionsAndMuteConsole(); - - v8::MaybeLocal maybeResultValue = m_pausedCallFrames[scope.frameOrdinal()]->evaluate(toV8String(m_isolate, expression)); - - // Re-initialize after running client's code, as it could have destroyed context or session. - if (!scope.initialize()) - return; - scope.injectedScript()->wrapEvaluateResult(errorString, - maybeResultValue, - scope.tryCatch(), - objectGroup.fromMaybe(""), - returnByValue.fromMaybe(false), - generatePreview.fromMaybe(false), - result, - exceptionDetails); -} - -void V8DebuggerAgentImpl::setVariableValue(ErrorString* errorString, - int scopeNumber, - const String16& variableName, - std::unique_ptr newValueArgument, - const String16& callFrameId) -{ - if (!checkEnabled(errorString)) - return; - if (!assertPaused(errorString)) - return; - InjectedScript::CallFrameScope scope(errorString, m_inspector, m_session->contextGroupId(), callFrameId); - if (!scope.initialize()) - return; - - v8::Local newValue; - if (!scope.injectedScript()->resolveCallArgument(errorString, newValueArgument.get()).ToLocal(&newValue)) - return; - - if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { - *errorString = "Could not find call frame with given id"; - return; - } - v8::MaybeLocal result = m_pausedCallFrames[scope.frameOrdinal()]->setVariableValue(scopeNumber, toV8String(m_isolate, variableName), newValue); - if (scope.tryCatch().HasCaught() || result.IsEmpty()) { - *errorString = "Internal error"; - return; - } -} - -void V8DebuggerAgentImpl::setAsyncCallStackDepth(ErrorString* errorString, int depth) -{ - if (!checkEnabled(errorString)) - return; - m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, depth); - m_debugger->setAsyncCallStackDepth(this, depth); -} - -void V8DebuggerAgentImpl::setBlackboxPatterns(ErrorString* errorString, std::unique_ptr> patterns) -{ - if (!patterns->length()) { - m_blackboxPattern = nullptr; - m_state->remove(DebuggerAgentState::blackboxPattern); - return; - } - - String16Builder patternBuilder; - patternBuilder.append('('); - for (size_t i = 0; i < patterns->length() - 1; ++i) { - patternBuilder.append(patterns->get(i)); - patternBuilder.append("|"); - } - patternBuilder.append(patterns->get(patterns->length() - 1)); - patternBuilder.append(')'); - String16 pattern = patternBuilder.toString(); - if (!setBlackboxPattern(errorString, pattern)) - return; - m_state->setString(DebuggerAgentState::blackboxPattern, pattern); -} - -bool V8DebuggerAgentImpl::setBlackboxPattern(ErrorString* errorString, const String16& pattern) -{ - std::unique_ptr regex(new V8Regex(m_inspector, pattern, true /** caseSensitive */, false /** multiline */)); - if (!regex->isValid()) { - *errorString = "Pattern parser error: " + regex->errorMessage(); - return false; - } - m_blackboxPattern = std::move(regex); - return true; -} - -void V8DebuggerAgentImpl::setBlackboxedRanges(ErrorString* error, const String16& scriptId, - std::unique_ptr> inPositions) -{ - if (m_scripts.find(scriptId) == m_scripts.end()) { - *error = "No script with passed id."; - return; - } - - if (!inPositions->length()) { - m_blackboxedPositions.erase(scriptId); - return; - } - - std::vector> positions; - positions.reserve(inPositions->length()); - for (size_t i = 0; i < inPositions->length(); ++i) { - protocol::Debugger::ScriptPosition* position = inPositions->get(i); - if (position->getLineNumber() < 0) { - *error = "Position missing 'line' or 'line' < 0."; - return; - } - if (position->getColumnNumber() < 0) { - *error = "Position missing 'column' or 'column' < 0."; - return; - } - positions.push_back(std::make_pair(position->getLineNumber(), position->getColumnNumber())); - } - - for (size_t i = 1; i < positions.size(); ++i) { - if (positions[i - 1].first < positions[i].first) - continue; - if (positions[i - 1].first == positions[i].first && positions[i - 1].second < positions[i].second) - continue; - *error = "Input positions array is not sorted or contains duplicate values."; - return; - } - - m_blackboxedPositions[scriptId] = positions; -} - -void V8DebuggerAgentImpl::willExecuteScript(int scriptId) -{ - changeJavaScriptRecursionLevel(+1); - // Fast return. - if (m_scheduledDebuggerStep != StepInto) - return; - schedulePauseOnNextStatementIfSteppingInto(); -} - -void V8DebuggerAgentImpl::didExecuteScript() -{ - changeJavaScriptRecursionLevel(-1); -} - -void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) -{ - if (m_javaScriptPauseScheduled && !m_skipAllPauses && !m_debugger->isPaused()) { - // Do not ever loose user's pause request until we have actually paused. - m_debugger->setPauseOnNextStatement(true); - } - if (m_scheduledDebuggerStep == StepOut) { - m_recursionLevelForStepOut += step; - if (!m_recursionLevelForStepOut) { - // When StepOut crosses a task boundary (i.e. js -> blink_c++) from where it was requested, - // switch stepping to step into a next JS task, as if we exited to a blackboxed framework. - m_scheduledDebuggerStep = StepInto; - m_skipNextDebuggerStepOut = false; - } - } - if (m_recursionLevelForStepFrame) { - m_recursionLevelForStepFrame += step; - if (!m_recursionLevelForStepFrame) { - // We have walked through a blackboxed framework and got back to where we started. - // If there was no stepping scheduled, we should cancel the stepping explicitly, - // since there may be a scheduled StepFrame left. - // Otherwise, if we were stepping in/over, the StepFrame will stop at the right location, - // whereas if we were stepping out, we should continue doing so after debugger pauses - // from the old StepFrame. - m_skippedStepFrameCount = 0; - if (m_scheduledDebuggerStep == NoStep) - m_debugger->clearStepping(); - else if (m_scheduledDebuggerStep == StepOut) - m_skipNextDebuggerStepOut = true; - } - } -} - -std::unique_ptr> V8DebuggerAgentImpl::currentCallFrames(ErrorString* errorString) -{ - if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) - return Array::create(); - ErrorString ignored; - v8::HandleScope handles(m_isolate); - v8::Local debuggerContext = v8::Debug::GetDebugContext(m_isolate); - v8::Context::Scope contextScope(debuggerContext); - - v8::Local objects = v8::Array::New(m_isolate); - - for (size_t frameOrdinal = 0; frameOrdinal < m_pausedCallFrames.size(); ++frameOrdinal) { - const std::unique_ptr& currentCallFrame = m_pausedCallFrames[frameOrdinal]; - - v8::Local details = currentCallFrame->details(); - if (hasInternalError(errorString, details.IsEmpty())) - return Array::create(); - - int contextId = currentCallFrame->contextId(); - InjectedScript* injectedScript = contextId ? m_session->findInjectedScript(&ignored, contextId) : nullptr; - - String16 callFrameId = RemoteCallFrameId::serialize(contextId, frameOrdinal); - if (hasInternalError(errorString, !details->Set(debuggerContext, toV8StringInternalized(m_isolate, "callFrameId"), toV8String(m_isolate, callFrameId)).FromMaybe(false))) - return Array::create(); - - if (injectedScript) { - v8::Local scopeChain; - if (hasInternalError(errorString, !details->Get(debuggerContext, toV8StringInternalized(m_isolate, "scopeChain")).ToLocal(&scopeChain) || !scopeChain->IsArray())) - return Array::create(); - v8::Local scopeChainArray = scopeChain.As(); - if (!injectedScript->wrapPropertyInArray(errorString, scopeChainArray, toV8StringInternalized(m_isolate, "object"), backtraceObjectGroup)) - return Array::create(); - if (!injectedScript->wrapObjectProperty(errorString, details, toV8StringInternalized(m_isolate, "this"), backtraceObjectGroup)) - return Array::create(); - if (details->Has(debuggerContext, toV8StringInternalized(m_isolate, "returnValue")).FromMaybe(false)) { - if (!injectedScript->wrapObjectProperty(errorString, details, toV8StringInternalized(m_isolate, "returnValue"), backtraceObjectGroup)) - return Array::create(); - } - } else { - if (hasInternalError(errorString, !details->Set(debuggerContext, toV8StringInternalized(m_isolate, "scopeChain"), v8::Array::New(m_isolate, 0)).FromMaybe(false))) - return Array::create(); - v8::Local remoteObject = v8::Object::New(m_isolate); - if (hasInternalError(errorString, !remoteObject->Set(debuggerContext, toV8StringInternalized(m_isolate, "type"), toV8StringInternalized(m_isolate, "undefined")).FromMaybe(false))) - return Array::create(); - if (hasInternalError(errorString, !details->Set(debuggerContext, toV8StringInternalized(m_isolate, "this"), remoteObject).FromMaybe(false))) - return Array::create(); - if (hasInternalError(errorString, !details->Delete(debuggerContext, toV8StringInternalized(m_isolate, "returnValue")).FromMaybe(false))) - return Array::create(); - } - - if (hasInternalError(errorString, !objects->Set(debuggerContext, frameOrdinal, details).FromMaybe(false))) - return Array::create(); - } - - protocol::ErrorSupport errorSupport; - std::unique_ptr> callFrames = Array::parse(toProtocolValue(debuggerContext, objects).get(), &errorSupport); - if (hasInternalError(errorString, !callFrames)) - return Array::create(); - return callFrames; -} - -std::unique_ptr V8DebuggerAgentImpl::currentAsyncStackTrace() -{ - if (m_pausedContext.IsEmpty()) - return nullptr; - V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); - return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) : nullptr; -} - -void V8DebuggerAgentImpl::didParseSource(std::unique_ptr script, bool success) -{ - v8::HandleScope handles(m_isolate); - String16 scriptSource = toProtocolString(script->source(m_isolate)); - if (!success) - script->setSourceURL(findSourceURL(scriptSource, false)); - if (!success) - script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); - - std::unique_ptr executionContextAuxData; - if (!script->executionContextAuxData().isEmpty()) - executionContextAuxData = protocol::DictionaryValue::cast(parseJSON(script->executionContextAuxData())); - bool isLiveEdit = script->isLiveEdit(); - bool hasSourceURL = script->hasSourceURL(); - String16 scriptId = script->scriptId(); - String16 scriptURL = script->sourceURL(); - - const Maybe& sourceMapURLParam = script->sourceMappingURL(); - const Maybe& executionContextAuxDataParam(std::move(executionContextAuxData)); - const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; - const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; - if (success) - m_frontend.scriptParsed(scriptId, scriptURL, script->startLine(), script->startColumn(), script->endLine(), script->endColumn(), script->executionContextId(), script->hash(), executionContextAuxDataParam, isLiveEditParam, sourceMapURLParam, hasSourceURLParam); - else - m_frontend.scriptFailedToParse(scriptId, scriptURL, script->startLine(), script->startColumn(), script->endLine(), script->endColumn(), script->executionContextId(), script->hash(), executionContextAuxDataParam, sourceMapURLParam, hasSourceURLParam); - - m_scripts[scriptId] = std::move(script); - - if (scriptURL.isEmpty() || !success) - return; - - protocol::DictionaryValue* breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); - if (!breakpointsCookie) - return; - - for (size_t i = 0; i < breakpointsCookie->size(); ++i) { - auto cookie = breakpointsCookie->at(i); - protocol::DictionaryValue* breakpointObject = protocol::DictionaryValue::cast(cookie.second); - bool isRegex; - breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex); - String16 url; - breakpointObject->getString(DebuggerAgentState::url, &url); - if (!matches(m_inspector, scriptURL, url, isRegex)) - continue; - ScriptBreakpoint breakpoint; - breakpointObject->getInteger(DebuggerAgentState::lineNumber, &breakpoint.lineNumber); - breakpointObject->getInteger(DebuggerAgentState::columnNumber, &breakpoint.columnNumber); - breakpointObject->getString(DebuggerAgentState::condition, &breakpoint.condition); - std::unique_ptr location = resolveBreakpoint(cookie.first, scriptId, breakpoint, UserBreakpointSource); - if (location) - m_frontend.breakpointResolved(cookie.first, std::move(location)); - } -} - -V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause(v8::Local context, v8::Local exception, const std::vector& hitBreakpoints, bool isPromiseRejection) -{ - JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(1); - JavaScriptCallFrame* topCallFrame = !callFrames.empty() ? callFrames.begin()->get() : nullptr; - - V8DebuggerAgentImpl::SkipPauseRequest result; - if (m_skipAllPauses) - result = RequestContinue; - else if (!hitBreakpoints.empty()) - result = RequestNoSkip; // Don't skip explicit breakpoints even if set in frameworks. - else if (!exception.IsEmpty()) - result = shouldSkipExceptionPause(topCallFrame); - else if (m_scheduledDebuggerStep != NoStep || m_javaScriptPauseScheduled || m_pausingOnNativeEvent) - result = shouldSkipStepPause(topCallFrame); - else - result = RequestNoSkip; - - m_skipNextDebuggerStepOut = false; - if (result != RequestNoSkip) - return result; - // Skip pauses inside V8 internal scripts and on syntax errors. - if (!topCallFrame) - return RequestContinue; - - DCHECK(m_pausedContext.IsEmpty()); - JavaScriptCallFrames frames = m_debugger->currentCallFrames(); - m_pausedCallFrames.swap(frames); - m_pausedContext.Reset(m_isolate, context); - v8::HandleScope handles(m_isolate); - - if (!exception.IsEmpty()) { - ErrorString ignored; - InjectedScript* injectedScript = m_session->findInjectedScript(&ignored, V8Debugger::contextId(context)); - if (injectedScript) { - m_breakReason = isPromiseRejection ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection : protocol::Debugger::Paused::ReasonEnum::Exception; - ErrorString errorString; - auto obj = injectedScript->wrapObject(&errorString, exception, backtraceObjectGroup); - m_breakAuxData = obj ? obj->serialize() : nullptr; - // m_breakAuxData might be null after this. - } - } - - std::unique_ptr> hitBreakpointIds = Array::create(); - - for (const auto& point : hitBreakpoints) { - DebugServerBreakpointToBreakpointIdAndSourceMap::iterator breakpointIterator = m_serverBreakpoints.find(point); - if (breakpointIterator != m_serverBreakpoints.end()) { - const String16& localId = breakpointIterator->second.first; - hitBreakpointIds->addItem(localId); - - BreakpointSource source = breakpointIterator->second.second; - if (m_breakReason == protocol::Debugger::Paused::ReasonEnum::Other && source == DebugCommandBreakpointSource) - m_breakReason = protocol::Debugger::Paused::ReasonEnum::DebugCommand; - } - } - - ErrorString errorString; - m_frontend.paused(currentCallFrames(&errorString), m_breakReason, std::move(m_breakAuxData), std::move(hitBreakpointIds), currentAsyncStackTrace()); - m_scheduledDebuggerStep = NoStep; - m_javaScriptPauseScheduled = false; - m_steppingFromFramework = false; - m_pausingOnNativeEvent = false; - m_skippedStepFrameCount = 0; - m_recursionLevelForStepFrame = 0; - - if (!m_continueToLocationBreakpointId.isEmpty()) { - m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); - m_continueToLocationBreakpointId = ""; - } - return result; -} - -void V8DebuggerAgentImpl::didContinue() -{ - m_pausedContext.Reset(); - JavaScriptCallFrames emptyCallFrames; - m_pausedCallFrames.swap(emptyCallFrames); - clearBreakDetails(); - m_frontend.resumed(); -} - -void V8DebuggerAgentImpl::breakProgram(const String16& breakReason, std::unique_ptr data) -{ - if (!enabled() || m_skipAllPauses || !m_pausedContext.IsEmpty() || isCurrentCallStackEmptyOrBlackboxed() || !m_debugger->breakpointsActivated()) - return; - m_breakReason = breakReason; - m_breakAuxData = std::move(data); - m_scheduledDebuggerStep = NoStep; - m_steppingFromFramework = false; - m_pausingOnNativeEvent = false; - m_debugger->breakProgram(); -} - -void V8DebuggerAgentImpl::breakProgramOnException(const String16& breakReason, std::unique_ptr data) -{ - if (!enabled() || m_debugger->getPauseOnExceptionsState() == V8Debugger::DontPauseOnExceptions) - return; - breakProgram(breakReason, std::move(data)); -} - -bool V8DebuggerAgentImpl::assertPaused(ErrorString* errorString) -{ - if (m_pausedContext.IsEmpty()) { - *errorString = "Can only perform operation while paused."; - return false; - } - return true; -} - -void V8DebuggerAgentImpl::clearBreakDetails() -{ - m_breakReason = protocol::Debugger::Paused::ReasonEnum::Other; - m_breakAuxData = nullptr; -} - -void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource source, const String16& condition) -{ - String16 breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, source); - ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); - resolveBreakpoint(breakpointId, scriptId, breakpoint, source); -} - -void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource source) -{ - removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, source)); -} - -void V8DebuggerAgentImpl::reset() -{ - if (!enabled()) - return; - m_scheduledDebuggerStep = NoStep; - m_scripts.clear(); - m_blackboxedPositions.clear(); - m_breakpointIdToDebuggerBreakpointIds.clear(); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.h deleted file mode 100644 index 04d1ad7c8927d0..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerAgentImpl.h +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2015 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 V8DebuggerAgentImpl_h -#define V8DebuggerAgentImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/JavaScriptCallFrame.h" -#include "platform/v8_inspector/protocol/Debugger.h" - -#include - -namespace v8_inspector { - -struct ScriptBreakpoint; -class JavaScriptCallFrame; -class PromiseTracker; -class V8Debugger; -class V8DebuggerScript; -class V8InspectorImpl; -class V8InspectorSessionImpl; -class V8Regex; -class V8StackTraceImpl; - -namespace protocol = blink::protocol; -using blink::protocol::Maybe; - -class V8DebuggerAgentImpl : public protocol::Debugger::Backend { - PROTOCOL_DISALLOW_COPY(V8DebuggerAgentImpl); -public: - enum SkipPauseRequest { - RequestNoSkip, - RequestContinue, - RequestStepInto, - RequestStepOut, - RequestStepFrame - }; - - enum BreakpointSource { - UserBreakpointSource, - DebugCommandBreakpointSource, - MonitorCommandBreakpointSource - }; - - V8DebuggerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, protocol::DictionaryValue* state); - ~V8DebuggerAgentImpl() override; - void restore(); - - // Part of the protocol. - void enable(ErrorString*) override; - void disable(ErrorString*) override; - void setBreakpointsActive(ErrorString*, bool active) override; - void setSkipAllPauses(ErrorString*, bool skip) override; - void setBreakpointByUrl(ErrorString*, - int lineNumber, - const Maybe& optionalURL, - const Maybe& optionalURLRegex, - const Maybe& optionalColumnNumber, - const Maybe& optionalCondition, - String16*, - std::unique_ptr>* locations) override; - void setBreakpoint(ErrorString*, - std::unique_ptr, - const Maybe& optionalCondition, - String16*, - std::unique_ptr* actualLocation) override; - void removeBreakpoint(ErrorString*, const String16& breakpointId) override; - void continueToLocation(ErrorString*, - std::unique_ptr) override; - void searchInContent(ErrorString*, - const String16& scriptId, - const String16& query, - const Maybe& optionalCaseSensitive, - const Maybe& optionalIsRegex, - std::unique_ptr>*) override; - void setScriptSource(ErrorString*, - const String16& inScriptId, - const String16& inScriptSource, - const Maybe& dryRun, - Maybe>* optOutCallFrames, - Maybe* optOutStackChanged, - Maybe* optOutAsyncStackTrace, - Maybe* optOutCompileError) override; - void restartFrame(ErrorString*, - const String16& callFrameId, - std::unique_ptr>* newCallFrames, - Maybe* asyncStackTrace) override; - void getScriptSource(ErrorString*, const String16& scriptId, String16* scriptSource) override; - void pause(ErrorString*) override; - void resume(ErrorString*) override; - void stepOver(ErrorString*) override; - void stepInto(ErrorString*) override; - void stepOut(ErrorString*) override; - void setPauseOnExceptions(ErrorString*, const String16& pauseState) override; - void evaluateOnCallFrame(ErrorString*, - const String16& callFrameId, - const String16& expression, - const Maybe& objectGroup, - const Maybe& includeCommandLineAPI, - const Maybe& silent, - const Maybe& returnByValue, - const Maybe& generatePreview, - std::unique_ptr* result, - Maybe*) override; - void setVariableValue(ErrorString*, - int scopeNumber, - const String16& variableName, - std::unique_ptr newValue, - const String16& callFrame) override; - void setAsyncCallStackDepth(ErrorString*, int depth) override; - void setBlackboxPatterns(ErrorString*, - std::unique_ptr> patterns) override; - void setBlackboxedRanges(ErrorString*, - const String16& scriptId, - std::unique_ptr> positions) override; - - bool enabled(); - - void setBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource, const String16& condition = String16()); - void removeBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource); - void schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr data); - void cancelPauseOnNextStatement(); - void breakProgram(const String16& breakReason, std::unique_ptr data); - void breakProgramOnException(const String16& breakReason, std::unique_ptr data); - - void reset(); - - // Interface for V8InspectorImpl - SkipPauseRequest didPause(v8::Local, v8::Local exception, const std::vector& hitBreakpoints, bool isPromiseRejection); - void didContinue(); - void didParseSource(std::unique_ptr, bool success); - void willExecuteScript(int scriptId); - void didExecuteScript(); - - v8::Isolate* isolate() { return m_isolate; } - -private: - bool checkEnabled(ErrorString*); - void enable(); - - SkipPauseRequest shouldSkipExceptionPause(JavaScriptCallFrame* topCallFrame); - SkipPauseRequest shouldSkipStepPause(JavaScriptCallFrame* topCallFrame); - - void schedulePauseOnNextStatementIfSteppingInto(); - - std::unique_ptr> currentCallFrames(ErrorString*); - std::unique_ptr currentAsyncStackTrace(); - - void changeJavaScriptRecursionLevel(int step); - - void setPauseOnExceptionsImpl(ErrorString*, int); - - std::unique_ptr resolveBreakpoint(const String16& breakpointId, const String16& scriptId, const ScriptBreakpoint&, BreakpointSource); - void removeBreakpoint(const String16& breakpointId); - bool assertPaused(ErrorString*); - void clearBreakDetails(); - - bool isCurrentCallStackEmptyOrBlackboxed(); - bool isTopPausedCallFrameBlackboxed(); - bool isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCallFrame*); - - void internalSetAsyncCallStackDepth(int); - void increaseCachedSkipStackGeneration(); - - bool setBlackboxPattern(ErrorString*, const String16& pattern); - - using ScriptsMap = protocol::HashMap>; - using BreakpointIdToDebuggerBreakpointIdsMap = protocol::HashMap>; - using DebugServerBreakpointToBreakpointIdAndSourceMap = protocol::HashMap>; - using MuteBreakpoins = protocol::HashMap>; - - enum DebuggerStep { - NoStep = 0, - StepInto, - StepOver, - StepOut - }; - - V8InspectorImpl* m_inspector; - V8Debugger* m_debugger; - V8InspectorSessionImpl* m_session; - bool m_enabled; - protocol::DictionaryValue* m_state; - protocol::Debugger::Frontend m_frontend; - v8::Isolate* m_isolate; - v8::Global m_pausedContext; - JavaScriptCallFrames m_pausedCallFrames; - ScriptsMap m_scripts; - BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds; - DebugServerBreakpointToBreakpointIdAndSourceMap m_serverBreakpoints; - String16 m_continueToLocationBreakpointId; - String16 m_breakReason; - std::unique_ptr m_breakAuxData; - DebuggerStep m_scheduledDebuggerStep; - bool m_skipNextDebuggerStepOut; - bool m_javaScriptPauseScheduled; - bool m_steppingFromFramework; - bool m_pausingOnNativeEvent; - - int m_skippedStepFrameCount; - int m_recursionLevelForStepOut; - int m_recursionLevelForStepFrame; - bool m_skipAllPauses; - - std::unique_ptr m_blackboxPattern; - protocol::HashMap>> m_blackboxedPositions; -}; - -} // namespace v8_inspector - -#endif // V8DebuggerAgentImpl_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerScript.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerScript.cpp deleted file mode 100644 index 76e0c0066bfb89..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8DebuggerScript.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2014 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 "platform/v8_inspector/V8DebuggerScript.h" - -#include "platform/v8_inspector/V8StringUtil.h" - -namespace v8_inspector { - -static const char hexDigits[17] = "0123456789ABCDEF"; - -static void appendUnsignedAsHex(unsigned number, String16Builder* destination) -{ - for (size_t i = 0; i < 8; ++i) { - UChar c = hexDigits[number & 0xF]; - destination->append(c); - number >>= 4; - } -} - -// Hash algorithm for substrings is described in "Über die Komplexität der Multiplikation in -// eingeschränkten Branchingprogrammmodellen" by Woelfe. -// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000 -static String16 calculateHash(const String16& str) -{ - static uint64_t prime[] = { 0x3FB75161, 0xAB1F4E4F, 0x82675BC5, 0xCD924D35, 0x81ABE279 }; - static uint64_t random[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; - static uint32_t randomOdd[] = { 0xB4663807, 0xCC322BF5, 0xD4F91BBD, 0xA7BEA11D, 0x8F462907 }; - - uint64_t hashes[] = { 0, 0, 0, 0, 0 }; - uint64_t zi[] = { 1, 1, 1, 1, 1 }; - - const size_t hashesSize = PROTOCOL_ARRAY_LENGTH(hashes); - - size_t current = 0; - const uint32_t* data = nullptr; - size_t sizeInBytes = sizeof(UChar) * str.length(); - data = reinterpret_cast(str.characters16()); - for (size_t i = 0; i < sizeInBytes / 4; i += 4) { - uint32_t v = data[i]; - uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF; - hashes[current] = (hashes[current] + zi[current] * xi) % prime[current]; - zi[current] = (zi[current] * random[current]) % prime[current]; - current = current == hashesSize - 1 ? 0 : current + 1; - } - if (sizeInBytes % 4) { - uint32_t v = 0; - for (size_t i = sizeInBytes - sizeInBytes % 4; i < sizeInBytes; ++i) { - v <<= 8; - v |= reinterpret_cast(data)[i]; - } - uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF; - hashes[current] = (hashes[current] + zi[current] * xi) % prime[current]; - zi[current] = (zi[current] * random[current]) % prime[current]; - current = current == hashesSize - 1 ? 0 : current + 1; - } - - for (size_t i = 0; i < hashesSize; ++i) - hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i]; - - String16Builder hash; - for (size_t i = 0; i < hashesSize; ++i) - appendUnsignedAsHex(hashes[i], &hash); - return hash.toString(); -} - -V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, v8::Local object, bool isLiveEdit) -{ - v8::Local idValue = object->Get(toV8StringInternalized(isolate, "id")); - DCHECK(!idValue.IsEmpty() && idValue->IsInt32()); - m_id = String16::fromInteger(idValue->Int32Value()); - - m_url = toProtocolStringWithTypeCheck(object->Get(toV8StringInternalized(isolate, "name"))); - m_sourceURL = toProtocolStringWithTypeCheck(object->Get(toV8StringInternalized(isolate, "sourceURL"))); - m_sourceMappingURL = toProtocolStringWithTypeCheck(object->Get(toV8StringInternalized(isolate, "sourceMappingURL"))); - m_startLine = object->Get(toV8StringInternalized(isolate, "startLine"))->ToInteger(isolate)->Value(); - m_startColumn = object->Get(toV8StringInternalized(isolate, "startColumn"))->ToInteger(isolate)->Value(); - m_endLine = object->Get(toV8StringInternalized(isolate, "endLine"))->ToInteger(isolate)->Value(); - m_endColumn = object->Get(toV8StringInternalized(isolate, "endColumn"))->ToInteger(isolate)->Value(); - m_executionContextAuxData = toProtocolStringWithTypeCheck(object->Get(toV8StringInternalized(isolate, "executionContextAuxData"))); - m_executionContextId = object->Get(toV8StringInternalized(isolate, "executionContextId"))->ToInteger(isolate)->Value(); - m_isLiveEdit = isLiveEdit; - - v8::Local sourceValue = object->Get(toV8StringInternalized(isolate, "source")); - if (!sourceValue.IsEmpty() && sourceValue->IsString()) - setSource(isolate, sourceValue.As()); -} - -V8DebuggerScript::~V8DebuggerScript() -{ -} - -const String16& V8DebuggerScript::sourceURL() const -{ - return m_sourceURL.isEmpty() ? m_url : m_sourceURL; -} - -v8::Local V8DebuggerScript::source(v8::Isolate* isolate) const -{ - return m_source.Get(isolate); -} - -void V8DebuggerScript::setSourceURL(const String16& sourceURL) -{ - m_sourceURL = sourceURL; -} - -void V8DebuggerScript::setSourceMappingURL(const String16& sourceMappingURL) -{ - m_sourceMappingURL = sourceMappingURL; -} - -void V8DebuggerScript::setSource(v8::Isolate* isolate, v8::Local source) -{ - m_source.Reset(isolate, source); - m_hash = calculateHash(toProtocolString(source)); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8FunctionCall.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8FunctionCall.cpp deleted file mode 100644 index 2f3389c5365d78..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8FunctionCall.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#include "platform/v8_inspector/V8FunctionCall.h" - -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -#include - -namespace v8_inspector { - -V8FunctionCall::V8FunctionCall(V8InspectorImpl* inspector, v8::Local context, v8::Local value, const String16& name) - : m_inspector(inspector) - , m_context(context) - , m_name(toV8String(context->GetIsolate(), name)) - , m_value(value) -{ -} - -void V8FunctionCall::appendArgument(v8::Local value) -{ - m_arguments.push_back(value); -} - -void V8FunctionCall::appendArgument(const String16& argument) -{ - m_arguments.push_back(toV8String(m_context->GetIsolate(), argument)); -} - -void V8FunctionCall::appendArgument(int argument) -{ - m_arguments.push_back(v8::Number::New(m_context->GetIsolate(), argument)); -} - -void V8FunctionCall::appendArgument(bool argument) -{ - m_arguments.push_back(argument ? v8::True(m_context->GetIsolate()) : v8::False(m_context->GetIsolate())); -} - -v8::Local V8FunctionCall::call(bool& hadException, bool reportExceptions) -{ - v8::TryCatch tryCatch(m_context->GetIsolate()); - tryCatch.SetVerbose(reportExceptions); - - v8::Local result = callWithoutExceptionHandling(); - hadException = tryCatch.HasCaught(); - return result; -} - -v8::Local V8FunctionCall::callWithoutExceptionHandling() -{ - v8::Local thisObject = v8::Local::Cast(m_value); - v8::Local value; - if (!thisObject->Get(m_context, m_name).ToLocal(&value)) - return v8::Local(); - - DCHECK(value->IsFunction()); - - v8::Local function = v8::Local::Cast(value); - std::unique_ptr[]> info(new v8::Local[m_arguments.size()]); - for (size_t i = 0; i < m_arguments.size(); ++i) { - info[i] = m_arguments[i]; - DCHECK(!info[i].IsEmpty()); - } - - int contextGroupId = V8Debugger::getGroupId(m_context); - if (contextGroupId) { - m_inspector->client()->muteMetrics(contextGroupId); - m_inspector->muteExceptions(contextGroupId); - } - v8::MicrotasksScope microtasksScope(m_context->GetIsolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::MaybeLocal maybeResult = function->Call(m_context, thisObject, m_arguments.size(), info.get()); - if (contextGroupId) { - m_inspector->client()->unmuteMetrics(contextGroupId); - m_inspector->unmuteExceptions(contextGroupId); - } - - v8::Local result; - if (!maybeResult.ToLocal(&result)) - return v8::Local(); - return result; -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp deleted file mode 100644 index fb2981fadb3308..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp +++ /dev/null @@ -1,401 +0,0 @@ -// 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 "platform/v8_inspector/V8HeapProfilerAgentImpl.h" - -#include "platform/v8_inspector/InjectedScript.h" -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" -#include -#include - -namespace v8_inspector { - -namespace { - -namespace HeapProfilerAgentState { -static const char heapProfilerEnabled[] = "heapProfilerEnabled"; -static const char heapObjectsTrackingEnabled[] = "heapObjectsTrackingEnabled"; -static const char allocationTrackingEnabled[] = "allocationTrackingEnabled"; -#if V8_MAJOR_VERSION >= 5 -static const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled"; -static const char samplingHeapProfilerInterval[] = "samplingHeapProfilerInterval"; -#endif -} - -class HeapSnapshotProgress final : public v8::ActivityControl { -public: - HeapSnapshotProgress(protocol::HeapProfiler::Frontend* frontend) - : m_frontend(frontend) { } - ControlOption ReportProgressValue(int done, int total) override - { - m_frontend->reportHeapSnapshotProgress(done, total, protocol::Maybe()); - if (done >= total) { - m_frontend->reportHeapSnapshotProgress(total, total, true); - } - m_frontend->flush(); - return kContinue; - } -private: - protocol::HeapProfiler::Frontend* m_frontend; -}; - -class GlobalObjectNameResolver final : public v8::HeapProfiler::ObjectNameResolver { -public: - explicit GlobalObjectNameResolver(V8InspectorSessionImpl* session) - : m_offset(0), m_strings(10000), m_session(session) {} - - const char* GetName(v8::Local object) override - { - InspectedContext* context = m_session->inspector()->getContext(m_session->contextGroupId(), V8Debugger::contextId(object->CreationContext())); - if (!context) - return ""; - String16 name = context->origin(); - size_t length = name.length(); - if (m_offset + length + 1 >= m_strings.size()) - return ""; - for (size_t i = 0; i < length; ++i) { - UChar ch = name[i]; - m_strings[m_offset + i] = ch > 0xff ? '?' : static_cast(ch); - } - m_strings[m_offset + length] = '\0'; - char* result = &*m_strings.begin() + m_offset; - m_offset += length + 1; - return result; - } - -private: - size_t m_offset; - std::vector m_strings; - V8InspectorSessionImpl* m_session; -}; - -class HeapSnapshotOutputStream final : public v8::OutputStream { -public: - HeapSnapshotOutputStream(protocol::HeapProfiler::Frontend* frontend) - : m_frontend(frontend) { } - void EndOfStream() override { } - int GetChunkSize() override { return 102400; } - WriteResult WriteAsciiChunk(char* data, int size) override - { - m_frontend->addHeapSnapshotChunk(String16(data, size)); - m_frontend->flush(); - return kContinue; - } -private: - protocol::HeapProfiler::Frontend* m_frontend; -}; - -v8::Local objectByHeapObjectId(v8::Isolate* isolate, int id) -{ - v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); - v8::Local value = profiler->FindObjectById(id); - if (value.IsEmpty() || !value->IsObject()) - return v8::Local(); - return value.As(); -} - -class InspectableHeapObject final : public V8InspectorSession::Inspectable { -public: - explicit InspectableHeapObject(int heapObjectId) : m_heapObjectId(heapObjectId) { } - v8::Local get(v8::Local context) override - { - return objectByHeapObjectId(context->GetIsolate(), m_heapObjectId); - } -private: - int m_heapObjectId; -}; - -class HeapStatsStream final : public v8::OutputStream { -public: - HeapStatsStream(protocol::HeapProfiler::Frontend* frontend) - : m_frontend(frontend) - { - } - - void EndOfStream() override { } - - WriteResult WriteAsciiChunk(char* data, int size) override - { - DCHECK(false); - return kAbort; - } - - WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData, int count) override - { - DCHECK_GT(count, 0); - std::unique_ptr> statsDiff = protocol::Array::create(); - for (int i = 0; i < count; ++i) { - statsDiff->addItem(updateData[i].index); - statsDiff->addItem(updateData[i].count); - statsDiff->addItem(updateData[i].size); - } - m_frontend->heapStatsUpdate(std::move(statsDiff)); - return kContinue; - } - -private: - protocol::HeapProfiler::Frontend* m_frontend; -}; - -} // namespace - -V8HeapProfilerAgentImpl::V8HeapProfilerAgentImpl(V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, protocol::DictionaryValue* state) - : m_session(session) - , m_isolate(session->inspector()->isolate()) - , m_frontend(frontendChannel) - , m_state(state) - , m_hasTimer(false) -{ -} - -V8HeapProfilerAgentImpl::~V8HeapProfilerAgentImpl() -{ -} - -void V8HeapProfilerAgentImpl::restore() -{ - if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled, false)) - m_frontend.resetProfiles(); - if (m_state->booleanProperty(HeapProfilerAgentState::heapObjectsTrackingEnabled, false)) - startTrackingHeapObjectsInternal(m_state->booleanProperty(HeapProfilerAgentState::allocationTrackingEnabled, false)); -#if V8_MAJOR_VERSION >= 5 - if (m_state->booleanProperty(HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { - ErrorString error; - double samplingInterval = m_state->doubleProperty(HeapProfilerAgentState::samplingHeapProfilerInterval, -1); - DCHECK_GE(samplingInterval, 0); - startSampling(&error, Maybe(samplingInterval)); - } -#endif -} - -void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*) -{ - m_isolate->LowMemoryNotification(); -} - -void V8HeapProfilerAgentImpl::startTrackingHeapObjects(ErrorString*, const protocol::Maybe& trackAllocations) -{ - m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true); - bool allocationTrackingEnabled = trackAllocations.fromMaybe(false); - m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, allocationTrackingEnabled); - startTrackingHeapObjectsInternal(allocationTrackingEnabled); -} - -void V8HeapProfilerAgentImpl::stopTrackingHeapObjects(ErrorString* error, const protocol::Maybe& reportProgress) -{ - requestHeapStatsUpdate(); - takeHeapSnapshot(error, reportProgress); - stopTrackingHeapObjectsInternal(); -} - -void V8HeapProfilerAgentImpl::enable(ErrorString*) -{ - m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true); -} - -void V8HeapProfilerAgentImpl::disable(ErrorString* error) -{ - stopTrackingHeapObjectsInternal(); -#if V8_MAJOR_VERSION >= 5 - if (m_state->booleanProperty(HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { - v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); - if (profiler) - profiler->StopSamplingHeapProfiler(); - } -#endif - m_isolate->GetHeapProfiler()->ClearObjectIds(); - m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false); -} - -void V8HeapProfilerAgentImpl::takeHeapSnapshot(ErrorString* errorString, const protocol::Maybe& reportProgress) -{ - v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); - if (!profiler) { - *errorString = "Cannot access v8 heap profiler"; - return; - } - std::unique_ptr progress; - if (reportProgress.fromMaybe(false)) - progress = wrapUnique(new HeapSnapshotProgress(&m_frontend)); - - GlobalObjectNameResolver resolver(m_session); - const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(progress.get(), &resolver); - if (!snapshot) { - *errorString = "Failed to take heap snapshot"; - return; - } - HeapSnapshotOutputStream stream(&m_frontend); - snapshot->Serialize(&stream); - const_cast(snapshot)->Delete(); -} - -void V8HeapProfilerAgentImpl::getObjectByHeapObjectId(ErrorString* error, const String16& heapSnapshotObjectId, const protocol::Maybe& objectGroup, std::unique_ptr* result) -{ - bool ok; - int id = heapSnapshotObjectId.toInteger(&ok); - if (!ok) { - *error = "Invalid heap snapshot object id"; - return; - } - - v8::HandleScope handles(m_isolate); - v8::Local heapObject = objectByHeapObjectId(m_isolate, id); - if (heapObject.IsEmpty()) { - *error = "Object is not available"; - return; - } - - if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) { - *error = "Object is not available"; - return; - } - - *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, objectGroup.fromMaybe(""), false); - if (!result) - *error = "Object is not available"; -} - -void V8HeapProfilerAgentImpl::addInspectedHeapObject(ErrorString* errorString, const String16& inspectedHeapObjectId) -{ - bool ok; - int id = inspectedHeapObjectId.toInteger(&ok); - if (!ok) { - *errorString = "Invalid heap snapshot object id"; - return; - } - - v8::HandleScope handles(m_isolate); - v8::Local heapObject = objectByHeapObjectId(m_isolate, id); - if (heapObject.IsEmpty()) { - *errorString = "Object is not available"; - return; - } - - if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) { - *errorString = "Object is not available"; - return; - } - - m_session->addInspectedObject(wrapUnique(new InspectableHeapObject(id))); -} - -void V8HeapProfilerAgentImpl::getHeapObjectId(ErrorString* errorString, const String16& objectId, String16* heapSnapshotObjectId) -{ - v8::HandleScope handles(m_isolate); - v8::Local value; - v8::Local context; - String16 objectGroup; - if (!m_session->unwrapObject(errorString, objectId, &value, &context, &objectGroup) || value->IsUndefined()) - return; - - v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value); - *heapSnapshotObjectId = String16::fromInteger(id); -} - -void V8HeapProfilerAgentImpl::requestHeapStatsUpdate() -{ - HeapStatsStream stream(&m_frontend); - v8::SnapshotObjectId lastSeenObjectId = m_isolate->GetHeapProfiler()->GetHeapStats(&stream); - m_frontend.lastSeenObjectId(lastSeenObjectId, m_session->inspector()->client()->currentTimeMS()); -} - -// static -void V8HeapProfilerAgentImpl::onTimer(void* data) -{ - reinterpret_cast(data)->requestHeapStatsUpdate(); -} - -void V8HeapProfilerAgentImpl::startTrackingHeapObjectsInternal(bool trackAllocations) -{ - m_isolate->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations); - if (!m_hasTimer) { - m_hasTimer = true; - m_session->inspector()->client()->startRepeatingTimer(0.05, &V8HeapProfilerAgentImpl::onTimer, reinterpret_cast(this)); - } -} - -void V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal() -{ - if (m_hasTimer) { - m_session->inspector()->client()->cancelTimer(reinterpret_cast(this)); - m_hasTimer = false; - } - m_isolate->GetHeapProfiler()->StopTrackingHeapObjects(); - m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, false); - m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false); -} - -void V8HeapProfilerAgentImpl::startSampling(ErrorString* errorString, const Maybe& samplingInterval) -{ -#if V8_MAJOR_VERSION >= 5 - v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); - if (!profiler) { - *errorString = "Cannot access v8 heap profiler"; - return; - } - const unsigned defaultSamplingInterval = 1 << 15; - double samplingIntervalValue = samplingInterval.fromMaybe(defaultSamplingInterval); - m_state->setDouble(HeapProfilerAgentState::samplingHeapProfilerInterval, samplingIntervalValue); - m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, true); -#if V8_MAJOR_VERSION * 1000 + V8_MINOR_VERSION >= 5002 - profiler->StartSamplingHeapProfiler(static_cast(samplingIntervalValue), 128, v8::HeapProfiler::kSamplingForceGC); -#else - profiler->StartSamplingHeapProfiler(static_cast(samplingIntervalValue), 128); -#endif -#endif -} - -#if V8_MAJOR_VERSION >= 5 -namespace { -std::unique_ptr buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node) -{ - auto children = protocol::Array::create(); - for (const auto* child : node->children) - children->addItem(buildSampingHeapProfileNode(child)); - size_t selfSize = 0; - for (const auto& allocation : node->allocations) - selfSize += allocation.size * allocation.count; - std::unique_ptr callFrame = protocol::Runtime::CallFrame::create() - .setFunctionName(toProtocolString(node->name)) - .setScriptId(String16::fromInteger(node->script_id)) - .setUrl(toProtocolString(node->script_name)) - .setLineNumber(node->line_number - 1) - .setColumnNumber(node->column_number - 1) - .build(); - std::unique_ptr result = protocol::HeapProfiler::SamplingHeapProfileNode::create() - .setCallFrame(std::move(callFrame)) - .setSelfSize(selfSize) - .setChildren(std::move(children)).build(); - return result; -} -} // namespace -#endif - -void V8HeapProfilerAgentImpl::stopSampling(ErrorString* errorString, std::unique_ptr* profile) -{ -#if V8_MAJOR_VERSION >= 5 - v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); - if (!profiler) { - *errorString = "Cannot access v8 heap profiler"; - return; - } - v8::HandleScope scope(m_isolate); // Allocation profile contains Local handles. - std::unique_ptr v8Profile(profiler->GetAllocationProfile()); - profiler->StopSamplingHeapProfiler(); - m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, false); - if (!v8Profile) { - *errorString = "Cannot access v8 sampled heap profile."; - return; - } - v8::AllocationProfile::Node* root = v8Profile->GetRootNode(); - *profile = protocol::HeapProfiler::SamplingHeapProfile::create() - .setHead(buildSampingHeapProfileNode(root)).build(); -#endif -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.h deleted file mode 100644 index 198772a4836a4c..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8HeapProfilerAgentImpl.h +++ /dev/null @@ -1,59 +0,0 @@ -// 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 V8HeapProfilerAgentImpl_h -#define V8HeapProfilerAgentImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/HeapProfiler.h" - -#include - -namespace v8_inspector { - -class V8InspectorSessionImpl; - -namespace protocol = blink::protocol; -using blink::protocol::Maybe; - -class V8HeapProfilerAgentImpl : public protocol::HeapProfiler::Backend { - PROTOCOL_DISALLOW_COPY(V8HeapProfilerAgentImpl); -public: - V8HeapProfilerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, protocol::DictionaryValue* state); - ~V8HeapProfilerAgentImpl() override; - void restore(); - - void collectGarbage(ErrorString*) override; - - void enable(ErrorString*) override; - void startTrackingHeapObjects(ErrorString*, const Maybe& trackAllocations) override; - void stopTrackingHeapObjects(ErrorString*, const Maybe& reportProgress) override; - - void disable(ErrorString*) override; - - void takeHeapSnapshot(ErrorString*, const Maybe& reportProgress) override; - - void getObjectByHeapObjectId(ErrorString*, const String16& heapSnapshotObjectId, const Maybe& objectGroup, std::unique_ptr* result) override; - void addInspectedHeapObject(ErrorString*, const String16& inspectedHeapObjectId) override; - void getHeapObjectId(ErrorString*, const String16& objectId, String16* heapSnapshotObjectId) override; - - void startSampling(ErrorString*, const Maybe& samplingInterval) override; - void stopSampling(ErrorString*, std::unique_ptr*) override; - -private: - void startTrackingHeapObjectsInternal(bool trackAllocations); - void stopTrackingHeapObjectsInternal(); - void requestHeapStatsUpdate(); - static void onTimer(void*); - - V8InspectorSessionImpl* m_session; - v8::Isolate* m_isolate; - protocol::HeapProfiler::Frontend m_frontend; - protocol::DictionaryValue* m_state; - bool m_hasTimer; -}; - -} // namespace v8_inspector - -#endif // !defined(V8HeapProfilerAgentImpl_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.cpp deleted file mode 100644 index 782e5bbab01473..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2015 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 "platform/v8_inspector/V8InjectedScriptHost.h" - -#include "platform/v8_inspector/InjectedScriptNative.h" -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InternalValueType.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -namespace v8_inspector { - -namespace { - -void setFunctionProperty(v8::Local context, v8::Local obj, const char* name, v8::FunctionCallback callback, v8::Local external) -{ - v8::Local funcName = toV8StringInternalized(context->GetIsolate(), name); - v8::Local func; - if (!V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, callback, external, 0).ToLocal(&func)) - return; - func->SetName(funcName); - if (!obj->Set(context, funcName, func).FromMaybe(false)) - return; -} - -V8InspectorImpl* unwrapInspector(const v8::FunctionCallbackInfo& info) -{ - DCHECK(!info.Data().IsEmpty()); - DCHECK(info.Data()->IsExternal()); - V8InspectorImpl* inspector = static_cast(info.Data().As()->Value()); - DCHECK(inspector); - return inspector; -} - -} // namespace - -v8::Local V8InjectedScriptHost::create(v8::Local context, V8InspectorImpl* inspector) -{ - v8::Isolate* isolate = inspector->isolate(); - v8::Local injectedScriptHost = v8::Object::New(isolate); - bool success = injectedScriptHost->SetPrototype(context, v8::Null(isolate)).FromMaybe(false); - DCHECK(success); - v8::Local debuggerExternal = v8::External::New(isolate, inspector); - setFunctionProperty(context, injectedScriptHost, "internalConstructorName", V8InjectedScriptHost::internalConstructorNameCallback, debuggerExternal); - setFunctionProperty(context, injectedScriptHost, "formatAccessorsAsProperties", V8InjectedScriptHost::formatAccessorsAsProperties, debuggerExternal); - setFunctionProperty(context, injectedScriptHost, "subtype", V8InjectedScriptHost::subtypeCallback, debuggerExternal); - setFunctionProperty(context, injectedScriptHost, "getInternalProperties", V8InjectedScriptHost::getInternalPropertiesCallback, debuggerExternal); - setFunctionProperty(context, injectedScriptHost, "objectHasOwnProperty", V8InjectedScriptHost::objectHasOwnPropertyCallback, debuggerExternal); - setFunctionProperty(context, injectedScriptHost, "bind", V8InjectedScriptHost::bindCallback, debuggerExternal); - setFunctionProperty(context, injectedScriptHost, "proxyTargetValue", V8InjectedScriptHost::proxyTargetValueCallback, debuggerExternal); - return injectedScriptHost; -} - -void V8InjectedScriptHost::internalConstructorNameCallback(const v8::FunctionCallbackInfo& info) -{ - if (info.Length() < 1 || !info[0]->IsObject()) - return; - - v8::Local object = info[0].As(); - info.GetReturnValue().Set(object->GetConstructorName()); -} - -void V8InjectedScriptHost::formatAccessorsAsProperties(const v8::FunctionCallbackInfo& info) -{ - DCHECK_EQ(info.Length(), 2); - info.GetReturnValue().Set(false); - if (!info[1]->IsFunction()) - return; - // Check that function is user-defined. - if (info[1].As()->ScriptId() != v8::UnboundScript::kNoScriptId) - return; - info.GetReturnValue().Set(unwrapInspector(info)->client()->formatAccessorsAsProperties(info[0])); -} - -void V8InjectedScriptHost::subtypeCallback(const v8::FunctionCallbackInfo& info) -{ - if (info.Length() < 1) - return; - - v8::Isolate* isolate = info.GetIsolate(); - v8::Local value = info[0]; - if (value->IsObject()) { - v8::Local internalType = v8InternalValueTypeFrom(isolate->GetCurrentContext(), v8::Local::Cast(value)); - if (internalType->IsString()) { - info.GetReturnValue().Set(internalType); - return; - } - } - if (value->IsArray() || value->IsArgumentsObject()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "array")); - return; - } - if (value->IsTypedArray()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "typedarray")); - return; - } - if (value->IsDate()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "date")); - return; - } - if (value->IsRegExp()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "regexp")); - return; - } - if (value->IsMap() || value->IsWeakMap()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "map")); - return; - } - if (value->IsSet() || value->IsWeakSet()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "set")); - return; - } - if (value->IsMapIterator() || value->IsSetIterator()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "iterator")); - return; - } - if (value->IsGeneratorObject()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "generator")); - return; - } - if (value->IsNativeError()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "error")); - return; - } - if (value->IsProxy()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "proxy")); - return; - } - if (value->IsPromise()) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "promise")); - return; - } - String16 subtype = unwrapInspector(info)->client()->valueSubtype(value); - if (!subtype.isEmpty()) { - info.GetReturnValue().Set(toV8String(isolate, subtype)); - return; - } -} - -void V8InjectedScriptHost::getInternalPropertiesCallback(const v8::FunctionCallbackInfo& info) -{ - if (info.Length() < 1) - return; - v8::Local properties; - if (unwrapInspector(info)->debugger()->internalProperties(info.GetIsolate()->GetCurrentContext(), info[0]).ToLocal(&properties)) - info.GetReturnValue().Set(properties); -} - -void V8InjectedScriptHost::objectHasOwnPropertyCallback(const v8::FunctionCallbackInfo& info) -{ - if (info.Length() < 2 || !info[0]->IsObject() || !info[1]->IsString()) - return; - bool result = info[0].As()->HasOwnProperty(info.GetIsolate()->GetCurrentContext(), v8::Local::Cast(info[1])).FromMaybe(false); - info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), result)); -} - -void V8InjectedScriptHost::bindCallback(const v8::FunctionCallbackInfo& info) -{ - if (info.Length() < 2 || !info[1]->IsString()) - return; - InjectedScriptNative* injectedScriptNative = InjectedScriptNative::fromInjectedScriptHost(info.Holder()); - if (!injectedScriptNative) - return; - - v8::Local v8groupName = info[1]->ToString(info.GetIsolate()); - String16 groupName = toProtocolStringWithTypeCheck(v8groupName); - int id = injectedScriptNative->bind(info[0], groupName); - info.GetReturnValue().Set(id); -} - -void V8InjectedScriptHost::proxyTargetValueCallback(const v8::FunctionCallbackInfo& info) -{ - if (info.Length() != 1 || !info[0]->IsProxy()) { - NOTREACHED(); - return; - } - v8::Local target = info[0].As(); - while (target->IsProxy()) - target = v8::Local::Cast(target)->GetTarget(); - info.GetReturnValue().Set(target); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.h deleted file mode 100644 index 3123319f6c56f0..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InjectedScriptHost.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015 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 V8InjectedScriptHost_h -#define V8InjectedScriptHost_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include - -namespace v8_inspector { - -class V8InspectorImpl; - -namespace protocol = blink::protocol; - -// SECURITY NOTE: Although the InjectedScriptHost is intended for use solely by the inspector, -// a reference to the InjectedScriptHost may be leaked to the page being inspected. Thus, the -// InjectedScriptHost must never implemment methods that have more power over the page than the -// page already has itself (e.g. origin restriction bypasses). - -class V8InjectedScriptHost { -public: - // We expect that debugger outlives any JS context and thus V8InjectedScriptHost (owned by JS) - // is destroyed before inspector. - static v8::Local create(v8::Local, V8InspectorImpl*); -private: - static void internalConstructorNameCallback(const v8::FunctionCallbackInfo&); - static void formatAccessorsAsProperties(const v8::FunctionCallbackInfo&); - static void subtypeCallback(const v8::FunctionCallbackInfo&); - static void getInternalPropertiesCallback(const v8::FunctionCallbackInfo&); - static void objectHasOwnPropertyCallback(const v8::FunctionCallbackInfo&); - static void bindCallback(const v8::FunctionCallbackInfo&); - static void proxyTargetValueCallback(const v8::FunctionCallbackInfo&); -}; - -} // namespace v8_inspector - -#endif // V8InjectedScriptHost_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorImpl.cpp deleted file mode 100644 index 1a56906f782416..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorImpl.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (c) 2010-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. - */ - -#include "platform/v8_inspector/V8InspectorImpl.h" - -#include "platform/v8_inspector/InspectedContext.h" -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8ConsoleAgentImpl.h" -#include "platform/v8_inspector/V8ConsoleMessage.h" -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/V8DebuggerAgentImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8RuntimeAgentImpl.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" -#include - -namespace v8_inspector { - -std::unique_ptr V8Inspector::create(v8::Isolate* isolate, V8InspectorClient* client) -{ - return wrapUnique(new V8InspectorImpl(isolate, client)); -} - -V8InspectorImpl::V8InspectorImpl(v8::Isolate* isolate, V8InspectorClient* client) - : m_isolate(isolate) - , m_client(client) - , m_debugger(new V8Debugger(isolate, this)) - , m_capturingStackTracesCount(0) - , m_lastExceptionId(0) -{ -} - -V8InspectorImpl::~V8InspectorImpl() -{ -} - -V8DebuggerAgentImpl* V8InspectorImpl::enabledDebuggerAgentForGroup(int contextGroupId) -{ - V8InspectorSessionImpl* session = sessionForContextGroup(contextGroupId); - V8DebuggerAgentImpl* agent = session ? session->debuggerAgent() : nullptr; - return agent && agent->enabled() ? agent : nullptr; -} - -V8RuntimeAgentImpl* V8InspectorImpl::enabledRuntimeAgentForGroup(int contextGroupId) -{ - V8InspectorSessionImpl* session = sessionForContextGroup(contextGroupId); - V8RuntimeAgentImpl* agent = session ? session->runtimeAgent() : nullptr; - return agent && agent->enabled() ? agent : nullptr; -} - -v8::MaybeLocal V8InspectorImpl::runCompiledScript(v8::Local context, v8::Local script) -{ - v8::MicrotasksScope microtasksScope(m_isolate, v8::MicrotasksScope::kRunMicrotasks); - int groupId = V8Debugger::getGroupId(context); - if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) - agent->willExecuteScript(script->GetUnboundScript()->GetId()); - v8::MaybeLocal result = script->Run(context); - // Get agent from the map again, since it could have detached during script execution. - if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) - agent->didExecuteScript(); - return result; -} - -v8::MaybeLocal V8InspectorImpl::callFunction(v8::Local function, v8::Local context, v8::Local receiver, int argc, v8::Local info[]) -{ - v8::MicrotasksScope microtasksScope(m_isolate, v8::MicrotasksScope::kRunMicrotasks); - int groupId = V8Debugger::getGroupId(context); - if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) - agent->willExecuteScript(function->ScriptId()); - v8::MaybeLocal result = function->Call(context, receiver, argc, info); - // Get agent from the map again, since it could have detached during script execution. - if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) - agent->didExecuteScript(); - return result; -} - -v8::MaybeLocal V8InspectorImpl::compileAndRunInternalScript(v8::Local context, v8::Local source) -{ - v8::Local script = compileScript(context, source, String16(), true); - if (script.IsEmpty()) - return v8::MaybeLocal(); - v8::MicrotasksScope microtasksScope(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - return script->Run(context); -} - -v8::Local V8InspectorImpl::compileScript(v8::Local context, v8::Local code, const String16& fileName, bool markAsInternal) -{ - v8::ScriptOrigin origin( - toV8String(m_isolate, fileName), - v8::Integer::New(m_isolate, 0), - v8::Integer::New(m_isolate, 0), - v8::False(m_isolate), // sharable - v8::Local(), - v8::Boolean::New(m_isolate, markAsInternal), // internal - toV8String(m_isolate, String16()), // sourceMap - v8::True(m_isolate)); // opaqueresource - v8::ScriptCompiler::Source source(code, origin); - v8::Local script; - if (!v8::ScriptCompiler::Compile(context, &source, v8::ScriptCompiler::kNoCompileOptions).ToLocal(&script)) - return v8::Local(); - return script; -} - -void V8InspectorImpl::enableStackCapturingIfNeeded() -{ - if (!m_capturingStackTracesCount) - V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(m_isolate, true); - ++m_capturingStackTracesCount; -} - -void V8InspectorImpl::disableStackCapturingIfNeeded() -{ - if (!(--m_capturingStackTracesCount)) - V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(m_isolate, false); -} - -void V8InspectorImpl::muteExceptions(int contextGroupId) -{ - m_muteExceptionsMap[contextGroupId]++; -} - -void V8InspectorImpl::unmuteExceptions(int contextGroupId) -{ - m_muteExceptionsMap[contextGroupId]--; -} - -V8ConsoleMessageStorage* V8InspectorImpl::ensureConsoleMessageStorage(int contextGroupId) -{ - ConsoleStorageMap::iterator storageIt = m_consoleStorageMap.find(contextGroupId); - if (storageIt == m_consoleStorageMap.end()) - storageIt = m_consoleStorageMap.insert(std::make_pair(contextGroupId, wrapUnique(new V8ConsoleMessageStorage(this, contextGroupId)))).first; - return storageIt->second.get(); -} - -std::unique_ptr V8InspectorImpl::createStackTrace(v8::Local stackTrace) -{ - return m_debugger->createStackTrace(stackTrace); -} - -std::unique_ptr V8InspectorImpl::connect(int contextGroupId, protocol::FrontendChannel* channel, const String16* state) -{ - DCHECK(m_sessions.find(contextGroupId) == m_sessions.cend()); - std::unique_ptr session = V8InspectorSessionImpl::create(this, contextGroupId, channel, state); - m_sessions[contextGroupId] = session.get(); - return std::move(session); -} - -void V8InspectorImpl::disconnect(V8InspectorSessionImpl* session) -{ - DCHECK(m_sessions.find(session->contextGroupId()) != m_sessions.end()); - m_sessions.erase(session->contextGroupId()); -} - -InspectedContext* V8InspectorImpl::getContext(int groupId, int contextId) const -{ - if (!groupId || !contextId) - return nullptr; - - ContextsByGroupMap::const_iterator contextGroupIt = m_contexts.find(groupId); - if (contextGroupIt == m_contexts.end()) - return nullptr; - - ContextByIdMap::iterator contextIt = contextGroupIt->second->find(contextId); - if (contextIt == contextGroupIt->second->end()) - return nullptr; - - return contextIt->second.get(); -} - -void V8InspectorImpl::contextCreated(const V8ContextInfo& info) -{ - int contextId = m_debugger->markContext(info); - - ContextsByGroupMap::iterator contextIt = m_contexts.find(info.contextGroupId); - if (contextIt == m_contexts.end()) - contextIt = m_contexts.insert(std::make_pair(info.contextGroupId, wrapUnique(new ContextByIdMap()))).first; - - const auto& contextById = contextIt->second; - - DCHECK(contextById->find(contextId) == contextById->cend()); - InspectedContext* context = new InspectedContext(this, info, contextId); - (*contextById)[contextId] = wrapUnique(context); - SessionMap::iterator sessionIt = m_sessions.find(info.contextGroupId); - if (sessionIt != m_sessions.end()) - sessionIt->second->runtimeAgent()->reportExecutionContextCreated(context); -} - -void V8InspectorImpl::contextDestroyed(v8::Local context) -{ - int contextId = V8Debugger::contextId(context); - int contextGroupId = V8Debugger::getGroupId(context); - - ConsoleStorageMap::iterator storageIt = m_consoleStorageMap.find(contextGroupId); - if (storageIt != m_consoleStorageMap.end()) - storageIt->second->contextDestroyed(contextId); - - InspectedContext* inspectedContext = getContext(contextGroupId, contextId); - if (!inspectedContext) - return; - - SessionMap::iterator iter = m_sessions.find(contextGroupId); - if (iter != m_sessions.end()) - iter->second->runtimeAgent()->reportExecutionContextDestroyed(inspectedContext); - discardInspectedContext(contextGroupId, contextId); -} - -void V8InspectorImpl::resetContextGroup(int contextGroupId) -{ - m_consoleStorageMap.erase(contextGroupId); - m_muteExceptionsMap.erase(contextGroupId); - SessionMap::iterator session = m_sessions.find(contextGroupId); - if (session != m_sessions.end()) - session->second->reset(); - m_contexts.erase(contextGroupId); -} - -void V8InspectorImpl::willExecuteScript(v8::Local context, int scriptId) -{ - if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(V8Debugger::getGroupId(context))) - agent->willExecuteScript(scriptId); -} - -void V8InspectorImpl::didExecuteScript(v8::Local context) -{ - if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(V8Debugger::getGroupId(context))) - agent->didExecuteScript(); -} - -void V8InspectorImpl::idleStarted() -{ - m_isolate->GetCpuProfiler()->SetIdle(true); -} - -void V8InspectorImpl::idleFinished() -{ - m_isolate->GetCpuProfiler()->SetIdle(false); -} - -unsigned V8InspectorImpl::exceptionThrown(v8::Local context, const String16& message, v8::Local exception, const String16& detailedMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr stackTrace, int scriptId) -{ - int contextGroupId = V8Debugger::getGroupId(context); - if (!contextGroupId || m_muteExceptionsMap[contextGroupId]) - return 0; - std::unique_ptr stackTraceImpl = wrapUnique(static_cast(stackTrace.release())); - unsigned exceptionId = nextExceptionId(); - std::unique_ptr consoleMessage = V8ConsoleMessage::createForException(m_client->currentTimeMS(), detailedMessage, url, lineNumber, columnNumber, std::move(stackTraceImpl), scriptId, m_isolate, message, V8Debugger::contextId(context), exception, exceptionId); - ensureConsoleMessageStorage(contextGroupId)->addMessage(std::move(consoleMessage)); - return exceptionId; -} - -void V8InspectorImpl::exceptionRevoked(v8::Local context, unsigned exceptionId, const String16& message) -{ - int contextGroupId = V8Debugger::getGroupId(context); - if (!contextGroupId) - return; - - std::unique_ptr consoleMessage = V8ConsoleMessage::createForRevokedException(m_client->currentTimeMS(), message, exceptionId); - ensureConsoleMessageStorage(contextGroupId)->addMessage(std::move(consoleMessage)); -} - -std::unique_ptr V8InspectorImpl::captureStackTrace(bool fullStack) -{ - return m_debugger->captureStackTrace(fullStack); -} - -void V8InspectorImpl::asyncTaskScheduled(const String16& taskName, void* task, bool recurring) -{ - m_debugger->asyncTaskScheduled(taskName, task, recurring); -} - -void V8InspectorImpl::asyncTaskCanceled(void* task) -{ - m_debugger->asyncTaskCanceled(task); -} - -void V8InspectorImpl::asyncTaskStarted(void* task) -{ - m_debugger->asyncTaskStarted(task); -} - -void V8InspectorImpl::asyncTaskFinished(void* task) -{ - m_debugger->asyncTaskFinished(task); -} - -void V8InspectorImpl::allAsyncTasksCanceled() -{ - m_debugger->allAsyncTasksCanceled(); -} - -v8::Local V8InspectorImpl::regexContext() -{ - if (m_regexContext.IsEmpty()) - m_regexContext.Reset(m_isolate, v8::Context::New(m_isolate)); - return m_regexContext.Get(m_isolate); -} - -void V8InspectorImpl::discardInspectedContext(int contextGroupId, int contextId) -{ - if (!getContext(contextGroupId, contextId)) - return; - m_contexts[contextGroupId]->erase(contextId); - if (m_contexts[contextGroupId]->empty()) - m_contexts.erase(contextGroupId); -} - -const V8InspectorImpl::ContextByIdMap* V8InspectorImpl::contextGroup(int contextGroupId) -{ - ContextsByGroupMap::iterator iter = m_contexts.find(contextGroupId); - return iter == m_contexts.end() ? nullptr : iter->second.get(); -} - -V8InspectorSessionImpl* V8InspectorImpl::sessionForContextGroup(int contextGroupId) -{ - if (!contextGroupId) - return nullptr; - SessionMap::iterator iter = m_sessions.find(contextGroupId); - return iter == m_sessions.end() ? nullptr : iter->second; -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorImpl.h deleted file mode 100644 index 395c48ddd79d09..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorImpl.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2010, 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. - */ - -#ifndef V8InspectorImpl_h -#define V8InspectorImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/public/V8Inspector.h" - -#include -#include -#include - -namespace v8_inspector { - -class InspectedContext; -class V8ConsoleMessageStorage; -class V8Debugger; -class V8DebuggerAgentImpl; -class V8InspectorSessionImpl; -class V8RuntimeAgentImpl; -class V8StackTraceImpl; - -namespace protocol = blink::protocol; - -class V8InspectorImpl : public V8Inspector { - PROTOCOL_DISALLOW_COPY(V8InspectorImpl); -public: - V8InspectorImpl(v8::Isolate*, V8InspectorClient*); - ~V8InspectorImpl() override; - - v8::Isolate* isolate() const { return m_isolate; } - V8InspectorClient* client() { return m_client; } - V8Debugger* debugger() { return m_debugger.get(); } - - v8::MaybeLocal runCompiledScript(v8::Local, v8::Local); - v8::MaybeLocal callFunction(v8::Local, v8::Local, v8::Local receiver, int argc, v8::Local info[]); - v8::MaybeLocal compileAndRunInternalScript(v8::Local, v8::Local); - v8::Local compileScript(v8::Local, v8::Local, const String16& fileName, bool markAsInternal); - v8::Local regexContext(); - - // V8Inspector implementation. - std::unique_ptr connect(int contextGroupId, protocol::FrontendChannel*, const String16* state) override; - void contextCreated(const V8ContextInfo&) override; - void contextDestroyed(v8::Local) override; - void resetContextGroup(int contextGroupId) override; - void willExecuteScript(v8::Local, int scriptId) override; - void didExecuteScript(v8::Local) override; - void idleStarted() override; - void idleFinished() override; - unsigned exceptionThrown(v8::Local, const String16& message, v8::Local exception, const String16& detailedMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr, int scriptId) override; - void exceptionRevoked(v8::Local, unsigned exceptionId, const String16& message) override; - std::unique_ptr createStackTrace(v8::Local) override; - std::unique_ptr captureStackTrace(bool fullStack) override; - void asyncTaskScheduled(const String16& taskName, void* task, bool recurring) override; - void asyncTaskCanceled(void* task) override; - void asyncTaskStarted(void* task) override; - void asyncTaskFinished(void* task) override; - void allAsyncTasksCanceled() override; - - unsigned nextExceptionId() { return ++m_lastExceptionId; } - void enableStackCapturingIfNeeded(); - void disableStackCapturingIfNeeded(); - void muteExceptions(int contextGroupId); - void unmuteExceptions(int contextGroupId); - V8ConsoleMessageStorage* ensureConsoleMessageStorage(int contextGroupId); - using ContextByIdMap = protocol::HashMap>; - void discardInspectedContext(int contextGroupId, int contextId); - const ContextByIdMap* contextGroup(int contextGroupId); - void disconnect(V8InspectorSessionImpl*); - V8InspectorSessionImpl* sessionForContextGroup(int contextGroupId); - InspectedContext* getContext(int groupId, int contextId) const; - V8DebuggerAgentImpl* enabledDebuggerAgentForGroup(int contextGroupId); - V8RuntimeAgentImpl* enabledRuntimeAgentForGroup(int contextGroupId); - -private: - v8::Isolate* m_isolate; - V8InspectorClient* m_client; - std::unique_ptr m_debugger; - v8::Global m_regexContext; - int m_capturingStackTracesCount; - unsigned m_lastExceptionId; - - using MuteExceptionsMap = protocol::HashMap; - MuteExceptionsMap m_muteExceptionsMap; - - using ContextsByGroupMap = protocol::HashMap>; - ContextsByGroupMap m_contexts; - - using SessionMap = protocol::HashMap; - SessionMap m_sessions; - - using ConsoleStorageMap = protocol::HashMap>; - ConsoleStorageMap m_consoleStorageMap; -}; - -} // namespace v8_inspector - - -#endif // V8InspectorImpl_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.cpp deleted file mode 100644 index 51b288de882d75..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// 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 "platform/v8_inspector/V8InspectorSessionImpl.h" - -#include "platform/v8_inspector/InjectedScript.h" -#include "platform/v8_inspector/InspectedContext.h" -#include "platform/v8_inspector/RemoteObjectId.h" -#include "platform/v8_inspector/V8ConsoleAgentImpl.h" -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/V8DebuggerAgentImpl.h" -#include "platform/v8_inspector/V8HeapProfilerAgentImpl.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8ProfilerAgentImpl.h" -#include "platform/v8_inspector/V8RuntimeAgentImpl.h" -#include "platform/v8_inspector/V8SchemaAgentImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8ContextInfo.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -namespace v8_inspector { - -// static -bool V8InspectorSession::canDispatchMethod(const String16& method) -{ - return method.startsWith(protocol::Runtime::Metainfo::commandPrefix) - || method.startsWith(protocol::Debugger::Metainfo::commandPrefix) - || method.startsWith(protocol::Profiler::Metainfo::commandPrefix) - || method.startsWith(protocol::HeapProfiler::Metainfo::commandPrefix) - || method.startsWith(protocol::Console::Metainfo::commandPrefix) - || method.startsWith(protocol::Schema::Metainfo::commandPrefix); -} - -std::unique_ptr V8InspectorSessionImpl::create(V8InspectorImpl* inspector, int contextGroupId, protocol::FrontendChannel* channel, const String16* state) -{ - return wrapUnique(new V8InspectorSessionImpl(inspector, contextGroupId, channel, state)); -} - -V8InspectorSessionImpl::V8InspectorSessionImpl(V8InspectorImpl* inspector, int contextGroupId, protocol::FrontendChannel* channel, const String16* savedState) - : m_contextGroupId(contextGroupId) - , m_inspector(inspector) - , m_customObjectFormatterEnabled(false) - , m_dispatcher(channel) - , m_state(nullptr) - , m_runtimeAgent(nullptr) - , m_debuggerAgent(nullptr) - , m_heapProfilerAgent(nullptr) - , m_profilerAgent(nullptr) - , m_consoleAgent(nullptr) - , m_schemaAgent(nullptr) -{ - if (savedState) { - std::unique_ptr state = protocol::parseJSON(*savedState); - if (state) - m_state = protocol::DictionaryValue::cast(std::move(state)); - if (!m_state) - m_state = protocol::DictionaryValue::create(); - } else { - m_state = protocol::DictionaryValue::create(); - } - - m_runtimeAgent = wrapUnique(new V8RuntimeAgentImpl(this, channel, agentState(protocol::Runtime::Metainfo::domainName))); - protocol::Runtime::Dispatcher::wire(&m_dispatcher, m_runtimeAgent.get()); - - m_debuggerAgent = wrapUnique(new V8DebuggerAgentImpl(this, channel, agentState(protocol::Debugger::Metainfo::domainName))); - protocol::Debugger::Dispatcher::wire(&m_dispatcher, m_debuggerAgent.get()); - - m_profilerAgent = wrapUnique(new V8ProfilerAgentImpl(this, channel, agentState(protocol::Profiler::Metainfo::domainName))); - protocol::Profiler::Dispatcher::wire(&m_dispatcher, m_profilerAgent.get()); - - m_heapProfilerAgent = wrapUnique(new V8HeapProfilerAgentImpl(this, channel, agentState(protocol::HeapProfiler::Metainfo::domainName))); - protocol::HeapProfiler::Dispatcher::wire(&m_dispatcher, m_heapProfilerAgent.get()); - - m_consoleAgent = wrapUnique(new V8ConsoleAgentImpl(this, channel, agentState(protocol::Console::Metainfo::domainName))); - protocol::Console::Dispatcher::wire(&m_dispatcher, m_consoleAgent.get()); - - m_schemaAgent = wrapUnique(new V8SchemaAgentImpl(this, channel, agentState(protocol::Schema::Metainfo::domainName))); - protocol::Schema::Dispatcher::wire(&m_dispatcher, m_schemaAgent.get()); - - if (savedState) { - m_runtimeAgent->restore(); - m_debuggerAgent->restore(); - m_heapProfilerAgent->restore(); - m_profilerAgent->restore(); - m_consoleAgent->restore(); - } -} - -V8InspectorSessionImpl::~V8InspectorSessionImpl() -{ - ErrorString errorString; - m_consoleAgent->disable(&errorString); - m_profilerAgent->disable(&errorString); - m_heapProfilerAgent->disable(&errorString); - m_debuggerAgent->disable(&errorString); - m_runtimeAgent->disable(&errorString); - - discardInjectedScripts(); - m_inspector->disconnect(this); -} - -protocol::DictionaryValue* V8InspectorSessionImpl::agentState(const String16& name) -{ - protocol::DictionaryValue* state = m_state->getObject(name); - if (!state) { - std::unique_ptr newState = protocol::DictionaryValue::create(); - state = newState.get(); - m_state->setObject(name, std::move(newState)); - } - return state; -} - -void V8InspectorSessionImpl::reset() -{ - m_debuggerAgent->reset(); - m_runtimeAgent->reset(); - discardInjectedScripts(); -} - -void V8InspectorSessionImpl::discardInjectedScripts() -{ - m_inspectedObjects.clear(); - const V8InspectorImpl::ContextByIdMap* contexts = m_inspector->contextGroup(m_contextGroupId); - if (!contexts) - return; - - std::vector keys; - keys.reserve(contexts->size()); - for (auto& idContext : *contexts) - keys.push_back(idContext.first); - for (auto& key : keys) { - contexts = m_inspector->contextGroup(m_contextGroupId); - if (!contexts) - continue; - auto contextIt = contexts->find(key); - if (contextIt != contexts->end()) - contextIt->second->discardInjectedScript(); // This may destroy some contexts. - } -} - -InjectedScript* V8InspectorSessionImpl::findInjectedScript(ErrorString* errorString, int contextId) -{ - if (!contextId) { - *errorString = "Cannot find context with specified id"; - return nullptr; - } - - const V8InspectorImpl::ContextByIdMap* contexts = m_inspector->contextGroup(m_contextGroupId); - if (!contexts) { - *errorString = "Cannot find context with specified id"; - return nullptr; - } - - auto contextsIt = contexts->find(contextId); - if (contextsIt == contexts->end()) { - *errorString = "Cannot find context with specified id"; - return nullptr; - } - - const std::unique_ptr& context = contextsIt->second; - if (!context->getInjectedScript()) { - context->createInjectedScript(); - if (!context->getInjectedScript()) { - *errorString = "Cannot access specified execution context"; - return nullptr; - } - if (m_customObjectFormatterEnabled) - context->getInjectedScript()->setCustomObjectFormatterEnabled(true); - } - return context->getInjectedScript(); -} - -InjectedScript* V8InspectorSessionImpl::findInjectedScript(ErrorString* errorString, RemoteObjectIdBase* objectId) -{ - return objectId ? findInjectedScript(errorString, objectId->contextId()) : nullptr; -} - -void V8InspectorSessionImpl::releaseObjectGroup(const String16& objectGroup) -{ - const V8InspectorImpl::ContextByIdMap* contexts = m_inspector->contextGroup(m_contextGroupId); - if (!contexts) - return; - - std::vector keys; - for (auto& idContext : *contexts) - keys.push_back(idContext.first); - for (auto& key : keys) { - contexts = m_inspector->contextGroup(m_contextGroupId); - if (!contexts) - continue; - auto contextsIt = contexts->find(key); - if (contextsIt == contexts->end()) - continue; - InjectedScript* injectedScript = contextsIt->second->getInjectedScript(); - if (injectedScript) - injectedScript->releaseObjectGroup(objectGroup); // This may destroy some contexts. - } -} - -bool V8InspectorSessionImpl::unwrapObject(ErrorString* errorString, const String16& objectId, v8::Local* object, v8::Local* context, String16* objectGroup) -{ - std::unique_ptr remoteId = RemoteObjectId::parse(errorString, objectId); - if (!remoteId) - return false; - InjectedScript* injectedScript = findInjectedScript(errorString, remoteId.get()); - if (!injectedScript) - return false; - if (!injectedScript->findObject(errorString, *remoteId, object)) - return false; - *context = injectedScript->context()->context(); - *objectGroup = injectedScript->objectGroupName(*remoteId); - return true; -} - -std::unique_ptr V8InspectorSessionImpl::wrapObject(v8::Local context, v8::Local value, const String16& groupName) -{ - return wrapObject(context, value, groupName, false); -} - -std::unique_ptr V8InspectorSessionImpl::wrapObject(v8::Local context, v8::Local value, const String16& groupName, bool generatePreview) -{ - ErrorString errorString; - InjectedScript* injectedScript = findInjectedScript(&errorString, V8Debugger::contextId(context)); - if (!injectedScript) - return nullptr; - return injectedScript->wrapObject(&errorString, value, groupName, false, generatePreview); -} - -std::unique_ptr V8InspectorSessionImpl::wrapTable(v8::Local context, v8::Local table, v8::Local columns) -{ - ErrorString errorString; - InjectedScript* injectedScript = findInjectedScript(&errorString, V8Debugger::contextId(context)); - if (!injectedScript) - return nullptr; - return injectedScript->wrapTable(table, columns); -} - -void V8InspectorSessionImpl::setCustomObjectFormatterEnabled(bool enabled) -{ - m_customObjectFormatterEnabled = enabled; - const V8InspectorImpl::ContextByIdMap* contexts = m_inspector->contextGroup(m_contextGroupId); - if (!contexts) - return; - for (auto& idContext : *contexts) { - InjectedScript* injectedScript = idContext.second->getInjectedScript(); - if (injectedScript) - injectedScript->setCustomObjectFormatterEnabled(enabled); - } -} - -void V8InspectorSessionImpl::reportAllContexts(V8RuntimeAgentImpl* agent) -{ - const V8InspectorImpl::ContextByIdMap* contexts = m_inspector->contextGroup(m_contextGroupId); - if (!contexts) - return; - for (auto& idContext : *contexts) - agent->reportExecutionContextCreated(idContext.second.get()); -} - -void V8InspectorSessionImpl::dispatchProtocolMessage(const String16& message) -{ - m_dispatcher.dispatch(message); -} - -String16 V8InspectorSessionImpl::stateJSON() -{ - return m_state->toJSONString(); -} - -std::unique_ptr> V8InspectorSessionImpl::supportedDomains() -{ - std::vector> domains = supportedDomainsImpl(); - std::unique_ptr> result = protocol::Array::create(); - for (size_t i = 0; i < domains.size(); ++i) - result->addItem(std::move(domains[i])); - return result; -} - -std::vector> V8InspectorSessionImpl::supportedDomainsImpl() -{ - std::vector> result; - result.push_back(protocol::Schema::Domain::create().setName(protocol::Runtime::Metainfo::domainName).setVersion(protocol::Runtime::Metainfo::version).build()); - result.push_back(protocol::Schema::Domain::create().setName(protocol::Debugger::Metainfo::domainName).setVersion(protocol::Debugger::Metainfo::version).build()); - result.push_back(protocol::Schema::Domain::create().setName(protocol::Profiler::Metainfo::domainName).setVersion(protocol::Profiler::Metainfo::version).build()); - result.push_back(protocol::Schema::Domain::create().setName(protocol::HeapProfiler::Metainfo::domainName).setVersion(protocol::HeapProfiler::Metainfo::version).build()); - result.push_back(protocol::Schema::Domain::create().setName(protocol::Schema::Metainfo::domainName).setVersion(protocol::Schema::Metainfo::version).build()); - return result; -} - -void V8InspectorSessionImpl::addInspectedObject(std::unique_ptr inspectable) -{ - m_inspectedObjects.insert(m_inspectedObjects.begin(), std::move(inspectable)); - if (m_inspectedObjects.size() > kInspectedObjectBufferSize) - m_inspectedObjects.resize(kInspectedObjectBufferSize); -} - -V8InspectorSession::Inspectable* V8InspectorSessionImpl::inspectedObject(unsigned num) -{ - if (num >= m_inspectedObjects.size()) - return nullptr; - return m_inspectedObjects[num].get(); -} - -void V8InspectorSessionImpl::schedulePauseOnNextStatement(const String16& breakReason, const String16& breakDetails) -{ - m_debuggerAgent->schedulePauseOnNextStatement(breakReason, protocol::DictionaryValue::cast(parseJSON(breakDetails))); -} - -void V8InspectorSessionImpl::cancelPauseOnNextStatement() -{ - m_debuggerAgent->cancelPauseOnNextStatement(); -} - -void V8InspectorSessionImpl::breakProgram(const String16& breakReason, const String16& breakDetails) -{ - m_debuggerAgent->breakProgram(breakReason, protocol::DictionaryValue::cast(parseJSON(breakDetails))); -} - -void V8InspectorSessionImpl::setSkipAllPauses(bool skip) -{ - ErrorString errorString; - m_debuggerAgent->setSkipAllPauses(&errorString, skip); -} - -void V8InspectorSessionImpl::resume() -{ - ErrorString errorString; - m_debuggerAgent->resume(&errorString); -} - -void V8InspectorSessionImpl::stepOver() -{ - ErrorString errorString; - m_debuggerAgent->stepOver(&errorString); -} - -std::unique_ptr> V8InspectorSessionImpl::searchInTextByLines(const String16& text, const String16& query, bool caseSensitive, bool isRegex) -{ - std::vector> matches = searchInTextByLinesImpl(this, text, query, caseSensitive, isRegex); - std::unique_ptr> result = protocol::Array::create(); - for (size_t i = 0; i < matches.size(); ++i) - result->addItem(std::move(matches[i])); - return result; -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.h deleted file mode 100644 index 18164b7daf0215..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InspectorSessionImpl.h +++ /dev/null @@ -1,96 +0,0 @@ -// 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 V8InspectorSessionImpl_h -#define V8InspectorSessionImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/Runtime.h" -#include "platform/v8_inspector/protocol/Schema.h" -#include "platform/v8_inspector/public/V8InspectorSession.h" - -#include - -#include - -namespace v8_inspector { - -class InjectedScript; -class RemoteObjectIdBase; -class V8ConsoleAgentImpl; -class V8DebuggerAgentImpl; -class V8InspectorImpl; -class V8HeapProfilerAgentImpl; -class V8ProfilerAgentImpl; -class V8RuntimeAgentImpl; -class V8SchemaAgentImpl; - -namespace protocol = blink::protocol; - -class V8InspectorSessionImpl : public V8InspectorSession { - PROTOCOL_DISALLOW_COPY(V8InspectorSessionImpl); -public: - static std::unique_ptr create(V8InspectorImpl*, int contextGroupId, protocol::FrontendChannel*, const String16* state); - ~V8InspectorSessionImpl(); - - V8InspectorImpl* inspector() const { return m_inspector; } - V8ConsoleAgentImpl* consoleAgent() { return m_consoleAgent.get(); } - V8DebuggerAgentImpl* debuggerAgent() { return m_debuggerAgent.get(); } - V8SchemaAgentImpl* schemaAgent() { return m_schemaAgent.get(); } - V8ProfilerAgentImpl* profilerAgent() { return m_profilerAgent.get(); } - V8RuntimeAgentImpl* runtimeAgent() { return m_runtimeAgent.get(); } - int contextGroupId() const { return m_contextGroupId; } - - InjectedScript* findInjectedScript(ErrorString*, int contextId); - InjectedScript* findInjectedScript(ErrorString*, RemoteObjectIdBase*); - void reset(); - void discardInjectedScripts(); - void reportAllContexts(V8RuntimeAgentImpl*); - void setCustomObjectFormatterEnabled(bool); - std::unique_ptr wrapObject(v8::Local, v8::Local, const String16& groupName, bool generatePreview); - std::unique_ptr wrapTable(v8::Local, v8::Local table, v8::Local columns); - std::vector> supportedDomainsImpl(); - - // V8InspectorSession implementation. - void dispatchProtocolMessage(const String16& message) override; - String16 stateJSON() override; - std::unique_ptr> supportedDomains() override; - void addInspectedObject(std::unique_ptr) override; - void schedulePauseOnNextStatement(const String16& breakReason, const String16& breakDetails) override; - void cancelPauseOnNextStatement() override; - void breakProgram(const String16& breakReason, const String16& breakDetails) override; - void setSkipAllPauses(bool) override; - void resume() override; - void stepOver() override; - std::unique_ptr> searchInTextByLines(const String16& text, const String16& query, bool caseSensitive, bool isRegex) override; - void releaseObjectGroup(const String16& objectGroup) override; - bool unwrapObject(ErrorString*, const String16& objectId, v8::Local*, v8::Local*, String16* objectGroup) override; - std::unique_ptr wrapObject(v8::Local, v8::Local, const String16& groupName) override; - - V8InspectorSession::Inspectable* inspectedObject(unsigned num); - static const unsigned kInspectedObjectBufferSize = 5; - -private: - V8InspectorSessionImpl(V8InspectorImpl*, int contextGroupId, protocol::FrontendChannel*, const String16* state); - protocol::DictionaryValue* agentState(const String16& name); - - int m_contextGroupId; - V8InspectorImpl* m_inspector; - bool m_customObjectFormatterEnabled; - - protocol::UberDispatcher m_dispatcher; - std::unique_ptr m_state; - - std::unique_ptr m_runtimeAgent; - std::unique_ptr m_debuggerAgent; - std::unique_ptr m_heapProfilerAgent; - std::unique_ptr m_profilerAgent; - std::unique_ptr m_consoleAgent; - std::unique_ptr m_schemaAgent; - std::vector> m_inspectedObjects; -}; - -} // namespace v8_inspector - -#endif diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InternalValueType.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InternalValueType.cpp deleted file mode 100644 index 652de5982abb7e..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InternalValueType.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// 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 "platform/v8_inspector/V8InternalValueType.h" - -#include "platform/v8_inspector/V8StringUtil.h" - -namespace v8_inspector { - -namespace { - -v8::Local internalSubtypePrivate(v8::Isolate* isolate) -{ - return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InternalType#internalSubtype")); -} - -v8::Local subtypeForInternalType(v8::Isolate* isolate, V8InternalValueType type) -{ - switch (type) { - case V8InternalValueType::kEntry: - return toV8StringInternalized(isolate, "internal#entry"); - case V8InternalValueType::kLocation: - return toV8StringInternalized(isolate, "internal#location"); - case V8InternalValueType::kScope: - return toV8StringInternalized(isolate, "internal#scope"); - case V8InternalValueType::kScopeList: - return toV8StringInternalized(isolate, "internal#scopeList"); - } - NOTREACHED(); - return v8::Local(); -} - -} // namespace - -bool markAsInternal(v8::Local context, v8::Local object, V8InternalValueType type) -{ - v8::Isolate* isolate = context->GetIsolate(); - v8::Local privateValue = internalSubtypePrivate(isolate); - v8::Local subtype = subtypeForInternalType(isolate, type); - return object->SetPrivate(context, privateValue, subtype).FromMaybe(false); -} - -bool markArrayEntriesAsInternal(v8::Local context, v8::Local array, V8InternalValueType type) -{ - v8::Isolate* isolate = context->GetIsolate(); - v8::Local privateValue = internalSubtypePrivate(isolate); - v8::Local subtype = subtypeForInternalType(isolate, type); - for (size_t i = 0; i < array->Length(); ++i) { - v8::Local entry; - if (!array->Get(context, i).ToLocal(&entry) || !entry->IsObject()) - return false; - if (!entry.As()->SetPrivate(context, privateValue, subtype).FromMaybe(false)) - return false; - } - return true; -} - -v8::Local v8InternalValueTypeFrom(v8::Local context, v8::Local object) -{ - v8::Isolate* isolate = context->GetIsolate(); - v8::Local privateValue = internalSubtypePrivate(isolate); - if (!object->HasPrivate(context, privateValue).FromMaybe(false)) - return v8::Null(isolate); - v8::Local subtypeValue; - if (!object->GetPrivate(context, privateValue).ToLocal(&subtypeValue) || !subtypeValue->IsString()) - return v8::Null(isolate); - return subtypeValue; -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InternalValueType.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InternalValueType.h deleted file mode 100644 index 8655fea51d2100..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8InternalValueType.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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 V8InternalValueType_h -#define V8InternalValueType_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include - -namespace v8_inspector { - -enum class V8InternalValueType { kEntry, kLocation, kScope, kScopeList }; - -bool markAsInternal(v8::Local, v8::Local, V8InternalValueType); -bool markArrayEntriesAsInternal(v8::Local, v8::Local, V8InternalValueType); -v8::Local v8InternalValueTypeFrom(v8::Local, v8::Local); - - -} // namespace v8_inspector - -#endif // V8InternalValueType_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.cpp deleted file mode 100644 index 3385c7ed07b408..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.cpp +++ /dev/null @@ -1,337 +0,0 @@ -// Copyright 2015 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 "platform/v8_inspector/V8ProfilerAgentImpl.h" - -#include "platform/v8_inspector/Atomics.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include - -#include - -#define ENSURE_V8_VERSION(major, minor) \ - (V8_MAJOR_VERSION * 1000 + V8_MINOR_VERSION >= (major) * 1000 + (minor)) - -namespace v8_inspector { - -namespace ProfilerAgentState { -static const char samplingInterval[] = "samplingInterval"; -static const char userInitiatedProfiling[] = "userInitiatedProfiling"; -static const char profilerEnabled[] = "profilerEnabled"; -} - -namespace { - -std::unique_ptr> buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) -{ - unsigned lineCount = node->GetHitLineCount(); - if (!lineCount) - return nullptr; - auto array = protocol::Array::create(); - std::vector entries(lineCount); - if (node->GetLineTicks(&entries[0], lineCount)) { - for (unsigned i = 0; i < lineCount; i++) { - std::unique_ptr line = protocol::Profiler::PositionTickInfo::create() - .setLine(entries[i].line) - .setTicks(entries[i].hit_count).build(); - array->addItem(std::move(line)); - } - } - return array; -} - -std::unique_ptr buildInspectorObjectFor(v8::Isolate* isolate, const v8::CpuProfileNode* node) -{ - v8::HandleScope handleScope(isolate); - auto callFrame = protocol::Runtime::CallFrame::create() - .setFunctionName(toProtocolString(node->GetFunctionName())) - .setScriptId(String16::fromInteger(node->GetScriptId())) - .setUrl(toProtocolString(node->GetScriptResourceName())) - .setLineNumber(node->GetLineNumber() - 1) - .setColumnNumber(node->GetColumnNumber() - 1) - .build(); - auto result = protocol::Profiler::CPUProfileNode::create() - .setCallFrame(std::move(callFrame)) - .setHitCount(node->GetHitCount()) - .setId(node->GetNodeId()).build(); - - const int childrenCount = node->GetChildrenCount(); - if (childrenCount) { - auto children = protocol::Array::create(); - for (int i = 0; i < childrenCount; i++) - children->addItem(node->GetChild(i)->GetNodeId()); - result->setChildren(std::move(children)); - } - - const char* deoptReason = node->GetBailoutReason(); - if (deoptReason && deoptReason[0] && strcmp(deoptReason, "no reason")) - result->setDeoptReason(deoptReason); - - auto positionTicks = buildInspectorObjectForPositionTicks(node); - if (positionTicks) - result->setPositionTicks(std::move(positionTicks)); - - return result; -} - -std::unique_ptr> buildInspectorObjectForSamples(v8::CpuProfile* v8profile) -{ - auto array = protocol::Array::create(); - int count = v8profile->GetSamplesCount(); - for (int i = 0; i < count; i++) - array->addItem(v8profile->GetSample(i)->GetNodeId()); - return array; -} - -std::unique_ptr> buildInspectorObjectForTimestamps(v8::CpuProfile* v8profile) -{ - auto array = protocol::Array::create(); - int count = v8profile->GetSamplesCount(); - uint64_t lastTime = v8profile->GetStartTime(); - for (int i = 0; i < count; i++) { - uint64_t ts = v8profile->GetSampleTimestamp(i); - array->addItem(static_cast(ts - lastTime)); - lastTime = ts; - } - return array; -} - -void flattenNodesTree(v8::Isolate* isolate, const v8::CpuProfileNode* node, protocol::Array* list) -{ - list->addItem(buildInspectorObjectFor(isolate, node)); - const int childrenCount = node->GetChildrenCount(); - for (int i = 0; i < childrenCount; i++) - flattenNodesTree(isolate, node->GetChild(i), list); -} - -std::unique_ptr createCPUProfile(v8::Isolate* isolate, v8::CpuProfile* v8profile) -{ - auto nodes = protocol::Array::create(); - flattenNodesTree(isolate, v8profile->GetTopDownRoot(), nodes.get()); - - auto profile = protocol::Profiler::CPUProfile::create() - .setNodes(std::move(nodes)) - .setStartTime(static_cast(v8profile->GetStartTime())) - .setEndTime(static_cast(v8profile->GetEndTime())).build(); - profile->setSamples(buildInspectorObjectForSamples(v8profile)); - profile->setTimestampDeltas(buildInspectorObjectForTimestamps(v8profile)); - return profile; -} - -std::unique_ptr currentDebugLocation(V8InspectorImpl* inspector) -{ - std::unique_ptr callStack = inspector->captureStackTrace(1); - auto location = protocol::Debugger::Location::create() - .setScriptId(callStack->topScriptId()) - .setLineNumber(callStack->topLineNumber()).build(); - location->setColumnNumber(callStack->topColumnNumber()); - return location; -} - -volatile int s_lastProfileId = 0; - -} // namespace - -class V8ProfilerAgentImpl::ProfileDescriptor { -public: - ProfileDescriptor(const String16& id, const String16& title) - : m_id(id) - , m_title(title) { } - String16 m_id; - String16 m_title; -}; - -V8ProfilerAgentImpl::V8ProfilerAgentImpl(V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, protocol::DictionaryValue* state) - : m_session(session) - , m_isolate(m_session->inspector()->isolate()) - , m_profiler(nullptr) - , m_state(state) - , m_frontend(frontendChannel) - , m_enabled(false) - , m_recordingCPUProfile(false) -{ -} - -V8ProfilerAgentImpl::~V8ProfilerAgentImpl() -{ -#if ENSURE_V8_VERSION(5, 4) - if (m_profiler) - m_profiler->Dispose(); -#endif -} - -void V8ProfilerAgentImpl::consoleProfile(const String16& title) -{ - if (!m_enabled) - return; - String16 id = nextProfileId(); - m_startedProfiles.push_back(ProfileDescriptor(id, title)); - startProfiling(id); - m_frontend.consoleProfileStarted(id, currentDebugLocation(m_session->inspector()), title); -} - -void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) -{ - if (!m_enabled) - return; - String16 id; - String16 resolvedTitle; - // Take last started profile if no title was passed. - if (title.isEmpty()) { - if (m_startedProfiles.empty()) - return; - id = m_startedProfiles.back().m_id; - resolvedTitle = m_startedProfiles.back().m_title; - m_startedProfiles.pop_back(); - } else { - for (size_t i = 0; i < m_startedProfiles.size(); i++) { - if (m_startedProfiles[i].m_title == title) { - resolvedTitle = title; - id = m_startedProfiles[i].m_id; - m_startedProfiles.erase(m_startedProfiles.begin() + i); - break; - } - } - if (id.isEmpty()) - return; - } - std::unique_ptr profile = stopProfiling(id, true); - if (!profile) - return; - std::unique_ptr location = currentDebugLocation(m_session->inspector()); - m_frontend.consoleProfileFinished(id, std::move(location), std::move(profile), resolvedTitle); -} - -void V8ProfilerAgentImpl::enable(ErrorString*) -{ - if (m_enabled) - return; - m_enabled = true; -#if ENSURE_V8_VERSION(5, 4) - DCHECK(!m_profiler); - m_profiler = v8::CpuProfiler::New(m_isolate); -#endif - m_state->setBoolean(ProfilerAgentState::profilerEnabled, true); -} - -void V8ProfilerAgentImpl::disable(ErrorString* errorString) -{ - if (!m_enabled) - return; - for (size_t i = m_startedProfiles.size(); i > 0; --i) - stopProfiling(m_startedProfiles[i - 1].m_id, false); - m_startedProfiles.clear(); - stop(nullptr, nullptr); -#if ENSURE_V8_VERSION(5, 4) - m_profiler->Dispose(); - m_profiler = nullptr; -#endif - m_enabled = false; - m_state->setBoolean(ProfilerAgentState::profilerEnabled, false); -} - -void V8ProfilerAgentImpl::setSamplingInterval(ErrorString* error, int interval) -{ - if (m_recordingCPUProfile) { - *error = "Cannot change sampling interval when profiling."; - return; - } - m_state->setInteger(ProfilerAgentState::samplingInterval, interval); - profiler()->SetSamplingInterval(interval); -} - -void V8ProfilerAgentImpl::restore() -{ - DCHECK(!m_enabled); - if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false)) - return; - m_enabled = true; -#if ENSURE_V8_VERSION(5, 4) - DCHECK(!m_profiler); - m_profiler = v8::CpuProfiler::New(m_isolate); -#endif - int interval = 0; - m_state->getInteger(ProfilerAgentState::samplingInterval, &interval); - if (interval) - profiler()->SetSamplingInterval(interval); - if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, false)) { - ErrorString error; - start(&error); - } -} - -void V8ProfilerAgentImpl::start(ErrorString* error) -{ - if (m_recordingCPUProfile) - return; - if (!m_enabled) { - *error = "Profiler is not enabled"; - return; - } - m_recordingCPUProfile = true; - m_frontendInitiatedProfileId = nextProfileId(); - startProfiling(m_frontendInitiatedProfileId); - m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true); -} - -void V8ProfilerAgentImpl::stop(ErrorString* errorString, std::unique_ptr* profile) -{ - if (!m_recordingCPUProfile) { - if (errorString) - *errorString = "No recording profiles found"; - return; - } - m_recordingCPUProfile = false; - std::unique_ptr cpuProfile = stopProfiling(m_frontendInitiatedProfileId, !!profile); - if (profile) { - *profile = std::move(cpuProfile); - if (!profile->get() && errorString) - *errorString = "Profile is not found"; - } - m_frontendInitiatedProfileId = String16(); - m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false); -} - -String16 V8ProfilerAgentImpl::nextProfileId() -{ - return String16::fromInteger(atomicIncrement(&s_lastProfileId)); -} - -void V8ProfilerAgentImpl::startProfiling(const String16& title) -{ - v8::HandleScope handleScope(m_isolate); - profiler()->StartProfiling(toV8String(m_isolate, title), true); -} - -std::unique_ptr V8ProfilerAgentImpl::stopProfiling(const String16& title, bool serialize) -{ - v8::HandleScope handleScope(m_isolate); - v8::CpuProfile* profile = profiler()->StopProfiling(toV8String(m_isolate, title)); - if (!profile) - return nullptr; - std::unique_ptr result; - if (serialize) - result = createCPUProfile(m_isolate, profile); - profile->Delete(); - return result; -} - -bool V8ProfilerAgentImpl::isRecording() const -{ - return m_recordingCPUProfile || !m_startedProfiles.empty(); -} - -v8::CpuProfiler* V8ProfilerAgentImpl::profiler() -{ -#if ENSURE_V8_VERSION(5, 4) - return m_profiler; -#else - return m_isolate->GetCpuProfiler(); -#endif -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.h deleted file mode 100644 index b6513fde058194..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ProfilerAgentImpl.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2015 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 V8ProfilerAgentImpl_h -#define V8ProfilerAgentImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/Profiler.h" - -#include - -namespace v8 { -class CpuProfiler; -class Isolate; -} - -namespace v8_inspector { - -class V8InspectorSessionImpl; - -namespace protocol = blink::protocol; - -class V8ProfilerAgentImpl : public protocol::Profiler::Backend { - PROTOCOL_DISALLOW_COPY(V8ProfilerAgentImpl); -public: - V8ProfilerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, protocol::DictionaryValue* state); - ~V8ProfilerAgentImpl() override; - - bool enabled() const { return m_enabled; } - void restore(); - - void enable(ErrorString*) override; - void disable(ErrorString*) override; - void setSamplingInterval(ErrorString*, int) override; - void start(ErrorString*) override; - void stop(ErrorString*, std::unique_ptr*) override; - - void consoleProfile(const String16& title); - void consoleProfileEnd(const String16& title); - -private: - String16 nextProfileId(); - v8::CpuProfiler* profiler(); - - void startProfiling(const String16& title); - std::unique_ptr stopProfiling(const String16& title, bool serialize); - - bool isRecording() const; - - V8InspectorSessionImpl* m_session; - v8::Isolate* m_isolate; - v8::CpuProfiler* m_profiler; - protocol::DictionaryValue* m_state; - protocol::Profiler::Frontend m_frontend; - bool m_enabled; - bool m_recordingCPUProfile; - class ProfileDescriptor; - std::vector m_startedProfiles; - String16 m_frontendInitiatedProfileId; -}; - -} // namespace v8_inspector - -#endif // !defined(V8ProfilerAgentImpl_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Regex.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Regex.cpp deleted file mode 100644 index e8c8db2e4ddee4..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Regex.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// 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 "platform/v8_inspector/V8Regex.h" - -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -#include - -namespace v8_inspector { - -V8Regex::V8Regex(V8InspectorImpl* inspector, const String16& pattern, bool caseSensitive, bool multiline) - : m_inspector(inspector) -{ - v8::Isolate* isolate = m_inspector->isolate(); - v8::HandleScope handleScope(isolate); - v8::Local context = m_inspector->regexContext(); - v8::Context::Scope contextScope(context); - v8::TryCatch tryCatch(isolate); - - unsigned flags = v8::RegExp::kNone; - if (!caseSensitive) - flags |= v8::RegExp::kIgnoreCase; - if (multiline) - flags |= v8::RegExp::kMultiline; - - v8::Local regex; - if (v8::RegExp::New(context, toV8String(isolate, pattern), static_cast(flags)).ToLocal(®ex)) - m_regex.Reset(isolate, regex); - else if (tryCatch.HasCaught()) - m_errorMessage = toProtocolString(tryCatch.Message()->Get()); - else - m_errorMessage = "Internal error"; -} - -int V8Regex::match(const String16& string, int startFrom, int* matchLength) const -{ - if (matchLength) - *matchLength = 0; - - if (m_regex.IsEmpty() || string.isEmpty()) - return -1; - - // v8 strings are limited to int. - if (string.length() > INT_MAX) - return -1; - - v8::Isolate* isolate = m_inspector->isolate(); - v8::HandleScope handleScope(isolate); - v8::Local context = m_inspector->regexContext(); - v8::MicrotasksScope microtasks(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::TryCatch tryCatch(isolate); - - v8::Local regex = m_regex.Get(isolate); - v8::Local exec; - if (!regex->Get(context, toV8StringInternalized(isolate, "exec")).ToLocal(&exec)) - return -1; - v8::Local argv[] = { toV8String(isolate, string.substring(startFrom)) }; - v8::Local returnValue; - if (!exec.As()->Call(context, regex, PROTOCOL_ARRAY_LENGTH(argv), argv).ToLocal(&returnValue)) - return -1; - - // RegExp#exec returns null if there's no match, otherwise it returns an - // Array of strings with the first being the whole match string and others - // being subgroups. The Array also has some random properties tacked on like - // "index" which is the offset of the match. - // - // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec - - DCHECK(!returnValue.IsEmpty()); - if (!returnValue->IsArray()) - return -1; - - v8::Local result = returnValue.As(); - v8::Local matchOffset; - if (!result->Get(context, toV8StringInternalized(isolate, "index")).ToLocal(&matchOffset)) - return -1; - if (matchLength) { - v8::Local match; - if (!result->Get(context, 0).ToLocal(&match)) - return -1; - *matchLength = match.As()->Length(); - } - - return matchOffset.As()->Value() + startFrom; -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Regex.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Regex.h deleted file mode 100644 index b1b09c7e55ab60..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8Regex.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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 V8Regex_h -#define V8Regex_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include - -namespace v8_inspector { - -class V8InspectorImpl; - -enum MultilineMode { - MultilineDisabled, - MultilineEnabled -}; - -class V8Regex { - PROTOCOL_DISALLOW_COPY(V8Regex); -public: - V8Regex(V8InspectorImpl*, const String16&, bool caseSensitive, bool multiline = false); - int match(const String16&, int startFrom = 0, int* matchLength = 0) const; - bool isValid() const { return !m_regex.IsEmpty(); } - const String16& errorMessage() const { return m_errorMessage; } - -private: - V8InspectorImpl* m_inspector; - v8::Global m_regex; - String16 m_errorMessage; -}; - -} // namespace v8_inspector - -#endif // V8Regex_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.cpp deleted file mode 100644 index c5a0449c1497d2..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.cpp +++ /dev/null @@ -1,687 +0,0 @@ -/* - * 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. - */ - -#include "platform/v8_inspector/V8RuntimeAgentImpl.h" - -#include "platform/v8_inspector/InjectedScript.h" -#include "platform/v8_inspector/InspectedContext.h" -#include "platform/v8_inspector/RemoteObjectId.h" -#include "platform/v8_inspector/V8Compat.h" -#include "platform/v8_inspector/V8ConsoleMessage.h" -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/V8DebuggerAgentImpl.h" -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8StackTraceImpl.h" -#include "platform/v8_inspector/V8StringUtil.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" - -namespace v8_inspector { - -namespace V8RuntimeAgentImplState { -static const char customObjectFormatterEnabled[] = "customObjectFormatterEnabled"; -static const char runtimeEnabled[] = "runtimeEnabled"; -}; - -using protocol::Runtime::RemoteObject; - -static bool hasInternalError(ErrorString* errorString, bool hasError) -{ - if (hasError) - *errorString = "Internal error"; - return hasError; -} - -namespace { - -template -class ProtocolPromiseHandler { -public: - static void add(V8InspectorImpl* inspector, v8::Local context, v8::MaybeLocal value, const String16& notPromiseError, int contextGroupId, int executionContextId, const String16& objectGroup, bool returnByValue, bool generatePreview, std::unique_ptr callback) - { - if (value.IsEmpty()) { - callback->sendFailure("Internal error"); - return; - } - if (!value.ToLocalChecked()->IsPromise()) { - callback->sendFailure(notPromiseError); - return; - } - v8::Local promise = v8::Local::Cast(value.ToLocalChecked()); - Callback* rawCallback = callback.get(); - ProtocolPromiseHandler* handler = new ProtocolPromiseHandler(inspector, contextGroupId, executionContextId, objectGroup, returnByValue, generatePreview, std::move(callback)); - v8::Local wrapper = handler->m_wrapper.Get(inspector->isolate()); - - v8::Local thenCallbackFunction = V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, thenCallback, wrapper, 0).ToLocalChecked(); - if (promise->Then(context, thenCallbackFunction).IsEmpty()) { - rawCallback->sendFailure("Internal error"); - return; - } - v8::Local catchCallbackFunction = V8_FUNCTION_NEW_REMOVE_PROTOTYPE(context, catchCallback, wrapper, 0).ToLocalChecked(); - if (promise->Catch(context, catchCallbackFunction).IsEmpty()) { - rawCallback->sendFailure("Internal error"); - return; - } - } -private: - static void thenCallback(const v8::FunctionCallbackInfo& info) - { - ProtocolPromiseHandler* handler = static_cast*>(info.Data().As()->Value()); - DCHECK(handler); - v8::Local value = info.Length() > 0 ? info[0] : v8::Local::Cast(v8::Undefined(info.GetIsolate())); - handler->m_callback->sendSuccess(handler->wrapObject(value), Maybe()); - } - - static void catchCallback(const v8::FunctionCallbackInfo& info) - { - ProtocolPromiseHandler* handler = static_cast*>(info.Data().As()->Value()); - DCHECK(handler); - v8::Local value = info.Length() > 0 ? info[0] : v8::Local::Cast(v8::Undefined(info.GetIsolate())); - - std::unique_ptr stack = handler->m_inspector->debugger()->captureStackTrace(true); - std::unique_ptr exceptionDetails = protocol::Runtime::ExceptionDetails::create() - .setExceptionId(handler->m_inspector->nextExceptionId()) - .setText("Uncaught (in promise)") - .setLineNumber(stack && !stack->isEmpty() ? stack->topLineNumber() : 0) - .setColumnNumber(stack && !stack->isEmpty() ? stack->topColumnNumber() : 0) - .setException(handler->wrapObject(value)) - .build(); - if (stack) - exceptionDetails->setStackTrace(stack->buildInspectorObjectImpl()); - if (stack && !stack->isEmpty()) - exceptionDetails->setScriptId(stack->topScriptId()); - handler->m_callback->sendSuccess(handler->wrapObject(value), std::move(exceptionDetails)); - } - - ProtocolPromiseHandler(V8InspectorImpl* inspector, int contextGroupId, int executionContextId, const String16& objectGroup, bool returnByValue, bool generatePreview, std::unique_ptr callback) - : m_inspector(inspector) - , m_contextGroupId(contextGroupId) - , m_executionContextId(executionContextId) - , m_objectGroup(objectGroup) - , m_returnByValue(returnByValue) - , m_generatePreview(generatePreview) - , m_callback(std::move(callback)) - , m_wrapper(inspector->isolate(), v8::External::New(inspector->isolate(), this)) - { - m_wrapper.SetWeak(this, cleanup, v8::WeakCallbackType::kParameter); - } - - static void cleanup(const v8::WeakCallbackInfo>& data) - { - if (!data.GetParameter()->m_wrapper.IsEmpty()) { - data.GetParameter()->m_wrapper.Reset(); - data.SetSecondPassCallback(cleanup); - } else { - data.GetParameter()->m_callback->sendFailure("Promise was collected"); - delete data.GetParameter(); - } - } - - std::unique_ptr wrapObject(v8::Local value) - { - ErrorString errorString; - InjectedScript::ContextScope scope(&errorString, m_inspector, m_contextGroupId, m_executionContextId); - if (!scope.initialize()) { - m_callback->sendFailure(errorString); - return nullptr; - } - std::unique_ptr wrappedValue = scope.injectedScript()->wrapObject(&errorString, value, m_objectGroup, m_returnByValue, m_generatePreview); - if (!wrappedValue) { - m_callback->sendFailure(errorString); - return nullptr; - } - return wrappedValue; - } - - V8InspectorImpl* m_inspector; - int m_contextGroupId; - int m_executionContextId; - String16 m_objectGroup; - bool m_returnByValue; - bool m_generatePreview; - std::unique_ptr m_callback; - v8::Global m_wrapper; -}; - -template -bool wrapEvaluateResultAsync(InjectedScript* injectedScript, v8::MaybeLocal maybeResultValue, const v8::TryCatch& tryCatch, const String16& objectGroup, bool returnByValue, bool generatePreview, Callback* callback) -{ - std::unique_ptr result; - Maybe exceptionDetails; - - ErrorString errorString; - injectedScript->wrapEvaluateResult(&errorString, - maybeResultValue, - tryCatch, - objectGroup, - returnByValue, - generatePreview, - &result, - &exceptionDetails); - if (errorString.isEmpty()) { - callback->sendSuccess(std::move(result), exceptionDetails); - return true; - } - callback->sendFailure(errorString); - return false; -} - -int ensureContext(ErrorString* errorString, V8InspectorImpl* inspector, int contextGroupId, const Maybe& executionContextId) -{ - int contextId; - if (executionContextId.isJust()) { - contextId = executionContextId.fromJust(); - } else { - v8::HandleScope handles(inspector->isolate()); - v8::Local defaultContext = inspector->client()->ensureDefaultContextInGroup(contextGroupId); - if (defaultContext.IsEmpty()) { - *errorString = "Cannot find default execution context"; - return 0; - } - contextId = V8Debugger::contextId(defaultContext); - } - return contextId; -} - -} // namespace - -V8RuntimeAgentImpl::V8RuntimeAgentImpl(V8InspectorSessionImpl* session, protocol::FrontendChannel* FrontendChannel, protocol::DictionaryValue* state) - : m_session(session) - , m_state(state) - , m_frontend(FrontendChannel) - , m_inspector(session->inspector()) - , m_enabled(false) -{ -} - -V8RuntimeAgentImpl::~V8RuntimeAgentImpl() -{ -} - -void V8RuntimeAgentImpl::evaluate( - const String16& expression, - const Maybe& objectGroup, - const Maybe& includeCommandLineAPI, - const Maybe& silent, - const Maybe& executionContextId, - const Maybe& returnByValue, - const Maybe& generatePreview, - const Maybe& userGesture, - const Maybe& awaitPromise, - std::unique_ptr callback) -{ - ErrorString errorString; - int contextId = ensureContext(&errorString, m_inspector, m_session->contextGroupId(), executionContextId); - if (!errorString.isEmpty()) { - callback->sendFailure(errorString); - return; - } - - InjectedScript::ContextScope scope(&errorString, m_inspector, m_session->contextGroupId(), contextId); - if (!scope.initialize()) { - callback->sendFailure(errorString); - return; - } - - if (silent.fromMaybe(false)) - scope.ignoreExceptionsAndMuteConsole(); - if (userGesture.fromMaybe(false)) - scope.pretendUserGesture(); - - if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI()) { - callback->sendFailure(errorString); - return; - } - - bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed(); - // Temporarily enable allow evals for inspector. - if (evalIsDisabled) - scope.context()->AllowCodeGenerationFromStrings(true); - - v8::MaybeLocal maybeResultValue; - v8::Local script = m_inspector->compileScript(scope.context(), toV8String(m_inspector->isolate(), expression), String16(), false); - if (!script.IsEmpty()) - maybeResultValue = m_inspector->runCompiledScript(scope.context(), script); - - if (evalIsDisabled) - scope.context()->AllowCodeGenerationFromStrings(false); - - // Re-initialize after running client's code, as it could have destroyed context or session. - if (!scope.initialize()) { - callback->sendFailure(errorString); - return; - } - - if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) { - wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), callback.get()); - return; - } - ProtocolPromiseHandler::add( - m_inspector, - scope.context(), - maybeResultValue, - "Result of the evaluation is not a promise", - m_session->contextGroupId(), - scope.injectedScript()->context()->contextId(), - objectGroup.fromMaybe(""), - returnByValue.fromMaybe(false), - generatePreview.fromMaybe(false), - std::move(callback)); -} - -void V8RuntimeAgentImpl::awaitPromise( - const String16& promiseObjectId, - const Maybe& returnByValue, - const Maybe& generatePreview, - std::unique_ptr callback) -{ - ErrorString errorString; - InjectedScript::ObjectScope scope(&errorString, m_inspector, m_session->contextGroupId(), promiseObjectId); - if (!scope.initialize()) { - callback->sendFailure(errorString); - return; - } - ProtocolPromiseHandler::add( - m_inspector, - scope.context(), - scope.object(), - "Could not find promise with given id", - m_session->contextGroupId(), - scope.injectedScript()->context()->contextId(), - scope.objectGroupName(), - returnByValue.fromMaybe(false), - generatePreview.fromMaybe(false), - std::move(callback)); -} - -void V8RuntimeAgentImpl::callFunctionOn( - const String16& objectId, - const String16& expression, - const Maybe>& optionalArguments, - const Maybe& silent, - const Maybe& returnByValue, - const Maybe& generatePreview, - const Maybe& userGesture, - const Maybe& awaitPromise, - std::unique_ptr callback) -{ - ErrorString errorString; - InjectedScript::ObjectScope scope(&errorString, m_inspector, m_session->contextGroupId(), objectId); - if (!scope.initialize()) { - callback->sendFailure(errorString); - return; - } - - std::unique_ptr[]> argv = nullptr; - int argc = 0; - if (optionalArguments.isJust()) { - protocol::Array* arguments = optionalArguments.fromJust(); - argc = arguments->length(); - argv.reset(new v8::Local[argc]); - for (int i = 0; i < argc; ++i) { - v8::Local argumentValue; - if (!scope.injectedScript()->resolveCallArgument(&errorString, arguments->get(i)).ToLocal(&argumentValue)) { - callback->sendFailure(errorString); - return; - } - argv[i] = argumentValue; - } - } - - if (silent.fromMaybe(false)) - scope.ignoreExceptionsAndMuteConsole(); - if (userGesture.fromMaybe(false)) - scope.pretendUserGesture(); - - v8::MaybeLocal maybeFunctionValue = m_inspector->compileAndRunInternalScript(scope.context(), toV8String(m_inspector->isolate(), "(" + expression + ")")); - // Re-initialize after running client's code, as it could have destroyed context or session. - if (!scope.initialize()) { - callback->sendFailure(errorString); - return; - } - - if (scope.tryCatch().HasCaught()) { - wrapEvaluateResultAsync(scope.injectedScript(), maybeFunctionValue, scope.tryCatch(), scope.objectGroupName(), false, false, callback.get()); - return; - } - - v8::Local functionValue; - if (!maybeFunctionValue.ToLocal(&functionValue) || !functionValue->IsFunction()) { - callback->sendFailure("Given expression does not evaluate to a function"); - return; - } - - v8::MaybeLocal maybeResultValue = m_inspector->callFunction(functionValue.As(), scope.context(), scope.object(), argc, argv.get()); - // Re-initialize after running client's code, as it could have destroyed context or session. - if (!scope.initialize()) { - callback->sendFailure(errorString); - return; - } - - if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) { - wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue, scope.tryCatch(), scope.objectGroupName(), returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), callback.get()); - return; - } - - ProtocolPromiseHandler::add( - m_inspector, - scope.context(), - maybeResultValue, - "Result of the function call is not a promise", - m_session->contextGroupId(), - scope.injectedScript()->context()->contextId(), - scope.objectGroupName(), - returnByValue.fromMaybe(false), - generatePreview.fromMaybe(false), - std::move(callback)); -} - -void V8RuntimeAgentImpl::getProperties( - ErrorString* errorString, - const String16& objectId, - const Maybe& ownProperties, - const Maybe& accessorPropertiesOnly, - const Maybe& generatePreview, - std::unique_ptr>* result, - Maybe>* internalProperties, - Maybe* exceptionDetails) -{ - using protocol::Runtime::InternalPropertyDescriptor; - - InjectedScript::ObjectScope scope(errorString, m_inspector, m_session->contextGroupId(), objectId); - if (!scope.initialize()) - return; - - scope.ignoreExceptionsAndMuteConsole(); - if (!scope.object()->IsObject()) { - *errorString = "Value with given id is not an object"; - return; - } - - v8::Local object = scope.object().As(); - scope.injectedScript()->getProperties(errorString, object, scope.objectGroupName(), ownProperties.fromMaybe(false), accessorPropertiesOnly.fromMaybe(false), generatePreview.fromMaybe(false), result, exceptionDetails); - if (!errorString->isEmpty() || exceptionDetails->isJust() || accessorPropertiesOnly.fromMaybe(false)) - return; - v8::Local propertiesArray; - if (hasInternalError(errorString, !m_inspector->debugger()->internalProperties(scope.context(), scope.object()).ToLocal(&propertiesArray))) - return; - std::unique_ptr> propertiesProtocolArray = protocol::Array::create(); - for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) { - v8::Local name; - if (hasInternalError(errorString, !propertiesArray->Get(scope.context(), i).ToLocal(&name)) || !name->IsString()) - return; - v8::Local value; - if (hasInternalError(errorString, !propertiesArray->Get(scope.context(), i + 1).ToLocal(&value))) - return; - std::unique_ptr wrappedValue = scope.injectedScript()->wrapObject(errorString, value, scope.objectGroupName()); - if (!wrappedValue) - return; - propertiesProtocolArray->addItem(InternalPropertyDescriptor::create() - .setName(toProtocolString(name.As())) - .setValue(std::move(wrappedValue)).build()); - } - if (!propertiesProtocolArray->length()) - return; - *internalProperties = std::move(propertiesProtocolArray); -} - -void V8RuntimeAgentImpl::releaseObject(ErrorString* errorString, const String16& objectId) -{ - InjectedScript::ObjectScope scope(errorString, m_inspector, m_session->contextGroupId(), objectId); - if (!scope.initialize()) - return; - scope.injectedScript()->releaseObject(objectId); -} - -void V8RuntimeAgentImpl::releaseObjectGroup(ErrorString*, const String16& objectGroup) -{ - m_session->releaseObjectGroup(objectGroup); -} - -void V8RuntimeAgentImpl::runIfWaitingForDebugger(ErrorString* errorString) -{ - m_inspector->client()->runIfWaitingForDebugger(m_session->contextGroupId()); -} - -void V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(ErrorString*, bool enabled) -{ - m_state->setBoolean(V8RuntimeAgentImplState::customObjectFormatterEnabled, enabled); - m_session->setCustomObjectFormatterEnabled(enabled); -} - -void V8RuntimeAgentImpl::discardConsoleEntries(ErrorString*) -{ - V8ConsoleMessageStorage* storage = m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId()); - storage->clear(); -} - -void V8RuntimeAgentImpl::compileScript(ErrorString* errorString, - const String16& expression, - const String16& sourceURL, - bool persistScript, - const Maybe& executionContextId, - Maybe* scriptId, - Maybe* exceptionDetails) -{ - if (!m_enabled) { - *errorString = "Runtime agent is not enabled"; - return; - } - int contextId = ensureContext(errorString, m_inspector, m_session->contextGroupId(), executionContextId); - if (!errorString->isEmpty()) - return; - InjectedScript::ContextScope scope(errorString, m_inspector, m_session->contextGroupId(), contextId); - if (!scope.initialize()) - return; - - if (!persistScript) - m_inspector->debugger()->muteScriptParsedEvents(); - v8::Local script = m_inspector->compileScript(scope.context(), toV8String(m_inspector->isolate(), expression), sourceURL, false); - if (!persistScript) - m_inspector->debugger()->unmuteScriptParsedEvents(); - if (script.IsEmpty()) { - if (scope.tryCatch().HasCaught()) - *exceptionDetails = scope.injectedScript()->createExceptionDetails(errorString, scope.tryCatch(), String16(), false); - else - *errorString = "Script compilation failed"; - return; - } - - if (!persistScript) - return; - - String16 scriptValueId = String16::fromInteger(script->GetUnboundScript()->GetId()); - std::unique_ptr> global(new v8::Global(m_inspector->isolate(), script)); - m_compiledScripts[scriptValueId] = std::move(global); - *scriptId = scriptValueId; -} - -void V8RuntimeAgentImpl::runScript( - const String16& scriptId, - const Maybe& executionContextId, - const Maybe& objectGroup, - const Maybe& silent, - const Maybe& includeCommandLineAPI, - const Maybe& returnByValue, - const Maybe& generatePreview, - const Maybe& awaitPromise, - std::unique_ptr callback) -{ - if (!m_enabled) { - callback->sendFailure("Runtime agent is not enabled"); - return; - } - - auto it = m_compiledScripts.find(scriptId); - if (it == m_compiledScripts.end()) { - callback->sendFailure("No script with given id"); - return; - } - - ErrorString errorString; - int contextId = ensureContext(&errorString, m_inspector, m_session->contextGroupId(), executionContextId); - if (!errorString.isEmpty()) { - callback->sendFailure(errorString); - return; - } - - InjectedScript::ContextScope scope(&errorString, m_inspector, m_session->contextGroupId(), contextId); - if (!scope.initialize()) { - callback->sendFailure(errorString); - return; - } - - if (silent.fromMaybe(false)) - scope.ignoreExceptionsAndMuteConsole(); - - std::unique_ptr> scriptWrapper = std::move(it->second); - m_compiledScripts.erase(it); - v8::Local script = scriptWrapper->Get(m_inspector->isolate()); - if (script.IsEmpty()) { - callback->sendFailure("Script execution failed"); - return; - } - - if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI()) - return; - - v8::MaybeLocal maybeResultValue = m_inspector->runCompiledScript(scope.context(), script); - - // Re-initialize after running client's code, as it could have destroyed context or session. - if (!scope.initialize()) - return; - - if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) { - wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), callback.get()); - return; - } - ProtocolPromiseHandler::add( - m_inspector, - scope.context(), - maybeResultValue.ToLocalChecked(), - "Result of the script execution is not a promise", - m_session->contextGroupId(), - scope.injectedScript()->context()->contextId(), - objectGroup.fromMaybe(""), - returnByValue.fromMaybe(false), - generatePreview.fromMaybe(false), - std::move(callback)); -} - -void V8RuntimeAgentImpl::restore() -{ - if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false)) - return; - m_frontend.executionContextsCleared(); - ErrorString error; - enable(&error); - if (m_state->booleanProperty(V8RuntimeAgentImplState::customObjectFormatterEnabled, false)) - m_session->setCustomObjectFormatterEnabled(true); -} - -void V8RuntimeAgentImpl::enable(ErrorString* errorString) -{ - if (m_enabled) - return; - m_inspector->client()->beginEnsureAllContextsInGroup(m_session->contextGroupId()); - m_enabled = true; - m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, true); - m_inspector->enableStackCapturingIfNeeded(); - m_session->reportAllContexts(this); - V8ConsoleMessageStorage* storage = m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId()); - for (const auto& message : storage->messages()) - reportMessage(message.get(), false); -} - -void V8RuntimeAgentImpl::disable(ErrorString* errorString) -{ - if (!m_enabled) - return; - m_enabled = false; - m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, false); - m_inspector->disableStackCapturingIfNeeded(); - m_session->discardInjectedScripts(); - reset(); - m_inspector->client()->endEnsureAllContextsInGroup(m_session->contextGroupId()); -} - -void V8RuntimeAgentImpl::reset() -{ - m_compiledScripts.clear(); - if (m_enabled) { - if (const V8InspectorImpl::ContextByIdMap* contexts = m_inspector->contextGroup(m_session->contextGroupId())) { - for (auto& idContext : *contexts) - idContext.second->setReported(false); - } - m_frontend.executionContextsCleared(); - } -} - -void V8RuntimeAgentImpl::reportExecutionContextCreated(InspectedContext* context) -{ - if (!m_enabled) - return; - context->setReported(true); - std::unique_ptr description = protocol::Runtime::ExecutionContextDescription::create() - .setId(context->contextId()) - .setName(context->humanReadableName()) - .setOrigin(context->origin()).build(); - if (!context->auxData().isEmpty()) - description->setAuxData(protocol::DictionaryValue::cast(parseJSON(context->auxData()))); - m_frontend.executionContextCreated(std::move(description)); -} - -void V8RuntimeAgentImpl::reportExecutionContextDestroyed(InspectedContext* context) -{ - if (m_enabled && context->isReported()) { - context->setReported(false); - m_frontend.executionContextDestroyed(context->contextId()); - } -} - -void V8RuntimeAgentImpl::inspect(std::unique_ptr objectToInspect, std::unique_ptr hints) -{ - if (m_enabled) - m_frontend.inspectRequested(std::move(objectToInspect), std::move(hints)); -} - -void V8RuntimeAgentImpl::messageAdded(V8ConsoleMessage* message) -{ - if (m_enabled) - reportMessage(message, true); -} - -void V8RuntimeAgentImpl::reportMessage(V8ConsoleMessage* message, bool generatePreview) -{ - message->reportToFrontend(&m_frontend, m_session, generatePreview); - m_frontend.flush(); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.h deleted file mode 100644 index d08a0b63311a83..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8RuntimeAgentImpl.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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. - */ - -#ifndef V8RuntimeAgentImpl_h -#define V8RuntimeAgentImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/Runtime.h" - -#include - -namespace v8_inspector { - -class InjectedScript; -class InspectedContext; -class RemoteObjectIdBase; -class V8ConsoleMessage; -class V8InspectorImpl; -class V8InspectorSessionImpl; - -namespace protocol = blink::protocol; -using blink::protocol::Maybe; - -class V8RuntimeAgentImpl : public protocol::Runtime::Backend { - PROTOCOL_DISALLOW_COPY(V8RuntimeAgentImpl); -public: - V8RuntimeAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, protocol::DictionaryValue* state); - ~V8RuntimeAgentImpl() override; - void restore(); - - // Part of the protocol. - void enable(ErrorString*) override; - void disable(ErrorString*) override; - void evaluate( - const String16& expression, - const Maybe& objectGroup, - const Maybe& includeCommandLineAPI, - const Maybe& silent, - const Maybe& executionContextId, - const Maybe& returnByValue, - const Maybe& generatePreview, - const Maybe& userGesture, - const Maybe& awaitPromise, - std::unique_ptr) override; - void awaitPromise( - const String16& promiseObjectId, - const Maybe& returnByValue, - const Maybe& generatePreview, - std::unique_ptr) override; - void callFunctionOn( - const String16& objectId, - const String16& expression, - const Maybe>& optionalArguments, - const Maybe& silent, - const Maybe& returnByValue, - const Maybe& generatePreview, - const Maybe& userGesture, - const Maybe& awaitPromise, - std::unique_ptr) override; - void releaseObject(ErrorString*, const String16& objectId) override; - void getProperties(ErrorString*, - const String16& objectId, - const Maybe& ownProperties, - const Maybe& accessorPropertiesOnly, - const Maybe& generatePreview, - std::unique_ptr>* result, - Maybe>* internalProperties, - Maybe*) override; - void releaseObjectGroup(ErrorString*, const String16& objectGroup) override; - void runIfWaitingForDebugger(ErrorString*) override; - void setCustomObjectFormatterEnabled(ErrorString*, bool) override; - void discardConsoleEntries(ErrorString*) override; - void compileScript(ErrorString*, - const String16& expression, - const String16& sourceURL, - bool persistScript, - const Maybe& executionContextId, - Maybe*, - Maybe*) override; - void runScript( - const String16&, - const Maybe& executionContextId, - const Maybe& objectGroup, - const Maybe& silent, - const Maybe& includeCommandLineAPI, - const Maybe& returnByValue, - const Maybe& generatePreview, - const Maybe& awaitPromise, - std::unique_ptr) override; - - void reset(); - void reportExecutionContextCreated(InspectedContext*); - void reportExecutionContextDestroyed(InspectedContext*); - void inspect(std::unique_ptr objectToInspect, std::unique_ptr hints); - void messageAdded(V8ConsoleMessage*); - bool enabled() const { return m_enabled; } - -private: - void reportMessage(V8ConsoleMessage*, bool generatePreview); - - V8InspectorSessionImpl* m_session; - protocol::DictionaryValue* m_state; - protocol::Runtime::Frontend m_frontend; - V8InspectorImpl* m_inspector; - bool m_enabled; - protocol::HashMap>> m_compiledScripts; -}; - -} // namespace v8_inspector - -#endif // V8RuntimeAgentImpl_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8SchemaAgentImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8SchemaAgentImpl.cpp deleted file mode 100644 index c43120f66c1f34..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8SchemaAgentImpl.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// 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 "platform/v8_inspector/V8SchemaAgentImpl.h" - -#include "platform/v8_inspector/V8InspectorSessionImpl.h" - -namespace v8_inspector { - -V8SchemaAgentImpl::V8SchemaAgentImpl(V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, protocol::DictionaryValue* state) - : m_session(session) - , m_frontend(frontendChannel) -{ -} - -V8SchemaAgentImpl::~V8SchemaAgentImpl() -{ -} - -void V8SchemaAgentImpl::getDomains(ErrorString*, std::unique_ptr>* result) -{ - std::vector> domains = m_session->supportedDomainsImpl(); - *result = protocol::Array::create(); - for (size_t i = 0; i < domains.size(); ++i) - (*result)->addItem(std::move(domains[i])); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8SchemaAgentImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8SchemaAgentImpl.h deleted file mode 100644 index 9838af6ce910fa..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8SchemaAgentImpl.h +++ /dev/null @@ -1,33 +0,0 @@ -// 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 V8SchemaAgentImpl_h -#define V8SchemaAgentImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/Schema.h" - -namespace v8_inspector { - -class V8InspectorSessionImpl; - -namespace protocol = blink::protocol; - -class V8SchemaAgentImpl : public protocol::Schema::Backend { - PROTOCOL_DISALLOW_COPY(V8SchemaAgentImpl); -public: - V8SchemaAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, protocol::DictionaryValue* state); - ~V8SchemaAgentImpl() override; - - void getDomains(ErrorString*, std::unique_ptr>*) override; - -private: - V8InspectorSessionImpl* m_session; - protocol::Schema::Frontend m_frontend; -}; - -} // namespace v8_inspector - - -#endif // !defined(V8SchemaAgentImpl_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StackTraceImpl.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StackTraceImpl.cpp deleted file mode 100644 index e0bab17d89084f..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StackTraceImpl.cpp +++ /dev/null @@ -1,265 +0,0 @@ -// 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 "platform/v8_inspector/V8StackTraceImpl.h" - -#include "platform/v8_inspector/V8Debugger.h" -#include "platform/v8_inspector/V8StringUtil.h" - -#include -#include -#include - -namespace v8_inspector { - -namespace { - -static const v8::StackTrace::StackTraceOptions stackTraceOptions = static_cast( - v8::StackTrace::kLineNumber | - v8::StackTrace::kColumnOffset | - v8::StackTrace::kScriptId | - v8::StackTrace::kScriptNameOrSourceURL | - v8::StackTrace::kFunctionName); - -V8StackTraceImpl::Frame toFrame(v8::Local frame) -{ - String16 scriptId = String16::fromInteger(frame->GetScriptId()); - String16 sourceName; - v8::Local sourceNameValue(frame->GetScriptNameOrSourceURL()); - if (!sourceNameValue.IsEmpty()) - sourceName = toProtocolString(sourceNameValue); - - String16 functionName; - v8::Local functionNameValue(frame->GetFunctionName()); - if (!functionNameValue.IsEmpty()) - functionName = toProtocolString(functionNameValue); - - int sourceLineNumber = frame->GetLineNumber(); - int sourceColumn = frame->GetColumn(); - return V8StackTraceImpl::Frame(functionName, scriptId, sourceName, sourceLineNumber, sourceColumn); -} - -void toFramesVector(v8::Local stackTrace, std::vector& frames, size_t maxStackSize, v8::Isolate* isolate) -{ - DCHECK(isolate->InContext()); - int frameCount = stackTrace->GetFrameCount(); - if (frameCount > static_cast(maxStackSize)) - frameCount = maxStackSize; - for (int i = 0; i < frameCount; i++) { - v8::Local stackFrame = stackTrace->GetFrame(i); - frames.push_back(toFrame(stackFrame)); - } -} - -} // namespace - -V8StackTraceImpl::Frame::Frame() - : m_functionName("undefined") - , m_scriptId("") - , m_scriptName("undefined") - , m_lineNumber(0) - , m_columnNumber(0) -{ -} - -V8StackTraceImpl::Frame::Frame(const String16& functionName, const String16& scriptId, const String16& scriptName, int lineNumber, int column) - : m_functionName(functionName) - , m_scriptId(scriptId) - , m_scriptName(scriptName) - , m_lineNumber(lineNumber) - , m_columnNumber(column) -{ - DCHECK(m_lineNumber != v8::Message::kNoLineNumberInfo); - DCHECK(m_columnNumber != v8::Message::kNoColumnInfo); -} - -V8StackTraceImpl::Frame::~Frame() -{ -} - -// buildInspectorObject() and SourceLocation's toTracedValue() should set the same fields. -// If either of them is modified, the other should be also modified. -std::unique_ptr V8StackTraceImpl::Frame::buildInspectorObject() const -{ - return protocol::Runtime::CallFrame::create() - .setFunctionName(m_functionName) - .setScriptId(m_scriptId) - .setUrl(m_scriptName) - .setLineNumber(m_lineNumber - 1) - .setColumnNumber(m_columnNumber - 1) - .build(); -} - -V8StackTraceImpl::Frame V8StackTraceImpl::Frame::clone() const -{ - return Frame(m_functionName.isolatedCopy(), m_scriptId.isolatedCopy(), m_scriptName.isolatedCopy(), m_lineNumber, m_columnNumber); -} - -// static -void V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(v8::Isolate* isolate, bool capture) -{ - isolate->SetCaptureStackTraceForUncaughtExceptions(capture, V8StackTraceImpl::maxCallStackSizeToCapture, stackTraceOptions); -} - -// static -std::unique_ptr V8StackTraceImpl::create(V8Debugger* debugger, int contextGroupId, v8::Local stackTrace, size_t maxStackSize, const String16& description) -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - std::vector frames; - if (!stackTrace.IsEmpty()) - toFramesVector(stackTrace, frames, maxStackSize, isolate); - - int maxAsyncCallChainDepth = 1; - V8StackTraceImpl* asyncCallChain = nullptr; - if (debugger && maxStackSize > 1) { - asyncCallChain = debugger->currentAsyncCallChain(); - maxAsyncCallChainDepth = debugger->maxAsyncCallChainDepth(); - } - // Do not accidentally append async call chain from another group. This should not - // happen if we have proper instrumentation, but let's double-check to be safe. - if (contextGroupId && asyncCallChain && asyncCallChain->m_contextGroupId && asyncCallChain->m_contextGroupId != contextGroupId) { - asyncCallChain = nullptr; - maxAsyncCallChainDepth = 1; - } - - // Only the top stack in the chain may be empty, so ensure that second stack is non-empty (it's the top of appended chain). - if (asyncCallChain && asyncCallChain->isEmpty()) - asyncCallChain = asyncCallChain->m_parent.get(); - - if (stackTrace.IsEmpty() && !asyncCallChain) - return nullptr; - - std::unique_ptr result(new V8StackTraceImpl(contextGroupId, description, frames, asyncCallChain ? asyncCallChain->cloneImpl() : nullptr)); - - // Crop to not exceed maxAsyncCallChainDepth. - V8StackTraceImpl* deepest = result.get(); - while (deepest && maxAsyncCallChainDepth) { - deepest = deepest->m_parent.get(); - maxAsyncCallChainDepth--; - } - if (deepest) - deepest->m_parent.reset(); - - return result; -} - -std::unique_ptr V8StackTraceImpl::capture(V8Debugger* debugger, int contextGroupId, size_t maxStackSize, const String16& description) -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Local stackTrace; - if (isolate->InContext()) { -#if V8_MAJOR_VERSION >= 5 - isolate->GetCpuProfiler()->CollectSample(); -#endif - stackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, stackTraceOptions); - } - return V8StackTraceImpl::create(debugger, contextGroupId, stackTrace, maxStackSize, description); -} - -std::unique_ptr V8StackTraceImpl::cloneImpl() -{ - std::vector framesCopy(m_frames); - return wrapUnique(new V8StackTraceImpl(m_contextGroupId, m_description, framesCopy, m_parent ? m_parent->cloneImpl() : nullptr)); -} - -std::unique_ptr V8StackTraceImpl::clone() -{ - std::vector frames; - for (size_t i = 0; i < m_frames.size(); i++) - frames.push_back(m_frames.at(i).clone()); - return wrapUnique(new V8StackTraceImpl(m_contextGroupId, m_description.isolatedCopy(), frames, nullptr)); -} - -V8StackTraceImpl::V8StackTraceImpl(int contextGroupId, const String16& description, std::vector& frames, std::unique_ptr parent) - : m_contextGroupId(contextGroupId) - , m_description(description) - , m_parent(std::move(parent)) -{ - m_frames.swap(frames); -} - -V8StackTraceImpl::~V8StackTraceImpl() -{ -} - -String16 V8StackTraceImpl::topSourceURL() const -{ - DCHECK(m_frames.size()); - return m_frames[0].m_scriptName; -} - -int V8StackTraceImpl::topLineNumber() const -{ - DCHECK(m_frames.size()); - return m_frames[0].m_lineNumber; -} - -int V8StackTraceImpl::topColumnNumber() const -{ - DCHECK(m_frames.size()); - return m_frames[0].m_columnNumber; -} - -String16 V8StackTraceImpl::topFunctionName() const -{ - DCHECK(m_frames.size()); - return m_frames[0].m_functionName; -} - -String16 V8StackTraceImpl::topScriptId() const -{ - DCHECK(m_frames.size()); - return m_frames[0].m_scriptId; -} - -std::unique_ptr V8StackTraceImpl::buildInspectorObjectImpl() const -{ - std::unique_ptr> frames = protocol::Array::create(); - for (size_t i = 0; i < m_frames.size(); i++) - frames->addItem(m_frames.at(i).buildInspectorObject()); - - std::unique_ptr stackTrace = protocol::Runtime::StackTrace::create() - .setCallFrames(std::move(frames)).build(); - if (!m_description.isEmpty()) - stackTrace->setDescription(m_description); - if (m_parent) - stackTrace->setParent(m_parent->buildInspectorObjectImpl()); - return stackTrace; -} - -std::unique_ptr V8StackTraceImpl::buildInspectorObjectForTail(V8Debugger* debugger) const -{ - v8::HandleScope handleScope(v8::Isolate::GetCurrent()); - // Next call collapses possible empty stack and ensures maxAsyncCallChainDepth. - std::unique_ptr fullChain = V8StackTraceImpl::create(debugger, m_contextGroupId, v8::Local(), V8StackTraceImpl::maxCallStackSizeToCapture); - if (!fullChain || !fullChain->m_parent) - return nullptr; - return fullChain->m_parent->buildInspectorObjectImpl(); -} - -std::unique_ptr V8StackTraceImpl::buildInspectorObject() const -{ - return buildInspectorObjectImpl(); -} - -String16 V8StackTraceImpl::toString() const -{ - String16Builder stackTrace; - for (size_t i = 0; i < m_frames.size(); ++i) { - const Frame& frame = m_frames[i]; - stackTrace.append("\n at " + (frame.functionName().length() ? frame.functionName() : "(anonymous function)")); - stackTrace.append(" ("); - stackTrace.append(frame.sourceURL()); - stackTrace.append(':'); - stackTrace.append(String16::fromInteger(frame.lineNumber())); - stackTrace.append(':'); - stackTrace.append(String16::fromInteger(frame.columnNumber())); - stackTrace.append(')'); - } - return stackTrace.toString(); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StackTraceImpl.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StackTraceImpl.h deleted file mode 100644 index 25ad3ab09d6120..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StackTraceImpl.h +++ /dev/null @@ -1,86 +0,0 @@ -// 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 V8StackTraceImpl_h -#define V8StackTraceImpl_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/Runtime.h" -#include "platform/v8_inspector/public/V8StackTrace.h" - -#include - -namespace v8_inspector { - -class TracedValue; -class V8Debugger; - -namespace protocol = blink::protocol; - -// Note: async stack trace may have empty top stack with non-empty tail to indicate -// that current native-only state had some async story. -// On the other hand, any non-top async stack is guaranteed to be non-empty. -class V8StackTraceImpl final : public V8StackTrace { - PROTOCOL_DISALLOW_COPY(V8StackTraceImpl); -public: - static const size_t maxCallStackSizeToCapture = 200; - - class Frame { - public: - Frame(); - Frame(const String16& functionName, const String16& scriptId, const String16& scriptName, int lineNumber, int column = 0); - ~Frame(); - - const String16& functionName() const { return m_functionName; } - const String16& scriptId() const { return m_scriptId; } - const String16& sourceURL() const { return m_scriptName; } - int lineNumber() const { return m_lineNumber; } - int columnNumber() const { return m_columnNumber; } - Frame clone() const; - - private: - friend class V8StackTraceImpl; - std::unique_ptr buildInspectorObject() const; - void toTracedValue(TracedValue*) const; - - String16 m_functionName; - String16 m_scriptId; - String16 m_scriptName; - int m_lineNumber; - int m_columnNumber; - }; - - static void setCaptureStackTraceForUncaughtExceptions(v8::Isolate*, bool capture); - static std::unique_ptr create(V8Debugger*, int contextGroupId, v8::Local, size_t maxStackSize, const String16& description = String16()); - static std::unique_ptr capture(V8Debugger*, int contextGroupId, size_t maxStackSize, const String16& description = String16()); - - // This method drops the async chain. Use cloneImpl() instead. - std::unique_ptr clone() override; - std::unique_ptr cloneImpl(); - std::unique_ptr buildInspectorObjectForTail(V8Debugger*) const; - std::unique_ptr buildInspectorObjectImpl() const; - ~V8StackTraceImpl() override; - - // V8StackTrace implementation. - bool isEmpty() const override { return !m_frames.size(); }; - String16 topSourceURL() const override; - int topLineNumber() const override; - int topColumnNumber() const override; - String16 topScriptId() const override; - String16 topFunctionName() const override; - std::unique_ptr buildInspectorObject() const override; - String16 toString() const override; - -private: - V8StackTraceImpl(int contextGroupId, const String16& description, std::vector& frames, std::unique_ptr parent); - - int m_contextGroupId; - String16 m_description; - std::vector m_frames; - std::unique_ptr m_parent; -}; - -} // namespace v8_inspector - -#endif // V8StackTraceImpl_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StringUtil.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StringUtil.cpp deleted file mode 100644 index d078da6a0e3b75..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StringUtil.cpp +++ /dev/null @@ -1,280 +0,0 @@ -// 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 "platform/v8_inspector/V8StringUtil.h" - -#include "platform/v8_inspector/V8InspectorImpl.h" -#include "platform/v8_inspector/V8InspectorSessionImpl.h" -#include "platform/v8_inspector/V8Regex.h" - -namespace v8_inspector { - -namespace { - -String16 findMagicComment(const String16& content, const String16& name, bool multiline) -{ - DCHECK(name.find("=") == String16::kNotFound); - unsigned length = content.length(); - unsigned nameLength = name.length(); - - size_t pos = length; - size_t equalSignPos = 0; - size_t closingCommentPos = 0; - while (true) { - pos = content.reverseFind(name, pos); - if (pos == String16::kNotFound) - return String16(); - - // Check for a /\/[\/*][@#][ \t]/ regexp (length of 4) before found name. - if (pos < 4) - return String16(); - pos -= 4; - if (content[pos] != '/') - continue; - if ((content[pos + 1] != '/' || multiline) - && (content[pos + 1] != '*' || !multiline)) - continue; - if (content[pos + 2] != '#' && content[pos + 2] != '@') - continue; - if (content[pos + 3] != ' ' && content[pos + 3] != '\t') - continue; - equalSignPos = pos + 4 + nameLength; - if (equalSignPos < length && content[equalSignPos] != '=') - continue; - if (multiline) { - closingCommentPos = content.find("*/", equalSignPos + 1); - if (closingCommentPos == String16::kNotFound) - return String16(); - } - - break; - } - - DCHECK(equalSignPos); - DCHECK(!multiline || closingCommentPos); - size_t urlPos = equalSignPos + 1; - String16 match = multiline - ? content.substring(urlPos, closingCommentPos - urlPos) - : content.substring(urlPos); - - size_t newLine = match.find("\n"); - if (newLine != String16::kNotFound) - match = match.substring(0, newLine); - match = match.stripWhiteSpace(); - - for (unsigned i = 0; i < match.length(); ++i) { - UChar c = match[i]; - if (c == '"' || c == '\'' || c == ' ' || c == '\t') - return ""; - } - - return match; -} - -String16 createSearchRegexSource(const String16& text) -{ - String16Builder result; - - for (unsigned i = 0; i < text.length(); i++) { - UChar c = text[i]; - if (c == '[' || c == ']' || c == '(' || c == ')' || c == '{' || c == '}' - || c == '+' || c == '-' || c == '*' || c == '.' || c == ',' || c == '?' - || c == '\\' || c == '^' || c == '$' || c == '|') { - result.append('\\'); - } - result.append(text[i]); - } - - return result.toString(); -} - -std::unique_ptr> lineEndings(const String16& text) -{ - std::unique_ptr> result(new std::vector()); - - const String16 lineEndString = "\n"; - unsigned start = 0; - while (start < text.length()) { - size_t lineEnd = text.find(lineEndString, start); - if (lineEnd == String16::kNotFound) - break; - - result->push_back(static_cast(lineEnd)); - start = lineEnd + 1; - } - result->push_back(text.length()); - - return result; -} - -std::vector> scriptRegexpMatchesByLines(const V8Regex& regex, const String16& text) -{ - std::vector> result; - if (text.isEmpty()) - return result; - - std::unique_ptr> endings(lineEndings(text)); - unsigned size = endings->size(); - unsigned start = 0; - for (unsigned lineNumber = 0; lineNumber < size; ++lineNumber) { - unsigned lineEnd = endings->at(lineNumber); - String16 line = text.substring(start, lineEnd - start); - if (line.length() && line[line.length() - 1] == '\r') - line = line.substring(0, line.length() - 1); - - int matchLength; - if (regex.match(line, 0, &matchLength) != -1) - result.push_back(std::pair(lineNumber, line)); - - start = lineEnd + 1; - } - return result; -} - -std::unique_ptr buildObjectForSearchMatch(int lineNumber, const String16& lineContent) -{ - return protocol::Debugger::SearchMatch::create() - .setLineNumber(lineNumber) - .setLineContent(lineContent) - .build(); -} - -std::unique_ptr createSearchRegex(V8InspectorImpl* inspector, const String16& query, bool caseSensitive, bool isRegex) -{ - String16 regexSource = isRegex ? query : createSearchRegexSource(query); - return wrapUnique(new V8Regex(inspector, regexSource, caseSensitive)); -} - -} // namespace - -v8::Local toV8String(v8::Isolate* isolate, const String16& string) -{ - if (string.isEmpty()) - return v8::String::Empty(isolate); - return v8::String::NewFromTwoByte(isolate, reinterpret_cast(string.characters16()), v8::NewStringType::kNormal, string.length()).ToLocalChecked(); -} - -v8::Local toV8StringInternalized(v8::Isolate* isolate, const String16& string) -{ - if (string.isEmpty()) - return v8::String::Empty(isolate); - return v8::String::NewFromTwoByte(isolate, reinterpret_cast(string.characters16()), v8::NewStringType::kInternalized, string.length()).ToLocalChecked(); -} - -v8::Local toV8StringInternalized(v8::Isolate* isolate, const char* str) -{ - return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kInternalized).ToLocalChecked(); -} - -String16 toProtocolString(v8::Local value) -{ - if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) - return String16(); - std::unique_ptr buffer(new UChar[value->Length()]); - value->Write(reinterpret_cast(buffer.get()), 0, value->Length()); - return String16(buffer.get(), value->Length()); -} - -String16 toProtocolStringWithTypeCheck(v8::Local value) -{ - if (value.IsEmpty() || !value->IsString()) - return String16(); - return toProtocolString(value.As()); -} - -std::vector> searchInTextByLinesImpl(V8InspectorSession* session, const String16& text, const String16& query, const bool caseSensitive, const bool isRegex) -{ - std::unique_ptr regex = createSearchRegex(static_cast(session)->inspector(), query, caseSensitive, isRegex); - std::vector> matches = scriptRegexpMatchesByLines(*regex.get(), text); - - std::vector> result; - for (const auto& match : matches) - result.push_back(buildObjectForSearchMatch(match.first, match.second)); - return result; -} - -String16 findSourceURL(const String16& content, bool multiline) -{ - return findMagicComment(content, "sourceURL", multiline); -} - -String16 findSourceMapURL(const String16& content, bool multiline) -{ - return findMagicComment(content, "sourceMappingURL", multiline); -} - -std::unique_ptr toProtocolValue(v8::Local context, v8::Local value, int maxDepth) -{ - if (value.IsEmpty()) { - NOTREACHED(); - return nullptr; - } - - if (!maxDepth) - return nullptr; - maxDepth--; - - if (value->IsNull() || value->IsUndefined()) - return protocol::Value::null(); - if (value->IsBoolean()) - return protocol::FundamentalValue::create(value.As()->Value()); - if (value->IsNumber()) { - double doubleValue = value.As()->Value(); - int intValue = static_cast(doubleValue); - if (intValue == doubleValue) - return protocol::FundamentalValue::create(intValue); - return protocol::FundamentalValue::create(doubleValue); - } - if (value->IsString()) - return protocol::StringValue::create(toProtocolString(value.As())); - if (value->IsArray()) { - v8::Local array = value.As(); - std::unique_ptr inspectorArray = protocol::ListValue::create(); - uint32_t length = array->Length(); - for (uint32_t i = 0; i < length; i++) { - v8::Local value; - if (!array->Get(context, i).ToLocal(&value)) - return nullptr; - std::unique_ptr element = toProtocolValue(context, value, maxDepth); - if (!element) - return nullptr; - inspectorArray->pushValue(std::move(element)); - } - return std::move(inspectorArray); - } - if (value->IsObject()) { - std::unique_ptr jsonObject = protocol::DictionaryValue::create(); - v8::Local object = v8::Local::Cast(value); - v8::Local propertyNames; - if (!object->GetPropertyNames(context).ToLocal(&propertyNames)) - return nullptr; - uint32_t length = propertyNames->Length(); - for (uint32_t i = 0; i < length; i++) { - v8::Local name; - if (!propertyNames->Get(context, i).ToLocal(&name)) - return nullptr; - // FIXME(yurys): v8::Object should support GetOwnPropertyNames - if (name->IsString()) { - v8::Maybe hasRealNamedProperty = object->HasRealNamedProperty(context, v8::Local::Cast(name)); - if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust()) - continue; - } - v8::Local propertyName; - if (!name->ToString(context).ToLocal(&propertyName)) - continue; - v8::Local property; - if (!object->Get(context, name).ToLocal(&property)) - return nullptr; - std::unique_ptr propertyValue = toProtocolValue(context, property, maxDepth); - if (!propertyValue) - return nullptr; - jsonObject->setValue(toProtocolString(propertyName), std::move(propertyValue)); - } - return std::move(jsonObject); - } - NOTREACHED(); - return nullptr; -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StringUtil.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StringUtil.h deleted file mode 100644 index 2245c8fed6a941..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8StringUtil.h +++ /dev/null @@ -1,34 +0,0 @@ -// 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 V8StringUtil_h -#define V8StringUtil_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/protocol/Debugger.h" -#include - -namespace v8_inspector { - -class V8InspectorSession; - -namespace protocol = blink::protocol; - -std::unique_ptr toProtocolValue(v8::Local, v8::Local, int maxDepth = protocol::Value::maxDepth); - -v8::Local toV8String(v8::Isolate*, const String16&); -v8::Local toV8StringInternalized(v8::Isolate*, const String16&); -v8::Local toV8StringInternalized(v8::Isolate*, const char*); - -String16 toProtocolString(v8::Local); -String16 toProtocolStringWithTypeCheck(v8::Local); - -String16 findSourceURL(const String16& content, bool multiline); -String16 findSourceMapURL(const String16& content, bool multiline); -std::vector> searchInTextByLinesImpl(V8InspectorSession*, const String16& text, const String16& query, bool caseSensitive, bool isRegex); - -} // namespace v8_inspector - - -#endif // !defined(V8StringUtil_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ValueCopier.cpp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ValueCopier.cpp deleted file mode 100644 index 3347abeba5929a..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ValueCopier.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// 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 "platform/v8_inspector/V8ValueCopier.h" - -namespace v8_inspector { - -namespace { - -static int kMaxDepth = 20; -static int kMaxCalls = 1000; - -class V8ValueCopier { -public: - v8::MaybeLocal copy(v8::Local value, int depth) - { - if (++m_calls > kMaxCalls || depth > kMaxDepth) - return v8::MaybeLocal(); - - if (value.IsEmpty()) - return v8::MaybeLocal(); - if (value->IsNull() || value->IsUndefined() || value->IsBoolean() || value->IsString() || value->IsNumber()) - return value; - if (!value->IsObject()) - return v8::MaybeLocal(); - v8::Local object = value.As(); - if (object->CreationContext() != m_from) - return value; - - if (object->IsArray()) { - v8::Local array = object.As(); - v8::Local result = v8::Array::New(m_isolate, array->Length()); - if (!result->SetPrototype(m_to, v8::Null(m_isolate)).FromMaybe(false)) - return v8::MaybeLocal(); - for (size_t i = 0; i < array->Length(); ++i) { - v8::Local item; - if (!array->Get(m_from, i).ToLocal(&item)) - return v8::MaybeLocal(); - v8::Local copied; - if (!copy(item, depth + 1).ToLocal(&copied)) - return v8::MaybeLocal(); - if (!result->Set(m_to, i, copied).FromMaybe(false)) - return v8::MaybeLocal(); - } - return result; - } - - - v8::Local result = v8::Object::New(m_isolate); - if (!result->SetPrototype(m_to, v8::Null(m_isolate)).FromMaybe(false)) - return v8::MaybeLocal(); - v8::Local properties; - if (!object->GetOwnPropertyNames(m_from).ToLocal(&properties)) - return v8::MaybeLocal(); - for (size_t i = 0; i < properties->Length(); ++i) { - v8::Local name; - if (!properties->Get(m_from, i).ToLocal(&name) || !name->IsString()) - return v8::MaybeLocal(); - v8::Local property; - if (!object->Get(m_from, name).ToLocal(&property)) - return v8::MaybeLocal(); - v8::Local copied; - if (!copy(property, depth + 1).ToLocal(&copied)) - return v8::MaybeLocal(); - if (!result->Set(m_to, name, copied).FromMaybe(false)) - return v8::MaybeLocal(); - } - return result; - } - - v8::Isolate* m_isolate; - v8::Local m_from; - v8::Local m_to; - int m_calls; -}; - -} // namespace - -v8::MaybeLocal copyValueFromDebuggerContext(v8::Isolate* isolate, v8::Local debuggerContext, v8::Local toContext, v8::Local value) -{ - V8ValueCopier copier; - copier.m_isolate = isolate; - copier.m_from = debuggerContext; - copier.m_to = toContext; - copier.m_calls = 0; - return copier.copy(value, 0); -} - -} // namespace v8_inspector diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ValueCopier.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ValueCopier.h deleted file mode 100644 index 9cd650cc80168b..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/V8ValueCopier.h +++ /dev/null @@ -1,16 +0,0 @@ -// 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 V8ValueCopier_h -#define V8ValueCopier_h - -#include - -namespace v8_inspector { - -v8::MaybeLocal copyValueFromDebuggerContext(v8::Isolate*, v8::Local debuggerContext, v8::Local toContext, v8::Local); - -} // namespace v8_inspector - -#endif // !defined(V8ValueCopier_h) diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/inspector_protocol_config.json b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/inspector_protocol_config.json deleted file mode 100644 index 512a1db7ef8d2c..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/inspector_protocol_config.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "protocol": { - "path": "js_protocol.json", - "package": "platform/v8_inspector/protocol", - "output": "v8_inspector/protocol" - }, - - "exported": { - "package": "platform/v8_inspector/public/protocol", - "output": "v8_inspector/public/protocol" - }, - - "string": { - "class_name": "String16" - }, - - "lib": { - "output": "inspector_protocol", - "string16_header": "platform/v8_inspector/String16WTF.h", - "platform_header": "platform/v8_inspector/PlatformWTF.h" - }, - - "lib_package": "platform/inspector_protocol", - - "class_export": { - "macro": "PLATFORM_EXPORT", - "header": "platform/PlatformExport.h" - } -} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/inspector_protocol_config_stl.json b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/inspector_protocol_config_stl.json deleted file mode 100644 index 1c5ee878cc2bdf..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/inspector_protocol_config_stl.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "protocol": { - "path": "js_protocol.json", - "package": "platform/v8_inspector/protocol", - "output": "v8_inspector/protocol" - }, - - "exported": { - "package": "platform/v8_inspector/public/protocol", - "output": "v8_inspector/public/protocol" - }, - - "string": { - "class_name": "String16" - }, - - "lib": { - "output": "inspector_protocol", - "string16_header": "platform/v8_inspector/String16STL.h", - "platform_header": "platform/v8_inspector/PlatformSTL.h" - }, - - "lib_package": "platform/inspector_protocol", - - "class_export": { - "macro": "PLATFORM_EXPORT", - "header": "platform/PlatformExport.h" - } -} diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/js_protocol-1.1.json b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/js_protocol-1.1.json deleted file mode 100644 index 8961f3bbd2321e..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/js_protocol-1.1.json +++ /dev/null @@ -1,1866 +0,0 @@ -{ - "domains": [ - { - "domain": "Runtime", - "description": "Runtime domain exposes JavaScript runtime by means of remote evaluation and mirror objects. Evaluation results are returned as mirror object that expose object type, string representation and unique identifier that can be used for further object reference. Original objects are maintained in memory unless they are either explicitly released or are released along with the other objects in their object group.", - "types": [ - { - "id": "RemoteObjectId", - "type": "string", - "description": "Unique object identifier." - }, - { - "id": "RemoteObject", - "type": "object", - "description": "Mirror object referencing original JavaScript object.", - "properties": [ - { - "name": "type", - "type": "string", - "enum": [ - "object", - "function", - "undefined", - "string", - "number", - "boolean" - ], - "description": "Object type." - }, - { - "name": "subtype", - "type": "string", - "optional": true, - "enum": [ - "array", - "null", - "node", - "regexp", - "date" - ], - "description": "Object subtype hint. Specified for object type values only." - }, - { - "name": "className", - "type": "string", - "optional": true, - "description": "Object class (constructor) name. Specified for object type values only." - }, - { - "name": "value", - "type": "any", - "optional": true, - "description": "Remote object value (in case of primitive values or JSON values if it was requested)." - }, - { - "name": "description", - "type": "string", - "optional": true, - "description": "String representation of the object." - }, - { - "name": "objectId", - "$ref": "RemoteObjectId", - "optional": true, - "description": "Unique object identifier (for non-primitive values)." - }, - { - "name": "preview", - "$ref": "ObjectPreview", - "optional": true, - "description": "Preview containing abbreviated property values.", - "hidden": true - } - ] - }, - { - "id": "ObjectPreview", - "type": "object", - "hidden": true, - "description": "Object containing abbreviated remote object value.", - "properties": [ - { - "name": "lossless", - "type": "boolean", - "description": "Determines whether preview is lossless (contains all information of the original object)." - }, - { - "name": "overflow", - "type": "boolean", - "description": "True iff some of the properties of the original did not fit." - }, - { - "name": "properties", - "type": "array", - "items": { - "$ref": "PropertyPreview" - }, - "description": "List of the properties." - } - ] - }, - { - "id": "PropertyPreview", - "type": "object", - "hidden": true, - "properties": [ - { - "name": "name", - "type": "string", - "description": "Property name." - }, - { - "name": "type", - "type": "string", - "enum": [ - "object", - "function", - "undefined", - "string", - "number", - "boolean" - ], - "description": "Object type." - }, - { - "name": "value", - "type": "string", - "optional": true, - "description": "User-friendly property value string." - }, - { - "name": "valuePreview", - "$ref": "ObjectPreview", - "optional": true, - "description": "Nested value preview." - }, - { - "name": "subtype", - "type": "string", - "optional": true, - "enum": [ - "array", - "null", - "node", - "regexp", - "date" - ], - "description": "Object subtype hint. Specified for object type values only." - } - ] - }, - { - "id": "PropertyDescriptor", - "type": "object", - "description": "Object property descriptor.", - "properties": [ - { - "name": "name", - "type": "string", - "description": "Property name." - }, - { - "name": "value", - "$ref": "RemoteObject", - "optional": true, - "description": "The value associated with the property." - }, - { - "name": "writable", - "type": "boolean", - "optional": true, - "description": "True if the value associated with the property may be changed (data descriptors only)." - }, - { - "name": "get", - "$ref": "RemoteObject", - "optional": true, - "description": "A function which serves as a getter for the property, or undefined if there is no getter (accessor descriptors only)." - }, - { - "name": "set", - "$ref": "RemoteObject", - "optional": true, - "description": "A function which serves as a setter for the property, or undefined if there is no setter (accessor descriptors only)." - }, - { - "name": "configurable", - "type": "boolean", - "description": "True if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object." - }, - { - "name": "enumerable", - "type": "boolean", - "description": "True if this property shows up during enumeration of the properties on the corresponding object." - }, - { - "name": "wasThrown", - "type": "boolean", - "optional": true, - "description": "True if the result was thrown during the evaluation." - }, - { - "name": "isOwn", - "optional": true, - "type": "boolean", - "description": "True if the property is owned for the object.", - "hidden": true - } - ] - }, - { - "id": "InternalPropertyDescriptor", - "type": "object", - "description": "Object internal property descriptor. This property isn't normally visible in JavaScript code.", - "properties": [ - { - "name": "name", - "type": "string", - "description": "Conventional property name." - }, - { - "name": "value", - "$ref": "RemoteObject", - "optional": true, - "description": "The value associated with the property." - } - ], - "hidden": true - }, - { - "id": "CallArgument", - "type": "object", - "description": "Represents function call argument. Either remote object id objectId or primitive value or neither of (for undefined) them should be specified.", - "properties": [ - { - "name": "value", - "type": "any", - "optional": true, - "description": "Primitive value." - }, - { - "name": "objectId", - "$ref": "RemoteObjectId", - "optional": true, - "description": "Remote object handle." - } - ] - }, - { - "id": "ExecutionContextId", - "type": "integer", - "description": "Id of an execution context." - }, - { - "id": "ExecutionContextDescription", - "type": "object", - "description": "Description of an isolated world.", - "properties": [ - { - "name": "id", - "$ref": "ExecutionContextId", - "description": "Unique id of the execution context. It can be used to specify in which execution context script evaluation should be performed." - }, - { - "name": "isPageContext", - "type": "boolean", - "description": "True if this is a context where inpspected web page scripts run. False if it is a content script isolated context.", - "hidden": true - }, - { - "name": "name", - "type": "string", - "description": "Human readable name describing given context.", - "hidden": true - }, - { - "name": "frameId", - "type": "string", - "description": "Id of the owning frame." - } - ] - } - ], - "commands": [ - { - "name": "evaluate", - "parameters": [ - { - "name": "expression", - "type": "string", - "description": "Expression to evaluate." - }, - { - "name": "objectGroup", - "type": "string", - "optional": true, - "description": "Symbolic group name that can be used to release multiple objects." - }, - { - "name": "includeCommandLineAPI", - "type": "boolean", - "optional": true, - "description": "Determines whether Command Line API should be available during the evaluation.", - "hidden": true - }, - { - "name": "doNotPauseOnExceptionsAndMuteConsole", - "type": "boolean", - "optional": true, - "description": "Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.", - "hidden": true - }, - { - "name": "contextId", - "$ref": "Runtime.ExecutionContextId", - "optional": true, - "description": "Specifies in which isolated context to perform evaluation. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page." - }, - { - "name": "returnByValue", - "type": "boolean", - "optional": true, - "description": "Whether the result is expected to be a JSON object that should be sent by value." - }, - { - "name": "generatePreview", - "type": "boolean", - "optional": true, - "hidden": true, - "description": "Whether preview should be generated for the result." - } - ], - "returns": [ - { - "name": "result", - "$ref": "RemoteObject", - "description": "Evaluation result." - }, - { - "name": "wasThrown", - "type": "boolean", - "optional": true, - "description": "True if the result was thrown during the evaluation." - } - ], - "description": "Evaluates expression on global object." - }, - { - "name": "callFunctionOn", - "parameters": [ - { - "name": "objectId", - "$ref": "RemoteObjectId", - "description": "Identifier of the object to call function on." - }, - { - "name": "functionDeclaration", - "type": "string", - "description": "Declaration of the function to call." - }, - { - "name": "arguments", - "type": "array", - "items": { - "$ref": "CallArgument", - "description": "Call argument." - }, - "optional": true, - "description": "Call arguments. All call arguments must belong to the same JavaScript world as the target object." - }, - { - "name": "doNotPauseOnExceptionsAndMuteConsole", - "type": "boolean", - "optional": true, - "description": "Specifies whether function call should stop on exceptions and mute console. Overrides setPauseOnException state.", - "hidden": true - }, - { - "name": "returnByValue", - "type": "boolean", - "optional": true, - "description": "Whether the result is expected to be a JSON object which should be sent by value." - }, - { - "name": "generatePreview", - "type": "boolean", - "optional": true, - "hidden": true, - "description": "Whether preview should be generated for the result." - } - ], - "returns": [ - { - "name": "result", - "$ref": "RemoteObject", - "description": "Call result." - }, - { - "name": "wasThrown", - "type": "boolean", - "optional": true, - "description": "True if the result was thrown during the evaluation." - } - ], - "description": "Calls function with given declaration on the given object. Object group of the result is inherited from the target object." - }, - { - "name": "getProperties", - "parameters": [ - { - "name": "objectId", - "$ref": "RemoteObjectId", - "description": "Identifier of the object to return properties for." - }, - { - "name": "ownProperties", - "optional": true, - "type": "boolean", - "description": "If true, returns properties belonging only to the element itself, not to its prototype chain." - }, - { - "name": "accessorPropertiesOnly", - "optional": true, - "type": "boolean", - "description": "If true, returns accessor properties (with getter/setter) only; internal properties are not returned either.", - "hidden": true - } - ], - "returns": [ - { - "name": "result", - "type": "array", - "items": { - "$ref": "PropertyDescriptor" - }, - "description": "Object properties." - }, - { - "name": "internalProperties", - "optional": true, - "type": "array", - "items": { - "$ref": "InternalPropertyDescriptor" - }, - "description": "Internal object properties (only of the element itself).", - "hidden": true - } - ], - "description": "Returns properties of a given object. Object group of the result is inherited from the target object." - }, - { - "name": "releaseObject", - "parameters": [ - { - "name": "objectId", - "$ref": "RemoteObjectId", - "description": "Identifier of the object to release." - } - ], - "description": "Releases remote object with given id." - }, - { - "name": "releaseObjectGroup", - "parameters": [ - { - "name": "objectGroup", - "type": "string", - "description": "Symbolic object group name." - } - ], - "description": "Releases all remote objects that belong to a given group." - }, - { - "name": "run", - "hidden": true, - "description": "Tells inspected instance(worker or page) that it can run in case it was started paused." - }, - { - "name": "enable", - "description": "Enables reporting of execution contexts creation by means of executionContextCreated event. When the reporting gets enabled the event will be sent immediately for each existing execution context." - }, - { - "name": "disable", - "hidden": true, - "description": "Disables reporting of execution contexts creation." - } - ], - "events": [ - { - "name": "executionContextCreated", - "parameters": [ - { - "name": "context", - "$ref": "ExecutionContextDescription", - "description": "A newly created execution contex." - } - ], - "description": "Issued when new execution context is created." - } - ] - }, - { - "domain": "Debugger", - "description": "Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing breakpoints, stepping through execution, exploring stack traces, etc.", - "types": [ - { - "id": "SearchMatch", - "type": "object", - "description": "Search match for resource.", - "properties": [ - { - "name": "lineNumber", - "type": "number", - "description": "Line number in resource content." - }, - { - "name": "lineContent", - "type": "string", - "description": "Line with match content." - } - ], - "hidden": true - }, - { - "id": "BreakpointId", - "type": "string", - "description": "Breakpoint identifier." - }, - { - "id": "ScriptId", - "type": "string", - "description": "Unique script identifier." - }, - { - "id": "CallFrameId", - "type": "string", - "description": "Call frame identifier." - }, - { - "id": "Location", - "type": "object", - "properties": [ - { - "name": "scriptId", - "$ref": "ScriptId", - "description": "Script identifier as reported in the Debugger.scriptParsed." - }, - { - "name": "lineNumber", - "type": "integer", - "description": "Line number in the script (0-based)." - }, - { - "name": "columnNumber", - "type": "integer", - "optional": true, - "description": "Column number in the script (0-based)." - } - ], - "description": "Location in the source code." - }, - { - "id": "FunctionDetails", - "hidden": true, - "type": "object", - "properties": [ - { - "name": "location", - "$ref": "Location", - "description": "Location of the function." - }, - { - "name": "name", - "type": "string", - "optional": true, - "description": "Name of the function. Not present for anonymous functions." - }, - { - "name": "displayName", - "type": "string", - "optional": true, - "description": "Display name of the function(specified in 'displayName' property on the function object)." - }, - { - "name": "inferredName", - "type": "string", - "optional": true, - "description": "Name of the function inferred from its initial assignment." - }, - { - "name": "scopeChain", - "type": "array", - "optional": true, - "items": { - "$ref": "Scope" - }, - "description": "Scope chain for this closure." - } - ], - "description": "Information about the function." - }, - { - "id": "CallFrame", - "type": "object", - "properties": [ - { - "name": "callFrameId", - "$ref": "CallFrameId", - "description": "Call frame identifier. This identifier is only valid while the virtual machine is paused." - }, - { - "name": "functionName", - "type": "string", - "description": "Name of the JavaScript function called on this call frame." - }, - { - "name": "location", - "$ref": "Location", - "description": "Location in the source code." - }, - { - "name": "scopeChain", - "type": "array", - "items": { - "$ref": "Scope" - }, - "description": "Scope chain for this call frame." - }, - { - "name": "this", - "$ref": "Runtime.RemoteObject", - "description": "this object for this call frame." - } - ], - "description": "JavaScript call frame. Array of call frames form the call stack." - }, - { - "id": "Scope", - "type": "object", - "properties": [ - { - "name": "type", - "type": "string", - "enum": [ - "global", - "local", - "with", - "closure", - "catch" - ], - "description": "Scope type." - }, - { - "name": "object", - "$ref": "Runtime.RemoteObject", - "description": "Object representing the scope. For global and with scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." - } - ], - "description": "Scope description." - }, - { - "id": "SetScriptSourceError", - "type": "object", - "properties": [ - { - "name": "compileError", - "optional": true, - "type": "object", - "properties": [ - { - "name": "message", - "type": "string", - "description": "Compiler error message" - }, - { - "name": "lineNumber", - "type": "integer", - "description": "Compile error line number (1-based)" - }, - { - "name": "columnNumber", - "type": "integer", - "description": "Compile error column number (1-based)" - } - ] - } - ], - "description": "Error data for setScriptSource command. compileError is a case type for uncompilable script source error.", - "hidden": true - } - ], - "commands": [ - { - "name": "enable", - "description": "Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received." - }, - { - "name": "disable", - "description": "Disables debugger for given page." - }, - { - "name": "setBreakpointsActive", - "parameters": [ - { - "name": "active", - "type": "boolean", - "description": "New value for breakpoints active state." - } - ], - "description": "Activates / deactivates all breakpoints on the page." - }, - { - "name": "setSkipAllPauses", - "hidden": true, - "parameters": [ - { - "name": "skipped", - "type": "boolean", - "description": "New value for skip pauses state." - }, - { - "name": "untilReload", - "type": "boolean", - "optional": true, - "description": "Whether page reload should set skipped to false." - } - ], - "description": "Makes page not interrupt on any pauses (breakpoint, exception, dom exception etc)." - }, - { - "name": "setBreakpointByUrl", - "parameters": [ - { - "name": "lineNumber", - "type": "integer", - "description": "Line number to set breakpoint at." - }, - { - "name": "url", - "type": "string", - "optional": true, - "description": "URL of the resources to set breakpoint on." - }, - { - "name": "urlRegex", - "type": "string", - "optional": true, - "description": "Regex pattern for the URLs of the resources to set breakpoints on. Either url or urlRegex must be specified." - }, - { - "name": "columnNumber", - "type": "integer", - "optional": true, - "description": "Offset in the line to set breakpoint at." - }, - { - "name": "condition", - "type": "string", - "optional": true, - "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." - }, - { - "name": "isAntibreakpoint", - "type": "boolean", - "optional": true, - "hidden": true, - "description": "Creates pseudo-breakpoint that prevents debugger from pausing on exception at this location." - } - ], - "returns": [ - { - "name": "breakpointId", - "$ref": "BreakpointId", - "description": "Id of the created breakpoint for further reference." - }, - { - "name": "locations", - "type": "array", - "items": { - "$ref": "Location" - }, - "description": "List of the locations this breakpoint resolved into upon addition." - } - ], - "description": "Sets JavaScript breakpoint at given location specified either by URL or URL regex. Once this command is issued, all existing parsed scripts will have breakpoints resolved and returned in locations property. Further matching script parsing will result in subsequent breakpointResolved events issued. This logical breakpoint will survive page reloads." - }, - { - "name": "setBreakpoint", - "parameters": [ - { - "name": "location", - "$ref": "Location", - "description": "Location to set breakpoint in." - }, - { - "name": "condition", - "type": "string", - "optional": true, - "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." - } - ], - "returns": [ - { - "name": "breakpointId", - "$ref": "BreakpointId", - "description": "Id of the created breakpoint for further reference." - }, - { - "name": "actualLocation", - "$ref": "Location", - "description": "Location this breakpoint resolved into." - } - ], - "description": "Sets JavaScript breakpoint at a given location." - }, - { - "name": "removeBreakpoint", - "parameters": [ - { - "name": "breakpointId", - "$ref": "BreakpointId" - } - ], - "description": "Removes JavaScript breakpoint." - }, - { - "name": "continueToLocation", - "parameters": [ - { - "name": "location", - "$ref": "Location", - "description": "Location to continue to." - }, - { - "name": "interstatementLocation", - "type": "boolean", - "optional": true, - "hidden": true, - "description": "Allows breakpoints at the intemediate positions inside statements." - } - ], - "description": "Continues execution until specific location is reached." - }, - { - "name": "stepOver", - "description": "Steps over the statement." - }, - { - "name": "stepInto", - "description": "Steps into the function call." - }, - { - "name": "stepOut", - "description": "Steps out of the function call." - }, - { - "name": "pause", - "description": "Stops on the next JavaScript statement." - }, - { - "name": "resume", - "description": "Resumes JavaScript execution." - }, - { - "name": "searchInContent", - "parameters": [ - { - "name": "scriptId", - "$ref": "ScriptId", - "description": "Id of the script to search in." - }, - { - "name": "query", - "type": "string", - "description": "String to search for." - }, - { - "name": "caseSensitive", - "type": "boolean", - "optional": true, - "description": "If true, search is case sensitive." - }, - { - "name": "isRegex", - "type": "boolean", - "optional": true, - "description": "If true, treats string parameter as regex." - } - ], - "returns": [ - { - "name": "result", - "type": "array", - "items": { - "$ref": "SearchMatch" - }, - "description": "List of search matches." - } - ], - "description": "Searches for given string in script content." - }, - { - "name": "canSetScriptSource", - "returns": [ - { - "name": "result", - "type": "boolean", - "description": "True if setScriptSource is supported." - } - ], - "description": "Always returns true." - }, - { - "name": "setScriptSource", - "parameters": [ - { - "name": "scriptId", - "$ref": "ScriptId", - "description": "Id of the script to edit." - }, - { - "name": "scriptSource", - "type": "string", - "description": "New content of the script." - }, - { - "name": "preview", - "type": "boolean", - "optional": true, - "description": " If true the change will not actually be applied. Preview mode may be used to get result description without actually modifying the code.", - "hidden": true - } - ], - "returns": [ - { - "name": "callFrames", - "type": "array", - "optional": true, - "items": { - "$ref": "CallFrame" - }, - "description": "New stack trace in case editing has happened while VM was stopped." - }, - { - "name": "result", - "type": "object", - "optional": true, - "description": "VM-specific description of the changes applied.", - "hidden": true - } - ], - "error": { - "$ref": "SetScriptSourceError" - }, - "description": "Edits JavaScript source live." - }, - { - "name": "restartFrame", - "parameters": [ - { - "name": "callFrameId", - "$ref": "CallFrameId", - "description": "Call frame identifier to evaluate on." - } - ], - "returns": [ - { - "name": "callFrames", - "type": "array", - "items": { - "$ref": "CallFrame" - }, - "description": "New stack trace." - }, - { - "name": "result", - "type": "object", - "description": "VM-specific description.", - "hidden": true - } - ], - "hidden": true, - "description": "Restarts particular call frame from the beginning." - }, - { - "name": "getScriptSource", - "parameters": [ - { - "name": "scriptId", - "$ref": "ScriptId", - "description": "Id of the script to get source for." - } - ], - "returns": [ - { - "name": "scriptSource", - "type": "string", - "description": "Script source." - } - ], - "description": "Returns source for the script with given id." - }, - { - "name": "getFunctionDetails", - "hidden": true, - "parameters": [ - { - "name": "functionId", - "$ref": "Runtime.RemoteObjectId", - "description": "Id of the function to get location for." - } - ], - "returns": [ - { - "name": "details", - "$ref": "FunctionDetails", - "description": "Information about the function." - } - ], - "description": "Returns detailed informtation on given function." - }, - { - "name": "setPauseOnExceptions", - "parameters": [ - { - "name": "state", - "type": "string", - "enum": [ - "none", - "uncaught", - "all" - ], - "description": "Pause on exceptions mode." - } - ], - "description": "Defines pause on exceptions state. Can be set to stop on all exceptions, uncaught exceptions or no exceptions. Initial pause on exceptions state is none." - }, - { - "name": "evaluateOnCallFrame", - "parameters": [ - { - "name": "callFrameId", - "$ref": "CallFrameId", - "description": "Call frame identifier to evaluate on." - }, - { - "name": "expression", - "type": "string", - "description": "Expression to evaluate." - }, - { - "name": "objectGroup", - "type": "string", - "optional": true, - "description": "String object group name to put result into (allows rapid releasing resulting object handles using releaseObjectGroup)." - }, - { - "name": "includeCommandLineAPI", - "type": "boolean", - "optional": true, - "description": "Specifies whether command line API should be available to the evaluated expression, defaults to false.", - "hidden": true - }, - { - "name": "doNotPauseOnExceptionsAndMuteConsole", - "type": "boolean", - "optional": true, - "description": "Specifies whether evaluation should stop on exceptions and mute console. Overrides setPauseOnException state.", - "hidden": true - }, - { - "name": "returnByValue", - "type": "boolean", - "optional": true, - "description": "Whether the result is expected to be a JSON object that should be sent by value." - }, - { - "name": "generatePreview", - "type": "boolean", - "optional": true, - "hidden": true, - "description": "Whether preview should be generated for the result." - } - ], - "returns": [ - { - "name": "result", - "$ref": "Runtime.RemoteObject", - "description": "Object wrapper for the evaluation result." - }, - { - "name": "wasThrown", - "type": "boolean", - "optional": true, - "description": "True if the result was thrown during the evaluation." - } - ], - "description": "Evaluates expression on a given call frame." - }, - { - "name": "compileScript", - "hidden": true, - "parameters": [ - { - "name": "expression", - "type": "string", - "description": "Expression to compile." - }, - { - "name": "sourceURL", - "type": "string", - "description": "Source url to be set for the script." - } - ], - "returns": [ - { - "name": "scriptId", - "$ref": "ScriptId", - "optional": true, - "description": "Id of the script." - }, - { - "name": "syntaxErrorMessage", - "type": "string", - "optional": true, - "description": "Syntax error message if compilation failed." - } - ], - "description": "Compiles expression." - }, - { - "name": "runScript", - "hidden": true, - "parameters": [ - { - "name": "scriptId", - "$ref": "ScriptId", - "description": "Id of the script to run." - }, - { - "name": "contextId", - "$ref": "Runtime.ExecutionContextId", - "optional": true, - "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter may be used to specify one of those contexts. If the parameter is omitted or 0 the evaluation will be performed in the context of the inspected page." - }, - { - "name": "objectGroup", - "type": "string", - "optional": true, - "description": "Symbolic group name that can be used to release multiple objects." - }, - { - "name": "doNotPauseOnExceptionsAndMuteConsole", - "type": "boolean", - "optional": true, - "description": "Specifies whether script run should stop on exceptions and mute console. Overrides setPauseOnException state." - } - ], - "returns": [ - { - "name": "result", - "$ref": "Runtime.RemoteObject", - "description": "Run result." - }, - { - "name": "wasThrown", - "type": "boolean", - "optional": true, - "description": "True if the result was thrown during the script run." - } - ], - "description": "Runs script with given id in a given context." - }, - { - "name": "setOverlayMessage", - "parameters": [ - { - "name": "message", - "type": "string", - "optional": true, - "description": "Overlay message to display when paused in debugger." - } - ], - "hidden": true, - "description": "Sets overlay message." - }, - { - "name": "setVariableValue", - "parameters": [ - { - "name": "scopeNumber", - "type": "integer", - "description": "0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually." - }, - { - "name": "variableName", - "type": "string", - "description": "Variable name." - }, - { - "name": "newValue", - "$ref": "Runtime.CallArgument", - "description": "New variable value." - }, - { - "name": "callFrameId", - "$ref": "CallFrameId", - "optional": true, - "description": "Id of callframe that holds variable." - }, - { - "name": "functionObjectId", - "$ref": "Runtime.RemoteObjectId", - "optional": true, - "description": "Object id of closure (function) that holds variable." - } - ], - "hidden": true, - "description": "Changes value of variable in a callframe or a closure. Either callframe or function must be specified. Object-based scopes are not supported and must be mutated manually." - }, - { - "name": "getStepInPositions", - "parameters": [ - { - "name": "callFrameId", - "$ref": "CallFrameId", - "description": "Id of a call frame where the current statement should be analized" - } - ], - "returns": [ - { - "name": "stepInPositions", - "type": "array", - "items": { - "$ref": "Location" - }, - "optional": true, - "description": "experimental" - } - ], - "hidden": true, - "description": "Lists all positions where step-in is possible for a current statement in a specified call frame" - }, - { - "name": "getBacktrace", - "returns": [ - { - "name": "callFrames", - "type": "array", - "items": { - "$ref": "CallFrame" - }, - "description": "Call stack the virtual machine stopped on." - } - ], - "hidden": true, - "description": "Returns call stack including variables changed since VM was paused. VM must be paused." - }, - { - "name": "skipStackFrames", - "parameters": [ - { - "name": "script", - "optional": true, - "type": "string", - "description": "Regular expression defining the scripts to ignore while stepping." - } - ], - "hidden": true, - "description": "Makes backend skip steps in the sources with names matching given pattern. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful." - } - ], - "events": [ - { - "name": "globalObjectCleared", - "description": "Called when global has been cleared and debugger client should reset its state. Happens upon navigation or reload." - }, - { - "name": "scriptParsed", - "parameters": [ - { - "name": "scriptId", - "$ref": "ScriptId", - "description": "Identifier of the script parsed." - }, - { - "name": "url", - "type": "string", - "description": "URL or name of the script parsed (if any)." - }, - { - "name": "startLine", - "type": "integer", - "description": "Line offset of the script within the resource with given URL (for script tags)." - }, - { - "name": "startColumn", - "type": "integer", - "description": "Column offset of the script within the resource with given URL." - }, - { - "name": "endLine", - "type": "integer", - "description": "Last line of the script." - }, - { - "name": "endColumn", - "type": "integer", - "description": "Length of the last line of the script." - }, - { - "name": "isContentScript", - "type": "boolean", - "optional": true, - "description": "Determines whether this script is a user extension script." - }, - { - "name": "sourceMapURL", - "type": "string", - "optional": true, - "description": "URL of source map associated with script (if any)." - }, - { - "name": "hasSourceURL", - "type": "boolean", - "optional": true, - "description": "True, if this script has sourceURL.", - "hidden": true - } - ], - "description": "Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger." - }, - { - "name": "scriptFailedToParse", - "parameters": [ - { - "name": "scriptId", - "$ref": "ScriptId", - "description": "Identifier of the script parsed." - }, - { - "name": "url", - "type": "string", - "description": "URL or name of the script parsed (if any)." - }, - { - "name": "startLine", - "type": "integer", - "description": "Line offset of the script within the resource with given URL (for script tags)." - }, - { - "name": "startColumn", - "type": "integer", - "description": "Column offset of the script within the resource with given URL." - }, - { - "name": "endLine", - "type": "integer", - "description": "Last line of the script." - }, - { - "name": "endColumn", - "type": "integer", - "description": "Length of the last line of the script." - }, - { - "name": "isContentScript", - "type": "boolean", - "optional": true, - "description": "Determines whether this script is a user extension script." - }, - { - "name": "sourceMapURL", - "type": "string", - "optional": true, - "description": "URL of source map associated with script (if any)." - }, - { - "name": "hasSourceURL", - "type": "boolean", - "optional": true, - "description": "True, if this script has sourceURL.", - "hidden": true - } - ], - "description": "Fired when virtual machine fails to parse the script." - }, - { - "name": "breakpointResolved", - "parameters": [ - { - "name": "breakpointId", - "$ref": "BreakpointId", - "description": "Breakpoint unique identifier." - }, - { - "name": "location", - "$ref": "Location", - "description": "Actual breakpoint location." - } - ], - "description": "Fired when breakpoint is resolved to an actual script and location." - }, - { - "name": "paused", - "parameters": [ - { - "name": "callFrames", - "type": "array", - "items": { - "$ref": "CallFrame" - }, - "description": "Call stack the virtual machine stopped on." - }, - { - "name": "reason", - "type": "string", - "enum": [ - "XHR", - "DOM", - "EventListener", - "exception", - "assert", - "CSPViolation", - "debugCommand", - "other" - ], - "description": "Pause reason." - }, - { - "name": "data", - "type": "object", - "optional": true, - "description": "Object containing break-specific auxiliary properties." - }, - { - "name": "hitBreakpoints", - "type": "array", - "optional": true, - "items": { - "type": "string" - }, - "description": "Hit breakpoints IDs", - "hidden": true - } - ], - "description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria." - }, - { - "name": "resumed", - "description": "Fired when the virtual machine resumed execution." - } - ] - }, - { - "domain": "Profiler", - "hidden": true, - "types": [ - { - "id": "ProfileHeader", - "type": "object", - "description": "Profile header.", - "properties": [ - { - "name": "title", - "type": "string", - "description": "Profile title." - }, - { - "name": "uid", - "type": "integer", - "description": "Unique identifier of the profile." - } - ] - }, - { - "id": "CPUProfileNode", - "type": "object", - "description": "CPU Profile node. Holds callsite information, execution statistics and child nodes.", - "properties": [ - { - "name": "functionName", - "type": "string", - "description": "Function name." - }, - { - "name": "scriptId", - "$ref": "Debugger.ScriptId", - "description": "Script identifier." - }, - { - "name": "url", - "type": "string", - "description": "URL." - }, - { - "name": "lineNumber", - "type": "integer", - "description": "Line number." - }, - { - "name": "hitCount", - "type": "integer", - "description": "Number of samples where this node was on top of the call stack." - }, - { - "name": "callUID", - "type": "number", - "description": "Call UID." - }, - { - "name": "children", - "type": "array", - "items": { - "$ref": "CPUProfileNode" - }, - "description": "Child nodes." - }, - { - "name": "deoptReason", - "type": "string", - "description": "The reason of being not optimized. The function may be deoptimized or marked as don't optimize." - }, - { - "name": "id", - "optional": true, - "type": "integer", - "description": "Unique id of the node." - } - ] - }, - { - "id": "CPUProfile", - "type": "object", - "description": "Profile.", - "properties": [ - { - "name": "head", - "$ref": "CPUProfileNode" - }, - { - "name": "startTime", - "type": "number", - "description": "Profiling start time in seconds." - }, - { - "name": "endTime", - "type": "number", - "description": "Profiling end time in seconds." - }, - { - "name": "samples", - "optional": true, - "type": "array", - "items": { - "type": "integer" - }, - "description": "Ids of samples top nodes." - } - ] - }, - { - "id": "HeapSnapshotObjectId", - "type": "string", - "description": "Heap snashot object id." - } - ], - "commands": [ - { - "name": "enable" - }, - { - "name": "disable" - }, - { - "name": "start" - }, - { - "name": "stop", - "returns": [ - { - "name": "header", - "$ref": "ProfileHeader", - "description": "The header of the recorded profile." - } - ] - }, - { - "name": "getProfileHeaders", - "returns": [ - { - "name": "headers", - "type": "array", - "items": { - "$ref": "ProfileHeader" - } - } - ] - }, - { - "name": "getCPUProfile", - "parameters": [ - { - "name": "uid", - "type": "integer" - } - ], - "returns": [ - { - "name": "profile", - "$ref": "CPUProfile" - } - ] - }, - { - "name": "removeProfile", - "parameters": [ - { - "name": "type", - "type": "string" - }, - { - "name": "uid", - "type": "integer" - } - ] - }, - { - "name": "clearProfiles" - } - ], - "events": [ - { - "name": "addProfileHeader", - "parameters": [ - { - "name": "header", - "$ref": "ProfileHeader" - } - ] - }, - { - "name": "setRecordingProfile", - "parameters": [ - { - "name": "isProfiling", - "type": "boolean" - } - ] - }, - { - "name": "resetProfiles" - } - ] - }, - { - "domain": "HeapProfiler", - "hidden": true, - "types": [ - { - "id": "ProfileHeader", - "type": "object", - "description": "Profile header.", - "properties": [ - { - "name": "title", - "type": "string", - "description": "Profile title." - }, - { - "name": "uid", - "type": "integer", - "description": "Unique identifier of the profile." - }, - { - "name": "maxJSObjectId", - "type": "integer", - "optional": true, - "description": "Last seen JS object Id." - } - ] - }, - { - "id": "HeapSnapshotObjectId", - "type": "string", - "description": "Heap snashot object id." - } - ], - "commands": [ - { - "name": "getProfileHeaders", - "returns": [ - { - "name": "headers", - "type": "array", - "items": { - "$ref": "ProfileHeader" - } - } - ] - }, - { - "name": "startTrackingHeapObjects" - }, - { - "name": "stopTrackingHeapObjects" - }, - { - "name": "getHeapSnapshot", - "parameters": [ - { - "name": "uid", - "type": "integer" - } - ] - }, - { - "name": "removeProfile", - "parameters": [ - { - "name": "uid", - "type": "integer" - } - ] - }, - { - "name": "clearProfiles" - }, - { - "name": "takeHeapSnapshot", - "parameters": [ - { - "name": "reportProgress", - "type": "boolean", - "optional": true, - "description": "If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken." - } - ] - }, - { - "name": "collectGarbage" - }, - { - "name": "getObjectByHeapObjectId", - "parameters": [ - { - "name": "objectId", - "$ref": "HeapSnapshotObjectId" - }, - { - "name": "objectGroup", - "type": "string", - "optional": true, - "description": "Symbolic group name that can be used to release multiple objects." - } - ], - "returns": [ - { - "name": "result", - "$ref": "Runtime.RemoteObject", - "description": "Evaluation result." - } - ] - }, - { - "name": "getHeapObjectId", - "parameters": [ - { - "name": "objectId", - "$ref": "Runtime.RemoteObjectId", - "description": "Identifier of the object to get heap object id for." - } - ], - "returns": [ - { - "name": "heapSnapshotObjectId", - "$ref": "HeapSnapshotObjectId", - "description": "Id of the heap snapshot object corresponding to the passed remote object id." - } - ] - } - ], - "events": [ - { - "name": "addProfileHeader", - "parameters": [ - { - "name": "header", - "$ref": "ProfileHeader" - } - ] - }, - { - "name": "addHeapSnapshotChunk", - "parameters": [ - { - "name": "uid", - "type": "integer" - }, - { - "name": "chunk", - "type": "string" - } - ] - }, - { - "name": "finishHeapSnapshot", - "parameters": [ - { - "name": "uid", - "type": "integer" - } - ] - }, - { - "name": "resetProfiles" - }, - { - "name": "reportHeapSnapshotProgress", - "parameters": [ - { - "name": "done", - "type": "integer" - }, - { - "name": "total", - "type": "integer" - } - ] - }, - { - "name": "lastSeenObjectId", - "description": "If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.", - "parameters": [ - { - "name": "lastSeenObjectId", - "type": "integer" - }, - { - "name": "timestamp", - "type": "number" - } - ] - }, - { - "name": "heapStatsUpdate", - "description": "If heap objects tracking has been started then backend may send update for one or more fragments", - "parameters": [ - { - "name": "statsUpdate", - "type": "array", - "items": { - "type": "integer" - }, - "description": "An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment." - } - ] - } - ] - } - ], - "version": { - "major": "1", - "minor": "1" - } -} \ No newline at end of file diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/InspectorVersion.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/InspectorVersion.h deleted file mode 100644 index 1cdee42a6e02dc..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/InspectorVersion.h +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is automatically generated. Do not modify. -#define V8_INSPECTOR_REVISION "60cd6e859b9f557d2312f5bf532f6aec5f284980" diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8ContextInfo.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8ContextInfo.h deleted file mode 100644 index 24570a4751a93b..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8ContextInfo.h +++ /dev/null @@ -1,37 +0,0 @@ -// 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 V8ContextInfo_h -#define V8ContextInfo_h - -#include "platform/inspector_protocol/InspectorProtocol.h" - -#include - -namespace v8_inspector { - -class V8ContextInfo { -public: - V8ContextInfo(v8::Local context, int contextGroupId, const String16& humanReadableName) - : context(context) - , contextGroupId(contextGroupId) - , humanReadableName(humanReadableName) - , hasMemoryOnConsole(false) - { - } - - v8::Local context; - // Each v8::Context is a part of a group. The group id is used to find appropriate - // V8DebuggerAgent to notify about events in the context. - // |contextGroupId| must be non-0. - int contextGroupId; - String16 humanReadableName; - String16 origin; - String16 auxData; - bool hasMemoryOnConsole; -}; - -} // namespace v8_inspector - -#endif // V8ContextInfo_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8Inspector.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8Inspector.h deleted file mode 100644 index bb078474f9bd92..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8Inspector.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2015 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 V8Inspector_h -#define V8Inspector_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/public/V8ContextInfo.h" - -#include - -namespace v8_inspector { - -class V8InspectorClient; -class V8InspectorSession; -class V8StackTrace; - -class PLATFORM_EXPORT V8Inspector { -public: - static std::unique_ptr create(v8::Isolate*, V8InspectorClient*); - virtual ~V8Inspector() { } - - // Contexts instrumentation. - virtual void contextCreated(const V8ContextInfo&) = 0; - virtual void contextDestroyed(v8::Local) = 0; - virtual void resetContextGroup(int contextGroupId) = 0; - - // Various instrumentation. - virtual void willExecuteScript(v8::Local, int scriptId) = 0; - virtual void didExecuteScript(v8::Local) = 0; - virtual void idleStarted() = 0; - virtual void idleFinished() = 0; - - // Async stack traces instrumentation. - virtual void asyncTaskScheduled(const String16& taskName, void* task, bool recurring) = 0; - virtual void asyncTaskCanceled(void* task) = 0; - virtual void asyncTaskStarted(void* task) = 0; - virtual void asyncTaskFinished(void* task) = 0; - virtual void allAsyncTasksCanceled() = 0; - - // Exceptions instrumentation. - virtual unsigned exceptionThrown(v8::Local, const String16& message, v8::Local exception, const String16& detailedMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr, int scriptId) = 0; - virtual void exceptionRevoked(v8::Local, unsigned exceptionId, const String16& message) = 0; - - // API methods. - virtual std::unique_ptr connect(int contextGroupId, blink::protocol::FrontendChannel*, const String16* state) = 0; - virtual std::unique_ptr createStackTrace(v8::Local) = 0; - virtual std::unique_ptr captureStackTrace(bool fullStack) = 0; -}; - -} // namespace v8_inspector - - -#endif // V8Inspector_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8InspectorClient.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8InspectorClient.h deleted file mode 100644 index eb3e2ae7a22609..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8InspectorClient.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2015 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 V8InspectorClient_h -#define V8InspectorClient_h - -#include "platform/inspector_protocol/InspectorProtocol.h" - -#include - -namespace v8_inspector { - -class V8StackTrace; - -enum class V8ConsoleAPIType { kClear, kDebug, kLog, kInfo, kWarning, kError }; - -class PLATFORM_EXPORT V8InspectorClient { -public: - virtual ~V8InspectorClient() { } - - virtual void runMessageLoopOnPause(int contextGroupId) { } - virtual void quitMessageLoopOnPause() { } - virtual void runIfWaitingForDebugger(int contextGroupId) { } - - virtual void muteMetrics(int contextGroupId) { } - virtual void unmuteMetrics(int contextGroupId) { } - - virtual void beginUserGesture() { } - virtual void endUserGesture() { } - - virtual String16 valueSubtype(v8::Local) { return String16(); } - virtual bool formatAccessorsAsProperties(v8::Local) { return false; } - virtual bool isInspectableHeapObject(v8::Local) { return true; } - - virtual v8::Local ensureDefaultContextInGroup(int contextGroupId) { return v8::Local(); } - virtual void beginEnsureAllContextsInGroup(int contextGroupId) { } - virtual void endEnsureAllContextsInGroup(int contextGroupId) { } - - virtual void installAdditionalCommandLineAPI(v8::Local, v8::Local) { } - virtual void consoleAPIMessage(int contextGroupId, V8ConsoleAPIType, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, V8StackTrace*) { } - virtual v8::MaybeLocal memoryInfo(v8::Isolate*, v8::Local) { return v8::MaybeLocal(); } - - virtual void consoleTime(const String16& title) { } - virtual void consoleTimeEnd(const String16& title) { } - virtual void consoleTimeStamp(const String16& title) { } - virtual double currentTimeMS() { return 0; } - typedef void (*TimerCallback)(void*); - virtual void startRepeatingTimer(double, TimerCallback, void* data) { } - virtual void cancelTimer(void* data) { } - - // TODO(dgozman): this was added to support service worker shadow page. We should not connect at all. - virtual bool canExecuteScripts(int contextGroupId) { return true; } -}; - -} // namespace v8_inspector - - -#endif // V8InspectorClient_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8InspectorSession.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8InspectorSession.h deleted file mode 100644 index 2954ae353b0a4f..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8InspectorSession.h +++ /dev/null @@ -1,52 +0,0 @@ -// 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 V8InspectorSession_h -#define V8InspectorSession_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/public/protocol/Debugger.h" -#include "platform/v8_inspector/public/protocol/Runtime.h" -#include "platform/v8_inspector/public/protocol/Schema.h" - -#include - -namespace v8_inspector { - -class PLATFORM_EXPORT V8InspectorSession { -public: - virtual ~V8InspectorSession() { } - - // Cross-context inspectable values (DOM nodes in different worlds, etc.). - class Inspectable { - public: - virtual v8::Local get(v8::Local) = 0; - virtual ~Inspectable() { } - }; - virtual void addInspectedObject(std::unique_ptr) = 0; - - // Dispatching protocol messages. - static bool canDispatchMethod(const String16& method); - virtual void dispatchProtocolMessage(const String16& message) = 0; - virtual String16 stateJSON() = 0; - virtual std::unique_ptr> supportedDomains() = 0; - - // Debugger actions. - virtual void schedulePauseOnNextStatement(const String16& breakReason, const String16& breakDetails) = 0; - virtual void cancelPauseOnNextStatement() = 0; - virtual void breakProgram(const String16& breakReason, const String16& breakDetails) = 0; - virtual void setSkipAllPauses(bool) = 0; - virtual void resume() = 0; - virtual void stepOver() = 0; - virtual std::unique_ptr> searchInTextByLines(const String16& text, const String16& query, bool caseSensitive, bool isRegex) = 0; - - // Remote objects. - virtual std::unique_ptr wrapObject(v8::Local, v8::Local, const String16& groupName) = 0; - virtual bool unwrapObject(ErrorString*, const String16& objectId, v8::Local*, v8::Local*, String16* objectGroup) = 0; - virtual void releaseObjectGroup(const String16&) = 0; -}; - -} // namespace v8_inspector - -#endif // V8InspectorSession_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8StackTrace.h b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8StackTrace.h deleted file mode 100644 index ac68c1b0e9ea0a..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/public/V8StackTrace.h +++ /dev/null @@ -1,34 +0,0 @@ -// 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 V8StackTrace_h -#define V8StackTrace_h - -#include "platform/inspector_protocol/InspectorProtocol.h" -#include "platform/v8_inspector/public/protocol/Runtime.h" - -#include - -namespace v8_inspector { - -class V8StackTrace { -public: - virtual bool isEmpty() const = 0; - virtual String16 topSourceURL() const = 0; - virtual int topLineNumber() const = 0; - virtual int topColumnNumber() const = 0; - virtual String16 topScriptId() const = 0; - virtual String16 topFunctionName() const = 0; - - virtual ~V8StackTrace() { } - virtual std::unique_ptr buildInspectorObject() const = 0; - virtual String16 toString() const = 0; - - // Safe to pass between threads, drops async chain. - virtual std::unique_ptr clone() = 0; -}; - -} // namespace v8_inspector - -#endif // V8StackTrace_h diff --git a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/v8_inspector.gyp b/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/v8_inspector.gyp deleted file mode 100644 index c957ee2c184635..00000000000000 --- a/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector/v8_inspector.gyp +++ /dev/null @@ -1,320 +0,0 @@ -# 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': { - 'blink_platform_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/platform', - }, - 'conditions': [ - ['v8_inspector!="true"', - { - 'targets': [ - { - # GN version: //third_party/WebKit/Source/platform:inspector_protocol_sources - 'target_name': 'protocol_sources', - 'type': 'none', - 'dependencies': ['protocol_version'], - 'actions': [ - { - 'action_name': 'generateV8InspectorProtocolBackendSources', - 'inputs': [ - # Source code templates. - '../inspector_protocol/Allocator_h.template', - '../inspector_protocol/Array_h.template', - '../inspector_protocol/BackendCallback_h.template', - '../inspector_protocol/CodeGenerator.py', - '../inspector_protocol/Collections_h.template', - '../inspector_protocol/DispatcherBase_cpp.template', - '../inspector_protocol/DispatcherBase_h.template', - '../inspector_protocol/ErrorSupport_cpp.template', - '../inspector_protocol/ErrorSupport_h.template', - '../inspector_protocol/Exported_h.template', - '../inspector_protocol/FrontendChannel_h.template', - '../inspector_protocol/Imported_h.template', - '../inspector_protocol/InspectorProtocol_cpp.template', - '../inspector_protocol/Maybe_h.template', - '../inspector_protocol/Object_cpp.template', - '../inspector_protocol/Object_h.template', - '../inspector_protocol/Parser_cpp.template', - '../inspector_protocol/Parser_h.template', - '../inspector_protocol/Platform_h.template', - '../inspector_protocol/String16_cpp.template', - '../inspector_protocol/String16_h.template', - '../inspector_protocol/TypeBuilder_cpp.template', - '../inspector_protocol/TypeBuilder_h.template', - '../inspector_protocol/ValueConversions_h.template', - '../inspector_protocol/Values_cpp.template', - '../inspector_protocol/Values_h.template', - # Protocol definitions - 'js_protocol.json', - # Config - 'inspector_protocol_config.json', - ], - 'outputs': [ - '<(blink_platform_output_dir)/inspector_protocol/InspectorProtocol.cpp', - '<(blink_platform_output_dir)/inspector_protocol/InspectorProtocol.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Console.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Console.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/HeapProfiler.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/HeapProfiler.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Profiler.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Profiler.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Runtime.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Runtime.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Schema.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Schema.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Debugger.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Runtime.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Schema.h', - ], - 'action': [ - 'python', - '../inspector_protocol/CodeGenerator.py', - '--output_base', '<(blink_platform_output_dir)', - '--config', 'inspector_protocol_config.json', - ], - 'message': 'Generating protocol backend sources from json definitions.', - }, - ] - }, - ], - }, - ], - ], - - 'targets': [ - { - # GN version: //third_party/WebKit/Source/platform:inspector_injected_script - 'target_name': 'inspector_injected_script', - 'type': 'none', - 'actions': [ - { - 'action_name': 'ConvertFileToHeaderWithCharacterArray', - 'inputs': [ - 'build/xxd.py', - 'InjectedScriptSource.js', - ], - 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/v8_inspector/InjectedScriptSource.h', ], - 'action': [ - 'python', 'build/xxd.py', 'InjectedScriptSource_js', 'InjectedScriptSource.js', '<@(_outputs)' - ], - }, - ], - # Since this target generates header files, it needs to be a hard dependency. - 'hard_dependency': 1, - }, - { - # GN version: //third_party/WebKit/Source/platform:inspector_debugger_script - 'target_name': 'inspector_debugger_script', - 'type': 'none', - 'actions': [ - { - 'action_name': 'ConvertFileToHeaderWithCharacterArray', - 'inputs': [ - 'build/xxd.py', - 'DebuggerScript.js', - ], - 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/blink/platform/v8_inspector/DebuggerScript.h', ], - 'action': [ - 'python', 'build/xxd.py', 'DebuggerScript_js', 'DebuggerScript.js', '<@(_outputs)' - ], - }, - ], - # Since this target generates header files, it needs to be a hard dependency. - 'hard_dependency': 1, - }, - { - # GN version: //third_party/WebKit/Source/core/inspector:protocol_version - 'target_name': 'protocol_version', - 'type': 'none', - 'actions': [ - { - 'action_name': 'generateV8InspectorProtocolVersion', - 'inputs': [ - '../inspector_protocol/generate-inspector-protocol-version', - 'js_protocol.json', - ], - 'outputs': [ - '<(blink_platform_output_dir)/v8_inspector/protocol.json', - ], - 'action': [ - 'python', - '../inspector_protocol/generate-inspector-protocol-version', - '--o', - '<@(_outputs)', - 'js_protocol.json', - ], - 'message': 'Validate v8_inspector protocol for backwards compatibility and generate version file', - }, - ] - }, - { - 'target_name': 'protocol_sources_stl', - 'type': 'none', - 'dependencies': ['protocol_version'], - 'actions': [ - { - 'action_name': 'generateV8InspectorProtocolBackendSourcesSTL', - 'inputs': [ - # Source code templates. - '../inspector_protocol/Allocator_h.template', - '../inspector_protocol/Array_h.template', - '../inspector_protocol/BackendCallback_h.template', - '../inspector_protocol/CodeGenerator.py', - '../inspector_protocol/Collections_h.template', - '../inspector_protocol/DispatcherBase_cpp.template', - '../inspector_protocol/DispatcherBase_h.template', - '../inspector_protocol/ErrorSupport_cpp.template', - '../inspector_protocol/ErrorSupport_h.template', - '../inspector_protocol/Exported_h.template', - '../inspector_protocol/FrontendChannel_h.template', - '../inspector_protocol/Imported_h.template', - '../inspector_protocol/InspectorProtocol_cpp.template', - '../inspector_protocol/Maybe_h.template', - '../inspector_protocol/Object_cpp.template', - '../inspector_protocol/Object_h.template', - '../inspector_protocol/Parser_cpp.template', - '../inspector_protocol/Parser_h.template', - '../inspector_protocol/Platform_h.template', - '../inspector_protocol/String16_cpp.template', - '../inspector_protocol/String16_h.template', - '../inspector_protocol/TypeBuilder_cpp.template', - '../inspector_protocol/TypeBuilder_h.template', - '../inspector_protocol/ValueConversions_h.template', - '../inspector_protocol/Values_cpp.template', - '../inspector_protocol/Values_h.template', - # Protocol definitions - 'js_protocol.json', - # Config - 'inspector_protocol_config_stl.json', - ], - 'outputs': [ - '<(blink_platform_output_dir)/inspector_protocol/InspectorProtocol.cpp', - '<(blink_platform_output_dir)/inspector_protocol/InspectorProtocol.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Console.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Console.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/HeapProfiler.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/HeapProfiler.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Profiler.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Profiler.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Runtime.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Runtime.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Schema.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Schema.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Debugger.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Runtime.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Schema.h', - ], - 'action': [ - 'python', - '../inspector_protocol/CodeGenerator.py', - '--output_base', '<(blink_platform_output_dir)', - '--config', 'inspector_protocol_config_stl.json', - ], - 'message': 'Generating protocol backend sources from json definitions.', - }, - ] - }, - { - 'target_name': 'v8_inspector_stl', - 'type': '<(component)', - 'dependencies': [ - ':inspector_injected_script', - ':inspector_debugger_script', - ':protocol_sources_stl', - ], - 'include_dirs': [ - '../..', - '../../../../../v8/include', - '../../../../../v8', - '<(SHARED_INTERMEDIATE_DIR)/blink', - ], - 'sources': [ - '<(blink_platform_output_dir)/inspector_protocol/InspectorProtocol.cpp', - '<(blink_platform_output_dir)/inspector_protocol/InspectorProtocol.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Console.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Console.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Debugger.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/HeapProfiler.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/HeapProfiler.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Profiler.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Profiler.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Runtime.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Runtime.h', - '<(blink_platform_output_dir)/v8_inspector/protocol/Schema.cpp', - '<(blink_platform_output_dir)/v8_inspector/protocol/Schema.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Debugger.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Runtime.h', - '<(blink_platform_output_dir)/v8_inspector/public/protocol/Schema.h', - - 'Atomics.h', - 'InjectedScript.cpp', - 'InjectedScript.h', - 'InjectedScriptNative.cpp', - 'InjectedScriptNative.h', - 'InspectedContext.cpp', - 'InspectedContext.h', - 'JavaScriptCallFrame.cpp', - 'JavaScriptCallFrame.h', - 'PlatformSTL.h', - 'RemoteObjectId.cpp', - 'RemoteObjectId.h', - 'ScriptBreakpoint.h', - 'String16STL.cpp', - 'String16STL.h', - 'V8Console.cpp', - 'V8Console.h', - 'V8ConsoleAgentImpl.cpp', - 'V8ConsoleAgentImpl.h', - 'V8ConsoleMessage.cpp', - 'V8ConsoleMessage.h', - 'V8Debugger.cpp', - 'V8Debugger.h', - 'V8DebuggerAgentImpl.cpp', - 'V8DebuggerAgentImpl.h', - 'V8InspectorImpl.cpp', - 'V8InspectorImpl.h', - 'V8DebuggerScript.cpp', - 'V8DebuggerScript.h', - 'V8FunctionCall.cpp', - 'V8FunctionCall.h', - 'V8HeapProfilerAgentImpl.cpp', - 'V8HeapProfilerAgentImpl.h', - 'V8InjectedScriptHost.cpp', - 'V8InjectedScriptHost.h', - 'V8InspectorSessionImpl.cpp', - 'V8InspectorSessionImpl.h', - 'V8InternalValueType.cpp', - 'V8InternalValueType.h', - 'V8ProfilerAgentImpl.cpp', - 'V8ProfilerAgentImpl.h', - 'V8Regex.cpp', - 'V8Regex.h', - 'V8RuntimeAgentImpl.cpp', - 'V8RuntimeAgentImpl.h', - 'V8SchemaAgentImpl.cpp', - 'V8SchemaAgentImpl.h', - 'V8StackTraceImpl.cpp', - 'V8StackTraceImpl.h', - 'V8StringUtil.cpp', - 'V8StringUtil.h', - 'V8ValueCopier.cpp', - 'V8ValueCopier.h', - 'public/V8ContextInfo.h', - 'public/V8Inspector.h', - 'public/V8InspectorClient.h', - 'public/V8InspectorSession.h', - 'public/V8StackTrace.h', - - '<(blink_platform_output_dir)/v8_inspector/DebuggerScript.h', - '<(blink_platform_output_dir)/v8_inspector/InjectedScriptSource.h', - ], - }, - ], # targets -} diff --git a/node.gyp b/node.gyp index 59bdc0d3a7dfc1..bfdbf927c9eea1 100644 --- a/node.gyp +++ b/node.gyp @@ -314,8 +314,6 @@ [ 'v8_inspector=="true"', { 'defines': [ 'HAVE_INSPECTOR=1', - 'V8_INSPECTOR_USE_STL=1', - 'V8_INSPECTOR_USE_OLD_STL=1', ], 'sources': [ 'src/inspector_agent.cc', @@ -324,13 +322,13 @@ 'src/inspector_agent.h', ], 'dependencies': [ - 'deps/v8_inspector/third_party/v8_inspector/platform/' - 'v8_inspector/v8_inspector.gyp:v8_inspector_stl', + 'deps/v8_inspector/src/inspector/inspector.gyp:standalone_inspector', 'v8_inspector_compress_protocol_json#host', ], 'include_dirs': [ - 'deps/v8_inspector/third_party/v8_inspector', - '<(SHARED_INTERMEDIATE_DIR)/blink', # for inspector + 'deps/v8_inspector/include', + '<(SHARED_INTERMEDIATE_DIR)/include', # for inspector + '<(SHARED_INTERMEDIATE_DIR)', ], }, { 'defines': [ 'HAVE_INSPECTOR=0' ] @@ -666,8 +664,7 @@ 'action_name': 'v8_inspector_compress_protocol_json', 'process_outputs_as_sources': 1, 'inputs': [ - 'deps/v8_inspector/third_party/' - 'v8_inspector/platform/v8_inspector/js_protocol.json', + 'deps/v8_inspector/src/inspector/js_protocol.json', ], 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/v8_inspector_protocol_json.h', diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index cb20bd702f37d1..7f82b7b0516fa6 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -7,21 +7,17 @@ #include "node_crypto.h" #include "node_mutex.h" #include "node_version.h" +#include "v8-inspector.h" #include "v8-platform.h" #include "util.h" #include "zlib.h" -#include "platform/v8_inspector/public/InspectorVersion.h" -#include "platform/v8_inspector/public/V8Inspector.h" -#include "platform/v8_inspector/public/V8InspectorClient.h" -#include "platform/v8_inspector/public/V8InspectorSession.h" -#include "platform/v8_inspector/public/V8StackTrace.h" -#include "platform/inspector_protocol/InspectorProtocol.h" - #include "libplatform/libplatform.h" #include #include +#include + #include #include #include @@ -31,6 +27,9 @@ namespace node { namespace inspector { namespace { +using v8_inspector::StringBuffer; +using v8_inspector::StringView; + const char TAG_CONNECT[] = "#connect"; const char TAG_DISCONNECT[] = "#disconnect"; @@ -48,10 +47,9 @@ void PrintDebuggerReadyMessage(int port, const std::string& id) { fprintf(stderr, "Debugger listening on port %d.\n" "Warning: This is an experimental feature and could change at any time.\n" "To start debugging, open the following URL in Chrome:\n" - " chrome-devtools://devtools/remote/serve_file/" - "@" V8_INSPECTOR_REVISION "/inspector.html?" + " chrome-devtools://devtools/bundled/inspector.html?" "experiments=true&v8only=true&ws=%s\n", - port, GetWsUrl(port, id).c_str()); + port, GetWsUrl(port, id).c_str()); fflush(stderr); } @@ -170,8 +168,40 @@ std::string GenerateID() { buffer[7]); return uuid; } -} // namespace +std::string StringViewToUtf8(const StringView& view) { + if (view.is8Bit()) { + return std::string(reinterpret_cast(view.characters8()), + view.length()); + } + const uint16_t* source = view.characters16(); + const UChar* unicodeSource = reinterpret_cast(source); + static_assert(sizeof(*source) == sizeof(*unicodeSource), + "sizeof(*source) == sizeof(*unicodeSource)"); + + size_t result_length = view.length() * sizeof(*source); + std::string result(result_length, '\0'); + UnicodeString utf16(unicodeSource, view.length()); + // ICU components for std::string compatibility are not enabled in build... + bool done = false; + while (!done) { + CheckedArrayByteSink sink(&result[0], result_length); + utf16.toUTF8(sink); + result_length = sink.NumberOfBytesAppended(); + result.resize(result_length); + done = !sink.Overflowed(); + } + return result; +} + +std::unique_ptr Utf8ToStringView(const char* source, + size_t length) { + UnicodeString utf16 = UnicodeString::fromUTF8(StringPiece(source, length)); + StringView view(reinterpret_cast(utf16.getBuffer()), + utf16.length()); + return StringBuffer::create(view); +} +} // namespace class V8NodeInspector; @@ -193,7 +223,8 @@ class AgentImpl { v8::Local message); private: - using MessageQueue = std::vector>; + using MessageQueue = + std::vector>>; enum class State { kNew, kAccepting, kConnected, kDone, kError }; static void ThreadCbIO(void* agent); @@ -211,11 +242,11 @@ class AgentImpl { const uv_buf_t* b); void SetConnected(bool connected); void DispatchMessages(); - void Write(int session_id, const String16& message); + void Write(int session_id, const StringView& message); bool AppendMessage(MessageQueue* vector, int session_id, - const String16& message); + std::unique_ptr buffer); void SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2); - void PostIncomingMessage(const String16& message); + void PostIncomingMessage(const char* message, size_t len); void WaitForFrontendMessage(); void NotifyMessageReceived(); State ToState(State state); @@ -279,22 +310,22 @@ class DispatchOnInspectorBackendTask : public v8::Task { AgentImpl* agent_; }; -class ChannelImpl final : public blink::protocol::FrontendChannel { +class ChannelImpl final : public v8_inspector::V8Inspector::Channel { public: explicit ChannelImpl(AgentImpl* agent): agent_(agent) {} virtual ~ChannelImpl() {} private: - void sendProtocolResponse(int callId, const String16& message) override { + void sendProtocolResponse(int callId, const StringView& message) override { sendMessageToFrontend(message); } - void sendProtocolNotification(const String16& message) override { + void sendProtocolNotification(const StringView& message) override { sendMessageToFrontend(message); } void flushProtocolNotifications() override { } - void sendMessageToFrontend(const String16& message) { + void sendMessageToFrontend(const StringView& message) { agent_->Write(agent_->frontend_session_id_, message); } @@ -316,8 +347,10 @@ class V8NodeInspector : public v8_inspector::V8InspectorClient { terminated_(false), running_nested_loop_(false), inspector_(V8Inspector::create(env->isolate(), this)) { - inspector_->contextCreated( - v8_inspector::V8ContextInfo(env->context(), 1, "NodeJS Main Context")); + const uint8_t CONTEXT_NAME[] = "Node.js Main Context"; + StringView context_name(CONTEXT_NAME, sizeof(CONTEXT_NAME) - 1); + v8_inspector::V8ContextInfo info(env->context(), 1, context_name); + inspector_->contextCreated(info); } void runMessageLoopOnPause(int context_group_id) override { @@ -343,14 +376,14 @@ class V8NodeInspector : public v8_inspector::V8InspectorClient { } void connectFrontend() { - session_ = inspector_->connect(1, new ChannelImpl(agent_), nullptr); + session_ = inspector_->connect(1, new ChannelImpl(agent_), StringView()); } void disconnectFrontend() { session_.reset(); } - void dispatchMessageFromFrontend(const String16& message) { + void dispatchMessageFromFrontend(const StringView& message) { CHECK(session_); session_->dispatchProtocolMessage(message); } @@ -530,15 +563,16 @@ void AgentImpl::InstallInspectorOnProcess() { env->SetMethod(inspector, "wrapConsoleCall", InspectorWrapConsoleCall); } -String16 ToProtocolString(v8::Local value) { +std::unique_ptr ToProtocolString(v8::Local value) { if (value.IsEmpty() || value->IsNull() || value->IsUndefined() || !value->IsString()) { - return String16(); + return StringBuffer::create(StringView()); } v8::Local string_value = v8::Local::Cast(value); - std::basic_string buffer(string_value->Length(), '\0'); - string_value->Write(&buffer[0], 0, string_value->Length()); - return String16(buffer); + size_t len = string_value->Length(); + std::basic_string buffer(len, '\0'); + string_value->Write(&buffer[0], 0, len); + return StringBuffer::create(StringView(buffer.data(), len)); } void AgentImpl::FatalException(v8::Local error, @@ -549,23 +583,26 @@ void AgentImpl::FatalException(v8::Local error, v8::Local context = env->context(); int script_id = message->GetScriptOrigin().ScriptID()->Value(); - std::unique_ptr stack_trace = - inspector_->inspector()->createStackTrace(message->GetStackTrace()); - if (stack_trace && !stack_trace->isEmpty() && - String16::fromInteger(script_id) == stack_trace->topScriptId()) { + v8::Local stack_trace = message->GetStackTrace(); + + if (!stack_trace.IsEmpty() && + stack_trace->GetFrameCount() > 0 && + script_id == stack_trace->GetFrame(0)->GetScriptId()) { script_id = 0; } + const uint8_t DETAILS[] = "Uncaught"; + inspector_->inspector()->exceptionThrown( context, - "Uncaught", + StringView(DETAILS, sizeof(DETAILS) - 1), error, - ToProtocolString(message->Get()), - ToProtocolString(message->GetScriptResourceName()), + ToProtocolString(message->Get())->string(), + ToProtocolString(message->GetScriptResourceName())->string(), message->GetLineNumber(context).FromMaybe(0), message->GetStartColumn(context).FromMaybe(0), - std::move(stack_trace), + inspector_->inspector()->createStackTrace(stack_trace), script_id); WaitForDisconnect(); } @@ -614,23 +651,24 @@ void AgentImpl::OnRemoteDataIO(InspectorSocket* socket, ssize_t read, const uv_buf_t* buf) { if (read > 0) { - String16 str = String16::fromUTF8(buf->base, read); // TODO(pfeldman): Instead of blocking execution while debugger // engages, node should wait for the run callback from the remote client // and initiate its startup. This is a change to node.cc that should be // upstreamed separately. - if (wait_&& str.find("\"Runtime.runIfWaitingForDebugger\"") - != std::string::npos) { - wait_ = false; - uv_sem_post(&start_sem_); + if (wait_) { + std::string message(buf->base, read); + if (message.find("\"Runtime.runIfWaitingForDebugger\"") != + std::string::npos) { + wait_ = false; + uv_sem_post(&start_sem_); + } } - PostIncomingMessage(str); + PostIncomingMessage(buf->base, read); } else { // EOF if (client_socket_ == socket) { - String16 message(TAG_DISCONNECT, sizeof(TAG_DISCONNECT) - 1); client_socket_ = nullptr; - PostIncomingMessage(message); + PostIncomingMessage(TAG_DISCONNECT, sizeof(TAG_DISCONNECT) - 1); } DisconnectAndDisposeIO(socket); } @@ -656,8 +694,7 @@ void AgentImpl::SendTargentsListResponse(InspectorSocket* socket) { std::string address = GetWsUrl(port_, id_); std::ostringstream frontend_url; - frontend_url << "https://chrome-devtools-frontend.appspot.com/serve_file/@"; - frontend_url << V8_INSPECTOR_REVISION; + frontend_url << "chrome-devtools://devtools/bundled"; frontend_url << "/inspector.html?experiments=true&v8only=true&ws="; frontend_url << address; @@ -699,8 +736,9 @@ void AgentImpl::WriteCbIO(uv_async_t* async) { agent->SwapBehindLock(&agent->outgoing_message_queue_, &outgoing_messages); for (const MessageQueue::value_type& outgoing : outgoing_messages) { if (outgoing.first == agent->frontend_session_id_) { - std::string message = outgoing.second.utf8(); - inspector_write(socket, message.c_str(), message.length()); + StringView message = outgoing.second->string(); + std::string utf8Message = StringViewToUtf8(message); + inspector_write(socket, utf8Message.c_str(), utf8Message.length()); } } } @@ -752,10 +790,10 @@ void AgentImpl::WorkerRunIO() { } bool AgentImpl::AppendMessage(MessageQueue* queue, int session_id, - const String16& message) { + std::unique_ptr buffer) { Mutex::ScopedLock scoped_lock(state_lock_); bool trigger_pumping = queue->empty(); - queue->push_back(std::make_pair(session_id, message)); + queue->push_back(std::make_pair(session_id, std::move(buffer))); return trigger_pumping; } @@ -764,8 +802,9 @@ void AgentImpl::SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2) { vector1->swap(*vector2); } -void AgentImpl::PostIncomingMessage(const String16& message) { - if (AppendMessage(&incoming_message_queue_, frontend_session_id_, message)) { +void AgentImpl::PostIncomingMessage(const char* message, size_t len) { + if (AppendMessage(&incoming_message_queue_, frontend_session_id_, + Utf8ToStringView(message, len))) { v8::Isolate* isolate = parent_env_->isolate(); platform_->CallOnForegroundThread(isolate, new DispatchOnInspectorBackendTask(this)); @@ -794,7 +833,7 @@ void AgentImpl::OnInspectorConnectionIO(InspectorSocket* socket) { client_socket_ = socket; inspector_read_start(socket, OnBufferAlloc, DataCallback); frontend_session_id_++; - PostIncomingMessage(String16(TAG_CONNECT, sizeof(TAG_CONNECT) - 1)); + PostIncomingMessage(TAG_CONNECT, sizeof(TAG_CONNECT) - 1); } void AgentImpl::DispatchMessages() { @@ -810,14 +849,20 @@ void AgentImpl::DispatchMessages() { tasks.clear(); SwapBehindLock(&incoming_message_queue_, &tasks); for (const MessageQueue::value_type& pair : tasks) { - const String16& message = pair.second; - if (message == TAG_CONNECT) { + StringView message = pair.second->string(); + std::string tag; + if (message.length() == sizeof(TAG_CONNECT) - 1 || + message.length() == sizeof(TAG_DISCONNECT) - 1) { + tag = StringViewToUtf8(message); + } + + if (tag == TAG_CONNECT) { CHECK_EQ(State::kAccepting, state_); backend_session_id_++; state_ = State::kConnected; fprintf(stderr, "Debugger attached.\n"); inspector_->connectFrontend(); - } else if (message == TAG_DISCONNECT) { + } else if (tag == TAG_DISCONNECT) { CHECK_EQ(State::kConnected, state_); if (shutting_down_) { state_ = State::kDone; @@ -836,8 +881,9 @@ void AgentImpl::DispatchMessages() { dispatching_messages_ = false; } -void AgentImpl::Write(int session_id, const String16& message) { - AppendMessage(&outgoing_message_queue_, session_id, message); +void AgentImpl::Write(int session_id, const StringView& inspector_message) { + AppendMessage(&outgoing_message_queue_, session_id, + StringBuffer::create(inspector_message)); int err = uv_async_send(&io_thread_req_); CHECK_EQ(0, err); } diff --git a/test/inspector/test-inspector.js b/test/inspector/test-inspector.js index eba4a0fc05dac2..d3d0bbd55923c1 100644 --- a/test/inspector/test-inspector.js +++ b/test/inspector/test-inspector.js @@ -173,6 +173,26 @@ function testNoUrlsWhenConnected(session) { }); } +function testI18NCharacters(session) { + console.log('[test]', 'Verify sending and receiving UTF8 characters'); + const chars = 'טֶ字и'; + session.sendInspectorCommands([ + { + 'method': 'Debugger.evaluateOnCallFrame', 'params': { + 'callFrameId': '{"ordinal":0,"injectedScriptId":1}', + 'expression': 'console.log("' + chars + '")', + 'objectGroup': 'console', + 'includeCommandLineAPI': true, + 'silent': false, + 'returnByValue': false, + 'generatePreview': true + } + } + ]).expectMessages([ + setupExpectConsoleOutput('log', [chars]), + ]); +} + function testWaitsForFrontendDisconnect(session, harness) { console.log('[test]', 'Verify node waits for the frontend to disconnect'); session.sendInspectorCommands({ 'method': 'Debugger.resume'}) @@ -193,6 +213,7 @@ function runTests(harness) { testBreakpointOnStart, testSetBreakpointAndResume, testInspectScope, + testI18NCharacters, testWaitsForFrontendDisconnect ]).expectShutDown(55); }