[inspector] introduced Script::TYPE_INSPECTOR

Inspector uses this type for all internal scripts, e.g. injected-script-source.js. Scripts with new type are not reported by remote debugging protocol, frames from them are ignored.

CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_precise_blink_rel
BUG=none
R=yangguo@chromium.org,dgozman@chromium.org

Review-Url: https://codereview.chromium.org/2499273003
Cr-Commit-Position: refs/heads/master@{#41056}
This commit is contained in:
kozyatinskiy 2016-11-16 20:39:30 -08:00 committed by Commit bot
parent d4a42a5f89
commit 6808ec1f83
16 changed files with 238 additions and 105 deletions

View File

@ -527,11 +527,10 @@ void Accessors::ScriptIsEmbedderDebugScriptGetter(
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
DisallowHeapAllocation no_allocation;
HandleScope scope(isolate);
Object* object = *Utils::OpenHandle(*info.Holder());
bool is_embedder_debug_script = Script::cast(JSValue::cast(object)->value())
->origin_options()
.IsEmbedderDebugScript();
Object* res = *isolate->factory()->ToBoolean(is_embedder_debug_script);
Object* script_obj = *Utils::OpenHandle(*info.Holder());
Script* script = Script::cast(script_obj);
Script::Type type = static_cast<Script::Type>(script->type());
Object* res = *isolate->factory()->ToBoolean(type == Script::TYPE_INSPECTOR);
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
}

View File

@ -97,6 +97,15 @@ namespace v8 {
ENTER_V8(isolate); \
bool has_pending_exception = false
#define PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, T) \
if (IsExecutionTerminatingCheck(isolate)) { \
return MaybeLocal<T>(); \
} \
InternalEscapableScope handle_scope(isolate); \
CallDepthScope<false> call_depth_scope(isolate, v8::Local<v8::Context>()); \
ENTER_V8(isolate); \
bool has_pending_exception = false
#define PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \
bailout_value, HandleScopeClass, \
do_callback) \
@ -9146,6 +9155,25 @@ DebugInterface::DisassembleWasmFunction(Isolate* v8_isolate,
return i::wasm::DisassembleFunction(compiled_module, function_index);
}
MaybeLocal<UnboundScript> DebugInterface::CompileInspectorScript(
Isolate* v8_isolate, Local<String> source) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, UnboundScript);
i::ScriptData* script_data = NULL;
i::Handle<i::String> str = Utils::OpenHandle(*source);
i::Handle<i::SharedFunctionInfo> result;
{
ScriptOriginOptions origin_options;
result = i::Compiler::GetSharedFunctionInfoForScript(
str, i::Handle<i::Object>(), 0, 0, origin_options,
i::Handle<i::Object>(), isolate->native_context(), NULL, &script_data,
ScriptCompiler::kNoCompileOptions, i::INSPECTOR_CODE, false);
has_pending_exception = result.is_null();
RETURN_ON_FAILED_EXECUTION(UnboundScript);
}
RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
}
Local<String> CpuProfileNode::GetFunctionName() const {
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
i::Isolate* isolate = node->isolate();

View File

@ -1451,6 +1451,9 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
} else if (natives == EXTENSION_CODE) {
script->set_type(Script::TYPE_EXTENSION);
script->set_hide_source(true);
} else if (natives == INSPECTOR_CODE) {
script->set_type(Script::TYPE_INSPECTOR);
script->set_hide_source(true);
}
if (!script_name.is_null()) {
script->set_name(*script_name);

View File

@ -198,9 +198,6 @@ class DebugInterface {
int GetSourcePosition(const Location& location) const;
};
/**
* Return array of compiled scripts.
*/
static void GetLoadedScripts(Isolate* isolate,
PersistentValueVector<Script>& scripts);
@ -213,6 +210,8 @@ class DebugInterface {
static std::pair<std::string, std::vector<std::tuple<uint32_t, int, int>>>
DisassembleWasmFunction(Isolate* isolate, v8::Local<v8::Object> script,
int function_index);
static MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* isolate,
Local<String> source);
};
} // namespace v8

View File

@ -177,10 +177,7 @@ bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
if (frame->is_java_script()) {
JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame);
if (!jsFrame->function()->IsJSFunction()) return false;
Object* script = jsFrame->function()->shared()->script();
// Don't show functions from native scripts to user.
return (script->IsScript() &&
Script::TYPE_NATIVE != Script::cast(script)->type());
return jsFrame->function()->shared()->IsSubjectToDebugging();
}
// apart from javascript, only wasm is valid
return frame->is_wasm();

