Skip to content

Commit 4fb3027

Browse files
icecrasher321claude
andcommitted
fix(executor): do not read a keyword-named method as a control-flow head
`p.catch(fn)` is a call whose name happens to be a keyword, and what follows its `)` is an operator rather than a statement — so the division in `p.catch(fn) / 2` opened regex mode and ran over the quotes around any reference later on that line. A control-flow head is never a property access, so the check now refuses one that follows a dot. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent d5c2b89 commit 4fb3027

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

apps/sim/executor/variables/resolver.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,23 @@ describe('VariableResolver function block inputs', () => {
947947
expect(code).toContain(`Number('' + JSON.stringify(globalThis["__blockRef_1"]) + '')`)
948948
})
949949

950+
it('does not read a method named after a keyword as a control-flow head', async () => {
951+
const { block, ctx, resolver } = createResolver('javascript')
952+
953+
const result = await resolver.resolveInputsForFunctionBlock(
954+
ctx,
955+
'function',
956+
{ code: `const n = params.p.catch(() => 0) / 2 + Number('<producer.result>')` },
957+
block
958+
)
959+
960+
// `.catch(…)` is a call, so the slash after it divides — it must not open a regex that
961+
// runs over the quotes around the reference.
962+
expect(result.resolvedInputs.code).toContain(
963+
`Number('' + JSON.stringify(globalThis["__blockRef_0"]) + '')`
964+
)
965+
})
966+
950967
it('binds a workflow variable carrying quote characters instead of splicing it into code', async () => {
951968
// A Variables block can assign trigger data at runtime, so a variable's value is not
952969
// necessarily the author's. Inlined as a literal it closed the string it landed in.

apps/sim/executor/variables/resolver.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,17 @@ export class VariableResolver {
11911191
while (start > 0 && this.isJavaScriptIdentifierChar(template[start - 1])) {
11921192
start--
11931193
}
1194-
return CONTROL_FLOW_HEAD_KEYWORDS.has(template.slice(start, end))
1194+
if (!CONTROL_FLOW_HEAD_KEYWORDS.has(template.slice(start, end))) {
1195+
return false
1196+
}
1197+
1198+
// `p.catch(fn)` is a method call whose name happens to be a keyword, and what follows its
1199+
// `)` is an operator, not a statement. A control-flow head can never be a property access.
1200+
let before = start
1201+
while (before > 0 && WHITESPACE_CHAR.test(template[before - 1])) {
1202+
before--
1203+
}
1204+
return template[before - 1] !== '.'
11951205
}
11961206

11971207
private matchesKeywordAt(template: string, index: number, keyword: string): boolean {

0 commit comments

Comments
 (0)