6.2.0 - 重新设计及编写项目文档; 新增多语言适配; 丰富控件选择器功能; 优化夜间模式适配等

This commit is contained in:
SuperMonster003
2023-01-21 22:17:16 +08:00
parent 069932c8d3
commit 10960ddbee
2139 changed files with 66316 additions and 41795 deletions

View File

@@ -0,0 +1,197 @@
/* Overwritten protection. */
let { util, plugins } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Arrayx}
*/
module.exports = (scriptRuntime, scope) => {
let _ = {
ArrayxCtor: ( /* @IIFE */ () => {
/**
* @implements Internal.Arrayx
*/
const ArrayxCtor = function () {
return Object.assign(Array.bind(Array), ArrayxCtor.prototype);
};
ArrayxCtor.prototype = {
constructor: ArrayxCtor,
// assureArray(o) {
// if (Array.isArray(o)) {
// return o;
// }
// if (isObjectSpecies(o) && typeof o.length === 'number' && o.length >= 0) {
// return Array.from(o);
// }
// return [ o ];
// },
ensureArray() {
Array.from(arguments).forEach(o => util.ensureArrayType(o));
},
distinct(arr) {
Arrayx.ensureArray(arr);
return Array.from(new Set(arr));
},
distinctBy(arr, selector) {
Arrayx.ensureArray(arr);
let res = [];
let cache = [];
arr.forEach(e => {
let selected = selector(e);
if (!cache.includes(selected)) {
cache.push(selected);
res.push(e);
}
});
return res;
},
/**
* TODO by SuperMonster003 on Jan 21, 2023.
* ! Better performance.
*/
union(arr, others) {
Arrayx.ensureArray(arr);
let res = Array.from(arguments).slice(1).reduce((a, b) => {
return Array.isArray(b) ? a.concat(b) : a.concat([ b ]);
}, arr);
return Arrayx.distinct(res);
},
/**
* TODO by SuperMonster003 on Jan 21, 2023.
* ! Better performance.
*/
intersect(arr, others) {
Arrayx.ensureArray(arr);
if (arr.length === 0 || arguments.length <= 1) {
return [];
}
return Arrayx.distinct(arr).filter((o) => {
return Array.from(arguments).slice(1).every((e) => {
return Array.isArray(e) ? Arrayx.distinct(e).includes(o) : e === o;
});
});
},
/**
* TODO by SuperMonster003 on Jan 21, 2023.
* ! Necessary or not ?
*/
different() {
throw Error('TODO');
},
sortBy(arr, selector) {
Arrayx.ensureArray(arr);
if (arr.length < 2) {
return arr;
}
return arr.sort((a, b) => {
let sA = selector(a);
let sB = selector(b);
return sA === sB ? 0 : sA > sB ? 1 : -1;
});
},
sortDescending(arr) {
Arrayx.ensureArray(arr);
if (arr.length < 2) {
return arr;
}
return arr.sort(_.bySimpleCompare).reverse();
},
sortByDescending(arr, selector) {
Arrayx.ensureArray(arr);
if (arr.length < 2) {
return arr;
}
return arr.sort((a, b) => {
let sA = selector(a);
let sB = selector(b);
return sA === sB ? 0 : sA > sB ? -1 : 1;
});
},
sorted(arr) {
Arrayx.ensureArray(arr);
return arr.slice().sort(_.bySimpleCompare);
},
sortedBy(arr, selector) {
Arrayx.ensureArray(arr);
let copy = arr.slice();
if (copy.length < 2) {
return copy;
}
return this.sortBy(copy, selector);
},
sortedDescending(arr) {
Arrayx.ensureArray(arr);
let copy = arr.slice();
if (copy.length < 2) {
return copy;
}
return this.sortDescending(copy);
},
sortedByDescending(arr, selector) {
Arrayx.ensureArray(arr);
let copy = arr.slice();
if (copy.length < 2) {
return copy;
}
return this.sortByDescending(arr, selector);
},
shuffle(arr) {
return arr.sort(() => Math.random() >= 0.5 ? 1 : -1);
},
};
return ArrayxCtor;
})(),
bySimpleCompare: (a, b) => a === b ? 0 : a > b ? 1 : -1,
registerPluginModule() {
plugins.extend.registerModule({
Arrayx: {
protoKeys: {
intersect: 0,
union: 0,
distinct: 0,
distinctBy: 0,
sortBy: 0,
sortDescending: 0,
sortByDescending: 0,
sorted: 0,
sortedBy: 0,
sortedDescending: 0,
sortedByDescending: 0,
shuffle: 0,
},
extendJsBuildInObjects() {
let that = this;
Object.keys(_.ArrayxCtor.prototype).forEach((key) => {
if (!(key in that.protoKeys)) {
Array[key] = Arrayx[key];
return;
}
if (typeof that.protoKeys[key] !== 'number') {
Array.prototype[key] = Arrayx[key];
return;
}
Array.prototype[key] = function () {
const args = Array.from(arguments);
args.splice(that.protoKeys[key], 0, this.valueOf());
return Arrayx[key].apply(Arrayx, args);
};
});
},
},
});
},
};
/**
* @type {Internal.Arrayx}
*/
const Arrayx = new _.ArrayxCtor();
_.registerPluginModule();
return Arrayx;
};

View File

@@ -0,0 +1,223 @@
/* Overwritten protection. */
let { plugins, Arrayx, Numberx } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Mathx}
*/
module.exports = (scriptRuntime, scope) => {
let _ = {
MathxCtor: ( /* @IIFE */ () => {
/**
* @implements Internal.Mathx
*/
const MathxCtor = function () {
// Empty interface body.
};
MathxCtor.prototype = {
constructor: MathxCtor,
randInt(range) {
let args = Array.from(arguments);
if (args.length === 0) {
return Mathx.randInt(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
}
if (args.length === 1) {
if (Array.isArray(args[0])) {
return Mathx.randInt.apply(Mathx, args.flat(Infinity));
}
util.ensureNumberType(args[0]);
return args[0] > 0
? Mathx.randInt(0, args[0])
: Mathx.randInt(args[0], 0);
}
let ranges = Arrayx.distinct(Arrayx.sorted(args.flat(Infinity).map(o => Number(o)).filter(o => !isNaN(o))));
let min, max;
util.ensureNumberType(min = Math.ceil(ranges.at(0)));
util.ensureNumberType(max = Math.floor(ranges.at(-1)));
return Math.floor(Math.random() * (max - min + 1)) + min;
},
sum(num, fraction) {
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
if (!nums.length || nums.includes(NaN)) {
return NaN;
}
let sum = nums.reduce((x, y) => Number(x) + Number(y));
let fracInt = parseInt(frac);
return isNaN(fracInt) ? sum : Numberx.toFixedNum(sum, fracInt);
},
avg(num, fraction) {
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
if (!nums.length || nums.includes(NaN)) {
return NaN;
}
let sum = Mathx.sum(nums);
let avg = sum / nums.length;
let fracInt = parseInt(frac);
return isNaN(fracInt) ? avg : Numberx.toFixedNum(avg, fracInt);
},
median(num, fraction) {
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
Arrayx.sortBy(nums, Number);
let len = nums.length;
if (!len || nums.includes(NaN)) {
return NaN;
}
let med = len % 2
? nums[Math.floor(len / 2)]
: (nums[len / 2 - 1] + nums[len / 2]) / 2;
let fracInt = parseInt(frac);
return isNaN(fracInt) ? med : Numberx.toFixedNum(med, fracInt);
},
var(num, fraction) {
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
let avg = Mathx.avg(nums);
let len = nums.length;
if (!len || nums.includes(NaN)) {
return NaN;
}
let acc = 0;
for (let i = 0; i < len; i += 1) {
acc += (nums[i] - avg) ** 2;
}
let res = acc / len;
let fracInt = parseInt(frac);
return isNaN(fracInt) ? res : Numberx.toFixedNum(res, fracInt);
},
std(num, fraction) {
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
if (!nums.length || nums.includes(NaN)) {
return NaN;
}
let std = Math.sqrt(Mathx.var(nums));
let fracInt = parseInt(frac);
return isNaN(fracInt) ? std : Numberx.toFixedNum(std, fracInt);
},
cv(num, fraction) {
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
let len = nums.length;
if (len < 2 || nums.includes(NaN)) {
return NaN;
}
let avg = Mathx.avg(nums);
let acc = 0;
for (let i = 0; i < len; i += 1) {
acc += (nums[i] - avg) ** 2;
}
/**
* Sample Standard Deviation (zh-CN: 样本标准差)
*/
let ssd = Math.pow(acc / (len - 1), 0.5);
let cv = ssd / avg;
let fracInt = parseInt(frac);
return isNaN(fracInt) ? cv : Numberx.toFixedNum(cv, fracInt);
},
max(num, fraction) {
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
let max = Math.max.apply(null, nums);
let fracInt = parseInt(frac);
return isNaN(fracInt) ? max : Numberx.toFixedNum(max, fracInt);
},
min(num, fraction) {
let [ nums, frac ] = _.parseArgs.apply(_, arguments);
let max = Math.min.apply(null, nums);
let fracInt = parseInt(frac);
return isNaN(fracInt) ? max : Numberx.toFixedNum(max, fracInt);
},
dist(pointA, pointB, fraction) {
if (pointA instanceof android.graphics.Rect) {
if (arguments.length === 1) {
return Mathx.dist({ x: pointA.left, y: pointA.top }, { x: pointA.right, y: pointA.bottom });
}
if (arguments.length === 2 && typeof arguments[1] === 'number') {
return Mathx.dist({ x: pointA.left, y: pointA.top }, { x: pointA.right, y: pointA.bottom }, /* fraction = */ arguments[1]);
}
}
let a = _.toPoint(pointA);
let b = _.toPoint(pointB);
let fracInt = Math.trunc(fraction);
let res = Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);
return isNaN(fracInt) ? res : Numberx.toFixedNum(res, fracInt);
},
logMn(base, antilogarithm, fraction) {
let _frac = typeof fraction === 'number' ? fraction : 13;
let _result = Math.log(antilogarithm) / Math.log(base);
if (isNaN(_result) || !isFinite(_result) || _frac !== -1) {
return _result;
}
return Number(_result.toFixed(_frac));
},
floorLog(base, antilogarithm) {
return Math.floor(Mathx.logMn(base, antilogarithm));
},
ceilLog(base, antilogarithm) {
return Math.ceil(Mathx.logMn(base, antilogarithm));
},
roundLog(base, antilogarithm) {
return Math.round(Mathx.logMn(base, antilogarithm));
},
floorPow(base, power) {
return Math.pow(base, Mathx.floorLog(base, power));
},
ceilPow(base, power) {
return Math.pow(base, Mathx.ceilLog(base, power));
},
roundPow(base, power) {
return Math.pow(base, Mathx.roundLog(base, power));
},
};
return MathxCtor;
})(),
parseArgs(nums, fraction) {
if (Array.isArray(nums)) {
return [ nums.flat(Infinity), fraction ];
}
return [ Array.from(arguments).flat(Infinity) ];
},
toPoint(o) {
if (Array.isArray(o)) {
if (o.length !== 2) {
throw Error('Points array must be length of 2');
}
return { x: Number(o[0]), y: Number(o[1]) };
}
if (o instanceof android.graphics.Rect) {
// @Hint by SuperMonster003 on Oct 28, 2022.
// ! centerX or centerY will lose the precision.
return { x: o.exactCenterX(), y: o.exactCenterY() };
}
if (o instanceof org.opencv.core.Point) {
return { x: o.x, y: o.y };
}
return isObjectSpecies(o) ? o : {};
},
registerPluginModule() {
plugins.extend.registerModule({
Mathx: {
extendJsBuildInObjects() {
let mapper = {
max: 'maxi',
min: 'mini',
};
Object.keys(_.MathxCtor.prototype).forEach((key) => {
Math[key in mapper ? mapper[key] : key] = Mathx[key];
});
},
},
});
},
};
/**
* @type {Internal.Mathx}
*/
const Mathx = new _.MathxCtor();
_.registerPluginModule();
return Mathx;
};

View File

@@ -0,0 +1,227 @@
/* Overwritten protection. */
let { util, plugins } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Numberx}
*/
module.exports = (scriptRuntime, scope) => {
let _ = {
compareOperators: {
'<': (a, b) => a < b,
'<=': (a, b) => a <= b,
'>': (a, b) => a > b,
'>=': (a, b) => a >= b,
'=': (a, b) => a === b,
},
NumberxCtor: ( /* @IIFE */ () => {
/**
* @implements Internal.Numberx
*/
const NumberxCtor = function () {
return Object.assign(Number.bind(Number), NumberxCtor.prototype);
};
NumberxCtor.prototype = {
constructor: NumberxCtor,
ICU: ( /* @IIFE */ () => {
const workdays = 5;
const weekends = 2;
const health = 'Your health';
const evil = 'Hard working only';
return Math.round(evil
.split(new RegExp(`[${health.toLowerCase()}]`))
.map(x => x ? x.codePointAt(0) : 996 / workdays / weekends - weekends)
.reduce((x, y) => x + y));
})(),
prototype: Number.prototype,
ensureNumber() {
Array.from(arguments).forEach(o => util.ensureNumberType(o));
},
check() {
if (arguments.length === 0) {
return false;
}
if (arguments.length === 1) {
return typeof arguments[0] === 'number';
}
if (arguments.length === 2) {
let numA = arguments[0];
let numB = arguments[1];
return this.check(numA) && this.check(numB) && numA === numB;
}
for (let i = 1; i < arguments.length; i += 2) {
let opr = arguments[i]; // operator string
if (typeof opr !== 'string' || !(opr in _.compareOperators)) {
throw Error(`arguments[${i}] for Numberx.check must be an operator rather than ${typeof opr === 'string' ? `"${opr}"` : opr}`);
}
let b = arguments[i + 1];
if (typeof b !== 'number') {
throw Error(`arguments[${i + 1}] for Numberx.check must be a number rather than ${typeof b === 'string' ? `"${b}"` : b}`);
}
let a = arguments[i - 1];
if (!_.compareOperators[opr](a, b)) {
return false;
}
}
return true;
},
clamp(num, clamps) {
Numberx.ensureNumber(num);
if (!Array.isArray(clamps)) {
clamps = Array.from(arguments).slice(1) || [];
}
let sortedClamps = clamps
.flat()
.filter(x => !isNaN(Number(x)))
.sort((x, y) => x - y);
if (sortedClamps.length > 0) {
let min = sortedClamps.at(0);
let max = sortedClamps.at(-1);
if (num < min) return min;
if (num > max) return max;
}
return num;
},
clampTo(num, range, cycle) {
let sortedClamps = range
.flat()
.filter(x => !isNaN(Number(x)))
.sort((x, y) => x - y);
if (sortedClamps.length > 0) {
let min = sortedClamps.at(0);
let max = sortedClamps.at(-1);
let t = typeof cycle === 'number' ? cycle : max - min;
if (t <= 0) {
throw RangeError(`Cycle must be a positive number`);
}
if (num < min) {
num += Math.ceil((min - num) / t) * t;
} else if (num > max) {
num -= Math.ceil((num - max) / t) * t;
}
}
return num;
},
toFixedNum(num, fraction) {
Numberx.ensureNumber(num);
return Number(num.toFixed(fraction));
},
padStart(num, targetLength, pad) {
Numberx.ensureNumber(num);
let s = num.toString();
return s.padStart.call(s, targetLength, pad || 0);
},
padEnd(num, targetLength, pad) {
Numberx.ensureNumber(num);
let s = num.toString();
return s.padEnd.call(s, targetLength, pad || 0);
},
parseFloat(string, radix) {
if (radix === undefined) {
return _.oriParseFloat(string);
}
if (typeof string !== 'string') {
if ('toString' in string && typeof string.toString === 'function') {
string = string.toString();
} else {
string = String(string);
}
}
// @Reference by SuperMonster003 on Nov 1, 2022.
// ! to https://stackoverflow.com/questions/37109968/how-to-convert-binary-fraction-to-decimal
return Number.parseInt(string.replace('.', ''), radix) / radix ** (string.split('.')[1] || '').length;
},
/**
* @example
* Numberx.parsePercent('1%'); // 0.01
* Numberx.parsePercent('1%%'); // 0.0001
*/
parsePercent(percent) {
if (typeof percent === 'number') {
return percent;
}
let matchArray = String(percent).replace(/\s*/g, '').match(/^([+-]?\d+(?:\.\d+)?)(%*)$/);
return matchArray ? matchArray[1] / 100 ** matchArray[2].length : NaN;
},
/**
* @example
* Numberx.parseRatio('3:2'); // 1.5
*/
parseRatio(ratio) {
let [ x, y ] = String(ratio).split(':').map(s => s.trim());
return parseFloat(x) / parseFloat(y);
},
parseAny(s) {
if (typeof s === 'number') {
return s;
}
if (typeof s !== 'string') {
s = String(s);
}
s = s.trim();
if (s.includes(':')) {
return this.parseRatio(s);
}
if (s.includes('%')) {
return this.parsePercent(s);
}
return Number(s);
},
};
return NumberxCtor;
})(),
oriParseFloat: Number.parseFloat.bind(Number),
registerPluginModule() {
plugins.extend.registerModule({
Numberx: {
protoKeys: {
clamp: 0,
clampTo: 0,
toFixedNum: 0,
padStart: 0,
padEnd: 0,
parseFloat() {
global.parseFloat = Number.parseFloat = Numberx.parseFloat;
},
},
extendJsBuildInObjects() {
let that = this;
Object.keys(_.NumberxCtor.prototype).forEach((key) => {
if (!(key in that.protoKeys)) {
Number[key] = Numberx[key];
return;
}
if (typeof that.protoKeys[key] === 'function') {
that.protoKeys[key].call(that.protoKeys);
return;
}
if (typeof that.protoKeys[key] === 'number') {
Number.prototype[key] = function () {
const args = Array.from(arguments);
args.splice(that.protoKeys[key], 0, this.valueOf());
return Numberx[key].apply(Numberx, args);
};
return;
}
Number.prototype[key] = Numberx[key];
});
},
},
});
},
};
/**
* @type {Internal.Numberx}
*/
const Numberx = new _.NumberxCtor();
_.registerPluginModule();
return Numberx;
};

View File

@@ -0,0 +1,40 @@
/* Overwritten protection. */
let { autojs } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.RootAutomator}
*/
module.exports = function (scriptRuntime, scope) {
const RootAutomator = org.autojs.autojs.core.inputevent.RootAutomator;
let _ = {
/**
* @extends Internal.RootAutomator
*/
RootAutomator(waitForReady) {
if (!autojs.isRootAvailable()) {
throw Error('RootAutomator must be instantiated with root access');
}
this.__ra__ = Object.create(new RootAutomator(scope.context, ( /* @IIFE */ () => {
if (typeof waitForReady === 'number') {
return waitForReady;
}
return Boolean(waitForReady);
})()));
[
'sendEvent', 'touch', 'setScreenMetrics',
'touchX', 'touchY', 'sendSync', 'sendMtSync',
'tap', 'swipe', 'press', 'longPress',
'touchDown', 'touchUp', 'touchMove',
'getDefaultId', 'setDefaultId', 'exit',
].forEach(key => this[key] = this.__ra__[key].bind(this.__ra__));
},
};
return _.RootAutomator;
};

View File