View File

@ -591,7 +591,12 @@ enum VisitMode {
};
// Flag indicating whether code is built into the VM (one of the natives files).
enum NativesFlag { NOT_NATIVES_CODE, EXTENSION_CODE, NATIVES_CODE };
enum NativesFlag {
NOT_NATIVES_CODE,
EXTENSION_CODE,
NATIVES_CODE,
INSPECTOR_CODE
};
// JavaScript defines two kinds of 'nil'.
enum NilValue { kNullValue, kUndefinedValue };

View File

@ -33,17 +33,6 @@
var DebuggerScript = {};
/**
* @param {?CompileEvent} eventData
*/
DebuggerScript.getAfterCompileScript = function(eventData)
{
var script = eventData.script().value();
if (!script.is_debugger_script)
return script;
return null;
}
/** @type {!Map<!ScopeType, string>} */
DebuggerScript._scopeTypeNames = new Map();
DebuggerScript._scopeTypeNames.set(ScopeType.Global, "global");

View File

@ -18,21 +18,6 @@ var Scope;
}} */
var RawLocation;
/** @typedef {{
id: number,
name: string,
sourceURL: (string|undefined),
sourceMappingURL: (string|undefined),
source: string,
startLine: number,
endLine: number,
startColumn: number,
endColumn: number,
executionContextId: number,
executionContextAuxData: string
}} */
var FormattedScript;
/** @typedef {{
functionName: string,
location: !RawLocation,
@ -173,13 +158,6 @@ BreakPoint.prototype.script_break_point = function() {}
BreakPoint.prototype.number = function() {}
/** @interface */
function CompileEvent() {}
/** @return {!ScriptMirror} */
CompileEvent.prototype.script = function() {}
/** @interface */
function BreakEvent() {}
@ -237,14 +215,6 @@ var SourceLocation;
/** @typedef{{
* id: number,
* context_data: (string|undefined),
* source_url: (string|undefined),
* source_mapping_url: (string|undefined),
* is_debugger_script: boolean,
* source: string,
* line_offset: number,
* column_offset: number,
* nameOrSourceURL: function():string,
* compilationType: function():!ScriptCompilationType,
* }}
*/
var Script;

View File

@ -588,23 +588,15 @@ void V8Debugger::handleV8DebugEvent(
v8::Local<v8::Value> scriptWrapper =
callInternalGetterFunction(scriptMirror.As<v8::Object>(), "value");
DCHECK(scriptWrapper->IsObject());
v8::Local<v8::DebugInterface::Script> script =
v8::DebugInterface::Script::Wrap(m_isolate,
scriptWrapper.As<v8::Object>())
.ToLocalChecked();
v8::Local<v8::DebugInterface::Script> script;
if (!v8::DebugInterface::Script::Wrap(m_isolate,
scriptWrapper.As<v8::Object>())
.ToLocal(&script)) {
return;
}
if (script->IsWasm()) {
m_wasmTranslation.AddScript(scriptWrapper.As<v8::Object>());
} else if (m_ignoreScriptParsedEventsCounter == 0) {
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(m_isolate, script, inLiveEditScope)),
event == v8::AfterCompile);

View File

