drummerSupport icon indicating copy to clipboard operation
drummerSupport copied to clipboard

Scripts that use forEach (and probably other uses of callbacks)

Open scripting opened this issue 4 years ago • 3 comments

@andrewshell --

I haven't had the time to dig in on this, but when writing sample scripts, I've noticed they behave weirdly if I use the built-in JavaScript forEach function, or one of the op.xxx visit routines such as op.visitAll.

I'm putting this note here as a reminder to write some minimal code that causes it to fail, if my observation turns out to be correct.

Obviously no rush on this, I'm digging in another space right now, working to get a better communication path for updates for users, eventually not just for testers.

Hope all is well! :-)

scripting avatar Aug 05 '21 15:08 scripting

attn @allenwb -- do you want to look into this?

scripting avatar Aug 08 '21 15:08 scripting

I haven't look into this, but I'm going to predict what think I will find:

You are converting (at the point of definition) the callback function into an async function). Async function always return a promise as their result. It is the await that converts the promise result into the normal value.

Builtin methods such as Array forEach or map are not expecting async function to be passed into them as callback parameters. So, they don't await their internal callback calls and the callback result they see is the promise.

This probably isn't a problem for Array forEach or any other method that ignores the callback result. But method such as Array map that do something with the callback result will either break or do something nonsensical.

I'll verify thisl

allenwb avatar Aug 08 '21 17:08 allenwb

yup, here's a script test case:

function f () {debugger; return [1,2,3,4].map(function(x){return x+1})}
dialog.alert(f());

which generates this code:

(async function () {async function f() {
    debugger;
    return await [
        1,
        2,
        3,
        4
    ].map(async function (x) {
        return x + 1;
    });
}
await dialog.alert(await f());})()

When run, the message in the alert is:

[object Promise],[object Promise],[object Promise],[object Promise]

but rewriting the call back as in:

function f () {debugger; return [1,2,3,4].map(x=>x+1)}
dialog.alert(f());

produces:

2,3,4,5

which is the expected result. The reason is that you aren't translating arrow functions into async arrow functions.

(async function () {async function f() {
    debugger;
    return await [
        1,
        2,
        3,
        4
    ].map(x => x + 1);
}
await dialog.alert(await f());})()

allenwb avatar Aug 08 '21 18:08 allenwb