diff --git a/app/src/main/assets/sample/协程/ui中使用协程/main.js b/app/src/main/assets/sample/协程/ui中使用协程/main.js
new file mode 100644
index 00000000..5baee904
--- /dev/null
+++ b/app/src/main/assets/sample/协程/ui中使用协程/main.js
@@ -0,0 +1,24 @@
+"ui";
+
+ui.layout(
+
+
+ UI中使用协程
+
+
+);
+
+continuation.delay(5000);
+if (!requestScreenCapture()) {
+ dialogs.alert("请授予软件截图权限").await();
+}
+
+
+// 退出应用对话框
+ui.emitter.on("back_pressed", function (e) {
+ e.consumed = true;
+ let exit = dialogs.confirm("确定要退出程序").await();
+ if (exit) {
+ ui.finish();
+ }
+});
\ No newline at end of file
diff --git a/app/src/main/assets/sample/协程/ui中使用协程/project.json b/app/src/main/assets/sample/协程/ui中使用协程/project.json
new file mode 100644
index 00000000..8afb2e9c
--- /dev/null
+++ b/app/src/main/assets/sample/协程/ui中使用协程/project.json
@@ -0,0 +1,11 @@
+{
+ "name": "协程UI示例",
+ "main": "main.js",
+ "ignore": [
+ "build"
+ ],
+ "packageName": "com.example.cont.ui",
+ "versionName": "1.0.0",
+ "versionCode": 1,
+ "useFeatures": ["continuation"]
+}
\ No newline at end of file
diff --git a/app/src/main/assets/sample/协程/协程HelloWorld/hello.txt b/app/src/main/assets/sample/协程/协程HelloWorld/hello.txt
new file mode 100644
index 00000000..9be9bcf8
--- /dev/null
+++ b/app/src/main/assets/sample/协程/协程HelloWorld/hello.txt
@@ -0,0 +1 @@
+Nothing
\ No newline at end of file
diff --git a/app/src/main/assets/sample/协程/协程HelloWorld/main.js b/app/src/main/assets/sample/协程/协程HelloWorld/main.js
new file mode 100644
index 00000000..9e93812a
--- /dev/null
+++ b/app/src/main/assets/sample/协程/协程HelloWorld/main.js
@@ -0,0 +1,54 @@
+// 注意,要使用协程这个特性,必须使用项目功能,并且在project.json配置好features属性
+
+
+// delay不同于sleep,不会阻塞当前线程
+function delay(millis) {
+ var cont = continuation.create();
+ setTimeout(()=>{
+ cont.resume();
+ }, millis);
+ cont.await();
+}
+
+// 异步IO例子,在另一个线程读取文件,读取完成后返回当前线程继续执行
+function read(path) {
+ var cont = continuation.create();
+ threads.start(function(){
+ try {
+ cont.resume(files.read(path));
+ }catch(err){
+ cont.resumeError(err);
+ }
+ });
+ return cont.await();
+}
+
+// 使用Promise和协程的例子
+function add(a, b) {
+ return new Promise(function(resolve, reject) {
+ var sum = a + b;
+ resolve(sum);
+ });
+}
+
+toastLog("Hello, Continuation!");
+
+//3秒后发出提示
+setTimeout(()=>{
+ toastLog("3秒后....");
+}, 3000);
+
+// 你可以尝试把delay更换成sleep,看会发生什么!
+delay(6000);
+toastLog("6秒后...");
+
+try {
+ toastLog("读取文件hello.txt: " + read("./hello.txt"));
+}catch(err){
+ console.error(err);
+}
+
+var sum = add(1, 2).await();
+toastLog("1 + 2 = " + sum);
+
+
diff --git a/app/src/main/assets/sample/协程/协程HelloWorld/project.json b/app/src/main/assets/sample/协程/协程HelloWorld/project.json
new file mode 100644
index 00000000..dccfca87
--- /dev/null
+++ b/app/src/main/assets/sample/协程/协程HelloWorld/project.json
@@ -0,0 +1,11 @@
+{
+ "name": "协程HelloWorld",
+ "main": "main.js",
+ "ignore": [
+ "build"
+ ],
+ "packageName": "com.example.cont.helloworld",
+ "versionName": "1.0.0",
+ "versionCode": 1,
+ "useFeatures": ["continuation"]
+}
\ No newline at end of file
diff --git a/autojs/src/main/assets/init.js b/autojs/src/main/assets/init.js
index 1b86ef43..78883805 100644
--- a/autojs/src/main/assets/init.js
+++ b/autojs/src/main/assets/init.js
@@ -16,16 +16,7 @@ runtime.init();
}
})();
-
- //初始化不依赖环境的模块
- global.JSON = require('__json2__.js');
- global.util = require('__util__.js');
- global.device = runtime.device;
-
- //设置JavaScriptBridges用于与Java层的交互和数据转换
- runtime.bridges.setBridges(require('__bridges__.js'));
-
- //一些内部函数
+ //内部函数
global.__asGlobal__ = function (obj, functions) {
var len = functions.length;
for (var i = 0; i < len; i++) {
@@ -50,7 +41,6 @@ runtime.init();
exit(err);
} else if (err instanceof Error) {
exit(new org.mozilla.javascript.EvaluatorException(err.name + ": " + err.message, err.fileName, err.lineNumber));
- //new java.lang.RuntimeException(err.name + ": " + err.message + "\n" + err.stack));
} else {
exit();
}
@@ -58,12 +48,24 @@ runtime.init();
}
};
+ // 初始化基础模块
+ global.timers = require('__timers__.js')(runtime, global);
+
+ //初始化不依赖环境的模块
+ global.JSON = require('__json2__.js');
+ global.util = require('__util__.js');
+ global.device = runtime.device;
+ global.Promise = require('promise.js');
+
+ //设置JavaScriptBridges用于与Java层的交互和数据转换
+ runtime.bridges.setBridges(require('__bridges__.js'));
+
//初始化全局函数
require("__globals__")(runtime, global);
//初始化一般模块
(function (scope) {
var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui',
- "images", "timers", "threads", "events", "engines", "RootAutomator", "http", "storages", "floaty",
+ "images", "threads", "events", "engines", "RootAutomator", "http", "storages", "floaty",
"sensors", "media", "plugins", "continuation"];
var len = modules.length;
for (var i = 0; i < len; i++) {
@@ -72,11 +74,6 @@ runtime.init();
}
})(global);
- global.Promise = require('promise.js');
- global.Promise.prototype.await = function () {
- return continuation.await(this);
- }
-
importClass(android.view.KeyEvent);
importClass(com.stardust.autojs.core.util.Shell);
importClass(android.graphics.Paint);
diff --git a/autojs/src/main/assets/modules/__continuation__.js b/autojs/src/main/assets/modules/__continuation__.js
index 532139c7..15fa8a5b 100644
--- a/autojs/src/main/assets/modules/__continuation__.js
+++ b/autojs/src/main/assets/modules/__continuation__.js
@@ -44,5 +44,21 @@ module.exports = function (runtime, global) {
throw new TypeError('cannot await ' + any);
}
+ continuation.delay = function (millis) {
+ var cont = continuation.create();
+ setTimeout(()=>{
+ cont.resume();
+ }, millis);
+ cont.await();
+ }
+
+ continuation.__defineGetter__('enabled', function () {
+ return engines.myEngine().hasFeature("continuation");
+ });
+
+ global.Promise.prototype.await = function () {
+ return continuation.await(this);
+ }
+
return continuation;
}
\ No newline at end of file
diff --git a/autojs/src/main/assets/modules/__http__.js b/autojs/src/main/assets/modules/__http__.js
index 431e4768..551714d2 100644
--- a/autojs/src/main/assets/modules/__http__.js
+++ b/autojs/src/main/assets/modules/__http__.js
@@ -41,7 +41,7 @@ module.exports = function (runtime, scope) {
http.request = function (url, options, callback) {
var cont = null;
- if (!callback && ui.isUiThread()) {
+ if (!callback && ui.isUiThread() && continuation.enabled) {
cont = continuation.create();
}
var call = http.client().newCall(http.buildRequest(url, options));
@@ -59,7 +59,7 @@ module.exports = function (runtime, scope) {
callback && callback(null, ex);
}
}));
- if(cont) {
+ if (cont) {
return cont.await();
}
}
diff --git a/autojs/src/main/assets/modules/__images__.js b/autojs/src/main/assets/modules/__images__.js
index 3f444eba..587e10af 100644
--- a/autojs/src/main/assets/modules/__images__.js
+++ b/autojs/src/main/assets/modules/__images__.js
@@ -65,7 +65,7 @@ module.exports = function (runtime, scope) {
if(landscape === false){
orientation = ScreenCapturer.ORIENTATION_PORTRAIT;
}
- return ResultAdapter.promise(javaImages.requestScreenCapture(orientation)).await();
+ return ResultAdapter.wait(javaImages.requestScreenCapture(orientation));
}
images.save = function (img, path, format, quality) {
diff --git a/autojs/src/main/assets/modules/__threads__.js b/autojs/src/main/assets/modules/__threads__.js
index 01bc05f4..1e3c1a26 100644
--- a/autojs/src/main/assets/modules/__threads__.js
+++ b/autojs/src/main/assets/modules/__threads__.js
@@ -1,12 +1,26 @@
-module.exports = function(__runtime__, scope){
- var threads = Object.create(__runtime__.threads);
+module.exports = function (__runtime__, scope) {
+ var threads = Object.create(__runtime__.threads);
- scope.sync = function(func, lock){
+ scope.sync = function (func, lock) {
lock = lock || null;
return new org.mozilla.javascript.Synchronizer(func, lock);
- }
+ }
- return threads;
+ global.Promise.prototype.wait = function () {
+ var disposable = threads.disposable();
+ promise.then(result => {
+ disposable.setAndNotify({ result: result });
+ }).catch(error => {
+ cont.resumeError({ error: error });
+ });
+ var r = cont.blockedGet();
+ if (r.error) {
+ throw r.error;
+ }
+ return r.result;
+ }
+
+ return threads;
}
\ No newline at end of file
diff --git a/autojs/src/main/assets/modules/result_adapter.js b/autojs/src/main/assets/modules/result_adapter.js
index 0f52acbe..b9d2496d 100644
--- a/autojs/src/main/assets/modules/result_adapter.js
+++ b/autojs/src/main/assets/modules/result_adapter.js
@@ -47,7 +47,7 @@ ResultAdapter.prototype.setError = function (error) {
ResultAdapter.prototype.callback = function () {
var that = this;
return function (result, error) {
- if(that.result !== undefined){
+ if (that.result !== undefined) {
that.result = {
result: result,
error: error
@@ -63,21 +63,33 @@ ResultAdapter.prototype.callback = function () {
}
ResultAdapter.prototype.get = function () {
- if(this.result){
+ if (this.result) {
return getOrThrow(this.result);
}
this.result = null;
return this.impl.get();
}
-ResultAdapter.promise = function(promiseAdapter) {
- return new Promise(function(resolve, reject){
- promiseAdapter.onResolve(function(result) {
+ResultAdapter.promise = function (promiseAdapter) {
+ return new Promise(function (resolve, reject) {
+ promiseAdapter.onResolve(function (result) {
resolve(result);
- }).onReject(function(error){
+ }).onReject(function (error) {
reject(error);
});
})
}
+ResultAdapter.wait = function (promise) {
+ var proto = Object.getPrototypeOf(promise);
+ if (!proto || proto.constructor !== Promise) {
+ promise = ResultAdapter.promise(promise);
+ }
+ if (continuation.enabled) {
+ return promise.await();
+ } else {
+ return promise.wait();
+ }
+}
+
module.exports = ResultAdapter;
\ No newline at end of file
diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/dialog/BlockedMaterialDialog.java b/autojs/src/main/java/com/stardust/autojs/core/ui/dialog/BlockedMaterialDialog.java
index c1ef2ee4..fb5f5766 100644
--- a/autojs/src/main/java/com/stardust/autojs/core/ui/dialog/BlockedMaterialDialog.java
+++ b/autojs/src/main/java/com/stardust/autojs/core/ui/dialog/BlockedMaterialDialog.java
@@ -63,7 +63,6 @@ public class BlockedMaterialDialog extends MaterialDialog {
private VolatileDispose