mirror of
https://github.com/Doodle3D/Doodle3D-API
synced 2024-12-23 14:13:47 +01:00
267 lines
7.4 KiB
JavaScript
267 lines
7.4 KiB
JavaScript
/* */
|
|
(function(process) {
|
|
'use strict';
|
|
var $ = require("./$"),
|
|
ctx = require("./$.ctx"),
|
|
cof = require("./$.cof"),
|
|
$def = require("./$.def"),
|
|
assert = require("./$.assert"),
|
|
forOf = require("./$.for-of"),
|
|
setProto = require("./$.set-proto").set,
|
|
same = require("./$.same"),
|
|
species = require("./$.species"),
|
|
SPECIES = require("./$.wks")('species'),
|
|
RECORD = require("./$.uid").safe('record'),
|
|
PROMISE = 'Promise',
|
|
global = $.g,
|
|
process = global.process,
|
|
isNode = cof(process) == 'process',
|
|
asap = process && process.nextTick || require("./$.task").set,
|
|
P = global[PROMISE],
|
|
isFunction = $.isFunction,
|
|
isObject = $.isObject,
|
|
assertFunction = assert.fn,
|
|
assertObject = assert.obj,
|
|
Wrapper;
|
|
function testResolve(sub) {
|
|
var test = new P(function() {});
|
|
if (sub)
|
|
test.constructor = Object;
|
|
return P.resolve(test) === test;
|
|
}
|
|
var useNative = function() {
|
|
var works = false;
|
|
function P2(x) {
|
|
var self = new P(x);
|
|
setProto(self, P2.prototype);
|
|
return self;
|
|
}
|
|
try {
|
|
works = isFunction(P) && isFunction(P.resolve) && testResolve();
|
|
setProto(P2, P);
|
|
P2.prototype = $.create(P.prototype, {constructor: {value: P2}});
|
|
if (!(P2.resolve(5).then(function() {}) instanceof P2)) {
|
|
works = false;
|
|
}
|
|
if (works && $.DESC) {
|
|
var thenableThenGotten = false;
|
|
P.resolve($.setDesc({}, 'then', {get: function() {
|
|
thenableThenGotten = true;
|
|
}}));
|
|
works = thenableThenGotten;
|
|
}
|
|
} catch (e) {
|
|
works = false;
|
|
}
|
|
return works;
|
|
}();
|
|
function isPromise(it) {
|
|
return isObject(it) && (useNative ? cof.classof(it) == 'Promise' : RECORD in it);
|
|
}
|
|
function sameConstructor(a, b) {
|
|
if (!$.FW && a === P && b === Wrapper)
|
|
return true;
|
|
return same(a, b);
|
|
}
|
|
function getConstructor(C) {
|
|
var S = assertObject(C)[SPECIES];
|
|
return S != undefined ? S : C;
|
|
}
|
|
function isThenable(it) {
|
|
var then;
|
|
if (isObject(it))
|
|
then = it.then;
|
|
return isFunction(then) ? then : false;
|
|
}
|
|
function notify(record) {
|
|
var chain = record.c;
|
|
if (chain.length)
|
|
asap.call(global, function() {
|
|
var value = record.v,
|
|
ok = record.s == 1,
|
|
i = 0;
|
|
function run(react) {
|
|
var cb = ok ? react.ok : react.fail,
|
|
ret,
|
|
then;
|
|
try {
|
|
if (cb) {
|
|
if (!ok)
|
|
record.h = true;
|
|
ret = cb === true ? value : cb(value);
|
|
if (ret === react.P) {
|
|
react.rej(TypeError('Promise-chain cycle'));
|
|
} else if (then = isThenable(ret)) {
|
|
then.call(ret, react.res, react.rej);
|
|
} else
|
|
react.res(ret);
|
|
} else
|
|
react.rej(value);
|
|
} catch (err) {
|
|
react.rej(err);
|
|
}
|
|
}
|
|
while (chain.length > i)
|
|
run(chain[i++]);
|
|
chain.length = 0;
|
|
});
|
|
}
|
|
function isUnhandled(promise) {
|
|
var record = promise[RECORD],
|
|
chain = record.a || record.c,
|
|
i = 0,
|
|
react;
|
|
if (record.h)
|
|
return false;
|
|
while (chain.length > i) {
|
|
react = chain[i++];
|
|
if (react.fail || !isUnhandled(react.P))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
function $reject(value) {
|
|
var record = this,
|
|
promise;
|
|
if (record.d)
|
|
return ;
|
|
record.d = true;
|
|
record = record.r || record;
|
|
record.v = value;
|
|
record.s = 2;
|
|
record.a = record.c.slice();
|
|
setTimeout(function() {
|
|
asap.call(global, function() {
|
|
if (isUnhandled(promise = record.p)) {
|
|
if (isNode) {
|
|
process.emit('unhandledRejection', value, promise);
|
|
} else if (global.console && console.error) {
|
|
console.error('Unhandled promise rejection', value);
|
|
}
|
|
}
|
|
record.a = undefined;
|
|
});
|
|
}, 1);
|
|
notify(record);
|
|
}
|
|
function $resolve(value) {
|
|
var record = this,
|
|
then;
|
|
if (record.d)
|
|
return ;
|
|
record.d = true;
|
|
record = record.r || record;
|
|
try {
|
|
if (then = isThenable(value)) {
|
|
asap.call(global, function() {
|
|
var wrapper = {
|
|
r: record,
|
|
d: false
|
|
};
|
|
try {
|
|
then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
|
|
} catch (e) {
|
|
$reject.call(wrapper, e);
|
|
}
|
|
});
|
|
} else {
|
|
record.v = value;
|
|
record.s = 1;
|
|
notify(record);
|
|
}
|
|
} catch (e) {
|
|
$reject.call({
|
|
r: record,
|
|
d: false
|
|
}, e);
|
|
}
|
|
}
|
|
if (!useNative) {
|
|
P = function Promise(executor) {
|
|
assertFunction(executor);
|
|
var record = {
|
|
p: assert.inst(this, P, PROMISE),
|
|
c: [],
|
|
a: undefined,
|
|
s: 0,
|
|
d: false,
|
|
v: undefined,
|
|
h: false
|
|
};
|
|
$.hide(this, RECORD, record);
|
|
try {
|
|
executor(ctx($resolve, record, 1), ctx($reject, record, 1));
|
|
} catch (err) {
|
|
$reject.call(record, err);
|
|
}
|
|
};
|
|
require("./$.mix")(P.prototype, {
|
|
then: function then(onFulfilled, onRejected) {
|
|
var S = assertObject(assertObject(this).constructor)[SPECIES];
|
|
var react = {
|
|
ok: isFunction(onFulfilled) ? onFulfilled : true,
|
|
fail: isFunction(onRejected) ? onRejected : false
|
|
};
|
|
var promise = react.P = new (S != undefined ? S : P)(function(res, rej) {
|
|
react.res = assertFunction(res);
|
|
react.rej = assertFunction(rej);
|
|
});
|
|
var record = this[RECORD];
|
|
record.c.push(react);
|
|
if (record.a)
|
|
record.a.push(react);
|
|
if (record.s)
|
|
notify(record);
|
|
return promise;
|
|
},
|
|
'catch': function(onRejected) {
|
|
return this.then(undefined, onRejected);
|
|
}
|
|
});
|
|
}
|
|
$def($def.G + $def.W + $def.F * !useNative, {Promise: P});
|
|
cof.set(P, PROMISE);
|
|
species(P);
|
|
species(Wrapper = $.core[PROMISE]);
|
|
$def($def.S + $def.F * !useNative, PROMISE, {reject: function reject(r) {
|
|
return new (getConstructor(this))(function(res, rej) {
|
|
rej(r);
|
|
});
|
|
}});
|
|
$def($def.S + $def.F * (!useNative || testResolve(true)), PROMISE, {resolve: function resolve(x) {
|
|
return isPromise(x) && sameConstructor(x.constructor, this) ? x : new this(function(res) {
|
|
res(x);
|
|
});
|
|
}});
|
|
$def($def.S + $def.F * !(useNative && require("./$.iter-detect")(function(iter) {
|
|
P.all(iter)['catch'](function() {});
|
|
})), PROMISE, {
|
|
all: function all(iterable) {
|
|
var C = getConstructor(this),
|
|
values = [];
|
|
return new C(function(res, rej) {
|
|
forOf(iterable, false, values.push, values);
|
|
var remaining = values.length,
|
|
results = Array(remaining);
|
|
if (remaining)
|
|
$.each.call(values, function(promise, index) {
|
|
C.resolve(promise).then(function(value) {
|
|
results[index] = value;
|
|
--remaining || res(results);
|
|
}, rej);
|
|
});
|
|
else
|
|
res(results);
|
|
});
|
|
},
|
|
race: function race(iterable) {
|
|
var C = getConstructor(this);
|
|
return new C(function(res, rej) {
|
|
forOf(iterable, false, function(promise) {
|
|
C.resolve(promise).then(res, rej);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
})(require("process"));
|