Task.Result API has unintuitive behavior

UNCONFIRMED
Unassigned

Status

()

UNCONFIRMED
5 years ago
5 years ago

People

(Reporter: jeremy, Unassigned)

Tracking

26 Branch
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

5 years ago
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0 conkeror/1.0pre (Beta/Release)
Build ID: git

Steps to reproduce:

Consider the code below:

Components.utils.import("resource://gre/modules/Task.jsm");
Task.spawn(function() {
  try {
    // do some stuff that may throw
    throw new Task.Result(1);
  } catch(e) {
      dump("Got exception: " + e + "\n");
      throw e;
  }
}).then(function(x) { dump("Result: " + x + "\n"); });



Actual results:

Got exception: [object Object]
Result: 1

Obviously this behavior is inherent to how exceptions work, but it is inconvenient that the only API for returning a value from a Task differs significantly in semantics from the normal return statement.


Expected results:

Result: 1

A better API would be to use the syntax:

yield Task.Result(x);

Supporting this syntax would be nearly backwards-compatible with existing code, in that only the edge case of using yield my_function(), where my_function() is a non-generation function that happens to return an instance of Task.Result, would be broken by supporting the new syntax (and it seems this would constitute a misuse of Task.Result in that case).  The existing throw-based syntax could also still be supported at the same time, but deprecated.

Note: The Conkeror web browser (based on Mozilla) has a coroutine implementation that is very similar in function to Task.jsm.  I faced this same issue in writing it, having initially chosen a throw-based API for returning values, and then switching to a yield-based one after realizing throw would have the wrong behavior with respect to catch clauses.
You need to log in before you can comment on or make changes to this bug.