esnext.async-disposable-stack.constructor.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. 'use strict';
  2. // https://github.com/tc39/proposal-async-explicit-resource-management
  3. var $ = require('../internals/export');
  4. var DESCRIPTORS = require('../internals/descriptors');
  5. var getBuiltIn = require('../internals/get-built-in');
  6. var aCallable = require('../internals/a-callable');
  7. var anObject = require('../internals/an-object');
  8. var anInstance = require('../internals/an-instance');
  9. var isNullOrUndefined = require('../internals/is-null-or-undefined');
  10. var defineBuiltIn = require('../internals/define-built-in');
  11. var defineBuiltIns = require('../internals/define-built-ins');
  12. var defineBuiltInAccessor = require('../internals/define-built-in-accessor');
  13. var wellKnownSymbol = require('../internals/well-known-symbol');
  14. var InternalStateModule = require('../internals/internal-state');
  15. var DisposableStackHelpers = require('../internals/disposable-stack-helpers');
  16. var Promise = getBuiltIn('Promise');
  17. var SuppressedError = getBuiltIn('SuppressedError');
  18. var $ReferenceError = ReferenceError;
  19. var ASYNC_DISPOSE = wellKnownSymbol('asyncDispose');
  20. var TO_STRING_TAG = wellKnownSymbol('toStringTag');
  21. var getDisposeMethod = DisposableStackHelpers.getDisposeMethod;
  22. var addDisposableResource = DisposableStackHelpers.addDisposableResource;
  23. var ASYNC_DISPOSABLE_STACK = 'AsyncDisposableStack';
  24. var setInternalState = InternalStateModule.set;
  25. var getAsyncDisposableStackInternalState = InternalStateModule.getterFor(ASYNC_DISPOSABLE_STACK);
  26. var HINT = 'async-dispose';
  27. var DISPOSED = 'disposed';
  28. var PENDING = 'pending';
  29. var ALREADY_DISPOSED = ASYNC_DISPOSABLE_STACK + ' already disposed';
  30. var $AsyncDisposableStack = function AsyncDisposableStack() {
  31. setInternalState(anInstance(this, AsyncDisposableStackPrototype), {
  32. type: ASYNC_DISPOSABLE_STACK,
  33. state: PENDING,
  34. stack: []
  35. });
  36. if (!DESCRIPTORS) this.disposed = false;
  37. };
  38. var AsyncDisposableStackPrototype = $AsyncDisposableStack.prototype;
  39. defineBuiltIns(AsyncDisposableStackPrototype, {
  40. disposeAsync: function disposeAsync() {
  41. var asyncDisposableStack = this;
  42. return new Promise(function (resolve, reject) {
  43. var internalState = getAsyncDisposableStackInternalState(asyncDisposableStack);
  44. if (internalState.state == DISPOSED) return resolve(undefined);
  45. internalState.state = DISPOSED;
  46. if (!DESCRIPTORS) asyncDisposableStack.disposed = true;
  47. var stack = internalState.stack;
  48. var i = stack.length;
  49. var thrown = false;
  50. var suppressed;
  51. var handleError = function (result) {
  52. if (thrown) {
  53. suppressed = new SuppressedError(result, suppressed);
  54. } else {
  55. thrown = true;
  56. suppressed = result;
  57. }
  58. loop();
  59. };
  60. var loop = function () {
  61. if (i) {
  62. var disposeMethod = stack[--i];
  63. stack[i] = null;
  64. try {
  65. Promise.resolve(disposeMethod()).then(loop, handleError);
  66. } catch (error) {
  67. handleError(error);
  68. }
  69. } else {
  70. internalState.stack = null;
  71. thrown ? reject(suppressed) : resolve(undefined);
  72. }
  73. };
  74. loop();
  75. });
  76. },
  77. use: function use(value) {
  78. var internalState = getAsyncDisposableStackInternalState(this);
  79. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  80. if (!isNullOrUndefined(value)) {
  81. anObject(value);
  82. var method = aCallable(getDisposeMethod(value, HINT));
  83. addDisposableResource(internalState, value, HINT, method);
  84. } return value;
  85. },
  86. adopt: function adopt(value, onDispose) {
  87. var internalState = getAsyncDisposableStackInternalState(this);
  88. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  89. aCallable(onDispose);
  90. addDisposableResource(internalState, undefined, HINT, function () {
  91. onDispose(value);
  92. });
  93. return value;
  94. },
  95. defer: function defer(onDispose) {
  96. var internalState = getAsyncDisposableStackInternalState(this);
  97. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  98. aCallable(onDispose);
  99. addDisposableResource(internalState, undefined, HINT, onDispose);
  100. },
  101. move: function move() {
  102. var internalState = getAsyncDisposableStackInternalState(this);
  103. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  104. var newAsyncDisposableStack = new $AsyncDisposableStack();
  105. getAsyncDisposableStackInternalState(newAsyncDisposableStack).stack = internalState.stack;
  106. internalState.stack = [];
  107. return newAsyncDisposableStack;
  108. }
  109. });
  110. if (DESCRIPTORS) defineBuiltInAccessor(AsyncDisposableStackPrototype, 'disposed', {
  111. configurable: true,
  112. get: function disposed() {
  113. return getAsyncDisposableStackInternalState(this).state == DISPOSED;
  114. }
  115. });
  116. defineBuiltIn(AsyncDisposableStackPrototype, ASYNC_DISPOSE, AsyncDisposableStackPrototype.disposeAsync, { name: 'disposeAsync' });
  117. defineBuiltIn(AsyncDisposableStackPrototype, TO_STRING_TAG, ASYNC_DISPOSABLE_STACK, { nonWritable: true });
  118. $({ global: true, constructor: true, forced: true }, {
  119. AsyncDisposableStack: $AsyncDisposableStack
  120. });