@difizen/mana-core
Version:
360 lines (357 loc) • 16.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.VSDisposable = exports.ReferenceCollection = exports.MutableDisposable = exports.MultiDisposeError = exports.ImmortalReference = exports.DisposableStore = void 0;
exports.combinedDisposable = combinedDisposable;
exports.dispose = dispose;
exports.isDisposable = isDisposable;
exports.once = once;
exports.setDisposableTracker = setDisposableTracker;
exports.toDisposable = toDisposable;
exports.trackDisposable = trackDisposable;
var _manaCommon = require("@difizen/mana-common");
var _manaSyringe = require("@difizen/mana-syringe");
var _dec, _class2, _VSDisposable;
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _isNativeFunction(fn) { try { return Function.toString.call(fn).indexOf("[native code]") !== -1; } catch (e) { return typeof fn === "function"; } }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
function once(fn) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
var _this = this;
var didCall = false;
var result;
return function () {
if (didCall) {
return result;
}
didCall = true;
// eslint-disable-next-line prefer-rest-params
result = fn.apply(_this, Array.prototype.slice.call(arguments));
return result;
};
}
/**
* Enables logging of potentially leaked disposables.
*
* A disposable is considered leaked if it is not disposed or not registered as the child of
* another disposable. This tracking is very simple an only works for classes that either
* extend VSDisposable or use a DisposableStore. This means there are a lot of false positives.
*/
var TRACK_DISPOSABLES = false;
var disposableTracker = null;
function setDisposableTracker(tracker) {
disposableTracker = tracker;
}
if (TRACK_DISPOSABLES) {
var __is_disposable_tracked__ = '__is_disposable_tracked__';
disposableTracker = new ( /*#__PURE__*/function () {
function _class() {
_classCallCheck(this, _class);
}
_createClass(_class, [{
key: "trackDisposable",
value: function trackDisposable(x) {
var stack = new Error('Potentially leaked disposable').stack;
setTimeout(function () {
if (!x[__is_disposable_tracked__]) {
console.warn(stack);
}
}, 3000);
}
}, {
key: "markTracked",
value: function markTracked(x) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
if (x && x !== VSDisposable.None) {
try {
x[__is_disposable_tracked__] = true;
} catch (_unused) {
// noop
}
}
}
}]);
return _class;
}())();
}
function markTracked(x) {
if (!disposableTracker) {
return;
}
disposableTracker.markTracked(x);
}
function trackDisposable(x) {
if (!disposableTracker) {
return x;
}
disposableTracker.trackDisposable(x);
return x;
}
var MultiDisposeError = exports.MultiDisposeError = /*#__PURE__*/function (_Error) {
_inherits(MultiDisposeError, _Error);
var _super = _createSuper(MultiDisposeError);
function MultiDisposeError(errors) {
var _this2;
_classCallCheck(this, MultiDisposeError);
_this2 = _super.call(this, "Encountered errors while disposing of store. Errors: [".concat(errors.join(', '), "]"));
_this2.errors = errors;
return _this2;
}
return _createClass(MultiDisposeError);
}( /*#__PURE__*/_wrapNativeSuper(Error));
function isDisposable(thing) {
return typeof thing.dispose === 'function' && thing.dispose.length === 0;
}
function dispose(arg) {
if (_manaCommon.Iterable.is(arg)) {
var errors = [];
var _iterator = _createForOfIteratorHelper(arg),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var d = _step.value;
if (d) {
markTracked(d);
try {
d.dispose();
} catch (e) {
errors.push(e);
}
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
if (errors.length === 1) {
throw errors[0];
} else if (errors.length > 1) {
throw new MultiDisposeError(errors);
}
return Array.isArray(arg) ? [] : arg;
}
if (arg) {
markTracked(arg);
arg.dispose();
return arg;
}
}
function combinedDisposable() {
for (var _len = arguments.length, disposables = new Array(_len), _key = 0; _key < _len; _key++) {
disposables[_key] = arguments[_key];
}
disposables.forEach(markTracked);
return toDisposable(function () {
return dispose(disposables);
});
}
function toDisposable(fn) {
var self = trackDisposable({
dispose: function dispose() {
markTracked(self);
fn();
}
});
return self;
}
var DisposableStore = exports.DisposableStore = /*#__PURE__*/function () {
function DisposableStore() {
_classCallCheck(this, DisposableStore);
this._toDispose = new Set();
this._isDisposed = false;
}
_createClass(DisposableStore, [{
key: "dispose",
value:
/**
* Dispose of all registered disposables and mark this object as disposed.
*
* Any future disposables added to this object will be disposed of on `add`.
*/
function dispose() {
if (this._isDisposed) {
return;
}
markTracked(this);
this._isDisposed = true;
this.clear();
}
/**
* Dispose of all registered disposables but do not mark this object as disposed.
*/
}, {
key: "clear",
value: function clear() {
try {
dispose(this._toDispose.values());
} finally {
this._toDispose.clear();
}
}
}, {
key: "add",
value: function add(t) {
if (!t) {
return t;
}
if (t === this) {
throw new Error('Cannot register a disposable on itself!');
}
markTracked(t);
if (this._isDisposed) {
if (!DisposableStore.DISABLE_DISPOSED_WARNING) {
console.warn(new Error('Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!').stack);
}
} else {
this._toDispose.add(t);
}
return t;
}
}]);
return DisposableStore;
}();
DisposableStore.DISABLE_DISPOSED_WARNING = false;
var VSDisposable = exports.VSDisposable = (_dec = (0, _manaSyringe.injectable)(), _dec(_class2 = (_VSDisposable = /*#__PURE__*/function () {
function VSDisposable() {
_classCallCheck(this, VSDisposable);
this._store = new DisposableStore();
trackDisposable(this);
}
_createClass(VSDisposable, [{
key: "dispose",
value: function dispose() {
markTracked(this);
this._store.dispose();
}
}, {
key: "_register",
value: function _register(t) {
if (t === this) {
throw new Error('Cannot register a disposable on itself!');
}
return this._store.add(t);
}
}]);
return VSDisposable;
}(), _VSDisposable.None = Object.freeze({
dispose: function dispose() {
//
}
}), _VSDisposable)) || _class2);
/**
* Manages the lifecycle of a disposable value that may be changed.
*
* This ensures that when the disposable value is changed, the previously held disposable is disposed of. You can
* also register a `MutableDisposable` on a `VSDisposable` to ensure it is automatically cleaned up.
*/
var MutableDisposable = exports.MutableDisposable = /*#__PURE__*/function () {
function MutableDisposable() {
_classCallCheck(this, MutableDisposable);
this._isDisposed = false;
trackDisposable(this);
}
_createClass(MutableDisposable, [{
key: "value",
get: function get() {
return this._isDisposed ? undefined : this._value;
},
set: function set(value) {
var _this$_value;
if (this._isDisposed || value === this._value) {
return;
}
(_this$_value = this._value) === null || _this$_value === void 0 || _this$_value.dispose();
if (value) {
markTracked(value);
}
this._value = value;
}
}, {
key: "clear",
value: function clear() {
this.value = undefined;
}
}, {
key: "dispose",
value: function dispose() {
var _this$_value2;
this._isDisposed = true;
markTracked(this);
(_this$_value2 = this._value) === null || _this$_value2 === void 0 || _this$_value2.dispose();
this._value = undefined;
}
}]);
return MutableDisposable;
}();
var ReferenceCollection = exports.ReferenceCollection = /*#__PURE__*/function () {
function ReferenceCollection() {
_classCallCheck(this, ReferenceCollection);
this.references = new Map();
}
_createClass(ReferenceCollection, [{
key: "acquire",
value: function acquire(key) {
var _this3 = this;
var reference = this.references.get(key);
if (!reference) {
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
reference = {
counter: 0,
object: this.createReferencedObject.apply(this, [key].concat(args))
};
this.references.set(key, reference);
}
var _reference = reference,
object = _reference.object;
// eslint-disable-next-line @typescript-eslint/no-shadow
var dispose = once(function () {
if (--reference.counter === 0) {
_this3.destroyReferencedObject(key, reference.object);
_this3.references.delete(key);
}
});
reference.counter++;
return {
object: object,
dispose: dispose
};
}
}]);
return ReferenceCollection;
}();
var ImmortalReference = exports.ImmortalReference = /*#__PURE__*/function () {
function ImmortalReference(object) {
_classCallCheck(this, ImmortalReference);
this.object = object;
}
_createClass(ImmortalReference, [{
key: "dispose",
value: function dispose() {
/* noop */
}
}]);
return ImmortalReference;
}();