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_GetValueNumber(ARKTS_Value value)234 double ARKTS_GetValueNumber(ARKTS_Value value)
235 {
236     auto ref = BIT_CAST(value, JSValueRef);
237     ARKTS_ASSERT_I(ref.IsNumber(), "not a number");
238     if (ref.IsInt()) {
239         return BIT_CAST(value, IntegerRef).Value();
240     } else {
241         return BIT_CAST(value, NumberRef).Value();
242     }
243 }
244 
ARKTS_IsNumber(ARKTS_Value value)245 bool ARKTS_IsNumber(ARKTS_Value value)
246 {
247     auto jValue = BIT_CAST(value, JSValueRef);
248     return jValue.IsNumber();
249 }
250 
251 struct LambdaData {
252     ARKTS_Env env;
253     int64_t lambdaId;
254 };
255 
CJLambdaInvoker(JsiRuntimeCallInfo* callInfo)256 static Local<JSValueRef> CJLambdaInvoker(JsiRuntimeCallInfo* callInfo)
257 {
258     auto data = reinterpret_cast<LambdaData*>(callInfo->GetData());
259     if (!data) {
260         return JSValueRef::Undefined(callInfo->GetVM());
261     }
262     auto result = ARKTSInner_CJLambdaInvoker(P_CAST(callInfo, ARKTS_CallInfo), data->lambdaId);
263     return BIT_CAST(result, Local<JSValueRef>);
264 }
265 
CJLambdaDeleter(void* , void* , void* raw)266 static void CJLambdaDeleter(void* /* env: napi_env */, void* /*invoker*/, void* raw)
267 {
268     auto data = reinterpret_cast<LambdaData*>(raw);
269     if (!data) {
270         return;
271     }
272     ARKTSInner_CJLambdaDeleter(data->env, data->lambdaId);
273     delete data;
274 }
275 
ARKTS_CreateFunc(ARKTS_Env env, int64_t lambdaId)276 ARKTS_Value ARKTS_CreateFunc(ARKTS_Env env, int64_t lambdaId)
277 {
278     ARKTS_ASSERT_P(env, "env is null");
279 
280     auto vm = P_CAST(env, EcmaVM*);
281     auto result = FunctionRef::New(vm, CJLambdaInvoker, CJLambdaDeleter, new LambdaData {env, lambdaId}, true);
282 
283     return ARKTS_FromHandle(result);
284 }
285 
ARKTS_IsClass(ARKTS_Env env, ARKTS_Value value)286 bool ARKTS_IsClass(ARKTS_Env env, ARKTS_Value value)
287 {
288     auto tag = BIT_CAST(value, JSValueRef);
289     if (!tag.IsHeapObject()) {
290         return false;
291     }
292     auto vm = P_CAST(env, EcmaVM*);
293     tag = *P_CAST(value, JSValueRef*);
294     return tag.IsConstructor(vm);
295 }
296 
ARKTS_CreateClass(ARKTS_Env env, int64_t lambdaId, ARKTS_Value base)297 ARKTS_Value ARKTS_CreateClass(ARKTS_Env env, int64_t lambdaId, ARKTS_Value base)
298 {
299     ARKTS_ASSERT_P(env, "env is null");
300 
301     auto vm = P_CAST(env, EcmaVM*);
302 
303     auto result = FunctionRef::NewClassFunction(vm, CJLambdaInvoker, CJLambdaDeleter,
304                                                 new LambdaData {env, lambdaId}, true);
305 
306     if (ARKTS_IsClass(env, base)) {
307         auto baseClass = BIT_CAST(base, Local<FunctionRef>);
308         result->Inherit(vm, baseClass);
309     }
310 
311     return ARKTS_FromHandle(result);
312 }
313 
ARKTS_GetPrototype(ARKTS_Env env, ARKTS_Value value)314 ARKTS_Value ARKTS_GetPrototype(ARKTS_Env env, ARKTS_Value value)
315 {
316     ARKTS_ASSERT_P(env, "env is null");
317     ARKTS_ASSERT_P(ARKTS_IsClass(env, value), "value is not constructor");
318     auto vm = P_CAST(env, EcmaVM*);
319     auto clazz = BIT_CAST(value, Local<FunctionRef>);
320     auto result = clazz->GetFunctionPrototype(vm);
321     return ARKTS_FromHandle(result);
322 }
323 
ARKTS_InstanceOf(ARKTS_Env env, ARKTS_Value object, ARKTS_Value clazz)324 bool ARKTS_InstanceOf(ARKTS_Env env, ARKTS_Value object, ARKTS_Value clazz)
325 {
326     ARKTS_ASSERT_F(env, "env is null");
327     ARKTS_ASSERT_F(ARKTS_IsHeapObject(object), "object is not heap object");
328     ARKTS_ASSERT_F(ARKTS_IsClass(env, clazz), "clazz is not a class");
329 
330     auto vm = P_CAST(env, EcmaVM*);
331     auto targetObject = BIT_CAST(object, Local<JSValueRef>);
332     auto targetClass = BIT_CAST(clazz, Local<FunctionRef>);
333 
334     return targetObject->InstanceOf(vm, targetClass);
335 }
336 
ARKTS_IsCallable(ARKTS_Env env, ARKTS_Value value)337 bool ARKTS_IsCallable(ARKTS_Env env, ARKTS_Value value)
338 {
339     return ARKTS_GetValueType(env, value) == N_FUNCTION;
340 }
341 
342 static constexpr auto MAX_CALL_ARGS = 255;
343 
FormatArguments(int32_t numArgs, ARKTS_Value args[], Local<JSValueRef>* result)344 ARKTS_INLINE void FormatArguments(int32_t numArgs, ARKTS_Value args[], Local<JSValueRef>* result)
345 {
346     for (int32_t i = 0;i < numArgs; ++i) {
347         result[i] = ARKTS_ToHandle<JSValueRef>(args[i]);
348     }
349 }
350 
ARKTS_Call(ARKTS_Env env, ARKTS_Value func, ARKTS_Value thisArg, int32_t numArgs, ARKTS_Value args[])351 ARKTS_Value ARKTS_Call(ARKTS_Env env, ARKTS_Value func, ARKTS_Value thisArg, int32_t numArgs, ARKTS_Value args[])
352 {
353     ARKTS_ASSERT_P(env, "env is null");
354     ARKTS_ASSERT_P(ARKTS_IsCallable(env, func), "func is not callable");
355     ARKTS_ASSERT_P(numArgs <= MAX_CALL_ARGS, "too many arguments, 255 most");
356 
357     auto vm = P_CAST(env, EcmaVM*);
358 
359     auto funcHandle = *P_CAST(func, FunctionRef*);
360     auto thisHandle = ARKTS_ToHandle<JSValueRef>(thisArg);
361 
362     Local<JSValueRef> formattedArgs[MAX_CALL_ARGS];
363     FormatArguments(numArgs, args, formattedArgs);
364 
365     auto result = funcHandle.Call(vm, thisHandle, formattedArgs, numArgs);
366 
367     ARKTSInner_ReportJSErrors(env, true);
368 
369     return ARKTS_FromHandle(result);
370 }
371 
ARKTS_New(ARKTS_Env env, ARKTS_Value clazz, int32_t numArgs, ARKTS_Value args[])372 ARKTS_Value ARKTS_New(ARKTS_Env env, ARKTS_Value clazz, int32_t numArgs, ARKTS_Value args[])
373 {
374     ARKTS_ASSERT_P(env, "env is null");
375     ARKTS_ASSERT_P(ARKTS_IsClass(env, clazz), "clazz is not class");
376     ARKTS_ASSERT_P(numArgs <= MAX_CALL_ARGS, "too many arguments, 255 most");
377 
378     auto vm = P_CAST(env, EcmaVM*);
379     auto funcHandle = *P_CAST(clazz, FunctionRef*);
380 
381     Local<JSValueRef> formattedArgs[MAX_CALL_ARGS];
382     FormatArguments(numArgs, args, formattedArgs);
383 
384     auto result = funcHandle.Constructor(vm, formattedArgs, numArgs);
385 
386     ARKTSInner_ReportJSErrors(env, true);
387 
388     return ARKTS_FromHandle(result);
389 }
390 
391 // JSArray elements stored in vector mode and dict mode.
392 // default in vector mode,
393 // if capacity grows gap bigger than 1024, will transform to dict mode.
ARKTS_CreateArray(ARKTS_Env env, uint32_t size)394 ARKTS_Value ARKTS_CreateArray(ARKTS_Env env, uint32_t size)
395 {
396     ARKTS_ASSERT_P(env, "env is null");
397 
398     auto vm = P_CAST(env, EcmaVM*);
399     auto result = ArrayRef::New(vm, size);
400     return BIT_CAST(result, ARKTS_Value);
401 }
402 
ARKTS_CreateArrayWithInit(ARKTS_Env env, uint32_t size, ARKTS_Value* data)403 ARKTS_Value ARKTS_CreateArrayWithInit(ARKTS_Env env, uint32_t size, ARKTS_Value* data)
404 {
405     ARKTS_ASSERT_P(env, "env is null");
406     auto vm = P_CAST(env, EcmaVM*);
407 
408     auto result = ArrayRef::New(vm, size);
409     for (uint32_t i = 0;i < size; ++i) {
410         ArrayRef::SetValueAt(vm, result, i, ARKTS_ToHandle<JSValueRef>(data[i]));
411     }
412 
413     return BIT_CAST(result, ARKTS_Value);
414 }
415 
ARKTS_GetArrayLength(ARKTS_Env env, ARKTS_Value array)416 uint32_t ARKTS_GetArrayLength(ARKTS_Env env, ARKTS_Value array)
417 {
418     ARKTS_ASSERT_I(env, "env is null");
419     ARKTS_ASSERT_I(ARKTS_IsArray(env, array), "array is not array");
420 
421     auto vm = P_CAST(env, EcmaVM*);
422     auto jArr = *P_CAST(array, ArrayRef*);
423 
424     return jArr.Length(vm);
425 }
426 
ARKTS_SetElement(ARKTS_Env env, ARKTS_Value array, uint32_t index, ARKTS_Value value)427 void ARKTS_SetElement(ARKTS_Env env, ARKTS_Value array, uint32_t index, ARKTS_Value value)
428 {
429     ARKTS_ASSERT_V(env, "env is null");
430     ARKTS_ASSERT_V(ARKTS_IsArray(env, array), "array is not array");
431 
432     auto vm = P_CAST(env, EcmaVM*);
433     auto jArr = BIT_CAST(array, Local<ArrayRef>);
434 
435     ArrayRef::SetValueAt(vm, jArr, index, ARKTS_ToHandle<JSValueRef>(value));
436 }
437 
ARKTS_GetElement(ARKTS_Env env, ARKTS_Value array, uint32_t index)438 ARKTS_Value ARKTS_GetElement(ARKTS_Env env, ARKTS_Value array, uint32_t index)
439 {
440     ARKTS_ASSERT_P(env, "env is null");
441     ARKTS_ASSERT_P(ARKTS_IsArray(env, array), "array is not array");
442     auto vm = P_CAST(env, EcmaVM*);
443     auto arr = BIT_CAST(array, Local<ArrayRef>);
444     ARKTS_ASSERT_P(arr->Length(vm) > index, "out of index");
445 
446     auto result = ArrayRef::GetValueAt(vm, arr, index);
447 
448     return ARKTS_FromHandle(result);
449 }
450 
ARKTS_IsArray(ARKTS_Env env, ARKTS_Value value)451 bool ARKTS_IsArray(ARKTS_Env env, ARKTS_Value value)
452 {
453     ARKTS_ASSERT_F(env, "env is NULL");
454     auto v = BIT_CAST(value, JSValueRef);
455     if (!v.IsHeapObject()) {
456         return false;
457     }
458     v = *P_CAST(value, JSValueRef*);
459     auto vm = P_CAST(env, EcmaVM*);
460     return v.IsArray(vm);
461 }
462 
ARKTS_CreateArrayBuffer(ARKTS_Env env, int32_t length)463 ARKTS_Value ARKTS_CreateArrayBuffer(ARKTS_Env env, int32_t length)
464 {
465     ARKTS_ASSERT_P(env, "env is null");
466     auto vm = P_CAST(env, EcmaVM*);
467     auto result = ArrayBufferRef::New(vm, length);
468     return ARKTS_FromHandle(result);
469 }
470 
ARKTS_CreateArrayBufferWithData(ARKTS_Env env, void* buffer, int32_t length, int64_t finalizerHint)471 ARKTS_Value ARKTS_CreateArrayBufferWithData(ARKTS_Env env, void* buffer, int32_t length,
472     int64_t finalizerHint)
473 {
474     ARKTS_ASSERT_P(env, "env is null");
475 
476     auto vm = P_CAST(env, EcmaVM*);
477     auto result = ArrayBufferRef::New(vm, buffer, length, ARKTSInner_CJArrayBufferDeleter,
478                                       reinterpret_cast<void*>(finalizerHint));
479 
480     return ARKTS_FromHandle(result);
481 }
482 
ARKTS_IsArrayBuffer(ARKTS_Env env, ARKTS_Value value)483 bool ARKTS_IsArrayBuffer(ARKTS_Env env, ARKTS_Value value)
484 {
485     auto tag = BIT_CAST(value, JSValueRef);
486     if (!tag.IsHeapObject()) {
487         return false;
488     }
489     auto vm = P_CAST(env, EcmaVM*);
490     tag = *P_CAST(value, JSValueRef*);
491     return tag.IsArrayBuffer(vm) || tag.IsTypedArray(vm) || tag.IsDataView(vm);
492 }
493 
ARKTS_GetArrayBufferLength(ARKTS_Env env, ARKTS_Value value)494 int32_t ARKTS_GetArrayBufferLength(ARKTS_Env env, ARKTS_Value value)
495 {
496     ARKTS_ASSERT_I(env, "env is null");
497     ARKTS_ASSERT_I(ARKTS_IsArrayBuffer(env, value), "value is not arrayBuffer");
498 
499     auto vm = P_CAST(env, EcmaVM*);
500     auto tag = *P_CAST(value, JSValueRef*);
501     if (tag.IsArrayBuffer(vm)) {
502         return P_CAST(value, ArrayBufferRef*)->ByteLength(vm);
503     } else if (tag.IsTypedArray(vm)) {
504         auto arr = P_CAST(value, TypedArrayRef*);
505         return arr->ByteLength(vm) - arr->ByteOffset(vm);
506     } else {
507         auto arr = P_CAST(value, DataViewRef*);
508         return arr->ByteLength() - arr->ByteOffset();
509     }
510 }
511 
ARKTS_GetArrayBufferRawPtr(ARKTS_Env env, ARKTS_Value value)512 void* ARKTS_GetArrayBufferRawPtr(ARKTS_Env env, ARKTS_Value value)
513 {
514     ARKTS_ASSERT_P(env, "env is null");
515     ARKTS_ASSERT_P(ARKTS_IsArrayBuffer(env, value), "value is not arrayBuffer");
516 
517     auto vm = P_CAST(env, EcmaVM*);
518     auto tag = *BIT_CAST(value, JSValueRef*);
519     if (tag.IsArrayBuffer(vm)) {
520         return P_CAST(value, ArrayBufferRef*)->GetBuffer(vm);
521     } else if (tag.IsTypedArray(vm)) {
522         auto arr = P_CAST(value, TypedArrayRef*);
523         auto rawStart = arr->GetArrayBuffer(vm)->GetBuffer(vm);
524         auto rawOffset = arr->ByteOffset(vm);
525         return P_CAST(rawStart, uint8_t*) + rawOffset;
526     } else {
527         auto arr = P_CAST(value, DataViewRef*);
528         auto rawStart = arr->GetArrayBuffer(vm)->GetBuffer(vm);
529         auto rawOffset = arr->ByteOffset();
530         return P_CAST(rawStart, uint8_t*) + rawOffset;
531     }
532 }
533 
ARKTS_ArrayBufferReadBytes(ARKTS_Env env, ARKTS_Value buffer, void* dest, int32_t count)534 int32_t ARKTS_ArrayBufferReadBytes(ARKTS_Env env, ARKTS_Value buffer, void* dest, int32_t count)
535 {
536     auto src = ARKTS_GetArrayBufferRawPtr(env, buffer);
537     auto srcSize = ARKTS_GetArrayBufferLength(env, buffer);
538     auto targetSize = std::min(srcSize, count);
539     if (memcpy_s(dest, count, src, targetSize) != targetSize) {
540         LOGE("ARKTS_ArrayBufferReadBytes error, memcpy_s ret size incorrect");
541     }
542     return targetSize;
543 }
544 
ARKTS_CreateExternal(ARKTS_Env env, void* data)545 ARKTS_Value ARKTS_CreateExternal(ARKTS_Env env, void* data)
546 {
547     ARKTS_ASSERT_P(env, "env is null");
548 
549     auto vm = P_CAST(env, EcmaVM*);
550     auto result = NativePointerRef::New(vm, data, ARKTSInner_CJExternalDeleter, env);
551     return BIT_CAST(result, ARKTS_Value);
552 }
553 
ARKTS_IsExternal(ARKTS_Env env, ARKTS_Value value)554 bool ARKTS_IsExternal(ARKTS_Env env, ARKTS_Value value)
555 {
556     auto prime = BIT_CAST(value, JSValueRef);
557     if (!prime.IsHeapObject()) {
558         return false;
559     }
560     auto handle = BIT_CAST(value, JSValueRef*);
561     auto vm = P_CAST(env, EcmaVM*);
562     return handle->IsNativePointer(vm);
563 }
564 
ARKTS_GetExternalData(ARKTS_Env env, ARKTS_Value value)565 void* ARKTS_GetExternalData(ARKTS_Env env, ARKTS_Value value)
566 {
567     ARKTS_ASSERT_P(ARKTS_IsExternal(env, value), "value is not external data");
568     auto external = *P_CAST(value, NativePointerRef*);
569     return external.Value();
570 }
571 
ARKTS_CreatePromiseCapability(ARKTS_Env env)572 ARKTS_Promise ARKTS_CreatePromiseCapability(ARKTS_Env env)
573 {
574     ARKTS_ASSERT_P(env, "env is null");
575 
576     auto vm = P_CAST(env, EcmaVM*);
577 
578     auto promise = PromiseCapabilityRef::New(vm);
579     auto result = new Global<PromiseCapabilityRef>(vm, promise);
580 
581     return BIT_CAST(result, ARKTS_Promise);
582 }
583 
ARKTS_GetPromiseFromCapability(ARKTS_Env env, ARKTS_Promise prom)584 ARKTS_Value ARKTS_GetPromiseFromCapability(ARKTS_Env env, ARKTS_Promise prom)
585 {
586     ARKTS_ASSERT_P(env, "env is null");
587     ARKTS_ASSERT_P(prom, "prom is null");
588 
589     auto vm = P_CAST(env, EcmaVM*);
590     auto promise = *P_CAST(prom, Global<PromiseCapabilityRef>*);
591     auto result = (*promise)->GetPromise(vm);
592 
593     return BIT_CAST(result, ARKTS_Value);
594 }
595 
ARKTS_PromiseCapabilityResolve(ARKTS_Env env, ARKTS_Promise prom, ARKTS_Value result)596 void ARKTS_PromiseCapabilityResolve(ARKTS_Env env, ARKTS_Promise prom, ARKTS_Value result)
597 {
598     ARKTS_ASSERT_V(env, "env is null");
599     ARKTS_ASSERT_V(prom, "prom is null");
600 
601     auto vm = P_CAST(env, EcmaVM*);
602     auto promise = P_CAST(prom, Global<PromiseCapabilityRef>*);
603     (*promise)->Resolve(vm, ARKTS_ToHandle<JSValueRef>(result));
604     delete promise;
605 }
606 
ARKTS_PromiseCapabilityReject(ARKTS_Env env, ARKTS_Promise prom, ARKTS_Value result)607 void ARKTS_PromiseCapabilityReject(ARKTS_Env env, ARKTS_Promise prom, ARKTS_Value result)
608 {
609     ARKTS_ASSERT_V(env, "env is null");
610     ARKTS_ASSERT_V(prom, "prom is null");
611 
612     auto vm = P_CAST(env, EcmaVM*);
613     auto promise = P_CAST(prom, Global<PromiseCapabilityRef>*);
614     (*promise)->Reject(vm, ARKTS_ToHandle<JSValueRef>(result));
615     delete promise;
616 }
617 
ARKTS_IsPromise(ARKTS_Env env, ARKTS_Value value)618 bool ARKTS_IsPromise(ARKTS_Env env, ARKTS_Value value)
619 {
620     auto v = BIT_CAST(value, JSValueRef);
621     if (!v.IsHeapObject()) {
622         return false;
623     }
624     auto vm = P_CAST(env, EcmaVM*);
625     v= *P_CAST(value, JSValueRef*);
626     return v.IsPromise(vm);
627 }
628 
ARKTS_PromiseThen(ARKTS_Env env, ARKTS_Value prom, ARKTS_Value onFulfilled, ARKTS_Value onRejected)629 ARKTS_Value ARKTS_PromiseThen(ARKTS_Env env, ARKTS_Value prom, ARKTS_Value onFulfilled, ARKTS_Value onRejected)
630 {
631     ARKTS_ASSERT_P(env, "env is null");
632     ARKTS_ASSERT_P(ARKTS_IsPromise(env, prom), "arg is not a JSPromise");
633     ARKTS_ASSERT_P(ARKTS_IsCallable(env, onFulfilled), "onFulfilled is not callable");
634 
635     auto vm = P_CAST(env, EcmaVM*);
636     auto promise = *BIT_CAST(prom, PromiseRef*);
637     auto onFulfilledFunc = BIT_CAST(onFulfilled, Local<FunctionRef>);
638     auto onRejectTag = BIT_CAST(onRejected, Local<JSValueRef>);
639     Local<PromiseRef> result;
640     if (onRejectTag->IsFunction(vm)) {
641         auto onRejectedFunc = BIT_CAST(onRejected, Local<FunctionRef>);
642         result = promise.Then(vm, onFulfilledFunc, onRejectedFunc);
643     } else {
644         result = promise.Then(vm, onFulfilledFunc);
645     }
646     return ARKTS_FromHandle(result);
647 }
648 
ARKTS_PromiseCatch(ARKTS_Env env, ARKTS_Value prom, ARKTS_Value callback)649 void ARKTS_PromiseCatch(ARKTS_Env env, ARKTS_Value prom, ARKTS_Value callback)
650 {
651     ARKTS_ASSERT_V(env, "env is null");
652     ARKTS_ASSERT_V(ARKTS_IsPromise(env, prom), "arg is not a JSPromise");
653     ARKTS_ASSERT_V(ARKTS_IsCallable(env, callback), "callback is not callable");
654 
655     auto vm = P_CAST(env, EcmaVM*);
656     auto promise = BIT_CAST(prom, PromiseRef*);
657     auto callbackFunc = BIT_CAST(callback, Local<FunctionRef>);
658     promise->Catch(vm, callbackFunc);
659 }
660 
ARKTS_OpenScope(ARKTS_Env env)661 ARKTS_Scope ARKTS_OpenScope(ARKTS_Env env)
662 {
663     ARKTS_ASSERT_P(env, "env is null");
664     auto vm = P_CAST(env, EcmaVM*);
665     return CJ::ARKTS_ScopeManager::OpenScope(vm);
666 }
667 
ARKTS_Return(ARKTS_Env env, ARKTS_Scope scope, ARKTS_Value value)668 ARKTS_Result ARKTS_Return(ARKTS_Env env, ARKTS_Scope scope, ARKTS_Value value)
669 {
670     ARKTS_ASSERT_P(env, "env is null");
671     ARKTS_ASSERT_P(value, "value is invalid");
672 
673     auto vm = P_CAST(env, EcmaVM*);
674     if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
675         ARKTSInner_ReportNativeError("exit scope of unknown");
676     }
677 
678     return ARKTS_ToResult(vm, value);
679 }
680 
ARKTS_CloseScope(ARKTS_Env env, ARKTS_Scope scope)681 void ARKTS_CloseScope(ARKTS_Env env, ARKTS_Scope scope)
682 {
683     ARKTS_ASSERT_V(env, "env is null");
684     ARKTS_ASSERT_V(scope, "scope is invalid");
685 
686     if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
687         ARKTSInner_ReportNativeError("exit scope of unknown");
688     }
689 }
690 
ARKTSInner_Escape(ARKTS_Env env, ARKTS_Scope scope, ARKTS_Value ret)691 panda::JSValueRef* ARKTSInner_Escape(ARKTS_Env env, ARKTS_Scope scope, ARKTS_Value ret)
692 {
693     if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
694         ARKTSInner_ReportNativeError("exit scope of unknown");
695     }
696 
697     auto vm = P_CAST(env, EcmaVM*);
698     auto value = ARKTS_ToValue(ret);
699 
700     auto result = JSNApi::CreateLocal(vm, value);
701 
702     return BIT_CAST(result, JSValueRef*);
703 }
704 
ARKTS_Throw(ARKTS_Env env, ARKTS_Value error)705 void ARKTS_Throw(ARKTS_Env env, ARKTS_Value error)
706 {
707     ARKTS_ASSERT_V(env, "env is null");
708     auto vm = P_CAST(env, EcmaVM*);
709 
710     if (JSNApi::HasPendingException(vm)) {
711         LOGE("ARKTS_Throw failed, vm has uncaught exception");
712         return;
713     }
714 
715     auto exception = ARKTS_ToHandle<JSValueRef>(error);
716     if (exception->IsString(vm)) {
717         JSNApi::ThrowException(vm, Exception::Error(vm, BIT_CAST(exception, Local<StringRef>)));
718     } else {
719         JSNApi::ThrowException(vm, exception);
720     }
721 }
722 
ARKTS_GetCallEnv(ARKTS_CallInfo info)723 ARKTS_Env ARKTS_GetCallEnv(ARKTS_CallInfo info)
724 {
725     ARKTS_ASSERT_I(info, "info is null");
726     auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
727     auto vm = runInfo->GetVM();
728     return P_CAST(vm, ARKTS_Env);
729 }
730 
ARKTS_GetArgCount(ARKTS_CallInfo info)731 uint32_t ARKTS_GetArgCount(ARKTS_CallInfo info)
732 {
733     ARKTS_ASSERT_I(info, "info is null");
734     auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
735     return runInfo->GetArgsNumber();
736 }
737 
ARKTS_GetArg(ARKTS_CallInfo info, uint32_t index)738 ARKTS_Value ARKTS_GetArg(ARKTS_CallInfo info, uint32_t index)
739 {
740     ARKTS_ASSERT_P(info, "info is null");
741     auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
742     ARKTS_ASSERT_P(runInfo->GetArgsNumber() > index, "out of index");
743     auto result = runInfo->GetCallArgRef(index);
744     return ARKTS_FromHandle(result);
745 }
746 
ARKTS_GetThisArg(ARKTS_CallInfo info)747 ARKTS_Value ARKTS_GetThisArg(ARKTS_CallInfo info)
748 {
749     ARKTS_ASSERT_P(info, "info is null");
750     auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
751     auto result = runInfo->GetThisRef();
752     return ARKTS_FromHandle(result);
753 }
754 
ARKTS_GetGlobalNapiEnv(ARKTS_Env env)755 void* ARKTS_GetGlobalNapiEnv(ARKTS_Env env)
756 {
757     ARKTS_ASSERT_P(env, "env is null");
758     auto vm = P_CAST(env, EcmaVM*);
759     return JSNApi::GetEnv(vm);
760 }
761