graaljs icon indicating copy to clipboard operation
graaljs copied to clipboard

[Bug]: Using async function to Symbol.iterator results in infinite loop

Open p51lee opened this issue 2 years ago • 2 comments

// input.js
var obj = {
  [ Symbol . iterator ]: async ( ) => {
      await 0 ;
      while ( true ) ;
  }
}

for ( { } of obj );

Hello,

I think the input code should throw TypeError and the while (true) loop under await 0 should not be executed:

image but running it using GraalJS results in infinite loop:
$ js --version
GraalVM JavaScript (GraalVM CE Native 22.2.0)
$ js input.js

// infinite loop
^C

Interestingly, V8 has a similar bug:

$ d8 input.js
input.js:8: TypeError: undefined is not a function
for ( { } of obj );
      ^
TypeError: undefined is not a function
    at input.js:8:7

// infinite loop
^C

but NodeJS terminates well:

$ node input.js
input.js:8
for ( { } of obj );
      ^

TypeError: undefined is not a function
...

Node.js v18.11.0

p51lee avatar Nov 11 '22 09:11 p51lee

Let me explain what is going on here. The provided async function is invoked to obtain the iterator. There is no special handling for async functions here. So, the returned Promise (that corresponds to the body of the async function) is being interpreted as the iterator. The promise does not have next method. Hence, TypeError occurs (when next is invoked). Unfortunately, there is still the infinite promise job trying to resolve the promise.

In fact, graal-js throws the TypeError but for some technical reasons the js launcher postpones the output of this error into the console until the promise job queue is empty. This never happens in this case.

You can verify that graal-js throws the TypeError if you replace the last line of your test-case by

try {
    for ( { } of obj );
} catch (e) {
    console.log(e);
}

So, the described behaviour can be considered as a confusing behaviour of js launcher but it cannot be considered as non-compliant behaviour with respect to ECMAScript specification. The specification does not cover how and when the user is informed about the abrupt completion of the top-level script.

iamstolis avatar Nov 11 '22 11:11 iamstolis

Thank you for your detailed explanation!

p51lee avatar Nov 11 '22 11:11 p51lee