@samitouri / QOS-React / commits / 293878e079

Replace ReactShallowRenderer with a dependency (#18144)

Closes #17321.

Minh Nguyen committed Feb 27, 2020 at 18:10 UTC 293878e079b170670b08449bfdcd7aebaa6afbc2
4 files changed +11 -864
packages/react-test-renderer/package.json
+1
@@ -22,6 +22,7 @@
22 "object-assign": "^4.1.1",
23 "prop-types": "^15.6.2",
24 "react-is": "^16.8.6",
25 + "react-shallow-renderer": "^16.12.0",
26 "scheduler": "^0.19.0"
27 },
28 "peerDependencies": {
packages/react-test-renderer/shallow.js
+1 -1
@@ -7,4 +7,4 @@
7 * @flow
8 */
9
10 -export {default} from './src/ReactShallowRenderer';
10 +export {default} from 'react-shallow-renderer';
packages/react-test-renderer/src/ReactShallowRenderer.js deleted
-863
@@ -1,863 +0,0 @@
1 -/**
2 - * Copyright (c) Facebook, Inc. and its affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -import * as React from 'react';
11 -import {isForwardRef, isMemo, ForwardRef} from 'react-is';
12 -import describeComponentFrame from 'shared/describeComponentFrame';
13 -import getComponentName from 'shared/getComponentName';
14 -import shallowEqual from 'shared/shallowEqual';
15 -import invariant from 'shared/invariant';
16 -import checkPropTypes from 'prop-types/checkPropTypes';
17 -import ReactSharedInternals from 'shared/ReactSharedInternals';
18 -import is from 'shared/objectIs';
19 -
20 -import type {Dispatcher as DispatcherType} from 'react-reconciler/src/ReactFiberHooks';
21 -import type {
22 - ReactContext,
23 - ReactEventResponderListener,
24 -} from 'shared/ReactTypes';
25 -import type {ReactElement} from 'shared/ReactElementType';
26 -
27 -type BasicStateAction<S> = (S => S) | S;
28 -type Dispatch<A> = A => void;
29 -
30 -type Update<A> = {|
31 - action: A,
32 - next: Update<A> | null,
33 -|};
34 -
35 -type UpdateQueue<A> = {|
36 - first: Update<A> | null,
37 - dispatch: any,
38 -|};
39 -
40 -type Hook = {|
41 - memoizedState: any,
42 - queue: UpdateQueue<any> | null,
43 - next: Hook | null,
44 -|};
45 -
46 -const {ReactCurrentDispatcher} = ReactSharedInternals;
47 -
48 -const RE_RENDER_LIMIT = 25;
49 -
50 -const emptyObject = {};
51 -if (__DEV__) {
52 - Object.freeze(emptyObject);
53 -}
54 -
55 -// In DEV, this is the name of the currently executing primitive hook
56 -let currentHookNameInDev: ?string;
57 -
58 -function areHookInputsEqual(
59 - nextDeps: Array<mixed>,
60 - prevDeps: Array<mixed> | null,
61 -) {
62 - if (prevDeps === null) {
63 - if (__DEV__) {
64 - console.error(
65 - '%s received a final argument during this render, but not during ' +
66 - 'the previous render. Even though the final argument is optional, ' +
67 - 'its type cannot change between renders.',
68 - currentHookNameInDev,
69 - );
70 - }
71 - return false;
72 - }
73 -
74 - if (__DEV__) {
75 - // Don't bother comparing lengths in prod because these arrays should be
76 - // passed inline.
77 - if (nextDeps.length !== prevDeps.length) {
78 - console.error(
79 - 'The final argument passed to %s changed size between renders. The ' +
80 - 'order and size of this array must remain constant.\n\n' +
81 - 'Previous: %s\n' +
82 - 'Incoming: %s',
83 - currentHookNameInDev,
84 - `[${nextDeps.join(', ')}]`,
85 - `[${prevDeps.join(', ')}]`,
86 - );
87 - }
88 - }
89 - for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
90 - if (is(nextDeps[i], prevDeps[i])) {
91 - continue;
92 - }
93 - return false;
94 - }
95 - return true;
96 -}
97 -
98 -class Updater {
99 - constructor(renderer) {
100 - this._renderer = renderer;
101 - this._callbacks = [];
102 - }
103 -
104 - _renderer: ReactShallowRenderer;
105 - _callbacks: Array<any>;
106 -
107 - _enqueueCallback(callback, publicInstance) {
108 - if (typeof callback === 'function' && publicInstance) {
109 - this._callbacks.push({
110 - callback,
111 - publicInstance,
112 - });
113 - }
114 - }
115 -
116 - _invokeCallbacks() {
117 - const callbacks = this._callbacks;
118 - this._callbacks = [];
119 -
120 - callbacks.forEach(({callback, publicInstance}) => {
121 - callback.call(publicInstance);
122 - });
123 - }
124 -
125 - isMounted(publicInstance) {
126 - return !!this._renderer._element;
127 - }
128 -
129 - enqueueForceUpdate(publicInstance, callback, callerName) {
130 - this._enqueueCallback(callback, publicInstance);
131 - this._renderer._forcedUpdate = true;
132 - this._renderer.render(this._renderer._element, this._renderer._context);
133 - }
134 -
135 - enqueueReplaceState(publicInstance, completeState, callback, callerName) {
136 - this._enqueueCallback(callback, publicInstance);
137 - this._renderer._newState = completeState;
138 - this._renderer.render(this._renderer._element, this._renderer._context);
139 - }
140 -
141 - enqueueSetState(publicInstance, partialState, callback, callerName) {
142 - this._enqueueCallback(callback, publicInstance);
143 - const currentState = this._renderer._newState || publicInstance.state;
144 -
145 - if (typeof partialState === 'function') {
146 - partialState = partialState.call(
147 - publicInstance,
148 - currentState,
149 - publicInstance.props,
150 - );
151 - }
152 -
153 - // Null and undefined are treated as no-ops.
154 - if (partialState === null || partialState === undefined) {
155 - return;
156 - }
157 -
158 - this._renderer._newState = {
159 - ...currentState,
160 - ...partialState,
161 - };
162 -
163 - this._renderer.render(this._renderer._element, this._renderer._context);
164 - }
165 -}
166 -
167 -function createHook(): Hook {
168 - return {
169 - memoizedState: null,
170 - queue: null,
171 - next: null,
172 - };
173 -}
174 -
175 -function basicStateReducer<S>(state: S, action: BasicStateAction<S>): S {
176 - // $FlowFixMe: Flow doesn't like mixed types
177 - return typeof action === 'function' ? action(state) : action;
178 -}
179 -
180 -class ReactShallowRenderer {
181 - static createRenderer = function() {
182 - return new ReactShallowRenderer();
183 - };
184 -
185 - constructor() {
186 - this._reset();
187 - }
188 -
189 - _reset() {
190 - this._context = null;
191 - this._element = null;
192 - this._instance = null;
193 - this._newState = null;
194 - this._rendered = null;
195 - this._rendering = false;
196 - this._forcedUpdate = false;
197 - this._updater = new Updater(this);
198 - this._dispatcher = this._createDispatcher();
199 - this._workInProgressHook = null;
200 - this._firstWorkInProgressHook = null;
201 - this._isReRender = false;
202 - this._didScheduleRenderPhaseUpdate = false;
203 - this._renderPhaseUpdates = null;
204 - this._numberOfReRenders = 0;
205 - }
206 -
207 - _context: null | Object;
208 - _newState: null | Object;
209 - _instance: any;
210 - _element: null | ReactElement;
211 - _rendered: null | mixed;
212 - _updater: Updater;
213 - _rendering: boolean;
214 - _forcedUpdate: boolean;
215 - _dispatcher: DispatcherType;
216 - _workInProgressHook: null | Hook;
217 - _firstWorkInProgressHook: null | Hook;
218 - _renderPhaseUpdates: Map<UpdateQueue<any>, Update<any>> | null;
219 - _isReRender: boolean;
220 - _didScheduleRenderPhaseUpdate: boolean;
221 - _numberOfReRenders: number;
222 -
223 - _validateCurrentlyRenderingComponent() {
224 - invariant(
225 - this._rendering && !this._instance,
226 - 'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
227 - ' one of the following reasons:\n' +
228 - '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
229 - '2. You might be breaking the Rules of Hooks\n' +
230 - '3. You might have more than one copy of React in the same app\n' +
231 - 'See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.',
232 - );
233 - }
234 -
235 - _createDispatcher(): DispatcherType {
236 - const useReducer = <S, I, A>(
237 - reducer: (S, A) => S,
238 - initialArg: I,
239 - init?: I => S,
240 - ): [S, Dispatch<A>] => {
241 - this._validateCurrentlyRenderingComponent();
242 - this._createWorkInProgressHook();
243 - const workInProgressHook: Hook = (this._workInProgressHook: any);
244 -
245 - if (this._isReRender) {
246 - // This is a re-render.
247 - const queue: UpdateQueue<A> = (workInProgressHook.queue: any);
248 - const dispatch: Dispatch<A> = (queue.dispatch: any);
249 - if (this._numberOfReRenders > 0) {
250 - // Apply the new render phase updates to the previous current hook.
251 - if (this._renderPhaseUpdates !== null) {
252 - // Render phase updates are stored in a map of queue -> linked list
253 - const firstRenderPhaseUpdate = this._renderPhaseUpdates.get(queue);
254 - if (firstRenderPhaseUpdate !== undefined) {
255 - (this._renderPhaseUpdates: any).delete(queue);
256 - let newState = workInProgressHook.memoizedState;
257 - let update = firstRenderPhaseUpdate;
258 - do {
259 - const action = update.action;
260 - newState = reducer(newState, action);
261 - update = update.next;
262 - } while (update !== null);
263 - workInProgressHook.memoizedState = newState;
264 - return [newState, dispatch];
265 - }
266 - }
267 - return [workInProgressHook.memoizedState, dispatch];
268 - }
269 - // Process updates outside of render
270 - let newState = workInProgressHook.memoizedState;
271 - let update = queue.first;
272 - if (update !== null) {
273 - do {
274 - const action = update.action;
275 - newState = reducer(newState, action);
276 - update = update.next;
277 - } while (update !== null);
278 - queue.first = null;
279 - workInProgressHook.memoizedState = newState;
280 - }
281 - return [newState, dispatch];
282 - } else {
283 - let initialState;
284 - if (reducer === basicStateReducer) {
285 - // Special case for `useState`.
286 - initialState =
287 - typeof initialArg === 'function'
288 - ? ((initialArg: any): () => S)()
289 - : ((initialArg: any): S);
290 - } else {
291 - initialState =
292 - init !== undefined ? init(initialArg) : ((initialArg: any): S);
293 - }
294 - workInProgressHook.memoizedState = initialState;
295 - const queue: UpdateQueue<A> = (workInProgressHook.queue = {
296 - first: null,
297 - dispatch: null,
298 - });
299 - const dispatch: Dispatch<A> = (queue.dispatch = (this._dispatchAction.bind(
300 - this,
301 - queue,
302 - ): any));
303 - return [workInProgressHook.memoizedState, dispatch];
304 - }
305 - };
306 -
307 - const useState = <S>(
308 - initialState: (() => S) | S,
309 - ): [S, Dispatch<BasicStateAction<S>>] => {
310 - return useReducer(
311 - basicStateReducer,
312 - // useReducer has a special case to support lazy useState initializers
313 - (initialState: any),
314 - );
315 - };
316 -
317 - const useMemo = <T>(
318 - nextCreate: () => T,
319 - deps: Array<mixed> | void | null,
320 - ): T => {
321 - this._validateCurrentlyRenderingComponent();
322 - this._createWorkInProgressHook();
323 -
324 - const nextDeps = deps !== undefined ? deps : null;
325 -
326 - if (
327 - this._workInProgressHook !== null &&
328 - this._workInProgressHook.memoizedState !== null
329 - ) {
330 - const prevState = this._workInProgressHook.memoizedState;
331 - const prevDeps = prevState[1];
332 - if (nextDeps !== null) {
333 - if (areHookInputsEqual(nextDeps, prevDeps)) {
334 - return prevState[0];
335 - }
336 - }
337 - }
338 -
339 - const nextValue = nextCreate();
340 - (this._workInProgressHook: any).memoizedState = [nextValue, nextDeps];
341 - return nextValue;
342 - };
343 -
344 - const useRef = <T>(initialValue: T): {|current: T|} => {
345 - this._validateCurrentlyRenderingComponent();
346 - this._createWorkInProgressHook();
347 - const previousRef = (this._workInProgressHook: any).memoizedState;
348 - if (previousRef === null) {
349 - const ref = {current: initialValue};
350 - if (__DEV__) {
351 - Object.seal(ref);
352 - }
353 - (this._workInProgressHook: any).memoizedState = ref;
354 - return ref;
355 - } else {
356 - return previousRef;
357 - }
358 - };
359 -
360 - const readContext = <T>(
361 - context: ReactContext<T>,
362 - observedBits: void | number | boolean,
363 - ): T => {
364 - return context._currentValue;
365 - };
366 -
367 - const noOp = () => {
368 - this._validateCurrentlyRenderingComponent();
369 - };
370 -
371 - const identity = (fn: Function): Function => {
372 - return fn;
373 - };
374 -
375 - const useResponder = (
376 - responder,
377 - props,
378 - ): ReactEventResponderListener<any, any> => ({
379 - props: props,
380 - responder,
381 - });
382 -
383 - // TODO: implement if we decide to keep the shallow renderer
384 - const useTransition = (
385 - config,
386 - ): [(callback: () => void) => void, boolean] => {
387 - this._validateCurrentlyRenderingComponent();
388 - const startTransition = callback => {
389 - callback();
390 - };
391 - return [startTransition, false];
392 - };
393 -
394 - // TODO: implement if we decide to keep the shallow renderer
395 - const useDeferredValue = <T>(value: T, config): T => {
396 - this._validateCurrentlyRenderingComponent();
397 - return value;
398 - };
399 -
400 - return {
401 - readContext,
402 - useCallback: (identity: any),
403 - useContext: <T>(context: ReactContext<T>): T => {
404 - this._validateCurrentlyRenderingComponent();
405 - return readContext(context);
406 - },
407 - useDebugValue: noOp,
408 - useEffect: noOp,
409 - useImperativeHandle: noOp,
410 - useLayoutEffect: noOp,
411 - useMemo,
412 - useReducer,
413 - useRef,
414 - useState,
415 - useResponder,
416 - useTransition,
417 - useDeferredValue,
418 - };
419 - }
420 -
421 - _dispatchAction<A>(queue: UpdateQueue<A>, action: A) {
422 - invariant(
423 - this._numberOfReRenders < RE_RENDER_LIMIT,
424 - 'Too many re-renders. React limits the number of renders to prevent ' +
425 - 'an infinite loop.',
426 - );
427 -
428 - if (this._rendering) {
429 - // This is a render phase update. Stash it in a lazily-created map of
430 - // queue -> linked list of updates. After this render pass, we'll restart
431 - // and apply the stashed updates on top of the work-in-progress hook.
432 - this._didScheduleRenderPhaseUpdate = true;
433 - const update: Update<A> = {
434 - action,
435 - next: null,
436 - };
437 - let renderPhaseUpdates = this._renderPhaseUpdates;
438 - if (renderPhaseUpdates === null) {
439 - this._renderPhaseUpdates = renderPhaseUpdates = new Map();
440 - }
441 - const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);
442 - if (firstRenderPhaseUpdate === undefined) {
443 - renderPhaseUpdates.set(queue, update);
444 - } else {
445 - // Append the update to the end of the list.
446 - let lastRenderPhaseUpdate = firstRenderPhaseUpdate;
447 - while (lastRenderPhaseUpdate.next !== null) {
448 - lastRenderPhaseUpdate = lastRenderPhaseUpdate.next;
449 - }
450 - lastRenderPhaseUpdate.next = update;
451 - }
452 - } else {
453 - const update: Update<A> = {
454 - action,
455 - next: null,
456 - };
457 -
458 - // Append the update to the end of the list.
459 - let last = queue.first;
460 - if (last === null) {
461 - queue.first = update;
462 - } else {
463 - while (last.next !== null) {
464 - last = last.next;
465 - }
466 - last.next = update;
467 - }
468 -
469 - // Re-render now.
470 - this.render(this._element, this._context);
471 - }
472 - }
473 -
474 - _createWorkInProgressHook(): Hook {
475 - if (this._workInProgressHook === null) {
476 - // This is the first hook in the list
477 - if (this._firstWorkInProgressHook === null) {
478 - this._isReRender = false;
479 - this._firstWorkInProgressHook = this._workInProgressHook = createHook();
480 - } else {
481 - // There's already a work-in-progress. Reuse it.
482 - this._isReRender = true;
483 - this._workInProgressHook = this._firstWorkInProgressHook;
484 - }
485 - } else {
486 - if (this._workInProgressHook.next === null) {
487 - this._isReRender = false;
488 - // Append to the end of the list
489 - this._workInProgressHook = (this
490 - ._workInProgressHook: any).next = createHook();
491 - } else {
492 - // There's already a work-in-progress. Reuse it.
493 - this._isReRender = true;
494 - this._workInProgressHook = this._workInProgressHook.next;
495 - }
496 - }
497 - return this._workInProgressHook;
498 - }
499 -
500 - _finishHooks(element: ReactElement, context: null | Object) {
501 - if (this._didScheduleRenderPhaseUpdate) {
502 - // Updates were scheduled during the render phase. They are stored in
503 - // the `renderPhaseUpdates` map. Call the component again, reusing the
504 - // work-in-progress hooks and applying the additional updates on top. Keep
505 - // restarting until no more updates are scheduled.
506 - this._didScheduleRenderPhaseUpdate = false;
507 - this._numberOfReRenders += 1;
508 -
509 - // Start over from the beginning of the list
510 - this._workInProgressHook = null;
511 - this._rendering = false;
512 - this.render(element, context);
513 - } else {
514 - this._workInProgressHook = null;
515 - this._renderPhaseUpdates = null;
516 - this._numberOfReRenders = 0;
517 - }
518 - }
519 -
520 - getMountedInstance() {
521 - return this._instance;
522 - }
523 -
524 - getRenderOutput() {
525 - return this._rendered;
526 - }
527 -
528 - render(element: ReactElement | null, context: null | Object = emptyObject) {
529 - invariant(
530 - React.isValidElement(element),
531 - 'ReactShallowRenderer render(): Invalid component element.%s',
532 - typeof element === 'function'
533 - ? ' Instead of passing a component class, make sure to instantiate ' +
534 - 'it by passing it to React.createElement.'
535 - : '',
536 - );
537 - element = ((element: any): ReactElement);
538 - // Show a special message for host elements since it's a common case.
539 - invariant(
540 - typeof element.type !== 'string',
541 - 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
542 - 'components, not primitives (%s). Instead of calling `.render(el)` and ' +
543 - 'inspecting the rendered output, look at `el.props` directly instead.',
544 - element.type,
545 - );
546 - invariant(
547 - isForwardRef(element) ||
548 - typeof element.type === 'function' ||
549 - isMemo(element),
550 - 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
551 - 'components, but the provided element type was `%s`.',
552 - Array.isArray(element.type)
553 - ? 'array'
554 - : element.type === null
555 - ? 'null'
556 - : typeof element.type,
557 - );
558 -
559 - if (this._rendering) {
560 - return;
561 - }
562 - if (this._element != null && this._element.type !== element.type) {
563 - this._reset();
564 - }
565 -
566 - const elementType = isMemo(element) ? element.type.type : element.type;
567 - const previousElement = this._element;
568 -
569 - this._rendering = true;
570 - this._element = element;
571 - this._context = getMaskedContext(elementType.contextTypes, context);
572 -
573 - // Inner memo component props aren't currently validated in createElement.
574 - if (isMemo(element) && elementType.propTypes) {
575 - currentlyValidatingElement = element;
576 - checkPropTypes(
577 - elementType.propTypes,
578 - element.props,
579 - 'prop',
580 - getComponentName(elementType),
581 - getStackAddendum,
582 - );
583 - }
584 -
585 - if (this._instance) {
586 - this._updateClassComponent(elementType, element, this._context);
587 - } else {
588 - if (shouldConstruct(elementType)) {
589 - this._instance = new elementType(
590 - element.props,
591 - this._context,
592 - this._updater,
593 - );
594 - if (typeof elementType.getDerivedStateFromProps === 'function') {
595 - const partialState = elementType.getDerivedStateFromProps.call(
596 - null,
597 - element.props,
598 - this._instance.state,
599 - );
600 - if (partialState != null) {
601 - this._instance.state = Object.assign(
602 - {},
603 - this._instance.state,
604 - partialState,
605 - );
606 - }
607 - }
608 -
609 - if (elementType.contextTypes) {
610 - currentlyValidatingElement = element;
611 - checkPropTypes(
612 - elementType.contextTypes,
613 - this._context,
614 - 'context',
615 - getName(elementType, this._instance),
616 - getStackAddendum,
617 - );
618 -
619 - currentlyValidatingElement = null;
620 - }
621 -
622 - this._mountClassComponent(elementType, element, this._context);
623 - } else {
624 - let shouldRender = true;
625 - if (isMemo(element) && previousElement !== null) {
626 - // This is a Memo component that is being re-rendered.
627 - const compare = element.type.compare || shallowEqual;
628 - if (compare(previousElement.props, element.props)) {
629 - shouldRender = false;
630 - }
631 - }
632 - if (shouldRender) {
633 - const prevDispatcher = ReactCurrentDispatcher.current;
634 - ReactCurrentDispatcher.current = this._dispatcher;
635 - try {
636 - // elementType could still be a ForwardRef if it was
637 - // nested inside Memo.
638 - if (elementType.$$typeof === ForwardRef) {
639 - invariant(
640 - typeof elementType.render === 'function',
641 - 'forwardRef requires a render function but was given %s.',
642 - typeof elementType.render,
643 - );
644 - this._rendered = elementType.render.call(
645 - undefined,
646 - element.props,
647 - element.ref,
648 - );
649 - } else {
650 - this._rendered = elementType(element.props, this._context);
651 - }
652 - } finally {
653 - ReactCurrentDispatcher.current = prevDispatcher;
654 - }
655 - this._finishHooks(element, context);
656 - }
657 - }
658 - }
659 -
660 - this._rendering = false;
661 - this._updater._invokeCallbacks();
662 -
663 - return this.getRenderOutput();
664 - }
665 -
666 - unmount() {
667 - if (this._instance) {
668 - if (typeof this._instance.componentWillUnmount === 'function') {
669 - this._instance.componentWillUnmount();
670 - }
671 - }
672 - this._reset();
673 - }
674 -
675 - _mountClassComponent(
676 - elementType: Function,
677 - element: ReactElement,
678 - context: null | Object,
679 - ) {
680 - this._instance.context = context;
681 - this._instance.props = element.props;
682 - this._instance.state = this._instance.state || null;
683 - this._instance.updater = this._updater;
684 -
685 - if (
686 - typeof this._instance.UNSAFE_componentWillMount === 'function' ||
687 - typeof this._instance.componentWillMount === 'function'
688 - ) {
689 - const beforeState = this._newState;
690 -
691 - // In order to support react-lifecycles-compat polyfilled components,
692 - // Unsafe lifecycles should not be invoked for components using the new APIs.
693 - if (
694 - typeof elementType.getDerivedStateFromProps !== 'function' &&
695 - typeof this._instance.getSnapshotBeforeUpdate !== 'function'
696 - ) {
697 - if (typeof this._instance.componentWillMount === 'function') {
698 - this._instance.componentWillMount();
699 - }
700 - if (typeof this._instance.UNSAFE_componentWillMount === 'function') {
701 - this._instance.UNSAFE_componentWillMount();
702 - }
703 - }
704 -
705 - // setState may have been called during cWM
706 - if (beforeState !== this._newState) {
707 - this._instance.state = this._newState || emptyObject;
708 - }
709 - }
710 -
711 - this._rendered = this._instance.render();
712 - // Intentionally do not call componentDidMount()
713 - // because DOM refs are not available.
714 - }
715 -
716 - _updateClassComponent(
717 - elementType: Function,
718 - element: ReactElement,
719 - context: null | Object,
720 - ) {
721 - const {props} = element;
722 -
723 - const oldState = this._instance.state || emptyObject;
724 - const oldProps = this._instance.props;
725 -
726 - if (oldProps !== props) {
727 - // In order to support react-lifecycles-compat polyfilled components,
728 - // Unsafe lifecycles should not be invoked for components using the new APIs.
729 - if (
730 - typeof elementType.getDerivedStateFromProps !== 'function' &&
731 - typeof this._instance.getSnapshotBeforeUpdate !== 'function'
732 - ) {
733 - if (typeof this._instance.componentWillReceiveProps === 'function') {
734 - this._instance.componentWillReceiveProps(props, context);
735 - }
736 - if (
737 - typeof this._instance.UNSAFE_componentWillReceiveProps === 'function'
738 - ) {
739 - this._instance.UNSAFE_componentWillReceiveProps(props, context);
740 - }
741 - }
742 - }
743 -
744 - // Read state after cWRP in case it calls setState
745 - let state = this._newState || oldState;
746 - if (typeof elementType.getDerivedStateFromProps === 'function') {
747 - const partialState = elementType.getDerivedStateFromProps.call(
748 - null,
749 - props,
750 - state,
751 - );
752 - if (partialState != null) {
753 - state = Object.assign({}, state, partialState);
754 - }
755 - }
756 -
757 - let shouldUpdate = true;
758 - if (this._forcedUpdate) {
759 - shouldUpdate = true;
760 - this._forcedUpdate = false;
761 - } else if (typeof this._instance.shouldComponentUpdate === 'function') {
762 - shouldUpdate = !!this._instance.shouldComponentUpdate(
763 - props,
764 - state,
765 - context,
766 - );
767 - } else if (
768 - elementType.prototype &&
769 - elementType.prototype.isPureReactComponent
770 - ) {
771 - shouldUpdate =
772 - !shallowEqual(oldProps, props) || !shallowEqual(oldState, state);
773 - }
774 -
775 - if (shouldUpdate) {
776 - // In order to support react-lifecycles-compat polyfilled components,
777 - // Unsafe lifecycles should not be invoked for components using the new APIs.
778 - if (
779 - typeof elementType.getDerivedStateFromProps !== 'function' &&
780 - typeof this._instance.getSnapshotBeforeUpdate !== 'function'
781 - ) {
782 - if (typeof this._instance.componentWillUpdate === 'function') {
783 - this._instance.componentWillUpdate(props, state, context);
784 - }
785 - if (typeof this._instance.UNSAFE_componentWillUpdate === 'function') {
786 - this._instance.UNSAFE_componentWillUpdate(props, state, context);
787 - }
788 - }
789 - }
790 -
791 - this._instance.context = context;
792 - this._instance.props = props;
793 - this._instance.state = state;
794 - this._newState = null;
795 -
796 - if (shouldUpdate) {
797 - this._rendered = this._instance.render();
798 - }
799 - // Intentionally do not call componentDidUpdate()
800 - // because DOM refs are not available.
801 - }
802 -}
803 -
804 -let currentlyValidatingElement = null;
805 -
806 -function getDisplayName(element) {
807 - if (element == null) {
808 - return '#empty';
809 - } else if (typeof element === 'string' || typeof element === 'number') {
810 - return '#text';
811 - } else if (typeof element.type === 'string') {
812 - return element.type;
813 - } else {
814 - const elementType = isMemo(element) ? element.type.type : element.type;
815 - return elementType.displayName || elementType.name || 'Unknown';
816 - }
817 -}
818 -
819 -function getStackAddendum() {
820 - let stack = '';
821 - if (currentlyValidatingElement) {
822 - const name = getDisplayName(currentlyValidatingElement);
823 - const owner = currentlyValidatingElement._owner;
824 - stack += describeComponentFrame(
825 - name,
826 - currentlyValidatingElement._source,
827 - owner && getComponentName(owner.type),
828 - );
829 - }
830 - return stack;
831 -}
832 -
833 -function getName(type, instance) {
834 - const constructor = instance && instance.constructor;
835 - return (
836 - type.displayName ||
837 - (constructor && constructor.displayName) ||
838 - type.name ||
839 - (constructor && constructor.name) ||
840 - null
841 - );
842 -}
843 -
844 -function shouldConstruct(Component) {
845 - return !!(Component.prototype && Component.prototype.isReactComponent);
846 -}
847 -
848 -function getMaskedContext(contextTypes, unmaskedContext) {
849 - if (!contextTypes || !unmaskedContext) {
850 - return emptyObject;
851 - }
852 - const context = {};
853 - for (let key in contextTypes) {
854 - context[key] = unmaskedContext[key];
855 - }
856 - return context;
857 -}
858 -
859 -// This should probably be a default export and a named export.
860 -// However, this not how any of other APIs are designed so doesn't line up
861 -// with our build configs and makes it hard to properly support ES modules
862 -// and CommonJS.
863 -export default ReactShallowRenderer;
yarn.lock
+9
@@ -10856,6 +10856,15 @@ react-native-web@^0.11.5:
10856 prop-types "^15.6.0"
10857 react-timer-mixin "^0.13.4"
10858
10859 +react-shallow-renderer@^16.12.0:
10860 + version "16.12.0"
10861 + resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.12.0.tgz#e68ca8fca7a616db42c36fdd6929723ba0bccef6"
10862 + integrity sha512-elIe2dhXJAO19IY1K3b4YWHBLnKE5wRH+PKx3AYzM6j2+N5UI+FGLKiRNFbLQcggrpBiy3GLhj7MqNUlRk9Z7g==
10863 + dependencies:
10864 + object-assign "^4.1.1"
10865 + prop-types "^15.7.2"
10866 + react-is "^16.12.0"
10867 +
10868 react-timer-mixin@^0.13.4:
10869 version "0.13.4"
10870 resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.4.tgz#75a00c3c94c13abe29b43d63b4c65a88fc8264d3"