@@ -0,0 +1,517 @@
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { autojs, shell, files, util } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.App}
*/
module.exports = function (scriptRuntime, scope) {
const File = java.io.File;
const Uri = android.net.Uri;
const JavaInteger = java.lang.Integer;
const FileProvider = androidx.core.content.FileProvider;
/**
* @type {org.autojs.autojs.runtime.api.AppUtils}
*/
const rtApp = scriptRuntime.app;
const packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
// noinspection SpellCheckingInspection
let _ = {
App: ( /* @IIFE */ () => {
/**
* @extends Internal.App
*/
const App = function () {
// Empty interface body.
};
App.prototype = {
constructor: App,
autojs,
versionCode: packageInfo.versionCode,
versionName: packageInfo.versionName,
/**
* @param {App.Intent.Preset.AppAlias | App.PackageName} app
* @returns {boolean}
*/
launch(app) {
return this.launchPackage(app);
},
/**
* @param {App.Intent.Common} o
* @return {Intent}
*/
intent(o) {
let intent = new Intent();
if (o.url) {
o.data = _.parseIntentUrl(o);
}
if (o.package) {
o.packageName = o.packageName || o.package;
} else if (o.packageName) {
o.package = o.packageName;
}
if (o.packageName) {
let k = String(o.packageName);
let presets = _.getPresetPackageNames();
if (k in presets) {
o.packageName = presets[k];
}
if (o.className) {
intent.setClassName(o.packageName, _.parseClassName(o));
} else {
// @Hint by SuperMonster003 on Jun 23, 2020.
// ! the Intent can only match the components
// ! in the given application package with setPackage().
// ! Otherwise, if there's more than one app that can handle the intent,
// ! the system presents the user with a dialog to pick which app to use.
intent.setPackage(o.packageName);
}
}
if (o.extras) {
Object.entries(o.extras).forEach((pairs) => {
let [ key, value ] = pairs;
intent.putExtra(key, value);
});
}
if (o.category) {
if (Array.isArray(o.category)) {
o.category.forEach(cat => intent.addCategory(o.category[cat]));
} else {
intent.addCategory(o.category);
}
}
if (o.action) {
intent.setAction(_.parseIntentAction(o.action));
}
if (o.flags) {
intent.setFlags(_.parseIntentFlags(o.flags));
}
if (o.type) {
if (o.data) {
intent.setDataAndType(this.parseUri(o.data), o.type);
} else {
intent.setType(o.type);
}
} else if (o.data) {
intent.setData(Uri.parse(o.data));
}
return intent;
},
/**
* @param {App.Intent.Common} i
* @return {string}
*/
intentToShell(i) {
let __ = {
init() {
this.cmd = '';
},
/**
* @typedef {{ body: string, isQuote?: boolean }} CmdBody
* @typedef {CmdBody | CmdBody[] | string} CmdBodies
*/
/**
* @param {string} cmdOptions
* @param {CmdBodies} cmdBodies
*/
append(cmdOptions, cmdBodies) {
this.cmd += ` -${cmdOptions} ${this.parseCmdBodies(cmdBodies)}`;
},
quote(str) {
return `'${str.replace('\'', '\\\'')}'`;
},
isInt(x) {
return Number.isInteger(x) && x <= JavaInteger.MAX_VALUE && x >= JavaInteger.MIN_VALUE;
},
parseType(type) {
if (typeof type === 'boolean') {
return 'z';
}
if (typeof type === 'number') {
return !Number.isInteger(type) ? 'f' : this.isInt(type) ? 'i' : 'l';
}
throw TypeError(`Unknown type: ${type}`);
},
/**
* @param {CmdBodies} o
* @return {string}
*/
parseCmdBodies(o) {
if (Array.isArray(o)) {
return o.map((p) => {
return p.isQuote ? this.quote(p.body) : p.body;
}).join('\x20');
}
let body = isObjectSpecies(o) ? o.body : o;
return o.isQuote ? this.quote(body) : body;
},
};
let $$ = {
getResult() {
this.init()
.parseNames()
.parseExtras()
.parseCategory()
.parseAction()
.parseFlags()
.parseType()
.parseData();
return this.cmd;
},
init() {
__.init();
Object.defineProperty(this, 'cmd', { get: () => __.cmd });
return this;
},
parseNames() {
if (i.className && i.packageName) {
let body = `${i.packageName}/${i.className}`;
__.append('n', { body, isQuote: true });
}
return this;
},
parseExtras() {
if (i.extras) {
Object.entries(i.extras).forEach((pairs) => {
let [ key, value ] = pairs;
if (typeof value === 'string') {
return __.append('-es', [
{ body: key, isQuote: true },
{ body: value, isQuote: true },
]);
}
if (Array.isArray(value)) {
if (value.length === 0) {
throw Error(`Empty array: ${key}`);
}
let [ element ] = value;
return typeof element === 'string'
? __.append('-esa', [
{ body: key, isQuote: true },
{ body: value.map(__.quote).join() },
])
: __.append(`-e${__.parseType(element)}a`, [
{ body: key, isQuote: true },
{ body: value },
]);
}
return __.append(`-e${__.parseType(value)}`, [
{ body: key, isQuote: true },
{ body: value },
]);
});
}
return this;
},
parseCategory() {
if (i.category) {
if (Array.isArray(i.category)) {
i.category.forEach(cat => __.append('c', cat));
} else {
__.append('c', i.category);
}
}
return this;
},
parseAction() {
if (i.action) {
__.append('a', {
body: _.parseIntentAction(i.action),
isQuote: true,
});
}
return this;
},
parseFlags() {
if (i.flags) {
__.append('f', _.parseIntentFlags(i.flags));
}
return this;
},
parseType() {
if (i.type) {
__.append('t', i.type);
}
return this;
},
parseData() {
if (i.data) {
__.append('d', i.data);
}
return this;
},
};
return $$.getResult();
},
startActivity(o) {
if (o instanceof Intent) {
return context.startActivity(o.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
if (typeof o === 'string') {
let prop = runtime.getProperty(`class.${o}`);
if (!prop) {
throw Error(`Class ${o} not found`);
}
let intent = new Intent(context, prop).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return context.startActivity(intent);
}
if (isObjectSpecies(o) && o.root) {
shell(`am start ${this.intentToShell(o)}`, true);
} else {
context.startActivity(this.intent(o).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
},
startService(i) {
if (isObjectSpecies(i) && i.root) {
// noinspection SpellCheckingInspection
shell(`am startservice ${this.intentToShell(i)}`, true);
} else {
context.startService(this.intent(i));
}
},
/**
* @param {App.Intent.Email} [options]
*/
sendEmail(options) {
let i = new Intent(Intent.ACTION_SEND);
let opt = options || {};
if (opt.email) {
i.putExtra(Intent.EXTRA_EMAIL, _.toArray(opt.email));
}
if (opt.cc) {
i.putExtra(Intent.EXTRA_CC, _.toArray(opt.cc));
}
if (opt.bcc) {
i.putExtra(Intent.EXTRA_BCC, _.toArray(opt.bcc));
}
if (opt.subject) {
i.putExtra(Intent.EXTRA_SUBJECT, opt.subject);
}
if (opt.text) {
i.putExtra(Intent.EXTRA_TEXT, opt.text);
}
if (opt.attachment) {
i.putExtra(Intent.EXTRA_STREAM, this.parseUri(opt.attachment));
}
i.setType('message/rfc822');
this.startActivity(Intent.createChooser(i, 'Send Email'));
},
sendBroadcast(i) {
if (typeof i === 'string') {
let property = runtime.getProperty(`broadcast.${i}`);
if (property) {
this.sendLocalBroadcastSync(this.intent({ action: property }));
}
} else {
if (isObjectSpecies(i) && i.root) {
shell(`am broadcast ${this.intentToShell(i)}`, true);
} else {
context.sendBroadcast(this.intent(i));
}
}
},
parseUri(uri) {
return uri.startsWith(_.protocol.file) ? this.getUriForFile(uri) : Uri.parse(uri);
},
getUriForFile(path) {
if (path.startsWith(_.protocol.file)) {
path = path.slice(_.protocol.file.length);
}
let file = new File(files.path(path));
return this.fileProviderAuthority === null
? Uri.fromFile(file)
: FileProvider.getUriForFile(context, this.fileProviderAuthority, file);
},
getAppByAlias(alias) {
return _.getAppByAlias(alias);
},
launchPackage(app) {
if (app instanceof App) {
app = app.getPackageName();
}
let preset = _.getAppByAlias(app);
return rtApp.launchPackage(preset ? preset.getPackageName() : app);
},
launchApp(app) {
if (app instanceof App) {
app = app.getAppName();
}
let preset = _.getAppByAlias(app);
return rtApp.launchApp(preset ? preset.getAppName() : app);
},
getAppName(app) {
if (app instanceof App) {
return app.getAppName();
}
let preset = _.getAppByAlias(app);
return preset ? preset.getAppName() : rtApp.getAppName(String(app));
},
getPackageName(app) {
if (app instanceof App) {
app = app.getPackageName();
}
let preset = _.getAppByAlias(app);
return preset ? preset.getPackageName() : rtApp.getPackageName(String(app));
},
openAppSetting(app) {
return this.openAppSettings(app);
},
openAppSettings(app) {
if (app instanceof App) {
app = app.getPackageName();
}
let preset = _.getAppByAlias(app);
return rtApp.openAppSettings(preset ? preset.getPackageName() : app);
},
uninstall(app) {
if (app instanceof App) {
app = app.getPackageName();
}
let preset = _.getAppByAlias(app);
return rtApp.uninstall(preset ? preset.getPackageName() : app);
},
isVersionNewer(name, version) {
//// -=-= PENDING =-=- ////
},
};
Object.setPrototypeOf(App.prototype, rtApp);
return App;
})(),
protocol: {
file: 'file://',
},
/**
* @returns {Object.<App.Intent.Preset.AppAlias, string>}
*/
getPresetPackageNames() {
if (_._presetPackageNames === undefined) {
_._presetPackageNames = {};
App.values().forEach((o) => {
_._presetPackageNames[o.getAlias()] = o.getPackageName();
});
}
return _._presetPackageNames;
},
/**
* @param {string} alias
* @returns {org.autojs.autojs.util.App}
*/
getAppByAlias(alias) {
return App.getAppByAlias(String(alias));
},
toArray(arg) {
if (!Array.isArray(arg)) {
arg = [ arg ];
}
let arr = util.java.array('string', arg.length);
arg.forEach((o, i) => arr[i] = o);
return arr;
},
parseIntentFlags(flags) {
let parse = (o) => {
if (typeof o === 'string') {
return Intent[`FLAG_${o.toUpperCase()}`];
}
if (typeof o === 'number') {
return o;
}
throw TypeError(`Invalid flags: ${o}`);
};
let result = 0x0;
if (Array.isArray(flags)) {
flags.forEach(flag => result |= parse(flag));
} else {
result = parse(flags);
}
return result;
},
parseIntentAction(action) {
if (typeof action === 'string' && !action.includes('.')) {
action = `android.intent.action.${action}`;
}
return action;
},
parseIntentUrl(o) {
let __ = {
/**
* @param {Appx.Intent.URI} uri
* @return {string}
*/
parseUrlObject(uri) {
let { src, query, exclude } = uri;
if (!src || !query) {
return src;
}
let separator = src.match(/\?/) ? '&' : '?';
return src + separator + (function parse(query) {
exclude = exclude || [];
if (!Array.isArray(exclude)) {
exclude = [ exclude ];
}
return Object.keys(query).map((key) => {
let val = query[key];
if (isObjectSpecies(val)) {
val = key === 'url' ? __.parseUrlObject(val) : parse(val);
val = (key === '__webview_options__' ? '&' : '') + val;
}
if (!exclude.includes(key)) {
val = encodeURI(val);
}
return key + '=' + val;
}).join('&');
})(query);
},
};
let { url } = o;
return typeof url === 'object' ? __.parseUrlObject(url) : url;
},
/**
* @param {App.Intent.Common} intent
* @returns {string}
*/
parseClassName(intent) {
return intent.className.replace(/@\{(\w+?)}|@(\w+)/g, ($, $1, $2) => {
let key = $1 || $2;
if (key in intent) {
return intent[$1 || $2];
}
throw ReferenceError(`Intent object doesn't have a key named ${key}`);
});
},
scopeAugment() {
/**
* @type {(keyof Internal.App)[]}
*/
let methods = [ 'launchPackage', 'launch', 'launchApp', 'getPackageName', 'getAppName', 'openAppSetting', 'openAppSettings' ];
__asGlobal__(app, methods, scope);
},
};
/**
* @type {Internal.App}
*/
const app = new _.App();
_.scopeAugment();
return app;
};

View File

@@ -0,0 +1,115 @@
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { util } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Autojs}
*/
module.exports = function (scriptRuntime, scope) {
const Manifest = android.Manifest;
const BuildConfig = org.autojs.autojs6.BuildConfig;
const PackageManager = android.content.pm.PackageManager;
const RootUtils = org.autojs.autojs.util.RootUtils;
const RootMode = RootUtils.RootMode;
const Settings = android.provider.Settings;
const System = Settings.System;
let _ = {
Autojs: ( /* @IIFE */ () => {
/**
* @implements Internal.Autojs
*/
const Autojs = function () {
// Empty interface body.
};
Autojs.prototype = {
constructor: Autojs,
versionCode: BuildConfig.VERSION_CODE,
versionName: BuildConfig.VERSION_NAME,
versionDate: BuildConfig.VERSION_DATE,
version: {
code: BuildConfig.VERSION_CODE,
name: BuildConfig.VERSION_NAME,
date: BuildConfig.VERSION_DATE,
isHigherThan(otherVersion) {
return new Version(this.name).isHigherThan(otherVersion);
},
isLowerThan(otherVersion) {
return new Version(this.name).isLowerThan(otherVersion);
},
isEqual(otherVersion) {
return new Version(this.name).isEqual(otherVersion);
},
isAtLeast(otherVersion, ignoreSuffix) {
if (typeof ignoreSuffix === 'undefined') {
return new Version(this.name).isAtLeast(otherVersion);
}
return new Version(this.name).isAtLeast(otherVersion, Boolean(ignoreSuffix));
},
},
R: global.R,
name: context.getString(R.strings.app_name),
isRootAvailable() {
return RootUtils.isRootAvailable();
},
getRootMode() {
return RootUtils.getRootMode();
},
setRootMode(mode, isWriteIntoPreference) {
let isWriteIntoPref = ( /* @IIFE */ () => {
if (typeof isWriteIntoPreference === 'undefined') {
return false;
}
if (typeof isWriteIntoPreference === 'boolean') {
return isWriteIntoPreference;
}
return util.checkStringParam(isWriteIntoPreference, 'write_into_pref');
})();
if (mode === 1 || mode === true || util.checkStringParam(mode, 'root')) {
RootUtils.setRootMode(RootMode.FORCE_ROOT, isWriteIntoPref);
} else if (mode === 0 || mode === false || util.checkStringParam(mode, 'non-root')) {
RootUtils.setRootMode(RootMode.FORCE_NON_ROOT, isWriteIntoPref);
} else if (mode === -1 || util.checkStringParam(mode, 'auto')) {
RootUtils.setRootMode(RootMode.AUTO_DETECT, isWriteIntoPref);
} else {
let errPrefix = `Unknown mode (${mode}) for setRootMode()`;
if (!mode) {
throw Error(`${errPrefix}. Did you mean to use false or 0 or 'non-root' to forcibly set non-root mode?`);
} else {
throw Error(`${errPrefix}. Did you mean to use true or 1 or 'root' to forcibly set root mode?`);
}
}
},
canModifySystemSettings() {
return System.canWrite(context);
},
canWriteSecureSettings() {
return context.checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) === PackageManager.PERMISSION_GRANTED;
},
canDisplayOverOtherApps() {
return Settings.canDrawOverlays(context);
},
getLanguage() {
return org.autojs.autojs.pref.Language.getPrefLanguage().getLocale();
},
getLanguageTag() {
return this.getLanguage().toLanguageTag();
},
};
return Autojs;
})(),
};
/**
* @type {Internal.Autojs}
*/
const autojs = new _.Autojs();
return autojs;
};

View File

@@ -0,0 +1,362 @@
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { util } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Automator}
*/
module.exports = function (scriptRuntime, scope) {
const ResultAdapter = require('result-adapter');
const Path = android.graphics.Path;
const Rect = android.graphics.Rect;
const GestureDescription = android.accessibilityservice.GestureDescription;
const AccessibilityBridge = org.autojs.autojs.core.accessibility.AccessibilityBridge;
/**
* @type {org.autojs.autojs.core.accessibility.SimpleActionAutomator}
*/
const rtAutomator = scriptRuntime.automator;
/**
* @type {org.autojs.autojs.core.accessibility.AccessibilityBridge}
*/
const a11yBridge = scriptRuntime.accessibilityBridge;
let _ = {
Auto: ( /* @IIFE */ () => {
/**
* @implements Internal.Auto
*/
const Auto = function () {
return Object.assign(function (mode) {
if (typeof mode === 'string') {
auto.setMode(mode);
}
a11yBridge.ensureServiceEnabled();
}, Auto.prototype);
};
Auto.prototype = {
constructor: Auto,
get service() {
return a11yBridge.getService();
},
get windows() {
return this.service === null ? [] : util.java.toJsArray(this.service.getWindows(), true);
},
get root() {
let root = a11yBridge.getRootInCurrentWindow();
return root ? UiObject.createRoot(root) : null;
},
get rootInActiveWindow() {
let root = a11yBridge.getRootInActiveWindow();
return root ? UiObject.createRoot(root) : null;
},
get windowRoots() {
return util.java.toJsArray(a11yBridge.windowRoots(), false)
.map(root => UiObject.createRoot(root));
},
waitFor(timeout) {
automator.waitForService(timeout);
},
setMode(modeStr) {
if (typeof modeStr !== 'string') {
throw TypeError('Mode should be a string for auto.setMode()');
}
let mode = _.modes[modeStr];
if (mode === undefined) {
throw Error(`Unknown mode for auto.setMode(): ${modeStr}`);
}
a11yBridge.setMode(mode);
},
setFlags(flags) {
let flagStrings;
if (Array.isArray(flags)) {
flagStrings = flags;
} else if (typeof flags === 'string') {
flagStrings = [ flags ];
} else {
throw TypeError(`Unknown flags: ${flags}`);
}
let flagsInt = 0;
flagStrings.forEach((s) => {
let flag = _.flagsMap[s];
if (flag === undefined) {
throw Error(`Unknown flag for auto.setFlags(): ${flag}`);
}
flagsInt |= flag;
});
a11yBridge.setFlags(flagsInt);
},
setWindowFilter(filter) {
a11yBridge.setWindowFilter(new AccessibilityBridge.WindowFilter({ filter }));
},
};
return Auto;
})(),
Automator: ( /* @IIFE */ () => {
/**
* @implements Internal.Automator
*/
const Automator = function () {
};
Automator.prototype = {
constructor: Automator,
press(x, y, delay) {
return rtAutomator.press(x, y, delay);
},
gesture(duration, points) {
return rtAutomator.gesture.apply(rtAutomator, [ 0 ].concat(Array.from(arguments)));
},
gestureAsync(duration, points) {
return rtAutomator.gestureAsync.apply(rtAutomator, [ 0 ].concat(Array.from(arguments)));
},
swipe(x1, y1, x2, y2, delay) {
return rtAutomator.swipe(x1, y1, x2, y2, delay);
},
isServiceRunning() {
return rtAutomator.isServiceRunning();
},
ensureService() {
rtAutomator.ensureService();
},
waitForService(timeout) {
a11yBridge.waitForServiceEnabled(_.parseNumber(timeout, -1));
},
click() {
if (arguments.length === 2) {
let [ x, y ] = arguments;
if (typeof x === 'number' && typeof y === 'number') {
return rtAutomator.click(x, y);
}
}
let target = arguments[0];
if (target instanceof Rect) {
return this.click(target.centerX(), target.centerY());
}
if (target instanceof UiObject) {
return target.clickable() ? target.click() : this.click(target.bounds());
}
return _.performAction(function (target) {
return rtAutomator.click(target);
}, arguments);
},
longClick() {
if (arguments.length === 2) {
let [ x, y ] = arguments;
if (typeof x === 'number' && typeof y === 'number') {
return rtAutomator.longClick(x, y);
}
}
return _.performAction(function (target) {
return rtAutomator.longClick(target);
}, arguments);
},
input() {
if (arguments.length === 2) {
let [ index, text ] = arguments;
return rtAutomator.appendText(rtAutomator.editable(index), text);
} else {
let [ text ] = arguments;
return rtAutomator.appendText(rtAutomator.editable(-1), text);
}
},
gestures() {
return rtAutomator.gestures(_.toStrokes(arguments));
},
gesturesAsync() {
rtAutomator.gesturesAsync(_.toStrokes(arguments));
},
scrollDown(index) {
if (typeof index === 'number') {
return rtAutomator.scrollForward(index);
}
if (arguments.length === 0) {
return rtAutomator.scrollMaxForward();
}
// @Comment by SuperMonster003 on Apr 20, 2022.
// ! Method runtime.automator.scrollForward() should be invoked with number rather than ActionTarget.
// ! Thus, there is a strong possibility that performAction() won't work properly as expected.
// return _.performAction(function (target) {
// return runtime.automator.scrollForward(target);
// }, arguments);
},
scrollUp(index) {
if (typeof index === 'number') {
return rtAutomator.scrollBackward(index);
}
if (arguments.length === 0) {
return rtAutomator.scrollMaxBackward();
}
// @Comment by SuperMonster003 on Apr 20, 2022.
// ! Method runtime.automator.scrollBackward() should be invoked with number rather than ActionTarget.
// ! Thus, there is a strong possibility that performAction() won't work properly as expected.
// return _.performAction(function (target) {
// return runtime.automator.scrollBackward(target);
// }, arguments);
},
setText() {
if (arguments.length === 2) {
let [ index, text ] = arguments;
return rtAutomator.setText(rtAutomator.editable(index), text);
} else {
let [ text ] = arguments;
return rtAutomator.setText(rtAutomator.editable(-1), text);
}
},
captureScreen() {
return ResultAdapter.wait(rtAutomator.captureScreen());
},
lockScreen() {
return rtAutomator.lockScreen();
},
takeScreenshot() {
return rtAutomator.takeScreenshot();
},
headsethook() {
return rtAutomator.headsethook();
},
accessibilityButton() {
return rtAutomator.accessibilityButton();
},
accessibilityButtonChooser() {
return rtAutomator.accessibilityButtonChooser();
},
accessibilityShortcut() {
return rtAutomator.accessibilityShortcut();
},
accessibilityAllApps() {
return rtAutomator.accessibilityAllApps();
},
dismissNotificationShade() {
return rtAutomator.dismissNotificationShade();
},
};
return Automator;
})(),
modes: {
normal: AccessibilityBridge.MODE_NORMAL,
fast: AccessibilityBridge.MODE_FAST,
},
flagsMap: {
findOnUiThread: AccessibilityBridge.FLAG_FIND_ON_UI_THREAD,
useUsageStats: AccessibilityBridge.FLAG_USE_USAGE_STATS,
useShell: AccessibilityBridge.FLAG_USE_SHELL,
},
/**
* @template {boolean} T
* @param {(target: org.autojs.autojs.core.automator.action.ActionTarget) => T} action
* @param {IArguments} args
* @return {T}
*/
performAction(action, args) {
if (args.length === 4) {
let [ left, top, right, bottom ] = args;
return action(rtAutomator.bounds(left, top, right, bottom));
}
if (args.length === 2) {
let [ text, index ] = args;
return action(rtAutomator.text(text, index));
}
let [ text ] = args;
return action(rtAutomator.text(text, -1));
},
toStrokes(argsList) {
let screenMetrics = scriptRuntime.getScreenMetrics();
let strokes = java.lang.reflect.Array.newInstance(GestureDescription.StrokeDescription, argsList.length);
for (let i = 0; i < argsList.length; i += 1) {
let args = argsList[i];
let startTime, durationIndex, pointsIndex;
if (typeof args[1] /* duration */ === 'number') {
/* arguments: [startTime, duration, points[]] */
startTime = args[0];
durationIndex = 1;
pointsIndex = 2;
} else {
/* arguments: [duration, points[]] */
startTime = 0; // default value
durationIndex = 0;
pointsIndex = 1;
}
let path = new Path();
let [ x, y ] = args[pointsIndex];
path.moveTo(screenMetrics.scaleX(x), screenMetrics.scaleY(y));
for (let j = pointsIndex + 1; j < args.length; j += 1) {
let [ x, y ] = args[j];
path.lineTo(screenMetrics.scaleX(x), screenMetrics.scaleY(y));
}
strokes[i] = new GestureDescription.StrokeDescription(path, startTime, args[durationIndex]);
}
return strokes;
},
/**
* @param {any} num
* @param {number|function():number} [def=0]
* @returns {number}
*/
parseNumber(num, def) {
return typeof num === 'number' ? num : typeof def === 'function' ? def() : def || 0;
},
scopeAugment() {
/**
* @type {(keyof Internal.Automator)[]}
*/
let methods = [
'click', 'longClick', 'press', 'swipe',
'gesture', 'gestures', 'gestureAsync', 'gesturesAsync',
'scrollDown', 'scrollUp', 'input', 'setText',
];
__asGlobal__(automator, methods, scope);
/**
* @type {(keyof org.autojs.autojs.core.accessibility.SimpleActionAutomator)[]}
*/
let methodsRt = [
'back', 'home', 'powerDialog', 'notifications',
'quickSettings', 'recents', 'splitScreen',
];
__asGlobal__(rtAutomator, methodsRt);
/**
* @Caution by SuperMonster003 on Apr 23, 2022.
* Use 'bind' or 'assign' will lose appended properties.
*
* @example
* let f = function () {}; f.code = 1;
* let g = f; console.log(g.code); // 1
* let h = f.bind({}); console.log(h.code); // undefined
* let o = {}; Object.assign(o, {f}); console.log(o.code); // undefined
*/
scope.auto = auto;
},
};
/**
* @type {Internal.Auto}
*/
const auto = new _.Auto();
/**
* @type {Internal.Automator}
*/
const automator = new _.Automator();
_.scopeAugment();
return automator;
};

View File

@@ -0,0 +1,65 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Base64}
*/
module.exports = function (scriptRuntime, scope) {
const Base64 = android.util.Base64;
const JavaString = java.lang.String;
const StandardCharsets = java.nio.charset.StandardCharsets;
let _ = {
Base64Ctor: ( /* @IIFE */ () => {
/**
* @implements Internal.Base64
*/
const Base64Ctor = function () {
// Empty interface body.
};
Base64Ctor.prototype = {
constructor: Base64Ctor,
/**
* @param str
* @param {string} encoding
* @return {string}
*/
encode(str, encoding) {
// noinspection JSValidateTypes
/**
* @type {java.lang.String}
*/
let string = new JavaString(str);
return _.isValidEncoding(encoding)
? Base64.encodeToString(string.getBytes(encoding), Base64.NO_WRAP)
: Base64.encodeToString(string.getBytes(), Base64.NO_WRAP);
},
decode(str, encoding) {
// noinspection JSValidateTypes
return _.isValidEncoding(encoding)
? String(new JavaString(Base64.decode(str, Base64.NO_WRAP), encoding))
: String(new JavaString(Base64.decode(str, Base64.NO_WRAP)));
},
};
return Base64Ctor;
})(),
isValidEncoding: (encode) => [
StandardCharsets.US_ASCII,
StandardCharsets.ISO_8859_1,
StandardCharsets.UTF_8,
StandardCharsets.UTF_16BE,
StandardCharsets.UTF_16LE,
StandardCharsets.UTF_16,
].map((javaCharset) => {
return javaCharset.name().toLowerCase();
}).includes(String(encode).toLowerCase()),
};
/**
* @type {Internal.Base64}
*/
const base64 = new _.Base64Ctor();
return base64;
};

