Ultralight  1.0.0
A fast, lightweight, HTML UI engine for native apps.
JSHelpers.h
1 #pragma once
2 #include <AppCore/Defines.h>
3 #include <JavaScriptCore/JavaScript.h>
4 #include <JavaScriptCore/JSStringRef.h>
5 #include <Ultralight/String.h>
6 #include <functional>
7 #include <vector>
8 #include <memory>
9 
15 namespace ultralight {
16 
25 void AExport SetJSContext(JSContextRef ctx);
26 
30 JSContextRef AExport GetJSContext();
31 
36 class AExport JSString {
37 public:
38  // Create empty string
39  JSString();
40 
41  // Create from C-string
42  JSString(const char* str);
43 
44  // Create from Ultralight String
45  JSString(const String& str);
46 
47  // Take ownership of existing JSStringRef
48  JSString(JSStringRef str);
49 
50  // Copy constructor
51  JSString(const JSString& other);
52 
53  ~JSString();
54 
55  // Assignment operator
56  JSString& operator=(const JSString& other);
57 
58  // Cast to String
59  operator String();
60 
61  // Cast to JSStringRef
62  operator JSStringRef() const { return instance_; }
63 
64 protected:
65  JSStringRef instance_;
66 };
67 
68 class JSArray;
69 class JSObject;
70 class JSFunction;
71 
72 // Used with the JSValue constructor to create "Null" types
73 struct AExport JSValueNullTag {};
74 
75 // Used with the JSValue constructor to create "Undefined" types
76 struct AExport JSValueUndefinedTag {};
77 
82 class AExport JSValue {
83 public:
84  // Create null (empty) JSValue
85  JSValue();
86 
87  // Create null JSValue explicitly
88  JSValue(JSValueNullTag);
89 
90  // Create undefined JSValue
91  JSValue(JSValueUndefinedTag);
92 
93  // Create boolean JSValue
94  JSValue(bool val);
95 
96  // Create unsigned integer JSValue (aka, Number) [will be cast to double]
97  JSValue(uint32_t val);
98 
99  // Create integer JSValue (aka, Number) [will be cast to double]
100  JSValue(int32_t val);
101 
102  // Create unsigned integer JSValue (aka, Number) [will be cast to double]
103  JSValue(uint64_t val);
104 
105  // Create integer JSValue (aka, Number) [will be cast to double]
106  JSValue(int64_t val);
107 
108  // Create double JSValue (aka, Number)
109  JSValue(double val);
110 
111  // Create string JSValue
112  JSValue(const char* val);
113 
114  // Create string JSValue
115  JSValue(const String& val);
116 
117  // Create string JSValue
118  JSValue(JSString val);
119 
120  // Create from existing JSValueRef
121  JSValue(JSValueRef val);
122 
123  // Create object JSValue
124  JSValue(JSObjectRef obj);
125 
126  // Copy constructor, a shallow copy is made, will end up pointing to same instance
127  JSValue(const JSValue& other);
128 
129  virtual ~JSValue();
130 
131  // A shallow copy is made, will end up pointing to same instance
132  virtual JSValue& operator=(const JSValue& other);
133 
134  bool IsNull() const;
135 
136  bool IsUndefined() const;
137 
138  bool IsBoolean() const;
139 
140  bool IsNumber() const;
141 
142  bool IsString() const;
143 
144  bool IsObject() const;
145 
146  bool IsArray() const;
147 
148  bool IsFunction() const;
149 
150  // Convert to Boolean
151  bool ToBoolean() const;
152 
153  // Convert to Number (Double)
154  double ToNumber() const;
155 
156  // Convert to Number (Integer)
157  int64_t ToInteger() const { return static_cast<int64_t>(ToNumber()); }
158 
159  // Convert to String
160  JSString ToString() const;
161 
162  // Convert to Object (will debug assert if not an Object)
163  JSObject ToObject() const;
164 
165  // Convert to Array (will debug asset if not an Array)
166  JSArray ToArray() const;
167 
168  // Convert to Function (will debug asset if not a Function)
169  JSFunction ToFunction() const;
170 
171  operator bool() const { return ToBoolean(); }
172 
173  operator double() const { return ToNumber(); }
174 
175  operator uint32_t() const { return static_cast<uint32_t>(ToNumber()); }
176 
177  operator int32_t() const { return static_cast<uint32_t>(ToNumber()); }
178 
179  operator uint64_t() const { return static_cast<uint64_t>(ToNumber()); }
180 
181  operator int64_t() const { return ToInteger(); }
182 
183  operator String() const { return ToString(); }
184 
185  operator JSString() const { return ToString(); }
186 
187  operator JSObject() const;
188 
189  operator JSObjectRef() const;
190 
191  operator JSArray() const;
192 
193  operator JSFunction() const;
194 
195  // Get the underlying JSValueRef
196  operator JSValueRef() const { return instance(); }
197 
198 protected:
199  JSValue(JSContextRef ctx);
200  JSValue(JSContextRef ctx, JSValueRef val);
201  virtual JSValueRef instance() const;
202 
203  JSContextRef ctx_;
204  JSValueRef instance_ = nullptr;
205  friend class JSFunction;
206 };
207 
208 typedef std::vector<JSValue> JSArgs;
209 typedef std::function<void(const JSObject&, const JSArgs&)> JSCallback;
210 typedef std::function<JSValue(const JSObject&, const JSArgs&)> JSCallbackWithRetval;
211 
212 // Macro to help bind JSCallback member function to JSPropertyValue
213 #define BindJSCallback(fn) (JSCallback)std::bind(fn, this, std::placeholders::_1, std::placeholders::_2)
214 #define BindJSCallbackWithRetval(fn) (JSCallbackWithRetval)std::bind(fn, this, std::placeholders::_1, std::placeholders::_2)
215 
221 class AExport JSPropertyValue : public JSValue {
222 public:
223  virtual ~JSPropertyValue();
224 
225  // Assign a new value to the property (internally calls JSObjectSetProperty)
226  virtual JSPropertyValue& operator=(const JSValue& value);
227 
228  // Bind to native C++ callback (creates a Function object that can be called from JS)
229  JSPropertyValue& operator=(const JSCallback& callback);
230 
231  // Bind to native C++ callback with return value (creates a Function object that can be called from JS)
232  JSPropertyValue& operator=(const JSCallbackWithRetval& callback);
233 
234 protected:
235  virtual JSValueRef instance() const;
236  JSPropertyValue(JSContextRef ctx, JSObjectRef proxy_obj, unsigned idx);
237  JSPropertyValue(JSContextRef ctx, JSObjectRef proxy_obj, JSString idx);
238  JSPropertyValue(const JSPropertyValue&) = default;
239  JSPropertyValue& operator=(const JSPropertyValue&) = delete;
240 
241  JSObject* proxyObj_;
242  bool using_numeric_idx_;
243  unsigned numeric_idx_;
244  JSString string_idx_;
245  friend class JSArray;
246  friend class JSObject;
247 };
248 
253 class AExport JSArray {
254 public:
255  // Create empty Array
256  JSArray();
257 
258  // Create Array from list of JSValues
259  JSArray(const std::initializer_list<JSValue>& values);
260 
261  // Create Array from existing JSObjectRef (JavaScriptCore C API)
262  JSArray(JSObjectRef array_obj);
263 
264  // Copy constructor (shallow copy, will point to same instance)
265  JSArray(const JSArray& other);
266 
267  ~JSArray();
268 
269  // Assignment (shallow assignment, will point to same instance)
270  JSArray& operator=(const JSArray& other);
271 
272  // Get number of elements in the Array
273  unsigned length();
274 
275  // Push an element to back of Array
276  void push(const JSValue& val);
277 
278  // Find the index (location) of a certain value, will return -1 if not found
279  int indexOf(const JSValue& val, int start = 0) const;
280 
281  // Get a property by array index (numbering starts at 0)
282  JSPropertyValue operator[](unsigned idx) const;
283 
284  // Get the underlying JSObjectRef (JavaScriptCore C API)
285  operator JSObjectRef() const { return instance_; }
286 
287 protected:
288  JSArray(JSContextRef ctx, JSValueRef val);
289 
290  JSContextRef ctx_;
291  JSObjectRef instance_;
292  friend class JSValue;
293 };
294 
299 class AExport JSObject {
300 public:
301  // Create empty Object
302  JSObject();
303 
304  // Create from existing JSObjectRef from JavaScriptCore C API
305  JSObject(JSObjectRef obj);
306 
307  // Copy constructor (shallow copy, will point to same instance)
308  JSObject(const JSObject& other);
309 
310  ~JSObject();
311 
312  // Assignment (shallow assignment, will point to same instance)
313  JSObject& operator=(const JSObject& other);
314 
315  // Get a property by name
316  JSPropertyValue operator[](JSString propertyName) const;
317 
318  // Check if a property exists
319  bool HasProperty(JSString propertyName) const;
320 
321  // Remove a property
322  bool DeleteProperty(JSString propertyName);
323 
324  // Get the underlying JSObjectRef (JavaScriptCore C API)
325  operator JSObjectRef() const { return instance_; }
326 
327 protected:
328  JSObject(JSContextRef ctx, JSValueRef val);
329  JSObject(JSContextRef ctx, JSObjectRef obj);
330 
331  JSContextRef ctx_;
332  JSObjectRef instance_;
333  friend class JSValue;
334  friend class JSPropertyValue;
335 };
336 
341 class AExport JSFunction {
342 public:
343  // Create an empty Function.
344  // NOTE: It is OKAY to create this without calling SetJSContext() first.
345  JSFunction();
346 
347  // Copy constructor (shallow copy, will point to same instance)
348  JSFunction(const JSFunction& other);
349 
350  ~JSFunction();
351 
352  // Assignment (shallow assignment, will point to same instance)
353  JSFunction& operator=(const JSFunction& other);
354 
355  // Whether or not this is a valid, callable Function object.
356  bool IsValid() const;
357 
358  // Call function (using Global Object for 'this') and return the result.
359  JSValue operator()(const JSArgs& args);
360 
361  // Call function (with explicit object for 'this') and return the result
362  JSValue operator()(const JSObject& thisObject, const JSArgs& args);
363 
364  // Get the underlying JSObjectRef (JavaScriptCore C API)
365  operator JSObjectRef() const { return instance_; }
366 
367 protected:
368  JSFunction(JSContextRef ctx, JSValueRef val);
369 
370  JSContextRef ctx_;
371  JSObjectRef instance_;
372  friend class JSValue;
373 };
374 
379 JSObject AExport JSGlobalObject();
380 
384 JSValue AExport JSEval(const JSString& str);
385 
386 } // namespace ultralight
JSString wrapper that automatically manages lifetime and provides helpful conversions.
Definition: JSHelpers.h:36
JSObject wrapper that automatically manages lifetime and provides convenient access to properties.
Definition: JSHelpers.h:299
Wrapper for JSObject property value (JSValue subclass).
Definition: JSHelpers.h:221
JSObject AExport JSGlobalObject()
Get the Global Object for the current JSContext.
JSValue wrapper that automatically manages lifetime and provides helpful conversions.
Definition: JSHelpers.h:82
JSContextRef AExport GetJSContext()
Get the current JSContext.
This is a set of common JavaScriptCore Helper functions to simplify sample code.
Definition: App.h:19
JSFunction wrapper that automatically manages lifetime and provides convenient function invocation op...
Definition: JSHelpers.h:341
UTF-16 String container with conversions for UTF-8 and UTF-32.
Definition: String.h:27
JSValue AExport JSEval(const JSString &str)
Evaluate a string of JavaScript and return a result.
The header for the String class.
JSArray wrapper that automatically manages lifetime and provides convenient access to indices and Arr...
Definition: JSHelpers.h:253
void AExport SetJSContext(JSContextRef ctx)
Set the current JSContext.