Commit Graph
685 Commits
Author SHA1 Message Date
Xin Chen 59476d06f3 Back out "Remove useOverflowInset flag as we rolled out 100% to public for over three months"
Summary:
Original commit changeset: 77da78a29270

Original Phabricator Diff: D36990986 (https://github.com/facebook/react-native/commit/df80ed40c7cde6cf81a0974d78ef0a7cfcf19e5c)

Reviewed By: mdvacca

Differential Revision: D37074879

fbshipit-source-id: 82668c90d50b4cc6c53986aa9450eea7934402b3
2022-06-10 13:21:38 -07:00
Xin Chen df80ed40c7 Remove useOverflowInset flag as we rolled out 100% to public for over three months
Summary:
Remove overflow inset optimization flags as they've been rolled out 100% to public.

Changelog:
[Android][Internal] - Clean up feature flags for overflowInset

Reviewed By: nlutsenko

Differential Revision: D36990986

fbshipit-source-id: 77da78a2927034893f25937c2ccbd0b53e08031d
2022-06-09 12:30:14 -07:00
Xin Chen 472e0e4a3c Make sure we only queue events when event emitter is null
Summary:
This diff adds an assertion to make sure the pending events are enqueued only when the event emitter is null. This is to avoid unexpected workflow when we queue events but we should just dispatch them.

Changelog:
[Android][Internal] - Make sure we only queue events when event emitter is null

Reviewed By: javache

Differential Revision: D36916482

fbshipit-source-id: fff305615b302ece26bc2482c826b74de4f70266
2022-06-08 14:19:01 -07:00
Xin Chen ea7c9f2ad9 Fix edge case when we enqueue a pending event to views on stopped surface
Summary:
This diff address an edge case when the pending events are enqueued when the surface is stopped. In this case we will reset map that holds view state to null, which will cause NPE.

Changelog:
[Android][Fixed] - Fix edge case when we enqueue a pending event to views on stopped surface

Reviewed By: javache, gorodscy

Differential Revision: D36912786

fbshipit-source-id: 3ae5a4b08a0a6bf55538d69ac80a101c2c3d899a
2022-06-06 15:44:13 -07:00
Joshua Gross a68dca3c46 Clean up View Recycling
Summary:
Followups to View Recycling diffs to improve things / clean up things a bit. This also fixes memory warnings which were not hooked up before.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D36707792

fbshipit-source-id: 410e70bf0eeec5569566138af547e1601394d0e6
2022-05-31 14:34:33 -07:00
Joshua Gross 7b778fbebb Prototype View recycling for View
Summary:
Prototype of View Recycling for View + generic APIs.

Changelog: [Added][Android] Adding experimental View Recycling for Fabric on Android.

Reviewed By: mdvacca

Differential Revision: D36608419

fbshipit-source-id: c469ce2fe12ef9332d3def591118befc4a619870
2022-05-26 03:40:21 -07:00
David Vacca fd9c677f0c EZ sort of annotations
Summary:
EZ sort of annotations

changelog: [internal] internal

Reviewed By: sshic

Differential Revision: D35682782

fbshipit-source-id: 5763b140ee4ce54e467e0a80c6d835ae0c4234db
2022-05-25 13:08:29 -07:00
David Vacca ddad5d1265 Remove DevToolsReactPerfLoggerListener when FabricUIManager is deallocated
Summary:
Remove DevToolsReactPerfLoggerListener when FabricUIManager is deallocated

changelog: [internal] internal

Reviewed By: JoshuaGross

Differential Revision: D36500223

fbshipit-source-id: d44e0d07390724191360540e04a51261803eb57c
2022-05-25 12:22:29 -07:00
Nicola Corti 26a54169f2 Remove unused Makefiles from React Native core
Summary:
This diff cleans up several Android Makefiles which we're not using anymore
as they've been replaced by CMake files.

There are still 3 Makefiles left, which I'm aiming to remove in the near future.

Changelog:
[Internal] [Changed] - Remove unused Makefiles from React Native core

Reviewed By: javache

Differential Revision: D36660902

fbshipit-source-id: 8afffac74d493616b0f9414567821cd69f4ef803
2022-05-25 07:54:06 -07:00
Pieter De Baets 7a16106b2d Simplify mapBufferSerializationEnabled feature flag
Summary:
There's no need for this to be a setter/getter, as there are no side-effects, and it means we can use the same helper method to read it as other feature flags.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D36595602

fbshipit-source-id: d27c01bd39d03606a6f8c17ba181a8cd0bf58dbb
2022-05-25 07:47:07 -07:00
Rubén Norte 83631848d2 Permamently enable yielding in runtime scheduler
Summary: changelog: [internal]

Reviewed By: RSNara

Differential Revision: D36638658

fbshipit-source-id: 770d56abb2e2490684ab01e97e5cc7018f247fc8
2022-05-25 05:08:37 -07:00
Joshua Gross b36afe74ca Improve systrace marker in IntBufferBatchMountItem
Summary:
It's useful to have more systrace markers that are all the same, so that they can all be aggregated and work underneath them aggregated across an entire trace. As it is, this marker gets treated as unique nearly every time which makes analysis harder.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D36533075

fbshipit-source-id: 925afa7db152eca1166891b41e7c6f6a511840af
2022-05-23 16:54:58 -07:00
Luna Wei 471907c047 PointerEvents: Mark when listened to for touch interactions
Summary: Changelog: [Internal] - Bypass dispatching an event if no view along the hierarchy is listening to it. Only applied for touch-based interactions. Next change will add optimization for mouse interactions

Reviewed By: vincentriemer

Differential Revision: D35739417

fbshipit-source-id: 134ffefef3bb4f97bf3e63b6bccc0caca464dfbd
2022-05-23 16:29:52 -07:00
Pieter De Baets 7e646361ee Avoid start/finishOperationBatch when using singleOp Animated experiment
Summary:
Splitting these changes of from D36482630, which is a minor improvement to the singleOp experiment. Since we call start/finish already on the native side, we don't need to repeat it from JS.

Changelog: [Internal]

Reviewed By: JoshuaGross

Differential Revision: D36541700

fbshipit-source-id: 7d61669710faca3153be557fb2d214011eda87c5
2022-05-23 07:57:42 -07:00
Nicola Corti c69c14374d Attempt to fix test_android by specifying source 8 (#33890)
Summary:
`test_android` is currently broken as it tries to build with `source = "7"` (the default).
This is a best guess fix to try to fix this issue.

## Changelog

[Internal] - Attempt to fix test_android by specifying source 8

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

Test Plan: Will rely on CI

Reviewed By: cipolleschi

Differential Revision: D36589814

Pulled By: cortinico

fbshipit-source-id: 8ef50f8531b9d4367d2f2c75a312e8fdaf38fd85
2022-05-23 03:17:52 -07:00
Joshua Gross 0fc42fd35c Add detail to Fabric perf logs (median, average, max)
Summary:
I'm finding it useful to keep track of a few additional numbers when doing perf analysis in Fabric.

Also making it easier to enable just these perf logs without all of the other verbose Fabric logs.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D36500518

fbshipit-source-id: e57e1e75131c5d59da876d1decb96d4da386f025
2022-05-19 18:55:56 -07:00
Pieter De Baets 56e9aa369f Avoid emitting mountitems for default values
Summary:
Noticed that we emit a large amount of (admittedly cheap) mountitems as part of node creation for values that are all zero (e.g. padding, overflowinset), which we can assume to be already initialised with these values on the native side.

There's a further opportunity to do this for State as well, as ReactImageComponentState exports just empty maps to Java.

Changelog: [Internal]

Reviewed By: genkikondo

Differential Revision: D36345402

fbshipit-source-id: 8d776ca124bdb9e1cd4de57a04e2785a9a0f918c
2022-05-18 05:44:11 -07:00
Xin Chen a093fe5f2f Queue the event for preallocated but not mounted view to dispatch later
Summary:
This diff fixed an edge case that event dispatching is failed after pre-allocation of a view and before the view is mounted.

When a cached image is loaded, we will dispatch the event to JS immediately. This is could happen after the view is created during pre-allocation phase, when the event emitter is not instantiated yet. In that case, we will see [an error](https://github.com/facebook/react-native/blob/main/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java#L927) and the event will effectively be ignored.

To fix that we introduced a queue in this diff for those events. They will be dispatched in order when the view is mounted and the event emitter is non-null.

Changelog:
[Android][Fixed] - Fixed an edge case that event dispatching is failed after pre-allocation of a view and before the view is mounted.

Reviewed By: mullender

Differential Revision: D36331914

fbshipit-source-id: cd065b0b36978cb5f0aac793d8d16f07a48f0881
2022-05-13 18:40:17 -07:00
Joshua Gross 6915fce898 Log more metadata when throwing error for non-existent viewState
Summary:
Collecting more telemetry to address or debug T112157805 further.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D36295635

fbshipit-source-id: 7896d641a0a745537c8dedf25f44913f47b83876
2022-05-10 16:45:31 -07:00
Pieter De Baets 80f7367149 Replace NativeRunnable with fbjni implementation (#33776)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/33776

The implementations of these modules is pretty much identical, and we're already shipping the fbjni version of this anyway.

Changelog: [Internal]

Reviewed By: mhorowitz

Differential Revision: D36200330

fbshipit-source-id: 135ee621e1e4c5eb9616ce7f442fc6d4b946f865
2022-05-09 05:13:38 -07:00
Anandraj Govindan 883a93871c Working around Long paths limitation on Windows (#33784)
Summary:
Cherry picking https://github.com/facebook/react-native/pull/33707 to main branch

This change is extending the changes made by alespergl to reduce the file paths and command lengths of ndk build commands
Essentially we are shortening the length of the source files by using relative paths instead of absolute paths as enumerated by the wildcard expression
This commit is extending the fix by including all the new modules introduced into RN for the new architecture, including the generated modules.
We are also reverting the ndk bump as ndk23 is crashing frequently when building RN with new arch. The reduced file paths lengths ensures the ndk bump is not required for relatively short application paths.

Fix building RN with new architecture on Windows boxes by using relative paths for C++ sources

## Changelog

Fix building RN with new architecture on Windows boxes by using relative paths for C++ sources

[CATEGORY] [TYPE] - Message

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

Test Plan: Verified building on windows box

Reviewed By: javache

Differential Revision: D36241928

Pulled By: cortinico

fbshipit-source-id: 1ce428a271724cbd3b00a24fe03e7d69253f169b
2022-05-09 04:42:53 -07:00
Pieter De Baets 0d9e054ec4 Cleanup JBackgroundExecutor and support thread naming (#33780)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/33780

Currently this just has a default ThreadPool name, which can be confusing in systraces and crash reports.

Changelog: [Internal]

Reviewed By: ryancat

Differential Revision: D36200090

fbshipit-source-id: 22918993e7c822ed721ccaf79cdcd9d2a972193d
2022-05-09 02:07:26 -07:00
Pieter De Baets 5de0f145ec Avoid allocating empty lists
Summary: Changelog: [Internal] Optimize Fabric memory allocations on Android

Reviewed By: genkikondo

Differential Revision: D36098912

fbshipit-source-id: 8d34a652db019865a8306bc070a08f5ddfef96bf
2022-05-04 04:22:40 -07:00
Xin Chen 72c1a770fe Disable preallocation for panel apps
Summary: Disable preallocation for panel apps to mitigate some crashes.

Reviewed By: javache

Differential Revision: D35866301

fbshipit-source-id: e6277e6be7a86682867c6a7ecfe60f7cf1ab549d
2022-05-03 14:47:47 -07:00
Xin Chen 16f30fc0ec Update overflowInset flag to use public static field
Summary: There's no need to use private feature flag for overflowInset feature. This makes future refactor on feature flags easier.

Reviewed By: javache

Differential Revision: D35866302

fbshipit-source-id: a3fde212ff40cd6d4c68832bb39b34de5a17a8d4
2022-05-03 14:47:47 -07:00
Nicola Corti 1730949e94 Expose scheduler through FabricUIManager
Summary:
Allows to access `react::renderer::Scheduler` given `FabricUIManager` from Java side.

Changelog: [Added] Added `FabricUIManager` binding with FBJNI

Reviewed By: javache

Differential Revision: D35313399

fbshipit-source-id: 54e7adcceae40368c2735ddfc8a083f87b08dc5e
2022-04-26 05:11:05 -07:00
David Vacca fbeb51ef51 Fix NullPointerException when disaptching events
Summary:
This diff fixes a NullPointerException when disaptching events while the SurfaceMountingManager is being destroyed

changelog: [android] android

Reviewed By: cortinico

Differential Revision: D35559550

fbshipit-source-id: c07f74493384fb1b306338ec1bc8b96f1b6f1f41
2022-04-12 12:18:14 -07:00
Chris Olszewski daa105aba5 Fixup typo in pfh labels
Summary:
Now that the PFH node has been renamed this updates the pfh label.

Produced via `xbgs -l -e '"pfh:ReactNative_CommonInfrastructurePlaceholde"' | xargs sed -i 's/"pfh:ReactNative_CommonInfrastructurePlaceholde"/"pfh:ReactNative_CommonInfrastructurePlaceholder"/'`

Reviewed By: jkeljo

Differential Revision: D35374087

fbshipit-source-id: 61590f69de5a69ec3b8a0478f6dd43409de3c70b
2022-04-05 12:15:05 -07:00
Andrei Shikov 651c4c1b55 Add kotlin stdlib as a dependency for Java targets depending on Kotlin (#33535)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/33535

Hack to support Kotlin functions in Buck compilation: adds Kotlin stdlib as a dependency to make sure upstream targets include Kotlin jvm internal classes.

Changelog: [Internal]

Reviewed By: cortinico

Differential Revision: D35284430

fbshipit-source-id: 0d29ad30386514c8df5376d0a6809d3105f0cd0f
2022-04-01 09:33:31 -07:00
Andrei Shikov 2a6a6851ec Rename C++ part of ReadableMapBuffer to JReadableMapBuffer
Summary:
Aligns naming with `JWritableMapBuffer` and other fbjni classes to indicate that it is a JNI binding.

Changelog: [Internal] - Rename C++ part of ReadableMapBuffer to JReadableMapBuffer

Reviewed By: mdvacca

Differential Revision: D35219323

fbshipit-source-id: a7eb644a700a35dc94fa18e4fb3cc68f2cfa3e99
2022-03-30 20:27:23 -07:00
Andrei Shikov 81e4249315 Adapt ReadableMapBuffer to MapBuffer interface
Summary:
Updates `ReadableMapBuffer` to conform to `MapBuffer` interface, to allow interchangeable use of `Readable/WritableMapBuffer` in the code.

Notable changes:
- MapBuffer.Entry getters are now represented as Kotlin properties and appended `Value` suffix (e.g. `entry.getInt()` becomes `entry.getIntValue()` in Java, or `entry.intValue` in Kotlin)
- `ByteBuffer` is imported in constructor instead of on demand. This method doesn't copy the data as the bytes are read directly from native heap, and benchmarking a 500-byte `MapBuffer` shows no difference in import speed.
- Internal logic of `ReadableMapBuffer` uses `UShort` kotlin type for key retrieval, for more correct representation of values.
- Explicit exception throws are replaced with `require` and `check` methods for `IllegalArgumentException` and `IllegalStateException` (default FB conversion).

The change also updates `ReadableMapBuffer` usages to `MapBuffer` interface where possible (virtually everywhere except JNI methods).

Changelog: [Android][Changed] - Adopt `MapBuffer` interface for `ReadableMapBuffer`

Reviewed By: mdvacca

Differential Revision: D35218633

fbshipit-source-id: 515dd974c27b2978ade325b2e1750ab8f068a20a
2022-03-30 20:27:23 -07:00
Chris Olszewski ceae48c0f7 Add pfh labels to targets
Summary:
While it would be better to be able to do all of the ownership metadata at the Buck macro level, that proved to be more work than expected.

This diff adds the corresponding pfh label to all targets in `xplat/js/react-native-github` that have a Supermodule label. Once the migration is complete the Supermodules labels will be able to be removed.

Reviewed By: cortinico

Differential Revision: D35221544

fbshipit-source-id: d87d5e266dfb5e6ee087251dc34dff5db299bbaf
2022-03-30 14:37:03 -07:00
Chris Olszewski 75edd288cb Backout feature args
Reviewed By: jkeljo

Differential Revision: D35203884

fbshipit-source-id: 87d50b138aaa3dd16a24b5ff2795910c3644d418
2022-03-30 06:53:44 -07:00
CodemodService Bot b6e72c5922 Annotate targets with feature xplat/js/react-native-github/Libraries/RCTRequired/BUCK -> xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK
Reviewed By: jkeljo

Differential Revision: D35178374

fbshipit-source-id: be4ad27928a1b9260a9d6321c9705b30aebe04d6
2022-03-28 13:11:16 -07:00
Andrei Shikov d63bf4add3 Align ReadableMap and MapBuffer measure methods in ViewManager
Summary:
Aligns two codepaths for measure, making sure we can use both MapBuffer and ReadableMap for measuring components.

Changelog: [Internal] - Align measure interface for MapBuffer experiment

Reviewed By: javache, mdvacca

Differential Revision: D34960317

fbshipit-source-id: a39eb84a0abb4414717463f2f1741e470be3531f
2022-03-18 00:36:07 -07:00
Andrei Shikov 69e8d3d883 Build Fabric with CMake
Summary:
More CMake configurations mirroring Android.mk in place.

Changelog: [Internal] - Build fabricjni with CMake

Reviewed By: cortinico

Differential Revision: D34927238

fbshipit-source-id: 929763ec79a7c168e300e065709a49e4b373326a
2022-03-17 17:08:24 -07:00
Andrei Shikov 5d5addd661 Separate folly into runtime + folly_futures specific for hermes inspector
Summary:
Rearranges folly_futures configuration into a static library only required for `hermes-inspector` + `folly_runtime` which merges `folly_json` and mutex-related implementations `folly_futures` was used for. As `hermes-executor-debug` is removed by `vmCleanup` configurations later, it allows to shave additional 300KB from the release APK size.

Changelog: [Internal] - Rearrange folly build to reduce APK size

Reviewed By: cortinico

Differential Revision: D34342514

fbshipit-source-id: b646680343e6b9a7674019506b87b96f6007caf2
2022-03-13 15:15:21 -07:00
Andrei Shikov 28291461a8 Add @DoNotStrip to stop obfuscation of Fabric related classes
Summary:
Proguard seems to keep Fabric methods a bit differently from Redex, with method signature lookup with `MountItem` and `StateWrapperImpl` failing in release RNTester builds because of mangled names. Adding these annotations should keep the classes, ensuring lookup from native is correct.

Changelog: [Internal] - Add DoNotStrip annotations to Fabric related classes

Reviewed By: ryancat

Differential Revision: D34726510

fbshipit-source-id: 0c1d8e1fabec75511942943b533ddd8b637a5e19
2022-03-11 09:16:01 -08:00
Samuel Susla e97e3499c3 Avoid string copy in event dispatching
Summary:
Changelog: [internal]

To avoid unnecessary string copy in event pipeline, use move semantics.

Event pipeline has ownership of event type. Passing it by reference ends up in a copy when `RawEvent` object is constructed. To avoid this, pass string by value through each layer and use move semantics to avoid extra copies.

Reviewed By: javache

Differential Revision: D34392608

fbshipit-source-id: c11d221be345665e165d9edbc360ba5a057e3890
2022-03-08 04:28:51 -08:00
Samuel Susla a159416333 Use std::optional instead of butter::optional
Summary: changelog: Use std::optional instead of butter::optional

Reviewed By: fkgozali

Differential Revision: D33352680

fbshipit-source-id: 45a53fec181a6ffb6218909bc23348f7c9f21ec4
2022-03-04 07:25:59 -08:00
David Vacca 97f3eb2d3b Ship large text measure cache in Fabric Android
Summary:
Ship large text measure cache in Fabric Android

changelog: [internal] internal

Reviewed By: sammy-SC

Differential Revision: D34602873

fbshipit-source-id: bd0a77b8b2f85301a78d528e7810938b78c7f7b8
2022-03-03 09:41:23 -08:00
Samuel Susla 8669277b3b Use std::unordered_set::find instead of std::unordered_set::contains
Summary:
changelog: [internal]

I'm looking into JS exceptions in React 18 on Android and I've noticed we use [std::unordered_set::contains]((https://en.cppreference.com/w/cpp/container/unordered_set/contains) that is only supported in C++20. I don't think this causes the exceptions but I would like to eliminate this option.

Reviewed By: javache

Differential Revision: D34547741

fbshipit-source-id: 6cffcff3366e7579a2c0e19bc01ffcb355b9ddb6
2022-03-03 09:22:32 -08:00
Samuel Susla 664f9b11ba Add option to delay deletion of viewState
Summary:
changelog: [internal]

ViewState is sometimes deleted but not created again because of race condition in C++ pre-allocation and how it checks for revision to determine if createView mount item should be dispatched.

In this diff, we add an option to delay deletion of ViewState until the next commit.

Reviewed By: ShikaSD

Differential Revision: D34553174

fbshipit-source-id: e5213f1d39137fb56fc745321a7c1b28d417ea27
2022-03-03 06:02:02 -08:00
Samuel Susla f7e4037c65 Clean up constructor in FabricMountingManager
Summary:
changelog: [internal]

Make all feature flags `const` and initialise them as ivars. Also makes the class final and removes virtualised destructor since it is not needed.

Reviewed By: ShikaSD

Differential Revision: D34549013

fbshipit-source-id: 2b326bc5b6c1dd6d89c2fb9c671bda6da669fa76
2022-03-03 04:35:53 -08:00
Andrei Shikov 131844f40e Add feature flag to disable pre-allocation on clone
Summary:
Disables preallocation for cloned nodes, switching to create during commit for those cases instead.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D34555621

fbshipit-source-id: 21fc834cea318ca299aa37a9aab28a2f2a9675b5
2022-03-01 18:10:49 -08:00
David Vacca ec27141b93 remove duplicate code in FabricUIManager
Summary:
remove duplicate code in FabricUIManager

The removed line is already called few lines above

changelog: [internal] internal

Reviewed By: JoshuaGross

Differential Revision: D34553849

fbshipit-source-id: 2e0102a77e7464c9803fb1175385fdafbb88f1fa
2022-03-01 14:56:44 -08:00
Andrei Shikov 964e816752 Update usages of default ReactNativeConfig (#33196)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/33196

Fixes compilation of Android template and renames the field according to Java guidelines.

Changelog: [Android][Changed] - Rename field with default values for ReactConfig to DEFAULT_CONFIG

Reviewed By: cortinico

Differential Revision: D34523356

fbshipit-source-id: 46ed703e7ca8ab5e05879dd93e8e4d2d816c2d03
2022-02-28 14:45:09 -08:00
David Vacca a7a2d2307c Quick update in the Fabric statistics loggiing
Summary:
Quick update in the Fabric statistics loggiing

changelog: [internal] internal

Reviewed By: ShikaSD

Differential Revision: D34315716

fbshipit-source-id: c0e2e1611b0b6a947ffef6e0cc444b15e812d01b
2022-02-27 22:23:48 -08:00
David Vacca 858ccfc9c8 Refactor to reuse EmptyReactNativeConfig from ReactNativeConfig
Summary:
Quick refactor to reuse EmptyReactNativeConfig from ReactNativeConfig

changelog: [internal] internal

Reviewed By: genkikondo

Differential Revision: D34283060

fbshipit-source-id: 32400d5ed6defd9f82953dc49ae365598db71bbc
2022-02-27 22:23:48 -08:00
David Vacca 5c9c901d0c Introduce DefaultValuesReactNativeConfig constant
Summary:
Introduce DefaultValuesReactNativeConfig constant that represents a ReactNativeConfig that always return default values

I also use this constant in all the apps using fbaric that don't have a custom Mobile Config

changelog: [internal] internal

Reviewed By: RSNara

Differential Revision: D34160478

fbshipit-source-id: 5730054fd4cc87e1fe5dc8247cc237194bf48981
2022-02-27 22:23:48 -08:00