• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ark_interop_napi.h"
17 
18 #include <thread>
19 #include <ecmascript/js_tagged_value.h>
20 
21 #include "ark_interop_external.h"
22 #include "ark_interop_internal.h"
23 #include "ark_interop_log.h"
24 #include "ark_interop_scope.h"
25 #include "securec.h"
26 
27 #ifdef ERROR
28 #undef ERROR
29 #endif
30 
31 using namespace panda;
32 using namespace panda::ecmascript;
33 
ARKTSInner_ReportJSErrors(ARKTS_Env env,bool abortIfUnhandled)34 bool ARKTSInner_ReportJSErrors(ARKTS_Env env, bool abortIfUnhandled)
35 {
36     auto vm = P_CAST(env, EcmaVM*);
37     if (!JSNApi::HasPendingException(vm)) {
38         return false;
39     }
40 
41     auto exception = JSNApi::GetAndClearUncaughtException(vm);
42     auto jError = ARKTS_FromHandle(exception);
43 
44     // throw CJ exception
45     ARKTSInner_ThrowJSErrorToCJ(env, jError);
46 
47     return true;
48 }
49 
ARKTSInner_ReportNativeError(const char * format,...)50 void ARKTSInner_ReportNativeError(const char* format, ...)
51 {
52     constexpr size_t MAX_MESSAGE_SIZE = 0x100;
53     char buffer[MAX_MESSAGE_SIZE];
54 
55     va_list args;
56     va_start(args, format);
57 #ifdef __clang__
58     /* code specific to clang compiler */
59 #pragma clang diagnostic push
60 #pragma clang diagnostic ignored "-Wformat-nonliteral"
61 #elif __GNUC__
62     /* code for GNU C compiler */
63 #pragma GCC diagnostic push
64 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
65 #endif
66     int ret = vsnprintf_s(buffer, sizeof(buffer) / sizeof(char), MAX_MESSAGE_SIZE - 1, format, args);
67 #ifdef __clang__
68 #pragma clang diagnostic pop
69 #elif __GNUC__
70 #pragma GCC diagnostic pop
71 #endif
72     va_end(args);
73     const char* formatMsg;
74 
75     if (ret == -1) {
76         formatMsg = format;
77     } else {
78         buffer[ret] = '\0';
79         formatMsg = buffer;
80     }
81     ARKTSInner_ThrowNativeErrorToCJ(formatMsg);
82 }
83 
ARKTSInner_FormatJSError(ARKTS_Env env,ARKTS_Value jsError)84 std::string ARKTSInner_FormatJSError(ARKTS_Env env, ARKTS_Value jsError)
85 {
86     auto vm = P_CAST(env, EcmaVM*);
87     auto exception = BIT_CAST(jsError, Local<JSValueRef>);
88     if (exception->IsString(vm)) {
89         auto errorInsJs = *P_CAST(jsError, StringRef*);
90         return errorInsJs.ToString(vm);
91     } else if (exception->IsError(vm)) {
92         auto errorObJ = *P_CAST(jsError, ObjectRef*);
93         auto nameValue = errorObJ.Get(vm, StringRef::NewFromUtf8(vm, "name"));
94         auto messageValue = errorObJ.Get(vm, StringRef::NewFromUtf8(vm, "message"));
95         auto stackValue = errorObJ.Get(vm, StringRef::NewFromUtf8(vm, "stack"));
96         std::string name = nameValue->IsString(vm) ? nameValue->ToString(vm)->ToString(vm) : "";
97         auto message = messageValue->IsString(vm) ? messageValue->ToString(vm)->ToString(vm) : "";
98         auto stack = stackValue->IsString(vm) ? stackValue->ToString(vm)->ToString(vm) : "";
99         return name + "\n" + message + "\n" + stack;
100     } else {
101         return "[unknown js Error type]";
102     }
103 }
104 
ARKTS_GetGlobalConstant(ARKTS_Env env)105 ARKTS_Value ARKTS_GetGlobalConstant(ARKTS_Env env)
106 {
107     ARKTS_ASSERT_P(env, "env is null");
108     auto vm = P_CAST(env, EcmaVM*);
109     auto result = JSNApi::GetGlobalObject(vm);
110     return ARKTS_FromHandle(result);
111 }
112 
ARKTS_GetPosixThreadId()113 uint64_t ARKTS_GetPosixThreadId()
114 {
115     auto id = std::this_thread::get_id();
116     return *reinterpret_cast<uint64_t*>(&id);
117 }
118 
ARKTS_GetValueType(ARKTS_Env env,ARKTS_Value src)119 ARKTS_ValueType ARKTS_GetValueType(ARKTS_Env env, ARKTS_Value src)
120 {
121     ARKTS_ASSERT(src, "src is null", N_UNDEFINED);
122     auto value = BIT_CAST(src, JSValueRef);
123     if (value.IsHole()) {
124         return N_UNDEFINED;
125     } else if (value.IsNull()) {
126         return N_NULL;
127     } else if (value.IsUndefined()) {
128         return N_UNDEFINED;
129     } else if (value.IsBoolean()) {
130         return N_BOOL;
131     } else if (value.IsNumber()) {
132         return N_NUMBER;
133     }
134 
135     value = *P_CAST(src, JSValueRef*);
136     auto vm = P_CAST(env, EcmaVM*);
137     if (value.IsNull()) {
138         return N_NULL;
139     } else if (value.IsString(vm)) {
140         return N_STRING;
141     } else if (value.IsSymbol(vm)) {
142         return N_SYMBOL;
143     } else if (value.IsFunction(vm)) {
144         return N_FUNCTION;
145     } else if (value.IsBigInt(vm)) {
146         return N_BIGINT;
147     } else if (value.IsNativePointer(vm)) {
148         return N_EXTERNAL;
149     } else {
150         return N_OBJECT;
151     }
152 }
153 
ARKTS_StrictEqual(ARKTS_Env env,ARKTS_Value a,ARKTS_Value b)154 bool ARKTS_StrictEqual(ARKTS_Env env, ARKTS_Value a, ARKTS_Value b)
155 {
156     ARKTS_ASSERT_F(env, "env is NULL");
157     auto aType = ARKTS_GetValueType(env, a);
158     auto bType = ARKTS_GetValueType(env, b);
159     if (aType != bType) {
160         return false;
161     }
162     if (aType == N_UNDEFINED || aType == N_NULL) {
163         return true;
164     }
165     switch (aType) {
166         case N_BOOL: {
167             auto aRef = BIT_CAST(a, BooleanRef);
168             auto bRef = BIT_CAST(b, BooleanRef);
169 
170             return aRef.Value() == bRef.Value();
171         }
172         case N_NUMBER: {
173             auto aRef = BIT_CAST(a, JSValueRef);
174             auto bRef = BIT_CAST(b, JSValueRef);
175 
176             double aValue = aRef.IsInt() ? BIT_CAST(a, IntegerRef).Value() : BIT_CAST(a, NumberRef).Value();
177             double bValue = bRef.IsInt() ? BIT_CAST(b, IntegerRef).Value() : BIT_CAST(b, NumberRef).Value();
178 
179             return aValue == bValue;
180         }
181         default:
182             auto aTag = *P_CAST(a, JSValueRef*);
183             auto bTag = BIT_CAST(b, Local<JSValueRef>);
184             auto vm = P_CAST(env, EcmaVM*);
185             return aTag.IsStrictEquals(vm, bTag);
186     }
187 }
188 
ARKTS_CreateNull()189 ARKTS_Value ARKTS_CreateNull()
190 {
191     return P_CAST(JSTaggedValue::VALUE_NULL, ARKTS_Value);
192 }
193 
ARKTS_IsNull(ARKTS_Value value)194 bool ARKTS_IsNull(ARKTS_Value value)
195 {
196     return P_CAST(value, JSTaggedType) == JSTaggedValue::VALUE_NULL;
197 }
198 
ARKTS_CreateUndefined()199 ARKTS_Value ARKTS_CreateUndefined()
200 {
201     return P_CAST(JSTaggedValue::VALUE_UNDEFINED, ARKTS_Value);
202 }
203 
ARKTS_IsUndefined(ARKTS_Value value)204 bool ARKTS_IsUndefined(ARKTS_Value value)
205 {
206     return P_CAST(value, JSTaggedType) == JSTaggedValue::VALUE_UNDEFINED;
207 }
208 
ARKTS_CreateBool(bool value)209 ARKTS_Value ARKTS_CreateBool(bool value)
210 {
211     return P_CAST(value ? JSTaggedValue::VALUE_TRUE : JSTaggedValue::VALUE_FALSE, ARKTS_Value);
212 }
213 
ARKTS_IsBool(ARKTS_Value value)214 bool ARKTS_IsBool(ARKTS_Value value)
215 {
216     auto v = BIT_CAST(value, JSValueRef);
217     return v.IsBoolean();
218 }
219 
ARKTS_GetValueBool(ARKTS_Value value)220 bool ARKTS_GetValueBool(ARKTS_Value value)
221 {
222     auto tag = BIT_CAST(value, JSValueRef);
223     ARKTS_ASSERT_F(tag.IsBoolean(), "not a boolean");
224     auto boolRef = BIT_CAST(value, BooleanRef);
225     return boolRef.Value();
226 }
227 
ARKTS_CreateF64(double value)228 ARKTS_Value ARKTS_CreateF64(double value)
229 {
230     JSTaggedValue result(value);
231     return BIT_CAST(result, ARKTS_Value);
232 }
233 
ARKTS_CreateI32(int32_t value)234 EXPORT ARKTS_Value ARKTS_CreateI32(int32_t value)
235 {
236     JSTaggedValue result(value);
237     return BIT_CAST(result, ARKTS_Value);
238 }
239 
ARKTS_GetValueNumber(ARKTS_Value value)240 double ARKTS_GetValueNumber(ARKTS_Value value)
241 {
242     auto ref = BIT_CAST(value, JSValueRef);
243     ARKTS_ASSERT_I(ref.IsNumber(), "not a number");
244     if (ref.IsInt()) {
245         return BIT_CAST(value, IntegerRef).Value();
246     } else {
247         return BIT_CAST(value, NumberRef).Value();
248     }
249 }
250 
ARKTS_IsNumber(ARKTS_Value value)251 bool ARKTS_IsNumber(ARKTS_Value value)
252 {
253     auto jValue = BIT_CAST(value, JSValueRef);
254     return jValue.IsNumber();
255 }
256 
257 struct LambdaData {
258     ARKTS_Env env;
259     int64_t lambdaId;
260 };
261 
CJLambdaInvoker(JsiRuntimeCallInfo * callInfo)262 static Local<JSValueRef> CJLambdaInvoker(JsiRuntimeCallInfo* callInfo)
263 {
264     auto data = reinterpret_cast<LambdaData*>(callInfo->GetData());
265     if (!data) {
266         return JSValueRef::Undefined(callInfo->GetVM());
267     }
268     auto result = ARKTSInner_CJLambdaInvoker(P_CAST(callInfo, ARKTS_CallInfo), data->lambdaId);
269     return BIT_CAST(result, Local<JSValueRef>);
270 }
271 
CJLambdaDeleter(void *,void *,void * raw)272 static void CJLambdaDeleter(void* /* env: napi_env */, void* /*invoker*/, void* raw)
273 {
274     auto data = reinterpret_cast<LambdaData*>(raw);
275     if (!data) {
276         return;
277     }
278     ARKTSInner_CJLambdaDeleter(data->env, data->lambdaId);
279     delete data;
280 }
281 
ARKTS_CreateFunc(ARKTS_Env env,int64_t lambdaId)282 ARKTS_Value ARKTS_CreateFunc(ARKTS_Env env, int64_t lambdaId)
283 {
284     ARKTS_ASSERT_P(env, "env is null");
285 
286     auto vm = P_CAST(env, EcmaVM*);
287     auto result = FunctionRef::New(vm, CJLambdaInvoker, CJLambdaDeleter, new LambdaData {env, lambdaId}, true);
288 
289     return ARKTS_FromHandle(result);
290 }
291 
ARKTS_IsClass(ARKTS_Env env,ARKTS_Value value)292 bool ARKTS_IsClass(ARKTS_Env env, ARKTS_Value value)
293 {
294     auto tag = BIT_CAST(value, JSValueRef);
295     if (!tag.IsHeapObject()) {
296         return false;
297     }
298     auto vm = P_CAST(env, EcmaVM*);
299     tag = *P_CAST(value, JSValueRef*);
300     return tag.IsConstructor(vm);
301 }
302 
ARKTS_CreateClass(ARKTS_Env env,int64_t lambdaId,ARKTS_Value base)303 ARKTS_Value ARKTS_CreateClass(ARKTS_Env env, int64_t lambdaId, ARKTS_Value base)
304 {
305     ARKTS_ASSERT_P(env, "env is null");
306 
307     auto vm = P_CAST(env, EcmaVM*);
308 
309     auto result = FunctionRef::NewClassFunction(vm, CJLambdaInvoker, CJLambdaDeleter,
310                                                 new LambdaData {env, lambdaId}, true);
311 
312     if (ARKTS_IsClass(env, base)) {
313         auto baseClass = BIT_CAST(base, Local<FunctionRef>);
314         result->Inherit(vm, baseClass);
315     }
316 
317     return ARKTS_FromHandle(result);
318 }
319 
ARKTS_GetPrototype(ARKTS_Env env,ARKTS_Value value)320 ARKTS_Value ARKTS_GetPrototype(ARKTS_Env env, ARKTS_Value value)
321 {
322     ARKTS_ASSERT_P(env, "env is null");
323     ARKTS_ASSERT_P(ARKTS_IsClass(env, value), "value is not constructor");
324     auto vm = P_CAST(env, EcmaVM*);
325     auto clazz = BIT_CAST(value, Local<FunctionRef>);
326     auto result = clazz->GetFunctionPrototype(vm);
327     return ARKTS_FromHandle(result);
328 }
329 
ARKTS_InstanceOf(ARKTS_Env env,ARKTS_Value object,ARKTS_Value clazz)330 bool ARKTS_InstanceOf(ARKTS_Env env, ARKTS_Value object, ARKTS_Value clazz)
331 {
332     ARKTS_ASSERT_F(env, "env is null");
333     ARKTS_ASSERT_F(ARKTS_IsHeapObject(object), "object is not heap object");
334     ARKTS_ASSERT_F(ARKTS_IsClass(env, clazz), "clazz is not a class");
335 
336     auto vm = P_CAST(env, EcmaVM*);
337     auto targetObject = BIT_CAST(object, Local<JSValueRef>);
338     auto targetClass = BIT_CAST(clazz, Local<FunctionRef>);
339 
340     return targetObject->InstanceOf(vm, targetClass);
341 }
342 
ARKTS_IsCallable(ARKTS_Env env,ARKTS_Value value)343 bool ARKTS_IsCallable(ARKTS_Env env, ARKTS_Value value)
344 {
345     return ARKTS_GetValueType(env, value) == N_FUNCTION;
346 }
347 
348 static constexpr auto MAX_CALL_ARGS = 255;
349 
FormatArguments(int32_t numArgs,ARKTS_Value args[],Local<JSValueRef> * result)350 ARKTS_INLINE void FormatArguments(int32_t numArgs, ARKTS_Value args[], Local<JSValueRef>* result)
351 {
352     for (int32_t i = 0;i < numArgs; ++i) {
353         result[i] = ARKTS_ToHandle<JSValueRef>(args[i]);
354     }
355 }
356 
ARKTS_Call(ARKTS_Env env,ARKTS_Value func,ARKTS_Value thisArg,int32_t numArgs,ARKTS_Value args[])357 ARKTS_Value ARKTS_Call(ARKTS_Env env, ARKTS_Value func, ARKTS_Value thisArg, int32_t numArgs, ARKTS_Value args[])
358 {
359     ARKTS_ASSERT_P(env, "env is null");
360     ARKTS_ASSERT_P(ARKTS_IsCallable(env, func), "func is not callable");
361     ARKTS_ASSERT_P(numArgs >= 0, "numArgs must be non-negative");
362     ARKTS_ASSERT_P(numArgs <= MAX_CALL_ARGS, "too many arguments, 255 most");
363 
364     auto vm = P_CAST(env, EcmaVM*);
365 
366     auto funcHandle = *P_CAST(func, FunctionRef*);
367     auto thisHandle = ARKTS_ToHandle<JSValueRef>(thisArg);
368 
369     Local<JSValueRef> formattedArgs[MAX_CALL_ARGS];
370     FormatArguments(numArgs, args, formattedArgs);
371 
372     auto result = funcHandle.Call(vm, thisHandle, formattedArgs, numArgs);
373 
374     ARKTSInner_ReportJSErrors(env, true);
375 
376     return ARKTS_FromHandle(result);
377 }
378 
ARKTS_New(ARKTS_Env env,ARKTS_Value clazz,int32_t numArgs,ARKTS_Value args[])379 ARKTS_Value ARKTS_New(ARKTS_Env env, ARKTS_Value clazz, int32_t numArgs, ARKTS_Value args[])
380 {
381     ARKTS_ASSERT_P(env, "env is null");
382     ARKTS_ASSERT_P(ARKTS_IsClass(env, clazz), "clazz is not class");
383     ARKTS_ASSERT_P(numArgs >= 0, "numArgs must be non-negative");
384     ARKTS_ASSERT_P(numArgs <= MAX_CALL_ARGS, "too many arguments, 255 most");
385 
386     auto vm = P_CAST(env, EcmaVM*);
387     auto funcHandle = *P_CAST(clazz, FunctionRef*);
388 
389     Local<JSValueRef> formattedArgs[MAX_CALL_ARGS];
390     FormatArguments(numArgs, args, formattedArgs);
391 
392     auto result = funcHandle.Constructor(vm, formattedArgs, numArgs);
393 
394     ARKTSInner_ReportJSErrors(env, true);
395 
396     return ARKTS_FromHandle(result);
397 }
398 
399 // JSArray elements stored in vector mode and dict mode.
400 // default in vector mode,
401 // if capacity grows gap bigger than 1024, will transform to dict mode.
ARKTS_CreateArray(ARKTS_Env env,uint32_t size)402 ARKTS_Value ARKTS_CreateArray(ARKTS_Env env, uint32_t size)
403 {
404     ARKTS_ASSERT_P(env, "env is null");
405 
406     auto vm = P_CAST(env, EcmaVM*);
407     auto result = ArrayRef::New(vm, size);
408     return ARKTS_FromHandle(result);
409 }
410 
ARKTS_CreateArrayWithInit(ARKTS_Env env,uint32_t size,ARKTS_Value * data)411 ARKTS_Value ARKTS_CreateArrayWithInit(ARKTS_Env env, uint32_t size, ARKTS_Value* data)
412 {
413     ARKTS_ASSERT_P(env, "env is null");
414     auto vm = P_CAST(env, EcmaVM*);
415 
416     auto result = ArrayRef::New(vm, size);
417     for (uint32_t i = 0;i < size; ++i) {
418         ArrayRef::SetValueAt(vm, result, i, ARKTS_ToHandle<JSValueRef>(data[i]));
419     }
420 
421     return ARKTS_FromHandle(result);
422 }
423 
ARKTS_GetArrayLength(ARKTS_Env env,ARKTS_Value array)424 uint32_t ARKTS_GetArrayLength(ARKTS_Env env, ARKTS_Value array)
425 {
426     ARKTS_ASSERT_I(env, "env is null");
427     ARKTS_ASSERT_I(ARKTS_IsArray(env, array), "array is not array");
428 
429     auto vm = P_CAST(env, EcmaVM*);
430     auto ref = P_CAST(array, JSValueRef*);
431     if (ref->IsJSArray(vm)) {
432         return P_CAST(array, ArrayRef*)->Length(vm);
433     }
434     auto l = ARKTS_CreateUtf8(env, "length", 6);
435     auto r = ARKTS_GetProperty(env, array, l);
436     if (ARKTS_IsNumber(r)) {
437         auto n = ARKTS_GetValueNumber(r);
438         return static_cast<uint32_t>(n);
439     }
440     return 0;
441 }
442 
ARKTS_SetElement(ARKTS_Env env,ARKTS_Value array,uint32_t index,ARKTS_Value value)443 void ARKTS_SetElement(ARKTS_Env env, ARKTS_Value array, uint32_t index, ARKTS_Value value)
444 {
445     ARKTS_ASSERT_V(env, "env is null");
446     ARKTS_ASSERT_V(ARKTS_IsArray(env, array), "array is not array");
447 
448     auto vm = P_CAST(env, EcmaVM*);
449     auto jArr = BIT_CAST(array, Local<ArrayRef>);
450 
451     ArrayRef::SetValueAt(vm, jArr, index, ARKTS_ToHandle<JSValueRef>(value));
452     ARKTSInner_ReportJSErrors(env, false);
453 }
454 
ARKTS_GetElement(ARKTS_Env env,ARKTS_Value array,uint32_t index)455 ARKTS_Value ARKTS_GetElement(ARKTS_Env env, ARKTS_Value array, uint32_t index)
456 {
457     ARKTS_ASSERT_P(env, "env is null");
458     ARKTS_ASSERT_P(ARKTS_IsArray(env, array), "array is not array");
459     auto vm = P_CAST(env, EcmaVM*);
460     auto arr = BIT_CAST(array, Local<ArrayRef>);
461     ARKTS_ASSERT_P(arr->Length(vm) > index, "out of index");
462 
463     auto result = ArrayRef::GetValueAt(vm, arr, index);
464     ARKTSInner_ReportJSErrors(env, false);
465     return ARKTS_FromHandle(result);
466 }
467 
ARKTS_IsArray(ARKTS_Env env,ARKTS_Value value)468 bool ARKTS_IsArray(ARKTS_Env env, ARKTS_Value value)
469 {
470     ARKTS_ASSERT_F(env, "env is NULL");
471     auto v = BIT_CAST(value, JSValueRef);
472     if (!v.IsHeapObject()) {
473         return false;
474     }
475     v = *P_CAST(value, JSValueRef*);
476     auto vm = P_CAST(env, EcmaVM*);
477     return v.IsArray(vm);
478 }
479 
ARKTS_CreateArrayBuffer(ARKTS_Env env,int32_t length)480 ARKTS_Value ARKTS_CreateArrayBuffer(ARKTS_Env env, int32_t length)
481 {
482     ARKTS_ASSERT_P(env, "env is null");
483     ARKTS_ASSERT_P(length >= 0, "length must be non-negative");
484     auto vm = P_CAST(env, EcmaVM*);
485     auto result = ArrayBufferRef::New(vm, length);
486     return ARKTS_FromHandle(result);
487 }
488 
ARKTS_CreateArrayBufferWithData(ARKTS_Env env,void * buffer,int32_t length,int64_t finalizerHint)489 ARKTS_Value ARKTS_CreateArrayBufferWithData(ARKTS_Env env, void* buffer, int32_t length,
490     int64_t finalizerHint)
491 {
492     ARKTS_ASSERT_P(env, "env is null");
493     ARKTS_ASSERT_P(length >= 0, "length must be non-negative");
494 
495     auto vm = P_CAST(env, EcmaVM*);
496     auto result = ArrayBufferRef::New(vm, buffer, length, ARKTSInner_CJArrayBufferDeleter,
497                                       reinterpret_cast<void*>(finalizerHint));
498 
499     return ARKTS_FromHandle(result);
500 }
501 
ARKTS_IsArrayBuffer(ARKTS_Env env,ARKTS_Value value)502 bool ARKTS_IsArrayBuffer(ARKTS_Env env, ARKTS_Value value)
503 {
504     ARKTS_ASSERT_F(env, "env is null");
505     auto tag = BIT_CAST(value, JSValueRef);
506     if (!tag.IsHeapObject()) {
507         return false;
508     }
509     auto vm = P_CAST(env, EcmaVM*);
510     auto handle = BIT_CAST(value, Local<JSValueRef>);
511     return handle->IsArrayBuffer(vm) || handle->IsTypedArray(vm) || handle->IsDataView(vm);
512 }
513 
ARKTS_GetArrayBufferLength(ARKTS_Env env,ARKTS_Value value)514 int32_t ARKTS_GetArrayBufferLength(ARKTS_Env env, ARKTS_Value value)
515 {
516     ARKTS_ASSERT_I(env, "env is null");
517     ARKTS_ASSERT_I(ARKTS_IsArrayBuffer(env, value), "value is not arrayBuffer");
518 
519     auto vm = P_CAST(env, EcmaVM*);
520     auto handle = BIT_CAST(value, Local<JSValueRef>);
521     if (handle->IsArrayBuffer(vm)) {
522         return BIT_CAST(value, Local<ArrayBufferRef>)->ByteLength(vm);
523     } else if (handle->IsTypedArray(vm)) {
524         auto arr = BIT_CAST(value, Local<TypedArrayRef>);
525         return arr->ByteLength(vm) - arr->ByteOffset(vm);
526     } else {
527         auto arr = BIT_CAST(value, Local<DataViewRef>);
528         return arr->ByteLength() - arr->ByteOffset();
529     }
530 }
531 
ARKTS_GetArrayBufferRawPtr(ARKTS_Env env,ARKTS_Value value)532 void* ARKTS_GetArrayBufferRawPtr(ARKTS_Env env, ARKTS_Value value)
533 {
534     ARKTS_ASSERT_P(env, "env is null");
535     ARKTS_ASSERT_P(ARKTS_IsArrayBuffer(env, value), "value is not arrayBuffer");
536 
537     auto vm = P_CAST(env, EcmaVM*);
538     auto handle = BIT_CAST(value, Local<JSValueRef>);
539     if (handle->IsArrayBuffer(vm)) {
540         return BIT_CAST(value, Local<ArrayBufferRef>)->GetBuffer(vm);
541     } else if (handle->IsTypedArray(vm)) {
542         auto arr = BIT_CAST(value, Local<TypedArrayRef>);
543         auto rawStart = arr->GetArrayBuffer(vm)->GetBuffer(vm);
544         auto rawOffset = arr->ByteOffset(vm);
545         return P_CAST(rawStart, uint8_t*) + rawOffset;
546     } else {
547         auto arr = BIT_CAST(value, Local<DataViewRef>);
548         auto rawStart = arr->GetArrayBuffer(vm)->GetBuffer(vm);
549         auto rawOffset = arr->ByteOffset();
550         return P_CAST(rawStart, uint8_t*) + rawOffset;
551     }
552 }
553 
ARKTS_ArrayBufferReadBytes(ARKTS_Env env,ARKTS_Value buffer,void * dest,int32_t count)554 int32_t ARKTS_ArrayBufferReadBytes(ARKTS_Env env, ARKTS_Value buffer, void* dest, int32_t count)
555 {
556     auto src = ARKTS_GetArrayBufferRawPtr(env, buffer);
557     auto srcSize = ARKTS_GetArrayBufferLength(env, buffer);
558     auto targetSize = std::min(srcSize, count);
559     auto status = memcpy_s(dest, count, src, targetSize);
560     if (status != 0) {
561         LOGE("ARKTS_ArrayBufferReadBytes error, memcpy_s ret %{public}d", status);
562         return 0;
563     }
564     return targetSize;
565 }
566 
ARKTS_CreateExternal(ARKTS_Env env,void * data)567 ARKTS_Value ARKTS_CreateExternal(ARKTS_Env env, void* data)
568 {
569     ARKTS_ASSERT_P(env, "env is null");
570 
571     auto vm = P_CAST(env, EcmaVM*);
572     auto result = NativePointerRef::New(vm, data, ARKTSInner_CJExternalDeleter, env);
573     return ARKTS_FromHandle(result);
574 }
575 
ARKTS_IsExternal(ARKTS_Env env,ARKTS_Value value)576 bool ARKTS_IsExternal(ARKTS_Env env, ARKTS_Value value)
577 {
578     ARKTS_ASSERT_F(env, "env is null");
579     auto prime = BIT_CAST(value, JSValueRef);
580     if (!prime.IsHeapObject()) {
581         return false;
582     }
583     auto handle = BIT_CAST(value, JSValueRef*);
584     auto vm = P_CAST(env, EcmaVM*);
585     return handle->IsNativePointer(vm);
586 }
587 
ARKTS_GetExternalData(ARKTS_Env env,ARKTS_Value value)588 void* ARKTS_GetExternalData(ARKTS_Env env, ARKTS_Value value)
589 {
590     ARKTS_ASSERT_P(ARKTS_IsExternal(env, value), "value is not external data");
591     auto external = *P_CAST(value, NativePointerRef*);
592     return external.Value();
593 }
594 
ARKTS_CreatePromiseCapability(ARKTS_Env env)595 ARKTS_Promise ARKTS_CreatePromiseCapability(ARKTS_Env env)
596 {
597     ARKTS_ASSERT_P(env, "env is null");
598 
599     auto vm = P_CAST(env, EcmaVM*);
600 
601     auto promise = PromiseCapabilityRef::New(vm);
602     auto result = new Global<PromiseCapabilityRef>(vm, promise);
603 
604     return BIT_CAST(result, ARKTS_Promise);
605 }
606 
ARKTS_GetPromiseFromCapability(ARKTS_Env env,ARKTS_Promise prom)607 ARKTS_Value ARKTS_GetPromiseFromCapability(ARKTS_Env env, ARKTS_Promise prom)
608 {
609     ARKTS_ASSERT_P(env, "env is null");
610     ARKTS_ASSERT_P(prom, "prom is null");
611 
612     auto vm = P_CAST(env, EcmaVM*);
613     auto promise = *P_CAST(prom, Global<PromiseCapabilityRef>*);
614     auto result = (*promise)->GetPromise(vm);
615 
616     return ARKTS_FromHandle(result);
617 }
618 
ARKTS_PromiseCapabilityResolve(ARKTS_Env env,ARKTS_Promise prom,ARKTS_Value result)619 void ARKTS_PromiseCapabilityResolve(ARKTS_Env env, ARKTS_Promise prom, ARKTS_Value result)
620 {
621     ARKTS_ASSERT_V(env, "env is null");
622     ARKTS_ASSERT_V(prom, "prom is null");
623 
624     auto vm = P_CAST(env, EcmaVM*);
625     auto promise = P_CAST(prom, Global<PromiseCapabilityRef>*);
626     (*promise)->Resolve(vm, ARKTS_ToHandle<JSValueRef>(result));
627     promise->FreeGlobalHandleAddr();
628     delete promise;
629 }
630 
ARKTS_PromiseCapabilityReject(ARKTS_Env env,ARKTS_Promise prom,ARKTS_Value result)631 void ARKTS_PromiseCapabilityReject(ARKTS_Env env, ARKTS_Promise prom, ARKTS_Value result)
632 {
633     ARKTS_ASSERT_V(env, "env is null");
634     ARKTS_ASSERT_V(prom, "prom is null");
635 
636     auto vm = P_CAST(env, EcmaVM*);
637     auto promise = P_CAST(prom, Global<PromiseCapabilityRef>*);
638     (*promise)->Reject(vm, ARKTS_ToHandle<JSValueRef>(result));
639     promise->FreeGlobalHandleAddr();
640     delete promise;
641 }
642 
ARKTS_IsPromise(ARKTS_Env env,ARKTS_Value value)643 bool ARKTS_IsPromise(ARKTS_Env env, ARKTS_Value value)
644 {
645     ARKTS_ASSERT_F(env, "env is null");
646     auto v = BIT_CAST(value, JSValueRef);
647     if (!v.IsHeapObject()) {
648         return false;
649     }
650     auto vm = P_CAST(env, EcmaVM*);
651     v= *P_CAST(value, JSValueRef*);
652     return v.IsPromise(vm);
653 }
654 
ARKTS_PromiseThen(ARKTS_Env env,ARKTS_Value prom,ARKTS_Value onFulfilled,ARKTS_Value onRejected)655 ARKTS_Value ARKTS_PromiseThen(ARKTS_Env env, ARKTS_Value prom, ARKTS_Value onFulfilled, ARKTS_Value onRejected)
656 {
657     ARKTS_ASSERT_P(env, "env is null");
658     ARKTS_ASSERT_P(ARKTS_IsPromise(env, prom), "arg is not a JSPromise");
659     ARKTS_ASSERT_P(ARKTS_IsCallable(env, onFulfilled), "onFulfilled is not callable");
660 
661     auto vm = P_CAST(env, EcmaVM*);
662     auto promise = *BIT_CAST(prom, PromiseRef*);
663     auto onFulfilledFunc = BIT_CAST(onFulfilled, Local<FunctionRef>);
664     Local<PromiseRef> result;
665     if (!ARKTS_IsUndefined(onRejected)) {
666         ARKTS_ASSERT_P(ARKTS_IsCallable(env, onRejected), "optional arg 'onRejected' is set but not callable");
667         auto onRejectedFunc = BIT_CAST(onRejected, Local<FunctionRef>);
668         result = promise.Then(vm, onFulfilledFunc, onRejectedFunc);
669     } else {
670         result = promise.Then(vm, onFulfilledFunc);
671     }
672     return ARKTS_FromHandle(result);
673 }
674 
ARKTS_PromiseCatch(ARKTS_Env env,ARKTS_Value prom,ARKTS_Value callback)675 ARKTS_Value ARKTS_PromiseCatch(ARKTS_Env env, ARKTS_Value prom, ARKTS_Value callback)
676 {
677     ARKTS_ASSERT_P(env, "env is null");
678     ARKTS_ASSERT_P(ARKTS_IsPromise(env, prom), "arg is not a JSPromise");
679     ARKTS_ASSERT_P(ARKTS_IsCallable(env, callback), "callback is not callable");
680 
681     auto vm = P_CAST(env, EcmaVM*);
682     auto promise = BIT_CAST(prom, PromiseRef*);
683     auto callbackFunc = BIT_CAST(callback, Local<FunctionRef>);
684     auto result = promise->Catch(vm, callbackFunc);
685     return ARKTS_FromHandle(result);
686 }
687 
ARKTS_OpenScope(ARKTS_Env env)688 ARKTS_Scope ARKTS_OpenScope(ARKTS_Env env)
689 {
690     ARKTS_ASSERT_P(env, "env is null");
691     auto vm = P_CAST(env, EcmaVM*);
692     return CJ::ARKTS_ScopeManager::OpenScope(vm);
693 }
694 
ARKTS_Return(ARKTS_Env env,ARKTS_Scope scope,ARKTS_Value value)695 ARKTS_Result ARKTS_Return(ARKTS_Env env, ARKTS_Scope scope, ARKTS_Value value)
696 {
697     ARKTS_ASSERT_P(env, "env is null");
698     ARKTS_ASSERT_P(value, "value is invalid");
699 
700     auto vm = P_CAST(env, EcmaVM*);
701     if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
702         ARKTSInner_ReportNativeError("exit scope of unknown");
703     }
704 
705     return ARKTS_ToResult(vm, value);
706 }
707 
ARKTS_CloseScope(ARKTS_Env env,ARKTS_Scope scope)708 void ARKTS_CloseScope(ARKTS_Env env, ARKTS_Scope scope)
709 {
710     ARKTS_ASSERT_V(env, "env is null");
711     ARKTS_ASSERT_V(scope, "scope is invalid");
712 
713     if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
714         ARKTSInner_ReportNativeError("exit scope of unknown");
715     }
716 }
717 
ARKTSInner_Escape(ARKTS_Env env,ARKTS_Scope scope,ARKTS_Value ret)718 panda::JSValueRef* ARKTSInner_Escape(ARKTS_Env env, ARKTS_Scope scope, ARKTS_Value ret)
719 {
720     if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
721         ARKTSInner_ReportNativeError("exit scope of unknown");
722     }
723 
724     auto vm = P_CAST(env, EcmaVM*);
725     auto value = ARKTS_ToValue(ret);
726 
727     auto result = JSNApi::CreateLocal(vm, value);
728 
729     return BIT_CAST(result, JSValueRef*);
730 }
731 
ARKTS_Throw(ARKTS_Env env,ARKTS_Value error)732 void ARKTS_Throw(ARKTS_Env env, ARKTS_Value error)
733 {
734     ARKTS_ASSERT_V(env, "env is null");
735     auto vm = P_CAST(env, EcmaVM*);
736 
737     if (JSNApi::HasPendingException(vm)) {
738         LOGE("ARKTS_Throw failed, vm has uncaught exception");
739         return;
740     }
741 
742     auto exception = ARKTS_ToHandle<JSValueRef>(error);
743     if (exception->IsString(vm)) {
744         JSNApi::ThrowException(vm, Exception::Error(vm, BIT_CAST(exception, Local<StringRef>)));
745     } else {
746         JSNApi::ThrowException(vm, exception);
747     }
748 }
749 
ARKTS_GetCallEnv(ARKTS_CallInfo info)750 ARKTS_Env ARKTS_GetCallEnv(ARKTS_CallInfo info)
751 {
752     ARKTS_ASSERT_I(info, "info is null");
753     auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
754     auto vm = runInfo->GetVM();
755     return P_CAST(vm, ARKTS_Env);
756 }
757 
ARKTS_GetArgCount(ARKTS_CallInfo info)758 uint32_t ARKTS_GetArgCount(ARKTS_CallInfo info)
759 {
760     ARKTS_ASSERT_I(info, "info is null");
761     auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
762     return runInfo->GetArgsNumber();
763 }
764 
ARKTS_GetArg(ARKTS_CallInfo info,uint32_t index)765 ARKTS_Value ARKTS_GetArg(ARKTS_CallInfo info, uint32_t index)
766 {
767     ARKTS_ASSERT_P(info, "info is null");
768     auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
769     ARKTS_ASSERT_P(runInfo->GetArgsNumber() > index, "out of index");
770     auto result = runInfo->GetCallArgRef(index);
771     return ARKTS_FromHandle(result);
772 }
773 
ARKTS_GetThisArg(ARKTS_CallInfo info)774 ARKTS_Value ARKTS_GetThisArg(ARKTS_CallInfo info)
775 {
776     ARKTS_ASSERT_P(info, "info is null");
777     auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
778     auto result = runInfo->GetThisRef();
779     return ARKTS_FromHandle(result);
780 }
781 
ARKTS_GetGlobalNapiEnv(ARKTS_Env env)782 void* ARKTS_GetGlobalNapiEnv(ARKTS_Env env)
783 {
784     ARKTS_ASSERT_P(env, "env is null");
785     auto vm = P_CAST(env, EcmaVM*);
786     return JSNApi::GetEnv(vm);
787 }
788 
ARKTS_UpdateStackInfo(unsigned long long vmAddress,void * subStackInfo,unsigned int opKind)789 void ARKTS_UpdateStackInfo(unsigned long long vmAddress, void *subStackInfo, unsigned int opKind)
790 {
791     ARKTS_ASSERT_V(vmAddress, "vm is null");
792     ARKTS_ASSERT_V(subStackInfo, "stack info is null");
793     auto vm = reinterpret_cast<panda::EcmaVM*>(vmAddress);
794     panda::JSNApi::UpdateStackInfo(vm, subStackInfo, opKind);
795 }
796 
797 namespace {
798 ARKTS_CycleFreeCallback* g_cycleFreeCallback = nullptr;
799 }
800 
ARKTS_RegisterCycleFreeCallback(ARKTS_CycleFreeCallback callback)801 void ARKTS_RegisterCycleFreeCallback(ARKTS_CycleFreeCallback callback)
802 {
803     if (g_cycleFreeCallback == nullptr) {
804         g_cycleFreeCallback = new ARKTS_CycleFreeCallback(callback);
805     } else {
806         LOGE("register cycle free callback failed, already registered.");
807     }
808 }
809 
CycleFreeFuncInvoker(JsiRuntimeCallInfo * callInfo)810 static Local<JSValueRef> CycleFreeFuncInvoker(JsiRuntimeCallInfo *callInfo)
811 {
812     Local<JSValueRef> result;
813     auto vm = callInfo->GetVM();
814     if (!vm) {
815         LOGE("failed to invoke cycleFree func, vm is null");
816         return result;
817     }
818     result = JSValueRef::Undefined(vm);
819     auto data = reinterpret_cast<LambdaData*>(callInfo->GetData());
820     if (!data) {
821         LOGE("failed to invoke cycleFree func, LambdaData is null");
822         return result;
823     }
824     if (!g_cycleFreeCallback) {
825         LOGE("failed to invoke cycleFree func, cycleFreeCallback is null");
826         return result;
827     }
828     auto value = g_cycleFreeCallback->funcInvoker(P_CAST(callInfo, ARKTS_CallInfo), data->lambdaId);
829     auto res = ARKTS_ToResult(vm, value);
830     result = BIT_CAST(res, Local<JSValueRef>);
831     return result;
832 }
833 
CycleFreeFuncReleaser(void *,void *,void * hint)834 static void CycleFreeFuncReleaser(void* /*env*/, void* /*data*/, void* hint)
835 {
836     auto data = reinterpret_cast<LambdaData*>(hint);
837     if (!data) {
838         return;
839     }
840     if (!g_cycleFreeCallback) {
841         delete data;
842         return;
843     }
844     g_cycleFreeCallback->refRelease(data->lambdaId);
845     delete data;
846 }
847 
ARKTS_CreateCycleFreeFunc(ARKTS_Env env,int64_t id)848 ARKTS_Value ARKTS_CreateCycleFreeFunc(ARKTS_Env env, int64_t id)
849 {
850     ARKTS_ASSERT_P(env, "env is null");
851     auto vm = P_CAST(env, EcmaVM*);
852     auto data = new (std::nothrow) LambdaData {env, id};
853     if (!data) {
854         return ARKTS_CreateUndefined();
855     }
856     auto result = FunctionRef::New(vm, CycleFreeFuncInvoker, CycleFreeFuncReleaser, data);
857     return ARKTS_FromHandle(result);
858 }
859 
CycleFreeObjectReleaser(void *,void * nativePointer,void *)860 static void CycleFreeObjectReleaser(void* /*env*/, void* nativePointer, void* /*hint*/)
861 {
862     if (!g_cycleFreeCallback) {
863         return;
864     }
865     auto id = static_cast<int64_t>(reinterpret_cast<uintptr_t>(nativePointer));
866     g_cycleFreeCallback->refRelease(id);
867 }
868 
ARKTS_CreateCycleFreeExtern(ARKTS_Env env,int64_t id)869 ARKTS_Value ARKTS_CreateCycleFreeExtern(ARKTS_Env env, int64_t id)
870 {
871     ARKTS_ASSERT_P(env, "env is null");
872     auto vm = P_CAST(env, EcmaVM*);
873     auto data = reinterpret_cast<void*>(static_cast<uintptr_t>(id));
874     auto result = NativePointerRef::New(vm, data, CycleFreeObjectReleaser, nullptr);
875     return ARKTS_FromHandle(result);
876 }
877 
ARKTS_GetExceptionAndClear(ARKTS_Env env)878 ARKTS_Value ARKTS_GetExceptionAndClear(ARKTS_Env env)
879 {
880     ARKTS_ASSERT_P(env, "env is null");
881     auto vm = P_CAST(env, EcmaVM*);
882     auto exception = JSNApi::GetAndClearUncaughtException(vm);
883     return ARKTS_FromHandle(exception);
884 }