main
js 703 lines 24.1 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and 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 {emptyContextObject} from './ReactFizzLegacyContext';
11 import {readContext} from './ReactFizzNewContext';
12
13 import {disableLegacyContext} from 'shared/ReactFeatureFlags';
14 import {get as getInstance, set as setInstance} from 'shared/ReactInstanceMap';
15 import getComponentNameFromType from 'shared/getComponentNameFromType';
16 import {REACT_CONTEXT_TYPE, REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';
17 import assign from 'shared/assign';
18 import isArray from 'shared/isArray';
19
20 const didWarnAboutNoopUpdateForComponent: {[string]: boolean} = {};
21 const didWarnAboutDeprecatedWillMount: {[string]: boolean} = {};
22
23 let didWarnAboutUninitializedState;
24 let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
25 let didWarnAboutLegacyLifecyclesAndDerivedState;
26 let didWarnAboutUndefinedDerivedState;
27 let didWarnAboutDirectlyAssigningPropsToState;
28 let didWarnAboutContextTypeAndContextTypes;
29 let didWarnAboutContextTypes;
30 let didWarnAboutChildContextTypes;
31 let didWarnAboutInvalidateContextType;
32 let didWarnOnInvalidCallback;
33
34 if (__DEV__) {
35 didWarnAboutUninitializedState = new Set<string>();
36 didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set<mixed>();
37 didWarnAboutLegacyLifecyclesAndDerivedState = new Set<string>();
38 didWarnAboutDirectlyAssigningPropsToState = new Set<string>();
39 didWarnAboutUndefinedDerivedState = new Set<string>();
40 didWarnAboutContextTypeAndContextTypes = new Set<mixed>();
41 didWarnAboutContextTypes = new Set<mixed>();
42 didWarnAboutChildContextTypes = new Set<mixed>();
43 didWarnAboutInvalidateContextType = new Set<mixed>();
44 didWarnOnInvalidCallback = new Set<string>();
45 }
46
47 function warnOnInvalidCallback(callback: mixed) {
48 if (__DEV__) {
49 if (callback === null || typeof callback === 'function') {
50 return;
51 }
52 // eslint-disable-next-line react-internal/safe-string-coercion
53 const key = String(callback);
54 if (!didWarnOnInvalidCallback.has(key)) {
55 didWarnOnInvalidCallback.add(key);
56 console.error(
57 'Expected the last optional `callback` argument to be a ' +
58 'function. Instead received: %s.',
59 callback,
60 );
61 }
62 }
63 }
64
65 function warnOnUndefinedDerivedState(type: any, partialState: any) {
66 if (__DEV__) {
67 if (partialState === undefined) {
68 const componentName = getComponentNameFromType(type) || 'Component';
69 if (!didWarnAboutUndefinedDerivedState.has(componentName)) {
70 didWarnAboutUndefinedDerivedState.add(componentName);
71 console.error(
72 '%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' +
73 'You have returned undefined.',
74 componentName,
75 );
76 }
77 }
78 }
79 }
80
81 function warnNoop(
82 publicInstance: component(...props: any),
83 callerName: string,
84 ) {
85 if (__DEV__) {
86 const constructor = publicInstance.constructor;
87 const componentName =
88 (constructor && getComponentNameFromType(constructor)) || 'ReactClass';
89 const warningKey = componentName + '.' + callerName;
90 if (didWarnAboutNoopUpdateForComponent[warningKey]) {
91 return;
92 }
93
94 console.error(
95 'Can only update a mounting component. ' +
96 'This usually means you called %s() outside componentWillMount() on the server. ' +
97 'This is a no-op.\n\nPlease check the code for the %s component.',
98 callerName,
99 componentName,
100 );
101 didWarnAboutNoopUpdateForComponent[warningKey] = true;
102 }
103 }
104
105 type InternalInstance = {
106 queue: null | Array<Object>,
107 replace: boolean,
108 };
109
110 const classComponentUpdater = {
111 // $FlowFixMe[missing-local-annot]
112 enqueueSetState(inst: any, payload: any, callback) {
113 const internals: InternalInstance = getInstance(inst);
114 if (internals.queue === null) {
115 warnNoop(inst, 'setState');
116 } else {
117 internals.queue.push(payload);
118 if (__DEV__) {
119 if (callback !== undefined && callback !== null) {
120 warnOnInvalidCallback(callback);
121 }
122 }
123 }
124 },
125 enqueueReplaceState(inst: any, payload: any, callback: null) {
126 const internals: InternalInstance = getInstance(inst);
127 internals.replace = true;
128 internals.queue = [payload];
129 if (__DEV__) {
130 if (callback !== undefined && callback !== null) {
131 warnOnInvalidCallback(callback);
132 }
133 }
134 },
135 // $FlowFixMe[missing-local-annot]
136 enqueueForceUpdate(inst: any, callback) {
137 const internals: InternalInstance = getInstance(inst);
138 if (internals.queue === null) {
139 warnNoop(inst, 'forceUpdate');
140 } else {
141 if (__DEV__) {
142 if (callback !== undefined && callback !== null) {
143 warnOnInvalidCallback(callback);
144 }
145 }
146 }
147 },
148 };
149
150 function applyDerivedStateFromProps(
151 instance: any,
152 ctor: any,
153 getDerivedStateFromProps: (props: any, state: any) => any,
154 prevState: any,
155 nextProps: any,
156 ) {
157 const partialState = getDerivedStateFromProps(nextProps, prevState);
158
159 if (__DEV__) {
160 warnOnUndefinedDerivedState(ctor, partialState);
161 }
162 // Merge the partial state and the previous state.
163 const newState =
164 partialState === null || partialState === undefined
165 ? prevState
166 : assign({}, prevState, partialState);
167 return newState;
168 }
169
170 export function constructClassInstance(
171 ctor: any,
172 props: any,
173 maskedLegacyContext: any,
174 ): any {
175 let context = emptyContextObject;
176 const contextType = ctor.contextType;
177
178 if (__DEV__) {
179 if ('contextType' in ctor) {
180 const isValid =
181 // Allow null for conditional declaration
182 contextType === null ||
183 (contextType !== undefined &&
184 contextType.$$typeof === REACT_CONTEXT_TYPE);
185
186 if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) {
187 didWarnAboutInvalidateContextType.add(ctor);
188
189 let addendum = '';
190 if (contextType === undefined) {
191 addendum =
192 ' However, it is set to undefined. ' +
193 'This can be caused by a typo or by mixing up named and default imports. ' +
194 'This can also happen due to a circular dependency, so ' +
195 'try moving the createContext() call to a separate file.';
196 } else if (typeof contextType !== 'object') {
197 addendum = ' However, it is set to a ' + typeof contextType + '.';
198 } else if (contextType.$$typeof === REACT_CONSUMER_TYPE) {
199 addendum = ' Did you accidentally pass the Context.Consumer instead?';
200 } else {
201 addendum =
202 ' However, it is set to an object with keys {' +
203 Object.keys(contextType).join(', ') +
204 '}.';
205 }
206 console.error(
207 '%s defines an invalid contextType. ' +
208 'contextType should point to the Context object returned by React.createContext().%s',
209 getComponentNameFromType(ctor) || 'Component',
210 addendum,
211 );
212 }
213 }
214 }
215
216 if (typeof contextType === 'object' && contextType !== null) {
217 context = readContext(contextType as any);
218 } else if (!disableLegacyContext) {
219 context = maskedLegacyContext;
220 }
221
222 const instance = new ctor(props, context);
223
224 if (__DEV__) {
225 if (
226 typeof ctor.getDerivedStateFromProps === 'function' &&
227 (instance.state === null || instance.state === undefined)
228 ) {
229 const componentName = getComponentNameFromType(ctor) || 'Component';
230 if (!didWarnAboutUninitializedState.has(componentName)) {
231 didWarnAboutUninitializedState.add(componentName);
232 console.error(
233 '`%s` uses `getDerivedStateFromProps` but its initial state is ' +
234 '%s. This is not recommended. Instead, define the initial state by ' +
235 'assigning an object to `this.state` in the constructor of `%s`. ' +
236 'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.',
237 componentName,
238 instance.state === null ? 'null' : 'undefined',
239 componentName,
240 );
241 }
242 }
243
244 // If new component APIs are defined, "unsafe" lifecycles won't be called.
245 // Warn about these lifecycles if they are present.
246 // Don't warn about react-lifecycles-compat polyfilled methods though.
247 if (
248 typeof ctor.getDerivedStateFromProps === 'function' ||
249 typeof instance.getSnapshotBeforeUpdate === 'function'
250 ) {
251 let foundWillMountName = null;
252 let foundWillReceivePropsName = null;
253 let foundWillUpdateName = null;
254 if (
255 typeof instance.componentWillMount === 'function' &&
256 instance.componentWillMount.__suppressDeprecationWarning !== true
257 ) {
258 foundWillMountName = 'componentWillMount';
259 } else if (typeof instance.UNSAFE_componentWillMount === 'function') {
260 foundWillMountName = 'UNSAFE_componentWillMount';
261 }
262 if (
263 typeof instance.componentWillReceiveProps === 'function' &&
264 instance.componentWillReceiveProps.__suppressDeprecationWarning !== true
265 ) {
266 foundWillReceivePropsName = 'componentWillReceiveProps';
267 } else if (
268 typeof instance.UNSAFE_componentWillReceiveProps === 'function'
269 ) {
270 foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps';
271 }
272 if (
273 typeof instance.componentWillUpdate === 'function' &&
274 instance.componentWillUpdate.__suppressDeprecationWarning !== true
275 ) {
276 foundWillUpdateName = 'componentWillUpdate';
277 } else if (typeof instance.UNSAFE_componentWillUpdate === 'function') {
278 foundWillUpdateName = 'UNSAFE_componentWillUpdate';
279 }
280 if (
281 foundWillMountName !== null ||
282 foundWillReceivePropsName !== null ||
283 foundWillUpdateName !== null
284 ) {
285 const componentName = getComponentNameFromType(ctor) || 'Component';
286 const newApiName =
287 typeof ctor.getDerivedStateFromProps === 'function'
288 ? 'getDerivedStateFromProps()'
289 : 'getSnapshotBeforeUpdate()';
290 if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(componentName)) {
291 didWarnAboutLegacyLifecyclesAndDerivedState.add(componentName);
292 console.error(
293 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
294 '%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' +
295 'The above lifecycles should be removed. Learn more about this warning here:\n' +
296 'https://react.dev/link/unsafe-component-lifecycles',
297 componentName,
298 newApiName,
299 foundWillMountName !== null ? `\n ${foundWillMountName}` : '',
300 foundWillReceivePropsName !== null
301 ? `\n ${foundWillReceivePropsName}`
302 : '',
303 foundWillUpdateName !== null ? `\n ${foundWillUpdateName}` : '',
304 );
305 }
306 }
307 }
308 }
309
310 return instance;
311 }
312
313 function checkClassInstance(instance: any, ctor: any, newProps: any) {
314 if (__DEV__) {
315 const name = getComponentNameFromType(ctor) || 'Component';
316 const renderPresent = instance.render;
317
318 if (!renderPresent) {
319 if (ctor.prototype && typeof ctor.prototype.render === 'function') {
320 console.error(
321 'No `render` method found on the %s ' +
322 'instance: did you accidentally return an object from the constructor?',
323 name,
324 );
325 } else {
326 console.error(
327 'No `render` method found on the %s ' +
328 'instance: you may have forgotten to define `render`.',
329 name,
330 );
331 }
332 }
333
334 if (
335 instance.getInitialState &&
336 !instance.getInitialState.isReactClassApproved &&
337 !instance.state
338 ) {
339 console.error(
340 'getInitialState was defined on %s, a plain JavaScript class. ' +
341 'This is only supported for classes created using React.createClass. ' +
342 'Did you mean to define a state property instead?',
343 name,
344 );
345 }
346 if (
347 instance.getDefaultProps &&
348 !instance.getDefaultProps.isReactClassApproved
349 ) {
350 console.error(
351 'getDefaultProps was defined on %s, a plain JavaScript class. ' +
352 'This is only supported for classes created using React.createClass. ' +
353 'Use a static property to define defaultProps instead.',
354 name,
355 );
356 }
357 if (instance.contextType) {
358 console.error(
359 'contextType was defined as an instance property on %s. Use a static ' +
360 'property to define contextType instead.',
361 name,
362 );
363 }
364
365 if (disableLegacyContext) {
366 if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {
367 didWarnAboutChildContextTypes.add(ctor);
368 console.error(
369 '%s uses the legacy childContextTypes API which was removed in React 19. ' +
370 'Use React.createContext() instead. (https://react.dev/link/legacy-context)',
371 name,
372 );
373 }
374 if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {
375 didWarnAboutContextTypes.add(ctor);
376 console.error(
377 '%s uses the legacy contextTypes API which was removed in React 19. ' +
378 'Use React.createContext() with static contextType instead. ' +
379 '(https://react.dev/link/legacy-context)',
380 name,
381 );
382 }
383 } else {
384 if (instance.contextTypes) {
385 console.error(
386 'contextTypes was defined as an instance property on %s. Use a static ' +
387 'property to define contextTypes instead. (https://react.dev/link/legacy-context)',
388 name,
389 );
390 }
391
392 if (
393 ctor.contextType &&
394 ctor.contextTypes &&
395 !didWarnAboutContextTypeAndContextTypes.has(ctor)
396 ) {
397 didWarnAboutContextTypeAndContextTypes.add(ctor);
398 console.error(
399 '%s declares both contextTypes and contextType static properties. ' +
400 'The legacy contextTypes property will be ignored.',
401 name,
402 );
403 }
404 if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {
405 didWarnAboutChildContextTypes.add(ctor);
406 console.error(
407 '%s uses the legacy childContextTypes API which will soon be removed. ' +
408 'Use React.createContext() instead. (https://react.dev/link/legacy-context)',
409 name,
410 );
411 }
412 if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {
413 didWarnAboutContextTypes.add(ctor);
414 console.error(
415 '%s uses the legacy contextTypes API which will soon be removed. ' +
416 'Use React.createContext() with static contextType instead. ' +
417 '(https://react.dev/link/legacy-context)',
418 name,
419 );
420 }
421 }
422
423 if (typeof instance.componentShouldUpdate === 'function') {
424 console.error(
425 '%s has a method called ' +
426 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
427 'The name is phrased as a question because the function is ' +
428 'expected to return a value.',
429 name,
430 );
431 }
432 if (
433 ctor.prototype &&
434 ctor.prototype.isPureReactComponent &&
435 typeof instance.shouldComponentUpdate !== 'undefined'
436 ) {
437 console.error(
438 '%s has a method called shouldComponentUpdate(). ' +
439 'shouldComponentUpdate should not be used when extending React.PureComponent. ' +
440 'Please extend React.Component if shouldComponentUpdate is used.',
441 getComponentNameFromType(ctor) || 'A pure component',
442 );
443 }
444 if (typeof instance.componentDidUnmount === 'function') {
445 console.error(
446 '%s has a method called ' +
447 'componentDidUnmount(). But there is no such lifecycle method. ' +
448 'Did you mean componentWillUnmount()?',
449 name,
450 );
451 }
452 if (typeof instance.componentDidReceiveProps === 'function') {
453 console.error(
454 '%s has a method called ' +
455 'componentDidReceiveProps(). But there is no such lifecycle method. ' +
456 'If you meant to update the state in response to changing props, ' +
457 'use componentWillReceiveProps(). If you meant to fetch data or ' +
458 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().',
459 name,
460 );
461 }
462 if (typeof instance.componentWillRecieveProps === 'function') {
463 console.error(
464 '%s has a method called ' +
465 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',
466 name,
467 );
468 }
469 if (typeof instance.UNSAFE_componentWillRecieveProps === 'function') {
470 console.error(
471 '%s has a method called ' +
472 'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?',
473 name,
474 );
475 }
476 const hasMutatedProps = instance.props !== newProps;
477 if (instance.props !== undefined && hasMutatedProps) {
478 console.error(
479 'When calling super() in `%s`, make sure to pass ' +
480 "up the same props that your component's constructor was passed.",
481 name,
482 );
483 }
484 if (instance.defaultProps) {
485 console.error(
486 'Setting defaultProps as an instance property on %s is not supported and will be ignored.' +
487 ' Instead, define defaultProps as a static property on %s.',
488 name,
489 name,
490 );
491 }
492
493 if (
494 typeof instance.getSnapshotBeforeUpdate === 'function' &&
495 typeof instance.componentDidUpdate !== 'function' &&
496 !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor)
497 ) {
498 didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor);
499 console.error(
500 '%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' +
501 'This component defines getSnapshotBeforeUpdate() only.',
502 getComponentNameFromType(ctor),
503 );
504 }
505
506 if (typeof instance.getDerivedStateFromProps === 'function') {
507 console.error(
508 '%s: getDerivedStateFromProps() is defined as an instance method ' +
509 'and will be ignored. Instead, declare it as a static method.',
510 name,
511 );
512 }
513 if (typeof instance.getDerivedStateFromError === 'function') {
514 console.error(
515 '%s: getDerivedStateFromError() is defined as an instance method ' +
516 'and will be ignored. Instead, declare it as a static method.',
517 name,
518 );
519 }
520 if (typeof ctor.getSnapshotBeforeUpdate === 'function') {
521 console.error(
522 '%s: getSnapshotBeforeUpdate() is defined as a static method ' +
523 'and will be ignored. Instead, declare it as an instance method.',
524 name,
525 );
526 }
527 const state = instance.state;
528 if (state && (typeof state !== 'object' || isArray(state))) {
529 console.error('%s.state: must be set to an object or null', name);
530 }
531 if (
532 typeof instance.getChildContext === 'function' &&
533 typeof ctor.childContextTypes !== 'object'
534 ) {
535 console.error(
536 '%s.getChildContext(): childContextTypes must be defined in order to ' +
537 'use getChildContext().',
538 name,
539 );
540 }
541 }
542 }
543
544 function callComponentWillMount(type: any, instance: any) {
545 const oldState = instance.state;
546
547 if (typeof instance.componentWillMount === 'function') {
548 if (__DEV__) {
549 if (instance.componentWillMount.__suppressDeprecationWarning !== true) {
550 const componentName = getComponentNameFromType(type) || 'Unknown';
551
552 if (!didWarnAboutDeprecatedWillMount[componentName]) {
553 console.warn(
554 // keep this warning in sync with ReactStrictModeWarning.js
555 'componentWillMount has been renamed, and is not recommended for use. ' +
556 'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
557 '* Move code from componentWillMount to componentDidMount (preferred in most cases) ' +
558 'or the constructor.\n' +
559 '\nPlease update the following components: %s',
560 componentName,
561 );
562 didWarnAboutDeprecatedWillMount[componentName] = true;
563 }
564 }
565 }
566
567 instance.componentWillMount();
568 }
569 if (typeof instance.UNSAFE_componentWillMount === 'function') {
570 instance.UNSAFE_componentWillMount();
571 }
572
573 if (oldState !== instance.state) {
574 if (__DEV__) {
575 console.error(
576 '%s.componentWillMount(): Assigning directly to this.state is ' +
577 "deprecated (except inside a component's " +
578 'constructor). Use setState instead.',
579 getComponentNameFromType(type) || 'Component',
580 );
581 }
582 classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
583 }
584 }
585
586 function processUpdateQueue(
587 internalInstance: InternalInstance,
588 inst: any,
589 props: any,
590 maskedLegacyContext: any,
591 ): void {
592 if (internalInstance.queue !== null && internalInstance.queue.length > 0) {
593 const oldQueue = internalInstance.queue;
594 const oldReplace = internalInstance.replace;
595 internalInstance.queue = null;
596 internalInstance.replace = false;
597
598 if (oldReplace && oldQueue.length === 1) {
599 inst.state = oldQueue[0];
600 } else {
601 let nextState = oldReplace ? oldQueue[0] : inst.state;
602 let dontMutate = true;
603 for (let i = oldReplace ? 1 : 0; i < oldQueue.length; i++) {
604 const partial = oldQueue[i];
605 const partialState =
606 typeof partial === 'function'
607 ? partial.call(inst, nextState, props, maskedLegacyContext)
608 : partial;
609 if (partialState != null) {
610 if (dontMutate) {
611 dontMutate = false;
612 nextState = assign({}, nextState, partialState);
613 } else {
614 assign(nextState, partialState);
615 }
616 }
617 }
618 inst.state = nextState;
619 }
620 } else {
621 internalInstance.queue = null;
622 }
623 }
624
625 // Invokes the mount life-cycles on a previously never rendered instance.
626 export function mountClassInstance(
627 instance: any,
628 ctor: any,
629 newProps: any,
630 maskedLegacyContext: any,
631 ): void {
632 if (__DEV__) {
633 checkClassInstance(instance, ctor, newProps);
634 }
635
636 const initialState = instance.state !== undefined ? instance.state : null;
637
638 instance.updater = classComponentUpdater;
639 instance.props = newProps;
640 instance.state = initialState;
641 // We don't bother initializing the refs object on the server, since we're not going to resolve them anyway.
642
643 // The internal instance will be used to manage updates that happen during this mount.
644 const internalInstance: InternalInstance = {
645 queue: [],
646 replace: false,
647 };
648 setInstance(instance, internalInstance);
649
650 const contextType = ctor.contextType;
651 if (typeof contextType === 'object' && contextType !== null) {
652 instance.context = readContext(contextType);
653 } else if (disableLegacyContext) {
654 instance.context = emptyContextObject;
655 } else {
656 instance.context = maskedLegacyContext;
657 }
658
659 if (__DEV__) {
660 if (instance.state === newProps) {
661 const componentName = getComponentNameFromType(ctor) || 'Component';
662 if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) {
663 didWarnAboutDirectlyAssigningPropsToState.add(componentName);
664 console.error(
665 '%s: It is not recommended to assign props directly to state ' +
666 "because updates to props won't be reflected in state. " +
667 'In most cases, it is better to use props directly.',
668 componentName,
669 );
670 }
671 }
672 }
673
674 const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
675 if (typeof getDerivedStateFromProps === 'function') {
676 instance.state = applyDerivedStateFromProps(
677 instance,
678 ctor,
679 getDerivedStateFromProps,
680 initialState,
681 newProps,
682 );
683 }
684
685 // In order to support react-lifecycles-compat polyfilled components,
686 // Unsafe lifecycles should not be invoked for components using the new APIs.
687 if (
688 typeof ctor.getDerivedStateFromProps !== 'function' &&
689 typeof instance.getSnapshotBeforeUpdate !== 'function' &&
690 (typeof instance.UNSAFE_componentWillMount === 'function' ||
691 typeof instance.componentWillMount === 'function')
692 ) {
693 callComponentWillMount(ctor, instance);
694 // If we had additional state updates during this life-cycle, let's
695 // process them now.
696 processUpdateQueue(
697 internalInstance,
698 instance,
699 newProps,
700 maskedLegacyContext,
701 );
702 }
703 }