• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Longque-JS-API使用指导
2Longque JS API 由 Longque JS Engine 提供,适用于在 OpenHarmony 平台构建稳定、高性能的应用。所有 API 均位于 `__Longque__` 对象下。接口的版本可通过 `__Longque__.version` 获得,开发者可使用该版本进行特性判断。
3
4**【注意】:Longque JS API 处于实验阶段,使用前请阅读本文档,评估其稳定性和兼容性。**
5
6## 接口说明
7| 接口                       | 功能说明                            |
8|----------------------------|-------------------------------------|
9|createDelegate         | 创建委托 |
10
11## 属性说明
12| 属性                       | 功能说明                            |
13|----------------------------|-------------------------------------|
14|version         | 用于表示 Longque JS API 的版本|
15|SKIP_PROTOTYPE_CHAIN |createDelegate 的属性过滤器,表示只委托自身属性,不考虑原型链|
16|SKIP_PREFIX_UNDERSCORE |createDelegate 的属性过滤器,表示过滤掉名字以 '_' 开头的属性|
17|SKIP_PREFIX_DOLLAR |createDelegate 的属性过滤器,表示过滤掉名字以 '$' 开头的属性|
18|SKIP_CONSTRUCTOR |createDelegate 的属性过滤器,表示过滤掉 'constructor' 属性|
19
20## createDelegate接口
21> 接口引入版本 : 1
22
23### 接口描述
24| 接口  | 名称  | 说明 |
25| -- | -- | -- |
26| createDelegate | 创建委托 | 创建 `underlyingObject` 的委托对象,对委托对象的属性读写操作将映射至 `underlyingObject`。通过 `initObject` 指定初始委托对象,通过 `propertyFilterFlags` 指定属性过滤器。默认情况下,将映射 `underlyingObject` 及其原型链上所有可枚举的字符串键属性。
27
28### 参数
29(1) `underlyingObject`: 必选参数。表示被委托的底层对象。参数要求:
30- `underlyingObject` 必须是对象,否则会抛出 `TypeError` 异常。
31- 若 `underlyingObject` 是代理对象,将抛出 `TypeError` 异常。
32- 若未指定 `SKIP_PROTOTYPE_CHAIN` 过滤器,且 `underlyingObject` 原型链上存在代理对象,则抛出 `TypeError` 异常。
33
34(2) `initObject`:可选参数。表示初始委托对象。若传入 undefined,表示不指定初始对象,将由接口自动创建。参数要求:
35- `initObject` 必须是对象,否则会抛出 `TypeError` 异常。
36- 若 `initObject` 是代理对象,将抛出 `TypeError` 异常。
37- 不能将委托对象作为 `initObject`,否则抛出 `TypeError` 异常。
38- 若 `initObject` 是不可扩展的,则抛出 `TypeError` 异常。
39- 若 `initObject` 中某些属性无法定义,将抛出 `TypeError` 异常,此时 `initObject` 中仅部分属性定义成功。
40
41(3) `propertyFilterFlags`:可选参数。表示属性过滤器。如果传入的是 undefined,表示不指定过滤器。参数要求:
42- 以下列出了当前支持的属性过滤器(未来可能扩展)。
43```sh
44__Longque__.SKIP_PROTOTYPE_CHAIN: 只委托 underlyingObject 自身属性,不考虑原型链
45__Longque__.SKIP_PREFIX_UNDERSCORE: 过滤掉名字以 '_' 开头的属性
46__Longque__.SKIP_PREFIX_DOLLAR: 过滤掉名字以 '$' 开头的属性
47__Longque__.SKIP_CONSTRUCTOR: 过滤掉 'constructor' 属性
48```
49- 必须使用列出的过滤器,否则接口行为未定义,可能导致代码兼容性问题。
50- 所有过滤器均为 `number` 类型,可用 | 运算符同时指定多个。
51- 若 `propertyFilterFlags` 非 `number` 类型,抛出 `TypeError` 异常。
52
53### 返回值
54只有接口在不抛出异常的情况下,才会正确返回:
55- 若未指定初始委托对象,返回新创建的委托对象。
56- 若已指定初始委托对象,返回该初始委托对象。
57
58### 注意事项
59(1) 委托对象的属性顺序可能与 for-in、Object.keys 方法的结果不一致,请勿依赖属性顺序。
60
61(2) 委托对象的实现是引擎内部机制。请勿依赖在委托对象上调用 `Object.getOwnPropertyDescriptor`、`getOwnPropertyDescriptors`、`Reflect.getOwnPropertyDescriptor` 等接口的返回结果。
62
63### 使用示例
64
65本示例展示了在 JSVM 中使用 Longque JS API 的方式,JSVM-API 接口开发流程参考[使用JSVM-API实现JS与C/C++语言交互开发流程](use-jsvm-process.md),本文仅对接口对应C++相关代码进行展示。
66
67cpp部分代码:
68``` cpp
69// 待执行的js代码
70static const char *STR_TASK = R"JS(
71  function createDelegateTest() {
72    var myobj = {
73      42: 0,
74      x: 1,
75      _y: 2,
76      $z:3
77    };
78
79    var proto = {
80      foo: 'foo'
81    };
82    Object.setPrototypeOf(myobj, proto);
83
84    var d1 = __Longque__.createDelegate(myobj, undefined);
85    consoleinfo(JSON.stringify(d1)); // {"42":0,"x":1,"_y":2,"$z":3,"foo":"foo"}
86
87    const propertyFilterFlags = __Longque__.SKIP_PREFIX_UNDERSCORE | __Longque__.SKIP_PREFIX_DOLLAR;
88    var d2 = __Longque__.createDelegate(myobj, undefined, propertyFilterFlags);
89    consoleinfo(JSON.stringify(d2)); // {"42":0,"x":1,"foo":"foo"}
90
91    d2[42] = 100;
92
93    const newFilter = propertyFilterFlags | __Longque__.SKIP_PROTOTYPE_CHAIN;
94    var d3 = __Longque__.createDelegate(myobj, undefined, newFilter);
95    consoleinfo(JSON.stringify(d3)); // {"42":100,"x":1}
96  }
97  createDelegateTest();
98)JS";
99
100// 保证js代码中的打印信息可以正常输出
101static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) {
102    size_t argc = 1;
103    JSVM_Value args[1];
104    char log[256] = "";
105    size_t logLength = 0;
106    JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
107
108    OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength);
109    log[255] = 0;
110    OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log);
111    return nullptr;
112}
113
114// 注册consoleinfo的方法
115JSVM_CallbackStruct param[] = {
116    {.data = nullptr, .callback = ConsoleInfo},
117};
118JSVM_PropertyDescriptor descriptor[] = {
119    {"consoleinfo", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
120};
121
122static int32_t TestJSVM() {
123    JSVM_InitOptions init_options;
124    memset(&init_options, 0, sizeof(init_options));
125    if (g_aa == 0) {
126        OH_JSVM_Init(&init_options);
127        g_aa++;
128    }
129    // 创建JavaScript虚拟机实例,打开虚拟机作用域
130    JSVM_VM vm;
131    JSVM_CreateVMOptions options;
132    memset(&options, 0, sizeof(options));
133    CHECK(OH_JSVM_CreateVM(&options, &vm));
134    JSVM_VMScope vm_scope;
135    CHECK(OH_JSVM_OpenVMScope(vm, &vm_scope));
136
137    JSVM_Env env;
138    CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env));
139    JSVM_EnvScope envScope;
140    CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
141    JSVM_HandleScope handlescope;
142    CHECK_RET(OH_JSVM_OpenHandleScope(env, &handlescope));
143    JSVM_Value sourcecodevalue;
144    CHECK_RET(OH_JSVM_CreateStringUtf8(env, STR_TASK, strlen(STR_TASK), &sourcecodevalue));
145    JSVM_Script script;
146    CHECK_RET(OH_JSVM_CompileScript(env, sourcecodevalue, nullptr, 0, true, nullptr, &script));
147    JSVM_Value result;
148    CHECK_RET(OH_JSVM_RunScript(env, script, &result));
149
150    // 关闭并销毁环境和虚拟机
151    CHECK_RET(OH_JSVM_CloseHandleScope(env, handlescope));
152    CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
153    CHECK(OH_JSVM_DestroyEnv(env));
154    CHECK(OH_JSVM_CloseVMScope(vm, vm_scope));
155    CHECK(OH_JSVM_DestroyVM(vm));
156    return 0;
157}
158```
159
160预期的输出:
161```
162JSVM API TEST: {"42":0,"x":1,"_y":2,"$z":3,"foo":"foo"}
163JSVM API TEST: {"42":0,"x":1,"foo":"foo"}
164JSVM API TEST: {"42":100,"x":1}
165```