diff --git a/configuration b/configuration index 744e7520ad8..f7b00c841d8 100644 --- a/configuration +++ b/configuration @@ -11,7 +11,7 @@ # in src/command/check/check.ts # Binary dependencies -export DENO=v1.46.3 +export DENO=v2.2.10 # TODO figure out where 0.1.41 apple silicon libs are available export DENO_DOM=v0.1.41-alpha-artifacts export PANDOC=3.6.3 diff --git a/package/scripts/deno_std/download.sh b/package/scripts/deno_std/download.sh index 0a10c5ff7f0..d815099435d 100755 --- a/package/scripts/deno_std/download.sh +++ b/package/scripts/deno_std/download.sh @@ -10,4 +10,4 @@ fi export DENO_DIR="$QUARTO_SRC_PATH/resources/deno_std/cache" -"$QUARTO_DENO" cache --no-config --unstable-ffi --lock "$QUARTO_SRC_PATH/resources/deno_std/deno_std.lock" "$@" "$QUARTO_PACKAGE_PATH/scripts/deno_std/deno_std.ts" \ No newline at end of file +"$QUARTO_DENO" cache --allow-import --no-config --unstable-ffi --lock "$QUARTO_SRC_PATH/resources/deno_std/deno_std.lock" "$@" "$QUARTO_PACKAGE_PATH/scripts/deno_std/deno_std.ts" \ No newline at end of file diff --git a/package/src/common/archive-binary-dependencies.ts b/package/src/common/archive-binary-dependencies.ts index f4b3ee16c96..35b45968261 100644 --- a/package/src/common/archive-binary-dependencies.ts +++ b/package/src/common/archive-binary-dependencies.ts @@ -159,9 +159,10 @@ export async function archiveBinaryDependency( } async function s3cmd(cmd: string, args: string[]) { - const s3Command = ["aws", "s3", cmd, ...args]; + const s3Args = ["s3", cmd, ...args]; const p = await execProcess({ - cmd: s3Command, + cmd: "aws", + args: s3Args, stdout: "piped", }); diff --git a/package/src/common/prepare-dist.ts b/package/src/common/prepare-dist.ts index 70779887c99..bcc43dfb959 100755 --- a/package/src/common/prepare-dist.ts +++ b/package/src/common/prepare-dist.ts @@ -90,6 +90,7 @@ export async function prepareDist( try { await configArchDependency(dependency, targetDir, config) } catch (e) { + if (!(e instanceof Error)) { throw e; } if ( e.message === "The architecture aarch64 is missing the dependency deno_dom" @@ -121,13 +122,11 @@ export async function prepareDist( info(""); // Create the deno bundle - const input = join(config.directoryInfo.src, "quarto.ts"); + // const input = join(config.directoryInfo.src, "quarto.ts"); const output = join(config.directoryInfo.pkgWorking.bin, "quarto.js"); info("\nCreating Deno Bundle"); info(output); await bundle( - input, - output, config, ); info(""); diff --git a/package/src/common/validate-bundle.ts b/package/src/common/validate-bundle.ts index 8c757c532de..1bfda0ebaf7 100644 --- a/package/src/common/validate-bundle.ts +++ b/package/src/common/validate-bundle.ts @@ -32,7 +32,8 @@ export async function validateBundle( // NPM Install info("Installing Dependencies"); const npm = await execProcess({ - cmd: ["npm", "install"], + cmd: "npm", + args: ["install"], stderr: "piped" }); if (!npm.success) { @@ -53,7 +54,8 @@ export async function validateBundle( // Test the bundled output info("Testing Bundled output"); const npx = await execProcess({ - cmd: ["npx", "eslint", "bundle.js"], + cmd: "npx", + args: ["eslint", "bundle.js"], stderr: "piped" }); diff --git a/package/src/util/cmd.ts b/package/src/util/cmd.ts index 49051223a99..0ce30974905 100644 --- a/package/src/util/cmd.ts +++ b/package/src/util/cmd.ts @@ -8,7 +8,7 @@ import { debug, error, info } from "../../../src/deno_ral/log.ts"; export interface CmdResult { - status: Deno.ProcessStatus; + status: Deno.CommandStatus; stdout: string; stderr: string; } @@ -17,34 +17,32 @@ export async function runCmd( runCmd: string, args: string[], ): Promise { - const cmd: string[] = []; - cmd.push(runCmd); - cmd.push(...args); + // const cmd: string[] = []; + // cmd.push(runCmd); + // cmd.push(...args); - info(cmd); + info([runCmd, ...args]); info(`Starting ${runCmd}`); - const p = Deno.run({ - cmd, + const cmd = new Deno.Command(runCmd, { + args, stdout: "piped", stderr: "piped", }); - const stdout = new TextDecoder().decode(await p.output()); - const stderr = new TextDecoder().decode(await p.stderrOutput()); + const output = await cmd.output(); + const stdout = new TextDecoder().decode(output.stdout); + const stderr = new TextDecoder().decode(output.stderr); info(`Finished ${runCmd}`); debug(stdout); - const status = await p.status(); - info(`Status ${status.code}`); - if (status.code !== 0) { + const code = output.code; + info(`Status ${code}`); + if (code !== 0) { error(stderr); - throw Error(`Command ${cmd} failed.`); + throw Error(`Command ${[runCmd, ...args]} failed.`); } - // Close the child process - p.close(); - return { - status, + status: output, stdout, stderr, }; diff --git a/package/src/util/deno.ts b/package/src/util/deno.ts index 89fef79c70a..6a314bfaf37 100644 --- a/package/src/util/deno.ts +++ b/package/src/util/deno.ts @@ -4,13 +4,14 @@ * Copyright (C) 2020-2022 Posit Software, PBC * */ +import { execProcess } from "../../../src/core/process.ts"; import { info } from "../../../src/deno_ral/log.ts"; import { isWindows } from "../../../src/deno_ral/platform.ts"; import { Configuration } from "../common/config.ts"; +// TODO in we only use the bundler for quarto.ts +// so we hardcode it in the new esbuild-based bundler export async function bundle( - input: string, - output: string, configuration: Configuration, ) { // Bundle source code @@ -19,28 +20,23 @@ export async function bundle( if (!denoExecPath) { throw Error("QUARTO_DENO is not defined"); } - denoBundleCmd.push(denoExecPath); - denoBundleCmd.push("bundle"); - denoBundleCmd.push("--no-check"); - denoBundleCmd.push("--unstable-kv"); - denoBundleCmd.push("--unstable-ffi"); - denoBundleCmd.push( - "--importmap=" + configuration.importmap, - ); + denoBundleCmd.push("run"); + denoBundleCmd.push("--allow-all"); + denoBundleCmd.push("../tools/deno-esbuild-bundle.ts"); /* denoBundleCmd.push("--log-level"); denoBundleCmd.push("debug"); */ + // denoBundleCmd.push(input); + // denoBundleCmd.push(output); - denoBundleCmd.push(input); - denoBundleCmd.push(output); - - const p = Deno.run({ - cmd: denoBundleCmd, + const status = await execProcess({ + cmd: denoExecPath, + args: denoBundleCmd, + cwd: configuration.directoryInfo.src, }); - const status = await p.status(); if (status.code !== 0) { - throw Error(`Failure to bundle ${input}`); + throw Error(`Failure to bundle src/quarto.ts`); } } @@ -55,7 +51,6 @@ export async function compile( if (!denoExecPath) { throw Error("QUARTO_DENO is not defined"); } - denoBundleCmd.push(denoExecPath); denoBundleCmd.push("compile"); denoBundleCmd.push("--unstable-kv"); denoBundleCmd.push("--unstable-ffi"); @@ -68,15 +63,14 @@ export async function compile( denoBundleCmd.push(input); - const p = Deno.run({ - cmd: denoBundleCmd, + const status = await execProcess({ + cmd: denoExecPath, + args: denoBundleCmd, }); - const status = await p.status(); if (status.code !== 0) { throw Error(`Failure to compile ${input}`); } } - export async function install( input: string, flags: string[], @@ -87,7 +81,6 @@ export async function install( if (!denoExecPath) { throw Error("QUARTO_DENO is not defined"); } - denoBundleCmd.push(denoExecPath); denoBundleCmd.push("install"); denoBundleCmd.push("--unstable-kv"); denoBundleCmd.push("--unstable-ffi"); @@ -98,24 +91,19 @@ export async function install( denoBundleCmd.push(input); - const p = Deno.run({ - cmd: denoBundleCmd, + const status = await execProcess({ + cmd: denoExecPath, + args: denoBundleCmd, stdout: "piped", }); - const status = await p.status(); if (status.code !== 0) { throw Error(`Failure to install ${input}`); } - const output = await p.output(); - - if (output) { - // Try to read the installation path and return it - const outputTxt = new TextDecoder().decode(output); - + if (status.stdout) { // Forward the output - info(outputTxt); + info(status.stdout); - const match = outputTxt.match(/Successfully installed.*\n(.*)/); + const match = status.stdout.match(/Successfully installed.*\n(.*)/); if (match) { return match[1]; } diff --git a/package/src/windows/installer.ts b/package/src/windows/installer.ts index 33aa941b3e8..b1e4e204699 100644 --- a/package/src/windows/installer.ts +++ b/package/src/windows/installer.ts @@ -157,8 +157,8 @@ export async function makeInstallerWindows(configuration: Configuration) { export function zip(input: string, output: string) { const dir = dirname(input); - const cmd = [ - "powershell", + const cmd = "powershell"; + const args = [ "Compress-Archive", "-Force", input, @@ -169,6 +169,7 @@ export function zip(input: string, output: string) { return execProcess( { cmd, + args, cwd: dir, stdout: "piped", }, diff --git a/src/command/check/check.ts b/src/command/check/check.ts index 60ebd434381..37eba5df40f 100644 --- a/src/command/check/check.ts +++ b/src/command/check/check.ts @@ -217,7 +217,8 @@ async function checkVersions(conf: CheckConfiguration) { let pandocVersion = lines( (await execProcess({ - cmd: [pandocBinaryPath(), "--version"], + cmd: pandocBinaryPath(), + args: ["--version"], stdout: "piped", })).stdout!, )[0]?.split(" ")[1]; @@ -225,7 +226,8 @@ async function checkVersions(conf: CheckConfiguration) { const denoVersion = Deno.version.deno; const typstVersion = lines( (await execProcess({ - cmd: [typstBinaryPath(), "--version"], + cmd: typstBinaryPath(), + args: ["--version"], stdout: "piped", })).stdout!, )[0].split(" ")[1]; @@ -300,7 +302,8 @@ async function checkInstall(conf: CheckConfiguration) { const quartoRoot = Deno.env.get("QUARTO_ROOT"); if (quartoRoot) { const gitHead = await execProcess({ - cmd: ["git", "-C", quartoRoot, "rev-parse", "HEAD"], + cmd: "git", + args: ["-C", quartoRoot, "rev-parse", "HEAD"], stdout: "piped", stderr: "piped", // to not show error if not in a git repo }); diff --git a/src/command/create/artifacts/artifact-shared.ts b/src/command/create/artifacts/artifact-shared.ts index cb4544a6f14..08a2b4b7621 100644 --- a/src/command/create/artifacts/artifact-shared.ts +++ b/src/command/create/artifacts/artifact-shared.ts @@ -150,7 +150,8 @@ export async function ejsData( async function gitAuthor() { const result = await execProcess({ - cmd: ["git", "config", "--global", "user.name"], + cmd: "git", + args: ["config", "--global", "user.name"], stdout: "piped", stderr: "piped", }); diff --git a/src/command/create/editor.ts b/src/command/create/editor.ts index 3268a68617b..5704b9aea6e 100644 --- a/src/command/create/editor.ts +++ b/src/command/create/editor.ts @@ -22,6 +22,7 @@ import { objectPredicate, stringTypePredicate, } from "../../typing/dynamic.ts"; +import { call } from "../../deno_ral/process.ts"; export interface Editor { // A short, command line friendly id @@ -103,11 +104,7 @@ function vscodeEditorInfo(): EditorInfo { : dirname(artifactPath); return async () => { - const p = Deno.run({ - cmd: [path, artifactPath], - cwd, - }); - await p.status(); + await call(path, { args: [artifactPath], cwd }); }; }, inEditor: isVSCodeTerminal(), @@ -164,11 +161,7 @@ function positronEditorInfo(): EditorInfo { : dirname(artifactPath); return async () => { - const p = Deno.run({ - cmd: [path, artifactPath], - cwd, - }); - await p.status(); + await call(path, { args: [artifactPath], cwd }); }; }, inEditor: isPositronTerminal(), @@ -231,15 +224,13 @@ function rstudioEditorInfo(): EditorInfo { const rProjPath = join(cwd, `${artifactName}.Rproj`); Deno.writeTextFileSync(rProjPath, kRProjContents); - const cmd = path.endsWith(".app") && isMac + const callCmd = path.endsWith(".app") && isMac ? ["open", "-na", path, "--args", rProjPath] : [path, rProjPath]; - const p = Deno.run({ - cmd, - cwd, - }); - await p.status(); + const callPath = callCmd[0]; + const args = callCmd.slice(1); + await call(callPath, { args, cwd }); }; }, inEditor: isRStudioTerminal(), diff --git a/src/command/editor-support/crossref.ts b/src/command/editor-support/crossref.ts index f028cd292f4..e0f7d866d3d 100644 --- a/src/command/editor-support/crossref.ts +++ b/src/command/editor-support/crossref.ts @@ -92,8 +92,9 @@ const makeCrossrefCommand = () => { Deno.env.set("QUARTO_CROSSREF_INPUT_TYPE", "qmd"); // build command - const cmd = [pandocBinaryPath(), "+RTS", "-K512m", "-RTS"]; - cmd.push(...[ + const cmd = pandocBinaryPath(); + const cmdArgs = ["+RTS", "-K512m", "-RTS"]; + cmdArgs.push(...[ "--from", resourcePath("filters/qmd-reader.lua"), "--to", @@ -118,6 +119,7 @@ const makeCrossrefCommand = () => { const result = await execProcess( { cmd, + args: cmdArgs, cwd: indexingDir, env: { "QUARTO_FILTER_PARAMS": filterParams, diff --git a/src/command/preview/preview-shiny.ts b/src/command/preview/preview-shiny.ts index c97477411ac..e9d120c79f1 100644 --- a/src/command/preview/preview-shiny.ts +++ b/src/command/preview/preview-shiny.ts @@ -159,13 +159,6 @@ function runPreviewControlService( const port = findOpenPort(); - const controlListener = Deno.listen({ port, hostname: kLocalhost }); - onCleanup(() => controlListener.close()); - - handleHttpRequests(controlListener, handler).then(() => { - // terminanted - }).catch((_error) => { - // ignore errors - }); + onCleanup(handleHttpRequests({ ...handlerOptions, handler }).stop); info(`Preview service running (${port})`); } diff --git a/src/command/preview/preview.ts b/src/command/preview/preview.ts index 6c8bdab0e32..4399f5e8966 100644 --- a/src/command/preview/preview.ts +++ b/src/command/preview/preview.ts @@ -195,9 +195,10 @@ export async function preview( ...(await resolvePreviewOptions(options)), }; + const ac = new AbortController(); // create listener and callback to stop the server - const listener = Deno.listen({ port: options.port!, hostname: options.host }); - const stopServer = () => listener.close(); + // const listener = Deno.listen({ port: options.port!, hostname: options.host }); + const stopServer = () => ac.abort(); // ensure resources previewEnsureResources(stopServer); @@ -271,23 +272,22 @@ export async function preview( previewMonitorResources(stopServer); // serve project - for await (const conn of listener) { - (async () => { + const server = Deno.serve( + { signal: ac.signal, port: options.port!, hostname: options.host }, + async (req: Request) => { try { - for await (const { request, respondWith } of Deno.serveHttp(conn)) { - await respondWith(handler(request)); - } + return await handler(req); } catch (err) { - warning(err.message); - try { - conn.close(); - } catch { - // + if (err instanceof Error) { + warning(err.message); } + throw err; } - })(); - } + }, + ); + await server.finished; } + export interface PreviewRenderRequest { version: 1 | 2; path: string; @@ -530,7 +530,7 @@ export function createChangeHandler( return result; } catch (e) { - if (e.message) { + if (e instanceof Error && e.message) { // jupyter notebooks being edited in juptyerlab sometimes get an // "Unexpected end of JSON input" error that remedies itself (so we ignore). // this may be a result of an intermediate save result? diff --git a/src/command/publish/cmd.ts b/src/command/publish/cmd.ts index e457abe0d53..a4317e300c8 100644 --- a/src/command/publish/cmd.ts +++ b/src/command/publish/cmd.ts @@ -20,10 +20,7 @@ import { initState, setInitializer, } from "../../core/lib/yaml-validation/state.ts"; -import { - projectContext, - projectInputFiles, -} from "../../project/project-context.ts"; +import { projectContext } from "../../project/project-context.ts"; import { projectIsManuscript, @@ -292,21 +289,24 @@ async function publish( await openUrl(siteUrl.toString()); } } catch (err) { + if (!(err instanceof Error)) { + // shouldn't ever happen + throw err; + } // attempt to recover from unauthorized - if (provider.isUnauthorized(err) && options.prompt) { - if (await handleUnauthorized(provider, account)) { - const authorizedAccount = await provider.authorizeToken( - options, - target, - ); - if (authorizedAccount) { - // recursve after re-authorization - return await publish(provider, authorizedAccount, options, target); - } - } - } else { + if (!(provider.isUnauthorized(err) && options.prompt)) { throw err; } + if (await handleUnauthorized(provider, account)) { + const authorizedAccount = await provider.authorizeToken( + options, + target, + ); + if (authorizedAccount) { + // recursve after re-authorization + return await publish(provider, authorizedAccount, options, target); + } + } } } diff --git a/src/command/publish/deployment.ts b/src/command/publish/deployment.ts index cbbda3e3f3b..4c01b77d433 100644 --- a/src/command/publish/deployment.ts +++ b/src/command/publish/deployment.ts @@ -251,6 +251,10 @@ async function resolveDeploymentTarget( try { return await provider.resolveTarget(account, record); } catch (err) { + if (!(err instanceof Error)) { + // shouldn't ever happen + throw err; + } if (provider.isNotFound(err)) { warning( `${record.url} not found (you may need to remove it from the publish configuration)`, diff --git a/src/command/render/latexmk/latex.ts b/src/command/render/latexmk/latex.ts index 13a248961d9..caf813d5103 100644 --- a/src/command/render/latexmk/latex.ts +++ b/src/command/render/latexmk/latex.ts @@ -11,7 +11,7 @@ import { error, info } from "../../../deno_ral/log.ts"; import { PdfEngine } from "../../../config/types.ts"; import { dirAndStem } from "../../../core/path.ts"; -import { execProcess } from "../../../core/process.ts"; +import { execProcess, ExecProcessOptions } from "../../../core/process.ts"; import { ProcessResult } from "../../../core/process-types.ts"; import { PackageManager } from "./pkgmgr.ts"; @@ -29,7 +29,8 @@ export interface LatexCommandReponse { export async function hasLatexDistribution() { try { const result = await execProcess({ - cmd: ["pdftex", "--version"], + cmd: "pdftex", + args: ["--version"], stdout: "piped", stderr: "piped", }); @@ -211,8 +212,9 @@ async function runLatexCommand( ): Promise { const fullLatexCmd = texLiveCmd(latexCmd, context.texLive); - const runOptions: Deno.RunOptions = { - cmd: [fullLatexCmd.fullPath, ...args], + const runOptions: ExecProcessOptions = { + cmd: fullLatexCmd.fullPath, + args, stdout: "piped", stderr: "piped", }; diff --git a/src/command/render/latexmk/texlive.ts b/src/command/render/latexmk/texlive.ts index b150f3ff57f..013baf07bb2 100644 --- a/src/command/render/latexmk/texlive.ts +++ b/src/command/render/latexmk/texlive.ts @@ -427,7 +427,8 @@ function tlmgrCommand( const execTlmgr = (tlmgrCmd: string[]) => { return execProcess( { - cmd: tlmgrCmd, + cmd: tlmgrCmd[0], + args: tlmgrCmd.slice(1), stdout: "piped", stderr: "piped", }, @@ -457,7 +458,8 @@ function fmtutilCommand(context: TexLiveContext) { const fmtutil = texLiveCmd("fmtutil-sys", context); return execProcess( { - cmd: [fmtutil.fullPath, "--all"], + cmd: fmtutil.fullPath, + args: ["--all"], stdout: "piped", stderr: "piped", }, diff --git a/src/command/render/output-tex.ts b/src/command/render/output-tex.ts index 2210a5f12ea..c7f5957458b 100644 --- a/src/command/render/output-tex.ts +++ b/src/command/render/output-tex.ts @@ -179,11 +179,12 @@ export function contextPdfOutputRecipe( const engine = pdfEngine(format.pandoc, format.render, pandocOptions.flags); // build context command - const cmd = ["context", input]; + const cmd = "context"; + const args = [input]; if (engine.pdfEngineOpts) { - cmd.push(...engine.pdfEngineOpts); + args.push(...engine.pdfEngineOpts); } - cmd.push( + args.push( // ConTeXt produces some auxiliary files: // direct PDF generation by Pandoc never produces these auxiliary // files because Pandoc runs ConTeXt in a temporary directory. @@ -194,7 +195,10 @@ export function contextPdfOutputRecipe( ); // run context - const result = await execProcess({ cmd }); + const result = await execProcess({ + cmd, + args, + }); if (result.success) { const [dir, stem] = dirAndStem(input); return computePath(stem, dir, format); diff --git a/src/command/render/pandoc.ts b/src/command/render/pandoc.ts index 158e271402d..b47fa12ff2d 100644 --- a/src/command/render/pandoc.ts +++ b/src/command/render/pandoc.ts @@ -207,6 +207,7 @@ 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 { call } from "../../deno_ral/process.ts"; // in case we are running multiple pandoc processes // we need to make sure we capture all of the trace files @@ -241,42 +242,38 @@ const handleCombinedLuaProfiles = ( }; function captureRenderCommand( - args: Deno.RunOptions, + args: Deno.CommandOptions, temp: TempContext, outputDir: string, ) { Deno.mkdirSync(outputDir, { recursive: true }); - const newArgs = [ - args.cmd[0], - ...args.cmd.slice(1).map((_arg) => { - const arg = _arg as string; // we know it's a string, TypeScript doesn't somehow - if (!arg.startsWith(temp.baseDir)) { - return arg; - } - const newArg = join(outputDir, basename(arg)); - if (arg.match(/^.*quarto\-defaults.*.yml$/)) { - // we need to correct the defaults YML because it contains a reference to a template in a temp directory - const ymlDefaults = Deno.readTextFileSync(arg); - const defaults = parseYml(ymlDefaults); - - const templateDirectory = dirname(defaults.template); - const newTemplateDirectory = join( - outputDir, - basename(templateDirectory), - ); - copyTo(templateDirectory, newTemplateDirectory); - defaults.template = join( - newTemplateDirectory, - basename(defaults.template), - ); - const defaultsOutputFile = join(outputDir, basename(arg)); - Deno.writeTextFileSync(defaultsOutputFile, stringify(defaults)); - return defaultsOutputFile; - } - Deno.copyFileSync(arg, newArg); - return newArg; - }), - ] as typeof args.cmd; + const newArgs: typeof args.args = (args.args ?? []).map((_arg) => { + const arg = _arg as string; // we know it's a string, TypeScript doesn't somehow + if (!arg.startsWith(temp.baseDir)) { + return arg; + } + const newArg = join(outputDir, basename(arg)); + if (arg.match(/^.*quarto\-defaults.*.yml$/)) { + // we need to correct the defaults YML because it contains a reference to a template in a temp directory + const ymlDefaults = Deno.readTextFileSync(arg); + const defaults = parseYml(ymlDefaults); + const templateDirectory = dirname(defaults.template); + const newTemplateDirectory = join( + outputDir, + basename(templateDirectory), + ); + copyTo(templateDirectory, newTemplateDirectory); + defaults.template = join( + newTemplateDirectory, + basename(defaults.template), + ); + const defaultsOutputFile = join(outputDir, basename(arg)); + Deno.writeTextFileSync(defaultsOutputFile, stringify(defaults)); + return defaultsOutputFile; + } + Deno.copyFileSync(arg, newArg); + return newArg; + }); // now we need to correct entries in filterParams const filterParams = JSON.parse( @@ -1322,7 +1319,8 @@ export async function runPandoc( setupPandocEnv(); const params = { - cmd, + cmd: cmd[0], + args: cmd.slice(1), cwd, env: pandocEnv, ourEnv: Deno.env.toObject(), @@ -1575,9 +1573,9 @@ async function resolveExtras( }; const woff2ttf = async (url: string) => { const path = url_to_path(url); - await Deno.run({ cmd: ["ttx", join(font_cache, path)] }); - await Deno.run({ - cmd: ["ttx", join(font_cache, path.replace(/woff2?$/, "ttx"))], + await call("ttx", { args: [join(font_cache, path)] }); + await call("ttx", { + args: [join(font_cache, path.replace(/woff2?$/, "ttx"))], }); }; const ttf_urls2: Array = [], woff_urls2: Array = []; diff --git a/src/command/render/project.ts b/src/command/render/project.ts index bc5730f46c8..514884ea44c 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -994,7 +994,8 @@ async function runScripts( } } else { const result = await execProcess({ - cmd: args, + cmd: args[0], + args: args.slice(1), cwd: projDir, stdout: quiet ? "piped" : "inherit", env, diff --git a/src/command/render/render-files.ts b/src/command/render/render-files.ts index 98527326688..0e8ffec77fd 100644 --- a/src/command/render/render-files.ts +++ b/src/command/render/render-files.ts @@ -115,6 +115,7 @@ import { import { NotebookContext } from "../../render/notebook/notebook-types.ts"; import { setExecuteEnvironment } from "../../execute/environment.ts"; import { safeCloneDeep } from "../../core/safe-clone-deep.ts"; +import { warn } from "log"; export async function renderExecute( context: RenderContext, @@ -346,6 +347,10 @@ export async function renderFiles( return await pandocRenderer.onComplete(false, options.flags?.quiet); } catch (error) { + if (!(error instanceof Error)) { + warn("Should not have arrived here:", error); + throw error; + } return { files: (await pandocRenderer.onComplete(true)).files, error: error || new Error(), @@ -399,6 +404,10 @@ export async function renderFile( } return await pandocRenderer.onComplete(false, options.flags?.quiet); } catch (error) { + if (!(error instanceof Error)) { + warn("Should not have arrived here:", error); + throw error; + } return { files: (await pandocRenderer.onComplete(true)).files, error: error || new Error(), diff --git a/src/command/use/commands/binder/binder.ts b/src/command/use/commands/binder/binder.ts index f060f5131bd..a3d3df64452 100644 --- a/src/command/use/commands/binder/binder.ts +++ b/src/command/use/commands/binder/binder.ts @@ -82,8 +82,8 @@ export const useBinderCommand = new Command() if (projectHasR(context, projEnv)) { const result = await execProcess( { - cmd: [ - await rBinaryPath("R"), + cmd: await rBinaryPath("R"), + args: [ "--version", ], stdout: "piped", diff --git a/src/core/bibliography.ts b/src/core/bibliography.ts index 09e7a36f240..94819545bef 100644 --- a/src/core/bibliography.ts +++ b/src/core/bibliography.ts @@ -41,7 +41,7 @@ export async function renderHtml(entry: CSL, csl?: string) { const cslStr = JSON.stringify([entry], undefined, 2); const result = await execProcess( - { cmd, stdout: "piped", stderr: "piped" }, + { cmd: cmd[0], args: cmd.slice(1), stdout: "piped", stderr: "piped" }, cslStr, ); if (result.success) { @@ -63,7 +63,7 @@ export async function renderBibTex(entry: CSL) { const cslStr = JSON.stringify([entry], undefined, 2); const result = await execProcess( - { cmd, stdout: "piped", stderr: "piped" }, + { cmd: cmd[0], args: cmd.slice(1), stdout: "piped", stderr: "piped" }, cslStr, ); if (result.success) { @@ -93,7 +93,13 @@ export async function renderToCSLJSON( cmd.push("--citeproc"); const result = await execProcess( - { cmd, stdout: "piped", stderr: "piped", cwd: dir }, + { + cmd: cmd[0], + args: cmd.slice(1), + stdout: "piped", + stderr: "piped", + cwd: dir, + }, ); if (result.success) { if (result.stdout) { diff --git a/src/core/cri/cri.ts b/src/core/cri/cri.ts index 0ab03ce81b9..b178d8febfc 100644 --- a/src/core/cri/cri.ts +++ b/src/core/cri/cri.ts @@ -21,6 +21,7 @@ import { registerForExitCleanup, unregisterForExitCleanup, } from "../process.ts"; +import { assert } from "testing/asserts"; async function waitForServer(port: number, timeout = 3000) { const interval = 50; @@ -87,8 +88,7 @@ export async function criClient(appPath?: string, port?: number) { // Allow to adapt the headless mode depending on the Chrome version const headlessMode = getenv("QUARTO_CHROMIUM_HEADLESS_MODE", "none"); - const cmd = [ - app, + const args = [ // TODO: Chrome v128 changed the default from --headless=old to --headless=new // in 2024-08. Old headless mode was effectively a separate browser render, // and while more performant did not share the same browser implementation as @@ -106,19 +106,27 @@ export async function criClient(appPath?: string, port?: number) { "--renderer-process-limit=1", `--remote-debugging-port=${port}`, ]; - const browser = Deno.run({ cmd, stdout: "piped", stderr: "piped" }); + const browser = new Deno.Command(app, { + args, + stdout: "piped", + stderr: "piped", + }); + const cmd = browser.spawn(); // Register for cleanup inside exitWithCleanup() in case something goes wrong - const thisProcessId = registerForExitCleanup(browser); + const thisProcessId = registerForExitCleanup(cmd); if (!(await waitForServer(port as number))) { let msg = "Couldn't find open server."; // Printing more error information if chrome process errored - if (!(await browser.status()).success) { + if (!(await cmd.status).success) { debug(`[CHROMIUM path] : ${app}`); debug(`[CHROMIUM cmd] : ${cmd}`); - const rawError = await browser.stderrOutput(); - const errorString = new TextDecoder().decode(rawError); + const rawError = await cmd.stderr; + const reader = rawError.getReader(); + const readerResult = await reader.read(); + assert(readerResult.done); + const errorString = new TextDecoder().decode(readerResult.value!); msg = msg + "\n" + `Chrome process error: ${errorString}`; } @@ -135,8 +143,7 @@ export async function criClient(appPath?: string, port?: number) { // We have a bug where `client.close()` doesn't return properly and we don't go below // meaning the `browser` process is not killed here, and it will be handled in exitWithCleanup(). - browser.kill(); // Chromium headless won't terminate on its own, so we need to send kill signal - browser.close(); // Closing the browser Deno process + cmd.kill(); // Chromium headless won't terminate on its own, so we need to send kill signal unregisterForExitCleanup(thisProcessId); // All went well so not need to cleanup on quarto exit }, diff --git a/src/core/dart-sass.ts b/src/core/dart-sass.ts index 2a307d3f906..f9b859149a3 100644 --- a/src/core/dart-sass.ts +++ b/src/core/dart-sass.ts @@ -71,14 +71,12 @@ export async function dartCommand(args: string[]) { }; const sass = resolvePath(); - const cmd = [ - sass, - ...args, - ]; + const cmd = sass; // Run the sass compiler const result = await execProcess( { cmd, + args, stdout: "piped", stderr: "piped", }, diff --git a/src/core/deno-dom.ts b/src/core/deno-dom.ts index 189c4a5dad3..2e5952e38f0 100644 --- a/src/core/deno-dom.ts +++ b/src/core/deno-dom.ts @@ -166,6 +166,9 @@ export async function initDenoDom() { return; } } catch (e) { + if (!(e instanceof Error)) { + throw e; + } debug("Error loading deno-dom-native: " + e.message); } } diff --git a/src/core/deno/monkey-patch.ts b/src/core/deno/monkey-patch.ts index 7f6fb6a8840..8492e6c4d3a 100644 --- a/src/core/deno/monkey-patch.ts +++ b/src/core/deno/monkey-patch.ts @@ -27,6 +27,9 @@ function withAttempts(callable: () => T) { try { return callable(); } catch (err) { + if (!(err instanceof Error)) { + throw err; + } if (err.message) { debug("Error attempting to create temp file: " + err.message); if (i === maxAttempts - 1) { @@ -43,6 +46,9 @@ function withAttempts(callable: () => T) { function withAttemptsAsync(callable: () => Promise) { const inner = (attempt: number): Promise => { return callable().catch((err) => { + if (!(err instanceof Error)) { + throw err; + } if (err.message) { debug("Error attempting to create temp file: " + err.message); } @@ -91,6 +97,9 @@ Deno.readTextFile = async ( const result = await oldReadTextFile(path, options); return result; } catch (err) { + if (!(err instanceof Error)) { + throw err; + } if (err.message) { err.message = err.message + "\n" + "Path: " + path; } @@ -103,6 +112,9 @@ Deno.readTextFileSync = (path: string | URL) => { const result = oldReadTextFileSync(path); return result; } catch (err) { + if (!(err instanceof Error)) { + throw err; + } if (err.message) { err.message = err.message + "\n" + "Path: " + path; } diff --git a/src/core/devconfig.ts b/src/core/devconfig.ts index 2e38ee17877..820bf55f0c6 100644 --- a/src/core/devconfig.ts +++ b/src/core/devconfig.ts @@ -146,12 +146,12 @@ export async function reconfigureQuarto( join(quartoConfig.sharePath(), "..", ".."), ); - const process = Deno.run({ - cmd: configureScript, + const process = new Deno.Command(configureScript[0], { + args: configureScript.slice(1), cwd: quartoDir, }); - await process.status(); + await process.output(); info(""); error( diff --git a/src/core/esbuild.ts b/src/core/esbuild.ts index 32a49191c76..cb974799f85 100644 --- a/src/core/esbuild.ts +++ b/src/core/esbuild.ts @@ -88,14 +88,12 @@ export async function esbuildCommand( input: string, workingDir: string, ) { - const cmd = [ - Deno.env.get("QUARTO_ESBUILD") || architectureToolsPath("esbuild"), - ...args, - ]; - + const cmd = Deno.env.get("QUARTO_ESBUILD") || + architectureToolsPath("esbuild"); const result = await execProcess( { cmd, + args, cwd: workingDir, stdout: "piped", stderr: "piped", diff --git a/src/core/file.ts b/src/core/file.ts index ceef61e97c6..1dcfdf0b8e2 100644 --- a/src/core/file.ts +++ b/src/core/file.ts @@ -67,7 +67,8 @@ export async function touch(path: string) { await Deno.writeFileSync(path, contents); } else { await execProcess({ - cmd: ["touch", path], + cmd: "touch", + args: [path], }); } } diff --git a/src/core/git.ts b/src/core/git.ts index 7749743931f..db6bb731cf3 100644 --- a/src/core/git.ts +++ b/src/core/git.ts @@ -8,11 +8,12 @@ import { which } from "./path.ts"; import { execProcess } from "./process.ts"; import SemVer from "semver/mod.ts"; -export async function gitCmds(dir: string, cmds: Array) { - for (const cmd of cmds) { +export async function gitCmds(dir: string, argsArray: Array) { + for (const args of argsArray) { if ( !(await execProcess({ - cmd: ["git", ...cmd], + cmd: "git", + args, cwd: dir, })).success ) { @@ -24,7 +25,8 @@ export async function gitCmds(dir: string, cmds: Array) { export async function gitVersion(): Promise { const result = await execProcess( { - cmd: ["git", "--version"], + cmd: "git", + args: ["--version"], stdout: "piped", }, ); @@ -49,7 +51,8 @@ export async function lsFiles( ): Promise { if (await which("git")) { const result = await execProcess({ - cmd: ["git", "ls-files", ...(args || [])], + cmd: "git", + args: ["ls-files", ...(args || [])], cwd, stdout: "piped", stderr: "piped", @@ -71,7 +74,8 @@ export async function gitBranchExists( ): Promise { if (await which("git")) { const result = await execProcess({ - cmd: ["git", "show-ref", "--verify", "--quiet", `refs/heads/${branch}`], + cmd: "git", + args: ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], cwd, stdout: "piped", stderr: "piped", diff --git a/src/core/github.ts b/src/core/github.ts index 4777353d619..04c862d4a20 100644 --- a/src/core/github.ts +++ b/src/core/github.ts @@ -26,7 +26,8 @@ export async function gitHubContext(dir: string) { // check for a repo in this directory if (context.git) { context.repo = (await execProcess({ - cmd: ["git", "rev-parse"], + cmd: "git", + args: ["rev-parse"], cwd: dir, stdout: "piped", stderr: "piped", @@ -35,7 +36,8 @@ export async function gitHubContext(dir: string) { // check for an origin remote if (context.repo) { const result = await execProcess({ - cmd: ["git", "config", "--get", "remote.origin.url"], + cmd: "git", + args: ["config", "--get", "remote.origin.url"], cwd: dir, stdout: "piped", stderr: "piped", @@ -45,8 +47,8 @@ export async function gitHubContext(dir: string) { // check for a gh-pages branch const ghPagesRemote = await execProcess({ - cmd: [ - "git", + cmd: "git", + args: [ "ls-remote", "--quiet", "--exit-code", diff --git a/src/core/handlers/dot.ts b/src/core/handlers/dot.ts index d20ebfdef22..2473528010e 100644 --- a/src/core/handlers/dot.ts +++ b/src/core/handlers/dot.ts @@ -75,6 +75,7 @@ const dotHandler: LanguageHandler = { console.log = oldConsoleLog; console.warn = oldConsoleWarn; } catch (e) { + if (!(e instanceof Error)) throw e; console.log = oldConsoleLog; console.warn = oldConsoleWarn; const m = (e.message as string).match( diff --git a/src/core/http-server.ts b/src/core/http-server.ts index 0b11c2c7ec5..3c99ac51018 100644 --- a/src/core/http-server.ts +++ b/src/core/http-server.ts @@ -1,30 +1,22 @@ /* -* http-server.ts -* -* Copyright (C) 2020-2022 Posit Software, PBC -* -*/ + * http-server.ts + * + * Copyright (C) 2025 Posit Software, PBC + */ -import { warning } from "../deno_ral/log.ts"; - -export async function handleHttpRequests( - listener: Deno.Listener, - handler: (req: Request) => Promise, +export function handleHttpRequests( + options: { + port?: number; + hostname?: string; + handler: (req: Request) => Promise; + }, ) { - for await (const conn of listener) { - (async () => { - try { - for await (const { request, respondWith } of Deno.serveHttp(conn)) { - await respondWith(handler(request)); - } - } catch (err) { - warning(err.message); - try { - conn.close(); - } catch { - // - } - } - })(); - } + const abortController = new AbortController(); + const server = Deno.serve({ ...options, signal: abortController.signal }); + return { + server, + stop: () => { + abortController.abort(); + }, + }; } diff --git a/src/core/http.ts b/src/core/http.ts index c948b555e83..d90f47793be 100644 --- a/src/core/http.ts +++ b/src/core/http.ts @@ -150,6 +150,7 @@ export function httpFileRequestHandler( } } } catch (e) { + if (!(e instanceof Error)) throw e; // it's possible for an exception to occur before we've normalized the path // so we need to renormalize it here if (fsPath) { diff --git a/src/core/image.ts b/src/core/image.ts index 6ea8eb07ac3..ec3cab85fa8 100644 --- a/src/core/image.ts +++ b/src/core/image.ts @@ -20,6 +20,7 @@ export function imageSize(path: string) { width: png.width, }; } catch (error) { + if (!(error instanceof Error)) throw error; throw new Error(`Error reading file ${path}\n${error.message}`); } } diff --git a/src/core/jupyter/capabilities.ts b/src/core/jupyter/capabilities.ts index 16b5c2c63bf..087ca4682e4 100644 --- a/src/core/jupyter/capabilities.ts +++ b/src/core/jupyter/capabilities.ts @@ -203,8 +203,9 @@ function getPyLauncherJupyterCapabilities() { async function getJupyterCapabilities(cmd: string[], pyLauncher = false) { try { const result = await execProcess({ - cmd: [ - ...cmd, + cmd: cmd[0], + args: [ + ...cmd.slice(1), resourcePath("capabilities/jupyter.py"), ], stdout: "piped", diff --git a/src/core/jupyter/jupyter-filters.ts b/src/core/jupyter/jupyter-filters.ts index a91c5357c38..4edc24a2926 100644 --- a/src/core/jupyter/jupyter-filters.ts +++ b/src/core/jupyter/jupyter-filters.ts @@ -71,10 +71,8 @@ export async function jupyterNotebookFiltered( stdout: "piped", }) : await execProcess({ - cmd: [ - isAbsolute(script) ? script : basename(script), - ...args.slice(1), - ], + cmd: isAbsolute(script) ? script : basename(script), + args: args.slice(1), cwd: dirname(file), env: { PYTHONUNBUFFERED: "1", diff --git a/src/core/jupyter/kernels.ts b/src/core/jupyter/kernels.ts index 69ca4d152b2..371b3285531 100644 --- a/src/core/jupyter/kernels.ts +++ b/src/core/jupyter/kernels.ts @@ -80,9 +80,11 @@ async function computeJupyterKernelspecs(): Promise< Map > { try { + const cmd = await jupyterExec(); const result = await execProcess( { - cmd: [...(await jupyterExec()), "--paths", "--json"], + cmd: cmd[0], + args: [...cmd.slice(1), "--paths", "--json"], stdout: "piped", stderr: "piped", }, @@ -125,6 +127,7 @@ async function computeJupyterKernelspecs(): Promise< return kDefaultKernelspecs; } } catch (e) { + if (!(e instanceof Error)) throw e; debug("Error reading kernelspecs: " + e.message); return kDefaultKernelspecs; } diff --git a/src/core/jupyter/venv.ts b/src/core/jupyter/venv.ts index b489d227a5d..b250010179b 100644 --- a/src/core/jupyter/venv.ts +++ b/src/core/jupyter/venv.ts @@ -23,7 +23,8 @@ export async function jupyterCreateVenv(dir: string, packages?: string[]) { if (caps) { const executable = caps.pyLauncher ? "py" : caps.executable; const result = await execProcess({ - cmd: [executable, "-m", "venv", kEnvDir], + cmd: executable, + args: ["-m", "venv", kEnvDir], cwd: dir, }); if (!result.success) { @@ -36,7 +37,8 @@ export async function jupyterCreateVenv(dir: string, packages?: string[]) { ); packages = ld.uniq(["jupyter"].concat(packages || [])); const installResult = await execProcess({ - cmd: [pip3, "install", ...packages], + cmd: pip3, + args: ["install", ...packages], cwd: dir, }); if (!installResult.success) { @@ -55,7 +57,8 @@ export async function jupyterCreateCondaenv(dir: string, packages?: string[]) { info(`Using conda at ${conda}`); packages = ld.uniq(["jupyter"].concat(packages || [])); const installResult = await execProcess({ - cmd: ["conda", "create", "--yes", "--prefix", "env", ...packages], + cmd: "conda", + args: ["create", "--yes", "--prefix", "env", ...packages], cwd: dir, }); if (!installResult.success) { diff --git a/src/core/knitr.ts b/src/core/knitr.ts index cdbc01e24fe..d525c97ea28 100644 --- a/src/core/knitr.ts +++ b/src/core/knitr.ts @@ -43,7 +43,8 @@ export async function checkRBinary() { const rBin = await rBinaryPath("Rscript"); try { const result = await execProcess({ - cmd: [rBin, "--version"], + cmd: rBin, + args: ["--version"], stdout: "piped", stderr: "piped", }); @@ -72,7 +73,8 @@ export async function knitrCapabilities(rBin: string | undefined) { try { debug(`-- Checking knitr engine capabilities --`); const result = await execProcess({ - cmd: [rBin, resourcePath("capabilities/knitr.R")], + cmd: rBin, + args: [resourcePath("capabilities/knitr.R")], stdout: "piped", }); if (result.success && result.stdout) { diff --git a/src/core/lib/markdown-analysis/level-one-headings.ts b/src/core/lib/markdown-analysis/level-one-headings.ts index 5722cca404b..96eca41dc5c 100644 --- a/src/core/lib/markdown-analysis/level-one-headings.ts +++ b/src/core/lib/markdown-analysis/level-one-headings.ts @@ -17,7 +17,8 @@ export async function hasLevelOneHeadings(markdown: string): Promise { join("filters", "quarto-internals", "leveloneanalysis.lua"), ); const result = await execProcess({ - cmd: [path, "-f", "markdown", "-t", "markdown", "-L", filterPath], + cmd: path, + args: ["-f", "markdown", "-t", "markdown", "-L", filterPath], stdout: "piped", }, markdown); return result.stdout?.trim() === "true"; diff --git a/src/core/lib/promise.ts b/src/core/lib/promise.ts index d03fe66c05f..458e18d9daf 100644 --- a/src/core/lib/promise.ts +++ b/src/core/lib/promise.ts @@ -1,9 +1,8 @@ /* -* promise.ts -* -* Copyright (C) 2020-2022 Posit Software, PBC -* -*/ + * promise.ts + * + * Copyright (C) 2020-2022 Posit Software, PBC + */ interface PendingPromise { promise: () => Promise; @@ -56,6 +55,7 @@ export class PromiseQueue { this.dequeue(); }); } catch (err) { + if (!(err instanceof Error)) throw err; this.running = false; item.reject(err); this.dequeue(); diff --git a/src/core/lib/yaml-intelligence/annotated-yaml.ts b/src/core/lib/yaml-intelligence/annotated-yaml.ts index 98885a2e034..f71e13c2d6b 100644 --- a/src/core/lib/yaml-intelligence/annotated-yaml.ts +++ b/src/core/lib/yaml-intelligence/annotated-yaml.ts @@ -109,7 +109,8 @@ export function readAnnotatedYamlFromMappedString( } try { return buildJsYamlAnnotation(mappedSource); - } catch (e) { + // deno-lint-ignore no-explicit-any + } catch (e: any) { if (e.name === "YAMLError") { e.name = "YAML Parsing"; } @@ -617,6 +618,7 @@ export function locateCursor( annotation: innermostAnnotation!, }; } catch (e) { + if (!(e instanceof Error)) throw e; if (e.message === kInternalLocateError) { return { withError: true, diff --git a/src/core/log.ts b/src/core/log.ts index d3971f31954..cdbf63ff5d1 100644 --- a/src/core/log.ts +++ b/src/core/log.ts @@ -113,7 +113,7 @@ export function logLevel() { } export class StdErrOutputHandler extends BaseHandler { - format(logRecord: LogRecord, prefix = true): string { + override format(logRecord: LogRecord, prefix = true): string { // Set default options const options = { newline: true, @@ -186,7 +186,7 @@ export class LogEventsHandler extends StdErrOutputHandler { formatter: (({ msg }) => `${msg}`), }); } - handle(logRecord: LogRecord) { + override handle(logRecord: LogRecord) { if (this.level > logRecord.level) return; LogEventsHandler.handlers_.forEach((handler) => @@ -214,11 +214,11 @@ export class LogFileHandler extends FileHandler { } msgFormat; - flush(): void { + override flush(): void { this.logger.flush(); } - format(logRecord: LogRecord): string { + override format(logRecord: LogRecord): string { // Messages that start with a carriage return are progress messages // that rewrite a line, so just ignore these if (logRecord.msg.startsWith("\r")) { @@ -253,7 +253,7 @@ export class LogFileHandler extends FileHandler { } } - async log(msg: string) { + override async log(msg: string) { // Ignore any messages that are blank if (msg !== "") { this.logger.log(msg); @@ -485,8 +485,8 @@ export async function logPandoc( ) { const cols = getColumns(); const result = await execProcess({ - cmd: [ - pandocBinaryPath(), + cmd: pandocBinaryPath(), + args: [ "-f", format, "-t", diff --git a/src/core/main.ts b/src/core/main.ts index abbdbdcf86b..5dc1d94f5c6 100644 --- a/src/core/main.ts +++ b/src/core/main.ts @@ -6,7 +6,7 @@ * Copyright (C) 2022 Posit Software, PBC */ -import { initializeLogger, logError, logOptions } from "../../src/core/log.ts"; +import { initializeLogger, logError, logOptions } from "./log.ts"; import { Args } from "flags"; import { parse } from "flags"; import { exitWithCleanup } from "./cleanup.ts"; diff --git a/src/core/pandoc/pandoc-formats.ts b/src/core/pandoc/pandoc-formats.ts index d3758ca9da7..ffd80fba4e0 100644 --- a/src/core/pandoc/pandoc-formats.ts +++ b/src/core/pandoc/pandoc-formats.ts @@ -15,7 +15,8 @@ export const kYamlMetadataBlock = "yaml_metadata_block"; export async function pandocListFormats() { const result = await execProcess({ - cmd: [pandocBinaryPath(), "--list-output-formats"], + cmd: pandocBinaryPath(), + args: ["--list-output-formats"], stdout: "piped", }); if (result.success) { @@ -31,7 +32,8 @@ export async function pandocListFormatDefaultExtensions(format: string) { return []; } const result = await execProcess({ - cmd: [pandocBinaryPath(), `--list-extensions=${format}`], + cmd: pandocBinaryPath(), + args: [`--list-extensions=${format}`], stdout: "piped", }); if (result.success) { diff --git a/src/core/pandoc/self-contained.ts b/src/core/pandoc/self-contained.ts index 252f7181466..1d0b32cf29d 100644 --- a/src/core/pandoc/self-contained.ts +++ b/src/core/pandoc/self-contained.ts @@ -72,7 +72,8 @@ export const pandocIngestSelfContainedContent = async ( cmd.push("--resource-path", resourcePath.join(":")); } const result = await execProcess({ - cmd, + cmd: cmd[0], + args: cmd.slice(1), stdout: "piped", cwd: workingDir, }, input.join("\n")); diff --git a/src/core/path.ts b/src/core/path.ts index c0f51e5ab24..65da687e6e1 100644 --- a/src/core/path.ts +++ b/src/core/path.ts @@ -40,6 +40,9 @@ export function safeRemoveIfExists(file: string) { try { removeIfExists(file); } catch (error) { + if (!(error instanceof Error)) { + throw error; + } warning(`Error removing file ${file}: ${error.message}`); } } @@ -108,7 +111,7 @@ export function safeExistsSync(path: string) { export async function which(cmd: string) { const args = isWindows ? ["CMD", "/C", "where", cmd] : ["which", cmd]; const result = await execProcess( - { cmd: args, stderr: "piped", stdout: "piped" }, + { cmd: args[0], args: args.slice(1), stderr: "piped", stdout: "piped" }, ); if (result.code === 0) { return isWindows diff --git a/src/core/performance/metrics.ts b/src/core/performance/metrics.ts index 2a72b2a18d6..8bb50375364 100644 --- a/src/core/performance/metrics.ts +++ b/src/core/performance/metrics.ts @@ -10,7 +10,7 @@ import { Stats } from "./stats.ts"; type FileReadRecord = { path: string; - stack: string; + stack: string[]; }; let fileReads: FileReadRecord[] | undefined = undefined; @@ -24,6 +24,7 @@ export function captureFileReads() { try { throw new Error("File read"); } catch (e) { + if (!(e instanceof Error)) throw e; const stack = e.stack!.split("\n").slice(2); fileReads!.push({ path: String(path), stack }); } diff --git a/src/core/previewurl.ts b/src/core/previewurl.ts index 9e34c6c0c67..b79b4ba4abe 100644 --- a/src/core/previewurl.ts +++ b/src/core/previewurl.ts @@ -106,7 +106,8 @@ export async function rswURL(port: number, path: string) { async function rswPortToken(port: number) { const result = await execProcess( { - cmd: ["/usr/lib/rstudio-server/bin/rserver-url", String(port)], + cmd: "/usr/lib/rstudio-server/bin/rserver-url", + args: [String(port)], stdout: "piped", stderr: "piped", }, diff --git a/src/core/process.ts b/src/core/process.ts index 809431547b8..131ccaf37d7 100644 --- a/src/core/process.ts +++ b/src/core/process.ts @@ -5,17 +5,15 @@ */ import { MuxAsyncIterator, pooledMap } from "async"; -import { iterateReader } from "io/iterate-reader"; -import { type Closer, type Reader } from "io/types"; import { debug, info } from "../deno_ral/log.ts"; import { onCleanup } from "./cleanup.ts"; import { ProcessResult } from "./process-types.ts"; -const processList = new Map(); +const processList = new Map(); let processCount = 0; let cleanupRegistered = false; -export function registerForExitCleanup(process: Deno.Process) { +export function registerForExitCleanup(process: Deno.ChildProcess) { const thisProcessId = ++processCount; // don't risk repeated PIDs processList.set(thisProcessId, process); return thisProcessId; @@ -32,7 +30,7 @@ function ensureCleanup() { for (const process of processList.values()) { try { process.kill(); - process.close(); + // process.close(); } catch (error) { info("Error occurred during cleanup: " + error); } @@ -41,8 +39,12 @@ function ensureCleanup() { } } +export type ExecProcessOptions = Deno.CommandOptions & { + cmd: string; +}; + export async function execProcess( - options: Deno.RunOptions, + options: ExecProcessOptions, stdin?: string, mergeOutput?: "stderr>stdout" | "stdout>stderr", stderrFilter?: (output: string) => string, @@ -65,16 +67,18 @@ export async function execProcess( // If the caller asked for stdout/stderr to be directed to the rid of an open // file, just allow that to happen. Otherwise, specify piped and we will implement // the proper behavior for inherit, etc.... - debug(`[execProcess] ${options.cmd.join(" ")}`); - const process = Deno.run({ + debug(`[execProcess] ${[options.cmd, ...(options.args || [])].join(" ")}`); + const denoCmd = new Deno.Command(options.cmd, { ...options, stdin: stdin !== undefined ? "piped" : options.stdin, stdout: typeof (options.stdout) === "number" ? options.stdout : "piped", stderr: typeof (options.stderr) === "number" ? options.stderr : "piped", }); + const process = denoCmd.spawn(); const thisProcessId = registerForExitCleanup(process); if (stdin !== undefined) { + const stdinWriter = process.stdin.getWriter(); if (!process.stdin) { unregisterForExitCleanup(thisProcessId); throw new Error("Process stdin not available"); @@ -86,9 +90,10 @@ export async function execProcess( while (offset < buffer.length) { const end = Math.min(offset + kWindowSize, buffer.length); const window = buffer.subarray(offset, end); - const written = await process.stdin.write(window); - offset += written; + await stdinWriter.write(window); + offset += window.byteLength; } + stdinWriter.releaseLock(); process.stdin.close(); } @@ -105,18 +110,17 @@ export async function execProcess( // Add streams to the multiplexer const addStream = ( - stream: (Reader & Closer) | null, + iterator: AsyncIterableIterator>, filter?: (output: string) => string, ) => { - if (stream !== null) { - const streamIter = filter - ? filteredAsyncIterator(iterateReader(stream), filter) - : iterateReader(stream); - multiplexIterator.add(streamIter); - } + const streamIter = filter + ? filteredAsyncIterator(iterator, filter) + : iterator; + multiplexIterator.add(streamIter); }; - addStream(process.stdout); - addStream(process.stderr, stderrFilter); + + addStream(process.stdout.values()); + addStream(process.stderr.values(), stderrFilter); // Process the output const allOutput = await processOutput( @@ -132,13 +136,15 @@ export async function execProcess( } // Close the streams - const closeStream = (stream: (Reader & Closer) | null) => { - if (stream) { - stream.close(); - } - }; - closeStream(process.stdout); - closeStream(process.stderr); + // FIXME: In Deno 2 we get ReadableStreams which do not have a close method? + // + // const closeStream = (stream: ReadableStream> | null) => { + // if (stream) { + // stream.close(); + // } + // }; + // closeStream(process.stdout); + // closeStream(process.stderr); } else { // Process the streams independently const promises: Promise[] = []; @@ -146,20 +152,20 @@ export async function execProcess( if (process.stdout !== null) { promises.push( processOutput( - iterateReader(process.stdout), + process.stdout.values(), options.stdout, respectStreams ? "stdout" : undefined, ).then((text) => { stdoutText = text; - process.stdout!.close(); + // process.stdout!.close(); }), ); } if (process.stderr != null) { const iterator = stderrFilter - ? filteredAsyncIterator(iterateReader(process.stderr), stderrFilter) - : iterateReader(process.stderr); + ? filteredAsyncIterator(process.stderr.values(), stderrFilter) + : process.stderr.values(); promises.push( processOutput( iterator, @@ -167,7 +173,7 @@ export async function execProcess( respectStreams ? "stderr" : undefined, ).then((text) => { stderrText = text; - process.stderr!.close(); + // process.stderr!.close(); }), ); } @@ -175,10 +181,10 @@ export async function execProcess( } // await result - const status = await withTimeout(process.status()); + const status = await withTimeout(process.output()); // close the process - process.close(); + // process.close(); unregisterForExitCleanup(thisProcessId); @@ -191,7 +197,10 @@ export async function execProcess( stderr: stderrText, }; } catch (e) { - throw new Error(`Error executing '${options.cmd[0]}': ${e.message}`); + if (!(e instanceof Error)) { + throw e; + } + throw new Error(`Error executing '${options.cmd}': ${e.message}`); } } diff --git a/src/core/puppeteer.ts b/src/core/puppeteer.ts index 891e6a968e9..bde97cd8989 100644 --- a/src/core/puppeteer.ts +++ b/src/core/puppeteer.ts @@ -125,6 +125,7 @@ export async function withPuppeteerBrowserAndPage( return result!; } } catch (error) { + if (!(error instanceof Error)) throw error; if ( (allowedErrorMessages.indexOf(error.message) !== -1) && (attempts < maxAttempts) @@ -166,6 +167,7 @@ export async function inPuppeteer( return clientSideResult; }); } catch (error) { + if (!(error instanceof Error)) throw error; if ( (allowedErrorMessages.indexOf(error.message) !== -1) && (attempts < maxAttempts) diff --git a/src/core/registry.ts b/src/core/registry.ts index e89a415f828..f719eae3d87 100644 --- a/src/core/registry.ts +++ b/src/core/registry.ts @@ -39,7 +39,8 @@ export async function registryReadString( let result: ProcessResult; try { result = await execProcess({ - cmd, + cmd: cmd[0], + args: cmd.slice(1), stdout: "piped", stderr: "null", }); diff --git a/src/core/retry.ts b/src/core/retry.ts index f6f89dcde23..017560a8b6d 100644 --- a/src/core/retry.ts +++ b/src/core/retry.ts @@ -1,9 +1,8 @@ /* -* retry.ts -* -* Copyright (C) 2020-2022 Posit Software, PBC -* -*/ + * retry.ts + * + * Copyright (C) 2020-2022 Posit Software, PBC + */ import { sleep } from "./wait.ts"; @@ -23,12 +22,13 @@ export async function withRetry( minWait = 1000, maxWait = 4000, retry = () => true, - } = (options || {}); + } = options || {}; let attempt = 0; while (true) { try { return fn(); } catch (err) { + if (!(err instanceof Error)) throw err; if ((attempt++ >= attempts) || (retry && !retry(err))) { throw err; } diff --git a/src/core/run/deno.ts b/src/core/run/deno.ts index a3e8cea7ee4..9d871b19139 100644 --- a/src/core/run/deno.ts +++ b/src/core/run/deno.ts @@ -43,8 +43,8 @@ export const denoRunHandler: RunHandler = { return await execProcess( { - cmd: [ - architectureToolsPath("deno"), + cmd: architectureToolsPath("deno"), + args: [ "run", "--import-map", importMap, diff --git a/src/core/run/lua.ts b/src/core/run/lua.ts index a26f06821ca..92644b74632 100644 --- a/src/core/run/lua.ts +++ b/src/core/run/lua.ts @@ -43,7 +43,8 @@ export const luaRunHandler: RunHandler = { return await execProcess( { - cmd, + cmd: cmd[0], + args: cmd.slice(1), ...options, }, "", @@ -96,8 +97,8 @@ setmetatable(_G, meta) // call pandoc w/ temp script as --to try { return await execProcess({ - cmd: [ - pandocBinaryPath(), + cmd: pandocBinaryPath(), + args: [ "--from", "markdown", "--to", diff --git a/src/core/run/python.ts b/src/core/run/python.ts index 1fda17f5fb9..dea50e057b9 100644 --- a/src/core/run/python.ts +++ b/src/core/run/python.ts @@ -20,10 +20,12 @@ export const pythonRunHandler: RunHandler = { stdin?: string, options?: RunHandlerOptions, ) => { + const pythonCmd = await pythonExec(); return await execProcess( { - cmd: [ - ...(await pythonExec()), + cmd: pythonCmd[0], + args: [ + ...pythonCmd.slice(1), script, ...args, ], diff --git a/src/core/run/r.ts b/src/core/run/r.ts index 185bfe1a15d..acda14f47dd 100644 --- a/src/core/run/r.ts +++ b/src/core/run/r.ts @@ -22,8 +22,8 @@ export const rRunHandler: RunHandler = { ) => { return await execProcess( { - cmd: [ - await rBinaryPath("Rscript"), + cmd: (await rBinaryPath("Rscript")), + args: [ script, ...args, ], diff --git a/src/core/run/types.ts b/src/core/run/types.ts index 185945395c1..f7b3a4f6461 100644 --- a/src/core/run/types.ts +++ b/src/core/run/types.ts @@ -11,7 +11,7 @@ export interface RunHandlerOptions { env?: { [key: string]: string; }; - stdout?: "inherit" | "piped" | "null" | number; + stdout?: "inherit" | "piped" | "null"; } export interface RunHandler { diff --git a/src/core/sass.ts b/src/core/sass.ts index 85ca011a04d..a5277c5bcba 100644 --- a/src/core/sass.ts +++ b/src/core/sass.ts @@ -383,6 +383,7 @@ export async function compileWithCache( const result = await memoizedGetVarsBlock(project, input); return input + "\n" + result; } catch (e) { + if (!(e instanceof Error)) throw e; if (e.name !== "SCSSParsingError") { throw e; } diff --git a/src/core/sass/add-css-vars.ts b/src/core/sass/add-css-vars.ts index 6bda466533d..3edcd99be8b 100644 --- a/src/core/sass/add-css-vars.ts +++ b/src/core/sass/add-css-vars.ts @@ -28,6 +28,7 @@ export const cssVarsBlock = (scssSource: string) => { try { astOriginal = getSassAst(scssSource); } catch (e) { + if (!(e instanceof Error)) throw e; throw new SCSSParsingError(e.message); } const ast = propagateDeclarationTypes(cleanSassAst(astOriginal)); diff --git a/src/core/schema/build-schema-file.ts b/src/core/schema/build-schema-file.ts index cb5e2b24ab3..5505bcbeb96 100644 --- a/src/core/schema/build-schema-file.ts +++ b/src/core/schema/build-schema-file.ts @@ -136,7 +136,7 @@ async function createHtmlDescriptions(): Promise< const cmd = [pandocBinaryPath(), "--to", "html"]; const pandocResult = await execProcess( - { stdout: "piped", cmd }, + { stdout: "piped", cmd: cmd[0], args: cmd.slice(1) }, markdownDescriptions, ); diff --git a/src/core/schema/types-from-schema.ts b/src/core/schema/types-from-schema.ts index 5e0f216356d..da7c69c5e54 100644 --- a/src/core/schema/types-from-schema.ts +++ b/src/core/schema/types-from-schema.ts @@ -27,9 +27,9 @@ export function typeNameFromSchemaName(schemaName: string) { } function fmtSource(source: string) { - return Deno.run({ - cmd: [Deno.execPath(), "fmt", source], - }).status(); + return new Deno.Command(Deno.execPath(), { + args: ["fmt", source], + }).output(); } export const generatedSrcMessage = diff --git a/src/core/schema/validate-document.ts b/src/core/schema/validate-document.ts index 2a99f6a9cfe..1e1c33a5123 100644 --- a/src/core/schema/validate-document.ts +++ b/src/core/schema/validate-document.ts @@ -97,6 +97,7 @@ export async function validateDocumentFromSource( } }); } catch (e) { + if (!(e instanceof Error)) throw e; if (e.name === "NoExprTag") { const err = e as NoExprTag; error(tidyverseFormatError(err.niceError), { colorize: false }); diff --git a/src/core/shell.ts b/src/core/shell.ts index d2aacccc8fa..cdb29112279 100644 --- a/src/core/shell.ts +++ b/src/core/shell.ts @@ -27,33 +27,37 @@ export async function openUrl(url: string) { const cmd = shellOpen[platformOs] || "xdg-open"; // Because URLs may contain characters like '&' that need to be escaped - // on Windoww, we need to check whether the url is one of those + // on Windows, we need to check whether the url is one of those // and use our special windows indirection in that case - if (isWindows) { + const safeWindowsArgs = (() => { + if (!isWindows) { + return undefined; + } const safeArgs = requireQuoting([url]); if (safeArgs.status) { - await safeWindowsExec( - cmd, - safeArgs.args, - (cmd: string[]) => { - return execProcess({ - cmd, - stdout: "piped", - stderr: "piped", - }); - }, - ); - } else { - // The traditional and simple way to run, which usually works - if (await which(cmd)) { - Deno.run({ cmd: [cmd, url] }); - } + return safeArgs.args; } + return undefined; + })(); + + if (safeWindowsArgs) { + await safeWindowsExec( + cmd, + safeWindowsArgs, + (cmd: string[]) => { + return execProcess({ + cmd: cmd[0], + args: cmd.slice(1), + stdout: "piped", + stderr: "piped", + }); + }, + ); } else { - // The traditional and simple way to run, which always - // works outside of windows + // The traditional and simple way to run, which usually works + // on windows and always works outside of windows if (await which(cmd)) { - Deno.run({ cmd: [cmd, url] }); + execProcess({ cmd, args: [url] }); } } } diff --git a/src/core/temp.ts b/src/core/temp.ts index 503fe3faf18..c85264fe281 100644 --- a/src/core/temp.ts +++ b/src/core/temp.ts @@ -27,6 +27,7 @@ export function initSessionTempDir() { ensureDirSync(tmpEnv); } } catch (err) { + if (!(err instanceof Error)) throw err; if (err.message) { debug("Error attempting to create TMPDIR: " + err.message); } diff --git a/src/core/typst.ts b/src/core/typst.ts index 2eb741e1a2f..09e95cab994 100644 --- a/src/core/typst.ts +++ b/src/core/typst.ts @@ -63,7 +63,7 @@ export async function typstCompile( ...fontPathsArgs(fontPaths), output, ); - const result = await execProcess({ cmd }); + const result = await execProcess({ cmd: cmd[0], args: cmd.slice(1) }); if (!quiet && result.success) { typstProgressDone(); } @@ -73,7 +73,12 @@ export async function typstCompile( export async function typstVersion() { const cmd = [typstBinaryPath(), "--version"]; try { - const result = await execProcess({ cmd, stdout: "piped", stderr: "piped" }); + const result = await execProcess({ + cmd: cmd[0], + args: cmd.slice(1), + stdout: "piped", + stderr: "piped", + }); if (result.success && result.stdout) { const match = result.stdout.trim().match(/^typst (\d+\.\d+\.\d+)/); if (match) { diff --git a/src/core/watch.ts b/src/core/watch.ts index 32c27e81b2f..78830cce822 100644 --- a/src/core/watch.ts +++ b/src/core/watch.ts @@ -99,6 +99,7 @@ export function watchForFileChanges( } } } catch (err) { + if (!(err instanceof Error)) throw err; error( "Unexpected error while scanning for file changes: " + err.message, ); diff --git a/src/core/windows.ts b/src/core/windows.ts index 84bafc4c3a1..aed3d21fab8 100644 --- a/src/core/windows.ts +++ b/src/core/windows.ts @@ -38,7 +38,8 @@ export async function readRegistryKey( safeArgs.args, (cmd: string[]) => { return execProcess({ - cmd, + cmd: cmd[0], + args: cmd.slice(1), stdout: "piped", stderr: "piped", }); diff --git a/src/core/xml.ts b/src/core/xml.ts index de12d7faf05..0993c6efa39 100644 --- a/src/core/xml.ts +++ b/src/core/xml.ts @@ -18,8 +18,8 @@ export async function reformat(xmlFile: string) { const xmlLint = await which(kXmlLint); if (xmlLint) { const result = await execProcess({ - cmd: [ - kXmlLint, + cmd: kXmlLint, + args: [ xmlFile, "--format", "-o", diff --git a/src/core/yaml.ts b/src/core/yaml.ts index 837aac8c98d..15b47988915 100644 --- a/src/core/yaml.ts +++ b/src/core/yaml.ts @@ -61,6 +61,7 @@ export function readYaml(file: string) { JSON.stringify(result); return result; } catch (e) { + if (!(e instanceof Error)) throw e; throw new Error( `Circular structures not allowed.\nFile ${file}\n${ e.message.split("\n").slice(1).join("\n") @@ -296,6 +297,9 @@ function parseWithNiceErrors( try { return parse(content, options || { json: true, schema: QuartoJSONSchema }); } catch (e) { + if (!(e instanceof Error)) { + throw e; + } throw improveYamlParseErrorMessage(e); } } diff --git a/src/core/zip.ts b/src/core/zip.ts index 16ba303da74..33cdeeeb5e9 100644 --- a/src/core/zip.ts +++ b/src/core/zip.ts @@ -25,7 +25,8 @@ export function unzip(file: string, dir?: string) { (cmd: string[]) => { return execProcess( { - cmd: cmd, + cmd: cmd[0], + args: cmd.slice(1), stdout: "piped", }, ); @@ -34,13 +35,13 @@ export function unzip(file: string, dir?: string) { } else { // Use the built in unzip command return execProcess( - { cmd: ["unzip", "-o", file], cwd: dir, stdout: "piped" }, + { cmd: "unzip", args: ["-o", file], cwd: dir, stdout: "piped" }, ); } } else { // use the tar command to untar this return execProcess( - { cmd: ["tar", "xfz", file], cwd: dir, stdout: "piped" }, + { cmd: "tar", args: ["xfz", file], cwd: dir, stdout: "piped" }, ); } } @@ -79,8 +80,11 @@ export function zip( ]; } }; + + const cmd = zipCmd(); return execProcess({ - cmd: zipCmd(), + cmd: cmd[0], + args: cmd.slice(1), cwd: options?.cwd, stdout: "piped", stderr: "piped", diff --git a/src/deno_ral/fs.ts b/src/deno_ral/fs.ts index cc1f2c2dee6..534a418f1f5 100644 --- a/src/deno_ral/fs.ts +++ b/src/deno_ral/fs.ts @@ -84,7 +84,9 @@ export function safeMoveSync( ): void { try { Deno.renameSync(src, dest); - } catch (err) { + // deno-lint-ignore no-explicit-any + } catch (err: any) { + // code isn't part of the generic error object, which is why we use `: any` if (err.code !== "EXDEV") { throw err; } diff --git a/src/deno_ral/process.ts b/src/deno_ral/process.ts new file mode 100644 index 00000000000..83fe5067cdd --- /dev/null +++ b/src/deno_ral/process.ts @@ -0,0 +1,10 @@ +/* + * process.ts + * + * Copyright (C) 2025 Posit Software, PBC + */ + +export const call = async (path: string, opts: Deno.CommandOptions = {}) => { + const cmd = new Deno.Command(path, opts); + return cmd.output(); +}; diff --git a/src/execute/engine.ts b/src/execute/engine.ts index 3b8f5d589a3..ba219e2094f 100644 --- a/src/execute/engine.ts +++ b/src/execute/engine.ts @@ -216,6 +216,7 @@ export async function fileExecutionEngine( flags, ); } catch (error) { + if (!(error instanceof Error)) throw error; if (error.name === "YAMLError") { error.message = `${file}:\n${error.message}`; } diff --git a/src/execute/jupyter/jupyter-kernel.ts b/src/execute/jupyter/jupyter-kernel.ts index f980f0039f9..dd864de4e20 100644 --- a/src/execute/jupyter/jupyter-kernel.ts +++ b/src/execute/jupyter/jupyter-kernel.ts @@ -72,12 +72,12 @@ export async function executeKernelKeepalive( options: JupyterExecuteOptions, ): Promise { // if we are in debug mode then tail follow the log file - let serverLogProcess: Deno.Process | undefined; + let serverLogProcess: Deno.ChildProcess | undefined; if (options.format.execute[kExecuteDebug]) { if (!isWindows) { - serverLogProcess = Deno.run({ - cmd: ["tail", "-F", "-n", "0", kernelLogFile()], - }); + serverLogProcess = new Deno.Command("tail", { + args: ["-F", "-n", "0", kernelLogFile()], + }).spawn(); } } @@ -156,10 +156,7 @@ export async function executeKernelKeepalive( } finally { conn.close(); - if (serverLogProcess) { - // deno-lint-ignore no-explicit-any - (serverLogProcess as any).kill("SIGKILL"); - } + serverLogProcess?.kill("SIGKILL"); } } @@ -191,10 +188,12 @@ async function execJupyter( kernelspec: JupyterKernelspec, ): Promise { try { + const cmd = await pythonExec(kernelspec); const result = await execProcess( { - cmd: [ - ...(await pythonExec(kernelspec)), + cmd: cmd[0], + args: [ + ...cmd.slice(1), resourcePath("jupyter/jupyter.py"), ], env: { @@ -218,6 +217,7 @@ async function execJupyter( } return result; } catch (e) { + if (!(e instanceof Error)) throw e; if (e?.message) { info(""); error(e.message); @@ -358,6 +358,7 @@ function readKernelTransportFile( throw new Error("Invalid file format"); } } catch (e) { + if (!(e instanceof Error)) throw e; error( "Error reading kernel transport file: " + e.toString() + "(removing file)", @@ -454,6 +455,7 @@ async function connectToKernel( try { return await denoConnectToKernel(kernelTransport); } catch (e) { + if (!(e instanceof Error)) throw e; // remove the transport file safeRemoveSync(transportFile); error("Error connecting to Jupyter kernel: " + e.toString()); diff --git a/src/execute/ojs/extract-resources.ts b/src/execute/ojs/extract-resources.ts index 441e9149e8b..9bacb1a89d3 100644 --- a/src/execute/ojs/extract-resources.ts +++ b/src/execute/ojs/extract-resources.ts @@ -335,9 +335,8 @@ async function resolveImport( projectRoot = projectRoot ?? dirname(referent); const deno = Deno.execPath(); - const p = Deno.run({ - cmd: [ - deno, + const p = new Deno.Command(deno, { + args: [ "check", file, "-c", @@ -346,8 +345,9 @@ async function resolveImport( ], stderr: "piped", }); - const [status, stderr] = await Promise.all([p.status(), p.stderrOutput()]); - if (!status.success) { + const output = await p.output(); + const stderr = output.stderr; + if (!output.success) { error("Compilation of typescript dependencies in ojs cell failed."); let errStr = new TextDecoder().decode(stderr); @@ -547,7 +547,7 @@ export async function extractResourceDescriptionsFromOJSChunk( const [thisResolvedImportPath, importResource]: [ string, ResourceDescription, - ] = imports.entries().next().value; + ] = imports.entries().next().value!; imports.delete(thisResolvedImportPath); if (handled.has(thisResolvedImportPath)) { continue; @@ -580,6 +580,7 @@ export async function extractResourceDescriptionsFromOJSChunk( try { safeRemoveSync(res.filename); } catch (e) { + if (!(e instanceof Error)) throw e; if (e.name !== "NotFound") { throw e; } diff --git a/src/execute/rmd.ts b/src/execute/rmd.ts index 97b747a5b0d..0ee1b46c3fa 100644 --- a/src/execute/rmd.ts +++ b/src/execute/rmd.ts @@ -97,6 +97,7 @@ export const knitrEngine: ExecutionEngine = { try { metadata = readYamlFromMarkdown(markdown.value); } catch (e) { + if (!(e instanceof Error)) throw e; error(`Error reading metadata from ${file}.\n${e.message}`); throw e; } @@ -282,8 +283,8 @@ async function callR( try { const result = await execProcess( { - cmd: [ - await rBinaryPath("Rscript"), + cmd: await rBinaryPath("Rscript"), + args: [ ...rscriptArgsArray, resourcePath("rmd/rmd.R"), ], @@ -317,6 +318,9 @@ async function callR( return Promise.reject(); } } catch (e) { + if (!(e instanceof Error)) { + throw e; + } if (reportError) { if (e?.message) { info(""); diff --git a/src/extension/extension-host.ts b/src/extension/extension-host.ts index eb7920afde3..63d4723f716 100644 --- a/src/extension/extension-host.ts +++ b/src/extension/extension-host.ts @@ -62,6 +62,9 @@ export async function extensionSource( }; } } catch (err) { + if (!(err instanceof Error)) { + throw err; + } err.message = `A network error occurred when attempting to inspect the extension '${target}'. Please try again.\n\n` + err.message; diff --git a/src/format/reveal/format-reveal-multiplex.ts b/src/format/reveal/format-reveal-multiplex.ts index af9bd12bbf9..e057d4feff8 100644 --- a/src/format/reveal/format-reveal-multiplex.ts +++ b/src/format/reveal/format-reveal-multiplex.ts @@ -159,6 +159,9 @@ async function revealMultiplexToken( }; return multiplex; } catch (e) { + if (!(e instanceof Error)) { + throw e; + } throw Error( "Error attempting to provision multiplex token from '" + url + "': " + e.message, diff --git a/src/preview/preview-server.ts b/src/preview/preview-server.ts index 4490852ede5..7deabc29553 100644 --- a/src/preview/preview-server.ts +++ b/src/preview/preview-server.ts @@ -5,7 +5,6 @@ */ import { MuxAsyncIterator } from "async/mux-async-iterator"; -import { iterateReader } from "io/iterate-reader"; import { isWindows } from "../deno_ral/platform.ts"; export interface PreviewServer { @@ -34,19 +33,23 @@ export function runExternalPreviewServer(options: { env?: { [key: string]: string }; cwd?: string; }): PreviewServer { + const { cmd } = options; // start the process - const process = Deno.run({ + const denoCommand = new Deno.Command(cmd[0], { + args: cmd.slice(1), ...options, stdout: "piped", stderr: "piped", }); + const process = denoCommand.spawn(); + // merge and stream stdout and stderr const multiplexIterator = new MuxAsyncIterator< Uint8Array >(); - multiplexIterator.add(iterateReader(process.stdout)); - multiplexIterator.add(iterateReader(process.stderr)); + multiplexIterator.add(process.stdout); + multiplexIterator.add(process.stderr); // wait for ready and then return from 'start' const decoder = new TextDecoder(); @@ -65,7 +68,7 @@ export function runExternalPreviewServer(options: { for await (const chunk of multiplexIterator) { Deno.stderr.writeSync(chunk); } - await process.status(); + await process.output(); }, stop: () => { if (!isWindows) { @@ -73,7 +76,6 @@ export function runExternalPreviewServer(options: { } else { process.kill(); } - process.close(); return Promise.resolve(); }, }; diff --git a/src/preview/preview-text.ts b/src/preview/preview-text.ts index a0820e58f8f..5a1bea0d63b 100644 --- a/src/preview/preview-text.ts +++ b/src/preview/preview-text.ts @@ -155,7 +155,8 @@ async function textPreviewHtml(file: string, req: Request) { ); cmd.push("--standalone"); const result = await execProcess({ - cmd, + cmd: cmd[0], + args: cmd.slice(1), stdout: "piped", }, markdown); if (result.success) { @@ -244,7 +245,7 @@ async function gfmPreview(file: string, request: Request) { // Github renders math with MathJax now, so our preview mode does the same cmd.push("--mathjax"); const result = await execProcess( - { cmd, stdout: "piped", stderr: "piped" }, + { cmd: cmd[0], args: cmd.slice(1), stdout: "piped", stderr: "piped" }, Deno.readTextFileSync(file), ); if (result.success) { diff --git a/src/project/project-gitignore.ts b/src/project/project-gitignore.ts index 4def51fce6e..ef781ab7fbd 100644 --- a/src/project/project-gitignore.ts +++ b/src/project/project-gitignore.ts @@ -55,7 +55,8 @@ export async function ensureGitignore( } else if (await which("git")) { // if it doesn't exist then auto-create if we are in a git project or we had the force flag const result = await execProcess({ - cmd: ["git", "rev-parse"], + cmd: "git", + args: ["rev-parse"], cwd: dir, stdout: "piped", stderr: "piped", diff --git a/src/project/serve/serve.ts b/src/project/serve/serve.ts index f4a6479688c..81d44d9b8c8 100644 --- a/src/project/serve/serve.ts +++ b/src/project/serve/serve.ts @@ -403,7 +403,7 @@ function externalPreviewServer( ): Promise { // run a control channel server for handling render requests // if there was a renderToken() passed - let controlListener: Deno.Listener | undefined; + let stop: () => void | undefined; if (renderToken()) { const outputDir = projectOutputDir(project); const handlerOptions: HttpFileRequestOptions = { @@ -425,12 +425,12 @@ function externalPreviewServer( const handler = httpFileRequestHandler(handlerOptions); const port = findOpenPort(); - controlListener = Deno.listen({ port, hostname: kLocalhost }); - handleHttpRequests(controlListener, handler).then(() => { - // terminanted - }).catch((_error) => { - // ignore errors - }); + ({ stop } = handleHttpRequests({ + port, + hostname: kLocalhost, + handler, + })); + // .abortController; info(`Preview service running (${port})`); } @@ -467,9 +467,7 @@ function externalPreviewServer( return server.serve(); }, stop: () => { - if (controlListener) { - controlListener.close(); - } + stop?.(); return server.stop(); }, }); @@ -647,6 +645,7 @@ async function internalPreviewServer( ); } } catch (e) { + if (!(e instanceof Error)) throw e; logError(e); renderError = e; } finally { @@ -771,15 +770,21 @@ async function internalPreviewServer( const path = (targetPath && targetPath !== "index.html") ? targetPath : ""; // start listening - const listener = Deno.listen({ port: options.port!, hostname: options.host }); + let stop: () => void | undefined; return { start: () => Promise.resolve(path), serve: async () => { - await handleHttpRequests(listener, handler); + const { server, stop: stopServer } = handleHttpRequests({ + port: options.port!, + hostname: options.host, + handler, + }); + stop = stopServer; + await server.finished; }, stop: () => { - listener.close(); + stop?.(); return Promise.resolve(); }, }; diff --git a/src/project/types/book/book-bibliography.ts b/src/project/types/book/book-bibliography.ts index 0c29281cfaa..9bc851f4e03 100644 --- a/src/project/types/book/book-bibliography.ts +++ b/src/project/types/book/book-bibliography.ts @@ -278,8 +278,8 @@ export async function generateBibliography( } const frontMatter = `---\n${stringify(yaml, { indent: 2 })}\n---\n`; const result = await execProcess({ - cmd: [ - pandocBinaryPath(), + cmd: pandocBinaryPath(), + args: [ "--from", "markdown", "--to", diff --git a/src/project/types/book/book-render.ts b/src/project/types/book/book-render.ts index d78d01e6683..f38e27b74ce 100644 --- a/src/project/types/book/book-render.ts +++ b/src/project/types/book/book-render.ts @@ -37,6 +37,7 @@ import { isHtmlOutput } from "../../../config/format.ts"; import { renderPandoc } from "../../../command/render/render.ts"; import { PandocRenderCompletion, + PandocRenderer, RenderFile, } from "../../../command/render/types.ts"; @@ -97,7 +98,7 @@ import { safeCloneDeep } from "../../../core/safe-clone-deep.ts"; export function bookPandocRenderer( options: RenderOptions, project: ProjectContext, -) { +): PandocRenderer { // rendered files to return. some formats need to end up returning all of the individual // renderedFiles (e.g. html or asciidoc) and some formats will consolidate all of their // files into a single one (e.g. pdf or epub) @@ -310,6 +311,9 @@ export function bookPandocRenderer( files: renderedFiles, }; } catch (error) { + if (!(error instanceof Error)) { + throw error; + } cleanupExecutedFiles(); return { files: renderedFiles, diff --git a/src/project/types/website/listing/website-listing-feed.ts b/src/project/types/website/listing/website-listing-feed.ts index d2812c215f0..53608de9d06 100644 --- a/src/project/types/website/listing/website-listing-feed.ts +++ b/src/project/types/website/listing/website-listing-feed.ts @@ -370,6 +370,9 @@ export function completeStagedFeeds( feedContents, ); } catch (error) { + if (!(error instanceof Error)) { + throw error; + } const errorMessage = error.message; warnOnce( `Unable to generate feed '${feedStem}.xml'\n${errorMessage}`, diff --git a/src/publish/confluence/api/index.ts b/src/publish/confluence/api/index.ts index 7b4015930c6..065033967d3 100644 --- a/src/publish/confluence/api/index.ts +++ b/src/publish/confluence/api/index.ts @@ -152,6 +152,9 @@ export class ConfluenceClient { `content/${testContentId}/restriction/byOperation/update/user?accountId=${user.accountId}`, ); } catch (error) { + if (!(error instanceof ApiError)) { + throw error; + } trace("lockDownResult Error", error); // Note, sometimes a successful call throws a // "SyntaxError: Unexpected end of JSON input" @@ -170,6 +173,9 @@ export class ConfluenceClient { try { await this.deleteContent(contentDelete); } catch (error) { + if (!(error instanceof ApiError)) { + throw error; + } trace("delete canSetPermissions Test Error", error); if (error?.status === 403) { //Delete is disabled for this user, attempt an archive diff --git a/src/publish/confluence/confluence-helper.ts b/src/publish/confluence/confluence-helper.ts index ca41b125156..b8b858ac856 100644 --- a/src/publish/confluence/confluence-helper.ts +++ b/src/publish/confluence/confluence-helper.ts @@ -301,8 +301,8 @@ export const findPagesToDelete = ( if ( !fileMetadataList.find( (file) => - pathWithForwardSlashes(file.fileName) === page?.metadata?.fileName ?? - "", + pathWithForwardSlashes(file.fileName) === + (page?.metadata?.fileName ?? ""), ) && !isActiveParent(page.id) ) { @@ -844,8 +844,10 @@ export const findAttachments = ( const pathList = filePath.split("/"); const parentPath = pathList.slice(0, pathList.length - 1).join("/"); - const imageFinderMatches:RegExpMatchArray | null = bodyValue.match(ATTACHMENT_FINDER); - let uniqueFoundImages:string[] = [...new Set(imageFinderMatches)]; + const imageFinderMatches: RegExpMatchArray | null = bodyValue.match( + ATTACHMENT_FINDER, + ); + let uniqueFoundImages: string[] = [...new Set(imageFinderMatches)]; if (publishFiles.length > 0) { uniqueFoundImages = uniqueFoundImages.map((assetFileName: string) => { diff --git a/src/publish/gh-pages/gh-pages.ts b/src/publish/gh-pages/gh-pages.ts index 019faf8ab9d..3da6209027b 100644 --- a/src/publish/gh-pages/gh-pages.ts +++ b/src/publish/gh-pages/gh-pages.ts @@ -210,7 +210,8 @@ async function publish( ); const worktreePath = join(projectScratchPath(input), entry.name); await execProcess({ - cmd: ["git", "worktree", "remove", worktreePath], + cmd: "git", + args: ["worktree", "remove", worktreePath], cwd: projectScratchPath(input), }); removeIfExists(worktreePath); @@ -343,7 +344,8 @@ function isNotFound(_err: Error) { async function gitStash(dir: string) { const result = await execProcess({ - cmd: ["git", "stash"], + cmd: "git", + args: ["stash"], cwd: dir, }); if (!result.success) { @@ -353,7 +355,8 @@ async function gitStash(dir: string) { async function gitStashApply(dir: string) { const result = await execProcess({ - cmd: ["git", "stash", "apply"], + cmd: "git", + args: ["stash", "apply"], cwd: dir, }); if (!result.success) { @@ -363,7 +366,8 @@ async function gitStashApply(dir: string) { async function gitDirIsClean(dir: string) { const result = await execProcess({ - cmd: ["git", "diff", "HEAD"], + cmd: "git", + args: ["diff", "HEAD"], cwd: dir, stdout: "piped", }); @@ -376,7 +380,8 @@ async function gitDirIsClean(dir: string) { async function gitCurrentBranch(dir: string) { const result = await execProcess({ - cmd: ["git", "rev-parse", "--abbrev-ref", "HEAD"], + cmd: "git", + args: ["rev-parse", "--abbrev-ref", "HEAD"], cwd: dir, stdout: "piped", }); @@ -393,8 +398,8 @@ async function withWorktree( f: () => Promise, ) { await execProcess({ - cmd: [ - "git", + cmd: "git", + args: [ "worktree", "add", "--track", @@ -408,7 +413,8 @@ async function withWorktree( // remove files in existing site, i.e. start clean await execProcess({ - cmd: ["git", "rm", "-r", "--quiet", "."], + cmd: "git", + args: ["rm", "-r", "--quiet", "."], cwd: join(dir, siteDir), }); @@ -416,7 +422,8 @@ async function withWorktree( await f(); } finally { await execProcess({ - cmd: ["git", "worktree", "remove", siteDir], + cmd: "git", + args: ["worktree", "remove", siteDir], cwd: dir, }); } diff --git a/src/publish/posit-cloud/posit-cloud.ts b/src/publish/posit-cloud/posit-cloud.ts index f756131f855..af74f372594 100644 --- a/src/publish/posit-cloud/posit-cloud.ts +++ b/src/publish/posit-cloud/posit-cloud.ts @@ -165,6 +165,9 @@ async function authorizeToken( token: tokenAndSecret, }; } catch (err) { + if (!(err instanceof Error)) { + throw err; + } if (isUnauthorized(err)) { promptError( "Credential is unauthorized.", diff --git a/src/publish/rsconnect/rsconnect.ts b/src/publish/rsconnect/rsconnect.ts index 53c015883d7..d511c1cdb5a 100644 --- a/src/publish/rsconnect/rsconnect.ts +++ b/src/publish/rsconnect/rsconnect.ts @@ -139,6 +139,9 @@ async function authorizeToken( try { await client.getUser(); } catch (err) { + if (!(err instanceof Error)) { + throw err; + } // connect server will give 401 for unauthorized, break out // of the loop in that case if (isUnauthorized(err)) { @@ -193,6 +196,9 @@ async function authorizeToken( ); } } catch (err) { + if (!(err instanceof Error)) { + throw err; + } if (isUnauthorized(err)) { promptError( "API key is not authorized for this Posit Connect server.", @@ -314,6 +320,9 @@ async function createContent( try { return await client.createContent(name, title); } catch (err) { + if (!(err instanceof Error)) { + throw err; + } if (!isConflict(err)) { throw err; } diff --git a/src/quarto.ts b/src/quarto.ts index bd9aea689a5..8a7bbd27568 100644 --- a/src/quarto.ts +++ b/src/quarto.ts @@ -83,7 +83,8 @@ const passThroughPandoc = async ( ) => { const result = await execProcess( { - cmd: [pandocBinaryPath(), ...args.slice(1)], + cmd: pandocBinaryPath(), + args: args.slice(1), env, }, undefined, @@ -106,7 +107,8 @@ const passThroughTypst = async ( Deno.exit(1); } const result = await execProcess({ - cmd: [typstBinaryPath(), ...args.slice(1)], + cmd: typstBinaryPath(), + args: args.slice(1), env, }); Deno.exit(result.code); diff --git a/src/resources/editor/tools/vs-code.mjs b/src/resources/editor/tools/vs-code.mjs index 2e863660b82..bb843786749 100644 --- a/src/resources/editor/tools/vs-code.mjs +++ b/src/resources/editor/tools/vs-code.mjs @@ -23719,14 +23719,6 @@ var require_yaml_intelligence_resources = __commonJS({ "Manuscript configuration", "internal-schema-hack", "List execution engines you want to give priority when determining\nwhich engine should render a notebook. If two engines have support for a\nnotebook, the one listed earlier will be chosen. Quarto\u2019s default order\nis \u2018knitr\u2019, \u2018jupyter\u2019, \u2018markdown\u2019, \u2018julia\u2019.", - { - short: "Include an automatically generated table of contents", - long: "" - }, - { - short: "Use smart quotes in document output. Defaults to true.", - long: "" - }, "Project configuration.", "Project type (default, website,\nbook, or manuscript)", "Files to render (defaults to all files)", @@ -24370,12 +24362,12 @@ var require_yaml_intelligence_resources = __commonJS({ mermaid: "%%" }, "handlers/mermaid/schema.yml": { - _internalId: 194571, + _internalId: 193837, type: "object", description: "be an object", properties: { "mermaid-format": { - _internalId: 194563, + _internalId: 193829, type: "enum", enum: [ "png", @@ -24391,7 +24383,7 @@ var require_yaml_intelligence_resources = __commonJS({ exhaustiveCompletions: true }, theme: { - _internalId: 194570, + _internalId: 193836, type: "anyOf", anyOf: [ { @@ -24431,42 +24423,7 @@ var require_yaml_intelligence_resources = __commonJS({ "case-detection": true }, $id: "handlers/mermaid" - }, - "schema/document-typst.yml": [ - { - name: "page-numbering", - tags: { - formats: [ - "typst" - ] - }, - schema: { - anyOf: [ - "string", - { - enum: [ - false - ] - } - ] - }, - description: { - short: "Include an automatically generated table of contents" - } - }, - { - name: "smart", - tags: { - formats: [ - "typst" - ] - }, - schema: "boolean", - description: { - short: "Use smart quotes in document output. Defaults to true." - } - } - ] + } }; } }); @@ -24951,8 +24908,7 @@ function mappedConcat(strings) { const mappedStrings = strings.map((s) => { if (typeof s === "string") { return asMappedString(s); - } else - return s; + } else return s; }); let currentOffset = 0; const offsets = [0]; @@ -25191,10 +25147,8 @@ function isObject(subject) { return typeof subject === "object" && subject !== null; } function toArray(sequence) { - if (Array.isArray(sequence)) - return sequence; - else if (isNothing(sequence)) - return []; + if (Array.isArray(sequence)) return sequence; + else if (isNothing(sequence)) return []; return [sequence]; } function extend(target, source) { @@ -25234,8 +25188,7 @@ var common = { }; function formatError(exception2, compact) { var where = "", message = exception2.reason || "(unknown reason)"; - if (!exception2.mark) - return message; + if (!exception2.mark) return message; if (exception2.mark.name) { where += 'in "' + exception2.mark.name + '" '; } @@ -25285,16 +25238,11 @@ function padStart(string, max) { } function makeSnippet(mark, options) { options = Object.create(options || null); - if (!mark.buffer) - return null; - if (!options.maxLength) - options.maxLength = 79; - if (typeof options.indent !== "number") - options.indent = 1; - if (typeof options.linesBefore !== "number") - options.linesBefore = 3; - if (typeof options.linesAfter !== "number") - options.linesAfter = 2; + if (!mark.buffer) return null; + if (!options.maxLength) options.maxLength = 79; + if (typeof options.indent !== "number") options.indent = 1; + if (typeof options.linesBefore !== "number") options.linesBefore = 3; + if (typeof options.linesAfter !== "number") options.linesAfter = 2; var re = /\r?\n|\r|\0/g; var lineStarts = [0]; var lineEnds = []; @@ -25307,8 +25255,7 @@ function makeSnippet(mark, options) { foundLineNo = lineStarts.length - 2; } } - if (foundLineNo < 0) - foundLineNo = lineStarts.length - 1; + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; var result = "", i, line; var lineNoLength = Math.min( mark.line + options.linesAfter, @@ -25316,8 +25263,7 @@ function makeSnippet(mark, options) { ).toString().length; var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); for (i = 1; i <= options.linesBefore; i++) { - if (foundLineNo - i < 0) - break; + if (foundLineNo - i < 0) break; line = getLine( mark.buffer, lineStarts[foundLineNo - i], @@ -25337,8 +25283,7 @@ function makeSnippet(mark, options) { result += common.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n"; result += common.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n"; for (i = 1; i <= options.linesAfter; i++) { - if (foundLineNo + i >= lineEnds.length) - break; + if (foundLineNo + i >= lineEnds.length) break; line = getLine( mark.buffer, lineStarts[foundLineNo + i], @@ -25457,10 +25402,8 @@ Schema$1.prototype.extend = function extend2(definition) { } else if (Array.isArray(definition)) { explicit = explicit.concat(definition); } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { - if (definition.implicit) - implicit = implicit.concat(definition.implicit); - if (definition.explicit) - explicit = explicit.concat(definition.explicit); + if (definition.implicit) implicit = implicit.concat(definition.implicit); + if (definition.explicit) explicit = explicit.concat(definition.explicit); } else { throw new exception( "Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })" @@ -25524,8 +25467,7 @@ var failsafe = new schema({ explicit: [str, seq, map] }); function resolveYamlNull(data) { - if (data === null) - return true; + if (data === null) return true; var max = data.length; return max === 1 && data === "~" || max === 4 && (data === "null" || data === "Null" || data === "NULL"); } @@ -25560,8 +25502,7 @@ var _null = new type("tag:yaml.org,2002:null", { defaultStyle: "lowercase" }); function resolveYamlBoolean(data) { - if (data === null) - return false; + if (data === null) return false; var max = data.length; return max === 4 && (data === "true" || data === "True" || data === "TRUE") || max === 5 && (data === "false" || data === "False" || data === "FALSE"); } @@ -25599,27 +25540,22 @@ function isDecCode(c) { return 48 <= c && c <= 57; } function resolveYamlInteger(data) { - if (data === null) - return false; + if (data === null) return false; var max = data.length, index = 0, hasDigits = false, ch; - if (!max) - return false; + if (!max) return false; ch = data[index]; if (ch === "-" || ch === "+") { ch = data[++index]; } if (ch === "0") { - if (index + 1 === max) - return true; + if (index + 1 === max) return true; ch = data[++index]; if (ch === "b") { index++; for (; index < max; index++) { ch = data[index]; - if (ch === "_") - continue; - if (ch !== "0" && ch !== "1") - return false; + if (ch === "_") continue; + if (ch !== "0" && ch !== "1") return false; hasDigits = true; } return hasDigits && ch !== "_"; @@ -25628,10 +25564,8 @@ function resolveYamlInteger(data) { index++; for (; index < max; index++) { ch = data[index]; - if (ch === "_") - continue; - if (!isHexCode(data.charCodeAt(index))) - return false; + if (ch === "_") continue; + if (!isHexCode(data.charCodeAt(index))) return false; hasDigits = true; } return hasDigits && ch !== "_"; @@ -25640,28 +25574,23 @@ function resolveYamlInteger(data) { index++; for (; index < max; index++) { ch = data[index]; - if (ch === "_") - continue; - if (!isOctCode(data.charCodeAt(index))) - return false; + if (ch === "_") continue; + if (!isOctCode(data.charCodeAt(index))) return false; hasDigits = true; } return hasDigits && ch !== "_"; } } - if (ch === "_") - return false; + if (ch === "_") return false; for (; index < max; index++) { ch = data[index]; - if (ch === "_") - continue; + if (ch === "_") continue; if (!isDecCode(data.charCodeAt(index))) { return false; } hasDigits = true; } - if (!hasDigits || ch === "_") - return false; + if (!hasDigits || ch === "_") return false; return true; } function constructYamlInteger(data) { @@ -25671,20 +25600,15 @@ function constructYamlInteger(data) { } ch = value[0]; if (ch === "-" || ch === "+") { - if (ch === "-") - sign = -1; + if (ch === "-") sign = -1; value = value.slice(1); ch = value[0]; } - if (value === "0") - return 0; + if (value === "0") return 0; if (ch === "0") { - if (value[1] === "b") - return sign * parseInt(value.slice(2), 2); - if (value[1] === "x") - return sign * parseInt(value.slice(2), 16); - if (value[1] === "o") - return sign * parseInt(value.slice(2), 8); + if (value[1] === "b") return sign * parseInt(value.slice(2), 2); + if (value[1] === "x") return sign * parseInt(value.slice(2), 16); + if (value[1] === "o") return sign * parseInt(value.slice(2), 8); } return sign * parseInt(value, 10); } @@ -25722,8 +25646,7 @@ var YAML_FLOAT_PATTERN = new RegExp( "^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$" ); function resolveYamlFloat(data) { - if (data === null) - return false; + if (data === null) return false; if (!YAML_FLOAT_PATTERN.test(data) || data[data.length - 1] === "_") { return false; } @@ -25801,21 +25724,16 @@ var YAML_TIMESTAMP_REGEXP = new RegExp( "^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$" ); function resolveYamlTimestamp(data) { - if (data === null) - return false; - if (YAML_DATE_REGEXP.exec(data) !== null) - return true; - if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) - return true; + if (data === null) return false; + if (YAML_DATE_REGEXP.exec(data) !== null) return true; + if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true; return false; } function constructYamlTimestamp(data) { var match, year, month, day, hour, minute, second, fraction = 0, delta = null, tz_hour, tz_minute, date; match = YAML_DATE_REGEXP.exec(data); - if (match === null) - match = YAML_TIMESTAMP_REGEXP.exec(data); - if (match === null) - throw new Error("Date resolve error"); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data); + if (match === null) throw new Error("Date resolve error"); year = +match[1]; month = +match[2] - 1; day = +match[3]; @@ -25836,12 +25754,10 @@ function constructYamlTimestamp(data) { tz_hour = +match[10]; tz_minute = +(match[11] || 0); delta = (tz_hour * 60 + tz_minute) * 6e4; - if (match[9] === "-") - delta = -delta; + if (match[9] === "-") delta = -delta; } date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); - if (delta) - date.setTime(date.getTime() - delta); + if (delta) date.setTime(date.getTime() - delta); return date; } function representYamlTimestamp(object) { @@ -25863,15 +25779,12 @@ var merge = new type("tag:yaml.org,2002:merge", { }); var BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r"; function resolveYamlBinary(data) { - if (data === null) - return false; + if (data === null) return false; var code2, idx, bitlen = 0, max = data.length, map2 = BASE64_MAP; for (idx = 0; idx < max; idx++) { code2 = map2.indexOf(data.charAt(idx)); - if (code2 > 64) - continue; - if (code2 < 0) - return false; + if (code2 > 64) continue; + if (code2 < 0) return false; bitlen += 6; } return bitlen % 8 === 0; @@ -25942,28 +25855,21 @@ var binary = new type("tag:yaml.org,2002:binary", { var _hasOwnProperty$3 = Object.prototype.hasOwnProperty; var _toString$2 = Object.prototype.toString; function resolveYamlOmap(data) { - if (data === null) - return true; + if (data === null) return true; var objectKeys = [], index, length, pair, pairKey, pairHasKey, object = data; for (index = 0, length = object.length; index < length; index += 1) { pair = object[index]; pairHasKey = false; - if (_toString$2.call(pair) !== "[object Object]") - return false; + if (_toString$2.call(pair) !== "[object Object]") return false; for (pairKey in pair) { if (_hasOwnProperty$3.call(pair, pairKey)) { - if (!pairHasKey) - pairHasKey = true; - else - return false; + if (!pairHasKey) pairHasKey = true; + else return false; } } - if (!pairHasKey) - return false; - if (objectKeys.indexOf(pairKey) === -1) - objectKeys.push(pairKey); - else - return false; + if (!pairHasKey) return false; + if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey); + else return false; } return true; } @@ -25977,24 +25883,20 @@ var omap = new type("tag:yaml.org,2002:omap", { }); var _toString$1 = Object.prototype.toString; function resolveYamlPairs(data) { - if (data === null) - return true; + if (data === null) return true; var index, length, pair, keys, result, object = data; result = new Array(object.length); for (index = 0, length = object.length; index < length; index += 1) { pair = object[index]; - if (_toString$1.call(pair) !== "[object Object]") - return false; + if (_toString$1.call(pair) !== "[object Object]") return false; keys = Object.keys(pair); - if (keys.length !== 1) - return false; + if (keys.length !== 1) return false; result[index] = [keys[0], pair[keys[0]]]; } return true; } function constructYamlPairs(data) { - if (data === null) - return []; + if (data === null) return []; var index, length, pair, keys, result, object = data; result = new Array(object.length); for (index = 0, length = object.length; index < length; index += 1) { @@ -26011,13 +25913,11 @@ var pairs = new type("tag:yaml.org,2002:pairs", { }); var _hasOwnProperty$2 = Object.prototype.hasOwnProperty; function resolveYamlSet(data) { - if (data === null) - return true; + if (data === null) return true; var key, object = data; for (key in object) { if (_hasOwnProperty$2.call(object, key)) { - if (object[key] !== null) - return false; + if (object[key] !== null) return false; } } return true; @@ -26727,8 +26627,7 @@ function readBlockScalar(state, nodeIndent) { } function readBlockSequence(state, nodeIndent) { var _line, _tag = state.tag, _anchor = state.anchor, _result = [], following, detected = false, ch; - if (state.firstTabInLine !== -1) - return false; + if (state.firstTabInLine !== -1) return false; if (state.anchor !== null) { state.anchorMap[state.anchor] = _result; } @@ -26776,8 +26675,7 @@ function readBlockSequence(state, nodeIndent) { } function readBlockMapping(state, nodeIndent, flowIndent) { var following, allowCompact, _line, _keyLine, _keyLineStart, _keyPos, _tag = state.tag, _anchor = state.anchor, _result = {}, overridableKeys = /* @__PURE__ */ Object.create(null), keyTag = null, keyNode = null, valueNode = null, atExplicitKey = false, detected = false, ch; - if (state.firstTabInLine !== -1) - return false; + if (state.firstTabInLine !== -1) return false; if (state.anchor !== null) { state.anchorMap[state.anchor] = _result; } @@ -26939,8 +26837,7 @@ function readBlockMapping(state, nodeIndent, flowIndent) { function readTagProperty(state) { var _position, isVerbatim = false, isNamed = false, tagHandle, tagName, ch; ch = state.input.charCodeAt(state.position); - if (ch !== 33) - return false; + if (ch !== 33) return false; if (state.tag !== null) { throwError(state, "duplication of a tag property"); } @@ -27014,8 +26911,7 @@ function readTagProperty(state) { function readAnchorProperty(state) { var _position, ch; ch = state.input.charCodeAt(state.position); - if (ch !== 38) - return false; + if (ch !== 38) return false; if (state.anchor !== null) { throwError(state, "duplication of an anchor property"); } @@ -27036,8 +26932,7 @@ function readAnchorProperty(state) { function readAlias(state) { var _position, alias, ch; ch = state.input.charCodeAt(state.position); - if (ch !== 42) - return false; + if (ch !== 42) return false; ch = state.input.charCodeAt(++state.position); _position = state.position; while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { @@ -27228,16 +27123,14 @@ function readDocument(state) { } while (ch !== 0 && !is_EOL(ch)); break; } - if (is_EOL(ch)) - break; + if (is_EOL(ch)) break; _position = state.position; while (ch !== 0 && !is_WS_OR_EOL(ch)) { ch = state.input.charCodeAt(++state.position); } directiveArgs.push(state.input.slice(_position, state.position)); } - if (ch !== 0) - readLineBreak(state); + if (ch !== 0) readLineBreak(state); if (_hasOwnProperty$1.call(directiveHandlers, directiveName)) { directiveHandlers[directiveName](state, directiveName, directiveArgs); } else { @@ -27393,8 +27286,7 @@ var DEPRECATED_BOOLEANS_SYNTAX = [ var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; function compileStyleMap(schema2, map2) { var result, keys, index, length, tag, style, type2; - if (map2 === null) - return {}; + if (map2 === null) return {}; result = {}; keys = Object.keys(map2); for (index = 0, length = keys.length; index < length; index += 1) { @@ -27465,8 +27357,7 @@ function indentString(string, spaces) { line = string.slice(position, next + 1); position = next + 1; } - if (line.length && line !== "\n") - result += ind; + if (line.length && line !== "\n") result += ind; result += line; } return result; @@ -27643,8 +27534,7 @@ function foldString(string, width) { return result; } function foldLine(line, width) { - if (line === "" || line[0] === " ") - return line; + if (line === "" || line[0] === " ") return line; var breakRe = / [^ ]/g; var match; var start = 0, end, curr = 0, next = 0; @@ -27675,8 +27565,7 @@ function escapeString(string) { escapeSeq = ESCAPE_SEQUENCES[char]; if (!escapeSeq && isPrintable(char)) { result += string[i]; - if (char >= 65536) - result += string[i + 1]; + if (char >= 65536) result += string[i + 1]; } else { result += escapeSeq || encodeHex(char); } @@ -27691,8 +27580,7 @@ function writeFlowSequence(state, level, object) { value = state.replacer.call(object, String(index), value); } if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) { - if (_result !== "") - _result += "," + (!state.condenseFlow ? " " : ""); + if (_result !== "") _result += "," + (!state.condenseFlow ? " " : ""); _result += state.dump; } } @@ -27725,10 +27613,8 @@ function writeFlowMapping(state, level, object) { var _result = "", _tag = state.tag, objectKeyList = Object.keys(object), index, length, objectKey, objectValue, pairBuffer; for (index = 0, length = objectKeyList.length; index < length; index += 1) { pairBuffer = ""; - if (_result !== "") - pairBuffer += ", "; - if (state.condenseFlow) - pairBuffer += '"'; + if (_result !== "") pairBuffer += ", "; + if (state.condenseFlow) pairBuffer += '"'; objectKey = objectKeyList[index]; objectValue = object[objectKey]; if (state.replacer) { @@ -27737,8 +27623,7 @@ function writeFlowMapping(state, level, object) { if (!writeNode(state, level, objectKey, false, false)) { continue; } - if (state.dump.length > 1024) - pairBuffer += "? "; + if (state.dump.length > 1024) pairBuffer += "? "; pairBuffer += state.dump + (state.condenseFlow ? '"' : "") + ":" + (state.condenseFlow ? "" : " "); if (!writeNode(state, level, objectValue, false, false)) { continue; @@ -27891,8 +27776,7 @@ function writeNode(state, level, object, block, compact, iskey, isblockseq) { } else if (type2 === "[object Undefined]") { return false; } else { - if (state.skipInvalid) - return false; + if (state.skipInvalid) return false; throw new exception("unacceptable kind of an object to dump " + type2); } if (state.tag !== null && state.tag !== "?") { @@ -27945,14 +27829,12 @@ function inspectNode(object, objects, duplicatesIndexes) { function dump$1(input, options) { options = options || {}; var state = new State(options); - if (!state.noRefs) - getDuplicateReferences(input, state); + if (!state.noRefs) getDuplicateReferences(input, state); var value = input; if (state.replacer) { value = state.replacer.call({ "": value }, "", value); } - if (writeNode(state, 0, value, true, true)) - return state.dump + "\n"; + if (writeNode(state, 0, value, true, true)) return state.dump + "\n"; return ""; } var dump_1 = dump$1; @@ -31389,6 +31271,7 @@ function locateCursor(annotation, position) { annotation: innermostAnnotation }; } catch (e) { + if (!(e instanceof Error)) throw e; if (e.message === kInternalLocateError) { return { withError: true @@ -32420,10 +32303,8 @@ function objectSchema(params = {}) { result.additionalProperties = allOfSchema(...additionalPropArray); } const propNamesArray = baseSchema.map((s) => s.propertyNames).filter((s) => { - if (typeof s !== "object") - return true; - if (s.tags === void 0) - return true; + if (typeof s !== "object") return true; + if (s.tags === void 0) return true; if (s.tags["case-detection"] === true) { return false; } @@ -32592,8 +32473,7 @@ function globToRegExp(glob, { const wildcard = "[^/]*"; const escapePrefix = "\\"; let newLength = glob.length; - for (; newLength > 1 && seps.includes(glob[newLength - 1]); newLength--) - ; + for (; newLength > 1 && seps.includes(glob[newLength - 1]); newLength--) ; glob = glob.slice(0, newLength); let regExpString = ""; for (let j = 0; j < glob.length; ) { @@ -32635,34 +32515,21 @@ function globToRegExp(glob, { } if (glob[k + 1] == ":" && glob[k + 2] == "]") { i = k + 2; - if (value == "alnum") - segment += "\\dA-Za-z"; - else if (value == "alpha") - segment += "A-Za-z"; - else if (value == "ascii") - segment += "\0-\x7F"; - else if (value == "blank") - segment += " "; - else if (value == "cntrl") - segment += "\0-\x7F"; - else if (value == "digit") - segment += "\\d"; - else if (value == "graph") - segment += "!-~"; - else if (value == "lower") - segment += "a-z"; - else if (value == "print") - segment += " -~"; + if (value == "alnum") segment += "\\dA-Za-z"; + else if (value == "alpha") segment += "A-Za-z"; + else if (value == "ascii") segment += "\0-\x7F"; + else if (value == "blank") segment += " "; + else if (value == "cntrl") segment += "\0-\x7F"; + else if (value == "digit") segment += "\\d"; + else if (value == "graph") segment += "!-~"; + else if (value == "lower") segment += "a-z"; + else if (value == "print") segment += " -~"; else if (value == "punct") { segment += `!"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_\u2018{|}~`; - } else if (value == "space") - segment += "\\s\v"; - else if (value == "upper") - segment += "A-Z"; - else if (value == "word") - segment += "\\w"; - else if (value == "xdigit") - segment += "\\dA-Fa-f"; + } else if (value == "space") segment += "\\s\v"; + else if (value == "upper") segment += "A-Z"; + else if (value == "word") segment += "\\w"; + else if (value == "xdigit") segment += "\\dA-Fa-f"; continue; } } @@ -32772,8 +32639,7 @@ function globToRegExp(glob, { regExpString += i < glob.length ? sep : sepMaybe; endsWithSep = true; } - while (seps.includes(glob[i])) - i++; + while (seps.includes(glob[i])) i++; if (!(i > j)) { throw new Error("Assertion failure: i > j (potential infinite loop)"); } diff --git a/src/resources/editor/tools/yaml/web-worker.js b/src/resources/editor/tools/yaml/web-worker.js index 7879d298d6e..75ac3343704 100644 --- a/src/resources/editor/tools/yaml/web-worker.js +++ b/src/resources/editor/tools/yaml/web-worker.js @@ -23720,14 +23720,6 @@ try { "Manuscript configuration", "internal-schema-hack", "List execution engines you want to give priority when determining\nwhich engine should render a notebook. If two engines have support for a\nnotebook, the one listed earlier will be chosen. Quarto\u2019s default order\nis \u2018knitr\u2019, \u2018jupyter\u2019, \u2018markdown\u2019, \u2018julia\u2019.", - { - short: "Include an automatically generated table of contents", - long: "" - }, - { - short: "Use smart quotes in document output. Defaults to true.", - long: "" - }, "Project configuration.", "Project type (default, website,\nbook, or manuscript)", "Files to render (defaults to all files)", @@ -24371,12 +24363,12 @@ try { mermaid: "%%" }, "handlers/mermaid/schema.yml": { - _internalId: 194571, + _internalId: 193837, type: "object", description: "be an object", properties: { "mermaid-format": { - _internalId: 194563, + _internalId: 193829, type: "enum", enum: [ "png", @@ -24392,7 +24384,7 @@ try { exhaustiveCompletions: true }, theme: { - _internalId: 194570, + _internalId: 193836, type: "anyOf", anyOf: [ { @@ -24432,42 +24424,7 @@ try { "case-detection": true }, $id: "handlers/mermaid" - }, - "schema/document-typst.yml": [ - { - name: "page-numbering", - tags: { - formats: [ - "typst" - ] - }, - schema: { - anyOf: [ - "string", - { - enum: [ - false - ] - } - ] - }, - description: { - short: "Include an automatically generated table of contents" - } - }, - { - name: "smart", - tags: { - formats: [ - "typst" - ] - }, - schema: "boolean", - description: { - short: "Use smart quotes in document output. Defaults to true." - } - } - ] + } }; } }); @@ -24965,8 +24922,7 @@ ${heading}`; const mappedStrings = strings.map((s) => { if (typeof s === "string") { return asMappedString(s); - } else - return s; + } else return s; }); let currentOffset = 0; const offsets = [0]; @@ -25205,10 +25161,8 @@ ${heading}`; return typeof subject === "object" && subject !== null; } function toArray(sequence) { - if (Array.isArray(sequence)) - return sequence; - else if (isNothing(sequence)) - return []; + if (Array.isArray(sequence)) return sequence; + else if (isNothing(sequence)) return []; return [sequence]; } function extend(target, source) { @@ -25248,8 +25202,7 @@ ${heading}`; }; function formatError(exception2, compact) { var where = "", message = exception2.reason || "(unknown reason)"; - if (!exception2.mark) - return message; + if (!exception2.mark) return message; if (exception2.mark.name) { where += 'in "' + exception2.mark.name + '" '; } @@ -25299,16 +25252,11 @@ ${heading}`; } function makeSnippet(mark, options) { options = Object.create(options || null); - if (!mark.buffer) - return null; - if (!options.maxLength) - options.maxLength = 79; - if (typeof options.indent !== "number") - options.indent = 1; - if (typeof options.linesBefore !== "number") - options.linesBefore = 3; - if (typeof options.linesAfter !== "number") - options.linesAfter = 2; + if (!mark.buffer) return null; + if (!options.maxLength) options.maxLength = 79; + if (typeof options.indent !== "number") options.indent = 1; + if (typeof options.linesBefore !== "number") options.linesBefore = 3; + if (typeof options.linesAfter !== "number") options.linesAfter = 2; var re = /\r?\n|\r|\0/g; var lineStarts = [0]; var lineEnds = []; @@ -25321,8 +25269,7 @@ ${heading}`; foundLineNo = lineStarts.length - 2; } } - if (foundLineNo < 0) - foundLineNo = lineStarts.length - 1; + if (foundLineNo < 0) foundLineNo = lineStarts.length - 1; var result = "", i, line; var lineNoLength = Math.min( mark.line + options.linesAfter, @@ -25330,8 +25277,7 @@ ${heading}`; ).toString().length; var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3); for (i = 1; i <= options.linesBefore; i++) { - if (foundLineNo - i < 0) - break; + if (foundLineNo - i < 0) break; line = getLine( mark.buffer, lineStarts[foundLineNo - i], @@ -25351,8 +25297,7 @@ ${heading}`; result += common.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n"; result += common.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n"; for (i = 1; i <= options.linesAfter; i++) { - if (foundLineNo + i >= lineEnds.length) - break; + if (foundLineNo + i >= lineEnds.length) break; line = getLine( mark.buffer, lineStarts[foundLineNo + i], @@ -25471,10 +25416,8 @@ ${heading}`; } else if (Array.isArray(definition)) { explicit = explicit.concat(definition); } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { - if (definition.implicit) - implicit = implicit.concat(definition.implicit); - if (definition.explicit) - explicit = explicit.concat(definition.explicit); + if (definition.implicit) implicit = implicit.concat(definition.implicit); + if (definition.explicit) explicit = explicit.concat(definition.explicit); } else { throw new exception( "Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })" @@ -25538,8 +25481,7 @@ ${heading}`; explicit: [str, seq, map] }); function resolveYamlNull(data) { - if (data === null) - return true; + if (data === null) return true; var max = data.length; return max === 1 && data === "~" || max === 4 && (data === "null" || data === "Null" || data === "NULL"); } @@ -25574,8 +25516,7 @@ ${heading}`; defaultStyle: "lowercase" }); function resolveYamlBoolean(data) { - if (data === null) - return false; + if (data === null) return false; var max = data.length; return max === 4 && (data === "true" || data === "True" || data === "TRUE") || max === 5 && (data === "false" || data === "False" || data === "FALSE"); } @@ -25613,27 +25554,22 @@ ${heading}`; return 48 <= c && c <= 57; } function resolveYamlInteger(data) { - if (data === null) - return false; + if (data === null) return false; var max = data.length, index = 0, hasDigits = false, ch; - if (!max) - return false; + if (!max) return false; ch = data[index]; if (ch === "-" || ch === "+") { ch = data[++index]; } if (ch === "0") { - if (index + 1 === max) - return true; + if (index + 1 === max) return true; ch = data[++index]; if (ch === "b") { index++; for (; index < max; index++) { ch = data[index]; - if (ch === "_") - continue; - if (ch !== "0" && ch !== "1") - return false; + if (ch === "_") continue; + if (ch !== "0" && ch !== "1") return false; hasDigits = true; } return hasDigits && ch !== "_"; @@ -25642,10 +25578,8 @@ ${heading}`; index++; for (; index < max; index++) { ch = data[index]; - if (ch === "_") - continue; - if (!isHexCode(data.charCodeAt(index))) - return false; + if (ch === "_") continue; + if (!isHexCode(data.charCodeAt(index))) return false; hasDigits = true; } return hasDigits && ch !== "_"; @@ -25654,28 +25588,23 @@ ${heading}`; index++; for (; index < max; index++) { ch = data[index]; - if (ch === "_") - continue; - if (!isOctCode(data.charCodeAt(index))) - return false; + if (ch === "_") continue; + if (!isOctCode(data.charCodeAt(index))) return false; hasDigits = true; } return hasDigits && ch !== "_"; } } - if (ch === "_") - return false; + if (ch === "_") return false; for (; index < max; index++) { ch = data[index]; - if (ch === "_") - continue; + if (ch === "_") continue; if (!isDecCode(data.charCodeAt(index))) { return false; } hasDigits = true; } - if (!hasDigits || ch === "_") - return false; + if (!hasDigits || ch === "_") return false; return true; } function constructYamlInteger(data) { @@ -25685,20 +25614,15 @@ ${heading}`; } ch = value[0]; if (ch === "-" || ch === "+") { - if (ch === "-") - sign = -1; + if (ch === "-") sign = -1; value = value.slice(1); ch = value[0]; } - if (value === "0") - return 0; + if (value === "0") return 0; if (ch === "0") { - if (value[1] === "b") - return sign * parseInt(value.slice(2), 2); - if (value[1] === "x") - return sign * parseInt(value.slice(2), 16); - if (value[1] === "o") - return sign * parseInt(value.slice(2), 8); + if (value[1] === "b") return sign * parseInt(value.slice(2), 2); + if (value[1] === "x") return sign * parseInt(value.slice(2), 16); + if (value[1] === "o") return sign * parseInt(value.slice(2), 8); } return sign * parseInt(value, 10); } @@ -25736,8 +25660,7 @@ ${heading}`; "^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$" ); function resolveYamlFloat(data) { - if (data === null) - return false; + if (data === null) return false; if (!YAML_FLOAT_PATTERN.test(data) || data[data.length - 1] === "_") { return false; } @@ -25815,21 +25738,16 @@ ${heading}`; "^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$" ); function resolveYamlTimestamp(data) { - if (data === null) - return false; - if (YAML_DATE_REGEXP.exec(data) !== null) - return true; - if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) - return true; + if (data === null) return false; + if (YAML_DATE_REGEXP.exec(data) !== null) return true; + if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true; return false; } function constructYamlTimestamp(data) { var match, year, month, day, hour, minute, second, fraction = 0, delta = null, tz_hour, tz_minute, date; match = YAML_DATE_REGEXP.exec(data); - if (match === null) - match = YAML_TIMESTAMP_REGEXP.exec(data); - if (match === null) - throw new Error("Date resolve error"); + if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data); + if (match === null) throw new Error("Date resolve error"); year = +match[1]; month = +match[2] - 1; day = +match[3]; @@ -25850,12 +25768,10 @@ ${heading}`; tz_hour = +match[10]; tz_minute = +(match[11] || 0); delta = (tz_hour * 60 + tz_minute) * 6e4; - if (match[9] === "-") - delta = -delta; + if (match[9] === "-") delta = -delta; } date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); - if (delta) - date.setTime(date.getTime() - delta); + if (delta) date.setTime(date.getTime() - delta); return date; } function representYamlTimestamp(object) { @@ -25877,15 +25793,12 @@ ${heading}`; }); var BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r"; function resolveYamlBinary(data) { - if (data === null) - return false; + if (data === null) return false; var code2, idx, bitlen = 0, max = data.length, map2 = BASE64_MAP; for (idx = 0; idx < max; idx++) { code2 = map2.indexOf(data.charAt(idx)); - if (code2 > 64) - continue; - if (code2 < 0) - return false; + if (code2 > 64) continue; + if (code2 < 0) return false; bitlen += 6; } return bitlen % 8 === 0; @@ -25956,28 +25869,21 @@ ${heading}`; var _hasOwnProperty$3 = Object.prototype.hasOwnProperty; var _toString$2 = Object.prototype.toString; function resolveYamlOmap(data) { - if (data === null) - return true; + if (data === null) return true; var objectKeys = [], index, length, pair, pairKey, pairHasKey, object = data; for (index = 0, length = object.length; index < length; index += 1) { pair = object[index]; pairHasKey = false; - if (_toString$2.call(pair) !== "[object Object]") - return false; + if (_toString$2.call(pair) !== "[object Object]") return false; for (pairKey in pair) { if (_hasOwnProperty$3.call(pair, pairKey)) { - if (!pairHasKey) - pairHasKey = true; - else - return false; + if (!pairHasKey) pairHasKey = true; + else return false; } } - if (!pairHasKey) - return false; - if (objectKeys.indexOf(pairKey) === -1) - objectKeys.push(pairKey); - else - return false; + if (!pairHasKey) return false; + if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey); + else return false; } return true; } @@ -25991,24 +25897,20 @@ ${heading}`; }); var _toString$1 = Object.prototype.toString; function resolveYamlPairs(data) { - if (data === null) - return true; + if (data === null) return true; var index, length, pair, keys, result, object = data; result = new Array(object.length); for (index = 0, length = object.length; index < length; index += 1) { pair = object[index]; - if (_toString$1.call(pair) !== "[object Object]") - return false; + if (_toString$1.call(pair) !== "[object Object]") return false; keys = Object.keys(pair); - if (keys.length !== 1) - return false; + if (keys.length !== 1) return false; result[index] = [keys[0], pair[keys[0]]]; } return true; } function constructYamlPairs(data) { - if (data === null) - return []; + if (data === null) return []; var index, length, pair, keys, result, object = data; result = new Array(object.length); for (index = 0, length = object.length; index < length; index += 1) { @@ -26025,13 +25927,11 @@ ${heading}`; }); var _hasOwnProperty$2 = Object.prototype.hasOwnProperty; function resolveYamlSet(data) { - if (data === null) - return true; + if (data === null) return true; var key, object = data; for (key in object) { if (_hasOwnProperty$2.call(object, key)) { - if (object[key] !== null) - return false; + if (object[key] !== null) return false; } } return true; @@ -26741,8 +26641,7 @@ ${heading}`; } function readBlockSequence(state, nodeIndent) { var _line, _tag = state.tag, _anchor = state.anchor, _result = [], following, detected = false, ch; - if (state.firstTabInLine !== -1) - return false; + if (state.firstTabInLine !== -1) return false; if (state.anchor !== null) { state.anchorMap[state.anchor] = _result; } @@ -26790,8 +26689,7 @@ ${heading}`; } function readBlockMapping(state, nodeIndent, flowIndent) { var following, allowCompact, _line, _keyLine, _keyLineStart, _keyPos, _tag = state.tag, _anchor = state.anchor, _result = {}, overridableKeys = /* @__PURE__ */ Object.create(null), keyTag = null, keyNode = null, valueNode = null, atExplicitKey = false, detected = false, ch; - if (state.firstTabInLine !== -1) - return false; + if (state.firstTabInLine !== -1) return false; if (state.anchor !== null) { state.anchorMap[state.anchor] = _result; } @@ -26953,8 +26851,7 @@ ${heading}`; function readTagProperty(state) { var _position, isVerbatim = false, isNamed = false, tagHandle, tagName, ch; ch = state.input.charCodeAt(state.position); - if (ch !== 33) - return false; + if (ch !== 33) return false; if (state.tag !== null) { throwError(state, "duplication of a tag property"); } @@ -27028,8 +26925,7 @@ ${heading}`; function readAnchorProperty(state) { var _position, ch; ch = state.input.charCodeAt(state.position); - if (ch !== 38) - return false; + if (ch !== 38) return false; if (state.anchor !== null) { throwError(state, "duplication of an anchor property"); } @@ -27050,8 +26946,7 @@ ${heading}`; function readAlias(state) { var _position, alias, ch; ch = state.input.charCodeAt(state.position); - if (ch !== 42) - return false; + if (ch !== 42) return false; ch = state.input.charCodeAt(++state.position); _position = state.position; while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { @@ -27242,16 +27137,14 @@ ${heading}`; } while (ch !== 0 && !is_EOL(ch)); break; } - if (is_EOL(ch)) - break; + if (is_EOL(ch)) break; _position = state.position; while (ch !== 0 && !is_WS_OR_EOL(ch)) { ch = state.input.charCodeAt(++state.position); } directiveArgs.push(state.input.slice(_position, state.position)); } - if (ch !== 0) - readLineBreak(state); + if (ch !== 0) readLineBreak(state); if (_hasOwnProperty$1.call(directiveHandlers, directiveName)) { directiveHandlers[directiveName](state, directiveName, directiveArgs); } else { @@ -27407,8 +27300,7 @@ ${heading}`; var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; function compileStyleMap(schema2, map2) { var result, keys, index, length, tag, style, type2; - if (map2 === null) - return {}; + if (map2 === null) return {}; result = {}; keys = Object.keys(map2); for (index = 0, length = keys.length; index < length; index += 1) { @@ -27479,8 +27371,7 @@ ${heading}`; line = string.slice(position, next + 1); position = next + 1; } - if (line.length && line !== "\n") - result += ind; + if (line.length && line !== "\n") result += ind; result += line; } return result; @@ -27657,8 +27548,7 @@ ${heading}`; return result; } function foldLine(line, width) { - if (line === "" || line[0] === " ") - return line; + if (line === "" || line[0] === " ") return line; var breakRe = / [^ ]/g; var match; var start = 0, end, curr = 0, next = 0; @@ -27689,8 +27579,7 @@ ${heading}`; escapeSeq = ESCAPE_SEQUENCES[char]; if (!escapeSeq && isPrintable(char)) { result += string[i]; - if (char >= 65536) - result += string[i + 1]; + if (char >= 65536) result += string[i + 1]; } else { result += escapeSeq || encodeHex(char); } @@ -27705,8 +27594,7 @@ ${heading}`; value = state.replacer.call(object, String(index), value); } if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) { - if (_result !== "") - _result += "," + (!state.condenseFlow ? " " : ""); + if (_result !== "") _result += "," + (!state.condenseFlow ? " " : ""); _result += state.dump; } } @@ -27739,10 +27627,8 @@ ${heading}`; var _result = "", _tag = state.tag, objectKeyList = Object.keys(object), index, length, objectKey, objectValue, pairBuffer; for (index = 0, length = objectKeyList.length; index < length; index += 1) { pairBuffer = ""; - if (_result !== "") - pairBuffer += ", "; - if (state.condenseFlow) - pairBuffer += '"'; + if (_result !== "") pairBuffer += ", "; + if (state.condenseFlow) pairBuffer += '"'; objectKey = objectKeyList[index]; objectValue = object[objectKey]; if (state.replacer) { @@ -27751,8 +27637,7 @@ ${heading}`; if (!writeNode(state, level, objectKey, false, false)) { continue; } - if (state.dump.length > 1024) - pairBuffer += "? "; + if (state.dump.length > 1024) pairBuffer += "? "; pairBuffer += state.dump + (state.condenseFlow ? '"' : "") + ":" + (state.condenseFlow ? "" : " "); if (!writeNode(state, level, objectValue, false, false)) { continue; @@ -27905,8 +27790,7 @@ ${heading}`; } else if (type2 === "[object Undefined]") { return false; } else { - if (state.skipInvalid) - return false; + if (state.skipInvalid) return false; throw new exception("unacceptable kind of an object to dump " + type2); } if (state.tag !== null && state.tag !== "?") { @@ -27959,14 +27843,12 @@ ${heading}`; function dump$1(input, options) { options = options || {}; var state = new State(options); - if (!state.noRefs) - getDuplicateReferences(input, state); + if (!state.noRefs) getDuplicateReferences(input, state); var value = input; if (state.replacer) { value = state.replacer.call({ "": value }, "", value); } - if (writeNode(state, 0, value, true, true)) - return state.dump + "\n"; + if (writeNode(state, 0, value, true, true)) return state.dump + "\n"; return ""; } var dump_1 = dump$1; @@ -31403,6 +31285,7 @@ ${tidyverseInfo( annotation: innermostAnnotation }; } catch (e) { + if (!(e instanceof Error)) throw e; if (e.message === kInternalLocateError) { return { withError: true @@ -32434,10 +32317,8 @@ ${tidyverseInfo( result.additionalProperties = allOfSchema(...additionalPropArray); } const propNamesArray = baseSchema.map((s) => s.propertyNames).filter((s) => { - if (typeof s !== "object") - return true; - if (s.tags === void 0) - return true; + if (typeof s !== "object") return true; + if (s.tags === void 0) return true; if (s.tags["case-detection"] === true) { return false; } @@ -32606,8 +32487,7 @@ ${tidyverseInfo( const wildcard = "[^/]*"; const escapePrefix = "\\"; let newLength = glob.length; - for (; newLength > 1 && seps.includes(glob[newLength - 1]); newLength--) - ; + for (; newLength > 1 && seps.includes(glob[newLength - 1]); newLength--) ; glob = glob.slice(0, newLength); let regExpString = ""; for (let j = 0; j < glob.length; ) { @@ -32649,34 +32529,21 @@ ${tidyverseInfo( } if (glob[k + 1] == ":" && glob[k + 2] == "]") { i = k + 2; - if (value == "alnum") - segment += "\\dA-Za-z"; - else if (value == "alpha") - segment += "A-Za-z"; - else if (value == "ascii") - segment += "\0-\x7F"; - else if (value == "blank") - segment += " "; - else if (value == "cntrl") - segment += "\0-\x7F"; - else if (value == "digit") - segment += "\\d"; - else if (value == "graph") - segment += "!-~"; - else if (value == "lower") - segment += "a-z"; - else if (value == "print") - segment += " -~"; + if (value == "alnum") segment += "\\dA-Za-z"; + else if (value == "alpha") segment += "A-Za-z"; + else if (value == "ascii") segment += "\0-\x7F"; + else if (value == "blank") segment += " "; + else if (value == "cntrl") segment += "\0-\x7F"; + else if (value == "digit") segment += "\\d"; + else if (value == "graph") segment += "!-~"; + else if (value == "lower") segment += "a-z"; + else if (value == "print") segment += " -~"; else if (value == "punct") { segment += `!"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_\u2018{|}~`; - } else if (value == "space") - segment += "\\s\v"; - else if (value == "upper") - segment += "A-Z"; - else if (value == "word") - segment += "\\w"; - else if (value == "xdigit") - segment += "\\dA-Fa-f"; + } else if (value == "space") segment += "\\s\v"; + else if (value == "upper") segment += "A-Z"; + else if (value == "word") segment += "\\w"; + else if (value == "xdigit") segment += "\\dA-Fa-f"; continue; } } @@ -32786,8 +32653,7 @@ ${tidyverseInfo( regExpString += i < glob.length ? sep : sepMaybe; endsWithSep = true; } - while (seps.includes(glob[i])) - i++; + while (seps.includes(glob[i])) i++; if (!(i > j)) { throw new Error("Assertion failure: i > j (potential infinite loop)"); } diff --git a/src/resources/editor/tools/yaml/yaml-intelligence-resources.json b/src/resources/editor/tools/yaml/yaml-intelligence-resources.json index 1e94fb292f2..d2d4cf0edd0 100644 --- a/src/resources/editor/tools/yaml/yaml-intelligence-resources.json +++ b/src/resources/editor/tools/yaml/yaml-intelligence-resources.json @@ -16691,14 +16691,6 @@ "Manuscript configuration", "internal-schema-hack", "List execution engines you want to give priority when determining\nwhich engine should render a notebook. If two engines have support for a\nnotebook, the one listed earlier will be chosen. Quarto’s default order\nis ‘knitr’, ‘jupyter’, ‘markdown’, ‘julia’.", - { - "short": "Include an automatically generated table of contents", - "long": "" - }, - { - "short": "Use smart quotes in document output. Defaults to true.", - "long": "" - }, "Project configuration.", "Project type (default, website,\nbook, or manuscript)", "Files to render (defaults to all files)", @@ -17342,12 +17334,12 @@ "mermaid": "%%" }, "handlers/mermaid/schema.yml": { - "_internalId": 194571, + "_internalId": 193837, "type": "object", "description": "be an object", "properties": { "mermaid-format": { - "_internalId": 194563, + "_internalId": 193829, "type": "enum", "enum": [ "png", @@ -17363,7 +17355,7 @@ "exhaustiveCompletions": true }, "theme": { - "_internalId": 194570, + "_internalId": 193836, "type": "anyOf", "anyOf": [ { @@ -17403,40 +17395,5 @@ "case-detection": true }, "$id": "handlers/mermaid" - }, - "schema/document-typst.yml": [ - { - "name": "page-numbering", - "tags": { - "formats": [ - "typst" - ] - }, - "schema": { - "anyOf": [ - "string", - { - "enum": [ - false - ] - } - ] - }, - "description": { - "short": "Include an automatically generated table of contents" - } - }, - { - "name": "smart", - "tags": { - "formats": [ - "typst" - ] - }, - "schema": "boolean", - "description": { - "short": "Use smart quotes in document output. Defaults to true." - } - } - ] + } } \ No newline at end of file diff --git a/src/tools/impl/tinytex.ts b/src/tools/impl/tinytex.ts index 290fd1b0a2d..ec638401020 100644 --- a/src/tools/impl/tinytex.ts +++ b/src/tools/impl/tinytex.ts @@ -472,7 +472,12 @@ async function uninstall(context: InstallContext) { } function exec(path: string, cmd: string[]) { - return execProcess({ cmd: [path, ...cmd], stdout: "piped", stderr: "piped" }); + return execProcess({ + cmd: path, + args: cmd, + stdout: "piped", + stderr: "piped", + }); } const kTlMgrKey = "tlmgr"; diff --git a/src/tools/tools.ts b/src/tools/tools.ts index 8518da7ae1e..01e0422ace0 100644 --- a/src/tools/tools.ts +++ b/src/tools/tools.ts @@ -297,6 +297,10 @@ const installContext = ( try { await downloadWithProgress(url, `Downloading ${name}`, target); } catch (error) { + // shouldn't happen, but this appeases the typechecker + if (!(error instanceof Error)) { + throw error; + } installMessaging.error( error.message, ); diff --git a/tests/integration/playwright-tests.test.ts b/tests/integration/playwright-tests.test.ts index 3b857b23f29..3f4abaf340f 100644 --- a/tests/integration/playwright-tests.test.ts +++ b/tests/integration/playwright-tests.test.ts @@ -52,7 +52,8 @@ for (const { path: fileName } of globOutput) { // mediabag inspection if we don't wait all renders // individually. This is very slow.. await execProcess({ - cmd: [quartoDevCmd(), "render", input, ...options], + cmd: quartoDevCmd(), + args: ["render", input, ...options], }); fileNames.push(fileName); } @@ -65,7 +66,8 @@ Deno.test({ try { // run playwright const res = await execProcess({ - cmd: [isWindows ? "npx.cmd" : "npx", "playwright", "test", "--ignore-snapshots"], + cmd: isWindows ? "npx.cmd" : "npx", + args: ["playwright", "test", "--ignore-snapshots"], cwd: "integration/playwright", }); if (!res.success) { diff --git a/tests/smoke/create/create.test.ts b/tests/smoke/create/create.test.ts index efd0182494e..8d898d24208 100644 --- a/tests/smoke/create/create.test.ts +++ b/tests/smoke/create/create.test.ts @@ -48,7 +48,8 @@ for (const type of Object.keys(kCreateTypes)) { const cmd = [quartoDevCmd(), "create", "--json"]; const stdIn = JSON.stringify(createDirective); const process = await execProcess({ - cmd, + cmd: cmd[0], + args: cmd.slice(1), stdout: "piped", stderr: "piped", }, stdIn); @@ -73,7 +74,8 @@ for (const type of Object.keys(kCreateTypes)) { // provide a step name and function const cmd = [quartoDevCmd(), "render", file]; const process = await execProcess({ - cmd, + cmd: cmd[0], + args: cmd.slice(1), cwd: path, stdout: "piped", stderr: "piped", diff --git a/tests/smoke/filters/editor-support.test.ts b/tests/smoke/filters/editor-support.test.ts index a506c762f35..77729c882e1 100644 --- a/tests/smoke/filters/editor-support.test.ts +++ b/tests/smoke/filters/editor-support.test.ts @@ -26,6 +26,7 @@ async function runEditorSupportCrossref(doc: string) { Deno.readTextFileSync(doc), ); await writer.write(buf); + writer.releaseLock(); await writer.close(); const outputBuf = await child.output(); const status = await child.status; diff --git a/tests/smoke/run/command-passthrough.test.ts b/tests/smoke/run/command-passthrough.test.ts index db89356b3fd..6db94e984e9 100644 --- a/tests/smoke/run/command-passthrough.test.ts +++ b/tests/smoke/run/command-passthrough.test.ts @@ -6,8 +6,8 @@ import { unitTest } from "../../test.ts"; const testPassthroughCmd = (name: string, command: string, args: string[]) => { unitTest(name, async () => { const result = await execProcess({ - cmd: [ - quartoDevCmd(), + cmd: quartoDevCmd(), + args: [ command, ...args, ] diff --git a/tests/smoke/run/run-script.test.ts b/tests/smoke/run/run-script.test.ts index 2a7ab6ee943..ee6fb0f16fe 100644 --- a/tests/smoke/run/run-script.test.ts +++ b/tests/smoke/run/run-script.test.ts @@ -14,8 +14,8 @@ ensureDirSync(workingDir); const ensureStreams = (name: string, script: string, stdout: string, stderr: string) => { unitTest(name, async () => { const result = await execProcess({ - cmd: [ - quartoDevCmd(), + cmd: quartoDevCmd(), + args: [ "run", basename(script), ], @@ -51,8 +51,8 @@ const ensureStreams = (name: string, script: string, stdout: string, stderr: str const testRunCmd = (name: string, script: string) => { unitTest(name, async () => { const result = await execProcess({ - cmd: [ - quartoDevCmd(), + cmd: quartoDevCmd(), + args: [ "run", basename(script), ] diff --git a/tests/smoke/run/stdlib-run-version.test.ts b/tests/smoke/run/stdlib-run-version.test.ts index 3994c5acbf8..bbe7dadf726 100644 --- a/tests/smoke/run/stdlib-run-version.test.ts +++ b/tests/smoke/run/stdlib-run-version.test.ts @@ -12,8 +12,8 @@ import { isWindows } from "../../../src/deno_ral/platform.ts"; unitTest("stdlib-run-version", async () => { const result = await execProcess({ - cmd: [ - "quarto", + cmd: "quarto", + args: [ "run", "docs/run/test-stdlib.ts", ], diff --git a/tests/smoke/smoke-all.test.ts b/tests/smoke/smoke-all.test.ts index a075de3f9e5..18c84612996 100644 --- a/tests/smoke/smoke-all.test.ts +++ b/tests/smoke/smoke-all.test.ts @@ -62,6 +62,7 @@ async function guessFormat(fileName: string): Promise { try { yaml = parse(src); } catch (e) { + if (!(e instanceof Error)) throw e; if (e.message.includes("unknown tag")) { // assume it's not necessary to guess the format continue; diff --git a/tests/test.ts b/tests/test.ts index 72f6542d7b4..e4d67ae894c 100644 --- a/tests/test.ts +++ b/tests/test.ts @@ -241,6 +241,7 @@ export function test(test: TestDescriptor) { } } } catch (ex) { + if (!(ex instanceof Error)) throw ex; const border = "-".repeat(80); const coloredName = userSession ? colors.brightGreen(colors.italic(testName)) @@ -287,7 +288,7 @@ export function test(test: TestDescriptor) { coloredVerify, "", ex.message, - ex.stack, + ex.stack ?? "", "", ]; diff --git a/tests/unit/schema-validation/object-super.test.ts b/tests/unit/schema-validation/object-super.test.ts index 8b17333693a..f44e9821ac0 100644 --- a/tests/unit/schema-validation/object-super.test.ts +++ b/tests/unit/schema-validation/object-super.test.ts @@ -127,7 +127,7 @@ website: asMappedString(obj), refSchema("project-config", ""), ); - } catch (e) { + } catch (e: any) { return expectValidationError(e) .forSchemaPathToEndWith("type") .toHaveLength(1); diff --git a/tests/utils.ts b/tests/utils.ts index 3f49578ba05..66db3d6d3c5 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -52,7 +52,7 @@ export function findProjectOutputDir(projectdir: string | undefined) { // deno-lint-ignore no-explicit-any type = ((yaml as any).project as any).type; } catch (error) { - throw new Error("Failed to read quarto project YAML", error); + throw new Error("Failed to read quarto project YAML" + String(error)); } if (type === "book") { return "_book"; diff --git a/tests/verify.ts b/tests/verify.ts index c9ae1cd1f22..8a2e368583c 100644 --- a/tests/verify.ts +++ b/tests/verify.ts @@ -19,7 +19,7 @@ import { outputForInput } from "./utils.ts"; import { unzip } from "../src/core/zip.ts"; import { dirAndStem, safeRemoveSync, which } from "../src/core/path.ts"; import { isWindows } from "../src/deno_ral/platform.ts"; -import { execProcess } from "../src/core/process.ts"; +import { execProcess, ExecProcessOptions } from "../src/core/process.ts"; import { canonicalizeSnapshot, checkSnapshot } from "./verify-snapshot.ts"; export const withDocxContent = async ( @@ -978,9 +978,10 @@ export const ensureXmlValidatesWithXsd = ( name: "Validating XML", verify: async (_output: ExecuteOutput[]) => { if (!isWindows) { - const cmd = ["xmllint", "--noout", "--valid", file, "--path", xsdPath]; - const runOptions: Deno.RunOptions = { - cmd, + const args = ["--noout", "--valid", file, "--path", xsdPath]; + const runOptions: ExecProcessOptions = { + cmd: "xmllint", + args, stderr: "piped", stdout: "piped", }; @@ -1006,7 +1007,8 @@ export const ensureMECAValidates = ( const hasMeca = await which("meca"); if (hasMeca) { const result = await execProcess({ - cmd: ["meca", "validate", mecaFile], + cmd: "meca", + args: ["validate", mecaFile], stderr: "piped", stdout: "piped", }); diff --git a/tools/deno-esbuild-bundle.ts b/tools/deno-esbuild-bundle.ts new file mode 100644 index 00000000000..788d419cf3d --- /dev/null +++ b/tools/deno-esbuild-bundle.ts @@ -0,0 +1,20 @@ +import * as esbuild from "npm:esbuild@0.20.2"; +// Import the Wasm build on platforms where running subprocesses is not +// permitted, such as Deno Deploy, or when running without `--allow-run`. +// import * as esbuild from "https://deno.land/x/esbuild@0.20.2/wasm.js"; + +import { denoPlugins } from "jsr:@luca/esbuild-deno-loader@^0.11.1"; + + +const importMapURL = `file://${Deno.cwd()}/import_map.json`; +// console.log("importMapURL", importMapURL); + +await esbuild.build({ + plugins: [...denoPlugins({ importMapURL })], + entryPoints: ["./quarto.ts"], + outfile: "../package/pkg-working/bin/quarto.js", + bundle: true, + format: "esm", +}); + +esbuild.stop(); \ No newline at end of file