@@ -450,7 +450,7 @@ class MergingOpAssembler {
450450 * @returns {Generator<Op, number> } The done value indicates how much the sequence of operations
451451 * changes the length of the document (in characters).
452452 */
453- const canonicalizeOps = function * ( ops , finalize ) {
453+ exports . canonicalizeOps = function * ( ops , finalize ) {
454454 let minusOps = [ ] ;
455455 let plusOps = [ ] ;
456456 let keepOps = [ ] ;
@@ -533,6 +533,8 @@ const opsFromText = function* (opcode, text, attribs = '', pool = null) {
533533 * - strips final "="
534534 * - ignores 0-length changes
535535 * - reorders consecutive + and - (which MergingOpAssembler doesn't do)
536+ *
537+ * @deprecated Use `canonicalizeOps` with `serializeOps` instead.
536538 */
537539class SmartOpAssembler {
538540 constructor ( ) {
@@ -541,7 +543,7 @@ class SmartOpAssembler {
541543
542544 _serialize ( finalize ) {
543545 this . _serialized = exports . serializeOps ( ( function * ( ) {
544- this . _lengthChange = yield * canonicalizeOps ( this . _ops , finalize ) ;
546+ this . _lengthChange = yield * exports . canonicalizeOps ( this . _ops , finalize ) ;
545547 } ) . call ( this ) ) ;
546548 }
547549
@@ -599,51 +601,54 @@ exports.checkRep = (cs) => {
599601 const unpacked = exports . unpack ( cs ) ;
600602 const oldLen = unpacked . oldLen ;
601603 const newLen = unpacked . newLen ;
602- const ops = unpacked . ops ;
603604 let charBank = unpacked . charBank ;
604605
605- const assem = new SmartOpAssembler ( ) ;
606606 let oldPos = 0 ;
607607 let calcNewLen = 0 ;
608608 let numInserted = 0 ;
609- for ( const o of exports . deserializeOps ( ops ) ) {
610- switch ( o . opcode ) {
611- case '=' :
612- oldPos += o . chars ;
613- calcNewLen += o . chars ;
614- break ;
615- case '-' :
616- oldPos += o . chars ;
617- assert ( oldPos <= oldLen , ` ${ oldPos } > ${ oldLen } in ${ cs } ` ) ;
618- break ;
619- case '+' :
620- {
621- calcNewLen += o . chars ;
622- numInserted += o . chars ;
623- assert ( calcNewLen <= newLen , `${ calcNewLen } > ${ newLen } in ${ cs } ` ) ;
624- break ;
609+ const ops = ( function * ( ) {
610+ for ( const o of exports . deserializeOps ( unpacked . ops ) ) {
611+ switch ( o . opcode ) {
612+ case '=' :
613+ oldPos += o . chars ;
614+ calcNewLen += o . chars ;
615+ break ;
616+ case '-' :
617+ oldPos += o . chars ;
618+ assert ( oldPos <= oldLen , ` ${ oldPos } > ${ oldLen } in ${ cs } ` ) ;
619+ break ;
620+ case '+' :
621+ calcNewLen += o . chars ;
622+ numInserted += o . chars ;
623+ assert ( calcNewLen <= newLen , `${ calcNewLen } > ${ newLen } in ${ cs } ` ) ;
624+ break ;
625625 }
626+ yield o ;
626627 }
627- assem . append ( o ) ;
628- }
628+ } ) ( ) ;
629+ const serializedOps = exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
629630
630631 calcNewLen += oldLen - oldPos ;
631632 charBank = charBank . substring ( 0 , numInserted ) ;
632633 while ( charBank . length < numInserted ) {
633634 charBank += '?' ;
634635 }
635636
636- assem . endDocument ( ) ;
637- const normalized = exports . pack ( oldLen , calcNewLen , assem . toString ( ) , charBank ) ;
637+ const normalized = exports . pack ( oldLen , calcNewLen , serializedOps , charBank ) ;
638638 assert ( normalized === cs , 'Invalid changeset (checkRep failed)' ) ;
639639
640640 return cs ;
641641} ;
642642
643643/**
644+ * @deprecated Use `canonicalizeOps` with `serializeOps` instead.
644645 * @returns {SmartOpAssembler }
645646 */
646- exports . smartOpAssembler = ( ) => new SmartOpAssembler ( ) ;
647+ exports . smartOpAssembler = ( ) => {
648+ warnDeprecated (
649+ 'Changeset.smartOpAssembler() is deprecated; use Changeset.canonicalizeOps() instead' ) ;
650+ return new SmartOpAssembler ( ) ;
651+ } ;
647652
648653/**
649654 * @deprecated Use `squashOps` with `serializeOps` instead.
@@ -1089,22 +1094,22 @@ class TextLinesMutator {
10891094 * @returns {string } the integrated changeset
10901095 */
10911096const applyZip = ( in1 , in2 , func ) => {
1092- const ops1 = exports . deserializeOps ( in1 ) ;
1093- const ops2 = exports . deserializeOps ( in2 ) ;
1094- let next1 = ops1 . next ( ) ;
1095- let next2 = ops2 . next ( ) ;
1096- const assem = new SmartOpAssembler ( ) ;
1097- while ( ! next1 . done || ! next2 . done ) {
1098- if ( ! next1 . done && ! next1 . value . opcode ) next1 = ops1 . next ( ) ;
1099- if ( ! next2 . done && ! next2 . value . opcode ) next2 = ops2 . next ( ) ;
1100- if ( next1 . value == null ) next1 . value = new Op ( ) ;
1101- if ( next2 . value == null ) next2 . value = new Op ( ) ;
1102- if ( ! next1 . value . opcode && ! next2 . value . opcode ) break ;
1103- const opOut = func ( next1 . value , next2 . value ) ;
1104- if ( opOut && opOut . opcode ) assem . append ( opOut ) ;
1105- }
1106- assem . endDocument ( ) ;
1107- return assem . toString ( ) ;
1097+ const ops = ( function * ( ) {
1098+ const ops1 = exports . deserializeOps ( in1 ) ;
1099+ const ops2 = exports . deserializeOps ( in2 ) ;
1100+ let next1 = ops1 . next ( ) ;
1101+ let next2 = ops2 . next ( ) ;
1102+ while ( ! next1 . done || ! next2 . done ) {
1103+ if ( ! next1 . done && ! next1 . value . opcode ) next1 = ops1 . next ( ) ;
1104+ if ( ! next2 . done && ! next2 . value . opcode ) next2 = ops2 . next ( ) ;
1105+ if ( next1 . value == null ) next1 . value = new Op ( ) ;
1106+ if ( next2 . value == null ) next2 . value = new Op ( ) ;
1107+ if ( ! next1 . value . opcode && ! next2 . value . opcode ) break ;
1108+ const opOut = func ( next1 . value , next2 . value ) ;
1109+ if ( opOut && opOut . opcode ) yield opOut ;
1110+ }
1111+ } ) ( ) ;
1112+ return exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
11081113} ;
11091114
11101115/**
@@ -1584,15 +1589,13 @@ exports.makeSplice = (oldFullText, spliceStart, numRemoved, newText, optNewTextA
15841589 const oldText = oldFullText . substring ( spliceStart , spliceStart + numRemoved ) ;
15851590 const newLen = oldLen + newText . length - oldText . length ;
15861591
1587- const assem = new SmartOpAssembler ( ) ;
15881592 const ops = ( function * ( ) {
15891593 yield * opsFromText ( '=' , oldFullText . substring ( 0 , spliceStart ) ) ;
15901594 yield * opsFromText ( '-' , oldText ) ;
15911595 yield * opsFromText ( '+' , newText , optNewTextAPairs , pool ) ;
15921596 } ) ( ) ;
1593- for ( const op of ops ) assem . append ( op ) ;
1594- assem . endDocument ( ) ;
1595- return exports . pack ( oldLen , newLen , assem . toString ( ) , newText ) ;
1597+ const serializedOps = exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
1598+ return exports . pack ( oldLen , newLen , serializedOps , newText ) ;
15961599} ;
15971600
15981601/**
@@ -1714,11 +1717,8 @@ exports.moveOpsToNewPool = (cs, oldPool, newPool) => {
17141717 * @param {string } text - text to insert
17151718 * @returns {string }
17161719 */
1717- exports . makeAttribution = ( text ) => {
1718- const assem = new SmartOpAssembler ( ) ;
1719- for ( const op of opsFromText ( '+' , text ) ) assem . append ( op ) ;
1720- return assem . toString ( ) ;
1721- } ;
1720+ exports . makeAttribution =
1721+ ( text ) => exports . serializeOps ( exports . canonicalizeOps ( opsFromText ( '+' , text ) , false ) ) ;
17221722
17231723/**
17241724 * Iterates over attributes in exports, attribution string, or attribs property of an op and runs
@@ -1955,8 +1955,7 @@ exports.attribsAttributeValue = (attribs, key, pool) => {
19551955 * @returns {Builder }
19561956 */
19571957exports . builder = ( oldLen ) => {
1958- const assem = new SmartOpAssembler ( ) ;
1959- const o = new Op ( ) ;
1958+ const ops = [ ] ;
19601959 const charBank = exports . stringAssembler ( ) ;
19611960
19621961 const self = {
@@ -1971,11 +1970,11 @@ exports.builder = (oldLen) => {
19711970 * @returns {Builder } this
19721971 */
19731972 keep : ( N , L , attribs , pool ) => {
1974- o . opcode = '=' ;
1973+ const o = new Op ( '=' ) ;
19751974 o . attribs = ( attribs && exports . makeAttribsString ( '=' , attribs , pool ) ) || '' ;
19761975 o . chars = N ;
19771976 o . lines = ( L || 0 ) ;
1978- assem . append ( o ) ;
1977+ ops . push ( o ) ;
19791978 return self ;
19801979 } ,
19811980
@@ -1988,7 +1987,7 @@ exports.builder = (oldLen) => {
19881987 * @returns {Builder } this
19891988 */
19901989 keepText : ( text , attribs , pool ) => {
1991- for ( const op of opsFromText ( '=' , text , attribs , pool ) ) assem . append ( op ) ;
1990+ ops . push ( ... opsFromText ( '=' , text , attribs , pool ) ) ;
19921991 return self ;
19931992 } ,
19941993
@@ -2001,7 +2000,7 @@ exports.builder = (oldLen) => {
20012000 * @returns {Builder } this
20022001 */
20032002 insert : ( text , attribs , pool ) => {
2004- for ( const op of opsFromText ( '+' , text , attribs , pool ) ) assem . append ( op ) ;
2003+ ops . push ( ... opsFromText ( '+' , text , attribs , pool ) ) ;
20052004 charBank . append ( text ) ;
20062005 return self ;
20072006 } ,
@@ -2013,18 +2012,22 @@ exports.builder = (oldLen) => {
20132012 * @returns {Builder } this
20142013 */
20152014 remove : ( N , L ) => {
2016- o . opcode = '-' ;
2015+ const o = new Op ( '-' ) ;
20172016 o . attribs = '' ;
20182017 o . chars = N ;
20192018 o . lines = ( L || 0 ) ;
2020- assem . append ( o ) ;
2019+ ops . push ( o ) ;
20212020 return self ;
20222021 } ,
20232022
20242023 toString : ( ) => {
2025- assem . endDocument ( ) ;
2026- const newLen = oldLen + assem . getLengthChange ( ) ;
2027- return exports . pack ( oldLen , newLen , assem . toString ( ) , charBank . toString ( ) ) ;
2024+ /** @type {number } */
2025+ let lengthChange ;
2026+ const serializedOps = exports . serializeOps ( ( function * ( ) {
2027+ lengthChange = yield * exports . canonicalizeOps ( ops , true ) ;
2028+ } ) ( ) ) ;
2029+ const newLen = oldLen + lengthChange ;
2030+ return exports . pack ( oldLen , newLen , serializedOps , charBank . toString ( ) ) ;
20282031 } ,
20292032 } ;
20302033
@@ -2058,11 +2061,11 @@ exports.makeAttribsString = (opcode, attribs, pool) => {
20582061exports . subattribution = ( astr , start , optEnd ) => {
20592062 const attOps = exports . deserializeOps ( astr ) ;
20602063 let attOpsNext = attOps . next ( ) ;
2061- const assem = new SmartOpAssembler ( ) ;
20622064 let attOp = new Op ( ) ;
2063- const csOp = new Op ( ) ;
2065+ const csOp = new Op ( '-' ) ;
2066+ csOp . chars = start ;
20642067
2065- const doCsOp = ( ) => {
2068+ const doCsOp = function * ( ) {
20662069 if ( ! csOp . chars ) return ;
20672070 while ( csOp . opcode && ( attOp . opcode || ! attOpsNext . done ) ) {
20682071 if ( ! attOp . opcode ) {
@@ -2074,27 +2077,22 @@ exports.subattribution = (astr, start, optEnd) => {
20742077 csOp . lines ++ ;
20752078 }
20762079 const opOut = slicerZipperFunc ( attOp , csOp , null ) ;
2077- if ( opOut . opcode ) assem . append ( opOut ) ;
2080+ if ( opOut . opcode ) yield opOut ;
20782081 }
20792082 } ;
20802083
2081- csOp . opcode = '-' ;
2082- csOp . chars = start ;
2083-
2084- doCsOp ( ) ;
2085-
2086- if ( optEnd === undefined ) {
2087- if ( attOp . opcode ) {
2088- assem . append ( attOp ) ;
2084+ const ops = ( function * ( ) {
2085+ yield * doCsOp ( ) ;
2086+ if ( optEnd === undefined ) {
2087+ if ( attOp . opcode ) yield attOp ;
2088+ yield * attOps ;
2089+ } else {
2090+ csOp . opcode = '=' ;
2091+ csOp . chars = optEnd - start ;
2092+ yield * doCsOp ( ) ;
20892093 }
2090- for ( const attOp of attOps ) assem . append ( attOp ) ;
2091- } else {
2092- csOp . opcode = '=' ;
2093- csOp . chars = optEnd - start ;
2094- doCsOp ( ) ;
2095- }
2096-
2097- return assem . toString ( ) ;
2094+ } ) ( ) ;
2095+ return exports . serializeOps ( exports . canonicalizeOps ( ops , false ) ) ;
20982096} ;
20992097
21002098exports . inverse = ( cs , lines , alines , pool ) => {
0 commit comments