Skip to content

Instantly share code, notes, and snippets.

@thebigbad
Created December 28, 2009 20:06
Show Gist options
  • Save thebigbad/264894 to your computer and use it in GitHub Desktop.
Save thebigbad/264894 to your computer and use it in GitHub Desktop.
// Usage:
// var file = fopen("/tmp/firefuck.txt");
// file.writeString("Hello, sir. How are you?\n");
// file.close();
var fopen = function (path) {
try {
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(path);
var stream = Components.classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
stream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
createInstance(Components.interfaces.nsIConverterOutputStream);
converter.init(stream, "UTF-8", 0, 1);
return converter;
} catch (e) {
puts("Cannot create file: " + path);
throw e;
}
};
var observerService = Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
var myObserver = {
observe: function (subject, topic, data) {
console.log("I observed a " + topic + " event");
console.log("I was notified by " + subject);
console.log("I received this data: " + data);
},
register: function () {
observerService.addObserver(this, "myTopicID", false);
},
unregister: function () {
observerService.removeObserver(this, "myTopicID");
}
};
var myNotifier = {
notify: function () {
observerService.notifyObservers(this, "myTopicID", { x: 0, y: 1, z: 2 });
}
};
myObserver.register();
myNotifier.notify(); // Causes myObserver.observe to be run
myObserver.unregister(); // Unregisters with ObserverService; do this or face
// memory leaks.
// Count an object's properties without checking prototype chain.
var obj = {
foo: "foo",
bar: "bar"
};
print(obj.__count__); // Prints 2
// In most cases, `__proto__` is the same as the constructor's prototype.
var Foo = function () {};
foo.constructor.prototype === Foo.prototype; // Prints true
foo.constructor.prototype === foo.__proto__; // Prints true
// Change the prototype for objects created by Foo constructor.
// This does not change __proto__ for already created objects.
Foo.prototype = new Bar();
// Directly modify a single object's prototype.
foo.__proto__ = new Bar();
// Merging two "hashes" like in Ruby
defaults = {
foo: 1,
bar: 2,
baz: 3
};
options = {
foo: 10,
bar: 20
};
options.__proto__ = defaults;
options.foo; // 10
options.bar; // 20
options.baz; // 3
// The `constructor` property returns the highest constructor in the prototype chain; not the
// function that constructed the object!
Foo.prototype = new Bar();
foo.constructor; // Bar
// Prototype chains must be finite and terminated by null.
var a = {};
var b = {};
a.__proto__ = b; //[object Object]
b.__proto__ = a; //typein:86: Error: cyclic __proto__ value
// Array's prototype chain is terminated by null. But I can't access the prototype property
// of some objects directly; I have to peek at the hidden [[Prototype]] (from ECMAScript spec)
// via the `__proto__` property.
Array.prototype.__proto__.__proto__; // null
Object.prototype.__proto__; // null
Array.prototype.__proto__ === Object.prototype; // true
// For object literals only
let foo = {
_x: 0,
get x() { return this._x; },
set x(v) { this._x = v; }
};
// For everything else
let Foo = function () {
this._x = 0;
};
Foo.prototype.__defineGetter__('x', function () { return this._x; });
Foo.prototype.__defineSetter__('x', function (v) { this._x = x; });
// It might be easier to define some convenience methods
let p = Foo.prototype;
p.get = p.__defineGetter__;
p.set = p.__defineSetter__;
p.get('y', function () { return this._x + 1; });
p.set('y', function (v) { this._x = v + 1; });
delete p.get;
delete p.set;
# Logging for HTTP layer. Wow!
export NSPR_LOG_MODULES=nsHttp:5,nsSocketTransport:5,nsHostResolver:5
export NSPR_LOG_FILE=/tmp/log.txt
// my_module.jsm
// Put this inside chrome/modules
// More info here: https://wiki.mozilla.org/Labs/JS_Modules
var EXPORTED_SYMBOLS = ["foo", "bar"];
var foo = function () { return "foo"; };
var bar = function () { return "bar"; };
var baz = function () { return "baz"; };
// In some other code, do an import to have exported symbols be injected into the current scope.
// Symbols are imported by-value (changes to a symbol in one scope do not affect another).
// Imports are cached and subsequent imports do not reload a new version of the module.
// Note:
// app is an alias to the location of the XUL application
// gre is an alias to the location of the XUL runtime
let myExtension = {};
Components.utils.import("resource://app/my_module.jsm", myExtension);
alert(myExtension.foo());
alert(myExtension.bar());
alert(myExtension.baz());
// If your XPI for extension foo has a top-level modules/ directory containing bar.jsm,
// Put this into your chrome.manifest:
// resource foo modules/
Components.utils.import("resource://foo/bar.jsm");
// Turn off Firefox's "Do you want to resume your session?" message when it's killed
pref("browser.sessionstore.resume_from_crash", false);
pref("browser.sessionstore.resume_session", false);
// Turn off Firefox's delay before extension install
pref("security.dialog_enable_delay", 0);
// Refresh XUL pages to see changes
pref("nglayout.debug.disable_xul_cache", true);
// Use dump(str) to print messages to stdout
pref("browser.dom.window.dump.enabled", true);
// Description: (Forces) Firefox to quit.
var quit = function (force) {
var service = Components.classes["@mozilla.org/toolkit/app-startup;1"].
getService(Components.interfaces.nsIAppStartup);
var severity = force ? service.eForceQuit : service.eAttemptQuit;
service.quit(severity);
};
function printStackTrace() {
var callstack = [];
var isCallstackPopulated = false;
try {
i.dont.exist+=0; //doesn't exist- that's the point
} catch(e) {
if (e.stack) { //Firefox
var lines = e.stack.split("\n");
for (var i=0, len=lines.length; i<len; i++) {
if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) {
callstack.push(lines[i]);
}
}
//Remove call to printStackTrace()
callstack.shift();
isCallstackPopulated = true;
}
else if (window.opera && e.message) { //Opera
var lines = e.message.split("\n");
for (var i=0, len=lines.length; i<len; i++) {
if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) {
var entry = lines[i];
//Append next line also since it has the file info
if (lines[i+1]) {
entry += " at " + lines[i+1];
i++;
}
callstack.push(entry);
}
}
//Remove call to printStackTrace()
callstack.shift();
isCallstackPopulated = true;
}
}
if (!isCallstackPopulated) { //IE and Safari
var currentFunction = arguments.callee.caller;
while (currentFunction) {
var fn = currentFunction.toString();
var fname = fn.substring(fn.indexOf("function") + 8, fn.indexOf("(")) ||
"anonymous";
callstack.push(fname);
currentFunction = currentFunction.caller;
}
}
output(callstack);
}
function output(arr) {
//Optput however you want
print(arr.join("\\n"));
}
// Global __FILE__ is available (only works in Spidermonkey)
(function(){
this.__defineGetter__("__FILE__", function() {
return (new Error).stack.
split("\n")[2].
split("@")[1].
split(":").
slice(0,-1).
join(":");
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment