Skip to content

[compiler] Inferred effect dependencies now include optional chains #33326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 22, 2025

Conversation

mofeiZ
Copy link
Contributor

@mofeiZ mofeiZ commented May 21, 2025

Inferred effect dependencies now include optional chains.

This is a temporary solution while #32099 and its followups are worked on. Ideally, we should model reactive scope dependencies in the IR similarly to ComputeIR -- dependencies should be hoisted and all references rewritten to use the hoisted dependencies.

`

Stack created with Sapling. Best reviewed with ReviewStack.

@mofeiZ mofeiZ force-pushed the pr33326 branch 2 times, most recently from 84347ec to 53cc92d Compare May 21, 2025 18:51
mofeiZ added a commit that referenced this pull request May 21, 2025
When collecting scope dependencies, mark each dependency with `reactive: true | false`. This prepares for later PRs #33326 and #32099 which rewrite scope dependencies into instructions.

Note that some reactive objects may have non-reactive properties, but we do not currently track this.

Technically, state[0] is reactive and state[1] is not. Currently, both would be marked as reactive.
```js
const state = useState();
```
@mofeiZ mofeiZ marked this pull request as ready for review May 21, 2025 18:52
@mofeiZ mofeiZ force-pushed the pr33326 branch 2 times, most recently from ab7d916 to fe7e4c8 Compare May 21, 2025 19:11
Comment on lines +29 to +31
const builder = new HIRBuilder(env, {
entryBlockKind: 'value',
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reusing HIRBuilder here since writing optional blocks needs the same reserve / enterReserved logic as buildHIR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh this makes sense now, definitely makes it easier to construct the optionals

@@ -86,6 +92,7 @@ export function inferEffectDependencies(fn: HIRFunction): void {
* reactive(Identifier i) = Union_{reference of i}(reactive(reference))
*/
const reactiveIds = inferReactiveIdentifiers(fn);
const rewriteBlocks: Array<BasicBlock> = [];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're now inserting new blocks into the function (see rewriteSplices)

) {
// exclude non-reactive hook results, which will never be in a memo block
continue;
}

const {place, instructions} = writeDependencyToInstructions(
const dep = truncateDepAtCurrent(maybeDep);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this check from writeDependencyToInstructions so that IDE highlighting and etc also receive the correct (truncated) dependency

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thank you!

IIUC, the IDE has access to all of the paths but we'll still need to look inside the effect body for property accesses/optional chains that correspond to deps, is that right?

And #32099 would make this easier because it would hoist the deps into temporaries that would be re-used inside the body.

@mofeiZ mofeiZ force-pushed the pr33326 branch 2 times, most recently from 0dfaec8 to 1a5a050 Compare May 21, 2025 19:21
fn.env.hasInferredEffect = true;
}
}

function writeDependencyToInstructions(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was moved to ScopeDependencyUtils

Copy link
Member

@josephsavona josephsavona left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super cool

Copy link
Contributor

@jbrown215 jbrown215 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wooo! this rocks

@@ -4,6 +4,12 @@ import {print} from 'shared-runtime';

// TODO: take optional chains as dependencies
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove the todo now :D

import {useEffect} from 'react';
import {print, shallowCopy} from 'shared-runtime';

// TODO: take optional chains as dependencies
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can drop this now!

import {useEffect} from 'react';
import {print, shallowCopy} from 'shared-runtime';

// TODO: take optional chains as dependencies
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this one!

) {
// exclude non-reactive hook results, which will never be in a memo block
continue;
}

const {place, instructions} = writeDependencyToInstructions(
const dep = truncateDepAtCurrent(maybeDep);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thank you!

IIUC, the IDE has access to all of the paths but we'll still need to look inside the effect body for property accesses/optional chains that correspond to deps, is that right?

And #32099 would make this easier because it would hoist the deps into temporaries that would be re-used inside the body.

mofeiZ added 3 commits May 22, 2025 15:44
When collecting scope dependencies, mark each dependency with `reactive: true | false`. This prepares for later PRs #33326 and #32099 which rewrite scope dependencies into instructions.

Note that some reactive objects may have non-reactive properties, but we do not currently track this.

Technically, state[0] is reactive and state[1] is not. Currently, both would be marked as reactive.
```js
const state = useState();
```
Inferred effect dependencies now include optional chains.

This is a temporary solution while #32099 and its followups are worked on. Ideally, we should model reactive scope dependencies in the IR similarly to `ComputeIR` -- dependencies should be hoisted and all references rewritten to use the hoisted dependencies.

`
mofeiZ added a commit that referenced this pull request May 22, 2025
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32286).
* #33326
* #33325
* __->__ #32286
mofeiZ added a commit that referenced this pull request May 22, 2025
When collecting scope dependencies, mark each dependency with `reactive:
true | false`. This prepares for later PRs
#33326 and
#32099 which rewrite scope
dependencies into instructions.

Note that some reactive objects may have non-reactive properties, but we
do not currently track this.

Technically, state[0] is reactive and state[1] is not. Currently, both
would be marked as reactive.
```js
const state = useState();
```
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33325).
* #33326
* __->__ #33325
* #32286
@mofeiZ mofeiZ merged commit 0d07288 into main May 22, 2025
27 of 30 checks passed
github-actions bot pushed a commit that referenced this pull request May 22, 2025
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32286).
* #33326
* #33325
* __->__ #32286

DiffTrain build for [13f2004](13f2004)
github-actions bot pushed a commit that referenced this pull request May 22, 2025
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32286).
* #33326
* #33325
* __->__ #32286

DiffTrain build for [13f2004](13f2004)
github-actions bot pushed a commit that referenced this pull request May 22, 2025
…33326)

Inferred effect dependencies now include optional chains.

This is a temporary solution while
#32099 and its followups are
worked on. Ideally, we should model reactive scope dependencies in the
IR similarly to `ComputeIR` -- dependencies should be hoisted and all
references rewritten to use the hoisted dependencies.

`
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33326).
* __->__ #33326
* #33325
* #32286

DiffTrain build for [0d07288](0d07288)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants