Continuations and forEach vs. for each

NEW
Unassigned

Status

10 years ago
10 years ago

People

(Reporter: johnandtina, Unassigned)

Tracking

1.7R1
x86
Windows XP

Details

(Reporter)

Description

10 years ago
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16
Build Identifier: 7R1

Trying out continuations, I wrote a couple coroutines using 'forEach'.  They didn't work properly. Changing one of them to 'for each' made them both work.

Reproducible: Always

Steps to Reproduce:
Run the following code:

$ java -jar rhino1_7R1/js.jar -opt -1
Rhino 1.7 release 1 2008 03 06
js> function call_cc(fun) { return fun(new Continuation()) }  
js> function coletters(other_cc) {
  >     ["a", "b", "c"].forEach( function(letter) {
  >             print(letter)
  >             other_cc = call_cc(other_cc)
  >     } )
  > }
js> function conumbers(other_cc) {
  >     [1, 2, 3].forEach( function(number) {
  >             print(number)
  >             other_cc = call_cc(other_cc)
  >     } )
  > }
js> conumbers(coletters)

Actual Results:  
1
a
b
c
2
js: "<stdin>", line 2: uncaught JavaScript runtime exception: TypeError: org.mozilla.javascript.Undefined@c4bcdc is not a function, it is undefined.
        at <stdin>:2 (call_cc)
        at <stdin>:17
        at <stdin>:15 (conumbers)
        at <stdin>:15


Expected Results:  
1
a
2
b
3
c

Yet this works:

$ java -jar rhino1_7R1/js.jar -opt -1
Rhino 1.7 release 1 2008 03 06
js> function call_cc(fun) { return fun(new Continuation()) }
js> function coletters(other_cc) {
  >     for each (var letter in ["a", "b", "c"]) {
  >             print(letter)
  >             other_cc = call_cc(other_cc)
  >     }
  > }
js>  function conumbers(other_cc) {
  >     [1, 2, 3].forEach( function(number) {
  >             print(number)
  >             other_cc = call_cc(other_cc)
  >     } )
  > }
js> conumbers(coletters)
1
a
2
b
3
c

The order (conumbers(coletters) vs. coletters(conumbers)) doesn't make a difference in either case.
(Reporter)

Updated

10 years ago
Version: other → 1.7R1

Comment 1

10 years ago
Indeed -- the problem is that continuations only work if the execution doesn't cross from JS code to Java code and then back to JS. As it happens, all array comprehension methods are implemented in Java, therefore continuations captured from their callback functions won't work.

A workaround you can attempt is to redefine forEach in JavaScript. Go here: <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach>
and take the JS code of forEach from the page's "Compatibility" section, and add it to your scripts (without the outermost "if"), as this:

  Array.prototype.forEach = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };

I'll confirm the bug, but am not sure about its solution... We could maybe provide such redefinition automatically for interpreted contexts as part of Context.initStandardObjects. I'd like to consult on this with other team members.
Status: UNCONFIRMED → NEW
Ever confirmed: true
You need to log in before you can comment on or make changes to this bug.