Remove jschelpers and privatedata
Summary: JSI doesn't use any of this. Reviewed By: RSNara Differential Revision: D10229167 fbshipit-source-id: 9eaa288a1d62bafb3ff0626f9f8430e699fdad4a
This commit is contained in:
parent
c49d3653ef
commit
00381920c6
|
@ -147,6 +147,5 @@ rn_xplat_cxx_library(
|
|||
react_native_xplat_target("microprofiler:microprofiler"),
|
||||
"xplat//folly:optional",
|
||||
"xplat//third-party/glog:glog",
|
||||
react_native_xplat_target("privatedata:privatedata"),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := jschelpers
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
JSCHelpers.cpp \
|
||||
Unicode.cpp \
|
||||
Value.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
-DLOG_TAG=\"ReactNative\"
|
||||
|
||||
LOCAL_CFLAGS += -fexceptions -frtti
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libfolly_json libjsc libglog
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
$(call import-module,folly)
|
||||
$(call import-module,jsc)
|
||||
$(call import-module,glog)
|
||||
$(call import-module,privatedata)
|
|
@ -1,73 +0,0 @@
|
|||
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "ANDROID_JSC_INTERNAL_DEPS", "APPLE", "APPLE_JSC_INTERNAL_DEPS", "react_native_xplat_target", "rn_xplat_cxx_library")
|
||||
|
||||
EXPORTED_HEADERS = [
|
||||
"JavaScriptCore.h",
|
||||
"JSCHelpers.h",
|
||||
"JSCWrapper.h",
|
||||
"noncopyable.h",
|
||||
"Unicode.h",
|
||||
"Value.h",
|
||||
]
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "jscinternalhelpers",
|
||||
srcs = glob(
|
||||
["*.cpp"],
|
||||
exclude = ["systemJSCWrapper.cpp"],
|
||||
),
|
||||
headers = glob(
|
||||
["*.h"],
|
||||
exclude = EXPORTED_HEADERS,
|
||||
),
|
||||
header_namespace = "",
|
||||
exported_headers = dict([
|
||||
(
|
||||
"jschelpers/%s" % header,
|
||||
header,
|
||||
)
|
||||
for header in EXPORTED_HEADERS
|
||||
]),
|
||||
compiler_flags = [
|
||||
"-Wall",
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-fvisibility=hidden",
|
||||
"-std=c++1y",
|
||||
],
|
||||
fbandroid_deps = ANDROID_JSC_INTERNAL_DEPS,
|
||||
fbobjc_deps = APPLE_JSC_INTERNAL_DEPS,
|
||||
force_static = True,
|
||||
platforms = (ANDROID, APPLE),
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
"xplat//folly:molly",
|
||||
"xplat//third-party/glog:glog",
|
||||
react_native_xplat_target("privatedata:privatedata"),
|
||||
],
|
||||
exported_deps = [
|
||||
react_native_xplat_target("privatedata:privatedata"),
|
||||
],
|
||||
)
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "jschelpers",
|
||||
srcs = [],
|
||||
compiler_flags = [
|
||||
"-Wall",
|
||||
"-fexceptions",
|
||||
"-fvisibility=hidden",
|
||||
"-std=c++1y",
|
||||
],
|
||||
fbobjc_frameworks = [
|
||||
"$SDKROOT/System/Library/Frameworks/JavaScriptCore.framework",
|
||||
],
|
||||
fbobjc_srcs = ["systemJSCWrapper.cpp"],
|
||||
force_static = True,
|
||||
platforms = (ANDROID, APPLE),
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [":jscinternalhelpers"],
|
||||
)
|
|
@ -1,299 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
#include <fbsystrace.h>
|
||||
#endif
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "JavaScriptCore.h"
|
||||
#include "Value.h"
|
||||
#include <privatedata/PrivateDataBase.h>
|
||||
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
#undef ASSERT
|
||||
#undef WTF_EXPORT_PRIVATE
|
||||
|
||||
#include <JavaScriptCore/config.h>
|
||||
#include <wtf/WTFThreadData.h>
|
||||
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
namespace {
|
||||
|
||||
class JSFunctionPrivateData : public PrivateDataBase {
|
||||
public:
|
||||
explicit JSFunctionPrivateData(JSFunction&& function) : jsFunction_{std::move(function)} {}
|
||||
|
||||
JSFunction& getJSFunction() {
|
||||
return jsFunction_;
|
||||
}
|
||||
|
||||
private:
|
||||
JSFunction jsFunction_;
|
||||
};
|
||||
|
||||
JSValueRef functionCaller(
|
||||
JSContextRef ctx,
|
||||
JSObjectRef function,
|
||||
JSObjectRef thisObject,
|
||||
size_t argumentCount,
|
||||
const JSValueRef arguments[],
|
||||
JSValueRef* exception) {
|
||||
const bool isCustomJSC = isCustomJSCPtr(ctx);
|
||||
auto* privateData = PrivateDataBase::cast<JSFunctionPrivateData>(
|
||||
JSC_JSObjectGetPrivate(isCustomJSC, function));
|
||||
return (privateData->getJSFunction())(ctx, thisObject, argumentCount, arguments);
|
||||
}
|
||||
|
||||
JSClassRef createFuncClass(JSContextRef ctx) {
|
||||
JSClassDefinition definition = kJSClassDefinitionEmpty;
|
||||
definition.attributes |= kJSClassAttributeNoAutomaticPrototype;
|
||||
|
||||
// Need to duplicate the two different finalizer blocks, since there's no way
|
||||
// for it to capture this static information.
|
||||
const bool isCustomJSC = isCustomJSCPtr(ctx);
|
||||
if (isCustomJSC) {
|
||||
definition.finalize = [](JSObjectRef object) {
|
||||
auto* privateData = PrivateDataBase::cast<JSFunctionPrivateData>(
|
||||
JSC_JSObjectGetPrivate(true, object));
|
||||
delete privateData;
|
||||
};
|
||||
} else {
|
||||
definition.finalize = [](JSObjectRef object) {
|
||||
auto* privateData = PrivateDataBase::cast<JSFunctionPrivateData>(
|
||||
JSC_JSObjectGetPrivate(false, object));
|
||||
delete privateData;
|
||||
};
|
||||
}
|
||||
definition.callAsFunction = exceptionWrapMethod<&functionCaller>();
|
||||
|
||||
return JSC_JSClassCreate(isCustomJSC, &definition);
|
||||
}
|
||||
|
||||
JSObjectRef makeFunction(
|
||||
JSContextRef ctx,
|
||||
JSStringRef name,
|
||||
JSFunction function) {
|
||||
static JSClassRef kClassDef = NULL, kCustomJSCClassDef = NULL;
|
||||
JSClassRef *classRef = isCustomJSCPtr(ctx) ? &kCustomJSCClassDef : &kClassDef;
|
||||
if (!*classRef) {
|
||||
*classRef = createFuncClass(ctx);
|
||||
}
|
||||
|
||||
// dealloc in kClassDef.finalize
|
||||
JSFunctionPrivateData *functionDataPtr = new JSFunctionPrivateData(std::move(function));
|
||||
auto functionObject = Object(ctx, JSC_JSObjectMake(ctx, *classRef, functionDataPtr));
|
||||
functionObject.setProperty("name", Value(ctx, name));
|
||||
return functionObject;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void JSException::buildMessage(JSContextRef ctx, JSValueRef exn, JSStringRef sourceURL, const char* errorMsg) {
|
||||
std::ostringstream msgBuilder;
|
||||
if (errorMsg && strlen(errorMsg) > 0) {
|
||||
msgBuilder << errorMsg << ": ";
|
||||
}
|
||||
|
||||
Object exnObject = Value(ctx, exn).asObject();
|
||||
Value exnMessage = exnObject.getProperty("message");
|
||||
msgBuilder << (exnMessage.isString() ? exnMessage : (Value)exnObject).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() : "";
|
||||
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;
|
||||
msg_ = std::move(exceptionText);
|
||||
|
||||
Value jsStack = exnObject.getProperty("stack");
|
||||
if (jsStack.isString()) {
|
||||
auto stackText = jsStack.toString().str();
|
||||
LOG(ERROR) << "Got JS Stack: " << stackText;
|
||||
stack_ = std::move(stackText);
|
||||
}
|
||||
}
|
||||
|
||||
namespace ExceptionHandling {
|
||||
|
||||
PlatformErrorExtractor platformErrorExtractor;
|
||||
|
||||
}
|
||||
|
||||
JSObjectRef makeFunction(
|
||||
JSContextRef ctx,
|
||||
const char* name,
|
||||
JSFunction function) {
|
||||
return makeFunction(ctx, String(ctx, name), std::move(function));
|
||||
}
|
||||
|
||||
void installGlobalFunction(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSFunction function) {
|
||||
auto jsName = String(ctx, name);
|
||||
auto functionObj = makeFunction(ctx, jsName, std::move(function));
|
||||
Object::getGlobalObject(ctx).setProperty(jsName, Value(ctx, functionObj));
|
||||
}
|
||||
|
||||
JSObjectRef makeFunction(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectCallAsFunctionCallback callback) {
|
||||
auto jsName = String(ctx, name);
|
||||
return JSC_JSObjectMakeFunctionWithCallback(ctx, jsName, callback);
|
||||
}
|
||||
|
||||
void installGlobalFunction(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectCallAsFunctionCallback callback) {
|
||||
String jsName(ctx, name);
|
||||
JSObjectRef functionObj = JSC_JSObjectMakeFunctionWithCallback(
|
||||
ctx, jsName, callback);
|
||||
Object::getGlobalObject(ctx).setProperty(jsName, Value(ctx, functionObj));
|
||||
}
|
||||
|
||||
void installGlobalProxy(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectGetPropertyCallback callback) {
|
||||
JSClassDefinition proxyClassDefintion = kJSClassDefinitionEmpty;
|
||||
proxyClassDefintion.attributes |= kJSClassAttributeNoAutomaticPrototype;
|
||||
proxyClassDefintion.getProperty = callback;
|
||||
|
||||
const bool isCustomJSC = isCustomJSCPtr(ctx);
|
||||
JSClassRef proxyClass = JSC_JSClassCreate(isCustomJSC, &proxyClassDefintion);
|
||||
JSObjectRef proxyObj = JSC_JSObjectMake(ctx, proxyClass, nullptr);
|
||||
JSC_JSClassRelease(isCustomJSC, proxyClass);
|
||||
|
||||
Object::getGlobalObject(ctx).setProperty(name, Value(ctx, proxyObj));
|
||||
}
|
||||
|
||||
void removeGlobal(JSGlobalContextRef ctx, const char* name) {
|
||||
Object::getGlobalObject(ctx).setProperty(name, Value::makeUndefined(ctx));
|
||||
}
|
||||
|
||||
JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef sourceURL) {
|
||||
JSValueRef exn, result;
|
||||
result = JSC_JSEvaluateScript(context, script, NULL, sourceURL, 0, &exn);
|
||||
if (result == nullptr) {
|
||||
throw JSException(context, exn, sourceURL);
|
||||
}
|
||||
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) {
|
||||
throw JSException(context, exn, sourceURL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
JSContextLock::JSContextLock(JSGlobalContextRef ctx) noexcept
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
: ctx_(ctx),
|
||||
globalLock_(PTHREAD_MUTEX_INITIALIZER)
|
||||
{
|
||||
WTFThreadData& threadData = wtfThreadData();
|
||||
|
||||
// Code below is responsible for acquiring locks. It should execute
|
||||
// atomically, thus none of the functions invoked from now on are allowed to
|
||||
// throw an exception
|
||||
try {
|
||||
if (!threadData.isDebuggerThread()) {
|
||||
CHECK(0 == pthread_mutex_lock(&globalLock_));
|
||||
}
|
||||
JSLock(ctx_);
|
||||
} catch (...) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#else
|
||||
{}
|
||||
#endif
|
||||
|
||||
|
||||
JSContextLock::~JSContextLock() noexcept {
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
WTFThreadData& threadData = wtfThreadData();
|
||||
|
||||
JSUnlock(ctx_);
|
||||
if (!threadData.isDebuggerThread()) {
|
||||
CHECK(0 == pthread_mutex_unlock(&globalLock_));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation) {
|
||||
try {
|
||||
throw;
|
||||
} catch (const std::bad_alloc& ex) {
|
||||
throw; // We probably shouldn't try to handle this in JS
|
||||
} catch (const std::exception& ex) {
|
||||
if (ExceptionHandling::platformErrorExtractor) {
|
||||
auto extractedEror = ExceptionHandling::platformErrorExtractor(ex, exceptionLocation);
|
||||
if (extractedEror.message.length() > 0) {
|
||||
return Value::makeError(ctx, extractedEror.message.c_str(), extractedEror.stack.c_str());
|
||||
}
|
||||
}
|
||||
auto msg = folly::to<std::string>("C++ exception in '", exceptionLocation, "'\n\n", ex.what());
|
||||
return Value::makeError(ctx, msg.c_str());
|
||||
} catch (const char* ex) {
|
||||
auto msg = folly::to<std::string>("C++ exception (thrown as a char*) in '", exceptionLocation, "'\n\n", ex);
|
||||
return Value::makeError(ctx, msg.c_str());
|
||||
} catch (...) {
|
||||
auto msg = folly::to<std::string>("Unknown C++ exception in '", exceptionLocation, "'");
|
||||
return Value::makeError(ctx, msg.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 Value::makeError(ctx, "Failed to translate native exception");
|
||||
}
|
||||
}
|
||||
|
||||
} }
|
|
@ -1,149 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <jschelpers/JavaScriptCore.h>
|
||||
#include <jschelpers/Value.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class RN_EXPORT JSException : public std::exception {
|
||||
public:
|
||||
explicit JSException(const char* msg)
|
||||
: msg_(msg) {}
|
||||
|
||||
explicit JSException(JSContextRef ctx, JSValueRef exn, const char* msg) {
|
||||
buildMessage(ctx, exn, nullptr, msg);
|
||||
}
|
||||
|
||||
explicit JSException(JSContextRef ctx, JSValueRef exn, JSStringRef sourceURL) {
|
||||
buildMessage(ctx, exn, 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_;
|
||||
|
||||
void buildMessage(JSContextRef ctx, JSValueRef exn, JSStringRef sourceURL, const char* errorMsg);
|
||||
};
|
||||
|
||||
namespace ExceptionHandling {
|
||||
struct ExtractedEror {
|
||||
std::string message;
|
||||
// Stacktrace formatted like JS stack
|
||||
// method@filename[:line[:column]]
|
||||
std::string stack;
|
||||
};
|
||||
typedef ExtractedEror(*PlatformErrorExtractor)(const std::exception &ex, const char *context);
|
||||
extern PlatformErrorExtractor platformErrorExtractor;
|
||||
}
|
||||
|
||||
using JSFunction = std::function<JSValueRef(JSContextRef, JSObjectRef, size_t, const JSValueRef[])>;
|
||||
|
||||
JSObjectRef makeFunction(
|
||||
JSContextRef ctx,
|
||||
const char* name,
|
||||
JSFunction function);
|
||||
|
||||
RN_EXPORT void installGlobalFunction(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSFunction function);
|
||||
|
||||
JSObjectRef makeFunction(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectCallAsFunctionCallback callback);
|
||||
|
||||
RN_EXPORT void installGlobalFunction(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectCallAsFunctionCallback callback);
|
||||
|
||||
void installGlobalProxy(
|
||||
JSGlobalContextRef ctx,
|
||||
const char* name,
|
||||
JSObjectGetPropertyCallback callback);
|
||||
|
||||
void removeGlobal(JSGlobalContextRef ctx, const char* name);
|
||||
|
||||
JSValueRef evaluateScript(
|
||||
JSContextRef ctx,
|
||||
JSStringRef script,
|
||||
JSStringRef sourceURL);
|
||||
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
JSValueRef evaluateSourceCode(
|
||||
JSContextRef ctx,
|
||||
JSSourceCodeRef source,
|
||||
JSStringRef sourceURL);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A lock for protecting accesses to the JSGlobalContext
|
||||
* This will be a no-op for most compilations, where #if WITH_FBJSCEXTENSIONS is false,
|
||||
* but avoids deadlocks in execution environments with advanced locking requirements,
|
||||
* particularly with uses of the pthread mutex lock
|
||||
**/
|
||||
class JSContextLock {
|
||||
public:
|
||||
JSContextLock(JSGlobalContextRef ctx) noexcept;
|
||||
~JSContextLock() noexcept;
|
||||
private:
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
JSGlobalContextRef ctx_;
|
||||
pthread_mutex_t globalLock_;
|
||||
#endif
|
||||
};
|
||||
|
||||
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 JSC_JSValueMakeUndefined(ctx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return &funcWrapper::call;
|
||||
}
|
||||
|
||||
} }
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "JSCWrapper.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
// TODO: use glog in OSS too
|
||||
#if __has_include(<glog/logging.h>)
|
||||
#define USE_GLOG 1
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#define USE_GLOG 0
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static const JSCWrapper* s_customWrapper = nullptr;
|
||||
|
||||
bool isCustomJSCWrapperSet() {
|
||||
return s_customWrapper != nullptr;
|
||||
}
|
||||
|
||||
const JSCWrapper* customJSCWrapper() {
|
||||
#if USE_GLOG
|
||||
CHECK(s_customWrapper != nullptr) << "Accessing custom JSC wrapper before it's set";
|
||||
#endif
|
||||
return s_customWrapper;
|
||||
}
|
||||
|
||||
void setCustomJSCWrapper(const JSCWrapper* wrapper) {
|
||||
#if USE_GLOG
|
||||
CHECK(s_customWrapper == nullptr) << "Can't set custom JSC wrapper multiple times";
|
||||
#endif
|
||||
s_customWrapper = wrapper;
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
|
@ -1,189 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <JavaScriptCore/JavaScript.h>
|
||||
|
||||
#if defined(JSCINTERNAL) || (!defined(__APPLE__))
|
||||
#define JSC_IMPORT extern "C"
|
||||
#else
|
||||
#define JSC_IMPORT extern
|
||||
#endif
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
class IInspector;
|
||||
}
|
||||
}
|
||||
|
||||
JSC_IMPORT void JSGlobalContextEnableDebugger(
|
||||
JSGlobalContextRef ctx,
|
||||
facebook::react::IInspector &globalInspector,
|
||||
const char *title,
|
||||
const std::function<bool()> &checkIsInspectedRemote);
|
||||
JSC_IMPORT void JSGlobalContextDisableDebugger(
|
||||
JSGlobalContextRef ctx,
|
||||
facebook::react::IInspector &globalInspector);
|
||||
|
||||
// This is used to substitute an alternate JSC implementation for
|
||||
// testing. These calls must all be ABI compatible with the standard JSC.
|
||||
JSC_IMPORT JSValueRef JSEvaluateBytecodeBundle(JSContextRef, JSObjectRef, int, JSStringRef, JSValueRef*);
|
||||
JSC_IMPORT bool JSSamplingProfilerEnabled();
|
||||
JSC_IMPORT void JSStartSamplingProfilingOnMainJSCThread(JSGlobalContextRef);
|
||||
JSC_IMPORT JSValueRef JSPokeSamplingProfiler(JSContextRef);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
JSC_IMPORT void configureJSCForIOS(std::string); // TODO: replace with folly::dynamic once supported
|
||||
JSC_IMPORT void FBJSContextStartGCTimers(JSContextRef);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <objc/objc.h>
|
||||
#include <JavaScriptCore/JSStringRefCF.h>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* JSNoBytecodeFileFormatVersion
|
||||
*
|
||||
* Version number indicating that bytecode is not supported by this runtime.
|
||||
*/
|
||||
RN_EXPORT extern const int32_t JSNoBytecodeFileFormatVersion;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
#define JSC_WRAPPER_METHOD(m) decltype(&m) m
|
||||
|
||||
struct JSCWrapper {
|
||||
// JSGlobalContext
|
||||
JSC_WRAPPER_METHOD(JSGlobalContextCreateInGroup);
|
||||
JSC_WRAPPER_METHOD(JSGlobalContextRelease);
|
||||
JSC_WRAPPER_METHOD(JSGlobalContextSetName);
|
||||
|
||||
// JSContext
|
||||
JSC_WRAPPER_METHOD(JSContextGetGlobalContext);
|
||||
JSC_WRAPPER_METHOD(JSContextGetGlobalObject);
|
||||
JSC_WRAPPER_METHOD(FBJSContextStartGCTimers);
|
||||
|
||||
// JSEvaluate
|
||||
JSC_WRAPPER_METHOD(JSEvaluateScript);
|
||||
JSC_WRAPPER_METHOD(JSEvaluateBytecodeBundle);
|
||||
|
||||
// JSString
|
||||
JSC_WRAPPER_METHOD(JSStringCreateWithUTF8CString);
|
||||
JSC_WRAPPER_METHOD(JSStringCreateWithCFString);
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
JSC_WRAPPER_METHOD(JSStringCreateWithUTF8CStringExpectAscii);
|
||||
#endif
|
||||
JSC_WRAPPER_METHOD(JSStringCopyCFString);
|
||||
JSC_WRAPPER_METHOD(JSStringGetCharactersPtr);
|
||||
JSC_WRAPPER_METHOD(JSStringGetLength);
|
||||
JSC_WRAPPER_METHOD(JSStringGetMaximumUTF8CStringSize);
|
||||
JSC_WRAPPER_METHOD(JSStringIsEqualToUTF8CString);
|
||||
JSC_WRAPPER_METHOD(JSStringRelease);
|
||||
JSC_WRAPPER_METHOD(JSStringRetain);
|
||||
|
||||
// JSClass
|
||||
JSC_WRAPPER_METHOD(JSClassCreate);
|
||||
JSC_WRAPPER_METHOD(JSClassRetain);
|
||||
JSC_WRAPPER_METHOD(JSClassRelease);
|
||||
|
||||
// JSObject
|
||||
JSC_WRAPPER_METHOD(JSObjectCallAsConstructor);
|
||||
JSC_WRAPPER_METHOD(JSObjectCallAsFunction);
|
||||
JSC_WRAPPER_METHOD(JSObjectGetPrivate);
|
||||
JSC_WRAPPER_METHOD(JSObjectGetProperty);
|
||||
JSC_WRAPPER_METHOD(JSObjectGetPropertyAtIndex);
|
||||
JSC_WRAPPER_METHOD(JSObjectIsConstructor);
|
||||
JSC_WRAPPER_METHOD(JSObjectIsFunction);
|
||||
JSC_WRAPPER_METHOD(JSObjectMake);
|
||||
JSC_WRAPPER_METHOD(JSObjectMakeArray);
|
||||
JSC_WRAPPER_METHOD(JSObjectMakeDate);
|
||||
JSC_WRAPPER_METHOD(JSObjectMakeError);
|
||||
JSC_WRAPPER_METHOD(JSObjectMakeFunctionWithCallback);
|
||||
JSC_WRAPPER_METHOD(JSObjectSetPrivate);
|
||||
JSC_WRAPPER_METHOD(JSObjectSetProperty);
|
||||
JSC_WRAPPER_METHOD(JSObjectSetPropertyAtIndex);
|
||||
|
||||
// JSPropertyNameArray
|
||||
JSC_WRAPPER_METHOD(JSObjectCopyPropertyNames);
|
||||
JSC_WRAPPER_METHOD(JSPropertyNameArrayGetCount);
|
||||
JSC_WRAPPER_METHOD(JSPropertyNameArrayGetNameAtIndex);
|
||||
JSC_WRAPPER_METHOD(JSPropertyNameArrayRelease);
|
||||
|
||||
// JSValue
|
||||
JSC_WRAPPER_METHOD(JSValueCreateJSONString);
|
||||
JSC_WRAPPER_METHOD(JSValueGetType);
|
||||
JSC_WRAPPER_METHOD(JSValueMakeFromJSONString);
|
||||
JSC_WRAPPER_METHOD(JSValueMakeBoolean);
|
||||
JSC_WRAPPER_METHOD(JSValueMakeNull);
|
||||
JSC_WRAPPER_METHOD(JSValueMakeNumber);
|
||||
JSC_WRAPPER_METHOD(JSValueMakeString);
|
||||
JSC_WRAPPER_METHOD(JSValueMakeUndefined);
|
||||
JSC_WRAPPER_METHOD(JSValueProtect);
|
||||
JSC_WRAPPER_METHOD(JSValueToBoolean);
|
||||
JSC_WRAPPER_METHOD(JSValueToNumber);
|
||||
JSC_WRAPPER_METHOD(JSValueToObject);
|
||||
JSC_WRAPPER_METHOD(JSValueToStringCopy);
|
||||
JSC_WRAPPER_METHOD(JSValueUnprotect);
|
||||
JSC_WRAPPER_METHOD(JSValueIsNull);
|
||||
|
||||
// Sampling profiler
|
||||
JSC_WRAPPER_METHOD(JSSamplingProfilerEnabled);
|
||||
JSC_WRAPPER_METHOD(JSPokeSamplingProfiler);
|
||||
JSC_WRAPPER_METHOD(JSStartSamplingProfilingOnMainJSCThread);
|
||||
|
||||
JSC_WRAPPER_METHOD(JSGlobalContextEnableDebugger);
|
||||
JSC_WRAPPER_METHOD(JSGlobalContextDisableDebugger);
|
||||
|
||||
JSC_WRAPPER_METHOD(configureJSCForIOS);
|
||||
|
||||
// Objective-C API
|
||||
Class JSContext;
|
||||
Class JSValue;
|
||||
|
||||
int32_t JSBytecodeFileFormatVersion;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool isCustomJSCPtr(T *x) {
|
||||
return (uintptr_t)x & 0x1;
|
||||
}
|
||||
|
||||
RN_EXPORT bool isCustomJSCWrapperSet();
|
||||
RN_EXPORT void setCustomJSCWrapper(const JSCWrapper* wrapper);
|
||||
|
||||
// This will return a single value for the whole life of the process.
|
||||
RN_EXPORT const JSCWrapper *systemJSCWrapper();
|
||||
RN_EXPORT const JSCWrapper *customJSCWrapper();
|
||||
|
||||
} }
|
||||
|
||||
#else
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
template <typename T>
|
||||
bool isCustomJSCPtr(T *x) {
|
||||
// Always use system JSC pointers
|
||||
return false;
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
|
@ -1,212 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jschelpers/JSCWrapper.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
// Use for methods that are taking JSContextRef as a first param
|
||||
#define __jsc_wrapper(method, ctx, ...) \
|
||||
(facebook::react::isCustomJSCPtr(ctx) ? \
|
||||
facebook::react::customJSCWrapper() : \
|
||||
facebook::react::systemJSCWrapper() \
|
||||
)->method(ctx, ## __VA_ARGS__)
|
||||
|
||||
// Use for methods that don't take a JSContextRef as a first param. The wrapped version
|
||||
// of this method will require context as an additional param, but it will be dropped
|
||||
// before calling into the JSC method.
|
||||
#define __jsc_drop_ctx_wrapper(method, ctx, ...) \
|
||||
(facebook::react::isCustomJSCPtr(ctx) ? \
|
||||
facebook::react::customJSCWrapper() : \
|
||||
facebook::react::systemJSCWrapper() \
|
||||
)->method(__VA_ARGS__)
|
||||
|
||||
// Use for methods were access to a JSContextRef is impractical. The first bool param
|
||||
// will be dropped before the JSC method is invoked.
|
||||
#define __jsc_ensure_bool(field) \
|
||||
static_assert(std::is_same<typename std::decay<decltype(field)>::type, bool>::value, "useCustomJSC must be bool");
|
||||
#define __jsc_bool_wrapper(method, useCustomJSC, ...) \
|
||||
([]{ __jsc_ensure_bool(useCustomJSC) }, useCustomJSC ? \
|
||||
facebook::react::customJSCWrapper() : \
|
||||
facebook::react::systemJSCWrapper() \
|
||||
)->method(__VA_ARGS__)
|
||||
|
||||
// Used for wrapping properties
|
||||
#define __jsc_prop_wrapper(prop, ctx) \
|
||||
(facebook::react::isCustomJSCPtr(ctx) ? \
|
||||
facebook::react::customJSCWrapper() : \
|
||||
facebook::react::systemJSCWrapper() \
|
||||
)->prop
|
||||
|
||||
// Poison all regular versions of the JSC API in shared code. This prevents accidental
|
||||
// mixed usage of regular and custom JSC methods.
|
||||
// See https://gcc.gnu.org/onlinedocs/gcc-3.3/cpp/Pragmas.html for details
|
||||
#define jsc_pragma(x) _Pragma(#x)
|
||||
#ifndef NO_JSC_POISON
|
||||
#define jsc_poison(methods) jsc_pragma(GCC poison methods)
|
||||
#else
|
||||
#define jsc_poison(methods)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define __jsc_wrapper(method, ctx, ...) method(ctx, ## __VA_ARGS__)
|
||||
#define __jsc_drop_ctx_wrapper(method, ctx, ...) ((void)ctx, method(__VA_ARGS__))
|
||||
#define __jsc_bool_wrapper(method, useCustomJSC, ...) \
|
||||
((void)useCustomJSC, method(__VA_ARGS__))
|
||||
#define __jsc_prop_wrapper(prop, ctx) prop
|
||||
|
||||
#define jsc_pragma(x)
|
||||
#define jsc_poison(methods)
|
||||
|
||||
#endif
|
||||
|
||||
// JSGlobalContext
|
||||
#define JSC_JSGlobalContextCreateInGroup(...) __jsc_bool_wrapper(JSGlobalContextCreateInGroup, __VA_ARGS__)
|
||||
#define JSC_JSGlobalContextRelease(...) __jsc_wrapper(JSGlobalContextRelease, __VA_ARGS__)
|
||||
#define JSC_JSGlobalContextSetName(...) __jsc_wrapper(JSGlobalContextSetName, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSContextGroupCreate JSContextGroupRelease JSContextGroupRetain
|
||||
JSGlobalContextCreate JSGlobalContextCreateInGroup JSGlobalContextCopyName
|
||||
JSGlobalContextRelease JSGlobalContextRetain JSGlobalContextSetName)
|
||||
|
||||
// JSContext
|
||||
#define JSC_JSContextGetGlobalContext(...) __jsc_wrapper(JSContextGetGlobalContext, __VA_ARGS__)
|
||||
#define JSC_JSContextGetGlobalObject(...) __jsc_wrapper(JSContextGetGlobalObject, __VA_ARGS__)
|
||||
#define JSC_FBJSContextStartGCTimers(...) __jsc_wrapper(FBJSContextStartGCTimers, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSContextGetGlobalContext JSContextGetGlobalObject JSContextGetGroup FBJSContextStartGCTimers)
|
||||
|
||||
// JSEvaluate
|
||||
#define JSC_JSEvaluateScript(...) __jsc_wrapper(JSEvaluateScript, __VA_ARGS__)
|
||||
#define JSC_JSEvaluateBytecodeBundle(...) __jsc_wrapper(JSEvaluateBytecodeBundle, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSCheckScriptSyntax JSEvaluateScript JSEvaluateBytecodeBundle JSGarbageCollect)
|
||||
|
||||
// JSString
|
||||
#define JSC_JSStringCreateWithCFString(...) __jsc_drop_ctx_wrapper(JSStringCreateWithCFString, __VA_ARGS__)
|
||||
#define JSC_JSStringCreateWithUTF8CString(...) __jsc_drop_ctx_wrapper(JSStringCreateWithUTF8CString, __VA_ARGS__)
|
||||
#define JSC_JSStringCreateWithUTF8CStringExpectAscii(...) __jsc_drop_ctx_wrapper(JSStringCreateWithUTF8CStringExpectAscii, __VA_ARGS__)
|
||||
#define JSC_JSStringCopyCFString(...) __jsc_drop_ctx_wrapper(JSStringCopyCFString, __VA_ARGS__)
|
||||
#define JSC_JSStringGetCharactersPtr(...) __jsc_drop_ctx_wrapper(JSStringGetCharactersPtr, __VA_ARGS__)
|
||||
#define JSC_JSStringGetLength(...) __jsc_drop_ctx_wrapper(JSStringGetLength, __VA_ARGS__)
|
||||
#define JSC_JSStringGetMaximumUTF8CStringSize(...) __jsc_drop_ctx_wrapper(JSStringGetMaximumUTF8CStringSize, __VA_ARGS__)
|
||||
#define JSC_JSStringIsEqualToUTF8CString(...) __jsc_drop_ctx_wrapper(JSStringIsEqualToUTF8CString, __VA_ARGS__)
|
||||
#define JSC_JSStringRelease(...) __jsc_drop_ctx_wrapper(JSStringRelease, __VA_ARGS__)
|
||||
#define JSC_JSStringRetain(...) __jsc_drop_ctx_wrapper(JSStringRetain, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSStringCopyCFString JSStringCreateWithCharacters JSStringCreateWithCFString
|
||||
JSStringCreateWithUTF8CString JSStringCreateWithUTF8CStringExpectAscii
|
||||
JSStringGetCharactersPtr JSStringGetLength JSStringGetMaximumUTF8CStringSize
|
||||
JSStringGetUTF8CString JSStringIsEqual JSStringIsEqualToUTF8CString
|
||||
JSStringRelease JSStringRetain)
|
||||
|
||||
// JSValueRef
|
||||
#define JSC_JSValueCreateJSONString(...) __jsc_wrapper(JSValueCreateJSONString, __VA_ARGS__)
|
||||
#define JSC_JSValueGetType(...) __jsc_wrapper(JSValueGetType, __VA_ARGS__)
|
||||
#define JSC_JSValueMakeFromJSONString(...) __jsc_wrapper(JSValueMakeFromJSONString, __VA_ARGS__)
|
||||
#define JSC_JSValueMakeBoolean(...) __jsc_wrapper(JSValueMakeBoolean, __VA_ARGS__)
|
||||
#define JSC_JSValueMakeNull(...) __jsc_wrapper(JSValueMakeNull, __VA_ARGS__)
|
||||
#define JSC_JSValueMakeNumber(...) __jsc_wrapper(JSValueMakeNumber, __VA_ARGS__)
|
||||
#define JSC_JSValueMakeString(...) __jsc_wrapper(JSValueMakeString, __VA_ARGS__)
|
||||
#define JSC_JSValueMakeUndefined(...) __jsc_wrapper(JSValueMakeUndefined, __VA_ARGS__)
|
||||
#define JSC_JSValueProtect(...) __jsc_wrapper(JSValueProtect, __VA_ARGS__)
|
||||
#define JSC_JSValueToBoolean(...) __jsc_wrapper(JSValueToBoolean, __VA_ARGS__)
|
||||
#define JSC_JSValueToNumber(...) __jsc_wrapper(JSValueToNumber, __VA_ARGS__)
|
||||
#define JSC_JSValueToObject(...) __jsc_wrapper(JSValueToObject, __VA_ARGS__)
|
||||
#define JSC_JSValueToStringCopy(...) __jsc_wrapper(JSValueToStringCopy, __VA_ARGS__)
|
||||
#define JSC_JSValueUnprotect(...) __jsc_wrapper(JSValueUnprotect, __VA_ARGS__)
|
||||
#define JSC_JSValueIsNull(...) __jsc_wrapper(JSValueIsNull, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSValueCreateJSONString JSValueGetType JSValueGetTypedArrayType JSValueIsArray
|
||||
JSValueIsBoolean JSValueIsDate JSValueIsEqual JSValueIsInstanceOfConstructor
|
||||
JSValueIsNull JSValueIsNumber JSValueIsObject JSValueIsObjectOfClass
|
||||
JSValueIsStrictEqual JSValueIsString JSValueIsString JSValueIsUndefined
|
||||
JSValueMakeBoolean JSValueMakeFromJSONString JSValueMakeNull JSValueMakeNumber
|
||||
JSValueMakeString JSValueMakeUndefined JSValueProtect JSValueToBoolean
|
||||
JSValueToNumber JSValueToObject JSValueToStringCopy JSValueUnprotect)
|
||||
|
||||
// JSClass
|
||||
#define JSC_JSClassCreate(...) __jsc_bool_wrapper(JSClassCreate, __VA_ARGS__)
|
||||
#define JSC_JSClassRetain(...) __jsc_bool_wrapper(JSClassRetain, __VA_ARGS__)
|
||||
#define JSC_JSClassRelease(...) __jsc_bool_wrapper(JSClassRelease, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSClassCreate JSClassRelease JSClassRetain)
|
||||
|
||||
// JSObject
|
||||
#define JSC_JSObjectCallAsConstructor(...) __jsc_wrapper(JSObjectCallAsConstructor, __VA_ARGS__)
|
||||
#define JSC_JSObjectCallAsFunction(...) __jsc_wrapper(JSObjectCallAsFunction, __VA_ARGS__)
|
||||
#define JSC_JSObjectGetPrivate(...) __jsc_bool_wrapper(JSObjectGetPrivate, __VA_ARGS__)
|
||||
#define JSC_JSObjectGetProperty(...) __jsc_wrapper(JSObjectGetProperty, __VA_ARGS__)
|
||||
#define JSC_JSObjectGetPropertyAtIndex(...) __jsc_wrapper(JSObjectGetPropertyAtIndex, __VA_ARGS__)
|
||||
#define JSC_JSObjectIsConstructor(...) __jsc_wrapper(JSObjectIsConstructor, __VA_ARGS__)
|
||||
#define JSC_JSObjectIsFunction(...) __jsc_wrapper(JSObjectIsFunction, __VA_ARGS__)
|
||||
#define JSC_JSObjectMake(...) __jsc_wrapper(JSObjectMake, __VA_ARGS__)
|
||||
#define JSC_JSObjectMakeArray(...) __jsc_wrapper(JSObjectMakeArray, __VA_ARGS__)
|
||||
#define JSC_JSObjectMakeDate(...) __jsc_wrapper(JSObjectMakeDate, __VA_ARGS__)
|
||||
#define JSC_JSObjectMakeError(...) __jsc_wrapper(JSObjectMakeError, __VA_ARGS__)
|
||||
#define JSC_JSObjectMakeFunctionWithCallback(...) __jsc_wrapper(JSObjectMakeFunctionWithCallback, __VA_ARGS__)
|
||||
#define JSC_JSObjectSetPrivate(...) __jsc_bool_wrapper(JSObjectSetPrivate, __VA_ARGS__)
|
||||
#define JSC_JSObjectSetProperty(...) __jsc_wrapper(JSObjectSetProperty, __VA_ARGS__)
|
||||
#define JSC_JSObjectSetPropertyAtIndex(...) __jsc_wrapper(JSObjectSetPropertyAtIndex, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSObjectCallAsConstructor JSObjectCallAsFunction JSObjectDeleteProperty
|
||||
JSObjectGetPrivate JSObjectGetProperty JSObjectGetPropertyAtIndex
|
||||
JSObjectGetPrototype JSObjectHasProperty JSObjectIsConstructor
|
||||
JSObjectIsFunction JSObjectMake JSObjectMakeArray JSObjectMakeConstructor
|
||||
JSObjectMakeDate JSObjectMakeError JSObjectMakeFunction
|
||||
JSObjectMakeFunctionWithCallback JSObjectMakeRegExp JSObjectSetPrivate
|
||||
JSObjectSetPrototype JSObjectSetProperty JSObjectSetPropertyAtIndex)
|
||||
|
||||
// JSPropertyNameArray
|
||||
#define JSC_JSObjectCopyPropertyNames(...) __jsc_wrapper(JSObjectCopyPropertyNames, __VA_ARGS__)
|
||||
#define JSC_JSPropertyNameArrayGetCount(...) __jsc_drop_ctx_wrapper(JSPropertyNameArrayGetCount, __VA_ARGS__)
|
||||
#define JSC_JSPropertyNameArrayGetNameAtIndex(...) __jsc_drop_ctx_wrapper(JSPropertyNameArrayGetNameAtIndex, __VA_ARGS__)
|
||||
#define JSC_JSPropertyNameArrayRelease(...) __jsc_drop_ctx_wrapper(JSPropertyNameArrayRelease, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSObjectCopyPropertyNames JSPropertyNameAccumulatorAddName
|
||||
JSPropertyNameArrayGetCount JSPropertyNameArrayGetNameAtIndex
|
||||
JSPropertyNameArrayRelease JSPropertyNameArrayRetain)
|
||||
|
||||
// JSTypedArray
|
||||
jsc_poison(JSObjectMakeArrayBufferWithBytesNoCopy JSObjectMakeTypedArray
|
||||
JSObjectMakeTypedArrayWithArrayBuffer
|
||||
JSObjectMakeTypedArrayWithArrayBufferAndOffset
|
||||
JSObjectMakeTypedArrayWithBytesNoCopy JSObjectGetTypedArrayByteLength
|
||||
JSObjectGetTypedArrayByteOffset JSObjectGetTypedArrayBytesPtr
|
||||
JSObjectGetTypedArrayBuffer JSObjectGetTypedArrayLength
|
||||
JSObjectGetArrayBufferBytesPtr JSObjectGetArrayBufferByteLength)
|
||||
|
||||
// Sampling profiler
|
||||
#define JSC_JSSamplingProfilerEnabled(...) __jsc_drop_ctx_wrapper(JSSamplingProfilerEnabled, __VA_ARGS__)
|
||||
#define JSC_JSPokeSamplingProfiler(...) __jsc_wrapper(JSPokeSamplingProfiler, __VA_ARGS__)
|
||||
#define JSC_JSStartSamplingProfilingOnMainJSCThread(...) __jsc_wrapper(JSStartSamplingProfilingOnMainJSCThread, __VA_ARGS__)
|
||||
|
||||
jsc_poison(JSSamplingProfilerEnabled JSPokeSamplingProfiler
|
||||
JSStartSamplingProfilingOnMainJSCThread)
|
||||
|
||||
#define JSC_JSGlobalContextEnableDebugger(...) __jsc_wrapper(JSGlobalContextEnableDebugger, __VA_ARGS__)
|
||||
// no need to poison JSGlobalContextEnableDebugger because it's not defined for System JSC / standard SDK header
|
||||
// jsc_poison(JSGlobalContextEnableDebugger)
|
||||
|
||||
#define JSC_JSGlobalContextDisableDebugger(...) __jsc_wrapper(JSGlobalContextDisableDebugger, __VA_ARGS__)
|
||||
// no need to poison JSGlobalContextDisableDebugger because it's not defined for System JSC / standard SDK header
|
||||
// jsc_poison(JSGlobalContextDisableDebugger)
|
||||
|
||||
|
||||
#define JSC_configureJSCForIOS(...) __jsc_bool_wrapper(configureJSCForIOS, __VA_ARGS__)
|
||||
|
||||
jsc_poison(configureJSCForIOS)
|
||||
|
||||
// Objective-C API
|
||||
#define JSC_JSContext(ctx) __jsc_prop_wrapper(JSContext, ctx)
|
||||
#define JSC_JSValue(ctx) __jsc_prop_wrapper(JSValue, ctx)
|
||||
|
||||
#undef jsc_poison
|
||||
#undef jsc_pragma
|
|
@ -1,91 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#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,17 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
namespace unicode {
|
||||
__attribute__((visibility("default"))) std::string utf16toUTF8(const uint16_t* utf16, size_t length) noexcept;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,325 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#include "Value.h"
|
||||
|
||||
#include <folly/json.h>
|
||||
#include <folly/Conv.h>
|
||||
|
||||
#include "JSCHelpers.h"
|
||||
#include "JavaScriptCore.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 {
|
||||
|
||||
/* static */
|
||||
Object Object::makeDate(JSContextRef ctx, Object::TimeType time) {
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::milliseconds;
|
||||
|
||||
JSValueRef arguments[1];
|
||||
arguments[0] = JSC_JSValueMakeNumber(
|
||||
ctx,
|
||||
duration_cast<milliseconds>(time.time_since_epoch()).count());
|
||||
|
||||
JSValueRef exn;
|
||||
auto result = JSC_JSObjectMakeDate(ctx, 1, arguments, &exn);
|
||||
if (!result) {
|
||||
throw JSException(ctx, exn, "Failed to create Date");
|
||||
}
|
||||
return Object(ctx, result);
|
||||
}
|
||||
|
||||
Object Object::makeArray(JSContextRef ctx, JSValueRef* elements, unsigned length) {
|
||||
JSValueRef exn;
|
||||
auto arr = JSC_JSObjectMakeArray(ctx, length, elements, &exn);
|
||||
if (!arr) {
|
||||
throw JSException(ctx, exn, "Failed to create an Array");
|
||||
}
|
||||
return Object(ctx, arr);
|
||||
}
|
||||
|
||||
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)) {}
|
||||
|
||||
JSContextRef Value::context() const {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
/* static */
|
||||
std::string Value::toJSONString(unsigned indent) const {
|
||||
JSValueRef exn;
|
||||
auto stringToAdopt = JSC_JSValueCreateJSONString(m_context, m_value, indent, &exn);
|
||||
if (!stringToAdopt) {
|
||||
throw JSException(m_context, exn, "Exception creating JSON string");
|
||||
}
|
||||
return String::adopt(m_context, stringToAdopt).str();
|
||||
}
|
||||
|
||||
/* static */
|
||||
Value Value::fromJSON(const String& json) {
|
||||
JSContextRef ctx = json.context();
|
||||
auto result = JSC_JSValueMakeFromJSONString(ctx, json);
|
||||
if (!result) {
|
||||
throw JSException(folly::to<std::string>(
|
||||
"Failed to create Value from JSON: ", json.str()).c_str());
|
||||
}
|
||||
return Value(ctx, result);
|
||||
}
|
||||
|
||||
Value 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 Value(ctx, jsVal);
|
||||
#else
|
||||
auto json = folly::toJson(value);
|
||||
return fromJSON(String(ctx, json.c_str()));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSValueRef Value::fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj) {
|
||||
switch (obj.type()) {
|
||||
// For primitive types (and strings), just create and return an equivalent JSValue
|
||||
case folly::dynamic::Type::NULLT:
|
||||
return JSC_JSValueMakeNull(ctx);
|
||||
|
||||
case folly::dynamic::Type::BOOL:
|
||||
return JSC_JSValueMakeBoolean(ctx, obj.getBool());
|
||||
|
||||
case folly::dynamic::Type::DOUBLE:
|
||||
return JSC_JSValueMakeNumber(ctx, obj.getDouble());
|
||||
|
||||
case folly::dynamic::Type::INT64:
|
||||
return JSC_JSValueMakeNumber(ctx, obj.asDouble());
|
||||
|
||||
case folly::dynamic::Type::STRING:
|
||||
return JSC_JSValueMakeString(ctx, String(ctx, 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 = JSC_JSObjectMakeArray(ctx, obj.size(), vals, nullptr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
case folly::dynamic::Type::OBJECT: {
|
||||
// Create an empty object
|
||||
JSObjectRef jsObj = JSC_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) {
|
||||
JSC_JSObjectSetProperty(
|
||||
ctx,
|
||||
jsObj,
|
||||
String(ctx, 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 JSC_JSValueMakeNull(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
Object Value::asObject() const {
|
||||
JSValueRef exn;
|
||||
JSObjectRef jsObj = JSC_JSValueToObject(context(), m_value, &exn);
|
||||
if (!jsObj) {
|
||||
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, const char *stack)
|
||||
{
|
||||
auto errorMsg = Value(ctx, String(ctx, error));
|
||||
JSValueRef args[] = {errorMsg};
|
||||
if (stack) {
|
||||
// Using this instead of JSObjectMakeError to actually get a stack property.
|
||||
// MakeError only sets it stack when returning from the invoked function, so we
|
||||
// can't extend it here.
|
||||
auto errorConstructor = Object::getGlobalObject(ctx).getProperty("Error").asObject();
|
||||
auto jsError = errorConstructor.callAsConstructor({errorMsg});
|
||||
auto fullStack = std::string(stack) + jsError.getProperty("stack").toString().str();
|
||||
jsError.setProperty("stack", String(ctx, fullStack.c_str()));
|
||||
return jsError;
|
||||
} else {
|
||||
JSValueRef exn;
|
||||
JSObjectRef errorObj = JSC_JSObjectMakeError(ctx, 1, args, &exn);
|
||||
if (!errorObj) {
|
||||
throw JSException(ctx, exn, "Exception making error");
|
||||
}
|
||||
return Value(ctx, errorObj);
|
||||
}
|
||||
}
|
||||
|
||||
void Value::throwTypeException(const std::string &expectedType) const {
|
||||
std::string wat("TypeError: Expected ");
|
||||
wat += expectedType;
|
||||
wat += ", instead got '";
|
||||
wat += toString().str();
|
||||
wat += "'";
|
||||
throw JSException(wat.c_str());
|
||||
}
|
||||
|
||||
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(static_cast<JSObjectRef>(thisObj), nArgs, args);
|
||||
}
|
||||
|
||||
Value Object::callAsFunction(JSObjectRef thisObj, int nArgs, const JSValueRef args[]) const {
|
||||
JSValueRef exn;
|
||||
JSValueRef result = JSC_JSObjectCallAsFunction(m_context, m_obj, thisObj, nArgs, args, &exn);
|
||||
if (!result) {
|
||||
throw JSException(m_context, exn, "Exception calling object as function");
|
||||
}
|
||||
return Value(m_context, result);
|
||||
}
|
||||
|
||||
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) {
|
||||
throw JSException(m_context, exn, "Exception calling object as constructor");
|
||||
}
|
||||
return Object(m_context, result);
|
||||
}
|
||||
|
||||
Value Object::getProperty(const String& propName) const {
|
||||
JSValueRef exn;
|
||||
JSValueRef property = JSC_JSObjectGetProperty(m_context, m_obj, propName, &exn);
|
||||
if (!property) {
|
||||
throw JSException(m_context, exn, folly::to<std::string>(
|
||||
"Failed to get property '", propName.str(), "'").c_str());
|
||||
}
|
||||
return Value(m_context, property);
|
||||
}
|
||||
|
||||
Value Object::getPropertyAtIndex(unsigned int index) const {
|
||||
JSValueRef exn;
|
||||
JSValueRef property = JSC_JSObjectGetPropertyAtIndex(m_context, m_obj, index, &exn);
|
||||
if (!property) {
|
||||
throw JSException(m_context, exn, folly::to<std::string>(
|
||||
"Failed to get property at index ", index).c_str());
|
||||
}
|
||||
return Value(m_context, property);
|
||||
}
|
||||
|
||||
Value Object::getProperty(const char *propName) const {
|
||||
return getProperty(String(m_context, propName));
|
||||
}
|
||||
|
||||
void Object::setProperty(const String& propName, const Value& value) {
|
||||
JSValueRef exn = nullptr;
|
||||
JSC_JSObjectSetProperty(m_context, m_obj, propName, value, kJSPropertyAttributeNone, &exn);
|
||||
if (exn) {
|
||||
throw JSException(m_context, exn, folly::to<std::string>(
|
||||
"Failed to set property '", propName.str(), "'").c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Object::setPropertyAtIndex(unsigned int index, const Value& value) {
|
||||
JSValueRef exn = nullptr;
|
||||
JSC_JSObjectSetPropertyAtIndex(m_context, m_obj, index, value, &exn);
|
||||
if (exn) {
|
||||
throw JSException(m_context, exn, folly::to<std::string>(
|
||||
"Failed to set property at index ", index).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Object::setProperty(const char *propName, const Value& value) {
|
||||
setProperty(String(m_context, propName), value);
|
||||
}
|
||||
|
||||
std::vector<String> Object::getPropertyNames() const {
|
||||
auto namesRef = JSC_JSObjectCopyPropertyNames(m_context, m_obj);
|
||||
size_t count = JSC_JSPropertyNameArrayGetCount(m_context, namesRef);
|
||||
std::vector<String> names;
|
||||
names.reserve(count);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
names.emplace_back(String::ref(m_context,
|
||||
JSC_JSPropertyNameArrayGetNameAtIndex(m_context, namesRef, i)));
|
||||
}
|
||||
JSC_JSPropertyNameArrayRelease(m_context, namesRef);
|
||||
return names;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> Object::toJSONMap() const {
|
||||
std::unordered_map<std::string, std::string> map;
|
||||
auto namesRef = JSC_JSObjectCopyPropertyNames(m_context, m_obj);
|
||||
size_t count = JSC_JSPropertyNameArrayGetCount(m_context, namesRef);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
auto key = String::ref(m_context,
|
||||
JSC_JSPropertyNameArrayGetNameAtIndex(m_context, namesRef, i));
|
||||
map.emplace(key.str(), getProperty(key).toJSONString());
|
||||
}
|
||||
JSC_JSPropertyNameArrayRelease(m_context, namesRef);
|
||||
return map;
|
||||
}
|
||||
|
||||
/* static */
|
||||
Object Object::create(JSContextRef ctx) {
|
||||
JSObjectRef newObj = JSC_JSObjectMake(
|
||||
ctx,
|
||||
NULL, // create instance of default object class
|
||||
NULL); // no private data
|
||||
return Object(ctx, newObj);
|
||||
}
|
||||
|
||||
} }
|
|
@ -1,373 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
#include <jschelpers/JavaScriptCore.h>
|
||||
#include <jschelpers/Unicode.h>
|
||||
#include <jschelpers/noncopyable.h>
|
||||
#include <privatedata/PrivateDataBase.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class Value;
|
||||
|
||||
// C++ object wrapper for JSStringRef
|
||||
class String : public noncopyable {
|
||||
public:
|
||||
explicit String(): m_context(nullptr), m_string(nullptr) {} // dummy empty constructor
|
||||
|
||||
explicit String(JSContextRef context, const char* utf8)
|
||||
: m_context(context), m_string(JSC_JSStringCreateWithUTF8CString(context, utf8)) {}
|
||||
|
||||
String(String&& other) :
|
||||
m_context(other.m_context), m_string(other.m_string)
|
||||
{
|
||||
other.m_string = nullptr;
|
||||
}
|
||||
|
||||
String(const String& other) :
|
||||
m_context(other.m_context), m_string(other.m_string)
|
||||
{
|
||||
if (m_string) {
|
||||
JSC_JSStringRetain(m_context, m_string);
|
||||
}
|
||||
}
|
||||
|
||||
~String() {
|
||||
if (m_string) {
|
||||
JSC_JSStringRelease(m_context, m_string);
|
||||
}
|
||||
}
|
||||
|
||||
String& operator=(String&& other) {
|
||||
if (m_string) {
|
||||
JSC_JSStringRelease(m_context, m_string);
|
||||
}
|
||||
|
||||
m_context = other.m_context;
|
||||
m_string = other.m_string;
|
||||
other.m_string = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator JSStringRef() const {
|
||||
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 nul-terminated utf8 encoded value
|
||||
size_t utf8Size() const {
|
||||
return m_string ? JSC_JSStringGetMaximumUTF8CStringSize(m_context, m_string) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
if (!m_string) {
|
||||
return "";
|
||||
}
|
||||
const JSChar* utf16 = JSC_JSStringGetCharactersPtr(m_context, m_string);
|
||||
size_t stringLength = JSC_JSStringGetLength(m_context, m_string);
|
||||
return unicode::utf16toUTF8(utf16, stringLength);
|
||||
}
|
||||
|
||||
// Assumes that utf8 is nul-terminated
|
||||
bool equals(const char* utf8) {
|
||||
return m_string ? JSC_JSStringIsEqualToUTF8CString(m_context, m_string, utf8) : false;
|
||||
}
|
||||
|
||||
// This assumes ascii is nul-terminated.
|
||||
static String createExpectingAscii(JSContextRef context, const char* ascii, size_t len) {
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
return String(context, JSC_JSStringCreateWithUTF8CStringExpectAscii(context, ascii, len), true);
|
||||
#else
|
||||
return String(context, JSC_JSStringCreateWithUTF8CString(context, ascii), true);
|
||||
#endif
|
||||
}
|
||||
|
||||
static String createExpectingAscii(JSContextRef context, std::string const &ascii) {
|
||||
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);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit String(JSContextRef context, JSStringRef string, bool adopt) :
|
||||
m_context(context), m_string(string)
|
||||
{
|
||||
if (!adopt && string) {
|
||||
JSC_JSStringRetain(context, string);
|
||||
}
|
||||
}
|
||||
|
||||
JSContextRef m_context;
|
||||
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:
|
||||
using TimeType = std::chrono::time_point<std::chrono::system_clock>;
|
||||
|
||||
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) {
|
||||
JSC_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 JSC_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 int index) const;
|
||||
void setProperty(const String& propName, const Value& value);
|
||||
void setProperty(const char *propName, const Value& value);
|
||||
void setPropertyAtIndex(unsigned int index, const Value& value);
|
||||
std::vector<String> getPropertyNames() const;
|
||||
std::unordered_map<std::string, std::string> toJSONMap() const;
|
||||
|
||||
void makeProtected() {
|
||||
if (!m_isProtected && m_obj) {
|
||||
JSC_JSValueProtect(m_context, m_obj);
|
||||
m_isProtected = true;
|
||||
}
|
||||
}
|
||||
|
||||
RN_EXPORT static Object makeArray(JSContextRef ctx, JSValueRef* elements, unsigned length);
|
||||
RN_EXPORT static Object makeDate(JSContextRef ctx, TimeType time);
|
||||
|
||||
template<typename ReturnType>
|
||||
ReturnType* getPrivate() const {
|
||||
const bool isCustomJSC = isCustomJSCPtr(m_context);
|
||||
return PrivateDataBase::cast<ReturnType>(JSC_JSObjectGetPrivate(isCustomJSC, m_obj));
|
||||
}
|
||||
|
||||
void setPrivate(PrivateDataBase* data) const {
|
||||
const bool isCustomJSC = isCustomJSCPtr(m_context);
|
||||
JSC_JSObjectSetPrivate(isCustomJSC, m_obj, data);
|
||||
}
|
||||
|
||||
JSContextRef context() const {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
static Object getGlobalObject(JSContextRef ctx) {
|
||||
auto globalObj = JSC_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;
|
||||
};
|
||||
|
||||
// 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:
|
||||
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;
|
||||
m_value = other.m_value;
|
||||
other.m_value = NULL;
|
||||
return *this;
|
||||
};
|
||||
|
||||
operator JSValueRef() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
JSType getType() const {
|
||||
return JSC_JSValueGetType(m_context, m_value);
|
||||
}
|
||||
|
||||
bool isBoolean() const {
|
||||
return getType() == kJSTypeBoolean;
|
||||
}
|
||||
|
||||
bool asBoolean() const {
|
||||
return JSC_JSValueToBoolean(context(), m_value);
|
||||
}
|
||||
|
||||
bool isNumber() const {
|
||||
return getType() == kJSTypeNumber;
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return getType() == kJSTypeNull;
|
||||
}
|
||||
|
||||
bool isUndefined() const {
|
||||
return getType() == kJSTypeUndefined;
|
||||
}
|
||||
|
||||
double asNumber() const {
|
||||
if (isNumber()) {
|
||||
return JSC_JSValueToNumber(context(), m_value, nullptr);
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
double getNumberOrThrow() const {
|
||||
if (!isNumber()) {
|
||||
throwTypeException("Number");
|
||||
}
|
||||
return JSC_JSValueToNumber(context(), m_value, nullptr);
|
||||
}
|
||||
|
||||
int32_t asInteger() const {
|
||||
return static_cast<int32_t>(asNumber());
|
||||
}
|
||||
|
||||
uint32_t asUnsignedInteger() const {
|
||||
return static_cast<uint32_t>(asNumber());
|
||||
}
|
||||
|
||||
bool isObject() const {
|
||||
return getType() == kJSTypeObject;
|
||||
}
|
||||
|
||||
RN_EXPORT Object asObject() const;
|
||||
|
||||
bool isString() const {
|
||||
return getType() == kJSTypeString;
|
||||
}
|
||||
|
||||
RN_EXPORT String toString() const;
|
||||
|
||||
// Create an error, optionally adding an additional number of lines to the stack.
|
||||
// Stack must be empty or newline terminated.
|
||||
RN_EXPORT static Value makeError(JSContextRef ctx, const char *error, const char *stack = nullptr);
|
||||
|
||||
static Value makeNumber(JSContextRef ctx, double value) {
|
||||
return Value(ctx, JSC_JSValueMakeNumber(ctx, value));
|
||||
}
|
||||
|
||||
static Value makeUndefined(JSContextRef ctx) {
|
||||
return Value(ctx, JSC_JSValueMakeUndefined(ctx));
|
||||
}
|
||||
|
||||
static Value makeNull(JSContextRef ctx) {
|
||||
return Value(ctx, JSC_JSValueMakeNull(ctx));
|
||||
}
|
||||
|
||||
static Value makeBoolean(JSContextRef ctx, bool value) {
|
||||
return Value(ctx, JSC_JSValueMakeBoolean(ctx, value));
|
||||
}
|
||||
|
||||
static Value makeString(JSContextRef ctx, const char* utf8) {
|
||||
return Value(ctx, String(ctx, utf8));
|
||||
}
|
||||
|
||||
RN_EXPORT std::string toJSONString(unsigned indent = 0) const;
|
||||
RN_EXPORT static Value fromJSON(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;
|
||||
|
||||
void throwTypeException(const std::string &expectedType) const;
|
||||
static JSValueRef fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj);
|
||||
|
||||
};
|
||||
|
||||
} }
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#pragma once
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
struct noncopyable {
|
||||
noncopyable(const noncopyable&) = delete;
|
||||
noncopyable& operator=(const noncopyable&) = delete;
|
||||
protected:
|
||||
noncopyable() = default;
|
||||
};
|
||||
}}
|
|
@ -1,154 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <jschelpers/JSCWrapper.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <objc/runtime.h>
|
||||
|
||||
// Crash the app (with a descriptive stack trace) if a function that is not supported by
|
||||
// the system JSC is called.
|
||||
#define UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(FUNC_NAME) \
|
||||
static void Unimplemented_##FUNC_NAME(__unused void* args...) { \
|
||||
assert(false); \
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(JSEvaluateBytecodeBundle)
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(JSStringCreateWithUTF8CStringExpectAscii)
|
||||
#endif
|
||||
UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(JSPokeSamplingProfiler)
|
||||
UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(JSStartSamplingProfilingOnMainJSCThread)
|
||||
|
||||
UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(JSGlobalContextEnableDebugger)
|
||||
UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(JSGlobalContextDisableDebugger)
|
||||
|
||||
UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(configureJSCForIOS)
|
||||
|
||||
UNIMPLEMENTED_SYSTEM_JSC_FUNCTION(FBJSContextStartGCTimers)
|
||||
|
||||
bool JSSamplingProfilerEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int32_t JSNoBytecodeFileFormatVersion = -1;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static JSCWrapper s_systemWrapper = {};
|
||||
|
||||
const JSCWrapper* systemJSCWrapper() {
|
||||
// Note that this is not used on Android. All methods are statically linked instead.
|
||||
// Some fields are lazily initialized
|
||||
static std::once_flag flag;
|
||||
std::call_once(flag, []() {
|
||||
s_systemWrapper = {
|
||||
.JSGlobalContextCreateInGroup = JSGlobalContextCreateInGroup,
|
||||
.JSGlobalContextRelease = JSGlobalContextRelease,
|
||||
.JSGlobalContextSetName = JSGlobalContextSetName,
|
||||
|
||||
.JSContextGetGlobalContext = JSContextGetGlobalContext,
|
||||
.JSContextGetGlobalObject = JSContextGetGlobalObject,
|
||||
.FBJSContextStartGCTimers =
|
||||
(decltype(&FBJSContextStartGCTimers))
|
||||
Unimplemented_FBJSContextStartGCTimers,
|
||||
|
||||
.JSEvaluateScript = JSEvaluateScript,
|
||||
.JSEvaluateBytecodeBundle =
|
||||
(decltype(&JSEvaluateBytecodeBundle))
|
||||
Unimplemented_JSEvaluateBytecodeBundle,
|
||||
|
||||
.JSStringCreateWithUTF8CString = JSStringCreateWithUTF8CString,
|
||||
.JSStringCreateWithCFString = JSStringCreateWithCFString,
|
||||
#if WITH_FBJSCEXTENSIONS
|
||||
.JSStringCreateWithUTF8CStringExpectAscii =
|
||||
(decltype(&JSStringCreateWithUTF8CStringExpectAscii))
|
||||
Unimplemented_JSStringCreateWithUTF8CStringExpectAscii,
|
||||
#endif
|
||||
.JSStringCopyCFString = JSStringCopyCFString,
|
||||
.JSStringGetCharactersPtr = JSStringGetCharactersPtr,
|
||||
.JSStringGetLength = JSStringGetLength,
|
||||
.JSStringGetMaximumUTF8CStringSize = JSStringGetMaximumUTF8CStringSize,
|
||||
.JSStringIsEqualToUTF8CString = JSStringIsEqualToUTF8CString,
|
||||
.JSStringRelease = JSStringRelease,
|
||||
.JSStringRetain = JSStringRetain,
|
||||
|
||||
.JSClassCreate = JSClassCreate,
|
||||
.JSClassRetain = JSClassRetain,
|
||||
.JSClassRelease = JSClassRelease,
|
||||
|
||||
.JSObjectCallAsConstructor = JSObjectCallAsConstructor,
|
||||
.JSObjectCallAsFunction = JSObjectCallAsFunction,
|
||||
.JSObjectGetPrivate = JSObjectGetPrivate,
|
||||
.JSObjectGetProperty = JSObjectGetProperty,
|
||||
.JSObjectGetPropertyAtIndex = JSObjectGetPropertyAtIndex,
|
||||
.JSObjectIsConstructor = JSObjectIsConstructor,
|
||||
.JSObjectIsFunction = JSObjectIsFunction,
|
||||
.JSObjectMake = JSObjectMake,
|
||||
.JSObjectMakeArray = JSObjectMakeArray,
|
||||
.JSObjectMakeDate = JSObjectMakeDate,
|
||||
.JSObjectMakeError = JSObjectMakeError,
|
||||
.JSObjectMakeFunctionWithCallback = JSObjectMakeFunctionWithCallback,
|
||||
.JSObjectSetPrivate = JSObjectSetPrivate,
|
||||
.JSObjectSetProperty = JSObjectSetProperty,
|
||||
.JSObjectSetPropertyAtIndex = JSObjectSetPropertyAtIndex,
|
||||
|
||||
.JSObjectCopyPropertyNames = JSObjectCopyPropertyNames,
|
||||
.JSPropertyNameArrayGetCount = JSPropertyNameArrayGetCount,
|
||||
.JSPropertyNameArrayGetNameAtIndex = JSPropertyNameArrayGetNameAtIndex,
|
||||
.JSPropertyNameArrayRelease = JSPropertyNameArrayRelease,
|
||||
|
||||
.JSValueCreateJSONString = JSValueCreateJSONString,
|
||||
.JSValueGetType = JSValueGetType,
|
||||
.JSValueMakeFromJSONString = JSValueMakeFromJSONString,
|
||||
.JSValueMakeBoolean = JSValueMakeBoolean,
|
||||
.JSValueMakeNull = JSValueMakeNull,
|
||||
.JSValueMakeNumber = JSValueMakeNumber,
|
||||
.JSValueMakeString = JSValueMakeString,
|
||||
.JSValueMakeUndefined = JSValueMakeUndefined,
|
||||
.JSValueProtect = JSValueProtect,
|
||||
.JSValueToBoolean = JSValueToBoolean,
|
||||
.JSValueToNumber = JSValueToNumber,
|
||||
.JSValueToObject = JSValueToObject,
|
||||
.JSValueToStringCopy = JSValueToStringCopy,
|
||||
.JSValueUnprotect = JSValueUnprotect,
|
||||
.JSValueIsNull = JSValueIsNull,
|
||||
|
||||
.JSSamplingProfilerEnabled = JSSamplingProfilerEnabled,
|
||||
.JSPokeSamplingProfiler =
|
||||
(decltype(&JSPokeSamplingProfiler))
|
||||
Unimplemented_JSPokeSamplingProfiler,
|
||||
.JSStartSamplingProfilingOnMainJSCThread =
|
||||
(decltype(&JSStartSamplingProfilingOnMainJSCThread))
|
||||
Unimplemented_JSStartSamplingProfilingOnMainJSCThread,
|
||||
|
||||
.JSGlobalContextEnableDebugger =
|
||||
(decltype(&JSGlobalContextEnableDebugger))
|
||||
Unimplemented_JSGlobalContextEnableDebugger,
|
||||
.JSGlobalContextDisableDebugger =
|
||||
(decltype(&JSGlobalContextDisableDebugger))
|
||||
Unimplemented_JSGlobalContextDisableDebugger,
|
||||
|
||||
.configureJSCForIOS =
|
||||
(decltype(&configureJSCForIOS))Unimplemented_configureJSCForIOS,
|
||||
|
||||
.JSContext = objc_getClass("JSContext"),
|
||||
.JSValue = objc_getClass("JSValue"),
|
||||
|
||||
.JSBytecodeFileFormatVersion = JSNoBytecodeFileFormatVersion,
|
||||
};
|
||||
});
|
||||
return &s_systemWrapper;
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := privatedata
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
PrivateDataBase.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
-DLOG_TAG=\"ReactNative\"
|
||||
|
||||
LOCAL_CFLAGS += -fexceptions -frtti
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
|
@ -1,24 +0,0 @@
|
|||
load("@fbsource//tools/build_defs:glob_defs.bzl", "subdir_glob")
|
||||
load("//tools/build_defs/oss:rn_defs.bzl", "rn_xplat_cxx_library")
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "privatedata",
|
||||
srcs = glob(["**/*.cpp"]),
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[
|
||||
("", "**/*.h"),
|
||||
],
|
||||
prefix = "privatedata",
|
||||
),
|
||||
compiler_flags = [
|
||||
"-Wall",
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-fvisibility=hidden",
|
||||
"-std=c++1y",
|
||||
],
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
)
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#include "PrivateDataBase.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
PrivateDataBase::~PrivateDataBase() {}
|
||||
|
||||
} }
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
// Base class for private data used to implement hybrid JS-native objects. A common root class,
|
||||
// rtti and dynamic_cast allow us to do some runtime type checking that makes it possible
|
||||
// for multiple hybrid object implementations to co-exist.
|
||||
class RN_EXPORT PrivateDataBase {
|
||||
public:
|
||||
virtual ~PrivateDataBase();
|
||||
|
||||
// Casts given void* to PrivateDataBase and performs dynamic_cast to desired type. Returns null on
|
||||
// failure.
|
||||
template <typename T>
|
||||
static typename std::enable_if<std::is_base_of<PrivateDataBase, T>::value, T>::type* tryCast(void* ptr) {
|
||||
return dynamic_cast<T*>(reinterpret_cast<PrivateDataBase*>(ptr));
|
||||
}
|
||||
|
||||
// Like tryCast, but aborts on failure.
|
||||
template <typename T>
|
||||
static typename std::enable_if<std::is_base_of<PrivateDataBase, T>::value, T>::type* cast(void* ptr) {
|
||||
auto result = tryCast<T>(ptr);
|
||||
if (!result) {
|
||||
assert(false && "could not cast to desired type");
|
||||
abort();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} }
|
Loading…
Reference in New Issue