Skip to content

Bugfix/safe clone deep #12388

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/command/render/pandoc-dependencies-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { ensureDirSync } from "../../deno_ral/fs.ts";
import { ProjectContext } from "../../project/types.ts";
import { projectOutputDir } from "../../project/project-shared.ts";
import { insecureHash } from "../../core/hash.ts";
import { safeCloneDeep } from "../../core/safe-clone-deep.ts";

export async function writeDependencies(
dependenciesFile: string,
Expand Down Expand Up @@ -146,7 +147,7 @@ export function resolveDependencies(
project?: ProjectContext,
) {
// deep copy to not mutate caller's object
extras = ld.cloneDeep(extras);
extras = safeCloneDeep(extras);

const lines: string[] = [];
const afterBodyLines: string[] = [];
Expand Down
13 changes: 7 additions & 6 deletions src/command/render/pandoc-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { join } from "../../deno_ral/path.ts";
import { cloneDeep, uniqBy } from "../../core/lodash.ts";
import { uniqBy } from "../../core/lodash.ts";

import {
Format,
Expand Down Expand Up @@ -39,6 +39,7 @@ import { md5HashBytes } from "../../core/hash.ts";
import { InternalError } from "../../core/lib/error.ts";
import { assert } from "testing/asserts";
import { safeModeFromFile } from "../../deno_ral/fs.ts";
import { safeCloneDeep } from "../../core/safe-clone-deep.ts";

// The output target for a sass bundle
// (controls the overall style tag that is emitted)
Expand All @@ -54,7 +55,7 @@ export async function resolveSassBundles(
format: Format,
project: ProjectContext,
) {
extras = cloneDeep(extras);
extras = safeCloneDeep(extras);

const mergedBundles: Record<string, SassBundleWithBrand[]> = {};

Expand Down Expand Up @@ -102,7 +103,7 @@ export async function resolveSassBundles(
const userBrand = bundle.user?.findIndex((layer) => layer === "brand");
let cloned = false;
if (userBrand && userBrand !== -1) {
bundle = cloneDeep(bundle);
bundle = safeCloneDeep(bundle);
cloned = true;
bundle.user!.splice(userBrand, 1, ...(maybeBrandBundle?.user || []));
foundBrand.light = true;
Expand All @@ -112,7 +113,7 @@ export async function resolveSassBundles(
);
if (darkBrand && darkBrand !== -1) {
if (!cloned) {
bundle = cloneDeep(bundle);
bundle = safeCloneDeep(bundle);
}
bundle.dark!.user!.splice(
darkBrand,
Expand Down Expand Up @@ -158,7 +159,7 @@ export async function resolveSassBundles(

// Provide a dark bundle for this
const darkBundles = bundles.map((bundle) => {
bundle = cloneDeep(bundle);
bundle = safeCloneDeep(bundle);
bundle.user = bundle.dark?.user || bundle.user;
bundle.quarto = bundle.dark?.quarto || bundle.quarto;
bundle.framework = bundle.dark?.framework || bundle.framework;
Expand Down Expand Up @@ -340,7 +341,7 @@ async function resolveQuartoSyntaxHighlighting(
return extras;
}

extras = cloneDeep(extras);
extras = safeCloneDeep(extras);

// If we're using default highlighting, use theme darkness to select highlight style
const mediaAttr = attribForThemeStyle(style);
Expand Down
26 changes: 18 additions & 8 deletions src/command/render/pandoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ import { isWindows } from "../../deno_ral/platform.ts";
import { appendToCombinedLuaProfile } from "../../core/performance/perfetto-utils.ts";
import { makeTimedFunctionAsync } from "../../core/performance/function-times.ts";
import { walkJson } from "../../core/json.ts";
import { safeCloneDeep } from "../../core/safe-clone-deep.ts";
import { assert } from "testing/asserts";

// in case we are running multiple pandoc processes
// we need to make sure we capture all of the trace files
Expand Down Expand Up @@ -330,7 +332,9 @@ export async function runPandoc(
JSON.stringify(paramsJson),
);

const traceFilters = pandocMetadata?.["_quarto"]?.["trace-filters"] ||
// deno-lint-ignore no-explicit-any
const traceFilters =
(pandocMetadata as any)?.["_quarto"]?.["trace-filters"] ||
Deno.env.get("QUARTO_TRACE_FILTERS");

if (traceFilters) {
Expand Down Expand Up @@ -445,7 +449,7 @@ export async function runPandoc(

// generate defaults and capture defaults to be printed
let allDefaults = (await generateDefaults(options)) || {};
let printAllDefaults = ld.cloneDeep(allDefaults) as FormatPandoc;
let printAllDefaults = safeCloneDeep(allDefaults);

// capture any filterParams in the FormatExtras
const formatFilterParams = {} as Record<string, unknown>;
Expand Down Expand Up @@ -1127,7 +1131,7 @@ export async function runPandoc(

// selectively overwrite some resolved metadata (e.g. ensure that metadata
// computed from inline r expressions gets included @ the bottom).
const pandocMetadata = ld.cloneDeep(options.format.metadata || {});
const pandocMetadata = safeCloneDeep(options.format.metadata || {});
for (const key of Object.keys(engineMetadata)) {
const isChapterTitle = key === kTitle && projectIsBook(options.project);

Expand Down Expand Up @@ -1161,6 +1165,7 @@ export async function runPandoc(
dateFields.forEach((dateField) => {
const date = pandocMetadata[dateField];
const format = pandocMetadata[kDateFormat];
assert(format === undefined || typeof format === "string");
pandocMetadata[dateField] = resolveAndFormatDate(
options.source,
date,
Expand All @@ -1180,15 +1185,19 @@ export async function runPandoc(
// Expand citation dates into CSL dates
const citationMetadata = pandocMetadata[kCitation];
if (citationMetadata) {
assert(typeof citationMetadata === "object");
// ideally we should be asserting non-arrayness here but that's not very fast.
// assert(!Array.isArray(citationMetadata));
const citationMetadataObj = citationMetadata as Record<string, unknown>;
const docCSLDate = dateRaw
? cslDate(resolveDate(options.source, dateRaw))
: undefined;
const fields = ["issued", "available-date"];
fields.forEach((field) => {
if (citationMetadata[field]) {
citationMetadata[field] = cslDate(citationMetadata[field]);
if (citationMetadataObj[field]) {
citationMetadataObj[field] = cslDate(citationMetadataObj[field]);
} else if (docCSLDate) {
citationMetadata[field] = docCSLDate;
citationMetadataObj[field] = docCSLDate;
}
});
}
Expand Down Expand Up @@ -1228,6 +1237,7 @@ export async function runPandoc(
!isBeamerOutput(options.format.pandoc)
) {
const docClass = pandocMetadata[kDocumentClass];
assert(typeof docClass === "string");
const isPrintDocumentClass = docClass &&
["book", "scrbook"].includes(docClass);

Expand Down Expand Up @@ -1281,7 +1291,7 @@ export async function runPandoc(
prefix: "quarto-metadata",
suffix: ".yml",
});
const pandocPassedMetadata = ld.cloneDeep(pandocMetadata);
const pandocPassedMetadata = safeCloneDeep(pandocMetadata);
delete pandocPassedMetadata.format;
delete pandocPassedMetadata.project;
delete pandocPassedMetadata.website;
Expand Down Expand Up @@ -1679,7 +1689,7 @@ function runPandocMessage(

const keys = Object.keys(metadata);
if (keys.length > 0) {
const printMetadata = ld.cloneDeep(metadata) as Metadata;
const printMetadata = safeCloneDeep(metadata);
delete printMetadata.format;

// print message
Expand Down
13 changes: 7 additions & 6 deletions src/command/render/render-contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import {
} from "../../core/pandoc/pandoc-formats.ts";
import { ExtensionContext } from "../../extension/types.ts";
import { NotebookContext } from "../../render/notebook/notebook-types.ts";
import { safeCloneDeep } from "../../core/safe-clone-deep.ts";

export async function resolveFormatsFromMetadata(
metadata: Metadata,
Expand Down Expand Up @@ -215,7 +216,7 @@ export async function renderContexts(
// we make it optional because some of the callers have
// actually just cloned it themselves and don't need to preserve
// the original
options = ld.cloneDeep(options) as RenderOptions;
options = safeCloneDeep(options);
}

const { engine, target } = await fileExecutionEngineAndTarget(
Expand Down Expand Up @@ -342,8 +343,8 @@ function mergeQuartoConfigs(
...configs: Array<Metadata>
): Metadata {
// copy all configs so we don't mutate them
config = ld.cloneDeep(config);
configs = ld.cloneDeep(configs);
config = safeCloneDeep(config);
configs = safeCloneDeep(configs);

// bibliography needs to always be an array so it can be merged
const fixupMergeableScalars = (metadata: Metadata) => {
Expand Down Expand Up @@ -445,7 +446,7 @@ async function resolveFormats(

// Remove any 'to' information that will force the
// rendering to a particular format
options = ld.cloneDeep(options);
options = safeCloneDeep(options);
delete options.flags?.to;
}

Expand Down Expand Up @@ -748,10 +749,10 @@ export async function projectMetadataForInputFile(
projectType(project.config?.project?.[kProjectType]),
project.dir,
dirname(input),
ld.cloneDeep(project.config),
safeCloneDeep(project.config),
) as Metadata;
} else {
// Just return the config or empty metadata
return ld.cloneDeep(project.config) || {};
return safeCloneDeep(project.config) || {};
}
}
2 changes: 1 addition & 1 deletion src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ export interface Format {

export interface LightDarkBrand {
[kLight]?: Brand;
[kDark]?: Brand
[kDark]?: Brand;
}

export interface FormatRender {
Expand Down
2 changes: 1 addition & 1 deletion src/render/notebook/notebook-contributor-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function resolveHtmlNotebook(
executedFile: ExecutedFile,
notebookMetadata?: NotebookMetadata,
) {
const resolved = safeCloneDeep(executedFile) as ExecutedFile;
const resolved = safeCloneDeep(executedFile);

// Set the output file
resolved.recipe.format.pandoc[kOutputFile] = `${outputFile(nbAbsPath)}`;
Expand Down
19 changes: 14 additions & 5 deletions src/resources/editor/tools/vs-code.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8371,6 +8371,10 @@ var require_yaml_intelligence_resources = __commonJS({
}
]
},
{
id: "date-format",
schema: "string"
},
{
id: "math-methods",
enum: {
Expand Down Expand Up @@ -12674,6 +12678,13 @@ var require_yaml_intelligence_resources = __commonJS({
},
description: "Document date"
},
{
name: "date-format",
schema: {
ref: "date-format"
},
descript: "Date format for the document"
},
{
name: "date-modified",
tags: {
Expand Down Expand Up @@ -22914,8 +22925,6 @@ var require_yaml_intelligence_resources = __commonJS({
"If <code>true</code>, force the presence of the OJS runtime. If\n<code>false</code>, force the absence instead. If unset, the OJS runtime\nis included only if OJS cells are present in the document.",
"Use the specified file as a style reference in producing a docx,\npptx, or odt file.",
"Branding information to use for this document. If a string, the path\nto a brand file. If false, don\u2019t use branding on this document. If an\nobject, an inline brand definition, or an object with light and dark\nbrand paths or definitions.",
"The path to a light brand file or an inline light brand\ndefinition.",
"The path to a dark brand file or an inline dark brand definition.",
"Theme name, theme scss file, or a mix of both.",
"The light theme name, theme scss file, or a mix of both.",
"The light theme name, theme scss file, or a mix of both.",
Expand Down Expand Up @@ -24248,12 +24257,12 @@ var require_yaml_intelligence_resources = __commonJS({
mermaid: "%%"
},
"handlers/mermaid/schema.yml": {
_internalId: 196120,
_internalId: 194255,
type: "object",
description: "be an object",
properties: {
"mermaid-format": {
_internalId: 196112,
_internalId: 194247,
type: "enum",
enum: [
"png",
Expand All @@ -24269,7 +24278,7 @@ var require_yaml_intelligence_resources = __commonJS({
exhaustiveCompletions: true
},
theme: {
_internalId: 196119,
_internalId: 194254,
type: "anyOf",
anyOf: [
{
Expand Down
19 changes: 14 additions & 5 deletions src/resources/editor/tools/yaml/web-worker.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading