Contents |
This guide is initially intended for code originated by Flock.
When editing existing scripts, the most important rule is to be consistent with the prevailing style, even when it's at odds with this document. If you're doing a significant refactor however, consider making the code match the style documented here. You may also pick a file and make a stylistic-only commit, to make it match the guidelines in this document. Do not mix minor functional code changes with style changes. Do not change the style in files that originate from upstream Firefox, since that makes merges much harder.
This is based on Mozilla's style guide.
if (x > 0).
svn:eol-style to native on all plain text files.
svn propset svn:eol-style native foo.txt
const FOO1 = 1; const FOO_BAR = "foo bar"; const FOO3 = 3; const FOOBAR1 = "foobar1"; const BAR = 2;
function valueObject(aValue) {
return { value: aValue };
}
var aHash = { key1: value1, key2: value2, ..., keyN: valueN };
if (arg1 ||
arg2 < arg1 ||
arg3)
{
doSomething();
}
if (dlmgrWindow) {
return;
}
if (dlmgrWindow) {
dlmgrWindow.focus();
}
if (dlmgrWindow) {
dlmgrWindow.focus();
} else {
dlmgr.open(window, null);
}
\uXXXX unicode escapes for non-ASCII characters. The character set for XUL, DTD, script, and properties files is UTF-8 which is not easily readable.
else after return, i.e.
if (x < y) return -1; if (x > y) return 1; return 0;
i++ and ++i are acceptable.
var offlineObserver = {
observe: function OO_observe(aSubject, aTopic, aState) {
if (aTopic == "network:offline-status-changed")
setOfflineUI(aState == "offline");
}
};
const kDisplayModeNormal = 0;.
gFormatToolbar.
_internalFunction
onLoad, onDialogAccept, onDialogCancel, etc., where this is unambiguous.
var UniqueName = {
_privateMember: 3,
publicMember: "A string",
init: function() {
this.doSomething(this.anotherMember);
},
doSomething: function(aParam) {
alert(aParam);
}
};
return; with return value; (use return null; instead of return;)
"name" in aObject, or if you are expecting a particular type you may use typeof aObject.name == "function" (or whichever type you are expecting).
[value1, value2] to create a JavaScript array in preference to using new Array(value1, value2) which can be confusing, as new Array(length) will actually create a physically empty array with the given logical length, while [value] will always create a 1-element array. You cannot actually guarantee to be able to preallocate memory for an array.
{ member: value, ... } to create a JavaScript object; a useful advantage over new Object() is the ability to create initial properties and use extended JavaScript syntax to define getters and setters. If having defined a constructor you need to assign default properties it is preferred to assign an object literal to the prototype property. For example,
function SupportsString(data) {
this.data = data;
}
SupportsString.prototype = {
toString: function toString() {
return data;
}
};
aString is not completely whitespace use /\S/.test(aString); only use aString.search if you need to know the position of the result, or aString.match if you need to collect matching substrings (delimited by parentheses in the regular expression). Regular expressions are less useful if the match is unknown in advance, or to extract substrings in known positions in the string. For instance, aString.slice(-1) returns the last letter in aString, or the empty string if aString is empty.
true or false. For example, write if (ioService.offline). Compare objects to null, numbers to 0 or strings to "" if there is chance for confusion.
var myTag = <menuitem id="prefMenuitem" />;
function FeedManager(data) {
this.data = data;
}
FeedManager.prototype = {
getData : function FM_getData() {
return data;
}
};
windowManager.getEnumerator(aType).hasMoreElements() may be replaced with windowManager.getMostRecentWindow(aType) != null.
QueryInterface unless you expect to succeed. Instead, use instanceof, e,g,:
if (target instanceof Components.interfaces.nsIRDFResource) return target.Value; if (target instanceof Components.interfaces.nsIRDFLiteral) return target.Value; return null;
QueryInterface, it always returns the original variable if it succeeds. XPConnect knows all about tearoffs and modifies the object that you QueryInterface or instanceof to cache all its known interfaces.
QueryInterface method. However in JavaScript this is quite simple even in the case of a weak reference which in C++ requires a helper class:
var weakObserver = {
QueryInterface: function QueryInterface(aIID) {
if (aIID.equals(Components.interfaces.nsIObserver) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
observe: function observe(aSubject, aTopic, aState) {
}
}
childNodes.length > 0. Similarly prefer document.getElementsByTagName(aTag).item(0) != null to document.getElementsByTagName(aTag).length > 0.
ordinal attribute but this defaults to "1" if it is not present.
class attribute, but unfortunately class is a reserved identifier, so the property is named className. (The property could have been implemented as ['class'] but that just looks silly.)
hidden and collapsed attributes to properties, but note that these are boolean properties whereas the above list are all string properties.
event.keyCode == KeyEvent.DOM_VK_RETURN rather than event.keyCode == 13.
Examples of valid indentation:
var result = prompt(aMessage,
aInitialValue,
aCaption);
var ioSvc = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var myObject = { a: foo, b: bar };
var ioSvc = CC["@mozilla.org/network/io-service;1"]
.getService(CI.nsIIOService);
switch (aSomething) {
// Do something for foo
case "foo":
fooFunction();
break;
// Do something else for bar
case "bar":
barFunction();
break;
// baz falls through
case "baz":
default:
defaultFunction();
break;
}
buildTooltip: function facebookPhoto_buildTooltip()
{
default xml namespace =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var tip =
<vbox>
<hbox>
<image src={this.midSizePhoto} style="margin-bottom: 2px;" />
<spacer flex="1" />
</hbox>
<hbox>
<image src={this.icon} />
<vbox style="max-width: 250px;">
<label crop="end">{this.title}</label>
<label class="user">{this.username}</label>
</vbox>
</hbox>
</vbox>;
var parser = CC["@mozilla.org/xmlextras/domparser;1"].
createInstance(CI.nsIDOMParser);
var doc = parser.parseFromString(tip, "text/xml");
return doc.documentElement;
},
Valid styles of XPCOM component initialization:
var ioSvc = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
const CI = Components.interfaces;
const CC = Components.classes;
var ioSvc = CC["@mozilla.org/network/io-service;1"]
.getService(CI.nsIIOService);
CC["@mozilla.org/consoleservice;1"].getService(CI.nsIConsoleService)
.logStringMessage(aMsg);