View File

@@ -0,0 +1,42 @@
( /* @ModuleIIFE */ () => {
let _ = {
unwrapIfNeeded(o) {
return isJavaObject(o) ? unwrapJavaObject(o) : o;
},
};
module.exports = {
toArray(iterable) {
let iterator = iterable.iterator();
let arr = [];
while (iterator.hasNext()) {
arr.push(iterator.next());
}
return arr;
},
asArray(list) {
let arr = [];
for (let i = 0; i < list.size(); i += 1) {
arr.push(list.get(i));
}
for (let key in list) {
if (typeof key !== 'number') {
let v = list[key];
arr[key] = typeof v === 'function' ? v.bind(list) : v;
}
}
return arr;
},
toString(o) {
return String(o);
},
call(func, target, args) {
return func.apply(target, args.map(_.unwrapIfNeeded));
},
toPrimitive(o) {
return _.unwrapIfNeeded(o);
},
};
})();

View File

@@ -0,0 +1,170 @@
/* Overwritten protection. */
let { files, util } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Console}
*/
module.exports = function (scriptRuntime, scope) {
const Log = android.util.Log;
const Level = org.apache.log4j.Level;
const ConsoleUtils = org.autojs.autojs.util.ConsoleUtils;
const LogConfigurator = de.mindpipe.android.logging.log4j.LogConfigurator;
const rtConsole = scriptRuntime.console;
let _ = {
Console: ( /* @IIFE */ () => {
/**
* @extends Internal.Console
*/
const Console = function () {
// Empty interface body.
};
Console.prototype = {
constructor: Console,
trace: function captureStack(message, level) {
let target = {};
Error.captureStackTrace(target, captureStack);
if (typeof level === 'string') {
level = level.toUpperCase();
}
let msg = `${util.format(message)}\n${target.stack}`;
switch (level) {
case Log.VERBOSE:
case 'VERBOSE':
console.verbose(msg);
break;
case Log.DEBUG:
case 'DEBUG':
console.log(msg);
break;
case Log.INFO:
case 'INFO':
console.info(msg);
break;
case Log.WARN:
case 'WARN':
console.warn(msg);
break;
case Log.ERROR:
case 'ERROR':
console.error(msg);
break;
default:
console.log(msg);
}
},
assert(value, message) {
rtConsole.assertTrue(
Boolean(typeof value === 'function' ? value() : value),
message || util.getClassName(java.lang.AssertionError));
},
input(data, param) {
return eval(String(this.rawInput(data, param)));
},
log() {
rtConsole.log(util.format.apply(util, arguments));
},
verbose() {
rtConsole.verbose(util.format.apply(util, arguments));
},
print() {
rtConsole.print(Log.DEBUG, util.format.apply(util, arguments));
},
info() {
rtConsole.info(util.format.apply(util, arguments));
},
warn() {
rtConsole.warn(util.format.apply(util, arguments));
},
error() {
rtConsole.error(util.format.apply(util, arguments));
},
time(label) {
_.timeTable.save(label);
},
timeEnd(label) {
_.timeTable.loadAndLog(label);
},
setGlobalLogConfig(config) {
let configurator = new LogConfigurator();
if (config.file) {
configurator.setFileName(files.path(config.file));
configurator.setUseFileAppender(true);
}
configurator.setFilePattern(_.parseOption(config.filePattern, '%m%n'));
configurator.setMaxFileSize(_.parseOption(config.maxFileSize, 512 * 1024));
configurator.setImmediateFlush(_.parseOption(config.immediateFlush, true));
configurator.setRootLevel(Level[_.parseOption(config.rootLevel, 'ALL').toUpperCase()]);
configurator.setMaxBackupSize(_.parseOption(config.maxBackupSize, 5));
configurator.setResetConfiguration(_.parseOption(config.resetConfiguration, true));
configurator.configure();
},
launch() {
ConsoleUtils.launch();
},
};
Object.keys(rtConsole).forEach((key) => {
if (!Console.prototype.hasOwnProperty(key)) {
if (typeof rtConsole[key] === 'function') {
Console.prototype[key] = rtConsole[key].bind(rtConsole);
} else {
Console.prototype[key] = rtConsole[key];
}
}
});
return Console;
})(),
timeTable: {
data: {},
default: 'default',
uptimeMillis() {
return android.os.SystemClock.uptimeMillis();
},
parseLabel(label) {
return label || this.default;
},
save(label) {
this.data[this.parseLabel(label)] = this.uptimeMillis();
},
load(label) {
return this.data[this.parseLabel(label)];
},
remove(label) {
delete this.data[this.parseLabel(label)];
},
log(label, text) {
console.log(`${this.parseLabel(label)}: ${text}ms`);
},
loadAndLog(label) {
let text = this.uptimeMillis() - this.load(label);
this.remove(label);
this.log(label, text);
},
},
parseOption(value, def) {
return value === undefined ? def : value;
},
scopeAugment() {
__asGlobal__(console, [
'verbose', 'print', 'log', 'warn', { err: 'error' },
{ openConsole: 'show' }, { clearConsole: 'clear' }, { launchConsole: 'launch' },
]);
},
};
/**
* @type {Internal.Console}
*/
const console = new _.Console();
_.scopeAugment();
return console;
};

View File

@@ -0,0 +1,121 @@
/* Overwritten protection. */
let { engines, global: _global } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Continuation}
*/
module.exports = function (scriptRuntime, scope) {
// @Caution by SuperMonster003 on Apr 19, 2022.
// ! Do not declare globally because variable Continuation which
// ! extends org.mozilla.javascript.NativeContinuation has already declared.
const Result = org.autojs.autojs.rhino.continuation.Continuation.Result;
let _ = {
Creator: ( /* @IIFE */ () => {
/**
* @extends Internal.Continuation.Creator
*/
const Creator = function (scope) {
this.cont = Object.create(scriptRuntime.createContinuation(scope || _global));
};
Creator.prototype = {
constructor: Creator,
await() {
/**
* @Caution by SuperMonster003 on Apr 19, 2022.
* Continuation without "continuation feature" will cause an exception
* which makes all invocations failed and interrupted here.
*
* @example Exception snippet
* Wrapped java.lang.IllegalStateException:
* Cannot capture continuation from JavaScript code not called directly
* by executeScriptWithContinuations or callFunctionWithContinuations
*
* @example Code for reappearance
* engines.myEngine().hasFeature('continuation'); // false
* Object.create(runtime.createContinuation()).suspend(); // throw error
*/
let result = this.cont.suspend();
if (result.error !== null) {
throw result.error;
}
return result.result;
},
resumeError(error) {
if (isNullish(error)) {
throw TypeError('Error is null or undefined');
}
this.cont.resumeWith(Result.failure(error));
},
resume(result) {
this.cont.resumeWith(Result.success(result));
},
};
return Creator;
})(),
Continuation: ( /* @IIFE */ () => {
/**
* @implements Internal.Continuation
*/
const Continuation = function () {
return Object.assign(function () {
// Empty interface body.
}, Continuation.prototype);
};
Continuation.prototype = {
constructor: Continuation,
get enabled() {
return engines.myEngine().hasFeature('continuation');
},
create(scope) {
return new _.Creator(scope);
},
await(promise) {
const cont = this.create(scope);
promise
.then(result => cont.resume(result))
.catch(error => cont.resumeError(error));
return cont.await();
},
delay(millis) {
const cont = this.create(scope);
setTimeout(() => cont.resume(), millis);
cont.await();
},
};
return Continuation;
})(),
promiseAugment() {
/**
* @implements Internal.Continuation.PromiseExtension
*/
const PromiseExtension = function () {
// Empty interface body.
};
Object.assign(PromiseExtension.prototype, {
await() {
return continuation.await(this);
},
});
Object.assign(Promise.prototype, PromiseExtension.prototype);
},
};
/**
* @type {Internal.Continuation}
*/
const continuation = new _.Continuation();
_.promiseAugment();
return continuation;
};

View File

@@ -0,0 +1,95 @@
/* Overwritten protection. */
let { util } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Device}
*/
module.exports = function (scriptRuntime, scope) {
const ScreenMetrics = org.autojs.autojs.runtime.api.ScreenMetrics;
const NetworkUtils = org.autojs.autojs.util.NetworkUtils;
const DeviceUtils = org.autojs.autojs.util.DeviceUtils;
const rtDevice = scriptRuntime.device;
let _ = {
Device: ( /* @IIFE */ () => {
/**
* @extends Internal.Device
*/
const Device = function () {
// Empty interface body.
};
Device.prototype = {
constructor: Device,
get width() {
return ScreenMetrics.getDeviceScreenWidth();
},
get height() {
return ScreenMetrics.getDeviceScreenHeight();
},
get rotation() {
return ScreenMetrics.getRotation();
},
get density() {
return ScreenMetrics.getDeviceScreenDensity();
},
get summary() {
return DeviceUtils.getDeviceSummary(context);
},
get digest() {
let digestList = [
`${this.brand}${this.manufacturer === this.brand ? `` : ` (${this.manufacturer})`}`,
`${this.device}${this.model === this.device ? `` : ` (${this.model})`}`,
`${this.release} (${this.sdkInt})`,
];
return digestList.join(' / ');
},
vibrate(off, millis) {
if (typeof arguments[0] === 'string') {
util.morseCode.vibrate.apply(util.morseCode, arguments);
} else {
rtDevice.vibrate.apply(rtDevice, arguments);
}
},
isScreenOff() {
return !rtDevice.isScreenOn();
},
getIpAddress(useIPv4) {
return useIPv4 === undefined
? NetworkUtils.getIpAddress()
: NetworkUtils.getIpAddress(useIPv4);
},
getIpv6Address() {
return NetworkUtils.getIpv6Address();
},
getGatewayAddress() {
return NetworkUtils.getGatewayAddress();
},
isActiveNetworkMetered() {
return NetworkUtils.isActiveNetworkMetered();
},
isConnectedOrConnecting() {
return NetworkUtils.isConnectedOrConnecting();
},
isWifiAvailable() {
return NetworkUtils.isWifiAvailable();
},
};
Object.setPrototypeOf(Device.prototype, rtDevice);
return Device;
})(),
};
/**
* @type {Internal.Device}
*/
const device = new _.Device();
return device;
};

View File

@@ -0,0 +1,419 @@
/* Overwritten protection. */
let { colors, threads, ui } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Dialogs}
*/
module.exports = function (scriptRuntime, scope) {
const Looper = android.os.Looper;
const Linkify = android.text.util.Linkify;
const LayoutParams = android.view.WindowManager.LayoutParams;
const ColorDrawable = android.graphics.drawable.ColorDrawable;
let _ = {
Dialogs: ( /* @IIFE */ () => {
/**
* @implements Internal.Dialogs
*/
const Dialogs = function () {
// Empty interface body.
};
Dialogs.prototype = {
constructor: Dialogs,
build(properties) {
/**
* @type {Dialogs.Builder}
*/
let builder = Object.create(scriptRuntime.dialogs.newBuilder(), {
thread: { value: threads.currentThread() },
});
Object.keys(properties).forEach((name) => {
_.applyDialogProperty(builder, name, properties[name]);
});
_.applyOtherDialogProperties(builder, properties);
let dialog = ui.run(() => builder.buildDialog());
_.applyBuiltDialogProperties(dialog, properties);
return dialog;
},
rawInput(title, prefill, callback) {
if (typeof prefill === 'function') {
return this.rawInput(title, /* prefill = */ null, /* callback = */ prefill);
}
if (_.isUiThread() && !callback) {
return new Promise((resolve) => {
_.rtDialogs.rawInput(title, prefill || '', function () {
resolve.apply(null, arguments);
});
});
}
return _.rtDialogs.rawInput(title, prefill || '', callback || null);
},
input(title, prefill, callback) {
if (typeof prefill === 'function') {
return this.input(title, /* prefill = */ null, /* callback = */ prefill);
}
if (_.isUiThread() && !callback) {
return new Promise((resolve) => {
_.rtDialogs.rawInput(title, prefill || '', function (str) {
resolve(eval(str));
});
});
}
if (!callback) {
return eval(String(this.rawInput(title, prefill)));
}
this.rawInput(title, prefill, str => callback(eval(str)));
},
prompt(title, prefill, callback) {
if (typeof prefill === 'function') {
return this.prompt(title, /* prefill = */ null, /* callback = */ prefill);
}
return this.rawInput(title, prefill, callback);
},
alert(title, prefill, callback) {
if (typeof prefill === 'function') {
return this.alert(title, /* prefill = */ null, /* callback = */ prefill);
}
if (_.isUiThread() && !callback) {
return new Promise((resolve) => {
_.rtDialogs.alert(title, prefill || '', function () {
resolve.apply(null, arguments);
});
});
}
return _.rtDialogs.alert(title, prefill || '', callback || null);
},
confirm(title, prefill, callback) {
if (typeof prefill === 'function') {
return this.confirm(title, /* prefill = */ null, /* callback = */ prefill);
}
if (_.isUiThread() && !callback) {
return new Promise((resolve) => {
_.rtDialogs.confirm(title, prefill || '', function () {
resolve.apply(null, arguments);
});
});
}
return _.rtDialogs.confirm(title, prefill || '', callback || null);
},
select(title, items, callback) {
if (Array.isArray(items)) {
if (_.isUiThread() && !callback) {
return new Promise((resolve) => {
_.rtDialogs.select(title, items, function () {
resolve.apply(null, arguments);
});
});
}
return _.rtDialogs.select(title, items, callback || null);
}
let itemsGatheredFromArguments = Array.from(arguments).slice(1);
return _.rtDialogs.select(title, itemsGatheredFromArguments, null);
},
singleChoice(title, items, index, callback) {
if (_.isUiThread() && !callback) {
return new Promise((resolve) => {
_.rtDialogs.singleChoice(title, index || 0, items, function () {
resolve.apply(null, arguments);
});
});
}
return _.rtDialogs.singleChoice(title, index || 0, items, callback || null);
},
multiChoice(title, items, index, callback) {
index = index || [];
if (_.isUiThread() && !callback) {
return new Promise((resolve) => {
_.rtDialogs.multiChoice(title, index, items, function (r) {
resolve(_.toJsArray(r));
});
});
}
if (callback) {
return _.toJsArray(_.rtDialogs.multiChoice(title, index, items, function (r) {
callback(_.toJsArray(r));
}));
}
return _.toJsArray(_.rtDialogs.multiChoice(title, index, items, null));
},
};
return Dialogs;
})(),
propertySetters: {
title: null,
titleColor: { adapter: colors.toInt.bind(colors) },
buttonRippleColor: { adapter: colors.toInt.bind(colors) },
icon: null,
content: null,
contentColor: { adapter: colors.toInt.bind(colors) },
contentLineSpacing: null,
items: null,
itemsColor: { adapter: colors.toInt.bind(colors) },
positive: { method: 'positiveText' },
positiveColor: { adapter: colors.toInt.bind(colors) },
neutral: { method: 'neutralText' },
neutralColor: { adapter: colors.toInt.bind(colors) },
negative: { method: 'negativeText' },
negativeColor: { adapter: colors.toInt.bind(colors) },
cancelable: null,
canceledOnTouchOutside: null,
autoDismiss: null,
limitIconToDefaultSize: undefined,
},
linkifyMask: [ 'all', 'emailAddresses', 'mapAddresses', 'phoneNumbers', 'webUrls' ],
animation: [ 'default', 'activity', 'dialog', 'inputMethod', 'toast', 'translucent' ],
/**
* @type {org.autojs.autojs.runtime.api.Dialogs|org.autojs.autojs.runtime.api.Dialogs.NonUiDialogs|*}
*/
get rtDialogs() {
if (_._rtDialogs === undefined) {
_._rtDialogs = _.isUiThread()
? scriptRuntime.dialogs
: scriptRuntime.dialogs.nonUiDialogs;
}
return _._rtDialogs;
},
applyDialogProperty(builder, name, value) {
if (_.propertySetters.hasOwnProperty(name)) {
let propertySetter = _.propertySetters[name];
if (isObjectSpecies(propertySetter)) {
if (propertySetter.method === undefined) {
propertySetter.method = name;
}
if (propertySetter.adapter) {
value = propertySetter.adapter(value);
}
builder[propertySetter.method](value);
} else {
if (propertySetter === undefined) {
value === true && builder[name]();
} else {
builder[name](value);
}
}
}
},
/**
* @param {Dialogs.Builder} builder
* @param {Dialogs.Build.Properties} props
*/
applyOtherDialogProperties(builder, props) {
if (props.inputHint !== undefined || props.inputPrefill !== undefined) {
let inputHint = _.wrapNonNullString(props.inputHint);
let inputPrefill = _.wrapNonNullString(props.inputPrefill);
builder.input(inputHint, inputPrefill, (dialog, input) => {
return builder.emit('input_change', builder.getDialog(), String(input));
}).alwaysCallInputCallback();
}
if (props.items !== undefined) {
let itemsSelectMode = props.itemsSelectMode;
if (itemsSelectMode === undefined || itemsSelectMode === 'select') {
builder.itemsCallback((dialog, view, position, text) => {
builder.emit('item_select', position, text.toString(), builder.getDialog());
});
} else if (itemsSelectMode === 'single') {
let selectedIndex = props.itemsSelectedIndex === undefined ? -1 : props.itemsSelectedIndex;
builder.itemsCallbackSingleChoice(selectedIndex, (dialog, view, which, text) => {
builder.emit('single_choice', which, text.toString(), builder.getDialog());
return true;
});
} else if (itemsSelectMode === 'multi') {
let selectedIndices = props.itemsSelectedIndices !== undefined
? Array.isArray(props.itemsSelectedIndices)
? props.itemsSelectedIndices
: [ props.itemsSelectedIndices ]
: props.itemsSelectedIndex === undefined ? []
: Array.isArray(props.itemsSelectedIndex)
? props.itemsSelectedIndex
: [ props.itemsSelectedIndex ];
builder.itemsCallbackMultiChoice(selectedIndices, (dialog, indices, texts) => {
builder.emit('multi_choice',
_.toJsArray(indices, (l, i) => parseInt(l[i])),
_.toJsArray(texts, (l, i) => l[i].toString()),
builder.getDialog());
return true;
});
} else {
throw Error(`Unknown itemsSelectMode ${itemsSelectMode}`);
}
}
if (props.progress !== undefined) {
let { progress } = props;
let isIndeterminate = progress.max === -1;
builder.progress(isIndeterminate, progress.max, Boolean(progress.showMinMax));
builder.progressIndeterminateStyle(Boolean(progress.horizontal));
}
if (props.checkBoxPrompt !== undefined || props.checkBoxChecked !== undefined) {
builder.checkBoxPrompt(_.wrapNonNullString(props.checkBoxPrompt),
Boolean(props.checkBoxChecked),
(view, checked) => builder.getDialog().emit('check', checked, builder.getDialog()));
}
if (props.customView !== undefined) {
let customView = props.customView;
// noinspection JSTypeOfValues
if (typeof customView === 'xml' || typeof customView === 'string') {
customView = ui.run(() => ui.inflate(customView));
}
let wrapInScrollView = props.wrapInScrollView === undefined || Boolean(props.wrapInScrollView);
builder.customView(customView, wrapInScrollView);
}
if (props.stubborn) {
let isOperationAvail = prop => prop === undefined || Boolean(prop) !== true;
if (isOperationAvail(props.autoDismiss) && isOperationAvail(props.canceledOnTouchOutside)) {
builder.autoDismiss(false);
builder.canceledOnTouchOutside(false);
}
}
},
/**
*
* @param {org.autojs.autojs.core.ui.dialog.JsDialog} dialog
* @param {Dialogs.Build.Properties} props
*/
applyBuiltDialogProperties(dialog, props) {
if (props.linkify !== undefined && Boolean(props.linkify) !== false) {
let linkify = ( /* @IIFE */ () => {
let linkify = typeof props.linkify === 'string' ? props.linkify : 'all';
if (_.linkifyMask.includes(linkify)) {
linkify = linkify.replace(/[A-Z]/g, '_$&').toUpperCase();
}
if (linkify in Linkify) {
return Linkify[linkify];
}
throw Error(`Unknown linkify: ${props.linkify}`);
})();
let view = dialog.getContentView();
let text = view.getText().toString();
ui.run(() => {
view.setAutoLinkMask(linkify);
view.setText(text);
});
}
if (props.onBackKey !== undefined) {
let isFunction = typeof props.onBackKey === 'function';
let isDisabled = Boolean(props.onBackKey) === false
|| String(props.onBackKey).match(/^disabled?$/i);
if (isDisabled || isFunction) {
dialog.setOnKeyListener({
onKey(dialogInterface, keyCode, event) {
if (event.getAction() !== KeyEvent.ACTION_UP || keyCode !== KeyEvent.KEYCODE_BACK) {
return false;
}
if (isFunction) {
props.onBackKey(dialog);
}
return true;
},
});
}
}
if (props.dimAmount !== undefined) {
let dim = Number(props.dimAmount);
while (dim > 1) {
dim /= 100;
}
if (!isNaN(dim)) {
ui.post(() => dialog.getWindow().setDimAmount(dim));
}
}
if (props.background !== undefined) {
let bg = props.background;
let win = dialog.getWindow();
ui.post(() => {
if (typeof bg === 'string') {
bg.startsWith('#')
? win.setBackgroundDrawable(new ColorDrawable(colors.toInt(bg)))
: win.setBackgroundDrawableResource(android.R.color[bg]);
} else if (typeof bg === 'number') {
win.setBackgroundDrawable(new ColorDrawable(bg));
} else {
throw TypeError(`Unknown type of background property: ${props.background}`);
}
});
}
if (props.animation !== undefined && Boolean(props.animation) !== false) {
let animation = typeof props.animation === 'string' ? props.animation : 'default';
if (!_.animation.includes(animation)) {
throw Error(`Unknown linkify: ${props.animation}`);
}
ui.post(() => {
let win = dialog.getWindow();
if (animation === 'default') {
win.setWindowAnimations(android.R.style.Animation);
} else {
let suffix = animation[0].toUpperCase() + animation.slice(1);
win.setWindowAnimations(android.R.style[`Animation_${suffix}`]);
}
});
}
if (props.keepScreenOn) {
ui.post(() => {
let win = dialog.getWindow();
win.addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
});
}
},
wrapNonNullString(str) {
return isNullish(str) ? '' : String(str);
},
toJsArray(javaArray, adapter) {
let jsArray = [];
if (typeof adapter === 'function') {
for (let i = 0; i < javaArray.length; i += 1) {
jsArray.push(adapter(javaArray, i));
}
} else {
for (let i = 0; i < javaArray.length; i += 1) {
jsArray.push(javaArray[i]);
}
}
return jsArray;
},
isUiThread() {
return Looper.myLooper() === Looper.getMainLooper();
},
parseColor(c) {
if (typeof c === 'string') {
return colors.parseColor(c);
}
return c;
},
scopeAugment() {
/**
* @type {(keyof Internal.Dialogs)[]}
*/
let methods = [ 'rawInput', 'alert', 'confirm', 'prompt' ];
__asGlobal__(dialogs, methods);
},
};
/**
* @type {Internal.Dialogs}
*/
let dialogs = new _.Dialogs();
_.scopeAugment();
return dialogs;
};

View File

