support app framework base library in assemblyscript (#164)
This commit is contained in:
parent
b5cbc02e90
commit
5a10651dd0
124
assembly-script/README.md
Normal file
124
assembly-script/README.md
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# AssemblyScript_on_WAMR
|
||||||
|
This project is based on [Wasm Micro Runtime](https://github.com/bytecodealliance/wasm-micro-runtime) (WAMR) and [AssemblyScript](https://github.com/AssemblyScript/assemblyscript). It implements some of the `wamr app framework` in *assemblyscript*, which allows you to write some applications in *assemblyscript* and dynamically installed on *WAMR Runtime*
|
||||||
|
|
||||||
|
## Building
|
||||||
|
To build the samples in this repo, you need `npm` on your system
|
||||||
|
``` bash
|
||||||
|
sudo apt install npm
|
||||||
|
```
|
||||||
|
|
||||||
|
Then install all the dependencies under the repo's root dir
|
||||||
|
``` bash
|
||||||
|
cd $repo_root
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the command to build all samples:
|
||||||
|
``` bash
|
||||||
|
npm run build:all
|
||||||
|
```
|
||||||
|
or you can build every sample individually:
|
||||||
|
``` bash
|
||||||
|
npm run build:timer
|
||||||
|
npm run build:publisher
|
||||||
|
npm run build:subscriber
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
You will get the compiled wasm file under `build` folder
|
||||||
|
|
||||||
|
Please refer to [package.json](./package.json) for more commands.
|
||||||
|
|
||||||
|
## Run
|
||||||
|
These applications require WAMR's application framework, you need to build WAMR first.
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
cd ${WAMR_ROOT}/samples/simple
|
||||||
|
./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
You will get two executable files under `out` folder:
|
||||||
|
|
||||||
|
`simple`: The wamr runtime with application framework
|
||||||
|
|
||||||
|
`host_tool`: The tool used to dynamically install/uninstall applications
|
||||||
|
|
||||||
|
1. Start the runtime:
|
||||||
|
``` bash
|
||||||
|
./simple -s
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Install the compiled wasm file using `host_tool`:
|
||||||
|
``` bash
|
||||||
|
./host_tool -i app_name -f your_compiled_wasm_file.wasm
|
||||||
|
```
|
||||||
|
You can also use the WAMR's AoT compiler `wamrc` to compile the wasm bytecode into native code before you run them. Please refer to this [guide](../README.md#build-wamrc-aot-compiler) to build and install `WAMR AoT compiler`.
|
||||||
|
|
||||||
|
After installing `wamrc`, you can compile the wasm file using command:
|
||||||
|
``` bash
|
||||||
|
wamrc -o file_name.aot file_name.wasm
|
||||||
|
```
|
||||||
|
and you can install the AoT file to the runtime:
|
||||||
|
``` bash
|
||||||
|
./host_tool -i app_name -f your_compiled_aot_file.aot
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
You can develop your own application based on the `wamr_app_lib` APIs.
|
||||||
|
|
||||||
|
### Console APIs
|
||||||
|
``` typescript
|
||||||
|
function log(a: string): void;
|
||||||
|
function log_number(a: number): void;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Timer APIs
|
||||||
|
``` typescript
|
||||||
|
function setTimeout(cb: () => void, timeout: i32): user_timer;
|
||||||
|
function setInterval(cb: () => void, timeout: i32): user_timer;
|
||||||
|
function timer_cancel(timer: user_timer): void;
|
||||||
|
function timer_restart(timer: user_timer, interval: number): void;
|
||||||
|
function now(): i32;
|
||||||
|
|
||||||
|
// export to runtime
|
||||||
|
function on_timer_callback(on_timer_id: i32): void;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Request APIs
|
||||||
|
``` typescript
|
||||||
|
// register handler
|
||||||
|
function register_resource_handler(url: string,
|
||||||
|
request_handle: request_handler_f): void;
|
||||||
|
// request
|
||||||
|
function post(url: string, payload: ArrayBuffer, payload_len: number,
|
||||||
|
tag: string, cb: (resp: wamr_response) => void): void;
|
||||||
|
function get(url: string, tag: string,
|
||||||
|
cb: (resp: wamr_response) => void): void;
|
||||||
|
function put(url: string, payload: ArrayBuffer, payload_len: number, tag: string,
|
||||||
|
cb: (resp: wamr_response) => void): void;
|
||||||
|
function del(url: string, tag: string,
|
||||||
|
cb: (resp: wamr_response) => void): void;
|
||||||
|
|
||||||
|
// response
|
||||||
|
function make_response_for_request(req: wamr_request): wamr_response;
|
||||||
|
function api_response_send(resp: wamr_response): void;
|
||||||
|
|
||||||
|
// event
|
||||||
|
function publish_event(url: string, fmt: number,
|
||||||
|
payload: ArrayBuffer, payload_len: number): void;
|
||||||
|
function subscribe_event(url: string, cb: request_handler_f): void;
|
||||||
|
|
||||||
|
// export to runtime
|
||||||
|
function on_request(buffer_offset: i32, size: i32): void;
|
||||||
|
function on_response(buffer_offset : i32, size: i32): void;
|
||||||
|
```
|
||||||
|
|
||||||
|
You should export the `on_timer_callback`, `on_request` and `on_response` in your application entry file, refer to the samples for example.
|
||||||
|
|
||||||
|
To build your application, you can use `asc`:
|
||||||
|
``` bash
|
||||||
|
asc app.ts -b build/app.wasm -t build/app.wat --sourceMap --validate --optimize
|
||||||
|
```
|
||||||
|
or you can add a command into [package.json](./package.json):
|
||||||
|
``` json
|
||||||
|
"build:app": "asc app.ts -b build/app.wasm -t build/app.wat --sourceMap --validate --optimize",
|
||||||
|
```
|
30
assembly-script/package-lock.json
generated
Normal file
30
assembly-script/package-lock.json
generated
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "assembly_script",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"assemblyscript": {
|
||||||
|
"version": "0.8.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/assemblyscript/download/assemblyscript-0.8.1.tgz",
|
||||||
|
"integrity": "sha1-xcYnSSQG5th/QmiXs9kr0qUz9/4=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"binaryen": "89.0.0-nightly.20191113",
|
||||||
|
"long": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binaryen": {
|
||||||
|
"version": "89.0.0-nightly.20191113",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/binaryen/download/binaryen-89.0.0-nightly.20191113.tgz",
|
||||||
|
"integrity": "sha1-oNORTzXJKXhzQeApELf/rrfYl6k=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"long": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/long/download/long-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-mntxz7fTYaGU6lVSQckvdGjVvyg=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
assembly-script/package.json
Normal file
20
assembly-script/package.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "assembly_script",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --validate --optimize",
|
||||||
|
"build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --validate --optimize",
|
||||||
|
"build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --validate --optimize",
|
||||||
|
"build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --validate --optimize",
|
||||||
|
"build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --validate --optimize",
|
||||||
|
"build:all": "npm run build:request_handler; npm run build:request_sender; npm run build:timer; npm run build:subscriber; npm run build:publisher"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"assemblyscript": "^0.8.1"
|
||||||
|
}
|
||||||
|
}
|
36
assembly-script/samples/event_publisher.ts
Normal file
36
assembly-script/samples/event_publisher.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The entry file of your WebAssembly module.
|
||||||
|
import * as console from "../wamr_app_lib/console"
|
||||||
|
import * as timer from "../wamr_app_lib/timer"
|
||||||
|
import * as request from "../wamr_app_lib/request"
|
||||||
|
|
||||||
|
function publish_overheat_event(): void {
|
||||||
|
var payload = String.UTF8.encode("warning: temperature is over high");
|
||||||
|
request.publish_event("alert/overheat", 0, payload, payload.byteLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on_init() : void {
|
||||||
|
timer.setInterval(publish_overheat_event, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on_destroy() : void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Function below are requred by wamr runtime, don't remove or modify them */
|
||||||
|
export function _on_timer_callback(on_timer_id: i32): void {
|
||||||
|
timer.on_timer_callback(on_timer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_request(buffer_offset: i32, size: i32): void {
|
||||||
|
request.on_request(buffer_offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_response(buffer_offset : i32, size: i32): void {
|
||||||
|
request.on_response(buffer_offset, size);
|
||||||
|
}
|
36
assembly-script/samples/event_subscriber.ts
Normal file
36
assembly-script/samples/event_subscriber.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The entry file of your WebAssembly module.
|
||||||
|
import * as console from "../wamr_app_lib/console"
|
||||||
|
import * as timer from "../wamr_app_lib/timer"
|
||||||
|
import * as request from "../wamr_app_lib/request"
|
||||||
|
|
||||||
|
export function on_init() : void {
|
||||||
|
request.subscribe_event("alert/overheat", (req) => {
|
||||||
|
console.log("### user over heat event handler called:");
|
||||||
|
|
||||||
|
console.log("");
|
||||||
|
console.log(" " + String.UTF8.decode(req.payload) + "\n");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on_destroy() : void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Function below are requred by wamr runtime, don't remove or modify them */
|
||||||
|
export function _on_timer_callback(on_timer_id: i32): void {
|
||||||
|
timer.on_timer_callback(on_timer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_request(buffer_offset: i32, size: i32): void {
|
||||||
|
request.on_request(buffer_offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_response(buffer_offset : i32, size: i32): void {
|
||||||
|
request.on_response(buffer_offset, size);
|
||||||
|
}
|
40
assembly-script/samples/request_handler.ts
Normal file
40
assembly-script/samples/request_handler.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The entry file of your WebAssembly module.
|
||||||
|
import * as console from "../wamr_app_lib/console"
|
||||||
|
import * as timer from "../wamr_app_lib/timer"
|
||||||
|
import * as request from "../wamr_app_lib/request"
|
||||||
|
|
||||||
|
export function on_init() : void {
|
||||||
|
request.register_resource_handler("/test", (req) => {
|
||||||
|
console.log("### Req: /test " + String.UTF8.decode(req.payload));
|
||||||
|
|
||||||
|
console.log(" request payload:");
|
||||||
|
console.log(" " + String.UTF8.decode(req.payload) + "\n");
|
||||||
|
|
||||||
|
var resp = request.make_response_for_request(req);
|
||||||
|
resp.set_payload(String.UTF8.encode("Ok"), 2);
|
||||||
|
request.api_response_send(resp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on_destroy() : void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Function below are requred by wamr runtime, don't remove or modify them */
|
||||||
|
export function _on_timer_callback(on_timer_id: i32): void {
|
||||||
|
timer.on_timer_callback(on_timer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_request(buffer_offset: i32, size: i32): void {
|
||||||
|
request.on_request(buffer_offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_response(buffer_offset : i32, size: i32): void {
|
||||||
|
request.on_response(buffer_offset, size);
|
||||||
|
}
|
43
assembly-script/samples/request_sender.ts
Normal file
43
assembly-script/samples/request_sender.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The entry file of your WebAssembly module.
|
||||||
|
import * as console from "../wamr_app_lib/console"
|
||||||
|
import * as timer from "../wamr_app_lib/timer"
|
||||||
|
import * as request from "../wamr_app_lib/request"
|
||||||
|
|
||||||
|
export function on_init() : void {
|
||||||
|
var payload = String.UTF8.encode("test message");
|
||||||
|
request.post("/test", payload, payload.byteLength, "", (resp) => {
|
||||||
|
if (resp != null) {
|
||||||
|
console.log("Post Success");
|
||||||
|
|
||||||
|
if (resp.payload != null) {
|
||||||
|
console.log(" response payload:")
|
||||||
|
console.log(" " + String.UTF8.decode(resp.payload!) + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
console.log("Post Timeout");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on_destroy() : void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Function below are requred by wamr runtime, don't remove or modify them */
|
||||||
|
export function _on_timer_callback(on_timer_id: i32): void {
|
||||||
|
timer.on_timer_callback(on_timer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_request(buffer_offset: i32, size: i32): void {
|
||||||
|
request.on_request(buffer_offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_response(buffer_offset : i32, size: i32): void {
|
||||||
|
request.on_response(buffer_offset, size);
|
||||||
|
}
|
36
assembly-script/samples/timer.ts
Normal file
36
assembly-script/samples/timer.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The entry file of your WebAssembly module.
|
||||||
|
import * as console from '../wamr_app_lib/console'
|
||||||
|
import * as timer from '../wamr_app_lib/timer'
|
||||||
|
|
||||||
|
/* clousure is not implemented yet, we need to declare global variables
|
||||||
|
so that they can be accessed inside a callback function */
|
||||||
|
var cnt = 0;
|
||||||
|
var my_timer: timer.user_timer;
|
||||||
|
|
||||||
|
export function on_init(): void {
|
||||||
|
/* The callback function will be called every 2 second,
|
||||||
|
and will stop after 10 calls */
|
||||||
|
my_timer = timer.setInterval(() => {
|
||||||
|
cnt ++;
|
||||||
|
console.log((cnt * 2).toString() + " seconds passed");
|
||||||
|
|
||||||
|
if (cnt >= 10) {
|
||||||
|
timer.timer_cancel(my_timer);
|
||||||
|
console.log("Stop Timer");
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on_destroy(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function below are requred by wamr runtime, don't remove or modify them */
|
||||||
|
export function _on_timer_callback(on_timer_id: i32): void {
|
||||||
|
timer.on_timer_callback(on_timer_id);
|
||||||
|
}
|
6
assembly-script/samples/tsconfig.json
Normal file
6
assembly-script/samples/tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": "../node_modules/assemblyscript/std/assembly.json",
|
||||||
|
"include": [
|
||||||
|
"./**/*.ts"
|
||||||
|
]
|
||||||
|
}
|
15
assembly-script/wamr_app_lib/console.ts
Normal file
15
assembly-script/wamr_app_lib/console.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
@external("env", "printf")
|
||||||
|
declare function printf(a: ArrayBuffer): i32;
|
||||||
|
|
||||||
|
export function log(a: string): void {
|
||||||
|
printf(String.UTF8.encode(a + '\n', true));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function log_number(a: number): void {
|
||||||
|
printf(String.UTF8.encode(a.toString() + '\n'));
|
||||||
|
}
|
495
assembly-script/wamr_app_lib/request.ts
Normal file
495
assembly-script/wamr_app_lib/request.ts
Normal file
@ -0,0 +1,495 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as console from './console'
|
||||||
|
import * as timer from './timer'
|
||||||
|
|
||||||
|
@external("env", "wasm_response_send")
|
||||||
|
declare function wasm_response_send(buffer: ArrayBuffer, size: i32): void;
|
||||||
|
|
||||||
|
@external("env", "wasm_register_resource")
|
||||||
|
declare function wasm_register_resource(url: ArrayBuffer): void;
|
||||||
|
|
||||||
|
@external("env", "wasm_post_request")
|
||||||
|
declare function wasm_post_request(buffer: ArrayBuffer, size: i32): void;
|
||||||
|
|
||||||
|
@external("env", "wasm_sub_event")
|
||||||
|
declare function wasm_sub_event(url: ArrayBuffer): void;
|
||||||
|
|
||||||
|
var COAP_GET = 1;
|
||||||
|
var COAP_POST = 2;
|
||||||
|
var COAP_PUT = 3;
|
||||||
|
var COAP_DELETE = 4;
|
||||||
|
var COAP_EVENT = COAP_DELETE + 2;
|
||||||
|
|
||||||
|
/* CoAP response codes */
|
||||||
|
export enum CoAP_Status {
|
||||||
|
NO_ERROR = 0,
|
||||||
|
|
||||||
|
CREATED_2_01 = 65, /* CREATED */
|
||||||
|
DELETED_2_02 = 66, /* DELETED */
|
||||||
|
VALID_2_03 = 67, /* NOT_MODIFIED */
|
||||||
|
CHANGED_2_04 = 68, /* CHANGED */
|
||||||
|
CONTENT_2_05 = 69, /* OK */
|
||||||
|
CONTINUE_2_31 = 95, /* CONTINUE */
|
||||||
|
|
||||||
|
BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */
|
||||||
|
UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */
|
||||||
|
BAD_OPTION_4_02 = 130, /* BAD_OPTION */
|
||||||
|
FORBIDDEN_4_03 = 131, /* FORBIDDEN */
|
||||||
|
NOT_FOUND_4_04 = 132, /* NOT_FOUND */
|
||||||
|
METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */
|
||||||
|
NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */
|
||||||
|
PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */
|
||||||
|
REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */
|
||||||
|
UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */
|
||||||
|
|
||||||
|
INTERNAL_SERVER_ERROR_5_00 = 160, /* INTERNAL_SERVER_ERROR */
|
||||||
|
NOT_IMPLEMENTED_5_01 = 161, /* NOT_IMPLEMENTED */
|
||||||
|
BAD_GATEWAY_5_02 = 162, /* BAD_GATEWAY */
|
||||||
|
SERVICE_UNAVAILABLE_5_03 = 163, /* SERVICE_UNAVAILABLE */
|
||||||
|
GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */
|
||||||
|
PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */
|
||||||
|
|
||||||
|
/* Erbium errors */
|
||||||
|
MEMORY_ALLOCATION_ERROR = 192, PACKET_SERIALIZATION_ERROR,
|
||||||
|
|
||||||
|
/* Erbium hooks */
|
||||||
|
MANUAL_RESPONSE, PING_RESPONSE
|
||||||
|
};
|
||||||
|
|
||||||
|
var g_mid: i32 = 0;
|
||||||
|
class wamr_request {
|
||||||
|
mid: i32 = 0;
|
||||||
|
url: string = "";
|
||||||
|
action: i32 = 0;
|
||||||
|
fmt: i32 = 0;
|
||||||
|
payload: ArrayBuffer;
|
||||||
|
payload_len: i32 = 0;
|
||||||
|
|
||||||
|
sender: i32 = 0;
|
||||||
|
|
||||||
|
constructor(mid: i32, url: string, action: i32, fmt: i32,
|
||||||
|
payload: ArrayBuffer, payload_len: number) {
|
||||||
|
this.mid = mid;
|
||||||
|
this.url = url;
|
||||||
|
this.action = action;
|
||||||
|
this.fmt = fmt;
|
||||||
|
this.payload = payload;
|
||||||
|
this.payload_len = i32(payload_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class wamr_response {
|
||||||
|
mid: i32 = 0;
|
||||||
|
status: i32 = 0;
|
||||||
|
fmt: i32 = 0;
|
||||||
|
payload: ArrayBuffer | null;
|
||||||
|
payload_len: i32 = 0;
|
||||||
|
|
||||||
|
receiver: i32 = 0;
|
||||||
|
|
||||||
|
constructor(mid: i32, status: i32, fmt: i32,
|
||||||
|
payload: ArrayBuffer | null, payload_len: i32) {
|
||||||
|
this.mid = mid;
|
||||||
|
this.status = status;
|
||||||
|
this.fmt = fmt;
|
||||||
|
this.payload = payload;
|
||||||
|
this.payload_len = payload_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_status(status: number): void {
|
||||||
|
this.status = i32(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_payload(payload: ArrayBuffer, payload_len: number): void {
|
||||||
|
this.payload = payload;
|
||||||
|
this.payload_len = i32(payload_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class wamr_resource {
|
||||||
|
url: string;
|
||||||
|
type: number;
|
||||||
|
cb: request_handler_f;
|
||||||
|
|
||||||
|
constructor(url: string, type: number, cb: request_handler_f) {
|
||||||
|
this.url = url;
|
||||||
|
this.type = type;
|
||||||
|
this.cb = cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_expire(trans: wamr_transaction, index: i32, array: Array<wamr_transaction>): bool {
|
||||||
|
var now = timer.now();
|
||||||
|
|
||||||
|
var elapsed_ms = (now < trans.time) ?
|
||||||
|
(now + (0xFFFFFFFF - trans.time) + 1) : (now - trans.time);
|
||||||
|
|
||||||
|
return elapsed_ms >= TRANSACTION_TIMEOUT_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function not_expire(trans: wamr_transaction, index: i32, array: Array<wamr_transaction>): bool {
|
||||||
|
var now = timer.now();
|
||||||
|
|
||||||
|
var elapsed_ms = (now < trans.time) ?
|
||||||
|
(now + (0xFFFFFFFF - trans.time) + 1) : (now - trans.time);
|
||||||
|
|
||||||
|
return elapsed_ms >= TRANSACTION_TIMEOUT_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function transaction_timeout_handler(): void {
|
||||||
|
var now = timer.now();
|
||||||
|
|
||||||
|
var expired = transaction_list.filter(is_expire);
|
||||||
|
transaction_list = transaction_list.filter(not_expire);
|
||||||
|
|
||||||
|
expired.forEach(item => {
|
||||||
|
item.cb(null);
|
||||||
|
transaction_remove(item);
|
||||||
|
})
|
||||||
|
|
||||||
|
if (transaction_list.length > 0) {
|
||||||
|
var elpased_ms: number, ms_to_expiry: number;
|
||||||
|
now = timer.now();
|
||||||
|
if (now < transaction_list[0].time) {
|
||||||
|
elpased_ms = now + (0xFFFFFFFF - transaction_list[0].time) + 1;
|
||||||
|
} else {
|
||||||
|
elpased_ms = now - transaction_list[0].time;
|
||||||
|
}
|
||||||
|
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
|
||||||
|
timer.timer_restart(g_trans_timer, ms_to_expiry);
|
||||||
|
} else {
|
||||||
|
timer.timer_cancel(g_trans_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transaction_find(mid: number): wamr_transaction | null {
|
||||||
|
for (let i = 0; i < transaction_list.length; i++) {
|
||||||
|
if (transaction_list[i].mid == mid)
|
||||||
|
return transaction_list[i];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function transaction_add(trans: wamr_transaction): void {
|
||||||
|
transaction_list.push(trans);
|
||||||
|
|
||||||
|
if (transaction_list.length == 1) {
|
||||||
|
g_trans_timer = timer.setTimeout(
|
||||||
|
transaction_timeout_handler,
|
||||||
|
TRANSACTION_TIMEOUT_MS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transaction_remove(trans: wamr_transaction): void {
|
||||||
|
var index = transaction_list.indexOf(trans);
|
||||||
|
transaction_list.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var transaction_list = new Array<wamr_transaction>();
|
||||||
|
class wamr_transaction {
|
||||||
|
mid: number;
|
||||||
|
time: number;
|
||||||
|
cb: (resp: wamr_response | null) => void;
|
||||||
|
|
||||||
|
constructor(mid: number, time: number, cb: (resp: wamr_response) => void) {
|
||||||
|
this.mid = mid;
|
||||||
|
this.time = time;
|
||||||
|
this.cb = cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var REQUEST_PACKET_FIX_PART_LEN = 18;
|
||||||
|
var RESPONSE_PACKET_FIX_PART_LEN = 16;
|
||||||
|
var TRANSACTION_TIMEOUT_MS = 5000;
|
||||||
|
var g_trans_timer: timer.user_timer;
|
||||||
|
|
||||||
|
var Reg_Event = 0;
|
||||||
|
var Reg_Request = 1;
|
||||||
|
|
||||||
|
function pack_request(req: wamr_request): DataView {
|
||||||
|
var url_len = req.url.length + 1;
|
||||||
|
var len = REQUEST_PACKET_FIX_PART_LEN + url_len + req.payload_len
|
||||||
|
var buf = new ArrayBuffer(len);
|
||||||
|
|
||||||
|
var dataview = new DataView(buf, 0, len);
|
||||||
|
|
||||||
|
dataview.setUint8(0, 1);
|
||||||
|
dataview.setUint8(1, u8(req.action));
|
||||||
|
dataview.setUint16(2, u16(req.fmt));
|
||||||
|
dataview.setUint32(4, req.mid);
|
||||||
|
dataview.setUint32(8, req.sender);
|
||||||
|
dataview.setUint16(12, u16(url_len))
|
||||||
|
dataview.setUint32(14, req.payload_len);
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
for (i = 0; i < url_len - 1; i++) {
|
||||||
|
dataview.setUint8(i + 18, u8(req.url.codePointAt(i)));
|
||||||
|
}
|
||||||
|
dataview.setUint8(i + 18, 0);
|
||||||
|
|
||||||
|
var payload_view = new DataView(req.payload);
|
||||||
|
for (i = 0; i < req.payload_len; i++) {
|
||||||
|
dataview.setUint8(i + 18 + url_len, u8(payload_view.getUint8(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataview;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpack_request(packet: ArrayBuffer, size: i32): wamr_request {
|
||||||
|
var dataview = new DataView(packet, 0, size);
|
||||||
|
|
||||||
|
if (dataview.getUint8(0) != 1)
|
||||||
|
throw new Error("packet version mismatch");
|
||||||
|
|
||||||
|
if (size < REQUEST_PACKET_FIX_PART_LEN)
|
||||||
|
throw new Error("packet size error");
|
||||||
|
|
||||||
|
var url_len = dataview.getUint16(12);
|
||||||
|
var payload_len = dataview.getUint32(14);
|
||||||
|
|
||||||
|
if (size != (REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len))
|
||||||
|
throw new Error("packet size error");
|
||||||
|
|
||||||
|
var action = dataview.getUint8(1);
|
||||||
|
var fmt = dataview.getUint16(2);
|
||||||
|
var mid = dataview.getUint32(4);
|
||||||
|
var sender = dataview.getUint32(8);
|
||||||
|
|
||||||
|
var url = packet.slice(REQUEST_PACKET_FIX_PART_LEN, REQUEST_PACKET_FIX_PART_LEN + url_len - 1);
|
||||||
|
var payload = packet.slice(REQUEST_PACKET_FIX_PART_LEN + url_len, REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len);
|
||||||
|
|
||||||
|
var req = new wamr_request(mid, String.UTF8.decode(url), action, fmt, payload, payload_len);
|
||||||
|
req.sender = sender;
|
||||||
|
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pack_response(resp: wamr_response): DataView {
|
||||||
|
var len = RESPONSE_PACKET_FIX_PART_LEN + resp.payload_len
|
||||||
|
var buf = new ArrayBuffer(len);
|
||||||
|
|
||||||
|
var dataview = new DataView(buf, 0, len);
|
||||||
|
|
||||||
|
dataview.setUint8(0, 1);
|
||||||
|
dataview.setUint8(1, u8(resp.status));
|
||||||
|
dataview.setUint16(2, u16(resp.fmt));
|
||||||
|
dataview.setUint32(4, resp.mid);
|
||||||
|
dataview.setUint32(8, resp.receiver);
|
||||||
|
dataview.setUint32(12, resp.payload_len)
|
||||||
|
|
||||||
|
if (resp.payload != null) {
|
||||||
|
var payload_view = new DataView(resp.payload!);
|
||||||
|
for (let i = 0; i < resp.payload_len; i++) {
|
||||||
|
dataview.setUint8(i + 16, payload_view.getUint8(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataview;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpack_response(packet: ArrayBuffer, size: i32): wamr_response {
|
||||||
|
var dataview = new DataView(packet, 0, size);
|
||||||
|
|
||||||
|
if (dataview.getUint8(0) != 1)
|
||||||
|
throw new Error("packet version mismatch");
|
||||||
|
|
||||||
|
if (size < RESPONSE_PACKET_FIX_PART_LEN)
|
||||||
|
throw new Error("packet size error");
|
||||||
|
|
||||||
|
var payload_len = dataview.getUint32(12);
|
||||||
|
if (size != RESPONSE_PACKET_FIX_PART_LEN + payload_len)
|
||||||
|
throw new Error("packet size error");
|
||||||
|
|
||||||
|
var status = dataview.getUint8(1);
|
||||||
|
var fmt = dataview.getUint16(2);
|
||||||
|
var mid = dataview.getUint32(4);
|
||||||
|
var receiver = dataview.getUint32(8);
|
||||||
|
|
||||||
|
var payload = packet.slice(RESPONSE_PACKET_FIX_PART_LEN);
|
||||||
|
|
||||||
|
var resp = new wamr_response(mid, status, fmt, payload, payload_len);
|
||||||
|
resp.receiver = receiver;
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_request(req: wamr_request, cb: (resp: wamr_response) => void): void {
|
||||||
|
var trans = new wamr_transaction(req.mid, timer.now(), cb);
|
||||||
|
var msg = pack_request(req);
|
||||||
|
|
||||||
|
transaction_add(trans);
|
||||||
|
|
||||||
|
wasm_post_request(msg.buffer, msg.byteLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_response(resp: wamr_response): void {
|
||||||
|
var msg = pack_response(resp);
|
||||||
|
|
||||||
|
wasm_response_send(msg.buffer, msg.byteLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
var resource_list = new Array<wamr_resource>();
|
||||||
|
type request_handler_f = (req: wamr_request) => void;
|
||||||
|
|
||||||
|
function registe_url_handler(url: string, cb: request_handler_f, type: number): void {
|
||||||
|
for (let i = 0; i < resource_list.length; i++) {
|
||||||
|
if (resource_list[i].type == type && resource_list[i].url == url) {
|
||||||
|
resource_list[i].cb = cb;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = new wamr_resource(url, type, cb);
|
||||||
|
resource_list.push(res);
|
||||||
|
|
||||||
|
if (type == Reg_Request)
|
||||||
|
wasm_register_resource(String.UTF8.encode(url));
|
||||||
|
else
|
||||||
|
wasm_sub_event(String.UTF8.encode(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_event_type(req: wamr_request): bool {
|
||||||
|
return req.action == COAP_EVENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_url_start(url: string, leading_str: string): bool {
|
||||||
|
return url.split('/')[0] == leading_str.split('/')[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* User APIs below */
|
||||||
|
export function post(url: string, payload: ArrayBuffer, payload_len: number, tag: string,
|
||||||
|
cb: (resp: wamr_response) => void): void {
|
||||||
|
var req = new wamr_request(g_mid++, url, COAP_POST, 0, payload, payload_len);
|
||||||
|
|
||||||
|
do_request(req, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function get(url: string, tag: string,
|
||||||
|
cb: (resp: wamr_response) => void): void {
|
||||||
|
var req = new wamr_request(g_mid++, url, COAP_GET, 0, new ArrayBuffer(0), 0);
|
||||||
|
|
||||||
|
do_request(req, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function put(url: string, payload: ArrayBuffer, payload_len: number, tag: string,
|
||||||
|
cb: (resp: wamr_response) => void): void {
|
||||||
|
var req = new wamr_request(g_mid++, url, COAP_PUT, 0, payload, payload_len);
|
||||||
|
|
||||||
|
do_request(req, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function del(url: string, tag: string,
|
||||||
|
cb: (resp: wamr_response) => void): void {
|
||||||
|
var req = new wamr_request(g_mid++, url, COAP_PUT, 0, new ArrayBuffer(0), 0);
|
||||||
|
|
||||||
|
do_request(req, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function make_response_for_request(req: wamr_request): wamr_response {
|
||||||
|
var resp = new wamr_response(req.mid, CoAP_Status.CONTENT_2_05, 0, null, 0);
|
||||||
|
resp.receiver = req.sender;
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function api_response_send(resp: wamr_response): void {
|
||||||
|
do_response(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function register_resource_handler(url: string,
|
||||||
|
request_handle: request_handler_f): void {
|
||||||
|
registe_url_handler(url, request_handle, Reg_Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function publish_event(url: string, fmt: number,
|
||||||
|
payload: ArrayBuffer, payload_len: number): void {
|
||||||
|
var req = new wamr_request(g_mid++, url, COAP_EVENT, i32(fmt), payload, payload_len);
|
||||||
|
|
||||||
|
var msg = pack_request(req);
|
||||||
|
|
||||||
|
wasm_post_request(msg.buffer, msg.byteLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function subscribe_event(url: string, cb: request_handler_f): void {
|
||||||
|
registe_url_handler(url, cb, Reg_Event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* These two APIs are required by wamr runtime,
|
||||||
|
use a wrapper to export them in the entry file
|
||||||
|
|
||||||
|
e.g:
|
||||||
|
|
||||||
|
import * as request from '.wamr_app_lib/request'
|
||||||
|
|
||||||
|
// Your code here ...
|
||||||
|
|
||||||
|
export function _on_request(buffer_offset: i32, size: i32): void {
|
||||||
|
on_request(buffer_offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _on_response(buffer_offset: i32, size: i32): void {
|
||||||
|
on_response(buffer_offset, size);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
export function on_request(buffer_offset: i32, size: i32): void {
|
||||||
|
var buffer = new ArrayBuffer(size);
|
||||||
|
var dataview = new DataView(buffer);
|
||||||
|
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
dataview.setUint8(i, load<i8>(buffer_offset + i, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
var req = unpack_request(buffer, size);
|
||||||
|
|
||||||
|
var is_event = is_event_type(req);
|
||||||
|
|
||||||
|
for (let i = 0; i < resource_list.length; i++) {
|
||||||
|
if ((is_event && resource_list[i].type == Reg_Event)
|
||||||
|
|| (!is_event && resource_list[i].type == Reg_Request)) {
|
||||||
|
if (check_url_start(req.url, resource_list[i].url)) {
|
||||||
|
resource_list[i].cb(req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("on_request: exit. no service handler.");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on_response(buffer_offset: i32, size: i32): void {
|
||||||
|
var buffer = new ArrayBuffer(size);
|
||||||
|
var dataview = new DataView(buffer);
|
||||||
|
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
dataview.setUint8(i, load<i8>(buffer_offset + i, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp = unpack_response(buffer, size);
|
||||||
|
var trans = transaction_find(resp.mid);
|
||||||
|
|
||||||
|
if (trans != null) {
|
||||||
|
if (transaction_list.indexOf(trans) == 0) {
|
||||||
|
if (transaction_list.length >= 2) {
|
||||||
|
var elpased_ms: number, ms_to_expiry: number;
|
||||||
|
var now = timer.now();
|
||||||
|
if (now < transaction_list[1].time) {
|
||||||
|
elpased_ms = now + (0xFFFFFFFF - transaction_list[1].time) + 1;
|
||||||
|
} else {
|
||||||
|
elpased_ms = now - transaction_list[1].time;
|
||||||
|
}
|
||||||
|
ms_to_expiry = TRANSACTION_TIMEOUT_MS - elpased_ms;
|
||||||
|
timer.timer_restart(g_trans_timer, ms_to_expiry);
|
||||||
|
} else {
|
||||||
|
timer.timer_cancel(g_trans_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trans.cb(resp);
|
||||||
|
}
|
||||||
|
}
|
80
assembly-script/wamr_app_lib/timer.ts
Normal file
80
assembly-script/wamr_app_lib/timer.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
@external("env", "wasm_create_timer")
|
||||||
|
declare function wasm_create_timer(a: i32, b: bool, c: bool): i32;
|
||||||
|
|
||||||
|
@external("env", "wasm_timer_cancel")
|
||||||
|
declare function wasm_timer_cancel(a: i32): void;
|
||||||
|
|
||||||
|
@external("env", "wasm_timer_restart")
|
||||||
|
declare function wasm_timer_restart(a: i32, b: i32): void;
|
||||||
|
|
||||||
|
@external("env", "wasm_get_sys_tick_ms")
|
||||||
|
declare function wasm_get_sys_tick_ms(): i32;
|
||||||
|
|
||||||
|
export var timer_list = new Array<user_timer>();
|
||||||
|
|
||||||
|
export class user_timer {
|
||||||
|
timer_id: i32 = 0;
|
||||||
|
timeout: i32;
|
||||||
|
period: bool = false;
|
||||||
|
cb: () => void;
|
||||||
|
|
||||||
|
constructor(cb: () => void, timeout: i32, period: bool) {
|
||||||
|
this.cb = cb;
|
||||||
|
this.timeout = timeout;
|
||||||
|
this.period = period
|
||||||
|
this.timer_id = timer_create(this.timeout, this.period, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function timer_create(a: i32, b: bool, c: bool): i32 {
|
||||||
|
return wasm_create_timer(a, b, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setTimeout(cb: () => void, timeout: i32): user_timer {
|
||||||
|
var timer = new user_timer(cb, timeout, false);
|
||||||
|
timer_list.push(timer);
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setInterval(cb: () => void, timeout: i32): user_timer {
|
||||||
|
var timer = new user_timer(cb, timeout, true);
|
||||||
|
timer_list.push(timer);
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function timer_cancel(timer: user_timer): void {
|
||||||
|
wasm_timer_cancel(timer.timer_id);
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
for (i = 0; i < timer_list.length; i++) {
|
||||||
|
if (timer_list[i].timer_id == timer.timer_id)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer_list.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function timer_restart(timer: user_timer, interval: number): void {
|
||||||
|
wasm_timer_restart(timer.timer_id, i32(interval));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function now(): i32 {
|
||||||
|
return wasm_get_sys_tick_ms();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This export function need to be copied to the top application file
|
||||||
|
//
|
||||||
|
export function on_timer_callback(on_timer_id: i32): void {
|
||||||
|
for (let i = 0; i < timer_list.length; i++) {
|
||||||
|
if (timer_list[i].timer_id == on_timer_id) {
|
||||||
|
timer_list[i].cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
6
assembly-script/wamr_app_lib/tsconfig.json
Normal file
6
assembly-script/wamr_app_lib/tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": "../node_modules/assemblyscript/std/assembly.json",
|
||||||
|
"include": [
|
||||||
|
"./**/*.ts"
|
||||||
|
]
|
||||||
|
}
|
@ -245,6 +245,7 @@ fail:
|
|||||||
aot_set_last_error("llvm build load failed."); \
|
aot_set_last_error("llvm build load failed."); \
|
||||||
goto fail; \
|
goto fail; \
|
||||||
} \
|
} \
|
||||||
|
LLVMSetAlignment(value, 1); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define BUILD_TRUNC(data_type) do { \
|
#define BUILD_TRUNC(data_type) do { \
|
||||||
@ -256,10 +257,12 @@ fail:
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define BUILD_STORE() do { \
|
#define BUILD_STORE() do { \
|
||||||
if (!LLVMBuildStore(comp_ctx->builder, value, maddr)) { \
|
LLVMValueRef res; \
|
||||||
|
if (!(res = LLVMBuildStore(comp_ctx->builder, value, maddr))) { \
|
||||||
aot_set_last_error("llvm build store failed."); \
|
aot_set_last_error("llvm build store failed."); \
|
||||||
goto fail; \
|
goto fail; \
|
||||||
} \
|
} \
|
||||||
|
LLVMSetAlignment(res, 1); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define BUILD_SIGN_EXT(dst_type) do { \
|
#define BUILD_SIGN_EXT(dst_type) do { \
|
||||||
@ -599,12 +602,7 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert call result from i8 to i1 */
|
BUILD_ICMP(LLVMIntUGT, ret_value, I8_ZERO, ret_value, "mem_grow_ret");
|
||||||
if (!(ret_value = LLVMBuildIntCast(comp_ctx->builder, ret_value,
|
|
||||||
INT1_TYPE, "mem_grow_ret"))) {
|
|
||||||
aot_set_last_error("llvm build bit cast failed.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ret_value = ret_value == true ? delta : pre_page_count */
|
/* ret_value = ret_value == true ? delta : pre_page_count */
|
||||||
if (!(ret_value = LLVMBuildSelect(comp_ctx->builder, ret_value,
|
if (!(ret_value = LLVMBuildSelect(comp_ctx->builder, ret_value,
|
||||||
|
@ -405,14 +405,23 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||||||
CHECK_LLVM_CONST(zero_undef);
|
CHECK_LLVM_CONST(zero_undef);
|
||||||
|
|
||||||
/* Call the LLVM intrinsic function */
|
/* Call the LLVM intrinsic function */
|
||||||
DEF_INT_UNARY_OP(call_llvm_intrinsic(comp_ctx,
|
if (type < POP_CNT32)
|
||||||
bit_cnt_llvm_intrinsic[type],
|
DEF_INT_UNARY_OP(call_llvm_intrinsic(comp_ctx,
|
||||||
ret_type,
|
bit_cnt_llvm_intrinsic[type],
|
||||||
param_types,
|
ret_type,
|
||||||
2,
|
param_types,
|
||||||
operand,
|
2,
|
||||||
zero_undef),
|
operand,
|
||||||
NULL);
|
zero_undef),
|
||||||
|
NULL);
|
||||||
|
else
|
||||||
|
DEF_INT_UNARY_OP(call_llvm_intrinsic(comp_ctx,
|
||||||
|
bit_cnt_llvm_intrinsic[type],
|
||||||
|
ret_type,
|
||||||
|
param_types,
|
||||||
|
1,
|
||||||
|
operand),
|
||||||
|
NULL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -42,6 +42,58 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
static bool
|
||||||
|
skip_leb(const uint8 *buf, const uint8 *buf_end,
|
||||||
|
uint32 *p_offset, uint32 maxbits,
|
||||||
|
char* error_buf, uint32 error_buf_size)
|
||||||
|
{
|
||||||
|
uint32 bcnt = 0;
|
||||||
|
uint64 byte;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (bcnt + 1 > (maxbits + 6) / 7) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"WASM module load failed: "
|
||||||
|
"integer representation too long");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_BUF(buf, buf_end, *p_offset + 1);
|
||||||
|
byte = buf[*p_offset];
|
||||||
|
*p_offset += 1;
|
||||||
|
bcnt += 1;
|
||||||
|
if ((byte & 0x80) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define skip_leb_int64(p, p_end) do { \
|
||||||
|
uint32 off = 0; \
|
||||||
|
if (!skip_leb(p, p_end, &off, 64, \
|
||||||
|
error_buf, error_buf_size)) \
|
||||||
|
return false; \
|
||||||
|
p += off; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define skip_leb_uint32(p, p_end) do { \
|
||||||
|
uint32 off = 0; \
|
||||||
|
if (!skip_leb(p, p_end, &off, 32, \
|
||||||
|
error_buf, error_buf_size)) \
|
||||||
|
return false; \
|
||||||
|
p += off; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define skip_leb_int32(p, p_end) do { \
|
||||||
|
uint32 off = 0; \
|
||||||
|
if (!skip_leb(p, p_end, &off, 32, \
|
||||||
|
error_buf, error_buf_size)) \
|
||||||
|
return false; \
|
||||||
|
p += off; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
read_leb(const uint8 *buf, const uint8 *buf_end,
|
read_leb(const uint8 *buf, const uint8 *buf_end,
|
||||||
uint32 *p_offset, uint32 maxbits,
|
uint32 *p_offset, uint32 maxbits,
|
||||||
@ -122,17 +174,18 @@ fail_integer_too_large:
|
|||||||
#define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p)
|
#define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p)
|
||||||
#define read_bool(p) TEMPLATE_READ_VALUE(bool, p)
|
#define read_bool(p) TEMPLATE_READ_VALUE(bool, p)
|
||||||
|
|
||||||
#define read_leb_uint64(p, p_end, res) do { \
|
|
||||||
uint32 off = 0; \
|
|
||||||
uint64 res64; \
|
|
||||||
if (!read_leb(p, p_end, &off, 64, false, &res64, \
|
|
||||||
error_buf, error_buf_size)) \
|
|
||||||
return false; \
|
|
||||||
p += off; \
|
|
||||||
res = (uint64)res64; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define read_leb_int64(p, p_end, res) do { \
|
#define read_leb_int64(p, p_end, res) do { \
|
||||||
|
if (p < p_end) { \
|
||||||
|
uint8 _val = *p; \
|
||||||
|
if (!(_val & 0x80)) { \
|
||||||
|
res = (int64)_val; \
|
||||||
|
if (_val & 0x40) \
|
||||||
|
/* sign extend */ \
|
||||||
|
res |= 0xFFFFFFFFFFFFFF80LL; \
|
||||||
|
p++; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
uint32 off = 0; \
|
uint32 off = 0; \
|
||||||
uint64 res64; \
|
uint64 res64; \
|
||||||
if (!read_leb(p, p_end, &off, 64, true, &res64, \
|
if (!read_leb(p, p_end, &off, 64, true, &res64, \
|
||||||
@ -143,6 +196,14 @@ fail_integer_too_large:
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define read_leb_uint32(p, p_end, res) do { \
|
#define read_leb_uint32(p, p_end, res) do { \
|
||||||
|
if (p < p_end) { \
|
||||||
|
uint8 _val = *p; \
|
||||||
|
if (!(_val & 0x80)) { \
|
||||||
|
res = _val; \
|
||||||
|
p++; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
uint32 off = 0; \
|
uint32 off = 0; \
|
||||||
uint64 res64; \
|
uint64 res64; \
|
||||||
if (!read_leb(p, p_end, &off, 32, false, &res64, \
|
if (!read_leb(p, p_end, &off, 32, false, &res64, \
|
||||||
@ -153,6 +214,17 @@ fail_integer_too_large:
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define read_leb_int32(p, p_end, res) do { \
|
#define read_leb_int32(p, p_end, res) do { \
|
||||||
|
if (p < p_end) { \
|
||||||
|
uint8 _val = *p; \
|
||||||
|
if (!(_val & 0x80)) { \
|
||||||
|
res = (int32)_val; \
|
||||||
|
if (_val & 0x40) \
|
||||||
|
/* sign extend */ \
|
||||||
|
res |= 0xFFFFFF80; \
|
||||||
|
p++; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
uint32 off = 0; \
|
uint32 off = 0; \
|
||||||
uint64 res64; \
|
uint64 res64; \
|
||||||
if (!read_leb(p, p_end, &off, 32, true, &res64, \
|
if (!read_leb(p, p_end, &off, 32, true, &res64, \
|
||||||
@ -1878,8 +1950,7 @@ wasm_loader_find_block_addr(WASMModule *module,
|
|||||||
{
|
{
|
||||||
const uint8 *p = start_addr, *p_end = code_end_addr;
|
const uint8 *p = start_addr, *p_end = code_end_addr;
|
||||||
uint8 *else_addr = NULL;
|
uint8 *else_addr = NULL;
|
||||||
uint32 block_nested_depth = 1, count, i, u32;
|
uint32 block_nested_depth = 1, count, i;
|
||||||
uint64 u64;
|
|
||||||
uint8 opcode, u8;
|
uint8 opcode, u8;
|
||||||
|
|
||||||
BlockAddr block_stack[16] = { 0 }, *block;
|
BlockAddr block_stack[16] = { 0 }, *block;
|
||||||
@ -1969,24 +2040,24 @@ wasm_loader_find_block_addr(WASMModule *module,
|
|||||||
|
|
||||||
case WASM_OP_BR:
|
case WASM_OP_BR:
|
||||||
case WASM_OP_BR_IF:
|
case WASM_OP_BR_IF:
|
||||||
read_leb_uint32(p, p_end, u32); /* labelidx */
|
skip_leb_uint32(p, p_end); /* labelidx */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WASM_OP_BR_TABLE:
|
case WASM_OP_BR_TABLE:
|
||||||
read_leb_uint32(p, p_end, count); /* lable num */
|
read_leb_uint32(p, p_end, count); /* lable num */
|
||||||
for (i = 0; i <= count; i++) /* lableidxs */
|
for (i = 0; i <= count; i++) /* lableidxs */
|
||||||
read_leb_uint32(p, p_end, u32);
|
skip_leb_uint32(p, p_end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WASM_OP_RETURN:
|
case WASM_OP_RETURN:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WASM_OP_CALL:
|
case WASM_OP_CALL:
|
||||||
read_leb_uint32(p, p_end, u32); /* funcidx */
|
skip_leb_uint32(p, p_end); /* funcidx */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WASM_OP_CALL_INDIRECT:
|
case WASM_OP_CALL_INDIRECT:
|
||||||
read_leb_uint32(p, p_end, u32); /* typeidx */
|
skip_leb_uint32(p, p_end); /* typeidx */
|
||||||
CHECK_BUF(p, p_end, 1);
|
CHECK_BUF(p, p_end, 1);
|
||||||
u8 = read_uint8(p); /* 0x00 */
|
u8 = read_uint8(p); /* 0x00 */
|
||||||
break;
|
break;
|
||||||
@ -2004,7 +2075,7 @@ wasm_loader_find_block_addr(WASMModule *module,
|
|||||||
case WASM_OP_TEE_LOCAL:
|
case WASM_OP_TEE_LOCAL:
|
||||||
case WASM_OP_GET_GLOBAL:
|
case WASM_OP_GET_GLOBAL:
|
||||||
case WASM_OP_SET_GLOBAL:
|
case WASM_OP_SET_GLOBAL:
|
||||||
read_leb_uint32(p, p_end, u32); /* localidx */
|
skip_leb_uint32(p, p_end); /* localidx */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WASM_OP_GET_LOCAL_FAST:
|
case WASM_OP_GET_LOCAL_FAST:
|
||||||
@ -2039,20 +2110,20 @@ wasm_loader_find_block_addr(WASMModule *module,
|
|||||||
case WASM_OP_I64_STORE8:
|
case WASM_OP_I64_STORE8:
|
||||||
case WASM_OP_I64_STORE16:
|
case WASM_OP_I64_STORE16:
|
||||||
case WASM_OP_I64_STORE32:
|
case WASM_OP_I64_STORE32:
|
||||||
read_leb_uint32(p, p_end, u32); /* align */
|
skip_leb_uint32(p, p_end); /* align */
|
||||||
read_leb_uint32(p, p_end, u32); /* offset */
|
skip_leb_uint32(p, p_end); /* offset */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WASM_OP_MEMORY_SIZE:
|
case WASM_OP_MEMORY_SIZE:
|
||||||
case WASM_OP_MEMORY_GROW:
|
case WASM_OP_MEMORY_GROW:
|
||||||
read_leb_uint32(p, p_end, u32); /* 0x00 */
|
skip_leb_uint32(p, p_end); /* 0x00 */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WASM_OP_I32_CONST:
|
case WASM_OP_I32_CONST:
|
||||||
read_leb_int32(p, p_end, u32);
|
skip_leb_int32(p, p_end);
|
||||||
break;
|
break;
|
||||||
case WASM_OP_I64_CONST:
|
case WASM_OP_I64_CONST:
|
||||||
read_leb_int64(p, p_end, u64);
|
skip_leb_int64(p, p_end);
|
||||||
break;
|
break;
|
||||||
case WASM_OP_F32_CONST:
|
case WASM_OP_F32_CONST:
|
||||||
p += sizeof(float32);
|
p += sizeof(float32);
|
||||||
@ -2195,8 +2266,6 @@ wasm_loader_find_block_addr(WASMModule *module,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)u32;
|
|
||||||
(void)u64;
|
|
||||||
(void)u8;
|
(void)u8;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ wasi_environ_get(wasm_exec_env_t exec_env,
|
|||||||
&environ_count, &environ_buf_size);
|
&environ_count, &environ_buf_size);
|
||||||
WASI_CHECK_ERR();
|
WASI_CHECK_ERR();
|
||||||
|
|
||||||
total_size = sizeof(uint32) * ((uint64)environ_count + 1);
|
total_size = sizeof(char*) * ((uint64)environ_count + 1);
|
||||||
if (total_size >= UINT32_MAX
|
if (total_size >= UINT32_MAX
|
||||||
|| !validate_app_addr(environ_offset, (uint32)total_size)
|
|| !validate_app_addr(environ_offset, (uint32)total_size)
|
||||||
|| environ_buf_size >= UINT32_MAX
|
|| environ_buf_size >= UINT32_MAX
|
||||||
|
Reference in New Issue
Block a user