14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_NAPI_JSNAPI_HELPER_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_NAPI_JSNAPI_HELPER_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/ecma_runtime_call_info.h" 204514f5e3Sopenharmony_ci#include "ecmascript/js_handle.h" 214514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h" 224514f5e3Sopenharmony_ci#include "ecmascript/napi/include/jsnapi.h" 234514f5e3Sopenharmony_ci 244514f5e3Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 254514f5e3Sopenharmony_ci#define RETURN_VALUE_IF_ABRUPT(thread, value) \ 264514f5e3Sopenharmony_ci do { \ 274514f5e3Sopenharmony_ci if (thread->HasPendingException()) { \ 284514f5e3Sopenharmony_ci LOG_FULL(ERROR) << "occur exception need return"; \ 294514f5e3Sopenharmony_ci return value; \ 304514f5e3Sopenharmony_ci } \ 314514f5e3Sopenharmony_ci } while (false) 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_NAPI_SPECIAL_CHECK 344514f5e3Sopenharmony_ci#define LOG_IF_SPECIAL(handleValue, level) \ 354514f5e3Sopenharmony_ci do { \ 364514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Enable napi special check"; \ 374514f5e3Sopenharmony_ci if ((handleValue).GetTaggedValue().IsSpecial()) { \ 384514f5e3Sopenharmony_ci LOG_FULL(level) << "Special value " << (handleValue).GetTaggedType() << " checked!"; \ 394514f5e3Sopenharmony_ci } \ 404514f5e3Sopenharmony_ci } while (false) 414514f5e3Sopenharmony_ci#else 424514f5e3Sopenharmony_ci#define LOG_IF_SPECIAL(handleValue, level) static_cast<void>(0) 434514f5e3Sopenharmony_ci#endif 444514f5e3Sopenharmony_ci 454514f5e3Sopenharmony_ci#define CROSS_THREAD_CHECK(vm) \ 464514f5e3Sopenharmony_ci [[maybe_unused]] JSThread *thread = (vm)->GetJSThread() 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ci#define CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, returnVal) \ 494514f5e3Sopenharmony_ci CROSS_THREAD_CHECK(vm); \ 504514f5e3Sopenharmony_ci do { \ 514514f5e3Sopenharmony_ci if (thread->HasPendingException()) { \ 524514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Pending exception before " << __FUNCTION__ << " called in line:" \ 534514f5e3Sopenharmony_ci << __LINE__ << ", exception details as follows:"; \ 544514f5e3Sopenharmony_ci JSNApi::PrintExceptionInfo(vm); \ 554514f5e3Sopenharmony_ci return returnVal; \ 564514f5e3Sopenharmony_ci } \ 574514f5e3Sopenharmony_ci } while (false) 584514f5e3Sopenharmony_ci 594514f5e3Sopenharmony_ci#define CROSS_THREAD_AND_EXCEPTION_CHECK(vm) \ 604514f5e3Sopenharmony_ci CROSS_THREAD_CHECK(vm); \ 614514f5e3Sopenharmony_ci do { \ 624514f5e3Sopenharmony_ci if (thread->HasPendingException()) { \ 634514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Pending exception before " << __FUNCTION__ << " called, in line:" \ 644514f5e3Sopenharmony_ci << __LINE__ << ", exception details as follows:"; \ 654514f5e3Sopenharmony_ci JSNApi::PrintExceptionInfo(vm); \ 664514f5e3Sopenharmony_ci return; \ 674514f5e3Sopenharmony_ci } \ 684514f5e3Sopenharmony_ci } while (false) 694514f5e3Sopenharmony_ci 704514f5e3Sopenharmony_ci#define SINGLE_THREAD_CHECK_WITH_RETURN(vm, result) \ 714514f5e3Sopenharmony_ci [[maybe_unused]] JSThread *thread = (vm)->GetJSThreadNoCheck(); \ 724514f5e3Sopenharmony_ci do { \ 734514f5e3Sopenharmony_ci if (thread->HasPendingException()) { \ 744514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Pending exception before " << __FUNCTION__ << " called in line:" \ 754514f5e3Sopenharmony_ci << __LINE__ << ", exception details as follows:"; \ 764514f5e3Sopenharmony_ci JSNApi::PrintExceptionInfo(vm); \ 774514f5e3Sopenharmony_ci return result; \ 784514f5e3Sopenharmony_ci } \ 794514f5e3Sopenharmony_ci if (!(vm)->CheckSingleThread()) { \ 804514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "cross thread to call " << __FUNCTION__ << "is not supported"; \ 814514f5e3Sopenharmony_ci return result; \ 824514f5e3Sopenharmony_ci } \ 834514f5e3Sopenharmony_ci } while (false) 844514f5e3Sopenharmony_ci 854514f5e3Sopenharmony_ci#define DCHECK_SPECIAL_VALUE(jsValueRef) \ 864514f5e3Sopenharmony_ci do { \ 874514f5e3Sopenharmony_ci auto val = reinterpret_cast<JSTaggedValue *>(jsValueRef); \ 884514f5e3Sopenharmony_ci if (UNLIKELY(val->IsSpecial())) { \ 894514f5e3Sopenharmony_ci LOG_FULL(ERROR) << "JSNApi special value:0x" << val->GetRawData() << " checked"; \ 904514f5e3Sopenharmony_ci return; \ 914514f5e3Sopenharmony_ci } \ 924514f5e3Sopenharmony_ci } while (false) 934514f5e3Sopenharmony_ci 944514f5e3Sopenharmony_ci#define DCHECK_SPECIAL_VALUE_WITH_RETURN(jsValueRef, retValue) \ 954514f5e3Sopenharmony_ci do { \ 964514f5e3Sopenharmony_ci auto val = reinterpret_cast<JSTaggedValue *>(jsValueRef); \ 974514f5e3Sopenharmony_ci if (UNLIKELY(val->IsSpecial())) { \ 984514f5e3Sopenharmony_ci LOG_FULL(ERROR) << "JSNApi special value:0x" << val->GetRawData() << " checked"; \ 994514f5e3Sopenharmony_ci return (retValue); \ 1004514f5e3Sopenharmony_ci } \ 1014514f5e3Sopenharmony_ci } while (false) 1024514f5e3Sopenharmony_ci 1034514f5e3Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 1044514f5e3Sopenharmony_ci#define TYPED_ARRAY_ALL(V) \ 1054514f5e3Sopenharmony_ci V(Int8Array) \ 1064514f5e3Sopenharmony_ci V(Uint8Array) \ 1074514f5e3Sopenharmony_ci V(Uint8ClampedArray) \ 1084514f5e3Sopenharmony_ci V(Int16Array) \ 1094514f5e3Sopenharmony_ci V(Uint16Array) \ 1104514f5e3Sopenharmony_ci V(Int32Array) \ 1114514f5e3Sopenharmony_ci V(Uint32Array) \ 1124514f5e3Sopenharmony_ci V(Float32Array) \ 1134514f5e3Sopenharmony_ci V(Float64Array) \ 1144514f5e3Sopenharmony_ci V(BigInt64Array) \ 1154514f5e3Sopenharmony_ci V(BigUint64Array) 1164514f5e3Sopenharmony_ci 1174514f5e3Sopenharmony_ci#define SENDABLE_TYPED_ARRAY_ALL(V) \ 1184514f5e3Sopenharmony_ci V(SharedInt8Array) \ 1194514f5e3Sopenharmony_ci V(SharedUint8Array) \ 1204514f5e3Sopenharmony_ci V(SharedInt16Array) \ 1214514f5e3Sopenharmony_ci V(SharedUint16Array) \ 1224514f5e3Sopenharmony_ci V(SharedInt32Array) \ 1234514f5e3Sopenharmony_ci V(SharedUint32Array) \ 1244514f5e3Sopenharmony_ci V(SharedUint8ClampedArray) \ 1254514f5e3Sopenharmony_ci V(SharedFloat32Array) 1264514f5e3Sopenharmony_ci 1274514f5e3Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 1284514f5e3Sopenharmony_ci#define EXCEPTION_ERROR_ALL(V) \ 1294514f5e3Sopenharmony_ci V(Error, ERROR) \ 1304514f5e3Sopenharmony_ci V(RangeError, RANGE_ERROR) \ 1314514f5e3Sopenharmony_ci V(SyntaxError, SYNTAX_ERROR) \ 1324514f5e3Sopenharmony_ci V(ReferenceError, REFERENCE_ERROR) \ 1334514f5e3Sopenharmony_ci V(TypeError, TYPE_ERROR) \ 1344514f5e3Sopenharmony_ci V(AggregateError, AGGREGATE_ERROR) \ 1354514f5e3Sopenharmony_ci V(EvalError, EVAL_ERROR) \ 1364514f5e3Sopenharmony_ci V(OOMError, OOM_ERROR) \ 1374514f5e3Sopenharmony_ci V(TerminationError, TERMINATION_ERROR) 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_cinamespace panda { 1404514f5e3Sopenharmony_ciusing NativeFinalize = void (*)(EcmaVM *); 1414514f5e3Sopenharmony_ciclass JSNApiHelper { 1424514f5e3Sopenharmony_cipublic: 1434514f5e3Sopenharmony_ci template<typename T> 1444514f5e3Sopenharmony_ci static inline Local<T> ToLocal(ecmascript::JSHandle<ecmascript::JSTaggedValue> from) 1454514f5e3Sopenharmony_ci { 1464514f5e3Sopenharmony_ci return Local<T>(from.GetAddress()); 1474514f5e3Sopenharmony_ci } 1484514f5e3Sopenharmony_ci 1494514f5e3Sopenharmony_ci static inline ecmascript::JSTaggedValue ToJSTaggedValue(JSValueRef *from) 1504514f5e3Sopenharmony_ci { 1514514f5e3Sopenharmony_ci ASSERT(from != nullptr); 1524514f5e3Sopenharmony_ci return *reinterpret_cast<ecmascript::JSTaggedValue *>(from); 1534514f5e3Sopenharmony_ci } 1544514f5e3Sopenharmony_ci 1554514f5e3Sopenharmony_ci static inline ecmascript::JSMutableHandle<ecmascript::JSTaggedValue> ToJSMutableHandle(Local<JSValueRef> from) 1564514f5e3Sopenharmony_ci { 1574514f5e3Sopenharmony_ci ASSERT(!from.IsEmpty()); 1584514f5e3Sopenharmony_ci return ecmascript::JSMutableHandle<ecmascript::JSTaggedValue>(reinterpret_cast<uintptr_t>(*from)); 1594514f5e3Sopenharmony_ci } 1604514f5e3Sopenharmony_ci 1614514f5e3Sopenharmony_ci static inline ecmascript::JSHandle<ecmascript::JSTaggedValue> ToJSHandle(Local<JSValueRef> from) 1624514f5e3Sopenharmony_ci { 1634514f5e3Sopenharmony_ci ASSERT(!from.IsEmpty()); 1644514f5e3Sopenharmony_ci return ecmascript::JSHandle<ecmascript::JSTaggedValue>(reinterpret_cast<uintptr_t>(*from)); 1654514f5e3Sopenharmony_ci } 1664514f5e3Sopenharmony_ci 1674514f5e3Sopenharmony_ci static inline ecmascript::JSHandle<ecmascript::JSTaggedValue> ToJSHandle(JSValueRef *from) 1684514f5e3Sopenharmony_ci { 1694514f5e3Sopenharmony_ci ASSERT(from != nullptr); 1704514f5e3Sopenharmony_ci return ecmascript::JSHandle<ecmascript::JSTaggedValue>(reinterpret_cast<uintptr_t>(from)); 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci}; 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_ciclass NativeReferenceHelper { 1754514f5e3Sopenharmony_cipublic: 1764514f5e3Sopenharmony_ci NativeReferenceHelper(EcmaVM *vm, Global<ObjectRef> obj, NativeFinalize callback) 1774514f5e3Sopenharmony_ci : vm_(vm), obj_(obj), callback_(callback) {} 1784514f5e3Sopenharmony_ci ~NativeReferenceHelper() 1794514f5e3Sopenharmony_ci { 1804514f5e3Sopenharmony_ci obj_.FreeGlobalHandleAddr(); 1814514f5e3Sopenharmony_ci } 1824514f5e3Sopenharmony_ci static void FreeGlobalCallBack(void* ref) 1834514f5e3Sopenharmony_ci { 1844514f5e3Sopenharmony_ci auto that = reinterpret_cast<NativeReferenceHelper*>(ref); 1854514f5e3Sopenharmony_ci that->obj_.FreeGlobalHandleAddr(); 1864514f5e3Sopenharmony_ci } 1874514f5e3Sopenharmony_ci 1884514f5e3Sopenharmony_ci static void NativeFinalizeCallBack(void* ref) 1894514f5e3Sopenharmony_ci { 1904514f5e3Sopenharmony_ci auto that = reinterpret_cast<NativeReferenceHelper*>(ref); 1914514f5e3Sopenharmony_ci if (that->callback_ != nullptr) { 1924514f5e3Sopenharmony_ci that->callback_(that->vm_); 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci that->callback_ = nullptr; 1954514f5e3Sopenharmony_ci } 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ci void SetWeakCallback() 1984514f5e3Sopenharmony_ci { 1994514f5e3Sopenharmony_ci obj_.SetWeakCallback(this, FreeGlobalCallBack, NativeFinalizeCallBack); 2004514f5e3Sopenharmony_ci } 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ciprivate: 2034514f5e3Sopenharmony_ci EcmaVM *vm_; 2044514f5e3Sopenharmony_ci Global<ObjectRef> obj_; 2054514f5e3Sopenharmony_ci NativeFinalize callback_ = nullptr; 2064514f5e3Sopenharmony_ci}; 2074514f5e3Sopenharmony_ci 2084514f5e3Sopenharmony_ciclass Callback { 2094514f5e3Sopenharmony_cipublic: 2104514f5e3Sopenharmony_ci static ecmascript::JSTaggedValue RegisterCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo); 2114514f5e3Sopenharmony_ci}; 2124514f5e3Sopenharmony_ci} // namespace panda 2134514f5e3Sopenharmony_ci#endif // ECMASCRIPT_NAPI_JSNAPI_HELPER_H 214