Skip to content

Commit eb9e285

Browse files
committed
Merge branch 'main' into mkzie2-issue/66714
2 parents c63341b + 85fdcf3 commit eb9e285

28 files changed

+585
-346
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* eslint-disable no-console */
2+
import type {Compiler} from 'webpack';
3+
4+
/**
5+
* Custom webpack plugin that forces garbage collection every 5 compilations
6+
* and logs memory usage to help monitor memory consumption during development.
7+
*
8+
* Note: Requires Node.js to be started with --expose-gc flag to enable garbage collection.
9+
*/
10+
class ForceGarbageCollectionPlugin {
11+
private compilationCount = 0;
12+
13+
apply(compiler: Compiler) {
14+
if (gc && typeof gc === 'function') {
15+
compiler.hooks.done.tap(this.constructor.name, () => {
16+
this.compilationCount++;
17+
18+
// Log memory usage every compilation
19+
const memUsage = process.memoryUsage();
20+
const heapUsedMB = Math.round(memUsage.heapUsed / 1024 / 1024);
21+
const heapTotalMB = Math.round(memUsage.heapTotal / 1024 / 1024);
22+
23+
console.log(`📊 Compilation #${this.compilationCount} - Heap: ${heapUsedMB}MB/${heapTotalMB}MB`);
24+
if (this.compilationCount % 5 === 0) {
25+
console.log(`🗑️ Forcing garbage collection after ${this.compilationCount} compilations`);
26+
// @ts-expect-error - gc is a global function provided when Node.js is started with --expose-gc flag
27+
gc();
28+
29+
// Log memory after garbage collection
30+
const memAfterGC = process.memoryUsage();
31+
const heapAfterMB = Math.round(memAfterGC.heapUsed / 1024 / 1024);
32+
console.log(`✅ Post-GC heap size: ${heapAfterMB}MB (freed ${heapUsedMB - heapAfterMB}MB)`);
33+
}
34+
});
35+
} else {
36+
console.warn('⚠️ ForceGarbageCollectionPlugin: gc() function not available. Start Node.js with --expose-gc flag to enable garbage collection.');
37+
}
38+
}
39+
}
40+
41+
export default ForceGarbageCollectionPlugin;

config/webpack/webpack.common.ts

Lines changed: 277 additions & 272 deletions
Large diffs are not rendered by default.

config/webpack/webpack.dev.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {Configuration} from 'webpack';
77
import {DefinePlugin} from 'webpack';
88
import type {Configuration as DevServerConfiguration} from 'webpack-dev-server';
99
import {merge} from 'webpack-merge';
10+
import ForceGarbageCollectionPlugin from './ForceGarbageCollectionPlugin';
1011
import type Environment from './types';
1112
import getCommonConfiguration from './webpack.common';
1213

@@ -65,6 +66,7 @@ const getConfiguration = (environment: Environment): Promise<Configuration> =>
6566
'process.env.NODE_ENV': JSON.stringify('development'),
6667
}),
6768
new ReactRefreshWebpackPlugin({overlay: {sockProtocol: 'wss'}}),
69+
new ForceGarbageCollectionPlugin(),
6870
],
6971
// This prevents import error coming from react-native-tab-view/lib/module/TabView.js
7072
// where Pager is imported without extension due to having platform-specific implementations

