react-native 0.83.0-nightly-20251104-502efe1cc → 0.84.0-nightly-20251105-5ec5cc3a3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/Libraries/AppDelegate/RCTReactNativeFactory.h +3 -0
  2. package/Libraries/AppDelegate/RCTReactNativeFactory.mm +12 -0
  3. package/Libraries/AppDelegate/RCTRootViewFactory.h +10 -4
  4. package/Libraries/AppDelegate/RCTRootViewFactory.mm +21 -5
  5. package/Libraries/Core/ReactNativeVersion.js +2 -2
  6. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +2 -2
  7. package/React/Base/RCTBundleManager.h +59 -7
  8. package/React/Base/RCTBundleManager.m +98 -0
  9. package/React/Base/RCTBundleURLProvider.h +24 -0
  10. package/React/Base/RCTBundleURLProvider.mm +49 -4
  11. package/React/Base/RCTVersion.m +2 -2
  12. package/React/CoreModules/RCTPlatform.mm +3 -2
  13. package/React/CxxBridge/RCTCxxBridge.mm +1 -2
  14. package/React/CxxModule/RCTCxxUtils.mm +1 -11
  15. package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +127 -127
  16. package/ReactAndroid/gradle.properties +1 -1
  17. package/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.kt +7 -7
  18. package/ReactAndroid/src/main/java/com/facebook/react/ViewManagerOnDemandReactPackage.kt +53 -4
  19. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.kt +99 -9
  20. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/InspectorNetworkHelper.kt +1 -1
  21. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayManager.kt +22 -1
  22. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/perfmonitor/PerfMonitorOverlayView.kt +4 -3
  23. package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +2 -2
  24. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
  25. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAxOrderHelper.kt +47 -0
  26. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +23 -3
  27. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +7 -2
  28. package/ReactAndroid/src/main/jni/react/devsupport/JCxxInspectorPackagerConnectionWebSocket.cpp +29 -2
  29. package/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp +1 -1
  30. package/ReactAndroid/src/main/jni/react/jni/JSLoader.h +2 -1
  31. package/ReactAndroid/src/main/res/devsupport/drawable/ic_perf_issue.xml +10 -0
  32. package/ReactCommon/cxxreact/JSBigString.h +14 -5
  33. package/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp +4 -5
  34. package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
  35. package/ReactCommon/jsiexecutor/jsireact/JSIExecutor.cpp +2 -3
  36. package/ReactCommon/jsiexecutor/jsireact/JSIExecutor.h +2 -2
  37. package/ReactCommon/jsinspector-modern/PerfMonitorV2.cpp +9 -1
  38. package/ReactCommon/jsinspector-modern/PerfMonitorV2.h +4 -1
  39. package/ReactCommon/jsinspector-modern/TracingAgent.cpp +1 -5
  40. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.cpp +99 -0
  41. package/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h +47 -1
  42. package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +2 -2
  43. package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm +4 -27
  44. package/ReactCommon/react/performance/cdpmetrics/CdpPerfIssuesReporter.cpp +4 -2
  45. package/ReactCommon/react/renderer/css/CSSSyntaxParser.h +7 -0
  46. package/ReactCommon/react/runtime/ReactInstance.cpp +4 -4
  47. package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h +3 -2
  48. package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +10 -6
  49. package/ReactCommon/yoga/yoga/style/StyleLength.h +7 -0
  50. package/ReactCommon/yoga/yoga/style/StyleSizeLength.h +7 -0
  51. package/package.json +9 -9
  52. package/sdks/hermes-engine/version.properties +1 -1
  53. package/src/private/components/virtualview/VirtualView.js +16 -9
  54. package/src/private/components/virtualview/logger/VirtualViewLogger.js +21 -0
  55. package/src/private/components/virtualview/logger/VirtualViewLoggerTypes.js +24 -0
  56. package/src/private/featureflags/ReactNativeFeatureFlags.js +2 -2
  57. package/types_generated/src/private/components/virtualview/VirtualView.d.ts +3 -1
  58. package/React/CxxModule/RCTCxxModule.h +0 -29
  59. package/React/CxxModule/RCTCxxModule.mm +0 -87
@@ -9,11 +9,17 @@ package com.facebook.react.devsupport
9
9
 
