зеркало из https://github.com/mozilla/gecko-dev.git
Bug 755346 - Global variables are not displayed in the debugger frontend; r=vporof,rcampbell
This commit is contained in:
Родитель
6d14db1293
Коммит
d342aa7757
|
@ -418,9 +418,11 @@ StackFrames.prototype = {
|
|||
_onFrames: function SF__onFrames() {
|
||||
if (!this.activeThread.cachedFrames.length) {
|
||||
DebuggerView.StackFrames.emptyText();
|
||||
DebuggerView.Properties.emptyText();
|
||||
return;
|
||||
}
|
||||
DebuggerView.StackFrames.empty();
|
||||
DebuggerView.Properties.empty();
|
||||
|
||||
for each (let frame in this.activeThread.cachedFrames) {
|
||||
this._addFrame(frame);
|
||||
|
@ -451,8 +453,7 @@ StackFrames.prototype = {
|
|||
_afterFramesCleared: function SF__afterFramesCleared() {
|
||||
if (!this.activeThread.cachedFrames.length) {
|
||||
DebuggerView.StackFrames.emptyText();
|
||||
DebuggerView.Properties.localScope.empty();
|
||||
DebuggerView.Properties.globalScope.empty();
|
||||
DebuggerView.Properties.emptyText();
|
||||
DebuggerController.dispatchEvent("Debugger:AfterFramesCleared");
|
||||
}
|
||||
},
|
||||
|
@ -521,39 +522,76 @@ StackFrames.prototype = {
|
|||
// Start recording any added variables or properties in any scope.
|
||||
DebuggerView.Properties.createHierarchyStore();
|
||||
|
||||
// Display the local variables.
|
||||
let localScope = DebuggerView.Properties.localScope;
|
||||
localScope.empty();
|
||||
|
||||
// Add "this".
|
||||
if (frame.this) {
|
||||
let thisVar = localScope.addVar("this");
|
||||
thisVar.setGrip({
|
||||
type: frame.this.type,
|
||||
class: frame.this.class
|
||||
});
|
||||
this._addExpander(thisVar, frame.this);
|
||||
}
|
||||
|
||||
DebuggerView.Properties.empty();
|
||||
if (frame.environment) {
|
||||
// Add nodes for every argument.
|
||||
let variables = frame.environment.bindings.arguments;
|
||||
for each (let variable in variables) {
|
||||
let name = Object.getOwnPropertyNames(variable)[0];
|
||||
let paramVar = localScope.addVar(name);
|
||||
let paramVal = variable[name].value;
|
||||
paramVar.setGrip(paramVal);
|
||||
this._addExpander(paramVar, paramVal);
|
||||
}
|
||||
let env = frame.environment;
|
||||
|
||||
// Add nodes for every other variable in scope.
|
||||
variables = frame.environment.bindings.variables;
|
||||
for (let variable in variables) {
|
||||
let paramVar = localScope.addVar(variable);
|
||||
let paramVal = variables[variable].value;
|
||||
paramVar.setGrip(paramVal);
|
||||
this._addExpander(paramVar, paramVal);
|
||||
}
|
||||
do {
|
||||
// Construct the scope name.
|
||||
let name = env.type.charAt(0).toUpperCase() + env.type.slice(1);
|
||||
// Call the outermost scope Global.
|
||||
if (!env.parent) {
|
||||
name = L10N.getStr("globalScopeLabel");
|
||||
}
|
||||
let label = L10N.getFormatStr("scopeLabel", [name]);
|
||||
switch (env.type) {
|
||||
case "with":
|
||||
case "object":
|
||||
label += " [" + env.object.class + "]";
|
||||
break;
|
||||
case "function":
|
||||
if (env.functionName) {
|
||||
label += " [" + env.functionName + "]";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
let scope = DebuggerView.Properties.addScope(label);
|
||||
|
||||
// Add "this" to the innermost scope.
|
||||
if (frame.this && env == frame.environment) {
|
||||
let thisVar = scope.addVar("this");
|
||||
thisVar.setGrip({
|
||||
type: frame.this.type,
|
||||
class: frame.this.class
|
||||
});
|
||||
this._addExpander(thisVar, frame.this);
|
||||
// Expand the innermost scope by default.
|
||||
scope.expand();
|
||||
}
|
||||
|
||||
switch (env.type) {
|
||||
case "with":
|
||||
case "object":
|
||||
let objClient = this.activeThread.pauseGrip(env.object);
|
||||
objClient.getPrototypeAndProperties(function SF_getProps(aResponse) {
|
||||
this._addScopeVariables(aResponse.ownProperties, scope);
|
||||
// Signal that variables have been fetched.
|
||||
DebuggerController.dispatchEvent("Debugger:FetchedVariables");
|
||||
}.bind(this));
|
||||
break;
|
||||
case "block":
|
||||
case "function":
|
||||
// Add nodes for every argument.
|
||||
let variables = env.bindings.arguments;
|
||||
for each (let variable in variables) {
|
||||
let name = Object.getOwnPropertyNames(variable)[0];
|
||||
let paramVar = scope.addVar(name);
|
||||
let paramVal = variable[name].value;
|
||||
paramVar.setGrip(paramVal);
|
||||
this._addExpander(paramVar, paramVal);
|
||||
}
|
||||
|
||||
// Add nodes for every other variable in scope.
|
||||
this._addScopeVariables(env.bindings.variables, scope);
|
||||
break;
|
||||
default:
|
||||
Cu.reportError("Unknown Debugger.Environment type: " + env.type);
|
||||
break;
|
||||
}
|
||||
} while (env = env.parent);
|
||||
}
|
||||
|
||||
// Signal that variables have been fetched.
|
||||
|
@ -567,6 +605,31 @@ StackFrames.prototype = {
|
|||
DebuggerView.Properties.commitHierarchy();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add nodes for every variable in scope.
|
||||
*
|
||||
* @param object aVariables
|
||||
* The map of names to variables, as specified in the Remote
|
||||
* Debugging Protocol.
|
||||
* @param object aScope
|
||||
* The scope where the nodes will be placed into.
|
||||
*/
|
||||
_addScopeVariables: function SF_addScopeVariables(aVariables, aScope) {
|
||||
// Sort all of the variables before adding them, for better UX.
|
||||
let variables = {};
|
||||
for each (let prop in Object.keys(aVariables).sort()) {
|
||||
variables[prop] = aVariables[prop];
|
||||
}
|
||||
|
||||
// Add the sorted variables to the specified scope.
|
||||
for (let variable in variables) {
|
||||
let paramVar = aScope.addVar(variable);
|
||||
let paramVal = variables[variable].value;
|
||||
paramVar.setGrip(paramVal);
|
||||
this._addExpander(paramVar, paramVal);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds an 'onexpand' callback for a variable, lazily handling the addition of
|
||||
* new properties.
|
||||
|
|
|
@ -760,12 +760,17 @@ StackFramesView.prototype = {
|
|||
* Functions handling the properties view.
|
||||
*/
|
||||
function PropertiesView() {
|
||||
this._addScope = this._addScope.bind(this);
|
||||
this.addScope = this._addScope.bind(this);
|
||||
this._addVar = this._addVar.bind(this);
|
||||
this._addProperties = this._addProperties.bind(this);
|
||||
}
|
||||
|
||||
PropertiesView.prototype = {
|
||||
/**
|
||||
* A monotonically-increasing counter, that guarantees the uniqueness of scope
|
||||
* IDs.
|
||||
*/
|
||||
_idCount: 1,
|
||||
|
||||
/**
|
||||
* Adds a scope to contain any inspected variables.
|
||||
|
@ -786,8 +791,8 @@ PropertiesView.prototype = {
|
|||
return null;
|
||||
}
|
||||
|
||||
// Compute the id of the element if not specified.
|
||||
aId = aId || (aName.toLowerCase().trim().replace(" ", "-") + "-scope");
|
||||
// Generate a unique id for the element, if not specified.
|
||||
aId = aId || aName.toLowerCase().trim().replace(" ", "-") + this._idCount++;
|
||||
|
||||
// Contains generic nodes and functionality.
|
||||
let element = this._createPropertyElement(aName, aId, "scope", this._vars);
|
||||
|
@ -806,6 +811,32 @@ PropertiesView.prototype = {
|
|||
return element;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all added scopes in the property container tree.
|
||||
*/
|
||||
empty: function DVP_empty() {
|
||||
while (this._vars.firstChild) {
|
||||
this._vars.removeChild(this._vars.firstChild);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all elements from the variables container, and adds a child node
|
||||
* with an empty text note attached.
|
||||
*/
|
||||
emptyText: function DVP_emptyText() {
|
||||
// Make sure the container is empty first.
|
||||
this.empty();
|
||||
|
||||
let item = document.createElement("label");
|
||||
|
||||
// The empty node should look grayed out to avoid confusion.
|
||||
item.className = "list-item empty";
|
||||
item.setAttribute("value", L10N.getStr("emptyVariablesText"));
|
||||
|
||||
this._vars.appendChild(item);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a variable to a specified scope.
|
||||
* If the optional id is not specified, the variable html node will have a
|
||||
|
@ -1685,103 +1716,11 @@ PropertiesView.prototype = {
|
|||
_currHierarchy: null,
|
||||
_prevHierarchy: null,
|
||||
|
||||
/**
|
||||
* Returns the global scope container.
|
||||
*/
|
||||
get globalScope() {
|
||||
return this._globalScope;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the display mode for the global scope container.
|
||||
*
|
||||
* @param boolean aFlag
|
||||
* False to hide the container, true to show.
|
||||
*/
|
||||
set globalScope(aFlag) {
|
||||
if (aFlag) {
|
||||
this._globalScope.show();
|
||||
} else {
|
||||
this._globalScope.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the local scope container.
|
||||
*/
|
||||
get localScope() {
|
||||
return this._localScope;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the display mode for the local scope container.
|
||||
*
|
||||
* @param boolean aFlag
|
||||
* False to hide the container, true to show.
|
||||
*/
|
||||
set localScope(aFlag) {
|
||||
if (aFlag) {
|
||||
this._localScope.show();
|
||||
} else {
|
||||
this._localScope.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the with block scope container.
|
||||
*/
|
||||
get withScope() {
|
||||
return this._withScope;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the display mode for the with block scope container.
|
||||
*
|
||||
* @param boolean aFlag
|
||||
* False to hide the container, true to show.
|
||||
*/
|
||||
set withScope(aFlag) {
|
||||
if (aFlag) {
|
||||
this._withScope.show();
|
||||
} else {
|
||||
this._withScope.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the closure scope container.
|
||||
*/
|
||||
get closureScope() {
|
||||
return this._closureScope;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the display mode for the with block scope container.
|
||||
*
|
||||
* @param boolean aFlag
|
||||
* False to hide the container, true to show.
|
||||
*/
|
||||
set closureScope(aFlag) {
|
||||
if (aFlag) {
|
||||
this._closureScope.show();
|
||||
} else {
|
||||
this._closureScope.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The cached variable properties container.
|
||||
*/
|
||||
_vars: null,
|
||||
|
||||
/**
|
||||
* Auto-created global, local, with block and closure scopes containing vars.
|
||||
*/
|
||||
_globalScope: null,
|
||||
_localScope: null,
|
||||
_withScope: null,
|
||||
_closureScope: null,
|
||||
|
||||
/**
|
||||
* Initialization function, called when the debugger is initialized.
|
||||
*/
|
||||
|
@ -1789,10 +1728,6 @@ PropertiesView.prototype = {
|
|||
this.createHierarchyStore();
|
||||
|
||||
this._vars = document.getElementById("variables");
|
||||
this._localScope = this._addScope(L10N.getStr("localScope")).expand();
|
||||
this._withScope = this._addScope(L10N.getStr("withScope")).hide();
|
||||
this._closureScope = this._addScope(L10N.getStr("closureScope")).hide();
|
||||
this._globalScope = this._addScope(L10N.getStr("globalScope"));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1802,10 +1737,6 @@ PropertiesView.prototype = {
|
|||
this._currHierarchy = null;
|
||||
this._prevHierarchy = null;
|
||||
this._vars = null;
|
||||
this._globalScope = null;
|
||||
this._localScope = null;
|
||||
this._withScope = null;
|
||||
this._closureScope = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ _BROWSER_TEST_FILES = \
|
|||
browser_dbg_propertyview-06.js \
|
||||
browser_dbg_propertyview-07.js \
|
||||
browser_dbg_propertyview-08.js \
|
||||
browser_dbg_propertyview-09.js \
|
||||
browser_dbg_propertyview-10.js \
|
||||
browser_dbg_propertyview-edit.js \
|
||||
browser_dbg_panesize.js \
|
||||
browser_dbg_stack-01.js \
|
||||
|
@ -66,6 +68,7 @@ _BROWSER_TEST_PAGES = \
|
|||
test-editor-mode \
|
||||
browser_dbg_displayName.html \
|
||||
browser_dbg_iframes.html \
|
||||
browser_dbg_with-frame.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
|
|
@ -23,65 +23,14 @@ function testSimpleCall() {
|
|||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let globalScope = gDebugger.DebuggerView.Properties._globalScope;
|
||||
let localScope = gDebugger.DebuggerView.Properties._localScope;
|
||||
let withScope = gDebugger.DebuggerView.Properties._withScope;
|
||||
let closureScope = gDebugger.DebuggerView.Properties._closureScope;
|
||||
|
||||
ok(globalScope,
|
||||
"Should have a globalScope container for the variables property view.");
|
||||
|
||||
ok(localScope,
|
||||
"Should have a localScope container for the variables property view.");
|
||||
|
||||
ok(withScope,
|
||||
"Should have a withScope container for the variables property view.");
|
||||
|
||||
ok(closureScope,
|
||||
"Should have a closureScope container for the variables property view.");
|
||||
|
||||
is(globalScope, gDebugger.DebuggerView.Properties.globalScope,
|
||||
"The globalScope object should be equal to the corresponding getter.");
|
||||
|
||||
is(localScope, gDebugger.DebuggerView.Properties.localScope,
|
||||
"The localScope object should be equal to the corresponding getter.");
|
||||
|
||||
is(withScope, gDebugger.DebuggerView.Properties.withScope,
|
||||
"The withScope object should be equal to the corresponding getter.");
|
||||
|
||||
is(closureScope, gDebugger.DebuggerView.Properties.closureScope,
|
||||
"The closureScope object should be equal to the corresponding getter.");
|
||||
|
||||
|
||||
ok(!globalScope.expanded,
|
||||
"The globalScope should be initially collapsed.");
|
||||
|
||||
ok(localScope.expanded,
|
||||
"The localScope should be initially expanded.");
|
||||
|
||||
ok(!withScope.expanded,
|
||||
"The withScope should be initially collapsed.");
|
||||
|
||||
ok(!withScope.visible,
|
||||
"The withScope should be initially hidden.");
|
||||
|
||||
ok(!closureScope.expanded,
|
||||
"The closureScope should be initially collapsed.");
|
||||
|
||||
ok(!closureScope.visible,
|
||||
"The closureScope should be initially hidden.");
|
||||
|
||||
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 4,
|
||||
"Should have only 4 scopes created: global, local, with and scope.");
|
||||
|
||||
resumeAndFinish();
|
||||
testScriptLabelShortening();
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
gDebuggee.simpleCall();
|
||||
}
|
||||
|
||||
function resumeAndFinish() {
|
||||
function testScriptLabelShortening() {
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
let vs = gDebugger.DebuggerView.Scripts;
|
||||
let ss = gDebugger.DebuggerController.SourceScripts;
|
||||
|
|
|
@ -28,7 +28,7 @@ function testSimpleCall() {
|
|||
ok(testScope,
|
||||
"Should have created a scope.");
|
||||
|
||||
is(testScope.id, "test-scope",
|
||||
is(testScope.id.substring(0, 4), "test",
|
||||
"The newly created scope should have the default id set.");
|
||||
|
||||
is(testScope.querySelector(".name").getAttribute("value"), "test",
|
||||
|
@ -37,8 +37,8 @@ function testSimpleCall() {
|
|||
is(testScope.querySelector(".details").childNodes.length, 0,
|
||||
"Any new scope should have a container with no child nodes.");
|
||||
|
||||
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 5,
|
||||
"Should have 5 scopes created: global, local, with, closure and test.");
|
||||
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 3,
|
||||
"Should have 3 scopes created.");
|
||||
|
||||
|
||||
ok(!testScope.expanded,
|
||||
|
|
|
@ -23,7 +23,7 @@ function testSimpleCall() {
|
|||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let testScope = gDebugger.DebuggerView.Properties._addScope("test");
|
||||
let testScope = gDebugger.DebuggerView.Properties._addScope("test-scope");
|
||||
let testVar = testScope.addVar("something");
|
||||
let duplVar = testScope.addVar("something");
|
||||
|
||||
|
@ -33,9 +33,6 @@ function testSimpleCall() {
|
|||
is(duplVar, null,
|
||||
"Shouldn't be able to duplicate variables in the same scope.");
|
||||
|
||||
is(testVar.id, "test-scope->something-variable",
|
||||
"The newly created scope should have the default id set.");
|
||||
|
||||
is(testVar.querySelector(".name").getAttribute("value"), "something",
|
||||
"Any new variable should have the designated title.");
|
||||
|
||||
|
@ -188,7 +185,7 @@ function testSimpleCall() {
|
|||
is(removeCallbackSender, testScope,
|
||||
"The removeCallback wasn't called as it should.");
|
||||
|
||||
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 4,
|
||||
is(gDebugger.DebuggerView.Properties._vars.childNodes.length, 2,
|
||||
"The scope should have been removed from the parent container tree.");
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
|
|
|
@ -23,8 +23,8 @@ function testSimpleCall() {
|
|||
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let globalScope = gDebugger.DebuggerView.Properties.globalScope;
|
||||
let localScope = gDebugger.DebuggerView.Properties.localScope;
|
||||
let globalScope = gDebugger.DebuggerView.Properties.addScope("Global");
|
||||
let localScope = gDebugger.DebuggerView.Properties.addScope("Local");
|
||||
globalScope.empty();
|
||||
localScope.empty();
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ function testFrameParameters()
|
|||
|
||||
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
||||
childNodes = frames.childNodes,
|
||||
localScope = gDebugger.DebuggerView.Properties.localScope,
|
||||
localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
|
||||
localNodes = localScope.querySelector(".details").childNodes;
|
||||
|
||||
dump("Got our variables:\n");
|
||||
|
@ -79,14 +79,14 @@ function testFrameParameters()
|
|||
is(localNodes[7].querySelector(".value").getAttribute("value"), "1",
|
||||
"Should have the right property value for 'a'.");
|
||||
|
||||
is(localNodes[8].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||
"Should have the right property value for 'b'.");
|
||||
is(localNodes[8].querySelector(".value").getAttribute("value"), "[object Arguments]",
|
||||
"Should have the right property value for 'arguments'.");
|
||||
|
||||
is(localNodes[9].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||
"Should have the right property value for 'c'.");
|
||||
"Should have the right property value for 'b'.");
|
||||
|
||||
is(localNodes[10].querySelector(".value").getAttribute("value"), "[object Arguments]",
|
||||
"Should have the right property value for 'arguments'.");
|
||||
is(localNodes[10].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||
"Should have the right property value for 'c'.");
|
||||
|
||||
resumeAndFinish();
|
||||
}}, 0);
|
||||
|
|
|
@ -36,7 +36,7 @@ function testFrameParameters()
|
|||
dump("After currentThread.dispatch!\n");
|
||||
|
||||
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
||||
localScope = gDebugger.DebuggerView.Properties.localScope,
|
||||
localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
|
||||
localNodes = localScope.querySelector(".details").childNodes;
|
||||
|
||||
dump("Got our variables:\n");
|
||||
|
@ -59,7 +59,7 @@ function testFrameParameters()
|
|||
// Expand the 'this', 'arguments' and 'c' tree nodes. This causes
|
||||
// their properties to be retrieved and displayed.
|
||||
localNodes[0].expand();
|
||||
localNodes[9].expand();
|
||||
localNodes[8].expand();
|
||||
localNodes[10].expand();
|
||||
|
||||
// Poll every few milliseconds until the properties are retrieved.
|
||||
|
@ -73,7 +73,7 @@ function testFrameParameters()
|
|||
resumeAndFinish();
|
||||
}
|
||||
if (!localNodes[0].fetched ||
|
||||
!localNodes[9].fetched ||
|
||||
!localNodes[8].fetched ||
|
||||
!localNodes[10].fetched) {
|
||||
return;
|
||||
}
|
||||
|
@ -86,29 +86,29 @@ function testFrameParameters()
|
|||
.getAttribute("value").search(/object/) != -1,
|
||||
"__proto__ should be an object.");
|
||||
|
||||
is(localNodes[9].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||
"Should have the right property value for 'c'.");
|
||||
|
||||
is(localNodes[9].querySelectorAll(".property > .title > .key")[1]
|
||||
.getAttribute("value"), "a",
|
||||
"Should have the right property name for 'a'.");
|
||||
|
||||
is(localNodes[9].querySelectorAll(".property > .title > .value")[1]
|
||||
.getAttribute("value"), 1,
|
||||
"Should have the right value for 'c.a'.");
|
||||
|
||||
is(localNodes[10].querySelector(".value").getAttribute("value"),
|
||||
is(localNodes[8].querySelector(".value").getAttribute("value"),
|
||||
"[object Arguments]",
|
||||
"Should have the right property value for 'arguments'.");
|
||||
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .key")[7]
|
||||
is(localNodes[8].querySelectorAll(".property > .title > .key")[7]
|
||||
.getAttribute("value"), "length",
|
||||
"Should have the right property name for 'length'.");
|
||||
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .value")[7]
|
||||
is(localNodes[8].querySelectorAll(".property > .title > .value")[7]
|
||||
.getAttribute("value"), 5,
|
||||
"Should have the right argument length.");
|
||||
|
||||
is(localNodes[10].querySelector(".value").getAttribute("value"), "[object Object]",
|
||||
"Should have the right property value for 'c'.");
|
||||
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .key")[1]
|
||||
.getAttribute("value"), "a",
|
||||
"Should have the right property name for 'a'.");
|
||||
|
||||
is(localNodes[10].querySelectorAll(".property > .title > .value")[1]
|
||||
.getAttribute("value"), 1,
|
||||
"Should have the right value for 'c.a'.");
|
||||
|
||||
resumeAndFinish();
|
||||
}, 100);
|
||||
}}, 0);
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Make sure that the property view populates the global scope pane.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "browser_dbg_frame-parameters.html";
|
||||
|
||||
var gPane = null;
|
||||
var gTab = null;
|
||||
var gDebugger = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testFrameParameters();
|
||||
});
|
||||
}
|
||||
|
||||
function testFrameParameters()
|
||||
{
|
||||
let count = 0;
|
||||
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
|
||||
// We expect 2 Debugger:FetchedVariables events, one from the global object
|
||||
// scope and the regular one.
|
||||
if (++count <2) {
|
||||
info("Number of received Debugger:FetchedVariables events: " + count);
|
||||
return;
|
||||
}
|
||||
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
||||
globalScope = gDebugger.DebuggerView.Properties._vars.lastChild,
|
||||
globalNodes = globalScope.querySelector(".details").childNodes;
|
||||
|
||||
globalScope.expand();
|
||||
|
||||
is(gDebugger.DebuggerController.activeThread.state, "paused",
|
||||
"Should only be getting stack frames while paused.");
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
|
||||
"Should have three frames.");
|
||||
|
||||
is(globalNodes[0].querySelector(".name").getAttribute("value"), "Array",
|
||||
"Should have the right property name for |Array|.");
|
||||
|
||||
is(globalNodes[0].querySelector(".value").getAttribute("value"), "[object Function]",
|
||||
"Should have the right property value for |Array|.");
|
||||
|
||||
let len = globalNodes.length - 1;
|
||||
is(globalNodes[len].querySelector(".name").getAttribute("value"), "window",
|
||||
"Should have the right property name for |window|.");
|
||||
|
||||
is(globalNodes[len].querySelector(".value").getAttribute("value"), "[object Proxy]",
|
||||
"Should have the right property value for |window|.");
|
||||
|
||||
resumeAndFinish();
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
content.document.querySelector("button"),
|
||||
content.window);
|
||||
}
|
||||
|
||||
function resumeAndFinish() {
|
||||
gDebugger.addEventListener("Debugger:AfterFramesCleared", function listener() {
|
||||
gDebugger.removeEventListener("Debugger:AfterFramesCleared", listener, true);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
var frames = gDebugger.DebuggerView.StackFrames._frames;
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"Should have no frames.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
}}, 0);
|
||||
}, true);
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume();
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebugger = null;
|
||||
});
|
|
@ -0,0 +1,105 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Make sure that the property view is correctly populated in |with| frames.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "browser_dbg_with-frame.html";
|
||||
|
||||
var gPane = null;
|
||||
var gTab = null;
|
||||
var gDebugger = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.contentWindow;
|
||||
|
||||
testWithFrame();
|
||||
});
|
||||
}
|
||||
|
||||
function testWithFrame()
|
||||
{
|
||||
let count = 0;
|
||||
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
|
||||
// We expect 4 Debugger:FetchedVariables events, one from the global object
|
||||
// scope, two from the |with| scopes and the regular one.
|
||||
if (++count <3) {
|
||||
info("Number of received Debugger:FetchedVariables events: " + count);
|
||||
return;
|
||||
}
|
||||
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
var frames = gDebugger.DebuggerView.StackFrames._frames,
|
||||
scopes = gDebugger.DebuggerView.Properties._vars,
|
||||
globalScope = scopes.lastChild,
|
||||
innerScope = scopes.firstChild,
|
||||
globalNodes = globalScope.querySelector(".details").childNodes,
|
||||
innerNodes = innerScope.querySelector(".details").childNodes;
|
||||
|
||||
globalScope.expand();
|
||||
|
||||
is(gDebugger.DebuggerController.activeThread.state, "paused",
|
||||
"Should only be getting stack frames while paused.");
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 2,
|
||||
"Should have three frames.");
|
||||
|
||||
is(scopes.children.length, 5, "Should have 5 variable scopes.");
|
||||
|
||||
is(innerNodes[1].querySelector(".name").getAttribute("value"), "one",
|
||||
"Should have the right property name for |one|.");
|
||||
|
||||
is(innerNodes[1].querySelector(".value").getAttribute("value"), "1",
|
||||
"Should have the right property value for |one|.");
|
||||
|
||||
is(globalNodes[0].querySelector(".name").getAttribute("value"), "Array",
|
||||
"Should have the right property name for |Array|.");
|
||||
|
||||
is(globalNodes[0].querySelector(".value").getAttribute("value"), "[object Function]",
|
||||
"Should have the right property value for |Array|.");
|
||||
|
||||
let len = globalNodes.length - 1;
|
||||
is(globalNodes[len].querySelector(".name").getAttribute("value"), "window",
|
||||
"Should have the right property name for |window|.");
|
||||
|
||||
is(globalNodes[len].querySelector(".value").getAttribute("value"), "[object Proxy]",
|
||||
"Should have the right property value for |window|.");
|
||||
|
||||
resumeAndFinish();
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
content.document.querySelector("button"),
|
||||
content.window);
|
||||
}
|
||||
|
||||
function resumeAndFinish() {
|
||||
gDebugger.addEventListener("Debugger:AfterFramesCleared", function listener() {
|
||||
gDebugger.removeEventListener("Debugger:AfterFramesCleared", listener, true);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
var frames = gDebugger.DebuggerView.StackFrames._frames;
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"Should have no frames.");
|
||||
|
||||
closeDebuggerAndFinish(gTab);
|
||||
}}, 0);
|
||||
}, true);
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume();
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebugger = null;
|
||||
});
|
|
@ -29,7 +29,7 @@ function testFrameEval() {
|
|||
is(gDebugger.DebuggerController.activeThread.state, "paused",
|
||||
"Should only be getting stack frames while paused.");
|
||||
|
||||
var localScope = gDebugger.DebuggerView.Properties.localScope,
|
||||
var localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
|
||||
localNodes = localScope.querySelector(".details").childNodes,
|
||||
varA = localNodes[7];
|
||||
|
||||
|
@ -68,11 +68,18 @@ function testModification(aVar, aCallback, aNewValue, aNewResult) {
|
|||
ok(aVar.querySelector(".element-input"),
|
||||
"There should be an input element created.");
|
||||
|
||||
let count = 0;
|
||||
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
|
||||
// We expect 2 Debugger:FetchedVariables events, one from the global
|
||||
// object scope and the regular one.
|
||||
if (++count <2) {
|
||||
info("Number of received Debugger:FetchedVariables events: " + count);
|
||||
return;
|
||||
}
|
||||
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
|
||||
// Get the variable reference anew, since the old ones were discarded when
|
||||
// we resumed.
|
||||
var localScope = gDebugger.DebuggerView.Properties.localScope,
|
||||
var localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
|
||||
localNodes = localScope.querySelector(".details").childNodes,
|
||||
varA = localNodes[7];
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<title>Debugger Function Call Parameter Test</title>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<script type="text/javascript">
|
||||
window.addEventListener("load", function() {
|
||||
function test(aNumber) {
|
||||
var a, obj = { one: 1, two: 2 };
|
||||
var r = aNumber;
|
||||
with (Math) {
|
||||
a = PI * r * r;
|
||||
with (obj) {
|
||||
var foo = two * PI;
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
};
|
||||
function load() {
|
||||
test(10);
|
||||
}
|
||||
var button = document.querySelector("button");
|
||||
button.addEventListener("click", load, false);
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<button>Click me!</button>
|
||||
</body>
|
||||
</html>
|
|
@ -42,22 +42,6 @@ pauseTooltip=Click to pause
|
|||
# button when the debugger is in a paused state.
|
||||
resumeTooltip=Click to resume
|
||||
|
||||
# LOCALIZATION NOTE (localScope): The label that is displayed in the variables
|
||||
# pane as a header on the local scope container.
|
||||
localScope=Local
|
||||
|
||||
# LOCALIZATION NOTE (globalScope): The label that is displayed in the variables
|
||||
# pane as a header on the globel scope container.
|
||||
globalScope=Global
|
||||
|
||||
# LOCALIZATION NOTE (withScope): The label that is displayed in the variables
|
||||
# pane as a header on the container for identifiers in a with block.
|
||||
withScope=With block
|
||||
|
||||
# LOCALIZATION NOTE (closureScope): The label that is displayed in the variables
|
||||
# pane as a header on container for identifiers in a closure scope.
|
||||
closureScope=Closure
|
||||
|
||||
# LOCALIZATION NOTE (emptyStackText): The text that is displayed in the stack
|
||||
# frames list when there are no frames to display.
|
||||
emptyStackText=No stacks to display.
|
||||
|
@ -72,3 +56,17 @@ loadingText=Loading\u2026
|
|||
# external resource file.
|
||||
# %1$S=URL, %2$S=status code
|
||||
loadingError=Error loading %1$S: %2$S
|
||||
|
||||
# LOCALIZATION NOTE (emptyVariablesText): The text that is displayed in the
|
||||
# variables pane when there are no variables to display.
|
||||
emptyVariablesText=No variables to display.
|
||||
|
||||
# LOCALIZATION NOTE (scopeLabel): The text that is displayed in the variables
|
||||
# pane as a header for each variable scope (e.g. "Global scope, "With scope",
|
||||
# etc.).
|
||||
scopeLabel=%S scope
|
||||
|
||||
# LOCALIZATION NOTE (globalScopeLabel): The name of the global scope. This text
|
||||
# is added to scopeLabel and displayed in the variables pane as a header for
|
||||
# the global scope.
|
||||
globalScopeLabel=Global
|
||||
|
|
|
@ -1078,6 +1078,10 @@ ObjectActor.prototype = {
|
|||
message: "cannot access the environment of this function." };
|
||||
}
|
||||
|
||||
// XXX: the following call of env.form() won't work until bug 747514 lands.
|
||||
// We can't get to the frame that defined this function's environment,
|
||||
// neither here, nor during ObjectActor's construction. Luckily, we don't
|
||||
// use the 'scope' request in the debugger frontend.
|
||||
return { name: this.obj.name || null,
|
||||
scope: envActor.form(this.obj) };
|
||||
},
|
||||
|
@ -1197,14 +1201,7 @@ FrameActor.prototype = {
|
|||
type: this.frame.type };
|
||||
if (this.frame.type === "call") {
|
||||
form.callee = this.threadActor.createValueGrip(this.frame.callee);
|
||||
if (this.frame.callee.name) {
|
||||
form.calleeName = this.frame.callee.name;
|
||||
} else {
|
||||
let desc = this.frame.callee.getOwnPropertyDescriptor("displayName");
|
||||
if (desc && desc.value && typeof desc.value == "string") {
|
||||
form.calleeName = desc.value;
|
||||
}
|
||||
}
|
||||
form.calleeName = getFunctionName(this.frame.callee);
|
||||
}
|
||||
|
||||
let envActor = this.threadActor
|
||||
|
@ -1335,13 +1332,13 @@ EnvironmentActor.prototype = {
|
|||
|
||||
/**
|
||||
* Returns an environment form for use in a protocol message. Note that the
|
||||
* requirement of passing the frame or function as a parameter is only
|
||||
* temporary, since when bug 747514 lands, the environment will have a callee
|
||||
* property that will contain it.
|
||||
* requirement of passing the frame as a parameter is only temporary, since
|
||||
* when bug 747514 lands, the environment will have a callee property that
|
||||
* will contain it.
|
||||
*
|
||||
* @param object aObject
|
||||
* The stack frame or function object whose environment bindings are
|
||||
* being generated.
|
||||
* @param Debugger.Frame aObject
|
||||
* The stack frame object whose environment bindings are being
|
||||
* generated.
|
||||
*/
|
||||
form: function EA_form(aObject) {
|
||||
// Debugger.Frame might be dead by the time we get here, which will cause
|
||||
|
@ -1353,24 +1350,29 @@ EnvironmentActor.prototype = {
|
|||
let parent;
|
||||
if (this.obj.parent) {
|
||||
let thread = this.threadActor;
|
||||
parent = thread.createEnvironmentActor(this.obj.parent.environment,
|
||||
parent = thread.createEnvironmentActor(this.obj.parent,
|
||||
this.registeredPool);
|
||||
}
|
||||
// Deduce the frame that created the parent scope in order to pass it to
|
||||
// parent.form(). TODO: this can be removed after bug 747514 is done.
|
||||
let parentFrame = aObject;
|
||||
if (this.obj.type == "declarative" && aObject.older) {
|
||||
parentFrame = aObject.older;
|
||||
}
|
||||
let form = { actor: this.actorID,
|
||||
parent: parent ? parent.form(this.obj.parent) : parent };
|
||||
parent: parent ? parent.form(parentFrame) : parent };
|
||||
|
||||
if (aObject.type == "object") {
|
||||
if (this.obj.parent) {
|
||||
form.type = "with";
|
||||
} else {
|
||||
form.type = "object";
|
||||
}
|
||||
form.object = this.threadActor.createValueGrip(aObject.object);
|
||||
} else {
|
||||
if (aObject.class == "Function") {
|
||||
if (this.obj.type == "with") {
|
||||
form.type = "with";
|
||||
form.object = this.threadActor.createValueGrip(this.obj.object);
|
||||
} else if (this.obj.type == "object") {
|
||||
form.type = "object";
|
||||
form.object = this.threadActor.createValueGrip(this.obj.object);
|
||||
} else { // this.obj.type == "declarative"
|
||||
if (aObject.callee) {
|
||||
form.type = "function";
|
||||
form.function = this.threadActor.createValueGrip(aObject);
|
||||
form.functionName = aObject.name;
|
||||
form.function = this.threadActor.createValueGrip(aObject.callee);
|
||||
form.functionName = getFunctionName(aObject.callee);
|
||||
} else {
|
||||
form.type = "block";
|
||||
}
|
||||
|
@ -1382,14 +1384,14 @@ EnvironmentActor.prototype = {
|
|||
|
||||
/**
|
||||
* Return the identifier bindings object as required by the remote protocol
|
||||
* specification. Note that the requirement of passing the frame or function
|
||||
* as a parameter is only temporary, since when bug 747514 lands, the
|
||||
* environment will have a callee property that will contain it.
|
||||
* specification. Note that the requirement of passing the frame as a
|
||||
* parameter is only temporary, since when bug 747514 lands, the environment
|
||||
* will have a callee property that will contain it.
|
||||
*
|
||||
* @param object aObject [optional]
|
||||
* The stack frame or function object whose environment bindings are
|
||||
* being generated. When left unspecified, the bindings do not contain
|
||||
* an 'arguments' property.
|
||||
* @param Debugger.Frame aObject [optional]
|
||||
* The stack frame whose environment bindings are being generated. When
|
||||
* left unspecified, the bindings do not contain an 'arguments'
|
||||
* property.
|
||||
*/
|
||||
_bindings: function EA_bindings(aObject) {
|
||||
let bindings = { arguments: [], variables: {} };
|
||||
|
@ -1514,3 +1516,22 @@ EnvironmentActor.prototype.requestTypes = {
|
|||
"assign": EnvironmentActor.prototype.onAssign,
|
||||
"bindings": EnvironmentActor.prototype.onBindings
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to deduce the name of the provided function.
|
||||
*
|
||||
* @param Debugger.Object aFunction
|
||||
* The function whose name will be returned.
|
||||
*/
|
||||
function getFunctionName(aFunction) {
|
||||
let name;
|
||||
if (aFunction.name) {
|
||||
name = aFunction.name;
|
||||
} else {
|
||||
let desc = aFunction.getOwnPropertyDescriptor("displayName");
|
||||
if (desc && desc.value && typeof desc.value == "string") {
|
||||
name = desc.value;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check a frame actor's parent bindings.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function() {
|
||||
attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||
let parentEnv = aPacket.frame.environment.parent;
|
||||
let bindings = parentEnv.bindings;
|
||||
let args = bindings.arguments;
|
||||
let vars = bindings.variables;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
do_check_eq(args.length, 0);
|
||||
do_check_eq(vars.stopMe.value.type, "object");
|
||||
do_check_eq(vars.stopMe.value.class, "Function");
|
||||
do_check_true(!!vars.stopMe.value.actor);
|
||||
|
||||
parentEnv = parentEnv.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
let objClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||
objClient.getPrototypeAndProperties(function(aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.Object.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.Object.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.Object.value.actor);
|
||||
|
||||
gThreadClient.resume(function() {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function() {
|
||||
function stopMe(aNumber, aBool, aString, aNull, aUndefined, aObject) {
|
||||
var a = 1;
|
||||
var b = true;
|
||||
var c = { a: "a" };
|
||||
debugger;
|
||||
};
|
||||
stopMe(42, true, "nasu", null, undefined, { foo: "bar" });
|
||||
} + ")()");
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check a |with| frame actor's bindings.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function() {
|
||||
attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||
let env = aPacket.frame.environment;
|
||||
do_check_neq(env, undefined);
|
||||
|
||||
let parentEnv = env.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
|
||||
let bindings = parentEnv.bindings;
|
||||
let args = bindings.arguments;
|
||||
let vars = bindings.variables;
|
||||
do_check_eq(args.length, 1);
|
||||
do_check_eq(args[0].aNumber.value, 10);
|
||||
do_check_eq(vars.r.value, 10);
|
||||
do_check_eq(vars.a.value, Math.PI * 100);
|
||||
do_check_eq(vars.arguments.value.class, "Arguments");
|
||||
do_check_true(!!vars.arguments.value.actor);
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(env.object);
|
||||
objClient.getPrototypeAndProperties(function(aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||
|
||||
gThreadClient.resume(function() {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function() {
|
||||
function stopMe(aNumber) {
|
||||
var a;
|
||||
var r = aNumber;
|
||||
with (Math) {
|
||||
a = PI * r * r;
|
||||
debugger;
|
||||
}
|
||||
};
|
||||
stopMe(10);
|
||||
} + ")()");
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check the environment bindongs of a |with| within a |with|.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function() {
|
||||
attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||
let env = aPacket.frame.environment;
|
||||
do_check_neq(env, undefined);
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(env.object);
|
||||
objClient.getPrototypeAndProperties(function(aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.one.value, 1);
|
||||
do_check_eq(aResponse.ownProperties.two.value, 2);
|
||||
do_check_eq(aResponse.ownProperties.foo, undefined);
|
||||
|
||||
let parentEnv = env.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
|
||||
let parentClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||
parentClient.getPrototypeAndProperties(function(aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||
|
||||
parentEnv = parentEnv.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
|
||||
let bindings = parentEnv.bindings;
|
||||
let args = bindings.arguments;
|
||||
let vars = bindings.variables;
|
||||
do_check_eq(args.length, 1);
|
||||
do_check_eq(args[0].aNumber.value, 10);
|
||||
do_check_eq(vars.r.value, 10);
|
||||
do_check_eq(vars.a.value, Math.PI * 100);
|
||||
do_check_eq(vars.arguments.value.class, "Arguments");
|
||||
do_check_true(!!vars.arguments.value.actor);
|
||||
do_check_eq(vars.foo.value, 2 * Math.PI);
|
||||
|
||||
gThreadClient.resume(function() {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function() {
|
||||
function stopMe(aNumber) {
|
||||
var a, obj = { one: 1, two: 2 };
|
||||
var r = aNumber;
|
||||
with (Math) {
|
||||
a = PI * r * r;
|
||||
with (obj) {
|
||||
var foo = two * PI;
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
};
|
||||
stopMe(10);
|
||||
} + ")()");
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check the environment bindings of a |with| in global scope.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function() {
|
||||
attachTestGlobalClientAndResume(gClient, "test-stack", function(aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||
let env = aPacket.frame.environment;
|
||||
do_check_neq(env, undefined);
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(env.object);
|
||||
objClient.getPrototypeAndProperties(function(aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||
|
||||
let parentEnv = env.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
|
||||
let parentClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||
parentClient.getPrototypeAndProperties(function(aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.a.value, Math.PI * 100);
|
||||
do_check_eq(aResponse.ownProperties.r.value, 10);
|
||||
do_check_eq(aResponse.ownProperties.Object.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.Object.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.Object.value.actor);
|
||||
|
||||
gThreadClient.resume(function() {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("var a, r = 10;\n" +
|
||||
"with (Math) {\n" +
|
||||
" a = PI * r * r;\n" +
|
||||
" debugger;\n" +
|
||||
"}");
|
||||
}
|
|
@ -54,3 +54,7 @@ tail =
|
|||
[test_stepping-03.js]
|
||||
[test_stepping-04.js]
|
||||
[test_framebindings-01.js]
|
||||
[test_framebindings-02.js]
|
||||
[test_framebindings-03.js]
|
||||
[test_framebindings-04.js]
|
||||
[test_framebindings-05.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче