{"ScriptPreparationCode":"const content = \u0060var emitter = require(\u0027../emitter\u0027);\\nvar logger = require(\u0027../logger\u0027);\\nvar ShareDBError = require(\u0027../error\u0027);\\nvar types = require(\u0027../types\u0027);\\nvar util = require(\u0027../util\u0027);\\nvar clone = util.clone;\\nvar deepEqual = require(\u0027fast-deep-equal\u0027);\\n\\nvar ERROR_CODE = ShareDBError.CODES;\\n\\n/**\\n * A Doc is a client\u0027s view on a sharejs document.\\n *\\n * It is is uniquely identified by its \\\u0060id\\\u0060 and \\\u0060collection\\\u0060. Documents\\n * should not be created directly. Create them with connection.get()\\n *\\n *\\n * Subscriptions\\n * -------------\\n *\\n * We can subscribe a document to stay in sync with the server.\\n * doc.subscribe(function(error) {\\n * doc.subscribed // = true\\n * })\\n * The server now sends us all changes concerning this document and these are\\n * applied to our data. If the subscription was successful the initial\\n * data and version sent by the server are loaded into the document.\\n *\\n * To stop listening to the changes we call \\\u0060doc.unsubscribe()\\\u0060.\\n *\\n * If we just want to load the data but not stay up-to-date, we call\\n * doc.fetch(function(error) {\\n * doc.data // sent by server\\n * })\\n *\\n *\\n * Events\\n * ------\\n *\\n * You can use doc.on(eventName, callback) to subscribe to the following events:\\n * - \\\u0060before op (op, source)\\\u0060 Fired before a partial operation is applied to the data.\\n * It may be used to read the old data just before applying an operation\\n * - \\\u0060op (op, source)\\\u0060 Fired after every partial operation with this operation as the\\n * first argument\\n * - \\\u0060create (source)\\\u0060 The document was created. That means its type was\\n * set and it has some initial data.\\n * - \\\u0060del (data, source)\\\u0060 Fired after the document is deleted, that is\\n * the data is null. It is passed the data before deletion as an\\n * argument\\n * - \\\u0060load ()\\\u0060 Fired when a new snapshot is ingested from a fetch, subscribe, or query\\n */\\n\\nmodule.exports = Doc;\\nfunction Doc(connection, collection, id) {\\n emitter.EventEmitter.call(this);\\n\\n this.connection = connection;\\n\\n this.collection = collection;\\n this.id = id;\\n\\n this.version = null;\\n this.type = null;\\n this.data = undefined;\\n\\n // Array of callbacks or nulls as placeholders\\n this.inflightFetch = [];\\n this.inflightSubscribe = null;\\n this.pendingFetch = [];\\n this.pendingSubscribe = [];\\n\\n // Whether we think we are subscribed on the server. Synchronously set to\\n // false on calls to unsubscribe and disconnect. Should never be true when\\n // this.wantSubscribe is false\\n this.subscribed = false;\\n // Whether to re-establish the subscription on reconnect\\n this.wantSubscribe = false;\\n\\n // The op that is currently roundtripping to the server, or null.\\n //\\n // When the connection reconnects, the inflight op is resubmitted.\\n //\\n // This has the same format as an entry in pendingOps\\n this.inflightOp = null;\\n\\n // All ops that are waiting for the server to acknowledge this.inflightOp\\n // This used to just be a single operation, but creates \u0026 deletes can\u0027t be\\n // composed with regular operations.\\n //\\n // This is a list of {[create:{...}], [del:true], [op:...], callbacks:[...]}\\n this.pendingOps = [];\\n\\n // The OT type of this document. An uncreated document has type \\\u0060null\\\u0060\\n this.type = null;\\n\\n // The applyStack enables us to track any ops submitted while we are\\n // applying an op incrementally. This value is an array when we are\\n // performing an incremental apply and null otherwise. When it is an array,\\n // all submitted ops should be pushed onto it. The \\\u0060_otApply\\\u0060 method will\\n // reset it back to null when all incremental apply loops are complete.\\n this.applyStack = null;\\n\\n // Disable the default behavior of composing submitted ops. This is read at\\n // the time of op submit, so it may be toggled on before submitting a\\n // specifc op and toggled off afterward\\n this.preventCompose = false;\\n\\n // If set to true, the source will be submitted over the connection. This\\n // will also have the side-effect of only composing ops whose sources are\\n // equal\\n this.submitSource = false;\\n\\n // Prevent own ops being submitted to the server. If subscribed, remote\\n // ops are still received. Should be toggled through the pause() and\\n // resume() methods to correctly flush on resume.\\n this.paused = false;\\n\\n // Internal counter that gets incremented every time doc.data is updated.\\n // Used as a cheap way to check if doc.data has changed.\\n this._dataStateVersion = 0;\\n}\\nemitter.mixin(Doc);\\n\\nDoc.prototype.destroy = function(callback) {\\n var doc = this;\\n doc.whenNothingPending(function() {\\n if (doc.wantSubscribe) {\\n doc.unsubscribe(function(err) {\\n if (err) {\\n if (callback) return callback(err);\\n return doc.emit(\u0027error\u0027, err);\\n }\\n doc.connection._destroyDoc(doc);\\n doc.emit(\u0027destroy\u0027);\\n if (callback) callback();\\n });\\n } else {\\n doc.connection._destroyDoc(doc);\\n doc.emit(\u0027destroy\u0027);\\n if (callback) callback();\\n }\\n });\\n};\\n\\n\\n// ****** Manipulating the document data, version and type.\\n\\n// Set the document\u0027s type, and associated properties. Most of the logic in\\n// this function exists to update the document based on any added \u0026 removed API\\n// methods.\\n//\\n// @param newType OT type provided by the ottypes library or its name or uri\\nDoc.prototype._setType = function(newType) {\\n if (typeof newType === \u0027string\u0027) {\\n newType = types.map[newType];\\n }\\n\\n if (newType) {\\n this.type = newType;\\n } else if (newType === null) {\\n this.type = newType;\\n // If we removed the type from the object, also remove its data\\n this._setData(undefined);\\n } else {\\n var err = new ShareDBError(ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNIZED, \u0027Missing type \u0027 \u002B newType);\\n return this.emit(\u0027error\u0027, err);\\n }\\n};\\n\\nDoc.prototype._setData = function(data) {\\n this.data = data;\\n this._dataStateVersion\u002B\u002B;\\n};\\n\\n// Ingest snapshot data. This data must include a version, snapshot and type.\\n// This is used both to ingest data that was exported with a webpage and data\\n// that was received from the server during a fetch.\\n//\\n// @param snapshot.v version\\n// @param snapshot.data\\n// @param snapshot.type\\n// @param callback\\nDoc.prototype.ingestSnapshot = function(snapshot, callback) {\\n if (!snapshot) return callback \u0026\u0026 callback();\\n\\n if (typeof snapshot.v !== \u0027number\u0027) {\\n var err = new ShareDBError(\\n ERROR_CODE.ERR_INGESTED_SNAPSHOT_HAS_NO_VERSION,\\n \u0027Missing version in ingested snapshot. \u0027 \u002B this.collection \u002B \u0027.\u0027 \u002B this.id\\n );\\n if (callback) return callback(err);\\n return this.emit(\u0027error\u0027, err);\\n }\\n\\n // If the doc is already created or there are ops pending, we cannot use the\\n // ingested snapshot and need ops in order to update the document\\n if (this.type || this.hasWritePending()) {\\n // The version should only be null on a created document when it was\\n // created locally without fetching\\n if (this.version == null) {\\n if (this.hasWritePending()) {\\n // If we have pending ops and we get a snapshot for a locally created\\n // document, we have to wait for the pending ops to complete, because\\n // we don\u0027t know what version to fetch ops from. It is possible that\\n // the snapshot came from our local op, but it is also possible that\\n // the doc was created remotely (which would conflict and be an error)\\n return callback \u0026\u0026 this.once(\u0027no write pending\u0027, callback);\\n }\\n // Otherwise, we\u0027ve encounted an error state\\n var err = new ShareDBError(\\n ERROR_CODE.ERR_DOC_MISSING_VERSION,\\n \u0027Cannot ingest snapshot in doc with null version. \u0027 \u002B this.collection \u002B \u0027.\u0027 \u002B this.id\\n );\\n if (callback) return callback(err);\\n return this.emit(\u0027error\u0027, err);\\n }\\n // If we got a snapshot for a version further along than the document is\\n // currently, issue a fetch to get the latest ops and catch us up\\n if (snapshot.v \u003E this.version) return this.fetch(callback);\\n return callback \u0026\u0026 callback();\\n }\\n\\n // Ignore the snapshot if we are already at a newer version. Under no\\n // circumstance should we ever set the current version backward\\n if (this.version \u003E snapshot.v) return callback \u0026\u0026 callback();\\n\\n this.version = snapshot.v;\\n var type = (snapshot.type === undefined) ? types.defaultType : snapshot.type;\\n this._setType(type);\\n this._setData(\\n (this.type \u0026\u0026 this.type.deserialize) ?\\n this.type.deserialize(snapshot.data) :\\n snapshot.data\\n );\\n this.emit(\u0027load\u0027);\\n callback \u0026\u0026 callback();\\n};\\n\\nDoc.prototype.whenNothingPending = function(callback) {\\n var doc = this;\\n util.nextTick(function() {\\n if (doc.hasPending()) {\\n doc.once(\u0027nothing pending\u0027, callback);\\n return;\\n }\\n callback();\\n });\\n};\\n\\nDoc.prototype.hasPending = function() {\\n return !!(\\n this.inflightOp ||\\n this.pendingOps.length ||\\n this.inflightFetch.length ||\\n this.inflightSubscribe ||\\n this.pendingFetch.length ||\\n this.pendingSubscribe.length\\n );\\n};\\n\\nDoc.prototype.hasWritePending = function() {\\n return !!(this.inflightOp || this.pendingOps.length);\\n};\\n\\nDoc.prototype._emitNothingPending = function() {\\n if (this.hasWritePending()) return;\\n this.emit(\u0027no write pending\u0027);\\n if (this.hasPending()) return;\\n this.emit(\u0027nothing pending\u0027);\\n};\\n\\n// **** Helpers for network messages\\n\\nDoc.prototype._emitResponseError = function(err, callback) {\\n if (err \u0026\u0026 err.code === ERROR_CODE.ERR_SNAPSHOT_READ_SILENT_REJECTION) {\\n this.wantSubscribe = false;\\n if (callback) {\\n callback();\\n }\\n this._emitNothingPending();\\n return;\\n }\\n if (callback) {\\n callback(err);\\n this._emitNothingPending();\\n return;\\n }\\n this._emitNothingPending();\\n this.emit(\u0027error\u0027, err);\\n};\\n\\nDoc.prototype._handleFetch = function(error, snapshot) {\\n var callbacks = this.pendingFetch;\\n this.pendingFetch = [];\\n var callback = this.inflightFetch.shift();\\n if (callback) callbacks.push(callback);\\n if (callbacks.length) {\\n callback = function(error) {\\n util.callEach(callbacks, error);\\n };\\n }\\n if (error) return this._emitResponseError(error, callback);\\n this.ingestSnapshot(snapshot, callback);\\n this._emitNothingPending();\\n};\\n\\nDoc.prototype._handleSubscribe = function(error, snapshot) {\\n var request = this.inflightSubscribe;\\n this.inflightSubscribe = null;\\n var callbacks = this.pendingFetch;\\n this.pendingFetch = [];\\n if (request.callback) callbacks.push(request.callback);\\n var callback;\\n if (callbacks.length) {\\n callback = function(error) {\\n util.callEach(callbacks, error);\\n };\\n }\\n if (error) return this._emitResponseError(error, callback);\\n this.subscribed = request.wantSubscribe;\\n if (this.subscribed) this.ingestSnapshot(snapshot, callback);\\n else if (callback) callback();\\n this._emitNothingPending();\\n this._flushSubscribe();\\n};\\n\\nDoc.prototype._handleOp = function(err, message) {\\n if (err) {\\n if (this.inflightOp) {\\n // The server has rejected submission of the current operation. If we get\\n // an \u0022Op submit rejected\u0022 error, this was done intentionally\\n // and we should roll back but not return an error to the user.\\n if (err.code === ERROR_CODE.ERR_OP_SUBMIT_REJECTED) err = null;\\n return this._rollback(err);\\n }\\n return this.emit(\u0027error\u0027, err);\\n }\\n\\n if (this.inflightOp \u0026\u0026\\n message.src === this.inflightOp.src \u0026\u0026\\n message.seq === this.inflightOp.seq) {\\n // The op has already been applied locally. Just update the version\\n // and pending state appropriately\\n this._opAcknowledged(message);\\n return;\\n }\\n\\n if (this.version == null || message.v \u003E this.version) {\\n // This will happen in normal operation if we become subscribed to a\\n // new document via a query. It can also happen if we get an op for\\n // a future version beyond the version we are expecting next. This\\n // could happen if the server doesn\u0027t publish an op for whatever reason\\n // or because of a race condition. In any case, we can send a fetch\\n // command to catch back up.\\n //\\n // Fetch only sends a new fetch command if no fetches are inflight, which\\n // will act as a natural debouncing so we don\u0027t send multiple fetch\\n // requests for many ops received at once.\\n this.fetch();\\n return;\\n }\\n\\n if (message.v \u003C this.version) {\\n // We can safely ignore the old (duplicate) operation.\\n return;\\n }\\n\\n if (this.inflightOp) {\\n var transformErr = transformX(this.inflightOp, message);\\n if (transformErr) return this._hardRollback(transformErr);\\n }\\n\\n for (var i = 0; i \u003C this.pendingOps.length; i\u002B\u002B) {\\n var transformErr = transformX(this.pendingOps[i], message);\\n if (transformErr) return this._hardRollback(transformErr);\\n }\\n\\n this.version\u002B\u002B;\\n try {\\n this._otApply(message, false);\\n } catch (error) {\\n return this._hardRollback(error);\\n }\\n};\\n\\n// Called whenever (you guessed it!) the connection state changes. This will\\n// happen when we get disconnected \u0026 reconnect.\\nDoc.prototype._onConnectionStateChanged = function() {\\n if (this.connection.canSend) {\\n this.flush();\\n this._resubscribe();\\n } else {\\n if (this.inflightOp) {\\n this.pendingOps.unshift(this.inflightOp);\\n this.inflightOp = null;\\n }\\n this.subscribed = false;\\n if (this.inflightSubscribe) {\\n if (this.inflightSubscribe.wantSubscribe) {\\n this.pendingSubscribe.unshift(this.inflightSubscribe);\\n this.inflightSubscribe = null;\\n } else {\\n this._handleSubscribe();\\n }\\n }\\n if (this.inflightFetch.length) {\\n this.pendingFetch = this.pendingFetch.concat(this.inflightFetch);\\n this.inflightFetch.length = 0;\\n }\\n }\\n};\\n\\nDoc.prototype._resubscribe = function() {\\n if (!this.pendingSubscribe.length \u0026\u0026 this.wantSubscribe) {\\n return this.subscribe();\\n }\\n var willFetch = this.pendingSubscribe.some(function(request) {\\n return request.wantSubscribe;\\n });\\n if (!willFetch \u0026\u0026 this.pendingFetch.length) this.fetch();\\n this._flushSubscribe();\\n};\\n\\n// Request the current document snapshot or ops that bring us up to date\\nDoc.prototype.fetch = function(callback) {\\n if (this.connection.canSend) {\\n var isDuplicate = this.connection.sendFetch(this);\\n pushActionCallback(this.inflightFetch, isDuplicate, callback);\\n return;\\n }\\n this.pendingFetch.push(callback);\\n};\\n\\n// Fetch the initial document and keep receiving updates\\nDoc.prototype.subscribe = function(callback) {\\n var wantSubscribe = true;\\n this._queueSubscribe(wantSubscribe, callback);\\n};\\n\\n// Unsubscribe. The data will stay around in local memory, but we\u0027ll stop\\n// receiving updates\\nDoc.prototype.unsubscribe = function(callback) {\\n var wantSubscribe = false;\\n this._queueSubscribe(wantSubscribe, callback);\\n};\\n\\nDoc.prototype._queueSubscribe = function(wantSubscribe, callback) {\\n var lastRequest = this.pendingSubscribe[this.pendingSubscribe.length - 1] || this.inflightSubscribe;\\n var isDuplicateRequest = lastRequest \u0026\u0026 lastRequest.wantSubscribe === wantSubscribe;\\n if (isDuplicateRequest) {\\n lastRequest.callback = combineCallbacks([lastRequest.callback, callback]);\\n return;\\n }\\n this.pendingSubscribe.push({\\n wantSubscribe: !!wantSubscribe,\\n callback: callback\\n });\\n this._flushSubscribe();\\n};\\n\\nDoc.prototype._flushSubscribe = function() {\\n if (this.inflightSubscribe || !this.pendingSubscribe.length) return;\\n\\n if (this.connection.canSend) {\\n this.inflightSubscribe = this.pendingSubscribe.shift();\\n this.wantSubscribe = this.inflightSubscribe.wantSubscribe;\\n if (this.wantSubscribe) {\\n this.connection.sendSubscribe(this);\\n } else {\\n // Be conservative about our subscription state. We\u0027ll be unsubscribed\\n // some time between sending this request, and receiving the callback,\\n // so let\u0027s just set ourselves to unsubscribed now.\\n this.subscribed = false;\\n this.connection.sendUnsubscribe(this);\\n }\\n\\n return;\\n }\\n\\n // If we\u0027re offline, then we\u0027re already unsubscribed. Therefore, call back\\n // the next request immediately if it\u0027s an unsubscribe request.\\n if (!this.pendingSubscribe[0].wantSubscribe) {\\n this.inflightSubscribe = this.pendingSubscribe.shift();\\n var doc = this;\\n util.nextTick(function() {\\n doc._handleSubscribe();\\n });\\n }\\n};\\n\\nfunction pushActionCallback(inflight, isDuplicate, callback) {\\n if (isDuplicate) {\\n var lastCallback = inflight.pop();\\n inflight.push(function(err) {\\n lastCallback \u0026\u0026 lastCallback(err);\\n callback \u0026\u0026 callback(err);\\n });\\n } else {\\n inflight.push(callback);\\n }\\n}\\n\\nfunction combineCallbacks(callbacks) {\\n callbacks = callbacks.filter(util.truthy);\\n if (!callbacks.length) return null;\\n return function(error) {\\n util.callEach(callbacks, error);\\n };\\n}\\n\\n\\n// Operations //\\n\\n// Send the next pending op to the server, if we can.\\n//\\n// Only one operation can be in-flight at a time. If an operation is already on\\n// its way, or we\u0027re not currently connected, this method does nothing.\\nDoc.prototype.flush = function() {\\n // Ignore if we can\u0027t send or we are already sending an op\\n if (!this.connection.canSend || this.inflightOp) return;\\n\\n // Send first pending op unless paused\\n if (!this.paused \u0026\u0026 this.pendingOps.length) {\\n this._sendOp();\\n }\\n};\\n\\n// Helper function to set op to contain a no-op.\\nfunction setNoOp(op) {\\n delete op.op;\\n delete op.create;\\n delete op.del;\\n}\\n\\n// Transform server op data by a client op, and vice versa. Ops are edited in place.\\nfunction transformX(client, server) {\\n // Order of statements in this function matters. Be especially careful if\\n // refactoring this function\\n\\n // A client delete op should dominate if both the server and the client\\n // delete the document. Thus, any ops following the client delete (such as a\\n // subsequent create) will be maintained, since the server op is transformed\\n // to a no-op\\n if (client.del) return setNoOp(server);\\n\\n if (server.del) {\\n return new ShareDBError(ERROR_CODE.ERR_DOC_WAS_DELETED, \u0027Document was deleted\u0027);\\n }\\n if (server.create) {\\n return new ShareDBError(ERROR_CODE.ERR_DOC_ALREADY_CREATED, \u0027Document already created\u0027);\\n }\\n\\n // Ignore no-op coming from server\\n if (!(\u0027op\u0027 in server)) return;\\n\\n // I believe that this should not occur, but check just in case\\n if (client.create) {\\n return new ShareDBError(ERROR_CODE.ERR_DOC_ALREADY_CREATED, \u0027Document already created\u0027);\\n }\\n\\n // They both edited the document. This is the normal case for this function -\\n // as in, most of the time we\u0027ll end up down here.\\n //\\n // You should be wondering why I\u0027m using client.type instead of this.type.\\n // The reason is, if we get ops at an old version of the document, this.type\\n // might be undefined or a totally different type. By pinning the type to the\\n // op data, we make sure the right type has its transform function called.\\n if (client.type.transformX) {\\n var result = client.type.transformX(client.op, server.op);\\n client.op = result[0];\\n server.op = result[1];\\n } else {\\n var clientOp = client.type.transform(client.op, server.op, \u0027left\u0027);\\n var serverOp = client.type.transform(server.op, client.op, \u0027right\u0027);\\n client.op = clientOp;\\n server.op = serverOp;\\n }\\n};\\n\\n/**\\n * Applies the operation to the snapshot\\n *\\n * If the operation is create or delete it emits \\\u0060create\\\u0060 or \\\u0060del\\\u0060. Then the\\n * operation is applied to the snapshot and \\\u0060op\\\u0060 and \\\u0060after op\\\u0060 are emitted.\\n * If the type supports incremental updates and \\\u0060this.incremental\\\u0060 is true we\\n * fire \\\u0060op\\\u0060 after every small operation.\\n *\\n * This is the only function to fire the above mentioned events.\\n *\\n * @private\\n */\\nDoc.prototype._otApply = function(op, source) {\\n if (\u0027op\u0027 in op) {\\n if (!this.type) {\\n // Throw here, because all usage of _otApply should be wrapped with a try/catch\\n throw new ShareDBError(\\n ERROR_CODE.ERR_DOC_DOES_NOT_EXIST,\\n \u0027Cannot apply op to uncreated document. \u0027 \u002B this.collection \u002B \u0027.\u0027 \u002B this.id\\n );\\n }\\n\\n // NB: If we need to add another argument to this event, we should consider\\n // the fact that the \u0027op\u0027 event has op.src as its 3rd argument\\n this.emit(\u0027before op batch\u0027, op.op, source);\\n\\n // Iteratively apply multi-component remote operations and rollback ops\\n // (source === false) for the default JSON0 OT type. It could use\\n // type.shatter(), but since this code is so specific to use cases for the\\n // JSON0 type and ShareDB explicitly bundles the default type, we might as\\n // well write it this way and save needing to iterate through the op\\n // components twice.\\n //\\n // Ideally, we would not need this extra complexity. However, it is\\n // helpful for implementing bindings that update DOM nodes and other\\n // stateful objects by translating op events directly into corresponding\\n // mutations. Such bindings are most easily written as responding to\\n // individual op components one at a time in order, and it is important\\n // that the snapshot only include updates from the particular op component\\n // at the time of emission. Eliminating this would require rethinking how\\n // such external bindings are implemented.\\n if (!source \u0026\u0026 this.type === types.defaultType \u0026\u0026 op.op.length \u003E 1) {\\n if (!this.applyStack) this.applyStack = [];\\n var stackLength = this.applyStack.length;\\n for (var i = 0; i \u003C op.op.length; i\u002B\u002B) {\\n var component = op.op[i];\\n var componentOp = {op: [component]};\\n // Apply the individual op component\\n this.emit(\u0027before op\u0027, componentOp.op, source, op.src);\\n // Transform componentOp against any ops that have been submitted\\n // sychronously inside of an op event handler since we began apply of\\n // our operation\\n for (var j = stackLength; j \u003C this.applyStack.length; j\u002B\u002B) {\\n var transformErr = transformX(this.applyStack[j], componentOp);\\n if (transformErr) return this._hardRollback(transformErr);\\n }\\n this._setData(this.type.apply(this.data, componentOp.op));\\n this.emit(\u0027op\u0027, componentOp.op, source, op.src);\\n }\\n this.emit(\u0027op batch\u0027, op.op, source);\\n // Pop whatever was submitted since we started applying this op\\n this._popApplyStack(stackLength);\\n return;\\n }\\n\\n // The \u0027before op\u0027 event enables clients to pull any necessary data out of\\n // the snapshot before it gets changed\\n this.emit(\u0027before op\u0027, op.op, source, op.src);\\n // Apply the operation to the local data, mutating it in place\\n this._setData(this.type.apply(this.data, op.op));\\n // Emit an \u0027op\u0027 event once the local data includes the changes from the\\n // op. For locally submitted ops, this will be synchronously with\\n // submission and before the server or other clients have received the op.\\n // For ops from other clients, this will be after the op has been\\n // committed to the database and published\\n this.emit(\u0027op\u0027, op.op, source, op.src);\\n this.emit(\u0027op batch\u0027, op.op, source);\\n return;\\n }\\n\\n if (op.create) {\\n this._setType(op.create.type);\\n if (this.type.deserialize) {\\n if (this.type.createDeserialized) {\\n this._setData(this.type.createDeserialized(op.create.data));\\n } else {\\n this._setData(this.type.deserialize(this.type.create(op.create.data)));\\n }\\n } else {\\n this._setData(this.type.create(op.create.data));\\n }\\n this.emit(\u0027create\u0027, source);\\n return;\\n }\\n\\n if (op.del) {\\n var oldData = this.data;\\n this._setType(null);\\n this.emit(\u0027del\u0027, oldData, source);\\n return;\\n }\\n};\\n\\n\\n// ***** Sending operations\\n\\n// Actually send op to the server.\\nDoc.prototype._sendOp = function() {\\n if (!this.connection.canSend) return;\\n var src = this.connection.id;\\n\\n // When there is no inflightOp, send the first item in pendingOps. If\\n // there is inflightOp, try sending it again\\n if (!this.inflightOp) {\\n // Send first pending op\\n this.inflightOp = this.pendingOps.shift();\\n }\\n var op = this.inflightOp;\\n if (!op) {\\n var err = new ShareDBError(ERROR_CODE.ERR_INFLIGHT_OP_MISSING, \u0027No op to send on call to _sendOp\u0027);\\n return this.emit(\u0027error\u0027, err);\\n }\\n\\n // Track data for retrying ops\\n op.sentAt = Date.now();\\n op.retries = (op.retries == null) ? 0 : op.retries \u002B 1;\\n\\n // The src \u002B seq number is a unique ID representing this operation. This tuple\\n // is used on the server to detect when ops have been sent multiple times and\\n // on the client to match acknowledgement of an op back to the inflightOp.\\n // Note that the src could be different from this.connection.id after a\\n // reconnect, since an op may still be pending after the reconnection and\\n // this.connection.id will change. In case an op is sent multiple times, we\\n // also need to be careful not to override the original seq value.\\n if (op.seq == null) {\\n if (this.connection.seq \u003E= util.MAX_SAFE_INTEGER) {\\n return this.emit(\u0027error\u0027, new ShareDBError(\\n ERROR_CODE.ERR_CONNECTION_SEQ_INTEGER_OVERFLOW,\\n \u0027Connection seq has exceeded the max safe integer, maybe from being open for too long\u0027\\n ));\\n }\\n\\n op.seq = this.connection.seq\u002B\u002B;\\n }\\n\\n this.connection.sendOp(this, op);\\n\\n // src isn\u0027t needed on the first try, since the server session will have the\\n // same id, but it must be set on the inflightOp in case it is sent again\\n // after a reconnect and the connection\u0027s id has changed by then\\n if (op.src == null) op.src = src;\\n};\\n\\n\\n// Queues the operation for submission to the server and applies it locally.\\n//\\n// Internal method called to do the actual work for submit(), create() and del().\\n// @private\\n//\\n// @param op\\n// @param [op.op]\\n// @param [op.del]\\n// @param [op.create]\\n// @param [callback] called when operation is submitted\\nDoc.prototype._submit = function(op, source, callback) {\\n // Locally submitted ops must always have a truthy source\\n if (!source) source = true;\\n\\n // The op contains either op, create, delete, or none of the above (a no-op).\\n if (\u0027op\u0027 in op) {\\n if (!this.type) {\\n var err = new ShareDBError(\\n ERROR_CODE.ERR_DOC_DOES_NOT_EXIST,\\n \u0027Cannot submit op. Document has not been created. \u0027 \u002B this.collection \u002B \u0027.\u0027 \u002B this.id\\n );\\n if (callback) return callback(err);\\n return this.emit(\u0027error\u0027, err);\\n }\\n // Try to normalize the op. This removes trailing skip:0\u0027s and things like that.\\n if (this.type.normalize) op.op = this.type.normalize(op.op);\\n }\\n\\n try {\\n this._pushOp(op, source, callback);\\n this._otApply(op, source);\\n } catch (error) {\\n return this._hardRollback(error);\\n }\\n\\n // The call to flush is delayed so if submit() is called multiple times\\n // synchronously, all the ops are combined before being sent to the server.\\n var doc = this;\\n util.nextTick(function() {\\n doc.flush();\\n });\\n};\\n\\nDoc.prototype._pushOp = function(op, source, callback) {\\n op.source = source;\\n if (this.applyStack) {\\n // If we are in the process of incrementally applying an operation, don\u0027t\\n // compose the op and push it onto the applyStack so it can be transformed\\n // against other components from the op or ops being applied\\n this.applyStack.push(op);\\n } else {\\n // If the type supports composes, try to compose the operation onto the\\n // end of the last pending operation.\\n var composed = this._tryCompose(op);\\n if (composed) {\\n composed.callbacks.push(callback);\\n return;\\n }\\n }\\n // Push on to the pendingOps queue of ops to submit if we didn\u0027t compose\\n op.type = this.type;\\n op.callbacks = [callback];\\n this.pendingOps.push(op);\\n};\\n\\nDoc.prototype._popApplyStack = function(to) {\\n if (to \u003E 0) {\\n this.applyStack.length = to;\\n return;\\n }\\n // Once we have completed the outermost apply loop, reset to null and no\\n // longer add ops to the applyStack as they are submitted\\n var op = this.applyStack[0];\\n this.applyStack = null;\\n if (!op) return;\\n // Compose the ops added since the beginning of the apply stack, since we\\n // had to skip compose when they were originally pushed\\n var i = this.pendingOps.indexOf(op);\\n if (i === -1) return;\\n var ops = this.pendingOps.splice(i);\\n for (var i = 0; i \u003C ops.length; i\u002B\u002B) {\\n var op = ops[i];\\n var composed = this._tryCompose(op);\\n if (composed) {\\n composed.callbacks = composed.callbacks.concat(op.callbacks);\\n } else {\\n this.pendingOps.push(op);\\n }\\n }\\n};\\n\\n// Try to compose a submitted op into the last pending op. Returns the\\n// composed op if it succeeds, undefined otherwise\\nDoc.prototype._tryCompose = function(op) {\\n if (this.preventCompose) return;\\n\\n // We can only compose into the last pending op. Inflight ops have already\\n // been sent to the server, so we can\u0027t modify them\\n var last = this.pendingOps[this.pendingOps.length - 1];\\n if (!last || last.sentAt) return;\\n\\n // If we\u0027re submitting the op source, we can only combine ops that have\\n // a matching source\\n if (this.submitSource \u0026\u0026 !deepEqual(op.source, last.source)) return;\\n\\n // Compose an op into a create by applying it. This effectively makes the op\\n // invisible, as if the document were created including the op originally\\n if (last.create \u0026\u0026 \u0027op\u0027 in op) {\\n last.create.data = this.type.apply(last.create.data, op.op);\\n return last;\\n }\\n\\n // Compose two ops into a single op if supported by the type. Types that\\n // support compose must be able to compose any two ops together\\n if (\u0027op\u0027 in last \u0026\u0026 \u0027op\u0027 in op \u0026\u0026 this.type.compose) {\\n last.op = this.type.compose(last.op, op.op);\\n return last;\\n }\\n};\\n\\n// *** Client OT entrypoints.\\n\\n// Submit an operation to the document.\\n//\\n// @param operation handled by the OT type\\n// @param options {source: ...}\\n// @param [callback] called after operation submitted\\n//\\n// @fires before op, op, after op\\nDoc.prototype.submitOp = function(component, options, callback) {\\n if (typeof options === \u0027function\u0027) {\\n callback = options;\\n options = null;\\n }\\n var op = {op: component};\\n var source = options \u0026\u0026 options.source;\\n this._submit(op, source, callback);\\n};\\n\\n// Create the document, which in ShareJS semantics means to set its type. Every\\n// object implicitly exists in the database but has no data and no type. Create\\n// sets the type of the object and can optionally set some initial data on the\\n// object, depending on the type.\\n//\\n// @param data initial\\n// @param type OT type\\n// @param options {source: ...}\\n// @param callback called when operation submitted\\nDoc.prototype.create = function(data, type, options, callback) {\\n if (typeof type === \u0027function\u0027) {\\n callback = type;\\n options = null;\\n type = null;\\n } else if (typeof options === \u0027function\u0027) {\\n callback = options;\\n options = null;\\n }\\n if (!type) {\\n type = types.defaultType.uri;\\n }\\n if (this.type) {\\n var err = new ShareDBError(ERROR_CODE.ERR_DOC_ALREADY_CREATED, \u0027Document already exists\u0027);\\n if (callback) return callback(err);\\n return this.emit(\u0027error\u0027, err);\\n }\\n var op = {create: {type: type, data: data}};\\n var source = options \u0026\u0026 options.source;\\n this._submit(op, source, callback);\\n};\\n\\n// Delete the document. This creates and submits a delete operation to the\\n// server. Deleting resets the object\u0027s type to null and deletes its data. The\\n// document still exists, and still has the version it used to have before you\\n// deleted it (well, old version \u002B1).\\n//\\n// @param options {source: ...}\\n// @param callback called when operation submitted\\nDoc.prototype.del = function(options, callback) {\\n if (typeof options === \u0027function\u0027) {\\n callback = options;\\n options = null;\\n }\\n if (!this.type) {\\n var err = new ShareDBError(ERROR_CODE.ERR_DOC_DOES_NOT_EXIST, \u0027Document does not exist\u0027);\\n if (callback) return callback(err);\\n return this.emit(\u0027error\u0027, err);\\n }\\n var op = {del: true};\\n var source = options \u0026\u0026 options.source;\\n this._submit(op, source, callback);\\n};\\n\\n\\n// Stops the document from sending any operations to the server.\\nDoc.prototype.pause = function() {\\n this.paused = true;\\n};\\n\\n// Continue sending operations to the server\\nDoc.prototype.resume = function() {\\n this.paused = false;\\n this.flush();\\n};\\n\\n// Create a snapshot that can be serialized, deserialized, and passed into \\\u0060Doc.ingestSnapshot\\\u0060.\\nDoc.prototype.toSnapshot = function() {\\n return {\\n v: this.version,\\n data: clone(this.data),\\n type: this.type.uri\\n };\\n};\\n\\n// *** Receiving operations\\n\\n// This is called when the server acknowledges an operation from the client.\\nDoc.prototype._opAcknowledged = function(message) {\\n if (this.inflightOp.create) {\\n this.version = message.v;\\n } else if (message.v !== this.version) {\\n // We should already be at the same version, because the server should\\n // have sent all the ops that have happened before acknowledging our op\\n logger.warn(\u0027Invalid version from server. Expected: \u0027 \u002B this.version \u002B \u0027 Received: \u0027 \u002B message.v, message);\\n\\n // Fetching should get us back to a working document state\\n return this.fetch();\\n }\\n\\n // The op was committed successfully. Increment the version number\\n this.version\u002B\u002B;\\n\\n this._clearInflightOp();\\n};\\n\\nDoc.prototype._rollback = function(err) {\\n // The server has rejected submission of the current operation. Invert by\\n // just the inflight op if possible. If not possible to invert, cancel all\\n // pending ops and fetch the latest from the server to get us back into a\\n // working state, then call back\\n var op = this.inflightOp;\\n\\n if (\u0027op\u0027 in op \u0026\u0026 op.type.invert) {\\n try {\\n op.op = op.type.invert(op.op);\\n } catch (error) {\\n // If the op doesn\u0027t support \\\u0060.invert()\\\u0060, we just reload the doc\\n // instead of trying to locally revert it.\\n return this._hardRollback(err);\\n }\\n\\n // Transform the undo operation by any pending ops.\\n for (var i = 0; i \u003C this.pendingOps.length; i\u002B\u002B) {\\n var transformErr = transformX(this.pendingOps[i], op);\\n if (transformErr) return this._hardRollback(transformErr);\\n }\\n\\n // ... and apply it locally, reverting the changes.\\n //\\n // This operation is applied to look like it comes from a remote source.\\n // I\u0027m still not 100% sure about this functionality, because its really a\\n // local op. Basically, the problem is that if the client\u0027s op is rejected\\n // by the server, the editor window should update to reflect the undo.\\n try {\\n this._otApply(op, false);\\n } catch (error) {\\n return this._hardRollback(error);\\n }\\n\\n this._clearInflightOp(err);\\n return;\\n }\\n\\n this._hardRollback(err);\\n};\\n\\nDoc.prototype._hardRollback = function(err) {\\n // Store pending ops so that we can notify their callbacks of the error.\\n // We combine the inflight op and the pending ops, because it\u0027s possible\\n // to hit a condition where we have no inflight op, but we do have pending\\n // ops. This can happen when an invalid op is submitted, which causes us\\n // to hard rollback before the pending op was flushed.\\n var pendingOps = [];\\n if (this.inflightOp) pendingOps.push(this.inflightOp);\\n pendingOps = pendingOps.concat(this.pendingOps);\\n\\n // Cancel all pending ops and reset if we can\u0027t invert\\n this._setType(null);\\n this.version = null;\\n this.inflightOp = null;\\n this.pendingOps = [];\\n\\n // Fetch the latest version from the server to get us back into a working state\\n var doc = this;\\n this.fetch(function() {\\n // We want to check that no errors are swallowed, so we check that:\\n // - there are callbacks to call, and\\n // - that every single pending op called a callback\\n // If there are no ops queued, or one of them didn\u0027t handle the error,\\n // then we emit the error.\\n var allOpsHadCallbacks = !!pendingOps.length;\\n for (var i = 0; i \u003C pendingOps.length; i\u002B\u002B) {\\n allOpsHadCallbacks = util.callEach(pendingOps[i].callbacks, err) \u0026\u0026 allOpsHadCallbacks;\\n }\\n if (err \u0026\u0026 !allOpsHadCallbacks) return doc.emit(\u0027error\u0027, err);\\n });\\n};\\n\\nDoc.prototype._clearInflightOp = function(err) {\\n var inflightOp = this.inflightOp;\\n\\n this.inflightOp = null;\\n\\n var called = util.callEach(inflightOp.callbacks, err);\\n\\n this.flush();\\n this._emitNothingPending();\\n\\n if (err \u0026\u0026 !called) return this.emit(\u0027error\u0027, err);\\n};\\n\u0060;\r\nconst query = \u0027pendingOps\u0027;\r\nconst query_ignore = query.toLowerCase();\r\nconst query_cased = query;\r\nconst regex_ignore = new RegExp(query, \u0027gi\u0027);\r\nconst regex_cased = new RegExp(query, \u0027g\u0027);\r\n\r\nfunction* search_index_cased() {\r\n const a = content;\r\n const len = query_cased.length;\r\n let i = 0;\r\n while (true) {\r\n i = a.indexOf(query_cased, i \u002B 1);\r\n if (i \u003C 0) return;\r\n yield [i, len];\r\n }\r\n}\r\n\r\nfunction* search_index_ignore() {\r\n const a = content.toLowerCase();\r\n const len = query_ignore.length;\r\n let i = 0;\r\n while (true) {\r\n i = a.indexOf(query_ignore, i \u002B 1);\r\n if (i \u003C 0) return;\r\n yield [i, len];\r\n }\r\n}\r\n\r\nfunction* search_regex_cased() {\r\n for (const match of content.matchAll(regex_cased)) {\r\n yield [match.index, match[0].length];\r\n }\r\n}\r\n\r\nfunction* search_regex_ignore() {\r\n for (const match of content.matchAll(regex_ignore)) {\r\n yield [match.index, match[0].length];\r\n }\r\n}","TestCases":[{"Name":"search_index_cased","Code":"Array.from(search_index_cased())","IsDeferred":false},{"Name":"search_index_ignore","Code":"Array.from(search_index_ignore())","IsDeferred":false},{"Name":"search_regex_cased","Code":"Array.from(search_regex_cased())","IsDeferred":false},{"Name":"search_regex_ignore","Code":"Array.from(search_regex_ignore())","IsDeferred":false}]}