зеркало из https://github.com/mozilla/pluotsorbet.git
remove task.js
This commit is contained in:
Родитель
67d073e0e6
Коммит
ebfb4b4bf5
32
LICENSE
32
LICENSE
|
@ -148,35 +148,3 @@ You should also get your employer (if you work as a programmer) or your school,
|
|||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.
|
||||
|
||||
---
|
||||
|
||||
task.js
|
||||
|
||||
Copyright (c) 2011, David Herman
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of David Herman nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
3
frame.js
3
frame.js
|
@ -133,8 +133,7 @@ Frame.prototype.run = function(args, done) {
|
|||
step();
|
||||
}
|
||||
|
||||
Frame.prototype.nop = function(done) {
|
||||
return done();
|
||||
Frame.prototype.nop = function() {
|
||||
}
|
||||
|
||||
Frame.prototype.aconst_null = function(done) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<meta charset="UTF-8">
|
||||
<script type="text/javascript" src="zipfile.js"></script>
|
||||
<script type="text/javascript" src="util.js"></script>
|
||||
<script type="text/javascript" src="task.js"></script>
|
||||
<script type="text/javascript" src="gLong.js"></script>
|
||||
<script type="text/javascript" src="classfile/reader.js"></script>
|
||||
<script type="text/javascript" src="classfile/accessflags.js"></script>
|
||||
|
|
535
task.js
535
task.js
|
@ -1,535 +0,0 @@
|
|||
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set shiftwidth=4 tabstop=4 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
(function(global) {
|
||||
|
||||
// local name for this module
|
||||
var exports;
|
||||
|
||||
var hasPrevious = "task" in global;
|
||||
var previous = global.task;
|
||||
|
||||
function uninstall() {
|
||||
if (hasPrevious)
|
||||
global.task = previous;
|
||||
else
|
||||
delete global.task;
|
||||
return exports;
|
||||
}
|
||||
|
||||
function enqueue_setTimeout() {
|
||||
function enqueue(thunk) {
|
||||
global.setTimeout(thunk, 0);
|
||||
}
|
||||
return enqueue;
|
||||
}
|
||||
|
||||
function enqueue_nextTick() {
|
||||
function enqueue(thunk) {
|
||||
global.process.nextTick(thunk);
|
||||
}
|
||||
return enqueue;
|
||||
}
|
||||
|
||||
// http://ajaxian.com/archives/settimeout-delay
|
||||
function enqueue_postMessage() {
|
||||
var timeouts = [];
|
||||
var messageName = "zero-timeout-message";
|
||||
|
||||
function enqueue(thunk) {
|
||||
timeouts.push(thunk);
|
||||
global.postMessage(messageName, "*");
|
||||
}
|
||||
|
||||
global.addEventListener("message", function(event) {
|
||||
if (event.source === global && event.data === messageName) {
|
||||
event.stopPropagation();
|
||||
if (timeouts.length > 0) {
|
||||
var thunk = timeouts.shift();
|
||||
thunk();
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
|
||||
return enqueue;
|
||||
}
|
||||
|
||||
function Promise() {
|
||||
if (!(this instanceof Promise))
|
||||
return new Promise();
|
||||
}
|
||||
|
||||
Promise.prototype = {
|
||||
get: function(key) {
|
||||
return this.then(function(obj) {
|
||||
return obj[key];
|
||||
});
|
||||
},
|
||||
put: function(key, val) {
|
||||
return this.then(function(obj) {
|
||||
return obj[key] = val;
|
||||
});
|
||||
},
|
||||
call: function(key) {
|
||||
return this.then(function(obj) {
|
||||
return obj[key].apply(obj, Array.prototype.slice.call(arguments, 1));
|
||||
});
|
||||
},
|
||||
addCallback: function(callback) {
|
||||
return this.then(callback);
|
||||
},
|
||||
addErrback: function(errback) {
|
||||
return this.then(function(){}, errback);
|
||||
},
|
||||
addBoth: function(callback) {
|
||||
return this.then(callback, callback);
|
||||
},
|
||||
addCallbacks: function(callback, errback) {
|
||||
return this.then(callback, errback);
|
||||
},
|
||||
timeout: function(delay, compensate) {
|
||||
return choose(this, sleep(delay, compensate).then(function() {
|
||||
throw new Error("timeout (" + delay + ")")
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
const P_UNRESOLVED = 0;
|
||||
const P_RESOLVED = 1;
|
||||
const P_REJECTED = 2;
|
||||
const P_CANCELLED = 3;
|
||||
|
||||
function Deferred(cancel) {
|
||||
if (!(this instanceof Deferred))
|
||||
return new Deferred(cancel);
|
||||
|
||||
// FIXME: could do the "nobody ever saw this error, throw it somewhere!" that node-promise does
|
||||
var result, state = P_UNRESOLVED, waiting = [];
|
||||
var promise = this.promise = new Promise();
|
||||
|
||||
function notifyAll(value, rejected) {
|
||||
switch (state) {
|
||||
case P_CANCELLED:
|
||||
return;
|
||||
case P_UNRESOLVED:
|
||||
break;
|
||||
default:
|
||||
throw new TypeError("deferred is already resolved (state is " + state + ")");
|
||||
}
|
||||
state = rejected ? P_REJECTED : P_RESOLVED;
|
||||
result = value;
|
||||
for (var i = 0, n = waiting.length; i < n; i++)
|
||||
notify(waiting[i]);
|
||||
waiting = null;
|
||||
}
|
||||
|
||||
function notify(listener) {
|
||||
var func = state === P_REJECTED ? listener.onError : listener.onResolve;
|
||||
if (func) {
|
||||
exports.enqueue(function() {
|
||||
try {
|
||||
listener.next.resolve(func(result));
|
||||
} catch (e) {
|
||||
listener.next.reject(e);
|
||||
}
|
||||
});
|
||||
} else if (state === P_REJECTED) {
|
||||
listener.next.reject(result);
|
||||
} else {
|
||||
listener.next.resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
this.resolve = this.callback = this.emitSuccess = function(value) {
|
||||
notifyAll(value, false);
|
||||
};
|
||||
|
||||
var reject = this.reject = this.errback = this.emitError = function(error) {
|
||||
notifyAll(error, true);
|
||||
};
|
||||
|
||||
this.progress = function(update) {
|
||||
for (var i = 0, n = waiting.length; i < n; i++) {
|
||||
var progress = waiting[i].progress;
|
||||
progress && progress(update);
|
||||
}
|
||||
};
|
||||
|
||||
this.then = promise.then = function(onResolve, onError, onProgress) {
|
||||
var next = new Deferred(cancel);
|
||||
var listener = {
|
||||
onResolve: onResolve,
|
||||
onError: onError,
|
||||
onProgress: onProgress,
|
||||
next: next
|
||||
};
|
||||
if (state !== P_UNRESOLVED)
|
||||
notify(listener);
|
||||
else
|
||||
waiting.push(listener);
|
||||
return next.promise;
|
||||
};
|
||||
|
||||
this.cancel = promise.cancel = function() {
|
||||
this.state = P_CANCELLED;
|
||||
this.waiting = null;
|
||||
cancel();
|
||||
};
|
||||
}
|
||||
|
||||
Deferred.prototype = Promise.prototype;
|
||||
|
||||
function now(value) {
|
||||
var deferred = new Deferred(function(){});
|
||||
deferred.resolve(value);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function never() {
|
||||
return (new Deferred(function(){})).promise;
|
||||
}
|
||||
|
||||
function join() {
|
||||
var promises = arguments, n = promises.length;
|
||||
|
||||
// resolve immediately
|
||||
if (n === 0)
|
||||
return now([]);
|
||||
|
||||
var state = P_UNRESOLVED, result = new Array(n), pending = new Array(n), remaining = n;
|
||||
var cancel = function() {
|
||||
if (state !== P_UNRESOLVED)
|
||||
return;
|
||||
remaining = 0;
|
||||
state = P_CANCELLED;
|
||||
for (var i = 0; i < n; i++) {
|
||||
var p = pending[i];
|
||||
if (p)
|
||||
p.cancel();
|
||||
}
|
||||
pending = null;
|
||||
};
|
||||
var deferred = new Deferred(cancel);
|
||||
// FIXME: what do we do about the dropped results and (worse) errors here?
|
||||
// or can we prove that the tests (and pending array) are unnecessary
|
||||
// based on invariants of promises?
|
||||
for (var i = 0; i < n; i++) {
|
||||
(function(i) {
|
||||
var p = promises[i];
|
||||
pending[i] = p;
|
||||
p.then(function(value) {
|
||||
if (state !== P_UNRESOLVED || !pending[i])
|
||||
return;
|
||||
result[i] = value;
|
||||
if ((--remaining) === 0) {
|
||||
state = P_RESOLVED;
|
||||
pending = null;
|
||||
deferred.resolve(result);
|
||||
} else {
|
||||
pending[i] = null;
|
||||
}
|
||||
}, function(e) {
|
||||
if (state !== P_UNRESOLVED || !pending[i])
|
||||
return;
|
||||
error = e;
|
||||
remaining = 0;
|
||||
state = P_REJECTED;
|
||||
for (var j = 0; j < n; j++) {
|
||||
if (j === i || !pending[j])
|
||||
continue;
|
||||
pending[j].cancel();
|
||||
}
|
||||
pending = null;
|
||||
deferred.reject(e);
|
||||
});
|
||||
})(i);
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function choose() {
|
||||
var promises = arguments, n = promises.length;
|
||||
var state = P_UNRESOLVED, result;
|
||||
var cancel = function() {
|
||||
if (state !== P_UNRESOLVED)
|
||||
return;
|
||||
for (var i = 0; i < n; i++)
|
||||
promises[i].cancel();
|
||||
}
|
||||
var deferred = new Deferred(cancel);
|
||||
for (var i = 0; i < n; i++) {
|
||||
(function(i) {
|
||||
promises[i].then(function(value) {
|
||||
if (state !== P_UNRESOLVED)
|
||||
return;
|
||||
result = value;
|
||||
state = P_RESOLVED;
|
||||
for (var j = 0; j < n; j++) {
|
||||
if (j !== i)
|
||||
promises[j].cancel();
|
||||
}
|
||||
deferred.resolve(value);
|
||||
}, function(e) {
|
||||
if (state !== P_UNRESOLVED)
|
||||
return;
|
||||
result = e;
|
||||
state = P_REJECTED;
|
||||
for (var j = 0; j < n; j++) {
|
||||
if (j !== i)
|
||||
promises[j].cancel();
|
||||
}
|
||||
deferred.reject(e);
|
||||
});
|
||||
})(i);
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
const T_PAUSED = 0; // can't be scheduled or executed
|
||||
const T_STARTED = 1; // may or may not currently be executing
|
||||
const T_CANCELLED = 2; // cancelled but not yet done cleaning up
|
||||
const T_CLOSED = 3; // completely done
|
||||
|
||||
const R_BLOCKED = 0; // waiting on a promise
|
||||
const R_RESOLVED = 1; // ready to resume with a resolved value
|
||||
const R_REJECTED = 2; // ready to resume with a rejected value
|
||||
const R_RUNNING = 3; // currently executing
|
||||
|
||||
var counter = 0;
|
||||
function nextTID() {
|
||||
var result = counter;
|
||||
counter = (counter + 1) & 0xffffffff;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Task(thunk) {
|
||||
if (!(this instanceof Task))
|
||||
return new Task(thunk);
|
||||
this.tid = nextTID(); // thread ID
|
||||
this.result = void 0; // intermediate or final result
|
||||
this.runState = R_RESOLVED; // execution status within scheduler
|
||||
this.threadState = T_PAUSED; // state in thread's lifecycle
|
||||
this.thread = thunk.call(this); // thread
|
||||
this.scheduler = currentScheduler(); // scheduler
|
||||
this.deferred = new Deferred();
|
||||
this.then = this.deferred.then;
|
||||
}
|
||||
|
||||
var Tp = Task.prototype = new Promise();
|
||||
|
||||
Tp.isStarted = function() {
|
||||
return this.threadState === T_STARTED;
|
||||
};
|
||||
|
||||
Tp.isRunning = function() {
|
||||
return this.runState === R_RUNNING;
|
||||
};
|
||||
|
||||
Tp.start = function() {
|
||||
if (this.threadState !== T_PAUSED)
|
||||
throw new Error("task is already started or completed");
|
||||
this.threadState = T_STARTED;
|
||||
if (this.runState !== R_BLOCKED) {
|
||||
this.scheduler.schedule(this);
|
||||
pump(this.scheduler);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Tp.pause = function() {
|
||||
if (this.runState === R_RUNNING)
|
||||
throw new Error("tasks can only be paused while blocked");
|
||||
this.threadState = T_PAUSED;
|
||||
this.scheduler.unschedule(this);
|
||||
return this;
|
||||
};
|
||||
|
||||
Tp.cancel = function() {
|
||||
if (this.runState === R_RUNNING)
|
||||
throw new Error("tasks can only be cancelled while blocked");
|
||||
this.threadState = T_CANCELLED;
|
||||
this.scheduler.schedule(this);
|
||||
pump(this.scheduler);
|
||||
return this;
|
||||
};
|
||||
|
||||
Tp.toString = function() {
|
||||
return "[object Task " + this.tid + "]";
|
||||
};
|
||||
|
||||
const READY = now();
|
||||
|
||||
function runScheduledTask(task) {
|
||||
var result = task.result, send = (task.runState === R_RESOLVED);
|
||||
try {
|
||||
task.runState = R_RUNNING;
|
||||
task.result = void 0;
|
||||
if (task.threadState === T_CANCELLED) {
|
||||
task.thread.close();
|
||||
task.result = void 0;
|
||||
task.runState = R_RESOLVED;
|
||||
task.threadState = T_CLOSED;
|
||||
} else {
|
||||
var p = (send ? task.thread.send(result) : task.thread["throw"](result)) || READY;
|
||||
task.runState = R_BLOCKED;
|
||||
p.then(function(value) {
|
||||
task.result = value;
|
||||
task.runState = R_RESOLVED;
|
||||
if (task.threadState === T_STARTED) {
|
||||
task.scheduler.schedule(task);
|
||||
pump(task.scheduler);
|
||||
}
|
||||
}, function(e) {
|
||||
task.result = e;
|
||||
task.runState = R_REJECTED;
|
||||
if (task.threadState === T_STARTED) {
|
||||
task.scheduler.schedule(task);
|
||||
pump(task.scheduler);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
task.threadState = T_CLOSED;
|
||||
if (e instanceof TaskResult || e instanceof StopIteration) {
|
||||
task.result = e.value;
|
||||
task.runState = R_RESOLVED;
|
||||
task.deferred.resolve(e.value);
|
||||
} else {
|
||||
task.result = e;
|
||||
task.runState = R_REJECTED;
|
||||
task.deferred.reject(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var runningTask = null;
|
||||
|
||||
Task.current = function() {
|
||||
return runningTask;
|
||||
}
|
||||
|
||||
function pump(scheduler) {
|
||||
if (runningTask)
|
||||
return;
|
||||
var task = scheduler.choose();
|
||||
if (!task)
|
||||
return;
|
||||
exports.enqueue(function() {
|
||||
runningTask = task;
|
||||
runScheduledTask(task);
|
||||
runningTask = null;
|
||||
pump(scheduler);
|
||||
});
|
||||
}
|
||||
|
||||
function spawn(thunk) {
|
||||
return (new Task(thunk)).start();
|
||||
}
|
||||
|
||||
function currentStack() {
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
return e.stack.split(/\n/).slice(1).map(function (line) {
|
||||
var match1 = line.match(/^[a-zA-Z0-9_]*/);
|
||||
var match2 = line.match(/[^\/]+:[0-9]+$/);
|
||||
return (match1 && match2) ? (match1[0] + "@" + match2[0]) : line;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function sourceOf(x) {
|
||||
return (x && typeof x === "object") ? x.toSource() : String(x);
|
||||
}
|
||||
|
||||
function RandomScheduler() {
|
||||
this.ready = []; // unblocked tasks ready to resume
|
||||
}
|
||||
|
||||
RandomScheduler.prototype = {
|
||||
choose: function() {
|
||||
var n = this.ready.length;
|
||||
if (n === 0)
|
||||
return null;
|
||||
if (n === 1) {
|
||||
var r = this.ready[0];
|
||||
this.ready = []
|
||||
return r;
|
||||
}
|
||||
var i = Math.floor(Math.random() * n);
|
||||
return this.ready.splice(i, 1)[0];
|
||||
},
|
||||
schedule: function(task) {
|
||||
this.ready.push(task);
|
||||
},
|
||||
unschedule: function(task) {
|
||||
var ready = this.ready;
|
||||
for (var i = 0, n = ready.length; i < n; i++) {
|
||||
if (ready[i] === task) {
|
||||
ready.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var scheduler = new RandomScheduler();
|
||||
|
||||
function currentScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
function setCurrentScheduler(s) {
|
||||
scheduler = s;
|
||||
}
|
||||
|
||||
function TaskResult(value) {
|
||||
if (!(this instanceof TaskResult))
|
||||
return new TaskResult(value);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
TaskResult.prototype = {
|
||||
toString: function() {
|
||||
return "[TaskResult " + this.value + "]";
|
||||
}
|
||||
};
|
||||
|
||||
function sleep(delay, compensate) {
|
||||
var start = Date.now();
|
||||
var deferred = new Deferred();
|
||||
var id = global.setTimeout(resolveOrTryAgain, delay);
|
||||
|
||||
function resolveOrTryAgain() {
|
||||
var end = Date.now();
|
||||
var actual = end - start;
|
||||
if (compensate && actual < delay) {
|
||||
id = global.setTimeout(resolveOrTryAgain, delay - actual);
|
||||
return;
|
||||
}
|
||||
deferred.resolve(actual);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
global.task = exports = {
|
||||
uninstall: uninstall,
|
||||
Deferred: Deferred,
|
||||
enqueue: enqueue_setTimeout(),
|
||||
Task: Task,
|
||||
TaskResult: TaskResult,
|
||||
join: join,
|
||||
choose: choose,
|
||||
now: now,
|
||||
never: never,
|
||||
spawn: spawn,
|
||||
sleep: sleep,
|
||||
currentScheduler: currentScheduler,
|
||||
setCurrentScheduler: setCurrentScheduler,
|
||||
RandomScheduler: RandomScheduler
|
||||
};
|
||||
|
||||
})(this);
|
Загрузка…
Ссылка в новой задаче