1 /* 2 * Copyright (c) 2021 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 #ifndef ECMASCRIPT_NAPI_JSNAPI_HELPER_H 17 #define ECMASCRIPT_NAPI_JSNAPI_HELPER_H 18 19 #include "ecmascript/ecma_runtime_call_info.h" 20 #include "ecmascript/js_handle.h" 21 #include "ecmascript/js_tagged_value.h" 22 #include "ecmascript/napi/include/jsnapi.h" 23 24 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 25 #define RETURN_VALUE_IF_ABRUPT(thread, value) \ 26 do { \ 27 if (thread->HasPendingException()) { \ 28 LOG_FULL(ERROR) << "occur exception need return"; \ 29 return value; \ 30 } \ 31 } while (false) 32 33 #if ECMASCRIPT_ENABLE_NAPI_SPECIAL_CHECK 34 #define LOG_IF_SPECIAL(handleValue, level) \ 35 do { \ 36 LOG_ECMA(DEBUG) << "Enable napi special check"; \ 37 if ((handleValue).GetTaggedValue().IsSpecial()) { \ 38 LOG_FULL(level) << "Special value " << (handleValue).GetTaggedType() << " checked!"; \ 39 } \ 40 } while (false) 41 #else 42 #define LOG_IF_SPECIAL(handleValue, level) static_cast<void>(0) 43 #endif 44 45 #define CROSS_THREAD_CHECK(vm) \ 46 [[maybe_unused]] JSThread *thread = (vm)->GetAndFastCheckJSThread() 47 48 #define CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, returnVal) \ 49 CROSS_THREAD_CHECK(vm); \ 50 do { \ 51 if (thread->HasPendingException()) { \ 52 LOG_ECMA(ERROR) << "Pending exception before " << __FUNCTION__ << " called in line:" \ 53 << __LINE__ << ", exception details as follows:"; \ 54 JSNApi::PrintExceptionInfo(vm); \ 55 return returnVal; \ 56 } \ 57 } while (false) 58 59 #define CROSS_THREAD_AND_EXCEPTION_CHECK(vm) \ 60 CROSS_THREAD_CHECK(vm); \ 61 do { \ 62 if (thread->HasPendingException()) { \ 63 LOG_ECMA(ERROR) << "Pending exception before " << __FUNCTION__ << " called, in line:" \ 64 << __LINE__ << ", exception details as follows:"; \ 65 JSNApi::PrintExceptionInfo(vm); \ 66 return; \ 67 } \ 68 } while (false) 69 70 #define DCHECK_SPECIAL_VALUE(jsValueRef) \ 71 do { \ 72 auto val = reinterpret_cast<JSTaggedValue *>(jsValueRef); \ 73 if (UNLIKELY(val->IsSpecial())) { \ 74 LOG_FULL(ERROR) << "JSNApi special value:0x" << val->GetRawData() << " checked"; \ 75 return; \ 76 } \ 77 } while (false) 78 79 #define DCHECK_SPECIAL_VALUE_WITH_RETURN(jsValueRef, retValue) \ 80 do { \ 81 auto val = reinterpret_cast<JSTaggedValue *>(jsValueRef); \ 82 if (UNLIKELY(val->IsSpecial())) { \ 83 LOG_FULL(ERROR) << "JSNApi special value:0x" << val->GetRawData() << " checked"; \ 84 return (retValue); \ 85 } \ 86 } while (false) 87 88 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 89 #define TYPED_ARRAY_ALL(V) \ 90 V(Int8Array) \ 91 V(Uint8Array) \ 92 V(Uint8ClampedArray) \ 93 V(Int16Array) \ 94 V(Uint16Array) \ 95 V(Int32Array) \ 96 V(Uint32Array) \ 97 V(Float32Array) \ 98 V(Float64Array) \ 99 V(BigInt64Array) \ 100 V(BigUint64Array) 101 102 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 103 #define EXCEPTION_ERROR_ALL(V) \ 104 V(Error, ERROR) \ 105 V(RangeError, RANGE_ERROR) \ 106 V(SyntaxError, SYNTAX_ERROR) \ 107 V(ReferenceError, REFERENCE_ERROR) \ 108 V(TypeError, TYPE_ERROR) \ 109 V(AggregateError, AGGREGATE_ERROR) \ 110 V(EvalError, EVAL_ERROR) \ 111 V(OOMError, OOM_ERROR) \ 112 V(TerminationError, TERMINATION_ERROR) 113 114 namespace panda { 115 using NativeFinalize = void (*)(EcmaVM *); 116 class JSNApiHelper { 117 public: 118 template<typename T> ToLocal(ecmascript::JSHandle<ecmascript::JSTaggedValue> from)119 static inline Local<T> ToLocal(ecmascript::JSHandle<ecmascript::JSTaggedValue> from) 120 { 121 return Local<T>(from.GetAddress()); 122 } 123 ToJSTaggedValue(JSValueRef * from)124 static inline ecmascript::JSTaggedValue ToJSTaggedValue(JSValueRef *from) 125 { 126 ASSERT(from != nullptr); 127 return *reinterpret_cast<ecmascript::JSTaggedValue *>(from); 128 } 129 ToJSHandle(Local<JSValueRef> from)130 static inline ecmascript::JSHandle<ecmascript::JSTaggedValue> ToJSHandle(Local<JSValueRef> from) 131 { 132 ASSERT(!from.IsEmpty()); 133 return ecmascript::JSHandle<ecmascript::JSTaggedValue>(reinterpret_cast<uintptr_t>(*from)); 134 } 135 ToJSHandle(JSValueRef * from)136 static inline ecmascript::JSHandle<ecmascript::JSTaggedValue> ToJSHandle(JSValueRef *from) 137 { 138 ASSERT(from != nullptr); 139 return ecmascript::JSHandle<ecmascript::JSTaggedValue>(reinterpret_cast<uintptr_t>(from)); 140 } 141 }; 142 143 class NativeReferenceHelper { 144 public: NativeReferenceHelper(EcmaVM * vm,Global<ObjectRef> obj,NativeFinalize callback)145 NativeReferenceHelper(EcmaVM *vm, Global<ObjectRef> obj, NativeFinalize callback) 146 : vm_(vm), obj_(obj), callback_(callback) {} ~NativeReferenceHelper()147 ~NativeReferenceHelper() 148 { 149 obj_.FreeGlobalHandleAddr(); 150 } FreeGlobalCallBack(void * ref)151 static void FreeGlobalCallBack(void* ref) 152 { 153 auto that = reinterpret_cast<NativeReferenceHelper*>(ref); 154 that->obj_.FreeGlobalHandleAddr(); 155 } 156 NativeFinalizeCallBack(void * ref)157 static void NativeFinalizeCallBack(void* ref) 158 { 159 auto that = reinterpret_cast<NativeReferenceHelper*>(ref); 160 if (that->callback_ != nullptr) { 161 that->callback_(that->vm_); 162 } 163 that->callback_ = nullptr; 164 } 165 SetWeakCallback()166 void SetWeakCallback() 167 { 168 obj_.SetWeakCallback(this, FreeGlobalCallBack, NativeFinalizeCallBack); 169 } 170 171 private: 172 EcmaVM *vm_; 173 Global<ObjectRef> obj_; 174 NativeFinalize callback_ = nullptr; 175 }; 176 177 class Callback { 178 public: 179 static ecmascript::JSTaggedValue RegisterCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo); 180 }; 181 } // namespace panda 182 #endif // ECMASCRIPT_NAPI_JSNAPI_HELPER_H 183