Bug 913665 - Detect minified files and pretty print them by default; r=fitzgen

This commit is contained in:
Hubert B Manilla 2013-12-24 15:32:55 +01:00
Родитель f46f9860a6
Коммит 4e53556018
14 изменённых файлов: 360 добавлений и 2 удалений

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

@ -1121,6 +1121,7 @@ pref("devtools.debugger.pause-on-exceptions", false);
pref("devtools.debugger.ignore-caught-exceptions", true);
pref("devtools.debugger.source-maps-enabled", true);
pref("devtools.debugger.pretty-print-enabled", true);
pref("devtools.debugger.auto-pretty-print", true);
pref("devtools.debugger.tracer", false);
// The default Debugger UI settings

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

@ -2185,6 +2185,7 @@ let Prefs = new ViewHelpers.Prefs("devtools", {
ignoreCaughtExceptions: ["Bool", "debugger.ignore-caught-exceptions"],
sourceMapsEnabled: ["Bool", "debugger.source-maps-enabled"],
prettyPrintEnabled: ["Bool", "debugger.pretty-print-enabled"],
autoPrettyPrint: ["Bool", "debugger.auto-pretty-print"],
tracerEnabled: ["Bool", "debugger.tracer"],
editorTabSize: ["Int", "editor.tabsize"]
});

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

