-
Notifications
You must be signed in to change notification settings - Fork 24.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add JSI API and JSIDynamic glue to OSS React Native
Summary: This will help abstract the JS engine from React Native Reviewed By: hramos Differential Revision: D9328237 fbshipit-source-id: 7b34f55f28e43d83ba24d22e83e836c92ca737a9
- Loading branch information
1 parent
c95fdb0
commit e337bca
Showing
8 changed files
with
2,052 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# BUILD FILE SYNTAX: SKYLARK | ||
|
||
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_xplat_dep", "rn_xplat_cxx_library") | ||
|
||
rn_xplat_cxx_library( | ||
name = "jsi", | ||
srcs = [ | ||
"jsi.cpp", | ||
], | ||
header_namespace = "jsi", | ||
exported_headers = [ | ||
"instrumentation.h", | ||
"jsi.h", | ||
"jsi-inl.h", | ||
], | ||
compiler_flags = [ | ||
"-O3", | ||
"-fexceptions", | ||
"-frtti", | ||
"-std=c++14", | ||
"-Wall", | ||
"-Werror", | ||
"-Wextra", | ||
"-Wcast-qual", | ||
"-Wdelete-non-virtual-dtor", | ||
"-Wwrite-strings", | ||
], | ||
cxx_compiler_flags = [ | ||
"-Wglobal-constructors", | ||
"-Wmissing-prototypes", | ||
], | ||
fbobjc_compiler_flags = [ | ||
"-Wglobal-constructors", | ||
"-Wmissing-prototypes", | ||
], | ||
visibility = ["PUBLIC"], | ||
) | ||
|
||
rn_xplat_cxx_library( | ||
name = "JSIDynamic", | ||
srcs = [ | ||
"JSIDynamic.cpp", | ||
], | ||
header_namespace = "jsi", | ||
exported_headers = [ | ||
"JSIDynamic.h", | ||
], | ||
compiler_flags = [ | ||
"-fexceptions", | ||
"-frtti", | ||
], | ||
fbobjc_force_static = True, | ||
visibility = [ | ||
"PUBLIC", | ||
], | ||
xcode_public_headers_symlinks = True, | ||
deps = [ | ||
"xplat//folly:molly", | ||
react_native_xplat_dep("jsi:jsi"), | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Copyright 2004-present Facebook. All Rights Reserved. | ||
|
||
#include "JSIDynamic.h" | ||
|
||
#include <folly/dynamic.h> | ||
#include <jsi/jsi.h> | ||
|
||
using namespace facebook::jsi; | ||
|
||
namespace facebook { | ||
namespace jsi { | ||
|
||
Value valueFromDynamic(Runtime& runtime, const folly::dynamic& dyn) { | ||
switch (dyn.type()) { | ||
case folly::dynamic::NULLT: | ||
return Value::null(); | ||
case folly::dynamic::ARRAY: { | ||
Array ret = Array(runtime, dyn.size()); | ||
for (size_t i = 0; i < dyn.size(); ++i) { | ||
ret.setValueAtIndex(runtime, i, valueFromDynamic(runtime, dyn[i])); | ||
} | ||
return std::move(ret); | ||
} | ||
case folly::dynamic::BOOL: | ||
return dyn.getBool(); | ||
case folly::dynamic::DOUBLE: | ||
return dyn.getDouble(); | ||
case folly::dynamic::INT64: | ||
// Can't use asDouble() here. If the int64 value is too bit to be | ||
// represented precisely as a double, folly will throw an | ||
// exception. | ||
return (double)dyn.getInt(); | ||
case folly::dynamic::OBJECT: { | ||
Object ret(runtime); | ||
for (const auto& element : dyn.items()) { | ||
Value value = valueFromDynamic(runtime, element.second); | ||
if (element.first.isNumber() || element.first.isString()) { | ||
ret.setProperty(runtime, element.first.asString().c_str(), value); | ||
} | ||
} | ||
return std::move(ret); | ||
} | ||
case folly::dynamic::STRING: | ||
return String::createFromUtf8(runtime, dyn.getString()); | ||
} | ||
CHECK(false); | ||
} | ||
|
||
folly::dynamic dynamicFromValue(Runtime& runtime, const Value& value) { | ||
if (value.isUndefined() || value.isNull()) { | ||
return nullptr; | ||
} else if (value.isBool()) { | ||
return value.getBool(); | ||
} else if (value.isNumber()) { | ||
return value.getNumber(); | ||
} else if (value.isString()) { | ||
return value.getString(runtime).utf8(runtime); | ||
} else { | ||
Object obj = value.getObject(runtime); | ||
if (obj.isArray(runtime)) { | ||
Array array = obj.getArray(runtime); | ||
folly::dynamic ret = folly::dynamic::array(); | ||
for (size_t i = 0; i < array.size(runtime); ++i) { | ||
ret.push_back(dynamicFromValue(runtime, array.getValueAtIndex(runtime, i))); | ||
} | ||
return ret; | ||
} else if (obj.isFunction(runtime)) { | ||
throw JSError(runtime, "JS Functions are not convertible to dynamic"); | ||
} else { | ||
folly::dynamic ret = folly::dynamic::object(); | ||
Array names = obj.getPropertyNames(runtime); | ||
for (size_t i = 0; i < names.size(runtime); ++i) { | ||
String name = names.getValueAtIndex(runtime, i).getString(runtime); | ||
Value prop = obj.getProperty(runtime, name); | ||
if (prop.isUndefined()) { | ||
continue; | ||
} | ||
// The JSC conversion uses JSON.stringify, which substitutes | ||
// null for a function, so we do the same here. Just dropping | ||
// the pair might also work, but would require more testing. | ||
if (prop.isObject() && prop.getObject(runtime).isFunction(runtime)) { | ||
prop = Value::null(); | ||
} | ||
ret.insert( | ||
name.utf8(runtime), dynamicFromValue(runtime, std::move(prop))); | ||
} | ||
return ret; | ||
} | ||
} | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright 2004-present Facebook. All Rights Reserved. | ||
|
||
#pragma once | ||
|
||
#include <folly/dynamic.h> | ||
#include <jsi/jsi.h> | ||
|
||
namespace facebook { | ||
namespace jsi { | ||
|
||
facebook::jsi::Value valueFromDynamic( | ||
facebook::jsi::Runtime& runtime, const folly::dynamic& dyn); | ||
|
||
folly::dynamic dynamicFromValue(facebook::jsi::Runtime& runtime, | ||
const facebook::jsi::Value& value); | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright 2004-present Facebook. All Rights Reserved. | ||
|
||
#pragma once | ||
|
||
#include <string> | ||
|
||
#include <jsi/jsi.h> | ||
|
||
namespace facebook { | ||
namespace jsi { | ||
|
||
/// Methods for starting and collecting instrumentation, an \c Instrumentation | ||
/// instance is associated with a particular \c Runtime instance, which it | ||
/// controls the instrumentation of. | ||
class Instrumentation { | ||
public: | ||
virtual ~Instrumentation() = default; | ||
|
||
/// Returns GC statistics as a JSON-encoded string, with an object containing | ||
/// "type" and "version" fields outermost. "type" is a string, unique to a | ||
/// particular implementation of \c jsi::Instrumentation, and "version" is a | ||
/// number to indicate any revision to that implementation and its output | ||
/// format. | ||
/// | ||
/// \pre This call can only be made on the instrumentation instance of a | ||
/// runtime initialised to collect GC statistics. | ||
/// | ||
/// \post All cumulative measurements mentioned in the output are accumulated | ||
/// across the entire lifetime of the Runtime. | ||
/// | ||
/// \return the GC statistics collected so far, as a JSON-encoded string. | ||
virtual std::string getRecordedGCStats() = 0; | ||
|
||
/// Request statistics about the current state of the runtime's heap. This | ||
/// function can be called at any time, and should produce information that is | ||
/// correct at the instant it is called (i.e, not stale). | ||
/// | ||
/// \return a jsi Value containing whichever statistics the runtime supports | ||
/// for its heap. | ||
virtual Value getHeapInfo(bool includeExpensive) = 0; | ||
|
||
/// perform a full garbage collection | ||
virtual void collectGarbage() = 0; | ||
|
||
/// Captures the heap to a file | ||
/// | ||
/// \param path to save the heap capture | ||
/// | ||
/// \param compact Whether the JSON should be compact or pretty | ||
/// | ||
/// \return true iff the heap capture succeeded | ||
virtual bool createSnapshotToFile(const std::string& path, bool compact) = 0; | ||
|
||
/// Write a trace of bridge traffic to the given file name. | ||
virtual void writeBridgeTrafficTraceToFile( | ||
const std::string& fileName) const = 0; | ||
|
||
/// Write basic block profile trace to the given file name. | ||
virtual void writeBasicBlockProfileTraceToFile( | ||
const std::string& fileName) const = 0; | ||
|
||
/// Enable sampling profiler. | ||
virtual void enableSamplingProfiler() const = 0; | ||
|
||
/// Dump sampled stack trace to the given file name. | ||
virtual void dumpSampledTraceToFile(const std::string& fileName) const = 0; | ||
|
||
/// Dump external profiler symbols to the given file name. | ||
virtual void dumpProfilerSymbolsToFile(const std::string& fileName) const = 0; | ||
}; | ||
|
||
} // namespace jsi | ||
} // namespace facebook |
Oops, something went wrong.