UNPKG

@tldraw/state

Version:

tldraw infinite canvas SDK (state).

253 lines (252 loc) • 8.98 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var Computed_exports = {}; __export(Computed_exports, { UNINITIALIZED: () => UNINITIALIZED, WithDiff: () => WithDiff, _Computed: () => _Computed, computed: () => computed, getComputedInstance: () => getComputedInstance, isComputed: () => isComputed, isUninitialized: () => isUninitialized, withDiff: () => withDiff }); module.exports = __toCommonJS(Computed_exports); var import_utils = require("@tldraw/utils"); var import_ArraySet = require("./ArraySet"); var import_HistoryBuffer = require("./HistoryBuffer"); var import_capture = require("./capture"); var import_constants = require("./constants"); var import_helpers = require("./helpers"); var import_transactions = require("./transactions"); var import_types = require("./types"); var import_warnings = require("./warnings"); const UNINITIALIZED = Symbol.for("com.tldraw.state/UNINITIALIZED"); function isUninitialized(value) { return value === UNINITIALIZED; } const WithDiff = (0, import_helpers.singleton)( "WithDiff", () => class WithDiff { constructor(value, diff) { this.value = value; this.diff = diff; } } ); function withDiff(value, diff) { return new WithDiff(value, diff); } class __UNSAFE__Computed { constructor(name, derive, options) { this.name = name; this.derive = derive; if (options?.historyLength) { this.historyBuffer = new import_HistoryBuffer.HistoryBuffer(options.historyLength); } this.computeDiff = options?.computeDiff; this.isEqual = options?.isEqual ?? import_helpers.equals; } lastChangedEpoch = import_constants.GLOBAL_START_EPOCH; lastTraversedEpoch = import_constants.GLOBAL_START_EPOCH; __debug_ancestor_epochs__ = null; /** * The epoch when the reactor was last checked. */ lastCheckedEpoch = import_constants.GLOBAL_START_EPOCH; parentSet = new import_ArraySet.ArraySet(); parents = []; parentEpochs = []; children = new import_ArraySet.ArraySet(); // eslint-disable-next-line no-restricted-syntax get isActivelyListening() { return !this.children.isEmpty; } historyBuffer; // The last-computed value of this signal. state = UNINITIALIZED; // If the signal throws an error we stash it so we can rethrow it on the next get() error = null; computeDiff; isEqual; __unsafe__getWithoutCapture(ignoreErrors) { const isNew = this.lastChangedEpoch === import_constants.GLOBAL_START_EPOCH; const globalEpoch = (0, import_transactions.getGlobalEpoch)(); if (!isNew && (this.lastCheckedEpoch === globalEpoch || this.isActivelyListening && (0, import_transactions.getIsReacting)() && this.lastTraversedEpoch < (0, import_transactions.getReactionEpoch)() || !(0, import_helpers.haveParentsChanged)(this))) { this.lastCheckedEpoch = globalEpoch; if (this.error) { if (!ignoreErrors) { throw this.error.thrownValue; } else { return this.state; } } else { return this.state; } } try { (0, import_capture.startCapturingParents)(this); const result = this.derive(this.state, this.lastCheckedEpoch); const newState = result instanceof WithDiff ? result.value : result; const isUninitialized2 = this.state === UNINITIALIZED; if (isUninitialized2 || !this.isEqual(newState, this.state)) { if (this.historyBuffer && !isUninitialized2) { const diff = result instanceof WithDiff ? result.diff : void 0; this.historyBuffer.pushEntry( this.lastChangedEpoch, (0, import_transactions.getGlobalEpoch)(), diff ?? this.computeDiff?.(this.state, newState, this.lastCheckedEpoch, (0, import_transactions.getGlobalEpoch)()) ?? import_types.RESET_VALUE ); } this.lastChangedEpoch = (0, import_transactions.getGlobalEpoch)(); this.state = newState; } this.error = null; this.lastCheckedEpoch = (0, import_transactions.getGlobalEpoch)(); return this.state; } catch (e) { if (this.state !== UNINITIALIZED) { this.state = UNINITIALIZED; this.lastChangedEpoch = (0, import_transactions.getGlobalEpoch)(); } this.lastCheckedEpoch = (0, import_transactions.getGlobalEpoch)(); if (this.historyBuffer) { this.historyBuffer.clear(); } this.error = { thrownValue: e }; if (!ignoreErrors) throw e; return this.state; } finally { (0, import_capture.stopCapturingParents)(); } } get() { try { return this.__unsafe__getWithoutCapture(); } finally { (0, import_capture.maybeCaptureParent)(this); } } getDiffSince(epoch) { this.__unsafe__getWithoutCapture(true); (0, import_capture.maybeCaptureParent)(this); if (epoch >= this.lastChangedEpoch) { return import_helpers.EMPTY_ARRAY; } return this.historyBuffer?.getChangesSince(epoch) ?? import_types.RESET_VALUE; } } const _Computed = (0, import_helpers.singleton)("Computed", () => __UNSAFE__Computed); function computedMethodLegacyDecorator(options = {}, _target, key, descriptor) { const originalMethod = descriptor.value; const derivationKey = Symbol.for("__@tldraw/state__computed__" + key); descriptor.value = function() { let d = this[derivationKey]; if (!d) { d = new _Computed(key, originalMethod.bind(this), options); Object.defineProperty(this, derivationKey, { enumerable: false, configurable: false, writable: false, value: d }); } return d.get(); }; descriptor.value[isComputedMethodKey] = true; return descriptor; } function computedGetterLegacyDecorator(options = {}, _target, key, descriptor) { const originalMethod = descriptor.get; const derivationKey = Symbol.for("__@tldraw/state__computed__" + key); descriptor.get = function() { let d = this[derivationKey]; if (!d) { d = new _Computed(key, originalMethod.bind(this), options); Object.defineProperty(this, derivationKey, { enumerable: false, configurable: false, writable: false, value: d }); } return d.get(); }; return descriptor; } function computedMethodTc39Decorator(options, compute, context) { (0, import_utils.assert)(context.kind === "method", "@computed can only be used on methods"); const derivationKey = Symbol.for("__@tldraw/state__computed__" + String(context.name)); const fn = function() { let d = this[derivationKey]; if (!d) { d = new _Computed(String(context.name), compute.bind(this), options); Object.defineProperty(this, derivationKey, { enumerable: false, configurable: false, writable: false, value: d }); } return d.get(); }; fn[isComputedMethodKey] = true; return fn; } function computedDecorator(options = {}, args) { if (args.length === 2) { const [originalMethod, context] = args; return computedMethodTc39Decorator(options, originalMethod, context); } else { const [_target, key, descriptor] = args; if (descriptor.get) { (0, import_warnings.logComputedGetterWarning)(); return computedGetterLegacyDecorator(options, _target, key, descriptor); } else { return computedMethodLegacyDecorator(options, _target, key, descriptor); } } } const isComputedMethodKey = "@@__isComputedMethod__@@"; function getComputedInstance(obj, propertyName) { const key = Symbol.for("__@tldraw/state__computed__" + propertyName.toString()); let inst = obj[key]; if (!inst) { const val = obj[propertyName]; if (typeof val === "function" && val[isComputedMethodKey]) { val.call(obj); } inst = obj[key]; } return inst; } function computed() { if (arguments.length === 1) { const options = arguments[0]; return (...args) => computedDecorator(options, args); } else if (typeof arguments[0] === "string") { return new _Computed(arguments[0], arguments[1], arguments[2]); } else { return computedDecorator(void 0, arguments); } } function isComputed(value) { return !!(value && value instanceof _Computed); } //# sourceMappingURL=Computed.js.map