@ -3,8 +3,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Used to detect minification for automatic pretty printing
const SAMPLE_SIZE = 30; // no of lines
const INDENT_COUNT_THRESHOLD = 20; // percentage
/**
* Functions handling the sources UI.
*/
@ -769,9 +774,20 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
if (!sourceItem) {
return;
}
const { source } = sourceItem.attachment;
const sourceClient = gThreadClient.source(source);
// The container is not empty and an actual item was selected.
DebuggerView.setEditorLocation(sourceItem.value);
if (Prefs.autoPrettyPrint && !sourceClient.isPrettyPrinted) {
DebuggerController.SourceScripts.getText(source).then(([, aText]) => {
if (SourceUtils.isMinified(sourceClient, aText)) {
this.togglePrettyPrint();
}
}).then(null, e => DevToolsUtils.reportException("_onSourceSelect", e));
}
// Set window title. No need to split the url by " -> " here, because it was
// already sanitized when the source was added.
document.title = L10N.getFormatStr("DebuggerWindowScriptTitle", sourceItem.value);
@ -1432,6 +1448,7 @@ TracerView.prototype = Heritage.extend(WidgetMethods, {
let SourceUtils = {
_labelsCache: new Map(), // Can't use WeakMaps because keys are strings.
_groupsCache: new Map(),
_minifiedCache: new WeakMap(),
/**
* Returns true if the specified url and/or content type are specific to
@ -1446,13 +1463,53 @@ let SourceUtils = {
},
/**
* Clears the labels cache, populated by methods like
* Determines if the source text is minified by using
* the percentage indented of a subset of lines
*
* @param string aText
* The source text.
* @return boolean
* True if source text is minified.
*/
isMinified: function(sourceClient, aText){
if (this._minifiedCache.has(sourceClient)) {
return this._minifiedCache.get(sourceClient);
}
let isMinified;
let lineEndIndex = 0;
let lineStartIndex = 0;
let lines = 0;
let indentCount = 0;
// Strip comments.
aText = aText.replace(/\/\*[\S\s]*?\*\/|\/\/(.+|\n)/g, "");
while (lines++ < SAMPLE_SIZE) {
lineEndIndex = aText.indexOf("\n", lineStartIndex);
if (lineEndIndex == -1) {
break;
}
if (/^\s+/.test(aText.slice(lineStartIndex, lineEndIndex))) {
indentCount++;
}
lineStartIndex = lineEndIndex + 1;
}
isMinified = ((indentCount / lines ) * 100) < INDENT_COUNT_THRESHOLD;
this._minifiedCache.set(sourceClient, isMinified);
return isMinified;
},
/**
* Clears the labels, groups and minify cache, populated by methods like
* SourceUtils.getSourceLabel or Source Utils.getSourceGroup.
* This should be done every time the content location changes.
*/
clearCache: function() {
this._labelsCache.clear();
this._groupsCache.clear();
this._minifiedCache.clear();
},
/**

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

@ -196,6 +196,7 @@ ToolbarView.prototype = {
function OptionsView() {
dumpn("OptionsView was instantiated");
this._toggleAutoPrettyPrint = this._toggleAutoPrettyPrint.bind(this);
this._togglePauseOnExceptions = this._togglePauseOnExceptions.bind(this);
this._toggleIgnoreCaughtExceptions = this._toggleIgnoreCaughtExceptions.bind(this);
this._toggleShowPanesOnStartup = this._toggleShowPanesOnStartup.bind(this);
@ -212,6 +213,7 @@ OptionsView.prototype = {
dumpn("Initializing the OptionsView");
this._button = document.getElementById("debugger-options");
this._autoPrettyPrint = document.getElementById("auto-pretty-print");
this._pauseOnExceptionsItem = document.getElementById("pause-on-exceptions");
this._ignoreCaughtExceptionsItem = document.getElementById("ignore-caught-exceptions");
this._showPanesOnStartupItem = document.getElementById("show-panes-on-startup");
@ -219,6 +221,7 @@ OptionsView.prototype = {
this._showVariablesFilterBoxItem = document.getElementById("show-vars-filter-box");
this._showOriginalSourceItem = document.getElementById("show-original-source");
this._autoPrettyPrint.setAttribute("checked", Prefs.autoPrettyPrint);
this._pauseOnExceptionsItem.setAttribute("checked", Prefs.pauseOnExceptions);
this._ignoreCaughtExceptionsItem.setAttribute("checked", Prefs.ignoreCaughtExceptions);
this._showPanesOnStartupItem.setAttribute("checked", Prefs.panesVisibleOnStartup);
@ -257,6 +260,14 @@ OptionsView.prototype = {
window.emit(EVENTS.OPTIONS_POPUP_HIDDEN);
},
/**
* Listener handling the 'auto pretty print' menuitem command.
*/
_toggleAutoPrettyPrint: function(){
Prefs.autoPrettyPrint =
this._autoPrettyPrint.getAttribute("checked") == "true";
},
/**
* Listener handling the 'pause on exceptions' menuitem command.
*/

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

@ -74,6 +74,8 @@
oncommand="DebuggerView.WatchExpressions._onCmdAddExpression()"/>
<command id="removeAllWatchExpressionsCommand"
oncommand="DebuggerView.WatchExpressions._onCmdRemoveAllExpressions()"/>
<command id="toggleAutoPrettyPrint"
oncommand="DebuggerView.Options._toggleAutoPrettyPrint()"/>
<command id="togglePauseOnExceptions"
oncommand="DebuggerView.Options._togglePauseOnExceptions()"/>
<command id="toggleIgnoreCaughtExceptions"
@ -172,6 +174,11 @@
onpopupshowing="DebuggerView.Options._onPopupShowing()"
onpopuphiding="DebuggerView.Options._onPopupHiding()"
onpopuphidden="DebuggerView.Options._onPopupHidden()">
<menuitem id="auto-pretty-print"
type="checkbox"
label="&debuggerUI.autoPrettyPrint;"
accesskey="&debuggerUI.autoPrettyPrint.key;"
command="toggleAutoPrettyPrint"/>
<menuitem id="pause-on-exceptions"
type="checkbox"
label="&debuggerUI.pauseExceptions;"

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

@ -25,6 +25,11 @@ support-files =
code_ugly-2.js
code_ugly-3.js
code_ugly-4.js
code_ugly-5.js
code_ugly-6.js
code_ugly-7.js
doc_auto-pretty-print-01.html
doc_auto-pretty-print-02.html
doc_binary_search.html
doc_blackboxing.html
doc_closures.html
@ -65,6 +70,8 @@ support-files =
testactors.js
[browser_dbg_aaa_run_first_leaktest.js]
[browser_dbg_auto-pretty-print-01.js]
[browser_dbg_auto-pretty-print-02.js]
[browser_dbg_bfcache.js]
[browser_dbg_blackboxing-01.js]
[browser_dbg_blackboxing-02.js]

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

@ -0,0 +1,107 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test auto pretty printing.
const TAB_URL = EXAMPLE_URL + "doc_auto-pretty-print-01.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gPrefs, gOptions, gView;
let gFirstSourceLabel = "code_ugly-5.js";
let gSecondSourceLabel = "code_ugly-6.js";
function test(){
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gPrefs = gDebugger.Prefs;
gOptions = gDebugger.DebuggerView.Options;
gView = gDebugger.DebuggerView;
// Should be on by default.
testAutoPrettyPrintOn();
waitForSourceShown(gPanel, gFirstSourceLabel)
.then(testSourceIsUgly)
.then(() => waitForSourceShown(gPanel, gFirstSourceLabel))
.then(testSourceIsPretty)
.then(disableAutoPrettyPrint)
.then(testAutoPrettyPrintOff)
.then(() => {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
gSources.selectedIndex = 1;
return finished;
})
.then(testSecondSourceLabel)
.then(testSourceIsUgly)
// Re-enable auto pretty printing for browser_dbg_auto-pretty-print-02.js
.then(enableAutoPrettyPrint)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
})
});
}
function testSourceIsUgly() {
ok(!gEditor.getText().contains("\n "),
"The source shouldn't be pretty printed yet.");
}
function testSecondSourceLabel(){
ok(gSources.containsValue(EXAMPLE_URL + gSecondSourceLabel),
"Second source url is correct.");
}
function testProgressBarShown() {
const deck = gDebugger.document.getElementById("editor-deck");
is(deck.selectedIndex, 2, "The progress bar should be shown");
}
function testAutoPrettyPrintOn(){
is(gPrefs.autoPrettyPrint, true,
"The auto-pretty-print pref should be on.");
is(gOptions._autoPrettyPrint.getAttribute("checked"), "true",
"The Auto pretty print menu item should be checked.");
}
function disableAutoPrettyPrint(){
gOptions._autoPrettyPrint.setAttribute("checked", "false");
gOptions._toggleAutoPrettyPrint();
gOptions._onPopupHidden();
}
function enableAutoPrettyPrint(){
gOptions._autoPrettyPrint.setAttribute("checked", "true");
gOptions._toggleAutoPrettyPrint();
gOptions._onPopupHidden();
}
function testAutoPrettyPrintOff(){
is(gPrefs.autoPrettyPrint, false,
"The auto-pretty-print pref should be off.");
isnot(gOptions._autoPrettyPrint.getAttribute("checked"), "true",
"The Auto pretty print menu item should not be checked.");
}
function testSourceIsPretty() {
ok(gEditor.getText().contains("\n "),
"The source should be pretty printed.")
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
gOptions = null;
gPrefs = null;
gView = null;
});

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

