1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | #pragma once
|
8 |
|
9 | #include <cassert>
|
10 | #include <cstring>
|
11 | #include <exception>
|
12 | #include <functional>
|
13 | #include <memory>
|
14 | #include <string>
|
15 | #include <vector>
|
16 |
|
17 | #ifndef JSI_EXPORT
|
18 | #ifdef _MSC_VER
|
19 | #ifdef JSI_CREATE_SHARED_LIBRARY
|
20 | #define JSI_EXPORT __declspec(dllexport)
|
21 | #else
|
22 | #define JSI_EXPORT
|
23 | #endif
|
24 | #else
|
25 | #define JSI_EXPORT __attribute__((visibility("default")))
|
26 | #endif
|
27 | #endif
|
28 |
|
29 | class FBJSRuntime;
|
30 | namespace facebook {
|
31 | namespace jsi {
|
32 |
|
33 | class Buffer {
|
34 | public:
|
35 | virtual ~Buffer();
|
36 | virtual size_t size() const = 0;
|
37 | virtual const uint8_t* data() const = 0;
|
38 | };
|
39 |
|
40 | class StringBuffer : public Buffer {
|
41 | public:
|
42 | StringBuffer(std::string s) : s_(std::move(s)) {}
|
43 | size_t size() const override {
|
44 | return s_.size();
|
45 | }
|
46 | const uint8_t* data() const override {
|
47 | return reinterpret_cast<const uint8_t*>(s_.data());
|
48 | }
|
49 |
|
50 | private:
|
51 | std::string s_;
|
52 | };
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 | class PreparedJavaScript {
|
59 | protected:
|
60 | PreparedJavaScript() = default;
|
61 |
|
62 | public:
|
63 | virtual ~PreparedJavaScript() = 0;
|
64 | };
|
65 |
|
66 | class Runtime;
|
67 | class Pointer;
|
68 | class PropNameID;
|
69 | class Symbol;
|
70 | class String;
|
71 | class Object;
|
72 | class WeakObject;
|
73 | class Array;
|
74 | class ArrayBuffer;
|
75 | class Function;
|
76 | class Value;
|
77 | class Instrumentation;
|
78 | class Scope;
|
79 | class JSIException;
|
80 | class JSError;
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 | using HostFunctionType = std::function<
|
94 | Value(Runtime& rt, const Value& thisVal, const Value* args, size_t count)>;
|
95 |
|
96 |
|
97 |
|
98 | class JSI_EXPORT HostObject {
|
99 | public:
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | virtual ~HostObject();
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | virtual Value get(Runtime&, const PropNameID& name);
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 | virtual void set(Runtime&, const PropNameID& name, const Value& value);
|
122 |
|
123 |
|
124 |
|
125 |
|
126 | virtual std::vector<PropNameID> getPropertyNames(Runtime& rt);
|
127 | };
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 | class Runtime {
|
148 | public:
|
149 | virtual ~Runtime();
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 | virtual Value evaluateJavaScript(
|
162 | const std::shared_ptr<const Buffer>& buffer,
|
163 | const std::string& sourceURL) = 0;
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 | virtual std::shared_ptr<const PreparedJavaScript> prepareJavaScript(
|
177 | const std::shared_ptr<const Buffer>& buffer,
|
178 | std::string sourceURL) = 0;
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 | virtual Value evaluatePreparedJavaScript(
|
185 | const std::shared_ptr<const PreparedJavaScript>& js) = 0;
|
186 |
|
187 |
|
188 | virtual Object global() = 0;
|
189 |
|
190 |
|
191 |
|
192 |
|
193 | virtual std::string description() = 0;
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 | virtual bool isInspectable() = 0;
|
202 |
|
203 |
|
204 |
|
205 |
|
206 | virtual Instrumentation& instrumentation();
|
207 |
|
208 | protected:
|
209 | friend class Pointer;
|
210 | friend class PropNameID;
|
211 | friend class Symbol;
|
212 | friend class String;
|
213 | friend class Object;
|
214 | friend class WeakObject;
|
215 | friend class Array;
|
216 | friend class ArrayBuffer;
|
217 | friend class Function;
|
218 | friend class Value;
|
219 | friend class Scope;
|
220 | friend class JSError;
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 | struct PointerValue {
|
228 | virtual void invalidate() = 0;
|
229 |
|
230 | protected:
|
231 | virtual ~PointerValue() = default;
|
232 | };
|
233 |
|
234 | virtual PointerValue* cloneSymbol(const Runtime::PointerValue* pv) = 0;
|
235 | virtual PointerValue* cloneString(const Runtime::PointerValue* pv) = 0;
|
236 | virtual PointerValue* cloneObject(const Runtime::PointerValue* pv) = 0;
|
237 | virtual PointerValue* clonePropNameID(const Runtime::PointerValue* pv) = 0;
|
238 |
|
239 | virtual PropNameID createPropNameIDFromAscii(
|
240 | const char* str,
|
241 | size_t length) = 0;
|
242 | virtual PropNameID createPropNameIDFromUtf8(
|
243 | const uint8_t* utf8,
|
244 | size_t length) = 0;
|
245 | virtual PropNameID createPropNameIDFromString(const String& str) = 0;
|
246 | virtual std::string utf8(const PropNameID&) = 0;
|
247 | virtual bool compare(const PropNameID&, const PropNameID&) = 0;
|
248 |
|
249 | virtual std::string symbolToString(const Symbol&) = 0;
|
250 |
|
251 | virtual String createStringFromAscii(const char* str, size_t length) = 0;
|
252 | virtual String createStringFromUtf8(const uint8_t* utf8, size_t length) = 0;
|
253 | virtual std::string utf8(const String&) = 0;
|
254 |
|
255 | virtual Object createObject() = 0;
|
256 | virtual Object createObject(std::shared_ptr<HostObject> ho) = 0;
|
257 | virtual std::shared_ptr<HostObject> getHostObject(const jsi::Object&) = 0;
|
258 | virtual HostFunctionType& getHostFunction(const jsi::Function&) = 0;
|
259 |
|
260 | virtual Value getProperty(const Object&, const PropNameID& name) = 0;
|
261 | virtual Value getProperty(const Object&, const String& name) = 0;
|
262 | virtual bool hasProperty(const Object&, const PropNameID& name) = 0;
|
263 | virtual bool hasProperty(const Object&, const String& name) = 0;
|
264 | virtual void
|
265 | setPropertyValue(Object&, const PropNameID& name, const Value& value) = 0;
|
266 | virtual void
|
267 | setPropertyValue(Object&, const String& name, const Value& value) = 0;
|
268 |
|
269 | virtual bool isArray(const Object&) const = 0;
|
270 | virtual bool isArrayBuffer(const Object&) const = 0;
|
271 | virtual bool isFunction(const Object&) const = 0;
|
272 | virtual bool isHostObject(const jsi::Object&) const = 0;
|
273 | virtual bool isHostFunction(const jsi::Function&) const = 0;
|
274 | virtual Array getPropertyNames(const Object&) = 0;
|
275 |
|
276 | virtual WeakObject createWeakObject(const Object&) = 0;
|
277 | virtual Value lockWeakObject(const WeakObject&) = 0;
|
278 |
|
279 | virtual Array createArray(size_t length) = 0;
|
280 | virtual size_t size(const Array&) = 0;
|
281 | virtual size_t size(const ArrayBuffer&) = 0;
|
282 | virtual uint8_t* data(const ArrayBuffer&) = 0;
|
283 | virtual Value getValueAtIndex(const Array&, size_t i) = 0;
|
284 | virtual void setValueAtIndexImpl(Array&, size_t i, const Value& value) = 0;
|
285 |
|
286 | virtual Function createFunctionFromHostFunction(
|
287 | const PropNameID& name,
|
288 | unsigned int paramCount,
|
289 | HostFunctionType func) = 0;
|
290 | virtual Value call(
|
291 | const Function&,
|
292 | const Value& jsThis,
|
293 | const Value* args,
|
294 | size_t count) = 0;
|
295 | virtual Value
|
296 | callAsConstructor(const Function&, const Value* args, size_t count) = 0;
|
297 |
|
298 |
|
299 | struct ScopeState;
|
300 | virtual ScopeState* pushScope();
|
301 | virtual void popScope(ScopeState*);
|
302 |
|
303 | virtual bool strictEquals(const Symbol& a, const Symbol& b) const = 0;
|
304 | virtual bool strictEquals(const String& a, const String& b) const = 0;
|
305 | virtual bool strictEquals(const Object& a, const Object& b) const = 0;
|
306 |
|
307 | virtual bool instanceOf(const Object& o, const Function& f) = 0;
|
308 |
|
309 |
|
310 |
|
311 | template <typename T>
|
312 | static T make(PointerValue* pv);
|
313 | static const PointerValue* getPointerValue(const Pointer& pointer);
|
314 | static const PointerValue* getPointerValue(const Value& value);
|
315 |
|
316 | friend class ::FBJSRuntime;
|
317 | template <typename Plain, typename Base>
|
318 | friend class RuntimeDecorator;
|
319 | };
|
320 |
|
321 |
|
322 | class Pointer {
|
323 | protected:
|
324 | explicit Pointer(Pointer&& other) : ptr_(other.ptr_) {
|
325 | other.ptr_ = nullptr;
|
326 | }
|
327 |
|
328 | ~Pointer() {
|
329 | if (ptr_) {
|
330 | ptr_->invalidate();
|
331 | }
|
332 | }
|
333 |
|
334 | Pointer& operator=(Pointer&& other);
|
335 |
|
336 | friend class Runtime;
|
337 | friend class Value;
|
338 |
|
339 | explicit Pointer(Runtime::PointerValue* ptr) : ptr_(ptr) {}
|
340 |
|
341 | typename Runtime::PointerValue* ptr_;
|
342 | };
|
343 |
|
344 |
|
345 | class PropNameID : public Pointer {
|
346 | public:
|
347 | using Pointer::Pointer;
|
348 |
|
349 | PropNameID(Runtime& runtime, const PropNameID& other)
|
350 | : Pointer(runtime.clonePropNameID(other.ptr_)) {}
|
351 |
|
352 | PropNameID(PropNameID&& other) = default;
|
353 | PropNameID& operator=(PropNameID&& other) = default;
|
354 |
|
355 |
|
356 |
|
357 | static PropNameID forAscii(Runtime& runtime, const char* str, size_t length) {
|
358 | return runtime.createPropNameIDFromAscii(str, length);
|
359 | }
|
360 |
|
361 |
|
362 |
|
363 | static PropNameID forAscii(Runtime& runtime, const char* str) {
|
364 | return forAscii(runtime, str, strlen(str));
|
365 | }
|
366 |
|
367 |
|
368 | static PropNameID forAscii(Runtime& runtime, const std::string& str) {
|
369 | return forAscii(runtime, str.c_str(), str.size());
|
370 | }
|
371 |
|
372 |
|
373 | static PropNameID
|
374 | forUtf8(Runtime& runtime, const uint8_t* utf8, size_t length) {
|
375 | return runtime.createPropNameIDFromUtf8(utf8, length);
|
376 | }
|
377 |
|
378 |
|
379 |
|
380 | static PropNameID forUtf8(Runtime& runtime, const std::string& utf8) {
|
381 | return runtime.createPropNameIDFromUtf8(
|
382 | reinterpret_cast<const uint8_t*>(utf8.data()), utf8.size());
|
383 | }
|
384 |
|
385 |
|
386 | static PropNameID forString(Runtime& runtime, const jsi::String& str) {
|
387 | return runtime.createPropNameIDFromString(str);
|
388 | }
|
389 |
|
390 |
|
391 | template <typename... Args>
|
392 | static std::vector<PropNameID> names(Runtime& runtime, Args&&... args);
|
393 |
|
394 |
|
395 | template <size_t N>
|
396 | static std::vector<PropNameID> names(PropNameID(&&propertyNames)[N]);
|
397 |
|
398 |
|
399 | std::string utf8(Runtime& runtime) const {
|
400 | return runtime.utf8(*this);
|
401 | }
|
402 |
|
403 | static bool compare(
|
404 | Runtime& runtime,
|
405 | const jsi::PropNameID& a,
|
406 | const jsi::PropNameID& b) {
|
407 | return runtime.compare(a, b);
|
408 | }
|
409 |
|
410 | friend class Runtime;
|
411 | friend class Value;
|
412 | };
|
413 |
|
414 |
|
415 |
|
416 |
|
417 |
|
418 |
|
419 | class Symbol : public Pointer {
|
420 | public:
|
421 | using Pointer::Pointer;
|
422 |
|
423 | Symbol(Symbol&& other) = default;
|
424 | Symbol& operator=(Symbol&& other) = default;
|
425 |
|
426 |
|
427 | static bool strictEquals(Runtime& runtime, const Symbol& a, const Symbol& b) {
|
428 | return runtime.strictEquals(a, b);
|
429 | }
|
430 |
|
431 |
|
432 |
|
433 | std::string toString(Runtime& runtime) const {
|
434 | return runtime.symbolToString(*this);
|
435 | }
|
436 |
|
437 | friend class Runtime;
|
438 | friend class Value;
|
439 | };
|
440 |
|
441 |
|
442 | class String : public Pointer {
|
443 | public:
|
444 | using Pointer::Pointer;
|
445 |
|
446 | String(String&& other) = default;
|
447 | String& operator=(String&& other) = default;
|
448 |
|
449 |
|
450 |
|
451 | static String
|
452 | createFromAscii(Runtime& runtime, const char* str, size_t length) {
|
453 | return runtime.createStringFromAscii(str, length);
|
454 | }
|
455 |
|
456 |
|
457 |
|
458 | static String createFromAscii(Runtime& runtime, const char* str) {
|
459 | return createFromAscii(runtime, str, strlen(str));
|
460 | }
|
461 |
|
462 |
|
463 |
|
464 | static String createFromAscii(Runtime& runtime, const std::string& str) {
|
465 | return createFromAscii(runtime, str.c_str(), str.size());
|
466 | }
|
467 |
|
468 |
|
469 |
|
470 | static String
|
471 | createFromUtf8(Runtime& runtime, const uint8_t* utf8, size_t length) {
|
472 | return runtime.createStringFromUtf8(utf8, length);
|
473 | }
|
474 |
|
475 |
|
476 |
|
477 | static String createFromUtf8(Runtime& runtime, const std::string& utf8) {
|
478 | return runtime.createStringFromUtf8(
|
479 | reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length());
|
480 | }
|
481 |
|
482 |
|
483 | static bool strictEquals(Runtime& runtime, const String& a, const String& b) {
|
484 | return runtime.strictEquals(a, b);
|
485 | }
|
486 |
|
487 |
|
488 | std::string utf8(Runtime& runtime) const {
|
489 | return runtime.utf8(*this);
|
490 | }
|
491 |
|
492 | friend class Runtime;
|
493 | friend class Value;
|
494 | };
|
495 |
|
496 | class Array;
|
497 | class Function;
|
498 |
|
499 |
|
500 | class Object : public Pointer {
|
501 | public:
|
502 | using Pointer::Pointer;
|
503 |
|
504 | Object(Object&& other) = default;
|
505 | Object& operator=(Object&& other) = default;
|
506 |
|
507 |
|
508 | Object(Runtime& runtime) : Object(runtime.createObject()) {}
|
509 |
|
510 | static Object createFromHostObject(
|
511 | Runtime& runtime,
|
512 | std::shared_ptr<HostObject> ho) {
|
513 | return runtime.createObject(ho);
|
514 | }
|
515 |
|
516 |
|
517 | static bool strictEquals(Runtime& runtime, const Object& a, const Object& b) {
|
518 | return runtime.strictEquals(a, b);
|
519 | }
|
520 |
|
521 |
|
522 | bool instanceOf(Runtime& rt, const Function& ctor) {
|
523 | return rt.instanceOf(*this, ctor);
|
524 | }
|
525 |
|
526 |
|
527 |
|
528 |
|
529 | Value getProperty(Runtime& runtime, const char* name) const;
|
530 |
|
531 |
|
532 |
|
533 |
|
534 | Value getProperty(Runtime& runtime, const String& name) const;
|
535 |
|
536 |
|
537 |
|
538 |
|
539 | Value getProperty(Runtime& runtime, const PropNameID& name) const;
|
540 |
|
541 |
|
542 |
|
543 | bool hasProperty(Runtime& runtime, const char* name) const;
|
544 |
|
545 |
|
546 |
|
547 | bool hasProperty(Runtime& runtime, const String& name) const;
|
548 |
|
549 |
|
550 |
|
551 | bool hasProperty(Runtime& runtime, const PropNameID& name) const;
|
552 |
|
553 |
|
554 |
|
555 |
|
556 | template <typename T>
|
557 | void setProperty(Runtime& runtime, const char* name, T&& value);
|
558 |
|
559 |
|
560 |
|
561 |
|
562 | template <typename T>
|
563 | void setProperty(Runtime& runtime, const String& name, T&& value);
|
564 |
|
565 |
|
566 |
|
567 |
|
568 | template <typename T>
|
569 | void setProperty(Runtime& runtime, const PropNameID& name, T&& value);
|
570 |
|
571 |
|
572 |
|
573 | bool isArray(Runtime& runtime) const {
|
574 | return runtime.isArray(*this);
|
575 | }
|
576 |
|
577 |
|
578 |
|
579 | bool isArrayBuffer(Runtime& runtime) const {
|
580 | return runtime.isArrayBuffer(*this);
|
581 | }
|
582 |
|
583 |
|
584 |
|
585 | bool isFunction(Runtime& runtime) const {
|
586 | return runtime.isFunction(*this);
|
587 | }
|
588 |
|
589 |
|
590 |
|
591 |
|
592 | template <typename T = HostObject>
|
593 | bool isHostObject(Runtime& runtime) const;
|
594 |
|
595 |
|
596 |
|
597 | Array getArray(Runtime& runtime) const&;
|
598 |
|
599 |
|
600 |
|
601 | Array getArray(Runtime& runtime) &&;
|
602 |
|
603 |
|
604 |
|
605 |
|
606 | Array asArray(Runtime& runtime) const&;
|
607 |
|
608 |
|
609 |
|
610 |
|
611 | Array asArray(Runtime& runtime) &&;
|
612 |
|
613 |
|
614 |
|
615 | ArrayBuffer getArrayBuffer(Runtime& runtime) const&;
|
616 |
|
617 |
|
618 |
|
619 | ArrayBuffer getArrayBuffer(Runtime& runtime) &&;
|
620 |
|
621 |
|
622 |
|
623 | Function getFunction(Runtime& runtime) const&;
|
624 |
|
625 |
|
626 |
|
627 | Function getFunction(Runtime& runtime) &&;
|
628 |
|
629 |
|
630 |
|
631 |
|
632 | Function asFunction(Runtime& runtime) const&;
|
633 |
|
634 |
|
635 |
|
636 |
|
637 | Function asFunction(Runtime& runtime) &&;
|
638 |
|
639 |
|
640 |
|
641 |
|
642 |
|
643 | template <typename T = HostObject>
|
644 | std::shared_ptr<T> getHostObject(Runtime& runtime) const;
|
645 |
|
646 |
|
647 |
|
648 |
|
649 | template <typename T = HostObject>
|
650 | std::shared_ptr<T> asHostObject(Runtime& runtime) const;
|
651 |
|
652 |
|
653 |
|
654 | Object getPropertyAsObject(Runtime& runtime, const char* name) const;
|
655 |
|
656 |
|
657 |
|
658 |
|
659 |
|
660 | Function getPropertyAsFunction(Runtime& runtime, const char* name) const;
|
661 |
|
662 |
|
663 |
|
664 |
|
665 |
|
666 | Array getPropertyNames(Runtime& runtime) const;
|
667 |
|
668 | protected:
|
669 | void
|
670 | setPropertyValue(Runtime& runtime, const String& name, const Value& value) {
|
671 | return runtime.setPropertyValue(*this, name, value);
|
672 | }
|
673 |
|
674 | void setPropertyValue(
|
675 | Runtime& runtime,
|
676 | const PropNameID& name,
|
677 | const Value& value) {
|
678 | return runtime.setPropertyValue(*this, name, value);
|
679 | }
|
680 |
|
681 | friend class Runtime;
|
682 | friend class Value;
|
683 | };
|
684 |
|
685 |
|
686 |
|
687 |
|
688 | class WeakObject : public Pointer {
|
689 | public:
|
690 | using Pointer::Pointer;
|
691 |
|
692 | WeakObject(WeakObject&& other) = default;
|
693 | WeakObject& operator=(WeakObject&& other) = default;
|
694 |
|
695 |
|
696 | WeakObject(Runtime& runtime, const Object& o)
|
697 | : WeakObject(runtime.createWeakObject(o)) {}
|
698 |
|
699 |
|
700 |
|
701 |
|
702 |
|
703 | Value lock(Runtime& runtime);
|
704 |
|
705 | friend class Runtime;
|
706 | };
|
707 |
|
708 |
|
709 |
|
710 | class Array : public Object {
|
711 | public:
|
712 | Array(Array&&) = default;
|
713 |
|
714 | Array(Runtime& runtime, size_t length) : Array(runtime.createArray(length)) {}
|
715 |
|
716 | Array& operator=(Array&&) = default;
|
717 |
|
718 |
|
719 |
|
720 | size_t size(Runtime& runtime) const {
|
721 | return runtime.size(*this);
|
722 | }
|
723 |
|
724 |
|
725 |
|
726 | size_t length(Runtime& runtime) const {
|
727 | return size(runtime);
|
728 | }
|
729 |
|
730 |
|
731 |
|
732 |
|
733 | Value getValueAtIndex(Runtime& runtime, size_t i) const;
|
734 |
|
735 |
|
736 |
|
737 |
|
738 | template <typename T>
|
739 | void setValueAtIndex(Runtime& runtime, size_t i, T&& value);
|
740 |
|
741 |
|
742 |
|
743 |
|
744 |
|
745 | template <typename... Args>
|
746 | static Array createWithElements(Runtime&, Args&&... args);
|
747 |
|
748 |
|
749 | static Array createWithElements(
|
750 | Runtime& runtime,
|
751 | std::initializer_list<Value> elements);
|
752 |
|
753 | private:
|
754 | friend class Object;
|
755 | friend class Value;
|
756 |
|
757 | void setValueAtIndexImpl(Runtime& runtime, size_t i, const Value& value) {
|
758 | return runtime.setValueAtIndexImpl(*this, i, value);
|
759 | }
|
760 |
|
761 | Array(Runtime::PointerValue* value) : Object(value) {}
|
762 | };
|
763 |
|
764 |
|
765 | class ArrayBuffer : public Object {
|
766 | public:
|
767 | ArrayBuffer(ArrayBuffer&&) = default;
|
768 | ArrayBuffer& operator=(ArrayBuffer&&) = default;
|
769 |
|
770 |
|
771 |
|
772 | size_t size(Runtime& runtime) const {
|
773 | return runtime.size(*this);
|
774 | }
|
775 |
|
776 | size_t length(Runtime& runtime) const {
|
777 | return runtime.size(*this);
|
778 | }
|
779 |
|
780 | uint8_t* data(Runtime& runtime) {
|
781 | return runtime.data(*this);
|
782 | }
|
783 |
|
784 | private:
|
785 | friend class Object;
|
786 | friend class Value;
|
787 |
|
788 | ArrayBuffer(Runtime::PointerValue* value) : Object(value) {}
|
789 | };
|
790 |
|
791 |
|
792 | class Function : public Object {
|
793 | public:
|
794 | Function(Function&&) = default;
|
795 | Function& operator=(Function&&) = default;
|
796 |
|
797 |
|
798 |
|
799 |
|
800 |
|
801 |
|
802 |
|
803 | static Function createFromHostFunction(
|
804 | Runtime& runtime,
|
805 | const jsi::PropNameID& name,
|
806 | unsigned int paramCount,
|
807 | jsi::HostFunctionType func);
|
808 |
|
809 |
|
810 |
|
811 | Value call(Runtime& runtime, const Value* args, size_t count) const;
|
812 |
|
813 |
|
814 |
|
815 |
|
816 | Value call(Runtime& runtime, std::initializer_list<Value> args) const;
|
817 |
|
818 |
|
819 |
|
820 |
|
821 | template <typename... Args>
|
822 | Value call(Runtime& runtime, Args&&... args) const;
|
823 |
|
824 |
|
825 |
|
826 | Value callWithThis(
|
827 | Runtime& Runtime,
|
828 | const Object& jsThis,
|
829 | const Value* args,
|
830 | size_t count) const;
|
831 |
|
832 |
|
833 |
|
834 |
|
835 | Value callWithThis(
|
836 | Runtime& runtime,
|
837 | const Object& jsThis,
|
838 | std::initializer_list<Value> args) const;
|
839 |
|
840 |
|
841 |
|
842 |
|
843 | template <typename... Args>
|
844 | Value callWithThis(Runtime& runtime, const Object& jsThis, Args&&... args)
|
845 | const;
|
846 |
|
847 |
|
848 |
|
849 |
|
850 | Value callAsConstructor(Runtime& runtime, const Value* args, size_t count)
|
851 | const;
|
852 |
|
853 |
|
854 |
|
855 | Value callAsConstructor(Runtime& runtime, std::initializer_list<Value> args)
|
856 | const;
|
857 |
|
858 |
|
859 |
|
860 | template <typename... Args>
|
861 | Value callAsConstructor(Runtime& runtime, Args&&... args) const;
|
862 |
|
863 |
|
864 |
|
865 |
|
866 | bool isHostFunction(Runtime& runtime) const {
|
867 | return runtime.isHostFunction(*this);
|
868 | }
|
869 |
|
870 |
|
871 |
|
872 |
|
873 |
|
874 |
|
875 |
|
876 |
|
877 | HostFunctionType& getHostFunction(Runtime& runtime) const {
|
878 | assert(isHostFunction(runtime));
|
879 | return runtime.getHostFunction(*this);
|
880 | }
|
881 |
|
882 | private:
|
883 | friend class Object;
|
884 | friend class Value;
|
885 |
|
886 | Function(Runtime::PointerValue* value) : Object(value) {}
|
887 | };
|
888 |
|
889 |
|
890 |
|
891 |
|
892 | class Value {
|
893 | public:
|
894 |
|
895 | Value() : Value(UndefinedKind) {}
|
896 |
|
897 |
|
898 | Value(std::nullptr_t) : kind_(NullKind) {}
|
899 |
|
900 |
|
901 | Value(bool b) : Value(BooleanKind) {
|
902 | data_.boolean = b;
|
903 | }
|
904 |
|
905 |
|
906 | Value(double d) : Value(NumberKind) {
|
907 | data_.number = d;
|
908 | }
|
909 |
|
910 |
|
911 | Value(int i) : Value(NumberKind) {
|
912 | data_.number = i;
|
913 | }
|
914 |
|
915 |
|
916 | template <typename T>
|
917 | Value(T&& other) : Value(kindOf(other)) {
|
918 | static_assert(
|
919 | std::is_base_of<Symbol, T>::value ||
|
920 | std::is_base_of<String, T>::value ||
|
921 | std::is_base_of<Object, T>::value,
|
922 | "Value cannot be implicitly move-constructed from this type");
|
923 | new (&data_.pointer) T(std::move(other));
|
924 | }
|
925 |
|
926 |
|
927 |
|
928 | template <typename T = void>
|
929 | Value(const char*) {
|
930 | static_assert(
|
931 | !std::is_same<void, T>::value,
|
932 | "Value cannot be constructed directly from const char*");
|
933 | }
|
934 |
|
935 | Value(Value&& value);
|
936 |
|
937 |
|
938 | Value(Runtime& runtime, const Symbol& sym) : Value(SymbolKind) {
|
939 | new (&data_.pointer) String(runtime.cloneSymbol(sym.ptr_));
|
940 | }
|
941 |
|
942 |
|
943 | Value(Runtime& runtime, const String& str) : Value(StringKind) {
|
944 | new (&data_.pointer) String(runtime.cloneString(str.ptr_));
|
945 | }
|
946 |
|
947 |
|
948 | Value(Runtime& runtime, const Object& obj) : Value(ObjectKind) {
|
949 | new (&data_.pointer) Object(runtime.cloneObject(obj.ptr_));
|
950 | }
|
951 |
|
952 |
|
953 | Value(Runtime& runtime, const Value& value);
|
954 |
|
955 |
|
956 |
|
957 | template <typename T = void>
|
958 | Value(Runtime&, const char*) {
|
959 | static_assert(
|
960 | !std::is_same<T, void>::value,
|
961 | "Value cannot be constructed directly from const char*");
|
962 | }
|
963 |
|
964 | ~Value();
|
965 |
|
966 | static Value undefined() {
|
967 | return Value();
|
968 | }
|
969 |
|
970 |
|
971 | static Value null() {
|
972 | return Value(nullptr);
|
973 | }
|
974 |
|
975 |
|
976 | static Value
|
977 | createFromJsonUtf8(Runtime& runtime, const uint8_t* json, size_t length);
|
978 |
|
979 |
|
980 |
|
981 | static bool strictEquals(Runtime& runtime, const Value& a, const Value& b);
|
982 |
|
983 | Value& operator=(Value&& other) {
|
984 | this->~Value();
|
985 | new (this) Value(std::move(other));
|
986 | return *this;
|
987 | }
|
988 |
|
989 | bool isUndefined() const {
|
990 | return kind_ == UndefinedKind;
|
991 | }
|
992 |
|
993 | bool isNull() const {
|
994 | return kind_ == NullKind;
|
995 | }
|
996 |
|
997 | bool isBool() const {
|
998 | return kind_ == BooleanKind;
|
999 | }
|
1000 |
|
1001 | bool isNumber() const {
|
1002 | return kind_ == NumberKind;
|
1003 | }
|
1004 |
|
1005 | bool isString() const {
|
1006 | return kind_ == StringKind;
|
1007 | }
|
1008 |
|
1009 | bool isSymbol() const {
|
1010 | return kind_ == SymbolKind;
|
1011 | }
|
1012 |
|
1013 | bool isObject() const {
|
1014 | return kind_ == ObjectKind;
|
1015 | }
|
1016 |
|
1017 |
|
1018 | bool getBool() const {
|
1019 | assert(isBool());
|
1020 | return data_.boolean;
|
1021 | }
|
1022 |
|
1023 |
|
1024 | double getNumber() const {
|
1025 | assert(isNumber());
|
1026 | return data_.number;
|
1027 | }
|
1028 |
|
1029 |
|
1030 |
|
1031 | double asNumber() const;
|
1032 |
|
1033 |
|
1034 | Symbol getSymbol(Runtime& runtime) const& {
|
1035 | assert(isSymbol());
|
1036 | return Symbol(runtime.cloneSymbol(data_.pointer.ptr_));
|
1037 | }
|
1038 |
|
1039 |
|
1040 |
|
1041 | Symbol getSymbol(Runtime&) && {
|
1042 | assert(isSymbol());
|
1043 | auto ptr = data_.pointer.ptr_;
|
1044 | data_.pointer.ptr_ = nullptr;
|
1045 | return static_cast<Symbol>(ptr);
|
1046 | }
|
1047 |
|
1048 |
|
1049 |
|
1050 | Symbol asSymbol(Runtime& runtime) const&;
|
1051 | Symbol asSymbol(Runtime& runtime) &&;
|
1052 |
|
1053 |
|
1054 | String getString(Runtime& runtime) const& {
|
1055 | assert(isString());
|
1056 | return String(runtime.cloneString(data_.pointer.ptr_));
|
1057 | }
|
1058 |
|
1059 |
|
1060 |
|
1061 | String getString(Runtime&) && {
|
1062 | assert(isString());
|
1063 | auto ptr = data_.pointer.ptr_;
|
1064 | data_.pointer.ptr_ = nullptr;
|
1065 | return static_cast<String>(ptr);
|
1066 | }
|
1067 |
|
1068 |
|
1069 |
|
1070 | String asString(Runtime& runtime) const&;
|
1071 | String asString(Runtime& runtime) &&;
|
1072 |
|
1073 |
|
1074 | Object getObject(Runtime& runtime) const& {
|
1075 | assert(isObject());
|
1076 | return Object(runtime.cloneObject(data_.pointer.ptr_));
|
1077 | }
|
1078 |
|
1079 |
|
1080 |
|
1081 | Object getObject(Runtime&) && {
|
1082 | assert(isObject());
|
1083 | auto ptr = data_.pointer.ptr_;
|
1084 | data_.pointer.ptr_ = nullptr;
|
1085 | return static_cast<Object>(ptr);
|
1086 | }
|
1087 |
|
1088 |
|
1089 |
|
1090 | Object asObject(Runtime& runtime) const&;
|
1091 | Object asObject(Runtime& runtime) &&;
|
1092 |
|
1093 |
|
1094 | String toString(Runtime& runtime) const;
|
1095 |
|
1096 | private:
|
1097 | friend class Runtime;
|
1098 |
|
1099 | enum ValueKind {
|
1100 | UndefinedKind,
|
1101 | NullKind,
|
1102 | BooleanKind,
|
1103 | NumberKind,
|
1104 | SymbolKind,
|
1105 | StringKind,
|
1106 | ObjectKind,
|
1107 | PointerKind = SymbolKind,
|
1108 | };
|
1109 |
|
1110 | union Data {
|
1111 |
|
1112 | Data() {
|
1113 | static_assert(
|
1114 | sizeof(Data) == sizeof(uint64_t),
|
1115 | "Value data should fit in a 64-bit register");
|
1116 | }
|
1117 | ~Data() {}
|
1118 |
|
1119 |
|
1120 | bool boolean;
|
1121 | double number;
|
1122 |
|
1123 | Pointer pointer;
|
1124 | };
|
1125 |
|
1126 | Value(ValueKind kind) : kind_(kind) {}
|
1127 |
|
1128 | constexpr static ValueKind kindOf(const Symbol&) {
|
1129 | return SymbolKind;
|
1130 | }
|
1131 | constexpr static ValueKind kindOf(const String&) {
|
1132 | return StringKind;
|
1133 | }
|
1134 | constexpr static ValueKind kindOf(const Object&) {
|
1135 | return ObjectKind;
|
1136 | }
|
1137 |
|
1138 | ValueKind kind_;
|
1139 | Data data_;
|
1140 |
|
1141 |
|
1142 | };
|
1143 |
|
1144 |
|
1145 |
|
1146 |
|
1147 |
|
1148 |
|
1149 |
|
1150 |
|
1151 |
|
1152 |
|
1153 |
|
1154 |
|
1155 |
|
1156 |
|
1157 |
|
1158 |
|
1159 |
|
1160 |
|
1161 |
|
1162 | class Scope {
|
1163 | public:
|
1164 | explicit Scope(Runtime& rt) : rt_(rt), prv_(rt.pushScope()) {}
|
1165 | ~Scope() {
|
1166 | rt_.popScope(prv_);
|
1167 | };
|
1168 |
|
1169 | Scope(const Scope&) = delete;
|
1170 | Scope(Scope&&) = delete;
|
1171 |
|
1172 | Scope& operator=(const Scope&) = delete;
|
1173 | Scope& operator=(Scope&&) = delete;
|
1174 |
|
1175 | template <typename F>
|
1176 | static auto callInNewScope(Runtime& rt, F f) -> decltype(f()) {
|
1177 | Scope s(rt);
|
1178 | return f();
|
1179 | }
|
1180 |
|
1181 | private:
|
1182 | Runtime& rt_;
|
1183 | Runtime::ScopeState* prv_;
|
1184 | };
|
1185 |
|
1186 |
|
1187 | class JSIException : public std::exception {
|
1188 | protected:
|
1189 | JSIException(){};
|
1190 | JSIException(std::string what) : what_(std::move(what)){};
|
1191 |
|
1192 | public:
|
1193 | virtual const char* what() const noexcept override {
|
1194 | return what_.c_str();
|
1195 | }
|
1196 |
|
1197 | protected:
|
1198 | std::string what_;
|
1199 | };
|
1200 |
|
1201 |
|
1202 |
|
1203 | class JSINativeException : public JSIException {
|
1204 | public:
|
1205 | JSINativeException(std::string what) : JSIException(std::move(what)) {}
|
1206 | };
|
1207 |
|
1208 |
|
1209 |
|
1210 |
|
1211 | class JSError : public JSIException {
|
1212 | public:
|
1213 |
|
1214 | JSError(Runtime& r, Value&& value);
|
1215 |
|
1216 |
|
1217 |
|
1218 | JSError(Runtime& rt, std::string message);
|
1219 |
|
1220 |
|
1221 |
|
1222 | JSError(Runtime& rt, const char* message)
|
1223 | : JSError(rt, std::string(message)){};
|
1224 |
|
1225 |
|
1226 |
|
1227 | JSError(Runtime& rt, std::string message, std::string stack);
|
1228 |
|
1229 |
|
1230 |
|
1231 |
|
1232 | JSError(std::string what, Runtime& rt, Value&& value);
|
1233 |
|
1234 | const std::string& getStack() const {
|
1235 | return stack_;
|
1236 | }
|
1237 |
|
1238 | const std::string& getMessage() const {
|
1239 | return message_;
|
1240 | }
|
1241 |
|
1242 | const jsi::Value& value() const {
|
1243 | assert(value_);
|
1244 | return *value_;
|
1245 | }
|
1246 |
|
1247 | private:
|
1248 |
|
1249 |
|
1250 |
|
1251 | void setValue(Runtime& rt, Value&& value);
|
1252 |
|
1253 |
|
1254 |
|
1255 | std::shared_ptr<jsi::Value> value_;
|
1256 | std::string message_;
|
1257 | std::string stack_;
|
1258 | };
|
1259 |
|
1260 | }
|
1261 | }
|
1262 |
|
1263 | #include <jsi/jsi-inl.h>
|