Files
AutoJs6/app/src/main/assets/modules/__globals__.js

550 lines
21 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// noinspection JSUnusedGlobalSymbols
/* Overwritten protection. */
let { autojs, console, device, pickup, ui, s13n, 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`). */
/**
* @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} }.`);
}
},
},
buildTypes: {
release: 100, beta: 50, alpha: 0,
},
extensions: {
/** @global */
get WIDTH() {
return ScreenMetrics.getDeviceScreenWidth();
},
/** @global */
get HEIGHT() {
return ScreenMetrics.getDeviceScreenHeight();
},
/** @global */
toastLog(msg, isLong, isForcible) {
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 {
runtime.exit(s13n.throwable(e));
}
},
/** @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 (species.isObject(arguments[1])) {
// @Overload wait(condition, callback): any
return this.wait(condition, /* limit = */ null, /* interval = */ null, /* callback = */ arguments[1]);
}
if (species.isObject(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);
},
// $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;
},
},
legacies: {
isObjectSpecies(o) {
return species.isObject(o);
},
},
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, _.legacies);
// Object.keys(_.extensions)
// .filter(key => !key.startsWith('$'))
// .forEach((key) => {
// Object.defineProperty(scope, key, {
// enumerable: true,
// configurable: false,
// writable: false,
// });
// });
};