@tldraw/state
Version:
tldraw infinite canvas SDK (state).
253 lines (252 loc) • 8.98 kB
JavaScript
"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