Skip to content

Commit 6db8404

Browse files
committed
fix: enable block label references in condition expressions
Inject block outputs as JavaScript variables by their normalized names, allowing users to reference blocks directly (e.g., `humanApproval.approved`) without requiring angle bracket syntax in condition expressions. This fixes Human in the Loop blocks where canvas labels like `humanApproval` were not accessible in Condition blocks, causing "humanApproval is not defined" errors. The fix includes safeguards to: - Skip JavaScript reserved words and built-in identifiers - Avoid overwriting existing context variables Fixes #2962
1 parent e9c4251 commit 6db8404

File tree

1 file changed

+48
-0
lines changed
  • apps/sim/app/api/function/execute

1 file changed

+48
-0
lines changed

apps/sim/app/api/function/execute/route.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,50 @@ function resolveEnvironmentVariables(
468468
return resolvedCode
469469
}
470470

471+
/**
472+
* JavaScript reserved words and built-in identifiers that should not be overwritten.
473+
*/
474+
const RESERVED_IDENTIFIERS = new Set([
475+
// JavaScript reserved words
476+
'break', 'case', 'catch', 'continue', 'debugger', 'default', 'delete', 'do',
477+
'else', 'finally', 'for', 'function', 'if', 'in', 'instanceof', 'new',
478+
'return', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'while',
479+
'with', 'class', 'const', 'enum', 'export', 'extends', 'import', 'super',
480+
'implements', 'interface', 'let', 'package', 'private', 'protected', 'public',
481+
'static', 'yield', 'await', 'async', 'null', 'true', 'false', 'undefined',
482+
// Built-in objects commonly used
483+
'console', 'Math', 'JSON', 'Date', 'Array', 'Object', 'String', 'Number',
484+
'Boolean', 'Error', 'Promise', 'Map', 'Set', 'Symbol', 'Proxy', 'Reflect',
485+
// Execution context variables
486+
'params', 'environmentVariables', 'context', 'fetch',
487+
])
488+
489+
/**
490+
* Injects block outputs as JavaScript variables by their normalized names.
491+
* This allows users to reference blocks directly by label (e.g., `humanApproval.approved`)
492+
* without requiring angle bracket syntax.
493+
*/
494+
function injectBlockVariables(
495+
blockData: Record<string, unknown>,
496+
blockNameMapping: Record<string, string>,
497+
contextVariables: Record<string, unknown>
498+
): void {
499+
for (const [normalizedName, blockId] of Object.entries(blockNameMapping)) {
500+
// Skip reserved identifiers to avoid conflicts
501+
if (RESERVED_IDENTIFIERS.has(normalizedName)) {
502+
continue
503+
}
504+
// Skip if already defined by another resolution step
505+
if (normalizedName in contextVariables) {
506+
continue
507+
}
508+
const blockOutput = blockData[blockId]
509+
if (blockOutput !== undefined) {
510+
contextVariables[normalizedName] = blockOutput
511+
}
512+
}
513+
}
514+
471515
function resolveTagVariables(
472516
code: string,
473517
blockData: Record<string, unknown>,
@@ -479,6 +523,10 @@ function resolveTagVariables(
479523
let resolvedCode = code
480524
const undefinedLiteral = language === 'python' ? 'None' : 'undefined'
481525

526+
// Inject block outputs as direct JavaScript variables
527+
// This allows `blockName.field` syntax in conditions without angle brackets
528+
injectBlockVariables(blockData, blockNameMapping, contextVariables)
529+
482530
const tagPattern = new RegExp(
483531
`${REFERENCE.START}([a-zA-Z_](?:[a-zA-Z0-9_${REFERENCE.PATH_DELIMITER}]*[a-zA-Z0-9_])?)${REFERENCE.END}`,
484532
'g'

0 commit comments

Comments
 (0)