@@ -0,0 +1,92 @@
/* Overwritten protection. */
let { files } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Engines}
*/
module.exports = function (scriptRuntime, scope) {
const ExecutionConfig = org.autojs.autojs.execution.ExecutionConfig;
const rtEngines = scriptRuntime.engines;
let _ = {
Engines: ( /* @IIFE */ () => {
/**
* @extends Internal.Engines
*/
const Engines = function () {
// Empty class body.
};
Engines.prototype = {
constructor: Engines,
all() {
return rtEngines.all();
},
myEngine() {
return rtEngines.myEngine();
},
stopAll() {
return rtEngines.stopAll();
},
stopAllAndToast() {
rtEngines.stopAllAndToast();
},
execScript(name, script, config) {
return rtEngines.execScript(name, script, _.fillConfig(config));
},
execScriptFile(path, config) {
return rtEngines.execScriptFile(path, _.fillConfig(config));
},
execAutoFile(path, config) {
return rtEngines.execAutoFile(path, _.fillConfig(config));
},
};
return Engines;
})(),
/**
* @param {Internal.Engines.ExecutionConfig | org.autojs.autojs.execution.ExecutionConfig} config
* @return {org.autojs.autojs.execution.ExecutionConfig}
*/
fillConfig(config) {
let executionConfig = new ExecutionConfig();
let c = config || {};
executionConfig.setWorkingDirectory(c.path || files.cwd());
executionConfig.setDelay(c.delay || 0);
executionConfig.setInterval(c.interval || 0);
executionConfig.setLoopTimes(typeof c.loopTimes === 'number' ? c.loopTimes : 1);
Object.entries(c.arguments || []).forEach((value) => {
let [ k, v ] = value;
executionConfig.setArgument(k, v);
});
return executionConfig;
},
setEngineExecArgv() {
engines.myEngine().setExecArgv( /* @IIFE */ ((e) => {
let execArgv = {};
let iterator = e.getTag(ExecutionConfig.CREATOR.getTag()).arguments.entrySet().iterator();
while (iterator.hasNext()) {
let entry = iterator.next();
execArgv[entry.getKey()] = entry.getValue();
}
return execArgv;
})(engines.myEngine()));
},
};
/**
* @type {Internal.Engines}
*/
let engines = new _.Engines();
_.setEngineExecArgv();
return engines;
};

View File

@@ -0,0 +1,69 @@
// noinspection JSUnusedGlobalSymbols
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Events}
*/
module.exports = function (scriptRuntime, scope) {
let _ = {
Events: ( /* @IIFE */ () => {
/**
* @extends Internal.Events
*/
const Events = function () {
// Empty class body.
};
Events.prototype = {
constructor: Events,
__asEmitter__(obj, thread) {
let emitter = thread ? this.emitter(thread) : this.emitter();
for (let key in emitter) {
if (obj[key] === undefined && typeof emitter[key] === 'function') {
obj[key] = emitter[key].bind(emitter);
}
}
return obj;
},
};
Object.setPrototypeOf(Events.prototype, scriptRuntime.events);
return Events;
})(),
Keys: ( /* @IIFE */ () => {
/**
* @implements Internal.Keys
*/
const Keys = function () {
// Empty interface body.
};
Keys.prototype = {
constructor: Keys,
home: KeyEvent.KEYCODE_HOME,
menu: KeyEvent.KEYCODE_MENU,
back: KeyEvent.KEYCODE_BACK,
volume_up: KeyEvent.KEYCODE_VOLUME_UP,
volume_down: KeyEvent.KEYCODE_VOLUME_DOWN,
};
return Keys;
})(),
scopeAugment() {
Object.assign(scope, {
keys: new _.Keys(),
});
},
};
/**
* @type {Internal.Events}
*/
const events = new _.Events();
_.scopeAugment();
return events;
};

View File

@@ -0,0 +1,47 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Files}
*/
module.exports = function (scriptRuntime, scope) {
const RtFiles = org.autojs.autojs.runtime.api.Files;
let _ = {
Files: ( /* @IIFE */ () => {
/**
* @extends Internal.Files
*/
const Files = function () {
// Empty class body.
};
Files.prototype = {
constructor: Files,
join(parent, children) {
return RtFiles.join.apply(RtFiles, arguments);
},
};
Object.setPrototypeOf(Files.prototype, scriptRuntime.files);
return Files;
})(),
scopeAugment() {
Object.assign(scope, {
/** @global */
open(path, mode, encoding, bufferSize) {
return files.open.apply(files, arguments);
},
});
},
};
/**
* @type {Internal.Files}
*/
const files = new _.Files();
_.scopeAugment();
return files;
};

View File

@@ -0,0 +1,80 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Floaty}
*/
module.exports = function (scriptRuntime, scope) {
const ProxyJavaObject = org.autojs.autojs.rhino.ProxyJavaObject;
const rtFloaty = scriptRuntime.floaty;
let _ = {
Floaty: ( /* @IIFE */ () => {
/**
* @implements Internal.Floaty
*/
const Floaty = function () {
// Empty interface body.
};
Floaty.prototype = {
constructor: Floaty,
closeAll() {
rtFloaty.closeAll();
},
window(xml) {
return _.wrap(rtFloaty.window.bind(rtFloaty), xml);
},
rawWindow(xml) {
return _.wrap(rtFloaty.rawWindow.bind(rtFloaty), xml);
},
};
return Floaty;
})(),
toXMLStringIfNeeded(xml) {
// noinspection JSTypeOfValues
return typeof xml === 'xml' ? xml.toXMLString() : String(xml);
},
/**
* @param {(f: (context: android.content.Context, parent: android.view.ViewGroup) => android.view.View)
* => org.autojs.autojs.runtime.api.Floaty.JsResizableWindow
* | org.autojs.autojs.runtime.api.Floaty.JsRawWindow} windowFunction
* @param {Xml} xml
* @return {org.autojs.autojs.rhino.ProxyJavaObject|android.view.View}
*/
wrap(windowFunction, xml) {
let { layoutInflater } = scriptRuntime.ui;
let window = windowFunction(function (context, parent) {
layoutInflater.setContext(context);
return layoutInflater.inflate(_.toXMLStringIfNeeded(xml), parent, true);
});
let proxyObject = new ProxyJavaObject(scope, window, getClass(window));
proxyObject.__proxy__ = {
set(name, value) {
window[name] = value;
},
get(name) {
let value = window[name];
if (typeof value === 'undefined') {
if (!value) {
value = window.findView(name);
}
if (!value) {
value = undefined;
}
}
return value;
},
};
return proxyObject;
},
};
/**
* @type {Internal.Floaty}
*/
const floaty = new _.Floaty();
return floaty;
};

View File

@@ -0,0 +1,697 @@
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { autojs, console, device, pickup, ui, util, Numberx } = global;
/* Here, importClass() is not recommended for intelligent code completion in IDE like WebStorm. */
/* The same is true of destructuring assignment syntax (like `let {Uri} = android.net`). */
let ScriptRuntime = org.autojs.autojs.runtime.ScriptRuntime;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} runtime
* @param {org.mozilla.javascript.Scriptable | global} scope
*/
module.exports = function (runtime, scope) {
let _ = {
scale: {
base: {
x: 720,
y: 1280,
},
baseState: {
x: false,
y: false,
},
ensureBase(o) {
if (!(o > 0 && Number.isInteger(o))) {
throw RangeError(`Scale base "${o}" must be a positive integer.`);
}
},
ensureBaseXSetOnlyOnce(x) {
if (this.baseState.x === x) {
throw Error(`Scale base X could be set only once, ${this.base.x} has been set as the base.`);
}
},
ensureBaseYSetOnlyOnce(y) {
if (this.baseState.y === y) {
throw Error(`Scale base Y could be set only once, ${this.base.y} has been set as the base.`);
}
},
ensureBasesConsistent() {
if (this.baseState.x !== this.baseState.y) {
throw Error(`Scale bases must be consistent, { x: ${this.baseState.x}, y: ${this.baseState.y} }.`);
}
},
},
uiHandler: runtime.getUiHandler(),
buildTypes: {
release: 100, beta: 50, alpha: 0,
},
toasts: {
/**
* @type {Set<android.widget.Toast>}
*/
pool: new Set(),
lock: new ReentrantLock(),
add(t) {
if (t instanceof Toast) {
this.lock.lock();
this.pool.add(t);
this.addCallback(t);
this.lock.unlock();
}
},
/**
* @param {android.widget.Toast} t
*/
addCallback(t) {
const remove = () => _.toasts.remove(t);
if (util.version.sdkInt >= util.versionCodes.R) {
t.addCallback(new JavaAdapter(Toast.Callback, {
onToastShown: () => void 0,
onToastHidden: remove,
}));
} else {
_.uiHandler.postDelayed(new JavaAdapter(java.lang.Runnable, {
run: remove,
}), this.getDuration(t) + 1e3 /* As toast may show with some delay. */);
}
},
remove(t) {
if (this.pool.has(t)) {
this.lock.lock();
this.pool.delete(t);
this.lock.unlock();
}
},
dismissAll() {
if (this.pool.size > 0) {
this.lock.lock();
this.pool.forEach((t) => t.cancel());
this.pool.clear();
this.lock.unlock();
}
},
getDuration(t) {
let du = {
SHORT_DELAY: 2e3,
LONG_DELAY: 3.5e3,
};
switch (t.getDuration()) {
case Toast.LENGTH_SHORT:
return du.SHORT_DELAY;
case Toast.LENGTH_LONG:
return du.LONG_DELAY;
default:
return Math.max.apply(null, Object.values(du));
}
},
},
extensions: {
/** @global */
get WIDTH() {
return ScreenMetrics.getDeviceScreenWidth();
},
/** @global */
get HEIGHT() {
return ScreenMetrics.getDeviceScreenHeight();
},
// @Caution by SuperMonster003 on Oct 11, 2022.
// ! android.widget.Toast.makeText() doesn't work well on Android API Level 28 (Android 9) [P].
// ! There hasn't been a solution for this so far.
// ! Tested devices:
// ! 1. SONY XPERIA XZ1 Compact (G8441)
// ! 2. Android Studio AVD (Android 9.0 x86)
/** @global */
toast(msg, isLong, isForcible) {
let $ = {
rex: {
long: /^l(ong)?$/i,
short: /^s(hort)?$/i,
forcible: /^f(orcible)?$/i,
},
toast() {
this.init(arguments);
this.show();
},
init() {
this.message = isNullish(msg) ? '' : String(msg);
this.isForcible = this.parseIsForcible(isForcible);
this.isLong = this.parseIsLong(isLong);
},
parseIsLong(isLong) {
if (typeof isLong === 'boolean') {
return isLong;
}
if (typeof isLong === 'number') {
return Boolean(isLong);
}
if (typeof isLong === 'string') {
if (this.rex.long.test(isLong)) {
return true;
}
if (this.rex.short.test(isLong)) {
return false;
}
if (this.rex.forcible.test(isLong)) {
this.isForcible = true;
return false;
}
throw Error(`Invalid param: {name: isLong, value: ${isLong}, type: ${species(isLong)}.`);
}
return false;
},
parseIsForcible(isForcible) {
if (typeof isForcible === 'boolean') {
return isForcible;
}
if (typeof isForcible === 'number') {
return Boolean(isForcible);
}
if (typeof isForcible === 'string') {
if (this.rex.forcible.test(isForcible)) {
return true;
}
throw Error(`Invalid param: {name: isForcible, value: ${isForcible}, type: ${species(isForcible)}.`);
}
return false;
},
show() {
_.uiHandler.post(() => {
if ($.isForcible) {
_.toasts.dismissAll();
}
let len = $.isLong ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT;
let o = Toast.makeText(_.uiHandler.getContext(), $.message, len);
_.toasts.add(o);
o.show();
});
},
};
$.toast();
},
/** @global */
toastLog(msg, isLong, isForcible) {
this.toast.apply(this, arguments);
console.log(msg);
},
/** @global */
sleep(millisMin, millisMax) {
let $ = {
rexNum: /[+-]?(\d+(\.\d+)?(e\d+)?)/,
set min(v) {
this._min = Number(v);
},
get min() {
return Math.max(this._min, 0);
},
set max(v) {
this._max = Number(v);
},
get max() {
return Math.min(this._max, Number.MAX_SAFE_INTEGER);
},
sleep(min, max) {
if (this.trigger()) {
this.parseArgs(min, max);
try {
runtime.sleep(this.min + this.randBound);
} catch (e) {
if (!(e.javaException instanceof ScriptInterruptedException)) {
throw e;
}
}
}
},
trigger() {
if (ui.isUiThread()) {
throw Error('不能在ui线程执行阻塞操作请使用setTimeout代替.');
}
return true;
},
parseArgs(min, max) {
this.parseMin(min);
this.parseMax(max);
this.parseRandBound();
},
parseMin(min) {
if (typeof min !== 'number') {
throw TypeError('Type of millisMin must be a number.');
}
this.min = min;
},
parseMax(max) {
if (typeof max === 'number') {
this.max = max;
} else if (typeof max === 'string') {
let matched = max.match(this.rexNum);
if (matched === null) {
throw TypeError('String millisMax must have a number contained.');
}
let delta = Number(matched[0]);
this.max = this.min + delta;
this.min = this.min - delta;
} else {
this.max = this.min;
}
},
parseRandBound() {
this.randBound = Math.ceil(Math.random() * (this.max - this.min));
},
};
$.sleep(millisMin, millisMax);
},
/** @global */
isStopped() {
return runtime.isStopped();
},
/** @global */
isShuttingDown() {
return isStopped();
},
/** @global */
notStopped() {
return !this.isStopped();
},
/** @global */
isRunning() {
return !this.isStopped();
},
/** @global */
exit(e) {
if (typeof e === 'undefined') {
runtime.exit();
} else if (typeof e === 'string') {
runtime.exit(new java.lang.Exception(e));
} else if (typeof e instanceof java.lang.Throwable) {
runtime.exit(e);
} else {
throw TypeError(`Unknown type of argument "e" with value ${e}} for exit()`);
}
},
/** @global */
stop() {
this.exit();
},
/** @global */
setClip(text) {
return runtime.setClip(text);
},
/** @global */
getClip() {
return runtime.getClip();
},
/** @global */
currentPackage() {
auto();
return runtime.info.getLatestPackage();
},
/** @global */
currentActivity() {
auto();
return runtime.info.getLatestActivity();
},
/**
* @global
* @param {Wait.Condition} condition
* @param {?number|Wait.Callback} [limit=10e3]
* @param {?number|Wait.Callback} [interval=200]
* @param {Wait.Callback} [callback]
* @return {any}
*/
wait(condition, limit, interval, callback) {
if (isObjectSpecies(arguments[1])) {
// @Overload wait(condition, callback): any
return this.wait(condition, /* limit = */ null, /* interval = */ null, /* callback = */ arguments[1]);
}
if (isObjectSpecies(arguments[2])) {
// @Overload wait(condition, limit, callback): any
return this.wait(condition, limit, /* interval = */ null, /* callback = */ arguments[2]);
}
let $ = {
result: false,
start: Date.now(),
callback: callback || {},
parseArgs() {
let lmt = typeof limit === 'number' ? limit : limit === null ? NaN : Number(limit);
if (isNaN(lmt)) {
lmt = 10e3;
}
if (lmt < 0) {
throw Error(`Limitation (${lmt}) cannot be negative for wait().`);
}
if (lmt < 100) {
this.times = lmt;
this.timeout = Infinity;
} else {
this.times = Infinity;
this.timeout = lmt;
}
let itv = typeof interval === 'number' ? interval : interval === null ? NaN : Number(interval);
if (isNaN(itv)) {
itv = 200;
}
if (!isFinite(itv)) {
throw Error(`Interval cannot be Infinity for wait().`);
}
if (itv < 0) {
throw Error(`Interval (${itv}) cannot be negative for wait().`);
}
this.interval = itv;
if (this.interval >= this.timeout) {
this.times = Math.min(this.times, 1);
}
},
check() {
if (condition instanceof UiObject) {
throw TypeError('UiObject cannot be used as the condition for wait().');
}
return typeof condition === 'function' ? condition() : pickup(condition);
},
wait() {
if (!this.times) {
return;
}
while (true) {
let checked = this.checked = this.check();
// Some falsy values [ 0, 0n, -0, "" (empty string) ] should pass the check.
this.result = !(isNullish(checked) || Number.isNaN(checked) || checked === false);
this.times -= 1;
if (this.result || !this.times) {
break;
}
if (Date.now() - this.start > this.timeout) {
break;
}
sleep(this.interval);
}
},
callbackIFN() {
let fn = this.result ? this.callback.then : this.callback.else;
if (fn !== undefined) {
if (typeof fn !== 'function') {
throw TypeError(`Callback must be function type for wait().`);
}
let res = fn(this.checked);
if (res !== undefined) {
this.result = res;
}
}
},
getResult() {
this.parseArgs();
this.wait();
this.callbackIFN();
return this.result;
},
};
return $.getResult();
},
/** @global */
waitForActivity(activityName, limit, interval, callback) {
_.ensureNonUiThread();
let condition = () => currentActivity() === activityName;
return wait.apply(scope, [ condition ].concat(Array.from(arguments).slice(1)));
},
/** @global */
waitForPackage(packageName, limit, interval, callback) {
_.ensureNonUiThread();
let condition = () => currentPackage() === packageName;
return wait.apply(scope, [ condition ].concat(Array.from(arguments).slice(1)));
},
/** @global */
random(min, max) {
if (arguments.length === 0) {
return Math.random();
}
return Math.floor(Math.random() * (max - min + 1)) + min;
},
/** @global */
setScreenMetrics(width, height) {
runtime.setScreenMetrics(width, height);
},
/** @global */
requiresApi(requiresApi) {
ScriptRuntime.requiresApi(requiresApi);
},
/** @global */
requiresAutojsVersion(version) {
if (typeof version === 'number') {
if (_.compare(version, autojs.versionCode) > 0) {
throw Error(`AutoJs6 版本号需不低于 ${version}.`);
}
} else {
if (_.compareVersion(version, autojs.versionName) > 0) {
throw Error(`AutoJs6 版本需不低于 ${version}.`);
}
}
},
getScaleBases() {
return _.scale.base;
},
getScaleBaseX() {
return _.scale.base.x;
},
getScaleBaseY() {
return _.scale.base.y;
},
setScaleBases(baseX, baseY) {
this.setScaleBaseX(baseX);
this.setScaleBaseY(baseY);
},
setScaleBaseX(baseX) {
_.scale.ensureBaseXSetOnlyOnce(baseX);
_.scale.ensureBase(baseX);
_.scale.base.x = baseX;
_.scale.baseState.x = true;
},
setScaleBaseY(baseY) {
_.scale.ensureBaseYSetOnlyOnce(baseY);
_.scale.ensureBase(baseY);
_.scale.base.y = baseY;
_.scale.baseState.y = true;
},
/** @global */
cX(num, base, isRatio) {
let W = device.width;
if (arguments.length === 0) {
return W;
}
// @Overload
if (typeof base === 'boolean') {
return this.cX(num, null, base);
}
if (Math.abs(num) < 1 && isRatio !== false || isRatio) {
return Math.round(W * num);
}
if (typeof base === 'number') {
_.scale.ensureBase(base);
} else {
base = _.scale.base.x;
}
return Math.round(W * num / base);
},
/** @global */
cY(num, base, isRatio) {
let H = device.height;
if (arguments.length === 0) {
return H;
}
// @Overload
if (typeof base === 'boolean') {
return this.cY(num, null, base);
}
if (Math.abs(num) < 1 && isRatio !== false || isRatio) {
return Math.round(H * num);
}
if (typeof base === 'number') {
_.scale.ensureBase(base);
} else {
base = _.scale.base.y;
}
return Math.round(H * num / base);
},
/** @global */
cYx(num, base, isRatio) {
_.scale.ensureBasesConsistent();
// @Overload
if (typeof base === 'boolean') {
return this.cYx(num, null, base);
}
// @Overload
if (typeof base === 'string') {
return this.cYx(num, Numberx.parseRatio(base), true);
}
let W = device.width;
if (Math.abs(num) < 1 || isRatio) {
if (isNullish(base)) {
base = _.scale.base.y / _.scale.base.x;
}
if (typeof base === 'number') {
return Numberx.check(0, '<', base, '<=', 1)
? Math.round(num * W / base)
: Math.round(num * W * base);
}
throw Error('Base of cYx() must be a valid number.');
}
if (isNullish(base)) {
base = _.scale.base.x;
}
return Math.round(num * W / base);
},
/** @global */
cXy(num, base, isRatio) {
_.scale.ensureBasesConsistent();
// @Overload
if (typeof base === 'boolean') {
return this.cXy(num, null, base);
}
// @Overload
if (typeof base === 'string') {
return this.cXy(num, Numberx.parseRatio(base), true);
}
let H = device.height;
if (Math.abs(num) < 1 || isRatio) {
if (isNullish(base)) {
base = _.scale.base.y / _.scale.base.x;
}
if (typeof base === 'number') {
return Numberx.check(0, '<', base, '<=', 1)
? Math.round(num * H * base)
: Math.round(num * H / base);
}
throw Error('Base of cXy() must be a valid number.');
}
if (isNullish(base)) {
base = _.scale.base.y;
}
return Math.round(num * H / base);
},
$bind() {
this.toast.dismissAll = () => {
_.uiHandler.post(() => {
_.toasts.dismissAll();
});
};
delete this.$bind;
return this;
},
// $selfProtect() {
// /* Protection of global properties from being modified or deleted. */
// ( /* @IIFE */ () => [
// [ 'auto', 'colors' ],
//
// [ 'android', 'com', 'edu', 'java', 'javax', 'net', 'org' ],
//
// [ 'Array', 'BigInt', 'Boolean', 'Error', 'Function', 'JSON', 'Map', 'Math' ],
// [ 'Module', 'Number', 'Object', 'Promise', 'RegExp', 'Set', 'String', 'Symbol' ],
//
// [ 'clearImmediate', 'clearInterval', 'clearTimeout', 'decodeURI', 'decodeURIComponent' ],
// [ 'encodeURI', 'encodeURIComponent', 'escape', 'eval', 'isFinite', 'isNaN', 'parseFloat' ],
// [ 'parseInt', 'setImmediate', 'setInterval', 'setTimeout', 'unescape' ],
//
// [ 'Packages', 'alert', 'confirm', 'click', 'err', 'log', 'pickup', 'detect', 'prompt' ],
// ]
// .flat()
// .filter((name) => {
// return Object.prototype.hasOwnProperty.call(scope, name)
// && Object.getOwnPropertyDescriptor(scope, name).writable;
// })
// .forEach((key) => {
// Object.defineProperty(scope, key, {
// configurable: false,
// writable: false,
// });
// }))();
//
// delete this.$selfProtect;
// },
$appropriateProtect() {
[
'continuation', 'selector',
].forEach((key) => {
Object.defineProperty(scope, key, {
enumerable: true,
configurable: false,
writable: false,
});
});
delete this.$appropriateProtect;
},
},
ensureNonUiThread() {
if (ui.isUiThread()) {
throw Error('不能在ui线程执行阻塞操作请在子线程或子脚本执行或者使用setInterval循环检测当前activity和package.');
}
},
compareVersion(v1, v2) {
v1 = this.parseVersion(v1);
v2 = this.parseVersion(v2);
if (v1.major !== v2.major) {
return this.compare(v1.major, v2.major);
}
if (v1.minor !== v2.minor) {
return this.compare(v1.minor, v2.minor);
}
if (v1.revision !== v2.revision) {
return this.compare(v1.revision, v2.revision);
}
if (v1.buildType !== v2.buildType) {
return this.compare(v1.buildType, v2.buildType);
}
return this.compare(v1.build, v2.build);
},
compare(a, b) {
return a > b ? 1 : a < b ? -1 : 0;
},
parseVersion(v) {
const m = /(\d+)\.(\d+)\.(\d+)\s*(A(lpha)?|B(eta)?)?(\d*)/i.exec(v);
if (!m) {
throw Error(`版本格式不合法: ${v}.`);
}
return {
major: parseInt(m[1]),
minor: parseInt(m[2]),
revision: parseInt(m[3]),
buildType: _.buildType(m[4]),
build: m[5] ? parseInt(m[5]) : 1,
};
},
buildType(str) {
if (str === 'Alpha') {
return this.buildTypes.alpha;
}
if (str === 'Beta') {
return this.buildTypes.beta;
}
return this.buildTypes.release;
},
};
Object.assign(scope, _.extensions.$bind());
// Object.keys(_.extensions)
// .filter(key => !key.startsWith('$'))
// .forEach((key) => {
// Object.defineProperty(scope, key, {
// enumerable: true,
// configurable: false,
// writable: false,
// });
// });
};

