react-native-reanimated
Version:
More powerful alternative to Animated library for React Native.
165 lines (130 loc) • 5.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.flushImmediates = void 0;
exports.runOnJS = runOnJS;
exports.runOnUI = runOnUI;
exports.runOnUIImmediately = runOnUIImmediately;
exports.setupSetImmediate = setupSetImmediate;
var _NativeReanimated = _interopRequireDefault(require("./NativeReanimated"));
var _PlatformChecker = require("./PlatformChecker");
var _shareables = require("./shareables");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const IS_JEST = (0, _PlatformChecker.isJest)();
const IS_WEB = (0, _PlatformChecker.shouldBeUseWeb)();
let _runOnUIQueue = [];
function setupSetImmediate() {
'worklet';
let immediateCallbacks = []; // @ts-ignore – typescript expects this to conform to NodeJS definition and expects the return value to be NodeJS.Immediate which is an object and not a number
global.setImmediate = callback => {
immediateCallbacks.push(callback);
return -1;
};
global.__flushImmediates = () => {
for (let index = 0; index < immediateCallbacks.length; index += 1) {
// we use classic 'for' loop because the size of the currentTasks array may change while executing some of the callbacks due to setImmediate calls
immediateCallbacks[index]();
}
immediateCallbacks = [];
};
}
function flushImmediatesOnUIThread() {
'worklet';
global.__flushImmediates();
}
const flushImmediates = (0, _PlatformChecker.shouldBeUseWeb)() ? () => {// on web flushing is a noop as immediates are handled by the browser
} : flushImmediatesOnUIThread;
/**
* Schedule a worklet to execute on the UI runtime. This method does not schedule the work immediately but instead
* waits for other worklets to be scheduled within the same JS loop. It uses setImmediate to schedule all the worklets
* at once making sure they will run within the same frame boundaries on the UI thread.
*/
exports.flushImmediates = flushImmediates;
function runOnUI(worklet) {
if (__DEV__ && !IS_WEB && worklet.__workletHash === undefined) {
throw new Error('runOnUI() can only be used on worklets');
}
return function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (IS_JEST) {
// Mocking time in Jest is tricky as both requestAnimationFrame and setImmediate
// callbacks run on the same queue and can be interleaved. There is no way
// to flush particular queue in Jest and the only control over mocked timers
// is by using jest.advanceTimersByTime() method which advances all types
// of timers including immediate and animation callbacks. Ideally we'd like
// to have some way here to schedule work along with React updates, but
// that's not possible, and hence in Jest environment instead of using scheduling
// mechanism we just schedule the work ommiting the queue. This is ok for the
// uses that we currently have but may not be ok for future tests that we write.
_NativeReanimated.default.scheduleOnUI((0, _shareables.makeShareableCloneRecursive)(() => {
'worklet';
worklet(...args);
}));
return;
}
_runOnUIQueue.push([worklet, args]);
if (_runOnUIQueue.length === 1) {
setImmediate(() => {
const queue = _runOnUIQueue;
_runOnUIQueue = [];
_NativeReanimated.default.scheduleOnUI((0, _shareables.makeShareableCloneRecursive)(() => {
'worklet';
queue.forEach(_ref => {
let [worklet, args] = _ref;
worklet(...args);
});
flushImmediates();
}));
});
}
};
}
/**
* Schedule a worklet to execute on the UI runtime skipping batching mechanism.
*/
function runOnUIImmediately(worklet) {
if (__DEV__ && !IS_WEB && worklet.__workletHash === undefined) {
throw new Error('runOnUI() can only be used on worklets');
}
return function () {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
_NativeReanimated.default.scheduleOnUI((0, _shareables.makeShareableCloneRecursive)(() => {
'worklet';
worklet(...args);
}));
};
}
if (__DEV__) {
try {
runOnUI(() => {
'worklet';
});
} catch (e) {
throw new Error('Failed to create a worklet. Did you forget to add Reanimated Babel plugin in babel.config.js? See installation docs at https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation#babel-plugin.');
}
}
function runOnJS(fun) {
'worklet';
if (fun.__remoteFunction) {
// in development mode the function provided as `fun` throws an error message
// such that when someone accidently calls it directly on the UI runtime, they
// see that they should use `runOnJS` instead. To facilitate that we purt the
// reference to the original remote function in the `__remoteFunction` property.
fun = fun.__remoteFunction;
}
if (!_WORKLET) {
return fun;
}
return function () {
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
_scheduleOnJS(fun, args.length > 0 ? (0, _shareables.makeShareableCloneOnUIRecursive)(args) : undefined);
};
}
//# sourceMappingURL=threads.js.map