/usr/share/xul-ext/downthemall/modules/cothread.jsm is in xul-ext-downthemall 2.0.13-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | /* You may find the license in the LICENSE file */
const EXPORTED_SYMBOLS = ['CoThread', 'CoThreadInterleaved', 'CoThreadListWalker'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const TYPE_REPEATING_SLACK = Ci.nsITimer.TYPE_REPEATING_SLACK;
const Timer = Components.Constructor('@mozilla.org/timer;1', 'nsITimer', 'initWithCallback');
// "Abstract" base c'tor
function CoThreadBase() {}
CoThreadBase.prototype = {
_idx: 0,
_ran: false,
_finishFunc: null,
init: function CoThreadBase_init(func, yieldEvery, thisCtx) {
this._thisCtx = thisCtx ? thisCtx : this;
// default to 1
this._yieldEvery = typeof yieldEvery == 'number' ? Math.floor(yieldEvery) : 1;
if (yieldEvery < 1) {
throw Cr.NS_ERROR_INVALID_ARG;
}
if (typeof func != 'function' && !(func instanceof Function)) {
throw Cr.NS_ERROR_INVALID_ARG;
}
this._func = func;
this.init = function() {};
},
run: function CoThreadBase_run(finishFunc) {
if (this._ran) {
throw new Error("You cannot run a CoThread/CoThreadListWalker instance more than once.");
}
this._finishFunc = finishFunc;
this._ran = true;
this._timer = new Timer(this, 10, TYPE_REPEATING_SLACK);
},
QueryInterface: function CoThreadBase_QueryInterface(iid) {
if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsITimerCallback)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
},
notify: function CoThreadBase_notify() {
let y = this._yieldEvery;
let g = this._generator;
let f = this._func;
let ctx = this._thisCtx;
let callf = this._callf;
try {
for (let i = 0; i < y; ++i) {
if (!callf(ctx, g.next(), this._idx++, f)) {
throw 'complete';
}
}
}
catch (ex) {
this.cancel();
}
},
cancel: function CoThreadBase_cancel() {
this._timer.cancel();
if (this._finishFunc) {
this._finishFunc.call(this._thisCtx);
}
}
}
/**
* Constructs a new CoThread (aka. pseudo-thread).
* A CoThread will repeatedly call a specified function, but "breaking"
* the operation temporarily after a certain amount of calls,
* so that the main thread gets a chance to process any outstanding
* events.
*
* Example:
* Components.utils.import('resource://dta/cothread.jsm');
* new CoThread(
* // What to do with each item?
* // Print it!
* function(count) document.write(count + "<br>") || (count < 30000),
* // When to turn over Control?
* // Each 1000 items
* 1000
* ).run();
*
* @param {Function} func Function to be called. Is passed call count as argument. Returning false will cancel the operation.
* @param {Number} yieldEvery Optional. After how many items control should be turned over to the main thread
* @param {Object} thisCtx Optional. The function will be called in the scope of this object (or if omitted in the scope of the CoThread instance)
*/
function CoThread(func, yieldEvery, thisCtx) {
this.init(func, yieldEvery, thisCtx);
// fake generator so we may use a common implementation. ;)
this._generator = (function() { for(;;) { yield null }; })();
}
CoThread.prototype = {
__proto__: CoThreadBase.prototype,
_callf: function CoThread__callf(ctx, item, idx, func) {
return func.call(ctx, idx);
}
}
/**
* Constructs a new CoThreadInterleaved (aka. pseudo-thread).
* The CoThread will process a interleaved function (generator)
*
* Example:
* Components.utils.import('resource://dta/cothread.jsm');
* new CoThread(
* function(count) {
* do_some();
* yield true;
* do_more();
* yield true;
* if (!do_even_more()) {
* return;
* }
* do_last();
* },
* // When to turn over Control?
* // Each 2 items
* 2
* ).run();
*
* @param {Function} func Function to be called. Is passed call count as argument. Returning false will cancel the operation.
* @param {Number} yieldEvery Optional. After how many items control should be turned over to the main thread
* @param {Object} thisCtx Optional. The function will be called in the scope of this object (or if omitted in the scope of the CoThread instance)
*/
function CoThreadInterleaved(generator, yieldEvery, thisCtx) {
this.init(function() true, yieldEvery, thisCtx);
this._generator = generator;
}
CoThreadInterleaved.prototype = {
__proto__: CoThreadBase.prototype,
_callf: function() true
};
/**
* Constructs a new CoThreadListWalker (aka. pseudo-thread).
* A CoThreadListWalker will walk a specified list and call a specified function
* on each item, but "breaking" the operation temporarily after a
* certain amount of processed items, so that the main thread may
* process any outstanding events.
*
* Example:
* Components.utils.import('resource://dta/cothread.jsm');
* new CoThreadListWalker(
* // What to do with each item?
* // Print it!
* function(item, idx) document.write(item + "/" + idx + "<br>") || true,
* // What items?
* // 0 - 29999
* (function() { for (let i = 0; i < 30000; ++i) yield i; })(),
* // When to turn over Control?
* // Each 1000 items
* 1000,
* null,
* ).run(function() alert('done'));
*
* @param {Function} func Function to be called on each item. Is passed item and index as arguments. Returning false will cancel the operation.
* @param {Array/Generator} arrayOrGenerator Array or Generator object to be used as the input list
* @param {Number} yieldEvery Optional. After how many items control should be turned over to the main thread
* @param {Object} thisCtx Optional. The function will be called in the scope of this object (or if omitted in the scope of the CoThread instance)
*/
function CoThreadListWalker(func, arrayOrGenerator, yieldEvery, thisCtx) {
this.init(func, yieldEvery, thisCtx);
if (arrayOrGenerator instanceof Array) {
// make a generator
this._generator = (i for each (i in arrayOrGenerator));
}
else {
this._generator = arrayOrGenerator;
}
if (this._lastFunc && (typeof func != 'function' && !(func instanceof Function))) {
throw Cr.NS_ERROR_INVALID_ARG;
}
}
CoThreadListWalker.prototype = {
__proto__: CoThreadBase.prototype,
_callf: function CoThreadListWalker__callf(ctx, item, idx, func) {
return func.call(ctx, item, idx);
}
}
|