Compare commits

..
Author SHA1 Message Date
Vojtech Novak f499de9031 fix hermes param handling in test-e2e-local.js 2024-12-03 16:42:57 +01:00
Dmitry Rykun 318db8eedf Add Android-specific ImageRequestParams (#47930)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47930

This diff adds a list of props that will be used by the Android `ImagePrefetcher` to create an `ImageRequest`. This list is derived from all the props that `ReactImageView` uses to create its `ImageOptions` and `ImageRequest` objects.
Changelog: [Internal]

Reviewed By: javache

Differential Revision: D66453306

fbshipit-source-id: ca4f59784c81f2b94ed4b052f6fbe5e8c6b97a2a
2024-12-03 04:09:42 -08:00
Richard Barnes 071d223ee0 Remove unused-variable in ../xplat/compphoto/gpuEngine/tools/ToolHelpers.cpp +3 (#48052)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48052

LLVM-15 has a warning `-Wunused-variable` which we treat as an error because it's so often diagnostic of a code issue. Unused variables can compromise readability or, worse, performance.

This diff either (a) removes an unused variable and, possibly, it's associated code or (b) qualifies the variable with `[[maybe_unused]]`.

#buildsonlynotests - Builds are sufficient

 - If you approve of this diff, please use the "Accept & Ship" button :-)

Reviewed By: javache, wuyuoss

Differential Revision: D66143498

fbshipit-source-id: a461f115610258777bd1173f91cf4d4472e2fc5e
2024-12-03 04:07:49 -08:00
David Vacca 67bff8734f Delete GuardedResultAsyncTask (#48058)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48058

Delete unused abstract class GuardedResultAsyncTask

I'm deleting without depreacting becuase I didn't find usages internally or externally

changelog: [Android][Breaking] Delete unused abstract class GuardedResultAsyncTask

Reviewed By: javache

Differential Revision: D66416570

fbshipit-source-id: 8b369dfcd3e99b24f97c62cec9229f82ba5eed77
2024-12-02 18:45:27 -08:00
David Vacca b25b65ba19 Delete deprecated class FabricViewStateManager (#48057)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48057

FabricViewStateManager has been deprecated for a long time and it's unused, let's delete it

changelog: [Android][Breaking] Delete deprecated class FabricViewStateManager

Reviewed By: javache, cortinico

Differential Revision: D66403219

fbshipit-source-id: e8f893b6a240ca09c0e86821c0a15fa345ffd221
2024-12-02 18:45:27 -08:00
David Vacca a4849cb3d6 Reduce visibility of ComponentNameResolver to internal (#48056)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48056

ComponentNameResolver is meant to be used only internaly, we reduce its visbility to internal

changelog: [Android][Breaking] Removed ComponentNameResolver from public API

Reviewed By: javache

Differential Revision: D66403218

fbshipit-source-id: bf08284400a6dc6446b771c894488ed3fb371e25
2024-12-02 18:45:27 -08:00
David Vacca 385b9f4265 Migrate ComponentNameResolver to kotlin (#47919)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47919

Migrate ComponentNameResolver to kotlin

changelog: [Android][Changed] Migrate ComponentNameResolver to kotlin

Reviewed By: javache

Differential Revision: D66403041

fbshipit-source-id: 7af1a89988373014c5aeb1f6145324cf889a1a36
2024-12-02 18:45:27 -08:00
Mateo Guzmán bfc8b3391e Migrate BatchEventDispatchedListener to kotlin (#48038)
Summary:
Migrating `BatchEventDispatchedListener` from Java to Kotlin

## Changelog:

[INTERNAL] - Migrating `BatchEventDispatchedListener` from Java to Kotlin

Pull Request resolved: https://github.com/facebook/react-native/pull/48038

Test Plan:
```bash
yarn test-android
```

Reviewed By: tdn120, cortinico

Differential Revision: D66653052

Pulled By: javache

fbshipit-source-id: 494866c54d349587e313c18717c6c587a2228aa8
2024-12-02 17:53:59 -08:00
Joe Vilches 2df7552fa2 Back out "Back out "[yoga][intrinsic sizing] Update public API for intrinsic sizing setters""
Summary:
Original commit changeset: 793f77dad021

Original Phabricator Diff: D66332309

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D66662661

fbshipit-source-id: 22ed3ac9492f0a563c041ce4cb5fba4b65b53211
2024-12-02 17:29:49 -08:00
Joe Vilches e1623b7525 Back out "Back out "[yoga][intrinsic sizing] Modify private apis to set, store, and get intrinsic sizing keywords"" (#48049)
Summary:
X-link: https://github.com/facebook/yoga/pull/1756

Pull Request resolved: https://github.com/facebook/react-native/pull/48049

Changelog: [Internal]

Original commit changeset: 1d596964e0c8

Original Phabricator Diff: D66332307

Reviewed By: NickGerleman

Differential Revision: D66662662

fbshipit-source-id: 4f9ac2b1557b848f519dcd728d7097b52f1190b3
2024-12-02 17:29:49 -08:00
Eli White fa8a25eb6b Make enum types annotation objects instead of literal strings and numbers (#47349)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47349

This is needed to be able to recurse into the literals and compare them.

I'm primarily unsure if there is a problem representing doubles/floats as numbers instead of strings though.

Changelog: [Internal]

Reviewed By: makovkastar

Differential Revision: D65284058

fbshipit-source-id: b2de9ed5fb7f079a432c94aaea69027863879909
2024-12-02 14:32:35 -08:00
Eli White 96c2be8567 Don't store pretty printed json in schema
Summary: Changelog: [Internal]

Reviewed By: javache

Differential Revision: D66603960

fbshipit-source-id: 2d7844df76f168b99eb76bb19359ee71e953d0b2
2024-12-02 14:32:35 -08:00
Thomas Nardone 53bc661138 ReactViewGroup - track clipped views (#47987)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47987

Store a tag value for whether the view is added or removed, to better track the state instead of checking view.getParent().

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D66383241

fbshipit-source-id: 16521eb4052e9473be058a00cfe29d7f198b7861
2024-12-02 14:28:35 -08:00
Ramanpreet Nara 69ecaef068 Remove native -> js call noop-ing after early js error (#47915)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47915

## Purpose of this noop-ing
If an fatal js error happens during js runtime init, the js thread continues executing and raises **yet another** fatal error.

This noop-ing was an **attempt** to prevent that second inactionable fatal from happening: That fatal is usually inactionable.

## Problems with this noop-ing
I don't think this is the right approach: There could be legitimate reasons to continue executing native -> js calls post first js fatal.

I don't think it does *much*: it doesn't noop native -> js calls executed on the runtime scheduler, which should be most of them.

## Changes

Instead of trying to prevent that fatal, just let it happen. Then, don't report the second fatal: D66193194 and D66392706.

## Safetly
The production impact is negligible: This codepath is executed only after early js errors. There shouldn't be any in production right now.

We've spent a lot of time making our javascript error handling pipeline's coverage compresive. So, after an early js fatal error happens, subsequent js fatals should get handled properly.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D66394278

fbshipit-source-id: ef342fc2eba9ae9f27b15a0f412fb69bd92aed43
2024-12-02 14:18:55 -08:00
Alex Hunt 215b0a50cf Update debugger-frontend from 6b80704...486803f (#48051)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48051

Changelog: [Internal] - Update `react-native/debugger-frontend` from 6b80704...486803f

Resyncs `react-native/debugger-frontend` from GitHub - see `rn-chrome-devtools-frontend` [changelog](https://github.com/facebookexperimental/rn-chrome-devtools-frontend/compare/6b80704fd50ea0bf10f5f5da5a4343de29aff8b2...486803f6bf272e0629297265dee8048a2f1269dd).

Reviewed By: hoxyq

Differential Revision: D66664563

fbshipit-source-id: 8c04c0f99e203f594d4e86a52aca99803c4b005f
2024-12-02 12:02:07 -08:00
Alex Hunt 11c214d0c9 Update FuseboxTracer to closer align with Chrome trace events (#48020)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48020

Progress towards Performance panel display parity for User Timing events in Chrome DevTools.

- Support nullable `track` name in `ReactPerfLogger`, passing track name directly to `FuseboxTracer`.
- Update `FuseboxTracer` to register "Main" process and send V8-aligned `blink.user_timing`-categorised tracing events.

The previous track naming strategy continues to be used under Perfetto.

Changelog: [Internal]

**Better, but not perfect yet**

For now, this is probably the upper limit of how aligned we can be with Chrome on web, since our forked DevTools frontend is 6mo+ behind `main`. Notably, it does not include equivalent custom track handling today: https://github.com/ChromeDevTools/devtools-frontend/commit/4b4435feef14c5c0ac71d932940c6ea7613f8afe

{F1969750671}

> Importing an exact trace from Chrome into RNDT is unable to sub-group the "Timings" track.

Reviewed By: rubennorte

Differential Revision: D66579308

fbshipit-source-id: fa57151d2be477eaa15f62e5c19ee09b1a0ef43a
2024-12-02 11:24:34 -08:00
Andrew Datsenko dc88683798 Corrently symbolicate message (#48048)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48048

Changelog: [Internal]
Some messages may contains multi line content, ie snapshot comparison, multiline strings comparison.

Fixing this by checking first code pointer in the stack and slicing from there.

Reviewed By: christophpurrer, rubennorte

Differential Revision: D66660107

fbshipit-source-id: 57cea02cf6aae3c24f351504c2e077b5a2de0761
2024-12-02 11:16:03 -08:00
73 changed files with 1585 additions and 582 deletions
+4 -1
View File
@@ -194,7 +194,10 @@ class ErrorWithCustomBlame extends Error {
this.#cachedProcessedStack = originalStack;
} else {
const lines = originalStack.split('\n');
lines.splice(1, this.#ignoredFrameCount);
const index = lines.findIndex(line =>
/at (.*) \((.*):(\d+):(\d+)\)/.test(line),
);
lines.splice(index > -1 ? index : 1, this.#ignoredFrameCount);
this.#cachedProcessedStack = lines.join('\n');
}
}
+3 -3
View File
@@ -1,9 +1,9 @@
@generated SignedSource<<d09e665db66f49ff47c245adf0a4b543>>
Git revision: 6b80704fd50ea0bf10f5f5da5a4343de29aff8b2
@generated SignedSource<<cecad43da3fd917e15322ee3efbed875>>
Git revision: 486803f6bf272e0629297265dee8048a2f1269dd
Built with --nohooks: false
Is local checkout: false
Remote URL: https://github.com/facebookexperimental/rn-chrome-devtools-frontend
Remote branch: 0.77-stable
Remote branch: main
GN build args (overrides only):
is_official_build = true
Git status in checkout:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -327,7 +327,7 @@ export interface NativeModuleBooleanTypeAnnotation {
export type NativeModuleEnumMember = {
readonly name: string;
readonly value: string | number;
readonly value: NativeModuleStringLiteralTypeAnnotation | NativeModuleNumberLiteralTypeAnnotation,
};
export type NativeModuleEnumMemberType =
+1 -1
View File
@@ -311,7 +311,7 @@ export type NativeModuleNumberTypeAnnotation = $ReadOnly<{
export type NativeModuleEnumMember = {
name: string,
value: string | number,
value: StringLiteralTypeAnnotation | NumberLiteralTypeAnnotation,
};
export type NativeModuleEnumMemberType =
@@ -96,7 +96,7 @@ function combineSchemasInFileListAndWriteToFile(
exclude: ?RegExp,
): void {
const combined = combineSchemasInFileList(fileList, platform, exclude);
const formattedSchema = JSON.stringify(combined, null, 2);
const formattedSchema = JSON.stringify(combined);
fs.writeFileSync(outfile, formattedSchema);
}
@@ -84,4 +84,4 @@ for (const file of schemaFiles) {
}
}
fs.writeFileSync(output, JSON.stringify({modules}, null, 2));
fs.writeFileSync(output, JSON.stringify({modules}));
@@ -406,6 +406,14 @@ struct Bridging<${enumName}> {
};`;
};
function getMemberValueAppearance(member: NativeModuleEnumMember['value']) {
if (member.type === 'StringLiteralTypeAnnotation') {
return `"${member.value}"`;
} else {
return member.value;
}
}
function generateEnum(
hasteModuleName: string,
origEnumName: string,
@@ -417,9 +425,6 @@ function generateEnum(
const nativeEnumMemberType: NativeEnumMemberValueType =
memberType === 'StringTypeAnnotation' ? 'std::string' : 'int32_t';
const getMemberValueAppearance = (value: string | number) =>
memberType === 'StringTypeAnnotation' ? `"${value}"` : `${value}`;
const fromCases =
members
.map(
@@ -163,11 +163,17 @@ const SIMPLE_NATIVE_MODULES: SchemaType = {
members: [
{
name: 'ONE',
value: '1',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 1,
},
},
{
name: 'TWO',
value: '2',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 2,
},
},
],
},
@@ -178,15 +184,24 @@ const SIMPLE_NATIVE_MODULES: SchemaType = {
members: [
{
name: 'POINT_ZERO',
value: '0.0',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 0.0,
},
},
{
name: 'POINT_ONE',
value: '0.1',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 0.1,
},
},
{
name: 'POINT_TWO',
value: '0.2',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 0.2,
},
},
],
},
@@ -197,11 +212,17 @@ const SIMPLE_NATIVE_MODULES: SchemaType = {
members: [
{
name: 'HELLO',
value: 'hello',
value: {
type: 'StringLiteralTypeAnnotation',
value: 'hello',
},
},
{
name: 'GoodBye',
value: 'goodbye',
value: {
type: 'StringLiteralTypeAnnotation',
value: 'goodbye',
},
},
],
},
@@ -1926,11 +1947,17 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
members: [
{
name: 'IA',
value: '23',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 23,
},
},
{
name: 'IB',
value: '42',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 42,
},
},
],
},
@@ -1941,11 +1968,17 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
members: [
{
name: 'FA',
value: '1.23',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 1.23,
},
},
{
name: 'FB',
value: '4.56',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 4.56,
},
},
],
},
@@ -1956,11 +1989,17 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
members: [
{
name: 'NA',
value: 'NA',
value: {
type: 'StringLiteralTypeAnnotation',
value: 'NA',
},
},
{
name: 'NB',
value: 'NB',
value: {
type: 'StringLiteralTypeAnnotation',
value: 'NB',
},
},
],
},
@@ -1971,11 +2010,17 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = {
members: [
{
name: 'SA',
value: 's---a',
value: {
type: 'StringLiteralTypeAnnotation',
value: 's---a',
},
},
{
name: 'SB',
value: 's---b',
value: {
type: 'StringLiteralTypeAnnotation',
value: 's---b',
},
},
],
},
@@ -2047,7 +2047,7 @@ template <>
struct Bridging<NativeSampleTurboModuleFloatEnum> {
static NativeSampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue) {
double value = (double)rawValue.asNumber();
if (value == 0.0) {
if (value == 0) {
return NativeSampleTurboModuleFloatEnum::POINT_ZERO;
} else if (value == 0.1) {
return NativeSampleTurboModuleFloatEnum::POINT_ONE;
@@ -2060,7 +2060,7 @@ struct Bridging<NativeSampleTurboModuleFloatEnum> {
static jsi::Value toJs(jsi::Runtime &rt, NativeSampleTurboModuleFloatEnum value) {
if (value == NativeSampleTurboModuleFloatEnum::POINT_ZERO) {
return bridging::toJs(rt, 0.0);
return bridging::toJs(rt, 0);
} else if (value == NativeSampleTurboModuleFloatEnum::POINT_ONE) {
return bridging::toJs(rt, 0.1);
} else if (value == NativeSampleTurboModuleFloatEnum::POINT_TWO) {
@@ -478,11 +478,17 @@ describe('typeEnumResolution', () => {
members: [
{
name: 'Hello',
value: 'hello',
value: {
type: 'StringLiteralTypeAnnotation',
value: 'hello',
},
},
{
name: 'Goodbye',
value: 'goodbye',
value: {
type: 'StringLiteralTypeAnnotation',
value: 'goodbye',
},
},
],
},
@@ -521,11 +527,17 @@ describe('typeEnumResolution', () => {
members: [
{
name: 'On',
value: '1',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 1,
},
},
{
name: 'Off',
value: '0',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 0,
},
},
],
},
@@ -147,11 +147,17 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`]
'members': [
{
'name': 'SD',
'value': 'SD'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'SD'
}
},
{
'name': 'HD',
'value': 'HD'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'HD'
}
}
]
},
@@ -162,15 +168,24 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`]
'members': [
{
'name': 'Corrupted',
'value': -1
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': -1
}
},
{
'name': 'Low',
'value': 720
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': 720
}
},
{
'name': 'High',
'value': 1080
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': 1080
}
}
]
},
@@ -181,15 +196,24 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`]
'members': [
{
'name': 'One',
'value': 'one'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'one'
}
},
{
'name': 'Two',
'value': 'two'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'two'
}
},
{
'name': 'Three',
'value': 'three'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'three'
}
}
]
}
@@ -471,11 +495,17 @@ exports[`RN Codegen Flow Parser can generate fixture IOS_ONLY_NATIVE_MODULE 1`]
'members': [
{
'name': 'SD',
'value': 'SD'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'SD'
}
},
{
'name': 'HD',
'value': 'HD'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'HD'
}
}
]
},
@@ -486,11 +516,17 @@ exports[`RN Codegen Flow Parser can generate fixture IOS_ONLY_NATIVE_MODULE 1`]
'members': [
{
'name': 'Low',
'value': 720
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': 720
}
},
{
'name': 'High',
'value': 1080
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': 1080
}
}
]
},
@@ -501,15 +537,24 @@ exports[`RN Codegen Flow Parser can generate fixture IOS_ONLY_NATIVE_MODULE 1`]
'members': [
{
'name': 'One',
'value': 'one'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'one'
}
},
{
'name': 'Two',
'value': 'two'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'two'
}
},
{
'name': 'Three',
'value': 'three'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'three'
}
}
]
}
+22 -4
View File
@@ -230,10 +230,28 @@ class FlowParser implements Parser {
parseEnumMembers(
typeAnnotation: $FlowFixMe,
): $ReadOnlyArray<NativeModuleEnumMember> {
return typeAnnotation.members.map(member => ({
name: member.id.name,
value: member.init?.value ?? member.id.name,
}));
return typeAnnotation.members.map(member => {
const value =
typeof member.init?.value === 'number'
? {
type: 'NumberLiteralTypeAnnotation',
value: member.init.value,
}
: typeof member.init?.value === 'string'
? {
type: 'StringLiteralTypeAnnotation',
value: member.init.value,
}
: {
type: 'StringLiteralTypeAnnotation',
value: member.id.name,
};
return {
name: member.id.name,
value: value,
};
});
}
isModuleInterface(node: $FlowFixMe): boolean {
+16 -4
View File
@@ -175,21 +175,33 @@ export class MockedParser implements Parser {
? [
{
name: 'Hello',
value: 'hello',
value: {
type: 'StringLiteralTypeAnnotation',
value: 'hello',
},
},
{
name: 'Goodbye',
value: 'goodbye',
value: {
type: 'StringLiteralTypeAnnotation',
value: 'goodbye',
},
},
]
: [
{
name: 'On',
value: '1',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 1,
},
},
{
name: 'Off',
value: '0',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 0,
},
},
];
}
@@ -134,11 +134,17 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL
'members': [
{
'name': 'SD',
'value': 'SD'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'SD'
}
},
{
'name': 'HD',
'value': 'HD'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'HD'
}
}
]
},
@@ -149,15 +155,24 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL
'members': [
{
'name': 'Corrupted',
'value': -1
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': -1
}
},
{
'name': 'Low',
'value': 720
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': 720
}
},
{
'name': 'High',
'value': 1080
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': 1080
}
}
]
},
@@ -168,15 +183,24 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL
'members': [
{
'name': 'One',
'value': 'one'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'one'
}
},
{
'name': 'Two',
'value': 'two'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'two'
}
},
{
'name': 'Three',
'value': 'three'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'three'
}
}
]
}
@@ -458,11 +482,17 @@ exports[`RN Codegen TypeScript Parser can generate fixture IOS_ONLY_NATIVE_MODUL
'members': [
{
'name': 'SD',
'value': 'SD'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'SD'
}
},
{
'name': 'HD',
'value': 'HD'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'HD'
}
}
]
},
@@ -473,11 +503,17 @@ exports[`RN Codegen TypeScript Parser can generate fixture IOS_ONLY_NATIVE_MODUL
'members': [
{
'name': 'Low',
'value': 720
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': 720
}
},
{
'name': 'High',
'value': 1080
'value': {
'type': 'NumberLiteralTypeAnnotation',
'value': 1080
}
}
]
},
@@ -488,15 +524,24 @@ exports[`RN Codegen TypeScript Parser can generate fixture IOS_ONLY_NATIVE_MODUL
'members': [
{
'name': 'One',
'value': 'one'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'one'
}
},
{
'name': 'Two',
'value': 'two'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'two'
}
},
{
'name': 'Three',
'value': 'three'
'value': {
'type': 'StringLiteralTypeAnnotation',
'value': 'three'
}
}
]
}
@@ -124,9 +124,27 @@ describe('TypeScript Module Parser', () => {
expect(parser).not.toThrow();
expect(parser().enumMap.MyEnum.members).toEqual([
{name: 'ZERO', value: 0},
{name: 'POSITIVE', value: 1},
{name: 'NEGATIVE', value: -1},
{
name: 'ZERO',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 0,
},
},
{
name: 'POSITIVE',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 1,
},
},
{
name: 'NEGATIVE',
value: {
type: 'NumberLiteralTypeAnnotation',
value: -1,
},
},
]);
});
@@ -147,8 +165,20 @@ describe('TypeScript Module Parser', () => {
expect(parser).not.toThrow();
expect(parser().enumMap.MyEnum.members).toEqual([
{name: 'ZERO', value: 0},
{name: 'POSITIVE', value: 1},
{
name: 'ZERO',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 0,
},
},
{
name: 'POSITIVE',
value: {
type: 'NumberLiteralTypeAnnotation',
value: 1,
},
},
]);
});
@@ -250,17 +250,30 @@ class TypeScriptParser implements Parser {
typeAnnotation: $FlowFixMe,
): $ReadOnlyArray<NativeModuleEnumMember> {
return typeAnnotation.members.map(member => {
// Handle negative values
if (member.initializer?.operator === '-') {
return {
name: member.id.name,
value: -member.initializer?.argument?.value ?? member.id.name,
};
}
const value =
member.initializer?.operator === '-'
? {
type: 'NumberLiteralTypeAnnotation',
value: -1 * member.initializer?.argument?.value,
}
: typeof member.initializer?.value === 'number'
? {
type: 'NumberLiteralTypeAnnotation',
value: member.initializer?.value,
}
: typeof member.initializer?.value === 'string'
? {
type: 'StringLiteralTypeAnnotation',
value: member.initializer?.value,
}
: {
type: 'StringLiteralTypeAnnotation',
value: member.id.name,
};
return {
name: member.id.name,
value: member.initializer?.value ?? member.id.name,
value,
};
});
}
@@ -468,8 +468,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init);
- (dispatch_queue_t)methodQueue
{
if (_bridge.valid) {
id instance = self.instance;
RCTAssert(_methodQueue != nullptr, @"Module %@ has no methodQueue (instance: %@)", self, instance);
RCTAssert(_methodQueue != nullptr, @"Module %@ has no methodQueue (instance: %@)", self, self.instance);
}
return _methodQueue;
}
@@ -121,8 +121,8 @@ using namespace facebook::react;
auto &props = *sharedProps;
props.layoutConstraints = LayoutConstraints{{0, 0}, {500, 500}};
auto &yogaStyle = props.yogaStyle;
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
return sharedProps;
})
.children({
@@ -136,8 +136,8 @@ using namespace facebook::react;
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(0));
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(0));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
return sharedProps;
})
.children({
@@ -216,8 +216,8 @@ using namespace facebook::react;
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(0));
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(30));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(50));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(50));
return sharedProps;
})
.children({
@@ -260,8 +260,8 @@ using namespace facebook::react;
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(0));
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(90));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(50));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(50));
return sharedProps;
})
.children({
@@ -418,8 +418,8 @@ static ParagraphShadowNode::ConcreteState::Shared stateWithShadowNode(
auto &props = *sharedProps;
props.layoutConstraints = LayoutConstraints{{0, 0}, {500, 500}};
auto &yogaStyle = props.yogaStyle;
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
return sharedProps;
})
.children({
@@ -434,8 +434,8 @@ static ParagraphShadowNode::ConcreteState::Shared stateWithShadowNode(
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(0));
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(90));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(20));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(20));
return sharedProps;
})
.children({
@@ -87,6 +87,9 @@ CGFloat RCTCoreGraphicsFloatFromYogaValue(YGValue value, CGFloat baseFloatValue)
return RCTCoreGraphicsFloatFromYogaFloat(value.value) * baseFloatValue;
case YGUnitAuto:
case YGUnitUndefined:
case YGUnitMaxContent:
case YGUnitFitContent:
case YGUnitStretch:
return baseFloatValue;
}
}
@@ -63,6 +63,9 @@ typedef NS_ENUM(unsigned int, meta_prop_t) {
#define RCT_SET_YGVALUE(ygvalue, setter, ...) \
switch (ygvalue.unit) { \
case YGUnitAuto: \
case YGUnitMaxContent: \
case YGUnitFitContent: \
case YGUnitStretch: \
case YGUnitUndefined: \
setter(__VA_ARGS__, YGUndefined); \
break; \
@@ -88,6 +91,35 @@ typedef NS_ENUM(unsigned int, meta_prop_t) {
case YGUnitPercent: \
setter##Percent(__VA_ARGS__, ygvalue.value); \
break; \
case YGUnitMaxContent: \
case YGUnitFitContent: \
case YGUnitStretch: \
break; \
}
#define RCT_SET_YGVALUE_AUTO_INTRINSIC(ygvalue, setter, ...) \
switch (ygvalue.unit) { \
case YGUnitAuto: \
setter##Auto(__VA_ARGS__); \
break; \
case YGUnitMaxContent: \
setter##MaxContent(__VA_ARGS__); \
break; \
case YGUnitFitContent: \
setter##FitContent(__VA_ARGS__); \
break; \
case YGUnitStretch: \
setter##Stretch(__VA_ARGS__); \
break; \
case YGUnitUndefined: \
setter(__VA_ARGS__, YGUndefined); \
break; \
case YGUnitPoint: \
setter(__VA_ARGS__, ygvalue.value); \
break; \
case YGUnitPercent: \
setter##Percent(__VA_ARGS__, ygvalue.value); \
break; \
}
static void RCTProcessMetaPropsPadding(const YGValue metaProps[META_PROP_COUNT], YGNodeRef node)
@@ -483,14 +515,14 @@ RCT_BORDER_PROPERTY(Start, START)
RCT_BORDER_PROPERTY(End, END)
// Dimensions
#define RCT_DIMENSION_PROPERTY(setProp, getProp, cssProp) \
-(void)set##setProp : (YGValue)value \
{ \
RCT_SET_YGVALUE_AUTO(value, YGNodeStyleSet##cssProp, _yogaNode); \
} \
-(YGValue)getProp \
{ \
return YGNodeStyleGet##cssProp(_yogaNode); \
#define RCT_DIMENSION_PROPERTY(setProp, getProp, cssProp) \
-(void)set##setProp : (YGValue)value \
{ \
RCT_SET_YGVALUE_AUTO_INTRINSIC(value, YGNodeStyleSet##cssProp, _yogaNode); \
} \
-(YGValue)getProp \
{ \
return YGNodeStyleGet##cssProp(_yogaNode); \
}
#define RCT_MIN_MAX_DIMENSION_PROPERTY(setProp, getProp, cssProp) \
@@ -634,7 +666,7 @@ RCTShadowViewMeasure(YGNodeConstRef node, float width, YGMeasureMode widthMode,
- (void)setFlexBasis:(YGValue)value
{
RCT_SET_YGVALUE_AUTO(value, YGNodeStyleSetFlexBasis, _yogaNode);
RCT_SET_YGVALUE_AUTO_INTRINSIC(value, YGNodeStyleSetFlexBasis, _yogaNode);
}
- (YGValue)flexBasis
@@ -780,16 +780,6 @@ public abstract class com/facebook/react/bridge/GuardedAsyncTask : android/os/As
protected abstract fun doInBackgroundGuarded ([Ljava/lang/Object;)V
}
public abstract class com/facebook/react/bridge/GuardedResultAsyncTask : android/os/AsyncTask {
protected fun <init> (Lcom/facebook/react/bridge/JSExceptionHandler;)V
protected fun <init> (Lcom/facebook/react/bridge/ReactContext;)V
protected synthetic fun doInBackground ([Ljava/lang/Object;)Ljava/lang/Object;
protected final fun doInBackground ([Ljava/lang/Void;)Ljava/lang/Object;
protected abstract fun doInBackgroundGuarded ()Ljava/lang/Object;
protected final fun onPostExecute (Ljava/lang/Object;)V
protected abstract fun onPostExecuteGuarded (Ljava/lang/Object;)V
}
public abstract class com/facebook/react/bridge/GuardedRunnable : java/lang/Runnable {
public fun <init> (Lcom/facebook/react/bridge/JSExceptionHandler;)V
public fun <init> (Lcom/facebook/react/bridge/ReactContext;)V
@@ -4095,10 +4085,6 @@ public abstract class com/facebook/react/uimanager/BaseViewManagerDelegate : com
public fun setProperty (Landroid/view/View;Ljava/lang/String;Ljava/lang/Object;)V
}
public abstract interface class com/facebook/react/uimanager/ComponentNameResolver {
public abstract fun getComponentNames ()[Ljava/lang/String;
}
public final class com/facebook/react/uimanager/DisplayMetricsHolder {
public static final field INSTANCE Lcom/facebook/react/uimanager/DisplayMetricsHolder;
public static final fun getDisplayMetricsWritableMap (D)Lcom/facebook/react/bridge/WritableMap;
@@ -4110,22 +4096,6 @@ public final class com/facebook/react/uimanager/DisplayMetricsHolder {
public static final fun setWindowDisplayMetrics (Landroid/util/DisplayMetrics;)V
}
public class com/facebook/react/uimanager/FabricViewStateManager {
public fun <init> ()V
public fun getStateData ()Lcom/facebook/react/bridge/ReadableMap;
public fun hasStateWrapper ()Z
public fun setState (Lcom/facebook/react/uimanager/FabricViewStateManager$StateUpdateCallback;)V
public fun setStateWrapper (Lcom/facebook/react/uimanager/StateWrapper;)V
}
public abstract interface class com/facebook/react/uimanager/FabricViewStateManager$HasFabricViewStateManager {
public abstract fun getFabricViewStateManager ()Lcom/facebook/react/uimanager/FabricViewStateManager;
}
public abstract interface class com/facebook/react/uimanager/FabricViewStateManager$StateUpdateCallback {
public abstract fun getStateUpdate ()Lcom/facebook/react/bridge/WritableMap;
}
public final class com/facebook/react/uimanager/FloatUtil {
public static final field INSTANCE Lcom/facebook/react/uimanager/FloatUtil;
public static final fun floatsEqual (FF)Z
@@ -591,7 +591,8 @@ android {
"src/main/res/shell",
"src/main/res/views/alert",
"src/main/res/views/modal",
"src/main/res/views/uimanager"))
"src/main/res/views/uimanager",
"src/main/res/views/view"))
java.exclude("com/facebook/react/processing")
java.exclude("com/facebook/react/module/processing")
}
@@ -1,50 +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.react.bridge;
import android.os.AsyncTask;
/**
* Abstract base for a AsyncTask with result support that should have any RuntimeExceptions it
* throws handled by the {@link JSExceptionHandler} registered if the app is in dev mode.
*/
public abstract class GuardedResultAsyncTask<Result> extends AsyncTask<Void, Void, Result> {
private final JSExceptionHandler mExceptionHandler;
protected GuardedResultAsyncTask(ReactContext reactContext) {
this(reactContext.getExceptionHandler());
}
protected GuardedResultAsyncTask(JSExceptionHandler exceptionHandler) {
mExceptionHandler = exceptionHandler;
}
@Override
protected final Result doInBackground(Void... params) {
try {
return doInBackgroundGuarded();
} catch (RuntimeException e) {
mExceptionHandler.handleException(e);
throw e;
}
}
@Override
protected final void onPostExecute(Result result) {
try {
onPostExecuteGuarded(result);
} catch (RuntimeException e) {
mExceptionHandler.handleException(e);
}
}
protected abstract Result doInBackgroundGuarded();
protected abstract void onPostExecuteGuarded(Result result);
}
@@ -84,6 +84,7 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
view.setTag(R.id.accessibility_actions, null);
view.setTag(R.id.accessibility_value, null);
view.setTag(R.id.accessibility_state_expanded, null);
view.setTag(R.id.view_clipped, null);
// This indirectly calls (and resets):
// setTranslationX
@@ -5,13 +5,12 @@
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.uimanager;
package com.facebook.react.uimanager
import com.facebook.proguard.annotations.DoNotStripAny;
import com.facebook.proguard.annotations.DoNotStripAny
@DoNotStripAny
public interface ComponentNameResolver {
internal interface ComponentNameResolver {
/* returns a list of all the component names that are registered in React Native. */
String[] getComponentNames();
public val componentNames: Array<String>?
}
@@ -1,98 +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.react.uimanager;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
/**
* This is a helper base class for ViewGroups that use Fabric State.
*
* <p>Reason to use this: UpdateState calls from the View layer to the Fabric core can fail, and
* optionally Fabric will call a "failure callback" if that happens. This class abstracts that and
* makes it easier ensure that State in Fabric is always up-to-date.
*
* <p>1. Whenever ViewManager.updateState is called, call View.setStateWrapper. 2. Instead of
* calling StateWrapper.updateState directly, call View.setState and it will automatically keep
* retrying the UpdateState call until it succeeds; or you call setState again; or the View layer is
* updated with a newer StateWrapper.
*/
@Nullsafe(Nullsafe.Mode.LOCAL)
@Deprecated(
since =
"Deprecated class since v0.73.0, please use com.facebook.react.uimanager.StateWrapper"
+ " instead.",
forRemoval = true)
public class FabricViewStateManager {
private static final String TAG = "FabricViewStateManager";
@Deprecated
public interface HasFabricViewStateManager {
FabricViewStateManager getFabricViewStateManager();
}
@Deprecated
public interface StateUpdateCallback {
WritableMap getStateUpdate();
}
@Nullable private StateWrapper mStateWrapper = null;
@Deprecated
public void setStateWrapper(StateWrapper stateWrapper) {
mStateWrapper = stateWrapper;
}
@Deprecated
public boolean hasStateWrapper() {
return mStateWrapper != null;
}
private void setState(
@Nullable final StateWrapper stateWrapper,
final StateUpdateCallback stateUpdateCallback,
final int numTries) {
// The StateWrapper will change, breaking the async loop, whenever the UpdateState MountItem
// is executed.
// The caller is responsible for detecting if data is up-to-date, and doing nothing, or
// detecting if state is stale and calling setState again.
if (stateWrapper == null) {
FLog.e(TAG, "setState called without a StateWrapper");
return;
}
if (stateWrapper != mStateWrapper) {
return;
}
// We bail out after an arbitrary number of tries. In practice this should never go higher
// than 2 or 3, but there's nothing guaranteeing that.
if (numTries > 60) {
return;
}
@Nullable WritableMap stateUpdate = stateUpdateCallback.getStateUpdate();
if (stateUpdate == null) {
return;
}
// TODO: State update cannot fail; remove `failureRunnable` and custom retrying logic.
stateWrapper.updateState(stateUpdate);
}
@Deprecated
public void setState(final StateUpdateCallback stateUpdateCallback) {
setState(mStateWrapper, stateUpdateCallback, 0);
}
@Deprecated
public @Nullable ReadableMap getStateData() {
return mStateWrapper != null ? mStateWrapper.getStateData() : null;
}
}
@@ -5,10 +5,10 @@
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.uimanager.events;
package com.facebook.react.uimanager.events
public interface BatchEventDispatchedListener {
public fun interface BatchEventDispatchedListener {
/** Called after a batch of low priority events has been dispatched. */
void onBatchEventDispatched();
public fun onBatchEventDispatched()
}
@@ -125,6 +125,7 @@ public class ReactViewGroup extends ViewGroup
// {@link ViewGroup#getChildCount} so those methods may return views that are not attached.
// This is risky but allows us to perform a correct cleanup in {@link NativeViewHierarchyManager}.
private boolean mRemoveClippedSubviews;
private volatile boolean mInSubviewClippingLoop;
private @Nullable View[] mAllChildren;
private int mAllChildrenCount;
private @Nullable Rect mClippingRect;
@@ -158,6 +159,7 @@ public class ReactViewGroup extends ViewGroup
setClipChildren(false);
mRemoveClippedSubviews = false;
mInSubviewClippingLoop = false;
mAllChildren = null;
mAllChildrenCount = 0;
mClippingRect = null;
@@ -363,6 +365,7 @@ public class ReactViewGroup extends ViewGroup
View child = getChildAt(i);
mAllChildren[i] = child;
child.addOnLayoutChangeListener(mChildrenLayoutChangeListener);
setViewClipped(child, false);
}
updateClippingRect();
} else {
@@ -407,6 +410,7 @@ public class ReactViewGroup extends ViewGroup
private void updateClippingToRect(Rect clippingRect) {
Assertions.assertNotNull(mAllChildren);
mInSubviewClippingLoop = true;
int clippedSoFar = 0;
for (int i = 0; i < mAllChildrenCount; i++) {
try {
@@ -415,7 +419,7 @@ public class ReactViewGroup extends ViewGroup
int realClippedSoFar = 0;
Set<View> uniqueViews = new HashSet<>();
for (int j = 0; j < i; j++) {
realClippedSoFar += isViewClipped(mAllChildren[j]) ? 1 : 0;
realClippedSoFar += isViewClipped(mAllChildren[j], null) ? 1 : 0;
uniqueViews.add(mAllChildren[j]);
}
@@ -436,10 +440,11 @@ public class ReactViewGroup extends ViewGroup
+ uniqueViews.size(),
e);
}
if (isViewClipped(mAllChildren[i])) {
if (isViewClipped(mAllChildren[i], i)) {
clippedSoFar++;
}
}
mInSubviewClippingLoop = false;
}
private void updateSubviewClipStatus(Rect clippingRect, int idx, int clippedSoFar) {
@@ -458,14 +463,16 @@ public class ReactViewGroup extends ViewGroup
// it won't be size and located properly.
Animation animation = child.getAnimation();
boolean isAnimating = animation != null && !animation.hasEnded();
if (!intersects && !isViewClipped(child) && !isAnimating) {
if (!intersects && !isViewClipped(child, idx) && !isAnimating) {
setViewClipped(child, true);
// We can try saving on invalidate call here as the view that we remove is out of visible area
// therefore invalidation is not necessary.
removeViewInLayout(child);
needUpdateClippingRecursive = true;
} else if (intersects && isViewClipped(child)) {
} else if (intersects && isViewClipped(child, idx)) {
int adjustedIdx = idx - clippedSoFar;
Assertions.assertCondition(adjustedIdx >= 0);
setViewClipped(child, false);
addViewInLayout(child, adjustedIdx, sDefaultLayoutParam, true);
invalidate();
needUpdateClippingRecursive = true;
@@ -497,19 +504,21 @@ public class ReactViewGroup extends ViewGroup
subview.getLeft(), subview.getTop(), subview.getRight(), subview.getBottom());
// If it was intersecting before, should be attached to the parent
boolean oldIntersects = !isViewClipped(subview);
boolean oldIntersects = !isViewClipped(subview, null);
if (intersects != oldIntersects) {
mInSubviewClippingLoop = true;
int clippedSoFar = 0;
for (int i = 0; i < mAllChildrenCount; i++) {
if (mAllChildren[i] == subview) {
updateSubviewClipStatus(mClippingRect, i, clippedSoFar);
break;
}
if (isViewClipped(mAllChildren[i])) {
if (isViewClipped(mAllChildren[i], i)) {
clippedSoFar++;
}
}
mInSubviewClippingLoop = false;
}
}
@@ -541,7 +550,7 @@ public class ReactViewGroup extends ViewGroup
@Override
public void onViewAdded(View child) {
UiThreadUtil.assertOnUiThread();
checkViewClippingTag(child, Boolean.FALSE);
if (!customDrawOrderDisabled()) {
getDrawingOrderHelper().handleAddView(child);
setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder());
@@ -554,7 +563,7 @@ public class ReactViewGroup extends ViewGroup
@Override
public void onViewRemoved(View child) {
UiThreadUtil.assertOnUiThread();
checkViewClippingTag(child, Boolean.TRUE);
if (!customDrawOrderDisabled()) {
if (indexOfChild(child) == -1) {
return;
@@ -567,6 +576,21 @@ public class ReactViewGroup extends ViewGroup
super.onViewRemoved(child);
}
private void checkViewClippingTag(View child, Boolean expectedTag) {
if (mInSubviewClippingLoop) {
Object tag = child.getTag(R.id.view_clipped);
if (!expectedTag.equals(tag)) {
ReactSoftExceptionLogger.logSoftException(
"ReactViewGroup.onViewRemoved",
new ReactNoCrashSoftException(
"View clipping tag mismatch: tag=" + tag + " expected=" + expectedTag));
}
}
if (mRemoveClippedSubviews) {
child.setTag(R.id.view_clipped, expectedTag);
}
}
@Override
protected int getChildDrawingOrder(int childCount, int index) {
UiThreadUtil.assertOnUiThread();
@@ -638,19 +662,22 @@ public class ReactViewGroup extends ViewGroup
/*package*/ void addViewWithSubviewClippingEnabled(
final View child, int index, ViewGroup.LayoutParams params) {
Assertions.assertCondition(mRemoveClippedSubviews);
setViewClipped(child, true); // the view has not been added, so it is "clipped"
addInArray(child, index);
// we add view as "clipped" and then run {@link #updateSubviewClipStatus} to conditionally
// attach it
Rect clippingRect = Assertions.assertNotNull(mClippingRect);
View[] childArray = Assertions.assertNotNull(mAllChildren);
mInSubviewClippingLoop = true;
int clippedSoFar = 0;
for (int i = 0; i < index; i++) {
if (isViewClipped(childArray[i])) {
if (isViewClipped(childArray[i], i)) {
clippedSoFar++;
}
}
updateSubviewClipStatus(clippingRect, index, clippedSoFar);
mInSubviewClippingLoop = false;
child.addOnLayoutChangeListener(mChildrenLayoutChangeListener);
if (child instanceof ReactClippingProhibitedView) {
@@ -685,10 +712,10 @@ public class ReactViewGroup extends ViewGroup
View[] childArray = Assertions.assertNotNull(mAllChildren);
view.removeOnLayoutChangeListener(mChildrenLayoutChangeListener);
int index = indexOfChildInAllChildren(view);
if (!isViewClipped(childArray[index])) {
if (!isViewClipped(childArray[index], index)) {
int clippedSoFar = 0;
for (int i = 0; i < index; i++) {
if (isViewClipped(childArray[i])) {
if (isViewClipped(childArray[i], i)) {
clippedSoFar++;
}
}
@@ -709,9 +736,27 @@ public class ReactViewGroup extends ViewGroup
/**
* @return {@code true} if the view has been removed from the ViewGroup.
* @param index For logging - index of the view in {@code mAllChildren}, or {@code null} to skip
* logging.
*/
private boolean isViewClipped(View view) {
private boolean isViewClipped(View view, @Nullable Integer index) {
Object tag = view.getTag(R.id.view_clipped);
if (tag != null) {
return (boolean) tag;
}
ViewParent parent = view.getParent();
if (index != null) {
ReactSoftExceptionLogger.logSoftException(
"ReactViewGroup.isViewClipped",
new ReactNoCrashSoftException(
"View missing clipping tag: index="
+ index
+ " parentNull="
+ (parent == null)
+ " parentThis="
+ (parent == this)));
}
// fallback - parent *should* be null if the view was removed
if (parent == null) {
return true;
} else {
@@ -720,6 +765,10 @@ public class ReactViewGroup extends ViewGroup
}
}
private static void setViewClipped(View view, boolean clipped) {
view.setTag(R.id.view_clipped, clipped);
}
private int indexOfChildInAllChildren(View child) {
final int count = mAllChildrenCount;
final View[] childArray = Assertions.assertNotNull(mAllChildren);
@@ -74,6 +74,9 @@ public class YogaNative {
static native void jni_YGNodeStyleSetFlexBasisJNI(long nativePointer, float flexBasis);
static native void jni_YGNodeStyleSetFlexBasisPercentJNI(long nativePointer, float percent);
static native void jni_YGNodeStyleSetFlexBasisAutoJNI(long nativePointer);
static native void jni_YGNodeStyleSetFlexBasisMaxContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetFlexBasisFitContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetFlexBasisStretchJNI(long nativePointer);
static native long jni_YGNodeStyleGetMarginJNI(long nativePointer, int edge);
static native void jni_YGNodeStyleSetMarginJNI(long nativePointer, int edge, float margin);
static native void jni_YGNodeStyleSetMarginPercentJNI(long nativePointer, int edge, float percent);
@@ -91,22 +94,40 @@ public class YogaNative {
static native void jni_YGNodeStyleSetWidthJNI(long nativePointer, float width);
static native void jni_YGNodeStyleSetWidthPercentJNI(long nativePointer, float percent);
static native void jni_YGNodeStyleSetWidthAutoJNI(long nativePointer);
static native void jni_YGNodeStyleSetWidthMaxContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetWidthFitContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetWidthStretchJNI(long nativePointer);
static native long jni_YGNodeStyleGetHeightJNI(long nativePointer);
static native void jni_YGNodeStyleSetHeightJNI(long nativePointer, float height);
static native void jni_YGNodeStyleSetHeightPercentJNI(long nativePointer, float percent);
static native void jni_YGNodeStyleSetHeightAutoJNI(long nativePointer);
static native void jni_YGNodeStyleSetHeightMaxContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetHeightFitContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetHeightStretchJNI(long nativePointer);
static native long jni_YGNodeStyleGetMinWidthJNI(long nativePointer);
static native void jni_YGNodeStyleSetMinWidthJNI(long nativePointer, float minWidth);
static native void jni_YGNodeStyleSetMinWidthPercentJNI(long nativePointer, float percent);
static native void jni_YGNodeStyleSetMinWidthMaxContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetMinWidthFitContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetMinWidthStretchJNI(long nativePointer);
static native long jni_YGNodeStyleGetMinHeightJNI(long nativePointer);
static native void jni_YGNodeStyleSetMinHeightJNI(long nativePointer, float minHeight);
static native void jni_YGNodeStyleSetMinHeightPercentJNI(long nativePointer, float percent);
static native void jni_YGNodeStyleSetMinHeightMaxContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetMinHeightFitContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetMinHeightStretchJNI(long nativePointer);
static native long jni_YGNodeStyleGetMaxWidthJNI(long nativePointer);
static native void jni_YGNodeStyleSetMaxWidthJNI(long nativePointer, float maxWidth);
static native void jni_YGNodeStyleSetMaxWidthPercentJNI(long nativePointer, float percent);
static native void jni_YGNodeStyleSetMaxWidthMaxContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetMaxWidthFitContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetMaxWidthStretchJNI(long nativePointer);
static native long jni_YGNodeStyleGetMaxHeightJNI(long nativePointer);
static native void jni_YGNodeStyleSetMaxHeightJNI(long nativePointer, float maxheight);
static native void jni_YGNodeStyleSetMaxHeightPercentJNI(long nativePointer, float percent);
static native void jni_YGNodeStyleSetMaxHeightMaxContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetMaxHeightFitContentJNI(long nativePointer);
static native void jni_YGNodeStyleSetMaxHeightStretchJNI(long nativePointer);
static native float jni_YGNodeStyleGetAspectRatioJNI(long nativePointer);
static native void jni_YGNodeStyleSetAspectRatioJNI(long nativePointer, float aspectRatio);
static native float jni_YGNodeStyleGetGapJNI(long nativePointer, int gutter);
@@ -124,6 +124,12 @@ public abstract class YogaNode implements YogaProps {
public abstract void setFlexBasisAuto();
public abstract void setFlexBasisMaxContent();
public abstract void setFlexBasisFitContent();
public abstract void setFlexBasisStretch();
public abstract YogaValue getMargin(YogaEdge edge);
public abstract void setMargin(YogaEdge edge, float margin);
@@ -158,6 +164,12 @@ public abstract class YogaNode implements YogaProps {
public abstract void setWidthAuto();
public abstract void setWidthMaxContent();
public abstract void setWidthFitContent();
public abstract void setWidthStretch();
public abstract YogaValue getHeight();
public abstract void setHeight(float height);
@@ -166,30 +178,60 @@ public abstract class YogaNode implements YogaProps {
public abstract void setHeightAuto();
public abstract void setHeightMaxContent();
public abstract void setHeightFitContent();
public abstract void setHeightStretch();
public abstract YogaValue getMinWidth();
public abstract void setMinWidth(float minWidth);
public abstract void setMinWidthPercent(float percent);
public abstract void setMinWidthMaxContent();
public abstract void setMinWidthFitContent();
public abstract void setMinWidthStretch();
public abstract YogaValue getMinHeight();
public abstract void setMinHeight(float minHeight);
public abstract void setMinHeightPercent(float percent);
public abstract void setMinHeightMaxContent();
public abstract void setMinHeightFitContent();
public abstract void setMinHeightStretch();
public abstract YogaValue getMaxWidth();
public abstract void setMaxWidth(float maxWidth);
public abstract void setMaxWidthPercent(float percent);
public abstract void setMaxWidthMaxContent();
public abstract void setMaxWidthFitContent();
public abstract void setMaxWidthStretch();
public abstract YogaValue getMaxHeight();
public abstract void setMaxHeight(float maxheight);
public abstract void setMaxHeightPercent(float percent);
public abstract void setMaxHeightMaxContent();
public abstract void setMaxHeightFitContent();
public abstract void setMaxHeightStretch();
public abstract float getAspectRatio();
public abstract void setAspectRatio(float aspectRatio);
@@ -373,6 +373,18 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeStyleSetFlexBasisAutoJNI(mNativePointer);
}
public void setFlexBasisMaxContent() {
YogaNative.jni_YGNodeStyleSetFlexBasisMaxContentJNI(mNativePointer);
}
public void setFlexBasisFitContent() {
YogaNative.jni_YGNodeStyleSetFlexBasisFitContentJNI(mNativePointer);
}
public void setFlexBasisStretch() {
YogaNative.jni_YGNodeStyleSetFlexBasisStretchJNI(mNativePointer);
}
public YogaValue getMargin(YogaEdge edge) {
return valueFromLong(YogaNative.jni_YGNodeStyleGetMarginJNI(mNativePointer, edge.intValue()));
}
@@ -441,6 +453,18 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeStyleSetWidthAutoJNI(mNativePointer);
}
public void setWidthMaxContent() {
YogaNative.jni_YGNodeStyleSetWidthMaxContentJNI(mNativePointer);
}
public void setWidthFitContent() {
YogaNative.jni_YGNodeStyleSetWidthFitContentJNI(mNativePointer);
}
public void setWidthStretch() {
YogaNative.jni_YGNodeStyleSetWidthStretchJNI(mNativePointer);
}
public YogaValue getHeight() {
return valueFromLong(YogaNative.jni_YGNodeStyleGetHeightJNI(mNativePointer));
}
@@ -457,6 +481,18 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeStyleSetHeightAutoJNI(mNativePointer);
}
public void setHeightMaxContent() {
YogaNative.jni_YGNodeStyleSetHeightMaxContentJNI(mNativePointer);
}
public void setHeightFitContent() {
YogaNative.jni_YGNodeStyleSetHeightFitContentJNI(mNativePointer);
}
public void setHeightStretch() {
YogaNative.jni_YGNodeStyleSetHeightStretchJNI(mNativePointer);
}
public YogaValue getMinWidth() {
return valueFromLong(YogaNative.jni_YGNodeStyleGetMinWidthJNI(mNativePointer));
}
@@ -469,6 +505,18 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeStyleSetMinWidthPercentJNI(mNativePointer, percent);
}
public void setMinWidthMaxContent() {
YogaNative.jni_YGNodeStyleSetMinWidthMaxContentJNI(mNativePointer);
}
public void setMinWidthFitContent() {
YogaNative.jni_YGNodeStyleSetMinWidthFitContentJNI(mNativePointer);
}
public void setMinWidthStretch() {
YogaNative.jni_YGNodeStyleSetMinWidthStretchJNI(mNativePointer);
}
public YogaValue getMinHeight() {
return valueFromLong(YogaNative.jni_YGNodeStyleGetMinHeightJNI(mNativePointer));
}
@@ -481,6 +529,18 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeStyleSetMinHeightPercentJNI(mNativePointer, percent);
}
public void setMinHeightMaxContent() {
YogaNative.jni_YGNodeStyleSetMinHeightMaxContentJNI(mNativePointer);
}
public void setMinHeightFitContent() {
YogaNative.jni_YGNodeStyleSetMinHeightFitContentJNI(mNativePointer);
}
public void setMinHeightStretch() {
YogaNative.jni_YGNodeStyleSetMinHeightStretchJNI(mNativePointer);
}
public YogaValue getMaxWidth() {
return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxWidthJNI(mNativePointer));
}
@@ -493,6 +553,18 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeStyleSetMaxWidthPercentJNI(mNativePointer, percent);
}
public void setMaxWidthMaxContent() {
YogaNative.jni_YGNodeStyleSetMaxWidthMaxContentJNI(mNativePointer);
}
public void setMaxWidthFitContent() {
YogaNative.jni_YGNodeStyleSetMaxWidthFitContentJNI(mNativePointer);
}
public void setMaxWidthStretch() {
YogaNative.jni_YGNodeStyleSetMaxWidthStretchJNI(mNativePointer);
}
public YogaValue getMaxHeight() {
return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxHeightJNI(mNativePointer));
}
@@ -505,6 +577,18 @@ public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {
YogaNative.jni_YGNodeStyleSetMaxHeightPercentJNI(mNativePointer, percent);
}
public void setMaxHeightMaxContent() {
YogaNative.jni_YGNodeStyleSetMaxHeightMaxContentJNI(mNativePointer);
}
public void setMaxHeightFitContent() {
YogaNative.jni_YGNodeStyleSetMaxHeightFitContentJNI(mNativePointer);
}
public void setMaxHeightStretch() {
YogaNative.jni_YGNodeStyleSetMaxHeightStretchJNI(mNativePointer);
}
public float getAspectRatio() {
return YogaNative.jni_YGNodeStyleGetAspectRatioJNI(mNativePointer);
}
@@ -15,15 +15,33 @@ public interface YogaProps {
void setWidthPercent(float percent);
void setWidthAuto();
void setWidthMaxContent();
void setWidthFitContent();
void setWidthStretch();
void setMinWidth(float minWidth);
void setMinWidthPercent(float percent);
void setMinWidthMaxContent();
void setMinWidthFitContent();
void setMinWidthStretch();
void setMaxWidth(float maxWidth);
void setMaxWidthPercent(float percent);
void setWidthAuto();
void setMaxWidthMaxContent();
void setMaxWidthFitContent();
void setMaxWidthStretch();
/* Height properties */
@@ -31,15 +49,33 @@ public interface YogaProps {
void setHeightPercent(float percent);
void setHeightAuto();
void setHeightMaxContent();
void setHeightFitContent();
void setHeightStretch();
void setMinHeight(float minHeight);
void setMinHeightPercent(float percent);
void setMinHeightMaxContent();
void setMinHeightFitContent();
void setMinHeightStretch();
void setMaxHeight(float maxHeight);
void setMaxHeightPercent(float percent);
void setHeightAuto();
void setMaxHeightMaxContent();
void setMaxHeightFitContent();
void setMaxHeightStretch();
/* Margin properties */
@@ -81,6 +117,12 @@ public interface YogaProps {
void setFlexBasis(float flexBasis);
void setFlexBasisMaxContent();
void setFlexBasisFitContent();
void setFlexBasisStretch();
void setFlexDirection(YogaFlexDirection direction);
void setFlexGrow(float flexGrow);
@@ -13,7 +13,10 @@ public enum YogaUnit {
UNDEFINED(0),
POINT(1),
PERCENT(2),
AUTO(3);
AUTO(3),
MAX_CONTENT(4),
FIT_CONTENT(5),
STRETCH(6);
private final int mIntValue;
@@ -31,6 +34,9 @@ public enum YogaUnit {
case 1: return POINT;
case 2: return PERCENT;
case 3: return AUTO;
case 4: return MAX_CONTENT;
case 5: return FIT_CONTENT;
case 6: return STRETCH;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
}
}
@@ -429,6 +429,28 @@ static void jni_YGNodeCopyStyleJNI(
YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \
}
#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO_INTRINSIC(name) \
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \
YG_NODE_JNI_STYLE_UNIT_INTRINSIC(name)
#define YG_NODE_JNI_STYLE_UNIT_PROP_INTRINSIC(name) \
YG_NODE_JNI_STYLE_UNIT_PROP(name) \
YG_NODE_JNI_STYLE_UNIT_INTRINSIC(name)
#define YG_NODE_JNI_STYLE_UNIT_INTRINSIC(name) \
static void jni_YGNodeStyleSet##name##MaxContentJNI( \
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \
YGNodeStyleSet##name##MaxContent(_jlong2YGNodeRef(nativePointer)); \
} \
static void jni_YGNodeStyleSet##name##FitContentJNI( \
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \
YGNodeStyleSet##name##FitContent(_jlong2YGNodeRef(nativePointer)); \
} \
static void jni_YGNodeStyleSet##name##StretchJNI( \
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) { \
YGNodeStyleSet##name##Stretch(_jlong2YGNodeRef(nativePointer)); \
}
#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \
static jlong jni_YGNodeStyleGet##name##JNI( \
JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jint edge) { \
@@ -483,13 +505,13 @@ YG_NODE_JNI_STYLE_PROP(jfloat, float, Flex);
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow);
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(FlexBasis);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Width);
YG_NODE_JNI_STYLE_UNIT_PROP(MinWidth);
YG_NODE_JNI_STYLE_UNIT_PROP(MaxWidth);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Height);
YG_NODE_JNI_STYLE_UNIT_PROP(MinHeight);
YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO_INTRINSIC(FlexBasis);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO_INTRINSIC(Width);
YG_NODE_JNI_STYLE_UNIT_PROP_INTRINSIC(MinWidth);
YG_NODE_JNI_STYLE_UNIT_PROP_INTRINSIC(MaxWidth);
YG_NODE_JNI_STYLE_UNIT_PROP_AUTO_INTRINSIC(Height);
YG_NODE_JNI_STYLE_UNIT_PROP_INTRINSIC(MinHeight);
YG_NODE_JNI_STYLE_UNIT_PROP_INTRINSIC(MaxHeight);
YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(Position);
@@ -870,6 +892,15 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeStyleSetFlexBasisAutoJNI",
"(J)V",
(void*)jni_YGNodeStyleSetFlexBasisAutoJNI},
{"jni_YGNodeStyleSetFlexBasisMaxContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetFlexBasisMaxContentJNI},
{"jni_YGNodeStyleSetFlexBasisFitContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetFlexBasisFitContentJNI},
{"jni_YGNodeStyleSetFlexBasisStretchJNI",
"(J)V",
(void*)jni_YGNodeStyleSetFlexBasisStretchJNI},
{"jni_YGNodeStyleGetMarginJNI",
"(JI)J",
(void*)jni_YGNodeStyleGetMarginJNI},
@@ -917,6 +948,15 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeStyleSetWidthAutoJNI",
"(J)V",
(void*)jni_YGNodeStyleSetWidthAutoJNI},
{"jni_YGNodeStyleSetWidthMaxContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetWidthMaxContentJNI},
{"jni_YGNodeStyleSetWidthFitContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetWidthFitContentJNI},
{"jni_YGNodeStyleSetWidthStretchJNI",
"(J)V",
(void*)jni_YGNodeStyleSetWidthStretchJNI},
{"jni_YGNodeStyleGetHeightJNI", "(J)J", (void*)jni_YGNodeStyleGetHeightJNI},
{"jni_YGNodeStyleSetHeightJNI",
"(JF)V",
@@ -927,6 +967,15 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeStyleSetHeightAutoJNI",
"(J)V",
(void*)jni_YGNodeStyleSetHeightAutoJNI},
{"jni_YGNodeStyleSetHeightMaxContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetHeightMaxContentJNI},
{"jni_YGNodeStyleSetHeightFitContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetHeightFitContentJNI},
{"jni_YGNodeStyleSetHeightStretchJNI",
"(J)V",
(void*)jni_YGNodeStyleSetHeightStretchJNI},
{"jni_YGNodeStyleGetMinWidthJNI",
"(J)J",
(void*)jni_YGNodeStyleGetMinWidthJNI},
@@ -936,6 +985,15 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeStyleSetMinWidthPercentJNI",
"(JF)V",
(void*)jni_YGNodeStyleSetMinWidthPercentJNI},
{"jni_YGNodeStyleSetMinWidthMaxContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMinWidthMaxContentJNI},
{"jni_YGNodeStyleSetMinWidthFitContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMinWidthFitContentJNI},
{"jni_YGNodeStyleSetMinWidthStretchJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMinWidthStretchJNI},
{"jni_YGNodeStyleGetMinHeightJNI",
"(J)J",
(void*)jni_YGNodeStyleGetMinHeightJNI},
@@ -945,6 +1003,15 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeStyleSetMinHeightPercentJNI",
"(JF)V",
(void*)jni_YGNodeStyleSetMinHeightPercentJNI},
{"jni_YGNodeStyleSetMinHeightMaxContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMinHeightMaxContentJNI},
{"jni_YGNodeStyleSetMinHeightFitContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMinHeightFitContentJNI},
{"jni_YGNodeStyleSetMinHeightStretchJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMinHeightStretchJNI},
{"jni_YGNodeStyleGetMaxWidthJNI",
"(J)J",
(void*)jni_YGNodeStyleGetMaxWidthJNI},
@@ -954,6 +1021,15 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeStyleSetMaxWidthPercentJNI",
"(JF)V",
(void*)jni_YGNodeStyleSetMaxWidthPercentJNI},
{"jni_YGNodeStyleSetMaxWidthMaxContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMaxWidthMaxContentJNI},
{"jni_YGNodeStyleSetMaxWidthFitContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMaxWidthFitContentJNI},
{"jni_YGNodeStyleSetMaxWidthStretchJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMaxWidthStretchJNI},
{"jni_YGNodeStyleGetMaxHeightJNI",
"(J)J",
(void*)jni_YGNodeStyleGetMaxHeightJNI},
@@ -963,6 +1039,15 @@ static JNINativeMethod methods[] = {
{"jni_YGNodeStyleSetMaxHeightPercentJNI",
"(JF)V",
(void*)jni_YGNodeStyleSetMaxHeightPercentJNI},
{"jni_YGNodeStyleSetMaxHeightMaxContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMaxHeightMaxContentJNI},
{"jni_YGNodeStyleSetMaxHeightFitContentJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMaxHeightFitContentJNI},
{"jni_YGNodeStyleSetMaxHeightStretchJNI",
"(J)V",
(void*)jni_YGNodeStyleSetMaxHeightStretchJNI},
{"jni_YGNodeStyleGetAspectRatioJNI",
"(J)F",
(void*)jni_YGNodeStyleGetAspectRatioJNI},
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- tag used to store state of ReactViewGroup subview clipping -->
<item type="id" name="view_clipped"/>
</resources>
@@ -45,10 +45,8 @@ namespace {
#endif
NO_DESTROY const std::string TRACK_PREFIX = "Track:";
NO_DESTROY const std::string DEFAULT_TRACK_NAME = "# Web Performance";
NO_DESTROY const std::string CUSTOM_TRACK_NAME_PREFIX = "# Web Performance: ";
std::tuple<std::string, std::string_view> parseTrackName(
std::tuple<std::optional<std::string>, std::string_view> parseTrackName(
const std::string& name) {
// Until there's a standard way to pass through track information, parse it
// manually, e.g., "Track:Foo:Event name"
@@ -58,16 +56,13 @@ std::tuple<std::string, std::string_view> parseTrackName(
if (name.starts_with(TRACK_PREFIX)) {
const auto trackNameDelimiter = name.find(':', TRACK_PREFIX.length());
if (trackNameDelimiter != std::string::npos) {
trackName = CUSTOM_TRACK_NAME_PREFIX +
name.substr(
TRACK_PREFIX.length(),
trackNameDelimiter - TRACK_PREFIX.length());
trackName = name.substr(
TRACK_PREFIX.length(), trackNameDelimiter - TRACK_PREFIX.length());
eventName = std::string_view(name).substr(trackNameDelimiter + 1);
}
}
auto& trackNameRef = trackName.has_value() ? *trackName : DEFAULT_TRACK_NAME;
return std::make_tuple(trackNameRef, eventName);
return std::make_tuple(trackName, eventName);
}
class PerformanceObserverWrapper : public jsi::NativeState {
@@ -30,7 +30,24 @@ void ImageShadowNode::updateStateIfNeeded() {
auto newImageSource = getImageSource();
const auto& oldImageRequestParams = savedState.getImageRequestParams();
const auto& imageProps = getConcreteProps();
const auto& newImageRequestParams = ImageRequestParams(imageProps.blurRadius);
const auto& newImageRequestParams = ImageRequestParams(
imageProps.blurRadius
#ifdef ANDROID
,
imageProps.defaultSource,
imageProps.resizeMode,
imageProps.resizeMethod,
// TODO: should we resizeMultiplier * imageSource.scale ?
imageProps.resizeMultiplier,
imageProps.shouldNotify,
imageProps.overlayColor,
imageProps.tintColor,
imageProps.fadeDuration,
imageProps.progressiveRenderingEnabled,
imageProps.loadingIndicatorSource,
imageProps.internal_analyticTag
#endif
);
if (oldImageSource == newImageSource &&
oldImageRequestParams == newImageRequestParams) {
@@ -538,9 +538,9 @@ void YogaLayoutableShadowNode::setSize(Size size) const {
auto style = yogaNode_.style();
style.setDimension(
yoga::Dimension::Width, yoga::StyleLength::points(size.width));
yoga::Dimension::Width, yoga::StyleSizeLength::points(size.width));
style.setDimension(
yoga::Dimension::Height, yoga::StyleLength::points(size.height));
yoga::Dimension::Height, yoga::StyleSizeLength::points(size.height));
yogaNode_.setStyle(style);
yogaNode_.setDirty(true);
}
@@ -631,16 +631,18 @@ void YogaLayoutableShadowNode::layoutTree(
auto ownerHeight = yogaFloatFromFloat(maximumSize.height);
yogaStyle.setMaxDimension(
yoga::Dimension::Width, yoga::StyleLength::points(maximumSize.width));
yoga::Dimension::Width, yoga::StyleSizeLength::points(maximumSize.width));
yogaStyle.setMaxDimension(
yoga::Dimension::Height, yoga::StyleLength::points(maximumSize.height));
yoga::Dimension::Height,
yoga::StyleSizeLength::points(maximumSize.height));
yogaStyle.setMinDimension(
yoga::Dimension::Width, yoga::StyleLength::points(minimumSize.width));
yoga::Dimension::Width, yoga::StyleSizeLength::points(minimumSize.width));
yogaStyle.setMinDimension(
yoga::Dimension::Height, yoga::StyleLength::points(minimumSize.height));
yoga::Dimension::Height,
yoga::StyleSizeLength::points(minimumSize.height));
auto direction =
yogaDirectionFromLayoutDirection(layoutConstraints.layoutDirection);
@@ -93,18 +93,15 @@ inline yoga::FloatOptional yogaOptionalFloatFromFloat(Float value) {
inline std::optional<Float> optionalFloatFromYogaValue(
const yoga::Style::Length& length,
std::optional<Float> base = {}) {
switch (length.unit()) {
case yoga::Unit::Undefined:
return {};
case yoga::Unit::Point:
return floatFromYogaOptionalFloat(length.value());
case yoga::Unit::Percent:
return base.has_value()
? std::optional<Float>(
base.value() * floatFromYogaOptionalFloat(length.value()))
: std::optional<Float>();
case yoga::Unit::Auto:
return {};
if (length.isPoints()) {
return floatFromYogaOptionalFloat(length.value());
} else if (length.isPercent()) {
return base.has_value()
? std::optional<Float>(
base.value() * floatFromYogaOptionalFloat(length.value()))
: std::optional<Float>();
} else {
return {};
}
}
@@ -447,6 +444,47 @@ inline void fromRawValue(
LOG(ERROR) << "Could not parse yoga::Display: " << stringValue;
}
inline void fromRawValue(
const PropsParserContext& /*context*/,
const RawValue& value,
yoga::Style::SizeLength& result) {
if (value.hasType<Float>()) {
result = yoga::StyleSizeLength::points((float)value);
return;
} else if (value.hasType<std::string>()) {
const auto stringValue = (std::string)value;
if (stringValue == "auto") {
result = yoga::StyleSizeLength::ofAuto();
return;
} else if (stringValue == "max-content") {
result = yoga::StyleSizeLength::ofMaxContent();
return;
} else if (stringValue == "stretch") {
result = yoga::StyleSizeLength::ofStretch();
return;
} else if (stringValue == "fit-content") {
result = yoga::StyleSizeLength::ofFitContent();
return;
} else {
if (stringValue.back() == '%') {
auto tryValue = folly::tryTo<float>(
std::string_view(stringValue).substr(0, stringValue.length() - 1));
if (tryValue.hasValue()) {
result = yoga::StyleSizeLength::percent(tryValue.value());
return;
}
} else {
auto tryValue = folly::tryTo<float>(stringValue);
if (tryValue.hasValue()) {
result = yoga::StyleSizeLength::points(tryValue.value());
return;
}
}
}
}
result = yoga::StyleSizeLength::undefined();
}
inline void fromRawValue(
const PropsParserContext& context,
const RawValue& value,
@@ -1376,15 +1414,36 @@ inline std::string toString(const yoga::Display& value) {
}
inline std::string toString(const yoga::Style::Length& length) {
switch (length.unit()) {
case yoga::Unit::Undefined:
return "undefined";
case yoga::Unit::Point:
return std::to_string(length.value().unwrap());
case yoga::Unit::Percent:
return std::to_string(length.value().unwrap()) + "%";
case yoga::Unit::Auto:
return "auto";
if (length.isUndefined()) {
return "undefined";
} else if (length.isAuto()) {
return "auto";
} else if (length.isPoints()) {
return std::to_string(length.value().unwrap());
} else if (length.isPercent()) {
return std::to_string(length.value().unwrap()) + "%";
} else {
return "unknown";
}
}
inline std::string toString(const yoga::Style::SizeLength& length) {
if (length.isUndefined()) {
return "undefined";
} else if (length.isAuto()) {
return "auto";
} else if (length.isPoints()) {
return std::to_string(length.value().unwrap());
} else if (length.isPercent()) {
return std::to_string(length.value().unwrap()) + "%";
} else if (length.isMaxContent()) {
return "max-content";
} else if (length.isFitContent()) {
return "fit-content";
} else if (length.isStretch()) {
return "stretch";
} else {
return "unknown";
}
}
@@ -77,8 +77,8 @@ class LayoutTest : public ::testing::Test {
auto &props = *sharedProps;
props.layoutConstraints = LayoutConstraints{{0,0}, {500, 500}};
auto &yogaStyle = props.yogaStyle;
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
return sharedProps;
})
.children({
@@ -90,8 +90,8 @@ class LayoutTest : public ::testing::Test {
auto &props = *sharedProps;
auto &yogaStyle = props.yogaStyle;
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(50));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(50));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(50));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(50));
return sharedProps;
})
.children({
@@ -105,8 +105,8 @@ class LayoutTest : public ::testing::Test {
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(10));
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(10));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(30));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(90));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(30));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(90));
if (testCase == TRANSFORM_SCALE) {
props.transform = props.transform * Transform::Scale(2, 2, 1);
@@ -138,8 +138,8 @@ class LayoutTest : public ::testing::Test {
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(10));
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(10));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(110));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(20));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(110));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(20));
return sharedProps;
})
.children({
@@ -153,8 +153,8 @@ class LayoutTest : public ::testing::Test {
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(70));
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(-50));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(30));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(60));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(30));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(60));
return sharedProps;
})
}),
@@ -168,8 +168,8 @@ class LayoutTest : public ::testing::Test {
yogaStyle.setPositionType(yoga::PositionType::Absolute);
yogaStyle.setPosition(yoga::Edge::Left, yoga::StyleLength::points(-60));
yogaStyle.setPosition(yoga::Edge::Top, yoga::StyleLength::points(50));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(70));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(20));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(70));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(20));
return sharedProps;
})
})
@@ -16,7 +16,7 @@ add_compile_options(
file(GLOB react_render_imagemanager_SRC CONFIGURE_DEPENDS
*.cpp
platform/cxx/react/renderer/imagemanager/*.cpp)
platform/android/react/renderer/imagemanager/*.cpp)
add_library(react_render_imagemanager
OBJECT
@@ -25,7 +25,7 @@ add_library(react_render_imagemanager
target_include_directories(react_render_imagemanager
PUBLIC
${REACT_COMMON_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/platform/cxx/
${CMAKE_CURRENT_SOURCE_DIR}/platform/android/
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
@@ -1,30 +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.
*/
#pragma once
#include <react/renderer/graphics/Float.h>
namespace facebook::react {
class ImageRequestParams {
public:
ImageRequestParams() = default;
ImageRequestParams(Float blurRadius) : blurRadius(blurRadius) {}
Float blurRadius{};
bool operator==(const ImageRequestParams& rhs) const {
return this->blurRadius == rhs.blurRadius;
}
bool operator!=(const ImageRequestParams& rhs) const {
return !(*this == rhs);
}
};
} // namespace facebook::react
@@ -0,0 +1,94 @@
/*
* 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.
*/
#pragma once
#include <utility>
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/Float.h>
#include <react/renderer/imagemanager/primitives.h>
namespace facebook::react {
class ImageRequestParams {
public:
ImageRequestParams() = default;
ImageRequestParams(
Float blurRadius,
ImageSource defaultSource,
ImageResizeMode resizeMode,
std::string resizeMethod,
Float resizeMultiplier,
bool shouldNotify,
SharedColor overlayColor,
SharedColor tintColor,
Float fadeDuration,
bool progressiveRenderingEnabled,
ImageSource loadingIndicatorSource,
std::string analyticTag)
: blurRadius(blurRadius),
defaultSource(std::move(defaultSource)),
resizeMode(resizeMode),
resizeMethod(std::move(resizeMethod)),
resizeMultiplier(resizeMultiplier),
shouldNotify(shouldNotify),
overlayColor(overlayColor),
tintColor(tintColor),
fadeDuration(fadeDuration),
progressiveRenderingEnabled(progressiveRenderingEnabled),
loadingIndicatorSource(std::move(loadingIndicatorSource)),
analyticTag(std::move(analyticTag)) {}
Float blurRadius{};
ImageSource defaultSource{};
ImageResizeMode resizeMode{ImageResizeMode::Stretch};
std::string resizeMethod{};
Float resizeMultiplier{};
bool shouldNotify{};
SharedColor overlayColor{};
SharedColor tintColor{};
Float fadeDuration{};
bool progressiveRenderingEnabled{};
ImageSource loadingIndicatorSource{};
std::string analyticTag{};
bool operator==(const ImageRequestParams& rhs) const {
return std::tie(
this->blurRadius,
this->defaultSource,
this->resizeMode,
this->resizeMethod,
this->resizeMultiplier,
this->shouldNotify,
this->overlayColor,
this->tintColor,
this->fadeDuration,
this->progressiveRenderingEnabled,
this->loadingIndicatorSource,
this->analyticTag) ==
std::tie(
rhs.blurRadius,
rhs.defaultSource,
rhs.resizeMode,
rhs.resizeMethod,
rhs.resizeMultiplier,
rhs.shouldNotify,
rhs.overlayColor,
rhs.tintColor,
rhs.fadeDuration,
rhs.progressiveRenderingEnabled,
rhs.loadingIndicatorSource,
rhs.analyticTag);
}
bool operator!=(const ImageRequestParams& rhs) const {
return !(*this == rhs);
}
};
} // namespace facebook::react
@@ -0,0 +1,100 @@
/*
* 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.
*/
#pragma once
#include <string>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/imagemanager/ImageRequestParams.h>
#include <react/renderer/imagemanager/primitives.h>
#include <react/renderer/mapbuffer/MapBuffer.h>
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
namespace facebook::react {
inline std::string toString(const ImageResizeMode& value) {
switch (value) {
case ImageResizeMode::Cover:
return "cover";
case ImageResizeMode::Contain:
return "contain";
case ImageResizeMode::Stretch:
return "stretch";
case ImageResizeMode::Center:
return "center";
case ImageResizeMode::Repeat:
return "repeat";
case ImageResizeMode::None:
return "none";
}
}
constexpr static MapBuffer::Key IS_KEY_URI = 0;
constexpr static MapBuffer::Key IS_KEY_DEFAULT_SRC = 1;
constexpr static MapBuffer::Key IS_KEY_RESIZE_MODE = 2;
constexpr static MapBuffer::Key IS_KEY_RESIZE_METHOD = 3;
constexpr static MapBuffer::Key IS_KEY_BLUR_RADIUS = 4;
constexpr static MapBuffer::Key IS_KEY_VIEW_WIDTH = 5;
constexpr static MapBuffer::Key IS_KEY_VIEW_HEIGHT = 6;
constexpr static MapBuffer::Key IS_KEY_RESIZE_MULTIPLIER = 7;
constexpr static MapBuffer::Key IS_KEY_SHOULD_NOTIFY_LOAD_EVENTS = 8;
constexpr static MapBuffer::Key IS_KEY_OVERLAY_COLOR = 9;
constexpr static MapBuffer::Key IS_KEY_TINT_COLOR = 10;
constexpr static MapBuffer::Key IS_KEY_FADE_DURATION = 11;
constexpr static MapBuffer::Key IS_KEY_PROGRESSIVE_RENDERING_ENABLED = 12;
constexpr static MapBuffer::Key IS_KEY_LOADING_INDICATOR_SRC = 13;
constexpr static MapBuffer::Key IS_KEY_ANALYTIC_TAG = 14;
inline void serializeImageSource(
MapBufferBuilder& builder,
const ImageSource& imageSource) {
builder.putString(IS_KEY_URI, imageSource.uri);
builder.putDouble(IS_KEY_VIEW_WIDTH, imageSource.size.width);
builder.putDouble(IS_KEY_VIEW_HEIGHT, imageSource.size.height);
}
inline void serializeImageRequestParams(
MapBufferBuilder& builder,
const ImageRequestParams& imageRequestParams) {
builder.putString(IS_KEY_DEFAULT_SRC, imageRequestParams.defaultSource.uri);
builder.putString(
IS_KEY_RESIZE_MODE, toString(imageRequestParams.resizeMode));
builder.putString(IS_KEY_RESIZE_METHOD, imageRequestParams.resizeMethod);
builder.putDouble(IS_KEY_BLUR_RADIUS, imageRequestParams.blurRadius);
builder.putDouble(
IS_KEY_RESIZE_MULTIPLIER, imageRequestParams.resizeMultiplier);
builder.putBool(
IS_KEY_SHOULD_NOTIFY_LOAD_EVENTS, imageRequestParams.shouldNotify);
if (isColorMeaningful(imageRequestParams.overlayColor)) {
builder.putInt(
IS_KEY_OVERLAY_COLOR, toAndroidRepr(imageRequestParams.overlayColor));
}
if (isColorMeaningful(imageRequestParams.tintColor)) {
builder.putInt(
IS_KEY_TINT_COLOR, toAndroidRepr(imageRequestParams.tintColor));
}
builder.putDouble(IS_KEY_FADE_DURATION, imageRequestParams.fadeDuration);
builder.putBool(
IS_KEY_PROGRESSIVE_RENDERING_ENABLED,
imageRequestParams.progressiveRenderingEnabled);
builder.putString(
IS_KEY_LOADING_INDICATOR_SRC,
imageRequestParams.loadingIndicatorSource.uri);
builder.putString(IS_KEY_ANALYTIC_TAG, imageRequestParams.analyticTag);
}
inline MapBuffer serializeImageRequest(
const ImageSource& imageSource,
const ImageRequestParams& imageRequestParams) {
auto builder = MapBufferBuilder();
serializeImageSource(builder, imageSource);
serializeImageRequestParams(builder, imageRequestParams);
return builder.build();
}
} // namespace facebook::react
@@ -87,8 +87,8 @@ class PointerEventsProcessorTest : public ::testing::Test {
listenToAllPointerEvents(props);
props.layoutConstraints = LayoutConstraints{{0,0}, {500, 500}};
auto &yogaStyle = props.yogaStyle;
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(400));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(400));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(400));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(400));
yogaStyle.setDisplay(yoga::Display::Flex);
yogaStyle.setFlexDirection(yoga::FlexDirection::Row);
yogaStyle.setAlignItems(yoga::Align::Center);
@@ -109,8 +109,8 @@ class PointerEventsProcessorTest : public ::testing::Test {
yogaStyle.setFlexDirection(yoga::FlexDirection::Column);
yogaStyle.setAlignItems(yoga::Align::FlexEnd);
yogaStyle.setJustifyContent(yoga::Justify::Center);
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(150));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(300));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(150));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(300));
return sharedProps;
})
.children({
@@ -123,8 +123,8 @@ class PointerEventsProcessorTest : public ::testing::Test {
auto &props = *sharedProps;
listenToAllPointerEvents(props);
auto &yogaStyle = props.yogaStyle;
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(100));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(100));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
return sharedProps;
})
}),
@@ -141,8 +141,8 @@ class PointerEventsProcessorTest : public ::testing::Test {
yogaStyle.setFlexDirection(yoga::FlexDirection::Column);
yogaStyle.setAlignItems(yoga::Align::FlexStart);
yogaStyle.setJustifyContent(yoga::Justify::Center);
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(150));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(300));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(150));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(300));
return sharedProps;
})
.children({
@@ -155,8 +155,8 @@ class PointerEventsProcessorTest : public ::testing::Test {
auto &props = *sharedProps;
listenToAllPointerEvents(props);
auto &yogaStyle = props.yogaStyle;
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleLength::points(100));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleLength::points(200));
yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(100));
yogaStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(200));
return sharedProps;
})
})
@@ -57,62 +57,48 @@ ReactInstance::ReactInstance(
timerManager_(std::move(timerManager)),
jsErrorHandler_(std::make_shared<JsErrorHandler>(std::move(onJsError))),
parentInspectorTarget_(parentInspectorTarget) {
RuntimeExecutor runtimeExecutor = [weakRuntime = std::weak_ptr(runtime_),
weakTimerManager =
std::weak_ptr(timerManager_),
weakJsThread =
std::weak_ptr(jsMessageQueueThread_),
jsErrorHandler =
jsErrorHandler_](auto callback) {
if (weakRuntime.expired()) {
return;
}
/**
* If a fatal error was caught while executing the main bundle, assume the
* js runtime is invalid. And stop executing any more js.
*/
if (!jsErrorHandler->isRuntimeReady() &&
jsErrorHandler->hasHandledFatalError()) {
LOG(INFO)
<< "RuntimeExecutor: Detected fatal error. Dropping work on non-js thread."
<< std::endl;
return;
}
if (auto jsThread = weakJsThread.lock()) {
jsThread->runOnQueue([jsErrorHandler,
weakRuntime,
weakTimerManager,
callback = std::move(callback)]() {
auto runtime = weakRuntime.lock();
if (!runtime) {
RuntimeExecutor runtimeExecutor =
[weakRuntime = std::weak_ptr(runtime_),
weakTimerManager = std::weak_ptr(timerManager_),
weakJsThread = std::weak_ptr(jsMessageQueueThread_),
jsErrorHandler = jsErrorHandler_](auto callback) {
if (weakRuntime.expired()) {
return;
}
jsi::Runtime& jsiRuntime = runtime->getRuntime();
SystraceSection s("ReactInstance::_runtimeExecutor[Callback]");
try {
ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread(true);
callback(jsiRuntime);
// If we have first-class support for microtasks,
// they would've been called as part of the previous callback.
if (ReactNativeFeatureFlags::disableEventLoopOnBridgeless()) {
if (auto timerManager = weakTimerManager.lock()) {
timerManager->callReactNativeMicrotasks(jsiRuntime);
if (auto jsThread = weakJsThread.lock()) {
jsThread->runOnQueue([jsErrorHandler,
weakRuntime,
weakTimerManager,
callback = std::move(callback)]() {
auto runtime = weakRuntime.lock();
if (!runtime) {
return;
}
}
} catch (jsi::JSError& originalError) {
jsErrorHandler->handleError(jsiRuntime, originalError, true);
} catch (std::exception& ex) {
jsi::JSError error(
jsiRuntime, std::string("Non-js exception: ") + ex.what());
jsErrorHandler->handleError(jsiRuntime, error, true);
jsi::Runtime& jsiRuntime = runtime->getRuntime();
SystraceSection s("ReactInstance::_runtimeExecutor[Callback]");
try {
ShadowNode::setUseRuntimeShadowNodeReferenceUpdateOnThread(true);
callback(jsiRuntime);
// If we have first-class support for microtasks,
// they would've been called as part of the previous callback.
if (ReactNativeFeatureFlags::disableEventLoopOnBridgeless()) {
if (auto timerManager = weakTimerManager.lock()) {
timerManager->callReactNativeMicrotasks(jsiRuntime);
}
}
} catch (jsi::JSError& originalError) {
jsErrorHandler->handleError(jsiRuntime, originalError, true);
} catch (std::exception& ex) {
jsi::JSError error(
jsiRuntime, std::string("Non-js exception: ") + ex.what());
jsErrorHandler->handleError(jsiRuntime, error, true);
}
});
}
});
}
};
};
if (parentInspectorTarget_) {
auto executor = parentInspectorTarget_->executorFromThis();
@@ -14,6 +14,13 @@
namespace facebook::react {
namespace {
/** Process ID for all emitted events. */
const uint64_t PID = 1000;
} // namespace
bool FuseboxTracer::isTracing() {
std::lock_guard lock(mutex_);
return tracing_;
@@ -43,34 +50,43 @@ bool FuseboxTracer::stopTracing(
}
auto traceEvents = folly::dynamic::array();
// Register "Main" process
traceEvents.push_back(folly::dynamic::object(
"args", folly::dynamic::object("name", "Main"))("cat", "__metadata")(
"name", "process_name")("ph", "M")("pid", PID)("tid", 0)("ts", 0));
// Register "Timings" track
// NOTE: This is a hack to make the trace viewer show a "Timings" track
// adjacent to custom tracks in our current build of Chrome DevTools.
// In future, we should align events exactly.
traceEvents.push_back(folly::dynamic::object(
"args", folly::dynamic::object("name", "Timings"))("cat", "__metadata")(
"name", "thread_name")("ph", "M")("pid", PID)("tid", 1000)("ts", 0));
auto savedBuffer = std::move(buffer_);
buffer_.clear();
std::unordered_map<std::string, uint64_t> trackIdMap;
uint64_t nextTrack = 1000;
// Name the main process. Only one process is supported currently.
traceEvents.push_back(folly::dynamic::object(
"args", folly::dynamic::object("name", "Main App"))("cat", "__metadata")(
"name", "process_name")("ph", "M")("pid", 1000)("tid", 0)("ts", 0));
uint64_t nextTrack = 1001;
for (auto& event : savedBuffer) {
if (!trackIdMap.contains(event.track)) {
// For events with a custom track name, register track
if (event.track.length() && !trackIdMap.contains(event.track)) {
auto trackId = nextTrack++;
trackIdMap[event.track] = trackId;
// New track
traceEvents.push_back(folly::dynamic::object(
"args", folly::dynamic::object("name", event.track))(
"cat", "__metadata")("name", "thread_name")("ph", "M")("pid", 1000)(
"cat", "__metadata")("name", "thread_name")("ph", "M")("pid", PID)(
"tid", trackId)("ts", 0));
}
auto trackId = trackIdMap[event.track];
// New event
auto trackId =
trackIdMap.contains(event.track) ? trackIdMap[event.track] : 1000;
// Emit "blink.user_timing" trace event
traceEvents.push_back(folly::dynamic::object(
"args", folly::dynamic::object())("cat", "react.native")(
"args", folly::dynamic::object())("cat", "blink.user_timing")(
"dur", (event.end - event.start) * 1000)("name", event.name)("ph", "X")(
"ts", event.start * 1000)("pid", 1000)("tid", trackId));
"ts", event.start * 1000)("pid", PID)("tid", trackId));
if (traceEvents.size() >= 1000) {
resultCallback(traceEvents);
@@ -88,13 +104,13 @@ void FuseboxTracer::addEvent(
const std::string_view& name,
uint64_t start,
uint64_t end,
const std::string_view& track) {
const std::optional<std::string_view>& track) {
std::lock_guard<std::mutex> lock(mutex_);
if (!tracing_) {
return;
}
buffer_.push_back(
BufferEvent{start, end, std::string(name), std::string(track)});
buffer_.push_back(BufferEvent{
start, end, std::string(name), std::string(track.value_or(""))});
}
bool FuseboxTracer::stopTracingAndWriteToFile(const std::string& path) {
@@ -7,10 +7,12 @@
#pragma once
#include <functional>
#include <vector>
#include "folly/dynamic.h"
#include <functional>
#include <optional>
#include <vector>
namespace facebook::react {
struct BufferEvent {
@@ -38,7 +40,7 @@ class FuseboxTracer {
const std::string_view& name,
uint64_t start,
uint64_t end,
const std::string_view& track);
const std::optional<std::string_view>& track);
static FuseboxTracer& getFuseboxTracer();
@@ -14,15 +14,33 @@
#endif
#include <chrono>
#ifdef WITH_PERFETTO
#include "ReactPerfetto.h"
#endif
namespace facebook::react {
#ifdef WITH_PERFETTO
namespace {
const std::string PERFETTO_DEFAULT_TRACK_NAME = "# Web Performance";
const std::string PERFETTO_TRACK_NAME_PREFIX = "# Web Performance: ";
std::string toPerfettoTrackName(
const std::optional<std::string_view>& trackName) {
return trackName.has_value()
? PERFETTO_TRACK_NAME_PREFIX + std::string(trackName.value())
: PERFETTO_DEFAULT_TRACK_NAME;
}
} // namespace
#endif
/* static */ void ReactPerfLogger::measure(
const std::string_view& eventName,
double startTime,
double endTime,
const std::string_view& trackName) {
const std::optional<std::string_view>& trackName) {
#ifdef HAS_FUSEBOX
FuseboxTracer::getFuseboxTracer().addEvent(
eventName, (uint64_t)startTime, (uint64_t)endTime, trackName);
@@ -30,7 +48,7 @@ namespace facebook::react {
#ifdef WITH_PERFETTO
if (TRACE_EVENT_CATEGORY_ENABLED("react-native")) {
auto track = getPerfettoWebPerfTrackAsync(std::string(trackName));
auto track = getPerfettoWebPerfTrackAsync(toPerfettoTrackName(trackName));
TRACE_EVENT_BEGIN(
"react-native",
perfetto::DynamicString(eventName.data(), eventName.size()),
@@ -45,7 +63,7 @@ namespace facebook::react {
/* static */ void ReactPerfLogger::mark(
const std::string_view& eventName,
double startTime,
const std::string_view& trackName) {
const std::optional<std::string_view>& trackName) {
// TODO(T203046480) Support mark in FuseboxTracer
#ifdef WITH_PERFETTO
@@ -53,7 +71,7 @@ namespace facebook::react {
TRACE_EVENT_INSTANT(
"react-native",
perfetto::DynamicString(eventName.data(), eventName.size()),
getPerfettoWebPerfTrackSync(std::string(trackName)),
getPerfettoWebPerfTrackSync(toPerfettoTrackName(trackName)),
performanceNowToPerfettoTraceTime(startTime));
}
#endif
@@ -62,4 +80,5 @@ namespace facebook::react {
/* static */ double ReactPerfLogger::performanceNow() {
return chronoToDOMHighResTimeStamp(std::chrono::steady_clock::now());
}
} // namespace facebook::react
@@ -8,26 +8,30 @@
#pragma once
#include <reactperflogger/ReactPerfettoCategories.h>
#include <optional>
#include <string>
namespace facebook::react {
/**
* An internal interface for logging performance events to configured React
* Native performance tools, such as Perfetto or React Native DevTools.
*
* Approximates https://w3c.github.io/user-timing/.
*/
class ReactPerfLogger {
public:
static void mark(
const std::string_view& eventName,
double startTime,
const std::string_view& trackName);
const std::optional<std::string_view>& trackName);
/**
* This accepts performance events that should go to internal tracing
* frameworks like Perfetto, and should go to DevTools like Fusebox.
*/
static void measure(
const std::string_view& eventName,
double startTime,
double endTime,
const std::string_view& trackName);
const std::optional<std::string_view>& trackName);
static double performanceNow();
};
@@ -245,6 +245,12 @@ const char* YGUnitToString(const YGUnit value) {
return "percent";
case YGUnitAuto:
return "auto";
case YGUnitMaxContent:
return "max-content";
case YGUnitFitContent:
return "fit-content";
case YGUnitStretch:
return "stretch";
}
return "unknown";
}
@@ -131,7 +131,10 @@ YG_ENUM_DECL(
YGUnitUndefined,
YGUnitPoint,
YGUnitPercent,
YGUnitAuto)
YGUnitAuto,
YGUnitMaxContent,
YGUnitFitContent,
YGUnitStretch)
YG_ENUM_DECL(
YGWrap,
@@ -177,19 +177,34 @@ float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) {
void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleLength::points(flexBasis));
node, StyleSizeLength::points(flexBasis));
}
void YGNodeStyleSetFlexBasisPercent(
const YGNodeRef node,
const float flexBasisPercent) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleLength::percent(flexBasisPercent));
node, StyleSizeLength::percent(flexBasisPercent));
}
void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleLength::ofAuto());
node, StyleSizeLength::ofAuto());
}
void YGNodeStyleSetFlexBasisMaxContent(const YGNodeRef node) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleSizeLength::ofMaxContent());
}
void YGNodeStyleSetFlexBasisFitContent(const YGNodeRef node) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleSizeLength::ofFitContent());
}
void YGNodeStyleSetFlexBasisStretch(const YGNodeRef node) {
updateStyle<&Style::flexBasis, &Style::setFlexBasis>(
node, StyleSizeLength::ofStretch());
}
YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) {
@@ -308,17 +323,32 @@ YGBoxSizing YGNodeStyleGetBoxSizing(const YGNodeConstRef node) {
void YGNodeStyleSetWidth(YGNodeRef node, float points) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleLength::points(points));
node, Dimension::Width, StyleSizeLength::points(points));
}
void YGNodeStyleSetWidthPercent(YGNodeRef node, float percent) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleLength::percent(percent));
node, Dimension::Width, StyleSizeLength::percent(percent));
}
void YGNodeStyleSetWidthAuto(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleLength::ofAuto());
node, Dimension::Width, StyleSizeLength::ofAuto());
}
void YGNodeStyleSetWidthMaxContent(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleSizeLength::ofMaxContent());
}
void YGNodeStyleSetWidthFitContent(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleSizeLength::ofFitContent());
}
void YGNodeStyleSetWidthStretch(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Width, StyleSizeLength::ofStretch());
}
YGValue YGNodeStyleGetWidth(YGNodeConstRef node) {
@@ -327,17 +357,32 @@ YGValue YGNodeStyleGetWidth(YGNodeConstRef node) {
void YGNodeStyleSetHeight(YGNodeRef node, float points) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleLength::points(points));
node, Dimension::Height, StyleSizeLength::points(points));
}
void YGNodeStyleSetHeightPercent(YGNodeRef node, float percent) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleLength::percent(percent));
node, Dimension::Height, StyleSizeLength::percent(percent));
}
void YGNodeStyleSetHeightAuto(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleLength::ofAuto());
node, Dimension::Height, StyleSizeLength::ofAuto());
}
void YGNodeStyleSetHeightMaxContent(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleSizeLength::ofMaxContent());
}
void YGNodeStyleSetHeightFitContent(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleSizeLength::ofFitContent());
}
void YGNodeStyleSetHeightStretch(YGNodeRef node) {
updateStyle<&Style::dimension, &Style::setDimension>(
node, Dimension::Height, StyleSizeLength::ofStretch());
}
YGValue YGNodeStyleGetHeight(YGNodeConstRef node) {
@@ -346,12 +391,27 @@ YGValue YGNodeStyleGetHeight(YGNodeConstRef node) {
void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Width, StyleLength::points(minWidth));
node, Dimension::Width, StyleSizeLength::points(minWidth));
}
void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Width, StyleLength::percent(minWidth));
node, Dimension::Width, StyleSizeLength::percent(minWidth));
}
void YGNodeStyleSetMinWidthMaxContent(const YGNodeRef node) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Width, StyleSizeLength::ofMaxContent());
}
void YGNodeStyleSetMinWidthFitContent(const YGNodeRef node) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Width, StyleSizeLength::ofFitContent());
}
void YGNodeStyleSetMinWidthStretch(const YGNodeRef node) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Width, StyleSizeLength::ofStretch());
}
YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) {
@@ -360,14 +420,29 @@ YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) {
void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Height, StyleLength::points(minHeight));
node, Dimension::Height, StyleSizeLength::points(minHeight));
}
void YGNodeStyleSetMinHeightPercent(
const YGNodeRef node,
const float minHeight) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Height, StyleLength::percent(minHeight));
node, Dimension::Height, StyleSizeLength::percent(minHeight));
}
void YGNodeStyleSetMinHeightMaxContent(const YGNodeRef node) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Height, StyleSizeLength::ofMaxContent());
}
void YGNodeStyleSetMinHeightFitContent(const YGNodeRef node) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Height, StyleSizeLength::ofFitContent());
}
void YGNodeStyleSetMinHeightStretch(const YGNodeRef node) {
updateStyle<&Style::minDimension, &Style::setMinDimension>(
node, Dimension::Height, StyleSizeLength::ofStretch());
}
YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) {
@@ -376,12 +451,27 @@ YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) {
void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Width, StyleLength::points(maxWidth));
node, Dimension::Width, StyleSizeLength::points(maxWidth));
}
void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Width, StyleLength::percent(maxWidth));
node, Dimension::Width, StyleSizeLength::percent(maxWidth));
}
void YGNodeStyleSetMaxWidthMaxContent(const YGNodeRef node) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Width, StyleSizeLength::ofMaxContent());
}
void YGNodeStyleSetMaxWidthFitContent(const YGNodeRef node) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Width, StyleSizeLength::ofFitContent());
}
void YGNodeStyleSetMaxWidthStretch(const YGNodeRef node) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Width, StyleSizeLength::ofStretch());
}
YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) {
@@ -390,14 +480,29 @@ YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) {
void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Height, StyleLength::points(maxHeight));
node, Dimension::Height, StyleSizeLength::points(maxHeight));
}
void YGNodeStyleSetMaxHeightPercent(
const YGNodeRef node,
const float maxHeight) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Height, StyleLength::percent(maxHeight));
node, Dimension::Height, StyleSizeLength::percent(maxHeight));
}
void YGNodeStyleSetMaxHeightMaxContent(const YGNodeRef node) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Height, StyleSizeLength::ofMaxContent());
}
void YGNodeStyleSetMaxHeightFitContent(const YGNodeRef node) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Height, StyleSizeLength::ofFitContent());
}
void YGNodeStyleSetMaxHeightStretch(const YGNodeRef node) {
updateStyle<&Style::maxDimension, &Style::setMaxDimension>(
node, Dimension::Height, StyleSizeLength::ofStretch());
}
YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) {
@@ -64,6 +64,9 @@ YG_EXPORT float YGNodeStyleGetFlexShrink(YGNodeConstRef node);
YG_EXPORT void YGNodeStyleSetFlexBasis(YGNodeRef node, float flexBasis);
YG_EXPORT void YGNodeStyleSetFlexBasisPercent(YGNodeRef node, float flexBasis);
YG_EXPORT void YGNodeStyleSetFlexBasisAuto(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetFlexBasisMaxContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetFlexBasisFitContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetFlexBasisStretch(YGNodeRef node);
YG_EXPORT YGValue YGNodeStyleGetFlexBasis(YGNodeConstRef node);
YG_EXPORT void
@@ -101,27 +104,45 @@ YG_EXPORT YGBoxSizing YGNodeStyleGetBoxSizing(YGNodeConstRef node);
YG_EXPORT void YGNodeStyleSetWidth(YGNodeRef node, float width);
YG_EXPORT void YGNodeStyleSetWidthPercent(YGNodeRef node, float width);
YG_EXPORT void YGNodeStyleSetWidthAuto(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetWidthMaxContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetWidthFitContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetWidthStretch(YGNodeRef node);
YG_EXPORT YGValue YGNodeStyleGetWidth(YGNodeConstRef node);
YG_EXPORT void YGNodeStyleSetHeight(YGNodeRef node, float height);
YG_EXPORT void YGNodeStyleSetHeightPercent(YGNodeRef node, float height);
YG_EXPORT void YGNodeStyleSetHeightAuto(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetHeightMaxContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetHeightFitContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetHeightStretch(YGNodeRef node);
YG_EXPORT YGValue YGNodeStyleGetHeight(YGNodeConstRef node);
YG_EXPORT void YGNodeStyleSetMinWidth(YGNodeRef node, float minWidth);
YG_EXPORT void YGNodeStyleSetMinWidthPercent(YGNodeRef node, float minWidth);
YG_EXPORT void YGNodeStyleSetMinWidthMaxContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetMinWidthFitContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetMinWidthStretch(YGNodeRef node);
YG_EXPORT YGValue YGNodeStyleGetMinWidth(YGNodeConstRef node);
YG_EXPORT void YGNodeStyleSetMinHeight(YGNodeRef node, float minHeight);
YG_EXPORT void YGNodeStyleSetMinHeightPercent(YGNodeRef node, float minHeight);
YG_EXPORT void YGNodeStyleSetMinHeightMaxContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetMinHeightFitContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetMinHeightStretch(YGNodeRef node);
YG_EXPORT YGValue YGNodeStyleGetMinHeight(YGNodeConstRef node);
YG_EXPORT void YGNodeStyleSetMaxWidth(YGNodeRef node, float maxWidth);
YG_EXPORT void YGNodeStyleSetMaxWidthPercent(YGNodeRef node, float maxWidth);
YG_EXPORT void YGNodeStyleSetMaxWidthMaxContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetMaxWidthFitContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetMaxWidthStretch(YGNodeRef node);
YG_EXPORT YGValue YGNodeStyleGetMaxWidth(YGNodeConstRef node);
YG_EXPORT void YGNodeStyleSetMaxHeight(YGNodeRef node, float maxHeight);
YG_EXPORT void YGNodeStyleSetMaxHeightPercent(YGNodeRef node, float maxHeight);
YG_EXPORT void YGNodeStyleSetMaxHeightMaxContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetMaxHeightFitContent(YGNodeRef node);
YG_EXPORT void YGNodeStyleSetMaxHeightStretch(YGNodeRef node);
YG_EXPORT YGValue YGNodeStyleGetMaxHeight(YGNodeConstRef node);
YG_EXPORT void YGNodeStyleSetAspectRatio(YGNodeRef node, float aspectRatio);
@@ -65,6 +65,9 @@ inline bool operator==(const YGValue& lhs, const YGValue& rhs) {
switch (lhs.unit) {
case YGUnitUndefined:
case YGUnitAuto:
case YGUnitFitContent:
case YGUnitMaxContent:
case YGUnitStretch:
return true;
case YGUnitPoint:
case YGUnitPercent:
@@ -741,7 +741,7 @@ static float distributeFreeSpaceSecondPass(
marginCross;
const bool isLoosePercentageMeasurement =
currentLineChild->getProcessedDimension(dimension(crossAxis))
.unit() == Unit::Percent &&
.isPercent() &&
sizingModeCrossDim != SizingMode::StretchFit;
childCrossSizingMode =
yoga::isUndefined(childCrossSize) || isLoosePercentageMeasurement
@@ -20,11 +20,14 @@ enum class Unit : uint8_t {
Point = YGUnitPoint,
Percent = YGUnitPercent,
Auto = YGUnitAuto,
MaxContent = YGUnitMaxContent,
FitContent = YGUnitFitContent,
Stretch = YGUnitStretch,
};
template <>
constexpr int32_t ordinalCount<Unit>() {
return 4;
return 7;
}
constexpr Unit scopedEnum(YGUnit unscoped) {
@@ -314,16 +314,16 @@ void Node::setPosition(
crossAxisTrailingEdge);
}
Style::Length Node::processFlexBasis() const {
Style::Length flexBasis = style_.flexBasis();
if (flexBasis.unit() != Unit::Auto && flexBasis.unit() != Unit::Undefined) {
Style::SizeLength Node::processFlexBasis() const {
Style::SizeLength flexBasis = style_.flexBasis();
if (!flexBasis.isAuto() && !flexBasis.isUndefined()) {
return flexBasis;
}
if (style_.flex().isDefined() && style_.flex().unwrap() > 0.0f) {
return config_->useWebDefaults() ? StyleLength::ofAuto()
: StyleLength::points(0);
return config_->useWebDefaults() ? StyleSizeLength::ofAuto()
: StyleSizeLength::points(0);
}
return StyleLength::ofAuto();
return StyleSizeLength::ofAuto();
}
FloatOptional Node::resolveFlexBasis(
@@ -172,7 +172,7 @@ class YG_EXPORT Node : public ::YGNode {
return isDirty_;
}
Style::Length getProcessedDimension(Dimension dimension) const {
Style::SizeLength getProcessedDimension(Dimension dimension) const {
return processedDimensions_[static_cast<size_t>(dimension)];
}
@@ -268,7 +268,7 @@ class YG_EXPORT Node : public ::YGNode {
void setPosition(Direction direction, float ownerWidth, float ownerHeight);
// Other methods
Style::Length processFlexBasis() const;
Style::SizeLength processFlexBasis() const;
FloatOptional resolveFlexBasis(
Direction direction,
FlexDirection flexDirection,
@@ -322,8 +322,8 @@ class YG_EXPORT Node : public ::YGNode {
Node* owner_ = nullptr;
std::vector<Node*> children_;
const Config* config_;
std::array<Style::Length, 2> processedDimensions_{
{StyleLength::undefined(), StyleLength::undefined()}};
std::array<Style::SizeLength, 2> processedDimensions_{
{StyleSizeLength::undefined(), StyleSizeLength::undefined()}};
};
inline Node* resolveRef(const YGNodeRef ref) {
@@ -30,6 +30,7 @@
#include <yoga/enums/Wrap.h>
#include <yoga/numeric/FloatOptional.h>
#include <yoga/style/StyleLength.h>
#include <yoga/style/StyleSizeLength.h>
#include <yoga/style/StyleValuePool.h>
namespace facebook::yoga {
@@ -37,6 +38,7 @@ namespace facebook::yoga {
class YG_EXPORT Style {
public:
using Length = StyleLength;
using SizeLength = StyleSizeLength;
static constexpr float DefaultFlexGrow = 0.0f;
static constexpr float DefaultFlexShrink = 0.0f;
@@ -133,10 +135,10 @@ class YG_EXPORT Style {
pool_.store(flexShrink_, value);
}
Style::Length flexBasis() const {
return pool_.getLength(flexBasis_);
Style::SizeLength flexBasis() const {
return pool_.getSize(flexBasis_);
}
void setFlexBasis(Style::Length value) {
void setFlexBasis(Style::SizeLength value) {
pool_.store(flexBasis_, value);
}
@@ -175,17 +177,17 @@ class YG_EXPORT Style {
pool_.store(gap_[yoga::to_underlying(gutter)], value);
}
Style::Length dimension(Dimension axis) const {
return pool_.getLength(dimensions_[yoga::to_underlying(axis)]);
Style::SizeLength dimension(Dimension axis) const {
return pool_.getSize(dimensions_[yoga::to_underlying(axis)]);
}
void setDimension(Dimension axis, Style::Length value) {
void setDimension(Dimension axis, Style::SizeLength value) {
pool_.store(dimensions_[yoga::to_underlying(axis)], value);
}
Style::Length minDimension(Dimension axis) const {
return pool_.getLength(minDimensions_[yoga::to_underlying(axis)]);
Style::SizeLength minDimension(Dimension axis) const {
return pool_.getSize(minDimensions_[yoga::to_underlying(axis)]);
}
void setMinDimension(Dimension axis, Style::Length value) {
void setMinDimension(Dimension axis, Style::SizeLength value) {
pool_.store(minDimensions_[yoga::to_underlying(axis)], value);
}
@@ -207,10 +209,10 @@ class YG_EXPORT Style {
: FloatOptional{0.0});
}
Style::Length maxDimension(Dimension axis) const {
return pool_.getLength(maxDimensions_[yoga::to_underlying(axis)]);
Style::SizeLength maxDimension(Dimension axis) const {
return pool_.getSize(maxDimensions_[yoga::to_underlying(axis)]);
}
void setMaxDimension(Dimension axis, Style::Length value) {
void setMaxDimension(Dimension axis, Style::SizeLength value) {
pool_.store(maxDimensions_[yoga::to_underlying(axis)], value);
}
@@ -19,13 +19,11 @@ namespace facebook::yoga {
* 3. A CSS <length-percentage> value:
* a. <length> value (e.g. 10px)
* b. <percentage> value of a reference <length>
* 4. (soon) A math function which returns a <length-percentage> value
*
* References:
* 1. https://www.w3.org/TR/css-values-4/#lengths
* 2. https://www.w3.org/TR/css-values-4/#percentage-value
* 3. https://www.w3.org/TR/css-values-4/#mixed-percentages
* 4. https://www.w3.org/TR/css-values-4/#math
*/
class StyleLength {
public:
@@ -59,6 +57,14 @@ class StyleLength {
return unit_ == Unit::Undefined;
}
constexpr bool isPoints() const {
return unit_ == Unit::Point;
}
constexpr bool isPercent() const {
return unit_ == Unit::Percent;
}
constexpr bool isDefined() const {
return !isUndefined();
}
@@ -67,10 +73,6 @@ class StyleLength {
return value_;
}
constexpr Unit unit() const {
return unit_;
}
constexpr FloatOptional resolve(float referenceLength) {
switch (unit_) {
case Unit::Point:
@@ -90,6 +92,11 @@ class StyleLength {
return value_ == rhs.value_ && unit_ == rhs.unit_;
}
constexpr bool inexactEquals(const StyleLength& other) const {
return unit_ == other.unit_ &&
facebook::yoga::inexactEquals(value_, other.value_);
}
private:
// We intentionally do not allow direct construction using value and unit, to
// avoid invalid, or redundant combinations.
@@ -101,7 +108,7 @@ class StyleLength {
};
inline bool inexactEquals(const StyleLength& a, const StyleLength& b) {
return a.unit() == b.unit() && inexactEquals(a.value(), b.value());
return a.inexactEquals(b);
}
} // namespace facebook::yoga
@@ -0,0 +1,139 @@
/*
* 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.
*/
#pragma once
#include <yoga/enums/Unit.h>
#include <yoga/numeric/FloatOptional.h>
namespace facebook::yoga {
/**
* This class represents a CSS Value for sizes (e.g. width, height, min-width,
* etc.). It may be one of:
* 1. Undefined
* 2. A keyword (e.g. auto, max-content, stretch, etc.)
* 3. A CSS <length-percentage> value:
* a. <length> value (e.g. 10px)
* b. <percentage> value of a reference <length>
*
* References:
* 1. https://www.w3.org/TR/css-values-4/#lengths
* 2. https://www.w3.org/TR/css-values-4/#percentage-value
* 3. https://www.w3.org/TR/css-values-4/#mixed-percentages
*/
class StyleSizeLength {
public:
constexpr StyleSizeLength() = default;
constexpr static StyleSizeLength points(float value) {
return yoga::isUndefined(value) || yoga::isinf(value)
? undefined()
: StyleSizeLength{FloatOptional{value}, Unit::Point};
}
constexpr static StyleSizeLength percent(float value) {
return yoga::isUndefined(value) || yoga::isinf(value)
? undefined()
: StyleSizeLength{FloatOptional{value}, Unit::Percent};
}
constexpr static StyleSizeLength ofAuto() {
return StyleSizeLength{{}, Unit::Auto};
}
constexpr static StyleSizeLength ofMaxContent() {
return StyleSizeLength{{}, Unit::MaxContent};
}
constexpr static StyleSizeLength ofFitContent() {
return StyleSizeLength{{}, Unit::FitContent};
}
constexpr static StyleSizeLength ofStretch() {
return StyleSizeLength{{}, Unit::Stretch};
}
constexpr static StyleSizeLength undefined() {
return StyleSizeLength{{}, Unit::Undefined};
}
constexpr bool isAuto() const {
return unit_ == Unit::Auto;
}
constexpr bool isMaxContent() const {
return unit_ == Unit::MaxContent;
}
constexpr bool isFitContent() const {
return unit_ == Unit::FitContent;
}
constexpr bool isStretch() const {
return unit_ == Unit::Stretch;
}
constexpr bool isUndefined() const {
return unit_ == Unit::Undefined;
}
constexpr bool isDefined() const {
return !isUndefined();
}
constexpr bool isPoints() const {
return unit_ == Unit::Point;
}
constexpr bool isPercent() const {
return unit_ == Unit::Percent;
}
constexpr FloatOptional value() const {
return value_;
}
constexpr FloatOptional resolve(float referenceLength) {
switch (unit_) {
case Unit::Point:
return value_;
case Unit::Percent:
return FloatOptional{value_.unwrap() * referenceLength * 0.01f};
default:
return FloatOptional{};
}
}
explicit constexpr operator YGValue() const {
return YGValue{value_.unwrap(), unscopedEnum(unit_)};
}
constexpr bool operator==(const StyleSizeLength& rhs) const {
return value_ == rhs.value_ && unit_ == rhs.unit_;
}
constexpr bool inexactEquals(const StyleSizeLength& other) const {
return unit_ == other.unit_ &&
facebook::yoga::inexactEquals(value_, other.value_);
}
private:
// We intentionally do not allow direct construction using value and unit, to
// avoid invalid, or redundant combinations.
constexpr StyleSizeLength(FloatOptional value, Unit unit)
: value_(value), unit_(unit) {}
FloatOptional value_{};
Unit unit_{Unit::Undefined};
};
inline bool inexactEquals(const StyleSizeLength& a, const StyleSizeLength& b) {
return a.inexactEquals(b);
}
} // namespace facebook::yoga
@@ -62,8 +62,16 @@ class StyleValueHandle {
Percent,
Number,
Auto,
Keyword
};
// Intentionally leaving out auto as a fast path
enum class Keyword : uint8_t { MaxContent, FitContent, Stretch };
constexpr bool isKeyword(Keyword keyword) const {
return type() == Type::Keyword && value() == static_cast<uint16_t>(keyword);
}
constexpr Type type() const {
return static_cast<Type>(repr_ & kHandleTypeMask);
}
@@ -13,6 +13,7 @@
#include <yoga/numeric/FloatOptional.h>
#include <yoga/style/SmallValueBuffer.h>
#include <yoga/style/StyleLength.h>
#include <yoga/style/StyleSizeLength.h>
#include <yoga/style/StyleValueHandle.h>
namespace facebook::yoga {
@@ -32,13 +33,30 @@ class StyleValuePool {
} else if (length.isAuto()) {
handle.setType(StyleValueHandle::Type::Auto);
} else {
auto type = length.unit() == Unit::Point
? StyleValueHandle::Type::Point
: StyleValueHandle::Type::Percent;
auto type = length.isPoints() ? StyleValueHandle::Type::Point
: StyleValueHandle::Type::Percent;
storeValue(handle, length.value().unwrap(), type);
}
}
void store(StyleValueHandle& handle, StyleSizeLength sizeValue) {
if (sizeValue.isUndefined()) {
handle.setType(StyleValueHandle::Type::Undefined);
} else if (sizeValue.isAuto()) {
handle.setType(StyleValueHandle::Type::Auto);
} else if (sizeValue.isMaxContent()) {
storeKeyword(handle, StyleValueHandle::Keyword::MaxContent);
} else if (sizeValue.isStretch()) {
storeKeyword(handle, StyleValueHandle::Keyword::Stretch);
} else if (sizeValue.isFitContent()) {
storeKeyword(handle, StyleValueHandle::Keyword::FitContent);
} else {
auto type = sizeValue.isPoints() ? StyleValueHandle::Type::Point
: StyleValueHandle::Type::Percent;
storeValue(handle, sizeValue.value().unwrap(), type);
}
}
void store(StyleValueHandle& handle, FloatOptional number) {
if (number.isUndefined()) {
handle.setType(StyleValueHandle::Type::Undefined);
@@ -66,6 +84,31 @@ class StyleValuePool {
}
}
StyleSizeLength getSize(StyleValueHandle handle) const {
if (handle.isUndefined()) {
return StyleSizeLength::undefined();
} else if (handle.isAuto()) {
return StyleSizeLength::ofAuto();
} else if (handle.isKeyword(StyleValueHandle::Keyword::MaxContent)) {
return StyleSizeLength::ofMaxContent();
} else if (handle.isKeyword(StyleValueHandle::Keyword::FitContent)) {
return StyleSizeLength::ofFitContent();
} else if (handle.isKeyword(StyleValueHandle::Keyword::Stretch)) {
return StyleSizeLength::ofStretch();
} else {
assert(
handle.type() == StyleValueHandle::Type::Point ||
handle.type() == StyleValueHandle::Type::Percent);
float value = (handle.isValueIndexed())
? std::bit_cast<float>(buffer_.get32(handle.value()))
: unpackInlineInteger(handle.value());
return handle.type() == StyleValueHandle::Type::Point
? StyleSizeLength::points(value)
: StyleSizeLength::percent(value);
}
}
FloatOptional getNumber(StyleValueHandle handle) const {
if (handle.isUndefined()) {
return FloatOptional{};
@@ -98,6 +141,20 @@ class StyleValuePool {
}
}
void storeKeyword(
StyleValueHandle& handle,
StyleValueHandle::Keyword keyword) {
handle.setType(StyleValueHandle::Type::Keyword);
if (handle.isValueIndexed()) {
auto newIndex =
buffer_.replace(handle.value(), static_cast<uint32_t>(keyword));
handle.setValue(newIndex);
} else {
handle.setValue(static_cast<uint16_t>(keyword));
}
}
static constexpr bool isIntegerPackable(float f) {
constexpr uint16_t kMaxInlineAbsValue = (1 << 11) - 1;
+3 -2
View File
@@ -300,9 +300,10 @@ async function testRNTestProject(
'reactNativeArchitectures=arm64-v8a',
'android/gradle.properties',
);
const hermesEnabled = (await argv).hermes === true;
// Update gradle properties to set Hermes as false
if (argv.hermes == null) {
if (!hermesEnabled) {
sed(
'-i',
'hermesEnabled=true',
@@ -317,7 +318,7 @@ async function testRNTestProject(
exec('bundle install');
exec(
`HERMES_ENGINE_TARBALL_PATH=${hermesPath} USE_HERMES=${
argv.hermes === true ? 1 : 0
hermesEnabled ? 1 : 0
} bundle exec pod install --ansi`,
);
@@ -11,7 +11,6 @@
'use strict';
const chalk = require('chalk');
const {execSync: exec} = require('child_process');
const fetch = require('node-fetch');
@@ -31,18 +30,6 @@ type WorkflowRun = {
url: string,
created_at: string,
conclusion: "success" | "failure" | "neutral" | "cancelled" | "skipped" | "timed_out" | "action_required" | null,
head_commit: {
author: {
name: string,
},
message: string,
...
};
triggering_actor: {
login: string,
...
};
run_started_at: string,
};
@@ -115,13 +102,6 @@ async function _getArtifacts(run_id /*: number */) /*: Promise<Artifacts> */ {
return body;
}
function quote(text /*: string*/, prefix /*: string */ = ' > ') {
return text
.split('\n')
.map(line => prefix + line)
.join('\n');
}
// === Public Interface === //
async function initialize(
ciToken /*: string */,
@@ -169,21 +149,6 @@ async function initialize(
) ?? workflow;
}
const commit = workflow.head_commit;
const hours =
(new Date().getTime() - new Date(workflow.run_started_at).getTime()) /
(60 * 60 * 1000);
const started_by = workflow.triggering_actor.login;
console.log(
chalk.green(`The artifact being used is from a workflow started ${chalk.bold.magentaBright(hours.toFixed(0))} hours ago by ${chalk.bold.magentaBright(started_by)}:
Author: ${chalk.bold(commit.author.name)}
Message:
${chalk.magentaBright(quote(commit.message))}
`),
);
artifacts = await _getArtifacts(workflow.id);
}