123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- /**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
- */
- 'use strict';
- /**
- * If your application is accepting different values for the same field over
- * time and is doing a diff on them, you can either (1) create a copy or
- * (2) ensure that those values are not mutated behind two passes.
- * This function helps you with (2) by freezing the object and throwing if
- * the user subsequently modifies the value.
- *
- * There are two caveats with this function:
- * - If the call site is not in strict mode, it will only throw when
- * mutating existing fields, adding a new one
- * will unfortunately fail silently :(
- * - If the object is already frozen or sealed, it will not continue the
- * deep traversal and will leave leaf nodes unfrozen.
- *
- * Freezing the object and adding the throw mechanism is expensive and will
- * only be used in DEV.
- */
- function deepFreezeAndThrowOnMutationInDev<T: Object>(object: T): T {
- if (__DEV__) {
- if (
- typeof object !== 'object' ||
- object === null ||
- Object.isFrozen(object) ||
- Object.isSealed(object)
- ) {
- return object;
- }
- const keys = Object.keys(object);
- const hasOwnProperty = Object.prototype.hasOwnProperty;
- for (let i = 0; i < keys.length; i++) {
- const key = keys[i];
- if (hasOwnProperty.call(object, key)) {
- Object.defineProperty(object, key, {
- get: identity.bind(null, object[key]),
- });
- Object.defineProperty(object, key, {
- set: throwOnImmutableMutation.bind(null, key),
- });
- }
- }
- Object.freeze(object);
- Object.seal(object);
- for (let i = 0; i < keys.length; i++) {
- const key = keys[i];
- if (hasOwnProperty.call(object, key)) {
- deepFreezeAndThrowOnMutationInDev(object[key]);
- }
- }
- }
- return object;
- }
- function throwOnImmutableMutation(key, value) {
- throw Error(
- 'You attempted to set the key `' +
- key +
- '` with the value `' +
- JSON.stringify(value) +
- '` on an object that is meant to be immutable ' +
- 'and has been frozen.',
- );
- }
- function identity(value) {
- return value;
- }
- module.exports = deepFreezeAndThrowOnMutationInDev;
|