import { Deserializable } from "../client/util/SerializationHelper"; import { FieldWaiting } from "./Doc"; import { primitive, serializable } from "serializr"; import { observable, action, runInAction } from "mobx"; import { DocServer } from "../client/DocServer"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { Id, Copy, ToScriptString, ToString } from "./FieldSymbols"; import { scriptingGlobal } from "../client/util/Scripting"; import { Plugins } from "./util"; @Deserializable("proxy") export class ProxyField extends ObjectField { constructor(); constructor(value: T); constructor(fieldId: string); constructor(value?: T | string) { super(); this.fieldId = typeof value === "string" ? value : (value?.[Id] ?? ""); } [Copy]() { return new ProxyField((this.cache ?? this.fieldId) as T); } [ToScriptString]() { return "invalid"; } [ToString]() { return "ProxyField"; } @serializable(primitive()) readonly fieldId: string = ""; private failed = false; private promise?: Promise; private get cache(): T | undefined { return DocServer.GetCachedRefField(this.fieldId) as T } value(): T | undefined | FieldWaiting { if (this.cache) return this.cache; if (this.failed) return undefined; if (!this.promise) { this.promise = DocServer.GetRefField(this.fieldId).then(action((field: any) => { this.promise = undefined; if (field === undefined) this.failed = true; return field; })); } return this.promise as any; } promisedValue(): string { return !this.cache && !this.failed && !this.promise ? this.fieldId : ""; } setPromise(promise: any) { if (this.cache === undefined) this.promise = promise; } } export namespace ProxyField { let useProxy = true; export function DisableProxyFields() { useProxy = false; } export function EnableProxyFields() { useProxy = true; } export function WithoutProxy(fn: () => T) { DisableProxyFields(); try { return fn(); } finally { EnableProxyFields(); } } export function initPlugin() { Plugins.addGetterPlugin((doc, _, value) => { if (useProxy && value instanceof ProxyField) { return { value: value.value() }; } }); } } function prefetchValue(proxy: PrefetchProxy) { return proxy.value() as any; } @scriptingGlobal @Deserializable("prefetch_proxy", prefetchValue) export class PrefetchProxy extends ProxyField { }