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