esnext.disposable-stack.constructor.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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 anInstance = require('../internals/an-instance');
  8. var defineBuiltIn = require('../internals/define-built-in');
  9. var defineBuiltIns = require('../internals/define-built-ins');
  10. var defineBuiltInAccessor = require('../internals/define-built-in-accessor');
  11. var wellKnownSymbol = require('../internals/well-known-symbol');
  12. var InternalStateModule = require('../internals/internal-state');
  13. var addDisposableResource = require('../internals/add-disposable-resource');
  14. var SuppressedError = getBuiltIn('SuppressedError');
  15. var $ReferenceError = ReferenceError;
  16. var DISPOSE = wellKnownSymbol('dispose');
  17. var TO_STRING_TAG = wellKnownSymbol('toStringTag');
  18. var DISPOSABLE_STACK = 'DisposableStack';
  19. var setInternalState = InternalStateModule.set;
  20. var getDisposableStackInternalState = InternalStateModule.getterFor(DISPOSABLE_STACK);
  21. var HINT = 'sync-dispose';
  22. var DISPOSED = 'disposed';
  23. var PENDING = 'pending';
  24. var ALREADY_DISPOSED = DISPOSABLE_STACK + ' already disposed';
  25. var $DisposableStack = function DisposableStack() {
  26. setInternalState(anInstance(this, DisposableStackPrototype), {
  27. type: DISPOSABLE_STACK,
  28. state: PENDING,
  29. stack: []
  30. });
  31. if (!DESCRIPTORS) this.disposed = false;
  32. };
  33. var DisposableStackPrototype = $DisposableStack.prototype;
  34. defineBuiltIns(DisposableStackPrototype, {
  35. dispose: function dispose() {
  36. var internalState = getDisposableStackInternalState(this);
  37. if (internalState.state == DISPOSED) return;
  38. internalState.state = DISPOSED;
  39. if (!DESCRIPTORS) this.disposed = true;
  40. var stack = internalState.stack;
  41. var i = stack.length;
  42. var thrown = false;
  43. var suppressed;
  44. while (i) {
  45. var disposeMethod = stack[--i];
  46. stack[i] = null;
  47. try {
  48. disposeMethod();
  49. } catch (errorResult) {
  50. if (thrown) {
  51. suppressed = new SuppressedError(errorResult, suppressed);
  52. } else {
  53. thrown = true;
  54. suppressed = errorResult;
  55. }
  56. }
  57. }
  58. internalState.stack = null;
  59. if (thrown) throw suppressed;
  60. },
  61. use: function use(value) {
  62. var internalState = getDisposableStackInternalState(this);
  63. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  64. addDisposableResource(internalState, value, HINT);
  65. return value;
  66. },
  67. adopt: function adopt(value, onDispose) {
  68. var internalState = getDisposableStackInternalState(this);
  69. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  70. aCallable(onDispose);
  71. addDisposableResource(internalState, undefined, HINT, function () {
  72. onDispose(value);
  73. });
  74. return value;
  75. },
  76. defer: function defer(onDispose) {
  77. var internalState = getDisposableStackInternalState(this);
  78. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  79. aCallable(onDispose);
  80. addDisposableResource(internalState, undefined, HINT, onDispose);
  81. },
  82. move: function move() {
  83. var internalState = getDisposableStackInternalState(this);
  84. if (internalState.state == DISPOSED) throw $ReferenceError(ALREADY_DISPOSED);
  85. var newDisposableStack = new $DisposableStack();
  86. getDisposableStackInternalState(newDisposableStack).stack = internalState.stack;
  87. internalState.stack = [];
  88. return newDisposableStack;
  89. }
  90. });
  91. if (DESCRIPTORS) defineBuiltInAccessor(DisposableStackPrototype, 'disposed', {
  92. configurable: true,
  93. get: function disposed() {
  94. return getDisposableStackInternalState(this).state == DISPOSED;
  95. }
  96. });
  97. defineBuiltIn(DisposableStackPrototype, DISPOSE, DisposableStackPrototype.dispose, { name: 'dispose' });
  98. defineBuiltIn(DisposableStackPrototype, TO_STRING_TAG, DISPOSABLE_STACK, { nonWritable: true });
  99. $({ global: true, constructor: true }, {
  100. DisposableStack: $DisposableStack
  101. });