ericmckean / traceur-compiler

Automatically exported from code.google.com/p/traceur-compiler
Apache License 2.0
0 stars 0 forks source link

Generators: 'throw' outside of a 'try' continues to rethrow. #202

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

1.
//--cut--
// paste into traceur repl (either node or web is fine)
function* G() {
  yield 1;
  throw 2;
  yield 3;
}

var g = G();

var i;
for (i = 0; i < 8; i++) {
  try {
    if(!g.moveNext())
      break;
    console.log(g.current);
  } catch(e) {
    console.log('caught exception: %s', e.toString());
  }
}
//--cut--

What is the expected output? What do you see instead?

The exception gets rethrown at every call to g.moveNext(); this is a
potential infinite loop.

The exception should only get thrown once, after which g.moveNext()
should just return false, without executing any more generator code.

What version of the product are you using? On what operating system?

branch master as of commit 293d46585f83addb

Please provide any additional information below.

Working on a tentative fix. It seems to work for simple examples at
least.

Original issue reported on code.google.com by usrbi...@yahoo.com on 10 Feb 2013 at 10:19

GoogleCodeExporter commented 9 years ago
The statemachine generates

          case 1:
            throw 2;
            $state = 5;
            break;

it seems like it should be sufficient to set the state before the throw?

Original comment by arv@chromium.org on 10 Feb 2013 at 10:26

GoogleCodeExporter commented 9 years ago
Using the example above, that would generate something like:

  1
  caught exception: 2
  3

So we still 'yield 3' when the generator should have already exited.

----

Another problem is that in the normal case when you 'throw' from inside
a 'try', the generated code actually relies upon the "early exit"
behavior that you noted with:

  try {
    case 1:
      throw 2;
      $state = 5;
      break;
    // ...
  } catch(e) {
    // ....
    case 1: // "mirror image" on the 'catch' side.
      // when something gets thrown while in state 1, do this
      $state = ...;
  }

----

The problem as I currently understand it is that the "mirror image"
is only generated for states inside a catch, when it should really be
generated wherever a 'throw' occurs. So there are actually more mirror
images created than are strictly necessary. The fix I currently have
doesn't fix that bug; it just fills in the missing mirror images, along
with making sure that we're in the end state before doing the final
throw that exits the generator.

I'll have the tentative patch up within an hour; just checking to see
that I didn't make any facepalm errors.

Original comment by usrbi...@yahoo.com on 11 Feb 2013 at 12:36

GoogleCodeExporter commented 9 years ago
https://code.google.com/p/traceur-compiler/source/detail?r=9bddf900b716f0bcb0a2a
0a1dd3aef6934815040

Original comment by arv@google.com on 11 Feb 2013 at 10:48