• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# JSVM-API开发规范
2
3## 生命周期管理
4
5**【规则】** 合理使用OH_JSVM_OpenHandleScope和OH_JSVM_CloseHandleScope管理JSVM_Value的生命周期,做到生命周期最小化,避免发生内存泄漏问题。
6
7每个JSVM_Value属于特定的HandleScope,HandleScope通过OH_JSVM_OpenHandleScope和OH_JSVM_CloseHandleScope来建立和关闭,HandleScope关闭后,所属的JSVM_Value就会自动释放。
8
9**正确示例**:
10
11```c++
12// 在for循环中频繁调用JSVM接口创建js对象时,要加handle_scope及时释放不再使用的资源。
13// 下面例子中,每次循环结束局部变量res的生命周期已结束,因此加scope及时释放其持有的js对象,防止内存泄漏
14for (int i = 0; i < 100000; i++)
15{
16    JSVM_HandleScope scope = nullptr;
17    OH_JSVM_OpenHandleScope(env, &scope);
18    if (scope == nullptr)
19    {
20        return;
21    }
22    JSVM_Value res;
23    OH_JSVM_CreateObject(env, &res);
24    OH_JSVM_CloseHandleScope(env, scope);
25}
26```
27
28## 上下文敏感
29
30**【规则】** 多引擎实例场景下,禁止通过JSVM-API跨引擎实例访问JS对象。
31
32引擎实例是一个独立运行环境,JS对象创建访问等操作必须在同一个引擎实例中进行。若在不同引擎实例中操作同一个对象,可能会引发程序崩溃。引擎实例在接口中体现为JSVM_Env。
33
34**错误示例**:
35
36```c++
37// 线程1执行,在env1创建string对象,值为"bar"、
38OH_JSVM_CreateStringUtf8(env1, "value1", JSVM_AUTO_LENGTH , &string);
39// 线程2执行,在env2创建object对象,并将上述的string对象设置到object对象中
40JSVM_Status status = OH_JSVM_CreateObject(env2, &object);
41if (status != JSVM_OK)
42{
43    OH_JSVM_ThrowError(env, ...);
44    return;
45}
46
47status = OH_JSVM_SetNamedProperty(env2, object, "string1", string);
48if (status != JSVM_OK)
49{
50    OH_JSVM_ThrowError(env, ...);
51    return;
52}
53```
54
55所有的JS对象都隶属于具体的某一JSVM_Env,不可将env1的对象,设置到env2中的对象中。在env2中一旦访问到env1的对象,程序可能会发生崩溃。
56
57## 异常处理
58
59**【建议】** JSVM-API接口调用发生异常需要及时处理,不能遗漏异常到后续逻辑,否则程序可能发生不可预期行为。
60
61**正确示例**:
62
63```c++
64// 1.创建对象
65JSVM_Status status = OH_JSVM_CreateObject(env, &object);
66if (status != JSVM_OK)
67{
68    OH_JSVM_ThrowError(env, ...);
69    return;
70}
71// 2.创建属性值
72status = OH_JSVM_CreateStringUtf8(env, "bar", JSVM_AUTO_LENGTH, &string);
73if (status != JSVM_OK)
74{
75    OH_JSVM_ThrowError(env, ...);
76    return;
77}
78// 3.将步骤2的结果设置为对象object属性foo的值
79status = OH_JSVM_SetNamedProperty(env, object, "foo", string);
80if (status != JSVM_OK)
81{
82    OH_JSVM_ThrowError(env, ...);
83    return;
84}
85```
86
87如上示例中,步骤1或者步骤2出现异常时,步骤3都不会正常进行。只有当方法的返回值是JSVM_OK时,才能保持继续正常运行;否则后续流程可能会出现不可预期的行为。
88
89## 对象绑定
90
91**【规则】** 使用OH_JSVM_Wrap接口,如果最后一个参数result传递不为nullptr,需要开发者在合适的时机调用OH_JSVM_RemoveWrap函数主动删除创建的JSVM_Ref。
92
93OH_JSVM_Wrap接口定义如下:
94
95```c++
96JSVM_EXTERN JSVM_Status OH_JSVM_Wrap(JSVM_Env env,
97                                     JSVM_Value jsObject,
98                                     void* nativeObject,
99                                     JSVM_Finalize finalizeCb,
100                                     void* finalizeHint,
101                                     JSVM_Ref* result);
102```
103
104当最后一个参数result不为空时,框架会创建一个JSVM_Ref对象,指向js_object。此时开发者需要自己管理js_object的生命周期,即需要在合适的时机调用OH_JSVM_RemoveWrap删除JSVM_Ref,这样GC才能正常释放js_object,从而触发绑定C++对象native_object的析构函数finalizeCb。
105
106一般情况下,根据业务情况最后一个参数result可以直接传递为nullptr。
107
108**正确示例**:
109
110```c++
111// 用法1:OH_JSVM_Wrap不需要接收创建的JSVM_Ref,最后一个参数传递nullptr,创建的JSVM_Ref是弱引用,由系统管理,不需要用户手动释放
112OH_JSVM_Wrap(env, jsobject, nativeObject, cb, nullptr, nullptr);
113
114// 用法2:OH_JSVM_Wrap需要接收创建的JSVM_Ref,最后一个参数不为nullptr,返回的JSVM_Ref是强引用,需要用户手动释放,否则会内存泄漏
115JSVM_Ref result;
116OH_JSVM_Wrap(env, jsobject, nativeObject, cb, nullptr, &result);
117// 当js_object和result后续不再使用时,及时调用OH_JSVM_RemoveWrap释放result
118JSVM_Value result1;
119OH_JSVM_RemoveWrap(env, jsobject, result1);
120```
121