Commit Graph
19463 Commits
Author SHA1 Message Date
Sebastian Markbåge 9c58a0b647 Update Flight fixture to use use() instead of Promise as a child (#26715)
The Promise as a child case seems buggy. It ends up throwing the Promise
as fatal when used in Sync rendering.
2023-04-24 14:00:25 -04:00
Sophie Alpert 9ee7964302 Fix escaping in ReactDOMInput code (#26630)
JSON.stringify isn't the right thing here. Luckily this doesn't look to have any security impact.
2023-04-24 10:33:11 -07:00
Sebastian Markbåge 2fa6323818 Restore server controlled form fields to whatever they should be (#26708)
Fizz can emit whatever it wants for the SSR version of these fields when
it's a function action so they might not align with what is in the
previous props. Therefore we need to force them to update if we're
updating to a non-function where they might be relevant again.
2023-04-23 17:44:28 -04:00
Andrew Clark 7ce765ec32 Clean up enableUseHook flag (#26707)
This has been statically enabled everywhere for months.
2023-04-23 14:50:17 -04:00
Sebastian Markbåge a21d1475ff [Flight] Fix File Upload in Node.js (#26700)
Use the Blob constructor + append with filename instead of File
constructor. Node.js doesn't expose a global File constructor but does
support it in this form.

Queue fields until we get the 'end' event from the previous file. We
rely on previous files being available by the time a field is resolved.
However, since the 'end' event in Readable is fired after two
micro-tasks, these are not resolved in order.

I use a queue of the fields while we're still waiting on files to
finish. This still doesn't resolve files and fields in order relative to
each other but that doesn't matter for our usage.
2023-04-22 01:04:24 -04:00
Josh Story 36e4cbe2e9 [Float][Flight] Flight support for Float (#26502)
Stacked on #26557 

Supporting Float methods such as ReactDOM.preload() are challenging for
flight because it does not have an easy means to convey direct
executions in other environments. Because the flight wire format is a
JSON-like serialization that is expected to be rendered it currently
only describes renderable elements. We need a way to convey a function
invocation that gets run in the context of the client environment
whether that is Fizz or Fiber.

Fiber is somewhat straightforward because the HostDispatcher is always
active and we can just have the FlightClient dispatch the serialized
directive.

Fizz is much more challenging becaue the dispatcher is always scoped but
the specific request the dispatch belongs to is not readily available.
Environments that support AsyncLocalStorage (or in the future
AsyncContext) we will use this to be able to resolve directives in Fizz
to the appropriate Request. For other environments directives will be
elided. Right now this is pragmatic and non-breaking because all
directives are opportunistic and non-critical. If this changes in the
future we will need to reconsider how widespread support for async
context tracking is.

For Flight, if AsyncLocalStorage is available Float methods can be
called before and after await points and be expected to work. If
AsyncLocalStorage is not available float methods called in the sync
phase of a component render will be captured but anything after an await
point will be a noop. If a float call is dropped in this manner a DEV
warning should help you realize your code may need to be modified.

This PR also introduces a way for resources (Fizz) and hints (Flight) to
flush even if there is not active task being worked on. This will help
when Float methods are called in between async points within a function
execution but the task is blocked on the entire function finishing.

This PR also introduces deduping of Hints in Flight using the same
resource keys used in Fizz. This will help shrink payload sizes when the
same hint is attempted to emit over and over again
2023-04-21 20:45:51 -07:00
Andrew Clark 8f42196892 Change DOM HostContext to number instead of string (#26698)
In React DOM, we use HostContext to represent the namespace of whatever
is currently rendering — SVG, Math, or HTML. Because there is a fixed
set of possible values, we can switch this to be a number instead. My
motivation is that I want to start tracking additional information in
this type, and I want to pack all of it into a single number instead of
turning it into an object. For better performance.

(In dev, the host context type is already an object that includes
additional information, but that's dev so who cares.)

Technically, before this change, the host context could be any namespace
URI string, but any value other than SVG or Math was treated the same
way. Only SVG and Math have special behavior. So in the new structure,
there are three enum values: SVG, Math, or None, which represents the
HTML namespace as well as all other possible namespaces.
2023-04-21 21:44:43 -04:00
Joe Savona 32dccd48d2 [hir] Remove flag for inlineUseMemo 2023-04-21 13:43:32 -07:00
Lauren Tan b40de89805 Run snap in ci 2023-04-21 15:22:56 -04:00
Lauren Tan 2b75c7915b Add @panicOnBailout support to snap
Test plan: tests pass with snap
2023-04-21 15:22:56 -04:00
Lauren Tan b184d8567c [be] Add snap to yarn commands 2023-04-21 15:22:56 -04:00
Andrew Clark 967d46c76c Add error boundary to Flight fixture (#26695)
Errors in form actions are now rethrown during render (#26689), so we
can handle them using an error boundary.
2023-04-21 14:23:50 -04:00
Jan Kassens 5d7ebb4b78 Allow Node.js 20 to build (#26693)
This is stable and appears to build w/o problem. I don't see why we
should disallow it.
2023-04-21 19:23:27 +01:00
Andrew Clark fd3fb8e3c5 Rethrow errors from form actions (#26689)
This is the next step toward full support for async form actions.

Errors thrown inside form actions should cause the form to re-render and
throw the error so it can be captured by an error boundary. The behavior
is the same if the `<form />` had an internal useTransition hook, which
is pretty much exactly how we implement it, too.

The first time an action is called, the form's HostComponent is
"upgraded" to become stateful, by lazily mounting a list of hooks. The
rest of the implementation for function components can be shared.

Because the error handling behavior added in this commit is just using
useTransition under-the-hood, it also handles pending states, too.
However, this pending state can't be observed until we add a new hook
for that purpose. I'll add this next.
2023-04-21 13:29:46 -04:00
Jan Kassens c57a0f68a4 Remove react-is download hack (#26692)
This was added during an upgrade to Jest 24 in
https://github.com/facebook/react/pull/15778

By now we're at Jest 29. I think if CI passes we might not need this
hack anymore.
2023-04-21 13:11:09 -04:00
Joe Savona aa3edc8130 Cleanup unused wasm-based DOT diagram renderer
I forgot to remove this when we removed the diagram output. This brings test 
time from 6s -> 5s on my machine, still much slower than the new test runner in 
#1486.
2023-04-21 08:03:38 -07:00
Joe Savona 4a67d539dc Prune scopes wo own outputs
#1507 Ensured that declarations of reactive scopes were propagated to parent 
reactive scopes as necessary to ensure that those declarations would be 
available at the appropriate block scope. This meant that some scopes that were 
previously pruned would no longer be pruned. Specifically, an outer scope wo any 
declarations, but which contained a nested scope _with_ a propagated 
declaration, would now end up with non-empty declarations and not be pruned. 

This PR changes to track the declaring scope of each declaration, so we still 
prune scopes that don't have any of their own declarations.
2023-04-21 08:03:37 -07:00
Joe Savona cb72726e38 Cleanup Stack impl
Originally I defined `Stack` as an interface to ensure both Node and Empty 
variants would have an identical API. But exporting an interface allows a 
developer to define other implementations, when we really want to ensure that a 
Stack is precisely a Node or Empty instance. This PR changes to exporting a 
union of `Stack = Node | Empty`, and makes the interface private to the module.
2023-04-21 08:03:37 -07:00
Joe Savona f4896b45b2 Fix temporaries accessed outside of their defining scope
Fixed a bug identified in repro cases earlier in the stack. The case is where 
some later value is composed of several values, say A and B, where A is an 
identifier that is reassigned within B. Also, the mutable range of B surrounds 
the evaluation of A. In this case, the reference to A gets lowered to a 
temporary (say a t0 = LoadLocal A), and that temporary is created within the 
reactive scope for B. 

PropagateScopeDependencies bypasses LoadLocal indirections, and considers the 
reference to the temporary (t0) as if it was a reference to the identifier (A). 
That breaks the whole reason we lower Identifiers to temporaries - to preserve 
evaluation order. 

This PR fixes the bug by promoting temporaries to names values if they are 
referenced outside their defining scope. So, the reference to t0 stays a 
reference to t0, which correctly preserves the value of A at the right point in 
time. 

This is all much easier to see in the new test case.
2023-04-20 18:52:39 -07:00
Itai Mizlish c8369527ef update broken icon link (circleCi status) (#26688)
looks better now 🚀
2023-04-20 18:28:45 -07:00
Joe Savona e9abc41ea3 Fix evaluation order for JSX element tags
When lowering a JSX element we were correctly lowering to a temporary in all but 
one case: the common case of an identifier. That is fine in practice but breaks 
in the presence of the tag identifier being reassigned in the props/children. 
This PR fixes to always lower the tag to a temporary.
2023-04-20 16:48:34 -07:00
Joe Savona db378d39f3 Constant propagation for globals
This PR updates ConstantPropagation to support propagating global references: 

```javascript 

// Before 

const x = Math; 

foo(x); 

// After 

foo(Math); 

``` 

This is a generally useful optimization but also helps with a subset of cases 
around JSX element tags, which are frequently globals.
2023-04-20 16:48:30 -07:00
Joe Savona 5c9614785c [codegen] Create new temporary map when entering reactive scopes
During codegen, when we now cache and restore the temporary values map as we 
enter and exit the scope. This ensures that any temporaries within the reactive 
scope are only visible within that scope, and not to subsequent code. In a 
subsequent PR this surfaces a bug with temporaries not correctly exported from a 
reactive scope.
2023-04-20 16:48:26 -07:00
Joe Savona c72452895a [codegen] validate that temporary values are set
In codegen when we lower an operand we check to see if we have an already 
lowered value for it (stored in `cx.temp`). Currently we silently handle missing 
values by emitting a raw identifier, but this is really an error. This PR adds 
validation, which uncovered a few places where we legitimately won't have a 
value - things like function parameters that got swapped for temporaries bc of 
destructuring. We populate those as `null` values now, and fail if a temporary 
had a truly missing value.
2023-04-20 16:48:22 -07:00
Josh Story cc93a85332 [Fiber] InvokeGuardedCallback without metaprogramming (#26569)
InvokeGuardedCallback is now implemented with the browser fork done at
error-time rather than module-load-time. Originally it also tried to
freeze the window/document references to avoid mismatches in prototype
chains when testing React in different documents however we have since
updated our tests to not do this and it was a test only feature so I
removed it.
2023-04-20 15:08:51 -07:00
Josh Story fdad813ac7 [Float][Fiber] Enable Float methods to be called outside of render (#26557)
Stacked on #26570 

Previously we restricted Float methods to only being callable while
rendering. This allowed us to make associations between calls and their
position in the DOM tree, for instance hoisting preinitialized styles
into a ShadowRoot or an iframe Document.

When considering how we are going to support Flight support in Float
however it became clear that this restriction would lead to compromises
on the implementation because the Flight client does not execute within
the context of a client render. We want to be able to disaptch Float
directives coming from Flight as soon as possible and this requires
being able to call them outside of render.

this patch modifies Float so that its methods are callable anywhere. The
main consequence of this change is Float will always use the Document
the renderer script is running within as the HoistableRoot. This means
if you preinit as style inside a component render targeting a ShadowRoot
the style will load in the ownerDocument not the ShadowRoot. Practially
speaking it means that preinit is not useful inside ShadowRoots and
iframes.

This tradeoff was deemed acceptable because these methods are
optimistic, not critical. Additionally, the other methods, preconntect,
prefetchDNS, and preload, are not impacted because they already operated
at the level of the ownerDocument and really only interface with the
Network cache layer.

I added a couple additional fixes that were necessary for getting tests
to pass that are worth considering separately.

The first commit improves the diff for `waitForThrow` so it compares
strings if possible.

The second commit makes invokeGuardedCallback not use metaprogramming
pattern and swallows any novel errors produced from trying to run the
guarded callback. Swallowing may not be the best we can do but it at
least protects React against rapid failure when something causes the
dispatchEvent to throw.
2023-04-20 14:40:25 -07:00
Josh Story e5708b3ea9 [Tests][Fizz] Better HTML parsing behavior for Fizz tests (#26570)
In anticipation of making Fiber use the document global for dispatching
Float methods that arrive from Flight I needed to update some tests that
commonly recreated the JSDOM instance after importing react.

This change updates a few tests to only create JSDOM once per test,
before importing react-dom/client.

Additionally the current act implementation for server streaming did not
adequately model streaming semantics so I rewrite the act implementation
in a way that better mirrors how a browser would parse incoming HTML.

The new act implementation does the following

1. the first time it processes meaningful streamed content it figures
out whether it is rendering into the existing document container or if
it needs to reset the document. this is based on whether the streamed
content contains tags `<html>` or `<body>` etc...
2. Once the streaming container is set it will typically continue to
stream into that container for future calls to act. The exception is if
the streaming container is the `<head>` in which case it will switch to
streaming into the body once it receives a `<body>` tag.

This means for tests that render something like a `<div>...</div>` it
will naturally stream into the default `<div id="container">...` and for
tests that render a full document the HTML will parse like a real
browser would (with some very minor edge case differences)

I also refactored the way we move nodes from buffered content into the
document and execute any scripts we find. Previously we were using
window.eval and I switched this to just setting the external script
content as script text. Additionally the nonce logic is reworked to be a
bit simpler.
2023-04-20 14:27:02 -07:00
Lauren Tan 8bab0bca3c [babel] Compile individual components
Updates the Babel plugin so that we can individually compile components and skip 
over ones that have non-critical errors
2023-04-20 16:21:40 -04:00
Lauren Tan c228d63f03 [babel] Add panicOnBailout option
Adds an option to always throw errors regardless of severity (default, ie the 
status quo), or when the flag is disabled, only critical errors will be thrown. 
Any error that isn't considered a critical error (see 
`CompilerError.isCritical()`) since it might indicate that the compiler is 
buggy, while non-critical errors will result in that file being skipped for 
compilation, but otherwise continue compiling other files
2023-04-20 16:21:40 -04:00
Andrew Clark d73d7d5908 Add alwaysThrottleRetries flag (#26685)
This puts the change introduced by #26611 behind a flag until Meta is
able to roll it out. Disabling the flag reverts back to the old
behavior, where retries are throttled if there's still data remaining in
the tree, but not if all the data has finished loading.

The new behavior is still enabled in the public builds.
2023-04-20 14:23:22 -04:00
Joe Savona 275c755715 Repro for jsx lowering issues
* JSX tag value temporaries getting promoted due to being sandwiched inside the 
mutation of some other item 

* Incorrect order-of-evaluation for jsx tag relative to props/children
2023-04-20 09:29:37 -07:00
Ruslan Lesiutin 7f8c501f68 React DevTools 4.27.5 -> 4.27.6 (#26684)
Full list of changes:
* Use .slice() for all substring-ing
([sophiebits](https://github.com/sophiebits) in
[#26677](https://github.com/facebook/react/pull/26677))
* cleanup[devtools]: remove named hooks & profiler changed hook indices
feature flags ([hoxyq](https://github.com/hoxyq) in
[#26635](https://github.com/facebook/react/pull/26635))
* chore[devtools/release-scripts]: update messages / fixed npm view com…
([hoxyq](https://github.com/hoxyq) in
[#26660](https://github.com/facebook/react/pull/26660))
* (patch)[DevTools] bug fix: backend injection logic not working for
undocked devtools window ([mondaychen](https://github.com/mondaychen) in
[#26665](https://github.com/facebook/react/pull/26665))
* use backend manager to support multiple backends in extension
([mondaychen](https://github.com/mondaychen) in
[#26615](https://github.com/facebook/react/pull/26615))
2023-04-20 13:34:25 +01:00
Sophie Alpert 22d5942675 Add two event system cleanup TODOs (#26678)
There is so much old stuff in these files. I am weeping.
2023-04-19 18:41:46 -07:00
Sophie Alpert 767f52237c Use .slice() for all substring-ing (#26677)
- substr is Annex B
- substring silently flips its arguments if they're in the "wrong order", which is confusing
- slice is better than sliced bread (no pun intended) and also it works the same way on Arrays so there's less to remember

---

> I'd be down to just lint and enforce a single form just for the potential compression savings by using a repeated string.

_Originally posted by @sebmarkbage in https://github.com/facebook/react/pull/26663#discussion_r1170455401_
2023-04-19 14:26:01 -07:00
Joe Savona 3aa6196e30 Starting point for a new, parallel test runner to replace our hacked Jest
snapshotting 

As demo'd on our sync. This is meant as a replacement for `yarn test` just for 
fixtures. On my machine, a test run from a steady state of Jest watch mode takes 
6 seconds. With this script, it takes ~800ms. 

Workflow: make edits in `packages/snap/`, then `yarn build` in that directory to 
build the test runner. 

To run tests, `node packages/snap/dist/runner.js` from the main forget/ 
directory to run tests. Pass `--watch` for watch mode, `--update` to update 
snapshots. Note that this _only_ updates .expect.md files, it does not update 
Jest's `__snapshots__` directory (this is intentional, our use of Jest snapshots 
is a hack that this script is meant to replace). 

When running in watch mode, ctrl-c or q will quit, 'u' will update snapshots, 
and any other key will re-run tests. Tests will re-run on changes to the source 
code (after an incremental TS rebuild) and on changes to the fixtures. 

Main things that are missing: 

* Don't run tests if TS compilation had errors (the errors should be logged to 
console already, but we need to wire that up so that we abort tests if there are 
errors) 

* Actually delete stale files in update mode (there is some commented-out code 
to double-check and then uncomment) 

* Improve diff view: just print the diffed segments, not the whole file diff. 
See the API at https://github.com/facebook/jest/tree/main/packages/jest-diff 
(right now we're using `diff()` but should probably use one of the lower-level 
functions) 

* Properly parse/validate args with `yargs`, add a help option, etc 

* In watch mode, when tests finish print a list of commands so users know what 
they can do (like Jest does) 

* Support skipping tests and selecting a single test to focus. Suggestions: 

* Name files with `skip.` to skip 

* Allow passing a test name to the script to run only tests matching that 
pattern, eg `node runner.js -p <pattern>` 

* In watch mode, support typing 'p' to prompt the user for a pattern. After 
that, support typing 'a' to clear the pattern and run all tests.
2023-04-19 14:07:06 -07:00
Sebastian Markbåge c826dc50de Add (Client) Functions as Form Actions (#26674)
This lets you pass a function to `<form action={...}>` or `<button
formAction={...}>` or `<input type="submit formAction={...}>`. This will
behave basically like a `javascript:` URL except not quite implemented
that way. This is a convenience for the `onSubmit={e => {
e.preventDefault(); const fromData = new FormData(e.target); ... }`
pattern.

You can still implement a custom `onSubmit` handler and if it calls
`preventDefault`, it won't invoke the action, just like it would if you
used a full page form navigation or javascript urls. It behaves just
like a navigation and we might implement it with the Navigation API in
the future.

Currently this is just a synchronous function but in a follow up this
will accept async functions, handle pending states and handle errors.

This is implemented by setting `javascript:` URLs, but these only exist
to trigger an error message if something goes wrong instead of
navigating away. Like if you called `stopPropagation` to prevent React
from handling it or if you called `form.submit()` instead of
`form.requestSubmit()` which by-passes the `submit` event. If CSP is
used to ban `javascript:` urls, those will trigger errors when these
URLs are invoked which would be a different error message but it's still
there to notify the user that something went wrong in the plumbing.

Next up is improving the SSR state with action replaying and progressive
enhancement.
2023-04-19 16:31:08 -04:00
Andrew Clark cd2b79dedd Initial (client-only) async actions support (#26621)
Implements initial (client-only) support for async actions behind a
flag. This is an experimental feature and the design isn't completely
finalized but we're getting closer. It will be layered alongside other
features we're working on, so it may not feel complete when considered
in isolation.

The basic description is you can pass an async function to
`startTransition` and all the transition updates that are scheduled
inside that async function will be grouped together. The `isPending`
flag will be set to true immediately, and only set back to false once
the async action has completed (as well as all the updates that it
triggers).

The ideal behavior would be that all updates spawned by the async action
are automatically inferred and grouped together; however, doing this
properly requires the upcoming (stage 2) Async Context API, which is not
yet implemented by browsers. In the meantime, we will fake this by
grouping together all transition updates that occur until the async
function has terminated. This can lead to overgrouping between unrelated
actions, which is not wrong per se, just not ideal.

If the `useTransition` hook is removed from the UI before an async
action has completed — for example, if the user navigates to a new page
— subsequent transitions will no longer be grouped with together with
that action.

Another consequence of the lack of Async Context is that if you call
`setState` inside an action but after an `await`, it must be wrapped in
`startTransition` in order to be grouped properly. If we didn't require
this, then there would be no way to distinguish action updates from
urgent updates caused by user input, too. This is an unfortunate footgun
but we can likely detect the most common mistakes using a lint rule.

Once Async Context lands in browsers, we can start warning in dev if we
detect an update that hasn't been wrapped in `startTransition`. Then,
longer term, once the feature is ubiquitous, we can rely on it for real
and allow you to call `setState` without the additional wrapper.

Things that are _not_ yet implemented in this PR, but will be added as
follow ups:

- Support for non-hook form of `startTransition`
- Canceling the async action scope if the `useTransition` hook is
deleted from the UI
- Anything related to server actions
2023-04-19 13:33:11 -04:00
Jan Kassens 6d394e3d26 [actions] commit from special branches iff they exist (#26673)
This creates 2 special branches. If these special branches exist, we'll
commit build artifacts from these branches, main otherwise.
2023-04-19 12:11:40 -04:00
Sebastian MarkbågeandSophie Alpert 1f248bdd71 Switching checked to null should leave the current value (#26667)
I accidentally made a behavior change in the refactor. It turns out that
when switching off `checked` to an uncontrolled component, we used to
revert to the concept of "initialChecked" which used to be stored on
state.

When there's a diff to this computed prop and the value of props.checked
is null, then we end up in a case where it sets `checked` to
`initialChecked`:


https://github.com/facebook/react/blob/5cbe6258bc436b1683080a6d978c27849f1d9a22/packages/react-dom-bindings/src/client/ReactDOMInput.js#L69

Since we never changed `initialChecked` and it's not relevant if
non-null `checked` changes value, the only way this "change" could
trigger was if we move from having `checked` to having null.

This wasn't really consistent with how `value` works, where we instead
leave the current value in place regardless. So this is a "bug fix" that
changes `checked` to be consistent with `value` and just leave the
current value in place. This case should already have a warning in it
regardless since it's going from controlled to uncontrolled.

Related to that, there was also another issue observed in
https://github.com/facebook/react/pull/26596#discussion_r1162295872 and
https://github.com/facebook/react/pull/26588

We need to atomically apply mutations on radio buttons. I fixed this by
setting the name to empty before doing mutations to value/checked/type
in updateInput, and then set the name to whatever it should be. Setting
the name is what ends up atomically applying the changes.

---------

Co-authored-by: Sophie Alpert <git@sophiebits.com>
2023-04-19 11:46:29 -04:00
Ruslan Lesiutin b90e8ebaa5 cleanup[devtools]: remove named hooks & profiler changed hook indices feature flags (#26635)
## Summary

Removing `enableNamedHooksFeature`, `enableProfilerChangedHookIndices`,
`enableProfilerComponentTree` feature flags, they are the same for all
configurations.
2023-04-19 10:05:31 +01:00
Ruslan Lesiutin a227bcd4f4 chore[devtools/release-scripts]: update messages / fixed npm view com… (#26660)
Some minor changes, observed while working on 24.7.5 release:
- Updated numeration of text instructions
- `reactjs.org` -> `react.dev`
- Fixed using `npm view` command for node 16+, `publish-release` script
currently fails if used with node 16+
2023-04-19 10:05:16 +01:00
Joe Savona a0777212df Propagate scope declarations to parent scopes
Fix for bug demonstrated in #1506. When we add variables as output of their 
defining scope, we need to propagate this information upwards to all parent 
scopes which are not current active.
2023-04-18 21:27:11 -07:00
Sophie Alpert c6db19f9cd [Flight] Serialize Date (#26622)
This is kind of annoying because Date implements toJSON so
JSON.stringify turns it into a string before calling our replacer
function.
2023-04-18 20:52:03 -07:00
Mengdi Chen 96fd2fb726 (patch)[DevTools] bug fix: backend injection logic not working for undocked devtools window (#26665)
bugfix for #26492

This bug would cause users unable to use the devtools (component tree
empty).

The else-if logic is broken when user switch to undocked devtools mode
(separate window) because `sender.tab` would exist in that case.
<img width="314" alt="image"
src="https://user-images.githubusercontent.com/1001890/232930094-05a74445-9189-4d50-baf1-a0360b29ef7e.png">

Tested on Chrome with a local build
2023-04-18 20:39:22 -04:00
Joe Savona fdbfac8f82 Repro for bug with memo vars at wrong block scope
Minimal(ish) repro of a bug we saw internally, where an output of a nested 
reactive scope is defined at the wrong block scope, and so later references to 
that value are invalid. 

The simplified structure is: 

``` 

scope0 inputs=[] outputs=[] { 

scope1 inputs=[] outputs=[t0] { 

t0 = ... 

} 

} 

t0 

``` 

Note that `t0` correctly appears as an output of the inner scope1, but not as an 
output of the outer scope0. We need to propagate outputs upward as necessary to 
ensure they are available at the right block scope: in this case, that would add 
`t0` as an output of scope0. 

An earlier version of PropagateScopeDependencies did this but it looks like it 
got lost along the way (not a big deal)
2023-04-18 16:10:00 -07:00
Joe Savona 746c1dbed5 Add common (Relay) hooks to playground environment
This aligns the playground configuration with our internal compiler 
configuration to make it easier to repro compilation issues on playground. There 
is a bug that doesn't repro right now and i suspect it's because of different 
hooks being configured. 

Test plan: 

Before: playground output has no obvious bugs, but is different than internal 
compilation output where the bug occurs 

After: playground output matches internal compilation output w the bug
2023-04-18 15:29:17 -07:00
Sebastian MarkbågeandSophie Alpert d8089f2cf2 [Flight Reply] Encode FormData (#26663)
Builds on top of https://github.com/facebook/react/pull/26661

This lets you pass FormData objects through the Flight Reply
serialization. It does that by prefixing each entry with the ID of the
reference and then the decoding side creates a new FormData object
containing only those fields (without the prefix).

Ideally this should be more generic. E.g. you should be able to pass
Blobs, Streams and Typed Arrays by reference inside plain objects too.
You should also be able to send Blobs and FormData in the regular Flight
serialization too so that they can go both directions. They should be
symmetrical. We'll get around to adding more of those features in the
Flight protocol as we go.

---------

Co-authored-by: Sophie Alpert <git@sophiebits.com>
2023-04-18 14:57:33 -04:00
Joe Savona de89ed32a2 Use implicit return (undefined)
Making ReturnTerminal.value non-nullable broke our optimization to elide final 
value-less return statements. We now check if a return value is explicitly 
`undefined` and elide the value in this case, which then also propagates to 
allow removing the final `return` statement of a function if the value is 
missing.
2023-04-18 11:12:27 -07:00
Joe Savona b10f60f2b9 Cleanup from non-nullable return value
Now that ReturnTerminal.value is non-nullable we can make 
ReactiveReturnTerminal.value also non-nullable, and remove a bunch of null 
checks.
2023-04-18 11:12:23 -07:00
Sophie Alpert 1b4a0daba8 Add assertions about <input> value dirty state (#26626)
Since this is an observable behavior and is hard to think about, seems
good to have tests for this.

The expected value included in each test is the behavior that existed
prior to #26546.
2023-04-18 11:03:36 -07:00