Compare commits

..
50 changed files with 115 additions and 462 deletions
@@ -118,6 +118,7 @@ async function collectResults(discordWebHook) {
} else {
console.log('Discord webhook not set');
}
process.exit(1);
}
// Initialize Firebase client
@@ -1,128 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import * as Fantom from '@react-native/fantom';
import * as React from 'react';
import {createRef} from 'react';
import {ImageBackground} from 'react-native';
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
describe('<ImageBackground>', () => {
describe('props', () => {
describe('ImageProps', () => {
it('can have local source', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<ImageBackground source={require('./img/img1.png')} />);
});
expect(root.getRenderedOutput({props: ['source']}).toJSX()).toEqual(
<rn-image
source-scale="1"
source-size="{1, 1}"
source-type="local"
source-uri="file://drawable-mdpi/packages_reactnative_libraries_image___tests___img_img1.png"
/>,
);
});
it('can have remote source', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<ImageBackground
source={{
uri: 'https://reactnative.dev/img/tiny_logo.png',
width: 100,
height: 100,
scale: 2,
cache: 'only-if-cached',
method: 'POST',
body: 'name=React+Native',
headers: {
Authorization: 'Basic RandomString',
},
}}
/>,
);
});
expect(root.getRenderedOutput({props: ['source']}).toJSX()).toEqual(
<rn-image
source-body="name=React+Native"
source-cache="only-if-cached"
source-header-Authorization="Basic RandomString"
source-method="POST"
source-scale="2"
source-size="{100, 100}"
source-type="remote"
source-uri="https://reactnative.dev/img/tiny_logo.png"
/>,
);
});
it('can have srcSet', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(
<ImageBackground srcSet="https://reactnative.dev/img/tiny_logo.png 1x, https://reactnative.dev/img/header_logo.svg 2x" />,
);
});
expect(root.getRenderedOutput({props: ['source']}).toJSX()).toEqual(
<rn-image
source-1x-scale="1"
source-1x-type="remote"
source-1x-uri="https://reactnative.dev/img/tiny_logo.png"
source-2x-scale="2"
source-2x-type="remote"
source-2x-uri="https://reactnative.dev/img/header_logo.svg"
/>,
);
});
});
describe('style', () => {
it('can be set', () => {
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<ImageBackground style={{width: 100, height: 100}} />);
});
expect(
root.getRenderedOutput({props: ['width|height']}).toJSX(),
).toEqual(<rn-image width="100.000000" height="100.000000" />);
});
});
});
describe('ref', () => {
it('Allows to set a reference to the inner `Image` component', () => {
const elementRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<ImageBackground imageRef={elementRef} />);
});
const image = ensureInstance(elementRef.current, ReactNativeElement);
expect(image.tagName).toBe('RN:Image');
});
});
});
@@ -7,7 +7,9 @@
* @noformat
* @nolint
* @flow
* @generated SignedSource<<cf323fc5ca893bab5669c7d321660412>>
* @generated SignedSource<<16b364e89f43b8a47832b0dfb98af11e>>
*
* This file was sync'd from the facebook/react repository.
*/
'use strict';
@@ -7,7 +7,9 @@
* @noformat
* @nolint
* @flow strict-local
* @generated SignedSource<<908f5fb85384725318e261f40e49d9a6>>
* @generated SignedSource<<1dd9e9c3f20e37ae14e485fc6ee3d9e9>>
*
* This file was sync'd from the facebook/react repository.
*/
'use strict';
@@ -7,7 +7,9 @@
* @noformat
* @nolint
* @flow
* @generated SignedSource<<8f46fdc9267fcc4fdc9e76842fe24066>>
* @generated SignedSource<<e2c46705ed927302dbe9332dafba459d>>
*
* This file was sync'd from the facebook/react repository.
*/
'use strict';
@@ -7,7 +7,9 @@
* @noformat
* @nolint
* @flow strict-local
* @generated SignedSource<<83073425aa3f71ced2c8c51f25a25938>>
* @generated SignedSource<<e8dce0e82b831c91465d04b49fb48ab2>>
*
* This file was sync'd from the facebook/react repository.
*/
'use strict';
@@ -7,7 +7,9 @@
* @noformat
* @nolint
* @flow strict-local
* @generated SignedSource<<52163887de05f1cff05388145cf85b3b>>
* @generated SignedSource<<556d1487de0b9e4a09cbc67dd130a884>>
*
* This file was sync'd from the facebook/react repository.
*/
'use strict';
@@ -3348,10 +3348,8 @@ public final class com/facebook/react/uimanager/DisplayMetricsHolder {
public static final fun getDisplayMetricsWritableMap (D)Lcom/facebook/react/bridge/WritableMap;
public static final fun getScreenDisplayMetrics ()Landroid/util/DisplayMetrics;
public static final fun getWindowDisplayMetrics ()Landroid/util/DisplayMetrics;
public static final fun initScreenDisplayMetrics (Landroid/content/Context;)V
public static final fun initScreenDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
public static final fun initWindowDisplayMetrics (Landroid/content/Context;)V
public static final fun initWindowDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
public static final fun initDisplayMetrics (Landroid/content/Context;)V
public static final fun initDisplayMetricsIfNotInitialized (Landroid/content/Context;)V
public static final fun setScreenDisplayMetrics (Landroid/util/DisplayMetrics;)V
public static final fun setWindowDisplayMetrics (Landroid/util/DisplayMetrics;)V
}
@@ -630,7 +630,6 @@ dependencies {
api(libs.androidx.autofill)
api(libs.androidx.swiperefreshlayout)
api(libs.androidx.tracing)
api(libs.androidx.window)
api(libs.fbjni)
api(libs.fresco)
@@ -229,9 +229,6 @@ public class ReactInstanceManager {
return new ReactInstanceManagerBuilder();
}
/**
* @noinspection deprecation
*/
/* package */ ReactInstanceManager(
Context applicationContext,
@Nullable Activity currentActivity,
@@ -262,11 +259,7 @@ public class ReactInstanceManager {
FLog.d(TAG, "ReactInstanceManager.ctor()");
initializeSoLoaderIfNecessary(applicationContext);
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(applicationContext);
if (currentActivity != null) {
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(currentActivity);
}
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext);
// See {@code ReactInstanceManagerBuilder} for description of all flags here.
mApplicationContext = applicationContext;
@@ -931,13 +924,6 @@ public class ReactInstanceManager {
ReactContext currentReactContext = getCurrentReactContext();
if (currentReactContext != null) {
DisplayMetricsHolder.initScreenDisplayMetrics(currentReactContext);
Activity currentActivity = currentReactContext.getCurrentActivity();
if (currentActivity != null) {
DisplayMetricsHolder.initWindowDisplayMetrics(currentActivity);
}
AppearanceModule appearanceModule =
currentReactContext.getNativeModule(AppearanceModule.class);
@@ -136,8 +136,9 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
setRootViewTag(ReactRootViewTagGenerator.getNextRootViewTag());
setClipChildren(false);
DisplayMetricsHolder.initScreenDisplayMetrics(getContext());
DisplayMetricsHolder.initWindowDisplayMetrics(getContext());
if (ReactNativeFeatureFlags.enableFontScaleChangesUpdatingLayout()) {
DisplayMetricsHolder.initDisplayMetrics(getContext().getApplicationContext());
}
}
@Override
@@ -882,8 +883,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
private int mDeviceRotation = 0;
/* package */ CustomGlobalLayoutListener() {
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(getContext());
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(getContext());
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(getContext().getApplicationContext());
mVisibleViewArea = new Rect();
mMinKeyboardHeightDetected = (int) PixelUtil.toPixelFromDIP(60);
}
@@ -1006,8 +1006,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
return;
}
mDeviceRotation = rotation;
DisplayMetricsHolder.initScreenDisplayMetrics(getContext());
DisplayMetricsHolder.initWindowDisplayMetrics(getContext());
DisplayMetricsHolder.initDisplayMetrics(getContext().getApplicationContext());
emitOrientationChanged(rotation);
}
@@ -25,11 +25,6 @@ import com.facebook.react.packagerconnection.RequestHandler
*/
internal class DefaultDevSupportManagerFactory : DevSupportManagerFactory {
@Deprecated(
"Use the other create() method with useDevSupport parameter for New Architecture. This method will be removed in a future release.",
replaceWith =
ReplaceWith(
"create(applicationContext, reactInstanceManagerHelper, packagerPathForJSBundleName, enableOnCreate, redBoxHandler, devBundleDownloadListener, minNumShakes, customPackagerCommandHandlers, surfaceDelegateFactory, devLoadingViewManager, pausedInDebuggerOverlayManager)"))
override fun create(
applicationContext: Context,
reactInstanceManagerHelper: ReactInstanceDevHelper,
@@ -22,12 +22,6 @@ public interface DevSupportManagerFactory {
* Factory used by the Old Architecture flow to create a [DevSupportManager] and a
* [BridgeDevSupportManager]
*/
@Deprecated(
message =
"Use the other create() method with useDevSupport parameter for New Architecture. This method will be removed in a future release.",
replaceWith =
ReplaceWith(
"create(applicationContext, reactInstanceManagerHelper, packagerPathForJSBundleName, enableOnCreate, redBoxHandler, devBundleDownloadListener, minNumShakes, customPackagerCommandHandlers, surfaceDelegateFactory, devLoadingViewManager, pausedInDebuggerOverlayManager)"))
public fun create(
applicationContext: Context,
reactInstanceManagerHelper: ReactInstanceDevHelper,
@@ -15,8 +15,7 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.DisplayMetricsHolder.getDisplayMetricsWritableMap
import com.facebook.react.uimanager.DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized
import com.facebook.react.uimanager.DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized
import com.facebook.react.uimanager.DisplayMetricsHolder.initDisplayMetricsIfNotInitialized
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
/** Module that exposes Android Constants to JS. */
@@ -27,8 +26,7 @@ internal class DeviceInfoModule(reactContext: ReactApplicationContext) :
private var previousDisplayMetrics: ReadableMap? = null
init {
initScreenDisplayMetricsIfNotInitialized(reactContext)
reactContext.currentActivity?.let { initWindowDisplayMetricsIfNotInitialized(it) }
initDisplayMetricsIfNotInitialized(reactContext)
reactContext.addLifecycleEventListener(this)
}
@@ -625,8 +625,9 @@ public class ReactHostImpl(
override fun onConfigurationChanged(context: Context) {
val currentReactContext = this.currentReactContext
if (currentReactContext != null) {
DisplayMetricsHolder.initScreenDisplayMetrics(currentReactContext)
currentReactContext.currentActivity?.let { DisplayMetricsHolder.initWindowDisplayMetrics(it) }
if (ReactNativeFeatureFlags.enableFontScaleChangesUpdatingLayout()) {
DisplayMetricsHolder.initDisplayMetrics(currentReactContext)
}
val appearanceModule = currentReactContext.getNativeModule(AppearanceModule::class.java)
appearanceModule?.onConfigurationChanged(context)
@@ -917,7 +918,6 @@ public class ReactHostImpl(
val instance =
ReactInstance(
reactContext,
currentActivity,
reactHostDelegate,
componentFactory,
devSupportManager,
@@ -7,7 +7,6 @@
package com.facebook.react.runtime
import android.app.Activity
import android.content.res.AssetManager
import android.view.View
import com.facebook.common.logging.FLog
@@ -89,7 +88,6 @@ import kotlin.jvm.JvmStatic
@UnstableReactNativeAPI
internal class ReactInstance(
private val context: BridgelessReactContext,
private val activity: Activity?,
delegate: ReactHostDelegate,
componentFactory: ComponentFactory,
devSupportManager: DevSupportManager,
@@ -242,8 +240,7 @@ internal class ReactInstance(
FabricUIManager(context, ViewManagerRegistry(viewManagerResolver), eventBeatManager)
// Misc initialization that needs to be done before Fabric init
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(context)
activity?.let { DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(it) }
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
val binding = FabricUIManagerBinding()
binding.register(
@@ -13,20 +13,16 @@ import android.util.DisplayMetrics
import android.view.WindowManager
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.window.layout.WindowMetricsCalculator
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.WritableNativeMap
import com.facebook.react.views.view.isEdgeToEdgeFeatureFlagOn
/**
* Holds an instance of the current DisplayMetrics so we don't have to thread it through all the
* classes that need it.
*/
public object DisplayMetricsHolder {
private const val SCREEN_INITIALIZATION_MISSING_MESSAGE =
"DisplayMetricsHolder must be initialized with initScreenDisplayMetricsIfNotInitialized or initScreenDisplayMetrics"
private const val WINDOW_INITIALIZATION_MISSING_MESSAGE =
"DisplayMetricsHolder must be initialized with initWindowDisplayMetricsIfNotInitialized or initWindowDisplayMetrics"
private const val INITIALIZATION_MISSING_MESSAGE =
"DisplayMetricsHolder must be initialized with initDisplayMetricsIfNotInitialized or initDisplayMetrics"
@JvmStatic private var windowDisplayMetrics: DisplayMetrics? = null
@JvmStatic private var screenDisplayMetrics: DisplayMetrics? = null
@@ -34,7 +30,7 @@ public object DisplayMetricsHolder {
/** The metrics of the window associated to the Context used to initialize ReactNative */
@JvmStatic
public fun getWindowDisplayMetrics(): DisplayMetrics {
checkNotNull(windowDisplayMetrics) { WINDOW_INITIALIZATION_MISSING_MESSAGE }
checkNotNull(windowDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
return windowDisplayMetrics as DisplayMetrics
}
@@ -46,7 +42,7 @@ public object DisplayMetricsHolder {
/** Screen metrics returns the metrics of the default screen on the device. */
@JvmStatic
public fun getScreenDisplayMetrics(): DisplayMetrics {
checkNotNull(screenDisplayMetrics) { SCREEN_INITIALIZATION_MISSING_MESSAGE }
checkNotNull(screenDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
return screenDisplayMetrics as DisplayMetrics
}
@@ -56,58 +52,33 @@ public object DisplayMetricsHolder {
}
@JvmStatic
public fun initScreenDisplayMetricsIfNotInitialized(context: Context) {
if (screenDisplayMetrics == null) {
initScreenDisplayMetrics(context)
public fun initDisplayMetricsIfNotInitialized(context: Context) {
if (screenDisplayMetrics != null) {
return
}
initDisplayMetrics(context)
}
@JvmStatic
public fun initWindowDisplayMetricsIfNotInitialized(context: Context) {
if (windowDisplayMetrics == null) {
initWindowDisplayMetrics(context)
}
}
@JvmStatic
public fun initScreenDisplayMetrics(context: Context) {
val displayMetrics = DisplayMetrics()
displayMetrics.setTo(context.resources.displayMetrics)
public fun initDisplayMetrics(context: Context) {
val displayMetrics = context.resources.displayMetrics
windowDisplayMetrics = displayMetrics
val screenDisplayMetrics = DisplayMetrics()
screenDisplayMetrics.setTo(displayMetrics)
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
// Get the real display metrics if we are using API level 17 or higher.
// The real metrics include system decor elements (e.g. soft menu bar).
//
// See:
// http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics)
@Suppress("DEPRECATION") wm.defaultDisplay.getRealMetrics(displayMetrics)
screenDisplayMetrics = displayMetrics
}
/*
* NOTE: Unlike [initScreenDisplayMetrics], this method needs a UiContext (Activity of
* InputMethodService) else WindowMetircsCalculator will throw an exception.
*/
@JvmStatic
public fun initWindowDisplayMetrics(context: Context) {
val displayMetrics = DisplayMetrics()
displayMetrics.setTo(context.resources.displayMetrics)
if (isEdgeToEdgeFeatureFlagOn) {
WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context).let { windowMetrics
->
displayMetrics.widthPixels = windowMetrics.bounds.width()
displayMetrics.heightPixels = windowMetrics.bounds.height()
}
}
windowDisplayMetrics = displayMetrics
@Suppress("DEPRECATION") wm.defaultDisplay.getRealMetrics(screenDisplayMetrics)
DisplayMetricsHolder.screenDisplayMetrics = screenDisplayMetrics
}
@JvmStatic
public fun getDisplayMetricsWritableMap(fontScale: Double): WritableMap {
checkNotNull(windowDisplayMetrics) { WINDOW_INITIALIZATION_MISSING_MESSAGE }
checkNotNull(screenDisplayMetrics) { SCREEN_INITIALIZATION_MISSING_MESSAGE }
checkNotNull(windowDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
checkNotNull(screenDisplayMetrics) { INITIALIZATION_MISSING_MESSAGE }
return WritableNativeMap().apply {
putMap(
@@ -20,7 +20,7 @@ public object PixelUtil {
}
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, value, DisplayMetricsHolder.getScreenDisplayMetrics())
TypedValue.COMPLEX_UNIT_DIP, value, DisplayMetricsHolder.getWindowDisplayMetrics())
}
/** Convert from DIP to PX */
@@ -37,7 +37,7 @@ public object PixelUtil {
return Float.NaN
}
val displayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics()
val displayMetrics = DisplayMetricsHolder.getWindowDisplayMetrics()
val scaledValue = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, displayMetrics)
if (maxFontScale >= 1) {
@@ -60,13 +60,13 @@ public object PixelUtil {
return Float.NaN
}
return value / DisplayMetricsHolder.getScreenDisplayMetrics().density
return value / DisplayMetricsHolder.getWindowDisplayMetrics().density
}
/** @return [Float] that represents the density of the display metrics for device screen. */
@JvmStatic
public fun getDisplayMetricDensity(): Float =
DisplayMetricsHolder.getScreenDisplayMetrics().density
DisplayMetricsHolder.getWindowDisplayMetrics().density
/* Kotlin extensions */
public fun Int.dpToPx(): Float = toPixelFromDIP(this.toFloat())
@@ -12,7 +12,6 @@ import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_M
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
import static com.facebook.react.uimanager.common.UIManagerType.LEGACY;
import android.app.Activity;
import android.content.ComponentCallbacks2;
import android.content.res.Configuration;
import android.view.View;
@@ -127,11 +126,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule
ViewManagerResolver viewManagerResolver,
int minTimeLeftInFrameForNonBatchedOperationMs) {
super(reactContext);
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(reactContext);
Activity currentActivity = reactContext.getCurrentActivity();
if (currentActivity != null) {
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(currentActivity);
}
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
mEventDispatcher = new EventDispatcherImpl(reactContext);
mModuleConstants = createConstants(viewManagerResolver);
mCustomDirectEvents = UIManagerModuleConstants.directEventTypeConstants;
@@ -151,11 +146,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule
List<ViewManager> viewManagersList,
int minTimeLeftInFrameForNonBatchedOperationMs) {
super(reactContext);
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(reactContext);
Activity currentActivity = reactContext.getCurrentActivity();
if (currentActivity != null) {
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(currentActivity);
}
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
mEventDispatcher = new EventDispatcherImpl(reactContext);
mCustomDirectEvents = MapBuilder.newHashMap();
mModuleConstants = createConstants(viewManagersList, null, mCustomDirectEvents);
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
@@ -29,9 +27,6 @@ import com.facebook.react.uimanager.IllegalViewOperationException
* order to animate layout when a valid configuration has been supplied by the application.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal abstract class AbstractLayoutAnimation {
var interpolator: Interpolator? = null
var delayMs: Int = 0
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -17,9 +15,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
* creation.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal enum class AnimatedPropertyType {
OPACITY,
SCALE_X,
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
@@ -19,9 +17,6 @@ import com.facebook.react.uimanager.IllegalViewOperationException
/** Class responsible for default layout animation, i.e animation of view creation and deletion. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal abstract class BaseLayoutAnimation : AbstractLayoutAnimation() {
abstract fun isReverse(): Boolean
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -16,9 +14,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
* Enum representing the different interpolators that can be used in layout animation configuration.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal enum class InterpolatorType {
LINEAR,
EASE_IN,
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.util.SparseArray
@@ -31,9 +29,6 @@ import javax.annotation.concurrent.NotThreadSafe
*/
@NotThreadSafe
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public open class LayoutAnimationController {
private val layoutCreateAnimation: AbstractLayoutAnimation = LayoutCreateAnimation()
private val layoutUpdateAnimation: AbstractLayoutAnimation = LayoutUpdateAnimation()
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -14,9 +12,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
/** Listener invoked when a layout animation has completed. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
public fun interface LayoutAnimationListener {
public fun onAnimationEnd()
}
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -17,9 +15,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
* Enum representing the different animation type that can be specified in layout animation config.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal enum class LayoutAnimationType {
CREATE,
UPDATE,
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -18,9 +16,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
* config was supplied for the layout animation of DELETE type.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class LayoutDeleteAnimation : BaseLayoutAnimation() {
override fun isReverse(): Boolean = true
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import com.facebook.react.common.annotations.internal.LegacyArchitecture
@@ -14,9 +12,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
/** Interface for an animation type that takes care of updating the view layout. */
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal interface LayoutHandlingAnimation {
/**
* Notifies the animation of a layout update in case one occurs during the animation. This avoids
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
@@ -21,9 +19,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
* was supplied for the layout animation of UPDATE type.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class LayoutUpdateAnimation : AbstractLayoutAnimation() {
override fun isValid(): Boolean = durationMs > 0
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
@@ -23,9 +21,6 @@ import java.lang.ref.WeakReference
* optimize rendering performances.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class OpacityAnimation(view: View, private val startOpacity: Float, endOpacity: Float) :
Animation() {
private val viewRef = WeakReference(view)
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
@@ -24,9 +22,6 @@ import java.lang.ref.WeakReference
* ScaleAnimation and TranslateAnimation.
*/
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class PositionAndSizeAnimation(view: View, x: Int, y: Int, width: Int, height: Int) :
Animation(), LayoutHandlingAnimation {
private val viewRef = WeakReference(view)
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.animation.Interpolator
@@ -21,9 +19,6 @@ import kotlin.math.sin
/** Simple spring interpolator */
// TODO(7613736): Improve spring interpolator with friction and damping variable support
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
@Deprecated(
message = "This class is part of Legacy Architecture and will be removed in a future release",
level = DeprecationLevel.WARNING)
internal class SimpleSpringInterpolator @JvmOverloads constructor(springDamping: Float = FACTOR) :
Interpolator {
private val _springDamping: Float = springDamping
@@ -0,0 +1,25 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.yoga;
public class YogaConstants {
public static final float UNDEFINED = Float.NaN;
public static boolean isUndefined(float value) {
return Float.compare(value, UNDEFINED) == 0;
}
public static boolean isUndefined(YogaValue value) {
return value.unit == YogaUnit.UNDEFINED;
}
public static float getUndefined() {
return UNDEFINED;
}
}
@@ -1,18 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.yoga
public object YogaConstants {
@JvmField public val UNDEFINED: Float = Float.NaN
@JvmStatic public fun isUndefined(value: Float): Boolean = value.compareTo(UNDEFINED) == 0
@JvmStatic public fun isUndefined(value: YogaValue): Boolean = value.unit == YogaUnit.UNDEFINED
@JvmStatic public fun getUndefined(): Float = UNDEFINED
}
@@ -71,8 +71,7 @@ class RootViewTest {
reactContext = spy(BridgeReactContext(RuntimeEnvironment.getApplication()))
reactContext.initializeWithInstance(catalystInstanceMock)
DisplayMetricsHolder.initScreenDisplayMetricsIfNotInitialized(reactContext)
DisplayMetricsHolder.initWindowDisplayMetricsIfNotInitialized(reactContext)
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext)
val uiManagerModuleMock: UIManagerModule = mock()
whenever(catalystInstanceMock.getNativeModule(UIManagerModule::class.java))
.thenReturn(uiManagerModuleMock)
@@ -11,18 +11,12 @@
package com.facebook.react.bridge
import android.app.Application
import com.facebook.react.bridge.queue.MessageQueueThreadSpec
import com.facebook.react.bridge.queue.ReactQueueConfiguration
import com.facebook.react.bridge.queue.ReactQueueConfigurationImpl
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.runtime.BridgelessReactContext
import com.facebook.react.runtime.ReactHostImpl
import com.facebook.react.runtime.internal.bolts.Task
import com.facebook.react.uimanager.UIManagerModule
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
import org.robolectric.RuntimeEnvironment
@@ -55,20 +49,4 @@ object ReactTestHelper {
whenever(reactInstance.isDestroyed).thenReturn(false)
return reactInstance
}
@OptIn(UnstableReactNativeAPI::class)
fun createTestReactApplicationContext(application: Application): ReactApplicationContext {
val reactHost =
spy(
ReactHostImpl(
RuntimeEnvironment.getApplication(),
mock(),
mock(),
Task.Companion.IMMEDIATE_EXECUTOR,
Task.Companion.IMMEDIATE_EXECUTOR,
false /* allowPackagerServerAccess */,
false /* useDevSupport */,
))
return BridgelessReactContext(application, reactHost)
}
}
@@ -467,7 +467,7 @@ class TouchEventDispatchTest {
metrics.xdpi = 1f
metrics.ydpi = 1f
metrics.density = 1f
DisplayMetricsHolder.setScreenDisplayMetrics(metrics)
DisplayMetricsHolder.setWindowDisplayMetrics(metrics)
val reactContext = ReactTestHelper.createCatalystContextForTest()
@@ -5,45 +5,36 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.modules.clipboard
import android.annotation.SuppressLint
import android.content.ClipboardManager
import android.content.Context
import com.facebook.react.bridge.ReactTestHelper.createTestReactApplicationContext
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests
import com.facebook.testutils.shadows.ShadowSoLoader
import com.facebook.react.bridge.BridgeReactContext
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
@Suppress("DEPRECATION")
@SuppressLint("ClipboardManager", "DeprecatedClass")
@RunWith(RobolectricTestRunner::class)
@Config(shadows = [ShadowSoLoader::class])
class ClipboardModuleTest {
private lateinit var clipboardModule: ClipboardModule
private lateinit var clipboardManager: ClipboardManager
@Before
fun setUp() {
ReactNativeFeatureFlagsForTests.setUp()
clipboardModule =
ClipboardModule(createTestReactApplicationContext(RuntimeEnvironment.getApplication()))
clipboardModule = ClipboardModule(BridgeReactContext(RuntimeEnvironment.getApplication()))
clipboardManager =
RuntimeEnvironment.getApplication().getSystemService(Context.CLIPBOARD_SERVICE)
as ClipboardManager
}
@After
fun tearDown() {
ReactNativeFeatureFlags.dangerouslyReset()
}
@Suppress("DEPRECATION")
@Test
fun testSetString() {
clipboardModule.setString(TEST_CONTENT)
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import java.util.Locale
@@ -5,8 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
@file:Suppress("DEPRECATION")
package com.facebook.react.uimanager.layoutanimation
import android.view.View
@@ -25,7 +25,7 @@ class ColorStopTest {
fun setUp() {
val metrics = DisplayMetrics()
metrics.density = 1f
DisplayMetricsHolder.setScreenDisplayMetrics(metrics)
DisplayMetricsHolder.setWindowDisplayMetrics(metrics)
}
@Test
@@ -75,14 +75,14 @@ class ReactImagePropertyTest {
context.initializeWithInstance(catalystInstanceMock)
themeContext = ThemedReactContext(context, context, null, -1)
Fresco.initialize(context)
DisplayMetricsHolder.setScreenDisplayMetrics(DisplayMetrics())
DisplayMetricsHolder.setWindowDisplayMetrics(DisplayMetrics())
ReactNativeFeatureFlagsForTests.setUp()
}
@After
fun teardown() {
DisplayMetricsHolder.setScreenDisplayMetrics(null)
DisplayMetricsHolder.setWindowDisplayMetrics(null)
rnLog.close()
flogMock.close()
}
@@ -65,7 +65,7 @@ class ReactTextInputPropertyTest {
context.initializeWithInstance(catalystInstanceMock)
themedContext = ThemedReactContext(context, context.baseContext, null, ID_NULL)
manager = ReactTextInputManager()
DisplayMetricsHolder.setScreenDisplayMetrics(DisplayMetrics())
DisplayMetricsHolder.setWindowDisplayMetrics(DisplayMetrics())
view = manager.createViewInstance(themedContext)
}
@@ -47,7 +47,7 @@ class ReactVirtualViewTest {
val displayMetricsHolder = mockStatic(DisplayMetricsHolder::class.java)
displayMetricsHolder
.`when`<DisplayMetrics> { DisplayMetricsHolder.getScreenDisplayMetrics() }
.`when`<DisplayMetrics> { DisplayMetricsHolder.getWindowDisplayMetrics() }
.thenAnswer { DisplayMetrics().apply { density = 1f } }
}
@@ -16,7 +16,6 @@ androidx-swiperefreshlayout = "1.1.0"
androidx-test = "1.5.0"
androidx-test-junit = "1.2.1"
androidx-tracing = "1.1.0"
androidx-window = "1.4.0"
assertj = "3.21.0"
binary-compatibility-validator = "0.13.2"
download = "5.4.0"
@@ -65,7 +64,6 @@ androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidx-
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test" }
androidx-tracing = { module = "androidx.tracing:tracing", version.ref = "androidx-tracing" }
androidx-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "uiautomator" }
androidx-window = { module = "androidx.window:window", version.ref = "androidx-window" }
fbjni = { module = "com.facebook.fbjni:fbjni", version.ref = "fbjni" }
fresco = { module = "com.facebook.fresco:fresco", version.ref = "fresco" }
@@ -377,7 +377,7 @@ end
# This method can be used to set the fast_float config
# that can be used to configure libraries.
def set_fast_float_config(fast_float_config)
def set_fast_float_config(fmt_config)
Helpers::Constants.set_fast_float_config(fast_float_config)
end
+22 -19
View File
@@ -8,8 +8,6 @@
* @format
*/
import {markdownTable} from './utils';
type TestTaskTiming = {
name: string,
latency: {
@@ -33,7 +31,7 @@ export const printBenchmarkResultsRanking = (
testArtifact: mixed,
}>,
) => {
const testTaskTimings: {[string]: {[string]: number}} = {};
const testTaskTimings: {[string]: Array<[string, number]>} = {};
let numTestVariants = 0;
for (const testResult of testResults) {
@@ -51,9 +49,12 @@ export const printBenchmarkResultsRanking = (
for (const taskTiming of testArtifact.timings) {
const taskName = taskTiming.name;
if (testTaskTimings[taskName] === undefined) {
testTaskTimings[taskName] = {};
testTaskTimings[taskName] = [];
}
testTaskTimings[taskName][testResult.title] = taskTiming.latency.p50;
testTaskTimings[taskName].push([
testResult.title,
taskTiming.latency.p50,
]);
}
}
if (numTestVariants <= 1 || Object.keys(testTaskTimings).length === 0) {
@@ -61,23 +62,25 @@ export const printBenchmarkResultsRanking = (
return;
}
// Find relative execution times for tasks
const results: {[string]: {[string]: string}} = {};
// Sort by each task's execution times
for (const taskName in testTaskTimings) {
const kv = Object.entries(testTaskTimings[taskName]);
kv.sort((a, b) => a[1] - b[1]);
const bestTiming = kv[0][1];
results[taskName] = {};
kv.forEach(([key, val]) => {
results[taskName][key] =
`${val.toFixed(3)}ms ${getTimingDelta(bestTiming, val)}`;
});
results[taskName][kv[0][0]] = `🏆 ${bestTiming.toFixed(3)}ms`;
testTaskTimings[taskName].sort((a, b) => a[1] - b[1]);
}
console.log('### Benchmark Times Comparison (p50): ###');
console.log(markdownTable(results, 'Task name'));
console.log('');
// Print the rankings
console.log('### Benchmark Results Ranking ###');
for (const taskName in testTaskTimings) {
console.log(`> ${taskName}:`);
let lastTiming;
for (const [i, [testVariationName, latency]] of testTaskTimings[
taskName
].entries()) {
console.log(
` ${i + 1}. ${testVariationName}: ${latency.toFixed(2)}ms ${getTimingDelta(lastTiming, latency)}`,
);
lastTiming = latency;
}
}
};
function getTimingDelta(lastTiming: ?number, currentTiming: ?number): string {
-61
View File
@@ -371,64 +371,3 @@ export function printConsoleLog(log: ConsoleLogMessage): void {
break;
}
}
// Returns a markdown table corresponding to the given data, adopted from the RN console.table polyfill implementation
export function markdownTable(
data: {[string]: {[string]: string}},
indexColumnName?: string = '',
): string {
const repeat = (element: string, n: number) =>
Array.apply(null, Array(n)).map(() => element);
const rows = Object.keys(data).map((key: string) => ({
[indexColumnName]: key,
...data[key],
}));
if (rows.length === 0) {
return '';
}
const columns = Array.from(
rows.reduce((columnSet: Set<string>, row) => {
Object.keys(row).forEach(key => columnSet.add(key));
return columnSet;
}, new Set()),
);
const stringRows: Array<Array<string>> = [];
const columnWidths = [];
// Figure out max cell width for each column
columns.forEach((k, i) => {
columnWidths[i] = k.length;
for (let j = 0; j < rows.length; j++) {
const cellStr = rows[j][k];
stringRows[j] = stringRows[j] || [];
stringRows[j][i] = cellStr;
columnWidths[i] = Math.max(columnWidths[i], cellStr.length);
}
});
// Join all elements in the row into a single string with | separators
// (appends extra spaces to each cell to make separators | aligned)
const joinRow = (row: Array<string>, space?: string = ' ') => {
const cells = row.map((cell: string, i) => {
const extraSpaces = repeat(' ', columnWidths[i] - cell.length).join('');
return cell + extraSpaces;
});
return '| ' + cells.join(space + '|' + space) + ' |';
};
const separators = columnWidths.map(columnWidth =>
repeat('-', columnWidth).join(''),
);
const separatorRow = joinRow(separators);
const header = joinRow(columns);
const table = [header, separatorRow];
for (let i = 0; i < rows.length; i++) {
table.push(joinRow(stringRows[i]));
}
return '\n' + table.join('\n');
}