diff --git a/packages/builder/src/components/common/CodeEditor/validator/js.ts b/packages/builder/src/components/common/CodeEditor/validator/js.ts index 6d7c3ea8bf..20fb5abd07 100644 --- a/packages/builder/src/components/common/CodeEditor/validator/js.ts +++ b/packages/builder/src/components/common/CodeEditor/validator/js.ts @@ -1,7 +1,6 @@ import { Parser } from "acorn" -import { simple as walk } from "acorn-walk" +import * as walk from "acorn-walk" -import { iifeWrapper } from "@budibase/string-templates" import type { Diagnostic } from "@codemirror/lint" import { CodeValidator } from "@/types" @@ -12,13 +11,13 @@ export function validateJsTemplate( const diagnostics: Diagnostic[] = [] try { - // const helperUsages = new RegExp(/\bhelpers\.(\w)+\b/).exec(code) - const ast = Parser.parse(iifeWrapper(code), { + const ast = Parser.parse(code, { ecmaVersion: "latest", locations: true, + allowReturnOutsideFunction: true, }) - const lineOffsets: number[] = [0] + const lineOffsets: number[] = [] let offset = 0 for (const line of code.split("\n")) { lineOffsets.push(offset) @@ -26,9 +25,18 @@ export function validateJsTemplate( } let hasReturnStatement = false - walk(ast, { - ReturnStatement(node) { - hasReturnStatement = !!node.argument + walk.ancestor(ast, { + ReturnStatement(node, _state, ancestors) { + if ( + // it returns a value + node.argument && + // and it is top level + ancestors.length === 2 && + ancestors[0].type === "Program" && + ancestors[1].type === "ReturnStatement" + ) { + hasReturnStatement = true + } }, CallExpression(node) { const callee: any = node.callee diff --git a/packages/builder/src/components/common/CodeEditor/validator/tests/js.spec.ts b/packages/builder/src/components/common/CodeEditor/validator/tests/js.spec.ts index d0c25182f7..cd9fe4684c 100644 --- a/packages/builder/src/components/common/CodeEditor/validator/tests/js.spec.ts +++ b/packages/builder/src/components/common/CodeEditor/validator/tests/js.spec.ts @@ -49,6 +49,24 @@ describe("js validator", () => { ]) }) + it("checks that returns are at top level", () => { + const text = ` + function call(){ + return 1 + }` + const validators = {} + + const result = validateJsTemplate(text, validators) + expect(result).toEqual([ + { + from: 0, + message: "Your code must return a value.", + severity: "error", + to: text.length, + }, + ]) + }) + describe("helpers", () => { const validators: CodeValidator = { helperFunction: {