View File

@@ -0,0 +1,310 @@
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { ui } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Http}
*/
module.exports = function (scriptRuntime, scope) {
const PFile = org.autojs.pio.PFile;
const Request = okhttp3.Request;
const RequestBody = okhttp3.RequestBody;
const MultipartBody = okhttp3.MultipartBody;
const MediaType = okhttp3.MediaType;
const FormBody = okhttp3.FormBody;
const Callback = okhttp3.Callback;
const MimeTypeMap = android.webkit.MimeTypeMap;
let _ = {
Http: ( /* @IIFE */ () => {
/**
* @implements Internal.Http
*/
const Http = function () {
// Empty interface body.
};
Http.prototype = {
constructor: Http,
__okhttp__: new MutableOkHttp(),
/**
* @returns {okhttp3.OkHttpClient}
*/
client() {
return this.__okhttp__.client();
},
/**
* @param {string} url
* @param {Http.RequestOptions} [options]
* @return {okhttp3.Request}
*/
buildRequest(url, options) {
let __ = {
options: options || {},
getUrl(url) {
if (typeof url !== 'string') {
throw TypeError('Param url must be a string');
}
// noinspection HttpUrlsUsage
return url.match(/^https?:\/\//) ? url : `http://${url}`;
},
setHeaders(request) {
Object.entries(this.options.headers || {}).forEach((entries) => {
let [ key, value ] = entries;
if (Array.isArray(value)) {
value.forEach(v => request.header(key, v));
} else {
request.header(key, value);
}
});
},
setMethod(request) {
if (this.options.body) {
this.ensureMethodInOptions();
request.method(this.options.method, this.parseBody());
} else if (this.options.files) {
this.ensureMethodInOptions();
request.method(this.options.method, this.parseMultipart());
} else {
this.ensureMethodInOptions();
request.method(this.options.method, null);
}
},
ensureMethodInOptions() {
if (typeof this.options.method !== 'string') {
throw Error('Property method is required for header options');
}
},
parseBody() {
let body = this.options.body;
if (body instanceof RequestBody) {
return body;
}
if (typeof body === 'string') {
return RequestBody.create(MediaType.parse(this.options.contentType), body);
}
if (typeof body === 'function') {
// noinspection JSValidateTypes
return new RequestBody({
contentType() {
return MediaType.parse(this.options.contentType);
},
writeTo: body,
});
}
throw TypeError('Unknown type of body for header options');
},
parseMultipart() {
let files = this.options.files;
let builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
Object.entries(files).forEach((entries) => {
let [ key, value ] = entries;
if (typeof value === 'string') {
builder.addFormDataPart(key, value);
return;
}
let path, mimeType, fileName;
if (typeof value.getPath === 'function') {
path = value.getPath();
} else if (value.length === 2) {
[ fileName, path ] = value;
} else if (value.length > 2) {
[ fileName, mimeType, path ] = value;
}
let file = new PFile(path);
fileName = fileName || file.getName();
mimeType = mimeType || this.parseMimeType(file.getExtension());
let requestBody = RequestBody.create(MediaType.parse(mimeType), file);
builder.addFormDataPart(key, fileName, requestBody);
});
return builder.build();
},
parseMimeType(ext) {
if (ext.length > 0) {
let type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
if (type) {
return type;
}
}
return 'application/octet-stream';
},
};
let $$ = {
request: new Request.Builder(),
build() {
this.setUrl();
this.setHeader();
this.setMethod();
return this.request.build();
},
setUrl() {
this.request.url(__.getUrl(url));
},
setHeader() {
__.setHeaders(this.request);
},
setMethod() {
__.setMethod(this.request);
},
};
return $$.build();
},
/**
* @param {string} url
* @param {Http.RequestOptions} [options]
* @param {(response: Http.WrappedResponse, ex?: java.io.IOException) => void} [callback]
* @return {Http.WrappedResponse | void}
*/
request(url, options, callback) {
let cont = !callback && ui.isUiThread() && continuation.enabled
? continuation.create() : null;
/**
* @type {okhttp3.Call}
*/
let call = this.client().newCall(this.buildRequest(url, options));
if (!callback && !cont) {
return _.wrapResponse(call.execute());
}
call.enqueue(new Callback({
onResponse(call, response) {
let wrappedResponse = _.wrapResponse(response);
cont && cont.resume(wrappedResponse);
callback && callback(wrappedResponse);
},
onFailure(call, ex) {
cont && cont.resumeError(ex);
callback && callback(null, ex);
},
}));
if (cont) {
return cont.await();
}
},
get(url, options, callback) {
return this.request(url, Object.assign(options || {}, {
method: 'GET',
}), callback);
},
post(url, data, options, callback) {
let opt = Object.assign({
contentType: _.constants.DEF_CONTENT_TYPE,
}, options, {
method: 'POST',
});
_.fillPostData(opt, data);
return this.request(url, opt, callback);
},
postJson(url, data, options, callback) {
return this.post(url, data, Object.assign(options || {}, {
contentType: 'application/json',
}), callback);
},
postMultipart(url, files, options, callback) {
return this.request(url, Object.assign(options || {}, {
method: 'POST',
contentType: 'multipart/form-data',
files: files,
}), callback);
},
};
return Http;
})(),
constants: {
DEF_CONTENT_TYPE: 'application/x-www-form-urlencoded',
},
/**
* @param {okhttp3.Response} res
* @return {Http.WrappedResponse}
*/
wrapResponse: (res) => /* @AXR */ ({
request: res.request(),
getResponse() {
return {
request: this.request,
statusMessage: res.message(),
statusCode: res.code(),
body: this.getBody(),
headers: this.getHeaders(),
url: this.request.url(),
method: this.request.method(),
};
},
getHeaders() {
let result = {};
let headers = res.headers();
for (let i = 0; i < headers.size(); i += 1) {
let name = headers.name(i);
let value = headers.value(i);
if (!(name in result)) {
result[name] = value;
continue;
}
let origin = result[name];
if (!Array.isArray(origin)) {
result[name] = [ origin ];
}
result[name].push(value);
}
return result;
},
getBody() {
let body = res.body();
return {
string: body.string.bind(body),
bytes: body.bytes.bind(body),
contentType: body.contentType(),
json() {
try {
return JSON.parse(this.string());
} catch (e) {
throw Error('Failed to parse JSON. Body string may be not in JSON format');
}
},
};
},
}.getResponse()),
/**
* @param {Http.RequestOptions} options
* @param {?Object.<string, string> | string} data
*/
fillPostData(options, data) {
data = data || {};
if (options.contentType === _.constants.DEF_CONTENT_TYPE) {
let b = new FormBody.Builder();
Object.entries(data).forEach((entries) => {
let [ key, value ] = entries;
b.add(key, value);
});
options.body = b.build();
} else if (options.contentType === 'application/json') {
options.body = JSON.stringify(data);
} else {
options.body = data;
}
},
};
/**
* @type {Internal.Http}
*/
const http = new _.Http();
return http;
};

View File

@@ -0,0 +1,102 @@
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { files } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.I18n}
*/
module.exports = function (scriptRuntime, scope) {
let _ = {
I18n: ( /* @IIFE */ () => {
/**
* @type {Internal.Banana}
*/
const banana = new (require('banana-i18n'))(void 0, { finalFallback: 'default' });
/**
* @implements Internal.I18n
*/
const I18n = function () {
return Object.assign(banana.i18n.bind(banana), I18n.prototype);
};
I18n.prototype = {
constructor: I18n,
banana,
setPath(relativePath) {
if (!files.isDir(relativePath)) {
throw Error(`Invalid path: ${relativePath}`);
}
_.config.path = relativePath;
},
setLocale(locale) {
banana.setLocale(locale);
},
getFallbackLocales() {
return banana.getFallbackLocales();
},
getParser() {
return banana.parser;
},
getPath() {
if (!files.isDir(_.config.path)) {
let fallback = files.join('assets', _.config.path);
if (files.isDir(fallback)) {
this.setPath(fallback);
}
}
return _.config.path;
},
getLocale() {
return banana.locale;
},
getFinalFallback() {
return banana.finalFallback;
},
load(messageSource, locale) {
if (typeof messageSource === 'object') {
return banana.load(messageSource, locale);
}
if (typeof messageSource === 'string') {
if (arguments.length === 1) {
return this.load(messageSource, messageSource);
}
if (!`${messageSource}`.includes(java.io.File.separator)) {
messageSource = files.join(this.getPath(), `${messageSource}.json`);
}
let path = files.path(messageSource);
if (!files.isFile(path)) {
throw Error(`Invalid path: ${path}`);
}
try {
return this.load(JSON.parse(files.read(path)), locale);
} catch (e) {
scriptRuntime.console.warn(`${e.message}\n${e.stack}`);
throw Error(`Failed to parse JSON file: ${path}`);
}
}
throw TypeError(`Unknown message source: ${messageSource}`);
},
loadAll() {
files
.listDir(this.getPath(), file => files.getExtension(file).toLowerCase() === 'json')
.forEach((file) => this.load(files.getNameWithoutExtension(file)));
},
};
return I18n;
})(),
config: { path: 'i18n' },
};
/**
* @type {Internal.I18n}
*/
const i18n = new _.I18n();
return i18n;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Media}
*/
module.exports = function (scriptRuntime, scope) {
let _ = {
Media: ( /* @IIFE */ () => {
/**
* @extends Internal.Media
*/
const Media = function () {
// Empty interface body.
};
Media.prototype = {
constructor: Media,
};
Object.setPrototypeOf(Media.prototype, scriptRuntime.media);
return Media;
})(),
};
/**
* @type {Internal.Media}
*/
const media = new _.Media();
return media;
};

View File

@@ -0,0 +1,109 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Plugins}
*/
module.exports = function (scriptRuntime, scope) {
let _ = {
Plugins: ( /* @IIFE */ () => {
/**
* @implements Internal.Plugins
*/
const Plugins = function () {
// Empty interface body.
};
Plugins.prototype = {
constructor: Plugins,
/**
* @type {Internal.Plugins.Extend}
*/
extend: ( /* @IIFE */ () => {
/**
* @implements Internal.Plugins.Extend
*/
let Extend = function () {
return Object.assign(function (modules) {
Array.from(new Set(Array.from(arguments).flat(Infinity))).forEach((name) => {
let moduleName = _.normalizeModuleName(name);
if (moduleName in _.modules) {
_.modules[moduleName].extendJsBuildInObjects();
}
});
}, Extend.prototype);
};
Extend.prototype = {
constructor: Extend,
exclude() {
Array.from(arguments).flat(Infinity).forEach((name) => {
let moduleName = _.normalizeModuleName(name);
if (!_.excludes.includes(moduleName)) {
_.excludes.push(moduleName);
}
});
},
registerModule(module) {
Object.assign(_.modules, module);
},
};
return new Extend();
})(),
extendAll() {
Object.entries(_.modules).forEach((entry) => {
let [ name, action ] = entry;
if (!_.excludes.includes(name)) {
action.extendJsBuildInObjects();
}
});
},
extendAllBut() {
this.extend.exclude.apply(this.extend, arguments);
this.extendAll();
},
load(name) {
if (typeof name !== 'string') {
throw TypeError('The "name" argument for plugins.load() must be of type string');
}
if (name.includes('.') && !name.endsWith('.js')) /* As package name. */ {
let plugin = scriptRuntime.plugins.load(name);
let moduleExportedFunc = require(plugin.getMainScriptPath());
return moduleExportedFunc(plugin.unwrap());
}
if (files.exists('./plugins')) /* As project-level plugins name. */ {
return require(`./plugins${name}`);
}
throw Error('A directory named "plugins" must be found in the root directory of current project');
},
};
return Plugins;
})(),
/**
* @type {Object.<string, Internal.Plugins.ExtendModules.Interface>}
*/
modules: {},
/**
* @type {string[]}
*/
excludes: [],
/**
* @param {string} name
* @returns {string}
*/
normalizeModuleName(name) {
if (!name.endsWith('x')) {
name += 'x';
}
return name[0].toUpperCase() + name.slice(1);
},
};
/**
* @type {Internal.Plugins}
*/
const plugins = new _.Plugins();
return plugins;
};

View File

@@ -0,0 +1,149 @@
// noinspection JSUnusedGlobalSymbols
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Recorder}
*/
module.exports = function (scriptRuntime, scope) {
let _ = {
Recorder: ( /* @IIFE */ () => {
/**
* @implements Internal.Recorder
*/
const Recorder = function () {
/**
* Record or get the record for a time gap
* @param {string|function} [key]
* @param {number|ThisType<any>} [timestamp]
* @return {number|void} - timestamp
*/
const callable = function (key, timestamp) {
return _.shortcut(key, timestamp);
};
return Object.assign(callable, Recorder.prototype);
};
Recorder.prototype = {
constructor: Recorder,
/**
* @param {string} [key]
* @param {number} [ts=Date.now()]
*/
save: (key, ts) => _.save(key, ts),
/**
* @param {string} [key]
* @param {number} [ts=Date.now()]
* @return {number}
*/
load: (key, ts) => _.load(key, ts),
isLessThan: (key, compare) => _.load(key) < compare,
isGreaterThan: (key, compare) => _.load(key) > compare,
has: (key) => _.has(key),
remove: (key) => _.remove(key),
clear: () => _.clear(),
};
return Recorder;
})(),
/**
* @type {Object.<string,number>}
*/
keys: {},
/**
* @type {number[]}
*/
anonymity: [],
/**
* @param {?number} [ts]
* @return {number}
*/
ts(ts) {
return typeof ts === 'number' ? ts : Date.now();
},
/**
* @param {string} [key]
* @return {boolean}
*/
has(key) {
return key in this.keys;
},
clear() {
this.keys = {};
this.anonymity.splice(0);
},
/**
* @param {string} [key]
* @param {?number} [ts]
* @return {number}
*/
add(key, ts) {
key === undefined
? this.anonymity.push(this.ts(ts))
: this.keys[key] = this.ts(ts);
return this.ts(ts);
},
/**
* @param {string} [key]
* @param {boolean} [isErrorSuppressed=false]
* @return {number|void}
*/
get(key, isErrorSuppressed) {
if (key === undefined) {
return this.anonymity.pop();
}
if (!this.has(key) && !isErrorSuppressed) {
throw Error(`key "${key}" does not exist`);
}
return this.keys[key];
},
/**
* @param {string} [key]
* @param {?number} [ts]
* @return {number}
*/
save(key, ts) {
return this.add(key, ts);
},
/**
* @param {string} [key]
* @param {?number} [ts]
* @return {number}
*/
load(key, ts) {
return this.ts(ts) - this.get(key);
},
/**
* @param {string} key
* @returns {boolean}
*/
remove(key) {
return delete this.keys[key];
},
/**
* @param {string|function} [key]
* @param {?number|ThisType<any>} [ts]
* @return {number}
*/
shortcut(key, ts) {
if (typeof key === 'function') {
let k = `${key.name || '(anonymous)'}@${Date.now()}`;
this.save(k);
key.call(typeof ts === 'object' ? ts : null);
let res = this.load(k);
this.remove(k);
return res;
}
return typeof key !== 'undefined'
? this.has(key) ? this.load(key, ts) : this.save(key, ts)
: this.anonymity.length ? this.load() : this.save();
},
};
/**
* @type {Internal.Recorder}
*/
const recorder = new _.Recorder();
return recorder;
};

View File

@@ -0,0 +1,184 @@
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { i18n } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {() => Internal.Selector}
*/
module.exports = function (scriptRuntime, scope) {
let _ = {
Selector: (() => {
/**
* @extends Internal.Selector
*/
const Selector = function () {
/**
* @global
*/
const selector = function () {
return scriptRuntime.selector();
};
return Object.assign(selector, Selector.prototype);
};
Selector.prototype = {
constructor: Selector,
};
return Selector;
})(),
javaObjectInstance: new java.lang.Object(),
isInJavaObject: key => key in _.javaObjectInstance,
isInScope: key => key in scope,
scopeAugment() {
Object.assign(scope, {
pickup(root, selector, compass, resultType, callback) {
switch (arguments.length) {
case 5:
// @Signature pickup<R>(root: UiObject, selector: Pickup.Selector, compass: Selector.Compass, resultType: Pickup.ResultType, callback: (o: any) => R): R;
return UiSelector.pickup(root, selector, compass, resultType, callback);
case 4:
if (arguments[0] instanceof UiObject) {
if (typeof arguments[3] === 'function') {
if (UiObject.isCompass(arguments[2])) {
// @Overload pickup<R>(root: UiObject, selector: Pickup.Selector, compass: Selector.Compass, callback: (o: any) => R): R;
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], /* compass = */ arguments[2], UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[3]);
}
// @Overload pickup<R>(root: UiObject, selector: Pickup.Selector, resultType: Pickup.ResultType, callback: (o: any) => R): R;
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[2], /* callback = */ arguments[3]);
}
// @Overload pickup(root: UiObject, selector: Pickup.Selector, compass: Selector.Compass, resultType: Pickup.ResultType): any;
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], /* compass = */ arguments[2], /* resultType = */ arguments[3], /* callback = */ null);
}
// @Overload pickup<R>(selector: Pickup.Selector, compass: Selector.Compass, resultType: Pickup.ResultType, callback: (o: any) => R): R;
return this.pickup(/* root = */ null, /* selector = */ arguments[0], /* compass = */ arguments[1], /* resultType = */ arguments[2], /* callback = */ arguments[3]);
case 3:
if (arguments[0] instanceof UiObject) {
if (typeof arguments[2] === 'function') {
// @Overload pickup<R>(root: UiObject, selector: Pickup.Selector, callback: (o: any) => R): R;
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[2]);
}
if (UiObject.isCompass(arguments[2])) {
// @Overload pickup(root: UiObject, selector: Pickup.Selector, compass: Selector.Compass): any;
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], /* compass = */ arguments[2], UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
}
// @Overload pickup(root: UiObject, selector: Pickup.Selector, resultType: Pickup.ResultType): any;
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[2], /* callback = */ null);
}
if (typeof arguments[2] === 'function') {
if (UiObject.isCompass(arguments[1])) {
// @Overload pickup<R>(selector: Pickup.Selector, compass: Selector.Compass, callback: (o: any) => R): R;
return this.pickup(/* root = */ null, /* selector = */ arguments[0], /* compass = */ arguments[1], UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[2]);
}
// @Overload pickup<R>(selector: Pickup.Selector, resultType: Pickup.ResultType, callback: (o: any) => R): R;
return this.pickup(/* root = */ null, /* selector = */ arguments[0], UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[1], /* callback = */ arguments[2]);
}
// @Overload pickup(selector: Pickup.Selector, compass: Selector.Compass, resultType: Pickup.ResultType): any;
return this.pickup(/* root = */ null, /* selector = */ arguments[0], /* compass = */ arguments[1], /* resultType = */ arguments[2], /* callback = */ null);
case 2:
if (arguments[0] instanceof UiObject) {
// @Overload pickup(root: UiObject, selector: Pickup.Selector): any;
return this.pickup(/* root = */ arguments[0], /* selector = */ arguments[1], UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
}
if (typeof arguments[1] === 'function') {
// @Overload pickup<R>(selector: Pickup.Selector, callback: (o: any) => R): R;
return this.pickup(/* root = */ null, /* selector = */ arguments[0], UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[1]);
}
if (UiObject.isCompass(arguments[1])) {
// @Overload pickup(selector: Pickup.Selector, compass: Selector.Compass): any;
return this.pickup(/* root = */ null, /* selector = */ arguments[0], /* compass = */ arguments[1], UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
}
// @Overload pickup(selector: Pickup.Selector, resultType: Pickup.ResultType): any;
return this.pickup(/* root = */ null, /* selector = */ arguments[0], UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[1], /* callback = */ null);
case 1:
// @Overload pickup(selector: Pickup.Selector): any;
return this.pickup(/* root = */ null, /* selector = */ arguments[0], UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
case 0:
// @Signature pickup(): UiObject;
return findOnce();
default:
throw Error(i18n('error-invalid-arguments-with-name-and-args', 'pickup', Array.from(arguments).join()));
}
},
detect(w, compass, resultType, callback) {
switch (arguments.length) {
case 4:
// @Signature detect<R>(w: UiObject, compass: Detect.Compass, resultType: Detect.ResultType, callback: ((o: any) => R)): R;
return UiObject.detect(w, compass, resultType, callback);
case 3:
if (typeof arguments[2] === 'function') {
if (UiObject.isCompass(arguments[1])) {
// @Overload detect<R>(w: UiObject, compass: Detect.Compass, callback: ((w: UiObject) => R)): R;
return this.detect(w, /* compass = */ arguments[1], UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[2]);
}
// @Overload detect<R>(w: UiObject, resultType: Detect.ResultType, callback: ((o: any) => R)): R;
return this.detect(w, UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[1], /* callback = */ arguments[2]);
}
// @Overload detect(w: UiObject, compass: Detect.Compass, resultType: Detect.ResultType): any;
return this.detect(w, /* compass = */ arguments[1], /* resultType = */ arguments[2], /* callback = */ null);
case 2:
if (typeof arguments[1] === 'function') {
// @Overload detect<T extends UiObject, R>(w: T, callback: ((w: T) => R)): R;
return this.detect(w, UiObject.COMPASS_PASS_ON, UiObject.RESULT_TYPE_WIDGET, /* callback = */ arguments[1]);
}
if (UiObject.isCompass(arguments[1])) {
// @Overload detect(w: UiObject, compass: Detect.Compass): any;
return this.detect(w, /* compass = */ arguments[1], UiObject.RESULT_TYPE_WIDGET, /* callback = */ null);
}
// @Overload detect(w: UiObject, resultType: Detect.ResultType): any;
return this.detect(w, UiObject.COMPASS_PASS_ON, /* resultType = */ arguments[1], /* callback = */ null);
default:
throw Error(i18n('error-invalid-arguments-with-name-and-args', 'detect', Array.from(arguments).join()));
}
},
existsAll() {
return Array.from(arguments).every(sel => this.pickup(sel, '?'));
},
existsOne() {
return Array.from(arguments).some(sel => this.pickup(sel, '?'));
},
});
for (let method in scriptRuntime.selector()) {
if (_.isInJavaObject(method) || _.isInScope(method)) {
// @Caution by SuperMonster003 as of Oct 23, 2022.
// ! The following methods have been assigned by 'automator' module,
// ! which not belonging to UiSelector:
// ! [ click / longClick / scrollDown / scrollUp / setText ].
continue;
}
// @Caution by SuperMonster003 as of Apr 26, 2022.
// ! Make param "method" scoped to this IIFE immediately.
// ! Unwrapping this IIFE will cause TypeError.
// ! Reappearance: `let f = idMatches; f(/.+/).findOnce();`
// ! TypeError: Cannot find function findOnce in object true.
// @ScopeBinding
scope[method] = ( /* @IIFE */ (method) => {
return function () {
let s = selector();
try {
return s[method].apply(s, arguments);
} catch (e) {
scriptRuntime.console.warn(`${e.message}\n${e.stack}`);
scriptRuntime.console.warn(`method: ${method}, arguments: ${Array.from(arguments).join()}`);
throw e;
}
};
})(method);
}
},
};
/**
* @type {() => Internal.Selector}
*/
const selector = new _.Selector();
_.scopeAugment();
return selector;
};

