{
  "version": 3,
  "sources": ["../../src/editorbar/remote/RemoteConnection.ts", "../../src/editorbar/remote/RemoteProject.ts"],
  "sourcesContent": ["import { assert, getLogger } from \"@framerjs/shared\"\nimport { CanvasTreeVersion } from \"document/models/CanvasTree/CanvasTreeVersion.ts\"\nimport { getTunnelId } from \"environment/getTunnelId.ts\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { SocketStats } from \"socket/SocketStats.ts\"\nimport type { DisconnectReason, IncomingMessage, Message } from \"socket/types.ts\"\nimport { PROTOCOL_VERSION, getSocketDisconnectReason, parseSocketMessage } from \"socket/useSocket.ts\"\nimport type { IntervalId } from \"utils/IntervalId.ts\"\nimport { getMultiplayerServiceSubprotocols } from \"web/lib/getMultiplayerServiceSubprotocols.ts\"\nimport { getSocketURL } from \"web/lib/getSocketURL.ts\"\n\nconst log = getLogger(\"RemoteConnection\")\n\nconst PING_INTERVAL = 1000\n\ninterface RemoteConnectionEvents {\n\tconnect(isReconnect: boolean): void\n\tdisconnect(reason: DisconnectReason): void\n\tmessage(message: IncomingMessage): void\n}\n\nexport interface RemoteConnectionOptions {\n\tsocketURL?: string\n\tisMPSSocket?: boolean\n\tonPageEditing?: boolean\n}\n\nexport class RemoteConnection extends EventEmitter<RemoteConnectionEvents> {\n\tprivate isReconnect = false\n\n\tprivate readonly messageQueue: Message[] = []\n\n\tprivate baseURL: string\n\tprivate socket: WebSocket | undefined\n\tprivate stats: SocketStats | undefined\n\tprivate connectAbortController: AbortController | undefined\n\tprivate readonly isMPSSocket: boolean\n\tprivate readonly onPageEditing: boolean\n\n\tconstructor(projectId: string, options: RemoteConnectionOptions = {}) {\n\t\tsuper()\n\t\tthis.baseURL = options.socketURL ?? getSocketURL(projectId)\n\t\tthis.isMPSSocket = options.isMPSSocket ?? false\n\t\tthis.onPageEditing = options.onPageEditing ?? false\n\t}\n\n\tprivate createPingInterval(socket: WebSocket, stats: SocketStats) {\n\t\treturn setInterval(() => {\n\t\t\tassert(this.socket === socket, \"Invalid socket\")\n\t\t\tassert(this.stats === stats, \"Invalid stats\")\n\n\t\t\tif (performance.now() - stats.lastSend() < PING_INTERVAL) return\n\t\t\tif (stats.pendingCount(\"ping\") > 0) return\n\n\t\t\tconst data = \"ping {}\"\n\t\t\tsocket.send(data)\n\t\t\tstats.sent(\"ping\", data)\n\t\t}, PING_INTERVAL)\n\t}\n\n\tconnect(treeVersion: number) {\n\t\tif (this.socket || this.connectAbortController) return\n\n\t\tconst url = new URL(this.baseURL)\n\t\turl.searchParams.set(\"v\", String(PROTOCOL_VERSION))\n\t\turl.searchParams.set(\"tunnel\", getTunnelId() ?? \"\")\n\t\turl.searchParams.set(\"treeSchema\", String(CanvasTreeVersion))\n\t\turl.searchParams.set(\"treeVersion\", String(treeVersion))\n\t\tif (this.onPageEditing) {\n\t\t\turl.searchParams.set(\"onPageEditing\", \"true\")\n\t\t}\n\n\t\tif (!this.isMPSSocket) {\n\t\t\tthis.openSocket(url)\n\t\t\treturn\n\t\t}\n\n\t\tconst abortController = new AbortController()\n\t\tthis.connectAbortController = abortController\n\t\tvoid this.openSocketAsync(url, abortController.signal).finally(() => {\n\t\t\tif (this.connectAbortController === abortController) {\n\t\t\t\tthis.connectAbortController = undefined\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate async openSocketAsync(url: URL, signal: AbortSignal) {\n\t\tlet subprotocols: string[] | undefined\n\t\ttry {\n\t\t\tsubprotocols = await getMultiplayerServiceSubprotocols()\n\t\t} catch (error) {\n\t\t\tlog.warn(\"Error resolving websocket subprotocols:\", error)\n\t\t}\n\t\tif (signal.aborted) return\n\n\t\tthis.openSocket(url, subprotocols)\n\t}\n\n\tprivate openSocket(url: URL, subprotocols?: string[]) {\n\t\tconst socket = new WebSocket(url, subprotocols)\n\t\tconst stats = new SocketStats()\n\n\t\tthis.socket = socket\n\t\tthis.stats = stats\n\n\t\tlog.debug(\"Connecting:\", socket.url)\n\n\t\tlet pingInterval: IntervalId | undefined\n\n\t\tsocket.addEventListener(\"open\", () => {\n\t\t\tassert(this.socket === socket, \"Invalid socket\")\n\t\t\tassert(this.stats === stats, \"Invalid stats\")\n\n\t\t\tlog.debug(\"Connected:\", socket.url)\n\n\t\t\tpingInterval = this.createPingInterval(socket, stats)\n\n\t\t\tthis.emit(\"connect\", this.isReconnect)\n\t\t\tthis.isReconnect = true\n\n\t\t\tthis.flushMessageQueue(socket, stats)\n\t\t})\n\n\t\tsocket.addEventListener(\"message\", event => {\n\t\t\tassert(this.socket === socket, \"Invalid socket\")\n\t\t\tassert(this.stats === stats, \"Invalid stats\")\n\n\t\t\tconst data: string = event.data\n\t\t\tconst message = parseSocketMessage(data)\n\n\t\t\tstats.received(data)\n\n\t\t\tif (message.type === \"ack\") {\n\t\t\t\treturn stats.acked()\n\t\t\t}\n\n\t\t\tif (message.type === \"redirect\") {\n\t\t\t\tthis.baseURL = message.value.url\n\t\t\t}\n\n\t\t\tlog.trace(\"Received:\", message)\n\t\t\tthis.emit(\"message\", message)\n\t\t})\n\n\t\tsocket.addEventListener(\"close\", event => {\n\t\t\tassert(this.socket === socket, \"Invalid socket\")\n\t\t\tassert(this.stats === stats, \"Invalid stats\")\n\n\t\t\tclearInterval(pingInterval)\n\n\t\t\tconst reason = getSocketDisconnectReason(event)\n\t\t\tlog.debug(\"Disconnected:\", reason)\n\n\t\t\tthis.socket = undefined\n\t\t\tthis.stats = undefined\n\n\t\t\tthis.emit(\"disconnect\", reason)\n\t\t})\n\t}\n\n\tdisconnect() {\n\t\tthis.connectAbortController?.abort()\n\t\tthis.connectAbortController = undefined\n\t\tthis.socket?.close()\n\t}\n\n\tprivate flushMessageQueue(socket: WebSocket, stats: SocketStats) {\n\t\tif (socket.readyState !== WebSocket.OPEN) return\n\n\t\tfor (const { type, value } of this.messageQueue) {\n\t\t\ttry {\n\t\t\t\tconst json = JSON.stringify(value)\n\t\t\t\tconst data = `${type} ${json}`\n\t\t\t\tsocket.send(data)\n\t\t\t\tstats.sent(type, data)\n\t\t\t} catch (error) {\n\t\t\t\tlog.warn(\"Error sending:\", type, error)\n\t\t\t}\n\t\t}\n\n\t\tthis.messageQueue.length = 0\n\t}\n\n\tsend(message: Message) {\n\t\tthis.messageQueue.push(message)\n\n\t\tif (this.socket && this.stats) {\n\t\t\tthis.flushMessageQueue(this.socket, this.stats)\n\t\t}\n\t}\n\n\t/** Same as send, to match the interface of `SendMessage`. */\n\tsendMessage(message: Message) {\n\t\tthis.send(message)\n\t}\n\n\t/**\n\t * Compatibility with `Socket` interface for `ModulesAPI`.\n\t *\n\t * @deprecated Use `.on` and `.off` methods instead.\n\t */\n\tonMessage(callback: (message: IncomingMessage) => void) {\n\t\tthis.on(\"message\", callback)\n\n\t\treturn () => {\n\t\t\tthis.off(\"message\", callback)\n\t\t}\n\t}\n}\n", "import { AssetService } from \"@framerjs/assets\"\nimport type { ComponentLoader } from \"@framerjs/framer-runtime\"\nimport { assert, getLogger, getServiceMap, ResolvablePromise, unhandledError } from \"@framerjs/shared\"\nimport { JsonRemoteDocumentDataHandler } from \"document/JsonRemoteDocumentDataHandler.ts\"\nimport type {\n\tRemoteDocumentDataHandler,\n\tRemoteDocumentDataHandlerCallbacks,\n} from \"document/RemoteDocumentDataHandler.ts\"\nimport type { ServerTreeUpdate } from \"document/RemoteDocumentHandler.ts\"\nimport type { BaseTreeStore } from \"document/base-engine/BaseTreeStore.ts\"\nimport { treeModeWithFallback } from \"document/crdt/isCrdt.ts\"\nimport { CrdtRemoteDocumentDataHandler } from \"document/crdt/sync/index.ts\"\nimport type { DocumentLoader, DocumentLoaderSettings } from \"document/loader/DocumentLoader.ts\"\nimport { CanvasTreeVersion } from \"document/models/CanvasTree/CanvasTreeVersion.ts\"\nimport type { CanvasTree } from \"document/models/CanvasTree/index.ts\"\nimport type { CrdtConfirm, CrdtUpdate } from \"document/models/CanvasTree/treeSyncUtils.ts\"\nimport { setTreeMode, type TreeMode } from \"document/stores/TreeMode.ts\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { DisconnectReason, type IncomingMessage, type TreeMessageData } from \"socket/types.ts\"\nimport {\n\tgetRecoverableReconnectSchedule,\n\tisRecoverableDisconnectReason,\n\tRECONNECT_ATTEMPT_RESET_DELAY_MS,\n} from \"socket/useSocket.ts\"\nimport type { TimeoutId } from \"utils/TimeoutId.ts\"\nimport { accessTokenRefresher } from \"web/lib/accessTokenRefresherWeb.ts\"\nimport { isMultiplayerServiceURL } from \"web/lib/multiplayerService.ts\"\nimport { Pages, UIInteraction, record } from \"web/lib/tracker.ts\"\nimport { ModulesAPI } from \"web/pages/project/ModulesAPI.ts\"\nimport { API } from \"web/pages/project/lib/useAPI.ts\"\nimport { RemoteConnection, type RemoteConnectionOptions } from \"./RemoteConnection.ts\"\n\nconst log = getLogger(\"remote:project\")\nconst RETRY_SENDING_MS = 100\n\ninterface RemoteProjectEvents {\n\tupdate(tree: CanvasTree): void\n\tdisconnect(reason: DisconnectReason): void\n}\n\nexport class RemoteProject extends EventEmitter<RemoteProjectEvents> {\n\treadonly connection: RemoteConnection\n\tprivate treeDataHandler: RemoteDocumentDataHandler | undefined\n\treadonly api: API\n\treadonly modulesAPI: ModulesAPI\n\treadonly assetService: AssetService\n\tprivate reconnectTimeout: TimeoutId | undefined\n\tprivate reconnectAttemptResetTimeout: TimeoutId | undefined\n\tprivate reconnectAttempt = 0\n\tprivate documentLoader: DocumentLoader | undefined\n\tprivate readonly loadedPromise = new ResolvablePromise<void>()\n\tprivate readonly isMPSSocket: boolean\n\tprivate treeMode: TreeMode | undefined\n\n\t// Store reconnect flag so events (e.g. \"close\") can know if the disconnect was intentional\n\tprivate shouldReconnect = true\n\t// Flag for the next (expected) disconnection to reload the window instead of reconnecting\n\tprivate shouldReloadOnDisconnect = false\n\n\tprivate postponedLastUpdate: ReturnType<typeof setTimeout> | undefined\n\n\tconstructor(\n\t\treadonly treeStore: BaseTreeStore,\n\t\tprivate readonly componentLoader: ComponentLoader,\n\t\treadonly userId: string,\n\t\treadonly projectId: string,\n\t\treadonly abortSignal?: AbortSignal,\n\t\toptions: RemoteConnectionOptions = {},\n\t) {\n\t\tsuper()\n\n\t\tthis.isMPSSocket = options.isMPSSocket ?? false\n\t\tthis.connection = new RemoteConnection(this.projectId, options)\n\n\t\tthis.api = new API(this.connection, this.projectId)\n\t\tthis.assetService = new AssetService(this.api)\n\t\tthis.modulesAPI = new ModulesAPI(this.api, this.connection)\n\n\t\tthis.connection.on(\"disconnect\", this.onDisconnect, this)\n\t\tthis.connection.on(\"connect\", this.onConnect, this)\n\t\tthis.connection.on(\"message\", this.onMessage, this)\n\n\t\tthis.assetService.refresh().catch(unhandledError)\n\n\t\tabortSignal?.addEventListener(\"abort\", () => this.disconnect(), { once: true })\n\t}\n\n\twhenLoaded() {\n\t\treturn this.loadedPromise\n\t}\n\n\tprivate createDataHandler() {\n\t\tconst callbacks: RemoteDocumentDataHandlerCallbacks = {\n\t\t\terror: this.handleError,\n\t\t\terrorRecoverable: this.handleRecoverableError,\n\t\t\tupdateProcessed: this.handleUpdateProcessed,\n\t\t}\n\n\t\tif (this.treeStore.mode === \"crdt\") {\n\t\t\treturn new CrdtRemoteDocumentDataHandler(\n\t\t\t\tthis.treeStore.timeline,\n\t\t\t\tthis.componentLoader,\n\t\t\t\tthis.userId,\n\t\t\t\tthis.projectId,\n\t\t\t\tcallbacks,\n\t\t\t\tundefined,\n\t\t\t\tthis.isMPSSocket,\n\t\t\t\t\"on_page\",\n\t\t\t)\n\t\t}\n\n\t\treturn new JsonRemoteDocumentDataHandler(\n\t\t\tthis.treeStore.timeline,\n\t\t\tthis.componentLoader,\n\t\t\tthis.projectId,\n\t\t\tcallbacks,\n\t\t\tthis.isMPSSocket,\n\t\t\t\"on_page\",\n\t\t)\n\t}\n\n\tconnect() {\n\t\tconst treeVersion = this.treeDataHandler?.treeVersion ?? 0\n\t\tthis.connection.connect(treeVersion)\n\t\tthis.treeStore.timeline.setOnline(true)\n\t\tthis.shouldReconnect = true\n\t}\n\n\tdisconnect() {\n\t\tthis.shouldReconnect = false\n\t\tthis.cancelReconnect()\n\t\tthis.cancelReconnectAttemptReset()\n\t\tthis.connection.disconnect()\n\t\tthis.treeStore.timeline.setOnline(false)\n\t}\n\n\tmaybeSend() {\n\t\tif (this.postponedLastUpdate) {\n\t\t\tclearTimeout(this.postponedLastUpdate)\n\t\t\tthis.postponedLastUpdate = undefined\n\t\t}\n\n\t\tconst result = this.treeDataHandler?.maybeSend(this.connection) ?? \"postpone\"\n\t\tif (result === \"postpone\") {\n\t\t\tthis.postponedLastUpdate = setTimeout(() => this.maybeSend(), RETRY_SENDING_MS)\n\t\t}\n\n\t\tif (result === \"didSend\") {\n\t\t\trecord(\"editor_bar_interaction\", {\n\t\t\t\tpage: Pages.editorBarProjectPage,\n\t\t\t\tid: UIInteraction.editorBarTreeUpdate,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate cancelReconnect() {\n\t\tclearTimeout(this.reconnectTimeout)\n\t\tthis.reconnectTimeout = undefined\n\t}\n\n\tprivate scheduleReconnect(delay: number) {\n\t\tthis.cancelReconnect()\n\n\t\tthis.reconnectTimeout = setTimeout(() => {\n\t\t\tthis.reconnectTimeout = undefined\n\t\t\tthis.connect()\n\t\t}, delay)\n\t}\n\n\tprivate cancelReconnectAttemptReset() {\n\t\tclearTimeout(this.reconnectAttemptResetTimeout)\n\t\tthis.reconnectAttemptResetTimeout = undefined\n\t}\n\n\tprivate onConnect() {\n\t\tthis.cancelReconnectAttemptReset()\n\t\tthis.reconnectAttemptResetTimeout = setTimeout(() => {\n\t\t\tthis.reconnectAttempt = 0\n\t\t\tthis.reconnectAttemptResetTimeout = undefined\n\t\t}, RECONNECT_ATTEMPT_RESET_DELAY_MS)\n\t}\n\n\tprivate onDisconnect(reason: DisconnectReason) {\n\t\tthis.cancelReconnectAttemptReset()\n\n\t\t// Reset the tree data handler so it gets recreated on the next init\n\t\tthis.treeDataHandler = undefined\n\n\t\tif (this.shouldReloadOnDisconnect) {\n\t\t\t// Expected disconnection, reload the window.\n\t\t\twindow.location.reload()\n\t\t\treturn\n\t\t}\n\n\t\tif (!this.shouldReconnect) {\n\t\t\tlog.warn(\"Disconnect:\", reason)\n\t\t}\n\n\t\tif (this.shouldReconnect && isRecoverableDisconnectReason(reason)) {\n\t\t\tconst { delay, nextReconnectAttempt } = getRecoverableReconnectSchedule(reason, this.reconnectAttempt)\n\t\t\tthis.reconnectAttempt = nextReconnectAttempt\n\t\t\tthis.scheduleReconnect(delay)\n\t\t}\n\t}\n\n\tprivate onMessage(message: IncomingMessage) {\n\t\tswitch (message.type) {\n\t\t\tcase \"treeMessage\":\n\t\t\t\treturn this.handleTreeMessage(message.value)\n\t\t\tcase \"treeUpdate\":\n\t\t\t\treturn this.handleTreeUpdate(message.value as ServerTreeUpdate)\n\t\t\tcase \"rows\":\n\t\t\t\treturn this.handleRows(message.id, message.value)\n\t\t\tcase \"confirmRows\":\n\t\t\t\treturn this.handleConfirmRows(message.value as CrdtConfirm)\n\t\t\tcase \"redirect\":\n\t\t\t\t// Cross-type redirect: captured isMPSSocket is stale, reload to re-read access response.\n\t\t\t\tif (isMultiplayerServiceURL(message.value.url) !== this.isMPSSocket) {\n\t\t\t\t\tthis.shouldReloadOnDisconnect = true\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\tcase \"notifyProjectChange\":\n\t\t\t\tif (message.value.waitForRestart) {\n\t\t\t\t\t// We will get disconnected (and then presumably reconnect). That reconnection\n\t\t\t\t\t// is problematic in some cases though, as it wouldn't recreate the canvas based on\n\t\t\t\t\t// the new feature set. So, schedule a hard-reload of the window.\n\t\t\t\t\tthis.shouldReloadOnDisconnect = true\n\t\t\t\t}\n\n\t\t\t\tswitch (message.value.scope) {\n\t\t\t\t\tcase \"assets\":\n\t\t\t\t\t\treturn this.assetService.refresh()\n\t\t\t\t\tcase \"assetsInvalidated\":\n\t\t\t\t\t\treturn this.assetService.refreshFully()\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn\n\t\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleError = (error: Error) => {\n\t\tlog.warn(\"Permanent error:\", error)\n\t\tthis.emit(\"disconnect\", DisconnectReason.ClientSidePermanentError)\n\t}\n\n\tprivate handleRecoverableError = () => {\n\t\tthis.emit(\"disconnect\", DisconnectReason.ClientSidePermanentError)\n\t}\n\n\tprivate handleUpdateProcessed = (tree: CanvasTree) => {\n\t\tthis.emit(\"update\", tree)\n\t}\n\n\tprivate handleTreeMessage(message: TreeMessageData) {\n\t\tif (message.type !== \"init\") return\n\n\t\tconst serviceMap = getServiceMap()\n\t\tconst url = new URL(message.data.file, serviceMap.app)\n\t\tconst treeMode = treeModeWithFallback(message.data.mode ?? this.treeMode)\n\t\tif (this.treeMode !== undefined && this.treeMode !== treeMode) {\n\t\t\tthis.emit(\"disconnect\", DisconnectReason.TreeModeMismatch)\n\t\t\treturn\n\t\t}\n\n\t\tlet treeDataHandler = this.treeDataHandler\n\t\tif (!treeDataHandler) {\n\t\t\tthis.treeMode = treeMode\n\t\t\tthis.treeStore.mode = treeMode\n\t\t\tthis.treeStore.timeline.setOnline(true)\n\t\t\ttreeDataHandler = this.createDataHandler()\n\t\t\tthis.treeDataHandler = treeDataHandler\n\t\t}\n\n\t\tconst res = treeDataHandler.handleInit(message.data.treeVersion, message.data.initialUpdates)\n\t\tif (res.needsDownload) {\n\t\t\tthis.downloadDocument(url.href, message.data.treeVersion)\n\t\t}\n\t}\n\n\tprivate handleTreeUpdate(update: ServerTreeUpdate) {\n\t\tassert(this.treeDataHandler, \"Cannot handle remote updates before init\")\n\t\tthis.treeDataHandler.handleTreeUpdate(update)\n\t\tthis.treeDataHandler.processRemoteUpdates()\n\t}\n\n\tprivate handleRows(id: string, update: CrdtUpdate) {\n\t\tassert(this.treeDataHandler, \"Cannot handle remote updates before init\")\n\t\tthis.treeDataHandler.handleRows(id, update)\n\t\tthis.treeDataHandler.processRemoteUpdates()\n\t}\n\n\tprivate handleConfirmRows(message: CrdtConfirm) {\n\t\tassert(this.treeDataHandler, \"Cannot handle remote updates before init\")\n\t\tthis.treeDataHandler.handleConfirmRows(message)\n\t\tthis.treeDataHandler.processRemoteUpdates()\n\t}\n\n\tprivate downloadDocument(url: string, treeVersion: number) {\n\t\tconst treeDataHandler = this.treeDataHandler\n\t\tassert(treeDataHandler?.waitingForTree, \"Must be waiting for tree\")\n\n\t\tthis.cancelDocumentLoader()\n\n\t\tconst isMPSSocket = this.isMPSSocket\n\t\tconst settings: DocumentLoaderSettings = {\n\t\t\tpartialParsing: true,\n\t\t\tloadInBackground: true,\n\t\t\tasync refreshAccessToken(initData: RequestInit): Promise<RequestInit> {\n\t\t\t\tif (isMPSSocket) return accessTokenRefresher.withAuthorizationHeader(initData)\n\t\t\t\treturn { ...initData, credentials: \"include\" }\n\t\t\t},\n\t\t}\n\n\t\tconst loader = treeDataHandler.createLoader(url, treeVersion, settings)\n\t\tthis.documentLoader = loader\n\n\t\tloader.on(\"loadedFirstData\", tree => {\n\t\t\ttree.setService(\"metadata\", { projectId: this.projectId })\n\t\t\t// Socket init is the source of truth for project mode; this fallback is only for missing server mode.\n\t\t\tsetTreeMode(tree, treeModeWithFallback(this.treeMode))\n\t\t\tloader.pauseLoadingScopes()\n\n\t\t\tconst options = { isLoading: true }\n\t\t\ttreeDataHandler.setTree(tree, treeVersion, options)\n\n\t\t\ttreeDataHandler.processRemoteUpdates()\n\t\t\tthis.loadedPromise.resolve()\n\n\t\t\tif (loader.canvasTreeVersion < CanvasTreeVersion) {\n\t\t\t\tthis.emit(\"disconnect\", DisconnectReason.ClientTooNew)\n\t\t\t}\n\n\t\t\tif (loader.canvasTreeVersion > CanvasTreeVersion) {\n\t\t\t\tthis.emit(\"disconnect\", DisconnectReason.ClientNeedsUpdate)\n\t\t\t}\n\t\t})\n\n\t\tloader.on(\"loadedAllData\", () => {\n\t\t\ttreeDataHandler.loadedAllScopes()\n\t\t\tthis.emit(\"update\", this.treeStore.timeline.tree)\n\t\t})\n\n\t\tloader.on(\"loadedScope\", scope => {\n\t\t\ttreeDataHandler.loadOneScope(scope, false)\n\t\t\tthis.emit(\"update\", this.treeStore.timeline.tree)\n\t\t})\n\n\t\tloader.start().catch(unhandledError)\n\t}\n\n\tprivate cancelDocumentLoader() {\n\t\tif (!this.documentLoader) return\n\n\t\tthis.documentLoader.scheduler.cancel()\n\t\tthis.documentLoader.removeAllListeners()\n\t\tthis.documentLoader = undefined\n\t}\n}\n"],
  "mappings": "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",
  "names": ["EventEmitter", "log", "EventEmitter"]
}
