35
React.useMutableSource || React.unstable_useMutableSource;
36
});
37
38
- function dispatchAndSetCurrentEvent(el, event) {
39
- try {
40
- window.event = event;
41
- el.dispatchEvent(event);
42
- } finally {
43
- window.event = undefined;
44
- }
45
- }
46
-
38
const defaultGetSnapshot = source => source.value;
39
const defaultSubscribe = (source, callback) => source.subscribe(callback);
40
371
'an issue.',
372
]);
373
});
383
-
384
- // @gate !enableSyncDefaultUpdates
385
- // @gate enableUseMutableSource
386
- it('should detect a tear during a higher priority interruption', () => {
387
- const source = createSource('one');
388
- const mutableSource = createMutableSource(source, param => param.version);
389
-
390
- function Unrelated({flag}) {
391
- Scheduler.unstable_yieldValue(flag);
392
- return flag;
393
- }
394
-
395
- function TestComponent({flag}) {
396
- return (
397
- <>
398
- <Unrelated flag={flag} />
399
- <Component
400
- label="a"
401
- getSnapshot={defaultGetSnapshot}
402
- mutableSource={mutableSource}
403
- subscribe={defaultSubscribe}
404
- />
405
- </>
406
- );
407
- }
408
-
409
- const container = document.createElement('div');
410
- document.body.appendChild(container);
411
-
412
- const htmlString = ReactDOMServer.renderToString(
413
- <TestComponent flag={1} />,
414
- );
415
- container.innerHTML = htmlString;
416
- expect(Scheduler).toHaveYielded([1, 'a:one']);
417
- expect(source.listenerCount).toBe(0);
418
-
419
- expect(() => {
420
- act(() => {
421
- let root;
422
- if (gate(flags => flags.enableSyncDefaultUpdates)) {
423
- React.startTransition(() => {
424
- root = ReactDOM.hydrateRoot(container, <TestComponent flag={1} />, {
425
- mutableSources: [mutableSource],
426
- });
427
- });
428
- } else {
429
- root = ReactDOM.hydrateRoot(container, <TestComponent flag={1} />, {
430
- mutableSources: [mutableSource],
431
- });
432
- }
433
- expect(Scheduler).toFlushAndYieldThrough([1]);
434
-
435
- // Render an update which will be higher priority than the hydration.
436
- // We can do this by scheduling the update inside a mouseover event.
437
- const arbitraryElement = document.createElement('div');
438
- const mouseOverEvent = document.createEvent('MouseEvents');
439
- mouseOverEvent.initEvent('mouseover', true, true);
440
- arbitraryElement.addEventListener('mouseover', () => {
441
- root.render(<TestComponent flag={2} />);
442
- });
443
- dispatchAndSetCurrentEvent(arbitraryElement, mouseOverEvent);
444
-
445
- expect(Scheduler).toFlushAndYieldThrough([2]);
446
- source.value = 'two';
447
- });
448
- }).toErrorDev(
449
- 'Warning: Text content did not match. Server: "1" Client: "2"',
450
- );
451
- expect(source.listenerCount).toBe(1);
452
- if (gate(flags => flags.enableSyncDefaultUpdates)) {
453
- expect(Scheduler).toHaveYielded([2, 'a:two']);
454
- } else {
455
- expect(Scheduler).toHaveYielded(['a:two']);
456
- }
457
- });
374
});