Igor Baklan (2017-01-12T14:22:04.000Z)
Introduction of promise.return() and promise.throw() similar to
generator.return() and generator.throw() can be helpful

Assuming analogy in tuples ([``function*``](https://
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
Statements/function*), [``yield``](https://developer.
mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield),
[``Generator.prototype.return()``](https://developer.
mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_
Objects/Generator/return), [``Generator.prototype.throw()``](
https://developer.mozilla.org/en-US/docs/Web/JavaScript/
Reference/Global_Objects/Generator/throw) ) and ([``async function``](
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
Operators/async_function), [``await``](https://developer.
mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await),
``?Promise.prototype.return()``, ``?Promise.prototype.throw()``), it would
be good to have ``Promise.prototype.return()`` and
``Promise.prototype.throw()`` which in case of ``async``/``await`` function
should just "inject" some [``return``](https://developer.mozilla.org/en-US/
docs/Web/JavaScript/Reference/Statements/return)/[``throw``]
(https://developer.mozilla.org/en-US/docs/Web/JavaScript/
Reference/Statements/throw
<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return)/%5Bthrow%5D(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw>)
action in place of pending ``await`` statement.

While for ``.then``-like promises it should just force promise to abnormal
completion (with provided result) without calling callbacks provided in
.``then``/.``catch`` methods (if they was not yet called before, at the
time of "abruption" attempt).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170112/99894aea/attachment.html>
io.baklan at gmail.com (2017-01-12T14:23:55.469Z)
Assuming analogy in tuples ([``function*``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*), [``yield``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield), [``Generator.prototype.return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return), [``Generator.prototype.throw()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw) ) and ([``async function``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/async_function), [``await``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await), ``?Promise.prototype.return()``, ``?Promise.prototype.throw()``), it would be good to have ``Promise.prototype.return()`` and ``Promise.prototype.throw()`` which in case of ``async``/``await`` function should just "inject" some [``return``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return)/[``throw``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw) action in place of pending ``await`` statement. 

While for ``.then``-like promises it should just force promise to abnormal completion (with provided result) without calling callbacks provided in .``then``/.``catch`` methods (if they was not yet called before, at the time of "abruption" attempt). 

In case of general [``new Promise(promiseExecutor)``](
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)-like promises it supposedly should work in following manner: some ``abnormalReturn`` / ``abnormalThrow`` signals should be sent to [``promiseExecutor``](
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters), then [``promiseExecutor``](
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters) can handle this signal and initialte "``preventDefault`` behavior" which will correspond to ``catch``/``finally`` blocks capabilities, or  [``promiseExecutor``](
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters) can ignore and not handle this signals, then default behavior should be invoked (which will lead to promise abnormal completion with value provided in ``Promise.prototype.return(...)``/``Promise.prototype.throw()`` call) - this second option will correspond to that case when assumptive
 meta-code of [``promiseExecutor``](
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters) does not contain imaginary ``catch``/``finally`` blocks.

In code that last case might look like this:

```js
const waitAsync = (delay) => (new Promise(
  (setOk, setErr, signalsSource) => {
    const beforeComplete = () => {clearTimeout(tid);}
    const tid = setTimeout(
      () => {beforeComplete(); setOk();},
      delay
    );
    signalsSource.on(
      "abnormalReturn", (abnormalReturnSignal) => {
        if (abnormalReturnSignal.value < 5) {
          // reject offered for abnormal rerun value when it < 5
          abnormalReturnSignal.preventDefault();
          return;
        }
        // do some finally-like cleanup assuming that 
        // abnormalReturnSignal default behavior will be launched
        beforeComplete();
    );
    signalsSource.on(
      "abnormalThrow", (abnormalThrowSignal) => {
        if (abnormalThrowSignal.value instanceof HatedError) {
          // catch and reject HatedError-es, corresponds to catching this one 
          // and re-throwing/propagating anything else by abnormalThrowSignal default behavior
          abnormalThrowSignal.preventDefault();
          return;
        }
        // do some finally-like cleanup assuming that 
        // abnormalThrowSignal default behavior will be launched
        beforeComplete();
    );
  }
));

// waitTask = waitAsync(100);
// waitTask.then((value) => {console.log(`wait ok, value = ${value}`)});
// waitTask.return(3); - abnormal return should be rejected by promice executor logic, since 3 < 5
// waitTask.return(103); - abnormal return should happen since !(103 < 5) and default behavior should work

//   "wait ok, value = 100" message should be printed, without delay in 100ms
```

In case if some transpiler decide to implement ``async function``s using [generator functions]((https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*)) this ``promise.return(...)`` and ``promise.throw(...)`` functions can be obtained almost out-of-the-box using [``Generator.prototype.return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) and [``Generator.prototype.throw()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw).

Approximately it might look like:

```js
var someFunctionToTranslate = function (...args) {
   // ... some code here ...
   var someValue = await somePromice;
   // ... some code here ...
};
```
might be translated to

```js
var someFunctionToTranslate = _rawGeneratorFuncToNormalAsyncLikeFunc(function* (...args) {
   // ... some translated code here ...
   var _tmpAwaitTask = new AwaitTask(somePromice);
   yield _tmpAwaitTask;
   var someValue = _tmpAwaitTask.awaitResult;
   // ... some translated code here ...
});
```
Then ``promice.return(...)`` on obtained promise should cause ``generator.return(...)`` on underling generator object, and lead to abnormal completion delivered through ``yield`` instruction which here represents a part of ``await`` statement translation.

By the way during my reading of [``Generator#return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) and [``Generator#throw()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw) after reading [bluebirdjs-cancellation](
http://bluebirdjs.com/docs/api/cancellation.html) I've suddenly aware that native ``return`` statement can be "completely rejected" by the means of ``finally`` block, meaning that in general for example there are no 100%-guaranties that [``Generator#return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) will force generator to stop iterating same as there are either no guaranties that [``Generator#throw()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw) will force generator to stop (but this one is more obvious regarding ``catch`` statement natural behavior).

Here is some patched example from [``Generator#return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return)

```js
function* gen() { 
  // shielded yield 1
  do { try { yield 1; } finally{ continue; } } while (false);
  // shielded yield 2
  do { try { yield 2; } finally{ continue; } } while (false);
  // shielded yield 3
  do { try { yield 3; } finally{ continue; } } while (false);
}

var g = gen();

console.log(g.next());        // { value: 1, done: false }
console.log(g.return("foo")); // { value: 2, done: false } // impudent generator rejects return
console.log(g.return("bar")); // { value: 3, done: false } // impudent generator rejects return
console.log(g.next());        // { value: undefined, done: true } // generator finishes by its own will
```

So considering this possibility, I would say, in case if ``promise.return()`` would be implemented, provide possibility to [promiseExecutor](
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters) to intercept and override ``.return()`` action is quit natural (assuming that by default it will not handle that signals and not ``preventDefault`` on it, and that means - in general work like regular code without ``finally``/strange-``finally`` blocks)