@@ -1354,4 +1354,285 @@ describe('ReactFlightDOMEdge', () => {
13541354 expect ( error ) . not . toBe ( null ) ;
13551355 expect ( error . message ) . toBe ( 'Connection closed.' ) ;
13561356 } ) ;
1357+
1358+ // @gate experimental
1359+ it ( 'should be able to handle a rejected promise in unstable_prerender' , async ( ) => {
1360+ const expectedError = new Error ( 'Bam!' ) ;
1361+ const errors = [ ] ;
1362+
1363+ const { prelude} = await ReactServerDOMStaticServer . unstable_prerender (
1364+ Promise . reject ( expectedError ) ,
1365+ webpackMap ,
1366+ {
1367+ onError ( err ) {
1368+ errors . push ( err ) ;
1369+ } ,
1370+ } ,
1371+ ) ;
1372+
1373+ expect ( errors ) . toEqual ( [ expectedError ] ) ;
1374+
1375+ const response = ReactServerDOMClient . createFromReadableStream ( prelude , {
1376+ serverConsumerManifest : {
1377+ moduleMap : { } ,
1378+ moduleLoading : { } ,
1379+ } ,
1380+ } ) ;
1381+
1382+ let error = null ;
1383+ try {
1384+ await response ;
1385+ } catch ( x ) {
1386+ error = x ;
1387+ }
1388+
1389+ const expectedMessage = __DEV__
1390+ ? expectedError . message
1391+ : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.' ;
1392+
1393+ expect ( error ) . not . toBe ( null ) ;
1394+ expect ( error . message ) . toBe ( expectedMessage ) ;
1395+ } ) ;
1396+
1397+ // @gate experimental
1398+ it ( 'should be able to handle an erroring async iterable in unstable_prerender' , async ( ) => {
1399+ const expectedError = new Error ( 'Bam!' ) ;
1400+ const errors = [ ] ;
1401+
1402+ const { prelude} = await ReactServerDOMStaticServer . unstable_prerender (
1403+ {
1404+ async * [ Symbol . asyncIterator ] ( ) {
1405+ await serverAct ( ( ) => {
1406+ throw expectedError ;
1407+ } ) ;
1408+ } ,
1409+ } ,
1410+ webpackMap ,
1411+ {
1412+ onError ( err ) {
1413+ errors . push ( err ) ;
1414+ } ,
1415+ } ,
1416+ ) ;
1417+
1418+ expect ( errors ) . toEqual ( [ expectedError ] ) ;
1419+
1420+ const response = ReactServerDOMClient . createFromReadableStream ( prelude , {
1421+ serverConsumerManifest : {
1422+ moduleMap : { } ,
1423+ moduleLoading : { } ,
1424+ } ,
1425+ } ) ;
1426+
1427+ let error = null ;
1428+ try {
1429+ const result = await response ;
1430+ const iterator = result [ Symbol . asyncIterator ] ( ) ;
1431+ await iterator . next ( ) ;
1432+ } catch ( x ) {
1433+ error = x ;
1434+ }
1435+
1436+ const expectedMessage = __DEV__
1437+ ? expectedError . message
1438+ : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.' ;
1439+
1440+ expect ( error ) . not . toBe ( null ) ;
1441+ expect ( error . message ) . toBe ( expectedMessage ) ;
1442+ } ) ;
1443+
1444+ // @gate experimental
1445+ it ( 'should be able to handle an erroring readable stream in unstable_prerender' , async ( ) => {
1446+ const expectedError = new Error ( 'Bam!' ) ;
1447+ const errors = [ ] ;
1448+
1449+ const { prelude} = await ReactServerDOMStaticServer . unstable_prerender (
1450+ new ReadableStream ( {
1451+ async start ( controller ) {
1452+ await serverAct ( ( ) => {
1453+ setTimeout ( ( ) => {
1454+ controller . error ( expectedError ) ;
1455+ } ) ;
1456+ } ) ;
1457+ } ,
1458+ } ) ,
1459+ webpackMap ,
1460+ {
1461+ onError ( err ) {
1462+ errors . push ( err ) ;
1463+ } ,
1464+ } ,
1465+ ) ;
1466+
1467+ expect ( errors ) . toEqual ( [ expectedError ] ) ;
1468+
1469+ const response = ReactServerDOMClient . createFromReadableStream ( prelude , {
1470+ serverConsumerManifest : {
1471+ moduleMap : { } ,
1472+ moduleLoading : { } ,
1473+ } ,
1474+ } ) ;
1475+
1476+ let error = null ;
1477+ try {
1478+ const stream = await response ;
1479+ await stream . getReader ( ) . read ( ) ;
1480+ } catch ( x ) {
1481+ error = x ;
1482+ }
1483+
1484+ const expectedMessage = __DEV__
1485+ ? expectedError . message
1486+ : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.' ;
1487+
1488+ expect ( error ) . not . toBe ( null ) ;
1489+ expect ( error . message ) . toBe ( expectedMessage ) ;
1490+ } ) ;
1491+
1492+ // @gate experimental
1493+ it ( 'can prerender an async iterable' , async ( ) => {
1494+ const errors = [ ] ;
1495+
1496+ const { prelude} = await ReactServerDOMStaticServer . unstable_prerender (
1497+ {
1498+ async * [ Symbol . asyncIterator ] ( ) {
1499+ yield 'hello' ;
1500+ yield ' ' ;
1501+ yield 'world' ;
1502+ } ,
1503+ } ,
1504+ webpackMap ,
1505+ {
1506+ onError ( err ) {
1507+ errors . push ( err ) ;
1508+ } ,
1509+ } ,
1510+ ) ;
1511+
1512+ expect ( errors ) . toEqual ( [ ] ) ;
1513+
1514+ const response = ReactServerDOMClient . createFromReadableStream ( prelude , {
1515+ serverConsumerManifest : {
1516+ moduleMap : { } ,
1517+ moduleLoading : { } ,
1518+ } ,
1519+ } ) ;
1520+
1521+ let text = '' ;
1522+ const result = await response ;
1523+ const iterator = result [ Symbol . asyncIterator ] ( ) ;
1524+
1525+ while ( true ) {
1526+ const { done, value} = await iterator . next ( ) ;
1527+ if ( done ) {
1528+ break ;
1529+ }
1530+ text += value ;
1531+ }
1532+
1533+ expect ( text ) . toBe ( 'hello world' ) ;
1534+ } ) ;
1535+
1536+ // @gate experimental
1537+ it ( 'can prerender a readable stream' , async ( ) => {
1538+ const errors = [ ] ;
1539+
1540+ const { prelude} = await ReactServerDOMStaticServer . unstable_prerender (
1541+ new ReadableStream ( {
1542+ start ( controller ) {
1543+ controller . enqueue ( 'hello world' ) ;
1544+ controller . close ( ) ;
1545+ } ,
1546+ } ) ,
1547+ webpackMap ,
1548+ {
1549+ onError ( err ) {
1550+ errors . push ( err ) ;
1551+ } ,
1552+ } ,
1553+ ) ;
1554+
1555+ expect ( errors ) . toEqual ( [ ] ) ;
1556+
1557+ const response = ReactServerDOMClient . createFromReadableStream ( prelude , {
1558+ serverConsumerManifest : {
1559+ moduleMap : { } ,
1560+ moduleLoading : { } ,
1561+ } ,
1562+ } ) ;
1563+
1564+ const stream = await response ;
1565+ const result = await readResult ( stream ) ;
1566+
1567+ expect ( result ) . toBe ( 'hello world' ) ;
1568+ } ) ;
1569+
1570+ // @gate experimental
1571+ it ( 'does not return a prerender prelude early when an error is emitted and there are still pending tasks' , async ( ) => {
1572+ let rejectPromise ;
1573+ const rejectingPromise = new Promise (
1574+ ( resolve , reject ) => ( rejectPromise = reject ) ,
1575+ ) ;
1576+ const expectedError = new Error ( 'Boom!' ) ;
1577+ const errors = [ ] ;
1578+
1579+ const { prelude} = await ReactServerDOMStaticServer . unstable_prerender (
1580+ [
1581+ rejectingPromise ,
1582+ {
1583+ async * [ Symbol . asyncIterator ] ( ) {
1584+ yield 'hello' ;
1585+ yield ' ' ;
1586+ await serverAct ( ( ) => {
1587+ rejectPromise ( expectedError ) ;
1588+ } ) ;
1589+ yield 'world' ;
1590+ } ,
1591+ } ,
1592+ ] ,
1593+ webpackMap ,
1594+ {
1595+ onError ( err ) {
1596+ errors . push ( err ) ;
1597+ } ,
1598+ } ,
1599+ ) ;
1600+
1601+ expect ( errors ) . toEqual ( [ expectedError ] ) ;
1602+
1603+ const response = ReactServerDOMClient . createFromReadableStream ( prelude , {
1604+ serverConsumerManifest : {
1605+ moduleMap : { } ,
1606+ moduleLoading : { } ,
1607+ } ,
1608+ } ) ;
1609+
1610+ let text = '' ;
1611+ const [ promise , iterable ] = await response ;
1612+ const iterator = iterable [ Symbol . asyncIterator ] ( ) ;
1613+
1614+ while ( true ) {
1615+ const { done, value} = await iterator . next ( ) ;
1616+ if ( done ) {
1617+ break ;
1618+ }
1619+ text += value ;
1620+ }
1621+
1622+ expect ( text ) . toBe ( 'hello world' ) ;
1623+
1624+ let error = null ;
1625+ try {
1626+ await promise ;
1627+ } catch ( x ) {
1628+ error = x ;
1629+ }
1630+
1631+ const expectedMessage = __DEV__
1632+ ? expectedError . message
1633+ : 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.' ;
1634+
1635+ expect ( error ) . not . toBe ( null ) ;
1636+ expect ( error . message ) . toBe ( expectedMessage ) ;
1637+ } ) ;
13571638} ) ;
0 commit comments