• 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 "v8_native_function.h"
17 
18 #include "utils/log.h"
19 
V8NativeFunction(V8NativeEngine * engine,v8::Local<v8::Value> value)20 V8NativeFunction::V8NativeFunction(V8NativeEngine* engine, v8::Local<v8::Value> value) : V8NativeObject(engine, value)
21 {
22 }
23 
V8NativeFunction(V8NativeEngine * engine,const char * name,size_t length,NativeCallback cb,void * value)24 V8NativeFunction::V8NativeFunction(V8NativeEngine* engine,
25                                    const char* name,
26                                    size_t length,
27                                    NativeCallback cb,
28                                    void* value)
29     : V8NativeFunction(engine, v8::Local<v8::Value>())
30 {
31     auto context = engine->GetContext();
32     auto isolate = engine->GetIsolate();
33     v8::Local<v8::Array> cbdata = v8::Array::New(isolate);
34 
35     int32_t index = 0;
36     cbdata->Set(context, index++, v8::External::New(isolate, (void*)engine)).FromJust();
37     cbdata->Set(context, index++, v8::External::New(isolate, (void*)cb)).FromJust();
38     cbdata->Set(context, index, v8::External::New(isolate, value)).FromJust();
39 
40     v8::Local<v8::Function> fn =
41         v8::Function::New(context, NativeFunctionCallback, cbdata).ToLocalChecked();
42 
43     v8::Local<v8::String> fnName = v8::String::NewFromUtf8(isolate, name).ToLocalChecked();
44 
45     fn->SetName(fnName);
46 
47     value_ = fn;
48 }
49 
~V8NativeFunction()50 V8NativeFunction::~V8NativeFunction() {}
51 
GetInterface(int interfaceId)52 void* V8NativeFunction::GetInterface(int interfaceId)
53 {
54     return (NativeFunction::INTERFACE_ID == interfaceId) ? (NativeFunction*)this
55                                                          : V8NativeObject::GetInterface(interfaceId);
56 }
57 
NativeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value> & info)58 void V8NativeFunction::NativeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
59 {
60     v8::Isolate::Scope isolateScope(info.GetIsolate());
61     v8::HandleScope handleScope(info.GetIsolate());
62     v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
63     v8::Local<v8::Array> cbdata = info.Data().As<v8::Array>();
64 
65     int32_t index = 0;
66     V8NativeEngine* engine =
67         (V8NativeEngine*)cbdata->Get(context, index++).ToLocalChecked().As<v8::External>()->Value();
68     if (engine == nullptr) {
69         HILOG_ERROR("engine is nullptr");
70         return;
71     }
72     NativeCallback cb = (NativeCallback)cbdata->Get(context, index++).ToLocalChecked().As<v8::External>()->Value();
73     void* data = cbdata->Get(context, index).ToLocalChecked().As<v8::External>()->Value();
74 
75     auto funcinfo = new NativeFunctionInfo();
76     if (funcinfo == nullptr) {
77         HILOG_ERROR("create native function info failed");
78         return;
79     }
80 
81     funcinfo->engine = engine;
82     funcinfo->callback = cb;
83     funcinfo->data = data;
84 
85     NativeScopeManager* scopeManager = engine->GetScopeManager();
86     if (scopeManager == nullptr) {
87         HILOG_ERROR("Get scope manager failed");
88         delete funcinfo;
89         return;
90     }
91     NativeScope* scope = scopeManager->Open();
92     if (scope == nullptr) {
93         HILOG_ERROR("Open scope failed");
94         delete funcinfo;
95         return;
96     }
97 
98     NativeCallbackInfo cbinfo = { 0 };
99     cbinfo.thisVar = V8NativeEngine::V8ValueToNativeValue(engine, info.This());
100     cbinfo.function = V8NativeEngine::V8ValueToNativeValue(engine, info.NewTarget());
101     cbinfo.argc = info.Length();
102     cbinfo.argv = nullptr;
103     cbinfo.functionInfo = funcinfo;
104     if (cbinfo.argc > 0) {
105         cbinfo.argv = new NativeValue* [cbinfo.argc];
106         for (size_t i = 0; i < cbinfo.argc && cbinfo.argv != nullptr; i++) {
107             cbinfo.argv[i] = V8NativeEngine::V8ValueToNativeValue(engine, info[i]);
108         }
109     }
110 
111     NativeValue* result = nullptr;
112     if (cb != nullptr) {
113         result = cb(engine, &cbinfo);
114     }
115 
116     if (cbinfo.argv != nullptr) {
117         delete []cbinfo.argv;
118     }
119     delete funcinfo;
120 
121     v8::Local<v8::Value> v8Result;
122     if (result == nullptr) {
123         if (engine->IsExceptionPending()) {
124             NativeValue* error = engine->GetAndClearLastException();
125             if (error != nullptr) {
126                 v8Result = *error;
127             }
128         } else {
129             v8Result = v8::Undefined(engine->GetIsolate());
130         }
131     } else {
132         v8Result = *result;
133     }
134 
135     info.GetReturnValue().Set<v8::Value>(v8Result);
136     scopeManager->Close(scope);
137 }
138