Skip to content

Commit 29ab78a

Browse files
sammy-SCmeta-codesync[bot]
authored andcommitted
Remove folly::Endian::little from JSIndexedRAMBundle (#57109)
Summary: Pull Request resolved: #57109 changelog: [internal] The RAM bundle format stores offsets and lengths in little-endian, which previously required pulling in folly's byte-swapping library. This removes the folly dependency by implementing a simple little-endian decoder inline, cutting the build graph and making the code more self-contained. Reviewed By: javache Differential Revision: D107870286 fbshipit-source-id: c6f8399785189fad743123ecc51434c0feff9706
1 parent df4cadc commit 29ab78a

2 files changed

Lines changed: 92 additions & 6 deletions

File tree

packages/react-native/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,26 @@
99

1010
#ifndef RCT_REMOVE_LEGACY_ARCH
1111

12-
#include <glog/logging.h>
12+
#include <bit>
13+
#include <cstdint>
1314
#include <fstream>
1415
#include <memory>
1516
#include <sstream>
1617

17-
#include <folly/lang/Bits.h>
1818
#include <glog/logging.h>
1919

2020
namespace facebook::react {
2121

22+
namespace {
23+
uint32_t littleEndianToHost(uint32_t value) {
24+
if constexpr (std::endian::native == std::endian::big) {
25+
return (value << 24) | ((value & 0x0000FF00U) << 8) |
26+
((value & 0x00FF0000U) >> 8) | (value >> 24);
27+
}
28+
return value;
29+
}
30+
} // namespace
31+
2232
std::function<std::unique_ptr<JSModulesUnbundle>(std::string)>
2333
JSIndexedRAMBundle::buildFactory() {
2434
return [](const std::string& bundlePath) {
@@ -60,8 +70,8 @@ void JSIndexedRAMBundle::init() {
6070
"header size must exactly match the input file format");
6171

6272
readBundle(reinterpret_cast<char*>(header), sizeof(header));
63-
size_t numTableEntries = folly::Endian::little(header[1]);
64-
std::streamsize startupCodeSize = folly::Endian::little(header[2]);
73+
size_t numTableEntries = littleEndianToHost(header[1]);
74+
std::streamsize startupCodeSize = littleEndianToHost(header[2]);
6575

6676
// allocate memory for meta data and lookup table.
6777
m_table = ModuleTable(numTableEntries);
@@ -95,7 +105,7 @@ std::string JSIndexedRAMBundle::getModuleCode(const uint32_t id) const {
95105

96106
// entries without associated code have offset = 0 and length = 0
97107
const uint32_t length =
98-
moduleData != nullptr ? folly::Endian::little(moduleData->length) : 0;
108+
moduleData != nullptr ? littleEndianToHost(moduleData->length) : 0;
99109
if (length == 0) {
100110
throw std::ios_base::failure(
101111
"Error loading module" + std::to_string(id) + "from RAM Bundle");
@@ -105,7 +115,7 @@ std::string JSIndexedRAMBundle::getModuleCode(const uint32_t id) const {
105115
readBundle(
106116
&ret.front(),
107117
length - 1,
108-
m_baseOffset + folly::Endian::little(moduleData->offset));
118+
m_baseOffset + littleEndianToHost(moduleData->offset));
109119
return ret;
110120
}
111121

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <cstdint>
9+
#include <memory>
10+
#include <string>
11+
12+
#include <cxxreact/JSBigString.h>
13+
#include <cxxreact/JSIndexedRAMBundle.h>
14+
#include <gtest/gtest.h>
15+
16+
#ifndef RCT_REMOVE_LEGACY_ARCH
17+
18+
using namespace facebook::react;
19+
20+
namespace {
21+
constexpr uint32_t kRAMBundleMagic = 0xFB0BD1E5;
22+
23+
void appendLittleEndian32(std::string& out, uint32_t value) {
24+
out.push_back(static_cast<char>(value & 0xFF));
25+
out.push_back(static_cast<char>((value >> 8) & 0xFF));
26+
out.push_back(static_cast<char>((value >> 16) & 0xFF));
27+
out.push_back(static_cast<char>((value >> 24) & 0xFF));
28+
}
29+
30+
void appendNullTerminatedSection(std::string& out, const std::string& section) {
31+
out += section;
32+
out.push_back('\0');
33+
}
34+
} // namespace
35+
36+
TEST(JSIndexedRAMBundleTest, ReadsLittleEndianStartupAndModules) {
37+
const std::string startup = "var startup = true;";
38+
const std::string moduleZero = "module zero code";
39+
const std::string moduleOne = "m1";
40+
41+
const auto startupCodeSize = static_cast<uint32_t>(startup.size() + 1);
42+
const auto lengthZero = static_cast<uint32_t>(moduleZero.size() + 1);
43+
const auto lengthOne = static_cast<uint32_t>(moduleOne.size() + 1);
44+
const uint32_t offsetZero = startupCodeSize;
45+
const uint32_t offsetOne = offsetZero + lengthZero;
46+
47+
std::string bundle;
48+
appendLittleEndian32(bundle, kRAMBundleMagic);
49+
appendLittleEndian32(bundle, 2);
50+
appendLittleEndian32(bundle, startupCodeSize);
51+
appendLittleEndian32(bundle, offsetZero);
52+
appendLittleEndian32(bundle, lengthZero);
53+
appendLittleEndian32(bundle, offsetOne);
54+
appendLittleEndian32(bundle, lengthOne);
55+
appendNullTerminatedSection(bundle, startup);
56+
appendNullTerminatedSection(bundle, moduleZero);
57+
appendNullTerminatedSection(bundle, moduleOne);
58+
59+
#pragma GCC diagnostic push
60+
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
61+
JSIndexedRAMBundle ramBundle(std::make_unique<JSBigStdString>(bundle));
62+
63+
const auto startupCode = ramBundle.getStartupCode();
64+
EXPECT_EQ(std::string(startupCode->c_str(), startupCode->size()), startup);
65+
66+
const auto firstModule = ramBundle.getModule(0);
67+
EXPECT_EQ(firstModule.name, "0.js");
68+
EXPECT_EQ(firstModule.code, moduleZero);
69+
70+
const auto secondModule = ramBundle.getModule(1);
71+
EXPECT_EQ(secondModule.name, "1.js");
72+
EXPECT_EQ(secondModule.code, moduleOne);
73+
#pragma GCC diagnostic pop
74+
}
75+
76+
#endif // RCT_REMOVE_LEGACY_ARCH

0 commit comments

Comments
 (0)