Bug 1037675 - Improve Debugger 'findScripts': Add 'source' param and allow 'displayURL' with 'line'. r=jorendorff

This commit is contained in:
James Long 2014-08-28 08:55:00 -04:00
parent cb72ef06fb
commit c218cdcf60
4 changed files with 77 additions and 23 deletions

View File

@ -18,6 +18,13 @@ assertEq(fScripts.indexOf(fw.script) != -1, true);
assertEq(fScripts.indexOf(ggw.script), -1);
assertEq(fScripts.indexOf(hw.script), -1);
fScripts = dbg.findScripts({ displayURL: "f.js",
line: 1 });
assertEq(fScripts.indexOf(fw.script) != -1, true);
assertEq(fScripts.indexOf(ggw.script), -1);
assertEq(fScripts.indexOf(hw.script), -1);
var gScripts = dbg.findScripts({ displayURL: "g.js" });
assertEq(gScripts.indexOf(ggw.script) != -1, true);
assertEq(gScripts.indexOf(fw.script), -1);

View File

@ -0,0 +1,20 @@
var g = newGlobal();
var dbg = new Debugger();
var gw = dbg.addDebuggee(g);
g.eval('function f(){}');
var o = gw.makeDebuggeeValue(g.f);
var allScripts = dbg.findScripts();
var scripts = dbg.findScripts({
source: o.script.source
});
assertEq(scripts.length < allScripts.length, true);
assertEq(scripts.indexOf(o.script) !== -1, true);
scripts = dbg.findScripts({
source: o.script.source,
line: 1
});
assertEq(scripts.indexOf(o.script) !== -1, true);

View File

@ -371,8 +371,8 @@ MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY, 3, JSEXN_TYPEERR, "{0} is {1}{2}a global
MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 0, JSEXN_TYPEERR, "value is not a function or undefined")
MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true")
MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so")
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties")
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property")
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line' and either 'displayURL', 'url', or 'source'")
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'displayURL', 'url', or 'source' property")
// Intl
MSG_DEF(JSMSG_DATE_NOT_FINITE, 0, JSEXN_RANGEERR, "date value is not finite in DateTimeFormat.format()")

View File

@ -2514,16 +2514,19 @@ Debugger::removeDebuggeeGlobalUnderGC(FreeOp *fop, GlobalObject *global,
global->compartment()->removeDebuggeeUnderGC(fop, global, invalidate, compartmentEnum);
}
static inline ScriptSourceObject *GetSourceReferent(JSObject *obj);
/*
* A class for parsing 'findScripts' query arguments and searching for
* scripts that match the criteria they represent.
*/
class Debugger::ScriptQuery {
class MOZ_STACK_CLASS Debugger::ScriptQuery
{
public:
/* Construct a ScriptQuery to use matching scripts for |dbg|. */
ScriptQuery(JSContext *cx, Debugger *dbg):
cx(cx), debugger(dbg), compartments(cx->runtime()), url(cx), displayURLString(cx),
innermostForCompartment(cx->runtime())
source(cx), innermostForCompartment(cx->runtime())
{}
/*
@ -2579,6 +2582,39 @@ class Debugger::ScriptQuery {
return false;
}
/* Check for a 'source' property */
RootedValue debuggerSource(cx);
if (!JSObject::getProperty(cx, query, query, cx->names().source, &debuggerSource))
return false;
if (!debuggerSource.isUndefined()) {
if (!debuggerSource.isObject() ||
debuggerSource.toObject().getClass() != &DebuggerSource_class) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
"query object's 'source' property",
"not undefined nor a Debugger.Source object");
return false;
}
source = GetSourceReferent(&debuggerSource.toObject());
}
/* Check for a 'displayURL' property. */
RootedValue displayURL(cx);
if (!JSObject::getProperty(cx, query, query, cx->names().displayURL, &displayURL))
return false;
if (!displayURL.isUndefined() && !displayURL.isString()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
"query object's 'displayURL' property",
"neither undefined nor a string");
return false;
}
if (displayURL.isString()) {
displayURLString = displayURL.toString()->ensureLinear(cx);
if (!displayURLString)
return false;
}
/* Check for a 'line' property. */
RootedValue lineProperty(cx);
if (!JSObject::getProperty(cx, query, query, cx->names().line, &lineProperty))
@ -2586,7 +2622,7 @@ class Debugger::ScriptQuery {
if (lineProperty.isUndefined()) {
hasLine = false;
} else if (lineProperty.isNumber()) {
if (url.isUndefined()) {
if (displayURL.isUndefined() && url.isUndefined() && !source) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
JSMSG_QUERY_LINE_WITHOUT_URL);
return false;
@ -2613,30 +2649,13 @@ class Debugger::ScriptQuery {
innermost = ToBoolean(innermostProperty);
if (innermost) {
/* Technically, we need only check hasLine, but this is clearer. */
if (url.isUndefined() || !hasLine) {
if ((displayURL.isUndefined() && url.isUndefined() && !source) || !hasLine) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL);
return false;
}
}
/* Check for a 'displayURL' property. */
RootedValue displayURL(cx);
if (!JSObject::getProperty(cx, query, query, cx->names().displayURL, &displayURL))
return false;
if (!displayURL.isUndefined() && !displayURL.isString()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
"query object's 'displayURL' property",
"neither undefined nor a string");
return false;
}
if (displayURL.isString()) {
displayURLString = displayURL.toString()->ensureLinear(cx);
if (!displayURLString)
return false;
}
return true;
}
@ -2719,6 +2738,12 @@ class Debugger::ScriptQuery {
* it. */
RootedLinearString displayURLString;
/*
* If this is a source object, matching scripts will have sources
* equal to this instance.
*/
RootedScriptSource source;
/* True if the query contained a 'line' property. */
bool hasLine;
@ -2841,6 +2866,8 @@ class Debugger::ScriptQuery {
if (CompareChars(s, js_strlen(s), displayURLString) != 0)
return;
}
if (source && source != script->sourceObject())
return;
if (innermost) {
/*