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 BIT_CAST(result, ARKTS_Value);
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 BIT_CAST(result, ARKTS_Value);
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 jArr = *P_CAST(array, ArrayRef*);
431
432 return jArr.Length(vm);
433 }
434
ARKTS_SetElement(ARKTS_Env env,ARKTS_Value array,uint32_t index,ARKTS_Value value)435 void ARKTS_SetElement(ARKTS_Env env, ARKTS_Value array, uint32_t index, ARKTS_Value value)
436 {
437 ARKTS_ASSERT_V(env, "env is null");
438 ARKTS_ASSERT_V(ARKTS_IsArray(env, array), "array is not array");
439
440 auto vm = P_CAST(env, EcmaVM*);
441 auto jArr = BIT_CAST(array, Local<ArrayRef>);
442
443 ArrayRef::SetValueAt(vm, jArr, index, ARKTS_ToHandle<JSValueRef>(value));
444 ARKTSInner_ReportJSErrors(env, false);
445 }
446
ARKTS_GetElement(ARKTS_Env env,ARKTS_Value array,uint32_t index)447 ARKTS_Value ARKTS_GetElement(ARKTS_Env env, ARKTS_Value array, uint32_t index)
448 {
449 ARKTS_ASSERT_P(env, "env is null");
450 ARKTS_ASSERT_P(ARKTS_IsArray(env, array), "array is not array");
451 auto vm = P_CAST(env, EcmaVM*);
452 auto arr = BIT_CAST(array, Local<ArrayRef>);
453 ARKTS_ASSERT_P(arr->Length(vm) > index, "out of index");
454
455 auto result = ArrayRef::GetValueAt(vm, arr, index);
456 ARKTSInner_ReportJSErrors(env, false);
457 return ARKTS_FromHandle(result);
458 }
459
ARKTS_IsArray(ARKTS_Env env,ARKTS_Value value)460 bool ARKTS_IsArray(ARKTS_Env env, ARKTS_Value value)
461 {
462 ARKTS_ASSERT_F(env, "env is NULL");
463 auto v = BIT_CAST(value, JSValueRef);
464 if (!v.IsHeapObject()) {
465 return false;
466 }
467 v = *P_CAST(value, JSValueRef*);
468 auto vm = P_CAST(env, EcmaVM*);
469 return v.IsArray(vm);
470 }
471
ARKTS_CreateArrayBuffer(ARKTS_Env env,int32_t length)472 ARKTS_Value ARKTS_CreateArrayBuffer(ARKTS_Env env, int32_t length)
473 {
474 ARKTS_ASSERT_P(env, "env is null");
475 ARKTS_ASSERT_P(length >= 0, "length must be non-negative");
476 auto vm = P_CAST(env, EcmaVM*);
477 auto result = ArrayBufferRef::New(vm, length);
478 return ARKTS_FromHandle(result);
479 }
480
ARKTS_CreateArrayBufferWithData(ARKTS_Env env,void * buffer,int32_t length,int64_t finalizerHint)481 ARKTS_Value ARKTS_CreateArrayBufferWithData(ARKTS_Env env, void* buffer, int32_t length,
482 int64_t finalizerHint)
483 {
484 ARKTS_ASSERT_P(env, "env is null");
485 ARKTS_ASSERT_P(length >= 0, "length must be non-negative");
486
487 auto vm = P_CAST(env, EcmaVM*);
488 auto result = ArrayBufferRef::New(vm, buffer, length, ARKTSInner_CJArrayBufferDeleter,
489 reinterpret_cast<void*>(finalizerHint));
490
491 return ARKTS_FromHandle(result);
492 }
493
ARKTS_IsArrayBuffer(ARKTS_Env env,ARKTS_Value value)494 bool ARKTS_IsArrayBuffer(ARKTS_Env env, ARKTS_Value value)
495 {
496 ARKTS_ASSERT_F(env, "env is null");
497 auto tag = BIT_CAST(value, JSValueRef);
498 if (!tag.IsHeapObject()) {
499 return false;
500 }
501 auto vm = P_CAST(env, EcmaVM*);
502 auto handle = BIT_CAST(value, Local<JSValueRef>);
503 return handle->IsArrayBuffer(vm) || handle->IsTypedArray(vm) || handle->IsDataView(vm);
504 }
505
ARKTS_GetArrayBufferLength(ARKTS_Env env,ARKTS_Value value)506 int32_t ARKTS_GetArrayBufferLength(ARKTS_Env env, ARKTS_Value value)
507 {
508 ARKTS_ASSERT_I(env, "env is null");
509 ARKTS_ASSERT_I(ARKTS_IsArrayBuffer(env, value), "value is not arrayBuffer");
510
511 auto vm = P_CAST(env, EcmaVM*);
512 auto handle = BIT_CAST(value, Local<JSValueRef>);
513 if (handle->IsArrayBuffer(vm)) {
514 return BIT_CAST(value, Local<ArrayBufferRef>)->ByteLength(vm);
515 } else if (handle->IsTypedArray(vm)) {
516 auto arr = BIT_CAST(value, Local<TypedArrayRef>);
517 return arr->ByteLength(vm) - arr->ByteOffset(vm);
518 } else {
519 auto arr = BIT_CAST(value, Local<DataViewRef>);
520 return arr->ByteLength() - arr->ByteOffset();
521 }
522 }
523
ARKTS_GetArrayBufferRawPtr(ARKTS_Env env,ARKTS_Value value)524 void* ARKTS_GetArrayBufferRawPtr(ARKTS_Env env, ARKTS_Value value)
525 {
526 ARKTS_ASSERT_P(env, "env is null");
527 ARKTS_ASSERT_P(ARKTS_IsArrayBuffer(env, value), "value is not arrayBuffer");
528
529 auto vm = P_CAST(env, EcmaVM*);
530 auto handle = BIT_CAST(value, Local<JSValueRef>);
531 if (handle->IsArrayBuffer(vm)) {
532 return BIT_CAST(value, Local<ArrayBufferRef>)->GetBuffer(vm);
533 } else if (handle->IsTypedArray(vm)) {
534 auto arr = BIT_CAST(value, Local<TypedArrayRef>);
535 auto rawStart = arr->GetArrayBuffer(vm)->GetBuffer(vm);
536 auto rawOffset = arr->ByteOffset(vm);
537 return P_CAST(rawStart, uint8_t*) + rawOffset;
538 } else {
539 auto arr = BIT_CAST(value, Local<DataViewRef>);
540 auto rawStart = arr->GetArrayBuffer(vm)->GetBuffer(vm);
541 auto rawOffset = arr->ByteOffset();
542 return P_CAST(rawStart, uint8_t*) + rawOffset;
543 }
544 }
545
ARKTS_ArrayBufferReadBytes(ARKTS_Env env,ARKTS_Value buffer,void * dest,int32_t count)546 int32_t ARKTS_ArrayBufferReadBytes(ARKTS_Env env, ARKTS_Value buffer, void* dest, int32_t count)
547 {
548 auto src = ARKTS_GetArrayBufferRawPtr(env, buffer);
549 auto srcSize = ARKTS_GetArrayBufferLength(env, buffer);
550 auto targetSize = std::min(srcSize, count);
551 auto status = memcpy_s(dest, count, src, targetSize);
552 if (status != 0) {
553 LOGE("ARKTS_ArrayBufferReadBytes error, memcpy_s ret %{public}d", status);
554 return 0;
555 }
556 return targetSize;
557 }
558
ARKTS_CreateExternal(ARKTS_Env env,void * data)559 ARKTS_Value ARKTS_CreateExternal(ARKTS_Env env, void* data)
560 {
561 ARKTS_ASSERT_P(env, "env is null");
562 ARKTS_ASSERT_P(data, "data is null");
563
564 auto vm = P_CAST(env, EcmaVM*);
565 auto result = NativePointerRef::New(vm, data, ARKTSInner_CJExternalDeleter, env);
566 return BIT_CAST(result, ARKTS_Value);
567 }
568
ARKTS_IsExternal(ARKTS_Env env,ARKTS_Value value)569 bool ARKTS_IsExternal(ARKTS_Env env, ARKTS_Value value)
570 {
571 ARKTS_ASSERT_F(env, "env is null");
572 auto prime = BIT_CAST(value, JSValueRef);
573 if (!prime.IsHeapObject()) {
574 return false;
575 }
576 auto handle = BIT_CAST(value, JSValueRef*);
577 auto vm = P_CAST(env, EcmaVM*);
578 return handle->IsNativePointer(vm);
579 }
580
ARKTS_GetExternalData(ARKTS_Env env,ARKTS_Value value)581 void* ARKTS_GetExternalData(ARKTS_Env env, ARKTS_Value value)
582 {
583 ARKTS_ASSERT_P(ARKTS_IsExternal(env, value), "value is not external data");
584 auto external = *P_CAST(value, NativePointerRef*);
585 return external.Value();
586 }
587
ARKTS_CreatePromiseCapability(ARKTS_Env env)588 ARKTS_Promise ARKTS_CreatePromiseCapability(ARKTS_Env env)
589 {
590 ARKTS_ASSERT_P(env, "env is null");
591
592 auto vm = P_CAST(env, EcmaVM*);
593
594 auto promise = PromiseCapabilityRef::New(vm);
595 auto result = new Global<PromiseCapabilityRef>(vm, promise);
596
597 return BIT_CAST(result, ARKTS_Promise);
598 }
599
ARKTS_GetPromiseFromCapability(ARKTS_Env env,ARKTS_Promise prom)600 ARKTS_Value ARKTS_GetPromiseFromCapability(ARKTS_Env env, ARKTS_Promise prom)
601 {
602 ARKTS_ASSERT_P(env, "env is null");
603 ARKTS_ASSERT_P(prom, "prom is null");
604
605 auto vm = P_CAST(env, EcmaVM*);
606 auto promise = *P_CAST(prom, Global<PromiseCapabilityRef>*);
607 auto result = (*promise)->GetPromise(vm);
608
609 return BIT_CAST(result, ARKTS_Value);
610 }
611
ARKTS_PromiseCapabilityResolve(ARKTS_Env env,ARKTS_Promise prom,ARKTS_Value result)612 void ARKTS_PromiseCapabilityResolve(ARKTS_Env env, ARKTS_Promise prom, ARKTS_Value result)
613 {
614 ARKTS_ASSERT_V(env, "env is null");
615 ARKTS_ASSERT_V(prom, "prom is null");
616
617 auto vm = P_CAST(env, EcmaVM*);
618 auto promise = P_CAST(prom, Global<PromiseCapabilityRef>*);
619 (*promise)->Resolve(vm, ARKTS_ToHandle<JSValueRef>(result));
620 delete promise;
621 }
622
ARKTS_PromiseCapabilityReject(ARKTS_Env env,ARKTS_Promise prom,ARKTS_Value result)623 void ARKTS_PromiseCapabilityReject(ARKTS_Env env, ARKTS_Promise prom, ARKTS_Value result)
624 {
625 ARKTS_ASSERT_V(env, "env is null");
626 ARKTS_ASSERT_V(prom, "prom is null");
627
628 auto vm = P_CAST(env, EcmaVM*);
629 auto promise = P_CAST(prom, Global<PromiseCapabilityRef>*);
630 (*promise)->Reject(vm, ARKTS_ToHandle<JSValueRef>(result));
631 delete promise;
632 }
633
ARKTS_IsPromise(ARKTS_Env env,ARKTS_Value value)634 bool ARKTS_IsPromise(ARKTS_Env env, ARKTS_Value value)
635 {
636 ARKTS_ASSERT_F(env, "env is null");
637 auto v = BIT_CAST(value, JSValueRef);
638 if (!v.IsHeapObject()) {
639 return false;
640 }
641 auto vm = P_CAST(env, EcmaVM*);
642 v= *P_CAST(value, JSValueRef*);
643 return v.IsPromise(vm);
644 }
645
ARKTS_PromiseThen(ARKTS_Env env,ARKTS_Value prom,ARKTS_Value onFulfilled,ARKTS_Value onRejected)646 ARKTS_Value ARKTS_PromiseThen(ARKTS_Env env, ARKTS_Value prom, ARKTS_Value onFulfilled, ARKTS_Value onRejected)
647 {
648 ARKTS_ASSERT_P(env, "env is null");
649 ARKTS_ASSERT_P(ARKTS_IsPromise(env, prom), "arg is not a JSPromise");
650 ARKTS_ASSERT_P(ARKTS_IsCallable(env, onFulfilled), "onFulfilled is not callable");
651
652 auto vm = P_CAST(env, EcmaVM*);
653 auto promise = *BIT_CAST(prom, PromiseRef*);
654 auto onFulfilledFunc = BIT_CAST(onFulfilled, Local<FunctionRef>);
655 Local<PromiseRef> result;
656 if (!ARKTS_IsUndefined(onRejected)) {
657 ARKTS_ASSERT_P(ARKTS_IsCallable(env, onRejected), "optional arg 'onRejected' is set but not callable");
658 auto onRejectedFunc = BIT_CAST(onRejected, Local<FunctionRef>);
659 result = promise.Then(vm, onFulfilledFunc, onRejectedFunc);
660 } else {
661 result = promise.Then(vm, onFulfilledFunc);
662 }
663 return ARKTS_FromHandle(result);
664 }
665
ARKTS_PromiseCatch(ARKTS_Env env,ARKTS_Value prom,ARKTS_Value callback)666 ARKTS_Value ARKTS_PromiseCatch(ARKTS_Env env, ARKTS_Value prom, ARKTS_Value callback)
667 {
668 ARKTS_ASSERT_P(env, "env is null");
669 ARKTS_ASSERT_P(ARKTS_IsPromise(env, prom), "arg is not a JSPromise");
670 ARKTS_ASSERT_P(ARKTS_IsCallable(env, callback), "callback is not callable");
671
672 auto vm = P_CAST(env, EcmaVM*);
673 auto promise = BIT_CAST(prom, PromiseRef*);
674 auto callbackFunc = BIT_CAST(callback, Local<FunctionRef>);
675 auto result = promise->Catch(vm, callbackFunc);
676 return ARKTS_FromHandle(result);
677 }
678
ARKTS_OpenScope(ARKTS_Env env)679 ARKTS_Scope ARKTS_OpenScope(ARKTS_Env env)
680 {
681 ARKTS_ASSERT_P(env, "env is null");
682 auto vm = P_CAST(env, EcmaVM*);
683 return CJ::ARKTS_ScopeManager::OpenScope(vm);
684 }
685
ARKTS_Return(ARKTS_Env env,ARKTS_Scope scope,ARKTS_Value value)686 ARKTS_Result ARKTS_Return(ARKTS_Env env, ARKTS_Scope scope, ARKTS_Value value)
687 {
688 ARKTS_ASSERT_P(env, "env is null");
689 ARKTS_ASSERT_P(value, "value is invalid");
690
691 auto vm = P_CAST(env, EcmaVM*);
692 if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
693 ARKTSInner_ReportNativeError("exit scope of unknown");
694 }
695
696 return ARKTS_ToResult(vm, value);
697 }
698
ARKTS_CloseScope(ARKTS_Env env,ARKTS_Scope scope)699 void ARKTS_CloseScope(ARKTS_Env env, ARKTS_Scope scope)
700 {
701 ARKTS_ASSERT_V(env, "env is null");
702 ARKTS_ASSERT_V(scope, "scope is invalid");
703
704 if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
705 ARKTSInner_ReportNativeError("exit scope of unknown");
706 }
707 }
708
ARKTSInner_Escape(ARKTS_Env env,ARKTS_Scope scope,ARKTS_Value ret)709 panda::JSValueRef* ARKTSInner_Escape(ARKTS_Env env, ARKTS_Scope scope, ARKTS_Value ret)
710 {
711 if (!CJ::ARKTS_ScopeManager::CloseScope(scope)) {
712 ARKTSInner_ReportNativeError("exit scope of unknown");
713 }
714
715 auto vm = P_CAST(env, EcmaVM*);
716 auto value = ARKTS_ToValue(ret);
717
718 auto result = JSNApi::CreateLocal(vm, value);
719
720 return BIT_CAST(result, JSValueRef*);
721 }
722
ARKTS_Throw(ARKTS_Env env,ARKTS_Value error)723 void ARKTS_Throw(ARKTS_Env env, ARKTS_Value error)
724 {
725 ARKTS_ASSERT_V(env, "env is null");
726 auto vm = P_CAST(env, EcmaVM*);
727
728 if (JSNApi::HasPendingException(vm)) {
729 LOGE("ARKTS_Throw failed, vm has uncaught exception");
730 return;
731 }
732
733 auto exception = ARKTS_ToHandle<JSValueRef>(error);
734 if (exception->IsString(vm)) {
735 JSNApi::ThrowException(vm, Exception::Error(vm, BIT_CAST(exception, Local<StringRef>)));
736 } else {
737 JSNApi::ThrowException(vm, exception);
738 }
739 }
740
ARKTS_GetCallEnv(ARKTS_CallInfo info)741 ARKTS_Env ARKTS_GetCallEnv(ARKTS_CallInfo info)
742 {
743 ARKTS_ASSERT_I(info, "info is null");
744 auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
745 auto vm = runInfo->GetVM();
746 return P_CAST(vm, ARKTS_Env);
747 }
748
ARKTS_GetArgCount(ARKTS_CallInfo info)749 uint32_t ARKTS_GetArgCount(ARKTS_CallInfo info)
750 {
751 ARKTS_ASSERT_I(info, "info is null");
752 auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
753 return runInfo->GetArgsNumber();
754 }
755
ARKTS_GetArg(ARKTS_CallInfo info,uint32_t index)756 ARKTS_Value ARKTS_GetArg(ARKTS_CallInfo info, uint32_t index)
757 {
758 ARKTS_ASSERT_P(info, "info is null");
759 auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
760 ARKTS_ASSERT_P(runInfo->GetArgsNumber() > index, "out of index");
761 auto result = runInfo->GetCallArgRef(index);
762 return ARKTS_FromHandle(result);
763 }
764
ARKTS_GetThisArg(ARKTS_CallInfo info)765 ARKTS_Value ARKTS_GetThisArg(ARKTS_CallInfo info)
766 {
767 ARKTS_ASSERT_P(info, "info is null");
768 auto runInfo = P_CAST(info, JsiRuntimeCallInfo*);
769 auto result = runInfo->GetThisRef();
770 return ARKTS_FromHandle(result);
771 }
772
ARKTS_GetGlobalNapiEnv(ARKTS_Env env)773 void* ARKTS_GetGlobalNapiEnv(ARKTS_Env env)
774 {
775 ARKTS_ASSERT_P(env, "env is null");
776 auto vm = P_CAST(env, EcmaVM*);
777 return JSNApi::GetEnv(vm);
778 }
779
ARKTS_UpdateStackInfo(unsigned long long vmAddress,void * subStackInfo,unsigned int opKind)780 void ARKTS_UpdateStackInfo(unsigned long long vmAddress, void *subStackInfo, unsigned int opKind)
781 {
782 ARKTS_ASSERT_V(vmAddress, "vm is null");
783 ARKTS_ASSERT_V(subStackInfo, "stack info is null");
784 auto vm = reinterpret_cast<panda::EcmaVM*>(vmAddress);
785 panda::JSNApi::UpdateStackInfo(vm, subStackInfo, opKind);
786 }
787