зеркало из https://github.com/mozilla/pluotsorbet.git
Polyfill promises in the JS shell.
This commit is contained in:
Родитель
d008938e55
Коммит
ff9c561342
|
@ -1,6 +1,5 @@
|
|||
module J2ME {
|
||||
declare var util, config;
|
||||
declare var Promise;
|
||||
|
||||
import BytecodeStream = Bytecode.BytecodeStream;
|
||||
import BlockMap = Bytecode.BlockMap;
|
||||
|
|
57
jsshell.js
57
jsshell.js
|
@ -85,29 +85,11 @@ if (files.length !== 1) {
|
|||
}
|
||||
|
||||
var callbacks = [];
|
||||
var window = {
|
||||
setTimeout: function(callback) {
|
||||
callbacks.push(callback);
|
||||
},
|
||||
setZeroTimeout: function(callback) {
|
||||
callbacks.push(callback);
|
||||
},
|
||||
addEventListener: function() {
|
||||
},
|
||||
crypto: {
|
||||
getRandomValues: function() {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
var navigator = {
|
||||
language: "en-US",
|
||||
};
|
||||
|
||||
function Promise() {
|
||||
// ...
|
||||
}
|
||||
|
||||
var document = {
|
||||
documentElement: {
|
||||
classList: {
|
||||
|
@ -146,6 +128,32 @@ var document = {
|
|||
},
|
||||
};
|
||||
|
||||
var microTaskQueue = null;
|
||||
|
||||
var window = {
|
||||
addEventListener: function() {
|
||||
},
|
||||
crypto: {
|
||||
getRandomValues: function() {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
window.setZeroTimeout = window.setTimeout = function (fn, interval) {
|
||||
var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : [];
|
||||
var task = microTaskQueue.scheduleInterval(fn, args, interval, false);
|
||||
return task.id;
|
||||
};
|
||||
|
||||
window.setInterval = function (fn, interval) {
|
||||
var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : [];
|
||||
var task = microTaskQueue.scheduleInterval(fn, args, interval, true);
|
||||
return task.id;
|
||||
};
|
||||
window.clearTimeout = function (id) {
|
||||
microTaskQueue.remove(id);
|
||||
};
|
||||
|
||||
var Event = function() {
|
||||
}
|
||||
|
||||
|
@ -160,13 +168,15 @@ try {
|
|||
if (profileTimeline) {
|
||||
load("bld/shumway.js");
|
||||
}
|
||||
load("libs/relooper.js", "libs/native.js", "bld/j2me.js","libs/zipfile.js", "blackBox.js",
|
||||
load("polyfill/promise.js", "libs/relooper.js", "libs/native.js", "bld/j2me.js","libs/zipfile.js", "blackBox.js",
|
||||
"libs/encoding.js", "util.js", "libs/jarstore.js",
|
||||
"native.js", "midp/midp.js",
|
||||
"libs/long.js", "midp/crypto.js", "libs/forge/md5.js", "libs/forge/util.js"
|
||||
// "bld/classes.jar.js"
|
||||
);
|
||||
|
||||
microTaskQueue = new J2ME.Shell.MicroTasksQueue();
|
||||
|
||||
// load("bld/classes.jar.js");
|
||||
// load("bld/program.jar.js");
|
||||
// load("bld/tests.jar.js");
|
||||
|
@ -205,9 +215,12 @@ try {
|
|||
|
||||
start = dateNow();
|
||||
var runtime = jvm.startIsolate0(files[0], config.args);
|
||||
while (callbacks.length) {
|
||||
(callbacks.shift())();
|
||||
}
|
||||
|
||||
// Pump Event Queue
|
||||
microTaskQueue.run(0, 0, false, function () {
|
||||
return true;
|
||||
});
|
||||
|
||||
print("Time: " + (dateNow() - start).toFixed(4) + " ms");
|
||||
print("Bytecodes: " + J2ME.bytecodeCount);
|
||||
J2ME.interpreterCounter.traceSorted(new J2ME.IndentingWriter(false, function (x) {
|
||||
|
|
4
nat.ts
4
nat.ts
|
@ -23,7 +23,7 @@ module J2ME {
|
|||
|
||||
var asyncImplStringAsync = "Async";
|
||||
|
||||
export function asyncImplOld(returnKind: string, promise) {
|
||||
export function asyncImplOld(returnKind: string, promise: Promise<any>) {
|
||||
return asyncImpl(kindCharacterToKind(returnKind), promise);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ module J2ME {
|
|||
*
|
||||
* |onRejected| is called with a java.lang.Exception object.
|
||||
*/
|
||||
export function asyncImpl(returnKind: Kind, promise) {
|
||||
export function asyncImpl(returnKind: Kind, promise: Promise<any>) {
|
||||
var ctx = $.ctx;
|
||||
|
||||
promise.then(function onFulfilled(l: any, h?: number) {
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
// Polyfill for Promises
|
||||
(function PromiseClosure() {
|
||||
/*jshint -W061 */
|
||||
var global = Function("return this")();
|
||||
if (global.Promise) {
|
||||
// Promises existing in the DOM/Worker, checking presence of all/resolve
|
||||
if (typeof global.Promise.all !== 'function') {
|
||||
global.Promise.all = function (iterable) {
|
||||
var count = 0, results = [], resolve, reject;
|
||||
var promise = new global.Promise(function (resolve_, reject_) {
|
||||
resolve = resolve_;
|
||||
reject = reject_;
|
||||
});
|
||||
iterable.forEach(function (p, i) {
|
||||
count++;
|
||||
p.then(function (result) {
|
||||
results[i] = result;
|
||||
count--;
|
||||
if (count === 0) {
|
||||
resolve(results);
|
||||
}
|
||||
}, reject);
|
||||
});
|
||||
if (count === 0) {
|
||||
resolve(results);
|
||||
}
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
if (typeof global.Promise.resolve !== 'function') {
|
||||
global.Promise.resolve = function (x) {
|
||||
return new global.Promise(function (resolve) { resolve(x); });
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function getDeferred(C) {
|
||||
if (typeof C !== 'function') {
|
||||
throw new TypeError('Invalid deferred constructor');
|
||||
}
|
||||
var resolver = createDeferredConstructionFunctions();
|
||||
var promise = new C(resolver);
|
||||
var resolve = resolver.resolve;
|
||||
if (typeof resolve !== 'function') {
|
||||
throw new TypeError('Invalid resolve construction function');
|
||||
}
|
||||
var reject = resolver.reject;
|
||||
if (typeof reject !== 'function') {
|
||||
throw new TypeError('Invalid reject construction function');
|
||||
}
|
||||
return {promise: promise, resolve: resolve, reject: reject};
|
||||
}
|
||||
|
||||
function updateDeferredFromPotentialThenable(x, deferred) {
|
||||
if (typeof x !== 'object' || x === null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
var then = x.then;
|
||||
if (typeof then !== 'function') {
|
||||
return false;
|
||||
}
|
||||
var thenCallResult = then.call(x, deferred.resolve, deferred.reject);
|
||||
} catch (e) {
|
||||
var reject = deferred.reject;
|
||||
reject(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isPromise(x) {
|
||||
return typeof x === 'object' && x !== null &&
|
||||
typeof x.promiseStatus !== 'undefined';
|
||||
}
|
||||
|
||||
function rejectPromise(promise, reason) {
|
||||
if (promise.promiseStatus !== 'unresolved') {
|
||||
return;
|
||||
}
|
||||
var reactions = promise.rejectReactions;
|
||||
promise.result = reason;
|
||||
promise.resolveReactions = undefined;
|
||||
promise.rejectReactions = undefined;
|
||||
promise.promiseStatus = 'has-rejection';
|
||||
triggerPromiseReactions(reactions, reason);
|
||||
}
|
||||
|
||||
function resolvePromise(promise, resolution) {
|
||||
if (promise.promiseStatus !== 'unresolved') {
|
||||
return;
|
||||
}
|
||||
var reactions = promise.resolveReactions;
|
||||
promise.result = resolution;
|
||||
promise.resolveReactions = undefined;
|
||||
promise.rejectReactions = undefined;
|
||||
promise.promiseStatus = 'has-resolution';
|
||||
triggerPromiseReactions(reactions, resolution);
|
||||
}
|
||||
|
||||
function triggerPromiseReactions(reactions, argument) {
|
||||
for (var i = 0; i < reactions.length; i++) {
|
||||
queueMicrotask({reaction: reactions[i], argument: argument});
|
||||
}
|
||||
}
|
||||
|
||||
function queueMicrotask(task) {
|
||||
if (microtasksQueue.length === 0) {
|
||||
setTimeout(handleMicrotasksQueue, 0);
|
||||
}
|
||||
microtasksQueue.push(task);
|
||||
}
|
||||
|
||||
function executePromiseReaction(reaction, argument) {
|
||||
var deferred = reaction.deferred;
|
||||
var handler = reaction.handler;
|
||||
var handlerResult, updateResult;
|
||||
try {
|
||||
handlerResult = handler(argument);
|
||||
} catch (e) {
|
||||
var reject = deferred.reject;
|
||||
return reject(e);
|
||||
}
|
||||
|
||||
if (handlerResult === deferred.promise) {
|
||||
var reject = deferred.reject;
|
||||
return reject(new TypeError('Self resolution'));
|
||||
}
|
||||
|
||||
try {
|
||||
updateResult = updateDeferredFromPotentialThenable(handlerResult,
|
||||
deferred);
|
||||
if (!updateResult) {
|
||||
var resolve = deferred.resolve;
|
||||
return resolve(handlerResult);
|
||||
}
|
||||
} catch (e) {
|
||||
var reject = deferred.reject;
|
||||
return reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
var microtasksQueue = [];
|
||||
|
||||
function handleMicrotasksQueue() {
|
||||
while (microtasksQueue.length > 0) {
|
||||
var task = microtasksQueue[0];
|
||||
try {
|
||||
executePromiseReaction(task.reaction, task.argument);
|
||||
} catch (e) {
|
||||
// unhandler onFulfillment/onRejection exception
|
||||
if (typeof (Promise).onerror === 'function') {
|
||||
(Promise).onerror(e);
|
||||
}
|
||||
}
|
||||
microtasksQueue.shift();
|
||||
}
|
||||
}
|
||||
|
||||
function throwerFunction(e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
function identityFunction(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
function createRejectPromiseFunction(promise) {
|
||||
return function (reason) {
|
||||
rejectPromise(promise, reason);
|
||||
};
|
||||
}
|
||||
|
||||
function createResolvePromiseFunction(promise) {
|
||||
return function (resolution) {
|
||||
resolvePromise(promise, resolution);
|
||||
};
|
||||
}
|
||||
|
||||
function createDeferredConstructionFunctions() {
|
||||
var fn = function (resolve, reject) {
|
||||
fn.resolve = resolve;
|
||||
fn.reject = reject;
|
||||
};
|
||||
return fn;
|
||||
}
|
||||
|
||||
function createPromiseResolutionHandlerFunctions(promise,
|
||||
fulfillmentHandler, rejectionHandler) {
|
||||
return function (x) {
|
||||
if (x === promise) {
|
||||
return rejectionHandler(new TypeError('Self resolution'));
|
||||
}
|
||||
var cstr = promise.promiseConstructor;
|
||||
if (isPromise(x)) {
|
||||
var xConstructor = x.promiseConstructor;
|
||||
if (xConstructor === cstr) {
|
||||
return x.then(fulfillmentHandler, rejectionHandler);
|
||||
}
|
||||
}
|
||||
var deferred = getDeferred(cstr);
|
||||
var updateResult = updateDeferredFromPotentialThenable(x, deferred);
|
||||
if (updateResult) {
|
||||
var deferredPromise = deferred.promise;
|
||||
return deferredPromise.then(fulfillmentHandler, rejectionHandler);
|
||||
}
|
||||
return fulfillmentHandler(x);
|
||||
};
|
||||
}
|
||||
|
||||
function createPromiseAllCountdownFunction(index, values, deferred,
|
||||
countdownHolder) {
|
||||
return function (x) {
|
||||
values[index] = x;
|
||||
countdownHolder.countdown--;
|
||||
if (countdownHolder.countdown === 0) {
|
||||
deferred.resolve(values);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function Promise(resolver) {
|
||||
if (typeof resolver !== 'function') {
|
||||
throw new TypeError('resolver is not a function');
|
||||
}
|
||||
var promise = this;
|
||||
if (typeof promise !== 'object') {
|
||||
throw new TypeError('Promise to initialize is not an object');
|
||||
}
|
||||
promise.promiseStatus = 'unresolved';
|
||||
promise.resolveReactions = [];
|
||||
promise.rejectReactions = [];
|
||||
promise.result = undefined;
|
||||
|
||||
var resolve = createResolvePromiseFunction(promise);
|
||||
var reject = createRejectPromiseFunction(promise);
|
||||
|
||||
try {
|
||||
var result = resolver(resolve, reject);
|
||||
} catch (e) {
|
||||
rejectPromise(promise, e);
|
||||
}
|
||||
|
||||
promise.promiseConstructor = Promise;
|
||||
return promise;
|
||||
}
|
||||
|
||||
(Promise).all = function (iterable) {
|
||||
var deferred = getDeferred(this);
|
||||
var values = [];
|
||||
var countdownHolder = {countdown: 0};
|
||||
var index = 0;
|
||||
iterable.forEach(function (nextValue) {
|
||||
var nextPromise = this.cast(nextValue);
|
||||
var fn = createPromiseAllCountdownFunction(index, values,
|
||||
deferred, countdownHolder);
|
||||
nextPromise.then(fn, deferred.reject);
|
||||
index++;
|
||||
countdownHolder.countdown++;
|
||||
}, this);
|
||||
if (index === 0) {
|
||||
deferred.resolve(values);
|
||||
}
|
||||
return deferred.promise;
|
||||
};
|
||||
(Promise).cast = function (x) {
|
||||
if (isPromise(x)) {
|
||||
return x;
|
||||
}
|
||||
var deferred = getDeferred(this);
|
||||
deferred.resolve(x);
|
||||
return deferred.promise;
|
||||
};
|
||||
(Promise).reject = function (r) {
|
||||
var deferred = getDeferred(this);
|
||||
var rejectResult = deferred.reject(r);
|
||||
return deferred.promise;
|
||||
};
|
||||
(Promise).resolve = function (x) {
|
||||
var deferred = getDeferred(this);
|
||||
var rejectResult = deferred.resolve(x);
|
||||
return deferred.promise;
|
||||
};
|
||||
Promise.prototype = {
|
||||
'catch': function (onRejected) {
|
||||
this.then(undefined, onRejected);
|
||||
},
|
||||
then: function (onFulfilled, onRejected) {
|
||||
var promise = this;
|
||||
if (!isPromise(promise)) {
|
||||
throw new TypeError('this is not a Promises');
|
||||
}
|
||||
var cstr = promise.promiseConstructor;
|
||||
var deferred = getDeferred(cstr);
|
||||
|
||||
var rejectionHandler = typeof onRejected === 'function' ? onRejected :
|
||||
throwerFunction;
|
||||
var fulfillmentHandler = typeof onFulfilled === 'function' ? onFulfilled :
|
||||
identityFunction;
|
||||
var resolutionHandler = createPromiseResolutionHandlerFunctions(promise,
|
||||
fulfillmentHandler, rejectionHandler);
|
||||
|
||||
var resolveReaction = {deferred: deferred, handler: resolutionHandler};
|
||||
var rejectReaction = {deferred: deferred, handler: rejectionHandler};
|
||||
|
||||
switch (promise.promiseStatus) {
|
||||
case 'unresolved':
|
||||
promise.resolveReactions.push(resolveReaction);
|
||||
promise.rejectReactions.push(rejectReaction);
|
||||
break;
|
||||
case 'has-resolution':
|
||||
var resolution = promise.result;
|
||||
queueMicrotask({reaction: resolveReaction, argument: resolution});
|
||||
break;
|
||||
case 'has-rejection':
|
||||
var rejection = promise.result;
|
||||
queueMicrotask({reaction: rejectReaction, argument: rejection});
|
||||
break;
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
|
||||
global.Promise = Promise;
|
||||
})();
|
|
@ -1,6 +1,7 @@
|
|||
// Basics
|
||||
|
||||
///<reference path='tools/lib.d.ts' />
|
||||
///<reference path='tools/es6-promises.d.ts' />
|
||||
|
||||
///<reference path='config.ts' />
|
||||
///<reference path='utilities.ts' />
|
||||
|
@ -14,6 +15,7 @@
|
|||
///<reference path='types.ts' />
|
||||
///<reference path='vm/classRegistry.ts' />
|
||||
///<reference path='bindings.ts' />
|
||||
///<reference path='nat.ts' />
|
||||
///<reference path='int.ts' />
|
||||
///<reference path='scheduler.ts' />
|
||||
///<reference path='vm/runtime.ts' />
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Basics
|
||||
|
||||
///<reference path='tools/lib.d.ts' />
|
||||
///<reference path='tools/es6-promises.d.ts' />
|
||||
|
||||
///<reference path='config.ts' />
|
||||
///<reference path='utilities.ts' />
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
// Type definitions for es6-promise
|
||||
// Project: https://github.com/jakearchibald/ES6-Promise
|
||||
// Definitions by: François de Campredon <https://github.com/fdecampredon/>, vvakame <https://github.com/vvakame>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
interface Thenable<R> {
|
||||
then<U>(onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => U | Thenable<U>): Thenable<U>;
|
||||
then<U>(onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => void): Thenable<U>;
|
||||
}
|
||||
|
||||
declare class Promise<R> implements Thenable<R> {
|
||||
/**
|
||||
* If you call resolve in the body of the callback passed to the constructor,
|
||||
* your promise is fulfilled with result object passed to resolve.
|
||||
* If you call reject your promise is rejected with the object passed to resolve.
|
||||
* For consistency and debugging (eg stack traces), obj should be an instanceof Error.
|
||||
* Any errors thrown in the constructor callback will be implicitly passed to reject().
|
||||
*/
|
||||
constructor(callback: (resolve : (value?: R | Thenable<R>) => void, reject: (error?: any) => void) => void);
|
||||
|
||||
/**
|
||||
* onFulfilled is called when/if "promise" resolves. onRejected is called when/if "promise" rejects.
|
||||
* Both are optional, if either/both are omitted the next onFulfilled/onRejected in the chain is called.
|
||||
* Both callbacks have a single parameter , the fulfillment value or rejection reason.
|
||||
* "then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve.
|
||||
* If an error is thrown in the callback, the returned promise rejects with that error.
|
||||
*
|
||||
* @param onFulfilled called when/if "promise" resolves
|
||||
* @param onRejected called when/if "promise" rejects
|
||||
*/
|
||||
then<U>(onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => U | Thenable<U>): Promise<U>;
|
||||
then<U>(onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => void): Promise<U>;
|
||||
|
||||
/**
|
||||
* Sugar for promise.then(undefined, onRejected)
|
||||
*
|
||||
* @param onRejected called when/if "promise" rejects
|
||||
*/
|
||||
catch<U>(onRejected?: (error: any) => U | Thenable<U>): Promise<U>;
|
||||
}
|
||||
|
||||
declare module Promise {
|
||||
/**
|
||||
* Make a new promise from the thenable.
|
||||
* A thenable is promise-like in as far as it has a "then" method.
|
||||
*/
|
||||
function resolve<R>(value?: R | Thenable<R>): Promise<R>;
|
||||
|
||||
/**
|
||||
* Make a promise that rejects to obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error
|
||||
*/
|
||||
function reject(error: any): Promise<any>;
|
||||
|
||||
/**
|
||||
* Make a promise that fulfills when every item in the array fulfills, and rejects if (and when) any item rejects.
|
||||
* the array passed to all can be a mixture of promise-like objects and other objects.
|
||||
* The fulfillment value is an array (in order) of fulfillment values. The rejection value is the first rejection value.
|
||||
*/
|
||||
function all<R>(promises: (R | Thenable<R>)[]): Promise<R[]>;
|
||||
|
||||
/**
|
||||
* Make a Promise that fulfills when any item fulfills, and rejects if any item rejects.
|
||||
*/
|
||||
function race<R>(promises: (R | Thenable<R>)[]): Promise<R>;
|
||||
}
|
||||
|
||||
declare module 'es6-promise' {
|
||||
var foo: typeof Promise; // Temp variable to reference Promise in local context
|
||||
module rsvp {
|
||||
export var Promise: typeof foo;
|
||||
}
|
||||
export = rsvp;
|
||||
}
|
136
utilities.ts
136
utilities.ts
|
@ -927,3 +927,139 @@ module J2ME {
|
|||
return this.indexOf(str, this.length - str.length) !== -1;
|
||||
});
|
||||
})();
|
||||
|
||||
module J2ME.Shell {
|
||||
export class MicroTask {
|
||||
runAt: number;
|
||||
constructor(public id: number, public fn: () => any, public args: any[],
|
||||
public interval: number, public repeat: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
var RealDate = Date;
|
||||
var fakeTime = 1428107694580; // 3-Apr-2015
|
||||
var jsGlobal = (function() { return this || (1, eval)('this//# sourceURL=jsGlobal-getter'); })();
|
||||
|
||||
/**
|
||||
* This should only be called if you need fake time.
|
||||
*/
|
||||
export function installTimeWarper() {
|
||||
|
||||
// Go back in time.
|
||||
fakeTime = 1428107694580; // 3-Apr-2015
|
||||
|
||||
// Overload
|
||||
jsGlobal.Date = function (yearOrTimevalue, month, date, hour, minute, second, millisecond) {
|
||||
switch (arguments.length) {
|
||||
case 0: return new RealDate(fakeTime); break;
|
||||
case 1: return new RealDate(yearOrTimevalue); break;
|
||||
case 2: return new RealDate(yearOrTimevalue, month); break;
|
||||
case 3: return new RealDate(yearOrTimevalue, month, date); break;
|
||||
case 4: return new RealDate(yearOrTimevalue, month, date, hour); break;
|
||||
case 5: return new RealDate(yearOrTimevalue, month, date, hour, minute); break;
|
||||
case 6: return new RealDate(yearOrTimevalue, month, date, hour, minute, second); break;
|
||||
default: return new RealDate(yearOrTimevalue, month, date, hour, minute, second, millisecond); break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make date now deterministic.
|
||||
jsGlobal.Date.now = function () {
|
||||
return fakeTime += 10; // Advance time.
|
||||
}
|
||||
}
|
||||
|
||||
export class MicroTasksQueue {
|
||||
private tasks: MicroTask[] = [];
|
||||
private nextId: number = 1;
|
||||
private time: number = 1388556000000; // 1-Jan-2014
|
||||
private stopped: boolean = true;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public get isEmpty(): boolean {
|
||||
return this.tasks.length === 0;
|
||||
}
|
||||
|
||||
public scheduleInterval(fn: () => any, args: any[], interval: number, repeat: boolean) {
|
||||
var MIN_INTERVAL = 4;
|
||||
interval = Math.round((interval || 0)/10) * 10;
|
||||
if (interval < MIN_INTERVAL) {
|
||||
interval = MIN_INTERVAL;
|
||||
}
|
||||
var taskId = this.nextId++;
|
||||
var task = new MicroTask(taskId, fn, args, interval, repeat);
|
||||
this.enqueue(task);
|
||||
return task;
|
||||
}
|
||||
|
||||
public enqueue(task: MicroTask) {
|
||||
var tasks = this.tasks;
|
||||
task.runAt = this.time + task.interval;
|
||||
var i = tasks.length;
|
||||
while (i > 0 && tasks[i - 1].runAt > task.runAt) {
|
||||
i--;
|
||||
}
|
||||
if (i === tasks.length) {
|
||||
tasks.push(task);
|
||||
} else {
|
||||
tasks.splice(i, 0, task);
|
||||
}
|
||||
}
|
||||
|
||||
public dequeue(): MicroTask {
|
||||
var task = this.tasks.shift();
|
||||
this.time = task.runAt;
|
||||
return task;
|
||||
}
|
||||
|
||||
public remove(id: number) {
|
||||
var tasks = this.tasks;
|
||||
for (var i = 0; i < tasks.length; i++) {
|
||||
if (tasks[i].id === id) {
|
||||
tasks.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public clear() {
|
||||
this.tasks.length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs micro tasks for a certain |duration| and |count| whichever comes first. Optionally,
|
||||
* if the |clear| option is specified, the micro task queue is cleared even if not all the
|
||||
* tasks have been executed.
|
||||
*
|
||||
* If a |preCallback| function is specified, only continue execution if |preCallback()| returns true.
|
||||
*/
|
||||
run(duration: number = 0, count: number = 0, clear: boolean = false, preCallback: Function = null) {
|
||||
this.stopped = false;
|
||||
var executedTasks = 0;
|
||||
var stopAt = Date.now() + duration;
|
||||
while (!this.isEmpty && !this.stopped) {
|
||||
if (duration > 0 && Date.now() >= stopAt) {
|
||||
break;
|
||||
}
|
||||
if (count > 0 && executedTasks >= count) {
|
||||
break;
|
||||
}
|
||||
var task = this.dequeue();
|
||||
if (preCallback && !preCallback(task)) {
|
||||
return;
|
||||
}
|
||||
task.fn.apply(null, task.args);
|
||||
executedTasks ++;
|
||||
}
|
||||
if (clear) {
|
||||
this.clear();
|
||||
}
|
||||
this.stopped = true;
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.stopped = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,13 +21,9 @@ declare var Long: {
|
|||
fromNumber(value: number);
|
||||
}
|
||||
|
||||
interface Promise {
|
||||
catch(onRejected: { (reason: any): any; }): Promise;
|
||||
}
|
||||
|
||||
interface CompiledMethodCache {
|
||||
get(key: string): { key: string; source: string; referencedClasses: string[]; };
|
||||
put(obj: { key: string; source: string; referencedClasses: string[]; }): Promise;
|
||||
put(obj: { key: string; source: string; referencedClasses: string[]; }): Promise<any>;
|
||||
}
|
||||
|
||||
interface AOTMetaData {
|
||||
|
|
Загрузка…
Ссылка в новой задаче