View File

@@ -0,0 +1,32 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Sensors}
*/
module.exports = function (scriptRuntime, scope) {
let _ = {
Sensors: ( /* @IIFE */ () => {
/**
* @extends Internal.Sensors
*/
const Sensors = function () {
// Empty interface body.
};
Sensors.prototype = {
constructor: Sensors,
};
Object.setPrototypeOf(Sensors.prototype, scriptRuntime.sensors);
return Sensors;
})(),
};
/**
* @type {Internal.Sensors}
*/
const sensors = new _.Sensors();
return sensors;
};

View File

@@ -0,0 +1,84 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Shell}
*/
module.exports = function (scriptRuntime, scope) {
const rtRootShell = scriptRuntime.getRootShell();
let _ = {
ShellCtor: ( /* @IIFE */ () => {
/**
* @implements Internal.Shell
*/
const ShellCtor = function () {
/**
* @global
*/
const shell = function (cmd, root) {
return scriptRuntime.shell(cmd, Number(Boolean(root)));
};
return Object.assign(shell, ShellCtor.prototype);
};
ShellCtor.prototype = {
constructor: ShellCtor,
fromIntent(i) {
return app.intentToShell(i);
},
};
return ShellCtor;
})(),
scopeAugment() {
Object.assign(scope, {
/** @global */
Menu: () => KeyCode(KeyEvent.KEYCODE_MENU),
/** @global */
Home: () => KeyCode(KeyEvent.KEYCODE_HOME),
/** @global */
Back: () => KeyCode(KeyEvent.KEYCODE_BACK),
/** @global */
Up: () => KeyCode(KeyEvent.KEYCODE_DPAD_UP),
/** @global */
Down: () => KeyCode(KeyEvent.KEYCODE_DPAD_DOWN),
/** @global */
Left: () => KeyCode(KeyEvent.KEYCODE_DPAD_LEFT),
/** @global */
Right: () => KeyCode(KeyEvent.KEYCODE_DPAD_RIGHT),
/** @global */
OK: () => KeyCode(KeyEvent.KEYCODE_DPAD_CENTER),
/** @global */
VolumeUp: () => KeyCode(KeyEvent.KEYCODE_VOLUME_UP),
/** @global */
VolumeDown: () => KeyCode(KeyEvent.KEYCODE_VOLUME_DOWN),
/** @global */
Power: () => KeyCode(KeyEvent.KEYCODE_POWER),
/** @global */
Camera: () => KeyCode(KeyEvent.KEYCODE_CAMERA),
/** @global */
Text: text => rtRootShell.Text(text),
/** @global */
Input: text => rtRootShell.Text(text),
/** @global */
Tap: (x, y) => rtRootShell.Tap(x, y),
/** @global */
Screencap: path => rtRootShell.Screencap(path),
/** @global */
KeyCode: keyCode => rtRootShell.KeyCode(keyCode),
/** @global */
SetScreenMetrics: (w, h) => rtRootShell.SetScreenMetrics(w, h),
/** @global */
Swipe: (x1, y1, x2, y2, duration) => duration === undefined
? rtRootShell.Swipe(x1, y1, x2, y2)
: rtRootShell.Swipe(x1, y1, x2, y2, duration),
});
},
};
const shell = new _.ShellCtor();
_.scopeAugment();
return shell;
};

View File

@@ -0,0 +1,71 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Storages}
*/
module.exports = function (scriptRuntime, scope) {
const LocalStorage = org.autojs.autojs.core.storage.LocalStorage;
let _ = {
ProxyStorage: ( /* @IIFE */ () => {
/**
* @implements Internal.LocalStorage
*/
const ProxyStorage = function (name) {
this._storage = new LocalStorage(scope.context, name);
};
ProxyStorage.prototype = {
constructor: ProxyStorage,
put(key, value) {
if (value === undefined) {
throw TypeError('Value cannot be undefined');
}
this._storage.put(key, JSON.stringify(value));
},
get(key, def) {
let value = this._storage.getString(key, null);
return value ? JSON.parse(value) : def;
},
remove(key) {
this._storage.remove(key);
},
contains(key) {
return this._storage.contains(key);
},
clear() {
this._storage.clear();
},
};
return ProxyStorage;
})(),
Storages: ( /* @IIFE */ () => {
/**
* @implements Internal.Storages
*/
const Storage = function () {
// Empty interface body.
};
Storage.prototype = {
constructor: Storage,
create(name) {
return new _.ProxyStorage(name);
},
remove(name) {
this.create(name).clear();
},
};
return Storage;
})(),
};
/**
* @type {Internal.Storages}
*/
const storages = new _.Storages();
return storages;
};

View File

@@ -0,0 +1,354 @@
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { ui, threads, files } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Tasks}
*/
module.exports = function (scriptRuntime, scope) {
const TimedTask = org.autojs.autojs.timing.TimedTask;
const IntentTask = org.autojs.autojs.timing.IntentTask;
const TimedTaskManager = org.autojs.autojs.timing.TimedTaskManager;
const ExecutionConfig = org.autojs.autojs.execution.ExecutionConfig;
const DynamicBroadcastReceivers = org.autojs.autojs.external.receiver.DynamicBroadcastReceivers;
let _ = {
Tasks: ( /* @IIFE */ () => {
/**
* @implements Internal.Tasks
*/
let Task = function () {
// Empty interface body.
};
Task.prototype = {
constructor: Task,
timedTaskManager: TimedTaskManager.getInstance(),
/**
* @template {TimedTask$|IntentTask$|null} T
* @param {T} task
* @return {T}
*/
addTask(task) {
if (task) {
this.timedTaskManager.addTask(task);
}
return task || null;
},
/**
* @param {Timers.TimedTask.Daily} [options]
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
*/
addDailyTask(options) {
let opt = options || {};
let localTime = _.parseDateTime('LocalTime', opt.time || Date.now());
let path = _.parsePath(opt.path);
let config = _.parseConfig(opt);
let timedTask = this.addTask(TimedTask.dailyTask(localTime, path, config));
return _.taskFulfilled(timedTask, opt);
},
/**
* @param {Timers.TimedTask.Weekly} [options]
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
*/
addWeeklyTask(options) {
let timeFlag = 0;
let opt = options || {};
let daysOfWeek = opt.daysOfWeek || [ _.getCurrentDayOfWeek() ];
let daysOfWeekList = _.getDaysOfWeekFlatList();
for (let i = 0; i < daysOfWeek.length; i += 1) {
let dayString = daysOfWeek[i].toString();
let dayIndex = daysOfWeekList.indexOf(dayString.toLowerCase()) % 7;
if (dayIndex < 0) {
throw Error(`Unknown day: ${dayString}`);
}
timeFlag |= TimedTask.getDayOfWeekTimeFlag(dayIndex + 1);
}
let localTime = _.parseDateTime('LocalTime', opt.time || Date.now());
let flagsNum = Number(new java.lang.Long(timeFlag));
let path = _.parsePath(opt.path);
let config = _.parseConfig(opt);
let timedTask = this.addTask(TimedTask.weeklyTask(localTime, flagsNum, path, config));
return _.taskFulfilled(timedTask, opt);
},
/**
* @param {Timers.TimedTask.Disposable} options
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
*/
addDisposableTask(options) {
let opt = options || {};
let localDateTime = _.parseDateTime('LocalDateTime', opt.date || Date.now());
let path = _.parsePath(opt.path);
let config = _.parseConfig(opt);
let timedTask = this.addTask(TimedTask.disposableTask(localDateTime, path, config));
return _.taskFulfilled(timedTask, opt);
},
/**
* @param {Timers.IntentTask.Basic} [options]
* @return {IntentTask$|org.autojs.autojs.core.looper.TimerThread|null}
*/
addIntentTask(options) {
let opt = options || {};
let intentTask = (function $iiFe() {
let intentTask = new IntentTask();
intentTask.setScriptPath(_.parsePath(opt.path));
if (typeof opt.action === 'string') {
intentTask.setAction(opt.action);
if (opt.action === DynamicBroadcastReceivers.ACTION_STARTUP) {
// @Indecision opt.local
intentTask.setLocal(true);
}
}
if (typeof opt.dataType === 'string') {
intentTask.setDataType(opt.dataType);
}
if (typeof opt.local === 'boolean') {
// @FinalDecision opt.action
intentTask.setLocal(opt.local);
}
return intentTask;
})();
let timedTask = this.addTask(intentTask);
return _.taskFulfilled(timedTask, opt);
},
/**
* @param {number} id
* @return {TimedTask$}
*/
getTimedTask(id) {
return this.timedTaskManager.getTimedTask(id);
},
/**
* @param {number} id
* @return {IntentTask$}
*/
getIntentTask(id) {
return this.timedTaskManager.getIntentTask(id);
},
/**
* @param {TimedTask$|IntentTask$|null} task
* @return {TimedTask$|IntentTask$}
*/
removeTask(task) {
if (task) {
this.timedTaskManager.removeTask(task);
}
return task;
},
/**
* @param {number} id
* @param {Timers.TimedTask.Extension} [options]
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
*/
removeTimedTask(id, options) {
let opt = options || {};
let task = this.removeTask(this.getTimedTask(id));
return _.taskFulfilled(task, Object.assign(opt, {
condition: () => !this.getTimedTask(id),
}));
},
/**
* @param {number} id
* @param {Timers.TimedTask.Extension} [options]
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
*/
removeIntentTask(id, options) {
let opt = options || {};
let task = this.removeTask(this.getIntentTask(id));
return _.taskFulfilled(task, Object.assign(opt, {
condition: () => !this.getIntentTask(id),
}));
},
/**
* @param {TimedTask$|null} task
* @return {TimedTask$|null}
*/
updateTask(task) {
if (!task) {
return null;
}
task.setScheduled(false);
this.timedTaskManager.updateTask(task);
return task;
},
/**
* @param {{path?:string}} [options]
* @return {TimedTask$[]}
*/
queryTimedTasks(options) {
let opt = options || {};
let path = opt.path;
let list = this.timedTaskManager.getAllTasksAsList().toArray();
return path ? list.filter(task => task.getScriptPath() === path) : list;
},
/**
* @param {{path?:string,action?:string}} [options]
* @return {IntentTask$[]}
*/
queryIntentTasks(options) {
let opt = options || {};
let { path, action } = opt;
let list = this.timedTaskManager.getAllIntentTasksAsList().toArray();
if (!path && !action) {
return list;
}
let pathTrigger = task => !path || task.getScriptPath() === path;
let actionTrigger = task => !action || task.getAction() === action;
return list.filter(task => pathTrigger(task) && actionTrigger(task));
},
/**
* @param flag {number} -- number from 0 to 127
* @return {number[]}
*/
timeFlagToDays(flag) {
let days = [];
let binaryString = Number(flag).toString(2);
let currentDayNumber = binaryString.length - 1;
for (let i of binaryString) {
if (i !== '0') {
days.unshift(currentDayNumber);
}
currentDayNumber -= 1;
}
return days;
},
/**
* @param days {number[]}
* @return {number}
*/
daysToTimeFlag(days) {
return Array(7).fill(0).reduce((a, b, i) => {
return a + (days.includes(i) ? Math.pow(2, i) : 0);
}, 0);
},
};
return Task;
})(),
parsePath(path) {
if (!path) {
throw 'A path is necessary for a task';
}
if (!files.exists(path)) {
scriptRuntime.console.warn(`Specified path "${path}" doesn't exist`);
}
return files.path(path);
},
/**
* @param {any} num
* @param {number|function():number} [def=0]
* @returns {number}
*/
parseNumber(num, def) {
return typeof num === 'number' ? num : typeof def === 'function' ? def() : def || 0;
},
/**
* @param {Object} config
* @param {number} [config.delay=0]
* @param {number} [config.interval=0]
* @param {number} [config.loopTimes=1]
* @return {org.autojs.autojs.execution.ExecutionConfig}
*/
parseConfig(config) {
let execConfig = new ExecutionConfig();
execConfig.setDelay(_.parseNumber(config.delay, 0));
execConfig.setInterval(_.parseNumber(config.interval, 0));
execConfig.setLoopTimes(_.parseNumber(config.loopTimes, 1));
return execConfig;
},
/**
* @param {'LocalTime'|'LocalDateTime'} clazz
* @param {string|Date|number} dateTime
* @return {org.joda.time.LocalTime|org.joda.time.LocalDateTime}
*/
parseDateTime(clazz, dateTime) {
let clz = ( /* @IIFE */ () => {
switch (clazz) {
case 'LocalTime':
return org.joda.time.LocalTime;
case 'LocalDateTime':
return org.joda.time.LocalDateTime;
default:
throw Error('Unknown clazz for parseDateTime');
}
})();
if (typeof dateTime === 'string') {
return clz.parse(dateTime);
}
if (dateTime instanceof Date) {
return new clz(dateTime.getTime());
}
if (typeof dateTime === 'number') {
return new clz(dateTime);
}
throw Error('Unknown dateTime for parseDateTime');
},
/**
* @param {TimedTask$|IntentTask$} task
* @param {Timers.TimedTask.Extension|{}} [options]
* @return {TimedTask$|org.autojs.autojs.core.looper.TimerThread|null}
*/
taskFulfilled(task, options) {
let opt = options || {};
let run = () => {
if (task) {
let timeout = 2e3;
let interval = 50;
let condition = opt.condition || (() => task['id'] > 0);
while (timeout > 0) {
if (condition()) {
break;
}
sleep(interval);
timeout -= interval;
}
}
return opt.callback ? opt.callback(task) : task || null;
};
return opt.isAsync || ui.isUiThread() ? threads.start(run) : run();
},
getCurrentDayOfWeek() {
return new Date().getDay();
},
getDaysOfWeekFlatList() {
return [
'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun',
'一', '二', '三', '四', '五', '六', '日',
1, 2, 3, 4, 5, 6, 0,
1, 2, 3, 4, 5, 6, 7,
].map(x => typeof x === 'string' ? x : x.toString());
},
};
/**
* @type {Internal.Tasks}
*/
const tasks = new _.Tasks();
return tasks;
};

View File

@@ -0,0 +1,107 @@
// noinspection NpmUsedModulesInstalled
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Threads}
*/
module.exports = function (scriptRuntime, scope) {
const Throwable = java.lang.Throwable;
const Synchronizer = org.mozilla.javascript.Synchronizer;
const TimerThread = org.autojs.autojs.core.looper.TimerThread;
const rtThreads = runtime.threads;
let _ = {
Threads: ( /* @IIFE */ () => {
/**
* @implements Internal.Threads
*/
const Threads = function () {
// Empty interface body.
};
Threads.prototype = {
constructor: Threads,
atomic(value) {
return rtThreads.atomic.apply(rtThreads, arguments);
},
currentThread() {
return rtThreads.currentThread.apply(rtThreads, arguments);
},
disposable() {
return rtThreads.disposable.apply(rtThreads, arguments);
},
lock() {
return rtThreads.lock.apply(rtThreads, arguments);
},
interrupt(thread) {
if (thread instanceof TimerThread) {
thread.isAlive() && thread.interrupt();
}
},
start(runnable) {
try {
// noinspection JSCheckFunctionSignatures
return rtThreads.start(runnable);
} catch (e) {
if (!ScriptInterruptedException.causedByInterrupted(new Throwable(e))) {
if (!e.message.endsWith(context.getString(R.strings.error_script_is_on_exiting))) {
throw Error(`${e}\n${e.stack}`);
}
}
}
},
};
Object.setPrototypeOf(Threads.prototype, scriptRuntime.threads);
return Threads;
})(),
scopeAugment() {
Object.assign(scope, {
/**
* @global
*/
sync(func, lock) {
return new Synchronizer(func, lock || null);
},
});
},
promiseAugment() {
/**
* @implements Internal.Threads.PromiseExtension
*/
const PromiseExtension = function () {
// Empty interface body.
};
Object.assign(PromiseExtension.prototype, {
wait() {
let disposable = scriptRuntime.threads.disposable();
this
.then(result => disposable.setAndNotify({ result: result }))
.catch(error => disposable.setAndNotify({ error: error }));
let resultObj = disposable.blockedGet();
if (resultObj.error) {
throw resultObj.error;
}
return resultObj.result;
},
});
Object.assign(Promise.prototype, PromiseExtension.prototype);
},
};
/**
* @type {Internal.Threads}
*/
const threads = new _.Threads();
_.scopeAugment();
_.promiseAugment();
return threads;
};

View File

@@ -0,0 +1,86 @@
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Timers}
*/
module.exports = function (scriptRuntime, scope) {
let _ = {
Timers: (() => {
/**
* @implements Internal.Timers
*/
const Timers = function () {
// Empty interface body.
};
Timers.prototype = {
constructor: Timers,
setIntervalExt(listener, interval, timeout, callback) {
let $ = {
initTimestamp: Date.now(),
interval: interval > 0 ? interval : 200,
timeout: timeout > 0 ? timeout : Infinity,
setIntervalExt() {
return setTimeout(this.run.bind(this), this.interval);
},
run() {
listener();
this.relayIFN();
},
relayIFN() {
if (!this.isTimedOut()) {
this.setIntervalExt();
} else if (typeof callback === 'function') {
callback.call(this, this.timeoutResult);
}
},
isTimedOut() {
if (typeof this.isTimedOutCache !== 'function') {
this.isTimedOutCache = typeof timeout === 'function'
? timeout.bind(this)
: () => Date.now() - this.initTimestamp > this.timeout;
}
this.timeoutResult = this.isTimedOutCache();
return this.timeoutResult !== false && !isNullish(this.timeoutResult);
},
};
return $.setIntervalExt();
},
};
Object.setPrototypeOf(Timers.prototype, scriptRuntime.timers);
return Timers;
})(),
scopeAugment() {
/**
* @type {(keyof Internal.Timers)[]}
*/
let methods = [
'setTimeout', 'clearTimeout',
'setInterval', 'clearInterval',
'setImmediate', 'clearImmediate',
];
__asGlobal__(scriptRuntime.timers, methods);
Object.assign(scope, {
/**
* @global
*/
loop() {
return scriptRuntime.console.warn('Method loop() is deprecated and has no effect.');
},
});
},
};
/**
* @type {Internal.Timers}
*/
const timers = new _.Timers();
_.scopeAugment();
return timers;
};

View File

