Coder Social home page Coder Social logo

Comments (7)

rubennorte avatar rubennorte commented on September 26, 2024 1

cc @robik :)

from react-native.

robik avatar robik commented on September 26, 2024 1

@rubennorte I've put up a draft PR: #44759

Currently, this is for preview only, and pretty much untested. Feel free to point out what should be changed and whenever we want to extract some of the code into separate class as initially planned.

I am looking for a way to register the methods from NativeMicrotasks module into globals so they are visible in bridgeless mode. I am pretty unsure whenever it is a good approach that the logic was done in turbo module or it should be moved.

Also I am bit unsure if all cases were covered (e.g. bridgeless, bridge, flags etc) so there may be some missing parts in this regard

from react-native.

github-actions avatar github-actions commented on September 26, 2024
⚠ī¸ Missing Reproducible Example
ℹī¸ We could not detect a reproducible example in your issue report. Please provide either:
  • If your bug is UI related: a Snack
  • If your bug is build/update related: use our Reproducer Template. A reproducer needs to be in a GitHub repository under your username.

from react-native.

rubennorte avatar rubennorte commented on September 26, 2024

At a high level, this is how I'd implement this:

  1. Create an abstraction to handle idle callbacks, which would keep a queue of idle callbacks and would handle their promotion from idle callbacks to regular tasks after their timeout (we can just schedule a timer with the specified timeout, if any, which would execute the task and cancel the idle callback).
  2. Modify RuntimeScheduler_Modern to receive an idle callback queue (probably as an interface that the previous abstraction would implement, to avoid dependency cycles in C++). When there are no tasks left in the task queue, those tasks would be consumed). For the timeRemaining function, we could compute the deadline at the beginning of the idle period using now + 50ms. We don't need frame alignment as in the spec (and the spec doesn't require it). In that method we should also check shouldYield in the scheduler and return 0 if that's the case.
  3. Create a C++ TurboModule to expose requestIdleCallback, similar to what we did with queueMicrotask (module) (global). This should register the microtask in the new abstraction created in step.

The idle callbacks instance should probably be owned by ReactInstance because that's where we have access to the timer manager (to promote idle callbacks) and to the runtime scheduler. The native module can access it from RuntimeSchedulerBinding.

from react-native.

rubennorte avatar rubennorte commented on September 26, 2024

I've been thinking about this a bit more and there an alternative implementation we could use that perhaps would be simpler (although its alignment with the spec would be harder to "visualize").

Instead of keeping a separate queue for idle callbacks and specific logic in the scheduler, we can keep the scheduler unmodified and schedule all idle callbacks as idle priority tasks. The only extra thing we'd need is the native module I mentioned in my previous comment and the abstraction for promoting idle callbacks to regular tasks after the timeout. At a high level:

  1. Create an abstraction to handle the execution idle callbacks and their promotion to regular tasks after their timeout (e.g. IdleCallbackScheduler) (we can just schedule a timer with the specified timeout, if any, which would execute the task and cancel the idle callback).
  2. Create a C++ TurboModule to expose requestIdleCallback, similar to what we did with queueMicrotask (module) (global). This should register the microtask in the new abstraction created in step.

This abstraction (IdleCallbackScheduler or similar) would schedule an idle priority task in the scheduler which, when executed, would compute an initial deadline for the callback (e.g.: current time + 50ms) and would call the idle callback with an object that would return the right timeRemaining based on that time (and 0 if getShouldYield returns true). In the future, we can make this more spec compliant looking also at what's the expiration time for the next timeout callback to execute (we don't need to do this in this version).

from react-native.

robik avatar robik commented on September 26, 2024

@rubennorte I've noticed that the RuntimeScheduler has a priority queue based on task expirationTime already, it initially had priority, so there's some groundwork for it being handled in the scheduler itself. If we want to separate this and introduce an API boundary should we revert it to be priority-based?

It might be a bit confusing and error-prone in the current state, WDYT?

from react-native.

rubennorte avatar rubennorte commented on September 26, 2024

@rubennorte I've noticed that the RuntimeScheduler has a priority queue based on task expirationTime already, it initially had priority, so there's some groundwork for it being handled in the scheduler itself. If we want to separate this and introduce an API boundary should we revert it to be priority-based?

The expiration time in the RuntimeScheduler is just an implementation detail. It's just used to make sure that lower priority tasks execute eventually (except for idle priority tasks that have an infinite timeout), instead of being continuously deprioritized from new incoming tasks with a higher priority.

It might be a bit confusing and error-prone in the current state, WDYT?

The reason I was suggesting this approach was to avoid introducing new changes to the scheduler that we might regret later. Someone proposed allowing us to specify the scheduler timeout directly in the RuntimeScheduler API, but I think that wouldn't be a good idea.

Alternatively, we could do this:

  1. Add new methods in the RuntimeScheduler to schedule idle tasks with a timeout. Those methods would schedule tasks with an expiration time equals to something like max(customTimeout, timeoutForSchedulerPriority(NormalPriority)). This minimum time would be necessary to avoid that idle callbacks take higher priority than UserBlocking tasks when called with timeout equals 0.
  2. Call these methods directly from the native module that I mentioned before, which would also wrap the callback to implement the timeRemaining method.

from react-native.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤ī¸ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.