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