Ocean
Loading...
Searching...
No Matches
JSBase.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_INTERACTION_JS_BASE_H
9#define META_OCEAN_INTERACTION_JS_BASE_H
10
14
15#include "ocean/io/File.h"
17
18#include <v8.h>
19
20namespace Ocean
21{
22
23namespace Interaction
24{
25
26namespace JavaScript
27{
28
29/**
30 * This class implements the base class for all JavaScript wrappers.
31 * @ingroup interactionjs
32 */
33class OCEAN_INTERACTION_JS_EXPORT JSBase
34{
35 public:
36
37 /**
38 * Returns the std string of a given JavaScript string object.
39 * @param value JavaScript value holding a string
40 * @return Readable string value
41 */
42 static std::string toAString(const v8::Local<v8::String>& value);
43
44 /**
45 * Returns the std string of a given JavaScript string object.
46 * @param value JavaScript value holding a string
47 * @return Readable string value
48 */
49 static std::string toAString(v8::MaybeLocal<v8::String> value);
50
51 /**
52 * Creates a JavaScript string object from a given std string.
53 * @param value The string for which the JavaScript object will be created
54 * @param isolate The current v8 isolate, must be valid
55 * @return The JavaScript string object
56 */
57 static inline v8::Local<v8::String> newString(const std::string& value, v8::Isolate* isolate);
58
59 /**
60 * Creates a JavaScript string object from a given std string.
61 * @param value The string for which the JavaScript object will be created
62 * @param isolate The current v8 isolate, must be valid
63 * @return The JavaScript string object
64 */
65 static inline v8::Local<v8::String> newString(const char* value, v8::Isolate* isolate);
66
67 protected:
68
69 /**
70 * Creates an JavaScript array value for a given C++ array.
71 * @param values The C++ array for which the JavaScript value will be created
72 * @param context The current JavaScript context
73 * @return The resulting JavaScript value
74 * @tparam TNative The native C++ data type of all array elements
75 */
76 template <typename TNative>
77 static inline v8::Local<v8::Value> createValues(const std::vector<TNative>& values, const v8::Local<v8::Context>& context);
78
79 /**
80 * Creates an JavaScript array value for a given C++ array.
81 * @param values The C++ array for which the JavaScript value will be created
82 * @param size The number of elements int he array, with range [0, infinity)
83 * @param context The current JavaScript context
84 * @return The resulting JavaScript value
85 * @tparam TNative The native C++ data type of all array elements
86 */
87 template <typename TNative>
88 static v8::Local<v8::Value> createValues(const TNative* values, const size_t size, const v8::Local<v8::Context>& context);
89
90 /**
91 * Creates an JavaScript value for a given C++ wrapper object.
92 * @param value The C++ wrapper object for which the JavaScript value will be created, will be moved
93 * @param context The current JavaScript context
94 * @return The resulting JavaScript value
95 * @tparam T The data type of the C++ wrapper object
96 */
97 template <typename T>
98 static v8::Local<v8::Value> createObject(typename T::NativeType&& value, const v8::Local<v8::Context>& context);
99
100 /**
101 * Creates an JavaScript value for a given C++ wrapper object.
102 * @param value The C++ wrapper object for which the JavaScript value will be created
103 * @param context The current JavaScript context
104 * @return The resulting JavaScript value
105 * @tparam T The data type of the C++ wrapper object
106 */
107 template <typename T>
108 static v8::Local<v8::Value> createObject(const typename T::NativeType& value, const v8::Local<v8::Context>& context);
109
110 /**
111 * Creates an JavaScript array value for given C++ wrapper objects.
112 * @param values The C++ wrapper objects for which the JavaScript value will be created
113 * @param context The current JavaScript context
114 * @return The resulting JavaScript value
115 * @tparam T The data type of the C++ wrapper object
116 */
117 template <typename T>
118 static v8::Local<v8::Array> createObjects(const std::vector<typename T::NativeType>& values, const v8::Local<v8::Context>& context);
119
120 /**
121 * Returns whether a JavaScript function call holds a specific native type as parameter.
122 * @param info The function callback info
123 * @param index The index of the function parameter, with range [0, infinity)
124 * @param value The resulting native value of the JavaScript value in case the parameter exists
125 * @return True, if the function has at least `index + 1 parameters and if the parameter type fits with `TNative`
126 * @tparam TNative The data type of the native C++ wrapper object
127 */
128 template <typename TNative>
129 static bool hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, TNative& value);
130
131 /**
132 * Returns whether a JavaScript function call holds a specific native type as parameter.
133 * @param info The function callback info
134 * @param index The index of the function parameter, with range [0, infinity)
135 * @param value The resulting native value of the JavaScript value in case the parameter exists
136 * @return True, if the function has at least `index + 1 parameters and if the parameter type fits with `TNative`
137 * @tparam TNative The data type of the native C++ wrapper object
138 */
139 template <typename TNative>
140 static bool hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<TNative>& value);
141
142 /**
143 * Returns whether a JavaScript function call holds a sequence of specific native type as parameters.
144 * @param info The function callback info
145 * @param startIndex The start index of the function parameter to be checked, with range [0, infinity)
146 * @param endIndex The end index (exclusive) of the function parameter to be checked, with range [startIndex + 1, infinity)
147 * @param values The resulting native values of the JavaScript value in case several consecutive parameter exist
148 * @return The number of consecutive values with native data type `TNative`, with range [0, endIndex - startIndex]
149 * @tparam TNative The data type of the native C++ wrapper object
150 */
151 template <typename TNative>
152 static unsigned int hasValues(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int startIndex, const unsigned int endIndex, TNative* values);
153
154 /**
155 * Returns whether a JavaScript value wraps a specified native type.
156 * @param localValue The JavaScript value to check
157 * @param value The resulting native value of the JavaScript value in case the parameter exists
158 * @tparam TNative The data type of the native C++ wrapper object
159 * @return True, if the function has at least `index + 1 parameters and if the parameter type fits with `TNative`
160 */
161 template <typename TNative>
162 static bool isValue(v8::Local<v8::Value> localValue, TNative& value);
163
164 /**
165 * The callback function for all JavaScript constructors of wrapped C++ objects.
166 * @param info The function callback info
167 * @tparam TNative The data type of the native C++ wrapper object
168 */
169 template <typename TNative>
170 static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info);
171
172 /**
173 * The specialized callback function for all JavaScript constructors of wrapped C++ objects.
174 * @param thisValue The wrapped native C++ object which can be changed in the constructor
175 * @param info The function callback info
176 * @tparam TNative The data type of the native C++ wrapper object
177 */
178 template <typename TNative>
179 static void constructor(TNative& thisValue, const v8::FunctionCallbackInfo<v8::Value>& info);
180
181 /**
182 * The callback function for all JavaScript getters of wrapped C++ objects.
183 * @param property The property of the getter
184 * @param info The function callback info
185 * @tparam T The data type of the C++ wrapper object
186 * @tparam tGetterId The unique id of the getter, unique in combination with `T`
187 */
188 template <typename T, unsigned int tGetterId>
189 static inline void propertyGetter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info);
190
191 /**
192 * The specialized callback function for all JavaScript getters of wrapped C++ objects.
193 * This function will be template-specialized in the individual wrapper classes.
194 * @param thisValue The wrapped native C++ object
195 * @param property The property of the getter
196 * @param info The function callback info
197 * @tparam TNative The data type of the native C++ wrapper object
198 * @tparam tGetterId The unique id of the getter
199 */
200 template <typename TNative, unsigned int tGetterId>
201 static void propertyGetter(TNative& thisValue, v8::Local<v8::Name>& property, const v8::PropertyCallbackInfo<v8::Value>& info);
202
203 /**
204 * The callback function for all JavaScript setters of wrapped C++ objects.
205 * @param property The property of the setter
206 * @param value The value to be set
207 * @param info The function callback info
208 * @tparam T The data type of the C++ wrapper object
209 * @tparam tSetterId The unique id of the setter, unique in combination with `T`
210 */
211 template <typename T, unsigned int tSetterId>
212 static inline void propertySetter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info);
213
214 /**
215 * The specialized callback function for all JavaScript setters of wrapped C++ objects.
216 * This function will be template-specialized in the individual wrapper classes.
217 * @param thisValue The wrapped native C++ object
218 * @param property The property of the setter
219 * @param value The value to be set
220 * @param info The function callback info
221 * @tparam TNative The data type of the native C++ wrapper object
222 * @tparam tSetterId The unique id of the setter
223 */
224 template <typename TNative, unsigned int tSetterId>
225 static void propertySetter(TNative& thisValue, v8::Local<v8::Name>& property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info);
226
227 /**
228 * The callback function for all JavaScript functions of wrapped C++ objects.
229 * @param info The function callback info
230 * @tparam T The data type of the C++ wrapper object
231 * @tparam tFunctionId The unique id of the function, unique in combination with `T`
232 */
233 template <typename T, unsigned int tFunctionId>
234 static inline void function(const v8::FunctionCallbackInfo<v8::Value>& info);
235
236 /**
237 * The specialized callback function for all JavaScript functions of wrapped C++ objects.
238 * This function will be template-specialized in the individual wrapper classes.
239 * @param thisValue The wrapped native C++ object
240 * @param info The function callback info
241 * @tparam TNative The data type of the native C++ wrapper object
242 * @tparam tFunctionId The unique id of the function
243 */
244 template <typename T, unsigned int tFunctionId>
245 static void function(T& thisValue, const v8::FunctionCallbackInfo<v8::Value>& info);
246};
247
248template <>
249inline v8::Local<v8::Value> JSBase::createValues(const std::vector<bool>& values, const v8::Local<v8::Context>& context)
250{
251 v8::Isolate* isolate = v8::Isolate::GetCurrent();
252
253 v8::Local<v8::Array> result = v8::Array::New(isolate, int(values.size()));
254
255 for (size_t n = 0; n < values.size(); ++n)
256 {
257 if (!result->Set(context, v8::Int32::New(isolate, int(n)), v8::Boolean::New(isolate, values[n])).IsJust())
258 {
259 ocean_assert(false && "Invalid value!");
260 }
261 }
262
263 return result;
264}
265
266template <typename TNative>
267v8::Local<v8::Value> JSBase::createValues(const std::vector<TNative>& values, const v8::Local<v8::Context>& context)
268{
269 return createValues<TNative>(values.data(), values.size(), context);
270}
271
272template <>
273inline v8::Local<v8::Value> JSBase::createValues(const int* values, const size_t size, const v8::Local<v8::Context>& context)
274{
275 v8::Isolate* isolate = v8::Isolate::GetCurrent();
276
277 v8::Local<v8::Array> result = v8::Array::New(isolate, int(size));
278
279 for (size_t n = 0; n < size; ++n)
280 {
281 if (!result->Set(context, v8::Int32::New(isolate, int(n)), v8::Int32::New(isolate, values[n])).IsJust())
282 {
283 ocean_assert(false && "Invalid value!");
284 }
285 }
286
287 return result;
288}
289
290template <>
291inline v8::Local<v8::Value> JSBase::createValues(const float* values, const size_t size, const v8::Local<v8::Context>& context)
292{
293 v8::Isolate* isolate = v8::Isolate::GetCurrent();
294
295 v8::Local<v8::Array> result = v8::Array::New(isolate, int(size));
296
297 for (size_t n = 0; n < size; ++n)
298 {
299 if (!result->Set(context, v8::Int32::New(isolate, int(n)), v8::Number::New(isolate, double(values[n]))).IsJust())
300 {
301 ocean_assert(false && "Invalid value!");
302 }
303 }
304
305 return result;
306}
307
308template <>
309inline v8::Local<v8::Value> JSBase::createValues(const double* values, const size_t size, const v8::Local<v8::Context>& context)
310{
311 v8::Isolate* isolate = v8::Isolate::GetCurrent();
312
313 v8::Local<v8::Array> result = v8::Array::New(isolate, int(size));
314
315 for (size_t n = 0; n < size; ++n)
316 {
317 if (!result->Set(context, v8::Int32::New(isolate, int(n)), v8::Number::New(isolate, values[n])).IsJust())
318 {
319 ocean_assert(false && "Invalid value!");
320 }
321 }
322
323 return result;
324}
325
326template <>
327inline v8::Local<v8::Value> JSBase::createValues(const std::string* values, const size_t size, const v8::Local<v8::Context>& context)
328{
329 v8::Isolate* isolate = v8::Isolate::GetCurrent();
330
331 v8::Local<v8::Array> result = v8::Array::New(isolate, int(size));
332
333 for (size_t n = 0; n < size; ++n)
334 {
335 if (!result->Set(context, v8::Int32::New(isolate, int(n)), newString(values[n], isolate)).IsJust())
336 {
337 ocean_assert(false && "Invalid value!");
338 }
339 }
340
341 return result;
342}
343
344template <typename TNative>
345inline v8::Local<v8::Value> JSBase::createValues(const TNative* values, const size_t size, const v8::Local<v8::Context>& context)
346{
347 static_assert(oceanFalse<TNative>(), "This function is not defined for the data type");
348}
349
350template <typename T>
351v8::Local<v8::Value> JSBase::createObject(typename T::NativeType&& value, const v8::Local<v8::Context>& context)
352{
353 v8::MaybeLocal<v8::Object> maybeResult(T::objectTemplate()->NewInstance(context));
354
355 if (maybeResult.IsEmpty())
356 {
357 ocean_assert(false && "Invalid object!");
358 return v8::Local<v8::Value>();
359 }
360
361 v8::Isolate* isolate = v8::Isolate::GetCurrent();
362
363 v8::Local<v8::Object> result(maybeResult.ToLocalChecked());
364
365 JSExternal* newExternal = JSExternal::create(new typename T::NativeType(std::move(value)), result, isolate);
366 result->SetInternalField(0, v8::External::New(isolate, newExternal, v8::kExternalPointerTypeTagDefault));
367
368 return result;
369}
370
371template <typename T>
372v8::Local<v8::Value> JSBase::createObject(const typename T::NativeType& value, const v8::Local<v8::Context>& context)
373{
374 v8::MaybeLocal<v8::Object> maybeResult(T::objectTemplate()->NewInstance(context));
375
376 if (maybeResult.IsEmpty())
377 {
378 ocean_assert(false && "Invalid object!");
379 return v8::Local<v8::Value>();
380 }
381
382 v8::Isolate* isolate = v8::Isolate::GetCurrent();
383
384 v8::Local<v8::Object> result(maybeResult.ToLocalChecked());
385
386 JSExternal* newExternal = JSExternal::create(new typename T::NativeType(value), result, isolate);
387 result->SetInternalField(0, v8::External::New(isolate, newExternal, v8::kExternalPointerTypeTagDefault));
388
389 return result;
390}
391
392template <typename T>
393v8::Local<v8::Array> JSBase::createObjects(const std::vector<typename T::NativeType>& values, const v8::Local<v8::Context>& context)
394{
395 v8::Isolate* isolate = v8::Isolate::GetCurrent();
396
397 v8::Local<v8::Array> result = v8::Array::New(isolate, int(values.size()));
398
399 for (size_t n = 0; n < values.size(); ++n)
400 {
401 if (!result->Set(context, v8::Int32::New(isolate, int(n)), JSBase::createObject<T>(values[n], context)).IsJust())
402 {
403 ocean_assert(false && "Invalid value!");
404 }
405 }
406
407 return result;
408}
409
410inline v8::Local<v8::String> JSBase::newString(const std::string& value, v8::Isolate* isolate)
411{
412 ocean_assert(isolate != nullptr);
413
414 if (value.empty())
415 {
416 return v8::Local<v8::String>();
417 }
418
419 v8::MaybeLocal<v8::String> maybeString = v8::String::NewFromUtf8(isolate, value.c_str());
420 ocean_assert(!maybeString.IsEmpty());
421
422 return maybeString.ToLocalChecked();
423}
424
425inline v8::Local<v8::String> JSBase::newString(const char* value, v8::Isolate* isolate)
426{
427 ocean_assert(isolate != nullptr);
428
429 if (value == nullptr)
430 {
431 return v8::Local<v8::String>();
432 }
433
434 v8::MaybeLocal<v8::String> maybeString = v8::String::NewFromUtf8(isolate, value);
435 ocean_assert(!maybeString.IsEmpty());
436
437 return maybeString.ToLocalChecked();
438}
439
440template <typename TNative>
441inline void JSBase::constructor(const v8::FunctionCallbackInfo<v8::Value>& info)
442{
443 ocean_assert(info.This()->InternalFieldCount() == 1);
444
445 TNative* newValue = new TNative();
446
447 constructor<TNative>(*newValue, info);
448
449 v8::Isolate* isolate = v8::Isolate::GetCurrent();
450
451 v8::Local<v8::Object> ob = info.This();
452 JSExternal* newExternal = JSExternal::create(newValue, ob, isolate);
453
454 info.This()->SetInternalField(0, v8::External::New(isolate, newExternal, v8::kExternalPointerTypeTagDefault));
455 info.GetReturnValue().Set(info.This());
456}
457
458template <typename T, unsigned int tFunctionId>
459inline void JSBase::propertyGetter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info)
460{
461 ocean_assert(info.HolderV2()->InternalFieldCount() == 1);
462 v8::Local<v8::Data> internalField = info.HolderV2()->GetInternalField(0);
463 v8::Local<v8::Value> valueField = v8::Local<v8::Value>::Cast(internalField);
464 const v8::Local<v8::External> thisWrapper = v8::Local<v8::External>::Cast(valueField);
465
466 JSExternal* thisExternal = static_cast<JSExternal*>(thisWrapper->Value(v8::kExternalPointerTypeTagDefault));
467 ocean_assert(thisExternal->type() == JSExternal::type<T>());
468
469 propertyGetter<T, tFunctionId>(thisExternal->value<T>(), property, info);
470}
471
472template <typename T, unsigned int tFunctionId>
473inline void JSBase::propertySetter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
474{
475 ocean_assert(value.IsEmpty() == false);
476 ocean_assert(info.HolderV2()->InternalFieldCount() == 1);
477
478 v8::Local<v8::Data> internalField = info.HolderV2()->GetInternalField(0);
479 v8::Local<v8::Value> valueField = v8::Local<v8::Value>::Cast(internalField);
480 const v8::Local<v8::External> thisWrapper = v8::Local<v8::External>::Cast(valueField);
481
482 JSExternal* thisExternal = static_cast<JSExternal*>(thisWrapper->Value(v8::kExternalPointerTypeTagDefault));
483 ocean_assert(thisExternal->type() == JSExternal::type<T>());
484
485 propertySetter<T, tFunctionId>(thisExternal->value<T>(), property, value, info);
486}
487
488template <typename T, unsigned int tFunctionId>
489inline void JSBase::function(const v8::FunctionCallbackInfo<v8::Value>& info)
490{
491 ocean_assert(info.This()->InternalFieldCount() == 1);
492 v8::Local<v8::Data> internalField = info.This()->GetInternalField(0);
493 v8::Local<v8::Value> valueField = v8::Local<v8::Value>::Cast(internalField);
494 v8::Local<v8::External> thisWrapper = v8::Local<v8::External>::Cast(valueField);
495
496 JSExternal* thisExternal = static_cast<JSExternal*>(thisWrapper->Value(v8::kExternalPointerTypeTagDefault));
497 ocean_assert(thisExternal->type() == JSExternal::type<T>());
498
499 function<T, tFunctionId>(thisExternal->value<T>(), info);
500}
501
502template <>
503inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, bool& value)
504{
505 if (info.Length() >= int(index + 1u))
506 {
507 if (info[index]->IsBoolean())
508 {
509 value = info[index]->BooleanValue(v8::Isolate::GetCurrent());
510
511 return true;
512 }
513 }
514
515 return false;
516}
517
518template <>
519inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, int& value)
520{
521 if (info.Length() >= int(index + 1u))
522 {
523 if (info[index]->IsInt32())
524 {
525 value = info[index]->Int32Value(JSContext::currentContext()).FromJust();
526
527 return true;
528 }
529 }
530
531 return false;
532}
533
534template <>
535inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, double& value)
536{
537 if (info.Length() >= int(index + 1u))
538 {
539 if (info[index]->IsNumber())
540 {
541 value = info[index]->NumberValue(JSContext::currentContext()).FromJust();
542
543 return true;
544 }
545 }
546
547 return false;
548}
549
550template <>
551inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, float& value)
552{
553 if (info.Length() >= int(index + 1u))
554 {
555 if (info[index]->IsNumber())
556 {
557 value = float(info[index]->NumberValue(JSContext::currentContext()).FromJust());
558
559 return true;
560 }
561 }
562
563 return false;
564}
565
566template <>
567inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::string& value)
568{
569 if (info.Length() >= int(index + 1u))
570 {
571 if (info[index]->IsString())
572 {
573 value = toAString(info[index]->ToString(JSContext::currentContext()));
574
575 return true;
576 }
577 }
578
579 return false;
580}
581
582template <typename TNative>
583inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, TNative& value)
584{
585 if (info.Length() >= int(index + 1u))
586 {
587 JSExternal* externalParameter = JSExternal::external(info[index]);
588
589 if (externalParameter != nullptr && externalParameter->type() == JSExternal::type<TNative>())
590 {
591 value = externalParameter->value<TNative>();
592
593 return true;
594 }
595 }
596
597 return false;
598}
599
600template <>
601inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<bool>& value)
602{
603 if (info.Length() >= int(index + 1u))
604 {
605 if (info[index]->IsArray())
606 {
607 v8::Local<v8::Context> currentContext = JSContext::currentContext();
608 v8::Isolate* isolate = v8::Isolate::GetCurrent();
609
610 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
611
612 value.clear();
613 value.reserve(arrayValue->Length());
614
615 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
616 {
617 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
618
619 if (!element.IsEmpty() || !element.ToLocalChecked()->IsBoolean())
620 {
621 return false;
622 }
623
624 value.emplace_back(element.ToLocalChecked()->BooleanValue(isolate));
625 }
626
627 return true;
628 }
629 }
630
631 return false;
632}
633
634template <>
635inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<int>& value)
636{
637 if (info.Length() >= int(index + 1u))
638 {
639 if (info[index]->IsArray())
640 {
641 v8::Local<v8::Context> currentContext = JSContext::currentContext();
642
643 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
644
645 value.clear();
646 value.reserve(arrayValue->Length());
647
648 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
649 {
650 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
651
652 if (!element.IsEmpty() || !element.ToLocalChecked()->IsInt32())
653 {
654 return false;
655 }
656
657 value.emplace_back(element.ToLocalChecked()->Int32Value(currentContext).FromJust());
658 }
659
660 return true;
661 }
662 }
663
664 return false;
665}
666
667template <>
668inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<float>& value)
669{
670 if (info.Length() >= int(index + 1u))
671 {
672 if (info[index]->IsArray())
673 {
674 v8::Local<v8::Context> currentContext = JSContext::currentContext();
675
676 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
677
678 value.clear();
679 value.reserve(arrayValue->Length());
680
681 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
682 {
683 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
684
685 if (!element.IsEmpty() || !element.ToLocalChecked()->IsNumber())
686 {
687 return false;
688 }
689
690 value.emplace_back(float(element.ToLocalChecked()->NumberValue(currentContext).FromJust()));
691 }
692
693 return true;
694 }
695 }
696
697 return false;
698}
699
700template <>
701inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<double>& value)
702{
703 if (info.Length() >= int(index + 1u))
704 {
705 if (info[index]->IsArray())
706 {
707 v8::Local<v8::Context> currentContext = JSContext::currentContext();
708
709 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
710
711 value.clear();
712 value.reserve(arrayValue->Length());
713
714 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
715 {
716 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
717
718 if (!element.IsEmpty() || !element.ToLocalChecked()->IsNumber())
719 {
720 return false;
721 }
722
723 value.emplace_back(element.ToLocalChecked()->NumberValue(currentContext).FromJust());
724 }
725
726 return true;
727 }
728 }
729
730 return false;
731}
732
733template <>
734inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<Timestamp>& value)
735{
736 if (info.Length() >= int(index + 1u))
737 {
738 if (info[index]->IsArray())
739 {
740 v8::Local<v8::Context> currentContext = JSContext::currentContext();
741
742 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
743
744 value.clear();
745 value.reserve(arrayValue->Length());
746
747 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
748 {
749 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
750
751 if (!element.IsEmpty() || !element.ToLocalChecked()->IsNumber())
752 {
753 return false;
754 }
755
756 value.emplace_back(element.ToLocalChecked()->NumberValue(currentContext).FromJust());
757 }
758
759 return true;
760 }
761 }
762
763 return false;
764}
765
766template <>
767inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, Strings& value)
768{
769 if (info.Length() >= int(index + 1u))
770 {
771 if (info[index]->IsArray())
772 {
773 v8::Local<v8::Context> currentContext = JSContext::currentContext();
774
775 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
776
777 value.clear();
778 value.reserve(arrayValue->Length());
779
780 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
781 {
782 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
783
784 if (!element.IsEmpty() || !element.ToLocalChecked()->IsString())
785 {
786 return false;
787 }
788
789 value.emplace_back(toAString(element.ToLocalChecked()->ToString(currentContext)));
790 }
791
792 return true;
793 }
794 }
795
796 return false;
797}
798
799template <typename TNative>
800inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<TNative>& value)
801{
802 if (info.Length() >= int(index + 1u))
803 {
804 if (info[index]->IsArray())
805 {
806 v8::Local<v8::Context> currentContext = JSContext::currentContext();
807
808 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
809
810 value.clear();
811 value.reserve(arrayValue->Length());
812
813 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
814 {
815 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
816
817 if (!element.IsEmpty() || !element.ToLocalChecked()->IsObject())
818 {
819 return false;
820 }
821
822 value.emplace_back();
823 if (!JSBase::isValue<TNative>(element.ToLocalChecked(), value.back()))
824 {
825 return false;
826 }
827 }
828
829 return true;
830 }
831 }
832
833 return false;
834}
835
836template <>
837inline unsigned int JSBase::hasValues(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int startIndex, const unsigned int endIndex, double* values)
838{
839 ocean_assert(startIndex < endIndex);
840 ocean_assert(values != nullptr);
841
842 for (unsigned int index = startIndex; index < endIndex; ++index)
843 {
844 if (info.Length() >= int(index + 1u))
845 {
846 if (info[index]->IsNumber())
847 {
848 values[index - startIndex] = info[index]->NumberValue(JSContext::currentContext()).FromJust();
849 continue;
850 }
851 }
852
853 return index - startIndex;
854 }
855
856 return endIndex - startIndex;
857}
858
859template <>
860inline unsigned int JSBase::hasValues(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int startIndex, const unsigned int endIndex, float* values)
861{
862 ocean_assert(startIndex < endIndex);
863 ocean_assert(values != nullptr);
864
865 for (unsigned int index = startIndex; index < endIndex; ++index)
866 {
867 if (info.Length() >= int(index + 1u))
868 {
869 if (info[index]->IsNumber())
870 {
871 values[index - startIndex] = float(info[index]->NumberValue(JSContext::currentContext()).FromJust());
872 continue;
873 }
874 }
875
876 return index - startIndex;
877 }
878
879 return endIndex - startIndex;
880}
881
882template <typename TNative>
883inline unsigned int JSBase::hasValues(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int startIndex, const unsigned int endIndex, TNative* values)
884{
885 ocean_assert(startIndex < endIndex);
886 ocean_assert(values != nullptr);
887
888 for (unsigned int index = startIndex; index < endIndex; ++index)
889 {
890 if (info.Length() >= int(index + 1u))
891 {
892 if (JSBase::isValue<TNative>(info[index], values[index - startIndex]))
893 {
894 continue;
895 }
896 }
897
898 return index - startIndex;
899 }
900
901 return endIndex - startIndex;
902}
903
904template <>
905inline bool JSBase::isValue(v8::Local<v8::Value> localValue, bool& value)
906{
907 if (localValue->IsBoolean())
908 {
909
910 value = localValue->BooleanValue(v8::Isolate::GetCurrent());
911
912 return true;
913 }
914 else
915 {
916 return false;
917 }
918}
919
920template <>
921inline bool JSBase::isValue(v8::Local<v8::Value> localValue, double& value)
922{
923 if (localValue->IsNumber())
924 {
925 value = localValue->NumberValue(JSContext::currentContext()).FromJust();
926
927 return true;
928 }
929 else
930 {
931 return false;
932 }
933}
934
935template <>
936inline bool JSBase::isValue(v8::Local<v8::Value> localValue, float& value)
937{
938 if (localValue->IsNumber())
939 {
940 value = float(localValue->NumberValue(JSContext::currentContext()).FromJust());
941
942 return true;
943 }
944 else
945 {
946 return false;
947 }
948}
949
950template <>
951inline bool JSBase::isValue(v8::Local<v8::Value> localValue, std::string& value)
952{
953 if (localValue->IsString())
954 {
955 value = toAString(localValue->ToString(JSContext::currentContext()));
956
957 return true;
958 }
959 else
960 {
961 return false;
962 }
963}
964
965template <typename TNative>
966inline bool JSBase::isValue(v8::Local<v8::Value> localValue, TNative& value)
967{
968 JSExternal* externalParameter = JSExternal::external(localValue);
969
970 if (externalParameter != nullptr && externalParameter->type() == JSExternal::type<TNative>())
971 {
972 value = externalParameter->value<TNative>();
973
974 return true;
975 }
976
977 return false;
978}
979
980}
981
982}
983
984}
985
986#endif // META_OCEAN_INTERACTION_JS_BASE_H
This class implements the base class for all JavaScript wrappers.
Definition JSBase.h:34
static void function(T &thisValue, const v8::FunctionCallbackInfo< v8::Value > &info)
The specialized callback function for all JavaScript functions of wrapped C++ objects.
static v8::Local< v8::Value > createValues(const std::vector< TNative > &values, const v8::Local< v8::Context > &context)
Creates an JavaScript array value for a given C++ array.
Definition JSBase.h:267
static void propertyGetter(TNative &thisValue, v8::Local< v8::Name > &property, const v8::PropertyCallbackInfo< v8::Value > &info)
The specialized callback function for all JavaScript getters of wrapped C++ objects.
static bool isValue(v8::Local< v8::Value > localValue, TNative &value)
Returns whether a JavaScript value wraps a specified native type.
Definition JSBase.h:966
static v8::Local< v8::Value > createObject(typename T::NativeType &&value, const v8::Local< v8::Context > &context)
Creates an JavaScript value for a given C++ wrapper object.
Definition JSBase.h:351
static std::string toAString(v8::MaybeLocal< v8::String > value)
Returns the std string of a given JavaScript string object.
static v8::Local< v8::String > newString(const std::string &value, v8::Isolate *isolate)
Creates a JavaScript string object from a given std string.
Definition JSBase.h:410
static v8::Local< v8::Array > createObjects(const std::vector< typename T::NativeType > &values, const v8::Local< v8::Context > &context)
Creates an JavaScript array value for given C++ wrapper objects.
Definition JSBase.h:393
static void propertySetter(v8::Local< v8::Name > property, v8::Local< v8::Value > value, const v8::PropertyCallbackInfo< void > &info)
The callback function for all JavaScript setters of wrapped C++ objects.
Definition JSBase.h:473
static void constructor(TNative &thisValue, const v8::FunctionCallbackInfo< v8::Value > &info)
The specialized callback function for all JavaScript constructors of wrapped C++ objects.
static unsigned int hasValues(const v8::FunctionCallbackInfo< v8::Value > &info, const unsigned int startIndex, const unsigned int endIndex, TNative *values)
Returns whether a JavaScript function call holds a sequence of specific native type as parameters.
Definition JSBase.h:883
static void propertySetter(TNative &thisValue, v8::Local< v8::Name > &property, v8::Local< v8::Value > value, const v8::PropertyCallbackInfo< void > &info)
The specialized callback function for all JavaScript setters of wrapped C++ objects.
static void constructor(const v8::FunctionCallbackInfo< v8::Value > &info)
The callback function for all JavaScript constructors of wrapped C++ objects.
Definition JSBase.h:441
static std::string toAString(const v8::Local< v8::String > &value)
Returns the std string of a given JavaScript string object.
static void propertyGetter(v8::Local< v8::Name > property, const v8::PropertyCallbackInfo< v8::Value > &info)
The callback function for all JavaScript getters of wrapped C++ objects.
Definition JSBase.h:459
static bool hasValue(const v8::FunctionCallbackInfo< v8::Value > &info, const unsigned int index, TNative &value)
Returns whether a JavaScript function call holds a specific native type as parameter.
Definition JSBase.h:583
static void function(const v8::FunctionCallbackInfo< v8::Value > &info)
The callback function for all JavaScript functions of wrapped C++ objects.
Definition JSBase.h:489
static const v8::Local< v8::Context > & currentContext()
Returns the current JavaScript context object.
Definition JSContext.h:337
This class implements a type-safe object wrapper for non-JavaScript objects.
Definition JSExternal.h:50
Type type() const
Returns the type of the wrapped C++ object.
Definition JSExternal.h:215
static JSExternal * create(TNative *data, v8::Local< v8::Object > &owner, v8::Isolate *isolate)
Creates a new type-safe wrapper object for a specific native C++ object.
Definition JSExternal.h:210
TNative & value()
Returns the wrapped C++ object.
Definition JSExternal.h:383
static JSExternal * external(const v8::Local< v8::Value > &value)
Returns the external object from a given JavaScript object.
std::vector< std::string > Strings
Definition of a vector holding strings.
Definition Base.h:162
The namespace covering the entire Ocean framework.
Definition Accessor.h:15