@@ -432,7 +432,7 @@ class MergingOpAssembler {
432432 * @returns {Generator<Op, number> } The done value indicates how much the sequence of operations
433433 * changes the length of the document (in characters).
434434 */
435- const canonicalizeOps = function * ( ops , finalize ) {
435+ exports . canonicalizeOps = function * ( ops , finalize ) {
436436 let minusOps = [ ] ;
437437 let plusOps = [ ] ;
438438 let keepOps = [ ] ;
@@ -519,6 +519,8 @@ const opsFromText = function* (opcode, text, attribs = '', pool = null) {
519519 * - strips final "="
520520 * - ignores 0-length changes
521521 * - reorders consecutive + and - (which MergingOpAssembler doesn't do)
522+ *
523+ * @deprecated Use `canonicalizeOps` with `serializeOps` instead.
522524 */
523525class SmartOpAssembler {
524526 constructor ( ) {
@@ -533,7 +535,7 @@ class SmartOpAssembler {
533535
534536 _serialize ( finalize ) {
535537 this . _serialized = exports . serializeOps ( ( function * ( ) {
536- this . _lengthChange = yield * canonicalizeOps ( this . _ops , finalize ) ;
538+ this . _lengthChange = yield * exports . canonicalizeOps ( this . _ops , finalize ) ;
537539 } ) . call ( this ) ) ;
538540 }
539541
@@ -586,51 +588,54 @@ exports.checkRep = (cs) => {
586588 const unpacked = exports . unpack ( cs ) ;
587589 const oldLen = unpacked . oldLen ;
588590 const newLen = unpacked . newLen ;
589- const ops = unpacked . ops ;
590591 let charBank = unpacked . charBank ;
591592
592- const assem = new SmartOpAssembler ( ) ;
593593 let oldPos = 0 ;
594594 let calcNewLen = 0 ;
595595 let numInserted = 0 ;
596- for ( const o of exports . deserializeOps ( ops ) ) {
597- switch ( o . opcode ) {
598- case '=' :
599- oldPos += o . chars ;
600- calcNewLen += o . chars ;
601- break ;
602- case '-' :
603- oldPos += o . chars ;
604- assert ( oldPos <= oldLen , ` ${ oldPos } > ${ oldLen } in ${ cs } ` ) ;
605- break ;
606- case '+' :
607- {
608- calcNewLen += o . chars ;
609- numInserted += o . chars ;
610- assert ( calcNewLen <= newLen , `${ calcNewLen } > ${ newLen } in ${ cs } ` ) ;
611- break ;
596+ const ops = ( function * ( ) {
597+ for ( const o of exports . deserializeOps ( unpacked . ops ) ) {
598+ switch ( o . opcode ) {
599+ case '=' :
600+ oldPos += o . chars ;
601+ calcNewLen += o . chars ;
602+ break ;
603+ case '-' :
604+ oldPos += o . chars ;
605+ assert ( oldPos <= oldLen , ` ${ oldPos } > ${ oldLen } in ${ cs } ` ) ;
606+ break ;
607+ case '+' :
608+ calcNewLen += o . chars ;
609+ numInserted += o . chars ;
610+ assert ( calcNewLen <= newLen , `${ calcNewLen } > ${ newLen } in ${ cs } ` ) ;
611+ break ;
612612 }
613+ yield o ;
613614 }
614- assem . append ( o ) ;
615- }
615+ } ) ( ) ;
616+ const serializedOps = exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
616617
617618 calcNewLen += oldLen - oldPos ;
618619 charBank = charBank . substring ( 0 , numInserted ) ;
619620 while ( charBank . length < numInserted ) {
620621 charBank += '?' ;
621622 }
622623
623- assem . endDocument ( ) ;
624- const normalized = exports . pack ( oldLen , calcNewLen , assem . toString ( ) , charBank ) ;
624+ const normalized = exports . pack ( oldLen , calcNewLen , serializedOps , charBank ) ;
625625 assert ( normalized === cs , 'Invalid changeset (checkRep failed)' ) ;
626626
627627 return cs ;
628628} ;
629629
630630/**
631+ * @deprecated Use `canonicalizeOps` with `serializeOps` instead.
631632 * @returns {SmartOpAssembler }
632633 */
633- exports . smartOpAssembler = ( ) => new SmartOpAssembler ( ) ;
634+ exports . smartOpAssembler = ( ) => {
635+ padutils . warnWithStack (
636+ 'Changeset.smartOpAssembler() is deprecated; use Changeset.canonicalizeOps() instead' ) ;
637+ return new SmartOpAssembler ( ) ;
638+ } ;
634639
635640/**
636641 * @deprecated Use `squashOps` with `serializeOps` instead.
@@ -1079,22 +1084,22 @@ class TextLinesMutator {
10791084 * @returns {string } the integrated changeset
10801085 */
10811086const applyZip = ( in1 , in2 , func ) => {
1082- const ops1 = exports . deserializeOps ( in1 ) ;
1083- const ops2 = exports . deserializeOps ( in2 ) ;
1084- let next1 = ops1 . next ( ) ;
1085- let next2 = ops2 . next ( ) ;
1086- const assem = new SmartOpAssembler ( ) ;
1087- while ( ! next1 . done || ! next2 . done ) {
1088- if ( ! next1 . done && ! next1 . value . opcode ) next1 = ops1 . next ( ) ;
1089- if ( ! next2 . done && ! next2 . value . opcode ) next2 = ops2 . next ( ) ;
1090- if ( next1 . value == null ) next1 . value = new Op ( ) ;
1091- if ( next2 . value == null ) next2 . value = new Op ( ) ;
1092- if ( ! next1 . value . opcode && ! next2 . value . opcode ) break ;
1093- const opOut = func ( next1 . value , next2 . value ) ;
1094- if ( opOut && opOut . opcode ) assem . append ( opOut ) ;
1095- }
1096- assem . endDocument ( ) ;
1097- return assem . toString ( ) ;
1087+ const ops = ( function * ( ) {
1088+ const ops1 = exports . deserializeOps ( in1 ) ;
1089+ const ops2 = exports . deserializeOps ( in2 ) ;
1090+ let next1 = ops1 . next ( ) ;
1091+ let next2 = ops2 . next ( ) ;
1092+ while ( ! next1 . done || ! next2 . done ) {
1093+ if ( ! next1 . done && ! next1 . value . opcode ) next1 = ops1 . next ( ) ;
1094+ if ( ! next2 . done && ! next2 . value . opcode ) next2 = ops2 . next ( ) ;
1095+ if ( next1 . value == null ) next1 . value = new Op ( ) ;
1096+ if ( next2 . value == null ) next2 . value = new Op ( ) ;
1097+ if ( ! next1 . value . opcode && ! next2 . value . opcode ) break ;
1098+ const opOut = func ( next1 . value , next2 . value ) ;
1099+ if ( opOut && opOut . opcode ) yield opOut ;
1100+ }
1101+ } ) ( ) ;
1102+ return exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
10981103} ;
10991104
11001105/**
@@ -1545,15 +1550,13 @@ exports.makeSplice = (oldFullText, spliceStart, numRemoved, newText, optNewTextA
15451550 const oldText = oldFullText . substring ( spliceStart , spliceStart + numRemoved ) ;
15461551 const newLen = oldLen + newText . length - oldText . length ;
15471552
1548- const assem = new SmartOpAssembler ( ) ;
15491553 const ops = ( function * ( ) {
15501554 yield * opsFromText ( '=' , oldFullText . substring ( 0 , spliceStart ) ) ;
15511555 yield * opsFromText ( '-' , oldText ) ;
15521556 yield * opsFromText ( '+' , newText , optNewTextAPairs , pool ) ;
15531557 } ) ( ) ;
1554- for ( const op of ops ) assem . append ( op ) ;
1555- assem . endDocument ( ) ;
1556- return exports . pack ( oldLen , newLen , assem . toString ( ) , newText ) ;
1558+ const serializedOps = exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
1559+ return exports . pack ( oldLen , newLen , serializedOps , newText ) ;
15571560} ;
15581561
15591562/**
@@ -1675,11 +1678,8 @@ exports.moveOpsToNewPool = (cs, oldPool, newPool) => {
16751678 * @param {string } text - text to insert
16761679 * @returns {string }
16771680 */
1678- exports . makeAttribution = ( text ) => {
1679- const assem = new SmartOpAssembler ( ) ;
1680- for ( const op of opsFromText ( '+' , text ) ) assem . append ( op ) ;
1681- return assem . toString ( ) ;
1682- } ;
1681+ exports . makeAttribution =
1682+ ( text ) => exports . serializeOps ( exports . canonicalizeOps ( opsFromText ( '+' , text ) , false ) ) ;
16831683
16841684/**
16851685 * Iterates over attributes in exports, attribution string, or attribs property of an op and runs
@@ -1932,8 +1932,7 @@ exports.attribsAttributeValue = (attribs, key, pool) => {
19321932 * @returns {Builder }
19331933 */
19341934exports . builder = ( oldLen ) => {
1935- const assem = new SmartOpAssembler ( ) ;
1936- const o = new Op ( ) ;
1935+ const ops = [ ] ;
19371936 const charBank = exports . stringAssembler ( ) ;
19381937
19391938 const self = {
@@ -1948,12 +1947,12 @@ exports.builder = (oldLen) => {
19481947 * @returns {Builder } this
19491948 */
19501949 keep : ( N , L , attribs , pool ) => {
1951- o . opcode = '=' ;
1950+ const o = new Op ( '=' ) ;
19521951 o . attribs = typeof attribs === 'string'
19531952 ? attribs : new AttributeMap ( pool ) . update ( attribs || [ ] ) . toString ( ) ;
19541953 o . chars = N ;
19551954 o . lines = ( L || 0 ) ;
1956- assem . append ( o ) ;
1955+ ops . push ( o ) ;
19571956 return self ;
19581957 } ,
19591958
@@ -1966,7 +1965,7 @@ exports.builder = (oldLen) => {
19661965 * @returns {Builder } this
19671966 */
19681967 keepText : ( text , attribs , pool ) => {
1969- for ( const op of opsFromText ( '=' , text , attribs , pool ) ) assem . append ( op ) ;
1968+ ops . push ( ... opsFromText ( '=' , text , attribs , pool ) ) ;
19701969 return self ;
19711970 } ,
19721971
@@ -1979,7 +1978,7 @@ exports.builder = (oldLen) => {
19791978 * @returns {Builder } this
19801979 */
19811980 insert : ( text , attribs , pool ) => {
1982- for ( const op of opsFromText ( '+' , text , attribs , pool ) ) assem . append ( op ) ;
1981+ ops . push ( ... opsFromText ( '+' , text , attribs , pool ) ) ;
19831982 charBank . append ( text ) ;
19841983 return self ;
19851984 } ,
@@ -1991,18 +1990,22 @@ exports.builder = (oldLen) => {
19911990 * @returns {Builder } this
19921991 */
19931992 remove : ( N , L ) => {
1994- o . opcode = '-' ;
1993+ const o = new Op ( '-' ) ;
19951994 o . attribs = '' ;
19961995 o . chars = N ;
19971996 o . lines = ( L || 0 ) ;
1998- assem . append ( o ) ;
1997+ ops . push ( o ) ;
19991998 return self ;
20001999 } ,
20012000
20022001 toString : ( ) => {
2003- assem . endDocument ( ) ;
2004- const newLen = oldLen + assem . getLengthChange ( ) ;
2005- return exports . pack ( oldLen , newLen , assem . toString ( ) , charBank . toString ( ) ) ;
2002+ /** @type {number } */
2003+ let lengthChange ;
2004+ const serializedOps = exports . serializeOps ( ( function * ( ) {
2005+ lengthChange = yield * exports . canonicalizeOps ( ops , true ) ;
2006+ } ) ( ) ) ;
2007+ const newLen = oldLen + lengthChange ;
2008+ return exports . pack ( oldLen , newLen , serializedOps , charBank . toString ( ) ) ;
20062009 } ,
20072010 } ;
20082011
@@ -2037,11 +2040,11 @@ exports.makeAttribsString = (opcode, attribs, pool) => {
20372040exports . subattribution = ( astr , start , optEnd ) => {
20382041 const attOps = exports . deserializeOps ( astr ) ;
20392042 let attOpsNext = attOps . next ( ) ;
2040- const assem = new SmartOpAssembler ( ) ;
20412043 let attOp = new Op ( ) ;
2042- const csOp = new Op ( ) ;
2044+ const csOp = new Op ( '-' ) ;
2045+ csOp . chars = start ;
20432046
2044- const doCsOp = ( ) => {
2047+ const doCsOp = function * ( ) {
20452048 if ( ! csOp . chars ) return ;
20462049 while ( csOp . opcode && ( attOp . opcode || ! attOpsNext . done ) ) {
20472050 if ( ! attOp . opcode ) {
@@ -2053,30 +2056,25 @@ exports.subattribution = (astr, start, optEnd) => {
20532056 csOp . lines ++ ;
20542057 }
20552058 const opOut = slicerZipperFunc ( attOp , csOp , null ) ;
2056- if ( opOut . opcode ) assem . append ( opOut ) ;
2059+ if ( opOut . opcode ) yield opOut ;
20572060 }
20582061 } ;
20592062
2060- csOp . opcode = '-' ;
2061- csOp . chars = start ;
2062-
2063- doCsOp ( ) ;
2064-
2065- if ( optEnd === undefined ) {
2066- if ( attOp . opcode ) {
2067- assem . append ( attOp ) ;
2068- }
2069- while ( ! attOpsNext . done ) {
2070- assem . append ( attOpsNext . value ) ;
2071- attOpsNext = attOps . next ( ) ;
2063+ const ops = ( function * ( ) {
2064+ yield * doCsOp ( ) ;
2065+ if ( optEnd === undefined ) {
2066+ if ( attOp . opcode ) yield attOp ;
2067+ while ( ! attOpsNext . done ) {
2068+ yield attOpsNext . value ;
2069+ attOpsNext = attOps . next ( ) ;
2070+ }
2071+ } else {
2072+ csOp . opcode = '=' ;
2073+ csOp . chars = optEnd - start ;
2074+ yield * doCsOp ( ) ;
20722075 }
2073- } else {
2074- csOp . opcode = '=' ;
2075- csOp . chars = optEnd - start ;
2076- doCsOp ( ) ;
2077- }
2078-
2079- return assem . toString ( ) ;
2076+ } ) ( ) ;
2077+ return exports . serializeOps ( exports . canonicalizeOps ( ops , false ) ) ;
20802078} ;
20812079
20822080exports . inverse = ( cs , lines , alines , pool ) => {
0 commit comments