Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
# Controls whether to use Hermes from stable builds. This will force hermes version
# set in the sdks/hermes-engine/version.properties file to be used. This has a higher
# priority than react.internal.useHermesNightly.
react.internal.useHermesStable=false
react.internal.useHermesStable=true

# Controls whether to use Hermes from nightly builds. This will speed up builds
# but should NOT be turned on for CI or release builds.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ CallbackHandle NativeIdleCallbacks::requestIdleCallback(
if (options.has_value() && options.value().timeout.has_value()) {
HighResDuration userTimeout = options.value().timeout.value();
if (userTimeout > HighResDuration::zero()) {
timeout = userTimeout;
expirationTime = runtimeScheduler->now() + userTimeout;
}
}
Expand Down
56 changes: 53 additions & 3 deletions packages/rn-tester/js/examples/Playground/RNTesterPlayground.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,63 @@ import type {RNTesterModuleExample} from '../../types/RNTesterTypes';
import RNTesterText from '../../components/RNTesterText';
import * as React from 'react';
import {StyleSheet, View} from 'react-native';
import {useState, useEffect} from 'react';

/**
* Proves NativeIdleCallbacks forwards options.timeout into scheduleIdleTask.
*
* Strategy: keep scheduling LowPriority work (10s expiry each). That always
* beats an idle task with the default 5min expiry (bug), but after the first
* LowPriority tick a patched idle task (LowPriority + timeout ≈ 10s) becomes
* the earliest-expiring task and runs.
*
* Expect with the patch: fire within ~1s.
* Expect without (`timeout = userTimeout` removed): stuck on "starving…" for minutes.
*/
function Playground() {
const [label, setLabel] = useState('starving LowPriority queue…');

useEffect(() => {
const scheduler = global.nativeRuntimeScheduler;
const {unstable_scheduleCallback, unstable_LowPriority} = scheduler;

const start = performance.now();
let keepStarving = true;

const starve = () => {
if (!keepStarving) {
return;
}
unstable_scheduleCallback(unstable_LowPriority, () => {
const blockStart = performance.now();
while (performance.now() - blockStart < 30) {}
starve();
});
};

requestIdleCallback(
deadline => {
keepStarving = false;
const elapsedMs = Math.round(performance.now() - start);
setLabel(
`✅ PATCHED: fired after ${elapsedMs}ms under LowPriority load, didTimeout=${String(
deadline.didTimeout,
)}`,
);
},
{timeout: 10},
);

starve();

return () => {
keepStarving = false;
};
}, []);

return (
<View style={styles.container}>
<RNTesterText>
Edit "RNTesterPlayground.js" to change this file
</RNTesterText>
<RNTesterText>{label}</RNTesterText>
</View>
);
}
Expand Down