Skip to content

Commit 9359983

Browse files
authored
Merge pull request #11993 from quarto-dev/perf/2025-01-30-no-cloneDeep
perf - remove cloneDeep calls
2 parents 1dc41fa + 5471a39 commit 9359983

File tree

12 files changed

+70
-35
lines changed

12 files changed

+70
-35
lines changed

src/command/render/defaults.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@ export async function generateDefaults(
3939
let allDefaults: FormatPandoc | undefined;
4040

4141
if (options.format.pandoc) {
42-
allDefaults = (options.format.pandoc
43-
? ld.cloneDeep(options.format.pandoc)
44-
: {}) as FormatPandoc;
42+
allDefaults = {
43+
...(options.format.pandoc || {}),
44+
variables: {
45+
...(options.format.pandoc?.variables || {}),
46+
},
47+
} as FormatPandoc;
4548

4649
// resolve filters
4750
const resolvedFilters = await resolveFilters(

src/command/render/filters.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ function initFilterParams(dependenciesFile: string) {
713713
const kQuartoFilterMarker = "quarto";
714714
const kQuartoCiteProcMarker = "citeproc";
715715

716+
// NB: this mutates `pandoc.citeproc`
716717
export async function resolveFilters(
717718
filters: QuartoFilter[],
718719
options: PandocOptions,

src/command/render/flags.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ import {
2727
import { isQuartoMetadata } from "../../config/metadata.ts";
2828
import { RenderFlags, RenderOptions } from "./types.ts";
2929

30-
import * as ld from "../../core/lodash.ts";
31-
3230
import { isAbsolute, SEP_PATTERN } from "../../deno_ral/path.ts";
3331
import { normalizePath } from "../../core/path.ts";
3432
import { removeFlags } from "../../core/flags.ts";
@@ -471,7 +469,12 @@ export function removePandocToArg(args: string[]) {
471469
}
472470

473471
export function removePandocTo(renderOptions: RenderOptions) {
474-
renderOptions = ld.cloneDeep(renderOptions);
472+
renderOptions = {
473+
...renderOptions,
474+
flags: {
475+
...(renderOptions.flags || {}),
476+
},
477+
} as RenderOptions;
475478
delete renderOptions.flags?.to;
476479
if (renderOptions.pandocArgs) {
477480
renderOptions.pandocArgs = removePandocToArg(renderOptions.pandocArgs);

src/command/render/freeze.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ import {
2020
LF,
2121
} from "../../deno_ral/fs.ts";
2222

23-
import { cloneDeep } from "../../core/lodash.ts";
24-
2523
import { inputFilesDir } from "../../core/render.ts";
2624
import { TempContext } from "../../core/temp.ts";
2725
import { md5HashSync } from "../../core/hash.ts";
@@ -55,13 +53,15 @@ export function freezeExecuteResult(
5553
result: ExecuteResult,
5654
) {
5755
// resolve includes within executeResult
58-
result = cloneDeep(result) as ExecuteResult;
56+
const innerResult = {
57+
...result,
58+
} as ExecuteResult;
5959
const resolveIncludes = (
6060
name: "include-in-header" | "include-before-body" | "include-after-body",
6161
) => {
62-
if (result.includes) {
63-
if (result.includes[name]) {
64-
result.includes[name] = result.includes[name]!.map((file) =>
62+
if (innerResult.includes) {
63+
if (innerResult.includes[name]) {
64+
innerResult.includes[name] = innerResult.includes[name]!.map((file) =>
6565
// Storing file content using LF line ending
6666
format(Deno.readTextFileSync(file), LF)
6767
);
@@ -73,7 +73,7 @@ export function freezeExecuteResult(
7373
resolveIncludes(kIncludeAfterBody);
7474

7575
// make the supporting dirs relative to the input file dir
76-
result.supporting = result.supporting.map((file) => {
76+
innerResult.supporting = innerResult.supporting.map((file) => {
7777
if (isAbsolute(file)) {
7878
return relative(normalizePath(dirname(input)), file);
7979
} else {
@@ -88,7 +88,7 @@ export function freezeExecuteResult(
8888
const freezeJsonFile = freezeResultFile(input, output, true);
8989
Deno.writeTextFileSync(
9090
freezeJsonFile,
91-
JSON.stringify({ hash, result }, undefined, 2),
91+
JSON.stringify({ hash, result: innerResult }, undefined, 2),
9292
);
9393

9494
// return the file

src/command/render/pandoc.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,12 @@ export async function runPandoc(
391391
// save args and metadata so we can print them (we may subsequently edit them)
392392
const printArgs = [...args];
393393
let printMetadata = {
394-
...ld.cloneDeep(options.format.metadata),
394+
...options.format.metadata,
395+
crossref: {
396+
...(options.format.metadata.crossref || {}),
397+
},
395398
...options.flags?.metadata,
396-
};
399+
} as Metadata;
397400

398401
// remove some metadata that are used as parameters to our lua filters
399402
const cleanMetadataForPrinting = (metadata: Metadata) => {
@@ -691,7 +694,7 @@ export async function runPandoc(
691694
),
692695
...extras.metadataOverride || {},
693696
};
694-
printMetadata = mergeConfigs(extras.metadata, printMetadata);
697+
printMetadata = mergeConfigs(extras.metadata || {}, printMetadata);
695698
cleanMetadataForPrinting(printMetadata);
696699
}
697700

@@ -820,7 +823,9 @@ export async function runPandoc(
820823
}
821824

822825
// more cleanup
823-
options.format.metadata = cleanupPandocMetadata(options.format.metadata);
826+
options.format.metadata = cleanupPandocMetadata({
827+
...options.format.metadata,
828+
});
824829
printMetadata = cleanupPandocMetadata(printMetadata);
825830

826831
if (extras[kIncludeInHeader]) {
@@ -1370,21 +1375,20 @@ export async function runPandoc(
13701375
}
13711376
}
13721377

1378+
// this mutates metadata[kClassOption]
13731379
function cleanupPandocMetadata(metadata: Metadata) {
1374-
const cleaned = ld.cloneDeep(metadata);
1375-
13761380
// pdf classoption can end up with duplicaed options
1377-
const classoption = cleaned[kClassOption];
1381+
const classoption = metadata[kClassOption];
13781382
if (Array.isArray(classoption)) {
1379-
cleaned[kClassOption] = ld.uniqBy(
1383+
metadata[kClassOption] = ld.uniqBy(
13801384
classoption.reverse(),
13811385
(option: string) => {
13821386
return option.replace(/=.+$/, "");
13831387
},
13841388
).reverse();
13851389
}
13861390

1387-
return cleaned;
1391+
return metadata;
13881392
}
13891393

13901394
async function resolveExtras(
@@ -1687,7 +1691,10 @@ function resolveTextHighlightStyle(
16871691
extras: FormatExtras,
16881692
pandoc: FormatPandoc,
16891693
): FormatExtras {
1690-
extras = ld.cloneDeep(extras);
1694+
extras = {
1695+
...extras,
1696+
pandoc: extras.pandoc ? { ...extras.pandoc } : {},
1697+
} as FormatExtras;
16911698

16921699
// Get the user selected theme or choose a default
16931700
const highlightTheme = pandoc[kHighlightStyle] || kDefaultHighlightStyle;

src/command/render/project.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ const computeProjectRenderConfig = async (
144144

145145
// force execution for any incremental files (unless options.useFreezer is set)
146146
let alwaysExecuteFiles = incremental && !inputs.options.useFreezer
147-
? ld.cloneDeep(inputs.files) as string[]
147+
? [...(inputs.files!)]
148148
: undefined;
149149

150150
// file normaliation

src/core/jupyter/display-data.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,13 @@ export function displayDataWithMarkdownMath(output: JupyterOutputDisplayData) {
123123
if (Array.isArray(output.data[kTextLatex]) && !output.data[kTextMarkdown]) {
124124
const latex = output.data[kTextLatex] as string[];
125125
if (displayDataLatexIsMath(latex)) {
126-
output = ld.cloneDeep(output);
127-
output.data[kTextMarkdown] = output.data[kTextLatex];
126+
output = {
127+
...output,
128+
data: {
129+
...output.data,
130+
[kTextMarkdown]: latex,
131+
},
132+
};
128133
return output;
129134
}
130135
}

src/core/jupyter/jupyter.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,9 @@ export function mdFromContentCell(
963963
const contentCellEnvelope = createCellEnvelope(["cell", "markdown"], options);
964964

965965
// clone source for manipulation
966-
const source = ld.cloneDeep(cell.source) as string[];
966+
const source = typeof cell.source === "string"
967+
? [cell.source]
968+
: [...cell.source];
967969

968970
// handle user expressions (if any)
969971
if (options && source) {
@@ -1461,7 +1463,9 @@ async function mdFromCodeCell(
14611463
}
14621464
}
14631465
md.push("}\n");
1464-
let source = ld.cloneDeep(cell.source);
1466+
let source = typeof cell.source === "string"
1467+
? [cell.source]
1468+
: [...cell.source];
14651469
if (fenced) {
14661470
const optionsSource = cell.optionsSource.filter((line) =>
14671471
line.search(/\|\s+echo:\s+fenced\s*$/) === -1

src/execute/jupyter/jupyter.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,15 @@ export const jupyterEngine: ExecutionEngine = {
243243
isServerShinyPython(format, kJupyterEngine) &&
244244
format.render[kKeepHidden] !== true
245245
) {
246-
format = ld.cloneDeep(format);
246+
format = {
247+
...format,
248+
render: {
249+
...format.render,
250+
},
251+
metadata: {
252+
...format.metadata,
253+
},
254+
};
247255
format.render[kKeepHidden] = true;
248256
format.metadata[kRemoveHidden] = "all";
249257
}

src/execute/ojs/compile.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,9 @@ export async function ojsExecuteResult(
892892
executeResult: MappedExecuteResult,
893893
ojsBlockLineNumbers: number[],
894894
) {
895-
executeResult = ld.cloneDeep(executeResult);
895+
executeResult = {
896+
...executeResult,
897+
};
896898

897899
// evaluate ojs chunks
898900
const { markdown, includes, filters, resourceFiles } = await ojsCompile({

src/project/types/website/listing/website-listing-template.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,9 @@ export function reshapeListing(
318318
listing: Listing,
319319
format: Format,
320320
): ReshapedListing {
321-
const reshaped = cloneDeep(listing) as Listing;
321+
const reshaped = {
322+
...listing,
323+
} as Listing;
322324

323325
// Add template utilities
324326
const utilities = {} as Record<string, unknown>;

src/publish/config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { warning } from "../deno_ral/log.ts";
88
import { stringify } from "../core/yaml.ts";
99
import { basename, dirname, join } from "../deno_ral/path.ts";
1010

11-
import * as ld from "../core/lodash.ts";
12-
1311
import { Metadata } from "../config/types.ts";
1412
import { readYaml, readYamlFromString } from "../core/yaml.ts";
1513
import { ProjectContext } from "../project/types.ts";
@@ -69,7 +67,9 @@ export function writePublishDeployment(
6967
publish: PublishRecord,
7068
) {
7169
// don't write 'code' field if false
72-
publish = ld.cloneDeep(publish) as PublishRecord;
70+
publish = {
71+
...publish,
72+
} as PublishRecord;
7373
if (publish.code === false) {
7474
delete (publish as Record<string, unknown>).code;
7575
}

0 commit comments

Comments
 (0)