@ -113,32 +113,29 @@ v8::MaybeLocal<v8::Value> V8InspectorImpl::callFunction(
v8::MaybeLocal<v8::Value> V8InspectorImpl::compileAndRunInternalScript(
v8::Local<v8::Context> context, v8::Local<v8::String> source) {
v8::Local<v8::Script> script =
compileScript(context, source, String16(), true);
if (script.IsEmpty()) return v8::MaybeLocal<v8::Value>();
v8::Local<v8::UnboundScript> unboundScript;
if (!v8::DebugInterface::CompileInspectorScript(m_isolate, source)
.ToLocal(&unboundScript))
return v8::MaybeLocal<v8::Value>();
v8::MicrotasksScope microtasksScope(m_isolate,
v8::MicrotasksScope::kDoNotRunMicrotasks);
return script->Run(context);
v8::Context::Scope contextScope(context);
return unboundScript->BindToCurrentContext()->Run(context);
}
v8::Local<v8::Script> V8InspectorImpl::compileScript(
v8::Local<v8::Context> context, v8::Local<v8::String> code,
const String16& fileName, bool markAsInternal) {
v8::MaybeLocal<v8::Script> V8InspectorImpl::compileScript(
v8::Local<v8::Context> context, const String16& code,
const String16& fileName) {
v8::ScriptOrigin origin(
toV8String(m_isolate, fileName), v8::Integer::New(m_isolate, 0),
v8::Integer::New(m_isolate, 0),
v8::False(m_isolate), // sharable
v8::Local<v8::Integer>(),
v8::Boolean::New(m_isolate, markAsInternal), // internal
toV8String(m_isolate, String16()), // sourceMap
v8::True(m_isolate)); // opaqueresource
v8::ScriptCompiler::Source source(code, origin);
v8::Local<v8::Script> script;
if (!v8::ScriptCompiler::Compile(context, &source,
v8::ScriptCompiler::kNoCompileOptions)
.ToLocal(&script))
return v8::Local<v8::Script>();
return script;
v8::False(m_isolate), // sharable
v8::Local<v8::Integer>(), v8::Boolean::New(m_isolate, false), // internal
toV8String(m_isolate, String16()), // sourceMap
v8::True(m_isolate)); // opaqueresource
v8::ScriptCompiler::Source source(toV8String(m_isolate, code), origin);
return v8::ScriptCompiler::Compile(context, &source,
v8::ScriptCompiler::kNoCompileOptions);
}
void V8InspectorImpl::enableStackCapturingIfNeeded() {

View File

@ -67,10 +67,9 @@ class V8InspectorImpl : public V8Inspector {
int argc, v8::Local<v8::Value> info[]);
v8::MaybeLocal<v8::Value> compileAndRunInternalScript(v8::Local<v8::Context>,
v8::Local<v8::String>);
v8::Local<v8::Script> compileScript(v8::Local<v8::Context>,
v8::Local<v8::String>,
const String16& fileName,
bool markAsInternal);
v8::MaybeLocal<v8::Script> compileScript(v8::Local<v8::Context>,
const String16& code,
const String16& fileName);
v8::Local<v8::Context> regexContext();
// V8Inspector implementation.

View File

@ -293,11 +293,11 @@ void V8RuntimeAgentImpl::evaluate(
if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(true);
v8::MaybeLocal<v8::Value> maybeResultValue;
v8::Local<v8::Script> script = m_inspector->compileScript(
scope.context(), toV8String(m_inspector->isolate(), expression),
String16(), false);
if (!script.IsEmpty())
v8::Local<v8::Script> script;
if (m_inspector->compileScript(scope.context(), expression, String16())
.ToLocal(&script)) {
maybeResultValue = m_inspector->runCompiledScript(scope.context(), script);
}
if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(false);
@ -379,10 +379,14 @@ void V8RuntimeAgentImpl::callFunctionOn(
if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
if (userGesture.fromMaybe(false)) scope.pretendUserGesture();
v8::MaybeLocal<v8::Value> maybeFunctionValue =
m_inspector->compileAndRunInternalScript(
scope.context(),
toV8String(m_inspector->isolate(), "(" + expression + ")"));
v8::MaybeLocal<v8::Value> maybeFunctionValue;
v8::Local<v8::Script> functionScript;
if (m_inspector
->compileScript(scope.context(), "(" + expression + ")", String16())
.ToLocal(&functionScript)) {
maybeFunctionValue =
m_inspector->runCompiledScript(scope.context(), functionScript);
}
// Re-initialize after running client's code, as it could have destroyed
// context or session.
response = scope.initialize();
@ -543,11 +547,11 @@ Response V8RuntimeAgentImpl::compileScript(
if (!response.isSuccess()) return response;
if (!persistScript) m_inspector->debugger()->muteScriptParsedEvents();
v8::Local<v8::Script> script = m_inspector->compileScript(
scope.context(), toV8String(m_inspector->isolate(), expression),
sourceURL, false);
v8::Local<v8::Script> script;
bool isOk = m_inspector->compileScript(scope.context(), expression, sourceURL)
.ToLocal(&script);
if (!persistScript) m_inspector->debugger()->unmuteScriptParsedEvents();
if (script.IsEmpty()) {
if (!isOk) {
if (scope.tryCatch().HasCaught()) {
response = scope.injectedScript()->createExceptionDetails(
scope.tryCatch(), String16(), false, exceptionDetails);

View File

@ -7025,7 +7025,8 @@ class Script: public Struct {
TYPE_NATIVE = 0,
TYPE_EXTENSION = 1,
TYPE_NORMAL = 2,
TYPE_WASM = 3
TYPE_WASM = 3,
TYPE_INSPECTOR = 4
};
// Script compilation types.

View File

@ -0,0 +1,101 @@
Checks that inspector reports script compiled in Runtime.evaluate,Runtime.callFunctionOn and Runtime.compileScript
Runtime.evaluate with valid expression
{
method : Debugger.scriptParsed
params : {
endColumn : 29
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : true
hash : 9D04F7335D1661503EAB9AF3EACAF92020803F34
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : evaluate.js
}
}
Runtime.evaluate with syntax error
{
method : Debugger.scriptFailedToParse
params : {
endColumn : 39
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : true
hash : 9BCA34A10E5386925E74C1716C857BEB02821E15
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : evaluate-syntax-error.js
}
}
Runtime.callFunctionOn with valid functionDeclaration
{
method : Debugger.scriptParsed
params : {
endColumn : 18
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : false
hash : 9D04CEA1B54DF92A01A0498543D429DC872EBA18
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
}
Runtime.callFunctionOn with syntax error
{
method : Debugger.scriptFailedToParse
params : {
endColumn : 3
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : false
hash : 9D04D83251E2B7F64CB5762843D429DC872EBA18
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
}
Runtime.compileScript with valid expression
{
method : Debugger.scriptParsed
params : {
endColumn : 4
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : false
hash : 9D04F733E4E4F1BA4CB5762843D429DC872EBA18
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : compile-script.js
}
}
Runtime.compileScript with syntax error
{
method : Debugger.scriptFailedToParse
params : {
endColumn : 1
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : false
hash : FF746120E4E4F1BA4CB5762843D429DC872EBA18
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : compile-script-syntax-error.js
}
}
Runtime.compileScript persistScript: false (should be no script events)

View File

@ -0,0 +1,49 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
print("Checks that inspector reports script compiled in Runtime.evaluate," +
"Runtime.callFunctionOn and Runtime.compileScript");
Promise.prototype.thenLog = function log(message) {
return this.then(() => InspectorTest.log(message));
}
var objectId;
Protocol.Runtime.enable();
Protocol.Debugger.enable()
.then(() => Protocol.Debugger.onScriptParsed(InspectorTest.logMessage))
.then(() => Protocol.Debugger.onScriptFailedToParse(InspectorTest.logMessage))
.thenLog('Runtime.evaluate with valid expression')
.then(() => Protocol.Runtime.evaluate({
expression: "({})//# sourceURL=evaluate.js"}))
.then(msg => objectId = msg.result.result.objectId)
.thenLog('Runtime.evaluate with syntax error')
.then(() => Protocol.Runtime.evaluate({
expression: "}//# sourceURL=evaluate-syntax-error.js"}))
.thenLog('Runtime.callFunctionOn with valid functionDeclaration')
.then(() => Protocol.Runtime.callFunctionOn({ objectId: objectId,
functionDeclaration: "function foo(){}"}))
.thenLog('Runtime.callFunctionOn with syntax error')
.then(() => Protocol.Runtime.callFunctionOn({ objectId: objectId,
functionDeclaration: "}"}))
.thenLog('Runtime.compileScript with valid expression')
.then(() => Protocol.Runtime.compileScript({ expression: "({})",
sourceURL: "compile-script.js", persistScript: true }))
.thenLog('Runtime.compileScript with syntax error')
.then(() => Protocol.Runtime.compileScript({ expression: "}",
sourceURL: "compile-script-syntax-error.js", persistScript: true }))
.thenLog('Runtime.compileScript persistScript: false (should be no script events)')
.then(() => Protocol.Runtime.compileScript({ expression: "({})",
sourceURL: "compile-script-syntax-error.js", persistScript: false }))
.then(() => Protocol.Runtime.compileScript({ expression: "}",
sourceURL: "compile-script-syntax-error.js", persistScript: false }))
.then(InspectorTest.completeTest);

View File

@ -102,7 +102,7 @@ function callFunctionOn(objectExpression, functionDeclaration, argumentExpressio
var objectId;
var callArguments = [];
var promise = Protocol.Runtime.evaluate({ expression: objectExpression })
.then((result) => objectId = result.result.result.objectId)
.then((result) => objectId = result.result.result.objectId);
for (let argumentExpression of argumentExpressions) {
promise = promise
.then(() => Protocol.Runtime.evaluate({ expression: argumentExpression }))