Skip to content

Commit

Permalink
perf(Code Node): Improve n8n item key validation performance (#4669)
Browse files Browse the repository at this point in the history
⚡ Improve validator performance
  • Loading branch information
ivov authored Nov 22, 2022
1 parent 7b00d6e commit 740513b
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 14 deletions.
28 changes: 15 additions & 13 deletions packages/nodes-base/nodes/Code/Sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { normalizeItems } from 'n8n-core';
import { NodeVM, NodeVMOptions } from 'vm2';
import { ValidationError } from './ValidationError';
import { ExecutionError } from './ExecutionError';
import { CodeNodeMode, isObject, SUPPORTED_ITEM_KEYS } from './utils';
import { CodeNodeMode, isObject, N8N_ITEM_KEYS } from './utils';

import type { IExecuteFunctions, IWorkflowDataProxyData, WorkflowExecuteMode } from 'n8n-workflow';

Expand Down Expand Up @@ -95,6 +95,17 @@ export class Sandbox extends NodeVM {
}

if (Array.isArray(executionResult)) {
/**
* If at least one top-level key is an n8n item key (`json`, `binary`, etc.),
* then require all item keys to be an n8n item key.
*
* If no top-level key is an n8n key, then skip this check, allowing non-n8n
* item keys to be wrapped in `json` when normalizing items below.
*/
const mustHaveTopLevelN8nKey = executionResult.some((item) =>
Object.keys(item).find((key) => N8N_ITEM_KEYS.has(key)),
);

for (const item of executionResult) {
if (item.json !== undefined && !isObject(item.json)) {
throw new ValidationError({
Expand All @@ -104,18 +115,9 @@ export class Sandbox extends NodeVM {
});
}

// If at least one top-level key is a supported item key (`json`, `binary`, etc.),
// then validate all keys to be a supported item key, else allow user keys
// to be wrapped in `json` when normalizing items below.

if (
executionResult.some((item) =>
Object.keys(item).find((key) => SUPPORTED_ITEM_KEYS.has(key)),
)
) {
if (mustHaveTopLevelN8nKey) {
Object.keys(item).forEach((key) => {
if (SUPPORTED_ITEM_KEYS.has(key)) return;

if (N8N_ITEM_KEYS.has(key)) return;
throw new ValidationError({
message: `Unknown top-level item key: ${key}`,
description: 'Access the properties of an item under `.json`, e.g. `item.json`',
Expand Down Expand Up @@ -223,7 +225,7 @@ export class Sandbox extends NodeVM {
// directly on the item, when they intended to add it on the `json` property

Object.keys(executionResult).forEach((key) => {
if (SUPPORTED_ITEM_KEYS.has(key)) return;
if (N8N_ITEM_KEYS.has(key)) return;

throw new ValidationError({
message: `Unknown top-level item key: ${key}`,
Expand Down
2 changes: 1 addition & 1 deletion packages/nodes-base/nodes/Code/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ function isTraversable(maybe: unknown): maybe is IDataObject {

export type CodeNodeMode = 'runOnceForAllItems' | 'runOnceForEachItem';

export const SUPPORTED_ITEM_KEYS = new Set(['json', 'binary', 'error', 'pairedItem', 'index']);
export const N8N_ITEM_KEYS = new Set(['json', 'binary', 'error', 'pairedItem', 'index']);

0 comments on commit 740513b

Please sign in to comment.