@@ -0,0 +1,416 @@
// noinspection NpmUsedModulesInstalled,JSUnusedGlobalSymbols,JSUnusedLocalSymbols
/* Overwritten protection. */
let { files } = global;
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.UI}
*/
module.exports = function (scriptRuntime, scope) {
const Looper = android.os.Looper;
const Runnable = java.lang.Runnable;
const Color = android.graphics.Color;
const ContextThemeWrapper = android.view.ContextThemeWrapper;
const ViewExtras = org.autojs.autojs.core.ui.ViewExtras;
const JsListView = org.autojs.autojs.core.ui.widget.JsListView;
const JsGridView = org.autojs.autojs.core.ui.widget.JsGridView;
const JsViewHelper = org.autojs.autojs.core.ui.JsViewHelper;
const DynamicLayoutInflater = org.autojs.autojs.core.ui.inflater.DynamicLayoutInflater;
require('object-observe-lite.min').call(scope);
require('array-observe.min').call(scope);
// noinspection JSValidateTypes
let _ = {
// @Coerce by SuperMonster003 on Nov 9, 2022.
/** @type {Internal.UI} */
rtUi: ( /* @IIFE */ () => {
let inRtUi = scriptRuntime.ui;
inRtUi.bindingContext = scope;
inRtUi.__proxy__ = {
set(name, value) {
uiProxy[name] = value;
},
get(name) {
if (!uiProxy[name] && uiProxy.view) {
let view = uiProxy.findById(name);
if (view) {
return view;
}
}
return uiProxy[name];
},
};
return inRtUi;
})(),
UI: ( /* @IIFE */ () => {
/**
* @extends Internal.UI
*/
const UI = function () {
// Empty class body.
};
UI.prototype = {
constructor: UI,
__widgets__: {},
Widget: ( /* @IIFE */ () => {
/**
* @extends Internal.UI.Widget
*/
let Widget = function () {
this.__attrs__ = {};
return Object.assign(function () {
// Empty interface body.
}, Widget.prototype);
};
Widget.prototype = {
constructor: Widget,
renderInternal() {
if (typeof this.render === 'function') {
return this.render.call(this);
}
return '< />';
},
defineAttr(attrName, getter, setter) {
//// -=-= PENDING =-=- ////
let attrAlias = attrName;
let applier;
if (typeof arguments[1] === 'string') {
attrAlias = arguments[1];
if (arguments.length >= 3) {
applier = arguments[2];
}
} else if (typeof arguments[1] === 'function' && typeof arguments[2] !== 'function') {
applier = arguments[1];
}
if (!(typeof arguments[1] === 'function' && typeof arguments[2] === 'function')) {
getter = () => {
return this[attrAlias];
};
setter = (view, attrName, value, setter) => {
this[attrAlias] = value;
if (typeof applier === 'function') {
applier(view, attrName, value, setter);
}
};
}
this.__attrs__[attrName] = {
getter: getter,
setter: setter,
};
},
hasAttr(attrName) {
return this.__attrs__.hasOwnProperty(attrName);
},
setAttr(view, attrName, value, setter) {
this.__attrs__[attrName].setter(view, attrName, value, setter);
},
getAttr(view, attrName, getter) {
return this.__attrs__[attrName].getter(view, attrName, getter);
},
notifyViewCreated(view) {
if (typeof this.onViewCreated === 'function') {
this.onViewCreated.call(this, view);
}
},
notifyAfterInflation(view) {
if (typeof this.onFinishInflation === 'function') {
this.onFinishInflation.call(this, view);
}
},
};
return Widget;
})(),
get R() {
return scope.R;
},
get emitter() {
return typeof activity !== 'undefined' ? activity.getEventEmitter() : null;
},
__inflate__(ctx, xml, parent, isAttachedToParent) {
return layoutInflater.inflate(ctx, _.toXMLString(xml), parent || null, Boolean(isAttachedToParent));
},
inflate(xml, parent, isAttachedToParent) {
layoutInflater.setContext(typeof activity === 'undefined'
? new ContextThemeWrapper(context, R.style.ScriptTheme)
: activity);
return layoutInflater.inflate(_.toXMLString(xml), parent || null, Boolean(isAttachedToParent));
},
run(action) {
if (this.isUiThread()) {
return action();
}
let error, result;
let disposable = scope.threads.disposable();
scriptRuntime.getUiHandler().post(() => {
try {
result = action();
} catch (e) {
error = e;
} finally {
disposable.setAndNotify(true);
}
});
disposable.blockedGet();
if (error instanceof Error) {
scriptRuntime.console.warn(`${species(error)} occurred in \`ui.run()\`.`);
scriptRuntime.console.warn(error.message);
scriptRuntime.console.warn(error.stack);
throw error;
}
return result;
},
post(action, delay) {
if (delay === undefined) {
scriptRuntime.getUiHandler().post(_.wrapUiAction(action));
} else {
scriptRuntime.getUiHandler().postDelayed(_.wrapUiAction(action), delay);
}
},
layout(layout) {
_.ensureActivity();
layoutInflater.setContext(activity);
// noinspection JSCheckFunctionSignatures
this.setContentView(layoutInflater.inflate(layout, activity.window.decorView, false));
},
layoutFile(path) {
this.layout(files.read(path));
},
isUiThread() {
return Looper.myLooper() === Looper.getMainLooper();
},
registerWidget(name, widget) {
if (typeof widget !== 'function') {
throw TypeError('Param "widget" should be a class-like function');
}
this.__widgets__[name] = widget;
},
setContentView(view) {
_.ensureActivity();
this.view = view;
this.run(() => activity.setContentView(view));
},
statusBarColor(color) {
_.ensureActivity();
let colorInt = ( /* @IIFE */ () => {
if (typeof color === 'string') {
if (Number(color).toString() === color) {
color = Number(color);
}
}
if (typeof color === 'number') {
return color;
}
return scriptRuntime.colors.parseColor(String(color));
})();
this.run(() => activity.window.setStatusBarColor(colorInt));
},
findById(id) {
return this.view ? this.findByStringId(this.view, id) : null;
},
findByStringId(view, id) {
return JsViewHelper.findViewByStringId(view, id);
},
findView(id) {
return this.findById(id);
},
finish() {
_.ensureActivity();
this.run(() => activity.finish());
},
};
return UI;
})(),
/**
* @type {org.autojs.autojs.core.ui.inflater.LayoutInflaterDelegate}
*/
layoutInflaterDelegate: {
beforeConvertXml(context, xml) {
return null;
},
afterConvertXml(context, xml) {
return xml;
},
beforeInflation(context, xml, parent) {
return null;
},
afterInflation(context, result, xml, parent) {
return result;
},
beforeInflateView(context, node, parent, attachToParent) {
return null;
},
afterInflateView(context, view, node, parent, attachToParent) {
let { widget } = view;
if (widget && context.get('root') !== widget) {
widget.notifyAfterInflation(view);
}
return view;
},
beforeCreateView(context, node, viewName, parent, attrs) {
if (uiProxy.__widgets__.hasOwnProperty(viewName)) {
let Widget = uiProxy.__widgets__[viewName];
let widget = new Widget();
let ctx = layoutInflater.newInflateContext();
ctx.put('root', widget);
ctx.put('widget', widget);
return uiProxy.__inflate__(ctx, widget.renderInternal(), parent, false);
}
return null;
},
afterCreateView(context, view, node, viewName, parent, attrs) {
if (view instanceof JsListView || view instanceof JsGridView) {
_.initListView(view);
}
let widget = context.get('widget');
if (widget !== null) {
widget.view = view;
view.widget = widget;
ViewExtras.getViewAttributes(view, layoutInflater.getResourceParser()).setViewAttributeDelegate({
has: name => widget.hasAttr(name),
get: (view, name, getter) => widget.getAttr(view, name, getter),
set: (view, name, value, setter) => widget.setAttr(view, name, value, setter),
});
widget.notifyViewCreated(view);
}
return view;
},
beforeApplyAttributes(context, view, inflater, attrs, parent) {
return false;
},
afterApplyAttributes(context, view, inflater, attrs, parent) {
context.remove('widget');
},
beforeInflateChildren(context, inflater, node, parent) {
return false;
},
afterInflateChildren(context, inflater, node, parent) {
// Empty method body
},
beforeApplyPendingAttributesOfChildren(context, inflater, view) {
return false;
},
afterApplyPendingAttributesOfChildren(context, inflater, view) {
// Empty method body
},
beforeApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs) {
let isDynamic = layoutInflater.isDynamicValue(value);
return isDynamic && layoutInflater.getInflateFlags() === DynamicLayoutInflater.FLAG_IGNORES_DYNAMIC_ATTRS
|| !isDynamic && layoutInflater.getInflateFlags() === DynamicLayoutInflater.FLAG_JUST_DYNAMIC_ATTRS
|| ( /* @IIFE */ () => {
value = _.bind(value);
let widget = context.get('widget');
if (widget !== null && widget.hasAttr(attrName)) {
widget.setAttr(view, attrName, value, (view, attrName, value) => {
inflater.setAttr(view, ns, attrName, value, parent, attrs);
});
} else {
inflater.setAttr(view, ns, attrName, value, parent, attrs);
}
this.afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs);
return true;
})();
},
afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs) {
// Empty method body
},
},
bind(value) {
let ctx = this.rtUi.bindingContext;
if (ctx !== null) {
let i = -1;
while ((i = value.indexOf('{{', i + 1)) >= 0) {
let j = value.indexOf('}}', i + 1);
if (j < 0) {
return value;
}
value = value.slice(0, i) + _.evalInContext(value.slice(i + 2, j), ctx) + value.slice(j + 2);
i = j + 1;
}
return value;
}
},
toXMLString(xml) {
// noinspection JSTypeOfValues
if (typeof xml === 'xml') {
xml = xml.toXMLString();
}
return xml.toString();
},
evalInContext(expression, ctx) {
return __exitIfError__(() => {
// @ScopeBinding
// noinspection WithStatementJS
with (ctx) {
return ( /* @IIFE */ function () {
return eval(expression);
})();
}
});
},
initListView(list) {
list.setDataSourceAdapter({
getItemCount(data) {
return data.length;
},
getItem(data, i) {
return data[i];
},
setDataSource(data) {
let adapter = list.getAdapter();
Array.observe(data, function (changes) {
changes.forEach((change) => {
if (change.type === 'splice') {
if (change.removed && change.removed.length > 0) {
adapter.notifyItemRangeRemoved(change.index, change.removed.length);
}
if (change.addedCount > 0) {
adapter.notifyItemRangeInserted(change.index, change.addedCount);
}
} else if (change.type === 'update') {
try {
adapter.notifyItemChanged(parseInt(change.name));
} catch (e) {
// Ignored.
}
}
});
});
},
});
},
wrapUiAction(action) {
return new Runnable({
run: () => typeof activity !== 'undefined' ? action() : __exitIfError__(action),
});
},
ensureActivity() {
if (typeof activity === 'undefined') {
throw ReferenceError('An activity is needed. Try running in "ui" thread');
}
},
setLayoutInflaterDelegate() {
layoutInflater.setLayoutInflaterDelegate(this.layoutInflaterDelegate);
},
};
/**
* @type {Internal.UI}
*/
const ui = _.rtUi;
const uiProxy = new _.UI();
const layoutInflater = ui.layoutInflater;
_.setLayoutInflaterDelegate();
return ui;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
// noinspection JSUnusedGlobalSymbols
/**
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
* @param {org.mozilla.javascript.Scriptable | global} scope
* @return {Internal.Web}
*/
module.exports = function (scriptRuntime, scope) {
const Context = org.mozilla.javascript.Context;
const InjectableWebView = org.autojs.autojs.core.web.InjectableWebView;
const InjectableWebClient = org.autojs.autojs.core.web.InjectableWebClient;
let _ = {
Web: ( /* @IIFE */ () => {
/**
* @implements Internal.Web
*/
const Web = function () {
// Empty interface body.
};
Web.prototype = {
constructor: Web,
};
return Web;
})(),
scopeAugment() {
Object.assign(scope, {
/**
* @global
*/
newInjectableWebClient() {
return new InjectableWebClient(Context.getCurrentContext(), scope);
},
/**
* @global
*/
newInjectableWebView(activity) {
let ctx = activity || scope.activity;
return new InjectableWebView(ctx, Context.getCurrentContext(), scope);
},
});
},
};
/**
* @type {Internal.Web}
*/
const web = new _.Web();
_.scopeAugment();
return web;
};

View File

@@ -0,0 +1,3 @@
module.exports = function(){
Object.observe&&!Array.observe&&function(t,e){"use strict";var n=t.getNotifier,r="performChange",i="_original",o="splice";var u={push:function h(t){var e=arguments,u=h[i].apply(this,e);n(this)[r](o,function(){return{index:u-e.length,addedCount:e.length,removed:[]}});return u},unshift:function d(t){var e=arguments,u=d[i].apply(this,e);n(this)[r](o,function(){return{index:0,addedCount:e.length,removed:[]}});return u},pop:function a(){var t=this.length,e=a[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:this.length,addedCount:0,removed:[e]}},this);return e},shift:function l(){var t=this.length,e=l[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:0,addedCount:0,removed:[e]}},this);return e},splice:function f(t,e){var u=arguments,s=f[i].apply(this,u);if(s.length||u.length>2)n(this)[r](o,function(){return{index:t,addedCount:u.length-2,removed:s}},this);return s}};for(var s in u){u[s][i]=e.prototype[s];e.prototype[s]=u[s]}e.observe=function(e,n){return t.observe(e,n,["add","update","delete",o])};e.unobserve=t.unobserve}(Object,Array);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,282 @@
// noinspection JSUnusedGlobalSymbols
/**
* Copyright 2014-2016 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Since we intend to use the Function constructor.
/* jshint evil: true */
( /* @ModuleIIFE */ () => {
const File = java.io.File;
const Scanner = java.util.Scanner;
const System = java.lang.System;
const Thread = java.lang.Thread;
let _ = {
Module: ( /* @IIFE */ () => {
/**
* @extends Internal.Require.Module
*/
const Module = function (id, parent, core) {
this._exports = {};
this.id = id;
this.core = core;
this.parent = parent;
this.children = [];
this.filename = id;
this.loaded = false;
Object.defineProperty(this, 'exports', {
get() {
return this._exports;
},
set(val) {
require.cache[this.filename] = val;
this._exports = val;
},
});
this.exports = {};
if (parent && parent.children) {
parent.children.push(this);
}
this.require = function (id) {
return require(id, this);
}.bind(this);
};
Object.assign(Module, {
require(id, parent) {
return require(id, parent);
},
_load(file) {
return NativeRequire.require(file);
},
runMain(main) {
return Module._load(require.resolve(main));
},
});
return Module;
})(),
RequireCtor: ( /* @IIFE */ () => {
/**
* @implements Internal.Require
*/
const RequireCtor = function () {
return Object.assign(function (id, parent) {
const normalizedPath = _.normalizeName(id);
if (_.builtInModules.includes(normalizedPath) && !runtime.files.exists(normalizedPath)) {
return NativeRequire.require(normalizedPath);
}
if (id === 'events') {
return global[id];
}
// noinspection HttpUrlsUsage
if (id.startsWith('http://') || id.startsWith('https://')) {
return NativeRequire.require(id);
}
let file = this.resolve(id, parent);
if (!file) {
if (typeof NativeRequire.require === 'function') {
if (this.debug) {
System.out.println([ 'Cannot resolve', id, 'defaulting to native' ].join(' '));
}
let nativeRequired = NativeRequire.require(id);
if (nativeRequired) {
return nativeRequired;
}
}
if (this.debug) {
System.err.println('Cannot find module ' + id);
}
throw new _.ModuleError('Cannot find module ' + id, 'MODULE_NOT_FOUND');
}
if (file.core) {
file = file.path;
}
if (this.cache[file]) {
return this.cache[file];
}
if (file.endsWith('.js')) {
return _.Module._load(file, parent);
}
if (file.endsWith('.json')) {
return _.loadJSON(file);
}
}.bind(this), RequireCtor.prototype);
};
Object.assign(RequireCtor.prototype, {
NODE_PATH: undefined,
// System.getProperty('user.dir');
root: runtime.files.cwd(),
debug: true,
cache: {},
extensions: {},
resolve(id, parent) {
const roots = _.findRoots(parent);
for (let i = 0; i < roots.length; ++i) {
const root = roots[i];
const result = _.resolveCoreModule(id)
|| _.resolveAsFile(id, root, '.js')
|| _.resolveAsFile(id, root, '.json')
|| _.resolveAsDirectory(id, root)
|| _.resolveAsNodeModule(id, root);
if (result) {
return result;
}
}
return false;
},
paths() {
let r = [
System.getProperty('user.home') + '/.node_modules',
System.getProperty('user.home') + '/.node_libraries',
];
if (this.NODE_PATH) {
r = r.concat(_.parsePaths(this.NODE_PATH));
} else {
const { NODE_PATH } = System.getenv();
if (NODE_PATH) {
r = r.concat(_.parsePaths(NODE_PATH));
}
}
// r.push( $PREFIX + "/node/library" )
return r;
},
});
return RequireCtor;
})(),
ModuleError: ( /* @IIFE */ () => {
/**
* @param {?string} [message]
* @param {?string} [code]
* @param {?string} [cause]
* @extends Error
*/
const ModuleError = function (message, code, cause) {
this.message = message || 'Error loading module';
this.code = code || 'UNDEFINED';
this.cause = cause;
};
ModuleError.prototype = Object.assign(new Error(), { constructor: ModuleError });
return ModuleError;
})(),
builtInModules: [ 'lodash.js' ],
findRoots(parent) {
return [ this.findRoot(parent) ].concat(require.paths());
},
findRoot(parent) {
if (!parent || !parent.id) {
return require.root;
}
return (/* pathParts = */ parent.id.split(/[\/|\\,]+/g).slice(0, -1)).join(File.separator);
},
readFile(filename, core) {
try {
let input = core
? Thread.currentThread().getContextClassLoader().getResourceAsStream(filename)
: new File(filename);
// TODO: I think this is not very efficient
return new Scanner(input).useDelimiter('\\A').next();
} catch (e) {
throw new _.ModuleError(`Cannot read file [${filename}]: `, 'IO_ERROR', e);
}
},
parsePaths: (paths) => paths && paths !== ''
? paths.split(/* separator = */ System.getProperty('os.name').toLowerCase().includes('win') ? ';' : ':')
: [],
normalizeName(fileName, ext) {
if (fileName.endsWith('.json')) {
return fileName;
}
ext = ext || '.js';
if (!fileName.endsWith(ext)) {
fileName += ext;
}
return fileName;
},
loadJSON(file) {
return require.cache[file] = JSON.parse(this.readFile(file));
},
resolveCoreModule(id) {
const name = this.normalizeName(id);
if (Thread.currentThread().getContextClassLoader().getResource(name)) {
return { path: name, core: true };
}
},
resolveAsFile(id, root, ext) {
let file;
if (!id.startsWith(File.separator)) {
file = new File([ root, this.normalizeName(id, ext) ].join(File.separator));
if (!file.exists()) {
return;
}
} else {
file = new File(this.normalizeName(id, ext));
if (!file.exists()) {
return this.resolveAsDirectory(id);
}
}
return file.getCanonicalPath();
},
resolveAsDirectory(id, root) {
const base = [ root, id ].join(File.separator);
const file = new File([ base, 'package.json' ].join(File.separator));
if (file.exists()) {
try {
const body = this.readFile(file.getCanonicalPath());
const pkg = JSON.parse(body);
if (pkg.main) {
return this.resolveAsFile(pkg.main, base)
|| this.resolveAsDirectory(pkg.main, base);
}
return this.resolveAsFile('index.js', base);
} catch (ex) {
throw new _.ModuleError('Cannot load JSON file', 'PARSE_ERROR', ex);
}
}
return this.resolveAsFile('index.js', base);
},
resolveAsNodeModule(id, root) {
const base = [ root, 'node_modules' ].join(File.separator);
return this.resolveAsFile(id, base)
|| this.resolveAsDirectory(id, base)
|| (root ? this.resolveAsNodeModule(id, new File(root).getParent()) : false);
},
};
let NativeRequire = ( /* @IIFE */ function () {
const o = this['NativeRequire'] || {};
if (!o.require && typeof this.require === 'function') {
o.require = this.require;
}
return o;
}).call(global);
/**
* @type {Internal.Require}
*/
const require = global.require = new _.RequireCtor();
module.exports = _.Module;
})();

View File

