20
let act;
21
let use;
22
let clientExports;
23
+let clientExportsESM;
24
let turbopackMap;
25
let Stream;
26
let React;
30
let Suspense;
31
let ReactServerScheduler;
32
let reactServerAct;
33
+let ErrorBoundary;
34
35
describe('ReactFlightTurbopackDOM', () => {
36
beforeEach(() => {
51
52
const TurbopackMock = require('./utils/TurbopackMock');
53
clientExports = TurbopackMock.clientExports;
54
+ clientExportsESM = TurbopackMock.clientExportsESM;
55
turbopackMap = TurbopackMock.turbopackMap;
56
57
ReactServerDOMServer = require('react-server-dom-turbopack/server');
66
Suspense = React.Suspense;
67
ReactDOMClient = require('react-dom/client');
68
ReactServerDOMClient = require('react-server-dom-turbopack/client');
69
+
70
+ ErrorBoundary = class extends React.Component {
71
+ state = {hasError: false, error: null};
72
+ static getDerivedStateFromError(error) {
73
+ return {
74
+ hasError: true,
75
+ error,
76
+ };
77
+ }
78
+ render() {
79
+ if (this.state.hasError) {
80
+ return this.props.fallback(this.state.error);
81
+ }
82
+ return this.props.children;
83
+ }
84
+ };
85
});
86
87
async function serverAct(callback) {
239
});
240
expect(container.innerHTML).toBe('<p>Async: Module</p>');
241
});
242
+
243
+ it('should unwrap async ESM module references', async () => {
244
+ const AsyncModule = Promise.resolve(function AsyncModule({text}) {
245
+ return 'Async: ' + text;
246
+ });
247
+
248
+ const AsyncModule2 = Promise.resolve({
249
+ exportName: 'Module',
250
+ });
251
+
252
+ function Print({response}) {
253
+ return <p>{use(response)}</p>;
254
+ }
255
+
256
+ function App({response}) {
257
+ return (
258
+ <Suspense fallback={<h1>Loading...</h1>}>
259
+ <Print response={response} />
260
+ </Suspense>
261
+ );
262
+ }
263
+
264
+ const AsyncModuleRef = await clientExportsESM(AsyncModule);
265
+ const AsyncModuleRef2 = await clientExportsESM(AsyncModule2);
266
+
267
+ const {writable, readable} = getTestStream();
268
+ const {pipe} = await serverAct(() =>
269
+ ReactServerDOMServer.renderToPipeableStream(
270
+ <AsyncModuleRef text={AsyncModuleRef2.exportName} />,
271
+ turbopackMap,
272
+ ),
273
+ );
274
+ pipe(writable);
275
+ const response = ReactServerDOMClient.createFromReadableStream(readable);
276
+
277
+ const container = document.createElement('div');
278
+ const root = ReactDOMClient.createRoot(container);
279
+ await act(() => {
280
+ root.render(<App response={response} />);
281
+ });
282
+ expect(container.innerHTML).toBe('<p>Async: Module</p>');
283
+ });
284
+
285
+ it('should error when a bundler uses async ESM modules with createClientModuleProxy', async () => {
286
+ const AsyncModule = Promise.resolve(function AsyncModule() {
287
+ return 'This should not be rendered';
288
+ });
289
+
290
+ function Print({response}) {
291
+ return <p>{use(response)}</p>;
292
+ }
293
+
294
+ function App({response}) {
295
+ return (
296
+ <ErrorBoundary
297
+ fallback={error => (
298
+ <p>
299
+ {__DEV__ ? error.message + ' + ' : null}
300
+ {error.digest}
301
+ </p>
302
+ )}>
303
+ <Suspense fallback={<h1>Loading...</h1>}>
304
+ <Print response={response} />
305
+ </Suspense>
306
+ </ErrorBoundary>
307
+ );
308
+ }
309
+
310
+ const AsyncModuleRef = await clientExportsESM(AsyncModule, {
311
+ forceClientModuleProxy: true,
312
+ });
313
+
314
+ const {writable, readable} = getTestStream();
315
+ const {pipe} = await serverAct(() =>
316
+ ReactServerDOMServer.renderToPipeableStream(
317
+ <AsyncModuleRef />,
318
+ turbopackMap,
319
+ {
320
+ onError(error) {
321
+ return __DEV__ ? 'a dev digest' : `digest(${error.message})`;
322
+ },
323
+ },
324
+ ),
325
+ );
326
+ pipe(writable);
327
+ const response = ReactServerDOMClient.createFromReadableStream(readable);
328
+
329
+ const container = document.createElement('div');
330
+ const root = ReactDOMClient.createRoot(container);
331
+ await act(() => {
332
+ root.render(<App response={response} />);
333
+ });
334
+
335
+ const errorMessage = `The module "${Object.keys(turbopackMap).at(0)}" is marked as an async ESM module but was loaded as a CJS proxy. This is probably a bug in the React Server Components bundler.`;
336
+
337
+ expect(container.innerHTML).toBe(
338
+ __DEV__
339
+ ? `<p>${errorMessage} + a dev digest</p>`
340
+ : `<p>digest(${errorMessage})</p>`,
341
+ );
342
+ });
343
});