• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "ark_native_function.h"
17 
18 #ifdef ENABLE_CONTAINER_SCOPE
19 #include "core/common/container_scope.h"
20 #endif
21 
22 #include "utils/log.h"
23 
24 using panda::ArrayRef;
25 using panda::NativePointerRef;
26 using panda::FunctionRef;
27 using panda::StringRef;
28 using panda::JsiRuntimeCallInfo;
29 static constexpr uint32_t MAX_CHUNK_ARRAY_SIZE = 10;
30 
ArkNativeFunction(ArkNativeEngine * engine,Local<JSValueRef> value)31 ArkNativeFunction::ArkNativeFunction(ArkNativeEngine* engine, Local<JSValueRef> value) : ArkNativeObject(engine, value)
32 {
33 #ifdef ENABLE_CONTAINER_SCOPE
34     scopeId_ = OHOS::Ace::ContainerScope::CurrentId();
35 #endif
36 }
37 
38 // common function
ArkNativeFunction(ArkNativeEngine * engine,const char * name,size_t length,NativeCallback cb,void * value)39 ArkNativeFunction::ArkNativeFunction(ArkNativeEngine* engine,
40                                      const char* name,
41                                      size_t length,
42                                      NativeCallback cb,
43                                      void* value)
44     : ArkNativeFunction(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
45 {
46     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
47     LocalScope scope(vm);
48 
49     NativeFunctionInfo* funcInfo = NativeFunctionInfo::CreateNewInstance();
50     if (funcInfo == nullptr) {
51         HILOG_ERROR("funcInfo is nullptr");
52         return;
53     }
54     funcInfo->engine = engine;
55     funcInfo->callback = cb;
56     funcInfo->data = value;
57 
58     Local<FunctionRef> fn = FunctionRef::New(vm, NativeFunctionCallBack,
59                                              [](void* externalPointer, void* data) {
60                                                 auto info = reinterpret_cast<NativeFunctionInfo*>(data);
61                                                 if (info != nullptr) {
62                                                     delete info;
63                                                 }
64                                              },
65                                              reinterpret_cast<void*>(funcInfo), true);
66     Local<StringRef> fnName = StringRef::NewFromUtf8(vm, name);
67     fn->SetName(vm, fnName);
68 
69     Global<JSValueRef> globalFn(vm, fn);
70     value_ = globalFn;
71 }
72 
73 
74 // class function
ArkNativeFunction(ArkNativeEngine * engine,const char * name,NativeCallback cb,void * value)75 ArkNativeFunction::ArkNativeFunction(ArkNativeEngine* engine,
76                                      const char* name,
77                                      NativeCallback cb,
78                                      void* value)
79     : ArkNativeFunction(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
80 {
81     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
82     LocalScope scope(vm);
83 
84     NativeFunctionInfo* funcInfo = NativeFunctionInfo::CreateNewInstance();
85     if (funcInfo == nullptr) {
86         HILOG_ERROR("funcInfo is nullptr");
87         return;
88     }
89     funcInfo->engine = engine;
90     funcInfo->callback = cb;
91     funcInfo->data = value;
92 
93     Local<FunctionRef> fn = FunctionRef::NewClassFunction(vm, NativeFunctionCallBack,
94                                                           [](void* externalPointer, void* data) {
95                                                               auto info = reinterpret_cast<NativeFunctionInfo*>(data);
96                                                               if (info != nullptr) {
97                                                                  delete info;
98                                                               }
99                                                           },
100                                                           reinterpret_cast<void*>(funcInfo), true);
101     Local<StringRef> fnName = StringRef::NewFromUtf8(vm, name);
102     fn->SetName(vm, fnName);
103 
104     Global<JSValueRef> globalFn(vm, fn);
105     value_ = globalFn;
106 }
107 
~ArkNativeFunction()108 ArkNativeFunction::~ArkNativeFunction()
109 {
110 }
111 
GetInterface(int interfaceId)112 void* ArkNativeFunction::GetInterface(int interfaceId)
113 {
114     return (NativeFunction::INTERFACE_ID == interfaceId) ? (NativeFunction*)this
115                                                          : ArkNativeObject::GetInterface(interfaceId);
116 }
117 
NativeFunctionCallBack(JsiRuntimeCallInfo * runtimeInfo)118 Local<JSValueRef> ArkNativeFunction::NativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo)
119 {
120     EcmaVM *vm = runtimeInfo->GetVM();
121     panda::EscapeLocalScope scope(vm);
122     auto info = reinterpret_cast<NativeFunctionInfo*>(runtimeInfo->GetData());
123     auto engine = reinterpret_cast<ArkNativeEngine*>(info->engine);
124     auto cb = info->callback;
125     if (engine == nullptr) {
126         HILOG_ERROR("native engine is null");
127         return JSValueRef::Undefined(vm);
128     }
129 
130     NativeCallbackInfo cbInfo = { 0 };
131     NativeScopeManager* scopeManager = engine->GetScopeManager();
132     if (scopeManager == nullptr) {
133         HILOG_ERROR("scope manager is null");
134         return JSValueRef::Undefined(vm);
135     }
136 
137     StartNapiProfilerTrace(runtimeInfo);
138     NativeScope* nativeScope = scopeManager->Open();
139     cbInfo.thisVar = ArkNativeEngine::ArkValueToNativeValue(engine, runtimeInfo->GetThisRef());
140     cbInfo.function = ArkNativeEngine::ArkValueToNativeValue(engine, runtimeInfo->GetNewTargetRef());
141     cbInfo.argc = static_cast<size_t>(runtimeInfo->GetArgsNumber());
142     cbInfo.argv = nullptr;
143     cbInfo.functionInfo = info;
144     if (cbInfo.argc > 0) {
145         if (cbInfo.argc > MAX_CHUNK_ARRAY_SIZE) {
146             cbInfo.argv = new NativeValue* [cbInfo.argc];
147         } else {
148             cbInfo.argv = scopeManager->GetNativeChunk().NewArray<NativeValue *>(cbInfo.argc);
149         }
150         for (size_t i = 0; i < cbInfo.argc; i++) {
151             cbInfo.argv[i] = ArkNativeEngine::ArkValueToNativeValue(engine, runtimeInfo->GetCallArgRef(i));
152         }
153     }
154 
155     if (engine->IsMixedDebugEnabled()) {
156         engine->NotifyNativeCalling(reinterpret_cast<void *>(cb));
157     }
158 
159     NativeValue* result = nullptr;
160     if (cb != nullptr) {
161         result = cb(engine, &cbInfo);
162     }
163 
164     if (cbInfo.argv != nullptr) {
165         if (cbInfo.argc > MAX_CHUNK_ARRAY_SIZE) {
166             delete[] cbInfo.argv;
167         } else {
168             scopeManager->GetNativeChunk().Delete(cbInfo.argv);
169         }
170         cbInfo.argv = nullptr;
171     }
172 
173     Local<JSValueRef> localRet = JSValueRef::Undefined(vm);
174     if (result == nullptr) {
175         if (engine->IsExceptionPending()) {
176             [[maybe_unused]] NativeValue* error = engine->GetAndClearLastException();
177         }
178     } else {
179         Global<JSValueRef> ret = *result;
180         localRet = ret.ToLocal(vm);
181     }
182     scopeManager->Close(nativeScope);
183     FinishNapiProfilerTrace();
184     if (localRet.IsEmpty()) {
185         return scope.Escape(JSValueRef::Undefined(vm));
186     }
187     return scope.Escape(localRet);
188 }
189 
GetNativePtrCallBack(void * data)190 void* ArkNativeFunction::GetNativePtrCallBack(void* data)
191 {
192     auto info = reinterpret_cast<NativeFunctionInfo*>(data);
193     auto cb = reinterpret_cast<void*>(info->callback);
194     return cb;
195 }
196 
GetFunctionPrototype()197 NativeValue* ArkNativeFunction::GetFunctionPrototype()
198 {
199     auto vm = engine_->GetEcmaVm();
200     LocalScope scope(vm);
201     Global<FunctionRef> func = value_;
202     Local<JSValueRef> prototype = func->GetFunctionPrototype(vm);
203     return ArkNativeEngine::ArkValueToNativeValue(engine_, prototype);
204 }
205 
GetSourceCodeInfo(ErrorPos pos)206 std::string ArkNativeFunction::GetSourceCodeInfo(ErrorPos pos)
207 {
208     if (pos.first == 0) {
209         return "";
210     }
211     auto vm = engine_->GetEcmaVm();
212     LocalScope scope(vm);
213     Global<FunctionRef> func = value_;
214     uint32_t line = pos.first;
215     uint32_t column = pos.second;
216     Local<panda::StringRef> sourceCode = func->GetSourceCode(vm, line);
217     std::string sourceCodeStr = sourceCode->ToString();
218     if (sourceCodeStr.empty()) {
219         return "";
220     }
221     std::string sourceCodeInfo = "SourceCode:\n";
222     sourceCodeInfo.append(sourceCodeStr).append("\n");
223     for (uint32_t k = 0; k < column - 1; k++) {
224         sourceCodeInfo.push_back(' ');
225     }
226     sourceCodeInfo.append("^\n");
227     return sourceCodeInfo;
228 }
229