10
10
  import android.os.Handler
11
11
  import android.os.Looper
12
+ import com.facebook.common.logging.FLog
12
13
  import com.facebook.jni.HybridData
13
14
  import com.facebook.proguard.annotations.DoNotStrip
14
15
  import com.facebook.proguard.annotations.DoNotStripAny
16
+ import com.facebook.react.common.annotations.VisibleForTesting
15
17
  import com.facebook.soloader.SoLoader
16
18
  import java.io.Closeable
19
+ import java.nio.ByteBuffer
20
+ import java.nio.charset.StandardCharsets
21
+ import java.util.ArrayDeque
22
+ import java.util.Queue
17
23
  import java.util.concurrent.TimeUnit
18
24
  import okhttp3.OkHttpClient
19
25
  import okhttp3.Request
@@ -67,7 +73,7 @@ internal class CxxInspectorPackagerConnection(
67
73
  */
68
74
  @DoNotStripAny
69
75
  private interface IWebSocket : Closeable {
70
- fun send(message: String)
76
+ fun send(chunk: ByteBuffer)
71
77
 
72
78
  /**
73
79
  * Close the WebSocket connection. NOTE: There is no close() method in the C++ interface.
@@ -76,6 +82,95 @@ internal class CxxInspectorPackagerConnection(
76
82
  override fun close()
77
83
  }
78
84
 
85
+ /**
86
+ * A simple WebSocket wrapper that prevents having more than 16MiB of messages queued
87
+ * simultaneously. This is done to stop OkHttp from closing the WebSocket connection.
88
+ *
89
+ * https://github.com/facebook/react-native/issues/39651.
90
+ * https://github.com/square/okhttp/blob/4e7dbec1ea6c9cf8d80422ac9d44b9b185c749a3/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/ws/RealWebSocket.kt#L684.
91
+ */
92
+ private class InspectorPackagerWebSocketImpl(
93
+ private val nativeWebSocket: WebSocket,
94
+ private val handler: Handler,
95
+ ) : IWebSocket {
96
+ private val messageQueue: Queue<Pair<String, Int>> = ArrayDeque()
97
+ private val queueLock = Any()
98
+ private val drainRunnable =
99
+ object : Runnable {
100
+ override fun run() {
101
+ FLog.d(TAG, "Attempting to drain the message queue after ${drainDelayMs}ms")
102
+ tryDrainQueue()
103
+ }
104
+ }
105
+
106
+ /**
107
+ * We are providing a String to OkHttp's WebSocket, because there is no guarantee that all CDP
108
+ * clients will support binary data format.
109
+ */
110
+ override fun send(chunk: ByteBuffer) {
111
+ synchronized(queueLock) {
112
+ val messageSize = chunk.capacity()
113
+ val message = StandardCharsets.UTF_8.decode(chunk).toString()
114
+ val currentQueueSize = nativeWebSocket.queueSize()
115
+
116
+ if (currentQueueSize + messageSize > MAX_QUEUE_SIZE) {
117
+ FLog.d(TAG, "Reached queue size limit. Queueing the message.")
118
+ messageQueue.offer(Pair(message, messageSize))
119
+ scheduleDrain()
120
+ } else {
121
+ if (messageQueue.isEmpty()) {
122
+ nativeWebSocket.send(message)
123
+ } else {
124
+ messageQueue.offer(Pair(message, messageSize))
125
+ tryDrainQueue()
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ override fun close() {
132
+ synchronized(queueLock) {
133
+ handler.removeCallbacks(drainRunnable)
134
+ messageQueue.clear()
135
+ nativeWebSocket.close(1000, "End of session")
136
+ }
137
+ }
138
+
139
+ private fun tryDrainQueue() {
140
+ synchronized(queueLock) {
141
+ while (messageQueue.isNotEmpty()) {
142
+ val (nextMessage, nextMessageSize) = messageQueue.peek() ?: break
143
+ val currentQueueSize = nativeWebSocket.queueSize()
144
+
145
+ if (currentQueueSize + nextMessageSize <= MAX_QUEUE_SIZE) {
146
+ messageQueue.poll()
147
+ if (!nativeWebSocket.send(nextMessage)) {
148
+ // The WebSocket is closing, closed, or cancelled.
149
+ handler.removeCallbacks(drainRunnable)
150
+ messageQueue.clear()
151
+
152
+ break
153
+ }
154
+ } else {
155
+ scheduleDrain()
156
+ break
157
+ }
158
+ }
159
+ }
160
+ }
161
+
162
+ private fun scheduleDrain() {
163
+ FLog.d(TAG, "Scheduled a task to drain messages queue.")
164
+ handler.removeCallbacks(drainRunnable)
165
+ handler.postDelayed(drainRunnable, drainDelayMs)
166
+ }
167
+
168
+ companion object {
169
+ private val TAG: String = InspectorPackagerWebSocketImpl::class.java.simpleName
170
+ private const val drainDelayMs: Long = 100
171
+ }
172
+ }
173
+
79
174
  /** Java implementation of the C++ InspectorPackagerConnectionDelegate interface. */
80
175
  private class DelegateImpl {
81
176
  private val httpClient =
@@ -130,15 +225,8 @@ internal class CxxInspectorPackagerConnection(
130
225
  }
131
226
  },
132
227
  )
133
- return object : IWebSocket {
134
- override fun send(message: String) {
135
- webSocket.send(message)
136
- }
137
228
 
138
- override fun close() {
139
- webSocket.close(1000, "End of session")
140
- }
141
- }
229
+ return InspectorPackagerWebSocketImpl(webSocket, handler)
142
230
  }
143
231
 
144
232
  @DoNotStrip
@@ -152,6 +240,8 @@ internal class CxxInspectorPackagerConnection(
152
240
  SoLoader.loadLibrary("react_devsupportjni")
153
241
  }
154
242
 
243
+ @VisibleForTesting internal const val MAX_QUEUE_SIZE = 16L * 1024 * 1024 // 16MiB
244
+
155
245
  @JvmStatic
156
246
  private external fun initHybrid(
157
247
  url: String,
@@ -66,7 +66,7 @@ internal object InspectorNetworkHelper {
66
66
  response.body().use { responseBody ->
67
67
  if (responseBody != null) {
68
68
  val inputStream = responseBody.byteStream()
69
- val chunkSize = 1024
69
+ val chunkSize = 8 * 1024 // 8Kb
70
70
  val buffer = ByteArray(chunkSize)
71
71
  var bytesRead: Int
72
72
 
@@ -7,6 +7,8 @@
7
7
 
8
8
  package com.facebook.react.devsupport.perfmonitor
9
9
 
10
+ import android.os.Handler
11
+ import android.os.Looper
10
12
  import com.facebook.react.bridge.UiThreadUtil
11
13
  import com.facebook.react.devsupport.interfaces.TracingState
12
14
 
@@ -23,6 +25,7 @@ internal class PerfMonitorOverlayManager(
23
25
  private var view: PerfMonitorOverlayView? = null
24
26
  private var tracingState: TracingState = TracingState.ENABLEDINCDPMODE
25
27
  private var perfIssueCount: Int = 0
28
+ private val handler = Handler(Looper.getMainLooper())
26
29
 
27
30
  /** Enable the Perf Monitor overlay. */
28
31
  fun enable() {
@@ -75,6 +78,7 @@ internal class PerfMonitorOverlayManager(
75
78
  tracingState = state
76
79
  if (state != TracingState.DISABLED) {
77
80
  perfIssueCount = 0
81
+ handler.removeCallbacksAndMessages(null)
78
82
  }
79
83
  UiThreadUtil.runOnUiThread {
80
84
  view?.updateRecordingState(state)
@@ -84,10 +88,23 @@ internal class PerfMonitorOverlayManager(
84
88
  }
85
89
 
86
90
  override fun onPerfIssueAdded(name: String) {
91
+ perfIssueCount++
92
+
87
93
  UiThreadUtil.runOnUiThread {
88
- view?.updatePerfIssueCount(++perfIssueCount)
94
+ view?.updatePerfIssueCount(perfIssueCount)
89
95
  view?.show()
90
96
  }
97
+
98
+ handler.postDelayed(
99
+ {
100
+ perfIssueCount--
101
+ UiThreadUtil.runOnUiThread {
102
+ view?.updatePerfIssueCount(perfIssueCount)
103
+ view?.show()
104
+ }
105
+ },
106
+ PERF_ISSUE_EXPIRY_MS,
107
+ )
91
108
  }
92
109
 
93
110
  private fun handleRecordingButtonPress() {
@@ -105,4 +122,8 @@ internal class PerfMonitorOverlayManager(
105
122
  TracingState.ENABLEDINCDPMODE -> Unit
106
123
  }
107
124
  }
125
+
126
+ companion object {
127
+ private const val PERF_ISSUE_EXPIRY_MS = 20_000L
128
+ }
108
129
  }
@@ -120,12 +120,12 @@ internal class PerfMonitorOverlayView(
120
120
  setTextColor(Color.WHITE)
121
121
  typeface = TYPEFACE_BOLD
122
122
  val alertDrawable =
123
- context.getDrawable(android.R.drawable.ic_dialog_alert)?.apply {
123
+ context.getDrawable(R.drawable.ic_perf_issue)?.apply {
124
124
  setBounds(
125
125
  0,
126
126
  1,
127
- dpToPx(TEXT_SIZE_PRIMARY).toInt(),
128
- dpToPx(TEXT_SIZE_PRIMARY).toInt() + 1,
127
+ dpToPx(ISSUE_ICON_SIZE).toInt(),
128
+ dpToPx(ISSUE_ICON_SIZE).toInt() + 1,
129
129
  )
130
130
  }
131
131
  setCompoundDrawables(alertDrawable, null, null, null)
@@ -214,6 +214,7 @@ internal class PerfMonitorOverlayView(
214
214
  private val COLOR_OVERLAY_BORDER = Color.parseColor("#6C6C6C")
215
215
  private val TEXT_SIZE_PRIMARY = 12f
216
216
  private val TEXT_SIZE_ACCESSORY = 10f
217
+ private val ISSUE_ICON_SIZE = 15f
217
218
  private val TYPEFACE_BOLD = Typeface.create("sans-serif", Typeface.BOLD)
218
219
  }
219
220
  }
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<15ede8025e516f2bdc0329efe49f4a62>>
7
+ * @generated SignedSource<<890156e9513bff7c7c6252f8cf4402e4>>
8
8
  */
9
9
 
10
10
  /**
@@ -379,7 +379,7 @@ public object ReactNativeFeatureFlags {
379
379
  public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = accessor.overrideBySynchronousMountPropsAtMountingAndroid()
380
380
 
381
381
  /**
382
- * Enable reporting Performance Issues (`detail.rnPerfIssue`). Displayed in the V2 Performance Monitor and the "Performance Issues" sub-panel in DevTools.
382
+ * Enable reporting Performance Issues (`detail.devtools.performanceIssue`). Displayed in the V2 Performance Monitor and the "Performance Issues" sub-panel in DevTools.
383
383
  */
384
384
  @JvmStatic
385
385
  public fun perfIssuesEnabled(): Boolean = accessor.perfIssuesEnabled()
@@ -13,8 +13,8 @@ public object ReactNativeVersion {
13
13
  @JvmField
14
14
  public val VERSION: Map<String, Any?> = mapOf(
15
15
  "major" to 0,
16
- "minor" to 83,
16
+ "minor" to 84,
17
17
  "patch" to 0,
18
- "prerelease" to "nightly-20251104-502efe1cc"
18
+ "prerelease" to "nightly-20251105-5ec5cc3a3"
19
19
  )
20
20
  }
@@ -11,7 +11,22 @@ import android.view.View
11
11
  import android.view.ViewGroup
12
12
  import com.facebook.react.R
13
13
 
14
+ /**
15
+ * Helper object for managing accessibility order in React Native views.
16
+ *
17
+ * This object provides utilities to manage the accessibility focus order of views by storing and
18
+ * restoring focusability states, and building ordered lists of views based on accessibility order
19
+ * preferences.
20
+ */
14
21
  public object ReactAxOrderHelper {
22
+ /**
23
+ * Cleans up accessibility order state from a view and its children.
24
+ *
25
+ * This method removes stored focusability states and accessibility order parent references from
26
+ * the view hierarchy. It recursively processes all children of ViewGroup instances.
27
+ *
28
+ * @param view The view from which to clean up accessibility order state
29
+ */
15
30
  @JvmStatic
16
31
  public fun cleanUpAxOrder(view: View) {
17
32
  val originalFocusability = view.getTag(R.id.original_focusability) as Boolean?
@@ -31,6 +46,15 @@ public object ReactAxOrderHelper {
31
46
  }
32
47
  }
33
48
 
49
+ /**
50
+ * Restores the original focusability state of a view and its children.
51
+ *
52
+ * This method traverses the view hierarchy and restores the focusability state that was
53
+ * previously saved with the `R.id.original_focusability` tag. This is typically used after
54
+ * accessibility order operations are complete to return views to their original state.
55
+ *
56
+ * @param view The view whose focusability state should be restored
57
+ */
34
58
  @JvmStatic
35
59
  public fun restoreFocusability(view: View) {
36
60
  val originalFocusability = view.getTag(R.id.original_focusability) as Boolean?
@@ -45,6 +69,16 @@ public object ReactAxOrderHelper {
45
69
  }
46
70
  }
47
71
 
72
+ /**
73
+ * Disables focus for all views in the subtree that are not in the accessibility order list.
74
+ *
75
+ * This method recursively traverses the view hierarchy and disables focusability for views that
76
+ * are not included in the provided accessibility order list. It stores the original focusability
77
+ * state before modifying it, allowing for later restoration.
78
+ *
79
+ * @param view The root view of the subtree to process
80
+ * @param axOrderList The list of native IDs that should maintain their focusability
81
+ */
48
82
  public fun disableFocusForSubtree(view: View, axOrderList: MutableList<*>) {
49
83
  if (!axOrderList.contains(view.getTag(R.id.view_tag_native_id))) {
50
84
  if (view.getTag(R.id.original_focusability) == null) {
@@ -60,6 +94,19 @@ public object ReactAxOrderHelper {
60
94
  }
61
95
  }
62
96
 
97
+ /**
98
+ * Builds an ordered list of views based on accessibility order preferences.
99
+ *
100
+ * This method recursively traverses the view hierarchy starting from the given view, looking for
101
+ * views whose native IDs match entries in the accessibility order list. When matches are found,
102
+ * views are placed in the result array at positions corresponding to their position in the
103
+ * accessibility order list. This method also tags each view with its accessibility order parent.
104
+ *
105
+ * @param view The current view being processed in the hierarchy traversal
106
+ * @param parent The parent view that defines the accessibility order context
107
+ * @param axOrderList The list of native IDs defining the desired accessibility order
108
+ * @param result The output array where views are placed according to their order in axOrderList
109
+ */
63
110
  public fun buildAxOrderList(
64
111
  view: View,
65
112
  parent: View,
@@ -28,6 +28,7 @@ import android.view.KeyEvent;
28
28
  import android.view.MotionEvent;
29
29
  import android.view.View;
30
30
  import android.view.ViewGroup;
31
+ import android.view.ViewParent;
31
32
  import android.view.accessibility.AccessibilityNodeInfo;
32
33
  import android.widget.HorizontalScrollView;
33
34
  import android.widget.OverScroller;
@@ -740,6 +741,20 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
740
741
  return handled;
741
742
  }
742
743
 
744
+ private boolean isDescendantOf(View parent, View view) {
745
+ if (view == null || parent == null) {
746
+ return false;
747
+ }
748
+ ViewParent p = view.getParent();
749
+ while (p != null && p.getParent() != null) {
750
+ if (p == parent) {
751
+ return true;
752
+ }
753
+ p = p.getParent();
754
+ }
755
+ return false;
756
+ }
757
+
743
758
  @Override
744
759
  public boolean arrowScroll(int direction) {
745
760
  boolean handled = false;
@@ -751,7 +766,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
751
766
  View currentFocused = findFocus();
752
767
  View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
753
768
  View rootChild = getContentView();
754
- if (rootChild != null && nextFocused != null && nextFocused.getParent() == rootChild) {
769
+ if (isDescendantOf(rootChild, nextFocused)) {
755
770
  if (!isScrolledInView(nextFocused) && !isMostlyScrolledInView(nextFocused)) {
756
771
  smoothScrollToNextPage(direction);
757
772
  }
@@ -834,8 +849,13 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
834
849
  @Override
835
850
  public void run() {
836
851
  mPostTouchRunnable = null;
837
- // Trigger snap alignment now that scrolling has stopped
838
- handlePostTouchScrolling(0, 0);
852
+ // +1/-1 velocity if scrolling right or left. This is to ensure that the
853
+ // next/previous page is picked rather than sliding backwards to the current page
854
+ int velocityX = (int) Math.signum(hScroll);
855
+ if (mDisableIntervalMomentum) {
856
+ velocityX = 0;
857
+ }
858
+ flingAndSnap(velocityX);
839
859
  }
840
860
  };
841
861
  postOnAnimationDelayed(mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY);
@@ -688,8 +688,13 @@ public class ReactScrollView extends ScrollView
688
688
  @Override
689
689
  public void run() {
690
690
  mPostTouchRunnable = null;
691
- // Trigger snap alignment now that scrolling has stopped
692
- handlePostTouchScrolling(0, 0);
691
+ // +1/-1 velocity if scrolling down or up. This is to ensure that the
692
+ // next/previous page is picked rather than sliding backwards to the current page
693
+ int velocityY = (int) -Math.signum(vScroll);
694
+ if (mDisableIntervalMomentum) {
695
+ velocityY = 0;
696
+ }
697
+ flingAndSnap(velocityY);
693
698
  }
694
699
  };
695
700
  postOnAnimationDelayed(mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY);
@@ -5,6 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ #include <fbjni/ByteBuffer.h>
9
+
8
10
  #include "JCxxInspectorPackagerConnectionWebSocket.h"
9
11
 
10
12
  using namespace facebook::jni;
@@ -12,10 +14,35 @@ using namespace facebook::react::jsinspector_modern;
12
14
 
13
15
  namespace facebook::react::jsinspector_modern {
14
16
 
17
+ namespace {
18
+
19
+ local_ref<JByteBuffer::javaobject> getReadOnlyByteBufferFromStringView(
20
+ std::string_view sv) {
21
+ auto buffer = JByteBuffer::wrapBytes(
22
+ const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(sv.data())),
23
+ sv.size());
24
+
25
+ /**
26
+ * Return a read-only buffer that shares the underlying contents.
27
+ * This guards from accidential mutations on the Java side, since we did
28
+ * casting above.
29
+ *
30
+ * https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#asReadOnlyBuffer--
31
+ */
32
+ static auto method =
33
+ buffer->javaClassStatic()->getMethod<JByteBuffer::javaobject()>(
34
+ "asReadOnlyBuffer");
35
+ return method(buffer);
36
+ }
37
+
38
+ } // namespace
39
+
15
40
  void JCxxInspectorPackagerConnectionWebSocket::send(std::string_view message) {
16
41
  static auto method =
17
- javaClassStatic()->getMethod<void(const std::string&)>("send");
18
- method(self(), std::string(message));
42
+ javaClassStatic()->getMethod<void(local_ref<JByteBuffer::javaobject>)>(
43
+ "send");
44
+ auto byteBuffer = getReadOnlyByteBufferFromStringView(message);
45
+ method(self(), byteBuffer);
19
46
  }
20
47
 
21
48
  void JCxxInspectorPackagerConnectionWebSocket::close() {
@@ -72,7 +72,7 @@ loadScriptFromAssets(AAssetManager* manager, const std::string& assetName) {
72
72
  }
73
73
 
74
74
  auto buf = std::make_unique<JSBigBufferString>(script->size());
75
- memcpy(buf->data(), script->c_str(), script->size());
75
+ memcpy(buf->mutableData(), script->c_str(), script->size());
76
76
  return buf;
77
77
  }
78
78
  }
@@ -10,11 +10,12 @@
10
10
  #include <string>
11
11
 
12
12
  #include <android/asset_manager.h>
13
- #include <cxxreact/JSExecutor.h>
14
13
  #include <fbjni/fbjni.h>
15
14
 
16
15
  namespace facebook::react {
17
16
 
17
+ class JSBigString;
18
+
18
19
  struct JAssetManager : jni::JavaClass<JAssetManager> {
19
20
  static constexpr auto kJavaDescriptor = "Landroid/content/res/AssetManager;";
20
21
  };
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
3
+ android:width="24dp"
4
+ android:height="24dp"
5
+ android:viewportWidth="960"
6
+ android:viewportHeight="960">
7
+ <path
8
+ android:fillColor="@android:color/white"
9
+ android:pathData="M80,880L80,160Q80,127 103.5,103.5Q127,80 160,80L800,80Q833,80 856.5,103.5Q880,127 880,160L880,640Q880,673 856.5,696.5Q833,720 800,720L240,720L80,880ZM480,600Q497,600 508.5,588.5Q520,577 520,560Q520,543 508.5,531.5Q497,520 480,520Q463,520 451.5,531.5Q440,543 440,560Q440,577 451.5,588.5Q463,600 480,600ZM440,440L520,440L520,200L440,200L440,440Z"/>
10
+ </vector>
@@ -10,6 +10,8 @@
10
10
  #include <memory>
11
11
  #include <string>
12
12
 
13
+ #include <jsi/jsi.h>
14
+
13
15
  #ifndef RN_EXPORT
14
16
  #ifdef _MSC_VER
15
17
  #define RN_EXPORT
@@ -27,15 +29,17 @@ namespace facebook::react {
27
29
  // large string needs to be curried into a std::function<>, which must
28
30
  // by CopyConstructible.
29
31
 
30
- class JSBigString {
32
+ class JSBigString : public facebook::jsi::Buffer {
31
33
  public:
32
34
  JSBigString() = default;
33
35
 
34
- // Not copyable
36
+ // Not copyable or movable
35
37
  JSBigString(const JSBigString &) = delete;
36
38
  JSBigString &operator=(const JSBigString &) = delete;
39
+ JSBigString(JSBigString &&) = delete;
40
+ JSBigString &operator=(JSBigString &&) = delete;
37
41
 
38
- virtual ~JSBigString() = default;
42
+ ~JSBigString() override = default;
39
43
 
40
44
  virtual bool isAscii() const = 0;
41
45
 
@@ -43,7 +47,12 @@ class JSBigString {
43
47
  virtual const char *c_str() const = 0;
44
48
 
45
49
  // Length of the c_str without the NULL byte.
46
- virtual size_t size() const = 0;
50
+ size_t size() const override = 0;
51
+
52
+ const uint8_t *data() const final
53
+ {
54
+ return reinterpret_cast<const uint8_t *>(c_str());
55
+ }
47
56
  };
48
57
 
49
58
  // Concrete JSBigString implementation which holds a std::string
@@ -105,7 +114,7 @@ class RN_EXPORT JSBigBufferString : public JSBigString {
105
114
  return m_size;
106
115
  }
107
116
 
108
- char *data()
117
+ char *mutableData()
109
118
  {
110
119
  return m_data;
111
120
  }
@@ -60,8 +60,8 @@ void JSIndexedRAMBundle::init() {
60
60
  "header size must exactly match the input file format");
61
61
 
62
62
  readBundle(reinterpret_cast<char*>(header), sizeof(header));
63
- const size_t numTableEntries = folly::Endian::little(header[1]);
64
- const size_t startupCodeSize = folly::Endian::little(header[2]);
63
+ size_t numTableEntries = folly::Endian::little(header[1]);
64
+ std::streamsize startupCodeSize = folly::Endian::little(header[2]);
65
65
 
66
66
  // allocate memory for meta data and lookup table.
67
67
  m_table = ModuleTable(numTableEntries);
@@ -73,7 +73,7 @@ void JSIndexedRAMBundle::init() {
73
73
  // read the startup code
74
74
  m_startupCode = std::make_unique<JSBigBufferString>(startupCodeSize - 1);
75
75
 
76
- readBundle(m_startupCode->data(), startupCodeSize - 1);
76
+ readBundle(m_startupCode->mutableData(), startupCodeSize - 1);
77
77
  }
78
78
 
79
79
  JSIndexedRAMBundle::Module JSIndexedRAMBundle::getModule(
@@ -109,8 +109,7 @@ std::string JSIndexedRAMBundle::getModuleCode(const uint32_t id) const {
109
109
  return ret;
110
110
  }
111
111
 
112
- void JSIndexedRAMBundle::readBundle(char* buffer, const std::streamsize bytes)
113
- const {
112
+ void JSIndexedRAMBundle::readBundle(char* buffer, std::streamsize bytes) const {
114
113
  if (!m_bundle->read(buffer, bytes)) {
115
114
  if ((m_bundle->rdstate() & std::ios::eofbit) != 0) {
116
115
  throw std::ios_base::failure("Unexpected end of RAM Bundle file");
@@ -13,16 +13,16 @@
13
13
  #include <string_view>
14
14
 
15
15
  #define REACT_NATIVE_VERSION_MAJOR 0
16
- #define REACT_NATIVE_VERSION_MINOR 83
16
+ #define REACT_NATIVE_VERSION_MINOR 84
17
17
  #define REACT_NATIVE_VERSION_PATCH 0
18
18
 
19
19
  namespace facebook::react {
20
20
 
21
21
  constexpr struct {
22
22
  int32_t Major = 0;
23
- int32_t Minor = 83;
23
+ int32_t Minor = 84;
24
24
  int32_t Patch = 0;
25
- std::string_view Prerelease = "nightly-20251104-502efe1cc";
25
+ std::string_view Prerelease = "nightly-20251105-5ec5cc3a3";
26
26
  } ReactNativeVersion;
27
27
 
28
28
  } // namespace facebook::react
@@ -168,8 +168,7 @@ void JSIExecutor::loadBundle(
168
168
  ReactMarker::logTaggedMarker(
169
169
  ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());
170
170
  }
171
- runtime_->evaluateJavaScript(
172
- std::make_unique<BigStringBuffer>(std::move(script)), sourceURL);
171
+ runtime_->evaluateJavaScript(std::move(script), sourceURL);
173
172
  flush();
174
173
  if (hasLogger) {
175
174
  ReactMarker::logTaggedMarker(
@@ -212,7 +211,7 @@ void JSIExecutor::registerBundle(
212
211
  "Empty bundle registered with ID " + tag + " from " + bundlePath);
213
212
  }
214
213
  runtime_->evaluateJavaScript(
215
- std::make_unique<BigStringBuffer>(std::move(script)),
214
+ std::move(script),
216
215
  JSExecutor::getSyntheticBundlePath(bundleId, bundlePath));
217
216
  }
218
217
  ReactMarker::logTaggedMarker(
@@ -49,7 +49,7 @@ namespace facebook::react {
49
49
  using JSIScopedTimeoutInvoker =
50
50
  std::function<void(const std::function<void()> &invokee, std::function<std::string()> errorMessageProducer)>;
51
51
 
52
- class BigStringBuffer : public jsi::Buffer {
52
+ class [[deprecated("JSBigString implements jsi::Buffer directly")]] BigStringBuffer : public jsi::Buffer {
53
53
  public:
54
54
  BigStringBuffer(std::unique_ptr<const JSBigString> script) : script_(std::move(script)) {}
55
55
 
@@ -60,7 +60,7 @@ class BigStringBuffer : public jsi::Buffer {
60
60
 
61
61
  const uint8_t *data() const override
62
62
  {
63
- return reinterpret_cast<const uint8_t *>(script_->c_str());
63
+ return script_->data();
64
64
  }
65
65
 
66
66
  private:
@@ -21,7 +21,15 @@ void PerfMonitorUpdateHandler::handlePerfIssueAdded(
21
21
  delegate_.unstable_onPerfIssueAdded(
22
22
  PerfIssuePayload{
23
23
  .name = payload["name"].asString(),
24
- .severity = payload["severity"].asString(),
24
+ .severity = payload["severity"].isNull()
25
+ ? std::nullopt
26
+ : std::make_optional(payload["severity"].asString()),
27
+ .description = payload["description"].isNull()
28
+ ? std::nullopt
29
+ : std::make_optional(payload["description"].asString()),
30
+ .learnMoreUrl = payload["learnMoreUrl"].isNull()
31
+ ? std::nullopt
32
+ : std::make_optional(payload["learnMoreUrl"].asString()),
25
33
  });
26
34
  }
27
35
  }