From 11bae63bb1f833802ec6ce01342ebdd1d61e9252 Mon Sep 17 00:00:00 2001 From: John Porto Date: Fri, 8 Jul 2022 11:40:33 -0700 Subject: [PATCH] Add BigInt skeleton Summary: Adds a jsi::BigInt skeleton. Changelog: [General][Added] jsi::BigInt Reviewed By: kodafb Differential Revision: D35706101 fbshipit-source-id: 435b108050279ff30953b3e209cdc2f0ff84f40b --- ReactCommon/jsi/JSCRuntime.cpp | 12 ++++++++ ReactCommon/jsi/jsi/decorator.h | 6 ++++ ReactCommon/jsi/jsi/jsi.cpp | 26 +++++++++++++++++ ReactCommon/jsi/jsi/jsi.h | 50 +++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) diff --git a/ReactCommon/jsi/JSCRuntime.cpp b/ReactCommon/jsi/JSCRuntime.cpp index 6408f6bd26ad8f..5d8487b2cd5b93 100644 --- a/ReactCommon/jsi/JSCRuntime.cpp +++ b/ReactCommon/jsi/JSCRuntime.cpp @@ -142,6 +142,7 @@ class JSCRuntime : public jsi::Runtime { }; PointerValue *cloneSymbol(const Runtime::PointerValue *pv) override; + PointerValue *cloneBigInt(const Runtime::PointerValue *pv) override; PointerValue *cloneString(const Runtime::PointerValue *pv) override; PointerValue *cloneObject(const Runtime::PointerValue *pv) override; PointerValue *clonePropNameID(const Runtime::PointerValue *pv) override; @@ -214,6 +215,7 @@ class JSCRuntime : public jsi::Runtime { size_t count) override; bool strictEquals(const jsi::Symbol &a, const jsi::Symbol &b) const override; + bool strictEquals(const jsi::BigInt &a, const jsi::BigInt &b) const override; bool strictEquals(const jsi::String &a, const jsi::String &b) const override; bool strictEquals(const jsi::Object &a, const jsi::Object &b) const override; bool instanceOf(const jsi::Object &o, const jsi::Function &f) override; @@ -599,6 +601,11 @@ jsi::Runtime::PointerValue *JSCRuntime::cloneSymbol( return makeSymbolValue(symbol->sym_); } +jsi::Runtime::PointerValue *JSCRuntime::cloneBigInt( + const Runtime::PointerValue *) { + throw std::logic_error("Not implemented"); +} + jsi::Runtime::PointerValue *JSCRuntime::cloneString( const jsi::Runtime::PointerValue *pv) { if (!pv) { @@ -1299,6 +1306,11 @@ bool JSCRuntime::strictEquals(const jsi::Symbol &a, const jsi::Symbol &b) return ret; } +bool JSCRuntime::strictEquals(const jsi::BigInt &a, const jsi::BigInt &b) + const { + throw std::logic_error("Not implemented"); +} + bool JSCRuntime::strictEquals(const jsi::String &a, const jsi::String &b) const { return JSStringIsEqual(stringRef(a), stringRef(b)); diff --git a/ReactCommon/jsi/jsi/decorator.h b/ReactCommon/jsi/jsi/decorator.h index ee8a4b6ed00ba5..6f239c051b7d58 100644 --- a/ReactCommon/jsi/jsi/decorator.h +++ b/ReactCommon/jsi/jsi/decorator.h @@ -154,6 +154,9 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { Runtime::PointerValue* cloneSymbol(const Runtime::PointerValue* pv) override { return plain_.cloneSymbol(pv); }; + Runtime::PointerValue* cloneBigInt(const Runtime::PointerValue* pv) override { + return plain_.cloneBigInt(pv); + }; Runtime::PointerValue* cloneString(const Runtime::PointerValue* pv) override { return plain_.cloneString(pv); }; @@ -315,6 +318,9 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { bool strictEquals(const Symbol& a, const Symbol& b) const override { return plain_.strictEquals(a, b); }; + bool strictEquals(const BigInt& a, const BigInt& b) const override { + return plain_.strictEquals(a, b); + }; bool strictEquals(const String& a, const String& b) const override { return plain_.strictEquals(a, b); }; diff --git a/ReactCommon/jsi/jsi/jsi.cpp b/ReactCommon/jsi/jsi/jsi.cpp index a081eb34f97d9c..3f56d0623b0b31 100644 --- a/ReactCommon/jsi/jsi/jsi.cpp +++ b/ReactCommon/jsi/jsi/jsi.cpp @@ -32,6 +32,8 @@ std::string kindToString(const Value& v, Runtime* rt = nullptr) { return "a string"; } else if (v.isSymbol()) { return "a symbol"; + } else if (v.isBigInt()) { + return "a bigint"; } else { assert(v.isObject() && "Expecting object."); return rt != nullptr && v.getObject(*rt).isFunction(*rt) ? "a function" @@ -234,6 +236,8 @@ Value::Value(Runtime& runtime, const Value& other) : Value(other.kind_) { data_.number = other.data_.number; } else if (kind_ == SymbolKind) { new (&data_.pointer) Pointer(runtime.cloneSymbol(other.data_.pointer.ptr_)); + } else if (kind_ == BigIntKind) { + new (&data_.pointer) Pointer(runtime.cloneBigInt(other.data_.pointer.ptr_)); } else if (kind_ == StringKind) { new (&data_.pointer) Pointer(runtime.cloneString(other.data_.pointer.ptr_)); } else if (kind_ >= ObjectKind) { @@ -263,6 +267,10 @@ bool Value::strictEquals(Runtime& runtime, const Value& a, const Value& b) { return runtime.strictEquals( static_cast(a.data_.pointer), static_cast(b.data_.pointer)); + case BigIntKind: + return runtime.strictEquals( + static_cast(a.data_.pointer), + static_cast(b.data_.pointer)); case StringKind: return runtime.strictEquals( static_cast(a.data_.pointer), @@ -330,6 +338,24 @@ Symbol Value::asSymbol(Runtime& rt) && { return std::move(*this).getSymbol(rt); } +BigInt Value::asBigInt(Runtime& rt) const& { + if (!isBigInt()) { + throw JSError( + rt, "Value is " + kindToString(*this, &rt) + ", expected a BigInt"); + } + + return getBigInt(rt); +} + +BigInt Value::asBigInt(Runtime& rt) && { + if (!isBigInt()) { + throw JSError( + rt, "Value is " + kindToString(*this, &rt) + ", expected a BigInt"); + } + + return std::move(*this).getBigInt(rt); +} + String Value::asString(Runtime& rt) const& { if (!isString()) { throw JSError( diff --git a/ReactCommon/jsi/jsi/jsi.h b/ReactCommon/jsi/jsi/jsi.h index 56884908b6d5d9..7c1479f006824c 100644 --- a/ReactCommon/jsi/jsi/jsi.h +++ b/ReactCommon/jsi/jsi/jsi.h @@ -68,6 +68,7 @@ class Runtime; class Pointer; class PropNameID; class Symbol; +class BigInt; class String; class Object; class WeakObject; @@ -240,6 +241,7 @@ class JSI_EXPORT Runtime { friend class Pointer; friend class PropNameID; friend class Symbol; + friend class BigInt; friend class String; friend class Object; friend class WeakObject; @@ -263,6 +265,7 @@ class JSI_EXPORT Runtime { }; virtual PointerValue* cloneSymbol(const Runtime::PointerValue* pv) = 0; + virtual PointerValue* cloneBigInt(const Runtime::PointerValue* pv) = 0; virtual PointerValue* cloneString(const Runtime::PointerValue* pv) = 0; virtual PointerValue* cloneObject(const Runtime::PointerValue* pv) = 0; virtual PointerValue* clonePropNameID(const Runtime::PointerValue* pv) = 0; @@ -337,6 +340,7 @@ class JSI_EXPORT Runtime { virtual void popScope(ScopeState*); virtual bool strictEquals(const Symbol& a, const Symbol& b) const = 0; + virtual bool strictEquals(const BigInt& a, const BigInt& b) const = 0; virtual bool strictEquals(const String& a, const String& b) const = 0; virtual bool strictEquals(const Object& a, const Object& b) const = 0; @@ -482,6 +486,18 @@ class JSI_EXPORT Symbol : public Pointer { friend class Value; }; +/// Represents a JS BigInt. Movable, not copyable. +class JSI_EXPORT BigInt : public Pointer { + public: + using Pointer::Pointer; + + BigInt(BigInt&& other) = default; + BigInt& operator=(BigInt&& other) = default; + + friend class Runtime; + friend class Value; +}; + /// Represents a JS String. Movable, not copyable. class JSI_EXPORT String : public Pointer { public: @@ -973,6 +989,7 @@ class JSI_EXPORT Value { /* implicit */ Value(T&& other) : Value(kindOf(other)) { static_assert( std::is_base_of::value || + std::is_base_of::value || std::is_base_of::value || std::is_base_of::value, "Value cannot be implicitly move-constructed from this type"); @@ -995,6 +1012,11 @@ class JSI_EXPORT Value { new (&data_.pointer) Symbol(runtime.cloneSymbol(sym.ptr_)); } + /// Copies a BigInt lvalue into a new JS value. + Value(Runtime& runtime, const BigInt& bigint) : Value(BigIntKind) { + new (&data_.pointer) BigInt(runtime.cloneBigInt(bigint.ptr_)); + } + /// Copies a String lvalue into a new JS value. Value(Runtime& runtime, const String& str) : Value(StringKind) { new (&data_.pointer) String(runtime.cloneString(str.ptr_)); @@ -1064,6 +1086,10 @@ class JSI_EXPORT Value { return kind_ == StringKind; } + bool isBigInt() const { + return kind_ == BigIntKind; + } + bool isSymbol() const { return kind_ == SymbolKind; } @@ -1112,6 +1138,26 @@ class JSI_EXPORT Value { Symbol asSymbol(Runtime& runtime) const&; Symbol asSymbol(Runtime& runtime) &&; + /// \return the BigInt value, or asserts if not a bigint. + BigInt getBigInt(Runtime& runtime) const& { + assert(isBigInt()); + return BigInt(runtime.cloneBigInt(data_.pointer.ptr_)); + } + + /// \return the BigInt value, or asserts if not a bigint. + /// Can be used on rvalue references to avoid cloning more bigints. + BigInt getBigInt(Runtime&) && { + assert(isBigInt()); + auto ptr = data_.pointer.ptr_; + data_.pointer.ptr_ = nullptr; + return static_cast(ptr); + } + + /// \return the BigInt value, or throws JSIException if not a + /// bigint + BigInt asBigInt(Runtime& runtime) const&; + BigInt asBigInt(Runtime& runtime) &&; + /// \return the String value, or asserts if not a string. String getString(Runtime& runtime) const& { assert(isString()); @@ -1164,6 +1210,7 @@ class JSI_EXPORT Value { BooleanKind, NumberKind, SymbolKind, + BigIntKind, StringKind, ObjectKind, PointerKind = SymbolKind, @@ -1190,6 +1237,9 @@ class JSI_EXPORT Value { constexpr static ValueKind kindOf(const Symbol&) { return SymbolKind; } + constexpr static ValueKind kindOf(const BigInt&) { + return BigIntKind; + } constexpr static ValueKind kindOf(const String&) { return StringKind; }