Bug 948893 - Hovering certain bounds in a HTML source while paused in the debugger can sometimes incorrectly show a variable inspection popup, r=past

This commit is contained in:
Victor Porof 2013-12-13 22:28:04 +02:00
Родитель d1bf402a34
Коммит f6dea06b20
8 изменённых файлов: 111 добавлений и 34 удалений

Просмотреть файл

@ -1357,7 +1357,11 @@ VariableBubbleView.prototype = {
let scriptLine = hoveredLine - scriptLineOffset;
let scriptColumn = hoveredColumn - scriptColumnOffset;
let identifierInfo = parsedSource.getIdentifierAt(scriptLine + 1, scriptColumn);
let identifierInfo = parsedSource.getIdentifierAt({
line: scriptLine + 1,
column: scriptColumn,
scriptIndex: scriptInfo.index
});
// If the info is null, we're not hovering any identifier.
if (!identifierInfo) {

Просмотреть файл

@ -52,6 +52,7 @@ support-files =
doc_recursion-stack.html
doc_scope-variable.html
doc_scope-variable-2.html
doc_scope-variable-3.html
doc_script-switching-01.html
doc_script-switching-02.html
doc_step-out.html
@ -222,6 +223,7 @@ support-files =
[browser_dbg_variables-view-popup-06.js]
[browser_dbg_variables-view-popup-07.js]
[browser_dbg_variables-view-popup-08.js]
[browser_dbg_variables-view-popup-09.js]
[browser_dbg_variables-view-reexpand-01.js]
[browser_dbg_variables-view-reexpand-02.js]
[browser_dbg_variables-view-webidl.js]

Просмотреть файл

@ -33,44 +33,44 @@ function test() {
is(parsed.scriptCount, 3,
"There should be 3 scripts parsed in the parent HTML source.");
is(parsed.getScriptInfo(0).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(0).toSource(), "({start:-1, length:-1, index:-1})",
"There is no script at the beginning of the parent source.");
is(parsed.getScriptInfo(source.length - 1).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.length - 1).toSource(), "({start:-1, length:-1, index:-1})",
"There is no script at the end of the parent source.");
is(parsed.getScriptInfo(source.indexOf("let a")).toSource(), "({start:31, length:13})",
is(parsed.getScriptInfo(source.indexOf("let a")).toSource(), "({start:31, length:13, index:0})",
"The first script was located correctly.");
is(parsed.getScriptInfo(source.indexOf("let b")).toSource(), "({start:85, length:13})",
is(parsed.getScriptInfo(source.indexOf("let b")).toSource(), "({start:85, length:13, index:1})",
"The second script was located correctly.");
is(parsed.getScriptInfo(source.indexOf("let c")).toSource(), "({start:151, length:13})",
is(parsed.getScriptInfo(source.indexOf("let c")).toSource(), "({start:151, length:13, index:2})",
"The third script was located correctly.");
is(parsed.getScriptInfo(source.indexOf("let a") - 1).toSource(), "({start:31, length:13})",
is(parsed.getScriptInfo(source.indexOf("let a") - 1).toSource(), "({start:31, length:13, index:0})",
"The left edge of the first script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let b") - 1).toSource(), "({start:85, length:13})",
is(parsed.getScriptInfo(source.indexOf("let b") - 1).toSource(), "({start:85, length:13, index:1})",
"The left edge of the second script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let c") - 1).toSource(), "({start:151, length:13})",
is(parsed.getScriptInfo(source.indexOf("let c") - 1).toSource(), "({start:151, length:13, index:2})",
"The left edge of the third script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let a") - 2).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.indexOf("let a") - 2).toSource(), "({start:-1, length:-1, index:-1})",
"The left outside of the first script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let b") - 2).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.indexOf("let b") - 2).toSource(), "({start:-1, length:-1, index:-1})",
"The left outside of the second script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let c") - 2).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.indexOf("let c") - 2).toSource(), "({start:-1, length:-1, index:-1})",
"The left outside of the third script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let a") + 12).toSource(), "({start:31, length:13})",
is(parsed.getScriptInfo(source.indexOf("let a") + 12).toSource(), "({start:31, length:13, index:0})",
"The right edge of the first script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let b") + 12).toSource(), "({start:85, length:13})",
is(parsed.getScriptInfo(source.indexOf("let b") + 12).toSource(), "({start:85, length:13, index:1})",
"The right edge of the second script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let c") + 12).toSource(), "({start:151, length:13})",
is(parsed.getScriptInfo(source.indexOf("let c") + 12).toSource(), "({start:151, length:13, index:2})",
"The right edge of the third script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let a") + 13).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.indexOf("let a") + 13).toSource(), "({start:-1, length:-1, index:-1})",
"The right outside of the first script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let b") + 13).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.indexOf("let b") + 13).toSource(), "({start:-1, length:-1, index:-1})",
"The right outside of the second script was interpreted correctly.");
is(parsed.getScriptInfo(source.indexOf("let c") + 13).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.indexOf("let c") + 13).toSource(), "({start:-1, length:-1, index:-1})",
"The right outside of the third script was interpreted correctly.");
finish();

Просмотреть файл

