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