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:
Vladimir Morozov 2024-06-07 17:10:09 -07:00 коммит произвёл GitHub
Родитель fcd054c410
Коммит 4657e24da3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
24 изменённых файлов: 325 добавлений и 89 удалений

Просмотреть файл

@ -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");