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::String> 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::String>& 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::String> 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::String>& 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));
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));
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));
455 info.GetReturnValue().Set(info.This());
456}
457
458template <typename T, unsigned int tFunctionId>
459inline void JSBase::propertyGetter(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
460{
461 ocean_assert(info.Holder()->InternalFieldCount() == 1);
462 const v8::Local<v8::External> thisWrapper(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0)));
463
464 JSExternal* thisExternal = static_cast<JSExternal*>(thisWrapper->Value());
465 ocean_assert(thisExternal->type() == JSExternal::type<T>());
466
467 propertyGetter<T, tFunctionId>(thisExternal->value<T>(), property, info);
468}
469
470template <typename T, unsigned int tFunctionId>
471inline void JSBase::propertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
472{
473 ocean_assert(value.IsEmpty() == false);
474 ocean_assert(info.Holder()->InternalFieldCount() == 1);
475
476 const v8::Local<v8::External> thisWrapper(v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0)));
477
478 JSExternal* thisExternal = static_cast<JSExternal*>(thisWrapper->Value());
479 ocean_assert(thisExternal->type() == JSExternal::type<T>());
480
481 propertySetter<T, tFunctionId>(thisExternal->value<T>(), property, value, info);
482}
483
484template <typename T, unsigned int tFunctionId>
485inline void JSBase::function(const v8::FunctionCallbackInfo<v8::Value>& info)
486{
487 ocean_assert(info.This()->InternalFieldCount() == 1);
488 v8::Local<v8::External> thisWrapper(v8::Local<v8::External>::Cast(info.This()->GetInternalField(0)));
489
490 JSExternal* thisExternal = static_cast<JSExternal*>(thisWrapper->Value());
491 ocean_assert(thisExternal->type() == JSExternal::type<T>());
492
493 function<T, tFunctionId>(thisExternal->value<T>(), info);
494}
495
496template <>
497inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, bool& value)
498{
499 if (info.Length() >= int(index + 1u))
500 {
501 if (info[index]->IsBoolean())
502 {
503#if defined(OCEAN_V8_VERSION) && OCEAN_V8_VERSION > 70000
504 value = info[index]->BooleanValue(v8::Isolate::GetCurrent());
505#else
506 value = info[index]->BooleanValue(JSContext::currentContext()).FromJust();
507#endif
508
509 return true;
510 }
511 }
512
513 return false;
514}
515
516template <>
517inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, int& value)
518{
519 if (info.Length() >= int(index + 1u))
520 {
521 if (info[index]->IsInt32())
522 {
523 value = info[index]->Int32Value(JSContext::currentContext()).FromJust();
524
525 return true;
526 }
527 }
528
529 return false;
530}
531
532template <>
533inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, double& value)
534{
535 if (info.Length() >= int(index + 1u))
536 {
537 if (info[index]->IsNumber())
538 {
539 value = info[index]->NumberValue(JSContext::currentContext()).FromJust();
540
541 return true;
542 }
543 }
544
545 return false;
546}
547
548template <>
549inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, float& value)
550{
551 if (info.Length() >= int(index + 1u))
552 {
553 if (info[index]->IsNumber())
554 {
555 value = float(info[index]->NumberValue(JSContext::currentContext()).FromJust());
556
557 return true;
558 }
559 }
560
561 return false;
562}
563
564template <>
565inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::string& value)
566{
567 if (info.Length() >= int(index + 1u))
568 {
569 if (info[index]->IsString())
570 {
571 value = toAString(info[index]->ToString(JSContext::currentContext()));
572
573 return true;
574 }
575 }
576
577 return false;
578}
579
580template <typename TNative>
581inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, TNative& value)
582{
583 if (info.Length() >= int(index + 1u))
584 {
585 JSExternal* externalParameter = JSExternal::external(info[index]);
586
587 if (externalParameter != nullptr && externalParameter->type() == JSExternal::type<TNative>())
588 {
589 value = externalParameter->value<TNative>();
590
591 return true;
592 }
593 }
594
595 return false;
596}
597
598template <>
599inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<bool>& value)
600{
601 if (info.Length() >= int(index + 1u))
602 {
603 if (info[index]->IsArray())
604 {
605 v8::Local<v8::Context> currentContext = JSContext::currentContext();
606#if defined(OCEAN_V8_VERSION) && OCEAN_V8_VERSION > 70000
607 v8::Isolate* isolate = v8::Isolate::GetCurrent();
608#endif
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#if defined(OCEAN_V8_VERSION) && OCEAN_V8_VERSION > 70000
625 value.emplace_back(element.ToLocalChecked()->BooleanValue(isolate));
626#else
627 value.emplace_back(element.ToLocalChecked()->BooleanValue(currentContext).FromJust());
628#endif
629 }
630
631 return true;
632 }
633 }
634
635 return false;
636}
637
638template <>
639inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<int>& value)
640{
641 if (info.Length() >= int(index + 1u))
642 {
643 if (info[index]->IsArray())
644 {
645 v8::Local<v8::Context> currentContext = JSContext::currentContext();
646
647 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
648
649 value.clear();
650 value.reserve(arrayValue->Length());
651
652 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
653 {
654 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
655
656 if (!element.IsEmpty() || !element.ToLocalChecked()->IsInt32())
657 {
658 return false;
659 }
660
661 value.emplace_back(element.ToLocalChecked()->Int32Value(currentContext).FromJust());
662 }
663
664 return true;
665 }
666 }
667
668 return false;
669}
670
671template <>
672inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<float>& value)
673{
674 if (info.Length() >= int(index + 1u))
675 {
676 if (info[index]->IsArray())
677 {
678 v8::Local<v8::Context> currentContext = JSContext::currentContext();
679
680 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
681
682 value.clear();
683 value.reserve(arrayValue->Length());
684
685 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
686 {
687 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
688
689 if (!element.IsEmpty() || !element.ToLocalChecked()->IsNumber())
690 {
691 return false;
692 }
693
694 value.emplace_back(float(element.ToLocalChecked()->NumberValue(currentContext).FromJust()));
695 }
696
697 return true;
698 }
699 }
700
701 return false;
702}
703
704template <>
705inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<double>& value)
706{
707 if (info.Length() >= int(index + 1u))
708 {
709 if (info[index]->IsArray())
710 {
711 v8::Local<v8::Context> currentContext = JSContext::currentContext();
712
713 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
714
715 value.clear();
716 value.reserve(arrayValue->Length());
717
718 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
719 {
720 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
721
722 if (!element.IsEmpty() || !element.ToLocalChecked()->IsNumber())
723 {
724 return false;
725 }
726
727 value.emplace_back(element.ToLocalChecked()->NumberValue(currentContext).FromJust());
728 }
729
730 return true;
731 }
732 }
733
734 return false;
735}
736
737template <>
738inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<Timestamp>& value)
739{
740 if (info.Length() >= int(index + 1u))
741 {
742 if (info[index]->IsArray())
743 {
744 v8::Local<v8::Context> currentContext = JSContext::currentContext();
745
746 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
747
748 value.clear();
749 value.reserve(arrayValue->Length());
750
751 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
752 {
753 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
754
755 if (!element.IsEmpty() || !element.ToLocalChecked()->IsNumber())
756 {
757 return false;
758 }
759
760 value.emplace_back(element.ToLocalChecked()->NumberValue(currentContext).FromJust());
761 }
762
763 return true;
764 }
765 }
766
767 return false;
768}
769
770template <>
771inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<std::string>& value)
772{
773 if (info.Length() >= int(index + 1u))
774 {
775 if (info[index]->IsArray())
776 {
777 v8::Local<v8::Context> currentContext = JSContext::currentContext();
778
779 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
780
781 value.clear();
782 value.reserve(arrayValue->Length());
783
784 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
785 {
786 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
787
788 if (!element.IsEmpty() || !element.ToLocalChecked()->IsString())
789 {
790 return false;
791 }
792
793 value.emplace_back(toAString(element.ToLocalChecked()->ToString(currentContext)));
794 }
795
796 return true;
797 }
798 }
799
800 return false;
801}
802
803template <typename TNative>
804inline bool JSBase::hasValue(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int index, std::vector<TNative>& value)
805{
806 if (info.Length() >= int(index + 1u))
807 {
808 if (info[index]->IsArray())
809 {
810 v8::Local<v8::Context> currentContext = JSContext::currentContext();
811
812 v8::Local<v8::Array> arrayValue = v8::Local<v8::Array>::Cast(info[index]);
813
814 value.clear();
815 value.reserve(arrayValue->Length());
816
817 for (unsigned int n = 0; n < arrayValue->Length(); ++n)
818 {
819 v8::MaybeLocal<v8::Value> element = arrayValue->Get(currentContext, n);
820
821 if (!element.IsEmpty() || !element.ToLocalChecked()->IsObject())
822 {
823 return false;
824 }
825
826 value.emplace_back();
827 if (!JSBase::isValue<TNative>(element.ToLocalChecked(), value.back()))
828 {
829 return false;
830 }
831 }
832
833 return true;
834 }
835 }
836
837 return false;
838}
839
840template <>
841inline unsigned int JSBase::hasValues(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int startIndex, const unsigned int endIndex, double* values)
842{
843 ocean_assert(startIndex < endIndex);
844 ocean_assert(values != nullptr);
845
846 for (unsigned int index = startIndex; index < endIndex; ++index)
847 {
848 if (info.Length() >= int(index + 1u))
849 {
850 if (info[index]->IsNumber())
851 {
852 values[index - startIndex] = info[index]->NumberValue(JSContext::currentContext()).FromJust();
853 continue;
854 }
855 }
856
857 return index - startIndex;
858 }
859
860 return endIndex - startIndex;
861}
862
863template <>
864inline unsigned int JSBase::hasValues(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int startIndex, const unsigned int endIndex, float* values)
865{
866 ocean_assert(startIndex < endIndex);
867 ocean_assert(values != nullptr);
868
869 for (unsigned int index = startIndex; index < endIndex; ++index)
870 {
871 if (info.Length() >= int(index + 1u))
872 {
873 if (info[index]->IsNumber())
874 {
875 values[index - startIndex] = float(info[index]->NumberValue(JSContext::currentContext()).FromJust());
876 continue;
877 }
878 }
879
880 return index - startIndex;
881 }
882
883 return endIndex - startIndex;
884}
885
886template <typename TNative>
887inline unsigned int JSBase::hasValues(const v8::FunctionCallbackInfo<v8::Value>& info, const unsigned int startIndex, const unsigned int endIndex, TNative* values)
888{
889 ocean_assert(startIndex < endIndex);
890 ocean_assert(values != nullptr);
891
892 for (unsigned int index = startIndex; index < endIndex; ++index)
893 {
894 if (info.Length() >= int(index + 1u))
895 {
896 if (JSBase::isValue<TNative>(info[index], values[index - startIndex]))
897 {
898 continue;
899 }
900 }
901
902 return index - startIndex;
903 }
904
905 return endIndex - startIndex;
906}
907
908template <>
909inline bool JSBase::isValue(v8::Local<v8::Value> localValue, bool& value)
910{
911 if (localValue->IsBoolean())
912 {
913
914#if defined(OCEAN_V8_VERSION) && OCEAN_V8_VERSION > 70000
915 value = localValue->BooleanValue(v8::Isolate::GetCurrent());
916#else
917 value = localValue->BooleanValue(JSContext::currentContext()).FromJust();
918#endif
919
920 return true;
921 }
922 else
923 {
924 return false;
925 }
926}
927
928template <>
929inline bool JSBase::isValue(v8::Local<v8::Value> localValue, double& value)
930{
931 if (localValue->IsNumber())
932 {
933 value = localValue->NumberValue(JSContext::currentContext()).FromJust();
934
935 return true;
936 }
937 else
938 {
939 return false;
940 }
941}
942
943template <>
944inline bool JSBase::isValue(v8::Local<v8::Value> localValue, float& value)
945{
946 if (localValue->IsNumber())
947 {
948 value = float(localValue->NumberValue(JSContext::currentContext()).FromJust());
949
950 return true;
951 }
952 else
953 {
954 return false;
955 }
956}
957
958template <>
959inline bool JSBase::isValue(v8::Local<v8::Value> localValue, std::string& value)
960{
961 if (localValue->IsString())
962 {
963 value = toAString(localValue->ToString(JSContext::currentContext()));
964
965 return true;
966 }
967 else
968 {
969 return false;
970 }
971}
972
973template <typename TNative>
974inline bool JSBase::isValue(v8::Local<v8::Value> localValue, TNative& value)
975{
976 JSExternal* externalParameter = JSExternal::external(localValue);
977
978 if (externalParameter != nullptr && externalParameter->type() == JSExternal::type<TNative>())
979 {
980 value = externalParameter->value<TNative>();
981
982 return true;
983 }
984
985 return false;
986}
987
988}
989
990}
991
992}
993
994#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 void propertyGetter(TNative &thisValue, v8::Local< v8::String > &property, const v8::PropertyCallbackInfo< v8::Value > &info)
The specialized callback function for all JavaScript getters 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 bool isValue(v8::Local< v8::Value > localValue, TNative &value)
Returns whether a JavaScript value wraps a specified native type.
Definition JSBase.h:974
static void propertySetter(v8::Local< v8::String > 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:471
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(TNative &thisValue, v8::Local< v8::String > &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 propertyGetter(v8::Local< v8::String > property, const v8::PropertyCallbackInfo< v8::Value > &info)
The callback function for all JavaScript getters of wrapped C++ objects.
Definition JSBase.h:459
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:887
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 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:581
static void function(const v8::FunctionCallbackInfo< v8::Value > &info)
The callback function for all JavaScript functions of wrapped C++ objects.
Definition JSBase.h:485
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.
The namespace covering the entire Ocean framework.
Definition Accessor.h:15