From 872535a40c85dcfad3a4b27c57c026ae003f562f Mon Sep 17 00:00:00 2001 From: Tomi Turtiainen <10324676+tomi@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:32:28 +0200 Subject: [PATCH] fix(core): Opt-out from optimizations if `$item` is used (#12036) --- .../built-ins-parser/__tests__/built-ins-parser.test.ts | 9 ++++++++- .../js-task-runner/built-ins-parser/built-ins-parser.ts | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/__tests__/built-ins-parser.test.ts b/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/__tests__/built-ins-parser.test.ts index 58d314dc19..dd866fc381 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/__tests__/built-ins-parser.test.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/__tests__/built-ins-parser.test.ts @@ -17,7 +17,7 @@ describe('BuiltInsParser', () => { const parseAndExpectOk = (code: string) => { const result = parser.parseUsedBuiltIns(code); if (!result.ok) { - fail(result.error); + throw result.error; } return result.result; @@ -151,6 +151,13 @@ describe('BuiltInsParser', () => { }); }); + describe('$item', () => { + it('should require all nodes and input when $item is used', () => { + const state = parseAndExpectOk('$item("0").$node["my node"].json["title"]'); + expect(state).toEqual(new BuiltInsParserState({ needsAllNodes: true, needs$input: true })); + }); + }); + describe('ECMAScript syntax', () => { describe('ES2020', () => { it('should parse optional chaining', () => { diff --git a/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/built-ins-parser.ts b/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/built-ins-parser.ts index 9b9e4b34b2..7a5c7baf46 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/built-ins-parser.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/built-ins-parser/built-ins-parser.ts @@ -125,6 +125,11 @@ export class BuiltInsParser { private visitIdentifier = (node: Identifier, state: BuiltInsParserState) => { if (node.name === '$env') { state.markEnvAsNeeded(); + } else if (node.name === '$item') { + // $item is legacy syntax that is basically an alias for WorkflowDataProxy + // and allows accessing any data. We need to support it for backwards + // compatibility, but we're not gonna implement any optimizations + state.markNeedsAllNodes(); } else if ( node.name === '$input' || node.name === '$json' ||