mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-03-29 07:48:17 +08:00
Add new FileSourceProvider
Summary: Add a new interface to JSC that allows loading a file lazily from disk, i.e. using mmap, instead of loading the whole file upfront and copying into the VM. Reviewed By: michalgr Differential Revision: D3534042 fbshipit-source-id: 98b193cc7b7e33248073e2556ea94ce3391507c7
This commit is contained in:
committed by
Facebook Github Bot 9
parent
e5650560c0
commit
5d06918d07
@@ -7,6 +7,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#include "JSModulesUnbundle.h"
|
||||
@@ -134,6 +136,68 @@ private:
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
class JSBigMmapString : public JSBigString {
|
||||
public:
|
||||
enum class Encoding {
|
||||
Unknown,
|
||||
Ascii,
|
||||
Utf8,
|
||||
Utf16,
|
||||
};
|
||||
|
||||
|
||||
JSBigMmapString(int fd, size_t size, const uint8_t sha1[20], Encoding encoding) :
|
||||
m_fd(fd),
|
||||
m_size(size),
|
||||
m_encoding(encoding),
|
||||
m_str(nullptr)
|
||||
{
|
||||
memcpy(m_hash, sha1, 20);
|
||||
}
|
||||
|
||||
~JSBigMmapString() {
|
||||
if (m_str) {
|
||||
CHECK(munmap((void *)m_str, m_size) != -1);
|
||||
}
|
||||
close(m_fd);
|
||||
}
|
||||
|
||||
bool isAscii() const override {
|
||||
return m_encoding == Encoding::Ascii;
|
||||
}
|
||||
|
||||
const char* c_str() const override {
|
||||
if (!m_str) {
|
||||
m_str = (const char *)mmap(0, m_size, PROT_READ, MAP_SHARED, m_fd, 0);
|
||||
CHECK(m_str != MAP_FAILED);
|
||||
}
|
||||
return m_str;
|
||||
}
|
||||
|
||||
size_t size() const override {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
int fd() const {
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
const uint8_t* hash() const {
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
Encoding encoding() const {
|
||||
return m_encoding;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_fd;
|
||||
size_t m_size;
|
||||
uint8_t m_hash[20];
|
||||
Encoding m_encoding;
|
||||
mutable const char *m_str;
|
||||
};
|
||||
|
||||
class JSExecutor {
|
||||
public:
|
||||
/**
|
||||
|
||||
@@ -253,10 +253,33 @@ void JSCExecutor::terminateOnJSVMThread() {
|
||||
m_context = nullptr;
|
||||
}
|
||||
|
||||
#ifdef WITH_FBJSCEXTENSIONS
|
||||
static void loadApplicationSource(
|
||||
const JSGlobalContextRef context,
|
||||
const JSBigMmapString* script,
|
||||
const std::string& sourceURL) {
|
||||
String jsSourceURL(sourceURL.c_str());
|
||||
bool is8bit = script->encoding() == JSBigMmapString::Encoding::Ascii || script->encoding() == JSBigMmapString::Encoding::Utf8;
|
||||
JSSourceCodeRef sourceCode = JSCreateSourceCode(script->fd(), script->size(), jsSourceURL, script->hash(), is8bit);
|
||||
evaluateSourceCode(context, sourceCode, jsSourceURL);
|
||||
JSReleaseSourceCode(sourceCode);
|
||||
}
|
||||
#endif
|
||||
|
||||
void JSCExecutor::loadApplicationScript(std::unique_ptr<const JSBigString> script, std::string sourceURL) throw(JSException) {
|
||||
SystraceSection s("JSCExecutor::loadApplicationScript",
|
||||
"sourceURL", sourceURL);
|
||||
|
||||
#ifdef WITH_FBJSCEXTENSIONS
|
||||
if (auto source = dynamic_cast<const JSBigMmapString *>(script.get())) {
|
||||
loadApplicationSource(m_context, source, sourceURL);
|
||||
bindBridge();
|
||||
flush();
|
||||
ReactMarker::logMarker("CREATE_REACT_CONTEXT_END");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
fbsystrace_begin_section(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE,
|
||||
|
||||
@@ -44,47 +44,63 @@ JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef
|
||||
JSValueRef exn, result;
|
||||
result = JSEvaluateScript(context, script, NULL, source, 0, &exn);
|
||||
if (result == nullptr) {
|
||||
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());
|
||||
}
|
||||
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)) };
|
||||
|
||||
@@ -49,6 +49,18 @@ JSValueRef evaluateScript(
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user