oracle / graaljs

A high-performance, ECMAScript compliant, and embeddable JavaScript runtime for Java
https://www.graalvm.org/javascript/
Universal Permissive License v1.0
1.8k stars 190 forks source link

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

Open p51lee opened 1 year ago

p51lee commented 1 year ago
// 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
iamstolis commented 1 year ago

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.

p51lee commented 1 year ago

Thank you for your detailed explanation!