UNPKG

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