merge js_worker_module_master and mv to js_worker_module

Signed-off-by: lengchangjing <lengchangjing@huawei.com>
This commit is contained in:
lengchangjing 2022-07-20 15:34:19 +08:00
commit fedc3590e0
20 changed files with 3885 additions and 0 deletions

49
js_worker_module/BUILD.gn Normal file
View File

@ -0,0 +1,49 @@
# Copyright (c) 2022 Huawei Device Co., Ltd.
# 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.
import("//build/ohos.gni")
ohos_shared_library("worker") {
include_dirs = [
"//base/compileruntime/js_worker_module/worker",
"//base/compileruntime/js_worker_module/helper",
"//base/compileruntime/js_worker_module/plugin",
]
sources = [
"helper/napi_helper.cpp",
"plugin/timer.cpp",
"worker/message_queue.cpp",
"worker/native_module_worker.cpp",
"worker/thread.cpp",
"worker/worker.cpp",
"worker/worker_runner.cpp",
]
deps = [ "//foundation/arkui/napi:ace_napi" ]
if (is_standard_system) {
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
} else {
external_deps = [ "hilog:libhilog" ]
}
subsystem_name = "utils"
part_name = "jsapi_worker"
relative_install_dir = "module"
}
group("jsapi_packages") {
deps = [ ":worker" ]
}

177
js_worker_module/LICENSE Normal file
View File

@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

367
js_worker_module/README.md Normal file
View File

