Cleanup and document Value wrapper
Reviewed By: mhorowitz Differential Revision: D5087565 fbshipit-source-id: 21b15dc4c476d6ecd7c42f9334c6995fa43810c2
This commit is contained in:
parent
48156b7967
commit
374d08b8e4
|
@ -14,6 +14,7 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTCxxUtils.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <cxxreact/Platform.h>
|
||||
#import <jschelpers/Value.h>
|
||||
|
@ -30,8 +31,9 @@ JSValueRef nativeLoggingHook(
|
|||
level = MAX(level, (RCTLogLevel)Value(ctx, arguments[1]).asNumber());
|
||||
}
|
||||
if (argumentCount > 0) {
|
||||
String message = Value(ctx, arguments[0]).toString();
|
||||
_RCTLogJavaScriptInternal(level, @(message.str().c_str()));
|
||||
JSContext *contextObj = contextForGlobalContextRef(JSC_JSContextGetGlobalContext(ctx));
|
||||
JSValue *msg = [JSC_JSValue(ctx) valueWithJSValueRef:arguments[0] inContext:contextObj];
|
||||
_RCTLogJavaScriptInternal(level, [msg toString]);
|
||||
}
|
||||
return Value::makeUndefined(ctx);
|
||||
}
|
||||
|
@ -45,7 +47,7 @@ JSValueRef nativePerformanceNow(
|
|||
}
|
||||
|
||||
void RCTPrepareJSCExecutor() {
|
||||
ReactMarker::logTaggedMarker = [](const ReactMarker::ReactMarkerId, const char* tag) {};
|
||||
ReactMarker::logTaggedMarker = [](const ReactMarker::ReactMarkerId, const char *tag) {};
|
||||
PerfLogging::installNativeHooks = RCTFBQuickPerformanceLoggerConfigureHooks;
|
||||
JSNativeHooks::loggingHook = nativeLoggingHook;
|
||||
JSNativeHooks::nowHook = nativePerformanceNow;
|
||||
|
|
|
@ -348,7 +348,7 @@ void JSCExecutor::loadApplicationScript(std::unique_ptr<const JSBigString> scrip
|
|||
JSValueRef jsError;
|
||||
JSValueRef result = JSC_JSEvaluateBytecodeBundle(m_context, NULL, sourceFD, jsSourceURL, &jsError);
|
||||
if (result == nullptr) {
|
||||
formatAndThrowJSException(m_context, jsError, jsSourceURL);
|
||||
throw JSException(m_context, jsError, nullptr, jsSourceURL);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
@ -392,7 +392,7 @@ void JSCExecutor::bindBridge() throw(JSException) {
|
|||
batchedBridgeValue = requireBatchedBridge.asObject().callAsFunction({});
|
||||
}
|
||||
if (batchedBridgeValue.isUndefined()) {
|
||||
throwJSExecutionException("Could not get BatchedBridge, make sure your bundle is packaged correctly");
|
||||
throw JSException("Could not get BatchedBridge, make sure your bundle is packaged correctly");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
#include <jschelpers/JavaScriptCore.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
|
|
|
@ -68,6 +68,52 @@ JSObjectRef makeFunction(
|
|||
|
||||
}
|
||||
|
||||
JSException::JSException(JSContextRef ctx, JSValueRef exn, const char* errorMsg, JSStringRef sourceURL) {
|
||||
std::ostringstream msgBuilder;
|
||||
if (errorMsg != nullptr && strlen(errorMsg) > 0) {
|
||||
msgBuilder << errorMsg << ": ";
|
||||
}
|
||||
|
||||
Value exnValue = Value(ctx, exn);
|
||||
msgBuilder << exnValue.toString().str();
|
||||
|
||||
// The null/empty-ness of source tells us if the JS came from a
|
||||
// file/resource, or was a constructed statement. The location
|
||||
// info will include that source, if any.
|
||||
std::string locationInfo = sourceURL != nullptr ? String::ref(ctx, sourceURL).str() : "";
|
||||
Object exnObject = exnValue.asObject();
|
||||
auto line = exnObject.getProperty("line");
|
||||
if (line != nullptr && line.isNumber()) {
|
||||
if (locationInfo.empty() && line.asInteger() != 1) {
|
||||
// If there is a non-trivial line number, but there was no
|
||||
// location info, we include a placeholder, and the line
|
||||
// number.
|
||||
locationInfo = folly::to<std::string>("<unknown file>:", line.asInteger());
|
||||
} else if (!locationInfo.empty()) {
|
||||
// If there is location info, we always include the line
|
||||
// number, regardless of its value.
|
||||
locationInfo += folly::to<std::string>(":", line.asInteger());
|
||||
}
|
||||
}
|
||||
|
||||
if (!locationInfo.empty()) {
|
||||
msgBuilder << " (" << locationInfo << ")";
|
||||
}
|
||||
|
||||
auto exceptionText = msgBuilder.str();
|
||||
LOG(ERROR) << "Got JS Exception: " << exceptionText;
|
||||
|
||||
Value jsStack = exnObject.getProperty("stack");
|
||||
if (!jsStack.isString()) {
|
||||
msg_ = exceptionText.c_str();
|
||||
} else {
|
||||
LOG(ERROR) << "Got JS Stack: " << jsStack.toString().str();
|
||||
msg_ = exceptionText.c_str();
|
||||
stack_ = jsStack.toString().str().c_str();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JSObjectRef makeFunction(
|
||||
JSContextRef ctx,
|
||||
const char* name,
|
||||
|
@ -122,11 +168,11 @@ void removeGlobal(JSGlobalContextRef ctx, const char* name) {
|
|||
Object::getGlobalObject(ctx).setProperty(name, Value::makeUndefined(ctx));
|
||||
}
|
||||
|
||||
JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef source) {
|
||||
JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef sourceURL) {
|
||||
JSValueRef exn, result;
|
||||
result = JSC_JSEvaluateScript(context, script, NULL, source, 0, &exn);
|
||||
result = JSC_JSEvaluateScript(context, script, NULL, sourceURL, 0, &exn);
|
||||
if (result == nullptr) {
|
||||
formatAndThrowJSException(context, exn, source);
|
||||
throw JSException(context, exn, nullptr, sourceURL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -136,51 +182,12 @@ JSValueRef evaluateSourceCode(JSContextRef context, JSSourceCodeRef source, JSSt
|
|||
JSValueRef exn, result;
|
||||
result = JSEvaluateSourceCode(context, source, NULL, &exn);
|
||||
if (result == nullptr) {
|
||||
formatAndThrowJSException(context, exn, sourceURL);
|
||||
throw JSException(context, exn, nullptr, sourceURL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
void formatAndThrowJSException(JSContextRef context, JSValueRef exn, JSStringRef source) {
|
||||
Value exception = Value(context, exn);
|
||||
std::string exceptionText = exception.toString().str();
|
||||
|
||||
// The null/empty-ness of source tells us if the JS came from a
|
||||
// file/resource, or was a constructed statement. The location
|
||||
// info will include that source, if any.
|
||||
std::string locationInfo = source != nullptr ? String::ref(context, source).str() : "";
|
||||
Object exObject = exception.asObject();
|
||||
auto line = exObject.getProperty("line");
|
||||
if (line != nullptr && line.isNumber()) {
|
||||
if (locationInfo.empty() && line.asInteger() != 1) {
|
||||
// If there is a non-trivial line number, but there was no
|
||||
// location info, we include a placeholder, and the line
|
||||
// number.
|
||||
locationInfo = folly::to<std::string>("<unknown file>:", line.asInteger());
|
||||
} else if (!locationInfo.empty()) {
|
||||
// If there is location info, we always include the line
|
||||
// number, regardless of its value.
|
||||
locationInfo += folly::to<std::string>(":", line.asInteger());
|
||||
}
|
||||
}
|
||||
|
||||
if (!locationInfo.empty()) {
|
||||
exceptionText += " (" + locationInfo + ")";
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Got JS Exception: " << exceptionText;
|
||||
|
||||
Value jsStack = exObject.getProperty("stack");
|
||||
if (jsStack.isNull() || !jsStack.isString()) {
|
||||
throwJSExecutionException("%s", exceptionText.c_str());
|
||||
} else {
|
||||
LOG(ERROR) << "Got JS Stack: " << jsStack.toString().str();
|
||||
throwJSExecutionExceptionWithStack(
|
||||
exceptionText.c_str(), jsStack.toString().str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation) {
|
||||
std::ostringstream msg;
|
||||
try {
|
||||
|
|
|
@ -2,33 +2,44 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <jschelpers/Value.h>
|
||||
#include <jschelpers/JavaScriptCore.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <jschelpers/JavaScriptCore.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
inline void throwJSExecutionException(const char* msg) {
|
||||
throw JSException(msg);
|
||||
}
|
||||
class JSException : public std::exception {
|
||||
public:
|
||||
explicit JSException(const char* msg)
|
||||
: msg_(msg), stack_(nullptr) {}
|
||||
|
||||
template <typename... Args>
|
||||
inline void throwJSExecutionException(const char* fmt, Args... args) {
|
||||
int msgSize = snprintf(nullptr, 0, fmt, args...);
|
||||
msgSize = std::min(512, msgSize + 1);
|
||||
char *msg = (char*) alloca(msgSize);
|
||||
snprintf(msg, msgSize, fmt, args...);
|
||||
throw JSException(msg);
|
||||
}
|
||||
template <typename... Args>
|
||||
explicit JSException(const char* fmt, Args... args) {
|
||||
int msgSize = snprintf(nullptr, 0, fmt, args...);
|
||||
msgSize = std::min(512, msgSize + 1);
|
||||
char *msg = (char *) alloca(msgSize);
|
||||
snprintf(msg, msgSize, fmt, args...);
|
||||
msg_ = msg;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void throwJSExecutionExceptionWithStack(const char* msg, const char* stack) {
|
||||
throw JSException(msg, stack);
|
||||
}
|
||||
explicit JSException(JSContextRef ctx, JSValueRef exn, const char* msg = nullptr, JSStringRef sourceURL = nullptr);
|
||||
|
||||
const std::string& getStack() const {
|
||||
return stack_;
|
||||
}
|
||||
|
||||
virtual const char* what() const noexcept override {
|
||||
return msg_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string msg_;
|
||||
std::string stack_;
|
||||
};
|
||||
|
||||
using JSFunction = std::function<JSValueRef(JSContextRef, JSObjectRef, size_t, const JSValueRef[])>;
|
||||
|
||||
|
@ -71,11 +82,6 @@ JSValueRef evaluateSourceCode(
|
|||
JSStringRef sourceURL);
|
||||
#endif
|
||||
|
||||
void formatAndThrowJSException(
|
||||
JSContextRef ctx,
|
||||
JSValueRef exn,
|
||||
JSStringRef sourceURL);
|
||||
|
||||
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation);
|
||||
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, JSObjectRef jsFunctionCause);
|
||||
|
||||
|
|
|
@ -17,24 +17,11 @@
|
|||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
Value::Value(JSContextRef context, JSValueRef value) :
|
||||
m_context(context),
|
||||
m_value(value)
|
||||
{
|
||||
}
|
||||
Value::Value(JSContextRef context, JSValueRef value)
|
||||
: m_context(context), m_value(value) {}
|
||||
|
||||
Value::Value(JSContextRef context, JSStringRef str) :
|
||||
m_context(context),
|
||||
m_value(JSC_JSValueMakeString(context, str))
|
||||
{
|
||||
}
|
||||
|
||||
Value::Value(Value&& other) :
|
||||
m_context(other.m_context),
|
||||
m_value(other.m_value)
|
||||
{
|
||||
other.m_value = nullptr;
|
||||
}
|
||||
Value::Value(JSContextRef context, JSStringRef str)
|
||||
: m_context(context), m_value(JSC_JSValueMakeString(context, str)) {}
|
||||
|
||||
JSContextRef Value::context() const {
|
||||
return m_context;
|
||||
|
@ -43,9 +30,8 @@ JSContextRef Value::context() const {
|
|||
std::string Value::toJSONString(unsigned indent) const {
|
||||
JSValueRef exn;
|
||||
auto stringToAdopt = JSC_JSValueCreateJSONString(m_context, m_value, indent, &exn);
|
||||
if (stringToAdopt == nullptr) {
|
||||
std::string exceptionText = Value(m_context, exn).toString().str();
|
||||
throwJSExecutionException("Exception creating JSON string: %s", exceptionText.c_str());
|
||||
if (!stringToAdopt) {
|
||||
throw JSException(m_context, exn, "Exception creating JSON string");
|
||||
}
|
||||
return String::adopt(m_context, stringToAdopt).str();
|
||||
}
|
||||
|
@ -54,7 +40,7 @@ std::string Value::toJSONString(unsigned indent) const {
|
|||
Value Value::fromJSON(JSContextRef ctx, const String& json) {
|
||||
auto result = JSC_JSValueMakeFromJSONString(ctx, json);
|
||||
if (!result) {
|
||||
throwJSExecutionException("Failed to create String from JSON: %s", json.str().c_str());
|
||||
throw JSException("Failed to create Value from JSON: %s", json.str().c_str());
|
||||
}
|
||||
return Value(ctx, result);
|
||||
}
|
||||
|
@ -133,24 +119,31 @@ JSValueRef Value::fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj)
|
|||
}
|
||||
}
|
||||
|
||||
Object Value::asObject() {
|
||||
Object Value::asObject() const {
|
||||
JSValueRef exn;
|
||||
JSObjectRef jsObj = JSC_JSValueToObject(context(), m_value, &exn);
|
||||
if (!jsObj) {
|
||||
std::string exceptionText = Value(m_context, exn).toString().str();
|
||||
throwJSExecutionException("Failed to convert to object: %s", exceptionText.c_str());
|
||||
throw JSException(m_context, exn, "Failed to convert to object");
|
||||
}
|
||||
return Object(context(), jsObj);
|
||||
}
|
||||
|
||||
String Value::toString() const {
|
||||
JSValueRef exn;
|
||||
JSStringRef jsStr = JSC_JSValueToStringCopy(context(), m_value, &exn);
|
||||
if (!jsStr) {
|
||||
throw JSException(m_context, exn, "Failed to convert to string");
|
||||
}
|
||||
return String::adopt(context(), jsStr);
|
||||
}
|
||||
|
||||
Value Value::makeError(JSContextRef ctx, const char *error)
|
||||
{
|
||||
JSValueRef exn;
|
||||
JSValueRef args[] = { Value(ctx, String(ctx, error)) };
|
||||
JSObjectRef errorObj = JSC_JSObjectMakeError(ctx, 1, args, &exn);
|
||||
if (!errorObj) {
|
||||
std::string exceptionText = Value(ctx, exn).toString().str();
|
||||
throwJSExecutionException("%s", exceptionText.c_str());
|
||||
throw JSException(ctx, exn, "Exception making error");
|
||||
}
|
||||
return Value(ctx, errorObj);
|
||||
}
|
||||
|
@ -179,8 +172,7 @@ Value Object::callAsFunction(JSObjectRef thisObj, int nArgs, const JSValueRef ar
|
|||
JSValueRef exn;
|
||||
JSValueRef result = JSC_JSObjectCallAsFunction(m_context, m_obj, thisObj, nArgs, args, &exn);
|
||||
if (!result) {
|
||||
std::string exceptionText = Value(m_context, exn).toString().str();
|
||||
throwJSExecutionException("Exception calling object as function: %s", exceptionText.c_str());
|
||||
throw JSException(m_context, exn, "Exception calling object as function");
|
||||
}
|
||||
return Value(m_context, result);
|
||||
}
|
||||
|
@ -189,8 +181,7 @@ Object Object::callAsConstructor(std::initializer_list<JSValueRef> args) const {
|
|||
JSValueRef exn;
|
||||
JSObjectRef result = JSC_JSObjectCallAsConstructor(m_context, m_obj, args.size(), args.begin(), &exn);
|
||||
if (!result) {
|
||||
std::string exceptionText = Value(m_context, exn).toString().str();
|
||||
throwJSExecutionException("Exception calling object as constructor: %s", exceptionText.c_str());
|
||||
throw JSException(m_context, exn, "Exception calling object as constructor");
|
||||
}
|
||||
return Object(m_context, result);
|
||||
}
|
||||
|
@ -199,8 +190,7 @@ Value Object::getProperty(const String& propName) const {
|
|||
JSValueRef exn;
|
||||
JSValueRef property = JSC_JSObjectGetProperty(m_context, m_obj, propName, &exn);
|
||||
if (!property) {
|
||||
std::string exceptionText = Value(m_context, exn).toString().str();
|
||||
throwJSExecutionException("Failed to get property: %s", exceptionText.c_str());
|
||||
throw JSException(m_context, exn, "Failed to get property");
|
||||
}
|
||||
return Value(m_context, property);
|
||||
}
|
||||
|
@ -209,8 +199,7 @@ Value Object::getPropertyAtIndex(unsigned int index) const {
|
|||
JSValueRef exn;
|
||||
JSValueRef property = JSC_JSObjectGetPropertyAtIndex(m_context, m_obj, index, &exn);
|
||||
if (!property) {
|
||||
std::string exceptionText = Value(m_context, exn).toString().str();
|
||||
throwJSExecutionException("Failed to get property at index %u: %s", index, exceptionText.c_str());
|
||||
throw JSException(m_context, exn, "Failed to get property at index");
|
||||
}
|
||||
return Value(m_context, property);
|
||||
}
|
||||
|
@ -223,8 +212,7 @@ void Object::setProperty(const String& propName, const Value& value) {
|
|||
JSValueRef exn = nullptr;
|
||||
JSC_JSObjectSetProperty(m_context, m_obj, propName, value, kJSPropertyAttributeNone, &exn);
|
||||
if (exn) {
|
||||
std::string exceptionText = Value(m_context, exn).toString().str();
|
||||
throwJSExecutionException("Failed to set property: %s", exceptionText.c_str());
|
||||
throw JSException(m_context, exn, "Failed to set property");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,8 +220,7 @@ void Object::setPropertyAtIndex(unsigned int index, const Value& value) {
|
|||
JSValueRef exn = nullptr;
|
||||
JSC_JSObjectSetPropertyAtIndex(m_context, m_obj, index, value, &exn);
|
||||
if (exn) {
|
||||
std::string exceptionText = Value(m_context, exn).toString().str();
|
||||
throwJSExecutionException("Failed to set property: %s", exceptionText.c_str());
|
||||
throw JSException(m_context, exn, "Failed to set property at index");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,30 +15,13 @@
|
|||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
class Value;
|
||||
class Context;
|
||||
|
||||
class JSException : public std::exception {
|
||||
public:
|
||||
explicit JSException(const char* msg)
|
||||
: msg_(msg), stack_("") {}
|
||||
|
||||
JSException(const char* msg, const char* stack)
|
||||
: msg_(msg), stack_(stack) {}
|
||||
|
||||
const std::string& getStack() const {
|
||||
return stack_;
|
||||
}
|
||||
|
||||
virtual const char* what() const noexcept override {
|
||||
return msg_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string msg_;
|
||||
std::string stack_;
|
||||
};
|
||||
|
||||
// C++ object wrapper for JSStringRef
|
||||
class String : public noncopyable {
|
||||
public:
|
||||
explicit String(): m_context(nullptr), m_string(nullptr) {} // dummy empty constructor
|
||||
|
@ -82,12 +65,16 @@ public:
|
|||
return m_string;
|
||||
}
|
||||
|
||||
JSContextRef context() const {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
// Length in characters
|
||||
size_t length() const {
|
||||
return m_string ? JSC_JSStringGetLength(m_context, m_string) : 0;
|
||||
}
|
||||
|
||||
// Length in bytes of a null-terminated utf8 encoded value
|
||||
// Length in bytes of a nul-terminated utf8 encoded value
|
||||
size_t utf8Size() const {
|
||||
return m_string ? JSC_JSStringGetMaximumUTF8CStringSize(m_context, m_string) : 0;
|
||||
}
|
||||
|
@ -115,7 +102,7 @@ public:
|
|||
return unicode::utf16toUTF8(utf16, stringLength);
|
||||
}
|
||||
|
||||
// Assumes that utf8 is null terminated
|
||||
// Assumes that utf8 is nul-terminated
|
||||
bool equals(const char* utf8) {
|
||||
return m_string ? JSC_JSStringIsEqualToUTF8CString(m_context, m_string, utf8) : false;
|
||||
}
|
||||
|
@ -133,10 +120,13 @@ public:
|
|||
return createExpectingAscii(context, ascii.c_str(), ascii.size());
|
||||
}
|
||||
|
||||
// Creates a String wrapper and increases the refcount of the JSStringRef
|
||||
static String ref(JSContextRef context, JSStringRef string) {
|
||||
return String(context, string, false);
|
||||
}
|
||||
|
||||
// Creates a String wrapper that takes over ownership of the string. The
|
||||
// JSStringRef passed in must previously have been created or retained.
|
||||
static String adopt(JSContextRef context, JSStringRef string) {
|
||||
return String(context, string, true);
|
||||
}
|
||||
|
@ -154,6 +144,9 @@ private:
|
|||
JSStringRef m_string;
|
||||
};
|
||||
|
||||
// C++ object wrapper for JSObjectRef. The underlying JSObjectRef can be
|
||||
// optionally protected. You must protect the object if it is ever
|
||||
// heap-allocated, since otherwise you may end up with an invalid reference.
|
||||
class Object : public noncopyable {
|
||||
public:
|
||||
Object(JSContextRef context, JSObjectRef obj) :
|
||||
|
@ -248,11 +241,16 @@ private:
|
|||
Value callAsFunction(JSObjectRef thisObj, int nArgs, const JSValueRef args[]) const;
|
||||
};
|
||||
|
||||
// C++ object wrapper for JSValueRef. The underlying JSValueRef is not
|
||||
// protected, so this class should always be used as a stack-allocated
|
||||
// variable.
|
||||
class Value : public noncopyable {
|
||||
public:
|
||||
__attribute__((visibility("default"))) Value(JSContextRef context, JSValueRef value);
|
||||
__attribute__((visibility("default"))) Value(JSContextRef context, JSStringRef value);
|
||||
__attribute__((visibility("default"))) Value(Value&&);
|
||||
RN_EXPORT Value(JSContextRef context, JSValueRef value);
|
||||
RN_EXPORT Value(JSContextRef context, JSStringRef value);
|
||||
|
||||
RN_EXPORT Value(const Value &o) : Value(o.m_context, o.m_value) {}
|
||||
RN_EXPORT Value(const String &o) : Value(o.context(), o) {}
|
||||
|
||||
Value& operator=(Value&& other) {
|
||||
m_context = other.m_context;
|
||||
|
@ -309,15 +307,13 @@ public:
|
|||
return getType() == kJSTypeObject;
|
||||
}
|
||||
|
||||
Object asObject();
|
||||
Object asObject() const;
|
||||
|
||||
bool isString() const {
|
||||
return getType() == kJSTypeString;
|
||||
}
|
||||
|
||||
String toString() noexcept {
|
||||
return String::adopt(context(), JSC_JSValueToStringCopy(context(), m_value, nullptr));
|
||||
}
|
||||
String toString() const;
|
||||
|
||||
static Value makeError(JSContextRef ctx, const char *error);
|
||||
|
||||
|
@ -333,13 +329,15 @@ public:
|
|||
return Value(ctx, JSC_JSValueMakeNull(ctx));
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) std::string toJSONString(unsigned indent = 0) const;
|
||||
__attribute__((visibility("default"))) static Value fromJSON(JSContextRef ctx, const String& json);
|
||||
__attribute__((visibility("default"))) static Value fromDynamic(JSContextRef ctx, const folly::dynamic& value);
|
||||
__attribute__((visibility("default"))) JSContextRef context() const;
|
||||
protected:
|
||||
RN_EXPORT std::string toJSONString(unsigned indent = 0) const;
|
||||
RN_EXPORT static Value fromJSON(JSContextRef ctx, const String& json);
|
||||
RN_EXPORT static Value fromDynamic(JSContextRef ctx, const folly::dynamic& value);
|
||||
RN_EXPORT JSContextRef context() const;
|
||||
|
||||
private:
|
||||
JSContextRef m_context;
|
||||
JSValueRef m_value;
|
||||
|
||||
static JSValueRef fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue