From 12239a0803dc317f8b8bff258daa19d103254275 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Mon, 26 Jan 2026 01:33:06 -0800 Subject: [PATCH] consolidate literal gen --- apps/sim/app/api/function/execute/route.ts | 31 ++---------- apps/sim/executor/utils/code-formatting.ts | 48 +++++++++++++++++++ .../sim/executor/variables/resolvers/block.ts | 20 +------- 3 files changed, 53 insertions(+), 46 deletions(-) create mode 100644 apps/sim/executor/utils/code-formatting.ts diff --git a/apps/sim/app/api/function/execute/route.ts b/apps/sim/app/api/function/execute/route.ts index 9e7b9f573..4ccbd8d7c 100644 --- a/apps/sim/app/api/function/execute/route.ts +++ b/apps/sim/app/api/function/execute/route.ts @@ -8,6 +8,7 @@ import { executeInIsolatedVM } from '@/lib/execution/isolated-vm' import { CodeLanguage, DEFAULT_CODE_LANGUAGE, isValidCodeLanguage } from '@/lib/execution/languages' import { escapeRegExp, normalizeName, REFERENCE } from '@/executor/constants' import { type OutputSchema, resolveBlockReference } from '@/executor/utils/block-reference' +import { formatLiteralForCode } from '@/executor/utils/code-formatting' import { createEnvVarPattern, createWorkflowVariablePattern, @@ -692,15 +693,7 @@ export async function POST(req: NextRequest) { prologue += `const environmentVariables = JSON.parse(${JSON.stringify(JSON.stringify(envVars))});\n` prologueLineCount++ for (const [k, v] of Object.entries(contextVariables)) { - if (v === undefined) { - prologue += `const ${k} = undefined;\n` - } else if (v === null) { - prologue += `const ${k} = null;\n` - } else if (typeof v === 'boolean' || typeof v === 'number') { - prologue += `const ${k} = ${v};\n` - } else { - prologue += `const ${k} = JSON.parse(${JSON.stringify(JSON.stringify(v))});\n` - } + prologue += `const ${k} = ${formatLiteralForCode(v, 'javascript')};\n` prologueLineCount++ } @@ -771,25 +764,7 @@ export async function POST(req: NextRequest) { prologue += `environmentVariables = json.loads(${JSON.stringify(JSON.stringify(envVars))})\n` prologueLineCount++ for (const [k, v] of Object.entries(contextVariables)) { - if (v === undefined) { - prologue += `${k} = None\n` - } else if (v === null) { - prologue += `${k} = None\n` - } else if (typeof v === 'boolean') { - prologue += `${k} = ${v ? 'True' : 'False'}\n` - } else if (typeof v === 'number') { - if (Number.isNaN(v)) { - prologue += `${k} = float('nan')\n` - } else if (v === Number.POSITIVE_INFINITY) { - prologue += `${k} = float('inf')\n` - } else if (v === Number.NEGATIVE_INFINITY) { - prologue += `${k} = float('-inf')\n` - } else { - prologue += `${k} = ${v}\n` - } - } else { - prologue += `${k} = json.loads(${JSON.stringify(JSON.stringify(v))})\n` - } + prologue += `${k} = ${formatLiteralForCode(v, 'python')}\n` prologueLineCount++ } const wrapped = [ diff --git a/apps/sim/executor/utils/code-formatting.ts b/apps/sim/executor/utils/code-formatting.ts new file mode 100644 index 000000000..a4a73dee8 --- /dev/null +++ b/apps/sim/executor/utils/code-formatting.ts @@ -0,0 +1,48 @@ +/** + * Formats a JavaScript/TypeScript value as a code literal for the target language. + * Handles special cases like null, undefined, booleans, and Python-specific number representations. + * + * @param value - The value to format + * @param language - Target language ('javascript' or 'python') + * @returns A string literal representation valid in the target language + * + * @example + * formatLiteralForCode(null, 'python') // => 'None' + * formatLiteralForCode(true, 'python') // => 'True' + * formatLiteralForCode(NaN, 'python') // => "float('nan')" + * formatLiteralForCode("hello", 'javascript') // => '"hello"' + * formatLiteralForCode({a: 1}, 'python') // => "json.loads('{\"a\":1}')" + */ +export function formatLiteralForCode(value: unknown, language: 'javascript' | 'python'): string { + const isPython = language === 'python' + + if (value === undefined) { + return isPython ? 'None' : 'undefined' + } + if (value === null) { + return isPython ? 'None' : 'null' + } + if (typeof value === 'boolean') { + return isPython ? (value ? 'True' : 'False') : String(value) + } + if (typeof value === 'number') { + if (Number.isNaN(value)) { + return isPython ? "float('nan')" : 'NaN' + } + if (value === Number.POSITIVE_INFINITY) { + return isPython ? "float('inf')" : 'Infinity' + } + if (value === Number.NEGATIVE_INFINITY) { + return isPython ? "float('-inf')" : '-Infinity' + } + return String(value) + } + if (typeof value === 'string') { + return JSON.stringify(value) + } + // Objects and arrays - Python needs json.loads() because JSON true/false/null aren't valid Python + if (isPython) { + return `json.loads(${JSON.stringify(JSON.stringify(value))})` + } + return JSON.stringify(value) +} diff --git a/apps/sim/executor/variables/resolvers/block.ts b/apps/sim/executor/variables/resolvers/block.ts index c952b6202..63ab36138 100644 --- a/apps/sim/executor/variables/resolvers/block.ts +++ b/apps/sim/executor/variables/resolvers/block.ts @@ -10,6 +10,7 @@ import { type OutputSchema, resolveBlockReference, } from '@/executor/utils/block-reference' +import { formatLiteralForCode } from '@/executor/utils/code-formatting' import { navigatePath, type ResolutionContext, @@ -207,23 +208,6 @@ export class BlockResolver implements Resolver { } private formatValueForCodeContext(value: any, language?: string): string { - const isPython = language === 'python' - - if (typeof value === 'string') { - return JSON.stringify(value) - } - if (typeof value === 'object' && value !== null) { - return JSON.stringify(value) - } - if (value === undefined) { - return isPython ? 'None' : 'undefined' - } - if (value === null) { - return isPython ? 'None' : 'null' - } - if (typeof value === 'boolean') { - return isPython ? (value ? 'True' : 'False') : String(value) - } - return String(value) + return formatLiteralForCode(value, language === 'python' ? 'python' : 'javascript') } }