@@ -0,0 +1,29 @@
/**
* @license
* Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
* Build: `lodash core -o ./dist/lodash.core.js`
*/
;(function(){function n(n){return H(n)&&pn.call(n,"callee")&&!yn.call(n,"callee")}function t(n,t){return n.push.apply(n,t),n}function r(n){return function(t){return null==t?Z:t[n]}}function e(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function u(n,t){return j(t,function(t){return n[t]})}function o(n){return n instanceof i?n:new i(n)}function i(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t}function c(n,t,r){if(typeof n!="function")throw new TypeError("Expected a function");
return setTimeout(function(){n.apply(Z,r)},t)}function f(n,t){var r=true;return mn(n,function(n,e,u){return r=!!t(n,e,u)}),r}function a(n,t,r){for(var e=-1,u=n.length;++e<u;){var o=n[e],i=t(o);if(null!=i&&(c===Z?i===i:r(i,c)))var c=i,f=o}return f}function l(n,t){var r=[];return mn(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function p(n,r,e,u,o){var i=-1,c=n.length;for(e||(e=R),o||(o=[]);++i<c;){var f=n[i];0<r&&e(f)?1<r?p(f,r-1,e,u,o):t(o,f):u||(o[o.length]=f)}return o}function s(n,t){return n&&On(n,t,Dn);
}function h(n,t){return l(t,function(t){return U(n[t])})}function v(n,t){return n>t}function b(n,t,r,e,u){return n===t||(null==n||null==t||!H(n)&&!H(t)?n!==n&&t!==t:y(n,t,r,e,b,u))}function y(n,t,r,e,u,o){var i=Nn(n),c=Nn(t),f=i?"[object Array]":hn.call(n),a=c?"[object Array]":hn.call(t),f="[object Arguments]"==f?"[object Object]":f,a="[object Arguments]"==a?"[object Object]":a,l="[object Object]"==f,c="[object Object]"==a,a=f==a;o||(o=[]);var p=An(o,function(t){return t[0]==n}),s=An(o,function(n){
return n[0]==t});if(p&&s)return p[1]==t;if(o.push([n,t]),o.push([t,n]),a&&!l){if(i)r=T(n,t,r,e,u,o);else n:{switch(f){case"[object Boolean]":case"[object Date]":case"[object Number]":r=J(+n,+t);break n;case"[object Error]":r=n.name==t.name&&n.message==t.message;break n;case"[object RegExp]":case"[object String]":r=n==t+"";break n}r=false}return o.pop(),r}return 1&r||(i=l&&pn.call(n,"__wrapped__"),f=c&&pn.call(t,"__wrapped__"),!i&&!f)?!!a&&(r=B(n,t,r,e,u,o),o.pop(),r):(i=i?n.value():n,f=f?t.value():t,
r=u(i,f,r,e,o),o.pop(),r)}function g(n){return typeof n=="function"?n:null==n?X:(typeof n=="object"?d:r)(n)}function _(n,t){return n<t}function j(n,t){var r=-1,e=M(n)?Array(n.length):[];return mn(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function d(n){var t=_n(n);return function(r){var e=t.length;if(null==r)return!e;for(r=Object(r);e--;){var u=t[e];if(!(u in r&&b(n[u],r[u],3)))return false}return true}}function m(n,t){return n=Object(n),C(t,function(t,r){return r in n&&(t[r]=n[r]),t},{})}function O(n){return xn(I(n,void 0,X),n+"");
}function x(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++e<u;)r[e]=n[e+t];return r}function A(n){return x(n,0,n.length)}function E(n,t){var r;return mn(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function w(n,r){return C(r,function(n,r){return r.func.apply(r.thisArg,t([n],r.args))},n)}function k(n,t,r){var e=!r;r||(r={});for(var u=-1,o=t.length;++u<o;){var i=t[u],c=Z;if(c===Z&&(c=n[i]),e)r[i]=c;else{var f=r,a=f[i];pn.call(f,i)&&J(a,c)&&(c!==Z||i in f)||(f[i]=c);
}}return r}function N(n){return O(function(t,r){var e=-1,u=r.length,o=1<u?r[u-1]:Z,o=3<n.length&&typeof o=="function"?(u--,o):Z;for(t=Object(t);++e<u;){var i=r[e];i&&n(t,i,e,o)}return t})}function F(n){return function(){var t=arguments,r=dn(n.prototype),t=n.apply(r,t);return V(t)?t:r}}function S(n,t,r){function e(){for(var o=-1,i=arguments.length,c=-1,f=r.length,a=Array(f+i),l=this&&this!==on&&this instanceof e?u:n;++c<f;)a[c]=r[c];for(;i--;)a[c++]=arguments[++o];return l.apply(t,a)}if(typeof n!="function")throw new TypeError("Expected a function");
var u=F(n);return e}function T(n,t,r,e,u,o){var i=n.length,c=t.length;if(i!=c&&!(1&r&&c>i))return false;for(var c=-1,f=true,a=2&r?[]:Z;++c<i;){var l=n[c],p=t[c];if(void 0!==Z){f=false;break}if(a){if(!E(t,function(n,t){if(!P(a,t)&&(l===n||u(l,n,r,e,o)))return a.push(t)})){f=false;break}}else if(l!==p&&!u(l,p,r,e,o)){f=false;break}}return f}function B(n,t,r,e,u,o){var i=1&r,c=Dn(n),f=c.length,a=Dn(t).length;if(f!=a&&!i)return false;for(var l=f;l--;){var p=c[l];if(!(i?p in t:pn.call(t,p)))return false}for(a=true;++l<f;){var p=c[l],s=n[p],h=t[p];
if(void 0!==Z||s!==h&&!u(s,h,r,e,o)){a=false;break}i||(i="constructor"==p)}return a&&!i&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(a=false)),a}function R(t){return Nn(t)||n(t)}function D(n){var t=[];if(null!=n)for(var r in Object(n))t.push(r);return t}function I(n,t,r){return t=jn(t===Z?n.length-1:t,0),function(){for(var e=arguments,u=-1,o=jn(e.length-t,0),i=Array(o);++u<o;)i[u]=e[t+u];for(u=-1,
o=Array(t+1);++u<t;)o[u]=e[u];return o[t]=r(i),n.apply(this,o)}}function $(n){return(null==n?0:n.length)?p(n,1):[]}function q(n){return n&&n.length?n[0]:Z}function P(n,t,r){var e=null==n?0:n.length;r=typeof r=="number"?0>r?jn(e+r,0):r:0,r=(r||0)-1;for(var u=t===t;++r<e;){var o=n[r];if(u?o===t:o!==o)return r}return-1}function z(n,t){return mn(n,g(t))}function C(n,t,r){return e(n,g(t),r,3>arguments.length,mn)}function G(n,t){var r;if(typeof t!="function")throw new TypeError("Expected a function");return n=Fn(n),
function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=Z),r}}function J(n,t){return n===t||n!==n&&t!==t}function M(n){var t;return(t=null!=n)&&(t=n.length,t=typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t),t&&!U(n)}function U(n){return!!V(n)&&(n=hn.call(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function V(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function H(n){return null!=n&&typeof n=="object"}function K(n){
return typeof n=="number"||H(n)&&"[object Number]"==hn.call(n)}function L(n){return typeof n=="string"||!Nn(n)&&H(n)&&"[object String]"==hn.call(n)}function Q(n){return typeof n=="string"?n:null==n?"":n+""}function W(n){return null==n?[]:u(n,Dn(n))}function X(n){return n}function Y(n,r,e){var u=Dn(r),o=h(r,u);null!=e||V(r)&&(o.length||!u.length)||(e=r,r=n,n=this,o=h(r,Dn(r)));var i=!(V(e)&&"chain"in e&&!e.chain),c=U(n);return mn(o,function(e){var u=r[e];n[e]=u,c&&(n.prototype[e]=function(){var r=this.__chain__;
if(i||r){var e=n(this.__wrapped__);return(e.__actions__=A(this.__actions__)).push({func:u,args:arguments,thisArg:n}),e.__chain__=r,e}return u.apply(n,t([this.value()],arguments))})}),n}var Z,nn=1/0,tn=/[&<>"']/g,rn=RegExp(tn.source),en=/^(?:0|[1-9]\d*)$/,un=typeof self=="object"&&self&&self.Object===Object&&self,on=typeof global=="object"&&global&&global.Object===Object&&global||un||Function("return this")(),cn=(un=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,fn=function(n){
return function(t){return null==n?Z:n[t]}}({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}),an=Array.prototype,ln=Object.prototype,pn=ln.hasOwnProperty,sn=0,hn=ln.toString,vn=on._,bn=Object.create,yn=ln.propertyIsEnumerable,gn=on.isFinite,_n=function(n,t){return function(r){return n(t(r))}}(Object.keys,Object),jn=Math.max,dn=function(){function n(){}return function(t){return V(t)?bn?bn(t):(n.prototype=t,t=new n,n.prototype=Z,t):{}}}();i.prototype=dn(o.prototype),i.prototype.constructor=i;
var mn=function(n,t){return function(r,e){if(null==r)return r;if(!M(r))return n(r,e);for(var u=r.length,o=t?u:-1,i=Object(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}(s),On=function(n){return function(t,r,e){var u=-1,o=Object(t);e=e(t);for(var i=e.length;i--;){var c=e[n?i:++u];if(false===r(o[c],c,o))break}return t}}(),xn=X,An=function(n){return function(t,r,e){var u=Object(t);if(!M(t)){var o=g(r);t=Dn(t),r=function(n){return o(u[n],n,u)}}return r=n(t,r,e),-1<r?u[o?t[r]:r]:Z}}(function(n,t,r){var e=null==n?0:n.length;
if(!e)return-1;r=null==r?0:Fn(r),0>r&&(r=jn(e+r,0));n:{for(t=g(t),e=n.length,r+=-1;++r<e;)if(t(n[r],r,n)){n=r;break n}n=-1}return n}),En=O(function(n,t,r){return S(n,t,r)}),wn=O(function(n,t){return c(n,1,t)}),kn=O(function(n,t,r){return c(n,Sn(t)||0,r)}),Nn=Array.isArray,Fn=Number,Sn=Number,Tn=N(function(n,t){k(t,_n(t),n)}),Bn=N(function(n,t){k(t,D(t),n)}),Rn=O(function(n,t){n=Object(n);var r,e=-1,u=t.length,o=2<u?t[2]:Z;if(r=o){r=t[0];var i=t[1];if(V(o)){var c=typeof i;if("number"==c){if(c=M(o))var c=o.length,f=typeof i,c=null==c?9007199254740991:c,c=!!c&&("number"==f||"symbol"!=f&&en.test(i))&&-1<i&&0==i%1&&i<c;
}else c="string"==c&&i in o;r=!!c&&J(o[i],r)}else r=false}for(r&&(u=1);++e<u;)for(o=t[e],r=In(o),i=-1,c=r.length;++i<c;){var f=r[i],a=n[f];(a===Z||J(a,ln[f])&&!pn.call(n,f))&&(n[f]=o[f])}return n}),Dn=_n,In=D,$n=function(n){return xn(I(n,Z,$),n+"")}(function(n,t){return null==n?{}:m(n,t)});o.assignIn=Bn,o.before=G,o.bind=En,o.chain=function(n){return n=o(n),n.__chain__=true,n},o.compact=function(n){return l(n,Boolean)},o.concat=function(){var n=arguments.length;if(!n)return[];for(var r=Array(n-1),e=arguments[0];n--;)r[n-1]=arguments[n];
return t(Nn(e)?A(e):[e],p(r,1))},o.create=function(n,t){var r=dn(n);return null==t?r:Tn(r,t)},o.defaults=Rn,o.defer=wn,o.delay=kn,o.filter=function(n,t){return l(n,g(t))},o.flatten=$,o.flattenDeep=function(n){return(null==n?0:n.length)?p(n,nn):[]},o.iteratee=g,o.keys=Dn,o.map=function(n,t){return j(n,g(t))},o.matches=function(n){return d(Tn({},n))},o.mixin=Y,o.negate=function(n){if(typeof n!="function")throw new TypeError("Expected a function");return function(){return!n.apply(this,arguments)}},o.once=function(n){
return G(2,n)},o.pick=$n,o.slice=function(n,t,r){var e=null==n?0:n.length;return r=r===Z?e:+r,e?x(n,null==t?0:+t,r):[]},o.sortBy=function(n,t){var e=0;return t=g(t),j(j(n,function(n,r,u){return{value:n,index:e++,criteria:t(n,r,u)}}).sort(function(n,t){var r;n:{r=n.criteria;var e=t.criteria;if(r!==e){var u=r!==Z,o=null===r,i=r===r,c=e!==Z,f=null===e,a=e===e;if(!f&&r>e||o&&c&&a||!u&&a||!i){r=1;break n}if(!o&&r<e||f&&u&&i||!c&&i||!a){r=-1;break n}}r=0}return r||n.index-t.index}),r("value"))},o.tap=function(n,t){
return t(n),n},o.thru=function(n,t){return t(n)},o.toArray=function(n){return M(n)?n.length?A(n):[]:W(n)},o.values=W,o.extend=Bn,Y(o,o),o.clone=function(n){return V(n)?Nn(n)?A(n):k(n,_n(n)):n},o.escape=function(n){return(n=Q(n))&&rn.test(n)?n.replace(tn,fn):n},o.every=function(n,t,r){return t=r?Z:t,f(n,g(t))},o.find=An,o.forEach=z,o.has=function(n,t){return null!=n&&pn.call(n,t)},o.head=q,o.identity=X,o.indexOf=P,o.isArguments=n,o.isArray=Nn,o.isBoolean=function(n){return true===n||false===n||H(n)&&"[object Boolean]"==hn.call(n);
},o.isDate=function(n){return H(n)&&"[object Date]"==hn.call(n)},o.isEmpty=function(t){return M(t)&&(Nn(t)||L(t)||U(t.splice)||n(t))?!t.length:!_n(t).length},o.isEqual=function(n,t){return b(n,t)},o.isFinite=function(n){return typeof n=="number"&&gn(n)},o.isFunction=U,o.isNaN=function(n){return K(n)&&n!=+n},o.isNull=function(n){return null===n},o.isNumber=K,o.isObject=V,o.isRegExp=function(n){return H(n)&&"[object RegExp]"==hn.call(n)},o.isString=L,o.isUndefined=function(n){return n===Z},o.last=function(n){
var t=null==n?0:n.length;return t?n[t-1]:Z},o.max=function(n){return n&&n.length?a(n,X,v):Z},o.min=function(n){return n&&n.length?a(n,X,_):Z},o.noConflict=function(){return on._===this&&(on._=vn),this},o.noop=function(){},o.reduce=C,o.result=function(n,t,r){return t=null==n?Z:n[t],t===Z&&(t=r),U(t)?t.call(n):t},o.size=function(n){return null==n?0:(n=M(n)?n:_n(n),n.length)},o.some=function(n,t,r){return t=r?Z:t,E(n,g(t))},o.uniqueId=function(n){var t=++sn;return Q(n)+t},o.each=z,o.first=q,Y(o,function(){
var n={};return s(o,function(t,r){pn.call(o.prototype,r)||(n[r]=t)}),n}(),{chain:false}),o.VERSION="4.17.15",mn("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:an)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n);o.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Nn(u)?u:[],n)}return this[r](function(r){return t.apply(Nn(r)?r:[],n);
})}}),o.prototype.toJSON=o.prototype.valueOf=o.prototype.value=function(){return w(this.__wrapped__,this.__actions__)},typeof define=="function"&&typeof define.amd=="object"&&define.amd?(on._=o, define(function(){return o})):cn?((cn.exports=o)._=o,un._=o):on._=o}).call(this);

View File

@@ -0,0 +1,3 @@
module.exports = function(){
Object.observe||function(e,t,n,r){var o,i,c=["add","update","delete","reconfigure","setPrototype","preventExtensions"],a=t.isArray||function(e){return function(t){return"[object Array]"===e.call(t)}}(e.prototype.toString),f=t.prototype.indexOf?t.indexOf||function(e,n,r){return t.prototype.indexOf.call(e,n,r)}:function(e,t,n){for(var r=n||0;r<e.length;r++)if(e[r]===t)return r;return-1},s=n.Map!==r&&Map.prototype.forEach?function(){return new Map}:function(){var e=[],t=[];return{size:0,has:function(t){return f(e,t)>-1},get:function(n){return t[f(e,n)]},set:function(n,r){var o=f(e,n);-1===o?(e.push(n),t.push(r),this.size++):t[o]=r},"delete":function(n){var r=f(e,n);r>-1&&(e.splice(r,1),t.splice(r,1),this.size--)},forEach:function(n){for(var r=0;r<e.length;r++)n.call(arguments[1],t[r],e[r],this)}}},u=e.getOwnPropertyNames?function(){var t=e.getOwnPropertyNames;try{arguments.callee}catch(n){var r=(t(f).join(" ")+" ").replace(/prototype |length |name /g,"").slice(0,-1).split(" ");r.length&&(t=function(t){var n=e.getOwnPropertyNames(t);if("function"==typeof t)for(var o,i=0;i<r.length;)(o=f(n,r[i++]))>-1&&n.splice(o,1);return n})}return t}():function(t){var n,r,o=[];if("hasOwnProperty"in t)for(n in t)t.hasOwnProperty(n)&&o.push(n);else{r=e.hasOwnProperty;for(n in t)r.call(t,n)&&o.push(n)}return a(t)&&o.push("length"),o},p=n.requestAnimationFrame||n.webkitRequestAnimationFrame||function(){var e=+new Date,t=e;return function(n){return setTimeout(function(){n((t=+new Date)-e)},17)}}(),l=function(e,t,n){var r=o.get(e);r?(v(r,e),g(e,r,t,n)):(r=h(e),g(e,r,t,n),1===o.size&&p(d))},h=function(e,t){for(var n=u(e),r=[],i=0,t={handlers:s(),properties:n,values:r,notifier:b(e,t)};i<n.length;)r[i]=e[n[i++]];return o.set(e,t),t},v=function(e,t,n){if(e.handlers.size){var r,o,i,c,a,s,p,l=e.values,h=0;for(r=e.properties.slice(),o=r.length,i=u(t);h<i.length;)a=i[h++],c=f(r,a),s=t[a],-1===c?(w(t,e,{name:a,type:"add",object:t},n),e.properties.push(a),l.push(s)):(p=l[c],r[c]=null,o--,(p===s?0===p&&1/p!==1/s:p===p||s===s)&&(w(t,e,{name:a,type:"update",object:t,oldValue:p},n),e.values[c]=s));for(h=r.length;o&&h--;)null!==r[h]&&(w(t,e,{name:r[h],type:"delete",object:t,oldValue:l[h]},n),e.properties.splice(h,1),e.values.splice(h,1),o--)}},d=function(){o.size&&(o.forEach(v),i.forEach(y),p(d))},y=function(e,t){var n=e.changeRecords;n.length&&(e.changeRecords=[],t(n))},b=function(e,t){return arguments.length<2&&(t=o.get(e)),t&&t.notifier||{notify:function(t){t.type;var n=o.get(e);if(n){var r,i={object:e};for(r in t)"object"!==r&&(i[r]=t[r]);w(e,n,i)}},performChange:function(t,n){if("string"!=typeof t)throw new TypeError("Invalid non-string changeType");if("function"!=typeof n)throw new TypeError("Cannot perform non-function");var i,c,a=o.get(e),f=arguments[2],s=f===r?n():n.call(f);if(a&&v(a,e,t),a&&s&&"object"==typeof s){c={object:e,type:t};for(i in s)"object"!==i&&"type"!==i&&(c[i]=s[i]);w(e,a,c)}}}},g=function(e,t,n,r){var o=i.get(n);o||i.set(n,o={observed:s(),changeRecords:[]}),o.observed.set(e,{acceptList:r.slice(),data:t}),t.handlers.set(n,o)},w=function(e,t,n,r){t.handlers.forEach(function(t){var o=t.observed.get(e).acceptList;("string"!=typeof r||-1===f(o,r))&&f(o,n.type)>-1&&t.changeRecords.push(n)})};o=s(),i=s(),e.observe=function(t,n,o){if(!t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.observe cannot observe non-object");if("function"!=typeof n)throw new TypeError("Object.observe cannot deliver to non-function");if(e.isFrozen&&e.isFrozen(n))throw new TypeError("Object.observe cannot deliver to a frozen function object");if(o===r)o=c;else if(!o||"object"!=typeof o)throw new TypeError("Third argument to Object.observe must be an array of strings.");return l(t,n,o),t},e.unobserve=function(e,t){if(null===e||"object"!=typeof e&&"function"!=typeof e)throw new TypeError("Object.unobserve cannot unobserve non-object");if("function"!=typeof t)throw new TypeError("Object.unobserve cannot deliver to non-function");var n,r=i.get(t);return r&&(n=r.observed.get(e))&&(r.observed.forEach(function(e,t){v(e.data,t)}),p(function(){y(r,t)}),1===r.observed.size&&r.observed.has(e)?i["delete"](t):r.observed["delete"](e),1===n.data.handlers.size?o["delete"](e):n.data.handlers["delete"](t)),e},e.getNotifier=function(t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.getNotifier cannot getNotifier non-object");return e.isFrozen&&e.isFrozen(t)?null:b(t)},e.deliverChangeRecords=function(e){if("function"!=typeof e)throw new TypeError("Object.deliverChangeRecords cannot deliver to non-function");var t=i.get(e);t&&(t.observed.forEach(function(e,t){v(e.data,t)}),y(t,e))}}(Object,Array,this);
}

View File

@@ -0,0 +1,47 @@
module.exports = {
fill() {
// @Comment by SuperMonster003 on May 6, 2022.
// ! Already implemented in Rhino 1.7.15-SNAPSHOT as of Mar 18, 2022.
// if (!Object.getOwnPropertyDescriptors) {
// /**
// * @param {Object} o
// * @return {Object.<string,PropertyDescriptor>} <!-- or {PropertyDescriptorMap} -->
// */
// Object.getOwnPropertyDescriptors = function (o) {
// let descriptor = {};
// Object.getOwnPropertyNames(o).forEach((k) => {
// descriptor[k] = Object.getOwnPropertyDescriptor(o, k);
// });
// return descriptor;
// };
// }
if (!Array.prototype.flat) {
Object.defineProperty(Array.prototype, 'flat', {
value(depth) {
return ( /* @IIFE */ function flat(arr, d) {
return d <= 0 ? arr : arr.reduce((a, b) => {
return a.concat(Array.isArray(b) ? flat(b, d - 1) : b);
}, []);
})(this.slice(), Math.max(Number(depth) || 0, 1));
},
});
}
if (!Array.prototype.at) {
Object.defineProperty(Array.prototype, 'at', {
value(index) {
let relIdx = ( /* @IIFE */ () => {
const num = Number(index);
return isNaN(num) ? 0 : isFinite(num) ? Math.trunc(num) : num;
})();
let idx = relIdx >= 0 ? relIdx : relIdx + this.length;
return idx >= 0 && idx < this.length ? this[idx] : void 0;
},
});
}
},
};

View File

@@ -0,0 +1,305 @@
// noinspection JSUnusedGlobalSymbols
/**
* Updated and modified by SuperMonster003 on May 23, 2022.
* @see https://raw.githubusercontent.com/taylorhakes/promise-polyfill/master/dist/polyfill.js
*/
'use strict';
/**
* @type {PromiseConstructorLike}
*/
module.exports = ( /* @IIFE */ () => {
let _ = {
isArray(x) {
return Boolean(x && typeof x.length !== 'undefined');
},
noop() {
},
// Polyfill for Function.prototype.bind
bind(fn, thisArg) {
return function () {
fn.apply(thisArg, arguments);
};
},
handle(self, deferred) {
while (self._state === 3) {
self = self._value;
}
if (self._state === 0) {
self._deferreds.push(deferred);
return;
}
self._handled = true;
Promise._immediateFn(function () {
let cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
if (cb === null) {
(self._state === 1 ? _.resolve : _.reject)(deferred.promise, self._value);
return;
}
let ret;
try {
ret = cb(self._value);
} catch (e) {
_.reject(deferred.promise, e);
return;
}
_.resolve(deferred.promise, ret);
});
},
resolve(self, newValue) {
try {
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === self) {
// noinspection ExceptionCaughtLocallyJS
throw new TypeError('A promise cannot be resolved with itself.');
}
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
let then = newValue.then;
if (newValue instanceof Promise) {
self._state = 3;
self._value = newValue;
_.finale(self);
return;
} else if (typeof then === 'function') {
_.doResolve(_.bind(then, newValue), self);
return;
}
}
self._state = 1;
self._value = newValue;
_.finale(self);
} catch (e) {
_.reject(self, e);
}
},
reject(self, newValue) {
self._state = 2;
self._value = newValue;
_.finale(self);
},
finale(self) {
if (self._state === 2 && self._deferreds.length === 0) {
Promise._immediateFn(function () {
if (!self._handled) {
Promise._unhandledRejectionFn(self._value);
}
});
}
for (let i = 0, len = self._deferreds.length; i < len; i++) {
_.handle(self, self._deferreds[i]);
}
self._deferreds = null;
},
/**
* @constructor
*/
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.
*/
doResolve(fn, self) {
let done = false;
try {
fn(
function (value) {
if (done) return;
done = true;
_.resolve(self, value);
},
function (reason) {
if (done) return;
done = true;
_.reject(self, reason);
},
);
} catch (ex) {
if (done) return;
done = true;
_.reject(self, ex);
}
},
};
/**
* @constructor
* @param {Function} fn
*/
let Promise = function (fn) {
if (!(this instanceof Promise)) {
throw new TypeError('Promises must be constructed via new');
}
if (typeof fn !== 'function') {
throw new TypeError('not a function');
}
/** @type {!number} */
this._state = 0;
/** @type {!boolean} */
this._handled = false;
/** @type {Promise|undefined} */
this._value = undefined;
/** @type {!Array<!Function>} */
this._deferreds = [];
_.doResolve(fn, this);
};
Object.assign(Promise.prototype, {
catch(onRejected) {
return this.then(null, onRejected);
},
then(onFulfilled, onRejected) {
let prom = new this.constructor(_.noop);
_.handle(this, new _.Handler(onFulfilled, onRejected, prom));
return prom;
},
finally(callback) {
let constructor = this.constructor;
return this.then(
function (value) {
return constructor.resolve(callback()).then(function () {
return value;
});
},
function (reason) {
return constructor.resolve(callback()).then(function () {
return constructor.reject(reason);
});
},
);
},
});
Object.assign(Promise, {
// Use polyfill for setImmediate for performance gains
_immediateFn(fn) {
typeof setImmediate === 'function'
? setImmediate(fn)
: setTimeout(fn, 0);
},
_unhandledRejectionFn(err) {
if (typeof console !== 'undefined') {
console.warn('Possible Unhandled Promise Rejection:', err);
}
},
all(arr) {
return new Promise(function (resolve, reject) {
if (!_.isArray(arr)) {
return reject(new TypeError('Promise.all accepts an array'));
}
let args = Array.prototype.slice.call(arr);
let remaining = args.length;
if (remaining === 0) {
return resolve([]);
}
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
let then = val.then;
if (typeof then === 'function') {
then.call(
val,
function (val) {
res(i, val);
},
reject,
);
return;
}
}
args[i] = val;
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex);
}
}
for (let i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
},
allSettled(arr) {
let P = this;
return new P(function (resolve, reject) {
if (!(arr && typeof arr.length !== 'undefined')) {
let msg = `${typeof arr} ${arr} is not iterable (cannot read property Symbol(Symbol.iterator))`;
return reject(new TypeError(msg));
}
let args = Array.prototype.slice.call(arr);
let remaining = args.length;
if (remaining === 0) {
return resolve([]);
}
function res(i, val) {
if (val && (typeof val === 'object' || typeof val === 'function')) {
let then = val.then;
if (typeof then === 'function') {
then.call(
val,
function (val) {
res(i, val);
},
function (e) {
args[i] = {status: 'rejected', reason: e};
if (--remaining === 0) {
resolve(args);
}
},
);
return;
}
}
args[i] = {status: 'fulfilled', value: val};
if (--remaining === 0) {
resolve(args);
}
}
for (let i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
},
resolve(value) {
if (value && typeof value === 'object' && value.constructor === Promise) {
return value;
}
return new Promise(function (resolve) {
resolve(value);
});
},
reject(value) {
return new Promise(function (resolve, reject) {
reject(value);
});
},
race(arr) {
return new Promise(function (resolve, reject) {
if (!_.isArray(arr)) {
return reject(new TypeError('Promise.race accepts an array'));
}
for (let i = 0, len = arr.length; i < len; i++) {
Promise.resolve(arr[i]).then(resolve, reject);
}
});
},
});
return Promise;
})();

View File

@@ -0,0 +1,89 @@
( /* @ModuleIIFE */ () => {
const Looper = android.os.Looper;
let _ = {
isUiThread() {
return Looper.myLooper() === Looper.getMainLooper();
},
getOrThrow(result) {
if (result.error) {
throw result.error;
}
return result.result;
},
};
/**
* @class
* @extends {Internal.ResultAdapter}
*/
let ResultAdapter = _.isUiThread()
? function () {
this.cont = continuation.create();
this.impl = {
setResult: result => this.cont.resume(result),
setError: error => this.cont.resumeError(error),
get: () => this.cont.await(),
};
}
: function () {
this.disposable = runtime.threads.disposable();
this.impl = {
setResult: result => this.disposable.setAndNotify({ result }),
setError: error => this.disposable.setAndNotify({ error }),
get: () => _.getOrThrow(this.disposable.blockedGet()),
};
};
Object.assign(ResultAdapter, {
prototype: {
constructor: ResultAdapter,
setResult(result) {
this.impl.setResult(result);
},
setError(error) {
this.impl.setError(error);
},
callback() {
return function (result, error) {
this.result !== undefined
? this.result = { result, error }
: error ? this.setError(error) : this.setResult(result);
}.bind(this);
},
get() {
if (this.result) {
return _.getOrThrow(this.result);
}
this.result = null;
return this.impl.get();
},
},
/**
* @param {org.autojs.autojs.runtime.api.ScriptPromiseAdapter} promiseAdapter
* @return {Promise<unknown>}
*/
promise(promiseAdapter) {
return new Promise((resolve, reject) => {
promiseAdapter
.onResolve(result => resolve(result))
.onReject(error => reject(error));
});
},
/**
* @param {Promise<unknown> | org.autojs.autojs.runtime.api.ScriptPromiseAdapter} promise
* @return {*}
*/
wait(promise) {
if (!(promise instanceof Promise)) {
promise = ResultAdapter.promise(promise);
}
return continuation.enabled ? promise.await() : promise.wait();
},
});
/**
* @type {typeof Internal.ResultAdapter}
*/
module.exports = ResultAdapter;
})();

View File

@@ -0,0 +1,5 @@
/**
* Reserved for legacy usage with old module name.
* @type {typeof Internal.ResultAdapter}
*/
module.exports = require('result-adapter');