• 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_object.h"
17 
18 #include "native_engine/native_property.h"
19 #include "v8_headers.h"
20 #include "v8_native_array.h"
21 #include "v8_native_function.h"
22 #include "v8_native_reference.h"
23 
V8NativeObject(V8NativeEngine * engine)24 V8NativeObject::V8NativeObject(V8NativeEngine* engine) : V8NativeObject(engine, v8::Object::New(engine->GetIsolate()))
25 {
26 }
27 
V8NativeObject(V8NativeEngine * engine,v8::Local<v8::Value> value)28 V8NativeObject::V8NativeObject(V8NativeEngine* engine, v8::Local<v8::Value> value) : V8NativeValue(engine, value) {}
29 
~V8NativeObject()30 V8NativeObject::~V8NativeObject() {}
31 
GetInterface(int interfaceId)32 void* V8NativeObject::GetInterface(int interfaceId)
33 {
34     return (NativeObject::INTERFACE_ID == interfaceId) ? (NativeObject*)this : nullptr;
35 }
36 
ConvertToNativeBindingObject(void * engine,DetachCallback detach,AttachCallback attach,void * object,void * hint)37 bool V8NativeObject::ConvertToNativeBindingObject(
38     void* engine, DetachCallback detach, AttachCallback attach, void *object, void *hint)
39 {
40     return false;
41 }
42 
SetNativePointer(void * pointer,NativeFinalize cb,void * hint,NativeReference ** reference,size_t nativeBindingSize)43 void V8NativeObject::SetNativePointer(void* pointer, NativeFinalize cb, void* hint, NativeReference** reference,
44     [[maybe_unused]] size_t nativeBindingSize)
45 {
46     v8::Local<v8::Object> value = value_;
47     v8::Local<v8::String> key = v8::String::NewFromUtf8(engine_->GetIsolate(), "_napiwrapper").ToLocalChecked();
48     bool has = value->Has(engine_->GetContext(), key).FromJust();
49     auto context = engine_->GetContext();
50     if (has && pointer == nullptr) {
51         v8::Local<v8::External> val = value->Get(context, key).ToLocalChecked().As<v8::External>();
52         value->Delete(context, key).FromJust();
53         auto ref = reinterpret_cast<V8NativeReference*>(val->Value());
54         delete ref;
55     } else {
56         void* ref = new V8NativeReference(engine_, this, 0, true, cb, pointer, hint);
57         v8::Local<v8::External> val = v8::External::New(engine_->GetIsolate(), ref);
58         value->Set(context, key, val).FromJust();
59     }
60 }
61 
GetNativePointer()62 void* V8NativeObject::GetNativePointer()
63 {
64     v8::Local<v8::Object> value = value_;
65     v8::Local<v8::String> key = v8::String::NewFromUtf8(engine_->GetIsolate(), "_napiwrapper").ToLocalChecked();
66     v8::Local<v8::Value> val = value->Get(engine_->GetContext(), key).ToLocalChecked();
67     void* result = nullptr;
68     if (val->IsExternal()) {
69         v8::Local<v8::External> ext = val.As<v8::External>();
70         auto ref = reinterpret_cast<V8NativeReference*>(ext->Value());
71         result = ref->GetData();
72     }
73     return result;
74 }
75 
SetNativeBindingPointer(void * enginePointer,void * objPointer,void * hint,void * detachData,void * attachData)76 void V8NativeObject::SetNativeBindingPointer(
77     void* enginePointer, void* objPointer, void* hint, void* detachData, void* attachData)
78 {
79 }
80 
GetNativeBindingPointer(uint32_t index)81 void* V8NativeObject::GetNativeBindingPointer(uint32_t index)
82 {
83     return nullptr;
84 }
85 
GetPropertyNames()86 NativeValue* V8NativeObject::GetPropertyNames()
87 {
88     v8::Local<v8::Object> val = value_;
89     v8::Local<v8::Array> arrayVal =
90         val->GetPropertyNames(
91             engine_->GetContext(), v8::KeyCollectionMode::kIncludePrototypes,
92             static_cast<v8::PropertyFilter>(v8::PropertyFilter::ONLY_ENUMERABLE | v8::PropertyFilter::SKIP_SYMBOLS),
93             v8::IndexFilter::kIncludeIndices, v8::KeyConversionMode::kConvertToString).ToLocalChecked();
94 
95     return new V8NativeArray(engine_, arrayVal);
96 }
97 
GetEnumerablePropertyNames()98 NativeValue* V8NativeObject::GetEnumerablePropertyNames()
99 {
100     return nullptr;
101 }
102 
GetPrototype()103 NativeValue* V8NativeObject::GetPrototype()
104 {
105     v8::Local<v8::Object> obj = value_;
106 
107     v8::Local<v8::Value> val = obj->GetPrototype();
108     return V8NativeEngine::V8ValueToNativeValue(engine_, val);
109 }
110 
DefineProperty(NativePropertyDescriptor propertyDescriptor)111 bool V8NativeObject::DefineProperty(NativePropertyDescriptor propertyDescriptor)
112 {
113     v8::Local<v8::Object> obj = value_;
114 
115     bool result = false;
116 
117     v8::Local<v8::Name> propertyName =
118         v8::String::NewFromUtf8(engine_->GetIsolate(), propertyDescriptor.utf8name, v8::NewStringType::kNormal)
119             .ToLocalChecked();
120 
121     if (propertyDescriptor.getter != nullptr || propertyDescriptor.setter != nullptr) {
122         v8::Local<v8::Value> localGetter;
123         v8::Local<v8::Value> localSetter;
124 
125         if (propertyDescriptor.getter != nullptr) {
126             NativeValue* getter =
127                 new V8NativeFunction(engine_, "getter", 0, propertyDescriptor.getter, propertyDescriptor.data);
128             if (getter != nullptr) {
129                 localGetter = *getter;
130             }
131         }
132         if (propertyDescriptor.setter != nullptr) {
133             NativeValue* setter =
134                 new V8NativeFunction(engine_, "setter", 0, propertyDescriptor.setter, propertyDescriptor.data);
135             if (setter != nullptr) {
136                 localSetter = *setter;
137             }
138         }
139 
140         v8::PropertyDescriptor descriptor(localGetter, localSetter);
141         descriptor.set_enumerable((propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0);
142         descriptor.set_configurable((propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0);
143 
144         result = obj->DefineProperty(engine_->GetContext(), propertyName, descriptor).FromMaybe(false);
145     } else if (propertyDescriptor.method != nullptr) {
146         NativeValue* cb = new V8NativeFunction(engine_, propertyDescriptor.utf8name, 0, propertyDescriptor.method,
147                                                propertyDescriptor.data);
148         if (cb != nullptr) {
149             v8::PropertyDescriptor descriptor(*cb, (propertyDescriptor.attributes & NATIVE_WRITABLE) != 0);
150             descriptor.set_enumerable((propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0);
151             descriptor.set_configurable((propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0);
152             result = obj->DefineProperty(engine_->GetContext(), propertyName, descriptor).FromMaybe(false);
153         }
154     } else {
155         v8::Local<v8::Value> value = *(propertyDescriptor.value);
156 
157         v8::PropertyDescriptor descriptor(value, (propertyDescriptor.attributes & NATIVE_WRITABLE) != 0);
158         descriptor.set_enumerable((propertyDescriptor.attributes & NATIVE_ENUMERABLE) != 0);
159         descriptor.set_configurable((propertyDescriptor.attributes & NATIVE_CONFIGURABLE) != 0);
160 
161         result = obj->DefineProperty(engine_->GetContext(), propertyName, descriptor).FromMaybe(false);
162     }
163     return result;
164 }
165 
SetProperty(NativeValue * key,NativeValue * value)166 bool V8NativeObject::SetProperty(NativeValue* key, NativeValue* value)
167 {
168     v8::Local<v8::Object> obj = value_;
169 
170     v8::Local<v8::Value> k = *key;
171     v8::Local<v8::Value> val = *value;
172 
173     v8::Maybe<bool> setMaybe = obj->Set(engine_->GetContext(), k, val);
174 
175     return setMaybe.FromMaybe(false);
176 }
177 
GetProperty(NativeValue * key)178 NativeValue* V8NativeObject::GetProperty(NativeValue* key)
179 {
180     v8::Local<v8::Value> k = *key;
181     v8::Local<v8::Object> obj = value_;
182 
183     auto getMaybe = obj->Get(engine_->GetContext(), k);
184     v8::Local<v8::Value> val = getMaybe.ToLocalChecked();
185     return V8NativeEngine::V8ValueToNativeValue(engine_, val);
186 }
187 
HasProperty(NativeValue * key)188 bool V8NativeObject::HasProperty(NativeValue* key)
189 {
190     v8::Local<v8::Object> obj = value_;
191     v8::Local<v8::Value> k = *key;
192 
193     v8::Maybe<bool> hasMaybe = obj->Has(engine_->GetContext(), k);
194 
195     return hasMaybe.FromMaybe(false);
196 }
197 
DeleteProperty(NativeValue * key)198 bool V8NativeObject::DeleteProperty(NativeValue* key)
199 {
200     v8::Local<v8::Value> k = *key;
201     v8::Local<v8::Object> obj = value_;
202 
203     v8::Maybe<bool> deleteMaybe = obj->Delete(engine_->GetContext(), k);
204 
205     return deleteMaybe.FromMaybe(false);
206 }
207 
SetProperty(const char * name,NativeValue * value)208 bool V8NativeObject::SetProperty(const char* name, NativeValue* value)
209 {
210     v8::Local<v8::Object> obj = value_;
211 
212     v8::Local<v8::Name> key = v8::String::NewFromUtf8(engine_->GetIsolate(), name).ToLocalChecked();
213 
214     v8::Local<v8::Value> val = *value;
215 
216     v8::Maybe<bool> setMaybe = obj->Set(engine_->GetContext(), key, val);
217 
218     return setMaybe.FromMaybe(false);
219 }
220 
GetProperty(const char * name)221 NativeValue* V8NativeObject::GetProperty(const char* name)
222 {
223     v8::Local<v8::Name> key = v8::String::NewFromUtf8(engine_->GetIsolate(), name).ToLocalChecked();
224     v8::Local<v8::Object> obj = value_;
225 
226     auto getMaybe = obj->Get(engine_->GetContext(), key);
227 
228     v8::Local<v8::Value> val = getMaybe.ToLocalChecked();
229 
230     return V8NativeEngine::V8ValueToNativeValue(engine_, val);
231 }
232 
HasProperty(const char * name)233 bool V8NativeObject::HasProperty(const char* name)
234 {
235     v8::Local<v8::Name> key = v8::String::NewFromUtf8(engine_->GetIsolate(), name).ToLocalChecked();
236     v8::Local<v8::Object> obj = value_;
237 
238     v8::Maybe<bool> hasMaybe = obj->Has(engine_->GetContext(), key);
239     return hasMaybe.FromMaybe(false);
240 }
241 
DeleteProperty(const char * name)242 bool V8NativeObject::DeleteProperty(const char* name)
243 {
244     v8::Local<v8::Name> key = v8::String::NewFromUtf8(engine_->GetIsolate(), name).ToLocalChecked();
245     v8::Local<v8::Object> obj = value_;
246 
247     v8::Maybe<bool> deleteMaybe = obj->Delete(engine_->GetContext(), key);
248 
249     return deleteMaybe.FromMaybe(false);
250 }
251 
SetPrivateProperty(const char * name,NativeValue * value)252 bool V8NativeObject::SetPrivateProperty(const char* name, NativeValue* value)
253 {
254     v8::Local<v8::String> key = v8::String::NewFromUtf8(engine_->GetIsolate(), name).ToLocalChecked();
255     v8::Local<v8::Value> val = *value;
256     v8::Local<v8::Object> obj = value_;
257 
258     v8::Maybe<bool> setMaybe =
259         obj->SetPrivate(engine_->GetContext(), v8::Private::New(engine_->GetIsolate(), key), val);
260 
261     return setMaybe.FromMaybe(false);
262 }
263 
GetPrivateProperty(const char * name)264 NativeValue* V8NativeObject::GetPrivateProperty(const char* name)
265 {
266     v8::Local<v8::String> key = v8::String::NewFromUtf8(engine_->GetIsolate(), name).ToLocalChecked();
267     v8::Local<v8::Object> obj = value_;
268 
269     auto getMaybe = obj->GetPrivate(engine_->GetContext(), v8::Private::New(engine_->GetIsolate(), key));
270     v8::Local<v8::Value> val = getMaybe.ToLocalChecked();
271 
272     return V8NativeEngine::V8ValueToNativeValue(engine_, val);
273 }
274 
HasPrivateProperty(const char * name)275 bool V8NativeObject::HasPrivateProperty(const char* name)
276 {
277     v8::Local<v8::String> key = v8::String::NewFromUtf8(engine_->GetIsolate(), name).ToLocalChecked();
278     v8::Local<v8::Object> obj = value_;
279 
280     v8::Maybe<bool> hasMaybe = obj->HasPrivate(engine_->GetContext(), v8::Private::New(engine_->GetIsolate(), key));
281 
282     return hasMaybe.FromMaybe(false);
283 }
284 
DeletePrivateProperty(const char * name)285 bool V8NativeObject::DeletePrivateProperty(const char* name)
286 {
287     v8::Local<v8::String> key = v8::String::NewFromUtf8(engine_->GetIsolate(), name).ToLocalChecked();
288     v8::Local<v8::Object> obj = value_;
289 
290     v8::Maybe<bool> deleteMaybe =
291         obj->DeletePrivate(engine_->GetContext(), v8::Private::New(engine_->GetIsolate(), key));
292 
293     return deleteMaybe.FromMaybe(false);
294 }
295