From 91c2cfe8140d4d476aa1547e4e979b9f59634ec3 Mon Sep 17 00:00:00 2001 From: sebmarkbage Date: Sun, 21 Apr 2024 16:56:26 +0000 Subject: [PATCH] Warn for Child Iterator of all types but allow Generator Components (#28853) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This doesn't change production behavior. We always render Iterables to our best effort in prod even if they're Iterators. But this does change the DEV warnings which indicates which are valid patterns to use. It's a footgun to use an Iterator as a prop when you pass between components because if an intermediate component rerenders without its parent, React won't be able to iterate it again to reconcile and any mappers won't be able to re-apply. This is actually typically not a problem when passed only to React host components but as a pattern it's a problem for composability. We used to warn only for Generators - i.e. Iterators returned from Generator functions. This adds a warning for Iterators created by other means too (e.g. Flight or the native Iterator utils). The heuristic is to check whether the Iterator is the same as the Iterable because that means it's not possible to get new iterators out of it. This case used to just yield non-sense like empty sets in DEV but not in prod. However, a new realization is that when the Component itself is a Generator Function, it's not actually a problem. That's because the React Element itself works as an Iterable since we can ask for new generators by calling the function again. So this adds a special case to allow the Generator returned from a Generator Function's direct child. The principle is “don’t pass iterators around” but in this case there is no iterator floating around because it’s between React and the JS VM. Also see #28849 for context on AsyncIterables. Related to this, but Hooks should ideally be banned in these for the same reason they're banned in Async Functions. DiffTrain build for [368202181e772d411b2445930aea1edd9428b09b](https://github.com/facebook/react/commit/368202181e772d411b2445930aea1edd9428b09b) --- .../facebook-www/JSXDEVRuntime-dev.classic.js | 11 ++-- .../facebook-www/JSXDEVRuntime-dev.modern.js | 11 ++-- compiled/facebook-www/REVISION | 2 +- compiled/facebook-www/React-dev.classic.js | 13 ++-- compiled/facebook-www/React-dev.modern.js | 13 ++-- compiled/facebook-www/ReactART-dev.classic.js | 64 +++++++++---------- compiled/facebook-www/ReactART-dev.modern.js | 64 +++++++++---------- .../facebook-www/ReactART-prod.classic.js | 10 +-- compiled/facebook-www/ReactART-prod.modern.js | 10 +-- compiled/facebook-www/ReactDOM-dev.classic.js | 64 +++++++++---------- compiled/facebook-www/ReactDOM-dev.modern.js | 64 +++++++++---------- .../facebook-www/ReactDOM-prod.classic.js | 12 ++-- compiled/facebook-www/ReactDOM-prod.modern.js | 12 ++-- .../ReactDOM-profiling.classic.js | 12 ++-- .../facebook-www/ReactDOM-profiling.modern.js | 12 ++-- .../ReactDOMServer-dev.classic.js | 51 ++++++++------- .../facebook-www/ReactDOMServer-dev.modern.js | 51 ++++++++------- .../ReactDOMServerStreaming-dev.modern.js | 49 ++++++++------ .../ReactDOMTesting-dev.classic.js | 64 +++++++++---------- .../ReactDOMTesting-dev.modern.js | 64 +++++++++---------- .../ReactDOMTesting-prod.classic.js | 14 ++-- .../ReactDOMTesting-prod.modern.js | 14 ++-- .../ReactReconciler-dev.classic.js | 64 +++++++++---------- .../ReactReconciler-dev.modern.js | 64 +++++++++---------- .../ReactReconciler-prod.classic.js | 8 +-- .../ReactReconciler-prod.modern.js | 8 +-- .../ReactTestRenderer-dev.classic.js | 64 +++++++++---------- .../ReactTestRenderer-dev.modern.js | 64 +++++++++---------- .../__test_utils__/ReactAllWarnings.js | 2 +- 29 files changed, 474 insertions(+), 481 deletions(-) diff --git a/compiled/facebook-www/JSXDEVRuntime-dev.classic.js b/compiled/facebook-www/JSXDEVRuntime-dev.classic.js index 24bb660b1c..aca1e65618 100644 --- a/compiled/facebook-www/JSXDEVRuntime-dev.classic.js +++ b/compiled/facebook-www/JSXDEVRuntime-dev.classic.js @@ -1388,11 +1388,14 @@ function validateChildKeys(node, parentType) { // but now we print a separate warning for them later. if (iteratorFn !== node.entries) { var iterator = iteratorFn.call(node); - var step; - while (!(step = iterator.next()).done) { - if (isValidElement(step.value)) { - validateExplicitKey(step.value, parentType); + if (iterator !== node) { + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } } } } diff --git a/compiled/facebook-www/JSXDEVRuntime-dev.modern.js b/compiled/facebook-www/JSXDEVRuntime-dev.modern.js index ce384b8f86..03db5d1548 100644 --- a/compiled/facebook-www/JSXDEVRuntime-dev.modern.js +++ b/compiled/facebook-www/JSXDEVRuntime-dev.modern.js @@ -1391,11 +1391,14 @@ function validateChildKeys(node, parentType) { // but now we print a separate warning for them later. if (iteratorFn !== node.entries) { var iterator = iteratorFn.call(node); - var step; - while (!(step = iterator.next()).done) { - if (isValidElement(step.value)) { - validateExplicitKey(step.value, parentType); + if (iterator !== node) { + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } } } } diff --git a/compiled/facebook-www/REVISION b/compiled/facebook-www/REVISION index 94d1ff4a8b..d7ae26c1bb 100644 --- a/compiled/facebook-www/REVISION +++ b/compiled/facebook-www/REVISION @@ -1 +1 @@ -857ee8cdf9af81bc94a7f04528fbda7fb2510eb4 +368202181e772d411b2445930aea1edd9428b09b diff --git a/compiled/facebook-www/React-dev.classic.js b/compiled/facebook-www/React-dev.classic.js index 750a7ff01b..50f86c9857 100644 --- a/compiled/facebook-www/React-dev.classic.js +++ b/compiled/facebook-www/React-dev.classic.js @@ -25,7 +25,7 @@ if ( ) { __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); } - var ReactVersion = '19.0.0-www-classic-8ac39151'; + var ReactVersion = '19.0.0-www-classic-29916c01'; // ATTENTION // When adding new symbols to this file, @@ -1963,11 +1963,14 @@ function validateChildKeys(node, parentType) { // but now we print a separate warning for them later. if (iteratorFn !== node.entries) { var iterator = iteratorFn.call(node); - var step; - while (!(step = iterator.next()).done) { - if (isValidElement(step.value)) { - validateExplicitKey(step.value, parentType); + if (iterator !== node) { + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } } } } diff --git a/compiled/facebook-www/React-dev.modern.js b/compiled/facebook-www/React-dev.modern.js index 953a6ea001..3a5fff5184 100644 --- a/compiled/facebook-www/React-dev.modern.js +++ b/compiled/facebook-www/React-dev.modern.js @@ -25,7 +25,7 @@ if ( ) { __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); } - var ReactVersion = '19.0.0-www-modern-f6026193'; + var ReactVersion = '19.0.0-www-modern-16b8232b'; // ATTENTION // When adding new symbols to this file, @@ -1966,11 +1966,14 @@ function validateChildKeys(node, parentType) { // but now we print a separate warning for them later. if (iteratorFn !== node.entries) { var iterator = iteratorFn.call(node); - var step; - while (!(step = iterator.next()).done) { - if (isValidElement(step.value)) { - validateExplicitKey(step.value, parentType); + if (iterator !== node) { + var step; + + while (!(step = iterator.next()).done) { + if (isValidElement(step.value)) { + validateExplicitKey(step.value, parentType); + } } } } diff --git a/compiled/facebook-www/ReactART-dev.classic.js b/compiled/facebook-www/ReactART-dev.classic.js index 4d9b5c4bbe..6382d7a0c9 100644 --- a/compiled/facebook-www/ReactART-dev.classic.js +++ b/compiled/facebook-www/ReactART-dev.classic.js @@ -63,7 +63,7 @@ function _assertThisInitialized(self) { return self; } -var ReactVersion = '19.0.0-www-classic-d14dfff2'; +var ReactVersion = '19.0.0-www-classic-ff6202ef'; var LegacyRoot = 0; var ConcurrentRoot = 1; @@ -6987,45 +6987,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -7036,9 +7027,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -7095,7 +7091,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -7120,7 +7116,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { diff --git a/compiled/facebook-www/ReactART-dev.modern.js b/compiled/facebook-www/ReactART-dev.modern.js index 81288d2065..8eaa781162 100644 --- a/compiled/facebook-www/ReactART-dev.modern.js +++ b/compiled/facebook-www/ReactART-dev.modern.js @@ -63,7 +63,7 @@ function _assertThisInitialized(self) { return self; } -var ReactVersion = '19.0.0-www-modern-41846fdd'; +var ReactVersion = '19.0.0-www-modern-3c131a55'; var LegacyRoot = 0; var ConcurrentRoot = 1; @@ -6776,45 +6776,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -6825,9 +6816,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -6884,7 +6880,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -6909,7 +6905,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { diff --git a/compiled/facebook-www/ReactART-prod.classic.js b/compiled/facebook-www/ReactART-prod.classic.js index 18b1f95247..10578236af 100644 --- a/compiled/facebook-www/ReactART-prod.classic.js +++ b/compiled/facebook-www/ReactART-prod.classic.js @@ -2217,7 +2217,7 @@ function createChildReconciler(shouldTrackSideEffects) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -2241,7 +2241,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (step.done) return deleteRemainingChildren(returnFiber, oldFiber), iteratorFn; if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), @@ -2254,7 +2254,7 @@ function createChildReconciler(shouldTrackSideEffects) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && @@ -10622,7 +10622,7 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "19.0.0-www-classic-4cca10ad", + version: "19.0.0-www-classic-a0422099", rendererPackageName: "react-art" }; var internals$jscomp$inline_1322 = { @@ -10653,7 +10653,7 @@ var internals$jscomp$inline_1322 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-classic-4cca10ad" + reconcilerVersion: "19.0.0-www-classic-a0422099" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1323 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/compiled/facebook-www/ReactART-prod.modern.js b/compiled/facebook-www/ReactART-prod.modern.js index e5464822c1..1b69ec7ded 100644 --- a/compiled/facebook-www/ReactART-prod.modern.js +++ b/compiled/facebook-www/ReactART-prod.modern.js @@ -2015,7 +2015,7 @@ function createChildReconciler(shouldTrackSideEffects) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -2039,7 +2039,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (step.done) return deleteRemainingChildren(returnFiber, oldFiber), iteratorFn; if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), @@ -2052,7 +2052,7 @@ function createChildReconciler(shouldTrackSideEffects) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && @@ -10101,7 +10101,7 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "19.0.0-www-modern-c36cdef3", + version: "19.0.0-www-modern-07af3a38", rendererPackageName: "react-art" }; var internals$jscomp$inline_1307 = { @@ -10132,7 +10132,7 @@ var internals$jscomp$inline_1307 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-modern-c36cdef3" + reconcilerVersion: "19.0.0-www-modern-07af3a38" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1308 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/compiled/facebook-www/ReactDOM-dev.classic.js b/compiled/facebook-www/ReactDOM-dev.classic.js index a414cd6332..f3900beede 100644 --- a/compiled/facebook-www/ReactDOM-dev.classic.js +++ b/compiled/facebook-www/ReactDOM-dev.classic.js @@ -10601,45 +10601,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -10650,9 +10641,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -10714,7 +10710,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -10744,7 +10740,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { @@ -30832,7 +30828,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-www-classic-3bfa22a0'; +var ReactVersion = '19.0.0-www-classic-f994293c'; function createPortal$1(children, containerInfo, // TODO: figure out the API for cross-renderer implementation. implementation) { diff --git a/compiled/facebook-www/ReactDOM-dev.modern.js b/compiled/facebook-www/ReactDOM-dev.modern.js index c4ccc49b16..6b455975fd 100644 --- a/compiled/facebook-www/ReactDOM-dev.modern.js +++ b/compiled/facebook-www/ReactDOM-dev.modern.js @@ -16011,45 +16011,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -16060,9 +16051,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -16124,7 +16120,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -16154,7 +16150,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { @@ -38739,7 +38735,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-www-modern-b1784c6b'; +var ReactVersion = '19.0.0-www-modern-f079875a'; function createPortal$1(children, containerInfo, // TODO: figure out the API for cross-renderer implementation. implementation) { diff --git a/compiled/facebook-www/ReactDOM-prod.classic.js b/compiled/facebook-www/ReactDOM-prod.classic.js index e58fb30310..e78add365e 100644 --- a/compiled/facebook-www/ReactDOM-prod.classic.js +++ b/compiled/facebook-www/ReactDOM-prod.classic.js @@ -2910,7 +2910,7 @@ function createChildReconciler(shouldTrackSideEffects) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -2938,7 +2938,7 @@ function createChildReconciler(shouldTrackSideEffects) { iteratorFn ); if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), @@ -2952,7 +2952,7 @@ function createChildReconciler(shouldTrackSideEffects) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && @@ -17036,7 +17036,7 @@ Internals.Events = [ var devToolsConfig$jscomp$inline_1729 = { findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "19.0.0-www-classic-7b6a2c60", + version: "19.0.0-www-classic-8e0d593f", rendererPackageName: "react-dom" }; var internals$jscomp$inline_2160 = { @@ -17066,7 +17066,7 @@ var internals$jscomp$inline_2160 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-classic-7b6a2c60" + reconcilerVersion: "19.0.0-www-classic-8e0d593f" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_2161 = __REACT_DEVTOOLS_GLOBAL_HOOK__; @@ -17532,4 +17532,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-www-classic-7b6a2c60"; +exports.version = "19.0.0-www-classic-8e0d593f"; diff --git a/compiled/facebook-www/ReactDOM-prod.modern.js b/compiled/facebook-www/ReactDOM-prod.modern.js index c08db8d7df..10bc67fc99 100644 --- a/compiled/facebook-www/ReactDOM-prod.modern.js +++ b/compiled/facebook-www/ReactDOM-prod.modern.js @@ -5211,7 +5211,7 @@ function createChildReconciler(shouldTrackSideEffects) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -5239,7 +5239,7 @@ function createChildReconciler(shouldTrackSideEffects) { iteratorFn ); if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), @@ -5253,7 +5253,7 @@ function createChildReconciler(shouldTrackSideEffects) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && @@ -16398,7 +16398,7 @@ Internals.Events = [ var devToolsConfig$jscomp$inline_1722 = { findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "19.0.0-www-modern-c7f3d35a", + version: "19.0.0-www-modern-c10596ab", rendererPackageName: "react-dom" }; var internals$jscomp$inline_2162 = { @@ -16428,7 +16428,7 @@ var internals$jscomp$inline_2162 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-modern-c7f3d35a" + reconcilerVersion: "19.0.0-www-modern-c10596ab" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_2163 = __REACT_DEVTOOLS_GLOBAL_HOOK__; @@ -16736,4 +16736,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-www-modern-c7f3d35a"; +exports.version = "19.0.0-www-modern-c10596ab"; diff --git a/compiled/facebook-www/ReactDOM-profiling.classic.js b/compiled/facebook-www/ReactDOM-profiling.classic.js index a23539bd11..4e94c87a19 100644 --- a/compiled/facebook-www/ReactDOM-profiling.classic.js +++ b/compiled/facebook-www/ReactDOM-profiling.classic.js @@ -3046,7 +3046,7 @@ function createChildReconciler(shouldTrackSideEffects) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -3074,7 +3074,7 @@ function createChildReconciler(shouldTrackSideEffects) { iteratorFn ); if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), @@ -3088,7 +3088,7 @@ function createChildReconciler(shouldTrackSideEffects) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && @@ -17784,7 +17784,7 @@ Internals.Events = [ var devToolsConfig$jscomp$inline_1815 = { findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "19.0.0-www-classic-7a3394e6", + version: "19.0.0-www-classic-21ff4feb", rendererPackageName: "react-dom" }; (function (internals) { @@ -17828,7 +17828,7 @@ var devToolsConfig$jscomp$inline_1815 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-classic-7a3394e6" + reconcilerVersion: "19.0.0-www-classic-21ff4feb" }); var ReactFiberErrorDialogWWW = require("ReactFiberErrorDialog"); if ("function" !== typeof ReactFiberErrorDialogWWW.showErrorDialog) @@ -18281,7 +18281,7 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-www-classic-7a3394e6"; +exports.version = "19.0.0-www-classic-21ff4feb"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/compiled/facebook-www/ReactDOM-profiling.modern.js b/compiled/facebook-www/ReactDOM-profiling.modern.js index 77e3550cde..4a2f4d9d91 100644 --- a/compiled/facebook-www/ReactDOM-profiling.modern.js +++ b/compiled/facebook-www/ReactDOM-profiling.modern.js @@ -5347,7 +5347,7 @@ function createChildReconciler(shouldTrackSideEffects) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -5375,7 +5375,7 @@ function createChildReconciler(shouldTrackSideEffects) { iteratorFn ); if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), @@ -5389,7 +5389,7 @@ function createChildReconciler(shouldTrackSideEffects) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && @@ -17129,7 +17129,7 @@ Internals.Events = [ var devToolsConfig$jscomp$inline_1808 = { findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "19.0.0-www-modern-6d2a2ca0", + version: "19.0.0-www-modern-6f4c1c9f", rendererPackageName: "react-dom" }; (function (internals) { @@ -17173,7 +17173,7 @@ var devToolsConfig$jscomp$inline_1808 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-modern-6d2a2ca0" + reconcilerVersion: "19.0.0-www-modern-6f4c1c9f" }); var ReactFiberErrorDialogWWW = require("ReactFiberErrorDialog"); if ("function" !== typeof ReactFiberErrorDialogWWW.showErrorDialog) @@ -17468,7 +17468,7 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-www-modern-6d2a2ca0"; +exports.version = "19.0.0-www-modern-6f4c1c9f"; "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && diff --git a/compiled/facebook-www/ReactDOMServer-dev.classic.js b/compiled/facebook-www/ReactDOMServer-dev.classic.js index e30a50ed09..26a068f465 100644 --- a/compiled/facebook-www/ReactDOMServer-dev.classic.js +++ b/compiled/facebook-www/ReactDOMServer-dev.classic.js @@ -19,7 +19,7 @@ if (__DEV__) { var React = require('react'); var ReactDOM = require('react-dom'); -var ReactVersion = '19.0.0-www-classic-b065c3bc'; +var ReactVersion = '19.0.0-www-classic-7553220d'; // This refers to a WWW module. var warningWWW = require('warning'); @@ -10513,28 +10513,35 @@ function replayElement(request, task, keyPath, name, keyOrIndex, childIndex, typ } // We didn't find any matching nodes. We assume that this element was already // rendered in the prelude and skip it. -} // $FlowFixMe[missing-local-annot] +} - -function validateIterable(iterable, iteratorFn) { +function validateIterable(task, iterable, childIndex, iterator, iteratorFn) { { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && iterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (iterator === iterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = task.componentStack !== null && task.componentStack.tag === 1 && // FunctionComponent + // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(task.componentStack.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(iterator) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (iterable.entries === iteratorFn) { + } else if (iterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; + didWarnAboutMaps = true; + } } } } @@ -10639,18 +10646,18 @@ function renderNodeDestructive(request, task, node, childIndex) { var iteratorFn = getIteratorFn(node); if (iteratorFn) { - { - validateIterable(node, iteratorFn); - } - var iterator = iteratorFn.call(node); if (iterator) { - // We need to know how many total children are in this set, so that we + { + validateIterable(task, node, childIndex, iterator, iteratorFn); + } // We need to know how many total children are in this set, so that we // can allocate enough id slots to acommodate them. So we must exhaust // the iterator before we start recursively rendering the children. // TODO: This is not great but I think it's inherent to the id // generation algorithm. + + var step = iterator.next(); // If there are not entries, we need to push an empty so we start by checking that. if (!step.done) { diff --git a/compiled/facebook-www/ReactDOMServer-dev.modern.js b/compiled/facebook-www/ReactDOMServer-dev.modern.js index 41a0ad6ba1..cd31f30950 100644 --- a/compiled/facebook-www/ReactDOMServer-dev.modern.js +++ b/compiled/facebook-www/ReactDOMServer-dev.modern.js @@ -19,7 +19,7 @@ if (__DEV__) { var React = require('react'); var ReactDOM = require('react-dom'); -var ReactVersion = '19.0.0-www-modern-bdfde0e4'; +var ReactVersion = '19.0.0-www-modern-5517e912'; // This refers to a WWW module. var warningWWW = require('warning'); @@ -10443,28 +10443,35 @@ function replayElement(request, task, keyPath, name, keyOrIndex, childIndex, typ } // We didn't find any matching nodes. We assume that this element was already // rendered in the prelude and skip it. -} // $FlowFixMe[missing-local-annot] +} - -function validateIterable(iterable, iteratorFn) { +function validateIterable(task, iterable, childIndex, iterator, iteratorFn) { { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && iterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (iterator === iterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = task.componentStack !== null && task.componentStack.tag === 1 && // FunctionComponent + // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(task.componentStack.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(iterator) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (iterable.entries === iteratorFn) { + } else if (iterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; + didWarnAboutMaps = true; + } } } } @@ -10569,18 +10576,18 @@ function renderNodeDestructive(request, task, node, childIndex) { var iteratorFn = getIteratorFn(node); if (iteratorFn) { - { - validateIterable(node, iteratorFn); - } - var iterator = iteratorFn.call(node); if (iterator) { - // We need to know how many total children are in this set, so that we + { + validateIterable(task, node, childIndex, iterator, iteratorFn); + } // We need to know how many total children are in this set, so that we // can allocate enough id slots to acommodate them. So we must exhaust // the iterator before we start recursively rendering the children. // TODO: This is not great but I think it's inherent to the id // generation algorithm. + + var step = iterator.next(); // If there are not entries, we need to push an empty so we start by checking that. if (!step.done) { diff --git a/compiled/facebook-www/ReactDOMServerStreaming-dev.modern.js b/compiled/facebook-www/ReactDOMServerStreaming-dev.modern.js index 90bffef303..de43327d5e 100644 --- a/compiled/facebook-www/ReactDOMServerStreaming-dev.modern.js +++ b/compiled/facebook-www/ReactDOMServerStreaming-dev.modern.js @@ -10355,28 +10355,35 @@ function replayElement(request, task, keyPath, name, keyOrIndex, childIndex, typ } // We didn't find any matching nodes. We assume that this element was already // rendered in the prelude and skip it. -} // $FlowFixMe[missing-local-annot] +} - -function validateIterable(iterable, iteratorFn) { +function validateIterable(task, iterable, childIndex, iterator, iteratorFn) { { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && iterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (iterator === iterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = task.componentStack !== null && task.componentStack.tag === 1 && // FunctionComponent + // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(task.componentStack.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(iterator) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (iterable.entries === iteratorFn) { + } else if (iterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; + didWarnAboutMaps = true; + } } } } @@ -10481,18 +10488,18 @@ function renderNodeDestructive(request, task, node, childIndex) { var iteratorFn = getIteratorFn(node); if (iteratorFn) { - { - validateIterable(node, iteratorFn); - } - var iterator = iteratorFn.call(node); if (iterator) { - // We need to know how many total children are in this set, so that we + { + validateIterable(task, node, childIndex, iterator, iteratorFn); + } // We need to know how many total children are in this set, so that we // can allocate enough id slots to acommodate them. So we must exhaust // the iterator before we start recursively rendering the children. // TODO: This is not great but I think it's inherent to the id // generation algorithm. + + var step = iterator.next(); // If there are not entries, we need to push an empty so we start by checking that. if (!step.done) { diff --git a/compiled/facebook-www/ReactDOMTesting-dev.classic.js b/compiled/facebook-www/ReactDOMTesting-dev.classic.js index 89d67b808a..7eb95718bb 100644 --- a/compiled/facebook-www/ReactDOMTesting-dev.classic.js +++ b/compiled/facebook-www/ReactDOMTesting-dev.classic.js @@ -10732,45 +10732,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -10781,9 +10772,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -10845,7 +10841,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -10875,7 +10871,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { @@ -31388,7 +31384,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-www-classic-75e45b11'; +var ReactVersion = '19.0.0-www-classic-5a00c38b'; function createPortal$1(children, containerInfo, // TODO: figure out the API for cross-renderer implementation. implementation) { diff --git a/compiled/facebook-www/ReactDOMTesting-dev.modern.js b/compiled/facebook-www/ReactDOMTesting-dev.modern.js index 6e687be950..13a8ffed17 100644 --- a/compiled/facebook-www/ReactDOMTesting-dev.modern.js +++ b/compiled/facebook-www/ReactDOMTesting-dev.modern.js @@ -16142,45 +16142,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -16191,9 +16182,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -16255,7 +16251,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -16285,7 +16281,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { @@ -39427,7 +39423,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-www-modern-24100354'; +var ReactVersion = '19.0.0-www-modern-d0cd454d'; function createPortal$1(children, containerInfo, // TODO: figure out the API for cross-renderer implementation. implementation) { diff --git a/compiled/facebook-www/ReactDOMTesting-prod.classic.js b/compiled/facebook-www/ReactDOMTesting-prod.classic.js index c8812f9a01..96e048dccc 100644 --- a/compiled/facebook-www/ReactDOMTesting-prod.classic.js +++ b/compiled/facebook-www/ReactDOMTesting-prod.classic.js @@ -2996,7 +2996,7 @@ function createChildReconciler(shouldTrackSideEffects) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -3024,7 +3024,7 @@ function createChildReconciler(shouldTrackSideEffects) { iteratorFn ); if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), @@ -3038,7 +3038,7 @@ function createChildReconciler(shouldTrackSideEffects) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && @@ -12846,7 +12846,7 @@ function injectIntoDevTools(devToolsConfig) { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-classic-66a7ae3c" + reconcilerVersion: "19.0.0-www-classic-58a04a89" }; if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) devToolsConfig = !1; @@ -17409,7 +17409,7 @@ Internals.Events = [ injectIntoDevTools({ findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "19.0.0-www-classic-66a7ae3c", + version: "19.0.0-www-classic-58a04a89", rendererPackageName: "react-dom" }); var ReactFiberErrorDialogWWW = require("ReactFiberErrorDialog"); @@ -17542,7 +17542,7 @@ assign(Internals, { injectIntoDevTools({ findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "19.0.0-www-classic-66a7ae3c", + version: "19.0.0-www-classic-58a04a89", rendererPackageName: "react-dom" }); exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = @@ -18009,4 +18009,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-www-classic-66a7ae3c"; +exports.version = "19.0.0-www-classic-58a04a89"; diff --git a/compiled/facebook-www/ReactDOMTesting-prod.modern.js b/compiled/facebook-www/ReactDOMTesting-prod.modern.js index fa8501f0a8..4ade7733a2 100644 --- a/compiled/facebook-www/ReactDOMTesting-prod.modern.js +++ b/compiled/facebook-www/ReactDOMTesting-prod.modern.js @@ -5356,7 +5356,7 @@ function createChildReconciler(shouldTrackSideEffects) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -5384,7 +5384,7 @@ function createChildReconciler(shouldTrackSideEffects) { iteratorFn ); if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)), @@ -5398,7 +5398,7 @@ function createChildReconciler(shouldTrackSideEffects) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)), null !== step && @@ -16132,7 +16132,7 @@ function injectIntoDevTools(devToolsConfig) { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-modern-26fdeab5" + reconcilerVersion: "19.0.0-www-modern-252cdb5f" }; if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) devToolsConfig = !1; @@ -16830,7 +16830,7 @@ Internals.Events = [ injectIntoDevTools({ findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "19.0.0-www-modern-26fdeab5", + version: "19.0.0-www-modern-252cdb5f", rendererPackageName: "react-dom" }); if ("function" !== typeof require("ReactFiberErrorDialog").showErrorDialog) @@ -16838,7 +16838,7 @@ if ("function" !== typeof require("ReactFiberErrorDialog").showErrorDialog) injectIntoDevTools({ findFiberByHostInstance: getClosestInstanceFromNode, bundleType: 0, - version: "19.0.0-www-modern-26fdeab5", + version: "19.0.0-www-modern-252cdb5f", rendererPackageName: "react-dom" }); exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = @@ -17252,4 +17252,4 @@ exports.useFormState = function (action, initialState, permalink) { exports.useFormStatus = function () { return ReactSharedInternals.H.useHostTransitionStatus(); }; -exports.version = "19.0.0-www-modern-26fdeab5"; +exports.version = "19.0.0-www-modern-252cdb5f"; diff --git a/compiled/facebook-www/ReactReconciler-dev.classic.js b/compiled/facebook-www/ReactReconciler-dev.classic.js index 0b33e318ca..f36f060361 100644 --- a/compiled/facebook-www/ReactReconciler-dev.classic.js +++ b/compiled/facebook-www/ReactReconciler-dev.classic.js @@ -7535,45 +7535,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -7584,9 +7575,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -7648,7 +7644,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -7678,7 +7674,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { @@ -28651,7 +28647,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-www-classic-ebcd5e46'; +var ReactVersion = '19.0.0-www-classic-0d0181ca'; /* * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol diff --git a/compiled/facebook-www/ReactReconciler-dev.modern.js b/compiled/facebook-www/ReactReconciler-dev.modern.js index 5bf2058948..529741ce2a 100644 --- a/compiled/facebook-www/ReactReconciler-dev.modern.js +++ b/compiled/facebook-www/ReactReconciler-dev.modern.js @@ -7326,45 +7326,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -7375,9 +7366,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -7439,7 +7435,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -7469,7 +7465,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { @@ -27917,7 +27913,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-www-modern-880c3caa'; +var ReactVersion = '19.0.0-www-modern-78a11bf8'; /* * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol diff --git a/compiled/facebook-www/ReactReconciler-prod.classic.js b/compiled/facebook-www/ReactReconciler-prod.classic.js index 9a96e0dc8d..4271fa163f 100644 --- a/compiled/facebook-www/ReactReconciler-prod.classic.js +++ b/compiled/facebook-www/ReactReconciler-prod.classic.js @@ -2062,7 +2062,7 @@ module.exports = function ($$$config) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -2090,7 +2090,7 @@ module.exports = function ($$$config) { iteratorFn ); if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild( @@ -2108,7 +2108,7 @@ module.exports = function ($$$config) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap( oldFiber, @@ -12632,7 +12632,7 @@ module.exports = function ($$$config) { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-classic-873e0310" + reconcilerVersion: "19.0.0-www-classic-1c6ccd17" }; if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) devToolsConfig = !1; diff --git a/compiled/facebook-www/ReactReconciler-prod.modern.js b/compiled/facebook-www/ReactReconciler-prod.modern.js index 7c1fa2ad4a..7031ff2f08 100644 --- a/compiled/facebook-www/ReactReconciler-prod.modern.js +++ b/compiled/facebook-www/ReactReconciler-prod.modern.js @@ -1922,7 +1922,7 @@ module.exports = function ($$$config) { nextOldFiber = null, step = newChildrenIterable.next(); null !== oldFiber && !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) { oldFiber.index > newIdx ? ((nextOldFiber = oldFiber), (oldFiber = null)) @@ -1950,7 +1950,7 @@ module.exports = function ($$$config) { iteratorFn ); if (null === oldFiber) { - for (; !step.done; newIdx++, step = newChildrenIterable.next()) + for (; !step.done; newIdx++, step = newChildrenIterable.next(), null) (step = createChild(returnFiber, step.value, lanes)), null !== step && ((currentFirstChild = placeChild( @@ -1968,7 +1968,7 @@ module.exports = function ($$$config) { for ( oldFiber = mapRemainingChildren(oldFiber); !step.done; - newIdx++, step = newChildrenIterable.next() + newIdx++, step = newChildrenIterable.next(), null ) (step = updateFromMap( oldFiber, @@ -12149,7 +12149,7 @@ module.exports = function ($$$config) { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "19.0.0-www-modern-944c4921" + reconcilerVersion: "19.0.0-www-modern-41c33f0e" }; if ("undefined" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) devToolsConfig = !1; diff --git a/compiled/facebook-www/ReactTestRenderer-dev.classic.js b/compiled/facebook-www/ReactTestRenderer-dev.classic.js index 5e026aabaf..2c2c77fcef 100644 --- a/compiled/facebook-www/ReactTestRenderer-dev.classic.js +++ b/compiled/facebook-www/ReactTestRenderer-dev.classic.js @@ -6146,45 +6146,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -6195,9 +6186,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -6254,7 +6250,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -6279,7 +6275,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { @@ -23113,7 +23109,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-www-classic-3d1458be'; +var ReactVersion = '19.0.0-www-classic-6c3672cc'; /* * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol diff --git a/compiled/facebook-www/ReactTestRenderer-dev.modern.js b/compiled/facebook-www/ReactTestRenderer-dev.modern.js index d970701fd5..05b587639c 100644 --- a/compiled/facebook-www/ReactTestRenderer-dev.modern.js +++ b/compiled/facebook-www/ReactTestRenderer-dev.modern.js @@ -6146,45 +6146,36 @@ function createChildReconciler(shouldTrackSideEffects) { throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); } + var newChildren = iteratorFn.call(newChildrenIterable); + { - // We don't support rendering Generators because it's a mutation. - // See https://github.com/facebook/react/issues/12995 - if (typeof Symbol === 'function' && // $FlowFixMe[prop-missing] Flow doesn't know about toStringTag - newChildrenIterable[Symbol.toStringTag] === 'Generator') { - if (!didWarnAboutGenerators) { - error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + if (newChildren === newChildrenIterable) { + // We don't support rendering Generators as props because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + // We do support generators if they were created by a GeneratorFunction component + // as its direct child since we can recreate those by rerendering the component + // as needed. + var isGeneratorComponent = returnFiber.tag === FunctionComponent && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(returnFiber.type) === '[object GeneratorFunction]' && // $FlowFixMe[method-unbinding] + Object.prototype.toString.call(newChildren) === '[object Generator]'; + + if (!isGeneratorComponent) { + if (!didWarnAboutGenerators) { + error('Using Iterators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. You can also use an ' + 'Iterable that can iterate multiple times over the same items.'); + } + + didWarnAboutGenerators = true; } - - didWarnAboutGenerators = true; - } // Warn about using Maps as children - - - if (newChildrenIterable.entries === iteratorFn) { + } else if (newChildrenIterable.entries === iteratorFn) { + // Warn about using Maps as children if (!didWarnAboutMaps) { error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); - } - didWarnAboutMaps = true; - } // First, validate keys. - // We'll get a different iterator later for the main pass. - - - var _newChildren = iteratorFn.call(newChildrenIterable); - - if (_newChildren) { - var knownKeys = null; - - var _step = _newChildren.next(); - - for (; !_step.done; _step = _newChildren.next()) { - var child = _step.value; - knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); + didWarnAboutMaps = true; } } } - var newChildren = iteratorFn.call(newChildrenIterable); - if (newChildren == null) { throw new Error('An iterable object provided no iterator.'); } @@ -6195,9 +6186,14 @@ function createChildReconciler(shouldTrackSideEffects) { var lastPlacedIndex = 0; var newIdx = 0; var nextOldFiber = null; + var knownKeys = null; var step = newChildren.next(); - for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + { + knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber); + } + + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { if (oldFiber.index > newIdx) { nextOldFiber = oldFiber; oldFiber = null; @@ -6254,7 +6250,7 @@ function createChildReconciler(shouldTrackSideEffects) { if (oldFiber === null) { // If we don't have any more existing children we can choose a fast path // since the rest will all be insertions. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber3 = createChild(returnFiber, step.value, lanes, debugInfo); if (_newFiber3 === null) { @@ -6279,7 +6275,7 @@ function createChildReconciler(shouldTrackSideEffects) { var existingChildren = mapRemainingChildren(oldFiber); // Keep scanning and use the map to restore deleted items as moves. - for (; !step.done; newIdx++, step = newChildren.next()) { + for (; !step.done; newIdx++, step = newChildren.next(), knownKeys = warnOnInvalidKey(step.value, knownKeys, returnFiber) ) { var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes, debugInfo); if (_newFiber4 !== null) { @@ -23113,7 +23109,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition return root; } -var ReactVersion = '19.0.0-www-modern-3d1458be'; +var ReactVersion = '19.0.0-www-modern-6c3672cc'; /* * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol diff --git a/compiled/facebook-www/__test_utils__/ReactAllWarnings.js b/compiled/facebook-www/__test_utils__/ReactAllWarnings.js index a06cfef7c1..99bff6c9a8 100644 --- a/compiled/facebook-www/__test_utils__/ReactAllWarnings.js +++ b/compiled/facebook-www/__test_utils__/ReactAllWarnings.js @@ -315,7 +315,7 @@ export default [ "Use the `defaultValue` or `value` props instead of setting children on