Compare commits

..
Author SHA1 Message Date
Vojtech Novak 8647dcb68b fix cp command in ReactNativeDependencies.podspec 2025-08-07 15:42:11 +02:00
18 changed files with 72 additions and 285 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';
@@ -229,9 +229,6 @@ public class ReactInstanceManager {
return new ReactInstanceManagerBuilder();
}
/**
* @noinspection deprecation
*/
/* package */ ReactInstanceManager(
Context applicationContext,
@Nullable Activity currentActivity,
@@ -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,
@@ -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
}
@@ -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)
}
}
@@ -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)
@@ -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
@@ -64,7 +64,7 @@ Pod::Spec.new do |spec|
cp -R "$HEADERS_PATH/" Headers
mkdir -p framework/packages/react-native
cp -R "$XCFRAMEWORK_PATH/.." framework/packages/react-native/
cp -R "$XCFRAMEWORK_PATH/../." framework/packages/react-native/
find "$XCFRAMEWORK_PATH/.." -type f -exec rm {} +
find "$CURRENT_PATH" -type d -empty -delete
CMD
+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');
}