Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Clone objects via wrapper #22970

Merged
merged 15 commits into from
Jun 27, 2023
Merged
5 changes: 3 additions & 2 deletions lib/config/massage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import is from '@sindresorhus/is';
import { clone } from '../util/clone';
import { getOptions } from './options';
import type { PackageRule, RenovateConfig, UpdateType } from './types';

Expand All @@ -16,7 +17,7 @@ export function massageConfig(config: RenovateConfig): RenovateConfig {
}
});
}
const massagedConfig = structuredClone(config);
const massagedConfig = clone(config);
for (const [key, val] of Object.entries(config)) {
if (allowedStrings.includes(key) && is.string(val)) {
massagedConfig[key] = [val];
Expand Down Expand Up @@ -55,7 +56,7 @@ export function massageConfig(config: RenovateConfig): RenovateConfig {
PackageRule
][]) {
if (updateTypes.includes(key)) {
let newRule = structuredClone(rule);
let newRule = clone(rule);
Object.keys(newRule).forEach((newKey) => {
if (!(newKey.startsWith(`match`) || newKey.startsWith('exclude'))) {
delete newRule[newKey];
Expand Down
3 changes: 2 additions & 1 deletion lib/config/presets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
import { logger } from '../../logger';
import { ExternalHostError } from '../../types/errors/external-host-error';
import * as memCache from '../../util/cache/memory';
import { clone } from '../../util/clone';
import { regEx } from '../../util/regex';
import * as massage from '../massage';
import * as migration from '../migration';
Expand Down Expand Up @@ -273,7 +274,7 @@ export async function resolveConfigPresets(
_ignorePresets?: string[],
existingPresets: string[] = []
): Promise<AllConfig> {
let ignorePresets = structuredClone(_ignorePresets);
let ignorePresets = clone(_ignorePresets);
if (!ignorePresets || ignorePresets.length === 0) {
ignorePresets = inputConfig.ignorePresets ?? [];
}
Expand Down
5 changes: 3 additions & 2 deletions lib/config/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { logger } from '../logger';
import { clone } from '../util/clone';
import { getHighestVulnerabilitySeverity } from '../util/vulnerability/utils';
import * as options from './options';
import type { RenovateConfig } from './types';
Expand All @@ -11,8 +12,8 @@ export function mergeChildConfig<
if (!child) {
return parent as never;
}
const parentConfig = structuredClone(parent);
const childConfig = structuredClone(child);
const parentConfig = clone(parent);
const childConfig = clone(child);
const config: Record<string, any> = { ...parentConfig, ...childConfig };

// Ensure highest severity survives parent / child merge
Expand Down
2 changes: 1 addition & 1 deletion lib/logger/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export default function prepareError(err: Error): Record<string, unknown> {
statusCode: err.response?.statusCode,
statusMessage: err.response?.statusMessage,
body:
// istanbul ignore if: not easily testable
// istanbul ignore next: not easily testable
err.name === 'TimeoutError'
? undefined
: structuredClone(err.response.body),
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/datasource/jenkins-plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class JenkinsPluginsDatasource extends Datasource {
return null;
}

const result = structuredClone(plugin);
const result = clone(plugin);
const versions = await this.getJenkinsPluginVersions();
const releases = versions[packageName];
result.releases = releases ? clone(releases) : [];
Expand Down
3 changes: 2 additions & 1 deletion lib/modules/manager/bazel-module/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import parseGithubUrl from 'github-url-from-git';
import { z } from 'zod';
import { logger } from '../../../logger';
import type { SkipReason } from '../../../types';
import { clone } from '../../../util/clone';
import { regEx } from '../../../util/regex';
import { BazelDatasource } from '../../datasource/bazel';
import { GithubTagsDatasource } from '../../datasource/github-tags';
Expand Down Expand Up @@ -50,7 +51,7 @@ function isMerge(value: BazelModulePackageDep): value is MergePackageDep {
export function bazelModulePackageDepToPackageDependency(
bmpd: BazelModulePackageDep
): PackageDependency {
const copy: BazelModulePackageDep = structuredClone(bmpd);
const copy: BazelModulePackageDep = clone(bmpd);
if (isOverride(copy)) {
const partial = copy as Partial<OverridePackageDep>;
delete partial.bazelDepSkipReason;
Expand Down
3 changes: 2 additions & 1 deletion lib/modules/manager/gradle/parser/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { lexer, parser, query as q } from 'good-enough-parser';
import { clone } from '../../../../util/clone';
import { regEx } from '../../../../util/regex';
import type {
Ctx,
Expand Down Expand Up @@ -51,7 +52,7 @@ export function reduceNestingDepth(ctx: Ctx): Ctx {
}

export function prependNestingDepth(ctx: Ctx): Ctx {
ctx.varTokens = [...structuredClone(ctx.tmpNestingDepth), ...ctx.varTokens];
ctx.varTokens = [...clone(ctx.tmpNestingDepth), ...ctx.varTokens];
return ctx;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { updateLockedDependency } from '../..';
import { Fixtures } from '../../../../../../test/fixtures';
import * as httpMock from '../../../../../../test/http-mock';
import { clone } from '../../../../../util/clone';
import type { UpdateLockedConfig } from '../../../types';

const packageFileContent = Fixtures.get('package.json', './package-lock');
Expand Down Expand Up @@ -113,7 +114,7 @@ describe('modules/manager/npm/update/locked-dependency/index', () => {
});

it('fails to remediate if parent dep cannot support', async () => {
const acceptsModified = structuredClone(acceptsJson);
const acceptsModified = clone(acceptsJson);
acceptsModified.versions['2.0.0'] = {};
httpMock
.scope('https://registry.npmjs.org')
Expand Down
13 changes: 0 additions & 13 deletions lib/util/__snapshots__/clone.spec.ts.snap

This file was deleted.

40 changes: 28 additions & 12 deletions lib/util/clone.spec.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import { clone } from './clone';

describe('util/clone', () => {
it('returns null', () => {
const res = clone(null);
expect(res).toBeNull();
test.each`
input | expected
${undefined} | ${undefined}
${null} | ${null}
${true} | ${true}
${false} | ${false}
${0} | ${0}
${1} | ${1}
${NaN} | ${NaN}
${Infinity} | ${Infinity}
${-Infinity} | ${-Infinity}
${''} | ${''}
${'string'} | ${'string'}
${[]} | ${[]}
${[1, 2, 3]} | ${[1, 2, 3]}
${{}} | ${{}}
${{ a: 1 }} | ${{ a: 1 }}
`('returns $expected when input is $input', ({ input, expected }) => {
const res = clone(input);
expect(res).toStrictEqual(expected);
});

it('maintains same order', () => {
const obj: any = {
name: 'object',
type: 'object',
isObject: true,
b: 'foo',
a: 'bar',
c: 'baz',
};

const res = clone(obj);

expect(res).toMatchSnapshot(`{
name: 'object',
type: 'object',
isObject: true,
}`);
expect(Object.entries(res)).toMatchObject([
['b', 'foo'],
['a', 'bar'],
['c', 'baz'],
]);
});

it('assigns "[Circular]" to circular references', () => {
Expand Down
1 change: 0 additions & 1 deletion lib/util/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { quickStringify } from './stringify';

/**
* Creates a deep clone of an object.
* @deprecated Use {@link structuredClone} instead.
* @param input The object to clone.
*/
export function clone<T = unknown>(input: T): T {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DateTime, Settings } from 'luxon';
import * as memCache from '../../../cache/memory';
import { clone } from '../../../clone';
import type { GithubDatasourceItem, GithubGraphqlCacheRecord } from '../types';
import { GithubGraphqlMemoryCacheStrategy } from './memory-cache-strategy';

Expand Down Expand Up @@ -44,7 +45,7 @@ describe('util/github/graphql/cache-strategies/memory-cache-strategy', () => {
items,
createdAt: isoTs('2022-10-01 15:30'),
};
memCache.set('github-graphql-cache:foo:bar', structuredClone(cacheRecord));
memCache.set('github-graphql-cache:foo:bar', clone(cacheRecord));

// At this moment, cache is valid
let now = '2022-10-31 15:29:59';
Expand Down Expand Up @@ -84,7 +85,7 @@ describe('util/github/graphql/cache-strategies/memory-cache-strategy', () => {
items: oldItems,
createdAt: isoTs('2022-10-30 12:00'),
};
memCache.set('github-graphql-cache:foo:bar', structuredClone(cacheRecord));
memCache.set('github-graphql-cache:foo:bar', clone(cacheRecord));

const now = '2022-10-31 15:30';
mockTime(now);
Expand Down Expand Up @@ -120,7 +121,7 @@ describe('util/github/graphql/cache-strategies/memory-cache-strategy', () => {
items: oldItems,
createdAt: isoTs('2022-10-30 12:00'),
};
memCache.set('github-graphql-cache:foo:bar', structuredClone(cacheRecord));
memCache.set('github-graphql-cache:foo:bar', clone(cacheRecord));

const now = '2022-10-31 15:30';
mockTime(now);
Expand All @@ -146,7 +147,7 @@ describe('util/github/graphql/cache-strategies/memory-cache-strategy', () => {
items: oldItems,
createdAt: isoTs('2022-12-31 12:00'),
};
memCache.set('github-graphql-cache:foo:bar', structuredClone(cacheRecord));
memCache.set('github-graphql-cache:foo:bar', clone(cacheRecord));

const now = '2022-12-31 23:59';
mockTime(now);
Expand Down Expand Up @@ -190,7 +191,7 @@ describe('util/github/graphql/cache-strategies/memory-cache-strategy', () => {
items,
createdAt: isoTs('2022-10-30 12:00'),
};
memCache.set('github-graphql-cache:foo:bar', structuredClone(cacheRecord));
memCache.set('github-graphql-cache:foo:bar', clone(cacheRecord));

const now = '2022-10-31 15:30';
mockTime(now);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DateTime, Settings } from 'luxon';
import * as packageCache from '../../../cache/package';
import { clone } from '../../../clone';
import type { GithubDatasourceItem, GithubGraphqlCacheRecord } from '../types';
import { GithubGraphqlPackageCacheStrategy } from './package-cache-strategy';

Expand Down Expand Up @@ -30,7 +31,7 @@ describe('util/github/graphql/cache-strategies/package-cache-strategy', () => {
items: oldItems,
createdAt: isoTs('2022-10-15 12:00'),
};
cacheGet.mockResolvedValueOnce(structuredClone(cacheRecord));
cacheGet.mockResolvedValueOnce(clone(cacheRecord));

const now = '2022-10-30 12:00';
mockTime(now);
Expand Down
5 changes: 3 additions & 2 deletions lib/util/host-rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import is from '@sindresorhus/is';
import merge from 'deepmerge';
import { logger } from '../logger';
import type { HostRule, HostRuleSearchResult } from '../types';
import { clone } from './clone';
import * as sanitize from './sanitize';
import { toBase64 } from './string';
import { parseUrl, validateUrl } from './url';
Expand All @@ -17,7 +18,7 @@ export interface LegacyHostRule {
}

export function migrateRule(rule: LegacyHostRule & HostRule): HostRule {
const cloned: LegacyHostRule & HostRule = structuredClone(rule);
const cloned: LegacyHostRule & HostRule = clone(rule);
delete cloned.hostName;
delete cloned.domainName;
delete cloned.baseUrl;
Expand Down Expand Up @@ -188,7 +189,7 @@ export function findAll({ hostType }: { hostType: string }): HostRule[] {
* @returns a deep copy of all known host rules without any filtering
*/
export function getAll(): HostRule[] {
return structuredClone(hostRules);
return clone(hostRules);
}

export function clear(): void {
Expand Down
3 changes: 2 additions & 1 deletion lib/workers/repository/init/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { applySecretsToConfig } from '../../../config/secrets';
import type { RenovateConfig } from '../../../config/types';
import { logger } from '../../../logger';
import { platform } from '../../../modules/platform';
import { clone } from '../../../util/clone';
import { cloneSubmodules, setUserRepoConfig } from '../../../util/git';
import { getAll } from '../../../util/host-rules';
import { checkIfConfigured } from '../configured';
Expand All @@ -14,7 +15,7 @@ import { detectVulnerabilityAlerts } from './vulnerability';

function initializeConfig(config: RenovateConfig): RenovateConfig {
return {
...structuredClone(config),
...clone(config),
errors: [],
warnings: [],
branchList: [],
Expand Down
3 changes: 2 additions & 1 deletion lib/workers/repository/onboarding/branch/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import type {
RenovateSharedConfig,
} from '../../../../config/types';
import { logger } from '../../../../logger';
import { clone } from '../../../../util/clone';
import { EditorConfig, JSONWriter } from '../../../../util/json-writer';

async function getOnboardingConfig(
config: RenovateConfig
): Promise<RenovateSharedConfig | undefined> {
let onboardingConfig = structuredClone(config.onboardingConfig);
let onboardingConfig = clone(config.onboardingConfig);

let orgPreset: string | undefined;

Expand Down
3 changes: 2 additions & 1 deletion lib/workers/repository/package-files.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import is from '@sindresorhus/is';
import { logger } from '../../logger';
import type { PackageFile } from '../../modules/manager/types';
import { clone } from '../../util/clone';

export class PackageFiles {
private static data = new Map<string, Record<string, PackageFile[]> | null>();
Expand Down Expand Up @@ -44,7 +45,7 @@ export class PackageFiles {
let removed = false;
let truncated = false;

const data = new Map(structuredClone(Array.from(this.data)));
const data = new Map(clone(Array.from(this.data)));

// filter all deps with skip reason
for (const managers of [...data.values()].filter(is.truthy)) {
Expand Down
3 changes: 2 additions & 1 deletion lib/workers/repository/process/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
import { ExternalHostError } from '../../../types/errors/external-host-error';
import * as memCache from '../../../util/cache/memory';
import type { LookupStats } from '../../../util/cache/memory/types';
import { clone } from '../../../util/clone';
import { applyPackageRules } from '../../../util/package-rules';
import * as p from '../../../util/promises';
import { PackageFiles } from '../package-files';
Expand All @@ -37,7 +38,7 @@ async function fetchDepUpdates(
packageFileConfig: RenovateConfig & PackageFile,
indep: PackageDependency
): Promise<PackageDependency> {
const dep = structuredClone(indep);
const dep = clone(indep);
dep.updates = [];
if (is.string(dep.depName)) {
dep.depName = dep.depName.trim();
Expand Down
3 changes: 2 additions & 1 deletion lib/workers/repository/process/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { PackageFile } from '../../../modules/manager/types';
import { platform } from '../../../modules/platform';
import { scm } from '../../../modules/platform/scm';
import { getCache } from '../../../util/cache/repository';
import { clone } from '../../../util/clone';
import { getBranchList } from '../../../util/git';
import { configRegexPredicate } from '../../../util/regex';
import { addSplit } from '../../../util/split';
Expand All @@ -23,7 +24,7 @@ async function getBaseBranchConfig(
): Promise<RenovateConfig> {
logger.debug(`baseBranch: ${baseBranch}`);

let baseBranchConfig: RenovateConfig = structuredClone(config);
let baseBranchConfig: RenovateConfig = clone(config);

if (
config.useBaseBranchConfig === 'merge' &&
Expand Down
3 changes: 2 additions & 1 deletion lib/workers/repository/process/lookup/filter-checks.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { mocked } from '../../../../../test/util';
import type { Release } from '../../../../modules/datasource';
import * as allVersioning from '../../../../modules/versioning';
import { clone } from '../../../../util/clone';
import * as _dateUtil from '../../../../util/date';
import * as _mergeConfidence from '../../../../util/merge-confidence';
import { toMs } from '../../../../util/pretty-time';
Expand Down Expand Up @@ -41,7 +42,7 @@ describe('workers/repository/process/lookup/filter-checks', () => {

beforeEach(() => {
config = { currentVersion: '1.0.0' };
sortedReleases = structuredClone(releases);
sortedReleases = clone(releases);
jest.resetAllMocks();
dateUtil.getElapsedMs.mockReturnValueOnce(toMs('3 days') ?? 0);
dateUtil.getElapsedMs.mockReturnValueOnce(toMs('5 days') ?? 0);
Expand Down
Loading