@ -0,0 +1,110 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that auto pretty printing doesn't accidentally toggle
* pretty printing off when we switch to a minified source
* that is already pretty printed.
*/
const TAB_URL = EXAMPLE_URL + "doc_auto-pretty-print-02.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gPrefs, gOptions, gView;
let gFirstSourceLabel = "code_ugly-6.js";
let gSecondSourceLabel = "code_ugly-7.js";
function test(){
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gPrefs = gDebugger.Prefs;
gOptions = gDebugger.DebuggerView.Options;
gView = gDebugger.DebuggerView;
// Should be on by default.
testAutoPrettyPrintOn();
waitForSourceShown(gPanel, gFirstSourceLabel)
.then(testSourceIsUgly)
.then(() => waitForSourceShown(gPanel, gFirstSourceLabel))
.then(testSourceIsPretty)
.then(testPrettyPrintButtonOn)
.then(() => {
// Switch to the second source.
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
gSources.selectedIndex = 1;
return finished;
})
.then(testSecondSourceLabel)
.then(() => {
// Switch back to first source.
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
gSources.selectedIndex = 0;
return finished;
})
.then(testFirstSourceLabel)
.then(testPrettyPrintButtonOn)
// Disable auto pretty printing so it does not affect the following tests.
.then(disableAutoPrettyPrint)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
})
});
}
function testSourceIsUgly() {
ok(!gEditor.getText().contains("\n "),
"The source shouldn't be pretty printed yet.");
}
function testFirstSourceLabel(){
ok(gSources.containsValue(EXAMPLE_URL + gFirstSourceLabel),
"First source url is correct.");
}
function testSecondSourceLabel(){
ok(gSources.containsValue(EXAMPLE_URL + gSecondSourceLabel),
"Second source url is correct.");
}
function testAutoPrettyPrintOn(){
is(gPrefs.autoPrettyPrint, true,
"The auto-pretty-print pref should be on.");
is(gOptions._autoPrettyPrint.getAttribute("checked"), "true",
"The Auto pretty print menu item should be checked.");
}
function testPrettyPrintButtonOn(){
is(gDebugger.document.getElementById("pretty-print").checked, true,
"The button should be checked when the source is selected.");
}
function disableAutoPrettyPrint(){
gOptions._autoPrettyPrint.setAttribute("checked", "false");
gOptions._toggleAutoPrettyPrint();
gOptions._onPopupHidden();
}
function testSourceIsPretty() {
ok(gEditor.getText().contains("\n "),
"The source should be pretty printed.")
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
gOptions = null;
gPrefs = null;
gView = null;
});

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

