Skip to content

Commit

Permalink
Add default getStringData/getPropNameIdData implementation (#47530)
Browse files Browse the repository at this point in the history
Summary:

Adds the default implementation for `getStringData`/`getPropNameIdData`
for VMs that do not provide their own implementation

Changelog: [Internal]

Differential Revision: D65638889
  • Loading branch information
Chi Tsai authored and facebook-github-bot committed Nov 12, 2024
1 parent f3b7c7c commit 4746228
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 0 deletions.
34 changes: 34 additions & 0 deletions packages/react-native/ReactCommon/jsi/jsi/decorator.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,22 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
return plain_.utf16(sym);
}

void getStringData(
const jsi::String& str,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num))
override {
plain_.getStringData(str, ctx, cb);
}

void getPropNameIdData(
const jsi::PropNameID& sym,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num))
override {
plain_.getPropNameIdData(sym, ctx, cb);
}

Object createObject() override {
return plain_.createObject();
};
Expand Down Expand Up @@ -690,6 +706,24 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
return RD::utf16(sym);
}

void getStringData(
const jsi::String& str,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num))
override {
Around around{with_};
RD::getStringData(str, ctx, cb);
}

void getPropNameIdData(
const jsi::PropNameID& sym,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num))
override {
Around around{with_};
RD::getPropNameIdData(sym, ctx, cb);
}

Value createValueFromJsonUtf8(const uint8_t* json, size_t length) override {
Around around{with_};
return RD::createValueFromJsonUtf8(json, length);
Expand Down
16 changes: 16 additions & 0 deletions packages/react-native/ReactCommon/jsi/jsi/jsi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,22 @@ std::u16string Runtime::utf16(const String& str) {
return convertUTF8ToUTF16(utf8Str);
}

void Runtime::getStringData(
const jsi::String& str,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num)) {
auto utf16Str = utf16(str);
cb(ctx, false, utf16Str.data(), utf16Str.size());
}

void Runtime::getPropNameIdData(
const jsi::PropNameID& sym,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num)) {
auto utf16Str = utf16(sym);
cb(ctx, false, utf16Str.data(), utf16Str.size());
}

Pointer& Pointer::operator=(Pointer&& other) noexcept {
if (ptr_) {
ptr_->invalidate();
Expand Down
47 changes: 47 additions & 0 deletions packages/react-native/ReactCommon/jsi/jsi/jsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,24 @@ class JSI_EXPORT Runtime {
virtual std::u16string utf16(const String& str);
virtual std::u16string utf16(const PropNameID& sym);

/// Invokes the provided callback \p cb with the String content as either
/// ASCII or UTF16 String. It's possible for the callback to be called
/// multiple times, potentially with different types of String.
virtual void getStringData(
const jsi::String& str,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num));

/// Invokes the provided callback \p cb with the PropNameID content as either
/// ASCII or UTF16 String. It's possible for the callback to be called
/// multiple times, potentially with different types of String. It's possible
/// for the callback to be called multiple times, potentially with different
/// types of String.
virtual void getPropNameIdData(
const jsi::PropNameID& sym,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num));

// These exist so derived classes can access the private parts of
// Value, Symbol, String, and Object, which are all friends of Runtime.
template <typename T>
Expand Down Expand Up @@ -509,6 +527,20 @@ class JSI_EXPORT PropNameID : public Pointer {
return runtime.utf16(*this);
}

/// Invokes the user provided callback to process the content in PropNameId.
/// The callback must take in three arguments: bool ascii, const void* data,
/// and size_t num, respectively. The callback is responsible for handling
/// both ASCII and UTF16 string.
template <typename CB>
void getPropNameIdData(Runtime& runtime, const CB& cb) const {
runtime.getPropNameIdData(
*this,
&cb,
[](const void* ctx, bool ascii, const void* data, size_t num) {
(*((const CB*)ctx))(ascii, data, num);
});
}

static bool compare(
Runtime& runtime,
const jsi::PropNameID& a,
Expand Down Expand Up @@ -664,6 +696,21 @@ class JSI_EXPORT String : public Pointer {
return runtime.utf16(*this);
}

/// Invokes the user provided callback to process content in String. The
/// callback must take in three arguments: bool ascii, const void* data, and
/// size_t num, respectively. The callback is responsible for handling both
/// ASCII and UTF16 string. It's possible for the callback to be called
/// multiple times, potentially with different types of String.
template <typename CB>
void getStringData(Runtime& runtime, const CB& cb) const {
runtime.getStringData(
*this,
&cb,
[](const void* ctx, bool ascii, const void* data, size_t num) {
(*((const CB*)ctx))(ascii, data, num);
});
}

friend class Runtime;
friend class Value;
};
Expand Down
34 changes: 34 additions & 0 deletions packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1635,6 +1635,40 @@ TEST_P(JSITest, UTF16Test) {
EXPECT_EQ(str.utf16(rd), u"\uFFFD\u007A");
}

TEST_P(JSITest, GetStringDataTest) {
// This Runtime Decorator is used to test the default getStringData
// implementation for VMs that do not provide their own implementation
class RD : public RuntimeDecorator<Runtime, Runtime> {
public:
RD(Runtime& rt) : RuntimeDecorator(rt) {}

void getStringData(
const String& str,
const void* ctx,
void (*cb)(const void* ctx, bool ascii, const void* data, size_t num))
override {
Runtime::getStringData(str, ctx, cb);
}
};

RD rd = RD(rt);
String str = String::createFromUtf8(rd, "hello👋");

std::u16string buf;
auto cb = [&buf](bool ascii, const void* data, size_t num) {
auto begin = (const char16_t*)data;
auto end = begin + num;
while (begin < end) {
auto curr = begin[0];
buf.push_back(curr);
begin++;
}
};

str.getStringData(rd, cb);
EXPECT_EQ(buf, str.utf16(rd));
}

INSTANTIATE_TEST_CASE_P(
Runtimes,
JSITest,
Expand Down

0 comments on commit 4746228

Please sign in to comment.