@ -0,0 +1,367 @@
# js_worker_module
### Introduction
Worker enables JS to have the ability of multithreading, and completes the communication between worker thread and host thread through PostMessage.
### Interface description
For interface implementation, see: js_worker_module/jsapi/worker
#### Worker object description
The object object used by the host thread to communicate with the worker thread.
##### Interface
1.
- name
|constructor(scriptURL:string, options? WorkerOptions) | worker constructor to Creates a worker instance |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
```
2.
- name
| postMessage(message:Object, options?:PostMessageOptions) | Sends a message to the worker thread |
|---|---|
| postMessage(message:Object, transfer:ArrayBuffer[]) | Sends a message to the worker thread |
- example
```
// example 1
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// example 2
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
var buffer = new ArrayBuffer(8);
worker.postMessage(buffer, [buffer]);
```
3.
- name
| on(type:string, listener:EventListener) | Adds an event listener to the worker |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.on("alert", (e)=>{
console.log("worker on...");
})
```
4.
- name
| once(type:string, listener:EventListener) | Adds an event listener to the worker and removes the event listener automically after it is invoked once |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.once("alert", (e)=>{
console.log("worker on...");
})
```
5.
- name
| off(type:string, listener?:EventListener) | Removes an event listener to the worker |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.off("alert");
```
6.
- name
| terminate() | Terminates the worker thread to stop the worker from receiving messages |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.terminate();
```
7.
- name
| removeEventListener(type:string, listener?:EventListener) | Removes an event defined for the worker |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.removeEventListener("alert");
```
8.
- name
| dispatchEvent(event: Event) | Dispatches the event defined for the worker |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.dispatchEvent({type:"alert"});
```
9.
- name
| removeAllListener() | Removes all event listeners for the worker |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.removeAllListener();
```
##### Attribute
1.
- name
| onexit?:(code:number)=>void | The onexit attribute of the worker specifies the event handler to be called when the worker exits. The handler is executed in the host thread |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.onexit = function(e) {
console.log("onexit...");
}
```
2.
- name
| onerror?:(ev:ErrorEvent)=>void | The onerror attribute of the worker specifies the event handler to be called when an exception occurs during worker execution. The event handler is executed in the host thread |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.onerror = function(e) {
console.log("onerror...");
}
```
3.
- name
| onmessage?:(ev:MessageEvent)=>void | The onmessage attribute of the worker specifies the event handler to be called then the host thread receives a message created by itself and sent by the worker through the parentPort.postMessage. The event handler is executed in the host thread |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.onmessage = function(e) {
console.log("onmessage...");
}
```
4.
- name
| onmessageerror?:(event:MessageEvent)=>void | The onmessage attribute of the worker specifies the event handler when the worker receives a message that cannot be serialized. The event handler is executed in the host thread |
|---|---|
- example
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.onmessageerror = function(e) {
console.log("onmessageerror...");
}
```
#### parentPort object description
Object of the worker thread used to communicate with the host thread
##### Interface
1.
- name
| postMessage(message:Object, options?:PostMessageOptions) | Send a message to host thread |
|---|---|
| postMessage(message:Object, transfer:ArrayBuffer[]) | Send a message to host thread |
- example
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onmessage = function(e) {
parentPort.postMessage("hello world from worker.js");
}
```
2.
- name
| close() | Close the worker thread to stop the worker from receiving messages |
|---|---|
- example
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onmessage = function(e) {
parentPort.close();
}
```
##### Attribute
1.
- name
| onmessage?:(event:MessageEvent)=>void | The onmessage attribute of parentPort specifies the event handler to be called then the worker thread receives a message sent by the host thread through worker postMessage. The event handler is executed in the worker thread |
|---|---|
- example
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onmessage = function(e) {
console.log("receive main.js message");
}
```
2.
- name
| onerror?:(ev: ErrorEvent)=>void | The onerror attribute of parentPort specifies the event handler to be called when an exception occurs during worker execution. The event handler is executed in the worker thread |
|---|---|
- example
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onerror = function(e) {
console.log("onerror...");
}
```
3.
- name
| onmessageerror?:(event: MessageEvent)=>void | The onmessage attribute of parentPort specifies the event handler to be called then the worker receives a message that cannot be deserialized. The event handler is executed in the worker thread. |
|---|---|
- example
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onmessageerror = function(e) {
console.log("onmessageerror...");
}
```
### Repositories Involved
- ace_ace_engine(foundation/arkui/ace_engine-readme.md)
- ace_napi(foundation/arkui/napi-readme.md)
## Related warehouse
[js_worker_module Subsystem](base/compileruntime/js_worker_module-readme.md)
### License
Worker is available under [Mozilla license](https://www.mozilla.org/en-US/MPL/), and the documentation is detailed in [documentation](https://gitee.com/openharmony/js_worker_module/blob/master/mozilla_docs.txt). See [LICENSE](https://gitee.com/openharmony/js_worker_module/blob/master/LICENSE) for the full license text.

View File

@ -0,0 +1,368 @@
# js_worker_module
### 简介
worker能够让js拥有多线程的能力通过postMessage完成worker线程与宿主线程通信。
### 接口说明
接口实现详见js_worker_module/jsapi/worker
#### Worker对象描述
宿主线程用于与worker线程通信的Object对象。
##### 接口
1.
- 接口名
|constructor(scriptURL:string, options? WorkerOptions) | 构造函数 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
```
2.
- 接口名
| postMessage(message:Object, options?:PostMessageOptions) | 向worker线程发送消息 |
|---|---|
| postMessage(message:Object, transfer:ArrayBuffer[]) | 向worker线程发送消息 |
- 使用示例
```
// 示例一
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// 示例二
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
var buffer = new ArrayBuffer(8);
worker.postMessage(buffer, [buffer]);
```
3.
- 接口名
| on(type:string, listener:EventListener) | 向worker添加一个事件监听 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.on("alert", (e)=>{
console.log("worker on...");
})
```
4.
- 接口名
| once(type:string, listener:EventListener) | 向worker添加一个事件监听, 事件监听只执行一次便自动删除 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.once("alert", (e)=>{
console.log("worker on...");
})
```
5.
- 接口名
| off(type:string, listener?:EventListener) | 删除worker的事件监听 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.off("alert");
```
6.
- 接口名
| terminate() | 关闭worker线程终止worker发送消息 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.terminate();
```
7.
- 接口名
| removeEventListener(type:string, listener?:EventListener) | 删除worker的事件监听 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.removeEventListener("alert");
```
8.
- 接口名
| dispatchEvent(event: Event) | 分发定义在worker的事件 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.dispatchEvent({type:"alert"});
```
9.
- 接口名
| removeAllListener() | 删除worker的所有事件监听 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.removeAllListener();
```
##### 属性
1.
- 属性名
| onexit?:(code:number)=>void | worker退出时被调用的事件处理程序处理程序在宿主线程中执行 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.onexit = function(e) {
console.log("onexit...");
}
```
2.
- 属性名
| onerror?:(ev:ErrorEvent)=>void | worker在执行过程中发生异常被调用的事件处理程序处理程序在宿主线程中执行 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.onerror = function(e) {
console.log("onerror...");
}
```
3.
- 属性名
| onmessage?:(ev:MessageEvent)=>void | 宿主线程收到来自其创建的worker通过parentPort.postMessage接口发送的消息时被调用的事件处理程序 处理程序在宿主线程中执行 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.onmessage = function(e) {
console.log("onmessage...");
}
```
4.
- 属性名
| onmessageerror?:(event:MessageEvent)=>void | worker对象接收到一条无法序列化的消息时被调用的事件处理程序 处理程序在宿主线程中执行 |
|---|---|
- 使用示例
```
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.onmessageerror = function(e) {
console.log("onmessageerror...");
}
```
#### parentPort对象描述
worker线程用于与宿主线程通信的Object对象。
##### 接口
1.
- 接口名
| postMessage(message:Object, options?:PostMessageOptions) | 向宿主线程发送消息 |
|---|---|
| postMessage(message:Object, transfer:ArrayBuffer[]) | 向宿主线程发送消息 |
- 使用示例
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onmessage = function(e) {
parentPort.postMessage("hello world from worker.js");
}
```
2.
- 接口名
| close() | 关闭worker线程终止worker接收消息 |
|---|---|
- 使用示例
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onmessage = function(e) {
parentPort.close();
}
```
##### 属性
1.
- 属性名
| onmessage?:(event:MessageEvent)=>void | 宿主线程收到来自其创建的worker通过worker.postMessage接口发送的消息时被调用的事件处理程序处理程序在worker线程中执行 |
|---|---|
- 使用示例
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onmessage = function(e) {
console.log("receive main.js message");
}
```
2.
- 属性名
| onerror?:(ev: ErrorEvent)=>void | worker在执行过程中发生异常被调用的事件处理程序处理程序在worker线程中执行 |
|---|---|
- 使用示例
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onerror = function(e) {
console.log("onerror...");
}
```
3.
- 属性名
| onmessageerror?:(event: MessageEvent)=>void | worker对象接收到一条无法被反序列化的消息时被调用的事件处理程序 处理程序在worker线程中执行 |
|---|---|
- 使用示例
```
// main.js
import worker from "@ohos.worker"
const worker = new worker.Worker("workers/worker.js");
worker.postMessage("hello world");
// worker.js
import worker from "@ohos.worker"
const parentPort = worker.parentPort;
parentPort.onmessageerror = function(e) {
console.log("onmessageerror...");
}
```
### 涉及仓
- ace_ace_engine(foundation/arkui/ace_engine-readme_zh.md)
- ace_napi(foundation/arkui/napi-readme_zh.md)
## 相关仓
[js_worker_module 子系统](base/compileruntime/js_worker_module-readme_zh.md)
### 许可证
Worker在[Mozilla许可证](https://www.mozilla.org/en-US/MPL/)下可用,说明文档详见[说明文档](https://gitee.com/openharmony/js_worker_module/blob/master/mozilla_docs.txt)。有关完整的许可证文本,有关完整的许可证文本,请参见[许可证](https://gitee.com/openharmony/js_worker_module/blob/master/LICENSE)

View File

@ -0,0 +1,58 @@
{
"name": "@ohos/js_worker_module",
"version": "",
"description": "Provide JS multi-threading capability | 提供JS多线程能力",
"homePage": "https://gitee.com/openharmony",
"license": "Apache V2",
"repository": "https://gitee.com/openharmony/js_worker_module",
"domain": "os",
"language": "",
"publishAs": "code-segment",
"private": false,
"scripts": {},
"tags": [
"js"
],
"keywords": [
"js",
"worker",
"module"
],
"envs": {},
"dirs": {},
"author": {
"name": "",
"email": "",
"url": ""
},
"contributors": [
{
"name": "",
"email": "",
"url": ""
}
],
"segment": {
"destPath": "base/compileruntime/js_worker_module"
},
"component": {
"name": "jsapi_worker",
"subsystem": "utils",
"syscap": [],
"features": [],
"adapted_system_type": [],
"rom": "",
"ram": "",
"deps": {
"components": [],
"third_party": []
},
"build": {
"sub_component": [
"//base/compileruntime/js_worker_module:jsapi_packages"
],
"inner_kits": [],
"test": []
}
}
}

View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#include "base/compileruntime/js_worker_module/helper/napi_helper.h"
#include "native_engine/native_value.h"
namespace CompilerRuntime::WorkerModule::Helper {
const static int32_t MAXCHARLENGTH = 200;
bool NapiHelper::IsString(napi_value value)
{
auto valNative = reinterpret_cast<NativeValue*>(value);
return valNative == nullptr ? false : valNative->TypeOf() == NATIVE_STRING;
}
bool NapiHelper::IsArray(napi_value value)
{
auto valNative = reinterpret_cast<NativeValue*>(value);
return valNative == nullptr ? false : valNative->IsArray();
}
bool NapiHelper::IsConstructor(napi_env env, napi_callback_info cbInfo)
{
napi_value* funcObj = nullptr;
napi_get_new_target(env, cbInfo, funcObj);
return funcObj != nullptr;
}
size_t NapiHelper::GetCallbackInfoArgc(napi_env env, napi_callback_info cbInfo)
{
size_t argc = 0;
napi_get_cb_info(env, cbInfo, &argc, nullptr, nullptr, nullptr);
return argc;
}
napi_value NapiHelper::GetNamePropertyInParentPort(napi_env env, napi_ref parentPort, const char* name)
{
napi_value obj = nullptr;
napi_get_reference_value(env, parentPort, &obj);
napi_value value = nullptr;
napi_get_named_property(env, obj, name, &value);
return value;
}
napi_value NapiHelper::GetUndefinedValue(napi_env env)
{
napi_value result = nullptr;
napi_get_undefined(env, &result);
return result;
}
bool NapiHelper::IsCallable(napi_env env, napi_value value)
{
bool result = false;
napi_is_callable(env, value, &result);
return result;
}
bool NapiHelper::IsCallable(napi_env env, napi_ref value)
{
napi_value obj = nullptr;
napi_get_reference_value(env, value, &obj);
if (obj == nullptr) {
return false;
}
return IsCallable(env, obj);
}
void NapiHelper::SetNamePropertyInGlobal(napi_env env, const char* name, napi_value value)
{
napi_value object = nullptr;
napi_get_global(env, &object);
napi_set_named_property(env, object, name, value);
}
bool NapiHelper::IsObject(napi_value value)
{
auto nativeValue = reinterpret_cast<NativeValue*>(value);
return nativeValue->TypeOf() == NATIVE_OBJECT;
}
char* NapiHelper::GetString(napi_env env, napi_value value)
{
size_t bufferSize = 0;
size_t strLength = 0;
napi_get_value_string_utf8(env, value, nullptr, 0, &bufferSize);
if (bufferSize > MAXCHARLENGTH) {
return nullptr;
}
char* buffer = new char[bufferSize + 1] { 0 };
napi_get_value_string_utf8(env, value, buffer, bufferSize + 1, &strLength);
return buffer;
}
napi_value NapiHelper::CreateBooleanValue(napi_env env, bool value)
{
napi_value result = nullptr;
napi_get_boolean(env, value, &result);
return result;
}
napi_value NapiHelper::GetGlobalObject(napi_env env)
{
napi_value object = nullptr;
napi_get_global(env, &object);
return object;
}
napi_ref NapiHelper::CreateReference(napi_env env, napi_value value, uint32_t refcount)
{
napi_ref callback = nullptr;
napi_create_reference(env, value, refcount, &callback);
return callback;
}
napi_value NapiHelper::CreateUint32(napi_env env, uint32_t value)
{
napi_value result = nullptr;
napi_create_uint32(env, value, &result);
return result;
}
uv_loop_t* NapiHelper::GetLibUV(napi_env env)
{
uv_loop_t* loop;
napi_get_uv_event_loop(env, &loop);
return loop;
}
napi_value NapiHelper::GetReferenceValue(napi_env env, napi_ref ref)
{
napi_value result = nullptr;
napi_get_reference_value(env, ref, &result);
return result;
}
void NapiHelper::DeleteReference(napi_env env, napi_ref ref)
{
napi_delete_reference(env, ref);
}
napi_value NapiHelper::GetNameProperty(napi_env env, napi_value obj, const char* name)
{
napi_value result = nullptr;
napi_get_named_property(env, obj, name, &result);
return result;
}
bool NapiHelper::GetBooleanValue(napi_env env, napi_value value)
{
bool result = false;
napi_get_value_bool(env, value, &result);
return result;
}
bool NapiHelper::StrictEqual(napi_env env, napi_value value, napi_value cmpValue)
{
bool isEqual = false;
napi_strict_equals(env, value, cmpValue, &isEqual);
return isEqual;
}
} // namespace CompilerRuntime::WorkerModule::Helper

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef JS_WORKER_MODULE_HELPER_NAPI_HELPER_H_
#define JS_WORKER_MODULE_HELPER_NAPI_HELPER_H_
#include <uv.h>
#include "napi/native_api.h"
#include "napi/native_node_api.h"
namespace CompilerRuntime::WorkerModule::Helper {
class NapiHelper {
public:
static bool IsString(napi_value value);
static bool IsArray(napi_value value);
static bool IsConstructor(napi_env env, napi_callback_info cbInfo);
static bool IsCallable(napi_env env, napi_value value);
static bool IsCallable(napi_env env, napi_ref value);
static size_t GetCallbackInfoArgc(napi_env env, napi_callback_info cbInfo);
static napi_value GetNamePropertyInParentPort(napi_env env, napi_ref parentPort, const char* name);
static void SetNamePropertyInGlobal(napi_env env, const char* name, napi_value value);
static napi_value GetUndefinedValue(napi_env env);
static bool IsObject(napi_value value);
static char* GetString(napi_env env, napi_value value);
static napi_value CreateBooleanValue(napi_env env, bool value);
static napi_value GetGlobalObject(napi_env env);
static napi_ref CreateReference(napi_env env, napi_value value, uint32_t initial_refcount);
static napi_value CreateUint32(napi_env env, uint32_t value);
static uv_loop_t* GetLibUV(napi_env env);
static napi_value GetReferenceValue(napi_env env, napi_ref ref);
static void DeleteReference(napi_env env, napi_ref ref);
static napi_value GetNameProperty(napi_env env, napi_value obj, const char* name);
static bool GetBooleanValue(napi_env env, napi_value value);
static bool StrictEqual(napi_env env, napi_value value, napi_value cmpValue);
};
} // namespace CompilerRuntime::WorkerModule::Helper
#endif // JS_WORKER_MODULE_HELPER_NAPI_HELPER_H_

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef JS_WORKER_MODULE_WORKER_OBJECT_HELPER_H_
#define JS_WORKER_MODULE_WORKER_OBJECT_HELPER_H_
namespace CompilerRuntime::WorkerModule::Helper {
class DereferenceHelp {
public:
template<typename Inner, typename Outer>
static Outer* DereferenceOf(const Inner Outer::*field, const Inner* pointer)
{
if (field != nullptr && pointer != nullptr) {
auto fieldOffset = reinterpret_cast<uintptr_t>(&(static_cast<Outer*>(0)->*field));
auto outPointer = reinterpret_cast<Outer*>(reinterpret_cast<uintptr_t>(pointer) - fieldOffset);
return outPointer;
}
return nullptr;
}
};
class CloseHelp {
public:
template<typename T>
static void DeletePointer(const T* value, bool isArray)
{
if (value == nullptr) {
return;
}
if (isArray) {
delete[] value;
} else {
delete value;
}
}
};
template<typename T>
class ObjectScope {
public:
ObjectScope(const T* data, bool isArray) : data_(data), isArray_(isArray) {}
~ObjectScope()
{
if (data_ == nullptr) {
return;
}
if (isArray_) {
delete[] data_;
} else {
delete data_;
}
}
private:
const T* data_;
bool isArray_;
};
} // namespace CompilerRuntime::WorkerModule::Helper
#endif // JS_WORKER_MODULE_WORKER_OBJECT_HELPER_H_

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
The definitions of some interfaces implemented in jsapi/workers/worker.cpp are released under Mozilla license.
The definitions and functions of these interfaces are consistent with the standard interfaces under mozila license,
but the implementation of specific functions is independent and self-developed.
All interfaces are described in d.ts, the following is the interface written in d.ts under to Mozilla license
export interface WorkerOptions {
type?: "classic" | "module";
name?: string;
shared?: boolean;
}
export interface Event {
readonly type: string;
readonly timeStamp: number;
}
interface ErrorEvent extends Event {
readonly message: string;
readonly filename: string;
readonly lineno: number;
readonly colno: number;
readonly error: Object;
}
declare interface MessageEvent<T = Object> extends Event {
readonly data: T;
}
export interface PostMessageOptions {
transfer?: Object[];
}
export interface EventListener {
(evt: Event): void | Promise<void>;
}
type MessageType = "message" | "messageerror";
declare interface EventTarget {
addEventListener(
type: string,
listener: EventListener
): void;
dispatchEvent(event: Event): boolean;
removeEventListener(
type: string,
callback?: EventListener
): void;
removeAllListener(): void;
}
declare interface WorkerGlobalScope extends EventTarget {
readonly name: string;
onerror?: (ev: ErrorEvent) => void;
readonly self: WorkerGlobalScope & typeof globalThis;
}
declare interface DedicatedWorkerGlobalScope extends WorkerGlobalScope {
onmessage?: (this: DedicatedWorkerGlobalScope, ev: MessageEvent) => void;
onmessageerror?: (this: DedicatedWorkerGlobalScope, ev: MessageEvent) => void;
close(): void;
postMessage(messageObject: Object, transfer: Transferable[]): void;
postMessage(messageObject: Object, options?: PostMessageOptions): void;
}
declare namespace worker {
class Worker extends EventTarget {
constructor(scriptURL: string, options?: WorkerOptions);
onexit?: (code: number) => void;
onerror?: (err: ErrorEvent) => void;
onmessage?: (event: MessageEvent) => void;
onmessageerror?: (event: MessageEvent) => void;
postMessage(message: Object, transfer: ArrayBuffer[]): void;
postMessage(message: Object, options?: PostMessageOptions): void;
terminate(): void;
}
const parentPort: DedicatedWorkerGlobalScope;
}

View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#include "base/compileruntime/js_worker_module/plugin/timer.h"
#include "utils/log.h"
namespace CompilerRuntime::WorkerModule::Plugin {
uint32_t Timer::timeCallbackId = 0;
std::map<uint32_t, TimerCallbackInfo*> Timer::timerTable;
std::mutex Timer::timeLock;
TimerCallbackInfo::~TimerCallbackInfo()
{
Helper::NapiHelper::DeleteReference(env_, callback_);
for (size_t idx = 0; idx < argc_; idx++) {
Helper::NapiHelper::DeleteReference(env_, argv_[idx]);
}
Helper::CloseHelp::DeletePointer(argv_, true);
uv_timer_stop(&timeReq_);
uv_close(reinterpret_cast<uv_handle_t*>(&timeReq_), nullptr);
}
bool Timer::RegisterTime(napi_env env)
{
if (env == nullptr) {
return false;
}
napi_property_descriptor properties[] = {
DECLARE_NAPI_FUNCTION("setTimeout", SetTimeout),
DECLARE_NAPI_FUNCTION("setInterval", SetInterval),
DECLARE_NAPI_FUNCTION("clearTimeout", ClearTimer),
DECLARE_NAPI_FUNCTION("clearInterval", ClearTimer)
};
napi_value globalObj = Helper::NapiHelper::GetGlobalObject(env);
napi_status status = napi_define_properties(env, globalObj, sizeof(properties) / sizeof(properties[0]), properties);
return status == napi_ok;
}
napi_value Timer::SetTimeout(napi_env env, napi_callback_info cbinfo)
{
return Timer::SetTimeoutInner(env, cbinfo, false);
}
napi_value Timer::SetInterval(napi_env env, napi_callback_info cbinfo)
{
return Timer::SetTimeoutInner(env, cbinfo, true);
}
napi_value Timer::ClearTimer(napi_env env, napi_callback_info cbinfo)
{
// 1. check args
size_t argc = Helper::NapiHelper::GetCallbackInfoArgc(env, cbinfo);
if (argc <= 0) {
HILOG_WARN("first arg should be number");
return nullptr;
}
napi_value* argv = new napi_value[argc];
Helper::ObjectScope<napi_value> scope(argv, true);
napi_value thisVar = nullptr;
napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
uint32_t tId;
napi_status status = napi_get_value_uint32(env, argv[0], &tId);
if (status != napi_ok) {
HILOG_WARN("handler should be number");
return nullptr;
}
auto iter = timerTable.find(tId);
if (iter == timerTable.end()) {
HILOG_INFO("handler not in table");
return nullptr;
}
TimerCallbackInfo* callbackInfo = iter->second;
timerTable.erase(tId);
Helper::CloseHelp::DeletePointer(callbackInfo, false);
return Helper::NapiHelper::GetUndefinedValue(env);
}
void Timer::TimerCallback(uv_timer_t* handle)
{
TimerCallbackInfo* callbackInfo = Helper::DereferenceHelp::DereferenceOf(&TimerCallbackInfo::timeReq_, handle);
if (callbackInfo == nullptr) {
return;
}
napi_value callback = Helper::NapiHelper::GetReferenceValue(callbackInfo->env_, callbackInfo->callback_);
napi_value undefinedValue = Helper::NapiHelper::GetUndefinedValue(callbackInfo->env_);
napi_value callbackResult = nullptr;
napi_value* callbackArgv = new napi_value[callbackInfo->argc_];
Helper::ObjectScope<napi_value> scope(callbackArgv, true);
for (size_t idx = 0; idx < callbackInfo->argc_; idx++) {
callbackArgv[idx] = Helper::NapiHelper::GetReferenceValue(callbackInfo->env_, callbackInfo->argv_[idx]);
}
napi_call_function(callbackInfo->env_, undefinedValue, callback,
callbackInfo->argc_, callbackArgv, &callbackResult);
if (callbackResult == nullptr) {
HILOG_WARN("call callback error");
return;
}
if (!callbackInfo->repeat_) {
timerTable.erase(callbackInfo->tId_);
Helper::CloseHelp::DeletePointer(callbackInfo, false);
} else {
uv_timer_again(handle);
}
}
napi_value Timer::SetTimeoutInner(napi_env env, napi_callback_info cbinfo, bool repeat)
{
// 1. check args
size_t argc = Helper::NapiHelper::GetCallbackInfoArgc(env, cbinfo);
if (argc <= 0) {
napi_throw_error(env, nullptr, "callback must be a function. received undefined");
return nullptr;
}
napi_value* argv = new napi_value[argc];
Helper::ObjectScope<napi_value> scope(argv, true);
napi_value thisVar = nullptr;
napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
if (!Helper::NapiHelper::IsCallable(env, argv[0])) {
napi_throw_error(env, nullptr, "callback must be a function.");
return nullptr;
}
uint32_t timeout = 0;
if (argc > 1) {
napi_status status = napi_get_value_uint32(env, argv[1], &timeout);
if (status != napi_ok) {
HILOG_WARN("timeout should be number");
timeout = 0;
}
}
// 2. get callback args
size_t callbackArgc = argc >= 2 ? argc - 2 : 0; // 2 include callback and timeout
napi_ref* callbackArgv = nullptr;
if (callbackArgc > 0) {
callbackArgv = new napi_ref[callbackArgc];
for (size_t idx = 0; idx < callbackArgc; idx++) {
callbackArgv[idx] =
Helper::NapiHelper::CreateReference(env, argv[idx + 2], 1); // 2 include callback and timeout
}
}
// 3. generate time callback id;
uint32_t tId = 0;
{
std::lock_guard<std::mutex> lock(timeLock);
tId = timeCallbackId++;
}
// 4. generate time callback info
napi_ref callbackRef = Helper::NapiHelper::CreateReference(env, argv[0], 1);
TimerCallbackInfo* callbackInfo =
new TimerCallbackInfo(env, tId, timeout, callbackRef, repeat, callbackArgc, callbackArgv);
// 5. push callback info into timerTable
timerTable[tId] = callbackInfo;
// 6. start timer
uv_timer_start(&callbackInfo->timeReq_, TimerCallback, timeout, timeout > 0 ? timeout : 1);
return Helper::NapiHelper::CreateUint32(env, tId);
}
void Timer::ClearEnvironmentTimer(napi_env env)
{
auto iter = timerTable.begin();
while (iter != timerTable.end()) {
TimerCallbackInfo* callbackInfo = iter->second;
if (callbackInfo->env_ == env) {
iter = timerTable.erase(iter);
Helper::CloseHelp::DeletePointer(callbackInfo, false);
} else {
iter++;
}
}
}
} // namespace CompilerRuntime::WorkerModule::Plugin

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef JS_WORKER_MODULE_PLUGIN_TIMER_H_
#define JS_WORKER_MODULE_PLUGIN_TIMER_H_
#include <map>
#include <uv.h>
#include "base/compileruntime/js_worker_module/helper/napi_helper.h"
#include "base/compileruntime/js_worker_module/helper/object_helper.h"
#include "napi/native_api.h"
#include "napi/native_node_api.h"
namespace CompilerRuntime::WorkerModule::Plugin {
struct TimerCallbackInfo {
napi_env env_;
uint32_t tId_;
uint32_t timeout_;
napi_ref callback_;
bool repeat_;
uv_timer_t timeReq_;
size_t argc_;
napi_ref* argv_;
TimerCallbackInfo(napi_env env, uint32_t tId, uint32_t timeout, napi_ref callback,
bool repeat, size_t argc, napi_ref* argv)
: env_(env), tId_(tId), timeout_(timeout), callback_(callback),
repeat_(repeat), argc_(argc), argv_(argv)
{
uv_loop_t* loop = Helper::NapiHelper::GetLibUV(env_);
uv_timer_init(loop, &timeReq_);
}
~TimerCallbackInfo();
};
class Timer {
public:
Timer() = default;
~Timer() = default;
static bool RegisterTime(napi_env env);
static void ClearEnvironmentTimer(napi_env env);
private:
static napi_value SetTimeout(napi_env env, napi_callback_info cbinfo);
static napi_value SetInterval(napi_env env, napi_callback_info cbinfo);
static napi_value ClearTimer(napi_env env, napi_callback_info cbinfo);
static napi_value SetTimeoutInner(napi_env env, napi_callback_info cbinfo, bool repeat);
static void TimerCallback(uv_timer_t* handle);
static uint32_t timeCallbackId;
static std::map<uint32_t, TimerCallbackInfo*> timerTable;
static std::mutex timeLock;
};
} // namespace CompilerRuntime::WorkerModule::Plugin
#endif // JS_WORKER_MODULE_PLUGIN_TIMER_H_

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#include "base/compileruntime/js_worker_module/worker/message_queue.h"
#include "utils/log.h"
namespace CompilerRuntime::WorkerModule {
void MessageQueue::EnQueue(MessageDataType data)
{
queueLock_.lock();
queue_.push(data);
queueLock_.unlock();
}
bool MessageQueue::DeQueue(MessageDataType *data)
{
queueLock_.lock();
if (queue_.empty()) {
queueLock_.unlock();
return false;
}
if (data != nullptr) {
*data = queue_.front();
queue_.pop();
queueLock_.unlock();
} else {
HILOG_ERROR("worker:: data is nullptr.");
}
return true;
}
bool MessageQueue::IsEmpty() const
{
return queue_.empty();
}
void MessageQueue::Clear(napi_env env)
{
queueLock_.lock();
size_t size = queue_.size();
for (size_t i = 0; i < size; i++) {
MessageDataType data = queue_.front();
napi_delete_serialization_data(env, data);
queue_.pop();
}
queueLock_.unlock();
}
} // namespace CompilerRuntime::WorkerModule

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef JS_WORKER_MODULE_WORKER_MESSAGE_QUEUE_H_
#define JS_WORKER_MODULE_WORKER_MESSAGE_QUEUE_H_
#include <mutex>
#include <queue>
#include "napi/native_api.h"
#include "napi/native_node_api.h"
namespace CompilerRuntime::WorkerModule {
using MessageDataType = napi_value;
class MessageQueue final {
public:
void EnQueue(MessageDataType data);
bool DeQueue(MessageDataType *data);
bool IsEmpty() const;
void Clear(napi_env env);
size_t GetSize() const
{
return queue_.size();
}
private:
std::mutex queueLock_;
std::queue<MessageDataType> queue_;
};
} // namespace CompilerRuntime::WorkerModule
#endif // JS_WORKER_MODULE_WORKER_MESSAGE_QUEUE_H_

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#include "base/compileruntime/js_worker_module/worker/worker.h"
/*
* module define
*/
static napi_module g_workerModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = CompilerRuntime::WorkerModule::Worker::InitWorker,
.nm_modname = "worker",
.nm_priv = reinterpret_cast<void*>(0),
.reserved = { 0 },
};
/*
* module register
*/
extern "C" __attribute__((constructor)) void Register()
{
napi_module_register(&g_workerModule);
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#include "base/compileruntime/js_worker_module/worker/thread.h"
namespace CompilerRuntime::WorkerModule {
Thread::Thread() : tId_() {}
bool Thread::Start()
{
int ret = uv_thread_create(&tId_, [](void* arg) {
Thread* thread = reinterpret_cast<Thread*>(arg);
thread->Run();
}, this);
return ret != 0;
}
} // namespace CompilerRuntime::WorkerModule

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef JS_WORKER_MODULE_WORKER_THREAD_H_
#define JS_WORKER_MODULE_WORKER_THREAD_H_
#include <uv.h>
namespace CompilerRuntime::WorkerModule {
class Thread {
public:
Thread();
virtual ~Thread() = default;
bool Start();
virtual void Run() = 0;
uv_thread_t GetThreadId() const
{
return tId_;
}
private:
uv_thread_t tId_ {0};
};
} // namespace CompilerRuntime::WorkerModule
#endif // #define JS_WORKER_MODULE_WORKER_THREAD_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,457 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef JS_WORKER_MODULE_WORKER_WORKER_H_
#define JS_WORKER_MODULE_WORKER_WORKER_H_
#include <list>
#include <map>
#include <mutex>
#include "base/compileruntime/js_worker_module/worker/message_queue.h"
#include "base/compileruntime/js_worker_module/helper/napi_helper.h"
#include "base/compileruntime/js_worker_module/helper/object_helper.h"
#include "base/compileruntime/js_worker_module/worker/worker_runner.h"
#include "napi/native_api.h"
#include "napi/native_node_api.h"
#include "native_engine/native_engine.h"
#include "utils/log.h"
namespace CompilerRuntime::WorkerModule {
class Worker {
public:
static const int8_t WORKERPARAMNUM = 2;
enum RunnerState { STARTING, RUNNING, TERMINATEING, TERMINATED };
enum HostState { ACTIVE, INACTIVE };
enum ListenerMode { ONCE, PERMANENT };
enum ScriptMode { CLASSIC, MODULE };
struct WorkerListener {
WorkerListener(napi_env env, napi_ref callback, ListenerMode mode)
: env_(env), callback_(callback), mode_(mode)
{}
~WorkerListener()
{
Helper::NapiHelper::DeleteReference(env_, callback_);
callback_ = nullptr;
}
bool NextIsAvailable() const
{
return mode_ != ONCE;
}
void SetMode(ListenerMode mode)
{
mode_ = mode;
}
bool operator==(const WorkerListener& listener) const;
napi_env env_ {NULL};
napi_ref callback_ {NULL};
ListenerMode mode_ {PERMANENT};
};
struct FindWorkerListener {
FindWorkerListener(napi_env env, napi_ref ref) : env_(env), ref_(ref) {}
bool operator()(const WorkerListener* listener) const
{
napi_value compareObj = Helper::NapiHelper::GetReferenceValue(env_, listener->callback_);
napi_value obj = Helper::NapiHelper::GetReferenceValue(env_, ref_);
// the env of listener and cmp listener must be same env because of Synchronization method
return Helper::NapiHelper::StrictEqual(env_, compareObj, obj);
}
napi_env env_ {nullptr};
napi_ref ref_ {nullptr};
};
/**
* Creates a worker instance.
*
* @param env NAPI environment parameters.
* @param thisVar URL of the script to be executed by the worker.
*/
Worker(napi_env env, napi_ref thisVar);
/**
* The destructor of the Worker.
*/
~Worker();
/**
* The host thread receives the information.
*
* @param req The value of the object passed in by the js layer.
*/
static void HostOnMessage(const uv_async_t* req);
/**
* The host thread receives the information.
*
* @param req The value of the object passed in by the js layer.
*/
static void HostOnError(const uv_async_t* req);
/**
* The worker thread receives the information.
*
* @param req The value of the object passed in by the js layer.
*/
static void WorkerOnMessage(const uv_async_t* req);
/**
* ExecuteIn in thread.
*
* @param data The worker pointer.
*/
static void ExecuteInThread(const void* data);
/**
* Post a message.
*
* @param env NAPI environment parameters.
* @param thisVar The callback information of the js layer.
*/
static napi_value PostMessage(napi_env env, napi_callback_info cbinfo);
/**
* Add event listeners to host.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value PostMessageToHost(napi_env env, napi_callback_info cbinfo);
/**
* Terminates the worker thread to stop the worker from receiving messages.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value Terminate(napi_env env, napi_callback_info cbinfo);
/**
* Close the worker.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value CloseWorker(napi_env env, napi_callback_info cbinfo);
/**
* Adds an event listener to the worker.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value On(napi_env env, napi_callback_info cbinfo);
/**
* Adds an event listener to the worker and removes the event listener automatically after it is invoked once.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value Once(napi_env env, napi_callback_info cbinfo);
/**
* Removes an event listener to the worker.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value Off(napi_env env, napi_callback_info cbinfo);
/**
* Add event listeners.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value AddEventListener(napi_env env, napi_callback_info cbinfo);
/**
* Dispatch the event.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value DispatchEvent(napi_env env, napi_callback_info cbinfo);
/**
* Remove the event listener.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value RemoveEventListener(napi_env env, napi_callback_info cbinfo);
/**
* Remove all listener.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value RemoveAllListener(napi_env env, napi_callback_info cbinfo);
/**
* Add the listener.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value AddListener(napi_env env, napi_callback_info cbinfo, ListenerMode mode);
/**
* Remove the listener.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value RemoveListener(napi_env env, napi_callback_info cbinfo);
/**
* The constructor of worker.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value WorkerConstructor(napi_env env, napi_callback_info cbinfo);
/**
* Initialize the worker.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value InitWorker(napi_env env, napi_value exports);
/**
* Cancel the task.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value CancelTask(napi_env env, napi_callback_info cbinfo);
/**
* The parent port cancels the task.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value ParentPortCancelTask(napi_env env, napi_callback_info cbinfo);
/**
* The parent port adds an event listener.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value ParentPortAddEventListener(napi_env env, napi_callback_info cbinfo);
/**
* The parent port removes all event listener.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value ParentPortRemoveAllListener(napi_env env, napi_callback_info cbinfo);
/**
* The parent port dispatch the event listener.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value ParentPortDispatchEvent(napi_env env, napi_callback_info cbinfo);
/**
* The parent port removes the event listener.
*
* @param env NAPI environment parameters.
* @param cbinfo The callback information of the js layer.
*/
static napi_value ParentPortRemoveEventListener(napi_env env, napi_callback_info cbinfo);
void StartExecuteInThread(napi_env env, const char* script);
bool UpdateWorkerState(RunnerState state);
bool UpdateHostState(HostState state);
bool IsRunning() const
{
return runnerState_.load(std::memory_order_acquire) == RUNNING;
}
bool IsTerminated() const
{
return runnerState_.load(std::memory_order_acquire) >= TERMINATED;
}
bool IsTerminating() const
{
return runnerState_.load(std::memory_order_acquire) == TERMINATEING;
}
void SetScriptMode(ScriptMode mode)
{
scriptMode_ = mode;
}
void AddListenerInner(napi_env env, const char* type, const WorkerListener* listener);
void RemoveListenerInner(napi_env env, const char* type, napi_ref callback);
void RemoveAllListenerInner();
uv_loop_t* GetWorkerLoop() const
{
if (workerEnv_ != nullptr) {
return Helper::NapiHelper::GetLibUV(workerEnv_);
}
return nullptr;
}
void SetWorkerEnv(napi_env workerEnv)
{
workerEnv_ = workerEnv;
}
std::string GetScript() const
{
return script_;
}
std::string GetName() const
{
return name_;
}
bool ClearWorkerTasks()
{
if (hostEnv_ != nullptr) {
workerMessageQueue_.Clear(hostEnv_);
return true;
}
return false;
}
bool HostIsStop() const
{
return hostState_.load(std::memory_order_acquire) == INACTIVE;
}
bool IsSameWorkerEnv(napi_env env) const
{
return workerEnv_ == env;
}
void Loop()
{
uv_loop_t* loop = GetWorkerLoop();
if (loop != nullptr) {
uv_run(loop, UV_RUN_DEFAULT);
} else {
HILOG_ERROR("worker:: Worker loop is nullptr when start worker loop");
}
}
private:
void WorkerOnMessageInner();
void HostOnMessageInner();
void HostOnErrorInner();
void HostOnMessageErrorInner();
void WorkerOnMessageErrorInner();
void WorkerOnErrorInner(napi_value error);
void HandleException();
bool CallWorkerFunction(size_t argc, const napi_value* argv, const char* methodName, bool tryCatch);
void CallHostFunction(size_t argc, const napi_value* argv, const char* methodName) const;
void HandleEventListeners(napi_env env, napi_value recv, size_t argc, const napi_value* argv, const char* type);
void ParentPortHandleEventListeners(napi_env env, napi_value recv,
size_t argc, const napi_value* argv, const char* type);
void TerminateInner();
void PostMessageInner(MessageDataType data);
void PostMessageToHostInner(MessageDataType data);
void TerminateWorker();
void CloseInner();
void PublishWorkerOverSignal();
void CloseWorkerCallback();
void CloseHostCallback() const;
void ReleaseWorkerThreadContent();
void ReleaseHostThreadContent();
bool PrepareForWorkerInstance();
void ParentPortAddListenerInner(napi_env env, const char* type, const WorkerListener* listener);
void ParentPortRemoveAllListenerInner();
void ParentPortRemoveListenerInner(napi_env env, const char* type, napi_ref callback);
void PreparePandafile();
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
static void HandleDebuggerTask(const uv_async_t* req);
void DebuggerOnPostTask(std::function<void()>&& task);
#endif
napi_env GetHostEnv() const
{
return hostEnv_;
}
napi_env GetWorkerEnv() const
{
return workerEnv_;
}
std::string script_ {};
std::string name_ {};
ScriptMode scriptMode_ {CLASSIC};
MessageQueue workerMessageQueue_ {};
MessageQueue hostMessageQueue_ {};
MessageQueue errorQueue_ {};
uv_async_t workerOnMessageSignal_ {};
uv_async_t hostOnMessageSignal_ {};
uv_async_t hostOnErrorSignal_ {};
#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
uv_async_t debuggerOnPostTaskSignal_ {};
std::function<void()> debuggerTask_;
#endif
std::atomic<RunnerState> runnerState_ {STARTING};
std::atomic<HostState> hostState_ {ACTIVE};
std::unique_ptr<WorkerRunner> runner_ {};
napi_env hostEnv_ {nullptr};
napi_env workerEnv_ {nullptr};
napi_ref workerRef_ {nullptr};
napi_ref parentPort_ {nullptr};
std::map<std::string, std::list<WorkerListener*>> eventListeners_ {};
std::map<std::string, std::list<WorkerListener*>> parentPortEventListeners_ {};
std::recursive_mutex liveStatusLock_ {};
};
} // namespace CompilerRuntime::WorkerModule
#endif // JS_WORKER_MODULE_WORKER_WORKER_H_

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#include "base/compileruntime/js_worker_module/worker/worker_runner.h"
#include "base/compileruntime/js_worker_module/helper/object_helper.h"
namespace CompilerRuntime::WorkerModule {
WorkerRunner::WorkerRunner(WorkerStartCallback callback) : callback_(callback), selfThreadId_(uv_thread_self()) {}
WorkerRunner::~WorkerRunner()
{
Helper::CloseHelp::DeletePointer(workerInnerRunner_, false);
}
void WorkerRunner::WorkerInnerRunner::Run()
{
if (runner_ != nullptr) {
runner_->Run();
}
}
WorkerRunner::WorkerInnerRunner::WorkerInnerRunner(const WorkerRunner* runner) : runner_(runner) {}
void WorkerRunner::Run() const
{
if (callback_.callback != nullptr) {
callback_.callback(callback_.data);
}
}
bool WorkerRunner::Execute()
{
workerInnerRunner_ = new WorkerInnerRunner(this);
return workerInnerRunner_->Start();
}
} // namespace CompilerRuntime::WorkerModule

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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.
*/
#ifndef JS_WORKER_MODULE_WORKER_WORKER_RUNNER_H_
#define JS_WORKER_MODULE_WORKER_WORKER_RUNNER_H_
#include <functional>
#include "native_engine/native_engine.h"
#include "base/compileruntime/js_worker_module/worker/thread.h"
namespace CompilerRuntime::WorkerModule {
struct WorkerStartCallback {
using CallbackFunction = std::function<void(void*)>;
explicit WorkerStartCallback(CallbackFunction function = nullptr, void* dataArgs = nullptr)
: callback(function), data(dataArgs)
{}
CallbackFunction callback;
void* data;
};
class WorkerRunner {
public:
// real thread execute
class WorkerInnerRunner : public Thread {
public:
explicit WorkerInnerRunner(const WorkerRunner* runner);
~WorkerInnerRunner() = default;
void Run() override;
private:
const WorkerRunner* runner_;
};
explicit WorkerRunner(WorkerStartCallback callback);
~WorkerRunner();
bool Execute();
void Run() const;
void Stop();
private:
WorkerInnerRunner* workerInnerRunner_ {nullptr};
WorkerStartCallback callback_;
uv_thread_t selfThreadId_ {0};
};
} // namespace CompilerRuntime::WorkerModule
#endif // JS_WORKER_MODULE_WORKER_WORKER_RUNNER_H_