@ -0,0 +1,14 @@
/*1385419625,181944095,JIT Construction: v1021776,en_US*/
/**
* Copyright Test Inc.
*
* Licensed under the Apache License, Version 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*/
// Copyright Test Inc.
//
// etc...
// etc...
function foo(){var a=1;var b=2;bar(a,b);}
function bar(c,d){debugger;}
foo();

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

@ -0,0 +1,5 @@
// Copyright Test Inc.
//
// etc...
// etc...
function main(){ return 0; }

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

@ -0,0 +1,5 @@
// Copyright Test Inc.
//
// etc...
// etc...
function foo(){}; foo();

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

@ -0,0 +1,14 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Auto Pretty Printing Test Page</title>
</head>
<body>
<script src="code_ugly-5.js"></script>
<script src="code_ugly-6.js"></script>
</body>
</html>

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

@ -0,0 +1,14 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Auto Pretty Printing Test Page</title>
</head>
<body>
<script src="code_ugly-6.js"></script>
<script src="code_ugly-7.js"></script>
</body>
</html>

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

@ -41,6 +41,11 @@
- button that pretty prints the selected source. -->
<!ENTITY debuggerUI.sources.prettyPrint "Prettify Source">
<!-- LOCALIZATION NOTE (debuggerUI.autoPrettyPrint): This is the label for the
- checkbox that toggles auto pretty print. -->
<!ENTITY debuggerUI.autoPrettyPrint "Auto Prettify Minified Sources">
<!ENTITY debuggerUI.autoPrettyPrint.key "P">
<!-- LOCALIZATION NOTE (debuggerUI.sources.toggleBreakpoints): This is the tooltip for the
- button that toggles all breakpoints for all sources. -->
<!ENTITY debuggerUI.sources.toggleBreakpoints "Enable/disable all breakpoints">
@ -66,7 +71,7 @@
<!ENTITY debuggerUI.pauseExceptions "Pause on exceptions">
<!ENTITY debuggerUI.pauseExceptions.key "E">
<!-- LOCALIZATION NOTE (debuggerUI.pauseExceptions): This is the label for the
<!-- LOCALIZATION NOTE (debuggerUI.ignoreCaughtExceptions): This is the label for the
- checkbox that toggles ignoring caught exceptions. -->
<!ENTITY debuggerUI.ignoreCaughtExceptions "Ignore caught exceptions">
<!ENTITY debuggerUI.ignoreCaughtExceptions.key "C">