• 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;
ArkNativeFunction(ArkNativeEngine * engine,Local<JSValueRef> value)28 ArkNativeFunction::ArkNativeFunction(ArkNativeEngine* engine, Local<JSValueRef> value) : ArkNativeObject(engine, value)
29 {
30 #ifdef ENABLE_CONTAINER_SCOPE
31     scopeId_ = OHOS::Ace::ContainerScope::CurrentId();
32 #endif
33 }
34 
35 // common function
ArkNativeFunction(ArkNativeEngine * engine,const char * name,size_t length,NativeCallback cb,void * value)36 ArkNativeFunction::ArkNativeFunction(ArkNativeEngine* engine,
37                                      const char* name,
38                                      size_t length,
39                                      NativeCallback cb,
40                                      void* value)
41     : ArkNativeFunction(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
42 {
43     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
44     LocalScope scope(vm);
45 
46     NativeFunctionInfo* funcInfo = NativeFunctionInfo::CreateNewInstance();
47     if (funcInfo == nullptr) {
48         HILOG_ERROR("funcInfo is nullptr");
49         return;
50     }
51     funcInfo->engine = engine;
52     funcInfo->callback = cb;
53     funcInfo->data = value;
54 
55     Local<FunctionRef> fn = FunctionRef::New(vm, NativeFunctionCallBack,
56                                              [](void* externalPointer, void* data) {
57                                                 auto info = reinterpret_cast<NativeFunctionInfo*>(data);
58                                                 if (info != nullptr) {
59                                                     delete info;
60                                                 }
61                                              },
62                                              reinterpret_cast<void*>(funcInfo));
63     Local<StringRef> fnName = StringRef::NewFromUtf8(vm, name);
64     fn->SetName(vm, fnName);
65 
66     Global<JSValueRef> globalFn(vm, fn);
67     value_ = globalFn;
68 }
69 
70 
71 // class function
ArkNativeFunction(ArkNativeEngine * engine,const char * name,NativeCallback cb,void * value)72 ArkNativeFunction::ArkNativeFunction(ArkNativeEngine* engine,
73                                      const char* name,
74                                      NativeCallback cb,
75                                      void* value)
76     : ArkNativeFunction(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
77 {
78     auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
79     LocalScope scope(vm);
80 
81     NativeFunctionInfo* funcInfo = NativeFunctionInfo::CreateNewInstance();
82     if (funcInfo == nullptr) {
83         HILOG_ERROR("funcInfo is nullptr");
84         return;
85     }
86     funcInfo->engine = engine;
87     funcInfo->callback = cb;
88     funcInfo->data = value;
89 
90     Local<FunctionRef> fn = FunctionRef::NewClassFunction(vm, NativeClassFunctionCallBack,
91                                                           [](void* externalPointer, void* data) {
92                                                               auto info = reinterpret_cast<NativeFunctionInfo*>(data);
93                                                               if (info != nullptr) {
94                                                                  delete info;
95                                                               }
96                                                           },
97                                                           reinterpret_cast<void*>(funcInfo));
98     Local<StringRef> fnName = StringRef::NewFromUtf8(vm, name);
99     fn->SetName(vm, fnName);
100 
101     Global<JSValueRef> globalFn(vm, fn);
102     value_ = globalFn;
103 }
104 
~ArkNativeFunction()105 ArkNativeFunction::~ArkNativeFunction()
106 {
107 }
108 
GetInterface(int interfaceId)109 void* ArkNativeFunction::GetInterface(int interfaceId)
110 {
111     return (NativeFunction::INTERFACE_ID == interfaceId) ? (NativeFunction*)this
112                                                          : ArkNativeObject::GetInterface(interfaceId);
113 }
114 
NativeFunctionCallBack(EcmaVM * vm,Local<JSValueRef> thisObj,const Local<JSValueRef> argv[],int32_t length,void * data)115 Local<JSValueRef> ArkNativeFunction::NativeFunctionCallBack(EcmaVM* vm,
116                                                             Local<JSValueRef> thisObj,
117                                                             const Local<JSValueRef> argv[],
118                                                             int32_t length,
119                                                             void* data)
120 {
121     panda::EscapeLocalScope scope(vm);
122     auto info = reinterpret_cast<NativeFunctionInfo*>(data);
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     NativeScope* nativeScope = scopeManager->Open();
137     cbInfo.thisVar = ArkNativeEngine::ArkValueToNativeValue(engine, thisObj);
138     cbInfo.function = nullptr;
139     cbInfo.argc = static_cast<size_t>(length);
140     cbInfo.argv = nullptr;
141     cbInfo.functionInfo = info;
142     if (cbInfo.argc > 0) {
143         cbInfo.argv = new NativeValue* [cbInfo.argc];
144         for (size_t i = 0; i < cbInfo.argc; i++) {
145             cbInfo.argv[i] = ArkNativeEngine::ArkValueToNativeValue(engine, argv[i]);
146         }
147     }
148 
149     NativeValue* result = nullptr;
150     if (cb != nullptr) {
151         result = cb(engine, &cbInfo);
152     }
153 
154     if (cbInfo.argv != nullptr) {
155         delete[] cbInfo.argv;
156         cbInfo.argv = nullptr;
157     }
158 
159     Local<JSValueRef> localRet = JSValueRef::Undefined(vm);
160     if (result == nullptr) {
161         if (engine->IsExceptionPending()) {
162             [[maybe_unused]] NativeValue* error = engine->GetAndClearLastException();
163         }
164     } else {
165         Global<JSValueRef> ret = *result;
166         localRet = ret.ToLocal(vm);
167     }
168     scopeManager->Close(nativeScope);
169     if (localRet.IsEmpty()) {
170         return scope.Escape(JSValueRef::Undefined(vm));
171     }
172     return scope.Escape(localRet);
173 }
174 
NativeClassFunctionCallBack(EcmaVM * vm,Local<JSValueRef> function,Local<JSValueRef> newTarget,const Local<JSValueRef> argv[],int32_t length,void * data)175 Local<JSValueRef> ArkNativeFunction::NativeClassFunctionCallBack(EcmaVM* vm,
176                                                                  Local<JSValueRef> function,
177                                                                  Local<JSValueRef> newTarget,
178                                                                  const Local<JSValueRef> argv[],
179                                                                  int32_t length,
180                                                                  void* data)
181 {
182     panda::EscapeLocalScope scope(vm);
183     auto info = reinterpret_cast<NativeFunctionInfo*>(data);
184     auto engine = reinterpret_cast<ArkNativeEngine*>(info->engine);
185     auto cb = info->callback;
186     if (engine == nullptr) {
187         HILOG_ERROR("native engine is null");
188         return JSValueRef::Undefined(vm);
189     }
190 
191     NativeCallbackInfo cbInfo = { 0 };
192     NativeScopeManager* scopeManager = engine->GetScopeManager();
193     if (scopeManager == nullptr) {
194         HILOG_ERROR("scope manager is null");
195         return JSValueRef::Undefined(vm);
196     }
197     NativeScope* nativeScope = scopeManager->Open();
198     cbInfo.thisVar = ArkNativeEngine::ArkValueToNativeValue(engine, function);
199     cbInfo.function = ArkNativeEngine::ArkValueToNativeValue(engine, newTarget);
200     cbInfo.argc = static_cast<size_t>(length);
201     cbInfo.argv = nullptr;
202     cbInfo.functionInfo = info;
203     if (cbInfo.argc > 0) {
204         cbInfo.argv = new NativeValue* [cbInfo.argc];
205         for (size_t i = 0; i < cbInfo.argc; i++) {
206             cbInfo.argv[i] = ArkNativeEngine::ArkValueToNativeValue(engine, argv[i]);
207         }
208     }
209 
210     NativeValue* result = nullptr;
211     if (cb != nullptr) {
212         result = cb(engine, &cbInfo);
213     }
214 
215     if (cbInfo.argv != nullptr) {
216         delete[] cbInfo.argv;
217         cbInfo.argv = nullptr;
218     }
219 
220     Global<JSValueRef> ret(vm, JSValueRef::Undefined(vm));
221     if (result == nullptr) {
222         if (engine->IsExceptionPending()) {
223             [[maybe_unused]] NativeValue* error = engine->GetAndClearLastException();
224         }
225     } else {
226         ret = *result;
227     }
228     auto localRet = ret.ToLocal(vm);
229     scopeManager->Close(nativeScope);
230     if (localRet.IsEmpty()) {
231         return scope.Escape(JSValueRef::Undefined(vm));
232     }
233     return scope.Escape(localRet);
234 }
235 
GetFunctionPrototype()236 NativeValue* ArkNativeFunction::GetFunctionPrototype()
237 {
238     auto vm = engine_->GetEcmaVm();
239     LocalScope scope(vm);
240     Global<FunctionRef> func = value_;
241     Local<JSValueRef> prototype = func->GetFunctionPrototype(vm);
242     return ArkNativeEngine::ArkValueToNativeValue(engine_, prototype);
243 }
244