Loading...
Searching...
No Matches
JSHelpers.h
Go to the documentation of this file.
1/**************************************************************************************************
2 * This file is a part of Ultralight. *
3 * *
4 * See <https://ultralig.ht> for licensing and more. *
5 * *
6 * (C) 2024 Ultralight, Inc. *
7 **************************************************************************************************/
8#pragma once
9#include <AppCore/Defines.h>
12#include <Ultralight/String.h>
13#include <functional>
14#include <memory>
15
16namespace ultralight {
17
18///
19/// Set the current JSContext.
20///
21/// Most JavaScriptCore C API calls require an active JavaScript execution
22/// context (JSContextRef). You can get the JSContextRef for a page via
23/// `View::LockJSContext()`. This context changes with each page navigation.
24///
25/// @note You MUST set a JSContext before using most of the C++ API below.
26///
28
29///
30/// Get the current JSContext.
31///
33
34///
35/// JavaScript String wrapper that automatically manages JSStringRef lifetime
36/// and provides helpful conversions.
37///
39public:
40 /// Create empty string
42
43 /// Create from C-string
44 JSString(const char* str);
45
46 /// Create from Ultralight String
47 JSString(const String& str);
48
49 /// Create from existing JSStringRef
51
52 /// Copy constructor
53 JSString(const JSString& other);
54
55 /// Destructor
57
58 /// Assignment operator
59 JSString& operator=(const JSString& other);
60
61 /// Cast to String
62 operator String();
63
64 /// Cast to underlying JSStringRef
65 operator JSStringRef() const { return instance_; }
66
67protected:
69};
70
71class JSArray;
72class JSObject;
73class JSFunction;
74
75/// Tag type used with the JSValue constructor to create "Null" types
77
78/// Tag type used with the JSValue constructor to create "Undefined" types
80
81///
82/// JavaScript variant value wrapper that automatically manages JSValueRef
83/// lifetime and provides helpful conversions.
84///
86public:
87 /// Create null (empty) JSValue
89
90 /// Create null JSValue explicitly
92
93 /// Create undefined JSValue
95
96 /// Create boolean JSValue
97 JSValue(bool val);
98
99 /// Create unsigned integer JSValue (aka, Number) [will be cast to double]
100 JSValue(uint32_t val);
101
102 /// Create integer JSValue (aka, Number) [will be cast to double]
103 JSValue(int32_t val);
104
105 /// Create unsigned integer JSValue (aka, Number) [will be cast to double]
106 JSValue(uint64_t val);
107
108 /// Create integer JSValue (aka, Number) [will be cast to double]
109 JSValue(int64_t val);
110
111 /// Create double JSValue (aka, Number)
112 JSValue(double val);
113
114 /// Create string JSValue
115 JSValue(const char* val);
116
117 /// Create string JSValue
118 JSValue(const String& val);
119
120 /// Create string JSValue
122
123 /// Create from existing JSValueRef
125
126 /// Create object JSValue
128
129 /// Copy constructor, a shallow copy is made, the constructed JSValue will
130 /// point to the same JSValueRef.
131 JSValue(const JSValue& other);
132
133 /// Destructor
134 virtual ~JSValue();
135
136 /// A shallow copy is made, this JSValue will point to the same JSValueRef
137 virtual JSValue& operator=(const JSValue& other);
138
139 /// Whether or not the value is a JavaScript Null type.
140 bool IsNull() const;
141
142 /// Whether or not the value is a JavaScript Undefined type.
143 bool IsUndefined() const;
144
145 /// Whether or not the value is a JavaScript Boolean type.
146 bool IsBoolean() const;
147
148 /// Whether or not the value is a JavaScript Number type.
149 bool IsNumber() const;
150
151 /// Whether or not the value is a JavaScript String type.
152 bool IsString() const;
153
154 /// Whether or not the value is a JavaScript Object type.
155 bool IsObject() const;
156
157 /// Whether or not the value is a JavaScript Array type.
158 bool IsArray() const;
159
160 /// Whether or not the value is a JavaScript Function type.
161 bool IsFunction() const;
162
163 /// Get the value as a Boolean
164 bool ToBoolean() const;
165
166 /// Get the value as a Number (Double)
167 double ToNumber() const;
168
169 /// Get the value as a Number (Integer)
170 int64_t ToInteger() const { return static_cast<int64_t>(ToNumber()); }
171
172 /// Get the value as a String
174
175 /// Get the value as an Object (will debug assert if not an Object)
177
178 /// Get the value as an Array (will debug asset if not an Array)
180
181 /// Get the value as a Function (will debug asset if not a Function)
183
184 operator bool() const { return ToBoolean(); }
185
186 operator double() const { return ToNumber(); }
187
188 operator uint32_t() const { return static_cast<uint32_t>(ToNumber()); }
189
190 operator int32_t() const { return static_cast<uint32_t>(ToNumber()); }
191
192 operator uint64_t() const { return static_cast<uint64_t>(ToNumber()); }
193
194 operator int64_t() const { return ToInteger(); }
195
196 operator String() const { return ToString(); }
197
198 operator JSString() const { return ToString(); }
199
200 operator JSObject() const;
201
202 operator JSObjectRef() const;
203
204 operator JSArray() const;
205
206 operator JSFunction() const;
207
208 /// Get the underlying JSValueRef
209 operator JSValueRef() const { return instance(); }
210
211 ///
212 /// Get the bound context for this JSValue (it is cached at creation).
213 ///
214 JSContextRef context() const { return ctx_; }
215
216 ///
217 /// Set the JSContext for this JSValue.
218 ///
219 /// @note
220 /// JSValues created from within a JSCallback have a temporary JSContext
221 /// that is destroyed when the callback returns. You will need to "move"
222 /// any JSValues created within these callbacks to the View's main context
223 /// (call set_context() with the main context) before using them outside
224 /// the callback.
225 ///
226 void set_context(JSContextRef context) { ctx_ = context; }
227
228protected:
231 virtual JSValueRef instance() const;
232
234 JSValueRef instance_ = nullptr;
235 friend class JSFunction;
236};
237
238///
239/// A vector of JSValues, used for passing around arguments in JSCallback.
240///
242public:
243 /// Create an empty list of JavaScript arguments
245
246 /// Create a list of JavaScript arguments using a C++ initializer list
247 JSArgs(const std::initializer_list<JSValue>& values);
248
249 /// Copy-constructor
250 JSArgs(const JSArgs& other);
251
252 /// Destructor
254
255 /// Assignment operator
256 JSArgs& operator=(const JSArgs& other);
257
258 ///
259 /// Access an element of the argument list by index.
260 ///
261 /// @note
262 /// All JSValues are actually wrappers of JSValueRef instances so even
263 /// though this function doesn't return a JSValue& you are still operating
264 /// directly on the underlying JavaScript value instance.
265 ///
266 JSValue operator[](size_t pos);
267
268 ///
269 /// Access an element of the argument list by index. (const overload)
270 ///
271 /// @note
272 /// All JSValues are actually wrappers of JSValueRef instances so even
273 /// though this function doesn't return a JSValue& you are still operating
274 /// directly on the underlying JavaScript value instance.
275 ///
276 const JSValue operator[](size_t pos) const;
277
278 /// Whether or not the argument list is empty.
279 bool empty() const;
280
281 /// The number of elements in the argument list.
282 size_t size() const;
283
284 /// Clear the argument list.
285 void clear();
286
287 /// Add a new argument to the end of the list.
288 void push_back(const JSValue& val);
289
290 /// Remove the last item from the end of the list.
291 void pop_back();
292
293 /// Get the argument list as a C-array of JSValues
295
296 /// Get the argument list as a C-array of JSValues (const overload)
297 const JSValue* data() const;
298protected:
300};
301
302///
303/// JSCallback typedef used for binding C++ callbacks to JavaScript functions.
304///
305/// Takes two arguments (const JSObject& thisObj, const JSArgs& args) and
306/// returns nothing (void).
307///
308typedef std::function<void(const JSObject&, const JSArgs&)> JSCallback;
309
310///
311/// JSCallbackWithRetval typedef used for binding C++ callbacks to JavaScript
312/// functions with an optional return value.
313///
314/// Takes two arguments (const JSObject& thisObj, const JSArgs& args) and
315/// returns a JSValue back to JavaScript.
316///
317typedef std::function<JSValue(const JSObject&, const JSArgs&)> JSCallbackWithRetval;
318
319///
320/// Macro to help bind C++ member functions to a JSCallback
321///
322/// Usage: JSCallback callback = BindJSCallback(&MyClass::MyMemberFunction);
323///
324/// @note Expected to run from within an instance of 'MyClass', note the 'this' keyword in the
325/// macro.
326///
327#define BindJSCallback(fn) (JSCallback)std::bind(fn, this, std::placeholders::_1, std::placeholders::_2)
328
329///
330/// Macro to help bind C++ member functions to a JSCallbackWithRetval
331///
332/// Usage: JSCallback callback = BindJSCallback(&MyClass::MyMemberFunction);
333///
334/// @note Expected to run from within an instance of 'MyClass', note the 'this' keyword in the
335/// macro.
336///
337#define BindJSCallbackWithRetval(fn) (JSCallbackWithRetval)std::bind(fn, this, std::placeholders::_1, std::placeholders::_2)
338
339///
340/// Wrapper for JSObject property value (JSValue subclass). Allows new value assignment
341/// to object property, binding C++ callbacks to object properties via function objects,
342/// as well as value query via the JSValue interface.
343///
345public:
347
348 /// Assign a new value to the property (internally calls JSObjectSetProperty)
349 virtual JSPropertyValue& operator=(const JSValue& value);
350
351 /// Bind to native C++ callback (creates a Function object that can be called from JS)
353
354 /// Bind to native C++ callback with return value (creates a Function object that can be called from JS)
356
357protected:
358 virtual JSValueRef instance() const;
359 JSPropertyValue(JSContextRef ctx, JSObjectRef proxy_obj, unsigned idx);
363
366 unsigned numeric_idx_;
368 friend class JSArray;
369 friend class JSObject;
370};
371
372///
373/// JSArray wrapper that automatically manages lifetime and provides
374/// convenient access to indices and Array functions.
375///
377public:
378 /// Create empty Array
380
381 /// Create Array from list of JSValues
382 JSArray(const std::initializer_list<JSValue>& values);
383
384 /// Create Array from existing JSObjectRef (JavaScriptCore C API)
386
387 /// Copy constructor (shallow copy, will point to same instance)
388 JSArray(const JSArray& other);
389
391
392 /// Assignment (shallow assignment, will point to same instance)
393 JSArray& operator=(const JSArray& other);
394
395 /// Get number of elements in the Array
396 unsigned length();
397
398 /// Push an element to back of Array
399 void push(const JSValue& val);
400
401 /// Find the index (location) of a certain value, will return -1 if not found
402 int indexOf(const JSValue& val, int start = 0) const;
403
404 /// Get a property by array index (numbering starts at 0)
405 JSPropertyValue operator[](unsigned idx) const;
406
407 /// Get the underlying JSObjectRef (JavaScriptCore C API)
408 operator JSObjectRef() const { return instance_; }
409
410 ///
411 /// Get the bound context for this JSArray (it is cached at creation).
412 ///
413 JSContextRef context() const { return ctx_; }
414
415 ///
416 /// Set the JSContext for this JSArray.
417 ///
418 /// @note
419 /// JSArrays created from within a JSCallback have a temporary JSContext
420 /// that is destroyed when the callback returns. You will need to "move"
421 /// any JSArrays created within these callbacks to the View's main context
422 /// (call set_context() with the main context) before using them outside
423 /// the callback.
424 ///
425 void set_context(JSContextRef context) { ctx_ = context; }
426
427protected:
429
432 friend class JSValue;
433};
434
435///
436/// JSObject wrapper that automatically manages lifetime and provides
437/// convenient access to properties.
438///
440public:
441 /// Create empty Object
443
444 /// Create from existing JSObjectRef from JavaScriptCore C API
446
447 /// Copy constructor (shallow copy, will point to same instance)
448 JSObject(const JSObject& other);
449
451
452 /// Assignment (shallow assignment, will point to same instance)
454
455 /// Get a property by name
457
458 /// Check if a property exists
459 bool HasProperty(JSString propertyName) const;
460
461 /// Remove a property
462 bool DeleteProperty(JSString propertyName);
463
464 /// Get the underlying JSObjectRef (JavaScriptCore C API)
465 operator JSObjectRef() const { return instance_; }
466
467 ///
468 /// Get the bound context for this JSObject (it is cached at creation).
469 ///
470 JSContextRef context() const { return ctx_; }
471
472 ///
473 /// Set the JSContext for this JSObject.
474 ///
475 /// @note:
476 /// JSObjects created from within a JSCallback have a temporary JSContext
477 /// that is destroyed when the callback returns. You will need to "move"
478 /// any JSObjects created within these callbacks to the View's main context
479 /// (call set_context() with the main context) before using them outside
480 /// the callback.
481 ///
482 void set_context(JSContextRef context) { ctx_ = context; }
483
484protected:
487
490 friend class JSValue;
491 friend class JSPropertyValue;
492};
493
494///
495/// JSFunction wrapper that automatically manages lifetime and provides
496/// convenient function invocation operators.
497///
499public:
500 /// Create an empty Function.
501 /// NOTE: It is OKAY to create this without calling SetJSContext() first.
503
504 /// Copy constructor (shallow copy, will point to same instance)
505 JSFunction(const JSFunction& other);
506
508
509 /// Assignment (shallow assignment, will point to same instance)
511
512 /// Whether or not this is a valid, callable Function object.
513 bool IsValid() const;
514
515 /// Call function (using Global Object for 'this') and return the result.
517
518 /// Call function (with explicit object for 'this') and return the result
519 JSValue operator()(const JSObject& thisObject, const JSArgs& args);
520
521 /// Get the underlying JSObjectRef (JavaScriptCore C API)
522 operator JSObjectRef() const { return instance_; }
523
524 ///
525 /// Get the bound context for this JSFunction (it is cached at creation).
526 ///
527 JSContextRef context() const { return ctx_; }
528
529 ///
530 /// Set the JSContext for this JSFunction.
531 ///
532 /// @note
533 /// JSFunctions created from within a JSCallback have a temporary JSContext
534 /// that is destroyed when the callback returns. You will need to "move"
535 /// any JSFunctions created within these callbacks to the View's main context
536 /// (call set_context() with the main context) before using them outside
537 /// the callback.
538 ///
539 void set_context(JSContextRef context) { ctx_ = context; }
540
541protected:
543
546 friend class JSValue;
547};
548
549///
550/// Get the Global Object for the current JSContext.
551/// In JavaScript, this would be equivalent to the "window" object.
552///
554
555///
556/// Evaluate a string of JavaScript and return a result.
557///
559
560} // namespace ultralight
#define AExport
Definition Defines.h:42
struct OpaqueJSString * JSStringRef
Definition JSBase.h:49
struct OpaqueJSValue * JSObjectRef
Definition JSBase.h:69
const struct OpaqueJSValue * JSValueRef
Definition JSBase.h:66
const struct OpaqueJSContext * JSContextRef
Definition JSBase.h:43
A vector of JSValues, used for passing around arguments in JSCallback.
Definition JSHelpers.h:241
void pop_back()
Remove the last item from the end of the list.
JSArgs(const JSArgs &other)
Copy-constructor.
JSValue operator[](size_t pos)
Access an element of the argument list by index.
void push_back(const JSValue &val)
Add a new argument to the end of the list.
size_t size() const
The number of elements in the argument list.
JSArgs(const std::initializer_list< JSValue > &values)
Create a list of JavaScript arguments using a C++ initializer list.
bool empty() const
Whether or not the argument list is empty.
~JSArgs()
Destructor.
JSValue * data()
Get the argument list as a C-array of JSValues.
JSArgs()
Create an empty list of JavaScript arguments.
JSArgs & operator=(const JSArgs &other)
Assignment operator.
void * instance_
Definition JSHelpers.h:299
void clear()
Clear the argument list.
const JSValue * data() const
Get the argument list as a C-array of JSValues (const overload)
const JSValue operator[](size_t pos) const
Access an element of the argument list by index.
JSArray wrapper that automatically manages lifetime and provides convenient access to indices and Arr...
Definition JSHelpers.h:376
JSPropertyValue operator[](unsigned idx) const
Get a property by array index (numbering starts at 0)
void set_context(JSContextRef context)
Set the JSContext for this JSArray.
Definition JSHelpers.h:425
JSObjectRef instance_
Definition JSHelpers.h:431
JSArray(const JSArray &other)
Copy constructor (shallow copy, will point to same instance)
JSArray & operator=(const JSArray &other)
Assignment (shallow assignment, will point to same instance)
JSArray(JSContextRef ctx, JSValueRef val)
JSArray(const std::initializer_list< JSValue > &values)
Create Array from list of JSValues.
JSArray()
Create empty Array.
JSContextRef ctx_
Definition JSHelpers.h:430
void push(const JSValue &val)
Push an element to back of Array.
int indexOf(const JSValue &val, int start=0) const
Find the index (location) of a certain value, will return -1 if not found.
JSContextRef context() const
Get the bound context for this JSArray (it is cached at creation).
Definition JSHelpers.h:413
JSArray(JSObjectRef array_obj)
Create Array from existing JSObjectRef (JavaScriptCore C API)
unsigned length()
Get number of elements in the Array.
JSFunction wrapper that automatically manages lifetime and provides convenient function invocation op...
Definition JSHelpers.h:498
void set_context(JSContextRef context)
Set the JSContext for this JSFunction.
Definition JSHelpers.h:539
JSObjectRef instance_
Definition JSHelpers.h:545
JSFunction(JSContextRef ctx, JSValueRef val)
JSFunction & operator=(const JSFunction &other)
Assignment (shallow assignment, will point to same instance)
JSFunction()
Create an empty Function.
bool IsValid() const
Whether or not this is a valid, callable Function object.
JSContextRef ctx_
Definition JSHelpers.h:544
JSValue operator()(const JSObject &thisObject, const JSArgs &args)
Call function (with explicit object for 'this') and return the result.
JSFunction(const JSFunction &other)
Copy constructor (shallow copy, will point to same instance)
JSValue operator()(const JSArgs &args)
Call function (using Global Object for 'this') and return the result.
JSContextRef context() const
Get the bound context for this JSFunction (it is cached at creation).
Definition JSHelpers.h:527
JSObject wrapper that automatically manages lifetime and provides convenient access to properties.
Definition JSHelpers.h:439
void set_context(JSContextRef context)
Set the JSContext for this JSObject.
Definition JSHelpers.h:482
JSObjectRef instance_
Definition JSHelpers.h:489
JSObject(JSObjectRef obj)
Create from existing JSObjectRef from JavaScriptCore C API.
JSObject(JSContextRef ctx, JSObjectRef obj)
bool DeleteProperty(JSString propertyName)
Remove a property.
JSPropertyValue operator[](JSString propertyName) const
Get a property by name.
JSObject()
Create empty Object.
bool HasProperty(JSString propertyName) const
Check if a property exists.
JSObject(const JSObject &other)
Copy constructor (shallow copy, will point to same instance)
JSObject(JSContextRef ctx, JSValueRef val)
JSContextRef ctx_
Definition JSHelpers.h:488
JSContextRef context() const
Get the bound context for this JSObject (it is cached at creation).
Definition JSHelpers.h:470
JSObject & operator=(const JSObject &other)
Assignment (shallow assignment, will point to same instance)
Wrapper for JSObject property value (JSValue subclass).
Definition JSHelpers.h:344
JSString string_idx_
Definition JSHelpers.h:367
JSPropertyValue & operator=(const JSCallbackWithRetval &callback)
Bind to native C++ callback with return value (creates a Function object that can be called from JS)
virtual JSValueRef instance() const
JSPropertyValue & operator=(const JSPropertyValue &)=delete
JSObject * proxyObj_
Definition JSHelpers.h:364
JSPropertyValue(JSContextRef ctx, JSObjectRef proxy_obj, JSString idx)
JSPropertyValue(const JSPropertyValue &)=default
bool using_numeric_idx_
Definition JSHelpers.h:365
virtual JSPropertyValue & operator=(const JSValue &value)
Assign a new value to the property (internally calls JSObjectSetProperty)
JSPropertyValue & operator=(const JSCallback &callback)
Bind to native C++ callback (creates a Function object that can be called from JS)
JSPropertyValue(JSContextRef ctx, JSObjectRef proxy_obj, unsigned idx)
unsigned numeric_idx_
Definition JSHelpers.h:366
JavaScript String wrapper that automatically manages JSStringRef lifetime and provides helpful conver...
Definition JSHelpers.h:38
JSStringRef instance_
Definition JSHelpers.h:68
JSString(const JSString &other)
Copy constructor.
JSString(JSStringRef str)
Create from existing JSStringRef.
JSString(const char *str)
Create from C-string.
JSString()
Create empty string.
~JSString()
Destructor.
JSString(const String &str)
Create from Ultralight String.
JSString & operator=(const JSString &other)
Assignment operator.
JavaScript variant value wrapper that automatically manages JSValueRef lifetime and provides helpful ...
Definition JSHelpers.h:85
JSValue(JSObjectRef obj)
Create object JSValue.
JSValue(JSContextRef ctx)
void set_context(JSContextRef context)
Set the JSContext for this JSValue.
Definition JSHelpers.h:226
virtual JSValueRef instance() const
JSString ToString() const
Get the value as a String.
JSObject ToObject() const
Get the value as an Object (will debug assert if not an Object)
JSValue(uint32_t val)
Create unsigned integer JSValue (aka, Number) [will be cast to double].
bool ToBoolean() const
Get the value as a Boolean.
JSValue(const JSValue &other)
Copy constructor, a shallow copy is made, the constructed JSValue will point to the same JSValueRef.
JSValue(JSValueUndefinedTag)
Create undefined JSValue.
JSValue(JSContextRef ctx, JSValueRef val)
JSValue(bool val)
Create boolean JSValue.
bool IsNumber() const
Whether or not the value is a JavaScript Number type.
JSValue(int64_t val)
Create integer JSValue (aka, Number) [will be cast to double].
bool IsObject() const
Whether or not the value is a JavaScript Object type.
bool IsString() const
Whether or not the value is a JavaScript String type.
JSFunction ToFunction() const
Get the value as a Function (will debug asset if not a Function)
JSValue(JSValueNullTag)
Create null JSValue explicitly.
double ToNumber() const
Get the value as a Number (Double)
JSValue(double val)
Create double JSValue (aka, Number)
JSValue()
Create null (empty) JSValue.
bool IsNull() const
Whether or not the value is a JavaScript Null type.
JSContextRef ctx_
Definition JSHelpers.h:233
bool IsBoolean() const
Whether or not the value is a JavaScript Boolean type.
JSValue(JSValueRef val)
Create from existing JSValueRef.
JSValue(int32_t val)
Create integer JSValue (aka, Number) [will be cast to double].
int64_t ToInteger() const
Get the value as a Number (Integer)
Definition JSHelpers.h:170
JSValue(JSString val)
Create string JSValue.
virtual JSValue & operator=(const JSValue &other)
A shallow copy is made, this JSValue will point to the same JSValueRef.
JSValue(const String &val)
Create string JSValue.
JSContextRef context() const
Get the bound context for this JSValue (it is cached at creation).
Definition JSHelpers.h:214
JSValue(uint64_t val)
Create unsigned integer JSValue (aka, Number) [will be cast to double].
bool IsUndefined() const
Whether or not the value is a JavaScript Undefined type.
JSArray ToArray() const
Get the value as an Array (will debug asset if not an Array)
bool IsFunction() const
Whether or not the value is a JavaScript Function type.
JSValue(const char *val)
Create string JSValue.
bool IsArray() const
Whether or not the value is a JavaScript Array type.
virtual ~JSValue()
Destructor.
Unicode string container with conversions for UTF-8, UTF-16, and UTF-32.
Definition String.h:34
Definition App.h:14
std::function< void(const JSObject &, const JSArgs &)> JSCallback
JSCallback typedef used for binding C++ callbacks to JavaScript functions.
Definition JSHelpers.h:308
JSContextRef GetJSContext()
Get the current JSContext.
std::function< JSValue(const JSObject &, const JSArgs &)> JSCallbackWithRetval
JSCallbackWithRetval typedef used for binding C++ callbacks to JavaScript functions with an optional ...
Definition JSHelpers.h:317
JSObject JSGlobalObject()
Get the Global Object for the current JSContext.
void SetJSContext(JSContextRef ctx)
Set the current JSContext.
JSValue JSEval(const JSString &str)
Evaluate a string of JavaScript and return a result.
Tag type used with the JSValue constructor to create "Null" types.
Definition JSHelpers.h:76
Tag type used with the JSValue constructor to create "Undefined" types.
Definition JSHelpers.h:79