@@ -180,6 +180,28 @@ exports.oldLen = (cs) => exports.unpack(cs).oldLen;
180180 */
181181exports . newLen = ( cs ) => exports . unpack ( cs ) . newLen ;
182182
183+ /**
184+ * Parses a string of serialized changeset operations.
185+ *
186+ * @param {string } ops - Serialized changeset operations.
187+ * @yields {Op}
188+ * @returns {Generator<Op> }
189+ */
190+ const deserializeOps = function * ( ops ) {
191+ // TODO: Migrate to String.prototype.matchAll() once there is enough browser support.
192+ const regex = / ( (?: \* [ 0 - 9 a - z ] + ) * ) (?: \| ( [ 0 - 9 a - z ] + ) ) ? ( [ - + = ] ) ( [ 0 - 9 a - z ] + ) | ( .) / g;
193+ let match ;
194+ while ( ( match = regex . exec ( ops ) ) != null ) {
195+ if ( match [ 5 ] === '$' ) return ; // Start of the insert operation character bank.
196+ if ( match [ 5 ] != null ) error ( `invalid operation: ${ ops . slice ( regex . lastIndex - 1 ) } ` ) ;
197+ const op = new Op ( match [ 3 ] ) ;
198+ op . lines = exports . parseNum ( match [ 2 ] || '0' ) ;
199+ op . chars = exports . parseNum ( match [ 4 ] ) ;
200+ op . attribs = match [ 1 ] ;
201+ yield op ;
202+ }
203+ } ;
204+
183205/**
184206 * Iterator over a changeset's operations.
185207 *
@@ -190,24 +212,15 @@ class OpIter {
190212 * @param {string } ops - String encoding the change operations to iterate over.
191213 */
192214 constructor ( ops ) {
193- this . _ops = ops ;
194- this . _regex = / ( (?: \* [ 0 - 9 a - z ] + ) * ) (?: \| ( [ 0 - 9 a - z ] + ) ) ? ( [ - + = ] ) ( [ 0 - 9 a - z ] + ) | ( .) / g;
195- this . _nextMatch = this . _nextRegexMatch ( ) ;
196- }
197-
198- _nextRegexMatch ( ) {
199- const match = this . _regex . exec ( this . _ops ) ;
200- if ( ! match ) return null ;
201- if ( match [ 5 ] === '$' ) return null ; // Start of the insert operation character bank.
202- if ( match [ 5 ] != null ) error ( `invalid operation: ${ this . _ops . slice ( this . _regex . lastIndex - 1 ) } ` ) ;
203- return match ;
215+ this . _gen = deserializeOps ( ops ) ;
216+ this . _next = this . _gen . next ( ) ;
204217 }
205218
206219 /**
207220 * @returns {boolean } Whether there are any remaining operations.
208221 */
209222 hasNext ( ) {
210- return this . _nextMatch && ! ! this . _nextMatch [ 0 ] ;
223+ return ! this . _next . done ;
211224 }
212225
213226 /**
@@ -221,11 +234,8 @@ class OpIter {
221234 */
222235 next ( opOut = new Op ( ) ) {
223236 if ( this . hasNext ( ) ) {
224- opOut . attribs = this . _nextMatch [ 1 ] ;
225- opOut . lines = exports . parseNum ( this . _nextMatch [ 2 ] || '0' ) ;
226- opOut . opcode = this . _nextMatch [ 3 ] ;
227- opOut . chars = exports . parseNum ( this . _nextMatch [ 4 ] ) ;
228- this . _nextMatch = this . _nextRegexMatch ( ) ;
237+ copyOp ( this . _next . value , opOut ) ;
238+ this . _next = this . _gen . next ( ) ;
229239 } else {
230240 clearOp ( opOut ) ;
231241 }
0 commit comments