web 3d图形渲染器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

381 lines
13 KiB

  1. 'use strict';
  2. var $ = require('../internals/export');
  3. var IS_PURE = require('../internals/is-pure');
  4. var global = require('../internals/global');
  5. var getBuiltIn = require('../internals/get-built-in');
  6. var NativePromise = require('../internals/native-promise-constructor');
  7. var redefine = require('../internals/redefine');
  8. var redefineAll = require('../internals/redefine-all');
  9. var setToStringTag = require('../internals/set-to-string-tag');
  10. var setSpecies = require('../internals/set-species');
  11. var isObject = require('../internals/is-object');
  12. var aFunction = require('../internals/a-function');
  13. var anInstance = require('../internals/an-instance');
  14. var inspectSource = require('../internals/inspect-source');
  15. var iterate = require('../internals/iterate');
  16. var checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');
  17. var speciesConstructor = require('../internals/species-constructor');
  18. var task = require('../internals/task').set;
  19. var microtask = require('../internals/microtask');
  20. var promiseResolve = require('../internals/promise-resolve');
  21. var hostReportErrors = require('../internals/host-report-errors');
  22. var newPromiseCapabilityModule = require('../internals/new-promise-capability');
  23. var perform = require('../internals/perform');
  24. var InternalStateModule = require('../internals/internal-state');
  25. var isForced = require('../internals/is-forced');
  26. var wellKnownSymbol = require('../internals/well-known-symbol');
  27. var IS_NODE = require('../internals/engine-is-node');
  28. var V8_VERSION = require('../internals/engine-v8-version');
  29. var SPECIES = wellKnownSymbol('species');
  30. var PROMISE = 'Promise';
  31. var getInternalState = InternalStateModule.get;
  32. var setInternalState = InternalStateModule.set;
  33. var getInternalPromiseState = InternalStateModule.getterFor(PROMISE);
  34. var PromiseConstructor = NativePromise;
  35. var TypeError = global.TypeError;
  36. var document = global.document;
  37. var process = global.process;
  38. var $fetch = getBuiltIn('fetch');
  39. var newPromiseCapability = newPromiseCapabilityModule.f;
  40. var newGenericPromiseCapability = newPromiseCapability;
  41. var DISPATCH_EVENT = !!(document && document.createEvent && global.dispatchEvent);
  42. var NATIVE_REJECTION_EVENT = typeof PromiseRejectionEvent == 'function';
  43. var UNHANDLED_REJECTION = 'unhandledrejection';
  44. var REJECTION_HANDLED = 'rejectionhandled';
  45. var PENDING = 0;
  46. var FULFILLED = 1;
  47. var REJECTED = 2;
  48. var HANDLED = 1;
  49. var UNHANDLED = 2;
  50. var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen;
  51. var FORCED = isForced(PROMISE, function () {
  52. var GLOBAL_CORE_JS_PROMISE = inspectSource(PromiseConstructor) !== String(PromiseConstructor);
  53. if (!GLOBAL_CORE_JS_PROMISE) {
  54. // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
  55. // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
  56. // We can't detect it synchronously, so just check versions
  57. if (V8_VERSION === 66) return true;
  58. // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
  59. if (!IS_NODE && !NATIVE_REJECTION_EVENT) return true;
  60. }
  61. // We need Promise#finally in the pure version for preventing prototype pollution
  62. if (IS_PURE && !PromiseConstructor.prototype['finally']) return true;
  63. // We can't use @@species feature detection in V8 since it causes
  64. // deoptimization and performance degradation
  65. // https://github.com/zloirock/core-js/issues/679
  66. if (V8_VERSION >= 51 && /native code/.test(PromiseConstructor)) return false;
  67. // Detect correctness of subclassing with @@species support
  68. var promise = PromiseConstructor.resolve(1);
  69. var FakePromise = function (exec) {
  70. exec(function () { /* empty */ }, function () { /* empty */ });
  71. };
  72. var constructor = promise.constructor = {};
  73. constructor[SPECIES] = FakePromise;
  74. return !(promise.then(function () { /* empty */ }) instanceof FakePromise);
  75. });
  76. var INCORRECT_ITERATION = FORCED || !checkCorrectnessOfIteration(function (iterable) {
  77. PromiseConstructor.all(iterable)['catch'](function () { /* empty */ });
  78. });
  79. // helpers
  80. var isThenable = function (it) {
  81. var then;
  82. return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
  83. };
  84. var notify = function (state, isReject) {
  85. if (state.notified) return;
  86. state.notified = true;
  87. var chain = state.reactions;
  88. microtask(function () {
  89. var value = state.value;
  90. var ok = state.state == FULFILLED;
  91. var index = 0;
  92. // variable length - can't use forEach
  93. while (chain.length > index) {
  94. var reaction = chain[index++];
  95. var handler = ok ? reaction.ok : reaction.fail;
  96. var resolve = reaction.resolve;
  97. var reject = reaction.reject;
  98. var domain = reaction.domain;
  99. var result, then, exited;
  100. try {
  101. if (handler) {
  102. if (!ok) {
  103. if (state.rejection === UNHANDLED) onHandleUnhandled(state);
  104. state.rejection = HANDLED;
  105. }
  106. if (handler === true) result = value;
  107. else {
  108. if (domain) domain.enter();
  109. result = handler(value); // can throw
  110. if (domain) {
  111. domain.exit();
  112. exited = true;
  113. }
  114. }
  115. if (result === reaction.promise) {
  116. reject(TypeError('Promise-chain cycle'));
  117. } else if (then = isThenable(result)) {
  118. then.call(result, resolve, reject);
  119. } else resolve(result);
  120. } else reject(value);
  121. } catch (error) {
  122. if (domain && !exited) domain.exit();
  123. reject(error);
  124. }
  125. }
  126. state.reactions = [];
  127. state.notified = false;
  128. if (isReject && !state.rejection) onUnhandled(state);
  129. });
  130. };
  131. var dispatchEvent = function (name, promise, reason) {
  132. var event, handler;
  133. if (DISPATCH_EVENT) {
  134. event = document.createEvent('Event');
  135. event.promise = promise;
  136. event.reason = reason;
  137. event.initEvent(name, false, true);
  138. global.dispatchEvent(event);
  139. } else event = { promise: promise, reason: reason };
  140. if (!NATIVE_REJECTION_EVENT && (handler = global['on' + name])) handler(event);
  141. else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
  142. };
  143. var onUnhandled = function (state) {
  144. task.call(global, function () {
  145. var promise = state.facade;
  146. var value = state.value;
  147. var IS_UNHANDLED = isUnhandled(state);
  148. var result;
  149. if (IS_UNHANDLED) {
  150. result = perform(function () {
  151. if (IS_NODE) {
  152. process.emit('unhandledRejection', value, promise);
  153. } else dispatchEvent(UNHANDLED_REJECTION, promise, value);
  154. });
  155. // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
  156. state.rejection = IS_NODE || isUnhandled(state) ? UNHANDLED : HANDLED;
  157. if (result.error) throw result.value;
  158. }
  159. });
  160. };
  161. var isUnhandled = function (state) {
  162. return state.rejection !== HANDLED && !state.parent;
  163. };
  164. var onHandleUnhandled = function (state) {
  165. task.call(global, function () {
  166. var promise = state.facade;
  167. if (IS_NODE) {
  168. process.emit('rejectionHandled', promise);
  169. } else dispatchEvent(REJECTION_HANDLED, promise, state.value);
  170. });
  171. };
  172. var bind = function (fn, state, unwrap) {
  173. return function (value) {
  174. fn(state, value, unwrap);
  175. };
  176. };
  177. var internalReject = function (state, value, unwrap) {
  178. if (state.done) return;
  179. state.done = true;
  180. if (unwrap) state = unwrap;
  181. state.value = value;
  182. state.state = REJECTED;
  183. notify(state, true);
  184. };
  185. var internalResolve = function (state, value, unwrap) {
  186. if (state.done) return;
  187. state.done = true;
  188. if (unwrap) state = unwrap;
  189. try {
  190. if (state.facade === value) throw TypeError("Promise can't be resolved itself");
  191. var then = isThenable(value);
  192. if (then) {
  193. microtask(function () {
  194. var wrapper = { done: false };
  195. try {
  196. then.call(value,
  197. bind(internalResolve, wrapper, state),
  198. bind(internalReject, wrapper, state)
  199. );
  200. } catch (error) {
  201. internalReject(wrapper, error, state);
  202. }
  203. });
  204. } else {
  205. state.value = value;
  206. state.state = FULFILLED;
  207. notify(state, false);
  208. }
  209. } catch (error) {
  210. internalReject({ done: false }, error, state);
  211. }
  212. };
  213. // constructor polyfill
  214. if (FORCED) {
  215. // 25.4.3.1 Promise(executor)
  216. PromiseConstructor = function Promise(executor) {
  217. anInstance(this, PromiseConstructor, PROMISE);
  218. aFunction(executor);
  219. Internal.call(this);
  220. var state = getInternalState(this);
  221. try {
  222. executor(bind(internalResolve, state), bind(internalReject, state));
  223. } catch (error) {
  224. internalReject(state, error);
  225. }
  226. };
  227. // eslint-disable-next-line no-unused-vars -- required for `.length`
  228. Internal = function Promise(executor) {
  229. setInternalState(this, {
  230. type: PROMISE,
  231. done: false,
  232. notified: false,
  233. parent: false,
  234. reactions: [],
  235. rejection: false,
  236. state: PENDING,
  237. value: undefined
  238. });
  239. };
  240. Internal.prototype = redefineAll(PromiseConstructor.prototype, {
  241. // `Promise.prototype.then` method
  242. // https://tc39.es/ecma262/#sec-promise.prototype.then
  243. then: function then(onFulfilled, onRejected) {
  244. var state = getInternalPromiseState(this);
  245. var reaction = newPromiseCapability(speciesConstructor(this, PromiseConstructor));
  246. reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
  247. reaction.fail = typeof onRejected == 'function' && onRejected;
  248. reaction.domain = IS_NODE ? process.domain : undefined;
  249. state.parent = true;
  250. state.reactions.push(reaction);
  251. if (state.state != PENDING) notify(state, false);
  252. return reaction.promise;
  253. },
  254. // `Promise.prototype.catch` method
  255. // https://tc39.es/ecma262/#sec-promise.prototype.catch
  256. 'catch': function (onRejected) {
  257. return this.then(undefined, onRejected);
  258. }
  259. });
  260. OwnPromiseCapability = function () {
  261. var promise = new Internal();
  262. var state = getInternalState(promise);
  263. this.promise = promise;
  264. this.resolve = bind(internalResolve, state);
  265. this.reject = bind(internalReject, state);
  266. };
  267. newPromiseCapabilityModule.f = newPromiseCapability = function (C) {
  268. return C === PromiseConstructor || C === PromiseWrapper
  269. ? new OwnPromiseCapability(C)
  270. : newGenericPromiseCapability(C);
  271. };
  272. if (!IS_PURE && typeof NativePromise == 'function') {
  273. nativeThen = NativePromise.prototype.then;
  274. // wrap native Promise#then for native async functions
  275. redefine(NativePromise.prototype, 'then', function then(onFulfilled, onRejected) {
  276. var that = this;
  277. return new PromiseConstructor(function (resolve, reject) {
  278. nativeThen.call(that, resolve, reject);
  279. }).then(onFulfilled, onRejected);
  280. // https://github.com/zloirock/core-js/issues/640
  281. }, { unsafe: true });
  282. // wrap fetch result
  283. if (typeof $fetch == 'function') $({ global: true, enumerable: true, forced: true }, {
  284. // eslint-disable-next-line no-unused-vars -- required for `.length`
  285. fetch: function fetch(input /* , init */) {
  286. return promiseResolve(PromiseConstructor, $fetch.apply(global, arguments));
  287. }
  288. });
  289. }
  290. }
  291. $({ global: true, wrap: true, forced: FORCED }, {
  292. Promise: PromiseConstructor
  293. });
  294. setToStringTag(PromiseConstructor, PROMISE, false, true);
  295. setSpecies(PROMISE);
  296. PromiseWrapper = getBuiltIn(PROMISE);
  297. // statics
  298. $({ target: PROMISE, stat: true, forced: FORCED }, {
  299. // `Promise.reject` method
  300. // https://tc39.es/ecma262/#sec-promise.reject
  301. reject: function reject(r) {
  302. var capability = newPromiseCapability(this);
  303. capability.reject.call(undefined, r);
  304. return capability.promise;
  305. }
  306. });
  307. $({ target: PROMISE, stat: true, forced: IS_PURE || FORCED }, {
  308. // `Promise.resolve` method
  309. // https://tc39.es/ecma262/#sec-promise.resolve
  310. resolve: function resolve(x) {
  311. return promiseResolve(IS_PURE && this === PromiseWrapper ? PromiseConstructor : this, x);
  312. }
  313. });
  314. $({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION }, {
  315. // `Promise.all` method
  316. // https://tc39.es/ecma262/#sec-promise.all
  317. all: function all(iterable) {
  318. var C = this;
  319. var capability = newPromiseCapability(C);
  320. var resolve = capability.resolve;
  321. var reject = capability.reject;
  322. var result = perform(function () {
  323. var $promiseResolve = aFunction(C.resolve);
  324. var values = [];
  325. var counter = 0;
  326. var remaining = 1;
  327. iterate(iterable, function (promise) {
  328. var index = counter++;
  329. var alreadyCalled = false;
  330. values.push(undefined);
  331. remaining++;
  332. $promiseResolve.call(C, promise).then(function (value) {
  333. if (alreadyCalled) return;
  334. alreadyCalled = true;
  335. values[index] = value;
  336. --remaining || resolve(values);
  337. }, reject);
  338. });
  339. --remaining || resolve(values);
  340. });
  341. if (result.error) reject(result.value);
  342. return capability.promise;
  343. },
  344. // `Promise.race` method
  345. // https://tc39.es/ecma262/#sec-promise.race
  346. race: function race(iterable) {
  347. var C = this;
  348. var capability = newPromiseCapability(C);
  349. var reject = capability.reject;
  350. var result = perform(function () {
  351. var $promiseResolve = aFunction(C.resolve);
  352. iterate(iterable, function (promise) {
  353. $promiseResolve.call(C, promise).then(capability.resolve, reject);
  354. });
  355. });
  356. if (result.error) reject(result.value);
  357. return capability.promise;
  358. }
  359. });