Ocean
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"
16 #include "ocean/io/FileResolver.h"
17 
18 #include <v8.h>
19 
20 namespace Ocean
21 {
22 
23 namespace Interaction
24 {
25 
26 namespace JavaScript
27 {
28 
29 /**
30  * This class implements the base class for all JavaScript wrappers.
31  * @ingroup interactionjs
32  */
33 class 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 
248 template <>
249 inline 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 
266 template <typename TNative>
267 v8::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 
272 template <>
273 inline 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 
290 template <>
291 inline 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 
308 template <>
309 inline 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 
326 template <>
327 inline 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 
344 template <typename TNative>
345 inline 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 
350 template <typename T>
351 v8::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 
371 template <typename T>
372 v8::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 
392 template <typename T>
393 v8::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 
410 inline 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 
425 inline 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 
440 template <typename TNative>
441 inline 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 
458 template <typename T, unsigned int tFunctionId>
459 inline 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 
470 template <typename T, unsigned int tFunctionId>
471 inline 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 
484 template <typename T, unsigned int tFunctionId>
485 inline 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 
496 template <>
497 inline 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 
516 template <>
517 inline 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 
532 template <>
533 inline 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 
548 template <>
549 inline 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 
564 template <>
565 inline 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 
580 template <typename TNative>
581 inline 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 
598 template <>
599 inline 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 
638 template <>
639 inline 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 
671 template <>
672 inline 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 
704 template <>
705 inline 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 
737 template <>
738 inline 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 
770 template <>
771 inline 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 
803 template <typename TNative>
804 inline 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 
840 template <>
841 inline 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 
863 template <>
864 inline 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 
886 template <typename TNative>
887 inline 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 
908 template <>
909 inline 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 
928 template <>
929 inline 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 
943 template <>
944 inline 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 
958 template <>
959 inline 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 
973 template <typename TNative>
974 inline 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 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