compileJsExpression = (expr) => {
  // get all dotted identifiers (foo, bar.baz, .baz)
  const matches = expr.match(/([\w\.$]+)/g) ?? [];

  // get valid js identifiers (foo, bar)
  const vars = new Set(
    matches
      .filter((match) => /^[a-zA-Z$_]/.test(match)) // starts with valid js identifier (foo.bar)
      .map((match) => match.split('.')[0]) // top level identifier (foo)
      .filter((name) => !JS_KEYWORDS.includes(name)) // exclude js keywords
  );

  // globals such as Math
  const globals = [...vars].filter((name) => name in globalThis);

  const code = {
    vars: [...vars].join(', '),
    // pick global from context or globalThis
    globals: globals.map((name) => ` ${name} = ${name} ?? globalThis.${name};`).join('')
  };

  // param name that is unlikely to show up as a var in an expression
  const param = `__bruno__functionInnerContext`;
  const body = `let { ${code.vars} } = ${param}; ${code.globals}; return ${expr}`;

  return new Function(param, body);
}
Creates a function from a JavaScript expression

When the function is called, the variables used in this expression are picked up from the context

```js
res.data.pets.map(pet => pet.name.toUpperCase())

function(__bruno__functionInnerContext) {
  const { res, pet } = __bruno__functionInnerContext;
  return res.data.pets.map(pet => pet.name.toUpperCase())
}
```