@@ -451,7 +451,7 @@ class MergingOpAssembler {
451451 * @yields {Op} The canonicalized operations.
452452 * @returns {number } How much the sequence of operations changes the length (in characters).
453453 */
454- const canonicalizeOps = function * ( ops , finalize ) {
454+ exports . canonicalizeOps = function * ( ops , finalize ) {
455455 let minusOps = [ ] ;
456456 let plusOps = [ ] ;
457457 let keepOps = [ ] ;
@@ -533,6 +533,8 @@ const opsFromText = function* (opcode, text, attribs, pool) {
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
@@ -592,51 +594,54 @@ exports.checkRep = (cs) => {
592594 const unpacked = exports . unpack ( cs ) ;
593595 const oldLen = unpacked . oldLen ;
594596 const newLen = unpacked . newLen ;
595- const ops = unpacked . ops ;
596597 let charBank = unpacked . charBank ;
597598
598- const assem = new SmartOpAssembler ( ) ;
599599 let oldPos = 0 ;
600600 let calcNewLen = 0 ;
601601 let numInserted = 0 ;
602- for ( const o of new exports . OpIter ( ops ) ) {
603- switch ( o . opcode ) {
604- case '=' :
605- oldPos += o . chars ;
606- calcNewLen += o . chars ;
607- break ;
608- case '-' :
609- oldPos += o . chars ;
610- assert ( oldPos <= oldLen , oldPos , ' > ' , oldLen , ' in ' , cs ) ;
611- break ;
612- case '+' :
613- {
614- calcNewLen += o . chars ;
615- numInserted += o . chars ;
616- assert ( calcNewLen <= newLen , calcNewLen , ' > ' , newLen , ' in ' , cs ) ;
617- break ;
602+ const ops = ( function * ( ) {
603+ for ( const o of new exports . OpIter ( unpacked . ops ) ) {
604+ switch ( o . opcode ) {
605+ case '=' :
606+ oldPos += o . chars ;
607+ calcNewLen += o . chars ;
608+ break ;
609+ case '-' :
610+ oldPos += o . chars ;
611+ assert ( oldPos <= oldLen , oldPos , ' > ' , oldLen , ' in ' , cs ) ;
612+ break ;
613+ case '+' :
614+ calcNewLen += o . chars ;
615+ numInserted += o . chars ;
616+ assert ( calcNewLen <= newLen , calcNewLen , ' > ' , newLen , ' in ' , cs ) ;
617+ break ;
618618 }
619+ yield o ;
619620 }
620- assem . append ( o ) ;
621- }
621+ } ) ( ) ;
622+ const serializedOps = exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
622623
623624 calcNewLen += oldLen - oldPos ;
624625 charBank = charBank . substring ( 0 , numInserted ) ;
625626 while ( charBank . length < numInserted ) {
626627 charBank += '?' ;
627628 }
628629
629- assem . endDocument ( ) ;
630- const normalized = exports . pack ( oldLen , calcNewLen , assem . toString ( ) , charBank ) ;
630+ const normalized = exports . pack ( oldLen , calcNewLen , serializedOps , charBank ) ;
631631 assert ( normalized === cs , 'Invalid changeset (checkRep failed)' ) ;
632632
633633 return cs ;
634634} ;
635635
636636/**
637+ * @deprecated Use `canonicalizeOps` with `serializeOps` instead.
637638 * @returns {SmartOpAssembler }
638639 */
639- exports . smartOpAssembler = ( ) => new SmartOpAssembler ( ) ;
640+ exports . smartOpAssembler = ( ) => {
641+ warnDeprecated (
642+ 'Changeset.smartOpAssembler() is deprecated; use Changeset.canonicalizeOps() instead' ) ;
643+ return new SmartOpAssembler ( ) ;
644+ } ;
640645
641646/**
642647 * @deprecated Use `squashOps` with `serializeOps` instead.
@@ -1076,19 +1081,19 @@ class TextLinesMutator {
10761081 * @returns {string } the integrated changeset
10771082 */
10781083const applyZip = ( in1 , in2 , func ) => {
1079- const iter1 = new exports . OpIter ( in1 ) ;
1080- const iter2 = new exports . OpIter ( in2 ) ;
1081- const assem = new SmartOpAssembler ( ) ;
1082- let op1 = new exports . Op ( ) ;
1083- let op2 = new exports . Op ( ) ;
1084- while ( op1 . opcode || iter1 . hasNext ( ) || op2 . opcode || iter2 . hasNext ( ) ) {
1085- if ( ! op1 . opcode && iter1 . hasNext ( ) ) op1 = iter1 . next ( ) ;
1086- if ( ! op2 . opcode && iter2 . hasNext ( ) ) op2 = iter2 . next ( ) ;
1087- const opOut = func ( op1 , op2 ) ;
1088- if ( opOut && opOut . opcode ) assem . append ( opOut ) ;
1089- }
1090- assem . endDocument ( ) ;
1091- return assem . toString ( ) ;
1084+ const ops = ( function * ( ) {
1085+ const iter1 = new exports . OpIter ( in1 ) ;
1086+ const iter2 = new exports . OpIter ( in2 ) ;
1087+ let op1 = new exports . Op ( ) ;
1088+ let op2 = new exports . Op ( ) ;
1089+ while ( op1 . opcode || iter1 . hasNext ( ) || op2 . opcode || iter2 . hasNext ( ) ) {
1090+ if ( ! op1 . opcode && iter1 . hasNext ( ) ) op1 = iter1 . next ( ) ;
1091+ if ( ! op2 . opcode && iter2 . hasNext ( ) ) op2 = iter2 . next ( ) ;
1092+ const opOut = func ( op1 , op2 ) ;
1093+ if ( opOut && opOut . opcode ) yield opOut ;
1094+ }
1095+ } ) ( ) ;
1096+ return exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
10921097} ;
10931098
10941099/**
@@ -1546,15 +1551,13 @@ exports.makeSplice = (oldFullText, spliceStart, numRemoved, newText, optNewTextA
15461551 const oldText = oldFullText . substring ( spliceStart , spliceStart + numRemoved ) ;
15471552 const newLen = oldLen + newText . length - oldText . length ;
15481553
1549- const assem = new SmartOpAssembler ( ) ;
15501554 const ops = ( function * ( ) {
15511555 yield * opsFromText ( '=' , oldFullText . substring ( 0 , spliceStart ) ) ;
15521556 yield * opsFromText ( '-' , oldText ) ;
15531557 yield * opsFromText ( '+' , newText , optNewTextAPairs , pool ) ;
15541558 } ) ( ) ;
1555- for ( const op of ops ) assem . append ( op ) ;
1556- assem . endDocument ( ) ;
1557- return exports . pack ( oldLen , newLen , assem . toString ( ) , newText ) ;
1559+ const serializedOps = exports . serializeOps ( exports . canonicalizeOps ( ops , true ) ) ;
1560+ return exports . pack ( oldLen , newLen , serializedOps , newText ) ;
15581561} ;
15591562
15601563/**
@@ -1683,11 +1686,8 @@ exports.moveOpsToNewPool = (cs, oldPool, newPool) => {
16831686 * @param {string } text - text to insert
16841687 * @returns {string }
16851688 */
1686- exports . makeAttribution = ( text ) => {
1687- const assem = new SmartOpAssembler ( ) ;
1688- for ( const op of opsFromText ( '+' , text ) ) assem . append ( op ) ;
1689- return assem . toString ( ) ;
1690- } ;
1689+ exports . makeAttribution =
1690+ ( text ) => exports . serializeOps ( exports . canonicalizeOps ( opsFromText ( '+' , text ) , false ) ) ;
16911691
16921692/**
16931693 * Iterates over attributes in exports, attribution string, or attribs property of an op and runs
@@ -1919,8 +1919,8 @@ exports.attribsAttributeValue = (attribs, key, pool) => {
19191919 * @returns {Builder }
19201920 */
19211921exports . builder = ( oldLen ) => {
1922- const assem = new SmartOpAssembler ( ) ;
1923- const o = new exports . Op ( ) ;
1922+ const ops = [ ] ;
1923+ let packed = null ;
19241924 const charBank = exports . stringAssembler ( ) ;
19251925
19261926 const self = {
@@ -1929,34 +1929,44 @@ exports.builder = (oldLen) => {
19291929 * latter case).
19301930 */
19311931 keep : ( N , L , attribs , pool ) => {
1932- o . opcode = '=' ;
1932+ const o = new exports . Op ( '=' ) ;
19331933 o . attribs = ( attribs && exports . makeAttribsString ( '=' , attribs , pool ) ) || '' ;
19341934 o . chars = N ;
19351935 o . lines = ( L || 0 ) ;
1936- assem . append ( o ) ;
1936+ packed = null ;
1937+ ops . push ( o ) ;
19371938 return self ;
19381939 } ,
19391940 keepText : ( text , attribs , pool ) => {
1940- for ( const op of opsFromText ( '=' , text , attribs , pool ) ) assem . append ( op ) ;
1941+ packed = null ;
1942+ ops . push ( ...opsFromText ( '=' , text , attribs , pool ) ) ;
19411943 return self ;
19421944 } ,
19431945 insert : ( text , attribs , pool ) => {
1944- for ( const op of opsFromText ( '+' , text , attribs , pool ) ) assem . append ( op ) ;
1946+ packed = null ;
1947+ ops . push ( ...opsFromText ( '+' , text , attribs , pool ) ) ;
19451948 charBank . append ( text ) ;
19461949 return self ;
19471950 } ,
19481951 remove : ( N , L ) => {
1949- o . opcode = '-' ;
1952+ const o = new exports . Op ( '-' ) ;
19501953 o . attribs = '' ;
19511954 o . chars = N ;
19521955 o . lines = ( L || 0 ) ;
1953- assem . append ( o ) ;
1956+ packed = null ;
1957+ ops . push ( o ) ;
19541958 return self ;
19551959 } ,
19561960 toString : ( ) => {
1957- assem . endDocument ( ) ;
1958- const newLen = oldLen + assem . getLengthChange ( ) ;
1959- return exports . pack ( oldLen , newLen , assem . toString ( ) , charBank . toString ( ) ) ;
1961+ if ( packed == null ) {
1962+ let lengthChange ;
1963+ const serializedOps = exports . serializeOps ( ( function * ( ) {
1964+ lengthChange = yield * exports . canonicalizeOps ( ops , true ) ;
1965+ } ) ( ) ) ;
1966+ const newLen = oldLen + lengthChange ;
1967+ packed = exports . pack ( oldLen , newLen , serializedOps , charBank . toString ( ) ) ;
1968+ }
1969+ return packed ;
19601970 } ,
19611971 } ;
19621972
@@ -1989,11 +1999,11 @@ exports.makeAttribsString = (opcode, attribs, pool) => {
19891999 */
19902000exports . subattribution = ( astr , start , optEnd ) => {
19912001 const iter = new exports . OpIter ( astr ) ;
1992- const assem = new SmartOpAssembler ( ) ;
19932002 let attOp = new exports . Op ( ) ;
1994- const csOp = new exports . Op ( ) ;
2003+ const csOp = new exports . Op ( '-' ) ;
2004+ csOp . chars = start ;
19952005
1996- const doCsOp = ( ) => {
2006+ const doCsOp = function * ( ) {
19972007 if ( ! csOp . chars ) return ;
19982008 while ( csOp . opcode && ( attOp . opcode || iter . hasNext ( ) ) ) {
19992009 if ( ! attOp . opcode ) attOp = iter . next ( ) ;
@@ -2002,27 +2012,22 @@ exports.subattribution = (astr, start, optEnd) => {
20022012 csOp . lines ++ ;
20032013 }
20042014 const opOut = slicerZipperFunc ( attOp , csOp , null ) ;
2005- if ( opOut . opcode ) assem . append ( opOut ) ;
2015+ if ( opOut . opcode ) yield opOut ;
20062016 }
20072017 } ;
20082018
2009- csOp . opcode = '-' ;
2010- csOp . chars = start ;
2011-
2012- doCsOp ( ) ;
2013-
2014- if ( optEnd === undefined ) {
2015- if ( attOp . opcode ) {
2016- assem . append ( attOp ) ;
2019+ const ops = ( function * ( ) {
2020+ yield * doCsOp ( ) ;
2021+ if ( optEnd === undefined ) {
2022+ if ( attOp . opcode ) yield attOp ;
2023+ yield * iter ;
2024+ } else {
2025+ csOp . opcode = '=' ;
2026+ csOp . chars = optEnd - start ;
2027+ yield * doCsOp ( ) ;
20172028 }
2018- while ( iter . hasNext ( ) ) assem . append ( iter . next ( ) ) ;
2019- } else {
2020- csOp . opcode = '=' ;
2021- csOp . chars = optEnd - start ;
2022- doCsOp ( ) ;
2023- }
2024-
2025- return assem . toString ( ) ;
2029+ } ) ( ) ;
2030+ return exports . serializeOps ( exports . canonicalizeOps ( ops , false ) ) ;
20262031} ;
20272032
20282033exports . inverse = ( cs , lines , alines , pool ) => {
0 commit comments