Merge facebook/hermes version RN 0.74.2 and update JSI (#187)
* Integrate hermes-0.74.2 * Update JSI * Set the default JSI version to 11
This commit is contained in:
Родитель
fcd054c410
Коммит
4657e24da3
|
@ -94,16 +94,18 @@ if(HERMES_THREAD_SAFETY_ANALYSIS)
|
|||
endif()
|
||||
|
||||
add_hermes_library(synthTrace hermes_tracing.cpp SynthTrace.cpp TracingRuntime.cpp
|
||||
LINK_LIBS libhermes hermesPlatform)
|
||||
LINK_LIBS libhermes2 hermesPlatform)
|
||||
|
||||
add_hermes_library(timerStats TimerStats.cpp LINK_LIBS jsi hermesSupport)
|
||||
|
||||
add_hermes_library(traceInterpreter TraceInterpreter.cpp
|
||||
LINK_LIBS libhermes hermesInstrumentation synthTrace synthTraceParser)
|
||||
LINK_LIBS libhermes2 hermesInstrumentation synthTrace synthTraceParser)
|
||||
|
||||
add_library(libhermes2 ${api_sources})
|
||||
target_link_libraries(libhermes2 PUBLIC jsi PRIVATE hermesVMRuntime ${INSPECTOR_DEPS})
|
||||
target_link_options(libhermes2 PRIVATE ${HERMES_EXTRA_LINKER_FLAGS})
|
||||
|
||||
# Export the required header directory
|
||||
target_include_directories(libhermes2 PUBLIC .. ../../public ${HERMES_JSI_DIR})
|
||||
|
||||
add_library(libhermes SHARED ${api_sources2})
|
||||
|
@ -156,7 +158,6 @@ set_target_properties(libhermes PROPERTIES
|
|||
OUTPUT_NAME hermes
|
||||
)
|
||||
|
||||
# Create a lean version of libhermes in the same way.
|
||||
add_library(libhermes_lean ${api_sources})
|
||||
target_link_libraries(libhermes_lean PUBLIC jsi PRIVATE hermesVMRuntimeLean ${INSPECTOR_DEPS})
|
||||
target_link_options(libhermes_lean PRIVATE ${HERMES_EXTRA_LINKER_FLAGS})
|
||||
|
@ -171,7 +172,7 @@ target_include_directories(libhermes_lean PUBLIC
|
|||
set_target_properties(libhermes_lean PROPERTIES OUTPUT_NAME hermes_lean)
|
||||
|
||||
if(APPLE AND HERMES_BUILD_APPLE_FRAMEWORK)
|
||||
set_target_properties(libhermes PROPERTIES
|
||||
set_target_properties(libhermes2 PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION}
|
||||
|
@ -188,26 +189,26 @@ if(APPLE AND HERMES_BUILD_APPLE_FRAMEWORK)
|
|||
MACOSX_PACKAGE_LOCATION Headers/Public
|
||||
)
|
||||
if(HERMES_ENABLE_BITCODE)
|
||||
target_compile_options(libhermes PUBLIC "-fembed-bitcode")
|
||||
target_link_options(libhermes PUBLIC "-fembed-bitcode")
|
||||
target_compile_options(libhermes2 PUBLIC "-fembed-bitcode")
|
||||
target_link_options(libhermes2 PUBLIC "-fembed-bitcode")
|
||||
endif()
|
||||
# Define the deployment target in the frameworks metadata
|
||||
if(HERMES_APPLE_TARGET_PLATFORM MATCHES "iphone")
|
||||
add_custom_command(TARGET libhermes POST_BUILD
|
||||
COMMAND /usr/libexec/PlistBuddy -c "Add :MinimumOSVersion string ${CMAKE_OSX_DEPLOYMENT_TARGET}" $<TARGET_FILE_DIR:libhermes>/Info.plist
|
||||
add_custom_command(TARGET libhermes2 POST_BUILD
|
||||
COMMAND /usr/libexec/PlistBuddy -c "Add :MinimumOSVersion string ${CMAKE_OSX_DEPLOYMENT_TARGET}" $<TARGET_FILE_DIR:libhermes2>/Info.plist
|
||||
)
|
||||
elseif(HERMES_APPLE_TARGET_PLATFORM MATCHES "catalyst")
|
||||
add_custom_command(TARGET libhermes POST_BUILD
|
||||
COMMAND /usr/libexec/PlistBuddy -c "Add :LSMinimumSystemVersion string ${CMAKE_OSX_DEPLOYMENT_TARGET}" $<TARGET_FILE_DIR:libhermes>/Resources/Info.plist
|
||||
add_custom_command(TARGET libhermes2 POST_BUILD
|
||||
COMMAND /usr/libexec/PlistBuddy -c "Add :LSMinimumSystemVersion string ${CMAKE_OSX_DEPLOYMENT_TARGET}" $<TARGET_FILE_DIR:libhermes2>/Resources/Info.plist
|
||||
)
|
||||
elseif(HERMES_APPLE_TARGET_PLATFORM MATCHES "macos")
|
||||
add_custom_command(TARGET libhermes POST_BUILD
|
||||
COMMAND /usr/libexec/PlistBuddy -c "Add :LSMinimumSystemVersion string ${CMAKE_OSX_DEPLOYMENT_TARGET}" $<TARGET_FILE_DIR:libhermes>/Resources/Info.plist
|
||||
add_custom_command(TARGET libhermes2 POST_BUILD
|
||||
COMMAND /usr/libexec/PlistBuddy -c "Add :LSMinimumSystemVersion string ${CMAKE_OSX_DEPLOYMENT_TARGET}" $<TARGET_FILE_DIR:libhermes2>/Resources/Info.plist
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
install(TARGETS libhermes
|
||||
install(TARGETS libhermes2
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
|
@ -222,11 +223,11 @@ install(DIRECTORY "${PROJECT_SOURCE_DIR}/API/hermes" DESTINATION include
|
|||
# Largely inspired by https://github.com/llvm/llvm-project/blob/6701993027f8af172d7ba697884459261b00e3c6/llvm/cmake/modules/AddLLVM.cmake#L1934-L1986
|
||||
if(HERMES_BUILD_APPLE_DSYM)
|
||||
if(CMAKE_CXX_FLAGS MATCHES "-flto")
|
||||
set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/libhermes-lto.o)
|
||||
set_property(TARGET libhermes APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-object_path_lto,${lto_object}")
|
||||
set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/libhermes2-lto.o)
|
||||
set_property(TARGET libhermes2 APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-object_path_lto,${lto_object}")
|
||||
endif()
|
||||
|
||||
get_target_property(DSYM_PATH libhermes LOCATION)
|
||||
get_target_property(DSYM_PATH libhermes2 LOCATION)
|
||||
if(HERMES_BUILD_APPLE_FRAMEWORK)
|
||||
get_filename_component(DSYM_PATH ${DSYM_PATH} DIRECTORY)
|
||||
endif()
|
||||
|
@ -235,8 +236,8 @@ if(HERMES_BUILD_APPLE_DSYM)
|
|||
if(NOT CMAKE_DSYMUTIL)
|
||||
set(CMAKE_DSYMUTIL xcrun dsymutil)
|
||||
endif()
|
||||
add_custom_command(TARGET libhermes POST_BUILD
|
||||
COMMAND ${CMAKE_DSYMUTIL} $<TARGET_FILE:libhermes> --out ${DSYM_PATH}
|
||||
add_custom_command(TARGET libhermes2 POST_BUILD
|
||||
COMMAND ${CMAKE_DSYMUTIL} $<TARGET_FILE:libhermes2> --out ${DSYM_PATH}
|
||||
BYPRODUCTS ${DSYM_PATH}
|
||||
)
|
||||
|
||||
|
|
|
@ -710,8 +710,6 @@ class HermesRuntimeImpl final : public HermesRuntime,
|
|||
void checkStatus(vm::ExecutionStatus);
|
||||
vm::HermesValue stringHVFromAscii(const char *ascii, size_t length);
|
||||
vm::HermesValue stringHVFromUtf8(const uint8_t *utf8, size_t length);
|
||||
size_t getLength(vm::Handle<vm::ArrayImpl> arr);
|
||||
size_t getByteLength(vm::Handle<vm::JSArrayBuffer> arr);
|
||||
std::string utf8FromStringView(vm::StringView view);
|
||||
|
||||
/// Extract a UTF-8 message from the given exception \p ex as UTF-16. Uses
|
||||
|
@ -2374,27 +2372,6 @@ vm::HermesValue HermesRuntimeImpl::stringHVFromUtf8(
|
|||
return *strRes;
|
||||
}
|
||||
|
||||
size_t HermesRuntimeImpl::getLength(vm::Handle<vm::ArrayImpl> arr) {
|
||||
auto res = vm::JSObject::getNamed_RJS(
|
||||
arr, runtime_, vm::Predefined::getSymbolID(vm::Predefined::length));
|
||||
checkStatus(res.getStatus());
|
||||
if (!(*res)->isNumber()) {
|
||||
throw jsi::JSError(*this, "getLength: property 'length' is not a number");
|
||||
}
|
||||
return static_cast<size_t>((*res)->getDouble());
|
||||
}
|
||||
|
||||
size_t HermesRuntimeImpl::getByteLength(vm::Handle<vm::JSArrayBuffer> arr) {
|
||||
auto res = vm::JSObject::getNamed_RJS(
|
||||
arr, runtime_, vm::Predefined::getSymbolID(vm::Predefined::byteLength));
|
||||
checkStatus(res.getStatus());
|
||||
if (!(*res)->isNumber()) {
|
||||
throw jsi::JSError(
|
||||
*this, "getLength: property 'byteLength' is not a number");
|
||||
}
|
||||
return static_cast<size_t>((*res)->getDouble());
|
||||
}
|
||||
|
||||
void HermesRuntimeImpl::throwPendingError() {
|
||||
vm::GCScope scope{runtime_};
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ add_hermes_tool(hcds
|
|||
|
||||
# TODO: Even though this does not use llvh at all, a quirk of our build is that
|
||||
# pthread is found and provided by llvh.
|
||||
target_link_libraries(hcds libhermes LLVHSupport)
|
||||
target_link_libraries(hcds libhermes2 LLVHSupport)
|
||||
|
||||
install(TARGETS hcds
|
||||
RUNTIME DESTINATION bin
|
||||
|
|
|
@ -9,8 +9,11 @@ It is being used by React Native project to work with JS engines.
|
|||
JSI has versions associated with the following commit hashes in the
|
||||
https://github.com/facebook/hermes repo.
|
||||
|
||||
| Version | Commit Hash | Commit Description
|
||||
|--------:|:-----------------------------------------|------------------------------------------------------
|
||||
| Version | Commit Hash | Commit Description
|
||||
|--------:|:-------------------------------------------|------------------------------------------------------
|
||||
| 12 | `de9dfe408bc3f8715aef161c5fcec291fc6dacb2` | Add queueMicrotask method to JSI
|
||||
| | `a699e87f995bc2f7193990ff36a57ec9cad940e5` | Make queueMicrotask pure virtual
|
||||
| 11 | `a1c168705f609c8f1ae800c60d88eb199154264b` | Add JSI method for setting external memory size
|
||||
| 10 | `b81666598672cb5f8b365fe6548d3273f216322e` | Clarify const-ness of JSI references
|
||||
| 9 | `e6d887ae96bef5c71032f11ed1a9fb9fecec7b46` | Add external ArrayBuffers to JSI
|
||||
| 8 | `4d64e61a1f9926eca0afd4eb38d17cea30bdc34c` | Add BigInt JSI API support
|
||||
|
@ -22,4 +25,16 @@ https://github.com/facebook/hermes repo.
|
|||
| 3 | `0c9daa5a5eee7649558a53e3e541b80c89048c42` | Change jsi::Runtime::lockWeakObject to take a mutable ref
|
||||
| 2 | `e0616e77e1ddc3ea5e2ccbca2e20dd0c4049c637` | Make it possible for a Runtime implementation to provide its own JSON parsing
|
||||
| 1 | `3ba9615f80913764ecb6456779d502e31dde9e5d` | Fix build break in MSVC (#26462)
|
||||
| 0 | `f22a18f67da3f03db59c1ec715d6ec3776b03fbf` | Initial commit
|
||||
| 0 | `f22a18f67da3f03db59c1ec715d6ec3776b03fbf` | Initial commit
|
||||
|
||||
Relationship to React Native versions:
|
||||
|
||||
| RN Version | JSI version |
|
||||
|-----------:|------------:|
|
||||
| main | 12 |
|
||||
| 0.74 | 11 |
|
||||
| 0.73 | 10 |
|
||||
| 0.72 | 10 |
|
||||
| 0.71 | 9 |
|
||||
| 0.70 | 6 |
|
||||
| 0.69 | 5 |
|
||||
|
|
|
@ -126,6 +126,11 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
|
|||
const std::shared_ptr<const PreparedJavaScript>& js) override {
|
||||
return plain().evaluatePreparedJavaScript(js);
|
||||
}
|
||||
#if JSI_VERSION >= 12
|
||||
void queueMicrotask(const jsi::Function& callback) override {
|
||||
return plain().queueMicrotask(callback);
|
||||
}
|
||||
#endif
|
||||
#if JSI_VERSION >= 4
|
||||
bool drainMicrotasks(int maxMicrotasksHint) override {
|
||||
return plain().drainMicrotasks(maxMicrotasksHint);
|
||||
|
@ -262,9 +267,11 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if JSI_VERSION >= 11
|
||||
void setExternalMemoryPressure(const Object& obj, size_t amt) override {
|
||||
plain_.setExternalMemoryPressure(obj, amt);
|
||||
}
|
||||
#endif
|
||||
|
||||
Value getProperty(const Object& o, const PropNameID& name) override {
|
||||
return plain_.getProperty(o, name);
|
||||
|
|
|
@ -232,10 +232,12 @@ inline void Object::setNativeState(
|
|||
}
|
||||
#endif
|
||||
|
||||
#if JSI_VERSION >= 11
|
||||
inline void Object::setExternalMemoryPressure(Runtime& runtime, size_t amt)
|
||||
const {
|
||||
runtime.setExternalMemoryPressure(*this, amt);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline Array Object::getPropertyNames(Runtime& runtime) const {
|
||||
return runtime.getPropertyNames(*this);
|
||||
|
|
|
@ -15,22 +15,20 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifndef JSI_EXPORT
|
||||
#ifdef _MSC_VER
|
||||
#ifdef CREATE_SHARED_LIBRARY
|
||||
#define JSI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define JSI_EXPORT
|
||||
#endif // CREATE_SHARED_LIBRARY
|
||||
#else // _MSC_VER
|
||||
#define JSI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _MSC_VER
|
||||
#endif // !defined(JSI_EXPORT)
|
||||
|
||||
// JSI version defines set of features available in the API.
|
||||
// Each significant API change must be under a new version.
|
||||
// The JSI_VERSION can be provided as a parameter to compiler
|
||||
// or in the optional "jsi_version.h" file.
|
||||
|
||||
#ifndef JSI_VERSION
|
||||
#define JSI_VERSION 10
|
||||
#if defined(__has_include) && __has_include(<jsi/jsi-version.h>)
|
||||
#include <jsi/jsi-version.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef JSI_VERSION
|
||||
// Use the latest version by default
|
||||
#define JSI_VERSION 11
|
||||
#endif
|
||||
|
||||
#if JSI_VERSION >= 3
|
||||
|
@ -45,6 +43,18 @@
|
|||
#define JSI_CONST_10
|
||||
#endif
|
||||
|
||||
#ifndef JSI_EXPORT
|
||||
#ifdef _MSC_VER
|
||||
#ifdef CREATE_SHARED_LIBRARY
|
||||
#define JSI_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define JSI_EXPORT
|
||||
#endif // CREATE_SHARED_LIBRARY
|
||||
#else // _MSC_VER
|
||||
#define JSI_EXPORT __attribute__((visibility("default")))
|
||||
#endif // _MSC_VER
|
||||
#endif // !defined(JSI_EXPORT)
|
||||
|
||||
class FBJSRuntime;
|
||||
namespace facebook {
|
||||
namespace jsi {
|
||||
|
@ -233,6 +243,15 @@ class JSI_EXPORT Runtime {
|
|||
virtual Value evaluatePreparedJavaScript(
|
||||
const std::shared_ptr<const PreparedJavaScript>& js) = 0;
|
||||
|
||||
#if JSI_VERSION >= 12
|
||||
/// Queues a microtask in the JavaScript VM internal Microtask (a.k.a. Job in
|
||||
/// ECMA262) queue, to be executed when the host drains microtasks in
|
||||
/// its event loop implementation.
|
||||
///
|
||||
/// \param callback a function to be executed as a microtask.
|
||||
virtual void queueMicrotask(const jsi::Function& callback) = 0;
|
||||
#endif
|
||||
|
||||
#if JSI_VERSION >= 4
|
||||
/// Drain the JavaScript VM internal Microtask (a.k.a. Job in ECMA262) queue.
|
||||
///
|
||||
|
@ -430,11 +449,13 @@ class JSI_EXPORT Runtime {
|
|||
virtual bool strictEquals(const Object& a, const Object& b) const = 0;
|
||||
|
||||
virtual bool instanceOf(const Object& o, const Function& f) = 0;
|
||||
//TODO: (vmoroz) add version for setExternalMemoryPressure
|
||||
|
||||
#if JSI_VERSION >= 11
|
||||
/// See Object::setExternalMemoryPressure.
|
||||
virtual void setExternalMemoryPressure(
|
||||
const jsi::Object& obj,
|
||||
size_t amount) = 0;
|
||||
#endif
|
||||
|
||||
// These exist so derived classes can access the private parts of
|
||||
// Value, Symbol, String, and Object, which are all friends of Runtime.
|
||||
|
@ -895,7 +916,7 @@ class JSI_EXPORT Object : public Pointer {
|
|||
/// works. I only need it in one place.)
|
||||
Array getPropertyNames(Runtime& runtime) const;
|
||||
|
||||
//TODO: (vmoroz) add version for setExternalMemoryPressure
|
||||
#if JSI_VERSION >= 11
|
||||
/// Inform the runtime that there is additional memory associated with a given
|
||||
/// JavaScript object that is not visible to the GC. This can be used if an
|
||||
/// object is known to retain some native memory, and may be used to guide
|
||||
|
@ -905,6 +926,7 @@ class JSI_EXPORT Object : public Pointer {
|
|||
/// collected, the associated external memory will be considered freed and may
|
||||
/// no longer factor into GC decisions.
|
||||
void setExternalMemoryPressure(Runtime& runtime, size_t amt) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void setPropertyValue(
|
||||
|
|
|
@ -69,7 +69,6 @@ TEST_P(JSITestExt, ArrayBufferTest) {
|
|||
}
|
||||
|
||||
#if JSI_VERSION >= 9
|
||||
#ifndef JSI_V8_IMPL
|
||||
TEST_P(JSITestExt, ExternalArrayBufferTest) {
|
||||
struct FixedBuffer : MutableBuffer {
|
||||
size_t size() const override {
|
||||
|
@ -99,7 +98,6 @@ TEST_P(JSITestExt, ExternalArrayBufferTest) {
|
|||
EXPECT_EQ(buf->arr[i], i * i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_P(JSITestExt, NoCorruptionOnJSError) {
|
||||
// If the test crashes or infinite loops, the likely cause is that
|
||||
|
@ -224,6 +222,63 @@ TEST_P(JSITestExt, HostObjectWithOwnProperties) {
|
|||
}
|
||||
#endif
|
||||
|
||||
TEST_P(JSITestExt, WeakReferences) {
|
||||
Object o = eval("({one: 1})").getObject(rt);
|
||||
WeakObject wo = WeakObject(rt, o);
|
||||
rt.global().setProperty(rt, "obj", o);
|
||||
|
||||
eval("gc()");
|
||||
|
||||
Value v = wo.lock(rt);
|
||||
|
||||
// At this point, the object has three strong refs (C++ o, v; JS global.obj).
|
||||
|
||||
EXPECT_TRUE(v.isObject());
|
||||
EXPECT_EQ(v.getObject(rt).getProperty(rt, "one").asNumber(), 1);
|
||||
|
||||
// Now start removing references.
|
||||
|
||||
v = nullptr;
|
||||
|
||||
// Two left
|
||||
|
||||
eval("gc()");
|
||||
EXPECT_EQ(wo.lock(rt).getObject(rt).getProperty(rt, "one").asNumber(), 1);
|
||||
|
||||
o = Object(rt);
|
||||
|
||||
// Now one, only JS
|
||||
|
||||
eval("gc()");
|
||||
EXPECT_EQ(wo.lock(rt).getObject(rt).getProperty(rt, "one").asNumber(), 1);
|
||||
|
||||
eval("obj = null");
|
||||
|
||||
// Now none.
|
||||
|
||||
eval("gc()");
|
||||
EXPECT_TRUE(wo.lock(rt).isUndefined());
|
||||
|
||||
// test where the last ref is C++
|
||||
|
||||
o = eval("({two: 2})").getObject(rt);
|
||||
wo = WeakObject(rt, o);
|
||||
v = Value(rt, o);
|
||||
|
||||
eval("gc()");
|
||||
EXPECT_EQ(wo.lock(rt).getObject(rt).getProperty(rt, "two").asNumber(), 2);
|
||||
|
||||
v = nullptr;
|
||||
|
||||
eval("gc()");
|
||||
EXPECT_EQ(wo.lock(rt).getObject(rt).getProperty(rt, "two").asNumber(), 2);
|
||||
|
||||
o = Object(rt);
|
||||
|
||||
eval("gc()");
|
||||
EXPECT_TRUE(wo.lock(rt).isUndefined());
|
||||
}
|
||||
|
||||
TEST_P(JSITestExt, HostObjectAsParentTest) {
|
||||
class HostObjectWithProp : public HostObject {
|
||||
Value get(Runtime& runtime, const PropNameID& name) override {
|
||||
|
@ -242,6 +297,54 @@ TEST_P(JSITestExt, HostObjectAsParentTest) {
|
|||
eval("var subClass = {__proto__: ho}; subClass.prop1 == 10;").getBool());
|
||||
}
|
||||
|
||||
#if JSI_VERSION >= 7
|
||||
TEST_P(JSITestExt, NativeStateTest) {
|
||||
class C : public facebook::jsi::NativeState {
|
||||
public:
|
||||
int* dtors;
|
||||
C(int* _dtors) : dtors(_dtors) {}
|
||||
virtual ~C() override {
|
||||
++*dtors;
|
||||
}
|
||||
};
|
||||
int dtors1 = 0;
|
||||
int dtors2 = 0;
|
||||
{
|
||||
Object obj = eval("({one: 1})").getObject(rt);
|
||||
ASSERT_FALSE(obj.hasNativeState<C>(rt));
|
||||
{
|
||||
// Set some state.
|
||||
obj.setNativeState(rt, std::make_shared<C>(&dtors1));
|
||||
ASSERT_TRUE(obj.hasNativeState<C>(rt));
|
||||
auto ptr = obj.getNativeState<C>(rt);
|
||||
EXPECT_EQ(ptr->dtors, &dtors1);
|
||||
}
|
||||
{
|
||||
// Overwrite the state.
|
||||
obj.setNativeState(rt, std::make_shared<C>(&dtors2));
|
||||
ASSERT_TRUE(obj.hasNativeState<C>(rt));
|
||||
auto ptr = obj.getNativeState<C>(rt);
|
||||
EXPECT_EQ(ptr->dtors, &dtors2);
|
||||
}
|
||||
} // closing scope -> obj unreachable
|
||||
// should finalize both
|
||||
eval("gc()");
|
||||
EXPECT_EQ(1, dtors1);
|
||||
EXPECT_EQ(1, dtors2);
|
||||
|
||||
// Trying to set native state on frozen object should throw.
|
||||
// TODO: Make V8 implementation to throw here.
|
||||
// {
|
||||
// Object frozen = eval("Object.freeze({one: 1})").getObject(rt);
|
||||
// ASSERT_THROW(
|
||||
// frozen.setNativeState(rt, std::make_shared<C>(&dtors1)), JSIException);
|
||||
// }
|
||||
// Make sure any NativeState cells are finalized before leaving, since they
|
||||
// point to local variables. Otherwise ASAN will complain.
|
||||
eval("gc()");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if JSI_VERSION >= 5
|
||||
TEST_P(JSITestExt, PropNameIDFromSymbol) {
|
||||
auto strProp = PropNameID::forAscii(rt, "a");
|
||||
|
@ -294,7 +397,6 @@ TEST_P(JSITestExt, GlobalObjectTest) {
|
|||
#endif
|
||||
|
||||
#if JSI_VERSION >= 8
|
||||
#if !defined(JSI_V8_IMPL)
|
||||
TEST_P(JSITestExt, BigIntJSI) {
|
||||
Function bigintCtor = rt.global().getPropertyAsFunction(rt, "BigInt");
|
||||
auto BigInt = [&](const char* v) { return bigintCtor.call(rt, eval(v)); };
|
||||
|
@ -424,7 +526,6 @@ TEST_P(JSITestExt, BigIntJSITruncation) {
|
|||
EXPECT_EQ(toInt64(b), lossy(~0ull));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TEST_P(JSITestExt, NativeExceptionDoesNotUseGlobalError) {
|
||||
Function alwaysThrows = Function::createFromHostFunction(
|
||||
|
|
|
@ -288,7 +288,7 @@ set(HERMES_ENABLE_TEST_SUITE ON CACHE BOOL
|
|||
"Enable the test suite")
|
||||
|
||||
set(HERMES_BUILD_APPLE_FRAMEWORK ON CACHE BOOL
|
||||
"Whether to build the libhermes target as a framework bundle or dylib on Apple platforms")
|
||||
"Whether to build the libhermes2 target as a framework bundle or dylib on Apple platforms")
|
||||
|
||||
set(HERMES_BUILD_APPLE_DSYM OFF CACHE BOOL
|
||||
"Whether to build a DWARF debugging symbols bundle")
|
||||
|
@ -347,7 +347,7 @@ if (HERMES_STATIC_LINK)
|
|||
endif()
|
||||
|
||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
|
||||
# Check if the linker supports deleting unused sections and ICF.
|
||||
# Check if the linker supports deleting unused sections and ICF.
|
||||
# We can't simply CHECK_CXX_COMPILER_FLAG("-Wl,--gc-sections" ..) because CMake
|
||||
# will compile and link separately and only passes the flag during compilation.
|
||||
# TODO: Use check_linker_flag once we have CMake 3.18.
|
||||
|
@ -507,8 +507,6 @@ if(HERMES_SLOW_DEBUG)
|
|||
COMPILE_DEFINITIONS $<$<CONFIG:Debug>:HERMES_SLOW_DEBUG>)
|
||||
endif()
|
||||
|
||||
set(HERMES_ASSUMED_BUILD_MODE_IN_LIT_TEST $<IF:$<CONFIG:Debug>,dbg,opt>)
|
||||
|
||||
if (HERMES_HARDENED)
|
||||
add_definitions(-DHERMES_HARDENED)
|
||||
endif()
|
||||
|
@ -619,7 +617,7 @@ endif()
|
|||
|
||||
# If we have no ICU, then error out.
|
||||
if (NOT ICU_FOUND)
|
||||
message(FATAL_ERROR "Unable to find ICU for ${CMAKE_SYSTEM_VERSION}.")
|
||||
message(FATAL_ERROR "Unable to find ICU for ${CMAKE_SYSTEM_VERSION}.")
|
||||
endif()
|
||||
|
||||
# Declare a function that links ICU for the given target.
|
||||
|
|
|
@ -24,7 +24,7 @@ if(HERMES_IS_ANDROID)
|
|||
add_hermes_library(jsijni SHARED
|
||||
${jni_source_files}
|
||||
LINK_LIBS
|
||||
libhermes
|
||||
libhermes2
|
||||
compileJS
|
||||
fbjni::fbjni
|
||||
jsi
|
||||
|
@ -34,7 +34,7 @@ if(HERMES_IS_ANDROID)
|
|||
add_hermes_library(jsijniepi SHARED
|
||||
${epi_source_files}
|
||||
LINK_LIBS
|
||||
libhermes
|
||||
libhermes2
|
||||
compileJS
|
||||
fbjni::fbjni
|
||||
jsi
|
||||
|
|
|
@ -31,9 +31,9 @@ endif()
|
|||
# For compatibility, CMake adds /EHsc, /GR and /DUNICODE by default for MSVC. We want to set those
|
||||
# flags per target, so remove them.
|
||||
if (MSVC)
|
||||
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "/DUNICODE" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
# string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
# string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
# string(REPLACE "/DUNICODE" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
endif (MSVC)
|
||||
|
||||
# set stack reserved size to ~10MB
|
||||
|
|
|
@ -27,6 +27,7 @@ One popular implementation strategy followed by other engines, is to bundle an i
|
|||
- `Intl.DateTimeFormat`*
|
||||
- `Intl.DateTimeFormat.supportedLocalesOf`
|
||||
- `Intl.DateTimeFormat.prototype.format`
|
||||
- `Intl.DateTimeFormat.prototype.formatToParts`
|
||||
- `Intl.DateTimeFormat.prototype.resolvedOptions`
|
||||
|
||||
- `Intl.getCanonicalLocales`
|
||||
|
@ -50,7 +51,6 @@ One popular implementation strategy followed by other engines, is to bundle an i
|
|||
## Supported on Android only
|
||||
- `Intl.NumberFormat`
|
||||
- `Intl.NumberFormat.prototype.formatToParts`
|
||||
- `Intl.DateTimeFormat.prototype.formatToParts`
|
||||
|
||||
## * Limitations on property support
|
||||
|
||||
|
|
|
@ -1230,6 +1230,8 @@ class DateTimeFormatApple : public DateTimeFormat {
|
|||
|
||||
std::u16string format(double jsTimeValue) noexcept;
|
||||
|
||||
std::vector<Part> formatToParts(double x) noexcept;
|
||||
|
||||
private:
|
||||
void initializeNSDateFormatter() noexcept;
|
||||
|
||||
|
@ -1895,8 +1897,76 @@ std::u16string DateTimeFormat::format(double jsTimeValue) noexcept {
|
|||
return static_cast<DateTimeFormatApple *>(this)->format(jsTimeValue);
|
||||
}
|
||||
|
||||
static std::u16string returnTypeOfDate(const char16_t &c16) {
|
||||
if (c16 == u'a')
|
||||
return u"dayPeriod";
|
||||
if (c16 == u'z' || c16 == u'v' || c16 == u'O')
|
||||
return u"timeZoneName";
|
||||
if (c16 == u'G')
|
||||
return u"era";
|
||||
if (c16 == u'y')
|
||||
return u"year";
|
||||
if (c16 == u'M')
|
||||
return u"month";
|
||||
if (c16 == u'E')
|
||||
return u"weekday";
|
||||
if (c16 == u'd')
|
||||
return u"day";
|
||||
if (c16 == u'h' || c16 == u'k' || c16 == u'K' || c16 == u'H')
|
||||
return u"hour";
|
||||
if (c16 == u'm')
|
||||
return u"minute";
|
||||
if (c16 == u's')
|
||||
return u"second";
|
||||
if (c16 == u'S')
|
||||
return u"fractionalSecond";
|
||||
return u"literal";
|
||||
}
|
||||
|
||||
// Implementer note: This method corresponds roughly to
|
||||
// https://402.ecma-international.org/8.0/#sec-formatdatetimetoparts
|
||||
std::vector<Part> DateTimeFormatApple::formatToParts(double x) noexcept {
|
||||
// NOTE: We dont have access to localeData.patterns. Instead we use
|
||||
// NSDateFormatter's foramt string, and break it into components.
|
||||
// 1. Let parts be ? PartitionDateTimePattern(dateTimeFormat, x).
|
||||
auto fmt = nsStringToU16String(nsDateFormatter_.dateFormat);
|
||||
std::unique(fmt.begin(), fmt.end());
|
||||
auto formattedDate = format(x);
|
||||
// 2. Let result be ArrayCreate(0).
|
||||
std::vector<Part> result;
|
||||
// 3. Let n be 0.
|
||||
// 4. For each Record { [[Type]], [[Value]] } part in parts, do
|
||||
// a. Let O be OrdinaryObjectCreate(%Object.prototype%).
|
||||
// b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).
|
||||
// c. Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]).
|
||||
// d. Perform ! CreateDataProperty(result, ! ToString(n), O).
|
||||
// e. Increment n by 1.
|
||||
std::u16string currentPart;
|
||||
unsigned n = 0;
|
||||
static auto alphanumerics = NSCharacterSet.alphanumericCharacterSet;
|
||||
for (char16_t c16 : formattedDate) {
|
||||
if ([alphanumerics characterIsMember:c16]) {
|
||||
currentPart += c16;
|
||||
continue;
|
||||
}
|
||||
if (currentPart != u"") {
|
||||
result.push_back(
|
||||
{{u"type", returnTypeOfDate(fmt[n])}, {u"value", currentPart}});
|
||||
currentPart = u"";
|
||||
n++;
|
||||
}
|
||||
result.push_back({{u"type", u"literal"}, {u"value", {c16}}});
|
||||
n++;
|
||||
}
|
||||
// Last format string component.
|
||||
result.push_back(
|
||||
{{u"type", returnTypeOfDate(fmt[n])}, {u"value", currentPart}});
|
||||
// 5. Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Part> DateTimeFormat::formatToParts(double x) noexcept {
|
||||
llvm_unreachable("formatToParts is unimplemented on Apple platforms");
|
||||
return static_cast<DateTimeFormatApple *>(this)->formatToParts(x);
|
||||
}
|
||||
|
||||
class NumberFormatApple : public NumberFormat {
|
||||
|
|
|
@ -133,9 +133,18 @@ OptValue<uint32_t> base64DecodeOutputLength(llvh::ArrayRef<T> str) {
|
|||
numPadding++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The input string should always be divisible by 4.
|
||||
} else if (strLength % 4 == 1) {
|
||||
// If strLength divides by 4 leaving a remainder of 1, then this is for sure
|
||||
// not a valid base64 encoded data because there cannot be 3 '=' padding
|
||||
// characters.
|
||||
return llvh::None;
|
||||
} else {
|
||||
// Otherwise, the data could be padded with '=' and still be valid. In this
|
||||
// case, the padding characters are not included, but we need to process as
|
||||
// if they are there.
|
||||
uint32_t simulatedPadding = 4 - (strLength % 4);
|
||||
strLength += simulatedPadding;
|
||||
numPadding += simulatedPadding;
|
||||
}
|
||||
|
||||
// This shouldn't overflow because the value is guaranteed to be smaller.
|
||||
|
@ -166,7 +175,8 @@ bool base64Decode(llvh::ArrayRef<T> str, StringBuilder &builder) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (c == '=') {
|
||||
// Check for '=' in the middle
|
||||
if (LLVM_UNLIKELY(c == '=')) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
d4828120d1dfe08d0849cb09ce55da93dce784e9
|
||||
tag: hermes-2024-04-25-RNv0.74.1-b54a3a01c531f4f5f1904cb0770033e8b7153dff
|
||||
bb1e74fe1e95c2b5a2f4f9311152da052badc2bc
|
||||
Tag: hermes-2024-06-03-RNv0.74.2-bb1e74fe1e95c2b5a2f4f9311152da052badc2bc
|
||||
|
|
|
@ -16,6 +16,10 @@ print(atob('0w=='));
|
|||
// CHECK-NEXT: Ó
|
||||
print(atob('000='));
|
||||
// CHECK-NEXT: ÓM
|
||||
print(atob('aGVsbG8='));
|
||||
// CHECK-NEXT: hello
|
||||
print(atob('aGVsbG8'));
|
||||
// CHECK-NEXT: hello
|
||||
try {
|
||||
atob('\u03A9');
|
||||
} catch (e) {
|
||||
|
|
|
@ -142,5 +142,24 @@ print(new Intl.DateTimeFormat('en-US').resolvedOptions().numberingSystem);
|
|||
print(new Intl.DateTimeFormat('en-US', { timeZone: 'SGT'}).resolvedOptions().timeZone);
|
||||
// CHECK-NEXT: SGT
|
||||
|
||||
print(JSON.stringify(new Intl.DateTimeFormat('en-US').formatToParts(date)));
|
||||
// CHECK-NEXT: [{"value":"1","type":"month"},{"value":"/","type":"literal"},{"value":"2","type":"day"},{"value":"/","type":"literal"},{"value":"2020","type":"year"}]
|
||||
|
||||
print(JSON.stringify(new Intl.DateTimeFormat('en-GB').formatToParts(date)));
|
||||
// CHECK-NEXT: [{"value":"02","type":"day"},{"value":"/","type":"literal"},{"value":"01","type":"month"},{"value":"/","type":"literal"},{"value":"2020","type":"year"}]
|
||||
|
||||
print(JSON.stringify(new Intl.DateTimeFormat('en-US', {weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: 'numeric',
|
||||
fractionalSecondDigits: 3,
|
||||
hour12: true,
|
||||
timeZone: 'UTC'
|
||||
}).formatToParts(new Date(Date.UTC(2020, 0, 2, 3, 45, 00, 30)))));
|
||||
// CHECK-NEXT: [{"value":"Thursday","type":"weekday"},{"value":",","type":"literal"},{"value":" ","type":"literal"},{"value":"1","type":"month"},{"value":"/","type":"literal"},{"value":"2","type":"day"},{"value":"/","type":"literal"},{"value":"2020","type":"year"},{"value":",","type":"literal"},{"value":" ","type":"literal"},{"value":"3","type":"hour"},{"value":":","type":"literal"},{"value":"45","type":"minute"},{"value":":","type":"literal"},{"value":"00","type":"second"},{"value":".","type":"literal"},{"value":"030","type":"fractionalSecond"},{"value":" ","type":"literal"},{"value":"AM","type":"dayPeriod"}]
|
||||
|
||||
print(new Date(Date.UTC(2020, 0, 2)).toLocaleString("en-US", {weekday: "short", timeZone: "UTC"}))
|
||||
// CHECK-NEXT: Thu
|
||||
|
|
|
@ -13,5 +13,5 @@ if(HERMES_ENABLE_FUZZILLI)
|
|||
)
|
||||
|
||||
target_include_directories(fuzzilli PRIVATE ${HERMES_SOURCE_DIR}/API)
|
||||
target_link_libraries(fuzzilli libhermes)
|
||||
target_link_libraries(fuzzilli libhermes2)
|
||||
endif()
|
||||
|
|
|
@ -17,6 +17,6 @@ if(HERMES_ENABLE_LIBFUZZER)
|
|||
target_include_directories(fuzzer-jsi-entry PRIVATE ${HERMES_SOURCE_DIR}/API)
|
||||
target_link_libraries(fuzzer-jsi-entry
|
||||
PRIVATE
|
||||
libhermes
|
||||
libhermes2
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -18,7 +18,7 @@ if(HERMES_BUILD_NODE_HERMES)
|
|||
InternalBindings/util.cpp InternalBindings/tty_wrap.cpp
|
||||
InternalBindings/pipe_wrap.cpp InternalBindings/stream_base.cpp
|
||||
${ALL_HEADER_FILES}
|
||||
LINK_LIBS libhermes hermesNodeBytecode uv_a
|
||||
LINK_LIBS libhermes2 hermesNodeBytecode uv_a
|
||||
)
|
||||
target_include_directories(node-hermes PRIVATE third-party/libuv/include/)
|
||||
endif()
|
||||
|
|
|
@ -239,7 +239,7 @@ TEST_F(SynthTraceSerializationTest, TimeIsPrinted) {
|
|||
0xac, 0xcb, 0x02, 0x05, 0x5a, 0x4f}};
|
||||
// JSON emitters escape forward slashes.
|
||||
EXPECT_EQ(
|
||||
R"({"type":"BeginExecJSRecord","time":100,"sourceURL":"file:///file.js","sourceHash":"6440b537af26795e5f452bcd320faccb02055a4f","sourceIsBytecode":false})",
|
||||
R"({"type":"BeginExecJSRecord","time":100,"sourceURL":"file:\/\/\/file.js","sourceHash":"6440b537af26795e5f452bcd320faccb02055a4f","sourceIsBytecode":false})",
|
||||
to_string(SynthTrace::BeginExecJSRecord(
|
||||
std::chrono::milliseconds(100), "file:///file.js", hash, false)));
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ add_subdirectory(Parser)
|
|||
add_subdirectory(VMRuntime)
|
||||
add_subdirectory(Support)
|
||||
add_subdirectory(dtoa)
|
||||
add_subdirectory(PlatformUnicode)
|
||||
add_subdirectory(PlatformIntl)
|
||||
add_subdirectory(PlatformUnicode)
|
||||
add_subdirectory(API)
|
||||
add_subdirectory(ADT)
|
||||
add_subdirectory(Optimizer)
|
||||
|
|
|
@ -46,14 +46,22 @@ set(NAPITests
|
|||
test_symbol.cpp
|
||||
test_typedarray.cpp
|
||||
)
|
||||
|
||||
# Turn on EH and RTTI for APITests
|
||||
set(HERMES_ENABLE_EH ON)
|
||||
set(HERMES_ENABLE_RTTI ON)
|
||||
set(HERMES_ENABLE_EH_RTTI ON)
|
||||
# For some reason (bug?) add_unittest() is clearing LLVM_REQUIRES_RTTI, so
|
||||
# we need to set this one.
|
||||
set(LLVM_ENABLE_RTTI ON)
|
||||
|
||||
|
||||
# Enable exeption
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
|
||||
|
||||
# Enable RTTI
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR")
|
||||
|
||||
# Generate PDBs
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi")
|
||||
|
||||
add_hermes_unittest(NAPITests ${NAPITests} LINK_LIBS hermesNapi)
|
||||
target_link_libraries(NAPITests hermesNapi libhermes)
|
||||
target_include_directories(NAPITests PUBLIC ../../API/hermes)
|
||||
|
|
|
@ -127,7 +127,9 @@ TEST_F(Base64UtilTest, DecodeValid) {
|
|||
EXPECT_DECODED_ASCII_AND_UTF16("YWI=", u"ab");
|
||||
EXPECT_DECODED_ASCII_AND_UTF16("YWJj", u"abc");
|
||||
EXPECT_DECODED_ASCII_AND_UTF16("YWJjZA==", u"abcd");
|
||||
EXPECT_DECODED_ASCII_AND_UTF16("YWJjZA", u"abcd");
|
||||
EXPECT_DECODED_ASCII_AND_UTF16("YWJjZGU=", u"abcde");
|
||||
EXPECT_DECODED_ASCII_AND_UTF16("YWJjZGU", u"abcde");
|
||||
EXPECT_DECODED_ASCII_AND_UTF16("YWJjZGVm", u"abcdef");
|
||||
EXPECT_DECODED_ASCII_AND_UTF16("0w==", u"\xD3");
|
||||
EXPECT_DECODED_ASCII_AND_UTF16("000=", u"\xD3M");
|
||||
|
|
Загрузка…
Ссылка в новой задаче