Commit 50d06155 authored by dgozman's avatar dgozman Committed by Commit bot

[DevTools] Store script source in v8::Global.

This is a preparation step to migrate away from WTF::String in v8_inspector.
To avoid copying the global, this patch moves V8DebuggerScript to the heap.

BUG=580337

Review-Url: https://codereview.chromium.org/2104063002
Cr-Commit-Position: refs/heads/master@{#403320}
parent aa17d834
...@@ -142,7 +142,7 @@ public: ...@@ -142,7 +142,7 @@ public:
// Interface for V8DebuggerImpl // Interface for V8DebuggerImpl
SkipPauseRequest didPause(v8::Local<v8::Context>, v8::Local<v8::Value> exception, const std::vector<String16>& hitBreakpoints, bool isPromiseRejection); SkipPauseRequest didPause(v8::Local<v8::Context>, v8::Local<v8::Value> exception, const std::vector<String16>& hitBreakpoints, bool isPromiseRejection);
void didContinue(); void didContinue();
void didParseSource(const V8DebuggerParsedScript&); void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success);
void willExecuteScript(int scriptId); void willExecuteScript(int scriptId);
void didExecuteScript(); void didExecuteScript();
...@@ -178,7 +178,7 @@ private: ...@@ -178,7 +178,7 @@ private:
bool setBlackboxPattern(ErrorString*, const String16& pattern); bool setBlackboxPattern(ErrorString*, const String16& pattern);
using ScriptsMap = protocol::HashMap<String16, V8DebuggerScript>; using ScriptsMap = protocol::HashMap<String16, std::unique_ptr<V8DebuggerScript>>;
using BreakpointIdToDebuggerBreakpointIdsMap = protocol::HashMap<String16, std::vector<String16>>; using BreakpointIdToDebuggerBreakpointIdsMap = protocol::HashMap<String16, std::vector<String16>>;
using DebugServerBreakpointToBreakpointIdAndSourceMap = protocol::HashMap<String16, std::pair<String16, BreakpointSource>>; using DebugServerBreakpointToBreakpointIdAndSourceMap = protocol::HashMap<String16, std::pair<String16, BreakpointSource>>;
using MuteBreakpoins = protocol::HashMap<String16, std::pair<String16, int>>; using MuteBreakpoins = protocol::HashMap<String16, std::pair<String16, int>>;
......
...@@ -182,7 +182,7 @@ V8DebuggerAgentImpl* V8DebuggerImpl::findEnabledDebuggerAgent(v8::Local<v8::Cont ...@@ -182,7 +182,7 @@ V8DebuggerAgentImpl* V8DebuggerImpl::findEnabledDebuggerAgent(v8::Local<v8::Cont
return findEnabledDebuggerAgent(getGroupId(context)); return findEnabledDebuggerAgent(getGroupId(context));
} }
void V8DebuggerImpl::getCompiledScripts(int contextGroupId, std::vector<V8DebuggerParsedScript>& result) void V8DebuggerImpl::getCompiledScripts(int contextGroupId, std::vector<std::unique_ptr<V8DebuggerScript>>& result)
{ {
v8::HandleScope scope(m_isolate); v8::HandleScope scope(m_isolate);
v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::MicrotasksScope microtasks(m_isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
...@@ -195,9 +195,11 @@ void V8DebuggerImpl::getCompiledScripts(int contextGroupId, std::vector<V8Debugg ...@@ -195,9 +195,11 @@ void V8DebuggerImpl::getCompiledScripts(int contextGroupId, std::vector<V8Debugg
return; return;
DCHECK(value->IsArray()); DCHECK(value->IsArray());
v8::Local<v8::Array> scriptsArray = v8::Local<v8::Array>::Cast(value); v8::Local<v8::Array> scriptsArray = v8::Local<v8::Array>::Cast(value);
result.resize(scriptsArray->Length()); result.reserve(scriptsArray->Length());
for (unsigned i = 0; i < scriptsArray->Length(); ++i) for (unsigned i = 0; i < scriptsArray->Length(); ++i) {
result[i] = createParsedScript(v8::Local<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i))), true); v8::Local<v8::Object> scriptObject = v8::Local<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i)));
result.push_back(wrapUnique(new V8DebuggerScript(m_isolate, scriptObject, inLiveEditScope)));
}
} }
String16 V8DebuggerImpl::setBreakpoint(const String16& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation) String16 V8DebuggerImpl::setBreakpoint(const String16& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation)
...@@ -365,7 +367,7 @@ void V8DebuggerImpl::clearStepping() ...@@ -365,7 +367,7 @@ void V8DebuggerImpl::clearStepping()
callDebuggerMethod("clearStepping", 0, argv); callDebuggerMethod("clearStepping", 0, argv);
} }
bool V8DebuggerImpl::setScriptSource(const String16& sourceID, const String16& newContent, bool preview, ErrorString* error, Maybe<protocol::Debugger::SetScriptSourceError>* errorData, JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged) bool V8DebuggerImpl::setScriptSource(const String16& sourceID, v8::Local<v8::String> newSource, bool preview, ErrorString* error, Maybe<protocol::Debugger::SetScriptSourceError>* errorData, JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged)
{ {
class EnableLiveEditScope { class EnableLiveEditScope {
public: public:
...@@ -390,7 +392,7 @@ bool V8DebuggerImpl::setScriptSource(const String16& sourceID, const String16& n ...@@ -390,7 +392,7 @@ bool V8DebuggerImpl::setScriptSource(const String16& sourceID, const String16& n
if (!isPaused()) if (!isPaused())
contextScope = wrapUnique(new v8::Context::Scope(debuggerContext())); contextScope = wrapUnique(new v8::Context::Scope(debuggerContext()));
v8::Local<v8::Value> argv[] = { toV8String(m_isolate, sourceID), toV8String(m_isolate, newContent), v8Boolean(preview, m_isolate) }; v8::Local<v8::Value> argv[] = { toV8String(m_isolate, sourceID), newSource, v8Boolean(preview, m_isolate) };
v8::Local<v8::Value> v8result; v8::Local<v8::Value> v8result;
{ {
...@@ -569,8 +571,8 @@ void V8DebuggerImpl::handleV8DebugEvent(const v8::Debug::EventDetails& eventDeta ...@@ -569,8 +571,8 @@ void V8DebuggerImpl::handleV8DebugEvent(const v8::Debug::EventDetails& eventDeta
v8::Local<v8::Value> argv[] = { eventDetails.GetEventData() }; v8::Local<v8::Value> argv[] = { eventDetails.GetEventData() };
v8::Local<v8::Value> value = callDebuggerMethod("getAfterCompileScript", 1, argv).ToLocalChecked(); v8::Local<v8::Value> value = callDebuggerMethod("getAfterCompileScript", 1, argv).ToLocalChecked();
DCHECK(value->IsObject()); DCHECK(value->IsObject());
v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); v8::Local<v8::Object> scriptObject = v8::Local<v8::Object>::Cast(value);
agent->didParseSource(createParsedScript(object, event == v8::AfterCompile)); agent->didParseSource(wrapUnique(new V8DebuggerScript(m_isolate, scriptObject, inLiveEditScope)), event == v8::AfterCompile);
} else if (event == v8::Exception) { } else if (event == v8::Exception) {
v8::Local<v8::Object> eventData = eventDetails.GetEventData(); v8::Local<v8::Object> eventData = eventDetails.GetEventData();
v8::Local<v8::Value> exception = callInternalGetterFunction(eventData, "exception"); v8::Local<v8::Value> exception = callInternalGetterFunction(eventData, "exception");
...@@ -613,29 +615,6 @@ V8StackTraceImpl* V8DebuggerImpl::currentAsyncCallChain() ...@@ -613,29 +615,6 @@ V8StackTraceImpl* V8DebuggerImpl::currentAsyncCallChain()
return m_currentStacks.back().get(); return m_currentStacks.back().get();
} }
V8DebuggerParsedScript V8DebuggerImpl::createParsedScript(v8::Local<v8::Object> object, bool success)
{
v8::Local<v8::Value> id = object->Get(v8InternalizedString("id"));
DCHECK(!id.IsEmpty() && id->IsInt32());
V8DebuggerParsedScript parsedScript;
parsedScript.scriptId = String16::number(id->Int32Value());
parsedScript.script.setURL(toProtocolStringWithTypeCheck(object->Get(v8InternalizedString("name"))))
.setSourceURL(toProtocolStringWithTypeCheck(object->Get(v8InternalizedString("sourceURL"))))
.setSourceMappingURL(toProtocolStringWithTypeCheck(object->Get(v8InternalizedString("sourceMappingURL"))))
.setSource(toProtocolStringWithTypeCheck(object->Get(v8InternalizedString("source"))))
.setStartLine(object->Get(v8InternalizedString("startLine"))->ToInteger(m_isolate)->Value())
.setStartColumn(object->Get(v8InternalizedString("startColumn"))->ToInteger(m_isolate)->Value())
.setEndLine(object->Get(v8InternalizedString("endLine"))->ToInteger(m_isolate)->Value())
.setEndColumn(object->Get(v8InternalizedString("endColumn"))->ToInteger(m_isolate)->Value())
.setIsContentScript(object->Get(v8InternalizedString("isContentScript"))->ToBoolean(m_isolate)->Value())
.setIsInternalScript(object->Get(v8InternalizedString("isInternalScript"))->ToBoolean(m_isolate)->Value())
.setExecutionContextId(object->Get(v8InternalizedString("executionContextId"))->ToInteger(m_isolate)->Value())
.setIsLiveEdit(inLiveEditScope);
parsedScript.success = success;
return parsedScript;
}
void V8DebuggerImpl::compileDebuggerScript() void V8DebuggerImpl::compileDebuggerScript()
{ {
if (!m_debuggerScript.IsEmpty()) { if (!m_debuggerScript.IsEmpty()) {
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <v8-debug.h> #include <v8-debug.h>
#include <v8.h> #include <v8.h>
#include <vector>
#include <vector> #include <vector>
...@@ -87,13 +88,13 @@ public: ...@@ -87,13 +88,13 @@ public:
void stepOutOfFunction(); void stepOutOfFunction();
void clearStepping(); void clearStepping();
bool setScriptSource(const String16& sourceID, const String16& newContent, bool preview, ErrorString*, Maybe<protocol::Debugger::SetScriptSourceError>*, JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged); bool setScriptSource(const String16& sourceID, v8::Local<v8::String> newSource, bool preview, ErrorString*, Maybe<protocol::Debugger::SetScriptSourceError>*, JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged);
JavaScriptCallFrames currentCallFrames(int limit = 0); JavaScriptCallFrames currentCallFrames(int limit = 0);
// Each script inherits debug data from v8::Context where it has been compiled. // Each script inherits debug data from v8::Context where it has been compiled.
// Only scripts whose debug data matches |contextGroupId| will be reported. // Only scripts whose debug data matches |contextGroupId| will be reported.
// Passing 0 will result in reporting all scripts. // Passing 0 will result in reporting all scripts.
void getCompiledScripts(int contextGroupId, std::vector<V8DebuggerParsedScript>&); void getCompiledScripts(int contextGroupId, std::vector<std::unique_ptr<V8DebuggerScript>>&);
void debuggerAgentEnabled(); void debuggerAgentEnabled();
void debuggerAgentDisabled(); void debuggerAgentDisabled();
...@@ -162,8 +163,6 @@ private: ...@@ -162,8 +163,6 @@ private:
v8::Local<v8::Context> debuggerContext() const; v8::Local<v8::Context> debuggerContext() const;
void clearBreakpoints(); void clearBreakpoints();
V8DebuggerParsedScript createParsedScript(v8::Local<v8::Object> sourceObject, bool success);
static void breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>&); static void breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>&);
void handleProgramBreak(v8::Local<v8::Context> pausedContext, v8::Local<v8::Object> executionState, v8::Local<v8::Value> exception, v8::Local<v8::Array> hitBreakpoints, bool isPromiseRejection = false); void handleProgramBreak(v8::Local<v8::Context> pausedContext, 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&); static void v8DebugEventCallback(const v8::Debug::EventDetails&);
......
...@@ -4,101 +4,117 @@ ...@@ -4,101 +4,117 @@
#include "platform/v8_inspector/V8DebuggerScript.h" #include "platform/v8_inspector/V8DebuggerScript.h"
namespace blink { #include "platform/inspector_protocol/Collections.h"
#include "platform/v8_inspector/V8StringUtil.h"
V8DebuggerScript::V8DebuggerScript()
: m_startLine(0)
, m_startColumn(0)
, m_endLine(0)
, m_endColumn(0)
, m_executionContextId(0)
, m_isContentScript(false)
, m_isInternalScript(false)
, m_isLiveEdit(false)
{
}
String16 V8DebuggerScript::sourceURL() const
{
return m_sourceURL.isEmpty() ? m_url : m_sourceURL;
}
V8DebuggerScript& V8DebuggerScript::setURL(const String16& url) namespace blink {
{
m_url = url;
return *this;
}
V8DebuggerScript& V8DebuggerScript::setSourceURL(const String16& sourceURL)
{
m_sourceURL = sourceURL;
return *this;
}
V8DebuggerScript& V8DebuggerScript::setSourceMappingURL(const String16& sourceMappingURL) static const LChar hexDigits[17] = "0123456789ABCDEF";
{
m_sourceMappingURL = sourceMappingURL;
return *this;
}
V8DebuggerScript& V8DebuggerScript::setSource(const String16& source) static void appendUnsignedAsHex(unsigned number, String16Builder* destination)
{ {
m_source = source; for (size_t i = 0; i < 8; ++i) {
return *this; destination->append(hexDigits[number & 0xF]);
number >>= 4;
}
} }
V8DebuggerScript& V8DebuggerScript::setHash(const String16& hash) // Hash algorithm for substrings is described in "Über die Komplexität der Multiplikation in
// eingeschränkten Branchingprogrammmodellen" by Woelfe.
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
static String16 calculateHash(const String16& str)
{ {
m_hash = hash; static uint64_t prime[] = { 0x3FB75161, 0xAB1F4E4F, 0x82675BC5, 0xCD924D35, 0x81ABE279 };
return *this; static uint64_t random[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
static uint32_t randomOdd[] = { 0xB4663807, 0xCC322BF5, 0xD4F91BBD, 0xA7BEA11D, 0x8F462907 };
uint64_t hashes[] = { 0, 0, 0, 0, 0 };
uint64_t zi[] = { 1, 1, 1, 1, 1 };
const size_t hashesSize = PROTOCOL_ARRAY_LENGTH(hashes);
size_t current = 0;
const uint32_t* data = nullptr;
data = reinterpret_cast<const uint32_t*>(str.characters16());
for (size_t i = 0; i < str.sizeInBytes() / 4; i += 4) {
uint32_t v = data[i];
uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF;
hashes[current] = (hashes[current] + zi[current] * xi) % prime[current];
zi[current] = (zi[current] * random[current]) % prime[current];
current = current == hashesSize - 1 ? 0 : current + 1;
}
if (str.sizeInBytes() % 4) {
uint32_t v = 0;
for (size_t i = str.sizeInBytes() - str.sizeInBytes() % 4; i < str.sizeInBytes(); ++i) {
v <<= 8;
v |= reinterpret_cast<const uint8_t*>(data)[i];
}
uint64_t xi = v * randomOdd[current] & 0x7FFFFFFF;
hashes[current] = (hashes[current] + zi[current] * xi) % prime[current];
zi[current] = (zi[current] * random[current]) % prime[current];
current = current == hashesSize - 1 ? 0 : current + 1;
}
for (size_t i = 0; i < hashesSize; ++i)
hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i];
String16Builder hash;
for (size_t i = 0; i < hashesSize; ++i)
appendUnsignedAsHex(hashes[i], &hash);
return hash.toString();
} }
V8DebuggerScript& V8DebuggerScript::setStartLine(int startLine) V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, v8::Local<v8::Object> object, bool isLiveEdit)
{ {
m_startLine = startLine; v8::Local<v8::Value> idValue = object->Get(toV8StringInternalized(isolate, "id"));
return *this; DCHECK(!idValue.IsEmpty() && idValue->IsInt32());
} m_id = String16::number(idValue->Int32Value());
m_url = toProtocolStringWithTypeCheck(object->Get(toV8StringInternalized(isolate, "name")));
m_sourceURL = toProtocolStringWithTypeCheck(object->Get(toV8StringInternalized(isolate, "sourceURL")));
m_sourceMappingURL = toProtocolStringWithTypeCheck(object->Get(toV8StringInternalized(isolate, "sourceMappingURL")));
m_startLine = object->Get(toV8StringInternalized(isolate, "startLine"))->ToInteger(isolate)->Value();
m_startColumn = object->Get(toV8StringInternalized(isolate, "startColumn"))->ToInteger(isolate)->Value();
m_endLine = object->Get(toV8StringInternalized(isolate, "endLine"))->ToInteger(isolate)->Value();
m_endColumn = object->Get(toV8StringInternalized(isolate, "endColumn"))->ToInteger(isolate)->Value();
m_isContentScript = object->Get(toV8StringInternalized(isolate, "isContentScript"))->ToBoolean(isolate)->Value();
m_isInternalScript = object->Get(toV8StringInternalized(isolate, "isInternalScript"))->ToBoolean(isolate)->Value();
m_executionContextId = object->Get(toV8StringInternalized(isolate, "executionContextId"))->ToInteger(isolate)->Value();
m_isLiveEdit = isLiveEdit;
V8DebuggerScript& V8DebuggerScript::setStartColumn(int startColumn) v8::Local<v8::Value> sourceValue = object->Get(toV8StringInternalized(isolate, "source"));
{ if (!sourceValue.IsEmpty() && sourceValue->IsString())
m_startColumn = startColumn; setSource(isolate, sourceValue.As<v8::String>());
return *this;
} }
V8DebuggerScript& V8DebuggerScript::setEndLine(int endLine) V8DebuggerScript::~V8DebuggerScript()
{ {
m_endLine = endLine;
return *this;
} }
V8DebuggerScript& V8DebuggerScript::setEndColumn(int endColumn) String16 V8DebuggerScript::sourceURL() const
{ {
m_endColumn = endColumn; return m_sourceURL.isEmpty() ? m_url : m_sourceURL;
return *this;
} }
V8DebuggerScript& V8DebuggerScript::setExecutionContextId(int executionContextId) v8::Local<v8::String> V8DebuggerScript::source(v8::Isolate* isolate) const
{ {
m_executionContextId = executionContextId; return m_source.Get(isolate);
return *this;
} }
V8DebuggerScript& V8DebuggerScript::setIsContentScript(bool isContentScript) void V8DebuggerScript::setSourceURL(const String16& sourceURL)
{ {
m_isContentScript = isContentScript; m_sourceURL = sourceURL;
return *this;
} }
V8DebuggerScript& V8DebuggerScript::setIsInternalScript(bool isInternalScript) void V8DebuggerScript::setSourceMappingURL(const String16& sourceMappingURL)
{ {
m_isInternalScript = isInternalScript; m_sourceMappingURL = sourceMappingURL;
return *this;
} }
V8DebuggerScript& V8DebuggerScript::setIsLiveEdit(bool isLiveEdit) void V8DebuggerScript::setSource(v8::Isolate* isolate, v8::Local<v8::String> source)
{ {
m_isLiveEdit = isLiveEdit; m_source.Reset(isolate, source);
return *this; m_hash = calculateHash(toProtocolString(source));
} }
} // namespace blink } // namespace blink
...@@ -37,15 +37,17 @@ ...@@ -37,15 +37,17 @@
namespace blink { namespace blink {
class V8DebuggerScript { class V8DebuggerScript {
PROTOCOL_DISALLOW_NEW(); PROTOCOL_DISALLOW_COPY(V8DebuggerScript);
public: public:
V8DebuggerScript(); V8DebuggerScript(v8::Isolate*, v8::Local<v8::Object>, bool isLiveEdit);
~V8DebuggerScript();
String16 scriptId() const { return m_id; }
String16 url() const { return m_url; } String16 url() const { return m_url; }
bool hasSourceURL() const { return !m_sourceURL.isEmpty(); } bool hasSourceURL() const { return !m_sourceURL.isEmpty(); }
String16 sourceURL() const; String16 sourceURL() const;
String16 sourceMappingURL() const { return m_sourceMappingURL; } String16 sourceMappingURL() const { return m_sourceMappingURL; }
String16 source() const { return m_source; } v8::Local<v8::String> source(v8::Isolate*) const;
String16 hash() const { return m_hash; } String16 hash() const { return m_hash; }
int startLine() const { return m_startLine; } int startLine() const { return m_startLine; }
int startColumn() const { return m_startColumn; } int startColumn() const { return m_startColumn; }
...@@ -56,25 +58,16 @@ public: ...@@ -56,25 +58,16 @@ public:
bool isInternalScript() const { return m_isInternalScript; } bool isInternalScript() const { return m_isInternalScript; }
bool isLiveEdit() const { return m_isLiveEdit; } bool isLiveEdit() const { return m_isLiveEdit; }
V8DebuggerScript& setURL(const String16&); void setSourceURL(const String16&);
V8DebuggerScript& setSourceURL(const String16&); void setSourceMappingURL(const String16&);
V8DebuggerScript& setSourceMappingURL(const String16&); void setSource(v8::Isolate*, v8::Local<v8::String>);
V8DebuggerScript& setSource(const String16&);
V8DebuggerScript& setHash(const String16&);
V8DebuggerScript& setStartLine(int);
V8DebuggerScript& setStartColumn(int);
V8DebuggerScript& setEndLine(int);
V8DebuggerScript& setEndColumn(int);
V8DebuggerScript& setExecutionContextId(int);
V8DebuggerScript& setIsContentScript(bool);
V8DebuggerScript& setIsInternalScript(bool);
V8DebuggerScript& setIsLiveEdit(bool);
private: private:
String16 m_id;
String16 m_url; String16 m_url;
String16 m_sourceURL; String16 m_sourceURL;
String16 m_sourceMappingURL; String16 m_sourceMappingURL;
String16 m_source; v8::Global<v8::String> m_source;
String16 m_hash; String16 m_hash;
int m_startLine; int m_startLine;
int m_startColumn; int m_startColumn;
...@@ -86,12 +79,6 @@ private: ...@@ -86,12 +79,6 @@ private:
bool m_isLiveEdit; bool m_isLiveEdit;
}; };
struct V8DebuggerParsedScript {
String16 scriptId;
V8DebuggerScript script;
bool success;
};
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment