Commit Graph

64 Commits

Author SHA1 Message Date
salazarm e7d0053e65 [fizz] Fix validateIterable call (#24166)
* fix validate iterable call

* supports iterable

* gate test by experimental
2022-03-25 14:03:06 -04:00
Sebastian Markbåge c91892ec3c [Fizz] Don't flush empty segments (#24054)
Before this change, we would sometimes write segments without any content
in them. For example for a Suspense boundary that immediately suspends
we might emit something like:

<div hidden id="123">
  <template id="456"></template>
</div>

Where the outer div is just a temporary wrapper and the inner one is a
placeholder for something to be added later.

This serves no purpose.

We should ideally have a heuristic that holds back segments based on byte
size and time. However, this is a straight forward clear win for now.
2022-03-08 23:12:50 -05:00
Sebastian Markbåge 14c2be8dac Rename Node SSR Callbacks to onShellReady/onAllReady and Other Fixes (#24030)
* I forgot to call onFatalError

I can't figure out how to write a test for this because it only happens
when there is a bug in React itself which would then be fixed if we found
it.

We're also covered by the protection of ReadableStream which doesn't leak
other errors to us.

* Abort requests if the reader cancels

No need to continue computing at this point.

* Abort requests if node streams get destroyed

This is if the downstream cancels is for example.

* Rename Node APIs for Parity with allReady

The "Complete" terminology is a little misleading because not everything
has been written yet. It's just "Ready" to be written now.

onShellReady
onShellError
onAllReady

* 'close' should be enough
2022-03-04 14:38:46 -05:00
Sebastian Markbåge cb1e7b1c6c Move onCompleteAll to .allReady Promise (#24025)
* Move onCompleteAll to .allReady Promise

The onCompleteAll callback can sometimes resolve before the promise that
returns the stream which is tough to coordinate. A more idiomatic API
for a one shot event is a Promise.

That way the way you render for SEO or SSG is:

const stream = await renderToReadableStream(...);
await stream.readyAll;
respondWith(stream);

Ideally this should be a sub-class of ReadableStream but we don't yet
compile these to ES6 and they'd had to be to native class to subclass
a native stream.

I have other ideas for overriding the .tee() method in a subclass anyway.
So this is inline with that strategy.

* Reject the Promise on fatal errors
2022-03-03 12:46:12 -05:00
Sebastian Markbåge 1ad8d81292 Remove object-assign polyfill (#23351)
* Remove object-assign polyfill

We really rely on a more modern environment where this is typically
polyfilled anyway and we don't officially support IE with more extensive
polyfilling anyway. So all environments should have the native version
by now.

* Use shared/assign instead of Object.assign in code

This is so that we have one cached local instance in the bundle.

Ideally we should have a compile do this for us but we already follow
this pattern with hasOwnProperty, isArray, Object.is etc.

* Transform Object.assign to now use shared/assign

We need this to use the shared instance when Object.spread is used.
2022-02-23 19:34:24 -05:00
Sebastian Markbåge 40351575d3 Split writeChunk into void and return value (#23343)
This function was modeled after Node streams where write returns a boolean
whether to keep writing or not. I think we should probably switch this
up and read desired size explicitly in appropriate places.

However, in the meantime, we don't have to return a value where we're
not going to use it. So I split this so that we call writeChunkAndReturn
if we're going to return the boolean.

This should help with the compilation so that they can be inlined.
2022-02-23 11:35:21 -05:00
Sebastian Markbåge 2c693b2dee Re-add reentrancy avoidance (#23342)
* tests: add failing test to demonstrate bug in ReadableStream implementation

* Re-add reentrancy avoidance

I removed the equivalency of this in #22446. However, I didn't fully
understand the intended semantics of the spec but I understand this better
now.

The spec is not actually recursive. It won't call pull again inside of a
pull. It might not call it inside startWork neither which the original
issue avoided. However, it will call pull if you enqueue to the controller
without filling up the desired size outside any call.

We could avoid that by returning a Promise from pull that we wait to
resolve until we've performed all our pending tasks. That would be the
more idiomatic solution. That's a bit more involved but since we know
understand it, we can readd the reentrancy hack since we have an easy place
to detect it. If anything, it should probably throw or log here otherwise.

I believe this fixes #22772.

This includes the test from #22889 but should ideally have one for Fizz.

Co-authored-by: Josh Larson <josh.larson@shopify.com>
2022-02-23 00:33:41 -05:00
Sebastian Markbåge 5690932765 Add onErrorShell Callback (#23247)
This indicates that an error has happened before the shell completed and
there's no point in emitting the result of this stream.

This is not quite the same as other fatal errors that can happen even
after streaming as started.

It's also not quite the same as onError before onCompleteShell because
onError can be called for an error inside a Suspense boundary before the
shell completes.

Implement shell error handling in Node SSR fixtures

Instead of hanging indefinitely.

Update Browser Fixture

Expose onErrorShell to the Node build

This API is not Promisified so it's just a separate callback instead.

Promisify the Browser Fizz API

It's now a Promise of a readable stream. The Promise resolves when the
shell completes. If the shell errors, the Promise is rejected.
2022-02-08 22:38:14 -05:00
Andrew Clark 848e802d20 Add onRecoverableError option to hydrateRoot, createRoot (#23207)
* [RFC] Add onHydrationError option to hydrateRoot

This is not the final API but I'm pushing it for discussion purposes.

When an error is thrown during hydration, we fallback to client
rendering, without triggering an error boundary. This is good because,
in many cases, the UI will recover and the user won't even notice that
something has gone wrong behind the scenes.

However, we shouldn't recover from these errors silently, because the
underlying cause might be pretty serious. Server-client mismatches are
not supposed to happen, even if UI doesn't break from the users
perspective. Ignoring them could lead to worse problems later. De-opting
from server to client rendering could also be a significant performance
regression, depending on the scope of the UI it affects.

So we need a way to log when hydration errors occur.

This adds a new option for `hydrateRoot` called `onHydrationError`. It's
symmetrical to the server renderer's `onError` option, and serves the
same purpose.

When no option is provided, the default behavior is to schedule a
browser task and rethrow the error. This will trigger the normal browser
behavior for errors, including dispatching an error event. If the app
already has error monitoring, this likely will just work as expected
without additional configuration.

However, we can also expose additional metadata about these errors, like
which Suspense boundaries were affected by the de-opt to client
rendering. (I have not exposed any metadata in this commit; API needs
more design work.)

There are other situations besides hydration where we recover from an
error without surfacing it to the user, or notifying an error boundary.
For example, if an error occurs during a concurrent render, it could be
due to a data race, so we try again synchronously in case that fixes it.
We should probably expose a way to log these types of errors, too. (Also
not implemented in this commit.)

* Log all recoverable errors

This expands the scope of onHydrationError to include all errors that
are not surfaced to the UI (an error boundary). In addition to errors
that occur during hydration, this also includes errors that recoverable
by de-opting to synchronous rendering. Typically (or really, by
definition) these errors are the result of a concurrent data race;
blocking the main thread fixes them by prevents subsequent races.

The logic for de-opting to synchronous rendering already existed. The
only thing that has changed is that we now log the errors instead of
silently proceeding.

The logging API has been renamed from onHydrationError
to onRecoverableError.

* Don't log recoverable errors until commit phase

If the render is interrupted and restarts, we don't want to log the
errors multiple times.

This change only affects errors that are recovered by de-opting to
synchronous rendering; we'll have to do something else for errors
during hydration, since they use a different recovery path.

* Only log hydration error if client render succeeds

Similar to previous step.

When an error occurs during hydration, we only want to log it if falling
back to client rendering _succeeds_. If client rendering fails,
the error will get reported to the nearest error boundary, so there's
no need for a duplicate log.

To implement this, I added a list of errors to the hydration context.
If the Suspense boundary successfully completes, they are added to
the main recoverable errors queue (the one I added in the
previous step.)

* Log error with queueMicrotask instead of Scheduler

If onRecoverableError is not provided, we default to rethrowing the
error in a separate task. Originally, I scheduled the task with
idle priority, but @sebmarkbage made the good point that if there are
multiple errors logs, we want to preserve the original order. So I've
switched it to a microtask. The priority can be lowered in userspace
by scheduling an additional task inside onRecoverableError.

* Only use host config method for default behavior

Redefines the contract of the host config's logRecoverableError method
to be a default implementation for onRecoverableError if a user-provided
one is not provided when the root is created.

* Log with reportError instead of rethrowing

In modern browsers, reportError will dispatch an error event, emulating
an uncaught JavaScript error. We can do this instead of rethrowing
recoverable errors in a microtask, which is nice because it avoids any
subtle ordering issues.

In older browsers and test environments, we'll fall back
to console.error.

* Naming nits

queueRecoverableHydrationErrors -> upgradeHydrationErrorsToRecoverable
2022-02-04 07:57:33 -08:00
salazarm 3a44621296 Disable avoidThisFallback support in Fizz (#23224)
* disable fizz avoidThisFallback support

* true
2022-02-01 18:22:04 -05:00
Andrew Clark ebf9ae8579 useId (#22644)
* Add useId to dispatcher

* Initial useId implementation

Ids are base 32 strings whose binary representation corresponds to the
position of a node in a tree.

Every time the tree forks into multiple children, we add additional bits
to the left of the sequence that represent the position of the child
within the current level of children.

    00101       00010001011010101
    ╰─┬─╯       ╰───────┬───────╯
  Fork 5 of 20       Parent id

The leading 0s are important. In the above example, you only need 3 bits
to represent slot 5. However, you need 5 bits to represent all the forks
at the current level, so we must account for the empty bits at the end.

For this same reason, slots are 1-indexed instead of 0-indexed.
Otherwise, the zeroth id at a level would be indistinguishable from
its parent.

If a node has only one child, and does not materialize an id (i.e. does
not contain a useId hook), then we don't need to allocate any space in
the sequence. It's treated as a transparent indirection. For example,
these two trees produce the same ids:

<>                          <>
  <Indirection>               <A />
    <A />                     <B />
  </Indirection>            </>
  <B />
</>

However, we cannot skip any materializes an id. Otherwise, a parent id
that does not fork would be indistinguishable from its child id. For
example, this tree does not fork, but the parent and child must have
different ids.

<Parent>
  <Child />
</Parent>

To handle this scenario, every time we materialize an id, we allocate a
new level with a single slot. You can think of this as a fork with only
one prong, or an array of children with length 1.

It's possible for the the size of the sequence to exceed 32 bits, the
max size for bitwise operations. When this happens, we make more room by
converting the right part of the id to a string and storing it in an
overflow variable. We use a base 32 string representation, because 32 is
the largest power of 2 that is supported by toString(). We want the base
to be large so that the resulting ids are compact, and we want the base
to be a power of 2 because every log2(base) bits corresponds to a single
character, i.e. every log2(32) = 5 bits. That means we can lop bits off
the end 5 at a time without affecting the final result.

* Incremental hydration

Stores the tree context on the dehydrated Suspense boundary's state
object so it resume where it left off.

* Add useId to react-debug-tools

* Add selective hydration test

Demonstrates that selective hydration works and ids are preserved even
after subsequent client updates.
2021-11-01 13:30:44 -07:00
Sebastian Markbåge cdb8a1d19d [Fizz] Add option to inject bootstrapping script tags after the shell is injected (#22594)
* Add option to inject bootstrap scripts

These are emitted right after the shell as flushed.

* Update ssr fixtures to use bootstrapScripts instead of manual script tag

* Add option to FB renderer too
2021-10-19 19:36:10 -07:00
Andrew Clark a724a3b578 [RFC] Codemod invariant -> throw new Error (#22435)
* Hoist error codes import to module scope

When this code was written, the error codes map (`codes.json`) was
created on-the-fly, so we had to lazily require from inside the visitor.

Because `codes.json` is now checked into source, we can import it a
single time in module scope.

* Minify error constructors in production

We use a script to minify our error messages in production. Each message
is assigned an error code, defined in `scripts/error-codes/codes.json`.
Then our build script replaces the messages with a link to our
error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92

This enables us to write helpful error messages without increasing the
bundle size.

Right now, the script only works for `invariant` calls. It does not work
if you throw an Error object. This is an old Facebookism that we don't
really need, other than the fact that our error minification script
relies on it.

So, I've updated the script to minify error constructors, too:

Input:
  Error(`A ${adj} message that contains ${noun}`);
Output:
  Error(formatProdErrorMessage(ERR_CODE, adj, noun));

It only works for constructors that are literally named Error, though we
could add support for other names, too.

As a next step, I will add a lint rule to enforce that errors written
this way must have a corresponding error code.

* Minify "no fallback UI specified" error in prod

This error message wasn't being minified because it doesn't use
invariant. The reason it didn't use invariant is because this particular
error is created without begin thrown — it doesn't need to be thrown
because it's located inside the error handling part of the runtime.

Now that the error minification script supports Error constructors, we
can minify it by assigning it a production error code in
`scripts/error-codes/codes.json`.

To support the use of Error constructors more generally, I will add a
lint rule that enforces each message has a corresponding error code.

* Lint rule to detect unminified errors

Adds a lint rule that detects when an Error constructor is used without
a corresponding production error code.

We already have this for `invariant`, but not for regular errors, i.e.
`throw new Error(msg)`. There's also nothing that enforces the use of
`invariant` besides convention.

There are some packages where we don't care to minify errors. These are
packages that run in environments where bundle size is not a concern,
like react-pg. I added an override in the ESLint config to ignore these.

* Temporarily add invariant codemod script

I'm adding this codemod to the repo temporarily, but I'll revert it
in the same PR. That way we don't have to check it in but it's still
accessible (via the PR) if we need it later.

* [Automated] Codemod invariant -> Error

This commit contains only automated changes:

npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*"
yarn linc --fix
yarn prettier

I will do any manual touch ups in separate commits so they're easier
to review.

* Remove temporary codemod script

This reverts the codemod script and ESLint config I added temporarily
in order to perform the invariant codemod.

* Manual touch ups

A few manual changes I made after the codemod ran.

* Enable error code transform per package

Currently we're not consistent about which packages should have their
errors minified in production and which ones should.

This adds a field to the bundle configuration to control whether to
apply the transform. We should decide what the criteria is going
forward. I think it's probably a good idea to minify any package that
gets sent over the network. So yes to modules that run in the browser,
and no to modules that run on the server and during development only.
2021-09-30 12:01:28 -07:00
Sebastian Markbåge 7843b142ac [Fizz/Flight] Pass in Destination lazily to startFlowing instead of in createRequest (#22449)
* Pass in Destination lazily in startFlowing instead of createRequest

* Delay fatal errors until we have a destination to forward them to

* Flow can now be inferred by whether there's a destination set

We can drop the destination when we're not flowing since there's nothing to
write to.

Fatal errors now close once flowing starts back up again.

* Defer fatal errors in Flight too
2021-09-28 15:32:09 -07:00
Sebastian Markbåge eba248c390 [Fizz/Flight] Remove reentrancy hack (#22446)
* Remove reentrant check from Fizz/Flight

* Make startFlowing explicit in Flight

This is already an explicit call in Fizz. This moves flowing to be explicit.

That way we can avoid calling it in start() for web streams and therefore
avoid the reentrant call.

* Add regression test

This test doesn't actually error due to the streams polyfill not behaving
like Chrome but rather according to spec.

* Update the Web Streams polyfill

Not that we need this but just in case there are differences that are fixed.
2021-09-27 17:47:56 -07:00
Sebastian Markbåge 2cc6d79c98 Rename onReadyToStream to onCompleteShell (#22443) 2021-09-27 12:38:22 -07:00
Sebastian Markbåge d47339ea36 [Fizz] Remove assignID mechanism (#22410)
* Remove pushEmpty

This is only used to support the assignID mechanism.

* Remove assignID mechanism

This effectively isn't used anyway because we always insert a dummy tag
into the fallback.

* Emit the template tag with an ID directly in pending boundaries

This ensures that assigning the ID is deterministic since it's done during
writing.

This also avoids emitting it for client rendered boundaries that start as
client rendered since we never need to refer to them.

* Move lazy ID initialization to the core implementation

We never need an ID before we write a pending boundary. This also ensures
that ID generation is deterministic by moving it to the write phase.

* Simplify the inserted scripts

We can assume that there are no text nodes before the template tag so this
simplifies the script that finds the comment node. It should be the direct
previous child.
2021-09-24 10:22:02 -04:00
salazarm 64e70f82e9 [Fizz] add avoidThisFallback support (#22318) 2021-09-20 15:44:48 -04:00
Sebastian Markbåge 321087d134 [Fizz] Don't add aborted segments to the completedSegments list (#21976)
* Don't add aborted segments to the completedSegments list

* Update error message to include aborted status
2021-07-27 21:53:37 -04:00
Deniz Susman 3f62dec84a Typo fix (#21729)
emitted instead of emmitted
2021-07-19 17:19:52 -04:00
Ricky 14bac6193a Allow components to render undefined (#21869) 2021-07-13 15:48:11 -04:00
Sebastian Markbåge 502f8a2a07 [Fizz/Flight] Don't use default args (#21681)
* Don't use default args

* Hoist out creation for better inlining

The closures prevent inlining otherwise.
2021-06-14 15:28:20 -07:00
Sebastian Markbåge dbe3363ccd [Fizz] Implement Legacy renderToString and renderToNodeStream on top of Fizz (#21276)
* Wire up DOM legacy build

* Hack to filter extra comments for testing purposes

* Use string concat in renderToString

I think this might be faster. We could probably use a combination of this
technique in the stream too to lower the overhead.

* Error if we can't complete the root synchronously

Maybe this should always error but in the async forms we can just delay
the stream until it resolves so it does have some useful semantics.

In the synchronous form it's never useful though. I'm mostly adding the
error because we're testing this behavior for renderToString specifically.

* Gate memory leak tests of internals

These tests don't translate as is to the new implementation and have been
ported to the Fizz tests separately.

* Enable Fizz legacy mode in stable

* Add wrapper around the ServerFormatConfig for legacy mode

This ensures that we can inject custom overrides without negatively
affecting the new implementation.

This adds another field for static mark up for example.

* Wrap pushTextInstance to avoid emitting comments for text in static markup

* Don't emit static mark up for completed suspense boundaries

Completed and client rendered boundaries are only marked for the client
to take over.

Pending boundaries are still supported in case you stream non-hydratable
mark up.

* Wire up generateStaticMarkup to static API entry points

* Mark as renderer for stable

This shouldn't affect the FB one ideally but it's done with the same build
so let's hope this works.
2021-06-14 12:54:30 -07:00
Sebastian Markbåge e0d9b28999 [Fizz] Minor Fixes for Warning Parity (#21618) 2021-06-03 19:54:31 -04:00
Sebastian Markbåge 1b7b3592f4 [Fizz] Implement Component Stacks in DEV for warnings (#21610)
* Implement component stacks

This uses a reverse linked list in DEV-only to keep track of where we're
currently executing.

* Fix bug that wasn't picking up the right stack at suspended boundaries

This makes it more explicit which stack we pass in to be retained by the
task.
2021-06-03 13:02:41 -07:00
Sebastian Markbåge bd4f056a3e [Fizz] Implement lazy components and nodes (#21355)
* Implement lazy components

* Implement lazy elements / nodes

This is used by Flight to encode not yet resolved nodes of any kind.
2021-04-26 18:46:46 -07:00
Sebastian Markbåge 9cd52b27fe Restore context after an error happens (#21341)
Typically we don't need to restore the context here because we assume that
we'll terminate the rest of the subtree so we don't need the correct
context since we're not rendering any siblings.

However, after a nested suspense boundary we need to restore the context.
The boundary could do this but since we're already doing this in the
suspense branch of renderNode, we might as well do it in the error case
which isn't very perf sensitive anyway.
2021-04-23 12:24:10 -07:00
Sebastian Markbåge 709f948412 [Fizz] Add FB specific streaming API and build (#21337)
Add FB specific streaming API and build
2021-04-22 16:54:29 -07:00
Sebastian Markbåge cc4b431dab Mark boundary as client rendered even if aborting fallback (#21294) 2021-04-15 19:16:40 -04:00
Sebastian Markbåge 9eddfbf5af [Fizz] Two More Fixes (#21288)
* Emit value of option tags

* Mask the legacy context passed to classes
2021-04-15 10:26:49 -07:00
Sebastian Markbåge 96d00b9bba [Fizz] Random Fixes (#21277) 2021-04-14 23:29:30 -04:00
Sebastian Markbåge 81ef539535 Always insert a dummy node with an ID into fallbacks (#21272) 2021-04-14 15:39:51 -07:00
Sebastian Markbåge a4a940d7a1 [Fizz] Add unsupported Portal/Scope components (#21261)
* Update Portal error message

* Add Scope Component
2021-04-14 14:35:36 -07:00
Sebastian Markbåge f4d7a0f1ea Implement useOpaqueIdentifier (#21260)
The format of this ID is specific to the format.
2021-04-14 14:25:42 -07:00
Sebastian Markbåge dde875dfb1 [Fizz] Implement Hooks (#21257)
* Implement Fizz Hooks

This is pretty much just a copy of the partial renderer Hooks.

* Implement forward ref and memo
2021-04-14 14:16:41 -07:00
Sebastian Markbåge a597c2f5dc [Fizz] Fix reentrancy bug (#21270)
* Fix reentrancy bug

* Fix another reentrancy bug

There's also an issue if we try to schedule something to be client
rendered if its fallback hasn't rendered yet. So we don't do it
in that case.
2021-04-14 13:49:14 -07:00
Sebastian Markbåge 4f76a28c93 [Fizz] Implement New Context (#21255)
* Add NewContext module

This implements a reverse linked list tree containing the previous
contexts.

* Implement recursive algorithm

This algorithm pops the contexts back to a shared ancestor on the way down
the stack and then pushes new contexts in reverse order up the stack.

* Move isPrimaryRenderer to ServerFormatConfig

This is primarily intended to be used to support renderToString with a
separate build than the main one. This allows them to be nested.

* Wire up more element type matchers

* Wire up Context Provider type

* Wire up Context Consumer

* Test

* Implement reader in class

* Update error codez
2021-04-14 11:45:42 -07:00
Sebastian Markbåge dbadfa2c36 [Fizz] Classes Follow Up (#21253)
* Port Classes from Fiber to Fizz

* Test
2021-04-13 13:57:36 -07:00
Sebastian Markbåge 343710c923 [Fizz] Fragments and Iterable support (#21228) 2021-04-10 15:50:42 -04:00
Sebastian Markbåge b0407b55ff Support more empty types (#21225)
Undefined errors as a direct return value.

This changes semantics for "true" and functions to mirror the client.
2021-04-09 16:23:37 -07:00
Sebastian Markbåge cf45a623a1 [Fizz] Implement Classes (#21200)
* Legacy context

* Port Classes from Fiber to Fizz
2021-04-08 10:42:37 -07:00
Sebastian Markbåge ad6e6ec7bb [Fizz] Prepare Recursive Loop for More Types (#21186)
* Split out into helper functions

This is similar to the structure of beginWork in Fiber.

* Split the rendering of a node from recursively rendering a node

This lets us reuse render node at the root which doesn't spawn new work.
2021-04-07 11:29:06 -07:00
Sebastian Markbåge 172e89b4bf Reland Remove redundant initial of isArray (#21188)
* Remove redundant initial of isArray (#21163)

* Reapply prettier

* Type the isArray function with refinement support

This ensures that an argument gets refined just like it does if isArray is
used directly.

I'm not sure how to express with just a direct reference so I added a
function wrapper and confirmed that this does get inlined properly by
closure compiler.

* A few more

* Rename unit test to internal

This is not testing a bundle.

Co-authored-by: Behnam Mohammadi <itten@live.com>
2021-04-07 07:57:43 -07:00
Sebastian Markbage b4f119cdf1 Revert "Remove redundant initial of isArray (#21163)"
This reverts commit b130a0f5cd.
2021-04-01 15:19:00 -04:00
Behnam Mohammadi b130a0f5cd Remove redundant initial of isArray (#21163) 2021-04-01 10:50:48 -07:00
Sebastian Markbåge 1cf9978d89 Don't pass internals to callbacks (#21161)
I noticed that I accidentally pass the request object to public API callbacks
as "this".
2021-04-01 08:43:12 -07:00
Sebastian Markbåge b9e4c10e99 [Fizz] Implement all the DOM attributes and special cases (#21153)
* Implement DOM format config structure

* Styles

* Input warnings

* Textarea special cases

* Select special cases

* Option special cases

We read the currently selected value from the FormatContext.

* Warning for non-lower case HTML

We don't change to lower case at runtime anymore but keep the warning.

* Pre tags innerHTML needs to be prefixed

This is because if you do the equivalent on the client using innerHTML,
this is the effect you'd get.

* Extract errors
2021-03-31 17:39:38 -07:00
Sebastian Markbåge 0853aab74d Log all errors to console.error by default (#21130) 2021-03-29 19:39:55 -07:00
Sebastian Markbåge 32d6f39edd [Fizz] Support special HTML/SVG/MathML tags to suspend (#21113)
* Encode tables as a special insertion mode

The table modes are special in that its children can't be created outside
a table context so we need the segment container to be wrapped in a table.

* Move formatContext from Task to Segment

It works the same otherwise. It's just that this context needs to outlive
the task so that I can use it when writing the segment.

* Use template tag for placeholders and inserted dummy nodes with IDs

These can be used in any parent. At least outside IE11. Not sure yet what
happens in IE11 to these.

Not sure if these are bad for perf since they're special nodes.

* Add special wrappers around inserted segments depending on their insertion mode

* Allow the root namespace to be configured

This allows us to insert the correct wrappers when streaming into an
existing non-HTML tree.

* Add comment
2021-03-27 10:50:38 -07:00
Sebastian Markbåge 556644e237 Fix plurals (#21106) 2021-03-25 22:21:41 -04:00