test(core): Guard $jmespath resolution under the VM expression engine (backport to 1.x) (#31676)
Some checks are pending
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (22.x) (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (24.13.1) (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (25.x) (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions

Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
n8n-assistant[bot] 2026-06-03 18:08:43 +00:00 committed by GitHub
parent 08de252a0f
commit 2e5c4c21b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1126,4 +1126,64 @@ describe('Expression', () => {
).toBe('second');
});
});
// CAT-3267: `$jmespath($json, query)` returned null under the VM engine
// because `$json` is an in-isolate lazy proxy that could not cross the
// isolate bridge to the host-side `$jmespath` wrapper. The fix resolves
// `$jmespath` / `$jmesPath` entirely in-isolate so the proxy never crosses
// the bridge. Both engines must return the queried value.
describe('$jmespath through expression engine (engine parity)', () => {
const nodeTypes = Helpers.NodeTypes();
const workflow = new Workflow({
id: 'test-jmespath',
name: 'Test',
nodes: [
{
id: 'node-id',
name: 'node',
type: 'n8n-nodes-base.set',
typeVersion: 1,
position: [0, 0],
parameters: {},
},
],
connections: {},
active: false,
nodeTypes,
});
beforeAll(async () => {
await workflow.expression.acquireIsolate();
});
afterAll(async () => {
await workflow.expression.releaseIsolate();
});
const evaluate = (expr: string, data: INodeExecutionData[]) =>
workflow.expression.getParameterValue(expr, null, 0, 0, 'node', data, 'manual', {});
it('queries an in-isolate $json proxy (parity)', () => {
expect(
evaluate('={{ $jmespath($json, "users[*].name") }}', [
{ json: { users: [{ name: 'a' }, { name: 'b' }] } },
]),
).toEqual(['a', 'b']);
});
it('queries via the $jmesPath alias (parity)', () => {
expect(
evaluate('={{ $jmesPath($json, "users[*].name") }}', [
{ json: { users: [{ name: 'a' }, { name: 'b' }] } },
]),
).toEqual(['a', 'b']);
});
it('resolves a nested-object query (parity)', () => {
expect(
evaluate('={{ $jmespath($json, "user.address.city") }}', [
{ json: { user: { address: { city: 'Berlin' } } } },
]),
).toBe('Berlin');
});
});
});