UNPKG

@difizen/mana-observable

Version:

233 lines (230 loc) 7.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Tracker = exports.Trackable = void 0; exports.tryInvokeGetter = tryInvokeGetter; var _manaCommon = require("@difizen/mana-common"); var _core = require("./core"); var _notifiable = require("./notifiable"); var _notifier = require("./notifier"); var _observable = require("./observable"); var _utils = require("./utils"); /* eslint-disable @typescript-eslint/no-explicit-any */ function tryInvokeGetter(getter, proxy, origin) { try { return getter.call(proxy); } catch (e) { if (e instanceof TypeError && e.message.includes('Illegal invocation')) { return getter.call(origin); } throw e; } } var Trackable; (function (_Trackable) { var activator = _Trackable.activator = Symbol('activator'); function is(target) { return _utils.Observability.canBeObservable(target) && target[_core.ObservableSymbol.Tracker]; } _Trackable.is = is; function getOrigin(target) { return target[_core.ObservableSymbol.Tracker]; } _Trackable.getOrigin = getOrigin; function tryGetOrigin(target) { if (!is(target)) { return target; } return getOrigin(target); } _Trackable.tryGetOrigin = tryGetOrigin; })(Trackable || (exports.Trackable = Trackable = {})); var Tracker; (function (_Tracker) { function set(target, act, proxy) { Reflect.defineMetadata(act, proxy, target, _core.ObservableSymbol.Tracker); } _Tracker.set = set; function get(target, act) { return Reflect.getMetadata(act, target, _core.ObservableSymbol.Tracker); } _Tracker.get = get; function has(target, act) { return Reflect.hasOwnMetadata(act, target, _core.ObservableSymbol.Tracker); } _Tracker.has = has; function tramsform(toTrack, act, activator) { if (toTrack instanceof Array) { return transformArray(toTrack, act, activator); } if (toTrack instanceof Map) { return transformMap(toTrack, act, activator); } if ((0, _manaCommon.isPlainObject)(toTrack)) { return transformPlainObject(toTrack, act, activator); } return toTrack; } _Tracker.tramsform = tramsform; function transformArray(toTrack, act, activator) { return new Proxy(toTrack, { get: function get(target, property) { var value = target[property]; if (property === _core.ObservableSymbol.Self) { return value; } if (Object.isFrozen(target)) { return value; } if (property === Trackable.activator) { return activator; } return track(value, act); } }); } _Tracker.transformArray = transformArray; function transformPlainObject(toTrack, act, activator) { return new Proxy(toTrack, { get: function get(target, property) { var value = target[property]; if (property === _core.ObservableSymbol.Self) { return value; } if (Object.isFrozen(target)) { return value; } if (property === Trackable.activator) { return activator; } return track(value, act); } }); } _Tracker.transformPlainObject = transformPlainObject; function transformMap(toTrack, act, activator) { return new Proxy(toTrack, { get: function get(target, property) { var value = target[property]; if (property === _core.ObservableSymbol.Self) { return value; } if (Object.isFrozen(target)) { return value; } if (property === Trackable.activator) { return activator; } if (property === 'get' && typeof value === 'function') { return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var innerValue = value.apply(target, args); return track(innerValue, act); }; } return value; } }); } _Tracker.transformMap = transformMap; function toInstanceTracker(origin, act) { // try make observable if (!_utils.Observability.marked(origin)) { (0, _observable.observable)(origin); } var proxy = new Proxy(origin, { get: function get(target, property) { if (property === _core.ObservableSymbol.Tracker) { return target; } if (property === _core.ObservableSymbol.Self) { return target; } var notifier; var value; if (typeof property === 'string') { if (_utils.Observability.shouldKeepOrigin(target, property)) { return target[property]; } var descriptor = (0, _manaCommon.getPropertyDescriptor)(target, property); if ((descriptor === null || descriptor === void 0 ? void 0 : descriptor.configurable) === false && (descriptor === null || descriptor === void 0 ? void 0 : descriptor.writable) === false) { // non-configurable and non-writable property should return the actual value return target[property]; } if (_utils.Observability.marked(target, property)) { notifier = _notifier.Notifier.getOrCreate(target, property); _notifier.Notifier.once(notifier, act, function () { act({ key: property, value: target[property] }); }); value = target[property]; return track(value, act, true); } if (descriptor !== null && descriptor !== void 0 && descriptor.get) { return tryInvokeGetter(descriptor.get, proxy, target); } } value = target[property]; return track(value, act, true); } }); set(origin, act, proxy); return proxy; } _Tracker.toInstanceTracker = toInstanceTracker; function toNotifiableTracker(origin, act, asProperty) { var maybeNotifiable = _notifiable.Notifiable.get(origin); if (!maybeNotifiable) { maybeNotifiable = _notifiable.Notifiable.transform(origin); } // set reactable listener var activator; if (!asProperty && _notifiable.Notifiable.is(maybeNotifiable)) { var notifier = _notifiable.Notifiable.getNotifier(maybeNotifiable); activator = function activator() { _notifier.Notifier.once(notifier, act, function () { act(origin); }); }; activator(); } var proxy = tramsform(maybeNotifiable, act, activator); set(origin, act, proxy); return proxy; } _Tracker.toNotifiableTracker = toNotifiableTracker; function track(object, act) { var asProperty = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (!_utils.Observability.canBeObservable(object)) { return object; } // get origin var origin = object; if (Trackable.is(object)) { origin = Trackable.getOrigin(object); } origin = _utils.Observability.getOrigin(origin); // already has tracker var exist = undefined; if (has(origin, act)) { exist = get(origin, act); if (exist) { if (exist[Trackable.activator]) { exist[Trackable.activator](); } return exist; } } if (_notifiable.Notifiable.canBeNotifiable(origin)) { return toNotifiableTracker(origin, act, asProperty); } else { return toInstanceTracker(origin, act); } } _Tracker.track = track; })(Tracker || (exports.Tracker = Tracker = {}));