This is intentional - `catch` delegates to `then`, so that a subclass that overwrites `then` doesn't have to also override `catch` (and the same for `finally`, which also calls into `then`).
On Fri, Jul 20, 2018 at 4:29 AM, Darien Valentine <valentin...@gmail.com> wrote: > In `Promise.prototype.then`: > > > 1. Let promise be the this value. > > 2. If IsPromise(promise) is false, throw a TypeError exception. > > [ ... ] > > In `Promise.prototype.finally`: > > > 1. Let promise be the this value. > > 2. If Type(promise) is not Object, throw a TypeError exception. > > [...] > > In `Promise.prototype.catch`: > > > 1. Let promise be the this value. > > 2. Return ? Invoke(promise, "then", « undefined, onRejected »). > > First, this means that only `then` requires the this value to be a Promise: > > ```js > for (const key of [ 'then', 'finally', 'catch' ]) { > try { > Promise.prototype[key].call({ > then: () => console.log(`${ key } doesn’t brand check its this > value`) > }); > } catch (err) { > console.log(`${ key } does brand check its this value`); > } > } > > // > then does brand check its this value > // > finally doesn’t brand check its this value > // > catch doesn’t brand check its this value > ``` > > Second, note that `Invoke` uses `GetV`, not `Get`. Thus: > > ```js > for (const key of [ 'then', 'finally', 'catch' ]) { > try { > String.prototype.then = () => > console.log(`${ key } casts this value to object`); > > Promise.prototype[key].call('foo'); > } catch (err) { > console.log(`${ key } doesn’t cast this value to object`); > } > } > > // > then doesn’t cast this value to object > // > finally doesn’t cast this value to object > // > catch casts this value to object > ``` > > On reflection, I think I see the logic to this: > > - `Promise.prototype.then` ends up executing `PerformPromiseThen`, which > requires its first argument to be a native promise object. > - `Promise.prototype.finally` ends up executing `SpeciesConstructor`, > which requires its first argument to be an object. > - `Promise.prototype.catch` does neither. > > However the inconsistency within this trio seems pretty odd to me. I > suppose I would have expected them all to be as constrained as the most > constrained method needed to be for the sake of uniformity, given that they > constitute a single API. Conversely, if the goal was for each method to be > exactly as lenient as is possible, then `finally` seems to be > over-constrained; it seems like `C` could have just defaulted to `Promise` > in cases where `SpeciesConstructor` wasn’t applicable, making it as lenient > as `catch`. > > I wasn’t able to find prior discussion about this, though it’s a bit hard > to search for, so I may be missing it. Do these behaviors seem odd to > anyone else, or is it what you’d expect? > > _______________________________________________ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss