Bug 812859 - A JavaScript module to mark deprecation;r=dolske

This commit is contained in:
David Rajchenbach-Teller 2013-01-10 20:55:42 +01:00
Родитель 2042d1e413
Коммит df6964093f
5 изменённых файлов: 223 добавлений и 0 удалений

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

@ -368,6 +368,9 @@ pref("toolkit.telemetry.debugSlowSql", false);
pref("toolkit.identity.enabled", false);
pref("toolkit.identity.debug", false);
// Enable deprecation warnings.
pref("devtools.errorconsole.deprecation_warnings", true);
// Disable remote debugging protocol logging
pref("devtools.debugger.log", false);
// Disable remote debugging connections

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

@ -0,0 +1,81 @@
/* 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";
this.EXPORTED_SYMBOLS = [ "Deprecated" ];
const Cu = Components.utils;
const Ci = Components.interfaces;
const PREF_DEPRECATION_WARNINGS = "devtools.errorconsole.deprecation_warnings";
Cu.import("resource://gre/modules/Services.jsm");
// A flag that indicates whether deprecation warnings should be logged.
let logWarnings = Services.prefs.getBoolPref(PREF_DEPRECATION_WARNINGS);
Services.prefs.addObserver(PREF_DEPRECATION_WARNINGS,
function (aSubject, aTopic, aData) {
logWarnings = Services.prefs.getBoolPref(PREF_DEPRECATION_WARNINGS);
}, false);
/**
* Build a callstack log message.
*
* @param nsIStackFrame aStack
* A callstack to be converted into a string log message.
*/
function stringifyCallstack (aStack) {
// If aStack is invalid, use Components.stack (ignoring the last frame).
if (!aStack || !(aStack instanceof Ci.nsIStackFrame)) {
aStack = Components.stack.caller;
}
let frame = aStack.caller;
let msg = "";
// Get every frame in the callstack.
while (frame) {
msg += frame.filename + " " + frame.lineNumber +
" " + frame.name + "\n";
frame = frame.caller;
}
return msg;
}
const Deprecated = {
/**
* Log a deprecation warning.
*
* @param string aText
* Deprecation warning text.
* @param string aUrl
* A URL pointing to documentation describing deprecation
* and the way to address it.
* @param nsIStackFrame aStack
* An optional callstack. If it is not provided a
* snapshot of the current JavaScript callstack will be
* logged.
*/
warning: function (aText, aUrl, aStack) {
if (!logWarnings) {
return;
}
// If URL is not provided, report an error.
if (!aUrl) {
Cu.reportError("Error in Deprecated.warning: warnings must " +
"provide a URL documenting this deprecation.");
return;
}
let textMessage = "DEPRECATION WARNING: " + aText +
"\nYou may find more details about this deprecation at: " +
aUrl + "\n" +
// Append a callstack part to the deprecation message.
stringifyCallstack(aStack);
// Report deprecation warning.
Cu.reportError(textMessage);
}
};

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

@ -59,6 +59,7 @@ TEST_DIRS += tests
EXTRA_JS_MODULES = \
debug.js \
DeferredTask.jsm \
Deprecated.jsm \
Dict.jsm \
Geometry.jsm \
InlineSpellChecker.jsm \

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

@ -29,6 +29,7 @@ MOCHITEST_BROWSER_FILES = \
browser_DeferredTask.js \
browser_default_image_filename.js \
browser_Troubleshoot.js \
browser_Deprecated.js \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,137 @@
/* 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/. */
const Ci = Components.interfaces;
const Cu = Components.utils;
const PREF_DEPRECATION_WARNINGS = "devtools.errorconsole.deprecation_warnings";
Cu.import("resource://gre/modules/Services.jsm", this);
Cu.import("resource://gre/modules/Deprecated.jsm", this);
// Using this named functions to test deprecation and the properly logged
// callstacks.
function basicDeprecatedFunction () {
Deprecated.warning("this method is deprecated.", "http://example.com");
return true;
}
function deprecationFunctionBogusCallstack () {
Deprecated.warning("this method is deprecated.", "http://example.com", {
caller: {}
});
return true;
}
function deprecationFunctionCustomCallstack () {
// Get the nsIStackFrame that will contain the name of this function.
function getStack () {
return Components.stack;
}
Deprecated.warning("this method is deprecated.", "http://example.com",
getStack());
return true;
}
let tests = [
// Test deprecation warning without passing the callstack.
{
deprecatedFunction: basicDeprecatedFunction,
expectedObservation: function (aMessage) {
testAMessage(aMessage);
ok(aMessage.errorMessage.indexOf("basicDeprecatedFunction") > 0,
"Callstack is correctly logged.");
}
},
// Test a reported error when URL to documentation is not passed.
{
deprecatedFunction: function () {
Deprecated.warning("this method is deprecated.");
return true;
},
expectedObservation: function (aMessage) {
ok(aMessage.errorMessage.indexOf("must provide a URL") > 0,
"Deprecation warning logged an empty URL argument.");
}
},
// Test deprecation with a bogus callstack passed as an argument (it will be
// replaced with the current call stack).
{
deprecatedFunction: deprecationFunctionBogusCallstack,
expectedObservation: function (aMessage) {
testAMessage(aMessage);
ok(aMessage.errorMessage.indexOf("deprecationFunctionBogusCallstack") > 0,
"Callstack is correctly logged.");
}
},
// When pref is unset Deprecated.warning should not log anything.
{
deprecatedFunction: basicDeprecatedFunction,
expectedObservation: function (aMessage) {
// Nothing should be logged when pref is false.
ok(false, "Deprecated warning should not log anything when pref is unset.");
},
// Set pref to false.
logWarnings: false
},
// Test deprecation with a valid custom callstack passed as an argument.
{
deprecatedFunction: deprecationFunctionCustomCallstack,
expectedObservation: function (aMessage) {
testAMessage(aMessage);
ok(aMessage.errorMessage.indexOf("deprecationFunctionCustomCallstack") > 0,
"Callstack is correctly logged.");
finish();
},
// Set pref to true.
logWarnings: true
}];
function test() {
waitForExplicitFinish();
// Check if Deprecated is loaded.
ok(Deprecated, "Deprecated object exists");
// Run all test cases.
tests.forEach(testDeprecated);
}
// Test Consle Message attributes.
function testAMessage (aMessage) {
ok(aMessage.errorMessage.indexOf("DEPRECATION WARNING: " +
"this method is deprecated.") === 0,
"Deprecation is correctly logged.");
ok(aMessage.errorMessage.indexOf("http://example.com") > 0,
"URL is correctly logged.");
}
function testDeprecated (test) {
// Deprecation warnings will be logged only when the preference is set.
if (typeof test.logWarnings !== "undefined") {
Services.prefs.setBoolPref(PREF_DEPRECATION_WARNINGS, test.logWarnings);
}
// Create a console listener.
let consoleListener = {
observe: function (aMessage) {
// Ignore unexpected messages.
if (!(aMessage instanceof Ci.nsIScriptError)) {
return;
}
if (aMessage.errorMessage.indexOf("DEPRECATION WARNING: ") < 0 &&
aMessage.errorMessage.indexOf("must provide a URL") < 0) {
return;
}
ok(aMessage instanceof Ci.nsIScriptError,
"Deprecation log message is an instance of type nsIScriptError.");
test.expectedObservation(aMessage);
}
};
// Register a listener that contains the tests.
Services.console.registerListener(consoleListener);
// Run the deprecated function.
test.deprecatedFunction();
// Unregister a listener.
Services.console.unregisterListener(consoleListener);
}