esnext.disposable-stack.constructor.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. 'use strict';
  2. // https://github.com/tc39/proposal-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 SuppressedError = getBuiltIn('SuppressedError');
  17. var $ReferenceError = ReferenceError;
  18. var DISPOSE = wellKnownSymbol('dispose');
  19. var TO_STRING_TAG = wellKnownSymbol('toStringTag');
  20. var getDisposeMethod = DisposableStackHelpers.getDisposeMethod;
  21. var addDisposableResource = DisposableStackHelpers.addDisposableResource;
  22. var DISPOSABLE_STACK = 'DisposableStack';
  23. var setInternalState = InternalStateModule.set;
  24. var getDisposableStackInternalState = InternalStateModule.getterFor(DISPOSABLE_STACK);
  25. var HINT = 'sync-dispose';
  26. var DISPOSED = 'disposed';
  27. var PENDING = 'pending';
  28. var ALREADY_DISPOSED = DISPOSABLE_STACK + ' already disposed';
  29. var $DisposableStack = function DisposableStack() {
  30. setInternalState(anInstance(this, DisposableStackPrototype), {
  31. type: DISPOSABLE_STACK,
  32. state: PENDING,
  33. stack: []
  34. });
  35. if (!DESCRIPTORS) this.disposed = false;
  36. };
  37. var DisposableStackPrototype = $DisposableStack.prototype;
  38. defineBuiltIns(DisposableStackPrototype, {
  39. dispose: function dispose() {
  40. var internalState = getDisposableStackInternalState(this);
  41. if (internalState.state == DISPOSED) return;
  42. internalState.state = DISPOSED;
  43. if (!DESCRIPTORS) this.disposed = true;
  44. var stack = internalState.stack;
  45. var i = stack.length;
  46. var thrown = false;
  47. var suppressed;
  48. while (i) {
  49. var disposeMethod = stack[--i];
  50. stack[i] = null;
  51. try {
  52. disposeMethod();
  53. } catch (errorResult) {
  54. if (thrown) {
  55. suppressed = new SuppressedError(errorResult, suppressed);
  56. } else {
  57. thrown = true;
  58. suppressed = errorResult;
  59. }
  60. }
  61. }
  62. internalState.stack = null;
  63. if (thrown) throw suppressed;
  64. },
  65. use: function use(value) {
  66. var internalState = getDisposableStackInternalState(this);
  67. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  68. if (!isNullOrUndefined(value)) {
  69. anObject(value);
  70. var method = aCallable(getDisposeMethod(value, HINT));
  71. addDisposableResource(internalState, value, HINT, method);
  72. } return value;
  73. },
  74. adopt: function adopt(value, onDispose) {
  75. var internalState = getDisposableStackInternalState(this);
  76. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  77. aCallable(onDispose);
  78. addDisposableResource(internalState, undefined, HINT, function () {
  79. onDispose(value);
  80. });
  81. return value;
  82. },
  83. defer: function defer(onDispose) {
  84. var internalState = getDisposableStackInternalState(this);
  85. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  86. aCallable(onDispose);
  87. addDisposableResource(internalState, undefined, HINT, onDispose);
  88. },
  89. move: function move() {
  90. var internalState = getDisposableStackInternalState(this);
  91. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  92. var newDisposableStack = new $DisposableStack();
  93. getDisposableStackInternalState(newDisposableStack).stack = internalState.stack;
  94. internalState.stack = [];
  95. return newDisposableStack;
  96. }
  97. });
  98. if (DESCRIPTORS) defineBuiltInAccessor(DisposableStackPrototype, 'disposed', {
  99. configurable: true,
  100. get: function disposed() {
  101. return getDisposableStackInternalState(this).state == DISPOSED;
  102. }
  103. });
  104. defineBuiltIn(DisposableStackPrototype, DISPOSE, DisposableStackPrototype.dispose, { name: 'dispose' });
  105. defineBuiltIn(DisposableStackPrototype, TO_STRING_TAG, DISPOSABLE_STACK, { nonWritable: true });
  106. $({ global: true, constructor: true }, {
  107. DisposableStack: $DisposableStack
  108. });