diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-02-14 11:27:26 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-02-22 15:55:42 +0100 |
commit | 7a77daf24344db7942e34c962b0f1ee729ab7af5 (patch) | |
tree | e7cbe7bf4e2f4b802a8f5bc18336c546cd6a0d7f /deps/v8/src/inspector | |
parent | 5f08871ee93ea739148cc49e0f7679e33c70295a (diff) | |
download | android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.gz android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.tar.bz2 android-node-v8-7a77daf24344db7942e34c962b0f1ee729ab7af5.zip |
deps: update V8 to 5.6.326.55
PR-URL: https://github.com/nodejs/node/pull/10992
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/inspector')
40 files changed, 1477 insertions, 1624 deletions
diff --git a/deps/v8/src/inspector/BUILD.gn b/deps/v8/src/inspector/BUILD.gn index 15c090ff22..6ebb91ccbc 100644 --- a/deps/v8/src/inspector/BUILD.gn +++ b/deps/v8/src/inspector/BUILD.gn @@ -4,7 +4,7 @@ import("../../gni/v8.gni") -_inspector_protocol = "//third_party/WebKit/Source/platform/inspector_protocol" +_inspector_protocol = v8_path_prefix + "/third_party/inspector_protocol" import("$_inspector_protocol/inspector_protocol.gni") _protocol_generated = [ @@ -51,6 +51,7 @@ inspector_protocol_generate("protocol_generated_sources") { ":protocol_compatibility", ] + inspector_protocol_dir = _inspector_protocol out_dir = target_gen_dir config_file = "inspector_protocol_config.json" inputs = [ diff --git a/deps/v8/src/inspector/DEPS b/deps/v8/src/inspector/DEPS index 4486204d74..d49c6a6254 100644 --- a/deps/v8/src/inspector/DEPS +++ b/deps/v8/src/inspector/DEPS @@ -1,8 +1,11 @@ include_rules = [ "-src", - "+src/inspector", "+src/base/atomicops.h", "+src/base/macros.h", "+src/base/logging.h", "+src/base/platform/platform.h", + "+src/inspector", + "+src/tracing", + "-include/v8-debug.h", + "+src/debug/debug-interface.h", ] diff --git a/deps/v8/src/inspector/debugger-script.js b/deps/v8/src/inspector/debugger-script.js index 98910d69df..1614566ffa 100644 --- a/deps/v8/src/inspector/debugger-script.js +++ b/deps/v8/src/inspector/debugger-script.js @@ -33,18 +33,6 @@ var DebuggerScript = {}; -/** @enum */ -const PauseOnExceptionsState = { - DontPauseOnExceptions: 0, - PauseOnAllExceptions: 1, - PauseOnUncaughtExceptions: 2 -}; -DebuggerScript.PauseOnExceptionsState = PauseOnExceptionsState; - -DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions; -Debug.clearBreakOnException(); -Debug.clearBreakOnUncaughtException(); - /** * @param {?CompileEvent} eventData */ @@ -52,7 +40,7 @@ DebuggerScript.getAfterCompileScript = function(eventData) { var script = eventData.script().value(); if (!script.is_debugger_script) - return DebuggerScript._formatScript(eventData.script().value()); + return script; return null; } @@ -152,82 +140,6 @@ DebuggerScript._executionContextId = function(contextData) } /** - * @param {string|undefined} contextData - * @return {string} - */ -DebuggerScript._executionContextAuxData = function(contextData) -{ - if (!contextData) - return ""; - var match = contextData.match(/^[^,]*,[^,]*,(.*)$/); - return match ? match[1] : ""; -} - -/** - * @param {string} contextGroupId - * @return {!Array<!FormattedScript>} - */ -DebuggerScript.getScripts = function(contextGroupId) -{ - var result = []; - var scripts = Debug.scripts(); - var contextDataPrefix = null; - if (contextGroupId) - contextDataPrefix = contextGroupId + ","; - for (var i = 0; i < scripts.length; ++i) { - var script = scripts[i]; - if (contextDataPrefix) { - if (!script.context_data) - continue; - // Context data is a string in the following format: - // <contextGroupId>,<contextId>,<auxData> - if (script.context_data.indexOf(contextDataPrefix) !== 0) - continue; - } - if (script.is_debugger_script) - continue; - result.push(DebuggerScript._formatScript(script)); - } - return result; -} - -/** - * @param {!Script} script - * @return {!FormattedScript} - */ -DebuggerScript._formatScript = function(script) -{ - var lineEnds = script.line_ends; - var lineCount = lineEnds.length; - var endLine = script.line_offset + lineCount - 1; - var endColumn; - // V8 will not count last line if script source ends with \n. - if (script.source[script.source.length - 1] === '\n') { - endLine += 1; - endColumn = 0; - } else { - if (lineCount === 1) - endColumn = script.source.length + script.column_offset; - else - endColumn = script.source.length - (lineEnds[lineCount - 2] + 1); - } - return { - id: script.id, - name: script.nameOrSourceURL(), - sourceURL: script.source_url, - sourceMappingURL: script.source_mapping_url, - source: script.source, - startLine: script.line_offset, - startColumn: script.column_offset, - endLine: endLine, - endColumn: endColumn, - executionContextId: DebuggerScript._executionContextId(script.context_data), - // Note that we cannot derive aux data from context id because of compilation cache. - executionContextAuxData: DebuggerScript._executionContextAuxData(script.context_data) - }; -} - -/** * @param {!ExecutionState} execState * @param {!BreakpointInfo} info * @return {string|undefined} @@ -253,32 +165,6 @@ DebuggerScript.removeBreakpoint = function(execState, info) } /** - * @return {number} - */ -DebuggerScript.pauseOnExceptionsState = function() -{ - return DebuggerScript._pauseOnExceptionsState; -} - -/** - * @param {number} newState - */ -DebuggerScript.setPauseOnExceptionsState = function(newState) -{ - DebuggerScript._pauseOnExceptionsState = newState; - - if (DebuggerScript.PauseOnExceptionsState.PauseOnAllExceptions === newState) - Debug.setBreakOnException(); - else - Debug.clearBreakOnException(); - - if (DebuggerScript.PauseOnExceptionsState.PauseOnUncaughtExceptions === newState) - Debug.setBreakOnUncaughtException(); - else - Debug.clearBreakOnUncaughtException(); -} - -/** * @param {!ExecutionState} execState * @param {number} limit * @return {!Array<!JavaScriptCallFrame>} @@ -291,43 +177,6 @@ DebuggerScript.currentCallFrames = function(execState, limit) return frames; } -/** - * @param {!ExecutionState} execState - */ -DebuggerScript.stepIntoStatement = function(execState) -{ - execState.prepareStep(Debug.StepAction.StepIn); -} - -/** - * @param {!ExecutionState} execState - */ -DebuggerScript.stepFrameStatement = function(execState) -{ - execState.prepareStep(Debug.StepAction.StepFrame); -} - -/** - * @param {!ExecutionState} execState - */ -DebuggerScript.stepOverStatement = function(execState) -{ - execState.prepareStep(Debug.StepAction.StepNext); -} - -/** - * @param {!ExecutionState} execState - */ -DebuggerScript.stepOutOfFunction = function(execState) -{ - execState.prepareStep(Debug.StepAction.StepOut); -} - -DebuggerScript.clearStepping = function() -{ - Debug.clearStepping(); -} - // Returns array in form: // [ 0, <v8_result_report> ] in case of success // or [ 1, <general_error_message>, <compiler_message>, <line_number>, <column_number> ] in case of compile error, numbers are 1-based. @@ -416,6 +265,7 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror) var frameDetails = frameMirror.details(); var funcObject = frameDetails.func(); + var scriptObject = frameDetails.script(); var sourcePosition = frameDetails.sourcePosition(); var thisObject = frameDetails.receiver(); @@ -448,6 +298,7 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror) // Calculated lazily. var scopeChain; var funcMirror; + var scriptMirror; var location; /** @type {!Array<?RawLocation>} */ var scopeStartLocations; @@ -516,7 +367,7 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror) { if (!details) { var scopeObjects = ensureScopeChain(); - var script = ensureFuncMirror().script(); + var script = ensureScriptMirror(); /** @type {!Array<Scope>} */ var scopes = []; for (var i = 0; i < scopeObjects.length; ++i) { @@ -570,14 +421,24 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror) } /** + * @return {!ScriptMirror} + */ + function ensureScriptMirror() + { + if (!scriptMirror) { + scriptMirror = MakeMirror(scriptObject); + } + return /** @type {!ScriptMirror} */(scriptMirror); + } + + /** * @return {!{line: number, column: number}} */ function ensureLocation() { if (!location) { - var script = ensureFuncMirror().script(); - if (script) - location = script.locationFromPosition(sourcePosition, true); + var script = ensureScriptMirror(); + location = script.locationFromPosition(sourcePosition, true); if (!location) location = { line: 0, column: 0 }; } @@ -616,12 +477,12 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror) } /** - * @return {number|undefined} + * @return {number} */ function sourceID() { - var script = ensureFuncMirror().script(); - return script && script.id(); + var script = ensureScriptMirror(); + return script.id(); } /** diff --git a/deps/v8/src/inspector/debugger_script_externs.js b/deps/v8/src/inspector/debugger_script_externs.js index c7df61f3f4..cc152d5537 100644 --- a/deps/v8/src/inspector/debugger_script_externs.js +++ b/deps/v8/src/inspector/debugger_script_externs.js @@ -44,7 +44,7 @@ var FormattedScript; var JavaScriptCallFrameDetails; /** @typedef {{ - sourceID: function():(number|undefined), + sourceID: function():(number), line: function():number, column: function():number, thisObject: !Object, @@ -61,19 +61,6 @@ var JavaScriptCallFrame; */ var Debug = {}; -Debug.setBreakOnException = function() {} - -Debug.clearBreakOnException = function() {} - -Debug.setBreakOnUncaughtException = function() {} - -/** - * @return {undefined} - */ -Debug.clearBreakOnUncaughtException = function() {} - -Debug.clearStepping = function() {} - Debug.clearAllBreakPoints = function() {} /** @return {!Array<!Script>} */ @@ -203,9 +190,6 @@ BreakEvent.prototype.breakPointsHit = function() {} /** @interface */ function ExecutionState() {} -/** @param {!Debug.StepAction} action */ -ExecutionState.prototype.prepareStep = function(action) {} - /** * @param {string} source * @param {boolean} disableBreak @@ -257,7 +241,6 @@ var SourceLocation; * source_mapping_url: (string|undefined), * is_debugger_script: boolean, * source: string, - * line_ends: !Array<number>, * line_offset: number, * column_offset: number, * nameOrSourceURL: function():string, @@ -288,6 +271,9 @@ FrameDetails.prototype.receiver = function() {} /** @return {function()} */ FrameDetails.prototype.func = function() {} +/** @return {!Object} */ +FrameDetails.prototype.script = function() {} + /** @return {boolean} */ FrameDetails.prototype.isAtReturn = function() {} @@ -466,6 +452,9 @@ FrameMirror.prototype.allScopes = function(ignoreNestedScopes) {} /** @return {!FrameDetails} */ FrameMirror.prototype.details = function() {} +/** @return {!ScriptMirror} */ +FrameMirror.prototype.script = function() {} + /** * @param {string} source * @param {boolean} disableBreak diff --git a/deps/v8/src/inspector/injected-script-source.js b/deps/v8/src/inspector/injected-script-source.js index 39c6c9c1e8..f3c8d6b96e 100644 --- a/deps/v8/src/inspector/injected-script-source.js +++ b/deps/v8/src/inspector/injected-script-source.js @@ -260,18 +260,6 @@ InjectedScript.prototype = { }, /** - * @param {!Array<*>} array - * @param {string} groupName - * @param {boolean} forceValueType - * @param {boolean} generatePreview - */ - wrapObjectsInArray: function(array, groupName, forceValueType, generatePreview) - { - for (var i = 0; i < array.length; ++i) - array[i] = this.wrapObject(array[i], groupName, forceValueType, generatePreview); - }, - - /** * @param {!Object} table * @param {!Array.<string>|string|boolean} columns * @return {!RuntimeAgent.RemoteObject} diff --git a/deps/v8/src/inspector/injected-script.cc b/deps/v8/src/inspector/injected-script.cc index a100dea2e1..d605227222 100644 --- a/deps/v8/src/inspector/injected-script.cc +++ b/deps/v8/src/inspector/injected-script.cc @@ -54,11 +54,6 @@ 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> InjectedScript::create( InspectedContext* inspectedContext) { v8::Isolate* isolate = inspectedContext->isolate(); @@ -124,10 +119,9 @@ InjectedScript::InjectedScript( InjectedScript::~InjectedScript() {} -void InjectedScript::getProperties( - ErrorString* errorString, v8::Local<v8::Object> object, - const String16& groupName, bool ownProperties, bool accessorPropertiesOnly, - bool generatePreview, +Response InjectedScript::getProperties( + v8::Local<v8::Object> object, const String16& groupName, bool ownProperties, + bool accessorPropertiesOnly, bool generatePreview, std::unique_ptr<Array<PropertyDescriptor>>* properties, Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { v8::HandleScope handles(m_context->isolate()); @@ -143,21 +137,23 @@ void InjectedScript::getProperties( v8::TryCatch tryCatch(m_context->isolate()); v8::Local<v8::Value> resultValue = function.callWithoutExceptionHandling(); if (tryCatch.HasCaught()) { - *exceptionDetails = createExceptionDetails(errorString, tryCatch, groupName, - generatePreview); + Response response = createExceptionDetails( + tryCatch, groupName, generatePreview, exceptionDetails); + if (!response.isSuccess()) return response; // FIXME: make properties optional *properties = Array<PropertyDescriptor>::create(); - return; + return Response::OK(); } - if (hasInternalError(errorString, resultValue.IsEmpty())) return; - std::unique_ptr<protocol::Value> protocolValue = - toProtocolValue(errorString, context, resultValue); - if (!protocolValue) return; - protocol::ErrorSupport errors(errorString); + if (resultValue.IsEmpty()) return Response::InternalError(); + std::unique_ptr<protocol::Value> protocolValue; + Response response = toProtocolValue(context, resultValue, &protocolValue); + if (!response.isSuccess()) return response; + protocol::ErrorSupport errors; std::unique_ptr<Array<PropertyDescriptor>> result = Array<PropertyDescriptor>::parse(protocolValue.get(), &errors); - if (!hasInternalError(errorString, errors.hasErrors())) - *properties = std::move(result); + if (errors.hasErrors()) return Response::Error(errors.errors()); + *properties = std::move(result); + return Response::OK(); } void InjectedScript::releaseObject(const String16& objectId) { @@ -172,55 +168,52 @@ void InjectedScript::releaseObject(const String16& objectId) { m_native->unbind(boundId); } -std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapObject( - ErrorString* errorString, v8::Local<v8::Value> value, - const String16& groupName, bool forceValueType, - bool generatePreview) const { +Response InjectedScript::wrapObject( + v8::Local<v8::Value> value, const String16& groupName, bool forceValueType, + bool generatePreview, + std::unique_ptr<protocol::Runtime::RemoteObject>* result) const { v8::HandleScope handles(m_context->isolate()); v8::Local<v8::Value> wrappedObject; v8::Local<v8::Context> context = m_context->context(); - if (!wrapValue(errorString, value, groupName, forceValueType, generatePreview) - .ToLocal(&wrappedObject)) - return nullptr; + Response response = wrapValue(value, groupName, forceValueType, + generatePreview, &wrappedObject); + if (!response.isSuccess()) return response; protocol::ErrorSupport errors; - std::unique_ptr<protocol::Value> protocolValue = - toProtocolValue(errorString, context, wrappedObject); - if (!protocolValue) return nullptr; - std::unique_ptr<protocol::Runtime::RemoteObject> remoteObject = + std::unique_ptr<protocol::Value> protocolValue; + response = toProtocolValue(context, wrappedObject, &protocolValue); + if (!response.isSuccess()) return response; + + *result = protocol::Runtime::RemoteObject::parse(protocolValue.get(), &errors); - if (!remoteObject) *errorString = errors.errors(); - return remoteObject; + if (!result->get()) return Response::Error(errors.errors()); + return Response::OK(); } -bool InjectedScript::wrapObjectProperty(ErrorString* errorString, - v8::Local<v8::Object> object, - v8::Local<v8::Name> key, - const String16& groupName, - bool forceValueType, - bool generatePreview) const { +Response InjectedScript::wrapObjectProperty(v8::Local<v8::Object> object, + v8::Local<v8::Name> key, + const String16& groupName, + bool forceValueType, + bool generatePreview) const { v8::Local<v8::Value> property; v8::Local<v8::Context> context = m_context->context(); - if (hasInternalError(errorString, - !object->Get(context, key).ToLocal(&property))) - return false; + if (!object->Get(context, key).ToLocal(&property)) + return Response::InternalError(); v8::Local<v8::Value> wrappedProperty; - if (!wrapValue(errorString, property, groupName, forceValueType, - generatePreview) - .ToLocal(&wrappedProperty)) - return false; + Response response = wrapValue(property, groupName, forceValueType, + generatePreview, &wrappedProperty); + if (!response.isSuccess()) return response; v8::Maybe<bool> success = createDataProperty(context, object, key, wrappedProperty); - if (hasInternalError(errorString, success.IsNothing() || !success.FromJust())) - return false; - return true; + if (success.IsNothing() || !success.FromJust()) + return Response::InternalError(); + return Response::OK(); } -bool InjectedScript::wrapPropertyInArray(ErrorString* errorString, - v8::Local<v8::Array> array, - v8::Local<v8::String> property, - const String16& groupName, - bool forceValueType, - bool generatePreview) const { +Response InjectedScript::wrapPropertyInArray(v8::Local<v8::Array> array, + v8::Local<v8::String> property, + const String16& groupName, + bool forceValueType, + bool generatePreview) const { V8FunctionCall function(m_context->inspector(), m_context->context(), v8Value(), "wrapPropertyInArray"); function.appendArgument(array); @@ -230,29 +223,13 @@ bool InjectedScript::wrapPropertyInArray(ErrorString* errorString, function.appendArgument(generatePreview); bool hadException = false; function.call(hadException); - return !hasInternalError(errorString, hadException); + return hadException ? Response::InternalError() : Response::OK(); } -bool InjectedScript::wrapObjectsInArray(ErrorString* errorString, - v8::Local<v8::Array> 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<v8::Value> InjectedScript::wrapValue( - ErrorString* errorString, v8::Local<v8::Value> value, - const String16& groupName, bool forceValueType, - bool generatePreview) const { +Response InjectedScript::wrapValue(v8::Local<v8::Value> value, + const String16& groupName, + bool forceValueType, bool generatePreview, + v8::Local<v8::Value>* result) const { V8FunctionCall function(m_context->inspector(), m_context->context(), v8Value(), "wrapObject"); function.appendArgument(value); @@ -260,10 +237,9 @@ v8::MaybeLocal<v8::Value> InjectedScript::wrapValue( function.appendArgument(forceValueType); function.appendArgument(generatePreview); bool hadException = false; - v8::Local<v8::Value> r = function.call(hadException); - if (hasInternalError(errorString, hadException || r.IsEmpty())) - return v8::MaybeLocal<v8::Value>(); - return r; + *result = function.call(hadException); + if (hadException || result->IsEmpty()) return Response::InternalError(); + return Response::OK(); } std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable( @@ -280,21 +256,19 @@ std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable( bool hadException = false; v8::Local<v8::Value> r = function.call(hadException); if (hadException || r.IsEmpty()) return nullptr; - protocol::ErrorString errorString; - std::unique_ptr<protocol::Value> protocolValue = - toProtocolValue(&errorString, context, r); - if (!protocolValue) return nullptr; + std::unique_ptr<protocol::Value> protocolValue; + Response response = toProtocolValue(context, r, &protocolValue); + if (!response.isSuccess()) return nullptr; protocol::ErrorSupport errors; return protocol::Runtime::RemoteObject::parse(protocolValue.get(), &errors); } -bool InjectedScript::findObject(ErrorString* errorString, - const RemoteObjectId& objectId, - v8::Local<v8::Value>* outObject) const { +Response InjectedScript::findObject(const RemoteObjectId& objectId, + v8::Local<v8::Value>* outObject) const { *outObject = m_native->objectForId(objectId.id()); if (outObject->IsEmpty()) - *errorString = "Could not find object with given id"; - return !outObject->IsEmpty(); + return Response::Error("Could not find object with given id"); + return Response::OK(); } String16 InjectedScript::objectGroupName(const RemoteObjectId& objectId) const { @@ -326,47 +300,41 @@ v8::Local<v8::Value> InjectedScript::lastEvaluationResult() const { return m_lastEvaluationResult.Get(m_context->isolate()); } -v8::MaybeLocal<v8::Value> InjectedScript::resolveCallArgument( - ErrorString* errorString, protocol::Runtime::CallArgument* callArgument) { +Response InjectedScript::resolveCallArgument( + protocol::Runtime::CallArgument* callArgument, + v8::Local<v8::Value>* result) { if (callArgument->hasObjectId()) { - std::unique_ptr<RemoteObjectId> remoteObjectId = - RemoteObjectId::parse(errorString, callArgument->getObjectId("")); - if (!remoteObjectId) return v8::MaybeLocal<v8::Value>(); - if (remoteObjectId->contextId() != m_context->contextId()) { - *errorString = + std::unique_ptr<RemoteObjectId> remoteObjectId; + Response response = + RemoteObjectId::parse(callArgument->getObjectId(""), &remoteObjectId); + if (!response.isSuccess()) return response; + if (remoteObjectId->contextId() != m_context->contextId()) + return Response::Error( "Argument should belong to the same JavaScript world as target " - "object"; - return v8::MaybeLocal<v8::Value>(); - } - v8::Local<v8::Value> object; - if (!findObject(errorString, *remoteObjectId, &object)) - return v8::MaybeLocal<v8::Value>(); - return object; + "object"); + return findObject(*remoteObjectId, result); } if (callArgument->hasValue() || callArgument->hasUnserializableValue()) { String16 value = callArgument->hasValue() ? callArgument->getValue(nullptr)->toJSONString() : "Number(\"" + callArgument->getUnserializableValue("") + "\")"; - v8::Local<v8::Value> 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<v8::Value>(); + .ToLocal(result)) { + return Response::Error("Couldn't parse value object in call argument"); } - return object; + return Response::OK(); } - return v8::Undefined(m_context->isolate()); + *result = v8::Undefined(m_context->isolate()); + return Response::OK(); } -std::unique_ptr<protocol::Runtime::ExceptionDetails> -InjectedScript::createExceptionDetails(ErrorString* errorString, - const v8::TryCatch& tryCatch, - const String16& objectGroup, - bool generatePreview) { - if (!tryCatch.HasCaught()) return nullptr; +Response InjectedScript::createExceptionDetails( + const v8::TryCatch& tryCatch, const String16& objectGroup, + bool generatePreview, Maybe<protocol::Runtime::ExceptionDetails>* result) { + if (!tryCatch.HasCaught()) return Response::InternalError(); v8::Local<v8::Message> message = tryCatch.Message(); v8::Local<v8::Value> exception = tryCatch.Exception(); String16 messageText = @@ -396,43 +364,44 @@ InjectedScript::createExceptionDetails(ErrorString* errorString, ->buildInspectorObjectImpl()); } if (!exception.IsEmpty()) { - std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = wrapObject( - errorString, exception, objectGroup, false /* forceValueType */, - generatePreview && !exception->IsNativeError()); - if (!wrapped) return nullptr; + std::unique_ptr<protocol::Runtime::RemoteObject> wrapped; + Response response = + wrapObject(exception, objectGroup, false /* forceValueType */, + generatePreview && !exception->IsNativeError(), &wrapped); + if (!response.isSuccess()) return response; exceptionDetails->setException(std::move(wrapped)); } - return exceptionDetails; + *result = std::move(exceptionDetails); + return Response::OK(); } -void InjectedScript::wrapEvaluateResult( - ErrorString* errorString, v8::MaybeLocal<v8::Value> maybeResultValue, - const v8::TryCatch& tryCatch, const String16& objectGroup, - bool returnByValue, bool generatePreview, +Response InjectedScript::wrapEvaluateResult( + v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch& tryCatch, + const String16& objectGroup, bool returnByValue, bool generatePreview, std::unique_ptr<protocol::Runtime::RemoteObject>* result, Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { v8::Local<v8::Value> resultValue; if (!tryCatch.HasCaught()) { - if (hasInternalError(errorString, !maybeResultValue.ToLocal(&resultValue))) - return; - std::unique_ptr<RemoteObject> remoteObject = wrapObject( - errorString, resultValue, objectGroup, returnByValue, generatePreview); - if (!remoteObject) return; + if (!maybeResultValue.ToLocal(&resultValue)) + return Response::InternalError(); + Response response = wrapObject(resultValue, objectGroup, returnByValue, + generatePreview, result); + if (!response.isSuccess()) return response; if (objectGroup == "console") m_lastEvaluationResult.Reset(m_context->isolate(), resultValue); - *result = std::move(remoteObject); } else { v8::Local<v8::Value> exception = tryCatch.Exception(); - std::unique_ptr<RemoteObject> remoteObject = - wrapObject(errorString, exception, objectGroup, false, - generatePreview && !exception->IsNativeError()); - if (!remoteObject) return; + Response response = + wrapObject(exception, objectGroup, false, + generatePreview && !exception->IsNativeError(), result); + if (!response.isSuccess()) return response; // 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); + response = createExceptionDetails(tryCatch, objectGroup, generatePreview, + exceptionDetails); + if (!response.isSuccess()) return response; } + return Response::OK(); } v8::Local<v8::Object> InjectedScript::commandLineAPI() { @@ -442,41 +411,35 @@ v8::Local<v8::Object> InjectedScript::commandLineAPI() { return m_commandLineAPI.Get(m_context->isolate()); } -InjectedScript::Scope::Scope(ErrorString* errorString, - V8InspectorImpl* inspector, int contextGroupId) - : m_errorString(errorString), - m_inspector(inspector), +InjectedScript::Scope::Scope(V8InspectorImpl* inspector, int contextGroupId) + : 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_previousPauseOnExceptionsState(v8::DebugInterface::NoBreakOnException), m_userGesture(false) {} -bool InjectedScript::Scope::initialize() { +Response 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; + if (!session) return Response::InternalError(); + Response response = findInjectedScript(session); + if (!response.isSuccess()) return response; m_context = m_injectedScript->context()->context(); m_context->Enter(); - return true; + return Response::OK(); } -bool InjectedScript::Scope::installCommandLineAPI() { +void 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() { @@ -485,14 +448,14 @@ void InjectedScript::Scope::ignoreExceptionsAndMuteConsole() { m_inspector->client()->muteMetrics(m_contextGroupId); m_inspector->muteExceptions(m_contextGroupId); m_previousPauseOnExceptionsState = - setPauseOnExceptionsState(V8Debugger::DontPauseOnExceptions); + setPauseOnExceptionsState(v8::DebugInterface::NoBreakOnException); } -V8Debugger::PauseOnExceptionsState +v8::DebugInterface::ExceptionBreakState InjectedScript::Scope::setPauseOnExceptionsState( - V8Debugger::PauseOnExceptionsState newState) { + v8::DebugInterface::ExceptionBreakState newState) { if (!m_inspector->debugger()->enabled()) return newState; - V8Debugger::PauseOnExceptionsState presentState = + v8::DebugInterface::ExceptionBreakState presentState = m_inspector->debugger()->getPauseOnExceptionsState(); if (presentState != newState) m_inspector->debugger()->setPauseOnExceptionsState(newState); @@ -523,59 +486,57 @@ InjectedScript::Scope::~Scope() { cleanup(); } -InjectedScript::ContextScope::ContextScope(ErrorString* errorString, - V8InspectorImpl* inspector, +InjectedScript::ContextScope::ContextScope(V8InspectorImpl* inspector, int contextGroupId, int executionContextId) - : InjectedScript::Scope(errorString, inspector, contextGroupId), + : InjectedScript::Scope(inspector, contextGroupId), m_executionContextId(executionContextId) {} InjectedScript::ContextScope::~ContextScope() {} -void InjectedScript::ContextScope::findInjectedScript( +Response InjectedScript::ContextScope::findInjectedScript( V8InspectorSessionImpl* session) { - m_injectedScript = - session->findInjectedScript(m_errorString, m_executionContextId); + return session->findInjectedScript(m_executionContextId, m_injectedScript); } -InjectedScript::ObjectScope::ObjectScope(ErrorString* errorString, - V8InspectorImpl* inspector, +InjectedScript::ObjectScope::ObjectScope(V8InspectorImpl* inspector, int contextGroupId, const String16& remoteObjectId) - : InjectedScript::Scope(errorString, inspector, contextGroupId), + : InjectedScript::Scope(inspector, contextGroupId), m_remoteObjectId(remoteObjectId) {} InjectedScript::ObjectScope::~ObjectScope() {} -void InjectedScript::ObjectScope::findInjectedScript( +Response InjectedScript::ObjectScope::findInjectedScript( V8InspectorSessionImpl* session) { - std::unique_ptr<RemoteObjectId> remoteId = - RemoteObjectId::parse(m_errorString, m_remoteObjectId); - if (!remoteId) return; - InjectedScript* injectedScript = - session->findInjectedScript(m_errorString, remoteId.get()); - if (!injectedScript) return; + std::unique_ptr<RemoteObjectId> remoteId; + Response response = RemoteObjectId::parse(m_remoteObjectId, &remoteId); + if (!response.isSuccess()) return response; + InjectedScript* injectedScript = nullptr; + response = session->findInjectedScript(remoteId.get(), injectedScript); + if (!response.isSuccess()) return response; m_objectGroupName = injectedScript->objectGroupName(*remoteId); - if (!injectedScript->findObject(m_errorString, *remoteId, &m_object)) return; + response = injectedScript->findObject(*remoteId, &m_object); + if (!response.isSuccess()) return response; m_injectedScript = injectedScript; + return Response::OK(); } -InjectedScript::CallFrameScope::CallFrameScope(ErrorString* errorString, - V8InspectorImpl* inspector, +InjectedScript::CallFrameScope::CallFrameScope(V8InspectorImpl* inspector, int contextGroupId, const String16& remoteObjectId) - : InjectedScript::Scope(errorString, inspector, contextGroupId), + : InjectedScript::Scope(inspector, contextGroupId), m_remoteCallFrameId(remoteObjectId) {} InjectedScript::CallFrameScope::~CallFrameScope() {} -void InjectedScript::CallFrameScope::findInjectedScript( +Response InjectedScript::CallFrameScope::findInjectedScript( V8InspectorSessionImpl* session) { - std::unique_ptr<RemoteCallFrameId> remoteId = - RemoteCallFrameId::parse(m_errorString, m_remoteCallFrameId); - if (!remoteId) return; + std::unique_ptr<RemoteCallFrameId> remoteId; + Response response = RemoteCallFrameId::parse(m_remoteCallFrameId, &remoteId); + if (!response.isSuccess()) return response; m_frameOrdinal = static_cast<size_t>(remoteId->frameOrdinal()); - m_injectedScript = session->findInjectedScript(m_errorString, remoteId.get()); + return session->findInjectedScript(remoteId.get(), m_injectedScript); } } // namespace v8_inspector diff --git a/deps/v8/src/inspector/injected-script.h b/deps/v8/src/inspector/injected-script.h index 9b324c948d..6500f4dbb7 100644 --- a/deps/v8/src/inspector/injected-script.h +++ b/deps/v8/src/inspector/injected-script.h @@ -48,8 +48,8 @@ class V8FunctionCall; class V8InspectorImpl; class V8InspectorSessionImpl; -using protocol::ErrorString; using protocol::Maybe; +using protocol::Response; class InjectedScript final { public: @@ -58,56 +58,51 @@ class InjectedScript final { InspectedContext* context() const { return m_context; } - void getProperties( - ErrorString*, v8::Local<v8::Object>, const String16& groupName, - bool ownProperties, bool accessorPropertiesOnly, bool generatePreview, + Response getProperties( + v8::Local<v8::Object>, const String16& groupName, bool ownProperties, + bool accessorPropertiesOnly, bool generatePreview, std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>* result, Maybe<protocol::Runtime::ExceptionDetails>*); void releaseObject(const String16& objectId); - std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject( - ErrorString*, v8::Local<v8::Value>, const String16& groupName, - bool forceValueType = false, bool generatePreview = false) const; - bool wrapObjectProperty(ErrorString*, v8::Local<v8::Object>, - v8::Local<v8::Name> key, const String16& groupName, - bool forceValueType = false, - bool generatePreview = false) const; - bool wrapPropertyInArray(ErrorString*, v8::Local<v8::Array>, - v8::Local<v8::String> property, - const String16& groupName, - bool forceValueType = false, - bool generatePreview = false) const; - bool wrapObjectsInArray(ErrorString*, v8::Local<v8::Array>, - const String16& groupName, - bool forceValueType = false, - bool generatePreview = false) const; + Response wrapObject( + v8::Local<v8::Value>, const String16& groupName, bool forceValueType, + bool generatePreview, + std::unique_ptr<protocol::Runtime::RemoteObject>* result) const; + Response wrapObjectProperty(v8::Local<v8::Object>, v8::Local<v8::Name> key, + const String16& groupName, + bool forceValueType = false, + bool generatePreview = false) const; + Response wrapPropertyInArray(v8::Local<v8::Array>, + v8::Local<v8::String> property, + const String16& groupName, + bool forceValueType = false, + bool generatePreview = false) const; std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable( v8::Local<v8::Value> table, v8::Local<v8::Value> columns) const; - bool findObject(ErrorString*, const RemoteObjectId&, - v8::Local<v8::Value>*) const; + Response findObject(const RemoteObjectId&, v8::Local<v8::Value>*) const; String16 objectGroupName(const RemoteObjectId&) const; void releaseObjectGroup(const String16&); void setCustomObjectFormatterEnabled(bool); - v8::MaybeLocal<v8::Value> resolveCallArgument( - ErrorString*, protocol::Runtime::CallArgument*); - - std::unique_ptr<protocol::Runtime::ExceptionDetails> createExceptionDetails( - ErrorString*, const v8::TryCatch&, const String16& groupName, - bool generatePreview); - void wrapEvaluateResult( - ErrorString*, v8::MaybeLocal<v8::Value> maybeResultValue, - const v8::TryCatch&, const String16& objectGroup, bool returnByValue, - bool generatePreview, + Response resolveCallArgument(protocol::Runtime::CallArgument*, + v8::Local<v8::Value>* result); + + Response createExceptionDetails( + const v8::TryCatch&, const String16& groupName, bool generatePreview, + Maybe<protocol::Runtime::ExceptionDetails>* result); + Response wrapEvaluateResult( + v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch&, + const String16& objectGroup, bool returnByValue, bool generatePreview, std::unique_ptr<protocol::Runtime::RemoteObject>* result, Maybe<protocol::Runtime::ExceptionDetails>*); v8::Local<v8::Value> lastEvaluationResult() const; class Scope { public: - bool initialize(); - bool installCommandLineAPI(); + Response initialize(); + void installCommandLineAPI(); void ignoreExceptionsAndMuteConsole(); void pretendUserGesture(); v8::Local<v8::Context> context() const { return m_context; } @@ -115,37 +110,35 @@ class InjectedScript final { const v8::TryCatch& tryCatch() const { return m_tryCatch; } protected: - Scope(ErrorString*, V8InspectorImpl*, int contextGroupId); + Scope(V8InspectorImpl*, int contextGroupId); virtual ~Scope(); - virtual void findInjectedScript(V8InspectorSessionImpl*) = 0; + virtual Response findInjectedScript(V8InspectorSessionImpl*) = 0; - ErrorString* m_errorString; V8InspectorImpl* m_inspector; int m_contextGroupId; InjectedScript* m_injectedScript; private: void cleanup(); - V8Debugger::PauseOnExceptionsState setPauseOnExceptionsState( - V8Debugger::PauseOnExceptionsState); + v8::DebugInterface::ExceptionBreakState setPauseOnExceptionsState( + v8::DebugInterface::ExceptionBreakState); v8::HandleScope m_handleScope; v8::TryCatch m_tryCatch; v8::Local<v8::Context> m_context; std::unique_ptr<V8Console::CommandLineAPIScope> m_commandLineAPIScope; bool m_ignoreExceptionsAndMuteConsole; - V8Debugger::PauseOnExceptionsState m_previousPauseOnExceptionsState; + v8::DebugInterface::ExceptionBreakState m_previousPauseOnExceptionsState; bool m_userGesture; }; class ContextScope : public Scope { public: - ContextScope(ErrorString*, V8InspectorImpl*, int contextGroupId, - int executionContextId); + ContextScope(V8InspectorImpl*, int contextGroupId, int executionContextId); ~ContextScope(); private: - void findInjectedScript(V8InspectorSessionImpl*) override; + Response findInjectedScript(V8InspectorSessionImpl*) override; int m_executionContextId; DISALLOW_COPY_AND_ASSIGN(ContextScope); @@ -153,14 +146,14 @@ class InjectedScript final { class ObjectScope : public Scope { public: - ObjectScope(ErrorString*, V8InspectorImpl*, int contextGroupId, + ObjectScope(V8InspectorImpl*, int contextGroupId, const String16& remoteObjectId); ~ObjectScope(); const String16& objectGroupName() const { return m_objectGroupName; } v8::Local<v8::Value> object() const { return m_object; } private: - void findInjectedScript(V8InspectorSessionImpl*) override; + Response findInjectedScript(V8InspectorSessionImpl*) override; String16 m_remoteObjectId; String16 m_objectGroupName; v8::Local<v8::Value> m_object; @@ -170,13 +163,13 @@ class InjectedScript final { class CallFrameScope : public Scope { public: - CallFrameScope(ErrorString*, V8InspectorImpl*, int contextGroupId, + CallFrameScope(V8InspectorImpl*, int contextGroupId, const String16& remoteCallFrameId); ~CallFrameScope(); size_t frameOrdinal() const { return m_frameOrdinal; } private: - void findInjectedScript(V8InspectorSessionImpl*) override; + Response findInjectedScript(V8InspectorSessionImpl*) override; String16 m_remoteCallFrameId; size_t m_frameOrdinal; @@ -187,10 +180,9 @@ class InjectedScript final { InjectedScript(InspectedContext*, v8::Local<v8::Object>, std::unique_ptr<InjectedScriptNative>); v8::Local<v8::Value> v8Value() const; - v8::MaybeLocal<v8::Value> wrapValue(ErrorString*, v8::Local<v8::Value>, - const String16& groupName, - bool forceValueType, - bool generatePreview) const; + Response wrapValue(v8::Local<v8::Value>, const String16& groupName, + bool forceValueType, bool generatePreview, + v8::Local<v8::Value>* result) const; v8::Local<v8::Object> commandLineAPI(); InspectedContext* m_context; diff --git a/deps/v8/src/inspector/inspected-context.cc b/deps/v8/src/inspector/inspected-context.cc index 9100f64b2a..dab3bba050 100644 --- a/deps/v8/src/inspector/inspected-context.cc +++ b/deps/v8/src/inspector/inspected-context.cc @@ -14,23 +14,23 @@ namespace v8_inspector { -void InspectedContext::weakCallback( - const v8::WeakCallbackInfo<InspectedContext>& 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); - } -} +namespace { -void InspectedContext::consoleWeakCallback( - const v8::WeakCallbackInfo<InspectedContext>& data) { - data.GetParameter()->m_console.Reset(); +void clearContext(const v8::WeakCallbackInfo<v8::Global<v8::Context>>& data) { + // Inspected context is created in V8InspectorImpl::contextCreated method + // and destroyed in V8InspectorImpl::contextDestroyed. + // Both methods takes valid v8::Local<v8::Context> handle to the same context, + // it means that context is created before InspectedContext constructor and is + // always destroyed after InspectedContext destructor therefore this callback + // should be never called. + // It's possible only if inspector client doesn't call contextDestroyed which + // is considered an error. + CHECK(false); + data.GetParameter()->Reset(); } +} // namespace + InspectedContext::InspectedContext(V8InspectorImpl* inspector, const V8ContextInfo& info, int contextId) : m_inspector(inspector), @@ -41,7 +41,7 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector, m_humanReadableName(toString16(info.humanReadableName)), m_auxData(toString16(info.auxData)), m_reported(false) { - m_context.SetWeak(this, &InspectedContext::weakCallback, + m_context.SetWeak(&m_context, &clearContext, v8::WeakCallbackType::kParameter); v8::Isolate* isolate = m_inspector->isolate(); @@ -54,12 +54,11 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector, .FromMaybe(false)) return; m_console.Reset(isolate, console); - m_console.SetWeak(this, &InspectedContext::consoleWeakCallback, - v8::WeakCallbackType::kParameter); + m_console.SetWeak(); } InspectedContext::~InspectedContext() { - if (!m_context.IsEmpty() && !m_console.IsEmpty()) { + if (!m_console.IsEmpty()) { v8::HandleScope scope(isolate()); V8Console::clearInspectedContextIfNeeded(context(), m_console.Get(isolate())); diff --git a/deps/v8/src/inspector/inspected-context.h b/deps/v8/src/inspector/inspected-context.h index d8e72cc353..f31eb76419 100644 --- a/deps/v8/src/inspector/inspected-context.h +++ b/deps/v8/src/inspector/inspected-context.h @@ -41,9 +41,6 @@ class InspectedContext { private: friend class V8InspectorImpl; InspectedContext(V8InspectorImpl*, const V8ContextInfo&, int contextId); - static void weakCallback(const v8::WeakCallbackInfo<InspectedContext>&); - static void consoleWeakCallback( - const v8::WeakCallbackInfo<InspectedContext>&); V8InspectorImpl* m_inspector; v8::Global<v8::Context> m_context; diff --git a/deps/v8/src/inspector/inspector.gyp b/deps/v8/src/inspector/inspector.gyp index 2d5c7a5153..c70722f852 100644 --- a/deps/v8/src/inspector/inspector.gyp +++ b/deps/v8/src/inspector/inspector.gyp @@ -4,11 +4,11 @@ { 'variables': { - 'protocol_path': '<(PRODUCT_DIR)/../../third_party/WebKit/Source/platform/inspector_protocol', + 'protocol_path': '../../third_party/inspector_protocol', }, 'includes': [ 'inspector.gypi', - '<(PRODUCT_DIR)/../../../third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gypi', + '<(PRODUCT_DIR)/../../../third_party/inspector_protocol/inspector_protocol.gypi', ], 'targets': [ { 'target_name': 'inspector_injected_script', @@ -97,7 +97,7 @@ 'action': [ 'python', '<(protocol_path)/CodeGenerator.py', - '--jinja_dir', '<(PRODUCT_DIR)/../../third_party', + '--jinja_dir', '../../third_party', '--output_base', '<(SHARED_INTERMEDIATE_DIR)/src/inspector', '--config', 'inspector_protocol_config.json', ], diff --git a/deps/v8/src/inspector/java-script-call-frame.cc b/deps/v8/src/inspector/java-script-call-frame.cc index b70af21f86..2da4f04249 100644 --- a/deps/v8/src/inspector/java-script-call-frame.cc +++ b/deps/v8/src/inspector/java-script-call-frame.cc @@ -30,10 +30,9 @@ #include "src/inspector/java-script-call-frame.h" +#include "src/debug/debug-interface.h" #include "src/inspector/string-util.h" -#include "include/v8-debug.h" - namespace v8_inspector { JavaScriptCallFrame::JavaScriptCallFrame(v8::Local<v8::Context> debuggerContext, @@ -130,10 +129,10 @@ v8::MaybeLocal<v8::Value> JavaScriptCallFrame::restart() { v8::Local<v8::Function> restartFunction = v8::Local<v8::Function>::Cast( callFrame->Get(context, toV8StringInternalized(m_isolate, "restart")) .ToLocalChecked()); - v8::Debug::SetLiveEditEnabled(m_isolate, true); + v8::DebugInterface::SetLiveEditEnabled(m_isolate, true); v8::MaybeLocal<v8::Value> result = restartFunction->Call( m_debuggerContext.Get(m_isolate), callFrame, 0, nullptr); - v8::Debug::SetLiveEditEnabled(m_isolate, false); + v8::DebugInterface::SetLiveEditEnabled(m_isolate, false); return result; } diff --git a/deps/v8/src/inspector/js_protocol.json b/deps/v8/src/inspector/js_protocol.json index aff6806222..c1ac585ed1 100644 --- a/deps/v8/src/inspector/js_protocol.json +++ b/deps/v8/src/inspector/js_protocol.json @@ -538,6 +538,18 @@ "description": "Removes JavaScript breakpoint." }, { + "name": "getPossibleBreakpoints", + "parameters": [ + { "name": "start", "$ref": "Location", "description": "Start of range to search possible breakpoint locations in." }, + { "name": "end", "$ref": "Location", "optional": true, "description": "End of range to search possible breakpoint locations in (excluding). When not specifed, end of scripts is used as end of range." } + ], + "returns": [ + { "name": "locations", "type": "array", "items": { "$ref": "Location" }, "description": "List of the possible breakpoint locations." } + ], + "description": "Returns possible locations for breakpoint. scriptId in start and end range locations should be the same.", + "experimental": true + }, + { "name": "continueToLocation", "parameters": [ { "name": "location", "$ref": "Location", "description": "Location to continue to." } diff --git a/deps/v8/src/inspector/remote-object-id.cc b/deps/v8/src/inspector/remote-object-id.cc index d83020c6f2..aac6724498 100644 --- a/deps/v8/src/inspector/remote-object-id.cc +++ b/deps/v8/src/inspector/remote-object-id.cc @@ -27,44 +27,34 @@ RemoteObjectIdBase::parseInjectedScriptId(const String16& objectId) { RemoteObjectId::RemoteObjectId() : RemoteObjectIdBase(), m_id(0) {} -std::unique_ptr<RemoteObjectId> RemoteObjectId::parse( - ErrorString* errorString, const String16& objectId) { - std::unique_ptr<RemoteObjectId> result(new RemoteObjectId()); +Response RemoteObjectId::parse(const String16& objectId, + std::unique_ptr<RemoteObjectId>* result) { + std::unique_ptr<RemoteObjectId> remoteObjectId(new RemoteObjectId()); std::unique_ptr<protocol::DictionaryValue> parsedObjectId = - result->parseInjectedScriptId(objectId); - if (!parsedObjectId) { - *errorString = "Invalid remote object id"; - return nullptr; - } + remoteObjectId->parseInjectedScriptId(objectId); + if (!parsedObjectId) return Response::Error("Invalid remote object id"); - bool success = parsedObjectId->getInteger("id", &result->m_id); - if (!success) { - *errorString = "Invalid remote object id"; - return nullptr; - } - return result; + bool success = parsedObjectId->getInteger("id", &remoteObjectId->m_id); + if (!success) return Response::Error("Invalid remote object id"); + *result = std::move(remoteObjectId); + return Response::OK(); } RemoteCallFrameId::RemoteCallFrameId() : RemoteObjectIdBase(), m_frameOrdinal(0) {} -std::unique_ptr<RemoteCallFrameId> RemoteCallFrameId::parse( - ErrorString* errorString, const String16& objectId) { - std::unique_ptr<RemoteCallFrameId> result(new RemoteCallFrameId()); +Response RemoteCallFrameId::parse(const String16& objectId, + std::unique_ptr<RemoteCallFrameId>* result) { + std::unique_ptr<RemoteCallFrameId> remoteCallFrameId(new RemoteCallFrameId()); std::unique_ptr<protocol::DictionaryValue> parsedObjectId = - result->parseInjectedScriptId(objectId); - if (!parsedObjectId) { - *errorString = "Invalid call frame id"; - return nullptr; - } + remoteCallFrameId->parseInjectedScriptId(objectId); + if (!parsedObjectId) return Response::Error("Invalid call frame id"); - bool success = parsedObjectId->getInteger("ordinal", &result->m_frameOrdinal); - if (!success) { - *errorString = "Invalid call frame id"; - return nullptr; - } - - return result; + bool success = + parsedObjectId->getInteger("ordinal", &remoteCallFrameId->m_frameOrdinal); + if (!success) return Response::Error("Invalid call frame id"); + *result = std::move(remoteCallFrameId); + return Response::OK(); } String16 RemoteCallFrameId::serialize(int injectedScriptId, int frameOrdinal) { diff --git a/deps/v8/src/inspector/remote-object-id.h b/deps/v8/src/inspector/remote-object-id.h index a32f568fb8..3e6928a87e 100644 --- a/deps/v8/src/inspector/remote-object-id.h +++ b/deps/v8/src/inspector/remote-object-id.h @@ -9,7 +9,7 @@ namespace v8_inspector { -using protocol::ErrorString; +using protocol::Response; class RemoteObjectIdBase { public: @@ -27,7 +27,7 @@ class RemoteObjectIdBase { class RemoteObjectId final : public RemoteObjectIdBase { public: - static std::unique_ptr<RemoteObjectId> parse(ErrorString*, const String16&); + static Response parse(const String16&, std::unique_ptr<RemoteObjectId>*); ~RemoteObjectId() {} int id() const { return m_id; } @@ -39,8 +39,7 @@ class RemoteObjectId final : public RemoteObjectIdBase { class RemoteCallFrameId final : public RemoteObjectIdBase { public: - static std::unique_ptr<RemoteCallFrameId> parse(ErrorString*, - const String16&); + static Response parse(const String16&, std::unique_ptr<RemoteCallFrameId>*); ~RemoteCallFrameId() {} int frameOrdinal() const { return m_frameOrdinal; } diff --git a/deps/v8/src/inspector/string-16.cc b/deps/v8/src/inspector/string-16.cc index f6084602f4..09909a911b 100644 --- a/deps/v8/src/inspector/string-16.cc +++ b/deps/v8/src/inspector/string-16.cc @@ -377,7 +377,11 @@ String16 String16::fromInteger(int number) { String16 String16::fromInteger(size_t number) { const size_t kBufferSize = 50; char buffer[kBufferSize]; +#if !defined(_WIN32) && !defined(_WIN64) v8::base::OS::SNPrintF(buffer, kBufferSize, "%zu", number); +#else + v8::base::OS::SNPrintF(buffer, kBufferSize, "%Iu", number); +#endif return String16(buffer); } @@ -443,6 +447,26 @@ void String16Builder::append(const char* characters, size_t length) { m_buffer.insert(m_buffer.end(), characters, characters + length); } +void String16Builder::appendNumber(int number) { + const int kBufferSize = 11; + char buffer[kBufferSize]; + int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%d", number); + DCHECK_GT(kBufferSize, chars); + m_buffer.insert(m_buffer.end(), buffer, buffer + chars); +} + +void String16Builder::appendNumber(size_t number) { + const int kBufferSize = 20; + char buffer[kBufferSize]; +#if !defined(_WIN32) && !defined(_WIN64) + int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%zu", number); +#else + int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%Iu", number); +#endif + DCHECK_GT(kBufferSize, chars); + m_buffer.insert(m_buffer.end(), buffer, buffer + chars); +} + String16 String16Builder::toString() { return String16(m_buffer.data(), m_buffer.size()); } diff --git a/deps/v8/src/inspector/string-16.h b/deps/v8/src/inspector/string-16.h index 6dc7759de0..360ec93864 100644 --- a/deps/v8/src/inspector/string-16.h +++ b/deps/v8/src/inspector/string-16.h @@ -21,7 +21,10 @@ class String16 { static const size_t kNotFound = static_cast<size_t>(-1); String16() {} - String16(const String16& other) : m_impl(other.m_impl) {} + String16(const String16& other) + : m_impl(other.m_impl), hash_code(other.hash_code) {} + String16(const String16&& other) + : m_impl(std::move(other.m_impl)), hash_code(other.hash_code) {} String16(const UChar* characters, size_t size) : m_impl(characters, size) {} String16(const UChar* characters) // NOLINT(runtime/explicit) : m_impl(characters) {} @@ -31,6 +34,18 @@ class String16 { m_impl.resize(size); for (size_t i = 0; i < size; ++i) m_impl[i] = characters[i]; } + explicit String16(const std::basic_string<UChar>& impl) : m_impl(impl) {} + + String16& operator=(const String16& other) { + m_impl = other.m_impl; + hash_code = other.hash_code; + return *this; + } + String16& operator=(String16&& other) { + m_impl = std::move(other.m_impl); + hash_code = other.hash_code; + return *this; + } static String16 fromInteger(int); static String16 fromInteger(size_t); @@ -52,51 +67,53 @@ class String16 { 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); } + size_t find(UChar c, size_t start = 0) const { return m_impl.find(c, start); } + size_t reverseFind(UChar c, size_t start = UINT_MAX) const { + return m_impl.rfind(c, start); + } + void swap(String16& other) { + m_impl.swap(other.m_impl); + std::swap(hash_code, other.hash_code); + } // Convenience methods. std::string utf8() const; static String16 fromUTF8(const char* stringStart, size_t length); - const std::basic_string<UChar>& impl() const { return m_impl; } - explicit String16(const std::basic_string<UChar>& 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; + if (!hash_code) { + for (char c : m_impl) hash_code = 31 * hash_code + c; + // Map hash code 0 to 1. This double the number of hash collisions for 1, + // but avoids recomputing the hash code. + if (!hash_code) ++hash_code; } return hash_code; } + inline bool operator==(const String16& other) const { + return m_impl == other.m_impl; + } + inline bool operator<(const String16& other) const { + return m_impl < other.m_impl; + } + inline bool operator!=(const String16& other) const { + return m_impl != other.m_impl; + } + inline String16 operator+(const String16& other) const { + return String16(m_impl + other.m_impl); + } + + // Defined later, since it uses the String16Builder. + template <typename... T> + static String16 concat(T... args); + private: std::basic_string<UChar> 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()); + return String16(a) + b; } class String16Builder { @@ -107,13 +124,29 @@ class String16Builder { void append(char); void append(const UChar*, size_t); void append(const char*, size_t); + void appendNumber(int); + void appendNumber(size_t); String16 toString(); void reserveCapacity(size_t); + template <typename T, typename... R> + void appendAll(T first, R... rest) { + append(first); + appendAll(rest...); + } + void appendAll() {} + private: std::vector<UChar> m_buffer; }; +template <typename... T> +String16 String16::concat(T... args) { + String16Builder builder; + builder.appendAll(args...); + return builder.toString(); +} + } // namespace v8_inspector #if !defined(__APPLE__) || defined(_LIBCPP_VERSION) diff --git a/deps/v8/src/inspector/string-util.cc b/deps/v8/src/inspector/string-util.cc index e6b83a5d7d..e6ad5d0c5b 100644 --- a/deps/v8/src/inspector/string-util.cc +++ b/deps/v8/src/inspector/string-util.cc @@ -111,94 +111,6 @@ std::unique_ptr<protocol::Value> parseJSON(const String16& string) { } // namespace protocol -std::unique_ptr<protocol::Value> toProtocolValue(protocol::String* errorString, - v8::Local<v8::Context> context, - v8::Local<v8::Value> 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<v8::Boolean>()->Value()); - if (value->IsNumber()) { - double doubleValue = value.As<v8::Number>()->Value(); - int intValue = static_cast<int>(doubleValue); - if (intValue == doubleValue) - return protocol::FundamentalValue::create(intValue); - return protocol::FundamentalValue::create(doubleValue); - } - if (value->IsString()) - return protocol::StringValue::create( - toProtocolString(value.As<v8::String>())); - if (value->IsArray()) { - v8::Local<v8::Array> array = value.As<v8::Array>(); - std::unique_ptr<protocol::ListValue> inspectorArray = - protocol::ListValue::create(); - uint32_t length = array->Length(); - for (uint32_t i = 0; i < length; i++) { - v8::Local<v8::Value> value; - if (!array->Get(context, i).ToLocal(&value)) { - *errorString = "Internal error"; - return nullptr; - } - std::unique_ptr<protocol::Value> 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<protocol::DictionaryValue> jsonObject = - protocol::DictionaryValue::create(); - v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); - v8::Local<v8::Array> 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<v8::Value> 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<bool> hasRealNamedProperty = object->HasRealNamedProperty( - context, v8::Local<v8::String>::Cast(name)); - if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust()) - continue; - } - v8::Local<v8::String> propertyName; - if (!name->ToString(context).ToLocal(&propertyName)) continue; - v8::Local<v8::Value> property; - if (!object->Get(context, name).ToLocal(&property)) { - *errorString = "Internal error"; - return nullptr; - } - std::unique_ptr<protocol::Value> 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> StringBuffer::create(const StringView& string) { String16 owner = toString16(string); diff --git a/deps/v8/src/inspector/string-util.h b/deps/v8/src/inspector/string-util.h index 30137b8b78..e1a69e8906 100644 --- a/deps/v8/src/inspector/string-util.h +++ b/deps/v8/src/inspector/string-util.h @@ -40,11 +40,6 @@ std::unique_ptr<protocol::Value> parseJSON(const String16& json); } // namespace protocol -std::unique_ptr<protocol::Value> toProtocolValue(protocol::String* errorString, - v8::Local<v8::Context>, - v8::Local<v8::Value>, - int maxDepth = 1000); - v8::Local<v8::String> toV8String(v8::Isolate*, const String16&); v8::Local<v8::String> toV8StringInternalized(v8::Isolate*, const String16&); v8::Local<v8::String> toV8StringInternalized(v8::Isolate*, const char*); diff --git a/deps/v8/src/inspector/v8-console-agent-impl.cc b/deps/v8/src/inspector/v8-console-agent-impl.cc index 8eb883cb75..6b0e12a77b 100644 --- a/deps/v8/src/inspector/v8-console-agent-impl.cc +++ b/deps/v8/src/inspector/v8-console-agent-impl.cc @@ -26,28 +26,29 @@ V8ConsoleAgentImpl::V8ConsoleAgentImpl( V8ConsoleAgentImpl::~V8ConsoleAgentImpl() {} -void V8ConsoleAgentImpl::enable(ErrorString* errorString) { - if (m_enabled) return; +Response V8ConsoleAgentImpl::enable() { + if (m_enabled) return Response::OK(); m_state->setBoolean(ConsoleAgentState::consoleEnabled, true); m_enabled = true; m_session->inspector()->enableStackCapturingIfNeeded(); reportAllMessages(); + return Response::OK(); } -void V8ConsoleAgentImpl::disable(ErrorString* errorString) { - if (!m_enabled) return; +Response V8ConsoleAgentImpl::disable() { + if (!m_enabled) return Response::OK(); m_session->inspector()->disableStackCapturingIfNeeded(); m_state->setBoolean(ConsoleAgentState::consoleEnabled, false); m_enabled = false; + return Response::OK(); } -void V8ConsoleAgentImpl::clearMessages(ErrorString* errorString) {} +Response V8ConsoleAgentImpl::clearMessages() { return Response::OK(); } void V8ConsoleAgentImpl::restore() { if (!m_state->booleanProperty(ConsoleAgentState::consoleEnabled, false)) return; - ErrorString ignored; - enable(&ignored); + enable(); } void V8ConsoleAgentImpl::messageAdded(V8ConsoleMessage* message) { diff --git a/deps/v8/src/inspector/v8-console-agent-impl.h b/deps/v8/src/inspector/v8-console-agent-impl.h index f3d598bb34..db17e54718 100644 --- a/deps/v8/src/inspector/v8-console-agent-impl.h +++ b/deps/v8/src/inspector/v8-console-agent-impl.h @@ -14,7 +14,7 @@ namespace v8_inspector { class V8ConsoleMessage; class V8InspectorSessionImpl; -using protocol::ErrorString; +using protocol::Response; class V8ConsoleAgentImpl : public protocol::Console::Backend { public: @@ -22,9 +22,9 @@ class V8ConsoleAgentImpl : public protocol::Console::Backend { protocol::DictionaryValue* state); ~V8ConsoleAgentImpl() override; - void enable(ErrorString*) override; - void disable(ErrorString*) override; - void clearMessages(ErrorString*) override; + Response enable() override; + Response disable() override; + Response clearMessages() override; void restore(); void messageAdded(V8ConsoleMessage*); diff --git a/deps/v8/src/inspector/v8-console.cc b/deps/v8/src/inspector/v8-console.cc index ddd4bf629e..fee61177e7 100644 --- a/deps/v8/src/inspector/v8-console.cc +++ b/deps/v8/src/inspector/v8-console.cc @@ -618,12 +618,11 @@ static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info, if (!context) return; InjectedScript* injectedScript = context->getInjectedScript(); if (!injectedScript) return; - ErrorString errorString; - std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject = - injectedScript->wrapObject(&errorString, info[0], "", - false /** forceValueType */, - false /** generatePreview */); - if (!wrappedObject || !errorString.isEmpty()) return; + std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject; + protocol::Response response = + injectedScript->wrapObject(info[0], "", false /** forceValueType */, + false /** generatePreview */, &wrappedObject); + if (!response.isSuccess()) return; std::unique_ptr<protocol::DictionaryValue> hints = protocol::DictionaryValue::create(); diff --git a/deps/v8/src/inspector/v8-debugger-agent-impl.cc b/deps/v8/src/inspector/v8-debugger-agent-impl.cc index 80e261119e..224ae282c4 100644 --- a/deps/v8/src/inspector/v8-debugger-agent-impl.cc +++ b/deps/v8/src/inspector/v8-debugger-agent-impl.cc @@ -6,6 +6,7 @@ #include <algorithm> +#include "src/debug/debug-interface.h" #include "src/inspector/injected-script.h" #include "src/inspector/inspected-context.h" #include "src/inspector/java-script-call-frame.h" @@ -21,6 +22,7 @@ #include "src/inspector/v8-regex.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" @@ -52,8 +54,11 @@ static const char skipAllPauses[] = "skipAllPauses"; } // namespace DebuggerAgentState -static const int maxSkipStepFrameCount = 128; -static const char backtraceObjectGroup[] = "backtrace"; +static const int kMaxSkipStepFrameCount = 128; +static const char kBacktraceObjectGroup[] = "backtrace"; +static const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; +static const char kDebuggerNotPaused[] = + "Can only perform operation while paused."; static String16 breakpointIdSuffix( V8DebuggerAgentImpl::BreakpointSource source) { @@ -71,8 +76,14 @@ static String16 breakpointIdSuffix( static String16 generateBreakpointId( const String16& scriptId, int lineNumber, int columnNumber, V8DebuggerAgentImpl::BreakpointSource source) { - return scriptId + ":" + String16::fromInteger(lineNumber) + ":" + - String16::fromInteger(columnNumber) + breakpointIdSuffix(source); + String16Builder builder; + builder.append(scriptId); + builder.append(':'); + builder.appendNumber(lineNumber); + builder.append(':'); + builder.appendNumber(columnNumber); + builder.append(breakpointIdSuffix(source)); + return builder.toString(); } static bool positionComparator(const std::pair<int, int>& a, @@ -81,11 +92,6 @@ static bool positionComparator(const std::pair<int, int>& a, return a.second < b.second; } -static bool hasInternalError(ErrorString* errorString, bool hasError) { - if (hasError) *errorString = "Internal error"; - return hasError; -} - static std::unique_ptr<protocol::Debugger::Location> buildProtocolLocation( const String16& scriptId, int lineNumber, int columnNumber) { return protocol::Debugger::Location::create() @@ -120,13 +126,7 @@ V8DebuggerAgentImpl::V8DebuggerAgentImpl( V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} -bool V8DebuggerAgentImpl::checkEnabled(ErrorString* errorString) { - if (enabled()) return true; - *errorString = "Debugger agent is not enabled"; - return false; -} - -void V8DebuggerAgentImpl::enable() { +void V8DebuggerAgentImpl::enableImpl() { // 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; @@ -145,24 +145,23 @@ void V8DebuggerAgentImpl::enable() { bool V8DebuggerAgentImpl::enabled() { return m_enabled; } -void V8DebuggerAgentImpl::enable(ErrorString* errorString) { - if (enabled()) return; +Response V8DebuggerAgentImpl::enable() { + if (enabled()) return Response::OK(); - if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) { - *errorString = "Script execution is prohibited"; - return; - } + if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) + return Response::Error("Script execution is prohibited"); - enable(); + enableImpl(); + return Response::OK(); } -void V8DebuggerAgentImpl::disable(ErrorString*) { - if (!enabled()) return; +Response V8DebuggerAgentImpl::disable() { + if (!enabled()) return Response::OK(); m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, protocol::DictionaryValue::create()); m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, - V8Debugger::DontPauseOnExceptions); + v8::DebugInterface::NoBreakOnException); m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); if (!m_pausedContext.IsEmpty()) m_debugger->continueProgram(); @@ -188,6 +187,7 @@ void V8DebuggerAgentImpl::disable(ErrorString*) { m_state->remove(DebuggerAgentState::blackboxPattern); m_enabled = false; m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); + return Response::OK(); } void V8DebuggerAgentImpl::restore() { @@ -197,13 +197,11 @@ void V8DebuggerAgentImpl::restore() { if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) return; - enable(); - ErrorString error; + enableImpl(); - int pauseState = V8Debugger::DontPauseOnExceptions; + int pauseState = v8::DebugInterface::NoBreakOnException; m_state->getInteger(DebuggerAgentState::pauseOnExceptionsState, &pauseState); - setPauseOnExceptionsImpl(&error, pauseState); - DCHECK(error.isEmpty()); + setPauseOnExceptionsImpl(pauseState); m_skipAllPauses = m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false); @@ -216,19 +214,20 @@ void V8DebuggerAgentImpl::restore() { String16 blackboxPattern; if (m_state->getString(DebuggerAgentState::blackboxPattern, &blackboxPattern)) { - if (!setBlackboxPattern(&error, blackboxPattern)) UNREACHABLE(); + setBlackboxPattern(blackboxPattern); } } -void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, - bool active) { - if (!checkEnabled(errorString)) return; +Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { + if (!enabled()) return Response::Error(kDebuggerNotEnabled); m_debugger->setBreakpointsActivated(active); + return Response::OK(); } -void V8DebuggerAgentImpl::setSkipAllPauses(ErrorString*, bool skip) { +Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { m_skipAllPauses = skip; m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses); + return Response::OK(); } static std::unique_ptr<protocol::DictionaryValue> @@ -254,27 +253,21 @@ static bool matches(V8InspectorImpl* inspector, const String16& url, return url == pattern; } -void V8DebuggerAgentImpl::setBreakpointByUrl( - ErrorString* errorString, int lineNumber, - const Maybe<String16>& optionalURL, const Maybe<String16>& optionalURLRegex, - const Maybe<int>& optionalColumnNumber, - const Maybe<String16>& optionalCondition, String16* outBreakpointId, +Response V8DebuggerAgentImpl::setBreakpointByUrl( + int lineNumber, Maybe<String16> optionalURL, + Maybe<String16> optionalURLRegex, Maybe<int> optionalColumnNumber, + Maybe<String16> optionalCondition, String16* outBreakpointId, std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) { *locations = Array<protocol::Debugger::Location>::create(); - if (optionalURL.isJust() == optionalURLRegex.isJust()) { - *errorString = "Either url or urlRegex must be specified."; - return; - } + if (optionalURL.isJust() == optionalURLRegex.isJust()) + return Response::Error("Either url or urlRegex must be specified."); 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; - } + if (columnNumber < 0) return Response::Error("Incorrect column number"); } String16 condition = optionalCondition.fromMaybe(""); bool isRegex = optionalURLRegex.isJust(); @@ -291,10 +284,8 @@ void V8DebuggerAgentImpl::setBreakpointByUrl( m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, std::move(newValue)); } - if (breakpointsCookie->get(breakpointId)) { - *errorString = "Breakpoint at specified location already exists."; - return; - } + if (breakpointsCookie->get(breakpointId)) + return Response::Error("Breakpoint at specified location already exists."); breakpointsCookie->setObject( breakpointId, buildObjectForBreakpointCookie( @@ -310,30 +301,16 @@ void V8DebuggerAgentImpl::setBreakpointByUrl( } *outBreakpointId = breakpointId; + return Response::OK(); } -static bool parseLocation( - ErrorString* errorString, - std::unique_ptr<protocol::Debugger::Location> location, String16* scriptId, - int* lineNumber, int* columnNumber) { - *scriptId = location->getScriptId(); - *lineNumber = location->getLineNumber(); - *columnNumber = location->getColumnNumber(0); - return true; -} - -void V8DebuggerAgentImpl::setBreakpoint( - ErrorString* errorString, +Response V8DebuggerAgentImpl::setBreakpoint( std::unique_ptr<protocol::Debugger::Location> location, - const Maybe<String16>& optionalCondition, String16* outBreakpointId, + Maybe<String16> optionalCondition, String16* outBreakpointId, std::unique_ptr<protocol::Debugger::Location>* actualLocation) { - String16 scriptId; - int lineNumber; - int columnNumber; - - if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, - &columnNumber)) - return; + String16 scriptId = location->getScriptId(); + int lineNumber = location->getLineNumber(); + int columnNumber = location->getColumnNumber(0); String16 condition = optionalCondition.fromMaybe(""); @@ -341,28 +318,26 @@ void V8DebuggerAgentImpl::setBreakpoint( scriptId, lineNumber, columnNumber, UserBreakpointSource); if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != m_breakpointIdToDebuggerBreakpointIds.end()) { - *errorString = "Breakpoint at specified location already exists."; - return; + return Response::Error("Breakpoint at specified location already exists."); } ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); *actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, UserBreakpointSource); - if (*actualLocation) - *outBreakpointId = breakpointId; - else - *errorString = "Could not resolve breakpoint"; + if (!*actualLocation) return Response::Error("Could not resolve breakpoint"); + *outBreakpointId = breakpointId; + return Response::OK(); } -void V8DebuggerAgentImpl::removeBreakpoint(ErrorString* errorString, - const String16& breakpointId) { - if (!checkEnabled(errorString)) return; +Response V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { + if (!enabled()) return Response::Error(kDebuggerNotEnabled); protocol::DictionaryValue* breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); if (breakpointsCookie) breakpointsCookie->remove(breakpointId); - removeBreakpoint(breakpointId); + removeBreakpointImpl(breakpointId); + return Response::OK(); } -void V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { +void V8DebuggerAgentImpl::removeBreakpointImpl(const String16& breakpointId) { DCHECK(enabled()); BreakpointIdToDebuggerBreakpointIdsMap::iterator debuggerBreakpointIdsIterator = @@ -380,27 +355,64 @@ void V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { m_breakpointIdToDebuggerBreakpointIds.erase(breakpointId); } -void V8DebuggerAgentImpl::continueToLocation( - ErrorString* errorString, +Response V8DebuggerAgentImpl::getPossibleBreakpoints( + std::unique_ptr<protocol::Debugger::Location> start, + Maybe<protocol::Debugger::Location> end, + std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) { + String16 scriptId = start->getScriptId(); + + if (start->getLineNumber() < 0 || start->getColumnNumber(0) < 0) + return Response::Error( + "start.lineNumber and start.columnNumber should be >= 0"); + + v8::DebugInterface::Location v8Start(start->getLineNumber(), + start->getColumnNumber(0)); + v8::DebugInterface::Location v8End; + if (end.isJust()) { + if (end.fromJust()->getScriptId() != scriptId) + return Response::Error("Locations should contain the same scriptId"); + int line = end.fromJust()->getLineNumber(); + int column = end.fromJust()->getColumnNumber(0); + if (line < 0 || column < 0) + return Response::Error( + "end.lineNumber and end.columnNumber should be >= 0"); + v8End = v8::DebugInterface::Location(line, column); + } + auto it = m_scripts.find(scriptId); + if (it == m_scripts.end()) return Response::Error("Script not found"); + + std::vector<v8::DebugInterface::Location> v8Locations; + if (!it->second->getPossibleBreakpoints(v8Start, v8End, &v8Locations)) + return Response::InternalError(); + + *locations = protocol::Array<protocol::Debugger::Location>::create(); + for (size_t i = 0; i < v8Locations.size(); ++i) { + (*locations) + ->addItem(protocol::Debugger::Location::create() + .setScriptId(scriptId) + .setLineNumber(v8Locations[i].GetLineNumber()) + .setColumnNumber(v8Locations[i].GetColumnNumber()) + .build()); + } + return Response::OK(); +} + +Response V8DebuggerAgentImpl::continueToLocation( std::unique_ptr<protocol::Debugger::Location> location) { - if (!checkEnabled(errorString)) return; + if (!enabled()) return Response::Error(kDebuggerNotEnabled); 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; + String16 scriptId = location->getScriptId(); + int lineNumber = location->getLineNumber(); + int columnNumber = location->getColumnNumber(0); ScriptBreakpoint breakpoint(lineNumber, columnNumber, ""); m_continueToLocationBreakpointId = m_debugger->setBreakpoint( scriptId, breakpoint, &lineNumber, &columnNumber); - resume(errorString); + return resume(); } bool V8DebuggerAgentImpl::isCurrentCallStackEmptyOrBlackboxed() { @@ -471,7 +483,7 @@ V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipStepPause( if (!isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) return RequestNoSkip; - if (m_skippedStepFrameCount >= maxSkipStepFrameCount) return RequestStepOut; + if (m_skippedStepFrameCount >= kMaxSkipStepFrameCount) return RequestStepOut; if (!m_skippedStepFrameCount) m_recursionLevelForStepFrame = 1; @@ -509,17 +521,14 @@ V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, return buildProtocolLocation(scriptId, actualLineNumber, actualColumnNumber); } -void V8DebuggerAgentImpl::searchInContent( - ErrorString* error, const String16& scriptId, const String16& query, - const Maybe<bool>& optionalCaseSensitive, - const Maybe<bool>& optionalIsRegex, +Response V8DebuggerAgentImpl::searchInContent( + const String16& scriptId, const String16& query, + Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* 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; - } + if (it == m_scripts.end()) + return Response::Error("No script for id: " + scriptId); std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = searchInTextByLinesImpl(m_session, @@ -529,44 +538,46 @@ void V8DebuggerAgentImpl::searchInContent( *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); for (size_t i = 0; i < matches.size(); ++i) (*results)->addItem(std::move(matches[i])); + return Response::OK(); } -void V8DebuggerAgentImpl::setScriptSource( - ErrorString* errorString, const String16& scriptId, - const String16& newContent, const Maybe<bool>& dryRun, +Response V8DebuggerAgentImpl::setScriptSource( + const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, Maybe<bool>* stackChanged, Maybe<StackTrace>* asyncStackTrace, Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) { - if (!checkEnabled(errorString)) return; + if (!enabled()) return Response::Error(kDebuggerNotEnabled); v8::HandleScope handles(m_isolate); v8::Local<v8::String> newSource = toV8String(m_isolate, newContent); - if (!m_debugger->setScriptSource(scriptId, newSource, dryRun.fromMaybe(false), - errorString, optOutCompileError, - &m_pausedCallFrames, stackChanged)) - return; + bool compileError = false; + Response response = m_debugger->setScriptSource( + scriptId, newSource, dryRun.fromMaybe(false), optOutCompileError, + &m_pausedCallFrames, stackChanged, &compileError); + if (!response.isSuccess() || compileError) return response; ScriptsMap::iterator it = m_scripts.find(scriptId); - if (it != m_scripts.end()) it->second->setSource(m_isolate, newSource); + if (it != m_scripts.end()) it->second->setSource(newSource); - std::unique_ptr<Array<CallFrame>> callFrames = currentCallFrames(errorString); - if (!callFrames) return; + std::unique_ptr<Array<CallFrame>> callFrames; + response = currentCallFrames(&callFrames); + if (!response.isSuccess()) return response; *newCallFrames = std::move(callFrames); *asyncStackTrace = currentAsyncStackTrace(); + return Response::OK(); } -void V8DebuggerAgentImpl::restartFrame( - ErrorString* errorString, const String16& callFrameId, +Response V8DebuggerAgentImpl::restartFrame( + const String16& callFrameId, std::unique_ptr<Array<CallFrame>>* newCallFrames, Maybe<StackTrace>* 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; - } + if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); + InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), + callFrameId); + Response response = scope.initialize(); + if (!response.isSuccess()) return response; + if (scope.frameOrdinal() >= m_pausedCallFrames.size()) + return Response::Error("Could not find call frame with given id"); v8::Local<v8::Value> resultValue; v8::Local<v8::Boolean> result; @@ -575,28 +586,26 @@ void V8DebuggerAgentImpl::restartFrame( scope.tryCatch().HasCaught() || !resultValue->ToBoolean(scope.context()).ToLocal(&result) || !result->Value()) { - *errorString = "Internal error"; - return; + return Response::InternalError(); } JavaScriptCallFrames frames = m_debugger->currentCallFrames(); m_pausedCallFrames.swap(frames); - *newCallFrames = currentCallFrames(errorString); - if (!*newCallFrames) return; + response = currentCallFrames(newCallFrames); + if (!response.isSuccess()) return response; *asyncStackTrace = currentAsyncStackTrace(); + return Response::OK(); } -void V8DebuggerAgentImpl::getScriptSource(ErrorString* error, - const String16& scriptId, - String16* scriptSource) { - if (!checkEnabled(error)) return; +Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, + String16* scriptSource) { + if (!enabled()) return Response::Error(kDebuggerNotEnabled); ScriptsMap::iterator it = m_scripts.find(scriptId); - if (it == m_scripts.end()) { - *error = "No script for id: " + scriptId; - return; - } + if (it == m_scripts.end()) + return Response::Error("No script for id: " + scriptId); v8::HandleScope handles(m_isolate); *scriptSource = toProtocolString(it->second->source(m_isolate)); + return Response::OK(); } void V8DebuggerAgentImpl::schedulePauseOnNextStatement( @@ -632,103 +641,100 @@ void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { m_debugger->setPauseOnNextStatement(false); } -void V8DebuggerAgentImpl::pause(ErrorString* errorString) { - if (!checkEnabled(errorString)) return; - if (m_javaScriptPauseScheduled || m_debugger->isPaused()) return; +Response V8DebuggerAgentImpl::pause() { + if (!enabled()) return Response::Error(kDebuggerNotEnabled); + if (m_javaScriptPauseScheduled || m_debugger->isPaused()) + return Response::OK(); clearBreakDetails(); m_javaScriptPauseScheduled = true; m_scheduledDebuggerStep = NoStep; m_skippedStepFrameCount = 0; m_steppingFromFramework = false; m_debugger->setPauseOnNextStatement(true); + return Response::OK(); } -void V8DebuggerAgentImpl::resume(ErrorString* errorString) { - if (!assertPaused(errorString)) return; +Response V8DebuggerAgentImpl::resume() { + if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); m_scheduledDebuggerStep = NoStep; m_steppingFromFramework = false; - m_session->releaseObjectGroup(backtraceObjectGroup); + m_session->releaseObjectGroup(kBacktraceObjectGroup); m_debugger->continueProgram(); + return Response::OK(); } -void V8DebuggerAgentImpl::stepOver(ErrorString* errorString) { - if (!assertPaused(errorString)) return; +Response V8DebuggerAgentImpl::stepOver() { + if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); // 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; - } + if (frame && frame->isAtReturn()) return stepInto(); m_scheduledDebuggerStep = StepOver; m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); - m_session->releaseObjectGroup(backtraceObjectGroup); + m_session->releaseObjectGroup(kBacktraceObjectGroup); m_debugger->stepOverStatement(); + return Response::OK(); } -void V8DebuggerAgentImpl::stepInto(ErrorString* errorString) { - if (!assertPaused(errorString)) return; +Response V8DebuggerAgentImpl::stepInto() { + if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); m_scheduledDebuggerStep = StepInto; m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); - m_session->releaseObjectGroup(backtraceObjectGroup); + m_session->releaseObjectGroup(kBacktraceObjectGroup); m_debugger->stepIntoStatement(); + return Response::OK(); } -void V8DebuggerAgentImpl::stepOut(ErrorString* errorString) { - if (!assertPaused(errorString)) return; +Response V8DebuggerAgentImpl::stepOut() { + if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); m_scheduledDebuggerStep = StepOut; m_skipNextDebuggerStepOut = false; m_recursionLevelForStepOut = 1; m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); - m_session->releaseObjectGroup(backtraceObjectGroup); + m_session->releaseObjectGroup(kBacktraceObjectGroup); m_debugger->stepOutOfFunction(); + return Response::OK(); } -void V8DebuggerAgentImpl::setPauseOnExceptions( - ErrorString* errorString, const String16& stringPauseState) { - if (!checkEnabled(errorString)) return; - V8Debugger::PauseOnExceptionsState pauseState; +Response V8DebuggerAgentImpl::setPauseOnExceptions( + const String16& stringPauseState) { + if (!enabled()) return Response::Error(kDebuggerNotEnabled); + v8::DebugInterface::ExceptionBreakState pauseState; if (stringPauseState == "none") { - pauseState = V8Debugger::DontPauseOnExceptions; + pauseState = v8::DebugInterface::NoBreakOnException; } else if (stringPauseState == "all") { - pauseState = V8Debugger::PauseOnAllExceptions; + pauseState = v8::DebugInterface::BreakOnAnyException; } else if (stringPauseState == "uncaught") { - pauseState = V8Debugger::PauseOnUncaughtExceptions; + pauseState = v8::DebugInterface::BreakOnUncaughtException; } else { - *errorString = "Unknown pause on exceptions mode: " + stringPauseState; - return; + return Response::Error("Unknown pause on exceptions mode: " + + stringPauseState); } - setPauseOnExceptionsImpl(errorString, pauseState); + setPauseOnExceptionsImpl(pauseState); + return Response::OK(); } -void V8DebuggerAgentImpl::setPauseOnExceptionsImpl(ErrorString* errorString, - int pauseState) { +void V8DebuggerAgentImpl::setPauseOnExceptionsImpl(int pauseState) { m_debugger->setPauseOnExceptionsState( - static_cast<V8Debugger::PauseOnExceptionsState>(pauseState)); - if (m_debugger->getPauseOnExceptionsState() != pauseState) - *errorString = "Internal error. Could not change pause on exceptions state"; - else - m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); + static_cast<v8::DebugInterface::ExceptionBreakState>(pauseState)); + m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); } -void V8DebuggerAgentImpl::evaluateOnCallFrame( - ErrorString* errorString, const String16& callFrameId, - const String16& expression, const Maybe<String16>& objectGroup, - const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& silent, - const Maybe<bool>& returnByValue, const Maybe<bool>& generatePreview, +Response V8DebuggerAgentImpl::evaluateOnCallFrame( + const String16& callFrameId, const String16& expression, + Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, + Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, std::unique_ptr<RemoteObject>* result, Maybe<protocol::Runtime::ExceptionDetails>* 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 (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); + InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), + callFrameId); + Response response = scope.initialize(); + if (!response.isSuccess()) return response; + if (scope.frameOrdinal() >= m_pausedCallFrames.size()) + return Response::Error("Could not find call frame with given id"); + + if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); v8::MaybeLocal<v8::Value> maybeResultValue = @@ -737,56 +743,52 @@ void V8DebuggerAgentImpl::evaluateOnCallFrame( // 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); + response = scope.initialize(); + if (!response.isSuccess()) return response; + return scope.injectedScript()->wrapEvaluateResult( + maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), + returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, + exceptionDetails); } -void V8DebuggerAgentImpl::setVariableValue( - ErrorString* errorString, int scopeNumber, const String16& variableName, +Response V8DebuggerAgentImpl::setVariableValue( + int scopeNumber, const String16& variableName, std::unique_ptr<protocol::Runtime::CallArgument> 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; - + if (!enabled()) return Response::Error(kDebuggerNotEnabled); + if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); + InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), + callFrameId); + Response response = scope.initialize(); + if (!response.isSuccess()) return response; v8::Local<v8::Value> newValue; - if (!scope.injectedScript() - ->resolveCallArgument(errorString, newValueArgument.get()) - .ToLocal(&newValue)) - return; + response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), + &newValue); + if (!response.isSuccess()) return response; - if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { - *errorString = "Could not find call frame with given id"; - return; - } + if (scope.frameOrdinal() >= m_pausedCallFrames.size()) + return Response::Error("Could not find call frame with given id"); v8::MaybeLocal<v8::Value> result = m_pausedCallFrames[scope.frameOrdinal()]->setVariableValue( scopeNumber, toV8String(m_isolate, variableName), newValue); - if (scope.tryCatch().HasCaught() || result.IsEmpty()) { - *errorString = "Internal error"; - return; - } + if (scope.tryCatch().HasCaught() || result.IsEmpty()) + return Response::InternalError(); + return Response::OK(); } -void V8DebuggerAgentImpl::setAsyncCallStackDepth(ErrorString* errorString, - int depth) { - if (!checkEnabled(errorString)) return; +Response V8DebuggerAgentImpl::setAsyncCallStackDepth(int depth) { + if (!enabled()) return Response::Error(kDebuggerNotEnabled); m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, depth); m_debugger->setAsyncCallStackDepth(this, depth); + return Response::OK(); } -void V8DebuggerAgentImpl::setBlackboxPatterns( - ErrorString* errorString, +Response V8DebuggerAgentImpl::setBlackboxPatterns( std::unique_ptr<protocol::Array<String16>> patterns) { if (!patterns->length()) { m_blackboxPattern = nullptr; m_state->remove(DebuggerAgentState::blackboxPattern); - return; + return Response::OK(); } String16Builder patternBuilder; @@ -798,48 +800,41 @@ void V8DebuggerAgentImpl::setBlackboxPatterns( patternBuilder.append(patterns->get(patterns->length() - 1)); patternBuilder.append(')'); String16 pattern = patternBuilder.toString(); - if (!setBlackboxPattern(errorString, pattern)) return; + Response response = setBlackboxPattern(pattern); + if (!response.isSuccess()) return response; m_state->setString(DebuggerAgentState::blackboxPattern, pattern); + return Response::OK(); } -bool V8DebuggerAgentImpl::setBlackboxPattern(ErrorString* errorString, - const String16& pattern) { +Response V8DebuggerAgentImpl::setBlackboxPattern(const String16& pattern) { std::unique_ptr<V8Regex> regex(new V8Regex( m_inspector, pattern, true /** caseSensitive */, false /** multiline */)); - if (!regex->isValid()) { - *errorString = "Pattern parser error: " + regex->errorMessage(); - return false; - } + if (!regex->isValid()) + return Response::Error("Pattern parser error: " + regex->errorMessage()); m_blackboxPattern = std::move(regex); - return true; + return Response::OK(); } -void V8DebuggerAgentImpl::setBlackboxedRanges( - ErrorString* error, const String16& scriptId, +Response V8DebuggerAgentImpl::setBlackboxedRanges( + const String16& scriptId, std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> inPositions) { - if (m_scripts.find(scriptId) == m_scripts.end()) { - *error = "No script with passed id."; - return; - } + if (m_scripts.find(scriptId) == m_scripts.end()) + return Response::Error("No script with passed id."); if (!inPositions->length()) { m_blackboxedPositions.erase(scriptId); - return; + return Response::OK(); } std::vector<std::pair<int, int>> 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; - } + if (position->getLineNumber() < 0) + return Response::Error("Position missing 'line' or 'line' < 0."); + if (position->getColumnNumber() < 0) + return Response::Error("Position missing 'column' or 'column' < 0."); positions.push_back( std::make_pair(position->getLineNumber(), position->getColumnNumber())); } @@ -849,12 +844,12 @@ void V8DebuggerAgentImpl::setBlackboxedRanges( 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; + return Response::Error( + "Input positions array is not sorted or contains duplicate values."); } m_blackboxedPositions[scriptId] = positions; + return Response::OK(); } void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { @@ -907,14 +902,15 @@ void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { } } -std::unique_ptr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames( - ErrorString* errorString) { - if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) - return Array<CallFrame>::create(); - ErrorString ignored; +Response V8DebuggerAgentImpl::currentCallFrames( + std::unique_ptr<Array<CallFrame>>* result) { + if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) { + *result = Array<CallFrame>::create(); + return Response::OK(); + } v8::HandleScope handles(m_isolate); v8::Local<v8::Context> debuggerContext = - v8::Debug::GetDebugContext(m_isolate); + v8::DebugInterface::GetDebugContext(m_isolate); v8::Context::Scope contextScope(debuggerContext); v8::Local<v8::Array> objects = v8::Array::New(m_isolate); @@ -925,104 +921,92 @@ std::unique_ptr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames( m_pausedCallFrames[frameOrdinal]; v8::Local<v8::Object> details = currentCallFrame->details(); - if (hasInternalError(errorString, details.IsEmpty())) - return Array<CallFrame>::create(); + if (details.IsEmpty()) return Response::InternalError(); int contextId = currentCallFrame->contextId(); - InjectedScript* injectedScript = - contextId ? m_session->findInjectedScript(&ignored, contextId) - : nullptr; + + InjectedScript* injectedScript = nullptr; + if (contextId) m_session->findInjectedScript(contextId, injectedScript); String16 callFrameId = RemoteCallFrameId::serialize(contextId, static_cast<int>(frameOrdinal)); - if (hasInternalError( - errorString, - !details - ->Set(debuggerContext, - toV8StringInternalized(m_isolate, "callFrameId"), - toV8String(m_isolate, callFrameId)) - .FromMaybe(false))) - return Array<CallFrame>::create(); + if (!details + ->Set(debuggerContext, + toV8StringInternalized(m_isolate, "callFrameId"), + toV8String(m_isolate, callFrameId)) + .FromMaybe(false)) { + return Response::InternalError(); + } if (injectedScript) { v8::Local<v8::Value> scopeChain; - if (hasInternalError( - errorString, - !details->Get(debuggerContext, - toV8StringInternalized(m_isolate, "scopeChain")) - .ToLocal(&scopeChain) || - !scopeChain->IsArray())) - return Array<CallFrame>::create(); + if (!details + ->Get(debuggerContext, + toV8StringInternalized(m_isolate, "scopeChain")) + .ToLocal(&scopeChain) || + !scopeChain->IsArray()) { + return Response::InternalError(); + } v8::Local<v8::Array> scopeChainArray = scopeChain.As<v8::Array>(); - if (!injectedScript->wrapPropertyInArray( - errorString, scopeChainArray, - toV8StringInternalized(m_isolate, "object"), - backtraceObjectGroup)) - return Array<CallFrame>::create(); - if (!injectedScript->wrapObjectProperty( - errorString, details, toV8StringInternalized(m_isolate, "this"), - backtraceObjectGroup)) - return Array<CallFrame>::create(); + Response response = injectedScript->wrapPropertyInArray( + scopeChainArray, toV8StringInternalized(m_isolate, "object"), + kBacktraceObjectGroup); + if (!response.isSuccess()) return response; + response = injectedScript->wrapObjectProperty( + details, toV8StringInternalized(m_isolate, "this"), + kBacktraceObjectGroup); + if (!response.isSuccess()) return response; if (details ->Has(debuggerContext, toV8StringInternalized(m_isolate, "returnValue")) .FromMaybe(false)) { - if (!injectedScript->wrapObjectProperty( - errorString, details, - toV8StringInternalized(m_isolate, "returnValue"), - backtraceObjectGroup)) - return Array<CallFrame>::create(); + response = injectedScript->wrapObjectProperty( + details, toV8StringInternalized(m_isolate, "returnValue"), + kBacktraceObjectGroup); + if (!response.isSuccess()) return response; } } else { - if (hasInternalError(errorString, !details - ->Set(debuggerContext, - toV8StringInternalized( - m_isolate, "scopeChain"), - v8::Array::New(m_isolate, 0)) - .FromMaybe(false))) - return Array<CallFrame>::create(); + if (!details + ->Set(debuggerContext, + toV8StringInternalized(m_isolate, "scopeChain"), + v8::Array::New(m_isolate, 0)) + .FromMaybe(false)) { + return Response::InternalError(); + } v8::Local<v8::Object> remoteObject = v8::Object::New(m_isolate); - if (hasInternalError( - errorString, - !remoteObject - ->Set(debuggerContext, - toV8StringInternalized(m_isolate, "type"), - toV8StringInternalized(m_isolate, "undefined")) - .FromMaybe(false))) - return Array<CallFrame>::create(); - if (hasInternalError(errorString, - !details - ->Set(debuggerContext, - toV8StringInternalized(m_isolate, "this"), - remoteObject) - .FromMaybe(false))) - return Array<CallFrame>::create(); - if (hasInternalError( - errorString, - !details - ->Delete(debuggerContext, - toV8StringInternalized(m_isolate, "returnValue")) - .FromMaybe(false))) - return Array<CallFrame>::create(); + if (!remoteObject + ->Set(debuggerContext, toV8StringInternalized(m_isolate, "type"), + toV8StringInternalized(m_isolate, "undefined")) + .FromMaybe(false)) { + return Response::InternalError(); + } + if (!details + ->Set(debuggerContext, toV8StringInternalized(m_isolate, "this"), + remoteObject) + .FromMaybe(false)) { + return Response::InternalError(); + } + if (!details + ->Delete(debuggerContext, + toV8StringInternalized(m_isolate, "returnValue")) + .FromMaybe(false)) { + return Response::InternalError(); + } } - if (hasInternalError( - errorString, - !objects - ->Set(debuggerContext, static_cast<int>(frameOrdinal), details) - .FromMaybe(false))) - return Array<CallFrame>::create(); + if (!objects->Set(debuggerContext, static_cast<int>(frameOrdinal), details) + .FromMaybe(false)) { + return Response::InternalError(); + } } - std::unique_ptr<protocol::Value> protocolValue = - toProtocolValue(errorString, debuggerContext, objects); - if (!protocolValue) return Array<CallFrame>::create(); + std::unique_ptr<protocol::Value> protocolValue; + Response response = toProtocolValue(debuggerContext, objects, &protocolValue); + if (!response.isSuccess()) return response; protocol::ErrorSupport errorSupport; - std::unique_ptr<Array<CallFrame>> callFrames = - Array<CallFrame>::parse(protocolValue.get(), &errorSupport); - if (hasInternalError(errorString, !callFrames)) - return Array<CallFrame>::create(); - return callFrames; + *result = Array<CallFrame>::parse(protocolValue.get(), &errorSupport); + if (!*result) return Response::Error(errorSupport.errors()); + return Response::OK(); } std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { @@ -1049,8 +1033,8 @@ void V8DebuggerAgentImpl::didParseSource( String16 scriptId = script->scriptId(); String16 scriptURL = script->sourceURL(); - const Maybe<String16>& sourceMapURLParam = script->sourceMappingURL(); - const Maybe<protocol::DictionaryValue>& executionContextAuxDataParam( + Maybe<String16> sourceMapURLParam = script->sourceMappingURL(); + Maybe<protocol::DictionaryValue> executionContextAuxDataParam( std::move(executionContextAuxData)); const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; @@ -1058,14 +1042,14 @@ void V8DebuggerAgentImpl::didParseSource( m_frontend.scriptParsed( scriptId, scriptURL, script->startLine(), script->startColumn(), script->endLine(), script->endColumn(), script->executionContextId(), - script->hash(), executionContextAuxDataParam, isLiveEditParam, - sourceMapURLParam, hasSourceURLParam); + script->hash(), std::move(executionContextAuxDataParam), + isLiveEditParam, std::move(sourceMapURLParam), hasSourceURLParam); else m_frontend.scriptFailedToParse( scriptId, scriptURL, script->startLine(), script->startColumn(), script->endLine(), script->endColumn(), script->executionContextId(), - script->hash(), executionContextAuxDataParam, sourceMapURLParam, - hasSourceURLParam); + script->hash(), std::move(executionContextAuxDataParam), + std::move(sourceMapURLParam), hasSourceURLParam); m_scripts[scriptId] = std::move(script); @@ -1100,7 +1084,8 @@ void V8DebuggerAgentImpl::didParseSource( V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause( v8::Local<v8::Context> context, v8::Local<v8::Value> exception, - const std::vector<String16>& hitBreakpoints, bool isPromiseRejection) { + const std::vector<String16>& hitBreakpoints, bool isPromiseRejection, + bool isUncaught) { JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(1); JavaScriptCallFrame* topCallFrame = !callFrames.empty() ? callFrames.begin()->get() : nullptr; @@ -1131,18 +1116,23 @@ V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause( v8::HandleScope handles(m_isolate); if (!exception.IsEmpty()) { - ErrorString ignored; - InjectedScript* injectedScript = - m_session->findInjectedScript(&ignored, V8Debugger::contextId(context)); + InjectedScript* injectedScript = nullptr; + m_session->findInjectedScript(V8Debugger::contextId(context), + injectedScript); 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; + std::unique_ptr<protocol::Runtime::RemoteObject> obj; + injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, + &obj); + if (obj) { + m_breakAuxData = obj->serialize(); + m_breakAuxData->setBoolean("uncaught", isUncaught); + } else { + m_breakAuxData = nullptr; + } // m_breakAuxData might be null after this. } } @@ -1163,8 +1153,10 @@ V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause( } } - ErrorString errorString; - m_frontend.paused(currentCallFrames(&errorString), m_breakReason, + std::unique_ptr<Array<CallFrame>> protocolCallFrames; + Response response = currentCallFrames(&protocolCallFrames); + if (!response.isSuccess()) protocolCallFrames = Array<CallFrame>::create(); + m_frontend.paused(std::move(protocolCallFrames), m_breakReason, std::move(m_breakAuxData), std::move(hitBreakpointIds), currentAsyncStackTrace()); m_scheduledDebuggerStep = NoStep; @@ -1209,19 +1201,11 @@ void V8DebuggerAgentImpl::breakProgramOnException( std::unique_ptr<protocol::DictionaryValue> data) { if (!enabled() || m_debugger->getPauseOnExceptionsState() == - V8Debugger::DontPauseOnExceptions) + v8::DebugInterface::NoBreakOnException) 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; @@ -1240,7 +1224,7 @@ void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, int lineNumber, int columnNumber, BreakpointSource source) { - removeBreakpoint( + removeBreakpointImpl( generateBreakpointId(scriptId, lineNumber, columnNumber, source)); } diff --git a/deps/v8/src/inspector/v8-debugger-agent-impl.h b/deps/v8/src/inspector/v8-debugger-agent-impl.h index 62aa67b64b..e5285f4cc3 100644 --- a/deps/v8/src/inspector/v8-debugger-agent-impl.h +++ b/deps/v8/src/inspector/v8-debugger-agent-impl.h @@ -24,8 +24,8 @@ class V8InspectorSessionImpl; class V8Regex; class V8StackTraceImpl; -using protocol::ErrorString; using protocol::Maybe; +using protocol::Response; class V8DebuggerAgentImpl : public protocol::Debugger::Backend { public: @@ -49,67 +49,69 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend { 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<String16>& optionalURL, - const Maybe<String16>& optionalURLRegex, - const Maybe<int>& optionalColumnNumber, - const Maybe<String16>& optionalCondition, String16*, + Response enable() override; + Response disable() override; + Response setBreakpointsActive(bool active) override; + Response setSkipAllPauses(bool skip) override; + Response setBreakpointByUrl( + int lineNumber, Maybe<String16> optionalURL, + Maybe<String16> optionalURLRegex, Maybe<int> optionalColumnNumber, + Maybe<String16> optionalCondition, String16*, std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) override; - void setBreakpoint( - ErrorString*, std::unique_ptr<protocol::Debugger::Location>, - const Maybe<String16>& optionalCondition, String16*, + Response setBreakpoint( + std::unique_ptr<protocol::Debugger::Location>, + Maybe<String16> optionalCondition, String16*, std::unique_ptr<protocol::Debugger::Location>* actualLocation) override; - void removeBreakpoint(ErrorString*, const String16& breakpointId) override; - void continueToLocation( - ErrorString*, std::unique_ptr<protocol::Debugger::Location>) override; - void searchInContent( - ErrorString*, const String16& scriptId, const String16& query, - const Maybe<bool>& optionalCaseSensitive, - const Maybe<bool>& optionalIsRegex, + Response removeBreakpoint(const String16& breakpointId) override; + Response continueToLocation( + std::unique_ptr<protocol::Debugger::Location>) override; + Response searchInContent( + const String16& scriptId, const String16& query, + Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*) override; - void setScriptSource( - ErrorString*, const String16& inScriptId, const String16& inScriptSource, - const Maybe<bool>& dryRun, + Response getPossibleBreakpoints( + std::unique_ptr<protocol::Debugger::Location> start, + Maybe<protocol::Debugger::Location> end, + std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) + override; + Response setScriptSource( + const String16& inScriptId, const String16& inScriptSource, + Maybe<bool> dryRun, Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames, Maybe<bool>* optOutStackChanged, Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace, Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override; - void restartFrame( - ErrorString*, const String16& callFrameId, + Response restartFrame( + const String16& callFrameId, std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, Maybe<protocol::Runtime::StackTrace>* 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<String16>& objectGroup, - const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& silent, - const Maybe<bool>& returnByValue, const Maybe<bool>& generatePreview, + Response getScriptSource(const String16& scriptId, + String16* scriptSource) override; + Response pause() override; + Response resume() override; + Response stepOver() override; + Response stepInto() override; + Response stepOut() override; + Response setPauseOnExceptions(const String16& pauseState) override; + Response evaluateOnCallFrame( + const String16& callFrameId, const String16& expression, + Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, + Maybe<bool> silent, Maybe<bool> returnByValue, + Maybe<bool> generatePreview, std::unique_ptr<protocol::Runtime::RemoteObject>* result, Maybe<protocol::Runtime::ExceptionDetails>*) override; - void setVariableValue( - ErrorString*, int scopeNumber, const String16& variableName, + Response setVariableValue( + int scopeNumber, const String16& variableName, std::unique_ptr<protocol::Runtime::CallArgument> newValue, const String16& callFrame) override; - void setAsyncCallStackDepth(ErrorString*, int depth) override; - void setBlackboxPatterns( - ErrorString*, + Response setAsyncCallStackDepth(int depth) override; + Response setBlackboxPatterns( std::unique_ptr<protocol::Array<String16>> patterns) override; - void setBlackboxedRanges( - ErrorString*, const String16& scriptId, + Response setBlackboxedRanges( + const String16& scriptId, std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> positions) override; @@ -135,7 +137,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend { SkipPauseRequest didPause(v8::Local<v8::Context>, v8::Local<v8::Value> exception, const std::vector<String16>& hitBreakpoints, - bool isPromiseRejection); + bool isPromiseRejection, bool isUncaught); void didContinue(); void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success); void willExecuteScript(int scriptId); @@ -144,27 +146,25 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend { v8::Isolate* isolate() { return m_isolate; } private: - bool checkEnabled(ErrorString*); - void enable(); + void enableImpl(); SkipPauseRequest shouldSkipExceptionPause(JavaScriptCallFrame* topCallFrame); SkipPauseRequest shouldSkipStepPause(JavaScriptCallFrame* topCallFrame); void schedulePauseOnNextStatementIfSteppingInto(); - std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>> - currentCallFrames(ErrorString*); + Response currentCallFrames( + std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*); std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace(); void changeJavaScriptRecursionLevel(int step); - void setPauseOnExceptionsImpl(ErrorString*, int); + void setPauseOnExceptionsImpl(int); std::unique_ptr<protocol::Debugger::Location> resolveBreakpoint( const String16& breakpointId, const String16& scriptId, const ScriptBreakpoint&, BreakpointSource); - void removeBreakpoint(const String16& breakpointId); - bool assertPaused(ErrorString*); + void removeBreakpointImpl(const String16& breakpointId); void clearBreakDetails(); bool isCurrentCallStackEmptyOrBlackboxed(); @@ -174,7 +174,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend { void internalSetAsyncCallStackDepth(int); void increaseCachedSkipStackGeneration(); - bool setBlackboxPattern(ErrorString*, const String16& pattern); + Response setBlackboxPattern(const String16& pattern); using ScriptsMap = protocol::HashMap<String16, std::unique_ptr<V8DebuggerScript>>; diff --git a/deps/v8/src/inspector/v8-debugger-script.cc b/deps/v8/src/inspector/v8-debugger-script.cc index 485188a48f..ed0c0d63de 100644 --- a/deps/v8/src/inspector/v8-debugger-script.cc +++ b/deps/v8/src/inspector/v8-debugger-script.cc @@ -67,50 +67,66 @@ static String16 calculateHash(const String16& str) { return hash.toString(); } -static v8::Local<v8::Value> GetChecked(v8::Local<v8::Context> context, - v8::Local<v8::Object> object, - const char* name) { - return object - ->Get(context, toV8StringInternalized(context->GetIsolate(), name)) - .ToLocalChecked(); -} +V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, + v8::Local<v8::DebugInterface::Script> script, + bool isLiveEdit) { + m_isolate = script->GetIsolate(); + m_id = String16::fromInteger(script->Id()); + v8::Local<v8::String> tmp; + if (script->Name().ToLocal(&tmp)) m_url = toProtocolString(tmp); + if (script->SourceURL().ToLocal(&tmp)) { + m_sourceURL = toProtocolString(tmp); + if (m_url.isEmpty()) m_url = toProtocolString(tmp); + } + if (script->SourceMappingURL().ToLocal(&tmp)) + m_sourceMappingURL = toProtocolString(tmp); + m_startLine = script->LineOffset(); + m_startColumn = script->ColumnOffset(); + std::vector<int> lineEnds = script->LineEnds(); + CHECK(lineEnds.size()); + int source_length = lineEnds[lineEnds.size() - 1]; + if (lineEnds.size()) { + m_endLine = static_cast<int>(lineEnds.size()) + m_startLine - 1; + if (lineEnds.size() > 1) { + m_endColumn = source_length - lineEnds[lineEnds.size() - 2] - 1; + } else { + m_endColumn = source_length + m_startColumn; + } + } else { + m_endLine = m_startLine; + m_endColumn = m_startColumn; + } -static int GetCheckedInt(v8::Local<v8::Context> context, - v8::Local<v8::Object> object, const char* name) { - return static_cast<int>(GetChecked(context, object, name) - ->ToInteger(context) - .ToLocalChecked() - ->Value()); -} + if (script->ContextData().ToLocal(&tmp)) { + String16 contextData = toProtocolString(tmp); + size_t firstComma = contextData.find(",", 0); + size_t secondComma = firstComma != String16::kNotFound + ? contextData.find(",", firstComma + 1) + : String16::kNotFound; + if (secondComma != String16::kNotFound) { + String16 executionContextId = + contextData.substring(firstComma + 1, secondComma - firstComma - 1); + bool isOk = false; + m_executionContextId = executionContextId.toInteger(&isOk); + if (!isOk) m_executionContextId = 0; + m_executionContextAuxData = contextData.substring(secondComma + 1); + } + } -V8DebuggerScript::V8DebuggerScript(v8::Local<v8::Context> context, - v8::Local<v8::Object> object, - bool isLiveEdit) { - v8::Isolate* isolate = context->GetIsolate(); - v8::Local<v8::Value> 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<v8::Value> sourceValue; - if (!object->Get(context, toV8StringInternalized(isolate, "source")) - .ToLocal(&sourceValue) || - !sourceValue->IsString()) - return; - setSource(isolate, sourceValue.As<v8::String>()); + if (script->Source().ToLocal(&tmp)) { + m_source.Reset(m_isolate, tmp); + String16 source = toProtocolString(tmp); + m_hash = calculateHash(source); + // V8 will not count last line if script source ends with \n. + if (source.length() > 1 && source[source.length() - 1] == '\n') { + m_endLine++; + m_endColumn = 0; + } + } + + m_script.Reset(m_isolate, script); } V8DebuggerScript::~V8DebuggerScript() {} @@ -131,10 +147,18 @@ void V8DebuggerScript::setSourceMappingURL(const String16& sourceMappingURL) { m_sourceMappingURL = sourceMappingURL; } -void V8DebuggerScript::setSource(v8::Isolate* isolate, - v8::Local<v8::String> source) { - m_source.Reset(isolate, source); +void V8DebuggerScript::setSource(v8::Local<v8::String> source) { + m_source.Reset(m_isolate, source); m_hash = calculateHash(toProtocolString(source)); } +bool V8DebuggerScript::getPossibleBreakpoints( + const v8::DebugInterface::Location& start, + const v8::DebugInterface::Location& end, + std::vector<v8::DebugInterface::Location>* locations) { + v8::HandleScope scope(m_isolate); + v8::Local<v8::DebugInterface::Script> script = m_script.Get(m_isolate); + return script->GetPossibleBreakpoints(start, end, locations); +} + } // namespace v8_inspector diff --git a/deps/v8/src/inspector/v8-debugger-script.h b/deps/v8/src/inspector/v8-debugger-script.h index 78c44b5eb9..97b5ba9e51 100644 --- a/deps/v8/src/inspector/v8-debugger-script.h +++ b/deps/v8/src/inspector/v8-debugger-script.h @@ -34,12 +34,14 @@ #include "src/inspector/string-16.h" #include "include/v8.h" +#include "src/debug/debug-interface.h" namespace v8_inspector { class V8DebuggerScript { public: - V8DebuggerScript(v8::Local<v8::Context>, v8::Local<v8::Object>, + V8DebuggerScript(v8::Isolate* isolate, + v8::Local<v8::DebugInterface::Script> script, bool isLiveEdit); ~V8DebuggerScript(); @@ -62,7 +64,12 @@ class V8DebuggerScript { void setSourceURL(const String16&); void setSourceMappingURL(const String16&); - void setSource(v8::Isolate*, v8::Local<v8::String>); + void setSource(v8::Local<v8::String>); + + bool getPossibleBreakpoints( + const v8::DebugInterface::Location& start, + const v8::DebugInterface::Location& end, + std::vector<v8::DebugInterface::Location>* locations); private: String16 m_id; @@ -79,6 +86,9 @@ class V8DebuggerScript { String16 m_executionContextAuxData; bool m_isLiveEdit; + v8::Isolate* m_isolate; + v8::Global<v8::DebugInterface::Script> m_script; + DISALLOW_COPY_AND_ASSIGN(V8DebuggerScript); }; diff --git a/deps/v8/src/inspector/v8-debugger.cc b/deps/v8/src/inspector/v8-debugger.cc index d393f81ad4..b3657e577c 100644 --- a/deps/v8/src/inspector/v8-debugger.cc +++ b/deps/v8/src/inspector/v8-debugger.cc @@ -14,11 +14,11 @@ #include "src/inspector/v8-stack-trace-impl.h" #include "src/inspector/v8-value-copier.h" +#include "include/v8-util.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"; @@ -55,7 +55,8 @@ V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) m_breakpointsActivated(true), m_runningNestedMessageLoop(false), m_ignoreScriptParsedEventsCounter(0), - m_maxAsyncCallStackDepth(0) {} + m_maxAsyncCallStackDepth(0), + m_pauseOnExceptionsState(v8::DebugInterface::NoBreakOnException) {} V8Debugger::~V8Debugger() {} @@ -63,9 +64,14 @@ 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)); + v8::DebugInterface::SetDebugEventListener(m_isolate, + &V8Debugger::v8DebugEventCallback, + v8::External::New(m_isolate, this)); + m_debuggerContext.Reset(m_isolate, + v8::DebugInterface::GetDebugContext(m_isolate)); + v8::DebugInterface::ChangeBreakOnException( + m_isolate, v8::DebugInterface::NoBreakOnException); + m_pauseOnExceptionsState = v8::DebugInterface::NoBreakOnException; compileDebuggerScript(); } @@ -76,7 +82,7 @@ void V8Debugger::disable() { m_debuggerScript.Reset(); m_debuggerContext.Reset(); allAsyncTasksCanceled(); - v8::Debug::SetDebugEventListener(m_isolate, nullptr); + v8::DebugInterface::SetDebugEventListener(m_isolate, nullptr); } bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } @@ -112,29 +118,20 @@ void V8Debugger::getCompiledScripts( int contextGroupId, std::vector<std::unique_ptr<V8DebuggerScript>>& result) { v8::HandleScope scope(m_isolate); - v8::MicrotasksScope microtasks(m_isolate, - v8::MicrotasksScope::kDoNotRunMicrotasks); - v8::Local<v8::Context> context = debuggerContext(); - v8::Local<v8::Object> debuggerScript = m_debuggerScript.Get(m_isolate); - DCHECK(!debuggerScript->IsUndefined()); - v8::Local<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast( - debuggerScript - ->Get(context, toV8StringInternalized(m_isolate, "getScripts")) - .ToLocalChecked()); - v8::Local<v8::Value> argv[] = {v8::Integer::New(m_isolate, contextGroupId)}; - v8::Local<v8::Value> value; - if (!getScriptsFunction->Call(context, debuggerScript, arraysize(argv), argv) - .ToLocal(&value)) - return; - DCHECK(value->IsArray()); - v8::Local<v8::Array> scriptsArray = v8::Local<v8::Array>::Cast(value); - result.reserve(scriptsArray->Length()); - for (unsigned i = 0; i < scriptsArray->Length(); ++i) { - v8::Local<v8::Object> scriptObject = v8::Local<v8::Object>::Cast( - scriptsArray->Get(context, v8::Integer::New(m_isolate, i)) - .ToLocalChecked()); - result.push_back(wrapUnique( - new V8DebuggerScript(context, scriptObject, inLiveEditScope))); + v8::PersistentValueVector<v8::DebugInterface::Script> scripts(m_isolate); + v8::DebugInterface::GetLoadedScripts(m_isolate, scripts); + String16 contextPrefix = String16::fromInteger(contextGroupId) + ","; + for (size_t i = 0; i < scripts.Size(); ++i) { + v8::Local<v8::DebugInterface::Script> script = scripts.Get(i); + if (!script->WasCompiled()) continue; + v8::ScriptOriginOptions origin = script->OriginOptions(); + if (origin.IsEmbedderDebugScript()) continue; + v8::Local<v8::String> v8ContextData; + if (!script->ContextData().ToLocal(&v8ContextData)) continue; + String16 contextData = toProtocolString(v8ContextData); + if (contextData.find(contextPrefix) != 0) continue; + result.push_back( + wrapUnique(new V8DebuggerScript(m_isolate, script, false))); } } @@ -171,7 +168,7 @@ String16 V8Debugger::setBreakpoint(const String16& sourceID, ->Get(context, toV8StringInternalized(m_isolate, "setBreakpoint")) .ToLocalChecked()); v8::Local<v8::Value> breakpointId = - v8::Debug::Call(debuggerContext(), setBreakpointFunction, info) + v8::DebugInterface::Call(debuggerContext(), setBreakpointFunction, info) .ToLocalChecked(); if (!breakpointId->IsString()) return ""; *actualLineNumber = @@ -206,7 +203,7 @@ void V8Debugger::removeBreakpoint(const String16& breakpointId) { ->Get(context, toV8StringInternalized(m_isolate, "removeBreakpoint")) .ToLocalChecked()); - v8::Debug::Call(debuggerContext(), removeBreakpointFunction, info) + v8::DebugInterface::Call(debuggerContext(), removeBreakpointFunction, info) .ToLocalChecked(); } @@ -219,7 +216,8 @@ void V8Debugger::clearBreakpoints() { m_debuggerScript.Get(m_isolate) ->Get(context, toV8StringInternalized(m_isolate, "clearBreakpoints")) .ToLocalChecked()); - v8::Debug::Call(debuggerContext(), clearBreakpoints).ToLocalChecked(); + v8::DebugInterface::Call(debuggerContext(), clearBreakpoints) + .ToLocalChecked(); } void V8Debugger::setBreakpointsActivated(bool activated) { @@ -243,42 +241,32 @@ void V8Debugger::setBreakpointsActivated(bool activated) { ->Get(context, toV8StringInternalized(m_isolate, "setBreakpointsActivated")) .ToLocalChecked()); - v8::Debug::Call(debuggerContext(), setBreakpointsActivated, info) + v8::DebugInterface::Call(debuggerContext(), setBreakpointsActivated, info) .ToLocalChecked(); m_breakpointsActivated = activated; } -V8Debugger::PauseOnExceptionsState V8Debugger::getPauseOnExceptionsState() { +v8::DebugInterface::ExceptionBreakState +V8Debugger::getPauseOnExceptionsState() { DCHECK(enabled()); - v8::HandleScope scope(m_isolate); - v8::Local<v8::Context> context = debuggerContext(); - v8::Context::Scope contextScope(context); - - v8::Local<v8::Value> argv[] = {v8::Undefined(m_isolate)}; - v8::Local<v8::Value> result = - callDebuggerMethod("pauseOnExceptionsState", 0, argv).ToLocalChecked(); - return static_cast<V8Debugger::PauseOnExceptionsState>( - result->Int32Value(context).FromJust()); + return m_pauseOnExceptionsState; } void V8Debugger::setPauseOnExceptionsState( - PauseOnExceptionsState pauseOnExceptionsState) { + v8::DebugInterface::ExceptionBreakState pauseOnExceptionsState) { DCHECK(enabled()); - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local<v8::Value> argv[] = { - v8::Int32::New(m_isolate, pauseOnExceptionsState)}; - callDebuggerMethod("setPauseOnExceptionsState", 1, argv); + if (m_pauseOnExceptionsState == pauseOnExceptionsState) return; + v8::DebugInterface::ChangeBreakOnException(m_isolate, pauseOnExceptionsState); + m_pauseOnExceptionsState = pauseOnExceptionsState; } void V8Debugger::setPauseOnNextStatement(bool pause) { if (m_runningNestedMessageLoop) return; if (pause) - v8::Debug::DebugBreak(m_isolate); + v8::DebugInterface::DebugBreak(m_isolate); else - v8::Debug::CancelDebugBreak(m_isolate); + v8::DebugInterface::CancelDebugBreak(m_isolate); } bool V8Debugger::canBreakProgram() { @@ -306,7 +294,7 @@ void V8Debugger::breakProgram() { v8::ConstructorBehavior::kThrow) .ToLocal(&breakFunction)) return; - v8::Debug::Call(debuggerContext(), breakFunction).ToLocalChecked(); + v8::DebugInterface::Call(debuggerContext(), breakFunction).ToLocalChecked(); } void V8Debugger::continueProgram() { @@ -318,52 +306,42 @@ void V8Debugger::continueProgram() { void V8Debugger::stepIntoStatement() { DCHECK(isPaused()); DCHECK(!m_executionState.IsEmpty()); - v8::HandleScope handleScope(m_isolate); - v8::Local<v8::Value> argv[] = {m_executionState}; - callDebuggerMethod(stepIntoV8MethodName, 1, argv); + v8::DebugInterface::PrepareStep(m_isolate, v8::DebugInterface::StepIn); continueProgram(); } void V8Debugger::stepOverStatement() { DCHECK(isPaused()); DCHECK(!m_executionState.IsEmpty()); - v8::HandleScope handleScope(m_isolate); - v8::Local<v8::Value> argv[] = {m_executionState}; - callDebuggerMethod("stepOverStatement", 1, argv); + v8::DebugInterface::PrepareStep(m_isolate, v8::DebugInterface::StepNext); continueProgram(); } void V8Debugger::stepOutOfFunction() { DCHECK(isPaused()); DCHECK(!m_executionState.IsEmpty()); - v8::HandleScope handleScope(m_isolate); - v8::Local<v8::Value> argv[] = {m_executionState}; - callDebuggerMethod(stepOutV8MethodName, 1, argv); + v8::DebugInterface::PrepareStep(m_isolate, v8::DebugInterface::StepOut); continueProgram(); } void V8Debugger::clearStepping() { DCHECK(enabled()); - v8::HandleScope scope(m_isolate); - v8::Context::Scope contextScope(debuggerContext()); - - v8::Local<v8::Value> argv[] = {v8::Undefined(m_isolate)}; - callDebuggerMethod("clearStepping", 0, argv); + v8::DebugInterface::ClearStepping(m_isolate); } -bool V8Debugger::setScriptSource( +Response V8Debugger::setScriptSource( const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, - ErrorString* error, Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, - JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged) { + JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged, + bool* compileError) { class EnableLiveEditScope { public: explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { - v8::Debug::SetLiveEditEnabled(m_isolate, true); + v8::DebugInterface::SetLiveEditEnabled(m_isolate, true); inLiveEditScope = true; } ~EnableLiveEditScope() { - v8::Debug::SetLiveEditEnabled(m_isolate, false); + v8::DebugInterface::SetLiveEditEnabled(m_isolate, false); inLiveEditScope = false; } @@ -371,6 +349,7 @@ bool V8Debugger::setScriptSource( v8::Isolate* m_isolate; }; + *compileError = false; DCHECK(enabled()); v8::HandleScope scope(m_isolate); @@ -391,10 +370,9 @@ bool V8Debugger::setScriptSource( if (tryCatch.HasCaught()) { v8::Local<v8::Message> message = tryCatch.Message(); if (!message.IsEmpty()) - *error = toProtocolStringWithTypeCheck(message->Get()); + return Response::Error(toProtocolStringWithTypeCheck(message->Get())); else - *error = "Unknown error."; - return false; + return Response::InternalError(); } v8result = maybeResult.ToLocalChecked(); } @@ -419,7 +397,7 @@ bool V8Debugger::setScriptSource( JavaScriptCallFrames frames = currentCallFrames(); newCallFrames->swap(frames); } - return true; + return Response::OK(); } // Compile error. case 1: { @@ -441,11 +419,11 @@ bool V8Debugger::setScriptSource( ->Value()) - 1) .build(); - return false; + *compileError = true; + return Response::OK(); } } - *error = "Unknown error."; - return false; + return Response::InternalError(); } JavaScriptCallFrames V8Debugger::currentCallFrames(int limit) { @@ -459,8 +437,8 @@ JavaScriptCallFrames V8Debugger::currentCallFrames(int limit) { toV8StringInternalized(m_isolate, "currentCallFrames")) .ToLocalChecked()); currentCallFramesV8 = - v8::Debug::Call(debuggerContext(), currentCallFramesFunction, - v8::Integer::New(m_isolate, limit)) + v8::DebugInterface::Call(debuggerContext(), currentCallFramesFunction, + v8::Integer::New(m_isolate, limit)) .ToLocalChecked(); } else { v8::Local<v8::Value> argv[] = {m_executionState, @@ -508,7 +486,7 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext, v8::Local<v8::Object> executionState, v8::Local<v8::Value> exception, v8::Local<v8::Array> hitBreakpointNumbers, - bool isPromiseRejection) { + bool isPromiseRejection, bool isUncaught) { // Don't allow nested breaks. if (m_runningNestedMessageLoop) return; @@ -531,7 +509,7 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext, m_pausedContext = pausedContext; m_executionState = executionState; V8DebuggerAgentImpl::SkipPauseRequest result = agent->didPause( - pausedContext, exception, breakpointIds, isPromiseRejection); + pausedContext, exception, breakpointIds, isPromiseRejection, isUncaught); if (result == V8DebuggerAgentImpl::RequestNoSkip) { m_runningNestedMessageLoop = true; int groupId = getGroupId(pausedContext); @@ -547,19 +525,16 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext, m_executionState.Clear(); if (result == V8DebuggerAgentImpl::RequestStepFrame) { - v8::Local<v8::Value> argv[] = {executionState}; - callDebuggerMethod("stepFrameStatement", 1, argv); + v8::DebugInterface::PrepareStep(m_isolate, v8::DebugInterface::StepFrame); } else if (result == V8DebuggerAgentImpl::RequestStepInto) { - v8::Local<v8::Value> argv[] = {executionState}; - callDebuggerMethod(stepIntoV8MethodName, 1, argv); + v8::DebugInterface::PrepareStep(m_isolate, v8::DebugInterface::StepIn); } else if (result == V8DebuggerAgentImpl::RequestStepOut) { - v8::Local<v8::Value> argv[] = {executionState}; - callDebuggerMethod(stepOutV8MethodName, 1, argv); + v8::DebugInterface::PrepareStep(m_isolate, v8::DebugInterface::StepOut); } } void V8Debugger::v8DebugEventCallback( - const v8::Debug::EventDetails& eventDetails) { + const v8::DebugInterface::EventDetails& eventDetails) { V8Debugger* thisPtr = toV8Debugger(eventDetails.GetCallbackData()); thisPtr->handleV8DebugEvent(eventDetails); } @@ -575,12 +550,12 @@ v8::Local<v8::Value> V8Debugger::callInternalGetterFunction( .ToLocalChecked(); DCHECK(!getterValue.IsEmpty() && getterValue->IsFunction()); return v8::Local<v8::Function>::Cast(getterValue) - ->Call(m_isolate->GetCurrentContext(), object, 0, 0) + ->Call(m_isolate->GetCurrentContext(), object, 0, nullptr) .ToLocalChecked(); } void V8Debugger::handleV8DebugEvent( - const v8::Debug::EventDetails& eventDetails) { + const v8::DebugInterface::EventDetails& eventDetails) { if (!enabled()) return; v8::DebugEvent event = eventDetails.GetEvent(); if (event != v8::AsyncTaskEvent && event != v8::Break && @@ -604,26 +579,35 @@ void V8Debugger::handleV8DebugEvent( v8::HandleScope scope(m_isolate); if (m_ignoreScriptParsedEventsCounter == 0 && (event == v8::AfterCompile || event == v8::CompileError)) { - v8::Context::Scope contextScope(debuggerContext()); + v8::Local<v8::Context> context = debuggerContext(); + v8::Context::Scope contextScope(context); v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()}; v8::Local<v8::Value> value = callDebuggerMethod("getAfterCompileScript", 1, argv).ToLocalChecked(); if (value->IsNull()) return; DCHECK(value->IsObject()); v8::Local<v8::Object> scriptObject = v8::Local<v8::Object>::Cast(value); + v8::Local<v8::DebugInterface::Script> script; + if (!v8::DebugInterface::Script::Wrap(m_isolate, scriptObject) + .ToLocal(&script)) + return; agent->didParseSource( - wrapUnique(new V8DebuggerScript(debuggerContext(), scriptObject, - inLiveEditScope)), + wrapUnique(new V8DebuggerScript(m_isolate, script, inLiveEditScope)), event == v8::AfterCompile); } else if (event == v8::Exception) { + v8::Local<v8::Context> context = debuggerContext(); v8::Local<v8::Object> eventData = eventDetails.GetEventData(); v8::Local<v8::Value> exception = callInternalGetterFunction(eventData, "exception"); v8::Local<v8::Value> promise = callInternalGetterFunction(eventData, "promise"); bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); + v8::Local<v8::Value> uncaught = + callInternalGetterFunction(eventData, "uncaught"); + bool isUncaught = uncaught->BooleanValue(context).FromJust(); handleProgramBreak(eventContext, eventDetails.GetExecutionState(), - exception, v8::Local<v8::Array>(), isPromiseRejection); + exception, v8::Local<v8::Array>(), isPromiseRejection, + isUncaught); } else if (event == v8::Break) { v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()}; v8::Local<v8::Value> hitBreakpoints = @@ -729,7 +713,8 @@ v8::MaybeLocal<v8::Value> V8Debugger::functionScopes( v8::MaybeLocal<v8::Array> V8Debugger::internalProperties( v8::Local<v8::Context> context, v8::Local<v8::Value> value) { v8::Local<v8::Array> properties; - if (!v8::Debug::GetInternalProperties(m_isolate, value).ToLocal(&properties)) + if (!v8::DebugInterface::GetInternalProperties(m_isolate, value) + .ToLocal(&properties)) return v8::MaybeLocal<v8::Array>(); if (value->IsFunction()) { v8::Local<v8::Function> function = value.As<v8::Function>(); diff --git a/deps/v8/src/inspector/v8-debugger.h b/deps/v8/src/inspector/v8-debugger.h index 83c1b21b02..4c7477899a 100644 --- a/deps/v8/src/inspector/v8-debugger.h +++ b/deps/v8/src/inspector/v8-debugger.h @@ -8,12 +8,12 @@ #include <vector> #include "src/base/macros.h" +#include "src/debug/debug-interface.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 { @@ -23,7 +23,7 @@ class V8DebuggerAgentImpl; class V8InspectorImpl; class V8StackTraceImpl; -using protocol::ErrorString; +using protocol::Response; class V8Debugger { public: @@ -42,13 +42,8 @@ class V8Debugger { void setBreakpointsActivated(bool); bool breakpointsActivated() const { return m_breakpointsActivated; } - enum PauseOnExceptionsState { - DontPauseOnExceptions, - PauseOnAllExceptions, - PauseOnUncaughtExceptions - }; - PauseOnExceptionsState getPauseOnExceptionsState(); - void setPauseOnExceptionsState(PauseOnExceptionsState); + v8::DebugInterface::ExceptionBreakState getPauseOnExceptionsState(); + void setPauseOnExceptionsState(v8::DebugInterface::ExceptionBreakState); void setPauseOnNextStatement(bool); bool canBreakProgram(); void breakProgram(); @@ -58,12 +53,11 @@ class V8Debugger { void stepOutOfFunction(); void clearStepping(); - bool setScriptSource(const String16& sourceID, - v8::Local<v8::String> newSource, bool dryRun, - ErrorString*, - protocol::Maybe<protocol::Runtime::ExceptionDetails>*, - JavaScriptCallFrames* newCallFrames, - protocol::Maybe<bool>* stackChanged); + Response setScriptSource( + const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, + protocol::Maybe<protocol::Runtime::ExceptionDetails>*, + JavaScriptCallFrames* newCallFrames, protocol::Maybe<bool>* stackChanged, + bool* compileError); JavaScriptCallFrames currentCallFrames(int limit = 0); // Each script inherits debug data from v8::Context where it has been @@ -113,11 +107,12 @@ class V8Debugger { v8::Local<v8::Object> executionState, v8::Local<v8::Value> exception, v8::Local<v8::Array> hitBreakpoints, - bool isPromiseRejection = false); - static void v8DebugEventCallback(const v8::Debug::EventDetails&); + bool isPromiseRejection = false, + bool isUncaught = false); + static void v8DebugEventCallback(const v8::DebugInterface::EventDetails&); v8::Local<v8::Value> callInternalGetterFunction(v8::Local<v8::Object>, const char* functionName); - void handleV8DebugEvent(const v8::Debug::EventDetails&); + void handleV8DebugEvent(const v8::DebugInterface::EventDetails&); void handleV8AsyncTaskEvent(v8::Local<v8::Context>, v8::Local<v8::Object> executionState, v8::Local<v8::Object> eventData); @@ -152,6 +147,8 @@ class V8Debugger { std::vector<std::unique_ptr<V8StackTraceImpl>> m_currentStacks; protocol::HashMap<V8DebuggerAgentImpl*, int> m_maxAsyncCallStackDepthMap; + v8::DebugInterface::ExceptionBreakState m_pauseOnExceptionsState; + DISALLOW_COPY_AND_ASSIGN(V8Debugger); }; diff --git a/deps/v8/src/inspector/v8-heap-profiler-agent-impl.cc b/deps/v8/src/inspector/v8-heap-profiler-agent-impl.cc index 84c890bf3f..0ff04e75b9 100644 --- a/deps/v8/src/inspector/v8-heap-profiler-agent-impl.cc +++ b/deps/v8/src/inspector/v8-heap-profiler-agent-impl.cc @@ -164,39 +164,42 @@ void V8HeapProfilerAgentImpl::restore() { 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<double>(samplingInterval)); + startSampling(Maybe<double>(samplingInterval)); } } -void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*) { +Response V8HeapProfilerAgentImpl::collectGarbage() { m_isolate->LowMemoryNotification(); + return Response::OK(); } -void V8HeapProfilerAgentImpl::startTrackingHeapObjects( - ErrorString*, const protocol::Maybe<bool>& trackAllocations) { +Response V8HeapProfilerAgentImpl::startTrackingHeapObjects( + Maybe<bool> trackAllocations) { m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true); bool allocationTrackingEnabled = trackAllocations.fromMaybe(false); m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, allocationTrackingEnabled); startTrackingHeapObjectsInternal(allocationTrackingEnabled); + return Response::OK(); } -void V8HeapProfilerAgentImpl::stopTrackingHeapObjects( - ErrorString* error, const protocol::Maybe<bool>& reportProgress) { +Response V8HeapProfilerAgentImpl::stopTrackingHeapObjects( + Maybe<bool> reportProgress) { requestHeapStatsUpdate(); - takeHeapSnapshot(error, reportProgress); + takeHeapSnapshot(std::move(reportProgress)); stopTrackingHeapObjectsInternal(); + return Response::OK(); } -void V8HeapProfilerAgentImpl::enable(ErrorString*) { +Response V8HeapProfilerAgentImpl::enable() { m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true); + return Response::OK(); } -void V8HeapProfilerAgentImpl::disable(ErrorString* error) { +Response V8HeapProfilerAgentImpl::disable() { stopTrackingHeapObjectsInternal(); if (m_state->booleanProperty( HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { @@ -205,15 +208,12 @@ void V8HeapProfilerAgentImpl::disable(ErrorString* error) { } m_isolate->GetHeapProfiler()->ClearObjectIds(); m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false); + return Response::OK(); } -void V8HeapProfilerAgentImpl::takeHeapSnapshot( - ErrorString* errorString, const protocol::Maybe<bool>& reportProgress) { +Response V8HeapProfilerAgentImpl::takeHeapSnapshot(Maybe<bool> reportProgress) { v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); - if (!profiler) { - *errorString = "Cannot access v8 heap profiler"; - return; - } + if (!profiler) return Response::Error("Cannot access v8 heap profiler"); std::unique_ptr<HeapSnapshotProgress> progress; if (reportProgress.fromMaybe(false)) progress = wrapUnique(new HeapSnapshotProgress(&m_frontend)); @@ -221,80 +221,62 @@ void V8HeapProfilerAgentImpl::takeHeapSnapshot( GlobalObjectNameResolver resolver(m_session); const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(progress.get(), &resolver); - if (!snapshot) { - *errorString = "Failed to take heap snapshot"; - return; - } + if (!snapshot) return Response::Error("Failed to take heap snapshot"); HeapSnapshotOutputStream stream(&m_frontend); snapshot->Serialize(&stream); const_cast<v8::HeapSnapshot*>(snapshot)->Delete(); + return Response::OK(); } -void V8HeapProfilerAgentImpl::getObjectByHeapObjectId( - ErrorString* error, const String16& heapSnapshotObjectId, - const protocol::Maybe<String16>& objectGroup, +Response V8HeapProfilerAgentImpl::getObjectByHeapObjectId( + const String16& heapSnapshotObjectId, Maybe<String16> objectGroup, std::unique_ptr<protocol::Runtime::RemoteObject>* result) { bool ok; int id = heapSnapshotObjectId.toInteger(&ok); - if (!ok) { - *error = "Invalid heap snapshot object id"; - return; - } + if (!ok) return Response::Error("Invalid heap snapshot object id"); v8::HandleScope handles(m_isolate); v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); - if (heapObject.IsEmpty()) { - *error = "Object is not available"; - return; - } + if (heapObject.IsEmpty()) return Response::Error("Object is not available"); - if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) { - *error = "Object is not available"; - return; - } + if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) + return Response::Error("Object is not available"); *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, objectGroup.fromMaybe(""), false); - if (!result) *error = "Object is not available"; + if (!result) return Response::Error("Object is not available"); + return Response::OK(); } -void V8HeapProfilerAgentImpl::addInspectedHeapObject( - ErrorString* errorString, const String16& inspectedHeapObjectId) { +Response V8HeapProfilerAgentImpl::addInspectedHeapObject( + const String16& inspectedHeapObjectId) { bool ok; int id = inspectedHeapObjectId.toInteger(&ok); - if (!ok) { - *errorString = "Invalid heap snapshot object id"; - return; - } + if (!ok) return Response::Error("Invalid heap snapshot object id"); v8::HandleScope handles(m_isolate); v8::Local<v8::Object> 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; - } + if (heapObject.IsEmpty()) return Response::Error("Object is not available"); + if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) + return Response::Error("Object is not available"); m_session->addInspectedObject(wrapUnique(new InspectableHeapObject(id))); + return Response::OK(); } -void V8HeapProfilerAgentImpl::getHeapObjectId(ErrorString* errorString, - const String16& objectId, - String16* heapSnapshotObjectId) { +Response V8HeapProfilerAgentImpl::getHeapObjectId( + const String16& objectId, String16* heapSnapshotObjectId) { v8::HandleScope handles(m_isolate); v8::Local<v8::Value> value; v8::Local<v8::Context> context; - if (!m_session->unwrapObject(errorString, objectId, &value, &context, - nullptr) || - value->IsUndefined()) - return; + Response response = + m_session->unwrapObject(objectId, &value, &context, nullptr); + if (!response.isSuccess()) return response; + if (value->IsUndefined()) return Response::InternalError(); v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value); *heapSnapshotObjectId = String16::fromInteger(static_cast<size_t>(id)); + return Response::OK(); } void V8HeapProfilerAgentImpl::requestHeapStatsUpdate() { @@ -332,13 +314,10 @@ void V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal() { m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false); } -void V8HeapProfilerAgentImpl::startSampling( - ErrorString* errorString, const Maybe<double>& samplingInterval) { +Response V8HeapProfilerAgentImpl::startSampling( + Maybe<double> samplingInterval) { v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); - if (!profiler) { - *errorString = "Cannot access v8 heap profiler"; - return; - } + if (!profiler) return Response::Error("Cannot access v8 heap profiler"); const unsigned defaultSamplingInterval = 1 << 15; double samplingIntervalValue = samplingInterval.fromMaybe(defaultSamplingInterval); @@ -349,6 +328,7 @@ void V8HeapProfilerAgentImpl::startSampling( profiler->StartSamplingHeapProfiler( static_cast<uint64_t>(samplingIntervalValue), 128, v8::HeapProfiler::kSamplingForceGC); + return Response::OK(); } namespace { @@ -379,14 +359,10 @@ buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node) { } } // namespace -void V8HeapProfilerAgentImpl::stopSampling( - ErrorString* errorString, +Response V8HeapProfilerAgentImpl::stopSampling( std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) { v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); - if (!profiler) { - *errorString = "Cannot access v8 heap profiler"; - return; - } + if (!profiler) return Response::Error("Cannot access v8 heap profiler"); v8::HandleScope scope( m_isolate); // Allocation profile contains Local handles. std::unique_ptr<v8::AllocationProfile> v8Profile( @@ -394,14 +370,13 @@ void V8HeapProfilerAgentImpl::stopSampling( profiler->StopSamplingHeapProfiler(); m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, false); - if (!v8Profile) { - *errorString = "Cannot access v8 sampled heap profile."; - return; - } + if (!v8Profile) + return Response::Error("Cannot access v8 sampled heap profile."); v8::AllocationProfile::Node* root = v8Profile->GetRootNode(); *profile = protocol::HeapProfiler::SamplingHeapProfile::create() .setHead(buildSampingHeapProfileNode(root)) .build(); + return Response::OK(); } } // namespace v8_inspector diff --git a/deps/v8/src/inspector/v8-heap-profiler-agent-impl.h b/deps/v8/src/inspector/v8-heap-profiler-agent-impl.h index caa969870b..e0e244715f 100644 --- a/deps/v8/src/inspector/v8-heap-profiler-agent-impl.h +++ b/deps/v8/src/inspector/v8-heap-profiler-agent-impl.h @@ -15,8 +15,8 @@ namespace v8_inspector { class V8InspectorSessionImpl; -using protocol::ErrorString; using protocol::Maybe; +using protocol::Response; class V8HeapProfilerAgentImpl : public protocol::HeapProfiler::Backend { public: @@ -25,32 +25,26 @@ class V8HeapProfilerAgentImpl : public protocol::HeapProfiler::Backend { ~V8HeapProfilerAgentImpl() override; void restore(); - void collectGarbage(ErrorString*) override; + Response collectGarbage() override; - void enable(ErrorString*) override; - void startTrackingHeapObjects(ErrorString*, - const Maybe<bool>& trackAllocations) override; - void stopTrackingHeapObjects(ErrorString*, - const Maybe<bool>& reportProgress) override; + Response enable() override; + Response startTrackingHeapObjects(Maybe<bool> trackAllocations) override; + Response stopTrackingHeapObjects(Maybe<bool> reportProgress) override; - void disable(ErrorString*) override; + Response disable() override; - void takeHeapSnapshot(ErrorString*, - const Maybe<bool>& reportProgress) override; + Response takeHeapSnapshot(Maybe<bool> reportProgress) override; - void getObjectByHeapObjectId( - ErrorString*, const String16& heapSnapshotObjectId, - const Maybe<String16>& objectGroup, + Response getObjectByHeapObjectId( + const String16& heapSnapshotObjectId, Maybe<String16> objectGroup, std::unique_ptr<protocol::Runtime::RemoteObject>* result) override; - void addInspectedHeapObject(ErrorString*, - const String16& inspectedHeapObjectId) override; - void getHeapObjectId(ErrorString*, const String16& objectId, - String16* heapSnapshotObjectId) override; - - void startSampling(ErrorString*, - const Maybe<double>& samplingInterval) override; - void stopSampling( - ErrorString*, + Response addInspectedHeapObject( + const String16& inspectedHeapObjectId) override; + Response getHeapObjectId(const String16& objectId, + String16* heapSnapshotObjectId) override; + + Response startSampling(Maybe<double> samplingInterval) override; + Response stopSampling( std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>*) override; private: diff --git a/deps/v8/src/inspector/v8-injected-script-host.cc b/deps/v8/src/inspector/v8-injected-script-host.cc index dc41ef8631..3748ec9aa3 100644 --- a/deps/v8/src/inspector/v8-injected-script-host.cc +++ b/deps/v8/src/inspector/v8-injected-script-host.cc @@ -166,12 +166,69 @@ void V8InjectedScriptHost::subtypeCallback( void V8InjectedScriptHost::getInternalPropertiesCallback( const v8::FunctionCallbackInfo<v8::Value>& info) { if (info.Length() < 1) return; - v8::Local<v8::Array> properties; - if (unwrapInspector(info) - ->debugger() - ->internalProperties(info.GetIsolate()->GetCurrentContext(), info[0]) - .ToLocal(&properties)) + + std::unordered_set<String16> allowedProperties; + if (info[0]->IsBooleanObject() || info[0]->IsNumberObject() || + info[0]->IsStringObject() || info[0]->IsSymbolObject()) { + allowedProperties.insert(String16("[[PrimitiveValue]]")); + } else if (info[0]->IsPromise()) { + allowedProperties.insert(String16("[[PromiseStatus]]")); + allowedProperties.insert(String16("[[PromiseValue]]")); + } else if (info[0]->IsGeneratorObject()) { + allowedProperties.insert(String16("[[GeneratorStatus]]")); + } else if (info[0]->IsMapIterator() || info[0]->IsSetIterator()) { + allowedProperties.insert(String16("[[IteratorHasMore]]")); + allowedProperties.insert(String16("[[IteratorIndex]]")); + allowedProperties.insert(String16("[[IteratorKind]]")); + allowedProperties.insert(String16("[[Entries]]")); + } else if (info[0]->IsMap() || info[0]->IsWeakMap() || info[0]->IsSet() || + info[0]->IsWeakSet()) { + allowedProperties.insert(String16("[[Entries]]")); + } + if (!allowedProperties.size()) return; + + v8::Isolate* isolate = info.GetIsolate(); + v8::Local<v8::Array> allProperties; + if (!unwrapInspector(info) + ->debugger() + ->internalProperties(isolate->GetCurrentContext(), info[0]) + .ToLocal(&allProperties) || + !allProperties->IsArray() || allProperties->Length() % 2 != 0) + return; + + { + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + v8::TryCatch tryCatch(isolate); + v8::Isolate::DisallowJavascriptExecutionScope throwJs( + isolate, + v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE); + + v8::Local<v8::Array> properties = v8::Array::New(isolate); + if (tryCatch.HasCaught()) return; + + uint32_t outputIndex = 0; + for (uint32_t i = 0; i < allProperties->Length(); i += 2) { + v8::Local<v8::Value> key; + if (!allProperties->Get(context, i).ToLocal(&key)) continue; + if (tryCatch.HasCaught()) { + tryCatch.Reset(); + continue; + } + String16 keyString = toProtocolStringWithTypeCheck(key); + if (keyString.isEmpty() || + allowedProperties.find(keyString) == allowedProperties.end()) + continue; + v8::Local<v8::Value> value; + if (!allProperties->Get(context, i + 1).ToLocal(&value)) continue; + if (tryCatch.HasCaught()) { + tryCatch.Reset(); + continue; + } + createDataProperty(context, properties, outputIndex++, key); + createDataProperty(context, properties, outputIndex++, value); + } info.GetReturnValue().Set(properties); + } } void V8InjectedScriptHost::objectHasOwnPropertyCallback( diff --git a/deps/v8/src/inspector/v8-inspector-session-impl.cc b/deps/v8/src/inspector/v8-inspector-session-impl.cc index c3d3f48f00..e415575304 100644 --- a/deps/v8/src/inspector/v8-inspector-session-impl.cc +++ b/deps/v8/src/inspector/v8-inspector-session-impl.cc @@ -104,12 +104,11 @@ V8InspectorSessionImpl::V8InspectorSessionImpl(V8InspectorImpl* inspector, } V8InspectorSessionImpl::~V8InspectorSessionImpl() { - ErrorString errorString; - m_consoleAgent->disable(&errorString); - m_profilerAgent->disable(&errorString); - m_heapProfilerAgent->disable(&errorString); - m_debuggerAgent->disable(&errorString); - m_runtimeAgent->disable(&errorString); + m_consoleAgent->disable(); + m_profilerAgent->disable(); + m_heapProfilerAgent->disable(); + m_debuggerAgent->disable(); + m_runtimeAgent->disable(); discardInjectedScripts(); m_inspector->disconnect(this); @@ -165,42 +164,35 @@ void V8InspectorSessionImpl::discardInjectedScripts() { } } -InjectedScript* V8InspectorSessionImpl::findInjectedScript( - ErrorString* errorString, int contextId) { - if (!contextId) { - *errorString = "Cannot find context with specified id"; - return nullptr; - } +Response V8InspectorSessionImpl::findInjectedScript( + int contextId, InjectedScript*& injectedScript) { + injectedScript = nullptr; + if (!contextId) + return Response::Error("Cannot find context with specified id"); const V8InspectorImpl::ContextByIdMap* contexts = m_inspector->contextGroup(m_contextGroupId); - if (!contexts) { - *errorString = "Cannot find context with specified id"; - return nullptr; - } + if (!contexts) + return Response::Error("Cannot find context with specified id"); auto contextsIt = contexts->find(contextId); - if (contextsIt == contexts->end()) { - *errorString = "Cannot find context with specified id"; - return nullptr; - } + if (contextsIt == contexts->end()) + return Response::Error("Cannot find context with specified id"); const std::unique_ptr<InspectedContext>& context = contextsIt->second; if (!context->getInjectedScript()) { - if (!context->createInjectedScript()) { - *errorString = "Cannot access specified execution context"; - return nullptr; - } + if (!context->createInjectedScript()) + return Response::Error("Cannot access specified execution context"); if (m_customObjectFormatterEnabled) context->getInjectedScript()->setCustomObjectFormatterEnabled(true); } - return context->getInjectedScript(); + injectedScript = context->getInjectedScript(); + return Response::OK(); } -InjectedScript* V8InspectorSessionImpl::findInjectedScript( - ErrorString* errorString, RemoteObjectIdBase* objectId) { - return objectId ? findInjectedScript(errorString, objectId->contextId()) - : nullptr; +Response V8InspectorSessionImpl::findInjectedScript( + RemoteObjectIdBase* objectId, InjectedScript*& injectedScript) { + return findInjectedScript(objectId->contextId(), injectedScript); } void V8InspectorSessionImpl::releaseObjectGroup(const StringView& objectGroup) { @@ -230,31 +222,35 @@ bool V8InspectorSessionImpl::unwrapObject( std::unique_ptr<StringBuffer>* error, const StringView& objectId, v8::Local<v8::Value>* object, v8::Local<v8::Context>* context, std::unique_ptr<StringBuffer>* objectGroup) { - ErrorString errorString; String16 objectGroupString; - bool result = - unwrapObject(&errorString, toString16(objectId), object, context, - objectGroup ? &objectGroupString : nullptr); - if (error) *error = StringBufferImpl::adopt(errorString); + Response response = unwrapObject(toString16(objectId), object, context, + objectGroup ? &objectGroupString : nullptr); + if (!response.isSuccess()) { + if (error) { + String16 errorMessage = response.errorMessage(); + *error = StringBufferImpl::adopt(errorMessage); + } + return false; + } if (objectGroup) *objectGroup = StringBufferImpl::adopt(objectGroupString); - return result; + return true; } -bool V8InspectorSessionImpl::unwrapObject(ErrorString* errorString, - const String16& objectId, - v8::Local<v8::Value>* object, - v8::Local<v8::Context>* context, - String16* objectGroup) { - std::unique_ptr<RemoteObjectId> 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; +Response V8InspectorSessionImpl::unwrapObject(const String16& objectId, + v8::Local<v8::Value>* object, + v8::Local<v8::Context>* context, + String16* objectGroup) { + std::unique_ptr<RemoteObjectId> remoteId; + Response response = RemoteObjectId::parse(objectId, &remoteId); + if (!response.isSuccess()) return response; + InjectedScript* injectedScript = nullptr; + response = findInjectedScript(remoteId.get(), injectedScript); + if (!response.isSuccess()) return response; + response = injectedScript->findObject(*remoteId, object); + if (!response.isSuccess()) return response; *context = injectedScript->context()->context(); if (objectGroup) *objectGroup = injectedScript->objectGroupName(*remoteId); - return true; + return Response::OK(); } std::unique_ptr<protocol::Runtime::API::RemoteObject> @@ -269,21 +265,20 @@ V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context, v8::Local<v8::Value> value, const String16& groupName, bool generatePreview) { - ErrorString errorString; - InjectedScript* injectedScript = - findInjectedScript(&errorString, V8Debugger::contextId(context)); + InjectedScript* injectedScript = nullptr; + findInjectedScript(V8Debugger::contextId(context), injectedScript); if (!injectedScript) return nullptr; - return injectedScript->wrapObject(&errorString, value, groupName, false, - generatePreview); + std::unique_ptr<protocol::Runtime::RemoteObject> result; + injectedScript->wrapObject(value, groupName, false, generatePreview, &result); + return result; } std::unique_ptr<protocol::Runtime::RemoteObject> V8InspectorSessionImpl::wrapTable(v8::Local<v8::Context> context, v8::Local<v8::Value> table, v8::Local<v8::Value> columns) { - ErrorString errorString; - InjectedScript* injectedScript = - findInjectedScript(&errorString, V8Debugger::contextId(context)); + InjectedScript* injectedScript = nullptr; + findInjectedScript(V8Debugger::contextId(context), injectedScript); if (!injectedScript) return nullptr; return injectedScript->wrapTable(table, columns); } @@ -386,19 +381,12 @@ void V8InspectorSessionImpl::breakProgram(const StringView& breakReason, } void V8InspectorSessionImpl::setSkipAllPauses(bool skip) { - ErrorString errorString; - m_debuggerAgent->setSkipAllPauses(&errorString, skip); + m_debuggerAgent->setSkipAllPauses(skip); } -void V8InspectorSessionImpl::resume() { - ErrorString errorString; - m_debuggerAgent->resume(&errorString); -} +void V8InspectorSessionImpl::resume() { m_debuggerAgent->resume(); } -void V8InspectorSessionImpl::stepOver() { - ErrorString errorString; - m_debuggerAgent->stepOver(&errorString); -} +void V8InspectorSessionImpl::stepOver() { m_debuggerAgent->stepOver(); } std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>> V8InspectorSessionImpl::searchInTextByLines(const StringView& text, diff --git a/deps/v8/src/inspector/v8-inspector-session-impl.h b/deps/v8/src/inspector/v8-inspector-session-impl.h index e84e8c99a7..af65aa3c93 100644 --- a/deps/v8/src/inspector/v8-inspector-session-impl.h +++ b/deps/v8/src/inspector/v8-inspector-session-impl.h @@ -26,7 +26,7 @@ class V8ProfilerAgentImpl; class V8RuntimeAgentImpl; class V8SchemaAgentImpl; -using protocol::ErrorString; +using protocol::Response; class V8InspectorSessionImpl : public V8InspectorSession, public protocol::FrontendChannel { @@ -44,8 +44,8 @@ class V8InspectorSessionImpl : public V8InspectorSession, V8RuntimeAgentImpl* runtimeAgent() { return m_runtimeAgent.get(); } int contextGroupId() const { return m_contextGroupId; } - InjectedScript* findInjectedScript(ErrorString*, int contextId); - InjectedScript* findInjectedScript(ErrorString*, RemoteObjectIdBase*); + Response findInjectedScript(int contextId, InjectedScript*&); + Response findInjectedScript(RemoteObjectIdBase*, InjectedScript*&); void reset(); void discardInjectedScripts(); void reportAllContexts(V8RuntimeAgentImpl*); @@ -57,9 +57,8 @@ class V8InspectorSessionImpl : public V8InspectorSession, v8::Local<v8::Context>, v8::Local<v8::Value> table, v8::Local<v8::Value> columns); std::vector<std::unique_ptr<protocol::Schema::Domain>> supportedDomainsImpl(); - bool unwrapObject(ErrorString*, const String16& objectId, - v8::Local<v8::Value>*, v8::Local<v8::Context>*, - String16* objectGroup); + Response unwrapObject(const String16& objectId, v8::Local<v8::Value>*, + v8::Local<v8::Context>*, String16* objectGroup); void releaseObjectGroup(const String16& objectGroup); // V8InspectorSession implementation. diff --git a/deps/v8/src/inspector/v8-profiler-agent-impl.cc b/deps/v8/src/inspector/v8-profiler-agent-impl.cc index 0511ca39b5..8b888a066b 100644 --- a/deps/v8/src/inspector/v8-profiler-agent-impl.cc +++ b/deps/v8/src/inspector/v8-profiler-agent-impl.cc @@ -201,34 +201,34 @@ void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) { resolvedTitle); } -void V8ProfilerAgentImpl::enable(ErrorString*) { - if (m_enabled) return; +Response V8ProfilerAgentImpl::enable() { + if (m_enabled) return Response::OK(); m_enabled = true; DCHECK(!m_profiler); m_profiler = v8::CpuProfiler::New(m_isolate); m_state->setBoolean(ProfilerAgentState::profilerEnabled, true); + return Response::OK(); } -void V8ProfilerAgentImpl::disable(ErrorString* errorString) { - if (!m_enabled) return; +Response V8ProfilerAgentImpl::disable() { + if (!m_enabled) return Response::OK(); for (size_t i = m_startedProfiles.size(); i > 0; --i) stopProfiling(m_startedProfiles[i - 1].m_id, false); m_startedProfiles.clear(); - stop(nullptr, nullptr); + stop(nullptr); m_profiler->Dispose(); m_profiler = nullptr; m_enabled = false; m_state->setBoolean(ProfilerAgentState::profilerEnabled, false); + return Response::OK(); } -void V8ProfilerAgentImpl::setSamplingInterval(ErrorString* error, - int interval) { - if (m_recordingCPUProfile) { - *error = "Cannot change sampling interval when profiling."; - return; - } +Response V8ProfilerAgentImpl::setSamplingInterval(int interval) { + if (m_recordingCPUProfile) + return Response::Error("Cannot change sampling interval when profiling."); m_state->setInteger(ProfilerAgentState::samplingInterval, interval); m_profiler->SetSamplingInterval(interval); + return Response::OK(); } void V8ProfilerAgentImpl::restore() { @@ -243,39 +243,34 @@ void V8ProfilerAgentImpl::restore() { if (interval) m_profiler->SetSamplingInterval(interval); if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, false)) { - ErrorString error; - start(&error); + start(); } } -void V8ProfilerAgentImpl::start(ErrorString* error) { - if (m_recordingCPUProfile) return; - if (!m_enabled) { - *error = "Profiler is not enabled"; - return; - } +Response V8ProfilerAgentImpl::start() { + if (m_recordingCPUProfile) return Response::OK(); + if (!m_enabled) return Response::Error("Profiler is not enabled"); m_recordingCPUProfile = true; m_frontendInitiatedProfileId = nextProfileId(); startProfiling(m_frontendInitiatedProfileId); m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true); + return Response::OK(); } -void V8ProfilerAgentImpl::stop( - ErrorString* errorString, +Response V8ProfilerAgentImpl::stop( std::unique_ptr<protocol::Profiler::Profile>* profile) { - if (!m_recordingCPUProfile) { - if (errorString) *errorString = "No recording profiles found"; - return; - } + if (!m_recordingCPUProfile) + return Response::Error("No recording profiles found"); m_recordingCPUProfile = false; std::unique_ptr<protocol::Profiler::Profile> cpuProfile = stopProfiling(m_frontendInitiatedProfileId, !!profile); if (profile) { *profile = std::move(cpuProfile); - if (!profile->get() && errorString) *errorString = "Profile is not found"; + if (!profile->get()) return Response::Error("Profile is not found"); } m_frontendInitiatedProfileId = String16(); m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false); + return Response::OK(); } String16 V8ProfilerAgentImpl::nextProfileId() { diff --git a/deps/v8/src/inspector/v8-profiler-agent-impl.h b/deps/v8/src/inspector/v8-profiler-agent-impl.h index ee8997653a..a634ff3cd9 100644 --- a/deps/v8/src/inspector/v8-profiler-agent-impl.h +++ b/deps/v8/src/inspector/v8-profiler-agent-impl.h @@ -20,7 +20,7 @@ namespace v8_inspector { class V8InspectorSessionImpl; -using protocol::ErrorString; +using protocol::Response; class V8ProfilerAgentImpl : public protocol::Profiler::Backend { public: @@ -31,12 +31,11 @@ class V8ProfilerAgentImpl : public protocol::Profiler::Backend { 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<protocol::Profiler::Profile>*) override; + Response enable() override; + Response disable() override; + Response setSamplingInterval(int) override; + Response start() override; + Response stop(std::unique_ptr<protocol::Profiler::Profile>*) override; void consoleProfile(const String16& title); void consoleProfileEnd(const String16& title); diff --git a/deps/v8/src/inspector/v8-runtime-agent-impl.cc b/deps/v8/src/inspector/v8-runtime-agent-impl.cc index 640ec317d2..4dbe60f8f3 100644 --- a/deps/v8/src/inspector/v8-runtime-agent-impl.cc +++ b/deps/v8/src/inspector/v8-runtime-agent-impl.cc @@ -41,6 +41,7 @@ #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/tracing/trace-event.h" #include "include/v8-inspector.h" @@ -54,11 +55,6 @@ 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 <typename Callback> @@ -71,11 +67,11 @@ class ProtocolPromiseHandler { bool returnByValue, bool generatePreview, std::unique_ptr<Callback> callback) { if (value.IsEmpty()) { - callback->sendFailure("Internal error"); + callback->sendFailure(Response::InternalError()); return; } if (!value.ToLocalChecked()->IsPromise()) { - callback->sendFailure(notPromiseError); + callback->sendFailure(Response::Error(notPromiseError)); return; } v8::MicrotasksScope microtasks_scope(inspector->isolate(), @@ -93,7 +89,7 @@ class ProtocolPromiseHandler { v8::ConstructorBehavior::kThrow) .ToLocalChecked(); if (promise->Then(context, thenCallbackFunction).IsEmpty()) { - rawCallback->sendFailure("Internal error"); + rawCallback->sendFailure(Response::InternalError()); return; } v8::Local<v8::Function> catchCallbackFunction = @@ -101,7 +97,7 @@ class ProtocolPromiseHandler { v8::ConstructorBehavior::kThrow) .ToLocalChecked(); if (promise->Catch(context, catchCallbackFunction).IsEmpty()) { - rawCallback->sendFailure("Internal error"); + rawCallback->sendFailure(Response::InternalError()); return; } } @@ -179,25 +175,27 @@ class ProtocolPromiseHandler { data.GetParameter()->m_wrapper.Reset(); data.SetSecondPassCallback(cleanup); } else { - data.GetParameter()->m_callback->sendFailure("Promise was collected"); + data.GetParameter()->m_callback->sendFailure( + Response::Error("Promise was collected")); delete data.GetParameter(); } } std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject( v8::Local<v8::Value> value) { - ErrorString errorString; - InjectedScript::ContextScope scope(&errorString, m_inspector, - m_contextGroupId, m_executionContextId); - if (!scope.initialize()) { - m_callback->sendFailure(errorString); + InjectedScript::ContextScope scope(m_inspector, m_contextGroupId, + m_executionContextId); + Response response = scope.initialize(); + if (!response.isSuccess()) { + m_callback->sendFailure(response); return nullptr; } - std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue = - scope.injectedScript()->wrapObject(&errorString, value, m_objectGroup, - m_returnByValue, m_generatePreview); - if (!wrappedValue) { - m_callback->sendFailure(errorString); + std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue; + response = scope.injectedScript()->wrapObject( + value, m_objectGroup, m_returnByValue, m_generatePreview, + &wrappedValue); + if (!response.isSuccess()) { + m_callback->sendFailure(response); return nullptr; } return wrappedValue; @@ -222,34 +220,30 @@ bool wrapEvaluateResultAsync(InjectedScript* injectedScript, std::unique_ptr<RemoteObject> result; Maybe<protocol::Runtime::ExceptionDetails> exceptionDetails; - ErrorString errorString; - injectedScript->wrapEvaluateResult( - &errorString, maybeResultValue, tryCatch, objectGroup, returnByValue, - generatePreview, &result, &exceptionDetails); - if (errorString.isEmpty()) { - callback->sendSuccess(std::move(result), exceptionDetails); + Response response = injectedScript->wrapEvaluateResult( + maybeResultValue, tryCatch, objectGroup, returnByValue, generatePreview, + &result, &exceptionDetails); + if (response.isSuccess()) { + callback->sendSuccess(std::move(result), std::move(exceptionDetails)); return true; } - callback->sendFailure(errorString); + callback->sendFailure(response); return false; } -int ensureContext(ErrorString* errorString, V8InspectorImpl* inspector, - int contextGroupId, const Maybe<int>& executionContextId) { - int contextId; +Response ensureContext(V8InspectorImpl* inspector, int contextGroupId, + Maybe<int> executionContextId, int* contextId) { if (executionContextId.isJust()) { - contextId = executionContextId.fromJust(); + *contextId = executionContextId.fromJust(); } else { v8::HandleScope handles(inspector->isolate()); v8::Local<v8::Context> defaultContext = inspector->client()->ensureDefaultContextInGroup(contextGroupId); - if (defaultContext.IsEmpty()) { - *errorString = "Cannot find default execution context"; - return 0; - } - contextId = V8Debugger::contextId(defaultContext); + if (defaultContext.IsEmpty()) + return Response::Error("Cannot find default execution context"); + *contextId = V8Debugger::contextId(defaultContext); } - return contextId; + return Response::OK(); } } // namespace @@ -266,36 +260,33 @@ V8RuntimeAgentImpl::V8RuntimeAgentImpl( V8RuntimeAgentImpl::~V8RuntimeAgentImpl() {} void V8RuntimeAgentImpl::evaluate( - const String16& expression, const Maybe<String16>& objectGroup, - const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& silent, - const Maybe<int>& executionContextId, const Maybe<bool>& returnByValue, - const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture, - const Maybe<bool>& awaitPromise, - std::unique_ptr<EvaluateCallback> callback) { - ErrorString errorString; - int contextId = - ensureContext(&errorString, m_inspector, m_session->contextGroupId(), - executionContextId); - if (!errorString.isEmpty()) { - callback->sendFailure(errorString); + const String16& expression, Maybe<String16> objectGroup, + Maybe<bool> includeCommandLineAPI, Maybe<bool> silent, + Maybe<int> executionContextId, Maybe<bool> returnByValue, + Maybe<bool> generatePreview, Maybe<bool> userGesture, + Maybe<bool> awaitPromise, std::unique_ptr<EvaluateCallback> callback) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "EvaluateScript"); + int contextId = 0; + Response response = ensureContext(m_inspector, m_session->contextGroupId(), + std::move(executionContextId), &contextId); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } - InjectedScript::ContextScope scope(&errorString, m_inspector, - m_session->contextGroupId(), contextId); - if (!scope.initialize()) { - callback->sendFailure(errorString); + InjectedScript::ContextScope scope(m_inspector, m_session->contextGroupId(), + contextId); + response = scope.initialize(); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); if (userGesture.fromMaybe(false)) scope.pretendUserGesture(); - if (includeCommandLineAPI.fromMaybe(false) && - !scope.installCommandLineAPI()) { - callback->sendFailure(errorString); - return; - } + if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed(); // Temporarily enable allow evals for inspector. @@ -312,8 +303,9 @@ void V8RuntimeAgentImpl::evaluate( // Re-initialize after running client's code, as it could have destroyed // context or session. - if (!scope.initialize()) { - callback->sendFailure(errorString); + response = scope.initialize(); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } @@ -333,14 +325,14 @@ void V8RuntimeAgentImpl::evaluate( } void V8RuntimeAgentImpl::awaitPromise( - const String16& promiseObjectId, const Maybe<bool>& returnByValue, - const Maybe<bool>& generatePreview, + const String16& promiseObjectId, Maybe<bool> returnByValue, + Maybe<bool> generatePreview, std::unique_ptr<AwaitPromiseCallback> callback) { - ErrorString errorString; - InjectedScript::ObjectScope scope( - &errorString, m_inspector, m_session->contextGroupId(), promiseObjectId); - if (!scope.initialize()) { - callback->sendFailure(errorString); + InjectedScript::ObjectScope scope(m_inspector, m_session->contextGroupId(), + promiseObjectId); + Response response = scope.initialize(); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } ProtocolPromiseHandler<AwaitPromiseCallback>::add( @@ -353,17 +345,15 @@ void V8RuntimeAgentImpl::awaitPromise( void V8RuntimeAgentImpl::callFunctionOn( const String16& objectId, const String16& expression, - const Maybe<protocol::Array<protocol::Runtime::CallArgument>>& - optionalArguments, - const Maybe<bool>& silent, const Maybe<bool>& returnByValue, - const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture, - const Maybe<bool>& awaitPromise, + Maybe<protocol::Array<protocol::Runtime::CallArgument>> optionalArguments, + Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, + Maybe<bool> userGesture, Maybe<bool> awaitPromise, std::unique_ptr<CallFunctionOnCallback> callback) { - ErrorString errorString; - InjectedScript::ObjectScope scope(&errorString, m_inspector, - m_session->contextGroupId(), objectId); - if (!scope.initialize()) { - callback->sendFailure(errorString); + InjectedScript::ObjectScope scope(m_inspector, m_session->contextGroupId(), + objectId); + Response response = scope.initialize(); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } @@ -376,10 +366,10 @@ void V8RuntimeAgentImpl::callFunctionOn( argv.reset(new v8::Local<v8::Value>[argc]); for (int i = 0; i < argc; ++i) { v8::Local<v8::Value> argumentValue; - if (!scope.injectedScript() - ->resolveCallArgument(&errorString, arguments->get(i)) - .ToLocal(&argumentValue)) { - callback->sendFailure(errorString); + response = scope.injectedScript()->resolveCallArgument(arguments->get(i), + &argumentValue); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } argv[i] = argumentValue; @@ -395,8 +385,9 @@ void V8RuntimeAgentImpl::callFunctionOn( 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); + response = scope.initialize(); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } @@ -410,7 +401,8 @@ void V8RuntimeAgentImpl::callFunctionOn( v8::Local<v8::Value> functionValue; if (!maybeFunctionValue.ToLocal(&functionValue) || !functionValue->IsFunction()) { - callback->sendFailure("Given expression does not evaluate to a function"); + callback->sendFailure( + Response::Error("Given expression does not evaluate to a function")); return; } @@ -419,8 +411,9 @@ void V8RuntimeAgentImpl::callFunctionOn( argv.get()); // Re-initialize after running client's code, as it could have destroyed // context or session. - if (!scope.initialize()) { - callback->sendFailure(errorString); + response = scope.initialize(); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } @@ -441,10 +434,9 @@ void V8RuntimeAgentImpl::callFunctionOn( std::move(callback)); } -void V8RuntimeAgentImpl::getProperties( - ErrorString* errorString, const String16& objectId, - const Maybe<bool>& ownProperties, const Maybe<bool>& accessorPropertiesOnly, - const Maybe<bool>& generatePreview, +Response V8RuntimeAgentImpl::getProperties( + const String16& objectId, Maybe<bool> ownProperties, + Maybe<bool> accessorPropertiesOnly, Maybe<bool> generatePreview, std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>* result, Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>* @@ -452,105 +444,103 @@ void V8RuntimeAgentImpl::getProperties( Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { using protocol::Runtime::InternalPropertyDescriptor; - InjectedScript::ObjectScope scope(errorString, m_inspector, - m_session->contextGroupId(), objectId); - if (!scope.initialize()) return; + InjectedScript::ObjectScope scope(m_inspector, m_session->contextGroupId(), + objectId); + Response response = scope.initialize(); + if (!response.isSuccess()) return response; scope.ignoreExceptionsAndMuteConsole(); - if (!scope.object()->IsObject()) { - *errorString = "Value with given id is not an object"; - return; - } + if (!scope.object()->IsObject()) + return Response::Error("Value with given id is not an object"); v8::Local<v8::Object> object = scope.object().As<v8::Object>(); - 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; + response = scope.injectedScript()->getProperties( + object, scope.objectGroupName(), ownProperties.fromMaybe(false), + accessorPropertiesOnly.fromMaybe(false), generatePreview.fromMaybe(false), + result, exceptionDetails); + if (!response.isSuccess()) return response; + if (exceptionDetails->isJust() || accessorPropertiesOnly.fromMaybe(false)) + return Response::OK(); v8::Local<v8::Array> propertiesArray; - if (hasInternalError(errorString, !m_inspector->debugger() - ->internalProperties(scope.context(), - scope.object()) - .ToLocal(&propertiesArray))) - return; + if (!m_inspector->debugger() + ->internalProperties(scope.context(), scope.object()) + .ToLocal(&propertiesArray)) { + return Response::InternalError(); + } std::unique_ptr<protocol::Array<InternalPropertyDescriptor>> propertiesProtocolArray = protocol::Array<InternalPropertyDescriptor>::create(); for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) { v8::Local<v8::Value> name; - if (hasInternalError( - errorString, - !propertiesArray->Get(scope.context(), i).ToLocal(&name)) || - !name->IsString()) - return; + if (!propertiesArray->Get(scope.context(), i).ToLocal(&name) || + !name->IsString()) { + return Response::InternalError(); + } v8::Local<v8::Value> value; - if (hasInternalError( - errorString, - !propertiesArray->Get(scope.context(), i + 1).ToLocal(&value))) - return; - std::unique_ptr<RemoteObject> wrappedValue = - scope.injectedScript()->wrapObject(errorString, value, - scope.objectGroupName()); - if (!wrappedValue) return; + if (!propertiesArray->Get(scope.context(), i + 1).ToLocal(&value)) + return Response::InternalError(); + std::unique_ptr<RemoteObject> wrappedValue; + protocol::Response response = scope.injectedScript()->wrapObject( + value, scope.objectGroupName(), false, false, &wrappedValue); + if (!response.isSuccess()) return response; propertiesProtocolArray->addItem( InternalPropertyDescriptor::create() .setName(toProtocolString(name.As<v8::String>())) .setValue(std::move(wrappedValue)) .build()); } - if (!propertiesProtocolArray->length()) return; - *internalProperties = std::move(propertiesProtocolArray); + if (propertiesProtocolArray->length()) + *internalProperties = std::move(propertiesProtocolArray); + return Response::OK(); } -void V8RuntimeAgentImpl::releaseObject(ErrorString* errorString, - const String16& objectId) { - InjectedScript::ObjectScope scope(errorString, m_inspector, - m_session->contextGroupId(), objectId); - if (!scope.initialize()) return; +Response V8RuntimeAgentImpl::releaseObject(const String16& objectId) { + InjectedScript::ObjectScope scope(m_inspector, m_session->contextGroupId(), + objectId); + Response response = scope.initialize(); + if (!response.isSuccess()) return response; scope.injectedScript()->releaseObject(objectId); + return Response::OK(); } -void V8RuntimeAgentImpl::releaseObjectGroup(ErrorString*, - const String16& objectGroup) { +Response V8RuntimeAgentImpl::releaseObjectGroup(const String16& objectGroup) { m_session->releaseObjectGroup(objectGroup); + return Response::OK(); } -void V8RuntimeAgentImpl::runIfWaitingForDebugger(ErrorString* errorString) { +Response V8RuntimeAgentImpl::runIfWaitingForDebugger() { m_inspector->client()->runIfWaitingForDebugger(m_session->contextGroupId()); + return Response::OK(); } -void V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(ErrorString*, - bool enabled) { +Response V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(bool enabled) { m_state->setBoolean(V8RuntimeAgentImplState::customObjectFormatterEnabled, enabled); m_session->setCustomObjectFormatterEnabled(enabled); + return Response::OK(); } -void V8RuntimeAgentImpl::discardConsoleEntries(ErrorString*) { +Response V8RuntimeAgentImpl::discardConsoleEntries() { V8ConsoleMessageStorage* storage = m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId()); storage->clear(); + return Response::OK(); } -void V8RuntimeAgentImpl::compileScript( - ErrorString* errorString, const String16& expression, - const String16& sourceURL, bool persistScript, - const Maybe<int>& executionContextId, Maybe<String16>* scriptId, +Response V8RuntimeAgentImpl::compileScript( + const String16& expression, const String16& sourceURL, bool persistScript, + Maybe<int> executionContextId, Maybe<String16>* scriptId, Maybe<protocol::Runtime::ExceptionDetails>* 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 (!m_enabled) return Response::Error("Runtime agent is not enabled"); + + int contextId = 0; + Response response = ensureContext(m_inspector, m_session->contextGroupId(), + std::move(executionContextId), &contextId); + if (!response.isSuccess()) return response; + InjectedScript::ContextScope scope(m_inspector, m_session->contextGroupId(), + contextId); + response = scope.initialize(); + if (!response.isSuccess()) return response; if (!persistScript) m_inspector->debugger()->muteScriptParsedEvents(); v8::Local<v8::Script> script = m_inspector->compileScript( @@ -558,15 +548,17 @@ void V8RuntimeAgentImpl::compileScript( 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 (scope.tryCatch().HasCaught()) { + response = scope.injectedScript()->createExceptionDetails( + scope.tryCatch(), String16(), false, exceptionDetails); + if (!response.isSuccess()) return response; + return Response::OK(); + } else { + return Response::Error("Script compilation failed"); + } } - if (!persistScript) return; + if (!persistScript) return Response::OK(); String16 scriptValueId = String16::fromInteger(script->GetUnboundScript()->GetId()); @@ -574,38 +566,39 @@ void V8RuntimeAgentImpl::compileScript( new v8::Global<v8::Script>(m_inspector->isolate(), script)); m_compiledScripts[scriptValueId] = std::move(global); *scriptId = scriptValueId; + return Response::OK(); } void V8RuntimeAgentImpl::runScript( - const String16& scriptId, const Maybe<int>& executionContextId, - const Maybe<String16>& objectGroup, const Maybe<bool>& silent, - const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& returnByValue, - const Maybe<bool>& generatePreview, const Maybe<bool>& awaitPromise, + const String16& scriptId, Maybe<int> executionContextId, + Maybe<String16> objectGroup, Maybe<bool> silent, + Maybe<bool> includeCommandLineAPI, Maybe<bool> returnByValue, + Maybe<bool> generatePreview, Maybe<bool> awaitPromise, std::unique_ptr<RunScriptCallback> callback) { if (!m_enabled) { - callback->sendFailure("Runtime agent is not enabled"); + callback->sendFailure(Response::Error("Runtime agent is not enabled")); return; } auto it = m_compiledScripts.find(scriptId); if (it == m_compiledScripts.end()) { - callback->sendFailure("No script with given id"); + callback->sendFailure(Response::Error("No script with given id")); return; } - ErrorString errorString; - int contextId = - ensureContext(&errorString, m_inspector, m_session->contextGroupId(), - executionContextId); - if (!errorString.isEmpty()) { - callback->sendFailure(errorString); + int contextId = 0; + Response response = ensureContext(m_inspector, m_session->contextGroupId(), + std::move(executionContextId), &contextId); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } - InjectedScript::ContextScope scope(&errorString, m_inspector, - m_session->contextGroupId(), contextId); - if (!scope.initialize()) { - callback->sendFailure(errorString); + InjectedScript::ContextScope scope(m_inspector, m_session->contextGroupId(), + contextId); + response = scope.initialize(); + if (!response.isSuccess()) { + callback->sendFailure(response); return; } @@ -615,19 +608,22 @@ void V8RuntimeAgentImpl::runScript( m_compiledScripts.erase(it); v8::Local<v8::Script> script = scriptWrapper->Get(m_inspector->isolate()); if (script.IsEmpty()) { - callback->sendFailure("Script execution failed"); + callback->sendFailure(Response::Error("Script execution failed")); return; } - if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI()) - return; + if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); v8::MaybeLocal<v8::Value> 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; + response = scope.initialize(); + if (!response.isSuccess()) { + callback->sendFailure(response); + return; + } if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) { wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue, @@ -649,15 +645,14 @@ void V8RuntimeAgentImpl::restore() { if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false)) return; m_frontend.executionContextsCleared(); - ErrorString error; - enable(&error); + enable(); if (m_state->booleanProperty( V8RuntimeAgentImplState::customObjectFormatterEnabled, false)) m_session->setCustomObjectFormatterEnabled(true); } -void V8RuntimeAgentImpl::enable(ErrorString* errorString) { - if (m_enabled) return; +Response V8RuntimeAgentImpl::enable() { + if (m_enabled) return Response::OK(); m_inspector->client()->beginEnsureAllContextsInGroup( m_session->contextGroupId()); m_enabled = true; @@ -667,12 +662,13 @@ void V8RuntimeAgentImpl::enable(ErrorString* errorString) { V8ConsoleMessageStorage* storage = m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId()); for (const auto& message : storage->messages()) { - if (!reportMessage(message.get(), false)) return; + if (!reportMessage(message.get(), false)) break; } + return Response::OK(); } -void V8RuntimeAgentImpl::disable(ErrorString* errorString) { - if (!m_enabled) return; +Response V8RuntimeAgentImpl::disable() { + if (!m_enabled) return Response::OK(); m_enabled = false; m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, false); m_inspector->disableStackCapturingIfNeeded(); @@ -680,6 +676,7 @@ void V8RuntimeAgentImpl::disable(ErrorString* errorString) { reset(); m_inspector->client()->endEnsureAllContextsInGroup( m_session->contextGroupId()); + return Response::OK(); } void V8RuntimeAgentImpl::reset() { diff --git a/deps/v8/src/inspector/v8-runtime-agent-impl.h b/deps/v8/src/inspector/v8-runtime-agent-impl.h index edeeed47ed..9caa1fba47 100644 --- a/deps/v8/src/inspector/v8-runtime-agent-impl.h +++ b/deps/v8/src/inspector/v8-runtime-agent-impl.h @@ -46,7 +46,7 @@ class V8ConsoleMessage; class V8InspectorImpl; class V8InspectorSessionImpl; -using protocol::ErrorString; +using protocol::Response; using protocol::Maybe; class V8RuntimeAgentImpl : public protocol::Runtime::Backend { @@ -57,51 +57,45 @@ class V8RuntimeAgentImpl : public protocol::Runtime::Backend { void restore(); // Part of the protocol. - void enable(ErrorString*) override; - void disable(ErrorString*) override; - void evaluate(const String16& expression, const Maybe<String16>& objectGroup, - const Maybe<bool>& includeCommandLineAPI, - const Maybe<bool>& silent, const Maybe<int>& executionContextId, - const Maybe<bool>& returnByValue, - const Maybe<bool>& generatePreview, - const Maybe<bool>& userGesture, const Maybe<bool>& awaitPromise, + Response enable() override; + Response disable() override; + void evaluate(const String16& expression, Maybe<String16> objectGroup, + Maybe<bool> includeCommandLineAPI, Maybe<bool> silent, + Maybe<int> executionContextId, Maybe<bool> returnByValue, + Maybe<bool> generatePreview, Maybe<bool> userGesture, + Maybe<bool> awaitPromise, std::unique_ptr<EvaluateCallback>) override; - void awaitPromise(const String16& promiseObjectId, - const Maybe<bool>& returnByValue, - const Maybe<bool>& generatePreview, + void awaitPromise(const String16& promiseObjectId, Maybe<bool> returnByValue, + Maybe<bool> generatePreview, std::unique_ptr<AwaitPromiseCallback>) override; void callFunctionOn( const String16& objectId, const String16& expression, - const Maybe<protocol::Array<protocol::Runtime::CallArgument>>& - optionalArguments, - const Maybe<bool>& silent, const Maybe<bool>& returnByValue, - const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture, - const Maybe<bool>& awaitPromise, + Maybe<protocol::Array<protocol::Runtime::CallArgument>> optionalArguments, + Maybe<bool> silent, Maybe<bool> returnByValue, + Maybe<bool> generatePreview, Maybe<bool> userGesture, + Maybe<bool> awaitPromise, std::unique_ptr<CallFunctionOnCallback>) override; - void releaseObject(ErrorString*, const String16& objectId) override; - void getProperties( - ErrorString*, const String16& objectId, const Maybe<bool>& ownProperties, - const Maybe<bool>& accessorPropertiesOnly, - const Maybe<bool>& generatePreview, + Response releaseObject(const String16& objectId) override; + Response getProperties( + const String16& objectId, Maybe<bool> ownProperties, + Maybe<bool> accessorPropertiesOnly, Maybe<bool> generatePreview, std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>* result, Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>* internalProperties, Maybe<protocol::Runtime::ExceptionDetails>*) 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<int>& executionContextId, Maybe<String16>*, - Maybe<protocol::Runtime::ExceptionDetails>*) override; - void runScript(const String16&, const Maybe<int>& executionContextId, - const Maybe<String16>& objectGroup, const Maybe<bool>& silent, - const Maybe<bool>& includeCommandLineAPI, - const Maybe<bool>& returnByValue, - const Maybe<bool>& generatePreview, - const Maybe<bool>& awaitPromise, + Response releaseObjectGroup(const String16& objectGroup) override; + Response runIfWaitingForDebugger() override; + Response setCustomObjectFormatterEnabled(bool) override; + Response discardConsoleEntries() override; + Response compileScript(const String16& expression, const String16& sourceURL, + bool persistScript, Maybe<int> executionContextId, + Maybe<String16>*, + Maybe<protocol::Runtime::ExceptionDetails>*) override; + void runScript(const String16&, Maybe<int> executionContextId, + Maybe<String16> objectGroup, Maybe<bool> silent, + Maybe<bool> includeCommandLineAPI, Maybe<bool> returnByValue, + Maybe<bool> generatePreview, Maybe<bool> awaitPromise, std::unique_ptr<RunScriptCallback>) override; void reset(); diff --git a/deps/v8/src/inspector/v8-schema-agent-impl.cc b/deps/v8/src/inspector/v8-schema-agent-impl.cc index 9eed5bdf81..d7b6cdcb01 100644 --- a/deps/v8/src/inspector/v8-schema-agent-impl.cc +++ b/deps/v8/src/inspector/v8-schema-agent-impl.cc @@ -16,14 +16,14 @@ V8SchemaAgentImpl::V8SchemaAgentImpl(V8InspectorSessionImpl* session, V8SchemaAgentImpl::~V8SchemaAgentImpl() {} -void V8SchemaAgentImpl::getDomains( - ErrorString*, +Response V8SchemaAgentImpl::getDomains( std::unique_ptr<protocol::Array<protocol::Schema::Domain>>* result) { std::vector<std::unique_ptr<protocol::Schema::Domain>> domains = m_session->supportedDomainsImpl(); *result = protocol::Array<protocol::Schema::Domain>::create(); for (size_t i = 0; i < domains.size(); ++i) (*result)->addItem(std::move(domains[i])); + return Response::OK(); } } // namespace v8_inspector diff --git a/deps/v8/src/inspector/v8-schema-agent-impl.h b/deps/v8/src/inspector/v8-schema-agent-impl.h index 6150201f8b..e733aa0d5a 100644 --- a/deps/v8/src/inspector/v8-schema-agent-impl.h +++ b/deps/v8/src/inspector/v8-schema-agent-impl.h @@ -13,7 +13,7 @@ namespace v8_inspector { class V8InspectorSessionImpl; -using protocol::ErrorString; +using protocol::Response; class V8SchemaAgentImpl : public protocol::Schema::Backend { public: @@ -21,8 +21,7 @@ class V8SchemaAgentImpl : public protocol::Schema::Backend { protocol::DictionaryValue* state); ~V8SchemaAgentImpl() override; - void getDomains( - ErrorString*, + Response getDomains( std::unique_ptr<protocol::Array<protocol::Schema::Domain>>*) override; private: diff --git a/deps/v8/src/inspector/v8-value-copier.cc b/deps/v8/src/inspector/v8-value-copier.cc index 09d86b7b98..fcaeb618ca 100644 --- a/deps/v8/src/inspector/v8-value-copier.cc +++ b/deps/v8/src/inspector/v8-value-copier.cc @@ -73,6 +73,96 @@ class V8ValueCopier { int m_calls; }; +protocol::Response toProtocolValue(v8::Local<v8::Context> context, + v8::Local<v8::Value> value, int maxDepth, + std::unique_ptr<protocol::Value>* result) { + using protocol::Response; + if (value.IsEmpty()) { + UNREACHABLE(); + return Response::InternalError(); + } + + if (!maxDepth) return Response::Error("Object reference chain is too long"); + maxDepth--; + + if (value->IsNull() || value->IsUndefined()) { + *result = protocol::Value::null(); + return Response::OK(); + } + if (value->IsBoolean()) { + *result = + protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value()); + return Response::OK(); + } + if (value->IsNumber()) { + double doubleValue = value.As<v8::Number>()->Value(); + int intValue = static_cast<int>(doubleValue); + if (intValue == doubleValue) { + *result = protocol::FundamentalValue::create(intValue); + return Response::OK(); + } + *result = protocol::FundamentalValue::create(doubleValue); + return Response::OK(); + } + if (value->IsString()) { + *result = + protocol::StringValue::create(toProtocolString(value.As<v8::String>())); + return Response::OK(); + } + if (value->IsArray()) { + v8::Local<v8::Array> array = value.As<v8::Array>(); + std::unique_ptr<protocol::ListValue> inspectorArray = + protocol::ListValue::create(); + uint32_t length = array->Length(); + for (uint32_t i = 0; i < length; i++) { + v8::Local<v8::Value> value; + if (!array->Get(context, i).ToLocal(&value)) + return Response::InternalError(); + std::unique_ptr<protocol::Value> element; + Response response = toProtocolValue(context, value, maxDepth, &element); + if (!response.isSuccess()) return response; + inspectorArray->pushValue(std::move(element)); + } + *result = std::move(inspectorArray); + return Response::OK(); + } + if (value->IsObject()) { + std::unique_ptr<protocol::DictionaryValue> jsonObject = + protocol::DictionaryValue::create(); + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); + v8::Local<v8::Array> propertyNames; + if (!object->GetPropertyNames(context).ToLocal(&propertyNames)) + return Response::InternalError(); + uint32_t length = propertyNames->Length(); + for (uint32_t i = 0; i < length; i++) { + v8::Local<v8::Value> name; + if (!propertyNames->Get(context, i).ToLocal(&name)) + return Response::InternalError(); + // FIXME(yurys): v8::Object should support GetOwnPropertyNames + if (name->IsString()) { + v8::Maybe<bool> hasRealNamedProperty = object->HasRealNamedProperty( + context, v8::Local<v8::String>::Cast(name)); + if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust()) + continue; + } + v8::Local<v8::String> propertyName; + if (!name->ToString(context).ToLocal(&propertyName)) continue; + v8::Local<v8::Value> property; + if (!object->Get(context, name).ToLocal(&property)) + return Response::InternalError(); + std::unique_ptr<protocol::Value> propertyValue; + Response response = + toProtocolValue(context, property, maxDepth, &propertyValue); + if (!response.isSuccess()) return response; + jsonObject->setValue(toProtocolString(propertyName), + std::move(propertyValue)); + } + *result = std::move(jsonObject); + return Response::OK(); + } + return Response::Error("Object couldn't be returned by value"); +} + } // namespace v8::MaybeLocal<v8::Value> copyValueFromDebuggerContext( @@ -107,4 +197,10 @@ v8::Maybe<bool> createDataProperty(v8::Local<v8::Context> context, return array->CreateDataProperty(context, index, value); } +protocol::Response toProtocolValue(v8::Local<v8::Context> context, + v8::Local<v8::Value> value, + std::unique_ptr<protocol::Value>* result) { + return toProtocolValue(context, value, 1000, result); +} + } // namespace v8_inspector diff --git a/deps/v8/src/inspector/v8-value-copier.h b/deps/v8/src/inspector/v8-value-copier.h index c24a5648a2..ee887e5ad4 100644 --- a/deps/v8/src/inspector/v8-value-copier.h +++ b/deps/v8/src/inspector/v8-value-copier.h @@ -5,6 +5,8 @@ #ifndef V8_INSPECTOR_V8VALUECOPIER_H_ #define V8_INSPECTOR_V8VALUECOPIER_H_ +#include "src/inspector/protocol/Protocol.h" + #include "include/v8.h" namespace v8_inspector { @@ -19,6 +21,9 @@ v8::Maybe<bool> createDataProperty(v8::Local<v8::Context>, v8::Maybe<bool> createDataProperty(v8::Local<v8::Context>, v8::Local<v8::Array>, int index, v8::Local<v8::Value>); +protocol::Response toProtocolValue(v8::Local<v8::Context>, v8::Local<v8::Value>, + std::unique_ptr<protocol::Value>* result); + } // namespace v8_inspector #endif // V8_INSPECTOR_V8VALUECOPIER_H_ |