@ -43,11 +43,11 @@ function test() {
is(parsed.scriptCount, 1,
"There should be 1 script parsed in the parent HTML source.");
is(parsed.getScriptInfo(source.indexOf("let a")).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.indexOf("let a")).toSource(), "({start:-1, length:-1, index:-1})",
"The first script shouldn't be considered valid.");
is(parsed.getScriptInfo(source.indexOf("let b")).toSource(), "({start:85, length:13})",
is(parsed.getScriptInfo(source.indexOf("let b")).toSource(), "({start:85, length:13, index:0})",
"The second script was located correctly.");
is(parsed.getScriptInfo(source.indexOf("let c")).toSource(), "({start:-1, length:-1})",
is(parsed.getScriptInfo(source.indexOf("let c")).toSource(), "({start:-1, length:-1, index:-1})",
"The third script shouldn't be considered valid.");
finish();

Просмотреть файл

@ -32,11 +32,11 @@ function test() {
is(parsed.scriptCount, 1,
"There should be 1 script parsed in the parent source.");
is(parsed.getScriptInfo(source.indexOf("let a")).toSource(), "({start:0, length:261})",
is(parsed.getScriptInfo(source.indexOf("let a")).toSource(), "({start:0, length:261, index:0})",
"The script location is correct (1).");
is(parsed.getScriptInfo(source.indexOf("<script>")).toSource(), "({start:0, length:261})",
is(parsed.getScriptInfo(source.indexOf("<script>")).toSource(), "({start:0, length:261, index:0})",
"The script location is correct (2).");
is(parsed.getScriptInfo(source.indexOf("</script>")).toSource(), "({start:0, length:261})",
is(parsed.getScriptInfo(source.indexOf("</script>")).toSource(), "({start:0, length:261, index:0})",
"The script location is correct (3).");
finish();

Просмотреть файл

@ -0,0 +1,33 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests opening inspecting variables works across scopes.
*/
const TAB_URL = EXAMPLE_URL + "doc_scope-variable-3.html";
function test() {
Task.spawn(function() {
let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
let win = panel.panelWin;
let bubble = win.DebuggerView.VariableBubble;
let tooltip = bubble._tooltip.panel;
// Allow this generator function to yield first.
executeSoon(() => debuggee.test());
yield waitForSourceAndCaretAndScopes(panel, ".html", 15);
yield openVarPopup(panel, { line: 12, ch: 10 });
ok(true, "The variable inspection popup was shown for the real variable.");
once(tooltip, "popupshown").then(() => {
ok(false, "The variable inspection popup shouldn't have been opened.");
});
reopenVarPopup(panel, { line: 18, ch: 10 });
yield waitForTime(1000);
yield resumeDebuggerThenCloseAndFinish(panel);
});
}

Просмотреть файл

@ -0,0 +1,23 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Debugger test page</title>
</head>
<body>
<script type="text/javascript">
var trap = "first script";
function test() {
debugger;
}
</script>
<script type="text/javascript">/*
trololol
*/</script>
</body>
</html>

Просмотреть файл

@ -132,15 +132,15 @@ SyntaxTreesPool.prototype = {
/**
* @see SyntaxTree.prototype.getIdentifierAt
*/
getIdentifierAt: function(aLine, aColumn) {
return this._first(this._call("getIdentifierAt", aLine, aColumn));
getIdentifierAt: function({ line, column, scriptIndex }) {
return this._first(this._call("getIdentifierAt", scriptIndex, line, column));
},
/**
* @see SyntaxTree.prototype.getNamedFunctionDefinitions
*/
getNamedFunctionDefinitions: function(aSubstring) {
return this._call("getNamedFunctionDefinitions", aSubstring);
return this._call("getNamedFunctionDefinitions", -1, aSubstring);
},
/**
@ -161,12 +161,19 @@ SyntaxTreesPool.prototype = {
* The offset and length relative to the enclosing script.
*/
getScriptInfo: function(aOffset) {
let info = { start: -1, length: -1, index: -1 };
for (let { offset, length } of this._trees) {
if (offset <= aOffset && offset + length >= aOffset) {
return { start: offset, length: length };
info.index++;
if (offset <= aOffset && offset + length >= aOffset) {
info.start = offset;
info.length = length;
return info;
}
}
return { start: -1, length: -1 };
info.index = -1;
return info;
},
/**
@ -182,23 +189,31 @@ SyntaxTreesPool.prototype = {
},
/**
* Handles a request for all known syntax trees.
* Handles a request for a specific or all known syntax trees.
*
* @param string aFunction
* The function name to call on the SyntaxTree instances.
* @param number aSyntaxTreeIndex
* The syntax tree for which to handle the request. If the tree at
* the specified index isn't found, the accumulated results for all
* syntax trees are returned.
* @param any aParams
* Any kind params to pass to the request function.
* @return array
* The results given by all known syntax trees.
*/
_call: function(aFunction, ...aParams) {
_call: function(aFunction, aSyntaxTreeIndex, ...aParams) {
let results = [];
let requestId = aFunction + aParams.toSource(); // Cache all the things!
let requestId = [aFunction, aSyntaxTreeIndex, aParams].toSource();
if (this._cache.has(requestId)) {
return this._cache.get(requestId);
}
for (let syntaxTree of this._trees) {
let requestedTree = this._trees[aSyntaxTreeIndex];
let targettedTrees = requestedTree ? [requestedTree] : this._trees;
for (let syntaxTree of targettedTrees) {
try {
results.push({
sourceUrl: syntaxTree.url,