add: promise support; fix: dialogs and setClip ANR on ui thread;
This commit is contained in:
@@ -46,8 +46,9 @@ __runtime__.bridges.setBridges({
|
||||
});
|
||||
|
||||
var __that__ = this;
|
||||
JSON = require('__json2__.js');
|
||||
util = require('__util__.js');
|
||||
var Promise = require('promise.js');
|
||||
var JSON = require('__json2__.js');
|
||||
var util = require('__util__.js');
|
||||
|
||||
var __asGlobal__ = function(obj, functions){
|
||||
var len = functions.length;
|
||||
|
||||
@@ -2,43 +2,107 @@
|
||||
module.exports = function(__runtime__, scope){
|
||||
var dialogs = {};
|
||||
|
||||
dialogs.rawInput = function(title, prefill){
|
||||
dialogs.rawInput = function(title, prefill, callback){
|
||||
prefill = prefill || "";
|
||||
var s = __runtime__.dialogs.rawInput(title, prefill);
|
||||
return s ? String(s) : null;
|
||||
if(isUiThread() && !callback){
|
||||
return new Promise(function(resolve, reject){
|
||||
rtDialogs().rawInput(title, prefill, function(){
|
||||
resolve.apply(null, Array.prototype.slice.call(arguments));
|
||||
});
|
||||
});
|
||||
}
|
||||
return rtDialogs().rawInput(title, prefill, callback ? callback : null);
|
||||
};
|
||||
|
||||
dialogs.input = function(title, prefill){
|
||||
return eval(dialogs.rawInput(title, prefill));
|
||||
dialogs.input = function(title, prefill, callback){
|
||||
prefill = prefill || "";
|
||||
if(isUiThread() && !callback){
|
||||
return new Promise(function(resolve, reject){
|
||||
rtDialogs().rawInput(title, prefill, function(str){
|
||||
resolve(eval(str));
|
||||
});
|
||||
});
|
||||
}
|
||||
if(callback){
|
||||
dialogs.rawInput(title, prefill, function(str){
|
||||
callback(eval(str));
|
||||
});
|
||||
return;
|
||||
}
|
||||
return eval(dialogs.rawInput(title, prefill), callback ? callback : null);
|
||||
}
|
||||
|
||||
dialogs.prompt = dialogs.rawInput;
|
||||
|
||||
dialogs.alert = function(title, prefill){
|
||||
dialogs.alert = function(title, prefill, callback){
|
||||
prefill = prefill || "";
|
||||
return __runtime__.dialogs.alert(title, prefill);
|
||||
}
|
||||
|
||||
dialogs.confirm = function(title, prefill){
|
||||
prefill = prefill || "";
|
||||
return __runtime__.dialogs.confirm(title, prefill);
|
||||
}
|
||||
|
||||
dialogs.select = function(title, items){
|
||||
if(items instanceof Array){
|
||||
return __runtime__.dialogs.select(title, items);
|
||||
if(isUiThread() && !callback){
|
||||
return new Promise(function(resolve, reject){
|
||||
rtDialogs().alert(title, prefill, function(){
|
||||
resolve.apply(null, Array.prototype.slice.call(arguments));
|
||||
});
|
||||
});
|
||||
}
|
||||
return __runtime__.dialogs.select(title, [].slice.call(arguments, 1));
|
||||
return rtDialogs().alert(title, prefill, callback ? callback : null);
|
||||
}
|
||||
|
||||
dialogs.singleChoice = function(title, items, index){
|
||||
dialogs.confirm = function(title, prefill, callback){
|
||||
prefill = prefill || "";
|
||||
if(isUiThread() && !callback){
|
||||
return new Promise(function(resolve, reject){
|
||||
rtDialogs().confirm(title, prefill, function(){
|
||||
resolve.apply(null, Array.prototype.slice.call(arguments));
|
||||
});
|
||||
});
|
||||
}
|
||||
return rtDialogs().confirm(title, prefill, callback ? callback : null);
|
||||
}
|
||||
|
||||
dialogs.select = function(title, items, callback){
|
||||
if(items instanceof Array){
|
||||
if(isUiThread() && !callback){
|
||||
return new Promise(function(resolve, reject){
|
||||
rtDialogs().select(title, items, function(){
|
||||
resolve.apply(null, Array.prototype.slice.call(arguments));
|
||||
});
|
||||
});
|
||||
}
|
||||
return rtDialogs().select(title, items, callback ? callback : null);
|
||||
}
|
||||
return rtDialogs().select(title, [].slice.call(arguments, 1));
|
||||
}
|
||||
|
||||
dialogs.singleChoice = function(title, items, index, callback){
|
||||
index = index || 0;
|
||||
return __runtime__.dialogs.singleChoice(title, index, items);
|
||||
if(isUiThread() && !callback){
|
||||
return new Promise(function(resolve, reject){
|
||||
rtDialogs().singleChoice(title, index, items, function(){
|
||||
resolve.apply(null, Array.prototype.slice.call(arguments));
|
||||
});
|
||||
});
|
||||
}
|
||||
return rtDialogs().singleChoice(title, index, items, callback ? callback : null);
|
||||
}
|
||||
|
||||
dialogs.multiChoice = function(title, items, index){
|
||||
dialogs.multiChoice = function(title, items, index, callback){
|
||||
index = index || [];
|
||||
var javaArray = __runtime__.dialogs.multiChoice(title, index, items);
|
||||
if(isUiThread() && !callback){
|
||||
return new Promise(function(resolve, reject){
|
||||
rtDialogs().singleChoice(title, index, items, function(r){
|
||||
resolve.apply(null, toJsArray(r));
|
||||
});
|
||||
});
|
||||
}
|
||||
if(callback){
|
||||
return rtDialogs().multiChoice(title, index, items, function(r){
|
||||
callback(toJsArray(r));
|
||||
});
|
||||
}
|
||||
return toJsArray(rtDialogs().multiChoice(title, index, items, null));
|
||||
|
||||
}
|
||||
|
||||
function toJsArray(javaArray){
|
||||
var jsArray = [];
|
||||
var len = javaArray.length;
|
||||
for (var i = 0;i < len;i++){
|
||||
@@ -47,21 +111,26 @@ module.exports = function(__runtime__, scope){
|
||||
return jsArray;
|
||||
}
|
||||
|
||||
scope.rawInput = function(title, prefill){
|
||||
return dialogs.rawInput(title, prefill);
|
||||
function rtDialogs(){
|
||||
var d = __runtime__.dialogs;
|
||||
if(!isUiThread()){
|
||||
return d.nonUiDialogs;
|
||||
}else{
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
scope.alert = function(title, prefill){
|
||||
dialogs.alert(title, prefill);
|
||||
function isUiThread(){
|
||||
return android.os.Looper.myLooper() == android.os.Looper.getMainLooper();
|
||||
}
|
||||
|
||||
scope.confirm = function(title, prefill){
|
||||
return dialogs.confirm(title, prefill);
|
||||
}
|
||||
scope.rawInput = dialogs.rawInput.bind(dialogs);
|
||||
|
||||
scope.prompt = function(title, prefill){
|
||||
return dialogs.prompt(title, prefill);
|
||||
}
|
||||
scope.alert = dialogs.alert.bind(dialogs);
|
||||
|
||||
scope.confirm = dialogs.confirm.bind(dialogs);
|
||||
|
||||
scope.prompt = dialogs.prompt.bind(dialogs);
|
||||
|
||||
return dialogs;
|
||||
}
|
||||
215
autojs/src/main/assets/modules/promise.js
Normal file
215
autojs/src/main/assets/modules/promise.js
Normal file
@@ -0,0 +1,215 @@
|
||||
'use strict';
|
||||
|
||||
function asap(action){
|
||||
action();
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
|
||||
// States:
|
||||
//
|
||||
// 0 - pending
|
||||
// 1 - fulfilled with _value
|
||||
// 2 - rejected with _value
|
||||
// 3 - adopted the state of another promise, _value
|
||||
//
|
||||
// once the state is no longer pending (0) it is immutable
|
||||
|
||||
// All `_` prefixed properties will be reduced to `_{random number}`
|
||||
// at build time to obfuscate them and discourage their use.
|
||||
// We don't use symbols or Object.defineProperty to fully hide them
|
||||
// because the performance isn't good enough.
|
||||
|
||||
|
||||
// to avoid using try/catch inside critical functions, we
|
||||
// extract them to here.
|
||||
var LAST_ERROR = null;
|
||||
var IS_ERROR = {};
|
||||
function getThen(obj) {
|
||||
try {
|
||||
return obj.then;
|
||||
} catch (ex) {
|
||||
LAST_ERROR = ex;
|
||||
return IS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
function tryCallOne(fn, a) {
|
||||
try {
|
||||
return fn(a);
|
||||
} catch (ex) {
|
||||
LAST_ERROR = ex;
|
||||
return IS_ERROR;
|
||||
}
|
||||
}
|
||||
function tryCallTwo(fn, a, b) {
|
||||
try {
|
||||
fn(a, b);
|
||||
} catch (ex) {
|
||||
LAST_ERROR = ex;
|
||||
return IS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Promise;
|
||||
|
||||
function Promise(fn) {
|
||||
if (typeof this !== 'object') {
|
||||
throw new TypeError('Promises must be constructed via new');
|
||||
}
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('Promise constructor\'s argument is not a function');
|
||||
}
|
||||
this._deferredState = 0;
|
||||
this._state = 0;
|
||||
this._value = null;
|
||||
this._deferreds = null;
|
||||
if (fn === noop) return;
|
||||
doResolve(fn, this);
|
||||
}
|
||||
Promise._onHandle = null;
|
||||
Promise._onReject = null;
|
||||
Promise._noop = noop;
|
||||
|
||||
Promise.prototype.then = function(onFulfilled, onRejected) {
|
||||
if (this.constructor !== Promise) {
|
||||
return safeThen(this, onFulfilled, onRejected);
|
||||
}
|
||||
var res = new Promise(noop);
|
||||
handle(this, new Handler(onFulfilled, onRejected, res));
|
||||
return res;
|
||||
};
|
||||
|
||||
function safeThen(self, onFulfilled, onRejected) {
|
||||
return new self.constructor(function (resolve, reject) {
|
||||
var res = new Promise(noop);
|
||||
res.then(resolve, reject);
|
||||
handle(self, new Handler(onFulfilled, onRejected, res));
|
||||
});
|
||||
}
|
||||
function handle(self, deferred) {
|
||||
while (self._state === 3) {
|
||||
self = self._value;
|
||||
}
|
||||
if (Promise._onHandle) {
|
||||
Promise._onHandle(self);
|
||||
}
|
||||
if (self._state === 0) {
|
||||
if (self._deferredState === 0) {
|
||||
self._deferredState = 1;
|
||||
self._deferreds = deferred;
|
||||
return;
|
||||
}
|
||||
if (self._deferredState === 1) {
|
||||
self._deferredState = 2;
|
||||
self._deferreds = [self._deferreds, deferred];
|
||||
return;
|
||||
}
|
||||
self._deferreds.push(deferred);
|
||||
return;
|
||||
}
|
||||
handleResolved(self, deferred);
|
||||
}
|
||||
|
||||
function handleResolved(self, deferred) {
|
||||
asap(function() {
|
||||
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
|
||||
if (cb === null) {
|
||||
if (self._state === 1) {
|
||||
resolve(deferred.promise, self._value);
|
||||
} else {
|
||||
reject(deferred.promise, self._value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var ret = tryCallOne(cb, self._value);
|
||||
if (ret === IS_ERROR) {
|
||||
reject(deferred.promise, LAST_ERROR);
|
||||
} else {
|
||||
resolve(deferred.promise, ret);
|
||||
}
|
||||
});
|
||||
}
|
||||
function resolve(self, newValue) {
|
||||
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
|
||||
if (newValue === self) {
|
||||
return reject(
|
||||
self,
|
||||
new TypeError('A promise cannot be resolved with itself.')
|
||||
);
|
||||
}
|
||||
if (
|
||||
newValue &&
|
||||
(typeof newValue === 'object' || typeof newValue === 'function')
|
||||
) {
|
||||
var then = getThen(newValue);
|
||||
if (then === IS_ERROR) {
|
||||
return reject(self, LAST_ERROR);
|
||||
}
|
||||
if (
|
||||
then === self.then &&
|
||||
newValue instanceof Promise
|
||||
) {
|
||||
self._state = 3;
|
||||
self._value = newValue;
|
||||
finale(self);
|
||||
return;
|
||||
} else if (typeof then === 'function') {
|
||||
doResolve(then.bind(newValue), self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
self._state = 1;
|
||||
self._value = newValue;
|
||||
finale(self);
|
||||
}
|
||||
|
||||
function reject(self, newValue) {
|
||||
self._state = 2;
|
||||
self._value = newValue;
|
||||
if (Promise._onReject) {
|
||||
Promise._onReject(self, newValue);
|
||||
}
|
||||
finale(self);
|
||||
}
|
||||
function finale(self) {
|
||||
if (self._deferredState === 1) {
|
||||
handle(self, self._deferreds);
|
||||
self._deferreds = null;
|
||||
}
|
||||
if (self._deferredState === 2) {
|
||||
for (var i = 0; i < self._deferreds.length; i++) {
|
||||
handle(self, self._deferreds[i]);
|
||||
}
|
||||
self._deferreds = null;
|
||||
}
|
||||
}
|
||||
|
||||
function Handler(onFulfilled, onRejected, promise){
|
||||
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
|
||||
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
|
||||
this.promise = promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a potentially misbehaving resolver function and make sure
|
||||
* onFulfilled and onRejected are only called once.
|
||||
*
|
||||
* Makes no guarantees about asynchrony.
|
||||
*/
|
||||
function doResolve(fn, promise) {
|
||||
var done = false;
|
||||
var res = tryCallTwo(fn, function (value) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
resolve(promise, value);
|
||||
}, function (reason) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
reject(promise, reason);
|
||||
});
|
||||
if (!done && res === IS_ERROR) {
|
||||
done = true;
|
||||
reject(promise, LAST_ERROR);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user