desktop/start.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ portfinder
1212
port: basePort,
1313
})
1414
.then((port) => {
15-
const devServer = `webpack-dev-server --config config/webpack/webpack.dev.ts --port ${port} --env platform=desktop`;
15+
const devServer = `./scripts/start-dev-with-auto-restart.sh --port ${port} --env platform=desktop`;
1616
const buildMain = 'webpack watch --config config/webpack/webpack.desktop.ts --config-name desktop-main --mode=development';
1717

1818
const env = {

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"start": "npx rnef start",
2929
"web": "./scripts/set-pusher-suffix.sh && concurrently npm:web-proxy npm:web-server",
3030
"web-proxy": "ts-node web/proxy.ts",
31-
"web-server": "webpack-dev-server --open --config config/webpack/webpack.dev.ts",
31+
"web-server": "./scripts/start-dev-with-auto-restart.sh",
3232
"build": "webpack --config config/webpack/webpack.common.ts --env file=.env.production && ts-node ./scripts/combine-web-sourcemaps.ts",
3333
"build-staging": "webpack --config config/webpack/webpack.common.ts --env file=.env.staging && ts-node ./scripts/combine-web-sourcemaps.ts",
3434
"build-adhoc": "webpack --config config/webpack/webpack.common.ts --env file=.env.adhoc && ts-node ./scripts/combine-web-sourcemaps.ts",
@@ -46,7 +46,7 @@
4646
"test:debug": "TZ=utc NODE_OPTIONS='--inspect-brk --experimental-vm-modules' jest --runInBand",
4747
"perf-test": "NODE_OPTIONS=--experimental-vm-modules npx reassure",
4848
"typecheck": "NODE_OPTIONS=--max_old_space_size=8192 tsc",
49-
"lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=324 --cache --cache-location=node_modules/.cache/eslint",
49+
"lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=332 --cache --cache-location=node_modules/.cache/eslint",
5050
"lint-changed": "NODE_OPTIONS=--max_old_space_size=8192 ./scripts/lintChanged.sh",
5151
"lint-watch": "npx eslint-watch --watch --changed",
5252
"shellcheck": "./scripts/shellCheck.sh",
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/bin/bash
2+
3+
# Auto-restart webpack-dev-server on memory crashes
4+
# This script monitors for heap out of memory errors and automatically restarts
5+
# Usage: ./start-dev-with-auto-restart.sh [webpack-dev-server arguments]
6+
7+
WDS_ARGS=("$@")
8+
MAX_RESTARTS=10
9+
RESTART_COUNT=0
10+
RESTART_DELAY=1
11+
12+
echo "🚀 Starting webpack-dev-server with auto-restart (max restarts: $MAX_RESTARTS)"
13+
14+
run_wds () {
15+
# Check if platform is Desktop to determine open behavior
16+
if [[ "${WDS_ARGS[*]}" == *"--env platform=desktop"* ]]; then
17+
# For Desktop, always use --no-open since app is handled by Electron
18+
node --expose-gc --max-old-space-size=1100 ./node_modules/.bin/webpack-dev-server --no-open "${WDS_ARGS[@]}" --config config/webpack/webpack.dev.ts
19+
else
20+
# For Web, use the provided open flag
21+
node --expose-gc ./node_modules/.bin/webpack-dev-server "$1" "${WDS_ARGS[@]}" --config config/webpack/webpack.dev.ts
22+
fi
23+
}
24+
25+
while [ $RESTART_COUNT -lt $MAX_RESTARTS ]; do
26+
echo "📊 Attempt #$((RESTART_COUNT + 1)) - Starting webpack-dev-server..."
27+
28+
if [ $RESTART_COUNT -eq 0 ]; then
29+
run_wds --open
30+
else
31+
run_wds --no-open
32+
fi
33+
34+
# Capture exit code
35+
EXIT_CODE=$?
36+
# Check if it was a memory-related crash
37+
if [ $EXIT_CODE -eq 134 ] || [ $EXIT_CODE -eq 137 ] || [ $EXIT_CODE -eq 139 ]; then
38+
echo "💥 Memory crash detected (exit code: $EXIT_CODE)"
39+
RESTART_COUNT=$((RESTART_COUNT + 1))
40+
41+
if [ $RESTART_COUNT -lt $MAX_RESTARTS ]; then
42+
echo "🔄 Auto-restarting... (restart #$RESTART_COUNT)"
43+
sleep $RESTART_DELAY
44+
else
45+
echo "❌ Max restarts reached ($MAX_RESTARTS). Exiting."
46+
exit 1
47+
fi
48+
elif [ $EXIT_CODE -eq 0 ]; then
49+
echo "✅ Webpack-dev-server exited cleanly"
50+
exit 0
51+
else
52+
echo "❌ Webpack-dev-server exited with error code: $EXIT_CODE"
53+
exit $EXIT_CODE
54+
fi
55+
done
56+
57+
echo "❌ Maximum restart attempts reached. Please check for underlying issues."
58+
exit 1

src/CONST/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3186,6 +3186,7 @@ const CONST = {
31863186
},
31873187
LIMIT_VALUE: 21474836,
31883188
STEP_NAMES: ['1', '2', '3', '4', '5', '6'],
3189+
ASSIGNEE_EXCLUDED_STEP_NAMES: ['1', '2', '3', '4', '5'],
31893190
STEP: {
31903191
ASSIGNEE: 'Assignee',
31913192
CARD_TYPE: 'CardType',

src/components/CurrencySelectionList/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ function CurrencySelectionList({
1515
searchInputLabel,
1616
initiallySelectedCurrencyCode,
1717
onSelect,
18+
didScreenTransitionEnd = true,
1819
selectedCurrencies = [],
1920
canSelectMultiple = false,
2021
recentlyUsedCurrencies,
@@ -109,6 +110,7 @@ function CurrencySelectionList({
109110
initiallyFocusedOptionKey={initiallySelectedCurrencyCode}
110111
showScrollIndicator
111112
canSelectMultiple={canSelectMultiple}
113+
showLoadingPlaceholder={!didScreenTransitionEnd}
112114
/>
113115
);
114116
}

src/components/CurrencySelectionList/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ type CurrencySelectionListProps = Partial<SelectionListProps<CurrencyListItem>>
2626

2727
/** List of excluded currency codes */
2828
excludedCurrencies?: string[];
29+
30+
/** Whether the screen transition has ended */
31+
didScreenTransitionEnd?: boolean;
2932
};
3033

3134
export type {CurrencyListItem, CurrencySelectionListProps};

src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function MoneyRequestReportTransactionList({
103103
useCopySelectionHelper();
104104
const styles = useThemeStyles();
105105
const StyleUtils = useStyleUtils();
106-
const {translate} = useLocalize();
106+
const {translate, localeCompare} = useLocalize();
107107
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
108108
const {shouldUseNarrowLayout, isSmallScreenWidth, isMediumScreenWidth} = useResponsiveLayout();
109109
const [isModalVisible, setIsModalVisible] = useState(false);
@@ -157,12 +157,12 @@ function MoneyRequestReportTransactionList({
157157

158158
const sortedTransactions: TransactionWithOptionalHighlight[] = useMemo(() => {
159159
return [...transactions]
160-
.sort((a, b) => compareValues(a[getTransactionKey(a, sortBy)], b[getTransactionKey(b, sortBy)], sortOrder, sortBy))
160+
.sort((a, b) => compareValues(a[getTransactionKey(a, sortBy)], b[getTransactionKey(b, sortBy)], sortOrder, sortBy, localeCompare))
161161
.map((transaction) => ({
162162
...transaction,
163163
shouldBeHighlighted: newTransactions?.includes(transaction),
164164
}));
165-
}, [newTransactions, sortBy, sortOrder, transactions]);
165+
}, [newTransactions, sortBy, sortOrder, transactions, localeCompare]);
166166

167167
const navigateToTransaction = useCallback(
168168
(activeTransactionID: string) => {

0 commit comments

Comments
 (0)