Closed Bug 452501 Opened 16 years ago Closed 5 years ago

Continuations and forEach vs. for each

Categories

(Rhino Graveyard :: Core, defect)

1.7R1
x86
Windows XP
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED INACTIVE

People

(Reporter: johnandtina, Unassigned)

Details

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.
Version: other → 1.7R1
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

Closing. Bug management is now done here:
https://github.com/mozilla/rhino

Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → INACTIVE
You need to log in before you can comment on or make changes to this bug.