55 lines
1.2 KiB
JavaScript
55 lines
1.2 KiB
JavaScript
'use strict'
|
|
|
|
const ExtendableError = require('es6-error')
|
|
|
|
const constants = require('./constants')
|
|
|
|
class UnwrapError extends ExtendableError {
|
|
constructor (thenable) {
|
|
super('Could not unwrap asynchronous thenable')
|
|
this.thenable = thenable
|
|
}
|
|
}
|
|
|
|
// Logic is derived from the Promise Resolution Procedure, as described in the
|
|
// Promises/A+ specification: https://promisesaplus.com/#point-45
|
|
//
|
|
// Note that there is no cycle detection.
|
|
function unwrapSync (x) {
|
|
if (!x || typeof x !== 'object' && typeof x !== 'function') {
|
|
return x
|
|
}
|
|
|
|
const then = x.then
|
|
if (typeof then !== 'function') return x
|
|
|
|
let state = constants.PENDING
|
|
let value
|
|
const unwrapValue = y => {
|
|
if (state === constants.PENDING) {
|
|
state = constants.RESOLVED
|
|
value = y
|
|
}
|
|
}
|
|
const unwrapReason = r => {
|
|
if (state === constants.PENDING) {
|
|
state = constants.REJECTED
|
|
value = r
|
|
}
|
|
}
|
|
then.call(x, unwrapValue, unwrapReason)
|
|
|
|
if (state === constants.PENDING) {
|
|
state = constants.ASYNC
|
|
throw new UnwrapError(x)
|
|
}
|
|
|
|
if (state === constants.RESOLVED) {
|
|
return unwrapSync(value)
|
|
}
|
|
|
|
// state === REJECTED
|
|
throw value
|
|
}
|
|
module.exports = unwrapSync
|