mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-25 21:05:40 +08:00
Move JSCHelpers.h and Value.h into separate package
Reviewed By: javache Differential Revision: D3950748 fbshipit-source-id: 6315ea07f3217b485aeb4374b5f6e36333957848
This commit is contained in:
committed by
Facebook Github Bot
parent
95cb4ea752
commit
ddb8cb7cf0
@@ -9,7 +9,6 @@ LOCAL_SRC_FILES := \
|
||||
Executor.cpp \
|
||||
Instance.cpp \
|
||||
JSCExecutor.cpp \
|
||||
JSCHelpers.cpp \
|
||||
JSCLegacyProfiler.cpp \
|
||||
JSCLegacyTracing.cpp \
|
||||
JSCMemory.cpp \
|
||||
@@ -21,8 +20,7 @@ LOCAL_SRC_FILES := \
|
||||
ModuleRegistry.cpp \
|
||||
NativeToJsBridge.cpp \
|
||||
Platform.cpp \
|
||||
Value.cpp \
|
||||
Unicode.cpp \
|
||||
JSCUtils.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
||||
@@ -35,6 +33,7 @@ CXX11_FLAGS := -std=c++11
|
||||
LOCAL_CFLAGS += $(CXX11_FLAGS)
|
||||
LOCAL_EXPORT_CPPFLAGS := $(CXX11_FLAGS)
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := jschelpers
|
||||
LOCAL_SHARED_LIBRARIES := libfb libfolly_json libjsc libglog
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -43,3 +42,4 @@ $(call import-module,fb)
|
||||
$(call import-module,folly)
|
||||
$(call import-module,jsc)
|
||||
$(call import-module,glog)
|
||||
$(call import-module,jschelpers)
|
||||
|
||||
@@ -115,7 +115,6 @@ CXXREACT_PUBLIC_HEADERS = [
|
||||
'ExecutorTokenFactory.h',
|
||||
'Instance.h',
|
||||
'JSCExecutor.h',
|
||||
'JSCHelpers.h',
|
||||
'JSCNativeModules.h',
|
||||
'JSCWebWorker.h',
|
||||
'JSModulesUnbundle.h',
|
||||
@@ -124,11 +123,8 @@ CXXREACT_PUBLIC_HEADERS = [
|
||||
'ModuleRegistry.h',
|
||||
'NativeModule.h',
|
||||
'NativeToJsBridge.h',
|
||||
'noncopyable.h',
|
||||
'Platform.h',
|
||||
'SystraceSection.h',
|
||||
'Unicode.h',
|
||||
'Value.h',
|
||||
]
|
||||
|
||||
react_library(
|
||||
@@ -153,6 +149,7 @@ react_library(
|
||||
deps = [
|
||||
':module',
|
||||
'//xplat/fbsystrace:fbsystrace',
|
||||
react_native_xplat_target('jschelpers:jschelpers'),
|
||||
react_native_xplat_target('microprofiler:microprofiler'),
|
||||
],
|
||||
visibility = [ 'PUBLIC' ],
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#include "JSModulesUnbundle.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "SystraceSection.h"
|
||||
#include "Value.h"
|
||||
#include "JSCNativeModules.h"
|
||||
#include "JSCSamplingProfiler.h"
|
||||
#include "JSCUtils.h"
|
||||
#include "JSModulesUnbundle.h"
|
||||
#include "ModuleRegistry.h"
|
||||
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
#include <folly/json.h>
|
||||
#include <folly/Optional.h>
|
||||
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#include "Executor.h"
|
||||
#include "ExecutorToken.h"
|
||||
#include "JSCHelpers.h"
|
||||
#include "Value.h"
|
||||
#include "JSCNativeModules.h"
|
||||
|
||||
namespace facebook {
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
|
||||
#include <JavaScriptCore/JSStringRef.h>
|
||||
#include <folly/String.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include "SystraceSection.h"
|
||||
#include "Value.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
void installGlobalFunction(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectCallAsFunctionCallback callback) {
|
||||
JSStringRef jsName = JSStringCreateWithUTF8CString(name);
|
||||
JSObjectRef functionObj = JSObjectMakeFunctionWithCallback(
|
||||
ctx, jsName, callback);
|
||||
JSObjectRef globalObject = JSContextGetGlobalObject(ctx);
|
||||
JSObjectSetProperty(ctx, globalObject, jsName, functionObj, 0, NULL);
|
||||
JSStringRelease(jsName);
|
||||
}
|
||||
|
||||
void installGlobalProxy(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectGetPropertyCallback callback) {
|
||||
JSClassDefinition proxyClassDefintion = kJSClassDefinitionEmpty;
|
||||
proxyClassDefintion.className = "_FBProxyClass";
|
||||
proxyClassDefintion.getProperty = callback;
|
||||
JSClassRef proxyClass = JSClassCreate(&proxyClassDefintion);
|
||||
|
||||
JSObjectRef proxyObj = JSObjectMake(ctx, proxyClass, nullptr);
|
||||
|
||||
JSObjectRef globalObject = JSContextGetGlobalObject(ctx);
|
||||
JSStringRef jsName = JSStringCreateWithUTF8CString(name);
|
||||
JSObjectSetProperty(ctx, globalObject, jsName, proxyObj, 0, NULL);
|
||||
|
||||
JSStringRelease(jsName);
|
||||
JSClassRelease(proxyClass);
|
||||
}
|
||||
|
||||
JSValueRef makeJSCException(
|
||||
JSContextRef ctx,
|
||||
const char* exception_text) {
|
||||
JSStringRef message = JSStringCreateWithUTF8CString(exception_text);
|
||||
JSValueRef exceptionString = JSValueMakeString(ctx, message);
|
||||
JSStringRelease(message);
|
||||
return JSValueToObject(ctx, exceptionString, NULL);
|
||||
}
|
||||
|
||||
String jsStringFromBigString(const JSBigString& bigstr) {
|
||||
if (bigstr.isAscii()) {
|
||||
return String::createExpectingAscii(bigstr.c_str(), bigstr.size());
|
||||
} else {
|
||||
return String(bigstr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef source) {
|
||||
SystraceSection s("evaluateScript");
|
||||
JSValueRef exn, result;
|
||||
result = JSEvaluateScript(context, script, NULL, source, 0, &exn);
|
||||
if (result == nullptr) {
|
||||
formatAndThrowJSException(context, exn, source);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
JSValueRef evaluateSourceCode(JSContextRef context, JSSourceCodeRef source, JSStringRef sourceURL) {
|
||||
JSValueRef exn, result;
|
||||
result = JSEvaluateSourceCode(context, source, NULL, &exn);
|
||||
if (result == nullptr) {
|
||||
formatAndThrowJSException(context, exn, 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(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 makeJSError(JSContextRef ctx, const char *error) {
|
||||
JSValueRef nestedException = nullptr;
|
||||
JSValueRef args[] = { Value(ctx, String(error)) };
|
||||
JSObjectRef errorObj = JSObjectMakeError(ctx, 1, args, &nestedException);
|
||||
if (nestedException != nullptr) {
|
||||
return std::move(args[0]);
|
||||
}
|
||||
return errorObj;
|
||||
}
|
||||
|
||||
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation) {
|
||||
std::ostringstream msg;
|
||||
try {
|
||||
throw;
|
||||
} catch (const std::bad_alloc& ex) {
|
||||
throw; // We probably shouldn't try to handle this in JS
|
||||
} catch (const std::exception& ex) {
|
||||
msg << "C++ Exception in '" << exceptionLocation << "': " << ex.what();
|
||||
return makeJSError(ctx, msg.str().c_str());
|
||||
} catch (const char* ex) {
|
||||
msg << "C++ Exception (thrown as a char*) in '" << exceptionLocation << "': " << ex;
|
||||
return makeJSError(ctx, msg.str().c_str());
|
||||
} catch (...) {
|
||||
msg << "Unknown C++ Exception in '" << exceptionLocation << "'";
|
||||
return makeJSError(ctx, msg.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, JSObjectRef jsFunctionCause) {
|
||||
try {
|
||||
auto functionName = Object(ctx, jsFunctionCause).getProperty("name").toString().str();
|
||||
return translatePendingCppExceptionToJSError(ctx, functionName.c_str());
|
||||
} catch (...) {
|
||||
return makeJSError(ctx, "Failed to get function name while handling exception");
|
||||
}
|
||||
}
|
||||
|
||||
} }
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Executor.h"
|
||||
#include "Value.h"
|
||||
|
||||
#include <JavaScriptCore/JSContextRef.h>
|
||||
#include <JavaScriptCore/JSObjectRef.h>
|
||||
#include <JavaScriptCore/JSValueRef.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
inline void throwJSExecutionException(const char* msg) {
|
||||
throw JSException(msg);
|
||||
}
|
||||
|
||||
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>
|
||||
inline void throwJSExecutionExceptionWithStack(const char* msg, const char* stack) {
|
||||
throw JSException(msg, stack);
|
||||
}
|
||||
|
||||
void installGlobalFunction(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectCallAsFunctionCallback callback);
|
||||
|
||||
void installGlobalProxy(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectGetPropertyCallback callback);
|
||||
|
||||
JSValueRef makeJSCException(
|
||||
JSContextRef ctx,
|
||||
const char* exception_text);
|
||||
|
||||
String jsStringFromBigString(const JSBigString& bigstr);
|
||||
|
||||
JSValueRef evaluateScript(
|
||||
JSContextRef ctx,
|
||||
JSStringRef script,
|
||||
JSStringRef sourceURL);
|
||||
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
JSValueRef evaluateSourceCode(
|
||||
JSContextRef ctx,
|
||||
JSSourceCodeRef source,
|
||||
JSStringRef sourceURL);
|
||||
#endif
|
||||
|
||||
void formatAndThrowJSException(
|
||||
JSContextRef ctx,
|
||||
JSValueRef exn,
|
||||
JSStringRef sourceURL);
|
||||
|
||||
JSValueRef makeJSError(JSContextRef ctx, const char *error);
|
||||
|
||||
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation);
|
||||
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, JSObjectRef jsFunctionCause);
|
||||
|
||||
template<JSValueRef (method)(JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception)>
|
||||
inline JSObjectCallAsFunctionCallback exceptionWrapMethod() {
|
||||
struct funcWrapper {
|
||||
static JSValueRef call(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef *exception) {
|
||||
try {
|
||||
return (*method)(ctx, function, thisObject, argumentCount, arguments, exception);
|
||||
} catch (...) {
|
||||
*exception = translatePendingCppExceptionToJSError(ctx, function);
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return &funcWrapper::call;
|
||||
}
|
||||
|
||||
} }
|
||||
@@ -7,9 +7,9 @@
|
||||
#include <JavaScriptCore/JavaScript.h>
|
||||
#include <JavaScriptCore/API/JSProfilerPrivate.h>
|
||||
#include <jsc_legacy_profiler.h>
|
||||
#include "JSCHelpers.h"
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
#include "JSCLegacyProfiler.h"
|
||||
#include "Value.h"
|
||||
|
||||
static JSValueRef nativeProfilerStart(
|
||||
JSContextRef ctx,
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
#include <fbsystrace.h>
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
|
||||
#include "JSCTracing.h"
|
||||
|
||||
static const char *ENABLED_FBSYSTRACE_PROFILE_NAME = "__fbsystrace__";
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <JavaScriptCore/API/JSProfilerPrivate.h>
|
||||
#include "JSCHelpers.h"
|
||||
|
||||
#include "Value.h"
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
static JSValueRef nativeCaptureHeap(
|
||||
JSContextRef ctx,
|
||||
@@ -43,7 +42,7 @@ void addNativeMemoryHooks(JSGlobalContextRef ctx) {
|
||||
#ifdef WITH_FB_MEMORY_PROFILING
|
||||
installGlobalFunction(ctx, "nativeCaptureHeap", nativeCaptureHeap);
|
||||
#endif // WITH_FB_MEMORY_PROFILING
|
||||
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "Value.h"
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#include "ModuleRegistry.h"
|
||||
|
||||
namespace facebook {
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#include <JavaScriptCore/JSPerfStats.h>
|
||||
#include <JavaScriptCore/JSValueRef.h>
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
#include "Value.h"
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
static JSValueRef nativeGetHeapStats(
|
||||
JSContextRef ctx,
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <JavaScriptCore/API/JSProfilerPrivate.h>
|
||||
#include "JSCHelpers.h"
|
||||
|
||||
#include "Value.h"
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <fbsystrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "JSCHelpers.h"
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
|
||||
using std::min;
|
||||
|
||||
|
||||
17
ReactCommon/cxxreact/JSCUtils.cpp
Normal file
17
ReactCommon/cxxreact/JSCUtils.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include "JSCUtils.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
String jsStringFromBigString(const JSBigString& bigstr) {
|
||||
if (bigstr.isAscii()) {
|
||||
return String::createExpectingAscii(bigstr.c_str(), bigstr.size());
|
||||
} else {
|
||||
return String(bigstr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
15
ReactCommon/cxxreact/JSCUtils.h
Normal file
15
ReactCommon/cxxreact/JSCUtils.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#include "Executor.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
String jsStringFromBigString(const JSBigString& bigstr);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,11 @@
|
||||
|
||||
#include <folly/Memory.h>
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
#include <jschelpers/JSCHelpers.h>
|
||||
#include <jschelpers/Value.h>
|
||||
#include "MessageQueueThread.h"
|
||||
#include "Platform.h"
|
||||
#include "Value.h"
|
||||
#include "JSCUtils.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
@@ -122,7 +123,7 @@ JSValueRef JSCWebWorker::nativePostMessage(
|
||||
}
|
||||
|
||||
webWorker->postMessageToOwner(msg);
|
||||
|
||||
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <JavaScriptCore/JSValueRef.h>
|
||||
|
||||
#include "Value.h"
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
~JSCWebWorker();
|
||||
|
||||
/**
|
||||
* Post a message to be received by the worker on its thread. This must be called from
|
||||
* Post a message to be received by the worker on its thread. This must be called from
|
||||
* ownerMessageQueueThread_.
|
||||
*/
|
||||
void postMessage(JSValueRef msg);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "noncopyable.h"
|
||||
#include <jschelpers/noncopyable.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#include "Executor.h"
|
||||
#include "ExecutorToken.h"
|
||||
#include "JSCExecutor.h"
|
||||
@@ -16,7 +18,6 @@
|
||||
#include "MessageQueueThread.h"
|
||||
#include "MethodCall.h"
|
||||
#include "NativeModule.h"
|
||||
#include "Value.h"
|
||||
|
||||
namespace folly {
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include "Unicode.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
namespace unicode {
|
||||
namespace {
|
||||
|
||||
// TODO(12827176): Don't duplicate this code here and fbjni.
|
||||
|
||||
const uint16_t kUtf8OneByteBoundary = 0x80;
|
||||
const uint16_t kUtf8TwoBytesBoundary = 0x800;
|
||||
const uint16_t kUtf16HighSubLowBoundary = 0xD800;
|
||||
const uint16_t kUtf16HighSubHighBoundary = 0xDC00;
|
||||
const uint16_t kUtf16LowSubHighBoundary = 0xE000;
|
||||
|
||||
// Calculate how many bytes are needed to convert an UTF16 string into UTF8
|
||||
// UTF16 string
|
||||
size_t utf16toUTF8Length(const uint16_t* utf16String, size_t utf16StringLen) {
|
||||
if (!utf16String || utf16StringLen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t utf8StringLen = 0;
|
||||
auto utf16StringEnd = utf16String + utf16StringLen;
|
||||
auto idx16 = utf16String;
|
||||
while (idx16 < utf16StringEnd) {
|
||||
auto ch = *idx16++;
|
||||
if (ch < kUtf8OneByteBoundary) {
|
||||
utf8StringLen++;
|
||||
} else if (ch < kUtf8TwoBytesBoundary) {
|
||||
utf8StringLen += 2;
|
||||
} else if (
|
||||
(ch >= kUtf16HighSubLowBoundary) && (ch < kUtf16HighSubHighBoundary) &&
|
||||
(idx16 < utf16StringEnd) &&
|
||||
(*idx16 >= kUtf16HighSubHighBoundary) && (*idx16 < kUtf16LowSubHighBoundary)) {
|
||||
utf8StringLen += 4;
|
||||
idx16++;
|
||||
} else {
|
||||
utf8StringLen += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return utf8StringLen;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string utf16toUTF8(const uint16_t* utf16String, size_t utf16StringLen) noexcept {
|
||||
if (!utf16String || utf16StringLen <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string utf8String(utf16toUTF8Length(utf16String, utf16StringLen), '\0');
|
||||
auto idx8 = utf8String.begin();
|
||||
auto idx16 = utf16String;
|
||||
auto utf16StringEnd = utf16String + utf16StringLen;
|
||||
while (idx16 < utf16StringEnd) {
|
||||
auto ch = *idx16++;
|
||||
if (ch < kUtf8OneByteBoundary) {
|
||||
*idx8++ = (ch & 0x7F);
|
||||
} else if (ch < kUtf8TwoBytesBoundary) {
|
||||
*idx8++ = 0b11000000 | (ch >> 6);
|
||||
*idx8++ = 0b10000000 | (ch & 0x3F);
|
||||
} else if (
|
||||
(ch >= kUtf16HighSubLowBoundary) && (ch < kUtf16HighSubHighBoundary) &&
|
||||
(idx16 < utf16StringEnd) &&
|
||||
(*idx16 >= kUtf16HighSubHighBoundary) && (*idx16 < kUtf16LowSubHighBoundary)) {
|
||||
auto ch2 = *idx16++;
|
||||
uint8_t trunc_byte = (((ch >> 6) & 0x0F) + 1);
|
||||
*idx8++ = 0b11110000 | (trunc_byte >> 2);
|
||||
*idx8++ = 0b10000000 | ((trunc_byte & 0x03) << 4) | ((ch >> 2) & 0x0F);
|
||||
*idx8++ = 0b10000000 | ((ch & 0x03) << 4) | ((ch2 >> 6) & 0x0F);
|
||||
*idx8++ = 0b10000000 | (ch2 & 0x3F);
|
||||
} else {
|
||||
*idx8++ = 0b11100000 | (ch >> 12);
|
||||
*idx8++ = 0b10000000 | ((ch >> 6) & 0x3F);
|
||||
*idx8++ = 0b10000000 | (ch & 0x3F);
|
||||
}
|
||||
}
|
||||
|
||||
return utf8String;
|
||||
}
|
||||
|
||||
} // namespace unicode
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,14 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
namespace unicode {
|
||||
std::string utf16toUTF8(const uint16_t* utf16, size_t length) noexcept;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#include <folly/json.h>
|
||||
|
||||
#include "Value.h"
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
|
||||
// See the comment under Value::fromDynamic()
|
||||
#if !defined(__APPLE__) && defined(WITH_FB_JSC_TUNING)
|
||||
#define USE_FAST_FOLLY_DYNAMIC_CONVERSION 1
|
||||
#else
|
||||
#define USE_FAST_FOLLY_DYNAMIC_CONVERSION 0
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
Value::Value(JSContextRef context, JSValueRef value) :
|
||||
m_context(context),
|
||||
m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
Value::Value(JSContextRef context, JSStringRef str) :
|
||||
m_context(context),
|
||||
m_value(JSValueMakeString(context, str))
|
||||
{
|
||||
}
|
||||
|
||||
Value::Value(Value&& other) :
|
||||
m_context(other.m_context),
|
||||
m_value(other.m_value)
|
||||
{
|
||||
other.m_value = nullptr;
|
||||
}
|
||||
|
||||
JSContextRef Value::context() const {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
std::string Value::toJSONString(unsigned indent) const {
|
||||
JSValueRef exn;
|
||||
auto stringToAdopt = 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());
|
||||
}
|
||||
return String::adopt(stringToAdopt).str();
|
||||
}
|
||||
|
||||
/* static */
|
||||
Value Value::fromJSON(JSContextRef ctx, const String& json) {
|
||||
auto result = JSValueMakeFromJSONString(ctx, json);
|
||||
if (!result) {
|
||||
throwJSExecutionException("Failed to create String from JSON: %s", json.str().c_str());
|
||||
}
|
||||
return Value(ctx, result);
|
||||
}
|
||||
|
||||
JSValueRef Value::fromDynamic(JSContextRef ctx, const folly::dynamic& value) {
|
||||
// JavaScriptCore's iOS APIs have their own version of this direct conversion.
|
||||
// In addition, using this requires exposing some of JSC's private APIs,
|
||||
// so it's limited to non-apple platforms and to builds that use the custom JSC.
|
||||
// Otherwise, we use the old way of converting through JSON.
|
||||
#if USE_FAST_FOLLY_DYNAMIC_CONVERSION
|
||||
// Defer GC during the creation of the JSValue, as we don't want
|
||||
// intermediate objects to be collected.
|
||||
// We could use JSValueProtect(), but it will make the process much slower.
|
||||
JSDeferredGCRef deferGC = JSDeferGarbageCollection(ctx);
|
||||
// Set a global lock for the whole process,
|
||||
// instead of re-acquiring the lock for each operation.
|
||||
JSLock(ctx);
|
||||
JSValueRef jsVal = Value::fromDynamicInner(ctx, value);
|
||||
JSUnlock(ctx);
|
||||
JSResumeGarbageCollection(ctx, deferGC);
|
||||
return jsVal;
|
||||
#else
|
||||
auto json = folly::toJson(value);
|
||||
return fromJSON(ctx, String(json.c_str()));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSValueRef Value::fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj) {
|
||||
switch (obj.type()) {
|
||||
// For premitive types (and strings), just create and return an equivalent JSValue
|
||||
case folly::dynamic::Type::NULLT:
|
||||
return JSValueMakeNull(ctx);
|
||||
|
||||
case folly::dynamic::Type::BOOL:
|
||||
return JSValueMakeBoolean(ctx, obj.getBool());
|
||||
|
||||
case folly::dynamic::Type::DOUBLE:
|
||||
return JSValueMakeNumber(ctx, obj.getDouble());
|
||||
|
||||
case folly::dynamic::Type::INT64:
|
||||
return JSValueMakeNumber(ctx, obj.asDouble());
|
||||
|
||||
case folly::dynamic::Type::STRING:
|
||||
return JSValueMakeString(ctx, String(obj.getString().c_str()));
|
||||
|
||||
case folly::dynamic::Type::ARRAY: {
|
||||
// Collect JSValue for every element in the array
|
||||
JSValueRef vals[obj.size()];
|
||||
for (size_t i = 0; i < obj.size(); ++i) {
|
||||
vals[i] = fromDynamicInner(ctx, obj[i]);
|
||||
}
|
||||
// Create a JSArray with the values
|
||||
JSValueRef arr = JSObjectMakeArray(ctx, obj.size(), vals, nullptr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
case folly::dynamic::Type::OBJECT: {
|
||||
// Create an empty object
|
||||
JSObjectRef jsObj = JSObjectMake(ctx, nullptr, nullptr);
|
||||
// Create a JSValue for each of the object's children and set them in the object
|
||||
for (auto it = obj.items().begin(); it != obj.items().end(); ++it) {
|
||||
JSObjectSetProperty(
|
||||
ctx,
|
||||
jsObj,
|
||||
String(it->first.asString().c_str()),
|
||||
fromDynamicInner(ctx, it->second),
|
||||
kJSPropertyAttributeNone,
|
||||
nullptr);
|
||||
}
|
||||
return jsObj;
|
||||
}
|
||||
default:
|
||||
// Assert not reached
|
||||
LOG(FATAL) << "Trying to convert a folly object of unsupported type.";
|
||||
return JSValueMakeNull(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
Object Value::asObject() {
|
||||
JSValueRef exn;
|
||||
JSObjectRef jsObj = 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());
|
||||
}
|
||||
Object ret = Object(context(), jsObj);
|
||||
m_value = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Object::operator Value() const {
|
||||
return Value(m_context, m_obj);
|
||||
}
|
||||
|
||||
Value Object::callAsFunction(std::initializer_list<JSValueRef> args) const {
|
||||
return callAsFunction(nullptr, args.size(), args.begin());
|
||||
}
|
||||
|
||||
Value Object::callAsFunction(const Object& thisObj, std::initializer_list<JSValueRef> args) const {
|
||||
return callAsFunction((JSObjectRef) thisObj, args.size(), args.begin());
|
||||
}
|
||||
|
||||
Value Object::callAsFunction(int nArgs, const JSValueRef args[]) const {
|
||||
return callAsFunction(nullptr, nArgs, args);
|
||||
}
|
||||
|
||||
Value Object::callAsFunction(const Object& thisObj, int nArgs, const JSValueRef args[]) const {
|
||||
return callAsFunction((JSObjectRef) thisObj, nArgs, args);
|
||||
}
|
||||
|
||||
Value Object::callAsFunction(JSObjectRef thisObj, int nArgs, const JSValueRef args[]) const {
|
||||
JSValueRef exn;
|
||||
JSValueRef result = 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());
|
||||
}
|
||||
return Value(m_context, result);
|
||||
}
|
||||
|
||||
Object Object::callAsConstructor(std::initializer_list<JSValueRef> args) const {
|
||||
JSValueRef exn;
|
||||
JSObjectRef result = 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());
|
||||
}
|
||||
return Object(m_context, result);
|
||||
}
|
||||
|
||||
Value Object::getProperty(const String& propName) const {
|
||||
JSValueRef exn;
|
||||
JSValueRef property = 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());
|
||||
}
|
||||
return Value(m_context, property);
|
||||
}
|
||||
|
||||
Value Object::getPropertyAtIndex(unsigned index) const {
|
||||
JSValueRef exn;
|
||||
JSValueRef property = 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());
|
||||
}
|
||||
return Value(m_context, property);
|
||||
}
|
||||
|
||||
Value Object::getProperty(const char *propName) const {
|
||||
return getProperty(String(propName));
|
||||
}
|
||||
|
||||
void Object::setProperty(const String& propName, const Value& value) const {
|
||||
JSValueRef exn = NULL;
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void Object::setProperty(const char *propName, const Value& value) const {
|
||||
setProperty(String(propName), value);
|
||||
}
|
||||
|
||||
std::vector<String> Object::getPropertyNames() const {
|
||||
auto namesRef = JSObjectCopyPropertyNames(m_context, m_obj);
|
||||
size_t count = JSPropertyNameArrayGetCount(namesRef);
|
||||
std::vector<String> names;
|
||||
names.reserve(count);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
names.emplace_back(String::ref(JSPropertyNameArrayGetNameAtIndex(namesRef, i)));
|
||||
}
|
||||
JSPropertyNameArrayRelease(namesRef);
|
||||
return names;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> Object::toJSONMap() const {
|
||||
std::unordered_map<std::string, std::string> map;
|
||||
auto namesRef = JSObjectCopyPropertyNames(m_context, m_obj);
|
||||
size_t count = JSPropertyNameArrayGetCount(namesRef);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
auto key = String::ref(JSPropertyNameArrayGetNameAtIndex(namesRef, i));
|
||||
map.emplace(key.str(), getProperty(key).toJSONString());
|
||||
}
|
||||
JSPropertyNameArrayRelease(namesRef);
|
||||
return map;
|
||||
}
|
||||
|
||||
/* static */
|
||||
Object Object::create(JSContextRef ctx) {
|
||||
JSObjectRef newObj = JSObjectMake(
|
||||
ctx,
|
||||
NULL, // create instance of default object class
|
||||
NULL); // no private data
|
||||
return Object(ctx, newObj);
|
||||
}
|
||||
|
||||
} }
|
||||
@@ -1,308 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <JavaScriptCore/JSContextRef.h>
|
||||
#include <JavaScriptCore/JSObjectRef.h>
|
||||
#include <JavaScriptCore/JSStringRef.h>
|
||||
#include <JavaScriptCore/JSValueRef.h>
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#include "noncopyable.h"
|
||||
#include "Unicode.h"
|
||||
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
#include <jsc_stringref.h>
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class Value;
|
||||
class Context;
|
||||
|
||||
class JSException : public std::runtime_error {
|
||||
public:
|
||||
explicit JSException(const char* msg)
|
||||
: std::runtime_error(msg)
|
||||
, stack_("") {}
|
||||
|
||||
JSException(const char* msg, const char* stack)
|
||||
: std::runtime_error(msg)
|
||||
, stack_(stack) {}
|
||||
|
||||
const std::string& getStack() const {
|
||||
return stack_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string stack_;
|
||||
};
|
||||
|
||||
|
||||
class String : public noncopyable {
|
||||
public:
|
||||
explicit String(const char* utf8) :
|
||||
m_string(JSStringCreateWithUTF8CString(utf8))
|
||||
{}
|
||||
|
||||
String(String&& other) :
|
||||
m_string(other.m_string)
|
||||
{
|
||||
other.m_string = nullptr;
|
||||
}
|
||||
|
||||
String(const String& other) :
|
||||
m_string(other.m_string)
|
||||
{
|
||||
if (m_string) {
|
||||
JSStringRetain(m_string);
|
||||
}
|
||||
}
|
||||
|
||||
~String() {
|
||||
if (m_string) {
|
||||
JSStringRelease(m_string);
|
||||
}
|
||||
}
|
||||
|
||||
operator JSStringRef() const {
|
||||
return m_string;
|
||||
}
|
||||
|
||||
// Length in characters
|
||||
size_t length() const {
|
||||
return JSStringGetLength(m_string);
|
||||
}
|
||||
|
||||
// Length in bytes of a null-terminated utf8 encoded value
|
||||
size_t utf8Size() const {
|
||||
return JSStringGetMaximumUTF8CStringSize(m_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* JavaScriptCore is built with strict utf16 -> utf8 conversion.
|
||||
* This means if JSC's built-in conversion function encounters a JavaScript
|
||||
* string which contains half of a 32-bit UTF-16 symbol, it produces an error
|
||||
* rather than returning a string.
|
||||
*
|
||||
* Instead of relying on this, we use our own utf16 -> utf8 conversion function
|
||||
* which is more lenient and always returns a string. When an invalid UTF-16
|
||||
* string is provided, it'll likely manifest as a rendering glitch in the app for
|
||||
* the invalid symbol.
|
||||
*
|
||||
* For details on JavaScript's unicode support see:
|
||||
* https://mathiasbynens.be/notes/javascript-unicode
|
||||
*/
|
||||
std::string str() const {
|
||||
const JSChar* utf16 = JSStringGetCharactersPtr(m_string);
|
||||
int stringLength = JSStringGetLength(m_string);
|
||||
return unicode::utf16toUTF8(utf16, stringLength);
|
||||
}
|
||||
|
||||
// Assumes that utf8 is null terminated
|
||||
bool equals(const char* utf8) {
|
||||
return JSStringIsEqualToUTF8CString(m_string, utf8);
|
||||
}
|
||||
|
||||
// This assumes ascii is nul-terminated.
|
||||
static String createExpectingAscii(const char* ascii, size_t len) {
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
return String(JSStringCreateWithUTF8CStringExpectAscii(ascii, len), true);
|
||||
#else
|
||||
return String(JSStringCreateWithUTF8CString(ascii), true);
|
||||
#endif
|
||||
}
|
||||
|
||||
static String createExpectingAscii(std::string const &ascii) {
|
||||
return createExpectingAscii(ascii.c_str(), ascii.size());
|
||||
}
|
||||
|
||||
static String ref(JSStringRef string) {
|
||||
return String(string, false);
|
||||
}
|
||||
|
||||
static String adopt(JSStringRef string) {
|
||||
return String(string, true);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit String(JSStringRef string, bool adopt) :
|
||||
m_string(string)
|
||||
{
|
||||
if (!adopt && string) {
|
||||
JSStringRetain(string);
|
||||
}
|
||||
}
|
||||
|
||||
JSStringRef m_string;
|
||||
};
|
||||
|
||||
class Object : public noncopyable {
|
||||
public:
|
||||
Object(JSContextRef context, JSObjectRef obj) :
|
||||
m_context(context),
|
||||
m_obj(obj)
|
||||
{}
|
||||
|
||||
Object(Object&& other) :
|
||||
m_context(other.m_context),
|
||||
m_obj(other.m_obj),
|
||||
m_isProtected(other.m_isProtected) {
|
||||
other.m_obj = nullptr;
|
||||
other.m_isProtected = false;
|
||||
}
|
||||
|
||||
~Object() {
|
||||
if (m_isProtected && m_obj) {
|
||||
JSValueUnprotect(m_context, m_obj);
|
||||
}
|
||||
}
|
||||
|
||||
Object& operator=(Object&& other) {
|
||||
std::swap(m_context, other.m_context);
|
||||
std::swap(m_obj, other.m_obj);
|
||||
std::swap(m_isProtected, other.m_isProtected);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator JSObjectRef() const {
|
||||
return m_obj;
|
||||
}
|
||||
|
||||
operator Value() const;
|
||||
|
||||
bool isFunction() const {
|
||||
return JSObjectIsFunction(m_context, m_obj);
|
||||
}
|
||||
|
||||
Value callAsFunction(std::initializer_list<JSValueRef> args) const;
|
||||
Value callAsFunction(const Object& thisObj, std::initializer_list<JSValueRef> args) const;
|
||||
Value callAsFunction(int nArgs, const JSValueRef args[]) const;
|
||||
Value callAsFunction(const Object& thisObj, int nArgs, const JSValueRef args[]) const;
|
||||
|
||||
Object callAsConstructor(std::initializer_list<JSValueRef> args) const;
|
||||
|
||||
Value getProperty(const String& propName) const;
|
||||
Value getProperty(const char *propName) const;
|
||||
Value getPropertyAtIndex(unsigned index) const;
|
||||
void setProperty(const String& propName, const Value& value) const;
|
||||
void setProperty(const char *propName, const Value& value) const;
|
||||
std::vector<String> getPropertyNames() const;
|
||||
std::unordered_map<std::string, std::string> toJSONMap() const;
|
||||
|
||||
void makeProtected() {
|
||||
if (!m_isProtected && m_obj) {
|
||||
JSValueProtect(m_context, m_obj);
|
||||
m_isProtected = true;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ReturnType>
|
||||
ReturnType* getPrivate() const {
|
||||
return static_cast<ReturnType*>(JSObjectGetPrivate(m_obj));
|
||||
}
|
||||
|
||||
JSContextRef context() const {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
static Object getGlobalObject(JSContextRef ctx) {
|
||||
auto globalObj = JSContextGetGlobalObject(ctx);
|
||||
return Object(ctx, globalObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the default object class.
|
||||
*/
|
||||
static Object create(JSContextRef ctx);
|
||||
|
||||
private:
|
||||
JSContextRef m_context;
|
||||
JSObjectRef m_obj;
|
||||
bool m_isProtected = false;
|
||||
|
||||
Value callAsFunction(JSObjectRef thisObj, int nArgs, const JSValueRef args[]) const;
|
||||
};
|
||||
|
||||
class Value : public noncopyable {
|
||||
public:
|
||||
Value(JSContextRef context, JSValueRef value);
|
||||
Value(JSContextRef context, JSStringRef value);
|
||||
Value(Value&&);
|
||||
|
||||
operator JSValueRef() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
JSType getType() const {
|
||||
return JSValueGetType(m_context, m_value);
|
||||
}
|
||||
|
||||
bool isBoolean() const {
|
||||
return JSValueIsBoolean(context(), m_value);
|
||||
}
|
||||
|
||||
bool asBoolean() const {
|
||||
return JSValueToBoolean(context(), m_value);
|
||||
}
|
||||
|
||||
bool isNumber() const {
|
||||
return JSValueIsNumber(context(), m_value);
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return JSValueIsNull(context(), m_value);
|
||||
}
|
||||
|
||||
bool isUndefined() const {
|
||||
return JSValueIsUndefined(context(), m_value);
|
||||
}
|
||||
|
||||
double asNumber() const {
|
||||
if (isNumber()) {
|
||||
return JSValueToNumber(context(), m_value, nullptr);
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t asInteger() const {
|
||||
return static_cast<int32_t>(asNumber());
|
||||
}
|
||||
|
||||
uint32_t asUnsignedInteger() const {
|
||||
return static_cast<uint32_t>(asNumber());
|
||||
}
|
||||
|
||||
bool isObject() const {
|
||||
return JSValueIsObject(context(), m_value);
|
||||
}
|
||||
|
||||
Object asObject();
|
||||
|
||||
bool isString() const {
|
||||
return JSValueIsString(context(), m_value);
|
||||
}
|
||||
|
||||
String toString() noexcept {
|
||||
return String::adopt(JSValueToStringCopy(context(), m_value, nullptr));
|
||||
}
|
||||
|
||||
std::string toJSONString(unsigned indent = 0) const;
|
||||
static Value fromJSON(JSContextRef ctx, const String& json);
|
||||
static JSValueRef fromDynamic(JSContextRef ctx, const folly::dynamic& value);
|
||||
JSContextRef context() const;
|
||||
protected:
|
||||
JSContextRef m_context;
|
||||
JSValueRef m_value;
|
||||
static JSValueRef fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj);
|
||||
};
|
||||
|
||||
} }
|
||||
@@ -1,12 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
struct noncopyable {
|
||||
noncopyable(const noncopyable&) = delete;
|
||||
noncopyable& operator=(const noncopyable&) = delete;
|
||||
protected:
|
||||
noncopyable() = default;
|
||||
};
|
||||
}}
|
||||
@@ -37,6 +37,7 @@ if THIS_IS_FBOBJC:
|
||||
deps = [
|
||||
'//xplat/third-party/gmock:gtest',
|
||||
react_native_xplat_target('cxxreact:bridge'),
|
||||
react_native_xplat_target('jschelpers:jschelpers'),
|
||||
],
|
||||
visibility = [react_native_xplat_target('cxxreact/...')],
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <string>
|
||||
#include <gtest/gtest.h>
|
||||
#include <folly/json.h>
|
||||
#include <cxxreact/Value.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#ifdef WITH_FBJSCEXTENSION
|
||||
#undef ASSERT
|
||||
@@ -105,4 +105,3 @@ TEST(Value, BadUtf16) {
|
||||
JSGlobalContextRelease(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user