Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error handling and asynchronous behavior in evaluate function #670

Open
jacobgoh101 opened this issue Feb 2, 2024 · 0 comments
Open

Error handling and asynchronous behavior in evaluate function #670

jacobgoh101 opened this issue Feb 2, 2024 · 0 comments

Comments

@jacobgoh101
Copy link

  1. Problem description: In the JSONata library, the evaluate function does not properly handle errors when a callback function is used. The error is thrown without being returned to the callback function, causing unhandled errors. It is expected that the error should be returned in the callback function. The problematic code can be found here:

    jsonata/src/jsonata.js

    Lines 2094 to 2141 in d7790e8

    evaluate: async function (input, bindings, callback) {
    // throw if the expression compiled with syntax errors
    if(typeof errors !== 'undefined') {
    var err = {
    code: 'S0500',
    position: 0
    };
    populateMessage(err); // possible side-effects on `err`
    throw err;
    }
    if (typeof bindings !== 'undefined') {
    var exec_env;
    // the variable bindings have been passed in - create a frame to hold these
    exec_env = createFrame(environment);
    for (var v in bindings) {
    exec_env.bind(v, bindings[v]);
    }
    } else {
    exec_env = environment;
    }
    // put the input document into the environment as the root object
    exec_env.bind('$', input);
    // capture the timestamp and put it in the execution environment
    // the $now() and $millis() functions will return this value - whenever it is called
    timestamp = new Date();
    exec_env.timestamp = timestamp;
    // if the input is a JSON array, then wrap it in a singleton sequence so it gets treated as a single input
    if(Array.isArray(input) && !isSequence(input)) {
    input = createSequence(input);
    input.outerWrapper = true;
    }
    var it;
    try {
    it = await evaluate(ast, input, exec_env);
    if (typeof callback === "function") {
    callback(null, it);
    }
    return it;
    } catch (err) {
    // insert error message into structure
    populateMessage(err); // possible side-effects on `err`
    throw err;
    }
    },

  2. Inconsistent behavior: The documentation and this comment suggests using a callback function to enable asynchronous mode. However, during testing, it seems that the asynchronous function gets evaluated regardless of whether a callback function is used or not.

    image image

Reproduction Steps:

  1. Use the evaluate function with a callback function to handle the result asynchronously.
  2. Trigger an error condition that should result in an error being returned.
  3. Observe that the error is not returned through the callback function, but instead thrown directly.

Expected Behavior:

When a callback function is used, the evaluate function should return the error through the callback function instead of throwing it directly. Additionally, the asynchronous behavior should only take effect when a valid callback function is provided.

Environment:

  • JSONata library version: 2.0.3
  • Operating System: macOS 13.4.1
  • Browser or Node.js version: Node v18.16.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant