[inspector] migrate scriptParsed and getCompiledScripts to native

* Introduced DebugInterface::Script - native wrapper on internal::Script.
* Migrated getCompildScripts and scriptParsed to native wrapper.

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

Review-Url: https://codereview.chromium.org/2449213002
Cr-Commit-Position: refs/heads/master@{#40660}
This commit is contained in:
kozyatinskiy 2016-10-28 19:17:38 -07:00 committed by Commit bot
parent 6df8096a00
commit f7f591ab6b
9 changed files with 1005 additions and 146 deletions

View File

@ -8829,6 +8829,133 @@ void DebugInterface::ClearStepping(Isolate* v8_isolate) {
isolate->debug()->ClearStepping();
}
v8::Isolate* DebugInterface::Script::GetIsolate() const {
return reinterpret_cast<v8::Isolate*>(Utils::OpenHandle(this)->GetIsolate());
}
ScriptOriginOptions DebugInterface::Script::OriginOptions() const {
return Utils::OpenHandle(this)->origin_options();
}
bool DebugInterface::Script::WasCompiled() const {
return Utils::OpenHandle(this)->compilation_state() ==
i::Script::COMPILATION_STATE_COMPILED;
}
int DebugInterface::Script::Id() const { return Utils::OpenHandle(this)->id(); }
int DebugInterface::Script::LineOffset() const {
return Utils::OpenHandle(this)->line_offset();
}
int DebugInterface::Script::ColumnOffset() const {
return Utils::OpenHandle(this)->column_offset();
}
std::vector<int> DebugInterface::Script::LineEnds() const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
i::HandleScope scope(isolate);
i::Script::InitLineEnds(Utils::OpenHandle(this));
i::Handle<i::Object> line_ends_obj(Utils::OpenHandle(this)->line_ends(),
isolate);
std::vector<int> result;
if (!line_ends_obj->IsFixedArray()) return result;
i::Handle<i::FixedArray> line_ends =
i::Handle<i::FixedArray>::cast(line_ends_obj);
for (int i = 0; i < line_ends->length(); ++i) {
i::Handle<i::Object> line_end = i::FixedArray::get(*line_ends, i, isolate);
if (line_end->IsSmi()) {
result.push_back(i::Handle<i::Smi>::cast(line_end)->value());
} else {
result.push_back(0);
}
}
return result;
}
MaybeLocal<String> DebugInterface::Script::Name() const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
i::HandleScope handle_scope(isolate);
i::Handle<i::Script> script = Utils::OpenHandle(this);
i::Handle<i::Object> value(script->name(), isolate);
if (!value->IsString()) return MaybeLocal<String>();
return Utils::ToLocal(
handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
}
MaybeLocal<String> DebugInterface::Script::SourceURL() const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
i::HandleScope handle_scope(isolate);
i::Handle<i::Script> script = Utils::OpenHandle(this);
i::Handle<i::Object> value(script->source_url(), isolate);
if (!value->IsString()) return MaybeLocal<String>();
return Utils::ToLocal(
handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
}
MaybeLocal<String> DebugInterface::Script::SourceMappingURL() const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
i::HandleScope handle_scope(isolate);
i::Handle<i::Script> script = Utils::OpenHandle(this);
i::Handle<i::Object> value(script->source_mapping_url(), isolate);
if (!value->IsString()) return MaybeLocal<String>();
return Utils::ToLocal(
handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
}
MaybeLocal<String> DebugInterface::Script::ContextData() const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
i::HandleScope handle_scope(isolate);
i::Handle<i::Script> script = Utils::OpenHandle(this);
i::Handle<i::Object> value(script->context_data(), isolate);
if (!value->IsString()) return MaybeLocal<String>();
return Utils::ToLocal(
handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
}
MaybeLocal<String> DebugInterface::Script::Source() const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
i::HandleScope handle_scope(isolate);
i::Handle<i::Script> script = Utils::OpenHandle(this);
i::Handle<i::Object> value(script->source(), isolate);
if (!value->IsString()) return MaybeLocal<String>();
return Utils::ToLocal(
handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
}
MaybeLocal<DebugInterface::Script> DebugInterface::Script::Wrap(
v8::Isolate* v8_isolate, v8::Local<v8::Object> script) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
ENTER_V8(isolate);
i::HandleScope handle_scope(isolate);
i::Handle<i::JSReceiver> script_receiver(Utils::OpenHandle(*script));
if (!script_receiver->IsJSValue()) return MaybeLocal<Script>();
i::Handle<i::Object> script_value(
i::Handle<i::JSValue>::cast(script_receiver)->value(), isolate);
if (!script_value->IsScript()) {
return MaybeLocal<Script>();
}
i::Handle<i::Script> script_obj = i::Handle<i::Script>::cast(script_value);
if (script_obj->type() != i::Script::TYPE_NORMAL) return MaybeLocal<Script>();
return ToApiHandle<DebugInterface::Script>(
handle_scope.CloseAndEscape(script_obj));
}
void DebugInterface::GetLoadedScripts(
v8::Isolate* v8_isolate,
PersistentValueVector<DebugInterface::Script>& scripts) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
ENTER_V8(isolate);
i::HandleScope handle_scope(isolate);
i::Handle<i::FixedArray> instances = isolate->debug()->GetLoadedScripts();
for (int i = 0; i < instances->length(); i++) {
i::Handle<i::Script> script =
i::Handle<i::Script>(i::Script::cast(instances->get(i)));
if (script->type() != i::Script::TYPE_NORMAL) continue;
scripts.Append(ToApiHandle<Script>(script));
}
}
Local<String> CpuProfileNode::GetFunctionName() const {
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
i::Isolate* isolate = node->isolate();

View File

@ -7,6 +7,7 @@
#include "include/v8-testing.h"
#include "src/contexts.h"
#include "src/debug/debug-interface.h"
#include "src/factory.h"
#include "src/isolate.h"
#include "src/list.h"
@ -108,7 +109,8 @@ class RegisteredExtension {
V(StackTrace, JSArray) \
V(StackFrame, JSObject) \
V(Proxy, JSProxy) \
V(NativeWeakMap, JSWeakMap)
V(NativeWeakMap, JSWeakMap) \
V(DebugInterface::Script, Script)
class Utils {
public:

View File

@ -6,6 +6,7 @@
#define V8_DEBUG_DEBUG_INTERFACE_H_
#include "include/v8-debug.h"
#include "include/v8-util.h"
#include "include/v8.h"
namespace v8 {
@ -138,6 +139,43 @@ class DebugInterface {
static void PrepareStep(Isolate* isolate, StepAction action);
static void ClearStepping(Isolate* isolate);
/**
* Native wrapper around v8::internal::Script object.
*/
class Script {
public:
v8::Isolate* GetIsolate() const;
ScriptOriginOptions OriginOptions() const;
bool WasCompiled() const;
int Id() const;
int LineOffset() const;
int ColumnOffset() const;
std::vector<int> LineEnds() const;
MaybeLocal<String> Name() const;
MaybeLocal<String> SourceURL() const;
MaybeLocal<String> SourceMappingURL() const;
MaybeLocal<String> ContextData() const;
MaybeLocal<String> Source() const;
/**
* script parameter is a wrapper v8::internal::JSObject for
* v8::internal::Script.
* This function gets v8::internal::Script from v8::internal::JSObject and
* wraps it with DebugInterface::Script.
* Returns empty local if not called with a valid wrapper of
* v8::internal::Script.
*/
static MaybeLocal<Script> Wrap(Isolate* isolate,
v8::Local<v8::Object> script);
};
/**
* Return array of compiled scripts.
*/
static void GetLoadedScripts(Isolate* isolate,
PersistentValueVector<Script>& scripts);
};
} // namespace v8

View File

@ -40,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;
}
@ -139,82 +139,6 @@ DebuggerScript._executionContextId = function(contextData)
return parseInt(match[1], 10) || 0;
}
/**
* @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

View File

@ -67,50 +67,62 @@ 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();
}
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());
}
V8DebuggerScript::V8DebuggerScript(v8::Local<v8::Context> context,
v8::Local<v8::Object> object,
V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate,
v8::Local<v8::DebugInterface::Script> script,
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_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;
}
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);
}
}
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(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;
}
}
}
V8DebuggerScript::~V8DebuggerScript() {}

View File

@ -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();

View File

@ -14,6 +14,8 @@
#include "src/inspector/v8-stack-trace-impl.h"
#include "src/inspector/v8-value-copier.h"
#include "include/v8-util.h"
namespace v8_inspector {
namespace {
@ -116,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)));
}
}
@ -586,16 +579,20 @@ 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::Object> eventData = eventDetails.GetEventData();

View File

@ -0,0 +1,664 @@
Checks that inspector correctly process compiled scripts
scriptParsed
{
scriptSource : function foo1(){}//# sourceURL=oneline.js<nl>
}
{
endColumn : 0
endLine : 2
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : oneline.js
}
scriptParsed
{
scriptSource : function foo2(){}//# sourceURL=oneline-without-nl.js
}
{
endColumn : 52
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : oneline-without-nl.js
}
scriptParsed
{
scriptSource : function foo3(){}<nl>//# sourceURL=twoline.js<nl>
}
{
endColumn : 0
endLine : 3
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : twoline.js
}
scriptParsed
{
scriptSource : function foo4(){}<nl><nl>//# sourceURL=threeline.js<nl>
}
{
endColumn : 0
endLine : 4
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : threeline.js
}
scriptParsed
{
scriptSource : function foo5(){}//# sourceMappingURL=oneline-map<nl>
}
{
endColumn : 0
endLine : 2
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : oneline-map
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo6(){}//# sourceMappingURL=oneline-without-nl-map
}
{
endColumn : 60
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : oneline-without-nl-map
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo7(){}<nl>//# sourceMappingURL=twoline-map<nl>
}
{
endColumn : 0
endLine : 3
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : twoline-map
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo8(){}<nl><nl>//# sourceMappingURL=threeline-map<nl>
}
{
endColumn : 0
endLine : 4
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : threeline-map
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo9(){}//# sourceMappingURL=source-mapping-url-map<nl>//# sourceURL=source-url.js
}
{
endColumn : 27
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : source-mapping-url-map
startColumn : 0
startLine : 0
url : source-url.js
}
scriptParsed
{
scriptSource : function foo10(){}//# sourceURL=source-url.js<nl>//# sourceMappingURL=source-mapping-url-map
}
{
endColumn : 43
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : source-mapping-url-map
startColumn : 0
startLine : 0
url : source-url.js
}
scriptParsed
{
scriptSource : function foo11(){}<nl>//# sourceURL=end1.js
}
{
endColumn : 21
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : end1.js
}
scriptParsed
{
scriptSource : function foo12(){}<nl>//# sourceURL=end2.js
}
{
endColumn : 22
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : end2.js
}
scriptParsed
{
scriptSource : function foo13(){}
}
{
endColumn : 18
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo15(){}; eval("function foo14(){}//# sourceURL=eval.js")//# sourceURL=eval-wrapper.js
}
{
endColumn : 96
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : eval-wrapper.js
}
scriptParsed
{
scriptSource : function foo14(){}//# sourceURL=eval.js
}
{
endColumn : 39
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : eval.js
}
scriptParsed
{
scriptSource : function foo16(){}<nl>
}
{
endColumn : 0
endLine : 2
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo17(){}<nl><nl>
}
{
endColumn : 0
endLine : 3
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo18(){}<nl><nl><nl>
}
{
endColumn : 0
endLine : 4
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo19(){}<nl><nl><nl><nl>
}
{
endColumn : 0
endLine : 5
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo1(){}//# sourceURL=oneline.js<nl>
}
{
endColumn : 0
endLine : 2
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : oneline.js
}
scriptParsed
{
scriptSource : function foo2(){}//# sourceURL=oneline-without-nl.js
}
{
endColumn : 52
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : oneline-without-nl.js
}
scriptParsed
{
scriptSource : function foo3(){}<nl>//# sourceURL=twoline.js<nl>
}
{
endColumn : 0
endLine : 3
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : twoline.js
}
scriptParsed
{
scriptSource : function foo4(){}<nl><nl>//# sourceURL=threeline.js<nl>
}
{
endColumn : 0
endLine : 4
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : threeline.js
}
scriptParsed
{
scriptSource : function foo5(){}//# sourceMappingURL=oneline-map<nl>
}
{
endColumn : 0
endLine : 2
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : oneline-map
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo6(){}//# sourceMappingURL=oneline-without-nl-map
}
{
endColumn : 60
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : oneline-without-nl-map
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo7(){}<nl>//# sourceMappingURL=twoline-map<nl>
}
{
endColumn : 0
endLine : 3
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : twoline-map
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo8(){}<nl><nl>//# sourceMappingURL=threeline-map<nl>
}
{
endColumn : 0
endLine : 4
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : threeline-map
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo9(){}//# sourceMappingURL=source-mapping-url-map<nl>//# sourceURL=source-url.js
}
{
endColumn : 27
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : source-mapping-url-map
startColumn : 0
startLine : 0
url : source-url.js
}
scriptParsed
{
scriptSource : function foo10(){}//# sourceURL=source-url.js<nl>//# sourceMappingURL=source-mapping-url-map
}
{
endColumn : 43
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL : source-mapping-url-map
startColumn : 0
startLine : 0
url : source-url.js
}
scriptParsed
{
scriptSource : function foo11(){}<nl>//# sourceURL=end1.js
}
{
endColumn : 21
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : end1.js
}
scriptParsed
{
scriptSource : function foo12(){}<nl>//# sourceURL=end2.js
}
{
endColumn : 22
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : end2.js
}
scriptParsed
{
scriptSource : function foo13(){}
}
{
endColumn : 18
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo15(){}; eval("function foo14(){}//# sourceURL=eval.js")//# sourceURL=eval-wrapper.js
}
{
endColumn : 96
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : eval-wrapper.js
}
scriptParsed
{
scriptSource : function foo14(){}//# sourceURL=eval.js
}
{
endColumn : 39
endLine : 0
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url : eval.js
}
scriptFailedToParse
{
scriptSource : }//# sourceURL=failed.js<nl>//# sourceMappingURL=failed-map
}
{
endColumn : 31
endLine : 1
executionContextId : <executionContextId>
hasSourceURL : true
hash : <hash>
scriptId : <scriptId>
sourceMapURL : failed-map
startColumn : 0
startLine : 0
url : failed.js
}
scriptParsed
{
scriptSource : function foo16(){}<nl>
}
{
endColumn : 0
endLine : 2
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo17(){}<nl><nl>
}
{
endColumn : 0
endLine : 3
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo18(){}<nl><nl><nl>
}
{
endColumn : 0
endLine : 4
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
scriptParsed
{
scriptSource : function foo19(){}<nl><nl><nl><nl>
}
{
endColumn : 0
endLine : 5
executionContextId : <executionContextId>
hasSourceURL : false
hash : <hash>
isLiveEdit : false
scriptId : <scriptId>
sourceMapURL :
startColumn : 0
startLine : 0
url :
}
Run gc and then Debugger.enable()..

View File

@ -0,0 +1,93 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose_gc
print("Checks that inspector correctly process compiled scripts");
function addScripts() {
// sourceURL in the same line
return addScript("function foo1(){}//# sourceURL=oneline.js\n")
// sourceURL without end line
.then(() => addScript("function foo2(){}//# sourceURL=oneline-without-nl.js"))
// other source urls
.then(() => addScript("function foo3(){}\n//# sourceURL=twoline.js\n"))
.then(() => addScript("function foo4(){}\n\n//# sourceURL=threeline.js\n"))
// sourceMappingURL in the same line
.then(() => addScript("function foo5(){}//# sourceMappingURL=oneline-map\n"))
// sourceMappingURL without end line
.then(() => addScript("function foo6(){}//# sourceMappingURL=oneline-without-nl-map"))
// other sourceMappingURLs
.then(() => addScript("function foo7(){}\n//# sourceMappingURL=twoline-map\n"))
.then(() => addScript("function foo8(){}\n\n//# sourceMappingURL=threeline-map\n"))
// sourceURL + sourceMappingURL
.then(() => addScript("function foo9(){}//# sourceMappingURL=source-mapping-url-map\n//# sourceURL=source-url.js"))
.then(() => addScript("function foo10(){}//# sourceURL=source-url.js\n//# sourceMappingURL=source-mapping-url-map"))
// non zero endLine and endColumn..
.then(() => addScript("function foo11(){}\n//# sourceURL=end1.js"))
// .. + 1 character
.then(() => addScript("function foo12(){}\n//# sourceURL=end2.js "))
// script without sourceURL
.then(() => addScript("function foo13(){}"))
// script in eval
.then(() => addScript("function foo15(){}; eval(\"function foo14(){}//# sourceURL=eval.js\")//# sourceURL=eval-wrapper.js"))
// sourceURL and sourceMappingURL works even for script with syntax error
.then(() => addScript("}//# sourceURL=failed.js\n//# sourceMappingURL=failed-map"))
// empty lines at end
.then(() => addScript("function foo16(){}\n"))
.then(() => addScript("function foo17(){}\n\n"))
.then(() => addScript("function foo18(){}\n\n\n"))
.then(() => addScript("function foo19(){}\n\n\n\n"));
}
Protocol.Debugger.onScriptParsed((message) => requestSourceAndDump(message, true));
Protocol.Debugger.onScriptFailedToParse((message) => requestSourceAndDump(message, false));
addScripts()
.then(() => Protocol.Debugger.enable())
.then(addScripts)
.then(() => Protocol.Debugger.disable())
.then(() => InspectorTest.log("Run gc and then Debugger.enable().."))
.then(() => Protocol.Runtime.evaluate({ expression: "for (let i = 1; i < 20; ++i) eval(`foo${i} = undefined`); gc();" }))
.then(() => Protocol.Debugger.enable())
.then(InspectorTest.completeTest);
function addScript(source) {
return Protocol.Runtime.evaluate({ expression: source });
}
function requestSourceAndDump(scriptParsedMessage, scriptParsed) {
Protocol.Debugger.getScriptSource({ scriptId: scriptParsedMessage.params.scriptId })
.then((sourceMessage) => dumpScriptParsed(scriptParsedMessage, sourceMessage, scriptParsed));
}
function dumpScriptParsed(scriptParsedMessage, sourceMessage, scriptParsed) {
var params = scriptParsedMessage.params;
var re = /[A-Z0-9]{40,40}/;
if (!params.hash || !matchExact(re, params.hash))
params.hash = "Invalid hash: " + params.hash;
else
params.hash = "<hash>";
if (params.executionContextId <= 0)
params.executionContextId = "Invalid executionContextId: " + params.executionContextId;
else
params.executionContextId = "<executionContextId>";
if (params.scriptId * 1 <= 0)
params.scriptId = "Invalid scriptId: " + params.scriptId;
else
params.scriptId = "<scriptId>";
var sourceResult = sourceMessage.result;
sourceResult.scriptSource = sourceResult.scriptSource.replace(/\n/g, "<nl>");
InspectorTest.log(scriptParsed ? "scriptParsed" : "scriptFailedToParse");
InspectorTest.logObject(sourceResult);
InspectorTest.logObject(params);
}
function matchExact(re, str) {
var match = str.match(re);
return match !== null && str === match[0];
}