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