From 1e60a590846ae6a31ad190fd11ccc0664d2b81ae Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 8 Oct 2026 09:52:21 -0700 Subject: [PATCH] Run the With hooks around WithRuntimeDecorator::createArrayBuffer (#58935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/react/react-native/pull/58935 `WithRuntimeDecorator` wraps every override in `Around around{with_};` except `createArrayBuffer(std::shared_ptr)`, which calls `RD::createArrayBuffer` directly. It has been like that since external ArrayBuffers were added in https://github.com/facebook/hermes/issues/793, where the overrides next to it did get the guard. `HermesRuntimeImpl::createArrayBuffer` allocates a `JSArrayBuffer` on the GC heap, so on `makeThreadSafeHermesRuntime` it runs without the runtime lock, and reentrancy checks built on `WithRuntimeDecorator` never see the call. facebook/react-native#45042 and facebook/react-native#45049 fixed the same kind of gap for methods that had no `WithRuntimeDecorator` override at all. This one has an override that just skips the guard, so it wasn't caught there. A small stress program shows the race: one thread runs an allocating JS loop on a thread-safe runtime while another creates external ArrayBuffers. In a Debug build it fails the `makeA() calls can not be interleaved` assert in HadesGC. With the guard it runs clean. I didn't add it as a test because it depends on timing. React Native's copy of `decorator.h` has the same line. X-link: https://github.com/facebook/hermes/pull/2204 Test Plan: Added `HermesRuntimeDecoratorTest.CreateArrayBufferCallsWith`. It wraps `makeHermesRuntime()` in a counting `WithRuntimeDecorator`, creates an ArrayBuffer from a `MutableBuffer`, and checks that `before()` and `after()` each ran once. Without the change both counts are 0 and the test fails. With it the test passes, and so does the full `APITests` binary (356 tests) in a Debug + ASan build. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed By: avp Differential Revision: D123939407 Pulled By: lavenzg --- packages/react-native/ReactCommon/jsi/jsi/decorator.h | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/ReactCommon/jsi/jsi/decorator.h b/packages/react-native/ReactCommon/jsi/jsi/decorator.h index b78aa14214d..26478a3ad34 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/decorator.h +++ b/packages/react-native/ReactCommon/jsi/jsi/decorator.h @@ -1005,6 +1005,7 @@ class WithRuntimeDecorator : public RuntimeDecorator { } ArrayBuffer createArrayBuffer( std::shared_ptr buffer) override { + Around around{with_}; return RD::createArrayBuffer(std::move(buffer)); } size_t size(const Array& a) override {