// Copyright 2020-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import { has } from 'lodash'; /** * This function is like `Object.assign` but won't create a new object if we don't need * to. This is purely a performance optimization. * * This is useful in places where we don't want to create a new object unnecessarily, * like in reducers where we might cause an unnecessary re-render. * * See the tests for the specifics of how this works. */ export function assignWithNoUnnecessaryAllocation( obj: Readonly, source: Readonly> ): T { // We want to bail early so we use `for .. in` instead of `Object.keys` or similar. // eslint-disable-next-line no-restricted-syntax for (const key in source) { if (!has(source, key)) { continue; } if (!(key in obj) || obj[key] !== source[key]) { return { ...obj, ...source }; } } return obj; }