2019-02-19 14:40:38 +01:00
( function (){
var r = function (){ var e = "function" == typeof require && require , r = function ( i , o , u ){ o || ( o = 0 ); var n = r . resolve ( i , o ), t = r . m [ o ][ n ]; if ( ! t && e ){ if ( t = e ( n )) return t } else if ( t && t . c && ( o = t . c , n = t . m , t = r . m [ o ][ t . m ], ! t )) throw new Error ( 'failed to require "' + n + '" from ' + o ); if ( ! t ) throw new Error ( 'failed to require "' + i + '" from ' + u ); return t . exports || ( t . exports = {}, t . call ( t . exports , t , t . exports , r . relative ( n , o ))), t . exports }; return r . resolve = function ( e , n ){ var i = e , t = e + ".js" , o = e + "/index.js" ; return r . m [ n ][ t ] && t ? t : r . m [ n ][ o ] && o ? o : i }, r . relative = function ( e , t ){ return function ( n ){ if ( "." != n . charAt ( 0 )) return r ( n , t , e ); var o = e . split ( "/" ), f = n . split ( "/" ); o . pop (); for ( var i = 0 ; i < f . length ; i ++ ){ var u = f [ i ]; ".." == u ? o . pop () : "." != u && o . push ( u )} return r ( o . join ( "/" ), t , e )}}, r }(); r . m = [];
r . m [ 0 ] = {
"json.sortify" : { "c" : 1 , "m" : "dist/JSON.sortify.js" },
"Diff.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
var Operation = require ( './Operation' );
var Common = require ( './Common' );
/*::
import type { Operation_t } from './Operation';
*/
var DEFAULT_BLOCKSIZE = module . exports . DEFAULT_BLOCKSIZE = 8 ;
var hashScan = function ( str , blockSize ) {
var out = {};
for ( var i = 0 ; i + blockSize <= str . length ; i ++ ) {
var slice = str . slice ( i , i + blockSize );
( out [ slice ] = out [ slice ] || []). push ( i );
}
return out ;
};
// return true if two segments do not overlap, else false
var isCompatible = function ( m1 , m2 ) {
if ( m1 . oldIndex < m2 . oldIndex ) {
if ( m1 . oldIndex + m1 . length > m2 . oldIndex ) { return false ; }
if ( m1 . newIndex + m1 . length > m2 . newIndex ) { return false ; }
} else if ( m2 . oldIndex < m1 . oldIndex ) {
if ( m2 . oldIndex + m2 . length > m1 . oldIndex ) { return false ; }
if ( m2 . newIndex + m2 . length > m1 . newIndex ) { return false ; }
} else {
return false ;
}
return true ;
};
var scoreMatch = function ( m ) {
return ( m . length * 2 ) - m . oldIndex - m . newIndex ;
};
/* iterate backwards through and array, splicing out indices to remove
the indices to remove MUST be in ascending order
otherwise this could remove the wrong values
operates strictly via side-effects */
var removeAscendingIndices = function ( A , toRemove ) {
if ( ! toRemove . length ) { return ; }
for ( var j = toRemove . length - 1 ; j > - 1 ; j -- ) {
A . splice ( toRemove [ j ], 1 );
}
};
/* given a candidate match and the list of pending matches
evaluate whether the candidate conflicts with existing matches
if the candidate is determined to be a worse match than existing matches
return false
otherwise return the list of candidates which should be replaced
returns either:
false => the candidate is incompatible, and its conflicts are more valuable
empty array => truthy, but there is nothing to remove (no conflicts)
array => conflicting elements to replace with the candidate
*/
var listInferiorCandidates = function ( current , pending ) {
var score_m = scoreMatch ( current );
var score_rest = 0 ;
var toRemove = [];
var l = pending . length ;
for ( var i = 0 ; i < l ; i ++ ) {
if ( isCompatible ( current , pending [ i ])) { continue ; }
toRemove . push ( i );
score_rest += scoreMatch ( pending [ i ]);
if ( score_rest > score_m ) { return false ; }
}
return toRemove ;
};
/* called with all the matches, including the common start and common end, if they exist...
A: Common start (should not be replaced)
B: potential operations
B': satisfactory set of operations
C: Common end (should not be replaced)
this implementation does not do anything special to protect A and C
it is believed that the way matches are produced, they should not be removed.
*/
var reduceMatches = function ( matches ) {
// ascending sort
matches . sort ( function ( a , b ) { return ( a . oldIndex + a . newIndex ) - ( b . oldIndex + b . newIndex ); });
var out = [];
var l_m = matches . length ;
var toRemove ;
for ( var i = 0 ; i < l_m ; i ++ ) {
toRemove = listInferiorCandidates ( matches [ i ], out );
if ( toRemove ) {
removeAscendingIndices ( out , toRemove );
out . push ( matches [ i ]);
}
}
return out ;
};
var resolve = function ( str , hash , blockSize ) {
var matches = [];
var candidates = [];
// do the same thing as was done in hashscan, but for the new string
// look for commonalities between new and old data
for ( var i = 0 ; i + blockSize <= str . length ; i ++ ) {
var slice = str . slice ( i , i + blockSize );
var instances = ( hash [ slice ] || []). slice ( 0 );
for ( var j = candidates . length - 1 ; j >= 0 ; j -- ) {
var c = candidates [ j ];
var ii = instances . indexOf ( c . oldIndex + c . length - blockSize + 1 );
if ( ii > - 1 ) {
c . length ++ ;
instances . splice ( ii , 1 );
} else {
// We're pushing all of the candidates as "matches" and then we're going to sort them
// by length and pull out only ones which are non-intersecting because the result
// of this function needs to be a set of sequencial non-intersecting matches.
matches . push ( candidates [ j ]);
//if (candidates.length === 1) { matches.push(candidates[j]); }
candidates . splice ( j , 1 );
}
}
for ( var k = 0 ; k < instances . length ; k ++ ) {
candidates . push ({
newIndex : i ,
oldIndex : instances [ k ],
length : blockSize
});
}
//console.log(JSON.stringify(candidates));
}
// Normally we would only take one candidate, since they're equal value we just pick one and
// use it. However since we need all possible candidates which we will feed to our reduce
// function in order to get a list of sequencial non-intersecting matches.
// like concat, but destructive
Array . prototype . push . apply ( matches , candidates );
//if (candidates[0]) { matches.push(candidates[0]); }
return matches ;
};
var matchesToOps = function ( oldS , newS , matches ) {
// ascending sort
matches . sort ( function ( a , b ) { return a . oldIndex - b . oldIndex ; });
var oldI = 0 ;
var newI = 0 ;
var out = [];
for ( var i = 0 ; i < matches . length ; i ++ ) {
var m = matches [ i ];
out . push ( Operation . create ( oldI , m . oldIndex - oldI , newS . slice ( newI , m . newIndex )));
oldI = m . oldIndex + m . length ;
newI = m . newIndex + m . length ;
}
out . push ( Operation . create ( oldI , oldS . length - oldI , newS . slice ( newI ))); // does not check ops
if ( Common . PARANOIA ) {
out . forEach ( function ( op ) {
if ( ! op . toRemove || ! op . toInsert ) { return ; }
try { Operation . check ( op ); }
catch ( e ) {
console . log ( '\nINVALID OPERATION' );
console . log ( oldS );
console . log ( newS );
//console.log(m);
console . log ( '\nMATCHES' );
console . log ( matches );
console . log ( '\nOPS' );
console . log ( out );
throw e ;
}
});
}
return out . filter ( function ( x ) { return x . toRemove || x . toInsert ; });
};
var getCommonBeginning = function ( oldS , newS ) {
var commonStart = 0 ;
// This could be Math.min ?
var limit = oldS . length < newS . length ? oldS . length : newS . length ;
while ( oldS . charAt ( commonStart ) === newS . charAt ( commonStart ) && commonStart < limit ) {
commonStart ++ ;
}
return { newIndex : 0 , oldIndex : 0 , length : commonStart };
};
var getCommonEnd = function ( oldS , newS , commonBeginning ) {
var oldEnd = oldS . length - 1 ;
var newEnd = newS . length - 1 ;
var limit = Math . min ( oldEnd , newEnd ) - commonBeginning ;
var commonEnd = 0 ;
while ( oldS . charAt ( oldEnd ) === newS . charAt ( newEnd ) && limit >= 0 ) {
oldEnd -- ;
newEnd -- ;
commonEnd ++ ;
limit -- ;
}
return { newIndex : newEnd + 1 , oldIndex : oldEnd + 1 , length : commonEnd };
};
module . exports . diff = function (
oldS /*:string*/ ,
newS /*:string*/ ,
blockSize /*:?number*/ ) /*:Array<Operation_t>*/
{
blockSize = blockSize || DEFAULT_BLOCKSIZE ;
var cb = getCommonBeginning ( oldS , newS );
if ( cb . length === oldS . length && oldS . length === newS . length ) { return []; }
var ce = getCommonEnd ( oldS , newS , cb . length );
var oldST = oldS ;
var newST = newS ;
if ( ce . length ) {
oldST = oldST . slice ( 0 , ce . oldIndex + 1 );
newST = newST . slice ( 0 , ce . newIndex + 1 );
}
if ( cb . length ) {
oldST = oldST . slice ( cb . length );
newST = newST . slice ( cb . length );
}
var matches = resolve ( newST , hashScan ( oldST , blockSize ), blockSize );
if ( cb . length ) {
for ( var i = 0 ; i < matches . length ; i ++ ) {
matches [ i ]. oldIndex += cb . length ;
matches [ i ]. newIndex += cb . length ;
}
matches . push ( cb );
}
if ( ce . length ) { matches . push ( ce ); }
var reduced = reduceMatches ( matches );
var ops = matchesToOps ( oldS , newS , reduced ); // HERE produced operation with negative toRemove
if ( Operation . applyMulti ( ops , oldS ) !== newS ) {
// use 'self' instead of 'window' for node and webworkers
var x = ( typeof ( global ) !== 'undefined' ? global : self ). ChainPad_Diff_DEBUG = {
oldS : oldS ,
newS : newS ,
matches : matches ,
reduced : reduced ,
ops : ops
};
console . log ( x );
console . log ( "diff did not make a sane patch, check window.ChainPad_Diff_DEBUG" );
ops = matchesToOps ( oldS , newS , [ cb , ce ]);
if ( Operation . applyMulti ( ops , oldS ) !== newS ) {
throw new Error ( "diff is unrecoverable" );
}
}
return ops ;
};
},
"Patch.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
var Common = require ( './Common' );
var Operation = require ( './Operation' );
var Sha = require ( './sha256' );
var Patch = module . exports ;
/*::
import type {
Operation_t,
Operation_Packed_t,
Operation_Simplify_t,
Operation_Transform_t
} from './Operation';
import type { Sha256_t } from './sha256';
export type Patch_t = {
type: 'Patch',
operations: Array<Operation_t>,
parentHash: Sha256_t,
isCheckpoint: boolean,
mut: {
inverseOf: ?Patch_t,
}
};
export type Patch_Packed_t = Array<Operation_Packed_t|Sha256_t>;
export type Patch_Transform_t = (
toTransform:Array<Operation_t>,
transformBy:Array<Operation_t>,
state0:string
) => Array<Operation_t>;
*/
var create = Patch . create = function ( parentHash /*:Sha256_t*/ , isCheckpoint /*:?boolean*/ ) {
var out = Object . freeze ({
type : 'Patch' ,
operations : [],
parentHash : parentHash ,
isCheckpoint : !! isCheckpoint ,
mut : {
inverseOf : undefined
}
});
if ( isCheckpoint ) {
out . mut . inverseOf = out ;
}
return out ;
};
var check = Patch . check = function ( patch /*:any*/ , docLength_opt /*:?number*/ ) /*:Patch_t*/ {
Common . assert ( patch . type === 'Patch' );
Common . assert ( Array . isArray ( patch . operations ));
Common . assert ( /^[0-9a-f]{64}$/ . test ( patch . parentHash ));
for ( var i = patch . operations . length - 1 ; i >= 0 ; i -- ) {
Operation . check ( patch . operations [ i ], docLength_opt );
if ( i > 0 ) {
Common . assert ( ! Operation . shouldMerge ( patch . operations [ i ], patch . operations [ i - 1 ]));
}
if ( typeof ( docLength_opt ) === 'number' ) {
docLength_opt += Operation . lengthChange ( patch . operations [ i ]);
}
}
if ( patch . isCheckpoint ) {
Common . assert ( patch . operations . length === 1 );
Common . assert ( patch . operations [ 0 ]. offset === 0 );
if ( typeof ( docLength_opt ) === 'number' ) {
Common . assert ( ! docLength_opt || patch . operations [ 0 ]. toRemove === docLength_opt );
}
}
return patch ;
};
Patch . toObj = function ( patch /*:Patch_t*/ ) {
if ( Common . PARANOIA ) { check ( patch ); }
var out /*:Array<Operation_Packed_t|Sha256_t>*/ = new Array ( patch . operations . length + 1 );
var i ;
for ( i = 0 ; i < patch . operations . length ; i ++ ) {
out [ i ] = Operation . toObj ( patch . operations [ i ]);
}
out [ i ] = patch . parentHash ;
return out ;
};
Patch . fromObj = function ( obj /*:Patch_Packed_t*/ , isCheckpoint /*:?boolean*/ ) {
Common . assert ( Array . isArray ( obj ) && obj . length > 0 );
var patch = create ( Sha . check ( obj [ obj . length - 1 ]), isCheckpoint );
var i ;
for ( i = 0 ; i < obj . length - 1 ; i ++ ) {
patch . operations [ i ] = Operation . fromObj ( obj [ i ]);
}
if ( Common . PARANOIA ) { check ( patch ); }
return patch ;
};
var hash = function ( text ) {
return Sha . hex_sha256 ( text );
};
var addOperation = Patch . addOperation = function ( patch /*:Patch_t*/ , op /*:Operation_t*/ ) {
if ( Common . PARANOIA ) {
check ( patch );
Operation . check ( op );
}
for ( var i = 0 ; i < patch . operations . length ; i ++ ) {
if ( Operation . shouldMerge ( patch . operations [ i ], op )) {
var maybeOp = Operation . merge ( patch . operations [ i ], op );
patch . operations . splice ( i , 1 );
if ( maybeOp === null ) { return ; }
op = maybeOp ;
i -- ;
} else {
var out = Operation . rebase ( patch . operations [ i ], op );
if ( out === op ) {
// op could not be rebased further, insert it here to keep the list ordered.
patch . operations . splice ( i , 0 , op );
return ;
} else {
op = out ;
// op was rebased, try rebasing it against the next operation.
}
}
}
patch . operations . push ( op );
if ( Common . PARANOIA ) { check ( patch ); }
};
Patch . createCheckpoint = function (
parentContent /*:string*/ ,
checkpointContent /*:string*/ ,
parentContentHash_opt /*:?string*/ )
{
var op = Operation . create ( 0 , parentContent . length , checkpointContent );
if ( Common . PARANOIA && parentContentHash_opt ) {
Common . assert ( parentContentHash_opt === hash ( parentContent ));
}
parentContentHash_opt = parentContentHash_opt || hash ( parentContent );
var out = create ( parentContentHash_opt , true );
out . operations [ 0 ] = op ;
return out ;
};
var clone = Patch . clone = function ( patch /*:Patch_t*/ ) {
if ( Common . PARANOIA ) { check ( patch ); }
var out = create ( patch . parentHash , patch . isCheckpoint );
for ( var i = 0 ; i < patch . operations . length ; i ++ ) {
out . operations [ i ] = patch . operations [ i ];
}
return out ;
};
Patch . merge = function ( oldPatch /*:Patch_t*/ , newPatch /*:Patch_t*/ ) {
if ( Common . PARANOIA ) {
check ( oldPatch );
check ( newPatch );
}
if ( oldPatch . isCheckpoint ) {
Common . assert ( newPatch . parentHash === oldPatch . parentHash );
if ( newPatch . isCheckpoint ) {
return create ( oldPatch . parentHash );
}
return clone ( newPatch );
} else if ( newPatch . isCheckpoint ) {
return clone ( oldPatch );
}
oldPatch = clone ( oldPatch );
for ( var i = newPatch . operations . length - 1 ; i >= 0 ; i -- ) {
addOperation ( oldPatch , newPatch . operations [ i ]);
}
return oldPatch ;
};
Patch . apply = function ( patch /*:Patch_t*/ , doc /*:string*/ )
{
if ( Common . PARANOIA ) {
check ( patch );
Common . assert ( typeof ( doc ) === 'string' );
Common . assert ( Sha . hex_sha256 ( doc ) === patch . parentHash );
}
var newDoc = doc ;
for ( var i = patch . operations . length - 1 ; i >= 0 ; i -- ) {
newDoc = Operation . apply ( patch . operations [ i ], newDoc );
}
return newDoc ;
};
Patch . lengthChange = function ( patch /*:Patch_t*/ )
{
if ( Common . PARANOIA ) { check ( patch ); }
var out = 0 ;
for ( var i = 0 ; i < patch . operations . length ; i ++ ) {
out += Operation . lengthChange ( patch . operations [ i ]);
}
return out ;
};
Patch . invert = function ( patch /*:Patch_t*/ , doc /*:string*/ )
{
if ( Common . PARANOIA ) {
check ( patch );
Common . assert ( typeof ( doc ) === 'string' );
Common . assert ( Sha . hex_sha256 ( doc ) === patch . parentHash );
}
var newDoc = doc ;
var operations = new Array ( patch . operations . length );
for ( var i = patch . operations . length - 1 ; i >= 0 ; i -- ) {
operations [ i ] = Operation . invert ( patch . operations [ i ], newDoc );
newDoc = Operation . apply ( patch . operations [ i ], newDoc );
}
var opOffsets = new Array ( patch . operations . length );
( function () {
for ( var i = operations . length - 1 ; i >= 0 ; i -- ) {
opOffsets [ i ] = operations [ i ]. offset ;
for ( var j = i - 1 ; j >= 0 ; j -- ) {
opOffsets [ i ] += operations [ j ]. toRemove - operations [ j ]. toInsert . length ;
}
}
}());
var rpatch = create ( Sha . hex_sha256 ( newDoc ), patch . isCheckpoint );
rpatch . operations . splice ( 0 , rpatch . operations . length );
for ( var j = 0 ; j < operations . length ; j ++ ) {
rpatch . operations [ j ] =
Operation . create ( opOffsets [ j ], operations [ j ]. toRemove , operations [ j ]. toInsert );
}
if ( Common . PARANOIA ) { check ( rpatch ); }
return rpatch ;
};
Patch . simplify = function (
patch /*:Patch_t*/ ,
doc /*:string*/ ,
operationSimplify /*:Operation_Simplify_t*/ )
{
if ( Common . PARANOIA ) {
check ( patch );
Common . assert ( typeof ( doc ) === 'string' );
Common . assert ( Sha . hex_sha256 ( doc ) === patch . parentHash );
}
var spatch = create ( patch . parentHash );
var newDoc = doc ;
var outOps = [];
var j = 0 ;
for ( var i = patch . operations . length - 1 ; i >= 0 ; i -- ) {
var outOp = operationSimplify ( patch . operations [ i ], newDoc , Operation . simplify );
if ( outOp ) {
newDoc = Operation . apply ( outOp , newDoc );
outOps [ j ++ ] = outOp ;
}
}
Array . prototype . push . apply ( spatch . operations , outOps . reverse ());
if ( ! spatch . operations [ 0 ]) {
spatch . operations . shift ();
}
if ( Common . PARANOIA ) {
check ( spatch );
}
return spatch ;
};
Patch . equals = function ( patchA /*:Patch_t*/ , patchB /*:Patch_t*/ ) {
if ( patchA . operations . length !== patchB . operations . length ) { return false ; }
for ( var i = 0 ; i < patchA . operations . length ; i ++ ) {
if ( ! Operation . equals ( patchA . operations [ i ], patchB . operations [ i ])) { return false ; }
}
return true ;
};
var isCheckpointOp = function ( op , text ) {
return op . offset === 0 && op . toRemove === text . length && op . toInsert === text ;
};
Patch . transform = function (
toTransform /*:Patch_t*/ ,
transformBy /*:Patch_t*/ ,
doc /*:string*/ ,
patchTransformer /*:Patch_Transform_t*/ )
{
if ( Common . PARANOIA ) {
check ( toTransform , doc . length );
check ( transformBy , doc . length );
if ( Sha . hex_sha256 ( doc ) !== toTransform . parentHash ) { throw new Error ( "wrong hash" ); }
}
if ( toTransform . parentHash !== transformBy . parentHash ) { throw new Error (); }
var afterTransformBy = Patch . apply ( transformBy , doc );
var out = create ( transformBy . mut . inverseOf
? transformBy . mut . inverseOf . parentHash
: Sha . hex_sha256 ( afterTransformBy ),
toTransform . isCheckpoint
);
if ( transformBy . operations . length === 0 ) { return clone ( toTransform ); }
if ( toTransform . operations . length === 0 ) {
if ( toTransform . isCheckpoint ) { throw new Error (); }
return out ;
}
if ( toTransform . isCheckpoint ||
( toTransform . operations . length === 1 && isCheckpointOp ( toTransform . operations [ 0 ], doc )))
{
throw new Error ( "Attempting to transform a checkpoint, this should not happen" );
}
if ( transformBy . operations . length === 1 && isCheckpointOp ( transformBy . operations [ 0 ], doc )) {
if ( ! transformBy . isCheckpoint ) { throw new Error (); }
return toTransform ;
}
if ( transformBy . isCheckpoint ) { throw new Error (); }
var ops = patchTransformer ( toTransform . operations , transformBy . operations , doc );
Array . prototype . push . apply ( out . operations , ops );
if ( Common . PARANOIA ) {
check ( out , afterTransformBy . length );
}
return out ;
};
Patch . random = function ( doc /*:string*/ , opCount /*:?number*/ ) {
Common . assert ( typeof ( doc ) === 'string' );
opCount = opCount || ( Math . floor ( Math . random () * 30 ) + 1 );
var patch = create ( Sha . hex_sha256 ( doc ));
var docLength = doc . length ;
while ( opCount -- > 0 ) {
var op = Operation . random ( docLength );
docLength += Operation . lengthChange ( op );
addOperation ( patch , op );
}
check ( patch );
return patch ;
};
Object . freeze ( module . exports );
},
"SHA256.js" : function ( module , exports , require ){
/* A JavaScript implementation of the Secure Hash Algorithm, SHA-256
* Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
* Distributed under the BSD License
* Some bits taken from Paul Johnston's SHA-1 implementation
*/
( function () {
var chrsz = 8 ; /* bits per input character. 8 - ASCII; 16 - Unicode */
function safe_add ( x , y ) {
var lsw = ( x & 0xFFFF ) + ( y & 0xFFFF );
var msw = ( x >> 16 ) + ( y >> 16 ) + ( lsw >> 16 );
return ( msw << 16 ) | ( lsw & 0xFFFF );
}
function S ( X , n ) { return ( X >>> n ) | ( X << ( 32 - n ));}
function R ( X , n ) { return ( X >>> n );}
function Ch ( x , y , z ) { return (( x & y ) ^ (( ~ x ) & z ));}
function Maj ( x , y , z ) { return (( x & y ) ^ ( x & z ) ^ ( y & z ));}
function Sigma0256 ( x ) { return ( S ( x , 2 ) ^ S ( x , 13 ) ^ S ( x , 22 ));}
function Sigma1256 ( x ) { return ( S ( x , 6 ) ^ S ( x , 11 ) ^ S ( x , 25 ));}
function Gamma0256 ( x ) { return ( S ( x , 7 ) ^ S ( x , 18 ) ^ R ( x , 3 ));}
function Gamma1256 ( x ) { return ( S ( x , 17 ) ^ S ( x , 19 ) ^ R ( x , 10 ));}
function newArray ( n ) {
var a = [];
for (; n > 0 ; n -- ) {
a . push ( undefined );
}
return a ;
}
function core_sha256 ( m , l ) {
var K = [ 0x428A2F98 , 0x71374491 , 0xB5C0FBCF , 0xE9B5DBA5 , 0x3956C25B , 0x59F111F1 , 0x923F82A4 , 0xAB1C5ED5 , 0xD807AA98 , 0x12835B01 , 0x243185BE , 0x550C7DC3 , 0x72BE5D74 , 0x80DEB1FE , 0x9BDC06A7 , 0xC19BF174 , 0xE49B69C1 , 0xEFBE4786 , 0xFC19DC6 , 0x240CA1CC , 0x2DE92C6F , 0x4A7484AA , 0x5CB0A9DC , 0x76F988DA , 0x983E5152 , 0xA831C66D , 0xB00327C8 , 0xBF597FC7 , 0xC6E00BF3 , 0xD5A79147 , 0x6CA6351 , 0x14292967 , 0x27B70A85 , 0x2E1B2138 , 0x4D2C6DFC , 0x53380D13 , 0x650A7354 , 0x766A0ABB , 0x81C2C92E , 0x92722C85 , 0xA2BFE8A1 , 0xA81A664B , 0xC24B8B70 , 0xC76C51A3 , 0xD192E819 , 0xD6990624 , 0xF40E3585 , 0x106AA070 , 0x19A4C116 , 0x1E376C08 , 0x2748774C , 0x34B0BCB5 , 0x391C0CB3 , 0x4ED8AA4A , 0x5B9CCA4F , 0x682E6FF3 , 0x748F82EE , 0x78A5636F , 0x84C87814 , 0x8CC70208 , 0x90BEFFFA , 0xA4506CEB , 0xBEF9A3F7 , 0xC67178F2 ];
var HASH = [ 0x6A09E667 , 0xBB67AE85 , 0x3C6EF372 , 0xA54FF53A , 0x510E527F , 0x9B05688C , 0x1F83D9AB , 0x5BE0CD19 ];
var W = newArray ( 64 );
var a , b , c , d , e , f , g , h , i , j ;
var T1 , T2 ;
/* append padding */
m [ l >> 5 ] |= 0x80 << ( 24 - l % 32 );
m [(( l + 64 >> 9 ) << 4 ) + 15 ] = l ;
for ( var i = 0 ; i < m . length ; i += 16 ) {
a = HASH [ 0 ]; b = HASH [ 1 ]; c = HASH [ 2 ]; d = HASH [ 3 ];
e = HASH [ 4 ]; f = HASH [ 5 ]; g = HASH [ 6 ]; h = HASH [ 7 ];
for ( var j = 0 ; j < 64 ; j ++ ) {
if ( j < 16 ) {
W [ j ] = m [ j + i ];
} else {
W [ j ] = safe_add ( safe_add ( safe_add ( Gamma1256 (
W [ j - 2 ]), W [ j - 7 ]), Gamma0256 ( W [ j - 15 ])), W [ j - 16 ]);
}
T1 = safe_add ( safe_add ( safe_add (
safe_add ( h , Sigma1256 ( e )), Ch ( e , f , g )), K [ j ]), W [ j ]);
T2 = safe_add ( Sigma0256 ( a ), Maj ( a , b , c ));
h = g ; g = f ; f = e ; e = safe_add ( d , T1 );
d = c ; c = b ; b = a ; a = safe_add ( T1 , T2 );
}
HASH [ 0 ] = safe_add ( a , HASH [ 0 ]); HASH [ 1 ] = safe_add ( b , HASH [ 1 ]);
HASH [ 2 ] = safe_add ( c , HASH [ 2 ]); HASH [ 3 ] = safe_add ( d , HASH [ 3 ]);
HASH [ 4 ] = safe_add ( e , HASH [ 4 ]); HASH [ 5 ] = safe_add ( f , HASH [ 5 ]);
HASH [ 6 ] = safe_add ( g , HASH [ 6 ]); HASH [ 7 ] = safe_add ( h , HASH [ 7 ]);
}
return HASH ;
}
function str2binb ( str ) {
var bin = Array ();
var mask = ( 1 << chrsz ) - 1 ;
for ( var i = 0 ; i < str . length * chrsz ; i += chrsz )
bin [ i >> 5 ] |= ( str . charCodeAt ( i / chrsz ) & mask ) << ( 24 - i % 32 );
return bin ;
}
function binb2hex ( binarray ) {
var hexcase = 0 ; /* hex output format. 0 - lowercase; 1 - uppercase */
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef" ;
var str = "" ;
for ( var i = 0 ; i < binarray . length * 4 ; i ++ ) {
str += hex_tab . charAt (( binarray [ i >> 2 ] >> (( 3 - i % 4 ) * 8 + 4 )) & 0xF ) +
hex_tab . charAt (( binarray [ i >> 2 ] >> (( 3 - i % 4 ) * 8 )) & 0xF );
}
return str ;
}
function hex_sha256 ( s ){
return binb2hex ( core_sha256 ( str2binb ( s ), s . length * chrsz ));
}
module . exports . hex_sha256 = hex_sha256 ;
}());
},
"Common.js" : function ( module , exports , require ){
/*@flow*/
/* globals localStorage, window */
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
module . exports . global = ( function () {
if ( typeof ( self ) !== 'undefined' ) { return self ; }
if ( typeof ( global ) !== 'undefined' ) { return global ; }
if ( typeof ( window ) !== 'undefined' ) { return window ; }
throw new Error ( "no self, nor global, nor window" );
}());
var cfg = function ( name ) {
if ( typeof ( localStorage ) !== 'undefined' && localStorage [ name ]) {
return localStorage [ name ];
}
// flow thinks global may be undefined
return module . exports . global [ name ];
};
var PARANOIA = module . exports . PARANOIA = cfg ( "ChainPad_PARANOIA" );
/* Good testing but slooooooooooow */
module . exports . VALIDATE_ENTIRE_CHAIN_EACH_MSG = cfg ( "ChainPad_VALIDATE_ENTIRE_CHAIN_EACH_MSG" );
/* throw errors over non-compliant messages which would otherwise be treated as invalid */
module . exports . TESTING = cfg ( "ChainPad_TESTING" );
module . exports . assert = function ( expr /*:any*/ ) {
if ( ! expr ) { throw new Error ( "Failed assertion" ); }
};
module . exports . isUint = function ( integer /*:number*/ ) {
return ( typeof ( integer ) === 'number' ) &&
( Math . floor ( integer ) === integer ) &&
( integer >= 0 );
};
module . exports . randomASCII = function ( length /*:number*/ ) {
var content = [];
for ( var i = 0 ; i < length ; i ++ ) {
content [ i ] = String . fromCharCode ( Math . floor ( Math . random () * 256 ) % 57 + 65 );
}
return content . join ( '' );
};
module . exports . strcmp = function ( a /*:string*/ , b /*:string*/ ) {
if ( PARANOIA && typeof ( a ) !== 'string' ) { throw new Error (); }
if ( PARANOIA && typeof ( b ) !== 'string' ) { throw new Error (); }
return ( ( a === b ) ? 0 : ( ( a > b ) ? 1 : - 1 ) );
};
Object . freeze ( module . exports );
},
"sha256.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var asm_sha256 = require ( './sha256/exports.js' );
var old = require ( './SHA256.js' );
var Common = require ( './Common' );
/*::
export type Sha256_t = string;
*/
var brokenTextEncode = function ( str ) {
var out = new Uint8Array ( str . length );
for ( var i = 0 ; i < str . length ; i ++ ) {
out [ i ] = str . charCodeAt ( i ) & 0xff ;
}
return out ;
};
module . exports . check = function ( hex /*:any*/ ) /*:Sha256_t*/ {
if ( typeof ( hex ) !== 'string' ) { throw new Error (); }
if ( ! /[a-f0-9]{64}/ . test ( hex )) { throw new Error (); }
return hex ;
};
module . exports . hex_sha256 = function ( d /*:string*/ ) /*:Sha256_t*/ {
d = d + '' ;
var ret = asm_sha256 . hex ( brokenTextEncode ( d ));
if ( Common . PARANOIA ) {
var oldHash = old . hex_sha256 ( d );
if ( oldHash !== ret ) {
try {
throw new Error ();
} catch ( e ) {
console . log ({
hashErr : e ,
badHash : d ,
asmHasher : asm_sha256 . hex ,
oldHasher : old . hex_sha256
});
}
return oldHash ;
}
}
return ret ;
};
Object . freeze ( module . exports );
},
"Message.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
var Common = require ( './Common' );
//var Operation = require('./Operation');
var Patch = require ( './Patch' );
var Sha = require ( './sha256' );
var Message = module . exports ;
var PATCH = Message . PATCH = 2 ;
var CHECKPOINT = Message . CHECKPOINT = 4 ;
/*::
import type { Sha256_t } from './sha256'
import type { Patch_t } from './Patch'
export type Message_Type_t = 2 | 4;
export type Message_Status_t =
'accepted'|'initial_state'|'duplicate'|'failed_content_validation'|
'can_be_simplified'|'checkpoint_wrong_parentcount'|'parent_hash_invalid'|'unhandled';
export type Message_t = {
type: 'Message',
messageType: Message_Type_t,
content: Patch_t,
lastMsgHash: Sha256_t,
hashOf: Sha256_t,
mut: {
parentCount: ?number,
isInitialMessage: boolean,
parent: ?Message_t,
isFromMe: boolean,
recvOrder: number,
status: Message_Status_t
}
}
*/
var check = Message . check = function ( msg /*:any*/ ) /*:Message_t*/ {
Common . assert ( msg . type === 'Message' );
Common . assert ( msg . messageType === PATCH || msg . messageType === CHECKPOINT );
Patch . check ( msg . content );
Common . assert ( typeof ( msg . lastMsgHash ) === 'string' );
return msg ;
};
var DUMMY_HASH /*:Sha256_t*/ = "" ;
var create = Message . create = function (
type /*:Message_Type_t*/ ,
content /*:Patch_t*/ ,
lastMsgHash /*:Sha256_t*/ ) /*:Message_t*/
{
var msg = {
type : 'Message' ,
messageType : type ,
content : content ,
lastMsgHash : lastMsgHash ,
hashOf : DUMMY_HASH ,
mut : {
parentCount : undefined ,
isInitialMessage : false ,
isFromMe : false ,
parent : undefined ,
recvOrder : - 1 ,
status : "unhandled"
}
};
msg . hashOf = hashOf ( msg );
if ( Common . PARANOIA ) { check ( msg ); }
return Object . freeze ( msg );
};
// $FlowFixMe doesn't like the toString()
var toString = Message . toStr = Message . toString = function ( msg /*:Message_t*/ ) {
if ( Common . PARANOIA ) { check ( msg ); }
if ( msg . messageType === PATCH || msg . messageType === CHECKPOINT ) {
if ( ! msg . content ) { throw new Error (); }
return JSON . stringify ([ msg . messageType , Patch . toObj ( msg . content ), msg . lastMsgHash ]);
} else {
throw new Error ();
}
};
Message . fromString = function ( str /*:string*/ ) /*:Message_t*/ {
var m = JSON . parse ( str );
if ( m [ 0 ] !== CHECKPOINT && m [ 0 ] !== PATCH ) { throw new Error ( "invalid message type " + m [ 0 ]); }
var msg = create ( m [ 0 ], Patch . fromObj ( m [ 1 ], ( m [ 0 ] === CHECKPOINT )), m [ 2 ]);
return Object . freeze ( msg );
};
var hashOf = Message . hashOf = function ( msg /*:Message_t*/ ) {
if ( Common . PARANOIA ) { check ( msg ); }
var hash = Sha . hex_sha256 ( toString ( msg ));
return hash ;
};
Object . freeze ( module . exports );
},
"ChainPad.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
var Common = module . exports . Common = require ( './Common' );
var Operation = module . exports . Operation = require ( './Operation' );
var Patch = module . exports . Patch = require ( './Patch' );
var Message = module . exports . Message = require ( './Message' );
var Sha = module . exports . Sha = require ( './sha256' );
var Diff = module . exports . Diff = require ( './Diff' );
var TextTransformer = module . exports . TextTransformer = require ( './transform/TextTransformer' );
module . exports . NaiveJSONTransformer = require ( './transform/NaiveJSONTransformer' );
module . exports . SmartJSONTransformer = require ( './transform/SmartJSONTransformer' );
// hex_sha256('')
var EMPTY_STR_HASH = module . exports . EMPTY_STR_HASH =
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' ;
var ZERO = '0000000000000000000000000000000000000000000000000000000000000000' ;
// Default number of patches between checkpoints (patches older than this will be pruned)
// default for realtime.config.checkpointInterval
var DEFAULT_CHECKPOINT_INTERVAL = 50 ;
// Default number of milliseconds to wait before syncing to the server
var DEFAULT_AVERAGE_SYNC_MILLISECONDS = 300 ;
// By default, we allow checkpoints at any place but if this is set true, we will blow up on chains
// which have checkpoints not where we expect them to be.
var DEFAULT_STRICT_CHECKPOINT_VALIDATION = false ;
var debug = function ( realtime , msg ) {
if ( realtime . logLevel > 1 ) {
console . log ( "[" + realtime . userName + "] " + msg );
}
};
var warn = function ( realtime , msg ) {
if ( realtime . logLevel > 0 ) {
console . error ( "[" + realtime . userName + "] " + msg );
}
};
var schedule = function ( realtime , func , timeout ) {
if ( realtime . aborted ) { return ; }
if ( ! timeout ) {
timeout = Math . floor ( Math . random () * 2 * realtime . config . avgSyncMilliseconds );
}
var to = setTimeout ( function () {
realtime . schedules . splice ( realtime . schedules . indexOf ( to ), 1 );
func ();
}, timeout );
realtime . schedules . push ( to );
return to ;
};
var unschedule = function ( realtime , schedule ) {
var index = realtime . schedules . indexOf ( schedule );
if ( index > - 1 ) {
realtime . schedules . splice ( index , 1 );
}
clearTimeout ( schedule );
};
var onMessage = function ( realtime , message , callback /*:(?string)=>void*/ ) {
if ( ! realtime . messageHandlers . length ) {
callback ( "no onMessage() handler registered" );
}
try {
realtime . messageHandlers . forEach ( function ( handler ) {
handler ( message , function () {
callback . apply ( null , arguments );
callback = function () { };
});
});
} catch ( e ) {
callback ( e . stack );
}
};
var sendMessage = function ( realtime , msg , callback , timeSent ) {
var strMsg = Message . toStr ( msg );
onMessage ( realtime , strMsg , function ( err ) {
if ( err ) {
debug ( realtime , "Posting to server failed [" + err + "]" );
realtime . pending = null ;
} else {
var pending = realtime . pending ;
realtime . pending = null ;
if ( ! pending ) { throw new Error (); }
Common . assert ( pending . hash === msg . hashOf );
if ( handleMessage ( realtime , strMsg , true )) {
realtime . timeOfLastSuccess = + new Date ();
realtime . lag = + new Date () - pending . timeSent ;
} else {
debug ( realtime , "Our message [" + msg . hashOf + "] failed validation" );
}
pending . callback ();
}
});
var timeout = schedule ( realtime , function () {
debug ( realtime , "Failed to send message [" + msg . hashOf + "] to server" );
var pending = realtime . pending ;
if ( pending ) {
//var timeSent = pending.timeSent;
realtime . pending = null ;
realtime . syncSchedule = - 1 ;
}
sync ( realtime , 0 );
if ( ! pending ) {
throw new Error ( "INTERNAL ERROR: Message timed out but no realtime.pending" );
}
}, 10000 + ( Math . random () * 5000 ));
if ( realtime . pending ) { throw new Error ( "there is already a pending message" ); }
if ( realtime . timeOfLastSuccess === - 1 ) { realtime . timeOfLastSuccess = + new Date (); }
realtime . pending = {
hash : msg . hashOf ,
timeSent : timeSent || + new Date (),
callback : function () {
unschedule ( realtime , timeout );
realtime . syncSchedule = schedule ( realtime , function () { sync ( realtime ); }, 0 );
callback ();
}
};
if ( Common . PARANOIA ) { check ( realtime ); }
};
var settle = function ( realtime ) {
var onSettle = realtime . onSettle ;
realtime . onSettle = [];
onSettle . forEach ( function ( handler ) {
try {
handler ();
} catch ( e ) {
warn ( realtime , "Error in onSettle handler [" + e . stack + "]" );
}
});
};
var inversePatch = function ( patch ) {
if ( ! patch . mut . inverseOf ) { throw new Error (); }
return patch . mut . inverseOf ;
};
var sync = function ( realtime , timeSent ) {
if ( Common . PARANOIA ) { check ( realtime ); }
if ( realtime . syncSchedule && ! realtime . pending ) {
unschedule ( realtime , realtime . syncSchedule );
realtime . syncSchedule = null ;
} else {
//debug(realtime, "already syncing...");
// we're currently waiting on something from the server.
return ;
}
realtime . uncommitted = Patch . simplify (
realtime . uncommitted , realtime . authDoc , realtime . config . operationSimplify );
if ( realtime . uncommitted . operations . length === 0 ) {
//debug(realtime, "No data to sync to the server, sleeping");
settle ( realtime );
realtime . timeOfLastSuccess = + new Date ();
realtime . syncSchedule = schedule ( realtime , function () { sync ( realtime ); });
return ;
}
var pc = parentCount ( realtime , realtime . best ) + 1 ;
if (( pc % realtime . config . checkpointInterval ) === 0 ) {
var best = realtime . best ;
debug ( realtime , "Sending checkpoint (interval [" + realtime . config . checkpointInterval +
"]) patch no [" + pc + "]" );
debug ( realtime , parentCount ( realtime , realtime . best ));
if ( ! best || ! best . content || ! inversePatch ( best . content )) { throw new Error (); }
var cpp = Patch . createCheckpoint ( realtime . authDoc ,
realtime . authDoc ,
inversePatch ( best . content ). parentHash );
var cp = Message . create ( Message . CHECKPOINT , cpp , best . hashOf );
sendMessage ( realtime , cp , function () {
debug ( realtime , "Checkpoint sent and accepted" );
}, timeSent );
return ;
}
var msg ;
if ( realtime . setContentPatch ) {
msg = realtime . setContentPatch ;
} else {
msg = Message . create ( Message . PATCH , realtime . uncommitted , realtime . best . hashOf );
}
sendMessage ( realtime , msg , function () {
//debug(realtime, "patch sent");
if ( realtime . setContentPatch ) {
debug ( realtime , "initial Ack received [" + msg . hashOf + "]" );
realtime . setContentPatch = null ;
}
}, timeSent );
};
var storeMessage = function ( realtime , msg ) {
Common . assert ( msg . lastMsgHash );
Common . assert ( msg . hashOf );
realtime . messages [ msg . hashOf ] = msg ;
( realtime . messagesByParent [ msg . lastMsgHash ] =
realtime . messagesByParent [ msg . lastMsgHash ] || []). push ( msg );
msg . mut . status = "accepted" ;
};
var forgetMessage = function ( realtime , msg , reason ) {
Common . assert ( msg . lastMsgHash );
Common . assert ( msg . hashOf );
if ( reason ) {
msg . mut . status = reason ;
realtime . rejectedBlocks . push ( msg );
}
delete realtime . messages [ msg . hashOf ];
var list = realtime . messagesByParent [ msg . lastMsgHash ];
Common . assert ( list . indexOf ( msg ) > - 1 );
list . splice ( list . indexOf ( msg ), 1 );
if ( list . length === 0 ) {
delete realtime . messagesByParent [ msg . lastMsgHash ];
}
var children = realtime . messagesByParent [ msg . hashOf ];
if ( children ) {
for ( var i = 0 ; i < children . length ; i ++ ) {
delete children [ i ]. mut . parent ;
}
}
};
var create = function ( config ) {
var zeroPatch = Patch . create ( EMPTY_STR_HASH );
mkInverse ( zeroPatch , '' );
var zeroMsg = Message . create ( Message . PATCH , zeroPatch , ZERO );
zeroMsg . mut . parentCount = 0 ;
zeroMsg . mut . isInitialMessage = true ;
var best = zeroMsg ;
var initMsg ;
if ( config . initialState !== '' ) {
var initPatch = Patch . create ( EMPTY_STR_HASH );
Patch . addOperation ( initPatch , Operation . create ( 0 , 0 , config . initialState ));
mkInverse ( initPatch , '' );
initMsg = Message . create ( Message . PATCH , initPatch , zeroMsg . hashOf );
initMsg . mut . isInitialMessage = true ;
best = initMsg ;
}
var realtime = {
type : 'ChainPad' ,
authDoc : config . initialState ,
config : config ,
logLevel : config . logLevel ,
/** A patch representing all uncommitted work. */
uncommitted : Patch . create ( inversePatch ( best . content ). parentHash ),
patchHandlers : [],
changeHandlers : [],
messageHandlers : [],
schedules : [],
aborted : false ,
syncSchedule : - 2 ,
// this is only used if PARANOIA is enabled.
userInterfaceContent : config . initialState ,
// If we want to set the content to a particular thing, this patch will be sent across the
// wire. If the patch is not accepted we will not try to recover it. This is used for
// setting initial state.
setContentPatch : initMsg ,
// hash and callback for previously send patch, currently in flight.
pending : undefined ,
messages : {},
messagesByParent : {},
rootMessage : zeroMsg ,
onSettle : [],
userName : config . userName ,
best : best ,
lag : 0 ,
timeOfLastSuccess : - 1 ,
// Incremented every time a message comes in, valid or invalid, used to number messages.
recvCounter : 0 ,
// All of the messages which were discarded because they were faulty
rejectedBlocks : []
};
storeMessage ( realtime , zeroMsg );
if ( initMsg ) {
storeMessage ( realtime , initMsg );
}
return realtime ;
};
var getParent = function ( realtime , message ) {
var parent = message . mut . parent = message . mut . parent || realtime . messages [ message . lastMsgHash ];
return parent ;
};
var check = function ( realtime ) {
Common . assert ( realtime . type === 'ChainPad' );
Common . assert ( typeof ( realtime . authDoc ) === 'string' );
Patch . check ( realtime . uncommitted , realtime . authDoc . length );
var uiDoc = Patch . apply ( realtime . uncommitted , realtime . authDoc );
Common . assert ( uiDoc . length === uncommittedDocLength ( realtime ));
if ( realtime . userInterfaceContent !== '' ) {
Common . assert ( uiDoc === realtime . userInterfaceContent );
}
if ( ! Common . VALIDATE_ENTIRE_CHAIN_EACH_MSG ) { return ; }
var doc = realtime . authDoc ;
var patchMsg = realtime . best ;
Common . assert ( inversePatch ( patchMsg . content ). parentHash === realtime . uncommitted . parentHash );
var patches = [];
do {
patches . push ( patchMsg );
doc = Patch . apply ( inversePatch ( patchMsg . content ), doc );
} while (( patchMsg = getParent ( realtime , patchMsg )));
if ( realtime . rootMessage . content . isCheckpoint ) {
if ( doc !== realtime . rootMessage . content . operations [ 0 ]. toInsert ) { throw new Error (); }
} else if ( doc !== '' ) { throw new Error (); }
while (( patchMsg = patches . pop ())) {
doc = Patch . apply ( patchMsg . content , doc );
}
Common . assert ( doc === realtime . authDoc );
};
var uncommittedDocLength = function ( realtime ) {
return realtime . authDoc . length + Patch . lengthChange ( realtime . uncommitted );
};
var doOperation = function ( realtime , op ) {
if ( Common . PARANOIA ) {
check ( realtime );
realtime . userInterfaceContent = Operation . apply ( op , realtime . userInterfaceContent );
}
Operation . check ( op , uncommittedDocLength ( realtime ));
Patch . addOperation ( realtime . uncommitted , op );
};
var doPatch = function ( realtime , patch ) {
if ( Common . PARANOIA ) {
check ( realtime );
Common . assert ( Patch . invert ( realtime . uncommitted , realtime . authDoc ). parentHash ===
patch . parentHash );
realtime . userInterfaceContent = Patch . apply ( patch , realtime . userInterfaceContent );
}
Patch . check ( patch , uncommittedDocLength ( realtime ));
realtime . uncommitted = Patch . merge ( realtime . uncommitted , patch );
};
var isAncestorOf = function ( realtime , ancestor , decendent ) {
if ( ! ancestor ) { return false ; }
for (;;) {
if ( ! decendent ) { return false ; }
if ( ancestor === decendent ) { return true ; }
decendent = getParent ( realtime , decendent );
}
};
var parentCount = function ( realtime , message ) {
if ( typeof ( message . mut . parentCount ) === 'number' ) { return message . mut . parentCount ; }
var msgs = [];
for (; ( typeof ( message . mut . parentCount ) !== 'number' ); message = getParent ( realtime , message )) {
if ( ! message ) {
if ( message === realtime . rootMessage ) {
throw new Error ( "root message does not have parent count" );
}
throw new Error ( "parentCount called on unlinked message" );
}
msgs . unshift ( message );
}
var pc = message . mut . parentCount ;
for ( var i = 0 ; i < msgs . length ; i ++ ) {
msgs [ i ]. mut . parentCount = ++ pc ;
}
return pc ;
};
var applyPatch = function ( realtime , isFromMe , patch ) {
Common . assert ( patch );
var newAuthDoc ;
if ( isFromMe ) {
// Case 1: We're applying a patch which we originally created (yay our work was accepted)
// We will merge the inverse of the patch with our uncommitted work in order that
// we do not try to commit that work over again.
// Case 2: We're reverting a patch which had originally come from us, a.k.a. we're applying
// the inverse of that patch.
//
// In either scenario, we want to apply the inverse of the patch we are applying, to the
// uncommitted work. Whatever we "add" to the authDoc we "remove" from the uncommittedWork.
//
Common . assert ( patch . parentHash === realtime . uncommitted . parentHash );
realtime . uncommitted = Patch . merge ( inversePatch ( patch ), realtime . uncommitted );
} else {
// It's someone else's patch which was received, we need to *transform* out uncommitted
// work over their patch in order to preserve intent as much as possible.
//debug(realtime, "Transforming patch " + JSON.stringify(realtime.uncommitted.operations));
realtime . uncommitted = Patch . transform (
realtime . uncommitted ,
patch ,
realtime . authDoc ,
realtime . config . patchTransformer
);
//debug(realtime, "By " + JSON.stringify(patch.operations) +
// "\nResult " + JSON.stringify(realtime.uncommitted.operations));
if ( realtime . config . validateContent ) {
newAuthDoc = Patch . apply ( patch , realtime . authDoc );
var userDoc = Patch . apply ( realtime . uncommitted , newAuthDoc );
if ( ! realtime . config . validateContent ( userDoc )) {
warn ( realtime , "Transformed patch is not valid" );
// big hammer
realtime . uncommitted = Patch . create ( Sha . hex_sha256 ( realtime . authDoc ));
}
}
}
Common . assert ( realtime . uncommitted . parentHash === inversePatch ( patch ). parentHash );
realtime . authDoc = newAuthDoc || Patch . apply ( patch , realtime . authDoc );
if ( Common . PARANOIA ) {
Common . assert ( realtime . uncommitted . parentHash === inversePatch ( patch ). parentHash );
Common . assert ( Sha . hex_sha256 ( realtime . authDoc ) === realtime . uncommitted . parentHash );
realtime . userInterfaceContent = Patch . apply ( realtime . uncommitted , realtime . authDoc );
}
};
var revertPatch = function ( realtime , isFromMe , patch ) {
applyPatch ( realtime , isFromMe , inversePatch ( patch ));
};
var getBestChild = function ( realtime , msg ) {
var best = msg ;
( realtime . messagesByParent [ msg . hashOf ] || []). forEach ( function ( child ) {
Common . assert ( child . lastMsgHash === msg . hashOf );
child = getBestChild ( realtime , child );
if ( parentCount ( realtime , child ) > parentCount ( realtime , best )) { best = child ; }
});
return best ;
};
var pushUIPatch = function ( realtime , patch ) {
if ( ! patch . operations . length ) { return ; }
// push the uncommittedPatch out to the user interface.
realtime . patchHandlers . forEach ( function ( handler ) { handler ( patch ); });
realtime . changeHandlers . forEach ( function ( handler ) {
patch . operations . forEach ( function ( op ) {
handler ( op . offset , op . toRemove , op . toInsert );
});
});
};
var validContent = function ( realtime , contentGetter ) {
try {
return realtime . config . validateContent ( contentGetter ());
} catch ( e ) {
warn ( realtime , "Error in content validator [" + e . stack + "]" );
}
return false ;
};
var forEachParent = function ( realtime , patch , callback ) {
for ( var m = getParent ( realtime , patch ); m ; m = getParent ( realtime , m )) {
if ( callback ( m ) === false ) { return ; }
}
};
var mkInverse = function ( patch , content ) {
if ( patch . mut . inverseOf ) { return ; }
var inverse = patch . mut . inverseOf = Patch . invert ( patch , content );
inverse . mut . inverseOf = patch ;
};
var handleMessage = function ( realtime , msgStr , isFromMe ) {
if ( Common . PARANOIA ) { check ( realtime ); }
var msg = Message . fromString ( msgStr );
msg . mut . recvOrder = realtime . recvCounter ++ ;
debug ( realtime , JSON . stringify ([ msg . hashOf , msg . content . operations ]));
if ( realtime . messages [ msg . hashOf ]) {
if ( realtime . setContentPatch && realtime . setContentPatch . hashOf === msg . hashOf ) {
// We got the initial state patch, channel already has a pad, no need to send it.
realtime . setContentPatch = null ;
} else {
msg . mut . status = "duplicate" ;
realtime . rejectedBlocks . push ( msg );
if ( msg . content . isCheckpoint ) {
debug ( realtime , "[" +
( isFromMe ? "our" : "their" ) +
"] Checkpoint [" + msg . hashOf + "] is already known" );
return true ;
}
debug ( realtime , "Patch [" + msg . hashOf + "] is already known" );
}
if ( Common . PARANOIA ) { check ( realtime ); }
return ;
}
if ( msg . content . isCheckpoint &&
! validContent ( realtime , function () { return msg . content . operations [ 0 ]. toInsert ; }))
{
// If it's not a checkpoint, we verify it later on...
debug ( realtime , "Checkpoint [" + msg . hashOf + "] failed content validation" );
msg . mut . status = "failed_content_validation" ;
realtime . rejectedBlocks . push ( msg );
return ;
}
storeMessage ( realtime , msg );
if ( ! isAncestorOf ( realtime , realtime . rootMessage , msg )) {
if ( msg . content . isCheckpoint && realtime . best . mut . isInitialMessage ) {
// We're starting with a trucated chain from a checkpoint, we will adopt this
// as the root message and go with it...
debug ( realtime , 'applying checkpoint [' + msg . hashOf + ']' );
var userDoc = Patch . apply ( realtime . uncommitted , realtime . authDoc );
Common . assert ( ! Common . PARANOIA || realtime . userInterfaceContent === userDoc );
var fixUserDocPatch = Patch . invert ( realtime . uncommitted , realtime . authDoc );
Patch . addOperation ( fixUserDocPatch ,
Operation . create ( 0 , realtime . authDoc . length , msg . content . operations [ 0 ]. toInsert ));
fixUserDocPatch =
Patch . simplify ( fixUserDocPatch , userDoc , realtime . config . operationSimplify );
msg . mut . parentCount = 0 ;
realtime . rootMessage = realtime . best = msg ;
realtime . authDoc = msg . content . operations [ 0 ]. toInsert ;
realtime . uncommitted = Patch . create ( Sha . hex_sha256 ( realtime . authDoc ));
pushUIPatch ( realtime , fixUserDocPatch );
if ( Common . PARANOIA ) { realtime . userInterfaceContent = realtime . authDoc ; }
return true ;
} else {
// we'll probably find the missing parent later.
debug ( realtime , "Patch [" + msg . hashOf + "] not connected to root (parent: [" +
msg . lastMsgHash + "])" );
if ( Common . PARANOIA ) { check ( realtime ); }
return ;
}
}
// of this message fills in a hole in the chain which makes another patch better, swap to the
// best child of this patch since longest chain always wins.
msg = getBestChild ( realtime , msg );
msg . mut . isFromMe = isFromMe ;
var patch = msg . content ;
// Find the ancestor of this patch which is in the main chain, reverting as necessary
var toRevert = [];
var commonAncestor = realtime . best ;
if ( ! isAncestorOf ( realtime , realtime . best , msg )) {
var pcBest = parentCount ( realtime , realtime . best );
var pcMsg = parentCount ( realtime , msg );
if ( pcBest < pcMsg
|| ( pcBest === pcMsg
&& Common . strcmp ( realtime . best . hashOf , msg . hashOf ) > 0 ))
{
// switch chains
while ( commonAncestor && ! isAncestorOf ( realtime , commonAncestor , msg )) {
toRevert . push ( commonAncestor );
commonAncestor = getParent ( realtime , commonAncestor );
}
Common . assert ( commonAncestor );
debug ( realtime , "Patch [" + msg . hashOf + "] better than best chain, switching" );
} else {
debug ( realtime , "Patch [" + msg . hashOf + "] chain is [" + pcMsg + "] best chain is [" +
pcBest + "]" );
if ( Common . PARANOIA ) { check ( realtime ); }
return true ;
}
}
// Find the parents of this patch which are not in the main chain.
var toApply = [];
var current = msg ;
do {
toApply . unshift ( current );
current = getParent ( realtime , current );
Common . assert ( current );
} while ( current !== commonAncestor );
var authDocAtTimeOfPatch = realtime . authDoc ;
toRevert . forEach ( function ( tr ) {
authDocAtTimeOfPatch = Patch . apply ( inversePatch ( tr . content ), authDocAtTimeOfPatch );
});
toApply . forEach ( function ( ta , i ) {
// toApply.length-1 because we do not want to apply the new patch.
if ( i === toApply . length - 1 ) { return ; }
mkInverse ( ta . content , authDocAtTimeOfPatch );
authDocAtTimeOfPatch = Patch . apply ( ta . content , authDocAtTimeOfPatch );
});
var headAtTimeOfPatch = realtime . best ;
if ( toApply . length > 1 ) {
headAtTimeOfPatch = toApply [ toApply . length - 2 ];
Common . assert ( headAtTimeOfPatch );
} else if ( toRevert . length ) {
headAtTimeOfPatch = getParent ( realtime , toRevert [ toRevert . length - 1 ]);
Common . assert ( headAtTimeOfPatch );
}
Common . assert ( inversePatch ( headAtTimeOfPatch . content ). parentHash );
Common . assert ( ! Common . PARANOIA ||
inversePatch ( headAtTimeOfPatch . content ). parentHash ===
Sha . hex_sha256 ( authDocAtTimeOfPatch ));
if ( inversePatch ( headAtTimeOfPatch . content ). parentHash !== patch . parentHash ) {
debug ( realtime , "patch [" + msg . hashOf + "] parentHash is not valid" );
if ( Common . PARANOIA ) { check ( realtime ); }
if ( Common . TESTING ) { throw new Error (); }
forgetMessage ( realtime , msg , "parent_hash_invalid" );
return ;
}
if ( patch . isCheckpoint && realtime . config . noPrune ) {
// do nothing, just fall through
} else if ( patch . isCheckpoint ) {
// Ok, we have a checkpoint patch.
// If the chain length is not equal to checkpointInterval then this patch is invalid.
var checkpointP ;
forEachParent ( realtime , msg , function ( m ) {
if ( m . content . isCheckpoint ) {
if ( checkpointP ) {
checkpointP = m ;
return false ;
}
checkpointP = m ;
}
});
if ( checkpointP && checkpointP !== realtime . rootMessage ) {
var point = parentCount ( realtime , checkpointP );
if ( realtime . config . strictCheckpointValidation &&
( point % realtime . config . checkpointInterval ) !== 0 )
{
debug ( realtime , "checkpoint [" + msg . hashOf + "] at invalid point [" + point + "]" );
if ( Common . PARANOIA ) { check ( realtime ); }
if ( Common . TESTING ) { throw new Error (); }
forgetMessage ( realtime , msg , "checkpoint_wrong_parentcount" );
return ;
}
// Time to prune some old messages from the chain
debug ( realtime , "checkpoint [" + msg . hashOf + "]" );
forEachParent ( realtime , checkpointP , function ( m ) {
debug ( realtime , "pruning [" + m . hashOf + "]" );
forgetMessage ( realtime , m );
});
realtime . rootMessage = checkpointP ;
}
} else {
var simplePatch =
Patch . simplify ( patch , authDocAtTimeOfPatch , realtime . config . operationSimplify );
if ( ! Patch . equals ( simplePatch , patch )) {
debug ( realtime , "patch [" + msg . hashOf + "] can be simplified" );
if ( Common . PARANOIA ) { check ( realtime ); }
if ( Common . TESTING ) { throw new Error (); }
forgetMessage ( realtime , msg , "can_be_simplified" );
return ;
}
if ( ! validContent ( realtime ,
function () { return Patch . apply ( patch , authDocAtTimeOfPatch ); }))
{
debug ( realtime , "Patch [" + msg . hashOf + "] failed content validation" );
return ;
}
}
mkInverse ( patch , authDocAtTimeOfPatch );
realtime . uncommitted = Patch . simplify (
realtime . uncommitted , realtime . authDoc , realtime . config . operationSimplify );
var oldUserInterfaceContent = Patch . apply ( realtime . uncommitted , realtime . authDoc );
if ( Common . PARANOIA ) {
Common . assert ( oldUserInterfaceContent === realtime . userInterfaceContent );
}
// Derive the patch for the user's uncommitted work
var uncommittedPatch = Patch . invert ( realtime . uncommitted , realtime . authDoc );
toRevert . forEach ( function ( tr ) {
debug ( realtime , "reverting [" + tr . hashOf + "]" );
if ( tr . mut . isFromMe ) {
debug ( realtime , "reverting patch 'from me' [" + JSON . stringify ( tr . content . operations ) + "]" );
}
uncommittedPatch = Patch . merge ( uncommittedPatch , inversePatch ( tr . content ));
revertPatch ( realtime , tr . mut . isFromMe , tr . content );
});
toApply . forEach ( function ( ta ) {
debug ( realtime , "applying [" + ta . hashOf + "]" );
uncommittedPatch = Patch . merge ( uncommittedPatch , ta . content );
applyPatch ( realtime , ta . mut . isFromMe , ta . content );
});
uncommittedPatch = Patch . merge ( uncommittedPatch , realtime . uncommitted );
uncommittedPatch = Patch . simplify (
uncommittedPatch , oldUserInterfaceContent , realtime . config . operationSimplify );
realtime . best = msg ;
if ( Common . PARANOIA ) {
// apply the uncommittedPatch to the userInterface content.
var newUserInterfaceContent = Patch . apply ( uncommittedPatch , oldUserInterfaceContent );
Common . assert ( realtime . userInterfaceContent . length === uncommittedDocLength ( realtime ));
Common . assert ( newUserInterfaceContent === realtime . userInterfaceContent );
}
pushUIPatch ( realtime , uncommittedPatch );
if ( ! realtime . uncommitted . operations . length ) {
settle ( realtime );
}
if ( Common . PARANOIA ) { check ( realtime ); }
return true ;
};
var getDepthOfState = function ( content , minDepth , realtime ) {
Common . assert ( typeof ( content ) === 'string' );
// minimum depth is an optional argument which defaults to zero
minDepth = minDepth || 0 ;
if ( minDepth === 0 && realtime . authDoc === content ) {
return 0 ;
}
var hash = Sha . hex_sha256 ( content );
var patchMsg = realtime . best ;
var depth = 0 ;
do {
if ( depth < minDepth ) {
// you haven't exceeded the minimum depth
} else {
//console.log("Exceeded minimum depth");
// you *have* exceeded the minimum depth
if ( patchMsg . content . parentHash === hash ) {
// you found it!
return depth + 1 ;
}
}
depth ++ ;
} while (( patchMsg = getParent ( realtime , patchMsg )));
return - 1 ;
};
2019-02-26 15:48:29 +01:00
var getContentAtState = function ( realtime , msg , previousDoc ) {
2019-02-19 14:40:38 +01:00
var patches = [ msg ];
2019-02-26 15:48:29 +01:00
var doc = previousDoc || '' ;
if ( ! previousDoc ) {
while ( patches [ 0 ] !== realtime . rootMessage ) {
var parent = getParent ( realtime , patches [ 0 ]);
if ( ! parent ) {
return { error : 'not connected to root' , doc : undefined };
}
patches . unshift ( parent );
}
if ( realtime . rootMessage . content . operations . length ) {
Common . assert ( realtime . rootMessage . content . operations . length === 1 );
doc = realtime . rootMessage . content . operations [ 0 ]. toInsert ;
2019-02-19 14:40:38 +01:00
}
}
2019-02-26 15:48:29 +01:00
for ( var i = previousDoc ? 0 : 1 ; i < patches . length ; i ++ ) {
2019-02-19 14:40:38 +01:00
doc = Patch . apply ( patches [ i ]. content , doc );
}
return { error : undefined , doc : doc };
};
/*::
import type { Message_Status_t } from './Message.js';
export type ChainPad_BlockContent_t = {
error: ?string,
doc: ?string
};
export type ChainPad_Block_t = {
type: 'Block',
hashOf: string,
lastMsgHash: string,
isCheckpoint: boolean,
status: Message_Status_t,
recvOrder: number,
parentCount: number,
getParent: ()=>?ChainPad_Block_t,
getChildren: ()=>Array<ChainPad_Block_t>,
2019-02-26 15:48:29 +01:00
getContent: (?string)=>{
2019-02-19 14:40:38 +01:00
error: ?string,
doc: ?string
},
getPatch: ()=>Patch_t,
getInversePatch: ()=>Patch_t,
equals: (?ChainPad_Block_t, ?any)=>boolean
};
*/
var wrapMessage = function ( realtime , msg ) /*:ChainPad_Block_t*/ {
var pc = - 1 ;
try { pc = parentCount ( realtime , msg ); } catch ( e ) { }
return Object . freeze ({
type : 'Block' ,
hashOf : msg . hashOf ,
lastMsgHash : msg . lastMsgHash ,
isCheckpoint : !! msg . content . isCheckpoint ,
status : msg . mut . status ,
recvOrder : msg . mut . recvOrder ,
parentCount : pc ,
getParent : function () {
var parentMsg = getParent ( realtime , msg );
if ( parentMsg ) { return wrapMessage ( realtime , parentMsg ); }
},
getChildren : function () {
return ( realtime . messagesByParent [ msg . hashOf ] || []). map ( function ( x ) {
return wrapMessage ( realtime , x );
});
},
2019-02-26 15:48:29 +01:00
getContent : function ( previous ) { return getContentAtState ( realtime , msg , previous ); },
2019-02-19 14:40:38 +01:00
getPatch : function () { return Patch . clone ( msg . content ); },
getInversePatch : function () { return Patch . clone ( inversePatch ( msg . content )); },
equals : function ( block , msgOpt ) {
if ( msgOpt ) { return msg === msgOpt ; }
if ( ! block || typeof ( block ) !== 'object' || block . type !== 'Block' ) { return false ; }
return block . equals ( block , msg );
}
});
};
var mkConfig = function ( config ) {
config = config || {};
if ( config . transformFunction ) {
throw new Error ( "chainpad config transformFunction is nolonger used" );
}
return Object . freeze ({
initialState : config . initialState || '' ,
checkpointInterval : config . checkpointInterval || DEFAULT_CHECKPOINT_INTERVAL ,
avgSyncMilliseconds : config . avgSyncMilliseconds || DEFAULT_AVERAGE_SYNC_MILLISECONDS ,
strictCheckpointValidation : config . strictCheckpointValidation ||
DEFAULT_STRICT_CHECKPOINT_VALIDATION ,
operationSimplify : config . operationSimplify || Operation . simplify ,
logLevel : ( typeof ( config . logLevel ) === 'number' ) ? config . logLevel : 2 ,
noPrune : config . noPrune ,
patchTransformer : config . patchTransformer || TextTransformer ,
userName : config . userName || 'anonymous' ,
validateContent : config . validateContent || function ( x ) { x = x ; return true ; },
diffFunction : config . diffFunction ||
function ( strA , strB /*:string*/ ) {
return Diff . diff ( strA , strB , config . diffBlockSize );
},
});
};
/*::
import type { Operation_Transform_t } from './Operation';
import type { Operation_Simplify_t } from './Operation';
import type { Operation_t } from './Operation';
import type { Patch_t } from './Patch';
import type { Patch_Transform_t } from './Patch';
export type ChainPad_Config_t = {
initialState?: string,
checkpointInterval?: number,
avgSyncMilliseconds?: number,
validateContent?: (string)=>boolean,
strictCheckpointValidation?: boolean,
patchTransformer?: Patch_Transform_t,
operationSimplify?: Operation_Simplify_t,
logLevel?: number,
userName?: string,
noPrune?: boolean,
diffFunction?: (string, string)=>Array<Operation_t>,
diffBlockSize?: number
};
*/
module . exports . create = function ( conf /*:ChainPad_Config_t*/ ) {
var realtime = create ( mkConfig ( conf ));
var out = {
onPatch : function ( handler /*:(Patch_t)=>void*/ ) {
Common . assert ( typeof ( handler ) === 'function' );
realtime . patchHandlers . push ( handler );
},
patch : function ( patch /*:Patch_t|number*/ , x /*:?number*/ , y /*:?string*/ ) {
if ( typeof ( patch ) === 'number' ) {
// Actually they meant to call realtime.change()
if ( typeof ( x ) !== 'number' || typeof ( y ) !== 'string' ) { throw new Error (); }
out . change ( patch , x , y );
return ;
}
doPatch ( realtime , patch );
},
onChange : function ( handler /*:(number, number, string)=>void*/ ) {
Common . assert ( typeof ( handler ) === 'function' );
realtime . changeHandlers . push ( handler );
},
change : function ( offset /*:number*/ , count /*:number*/ , chars /*:string*/ ) {
if ( count === 0 && chars === '' ) { return ; }
doOperation ( realtime , Operation . create ( offset , count , chars ));
},
contentUpdate : function ( newContent /*:string*/ ) {
var ops = realtime . config . diffFunction ( realtime . authDoc , newContent );
var uncommitted = Patch . create ( realtime . uncommitted . parentHash );
Array . prototype . push . apply ( uncommitted . operations , ops );
realtime . uncommitted = uncommitted ;
},
onMessage : function ( handler /*:(string, ()=>void)=>void*/ ) {
Common . assert ( typeof ( handler ) === 'function' );
realtime . messageHandlers . push ( handler );
},
message : function ( message /*:string*/ ) {
handleMessage ( realtime , message , false );
},
/// Control functions
start : function () {
realtime . aborted = false ;
if ( realtime . syncSchedule ) { unschedule ( realtime , realtime . syncSchedule ); }
realtime . pending = null ;
realtime . syncSchedule = schedule ( realtime , function () { sync ( realtime ); });
},
abort : function () {
realtime . aborted = true ;
realtime . schedules . forEach ( function ( s ) { clearTimeout ( s ); });
},
sync : function () {
sync ( realtime );
},
getAuthDoc : function () { return realtime . authDoc ; },
getUserDoc : function () { return Patch . apply ( realtime . uncommitted , realtime . authDoc ); },
getDepthOfState : function ( content /*:string*/ , minDepth /*:?number*/ ) {
return getDepthOfState ( content , minDepth , realtime );
},
onSettle : function ( handler /*:()=>void*/ ) {
Common . assert ( typeof ( handler ) === 'function' );
realtime . onSettle . push ( handler );
},
getAuthBlock : function () {
return wrapMessage ( realtime , realtime . best );
},
getBlockForHash : function ( hash /*:string*/ ) {
Common . assert ( typeof ( hash ) === 'string' );
var msg = realtime . messages [ hash ];
if ( msg ) { return wrapMessage ( realtime , msg ); }
},
getBlockHashes : function () {
return Object . keys ( realtime . messages );
},
getRootBlock : function () {
return wrapMessage ( realtime , realtime . rootMessage );
},
getRejectedBlock : function ( number /*:number*/ ) {
var msg = realtime . rejectedBlocks [ number ];
return msg ? wrapMessage ( realtime , msg ) : undefined ;
},
getLag : function () {
var isPending = !! realtime . pending ;
var lag = realtime . lag ;
if ( realtime . pending ) { lag = + new Date () - realtime . timeOfLastSuccess ; }
return {
pending : isPending ,
lag : lag ,
active : ( ! realtime . aborted && realtime . syncSchedule !== - 2 )
};
},
_ : undefined
};
out . _ = realtime ;
return Object . freeze ( out );
};
Object . freeze ( module . exports );
},
"Operation.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
var Common = require ( './Common' );
var Operation = module . exports ;
/*::
export type Operation_t = {
type: 'Operation',
offset: number,
toRemove: number,
toInsert: string
};
export type Operation_Packed_t = [number, number, string];
export type Operation_Simplify_t = (Operation_t, string, typeof(Operation.simplify))=>?Operation_t;
export type Operation_Transform_t = (string, Operation_t, Operation_t)=>?Operation_t;
*/
var check = Operation . check = function ( op /*:any*/ , docLength_opt /*:?number*/ ) /*:Operation_t*/ {
Common . assert ( op . type === 'Operation' );
if ( ! Common . isUint ( op . offset )) { throw new Error (); }
if ( ! Common . isUint ( op . toRemove )) { throw new Error (); }
if ( typeof ( op . toInsert ) !== 'string' ) { throw new Error (); }
if ( op . toRemove < 1 && op . toInsert . length < 1 ) { throw new Error (); }
Common . assert ( typeof ( docLength_opt ) !== 'number' || op . offset + op . toRemove <= docLength_opt );
return op ;
};
var create = Operation . create = function (
offset /*:?number*/ ,
toRemove /*:?number*/ ,
toInsert /*:?string*/ )
{
var out = {
type : 'Operation' ,
offset : offset || 0 ,
toRemove : toRemove || 0 ,
toInsert : toInsert || '' ,
};
if ( Common . PARANOIA ) { check ( out ); }
return Object . freeze ( out );
};
Operation . toObj = function ( op /*:Operation_t*/ ) {
if ( Common . PARANOIA ) { check ( op ); }
return [ op . offset , op . toRemove , op . toInsert ];
};
// Allow any as input because we assert its type internally..
Operation . fromObj = function ( obj /*:any*/ ) {
Common . assert ( Array . isArray ( obj ) && obj . length === 3 );
return create ( obj [ 0 ], obj [ 1 ], obj [ 2 ]);
};
/**
* @param op the operation to apply.
* @param doc the content to apply the operation on
*/
var apply = Operation . apply = function ( op /*:Operation_t*/ , doc /*:string*/ )
{
if ( Common . PARANOIA ) {
Common . assert ( typeof ( doc ) === 'string' );
check ( op , doc . length );
}
return doc . substring ( 0 , op . offset ) + op . toInsert + doc . substring ( op . offset + op . toRemove );
};
Operation . applyMulti = function ( ops /*:Array<Operation_t>*/ , doc /*:string*/ )
{
for ( var i = ops . length - 1 ; i >= 0 ; i -- ) { doc = apply ( ops [ i ], doc ); }
return doc ;
};
var invert = Operation . invert = function ( op /*:Operation_t*/ , doc /*:string*/ ) {
if ( Common . PARANOIA ) {
check ( op );
Common . assert ( typeof ( doc ) === 'string' );
Common . assert ( op . offset + op . toRemove <= doc . length );
}
return create (
op . offset ,
op . toInsert . length ,
doc . substring ( op . offset , op . offset + op . toRemove )
);
};
// see http://unicode.org/faq/utf_bom.html#utf16-7
var surrogatePattern = /[\uD800-\uDBFF]|[\uDC00-\uDFFF]/ ;
var hasSurrogate = Operation . hasSurrogate = function ( str /*:string*/ ) {
return surrogatePattern . test ( str );
};
/**
* ATTENTION: This function is not just a neat way to make patches smaller, it's
* actually part of the ChainPad consensus rules, so if you have a clever
* idea to make it a bit faster, it is going to cause ChainPad to reject
* old patches, which means when you go to load the history of a pad, you're
* sunk.
* tl;dr can't touch this
*/
Operation . simplify = function ( op /*:Operation_t*/ , doc /*:string*/ ) {
if ( Common . PARANOIA ) {
check ( op );
Common . assert ( typeof ( doc ) === 'string' );
Common . assert ( op . offset + op . toRemove <= doc . length );
}
var rop = invert ( op , doc );
var minLen = Math . min ( op . toInsert . length , rop . toInsert . length );
var i = 0 ;
while ( i < minLen && rop . toInsert [ i ] === op . toInsert [ i ]) {
if ( hasSurrogate ( rop . toInsert [ i ]) || hasSurrogate ( op . toInsert [ i ])) {
if ( op . toInsert [ i + 1 ] === rop . toInsert [ i + 1 ]) {
i ++ ;
} else {
break ;
}
}
i ++ ;
}
var opOffset = op . offset + i ;
var opToRemove = op . toRemove - i ;
var opToInsert = op . toInsert . substring ( i );
var ropToInsert = rop . toInsert . substring ( i );
if ( ropToInsert . length === opToInsert . length ) {
for ( i = ropToInsert . length - 1 ; i >= 0 && ropToInsert [ i ] === opToInsert [ i ]; i -- ) ;
opToInsert = opToInsert . substring ( 0 , i + 1 );
opToRemove = i + 1 ;
}
if ( opToRemove === 0 && opToInsert . length === 0 ) { return null ; }
return create ( opOffset , opToRemove , opToInsert );
};
Operation . equals = function ( opA /*:Operation_t*/ , opB /*:Operation_t*/ ) {
return ( opA . toRemove === opB . toRemove
&& opA . toInsert === opB . toInsert
&& opA . offset === opB . offset );
};
Operation . lengthChange = function ( op /*:Operation_t*/ )
{
if ( Common . PARANOIA ) { check ( op ); }
return op . toInsert . length - op . toRemove ;
};
/*
* @return the merged operation OR null if the result of the merger is a noop.
*/
Operation . merge = function ( oldOpOrig /*:Operation_t*/ , newOpOrig /*:Operation_t*/ ) {
if ( Common . PARANOIA ) {
check ( newOpOrig );
check ( oldOpOrig );
}
var oldOp_offset = oldOpOrig . offset ;
var oldOp_toRemove = oldOpOrig . toRemove ;
var oldOp_toInsert = oldOpOrig . toInsert ;
var newOp_offset = newOpOrig . offset ;
var newOp_toRemove = newOpOrig . toRemove ;
var newOp_toInsert = newOpOrig . toInsert ;
var offsetDiff = newOp_offset - oldOp_offset ;
if ( newOp_toRemove > 0 ) {
var origOldInsert = oldOp_toInsert ;
oldOp_toInsert = (
oldOp_toInsert . substring ( 0 , offsetDiff )
+ oldOp_toInsert . substring ( offsetDiff + newOp_toRemove )
);
newOp_toRemove -= ( origOldInsert . length - oldOp_toInsert . length );
if ( newOp_toRemove < 0 ) { newOp_toRemove = 0 ; }
oldOp_toRemove += newOp_toRemove ;
newOp_toRemove = 0 ;
}
if ( offsetDiff < 0 ) {
oldOp_offset += offsetDiff ;
oldOp_toInsert = newOp_toInsert + oldOp_toInsert ;
} else if ( oldOp_toInsert . length === offsetDiff ) {
oldOp_toInsert = oldOp_toInsert + newOp_toInsert ;
} else if ( oldOp_toInsert . length > offsetDiff ) {
oldOp_toInsert = (
oldOp_toInsert . substring ( 0 , offsetDiff )
+ newOp_toInsert
+ oldOp_toInsert . substring ( offsetDiff )
);
} else {
throw new Error ( "should never happen\n" +
JSON . stringify ([ oldOpOrig , newOpOrig ], null , ' ' ));
}
if ( oldOp_toInsert === '' && oldOp_toRemove === 0 ) { return null ; }
return create ( oldOp_offset , oldOp_toRemove , oldOp_toInsert );
};
/**
* If the new operation deletes what the old op inserted or inserts content in the middle of
* the old op's content or if they abbut one another, they should be merged.
*/
Operation . shouldMerge = function ( oldOp /*:Operation_t*/ , newOp /*:Operation_t*/ )
{
if ( Common . PARANOIA ) {
check ( oldOp );
check ( newOp );
}
if ( newOp . offset < oldOp . offset ) {
return ( oldOp . offset <= ( newOp . offset + newOp . toRemove ));
} else {
return ( newOp . offset <= ( oldOp . offset + oldOp . toInsert . length ));
}
};
/**
* Rebase newOp against oldOp.
*
* @param oldOp the eariler operation to have happened.
* @param newOp the later operation to have happened (in time).
* @return either the untouched newOp if it need not be rebased,
* the rebased clone of newOp if it needs rebasing, or
* null if newOp and oldOp must be merged.
*/
Operation . rebase = function ( oldOp /*:Operation_t*/ , newOp /*:Operation_t*/ ) {
if ( Common . PARANOIA ) {
check ( oldOp );
check ( newOp );
}
if ( newOp . offset < oldOp . offset ) { return newOp ; }
return create (
newOp . offset + oldOp . toRemove - oldOp . toInsert . length ,
newOp . toRemove ,
newOp . toInsert
);
};
/** Used for testing. */
Operation . random = function ( docLength /*:number*/ ) {
Common . assert ( Common . isUint ( docLength ));
var offset = Math . floor ( Math . random () * 100000000 % docLength ) || 0 ;
var toRemove = Math . floor ( Math . random () * 100000000 % ( docLength - offset )) || 0 ;
var toInsert = '' ;
do {
toInsert = Common . randomASCII ( Math . floor ( Math . random () * 20 ));
} while ( toRemove === 0 && toInsert === '' );
return create ( offset , toRemove , toInsert );
};
Object . freeze ( module . exports );
},
"sha256/hash.js" : function ( module , exports , require ){
var Utils = require ( './utils.js' );
function hash_reset () {
this . result = null ;
this . pos = 0 ;
this . len = 0 ;
this . asm . reset ();
return this ;
}
function hash_process ( data ) {
if ( this . result !== null )
throw new IllegalStateError ( "state must be reset before processing new data" );
if ( Utils . is_string ( data ) )
data = Utils . string_to_bytes ( data );
if ( Utils . is_buffer ( data ) )
data = new Uint8Array ( data );
if ( ! Utils . is_bytes ( data ) )
throw new TypeError ( "data isn't of expected type" );
var asm = this . asm ,
heap = this . heap ,
hpos = this . pos ,
hlen = this . len ,
dpos = 0 ,
dlen = data . length ,
wlen = 0 ;
while ( dlen > 0 ) {
wlen = Utils . _heap_write ( heap , hpos + hlen , data , dpos , dlen );
hlen += wlen ;
dpos += wlen ;
dlen -= wlen ;
wlen = asm . process ( hpos , hlen );
hpos += wlen ;
hlen -= wlen ;
if ( ! hlen ) hpos = 0 ;
}
this . pos = hpos ;
this . len = hlen ;
return this ;
}
function hash_finish () {
if ( this . result !== null )
throw new IllegalStateError ( "state must be reset before processing new data" );
this . asm . finish ( this . pos , this . len , 0 );
this . result = new Uint8Array ( this . HASH_SIZE );
this . result . set ( this . heap . subarray ( 0 , this . HASH_SIZE ) );
this . pos = 0 ;
this . len = 0 ;
return this ;
}
module . exports . hash_reset = hash_reset ;
module . exports . hash_process = hash_process ;
module . exports . hash_finish = hash_finish ;
},
"sha256/utils.js" : function ( module , exports , require ){
//var FloatArray = global.Float64Array || global.Float32Array; // make PhantomJS happy
var string_to_bytes = module . exports . string_to_bytes = function ( str , utf8 ) {
utf8 = !! utf8 ;
var len = str . length ,
bytes = new Uint8Array ( utf8 ? 4 * len : len );
for ( var i = 0 , j = 0 ; i < len ; i ++ ) {
var c = str . charCodeAt ( i );
if ( utf8 && 0xd800 <= c && c <= 0xdbff ) {
if ( ++ i >= len ) throw new Error ( "Malformed string, low surrogate expected at position " + i );
c = ( ( c ^ 0xd800 ) << 10 ) | 0x10000 | ( str . charCodeAt ( i ) ^ 0xdc00 );
}
else if ( ! utf8 && c >>> 8 ) {
throw new Error ( "Wide characters are not allowed." );
}
if ( ! utf8 || c <= 0x7f ) {
bytes [ j ++ ] = c ;
}
else if ( c <= 0x7ff ) {
bytes [ j ++ ] = 0xc0 | ( c >> 6 );
bytes [ j ++ ] = 0x80 | ( c & 0x3f );
}
else if ( c <= 0xffff ) {
bytes [ j ++ ] = 0xe0 | ( c >> 12 );
bytes [ j ++ ] = 0x80 | ( c >> 6 & 0x3f );
bytes [ j ++ ] = 0x80 | ( c & 0x3f );
}
else {
bytes [ j ++ ] = 0xf0 | ( c >> 18 );
bytes [ j ++ ] = 0x80 | ( c >> 12 & 0x3f );
bytes [ j ++ ] = 0x80 | ( c >> 6 & 0x3f );
bytes [ j ++ ] = 0x80 | ( c & 0x3f );
}
}
return bytes . subarray ( 0 , j );
};
var hex_to_bytes = module . exports . hex_to_bytes = function ( str ) {
var len = str . length ;
if ( len & 1 ) {
str = '0' + str ;
len ++ ;
}
var bytes = new Uint8Array ( len >> 1 );
for ( var i = 0 ; i < len ; i += 2 ) {
bytes [ i >> 1 ] = parseInt ( str . substr ( i , 2 ), 16 );
}
return bytes ;
};
var base64_to_bytes = module . exports . base64_to_bytes = function ( str ) {
return string_to_bytes ( atob ( str ) );
};
var bytes_to_string = module . exports . bytes_to_string = function ( bytes , utf8 ) {
utf8 = !! utf8 ;
var len = bytes . length ,
chars = new Array ( len );
for ( var i = 0 , j = 0 ; i < len ; i ++ ) {
var b = bytes [ i ];
if ( ! utf8 || b < 128 ) {
chars [ j ++ ] = b ;
}
else if ( b >= 192 && b < 224 && i + 1 < len ) {
chars [ j ++ ] = ( ( b & 0x1f ) << 6 ) | ( bytes [ ++ i ] & 0x3f );
}
else if ( b >= 224 && b < 240 && i + 2 < len ) {
chars [ j ++ ] = ( ( b & 0xf ) << 12 ) | ( ( bytes [ ++ i ] & 0x3f ) << 6 ) | ( bytes [ ++ i ] & 0x3f );
}
else if ( b >= 240 && b < 248 && i + 3 < len ) {
var c = ( ( b & 7 ) << 18 ) | ( ( bytes [ ++ i ] & 0x3f ) << 12 ) | ( ( bytes [ ++ i ] & 0x3f ) << 6 ) | ( bytes [ ++ i ] & 0x3f );
if ( c <= 0xffff ) {
chars [ j ++ ] = c ;
}
else {
c ^= 0x10000 ;
chars [ j ++ ] = 0xd800 | ( c >> 10 );
chars [ j ++ ] = 0xdc00 | ( c & 0x3ff );
}
}
else {
throw new Error ( "Malformed UTF8 character at byte offset " + i );
}
}
var str = '' ,
bs = 16384 ;
for ( var _i = 0 ; _i < j ; _i += bs ) {
str += String . fromCharCode . apply ( String , chars . slice ( _i , _i + bs <= j ? _i + bs : j ) );
}
return str ;
};
var bytes_to_hex = module . exports . bytes_to_hex = function ( arr ) {
var str = '' ;
for ( var i = 0 ; i < arr . length ; i ++ ) {
var h = ( arr [ i ] & 0xff ). toString ( 16 );
if ( h . length < 2 ) str += '0' ;
str += h ;
}
return str ;
};
var bytes_to_base64 = module . exports . bytes_to_base64 = function ( arr ) {
return btoa ( bytes_to_string ( arr ) );
};
var pow2_ceil = module . exports . pow2_ceil = function ( a ) {
a -= 1 ;
a |= a >>> 1 ;
a |= a >>> 2 ;
a |= a >>> 4 ;
a |= a >>> 8 ;
a |= a >>> 16 ;
a += 1 ;
return a ;
};
var is_number = module . exports . is_number = function ( a ) {
return ( typeof a === 'number' );
};
var is_string = module . exports . is_string = function ( a ) {
return ( typeof a === 'string' );
};
var is_buffer = module . exports . is_buffer = function ( a ) {
return ( a instanceof ArrayBuffer );
};
var is_bytes = module . exports . is_bytes = function ( a ) {
return ( a instanceof Uint8Array );
};
var is_typed_array = module . exports . is_typed_array = function ( a ) {
return ( a instanceof Int8Array ) || ( a instanceof Uint8Array )
|| ( a instanceof Int16Array ) || ( a instanceof Uint16Array )
|| ( a instanceof Int32Array ) || ( a instanceof Uint32Array )
|| ( a instanceof Float32Array )
|| ( a instanceof Float64Array );
};
var _heap_init = module . exports . _heap_init = function ( constructor , options ) {
var heap = options . heap ,
size = heap ? heap . byteLength : options . heapSize || 65536 ;
if ( size & 0xfff || size <= 0 )
throw new Error ( "heap size must be a positive integer and a multiple of 4096" );
heap = heap || new constructor ( new ArrayBuffer ( size ) );
return heap ;
};
var _heap_write = module . exports . _heap_write = function ( heap , hpos , data , dpos , dlen ) {
var hlen = heap . length - hpos ,
wlen = ( hlen < dlen ) ? hlen : dlen ;
heap . set ( data . subarray ( dpos , dpos + wlen ), hpos );
return wlen ;
};
},
"sha256/sha256.js" : function ( module , exports , require ){
var Utils = require ( './utils.js' );
var Hash = require ( './hash.js' );
var Asm = require ( './sha256.asm.js' );
var _sha256_block_size = 64 ,
_sha256_hash_size = 32 ;
function sha256_constructor ( options ) {
options = options || {};
this . heap = Utils . _heap_init ( Uint8Array , options );
this . asm = options . asm || Asm . sha256_asm ( { Uint8Array : Uint8Array }, null , this . heap . buffer );
this . BLOCK_SIZE = _sha256_block_size ;
this . HASH_SIZE = _sha256_hash_size ;
this . reset ();
}
sha256_constructor . BLOCK_SIZE = _sha256_block_size ;
sha256_constructor . HASH_SIZE = _sha256_hash_size ;
var sha256_prototype = sha256_constructor . prototype ;
sha256_prototype . reset = Hash . hash_reset ;
sha256_prototype . process = Hash . hash_process ;
sha256_prototype . finish = Hash . hash_finish ;
var sha256_instance = null ;
function get_sha256_instance () {
if ( sha256_instance === null ) sha256_instance = new sha256_constructor ( { heapSize : 0x100000 } );
return sha256_instance ;
}
module . exports . get_sha256_instance = get_sha256_instance ;
module . exports . sha256_constructor = sha256_constructor ;
},
"sha256/exports.js" : function ( module , exports , require ){
var Sha256 = require ( './sha256.js' );
var Utils = require ( './utils.js' );
/**
* SHA256 exports
*/
function sha256_bytes ( data ) {
if ( data === undefined ) throw new SyntaxError ( "data required" );
return Sha256 . get_sha256_instance (). reset (). process ( data ). finish (). result ;
}
function sha256_hex ( data ) {
var result = sha256_bytes ( data );
return Utils . bytes_to_hex ( result );
}
function sha256_base64 ( data ) {
var result = sha256_bytes ( data );
return Utils . bytes_to_base64 ( result );
}
Sha256 . sha256_constructor . bytes = sha256_bytes ;
Sha256 . sha256_constructor . hex = sha256_hex ;
Sha256 . sha256_constructor . base64 = sha256_base64 ;
//exports.SHA256 = sha256_constructor;
module . exports = Sha256 . sha256_constructor ;
},
"sha256/sha256.asm.js" : function ( module , exports , require ){
module . exports . sha256_asm = function sha256_asm ( stdlib , foreign , buffer ) {
"use asm" ;
// SHA256 state
var H0 = 0 , H1 = 0 , H2 = 0 , H3 = 0 , H4 = 0 , H5 = 0 , H6 = 0 , H7 = 0 ,
TOTAL0 = 0 , TOTAL1 = 0 ;
// HMAC state
var I0 = 0 , I1 = 0 , I2 = 0 , I3 = 0 , I4 = 0 , I5 = 0 , I6 = 0 , I7 = 0 ,
O0 = 0 , O1 = 0 , O2 = 0 , O3 = 0 , O4 = 0 , O5 = 0 , O6 = 0 , O7 = 0 ;
// I/O buffer
var HEAP = new stdlib . Uint8Array ( buffer );
function _core ( w0 , w1 , w2 , w3 , w4 , w5 , w6 , w7 , w8 , w9 , w10 , w11 , w12 , w13 , w14 , w15 ) {
w0 = w0 | 0 ;
w1 = w1 | 0 ;
w2 = w2 | 0 ;
w3 = w3 | 0 ;
w4 = w4 | 0 ;
w5 = w5 | 0 ;
w6 = w6 | 0 ;
w7 = w7 | 0 ;
w8 = w8 | 0 ;
w9 = w9 | 0 ;
w10 = w10 | 0 ;
w11 = w11 | 0 ;
w12 = w12 | 0 ;
w13 = w13 | 0 ;
w14 = w14 | 0 ;
w15 = w15 | 0 ;
var a = 0 , b = 0 , c = 0 , d = 0 , e = 0 , f = 0 , g = 0 , h = 0 ,
t = 0 ;
a = H0 ;
b = H1 ;
c = H2 ;
d = H3 ;
e = H4 ;
f = H5 ;
g = H6 ;
h = H7 ;
// 0
t = ( w0 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x428a2f98 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 1
t = ( w1 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x71374491 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 2
t = ( w2 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xb5c0fbcf ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 3
t = ( w3 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xe9b5dba5 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 4
t = ( w4 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x3956c25b ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 5
t = ( w5 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x59f111f1 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 6
t = ( w6 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x923f82a4 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 7
t = ( w7 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xab1c5ed5 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 8
t = ( w8 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xd807aa98 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 9
t = ( w9 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x12835b01 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 10
t = ( w10 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x243185be ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 11
t = ( w11 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x550c7dc3 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 12
t = ( w12 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x72be5d74 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 13
t = ( w13 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x80deb1fe ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 14
t = ( w14 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x9bdc06a7 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 15
t = ( w15 + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xc19bf174 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 16
w0 = t = ( ( w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14 ) + ( w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13 ) + w0 + w9 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xe49b69c1 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 17
w1 = t = ( ( w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14 ) + ( w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13 ) + w1 + w10 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xefbe4786 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 18
w2 = t = ( ( w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14 ) + ( w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13 ) + w2 + w11 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x0fc19dc6 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 19
w3 = t = ( ( w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14 ) + ( w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13 ) + w3 + w12 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x240ca1cc ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 20
w4 = t = ( ( w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14 ) + ( w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13 ) + w4 + w13 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x2de92c6f ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 21
w5 = t = ( ( w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14 ) + ( w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13 ) + w5 + w14 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x4a7484aa ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 22
w6 = t = ( ( w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14 ) + ( w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13 ) + w6 + w15 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x5cb0a9dc ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 23
w7 = t = ( ( w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14 ) + ( w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13 ) + w7 + w0 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x76f988da ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 24
w8 = t = ( ( w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14 ) + ( w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13 ) + w8 + w1 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x983e5152 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 25
w9 = t = ( ( w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14 ) + ( w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13 ) + w9 + w2 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xa831c66d ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 26
w10 = t = ( ( w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14 ) + ( w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13 ) + w10 + w3 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xb00327c8 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 27
w11 = t = ( ( w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14 ) + ( w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13 ) + w11 + w4 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xbf597fc7 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 28
w12 = t = ( ( w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14 ) + ( w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13 ) + w12 + w5 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xc6e00bf3 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 29
w13 = t = ( ( w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14 ) + ( w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13 ) + w13 + w6 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xd5a79147 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 30
w14 = t = ( ( w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14 ) + ( w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13 ) + w14 + w7 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x06ca6351 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 31
w15 = t = ( ( w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14 ) + ( w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13 ) + w15 + w8 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x14292967 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 32
w0 = t = ( ( w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14 ) + ( w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13 ) + w0 + w9 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x27b70a85 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 33
w1 = t = ( ( w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14 ) + ( w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13 ) + w1 + w10 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x2e1b2138 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 34
w2 = t = ( ( w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14 ) + ( w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13 ) + w2 + w11 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x4d2c6dfc ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 35
w3 = t = ( ( w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14 ) + ( w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13 ) + w3 + w12 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x53380d13 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 36
w4 = t = ( ( w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14 ) + ( w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13 ) + w4 + w13 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x650a7354 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 37
w5 = t = ( ( w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14 ) + ( w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13 ) + w5 + w14 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x766a0abb ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 38
w6 = t = ( ( w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14 ) + ( w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13 ) + w6 + w15 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x81c2c92e ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 39
w7 = t = ( ( w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14 ) + ( w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13 ) + w7 + w0 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x92722c85 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 40
w8 = t = ( ( w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14 ) + ( w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13 ) + w8 + w1 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xa2bfe8a1 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 41
w9 = t = ( ( w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14 ) + ( w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13 ) + w9 + w2 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xa81a664b ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 42
w10 = t = ( ( w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14 ) + ( w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13 ) + w10 + w3 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xc24b8b70 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 43
w11 = t = ( ( w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14 ) + ( w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13 ) + w11 + w4 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xc76c51a3 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 44
w12 = t = ( ( w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14 ) + ( w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13 ) + w12 + w5 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xd192e819 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 45
w13 = t = ( ( w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14 ) + ( w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13 ) + w13 + w6 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xd6990624 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 46
w14 = t = ( ( w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14 ) + ( w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13 ) + w14 + w7 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xf40e3585 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 47
w15 = t = ( ( w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14 ) + ( w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13 ) + w15 + w8 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x106aa070 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 48
w0 = t = ( ( w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14 ) + ( w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13 ) + w0 + w9 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x19a4c116 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 49
w1 = t = ( ( w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14 ) + ( w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13 ) + w1 + w10 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x1e376c08 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 50
w2 = t = ( ( w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14 ) + ( w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13 ) + w2 + w11 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x2748774c ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 51
w3 = t = ( ( w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14 ) + ( w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13 ) + w3 + w12 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x34b0bcb5 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 52
w4 = t = ( ( w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14 ) + ( w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13 ) + w4 + w13 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x391c0cb3 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 53
w5 = t = ( ( w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14 ) + ( w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13 ) + w5 + w14 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x4ed8aa4a ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 54
w6 = t = ( ( w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14 ) + ( w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13 ) + w6 + w15 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x5b9cca4f ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 55
w7 = t = ( ( w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14 ) + ( w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13 ) + w7 + w0 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x682e6ff3 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 56
w8 = t = ( ( w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14 ) + ( w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13 ) + w8 + w1 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x748f82ee ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 57
w9 = t = ( ( w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14 ) + ( w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13 ) + w9 + w2 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x78a5636f ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 58
w10 = t = ( ( w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14 ) + ( w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13 ) + w10 + w3 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x84c87814 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 59
w11 = t = ( ( w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14 ) + ( w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13 ) + w11 + w4 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x8cc70208 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 60
w12 = t = ( ( w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14 ) + ( w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13 ) + w12 + w5 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0x90befffa ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 61
w13 = t = ( ( w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14 ) + ( w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13 ) + w13 + w6 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xa4506ceb ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 62
w14 = t = ( ( w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14 ) + ( w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13 ) + w14 + w7 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xbef9a3f7 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
// 63
w15 = t = ( ( w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14 ) + ( w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13 ) + w15 + w8 ) | 0 ;
t = ( t + h + ( e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7 ) + ( g ^ e & ( f ^ g ) ) + 0xc67178f2 ) | 0 ;
h = g ; g = f ; f = e ; e = ( d + t ) | 0 ; d = c ; c = b ; b = a ;
a = ( t + ( ( b & c ) ^ ( d & ( b ^ c ) ) ) + ( b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10 ) ) | 0 ;
H0 = ( H0 + a ) | 0 ;
H1 = ( H1 + b ) | 0 ;
H2 = ( H2 + c ) | 0 ;
H3 = ( H3 + d ) | 0 ;
H4 = ( H4 + e ) | 0 ;
H5 = ( H5 + f ) | 0 ;
H6 = ( H6 + g ) | 0 ;
H7 = ( H7 + h ) | 0 ;
}
function _core_heap ( offset ) {
offset = offset | 0 ;
_core (
HEAP [ offset | 0 ] << 24 | HEAP [ offset | 1 ] << 16 | HEAP [ offset | 2 ] << 8 | HEAP [ offset | 3 ],
HEAP [ offset | 4 ] << 24 | HEAP [ offset | 5 ] << 16 | HEAP [ offset | 6 ] << 8 | HEAP [ offset | 7 ],
HEAP [ offset | 8 ] << 24 | HEAP [ offset | 9 ] << 16 | HEAP [ offset | 10 ] << 8 | HEAP [ offset | 11 ],
HEAP [ offset | 12 ] << 24 | HEAP [ offset | 13 ] << 16 | HEAP [ offset | 14 ] << 8 | HEAP [ offset | 15 ],
HEAP [ offset | 16 ] << 24 | HEAP [ offset | 17 ] << 16 | HEAP [ offset | 18 ] << 8 | HEAP [ offset | 19 ],
HEAP [ offset | 20 ] << 24 | HEAP [ offset | 21 ] << 16 | HEAP [ offset | 22 ] << 8 | HEAP [ offset | 23 ],
HEAP [ offset | 24 ] << 24 | HEAP [ offset | 25 ] << 16 | HEAP [ offset | 26 ] << 8 | HEAP [ offset | 27 ],
HEAP [ offset | 28 ] << 24 | HEAP [ offset | 29 ] << 16 | HEAP [ offset | 30 ] << 8 | HEAP [ offset | 31 ],
HEAP [ offset | 32 ] << 24 | HEAP [ offset | 33 ] << 16 | HEAP [ offset | 34 ] << 8 | HEAP [ offset | 35 ],
HEAP [ offset | 36 ] << 24 | HEAP [ offset | 37 ] << 16 | HEAP [ offset | 38 ] << 8 | HEAP [ offset | 39 ],
HEAP [ offset | 40 ] << 24 | HEAP [ offset | 41 ] << 16 | HEAP [ offset | 42 ] << 8 | HEAP [ offset | 43 ],
HEAP [ offset | 44 ] << 24 | HEAP [ offset | 45 ] << 16 | HEAP [ offset | 46 ] << 8 | HEAP [ offset | 47 ],
HEAP [ offset | 48 ] << 24 | HEAP [ offset | 49 ] << 16 | HEAP [ offset | 50 ] << 8 | HEAP [ offset | 51 ],
HEAP [ offset | 52 ] << 24 | HEAP [ offset | 53 ] << 16 | HEAP [ offset | 54 ] << 8 | HEAP [ offset | 55 ],
HEAP [ offset | 56 ] << 24 | HEAP [ offset | 57 ] << 16 | HEAP [ offset | 58 ] << 8 | HEAP [ offset | 59 ],
HEAP [ offset | 60 ] << 24 | HEAP [ offset | 61 ] << 16 | HEAP [ offset | 62 ] << 8 | HEAP [ offset | 63 ]
);
}
// offset — multiple of 32
function _state_to_heap ( output ) {
output = output | 0 ;
HEAP [ output | 0 ] = H0 >>> 24 ;
HEAP [ output | 1 ] = H0 >>> 16 & 255 ;
HEAP [ output | 2 ] = H0 >>> 8 & 255 ;
HEAP [ output | 3 ] = H0 & 255 ;
HEAP [ output | 4 ] = H1 >>> 24 ;
HEAP [ output | 5 ] = H1 >>> 16 & 255 ;
HEAP [ output | 6 ] = H1 >>> 8 & 255 ;
HEAP [ output | 7 ] = H1 & 255 ;
HEAP [ output | 8 ] = H2 >>> 24 ;
HEAP [ output | 9 ] = H2 >>> 16 & 255 ;
HEAP [ output | 10 ] = H2 >>> 8 & 255 ;
HEAP [ output | 11 ] = H2 & 255 ;
HEAP [ output | 12 ] = H3 >>> 24 ;
HEAP [ output | 13 ] = H3 >>> 16 & 255 ;
HEAP [ output | 14 ] = H3 >>> 8 & 255 ;
HEAP [ output | 15 ] = H3 & 255 ;
HEAP [ output | 16 ] = H4 >>> 24 ;
HEAP [ output | 17 ] = H4 >>> 16 & 255 ;
HEAP [ output | 18 ] = H4 >>> 8 & 255 ;
HEAP [ output | 19 ] = H4 & 255 ;
HEAP [ output | 20 ] = H5 >>> 24 ;
HEAP [ output | 21 ] = H5 >>> 16 & 255 ;
HEAP [ output | 22 ] = H5 >>> 8 & 255 ;
HEAP [ output | 23 ] = H5 & 255 ;
HEAP [ output | 24 ] = H6 >>> 24 ;
HEAP [ output | 25 ] = H6 >>> 16 & 255 ;
HEAP [ output | 26 ] = H6 >>> 8 & 255 ;
HEAP [ output | 27 ] = H6 & 255 ;
HEAP [ output | 28 ] = H7 >>> 24 ;
HEAP [ output | 29 ] = H7 >>> 16 & 255 ;
HEAP [ output | 30 ] = H7 >>> 8 & 255 ;
HEAP [ output | 31 ] = H7 & 255 ;
}
function reset () {
H0 = 0x6a09e667 ;
H1 = 0xbb67ae85 ;
H2 = 0x3c6ef372 ;
H3 = 0xa54ff53a ;
H4 = 0x510e527f ;
H5 = 0x9b05688c ;
H6 = 0x1f83d9ab ;
H7 = 0x5be0cd19 ;
TOTAL0 = TOTAL1 = 0 ;
}
function init ( h0 , h1 , h2 , h3 , h4 , h5 , h6 , h7 , total0 , total1 ) {
h0 = h0 | 0 ;
h1 = h1 | 0 ;
h2 = h2 | 0 ;
h3 = h3 | 0 ;
h4 = h4 | 0 ;
h5 = h5 | 0 ;
h6 = h6 | 0 ;
h7 = h7 | 0 ;
total0 = total0 | 0 ;
total1 = total1 | 0 ;
H0 = h0 ;
H1 = h1 ;
H2 = h2 ;
H3 = h3 ;
H4 = h4 ;
H5 = h5 ;
H6 = h6 ;
H7 = h7 ;
TOTAL0 = total0 ;
TOTAL1 = total1 ;
}
// offset — multiple of 64
function process ( offset , length ) {
offset = offset | 0 ;
length = length | 0 ;
var hashed = 0 ;
if ( offset & 63 )
return - 1 ;
while ( ( length | 0 ) >= 64 ) {
_core_heap ( offset );
offset = ( offset + 64 ) | 0 ;
length = ( length - 64 ) | 0 ;
hashed = ( hashed + 64 ) | 0 ;
}
TOTAL0 = ( TOTAL0 + hashed ) | 0 ;
if ( TOTAL0 >>> 0 < hashed >>> 0 ) TOTAL1 = ( TOTAL1 + 1 ) | 0 ;
return hashed | 0 ;
}
// offset — multiple of 64
// output — multiple of 32
function finish ( offset , length , output ) {
offset = offset | 0 ;
length = length | 0 ;
output = output | 0 ;
var hashed = 0 ,
i = 0 ;
if ( offset & 63 )
return - 1 ;
if ( ~ output )
if ( output & 31 )
return - 1 ;
if ( ( length | 0 ) >= 64 ) {
hashed = process ( offset , length ) | 0 ;
if ( ( hashed | 0 ) == - 1 )
return - 1 ;
offset = ( offset + hashed ) | 0 ;
length = ( length - hashed ) | 0 ;
}
hashed = ( hashed + length ) | 0 ;
TOTAL0 = ( TOTAL0 + length ) | 0 ;
if ( TOTAL0 >>> 0 < length >>> 0 ) TOTAL1 = ( TOTAL1 + 1 ) | 0 ;
HEAP [ offset | length ] = 0x80 ;
if ( ( length | 0 ) >= 56 ) {
for ( i = ( length + 1 ) | 0 ; ( i | 0 ) < 64 ; i = ( i + 1 ) | 0 )
HEAP [ offset | i ] = 0x00 ;
_core_heap ( offset );
length = 0 ;
HEAP [ offset | 0 ] = 0 ;
}
for ( i = ( length + 1 ) | 0 ; ( i | 0 ) < 59 ; i = ( i + 1 ) | 0 )
HEAP [ offset | i ] = 0 ;
HEAP [ offset | 56 ] = TOTAL1 >>> 21 & 255 ;
HEAP [ offset | 57 ] = TOTAL1 >>> 13 & 255 ;
HEAP [ offset | 58 ] = TOTAL1 >>> 5 & 255 ;
HEAP [ offset | 59 ] = TOTAL1 << 3 & 255 | TOTAL0 >>> 29 ;
HEAP [ offset | 60 ] = TOTAL0 >>> 21 & 255 ;
HEAP [ offset | 61 ] = TOTAL0 >>> 13 & 255 ;
HEAP [ offset | 62 ] = TOTAL0 >>> 5 & 255 ;
HEAP [ offset | 63 ] = TOTAL0 << 3 & 255 ;
_core_heap ( offset );
if ( ~ output )
_state_to_heap ( output );
return hashed | 0 ;
}
function hmac_reset () {
H0 = I0 ;
H1 = I1 ;
H2 = I2 ;
H3 = I3 ;
H4 = I4 ;
H5 = I5 ;
H6 = I6 ;
H7 = I7 ;
TOTAL0 = 64 ;
TOTAL1 = 0 ;
}
function _hmac_opad () {
H0 = O0 ;
H1 = O1 ;
H2 = O2 ;
H3 = O3 ;
H4 = O4 ;
H5 = O5 ;
H6 = O6 ;
H7 = O7 ;
TOTAL0 = 64 ;
TOTAL1 = 0 ;
}
function hmac_init ( p0 , p1 , p2 , p3 , p4 , p5 , p6 , p7 , p8 , p9 , p10 , p11 , p12 , p13 , p14 , p15 ) {
p0 = p0 | 0 ;
p1 = p1 | 0 ;
p2 = p2 | 0 ;
p3 = p3 | 0 ;
p4 = p4 | 0 ;
p5 = p5 | 0 ;
p6 = p6 | 0 ;
p7 = p7 | 0 ;
p8 = p8 | 0 ;
p9 = p9 | 0 ;
p10 = p10 | 0 ;
p11 = p11 | 0 ;
p12 = p12 | 0 ;
p13 = p13 | 0 ;
p14 = p14 | 0 ;
p15 = p15 | 0 ;
// opad
reset ();
_core (
p0 ^ 0x5c5c5c5c ,
p1 ^ 0x5c5c5c5c ,
p2 ^ 0x5c5c5c5c ,
p3 ^ 0x5c5c5c5c ,
p4 ^ 0x5c5c5c5c ,
p5 ^ 0x5c5c5c5c ,
p6 ^ 0x5c5c5c5c ,
p7 ^ 0x5c5c5c5c ,
p8 ^ 0x5c5c5c5c ,
p9 ^ 0x5c5c5c5c ,
p10 ^ 0x5c5c5c5c ,
p11 ^ 0x5c5c5c5c ,
p12 ^ 0x5c5c5c5c ,
p13 ^ 0x5c5c5c5c ,
p14 ^ 0x5c5c5c5c ,
p15 ^ 0x5c5c5c5c
);
O0 = H0 ;
O1 = H1 ;
O2 = H2 ;
O3 = H3 ;
O4 = H4 ;
O5 = H5 ;
O6 = H6 ;
O7 = H7 ;
// ipad
reset ();
_core (
p0 ^ 0x36363636 ,
p1 ^ 0x36363636 ,
p2 ^ 0x36363636 ,
p3 ^ 0x36363636 ,
p4 ^ 0x36363636 ,
p5 ^ 0x36363636 ,
p6 ^ 0x36363636 ,
p7 ^ 0x36363636 ,
p8 ^ 0x36363636 ,
p9 ^ 0x36363636 ,
p10 ^ 0x36363636 ,
p11 ^ 0x36363636 ,
p12 ^ 0x36363636 ,
p13 ^ 0x36363636 ,
p14 ^ 0x36363636 ,
p15 ^ 0x36363636
);
I0 = H0 ;
I1 = H1 ;
I2 = H2 ;
I3 = H3 ;
I4 = H4 ;
I5 = H5 ;
I6 = H6 ;
I7 = H7 ;
TOTAL0 = 64 ;
TOTAL1 = 0 ;
}
// offset — multiple of 64
// output — multiple of 32
function hmac_finish ( offset , length , output ) {
offset = offset | 0 ;
length = length | 0 ;
output = output | 0 ;
var t0 = 0 , t1 = 0 , t2 = 0 , t3 = 0 , t4 = 0 , t5 = 0 , t6 = 0 , t7 = 0 ,
hashed = 0 ;
if ( offset & 63 )
return - 1 ;
if ( ~ output )
if ( output & 31 )
return - 1 ;
hashed = finish ( offset , length , - 1 ) | 0 ;
t0 = H0 , t1 = H1 , t2 = H2 , t3 = H3 , t4 = H4 , t5 = H5 , t6 = H6 , t7 = H7 ;
_hmac_opad ();
_core ( t0 , t1 , t2 , t3 , t4 , t5 , t6 , t7 , 0x80000000 , 0 , 0 , 0 , 0 , 0 , 0 , 768 );
if ( ~ output )
_state_to_heap ( output );
return hashed | 0 ;
}
// salt is assumed to be already processed
// offset — multiple of 64
// output — multiple of 32
function pbkdf2_generate_block ( offset , length , block , count , output ) {
offset = offset | 0 ;
length = length | 0 ;
block = block | 0 ;
count = count | 0 ;
output = output | 0 ;
var h0 = 0 , h1 = 0 , h2 = 0 , h3 = 0 , h4 = 0 , h5 = 0 , h6 = 0 , h7 = 0 ,
t0 = 0 , t1 = 0 , t2 = 0 , t3 = 0 , t4 = 0 , t5 = 0 , t6 = 0 , t7 = 0 ;
if ( offset & 63 )
return - 1 ;
if ( ~ output )
if ( output & 31 )
return - 1 ;
// pad block number into heap
// FIXME probable OOB write
HEAP [( offset + length ) | 0 ] = block >>> 24 ;
HEAP [( offset + length + 1 ) | 0 ] = block >>> 16 & 255 ;
HEAP [( offset + length + 2 ) | 0 ] = block >>> 8 & 255 ;
HEAP [( offset + length + 3 ) | 0 ] = block & 255 ;
// finish first iteration
hmac_finish ( offset , ( length + 4 ) | 0 , - 1 ) | 0 ;
h0 = t0 = H0 , h1 = t1 = H1 , h2 = t2 = H2 , h3 = t3 = H3 , h4 = t4 = H4 , h5 = t5 = H5 , h6 = t6 = H6 , h7 = t7 = H7 ;
count = ( count - 1 ) | 0 ;
// perform the rest iterations
while ( ( count | 0 ) > 0 ) {
hmac_reset ();
_core ( t0 , t1 , t2 , t3 , t4 , t5 , t6 , t7 , 0x80000000 , 0 , 0 , 0 , 0 , 0 , 0 , 768 );
t0 = H0 , t1 = H1 , t2 = H2 , t3 = H3 , t4 = H4 , t5 = H5 , t6 = H6 , t7 = H7 ;
_hmac_opad ();
_core ( t0 , t1 , t2 , t3 , t4 , t5 , t6 , t7 , 0x80000000 , 0 , 0 , 0 , 0 , 0 , 0 , 768 );
t0 = H0 , t1 = H1 , t2 = H2 , t3 = H3 , t4 = H4 , t5 = H5 , t6 = H6 , t7 = H7 ;
h0 = h0 ^ H0 ;
h1 = h1 ^ H1 ;
h2 = h2 ^ H2 ;
h3 = h3 ^ H3 ;
h4 = h4 ^ H4 ;
h5 = h5 ^ H5 ;
h6 = h6 ^ H6 ;
h7 = h7 ^ H7 ;
count = ( count - 1 ) | 0 ;
}
H0 = h0 ;
H1 = h1 ;
H2 = h2 ;
H3 = h3 ;
H4 = h4 ;
H5 = h5 ;
H6 = h6 ;
H7 = h7 ;
if ( ~ output )
_state_to_heap ( output );
return 0 ;
}
return {
// SHA256
reset : reset ,
init : init ,
process : process ,
finish : finish ,
// HMAC-SHA256
hmac_reset : hmac_reset ,
hmac_init : hmac_init ,
hmac_finish : hmac_finish ,
// PBKDF2-HMAC-SHA256
pbkdf2_generate_block : pbkdf2_generate_block
}
}
},
"transform/TextTransformer.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
/*::
import type { Operation_t } from '../Operation'
*/
var Operation = require ( '../Operation' );
var Common = require ( '../Common' );
var transformOp0 = function (
toTransform /*:Operation_t*/ ,
transformBy /*:Operation_t*/ )
{
if ( toTransform . offset > transformBy . offset ) {
if ( toTransform . offset > transformBy . offset + transformBy . toRemove ) {
// simple rebase
return Operation . create (
toTransform . offset - transformBy . toRemove + transformBy . toInsert . length ,
toTransform . toRemove ,
toTransform . toInsert
);
}
var newToRemove =
toTransform . toRemove - ( transformBy . offset + transformBy . toRemove - toTransform . offset );
if ( newToRemove < 0 ) { newToRemove = 0 ; }
if ( newToRemove === 0 && toTransform . toInsert . length === 0 ) { return null ; }
return Operation . create (
transformBy . offset + transformBy . toInsert . length ,
newToRemove ,
toTransform . toInsert
);
}
// they don't touch, yay
if ( toTransform . offset + toTransform . toRemove < transformBy . offset ) { return toTransform ; }
// Truncate what will be deleted...
var _newToRemove = transformBy . offset - toTransform . offset ;
if ( _newToRemove === 0 && toTransform . toInsert . length === 0 ) { return null ; }
return Operation . create ( toTransform . offset , _newToRemove , toTransform . toInsert );
};
var transformOp = function (
toTransform /*:Operation_t*/ ,
transformBy /*:Operation_t*/ )
{
if ( Common . PARANOIA ) {
Operation . check ( toTransform );
Operation . check ( transformBy );
}
var result = transformOp0 ( toTransform , transformBy );
if ( Common . PARANOIA && result ) { Operation . check ( result ); }
return result ;
};
module . exports = function (
opsToTransform /*:Array<Operation_t>*/ ,
opsTransformBy /*:Array<Operation_t>*/ ,
doc /*:string*/ ) /*:Array<Operation_t>*/
{
var resultOfTransformBy = doc ;
var i ;
for ( i = opsTransformBy . length - 1 ; i >= 0 ; i -- ) {
resultOfTransformBy = Operation . apply ( opsTransformBy [ i ], resultOfTransformBy );
}
var out = [];
for ( i = opsToTransform . length - 1 ; i >= 0 ; i -- ) {
var tti = opsToTransform [ i ];
for ( var j = opsTransformBy . length - 1 ; j >= 0 ; j -- ) {
try {
tti = transformOp ( tti , opsTransformBy [ j ]);
} catch ( e ) {
console . error ( "The pluggable transform function threw an error, " +
"failing operational transformation" );
console . error ( e . stack );
return [];
}
if ( ! tti ) {
break ;
}
}
if ( tti ) {
if ( Common . PARANOIA ) { Operation . check ( tti , resultOfTransformBy . length ); }
out . unshift ( tti );
}
}
return out ;
};
},
"transform/SmartJSONTransformer.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
var Sortify = require ( 'json.sortify' );
var Diff = require ( '../Diff' );
//var Patch = require('../Patch');
var Operation = require ( '../Operation' );
var TextTransformer = require ( './TextTransformer' );
//var Sha = require('../sha256');
/*::
import type { Operation_t } from '../Operation';
*/
var isArray = function ( obj ) {
return Object . prototype . toString . call ( obj ) === '[object Array]' ;
};
/* Arrays and nulls both register as 'object' when using native typeof
we need to distinguish them as their own types, so use this instead. */
var type = function ( dat ) {
return dat === null ? 'null' : isArray ( dat ) ? 'array' : typeof ( dat );
};
var find = function ( map , path ) {
var l = path . length ;
for ( var i = 0 ; i < l ; i ++ ) {
if ( typeof ( map [ path [ i ]]) === 'undefined' ) { return ; }
map = map [ path [ i ]];
}
return map ;
};
var clone = function ( val ) {
return JSON . parse ( JSON . stringify ( val ));
};
var deepEqual = function ( A /*:any*/ , B /*:any*/ ) {
var t_A = type ( A );
var t_B = type ( B );
if ( t_A !== t_B ) { return false ; }
if ( t_A === 'object' ) {
var k_A = Object . keys ( A );
var k_B = Object . keys ( B );
return k_A . length === k_B . length &&
! k_A . some ( function ( a ) { return ! deepEqual ( A [ a ], B [ a ]); }) &&
! k_B . some ( function ( b ) { return ! ( b in A ); });
} else if ( t_A === 'array' ) {
return A . length === B . length &&
! A . some ( function ( a , i ) { return ! deepEqual ( a , B [ i ]); });
} else {
return A === B ;
}
};
/*::
export type SmartJSONTransformer_Replace_t = {
type: 'replace',
path: Array<string|number>,
value: any,
prev: any
};
export type SmartJSONTransformer_Splice_t = {
type: 'splice',
path: Array<string|number>,
value: any,
offset: number,
removals: number
};
export type SmartJSONTransformer_Remove_t = {
type: 'remove',
path: Array<string|number>,
value: any
};
export type SmartJSONTransformer_Operation_t =
SmartJSONTransformer_Replace_t | SmartJSONTransformer_Splice_t | SmartJSONTransformer_Remove_t;
*/
var operation = function ( type , path , value , prev , other ) /*:SmartJSONTransformer_Operation_t*/ {
if ( type === 'replace' ) {
return ({
type : 'replace' ,
path : path ,
value : value ,
prev : prev ,
} /*:SmartJSONTransformer_Replace_t*/ );
} else if ( type === 'splice' ) {
if ( typeof ( prev ) !== 'number' ) { throw new Error (); }
if ( typeof ( other ) !== 'number' ) { throw new Error (); }
return ({
type : 'splice' ,
path : path ,
value : value ,
offset : prev ,
removals : other
} /*:SmartJSONTransformer_Splice_t*/ );
} else if ( type !== 'remove' ) { throw new Error ( 'expected a removal' ); }
// if it's not a replace or splice, it's a 'remove'
return ({
type : 'remove' ,
path : path ,
value : value ,
} /*:SmartJSONTransformer_Remove_t*/ );
};
var replace = function ( ops , path , to , from ) {
ops . push ( operation ( 'replace' , path , to , from ));
};
var remove = function ( ops , path , val ) {
ops . push ( operation ( 'remove' , path , val ));
};
// HERE
var splice = function ( ops , path , value , offset , removals ) {
ops . push ( operation ( 'splice' , path , value , offset , removals ));
};
/*
all of A's path is at the beginning of B
roughly: B.indexOf(A) === 0
*/
var pathOverlaps = function ( A /*:Array<string|number>*/ , B /*:Array<string|number>*/ ) {
return ! A . some ( function ( a , i ) {
return a !== B [ i ];
});
};
// OT Case #1 replace->replace ✔
// OT Case #2 replace->remove ✔
// OT Case #3 replace->splice ✔
// OT Case #4 remove->replace ✔
// OT Case #5 remove->remove ✔
// OT Case #6 remove->splice ✔
// OT Case #7 splice->replace ✔
// OT Case #8 splice->remove ✔
// OT Case #9 splice->splice ✔
var CASES = ( function () {
var types = [ 'replace' , 'remove' , 'splice' ];
var matrix = {};
var i = 1 ;
types . forEach ( function ( a ) {
matrix [ a ] = {};
return types . forEach ( function ( b ) { matrix [ a ][ b ] = i ++ ; });
});
return matrix ;
}());
// A and B are lists of operations which result from calling diff
var resolve = function ( A /*:any*/ , B /*:any*/ , arbiter /*:?function*/ ) {
if ( ! ( type ( A ) === 'array' && type ( B ) === 'array' )) {
throw new Error ( "[resolve] expected two arrays" );
}
/* OVERVIEW
* B
* 1. filter removals at identical paths
*
*/
B = B . filter ( function ( b ) {
// if A removed part of the tree you were working on...
if ( A . some ( function ( a ) {
if ( a . type === 'remove' ) {
if ( pathOverlaps ( a . path , b . path )) {
if ( b . path . length - a . path . length > 1 ) { return true ; }
}
}
})) {
// this is weird... FIXME
return false ;
}
/* remove operations which would no longer make sense
for instance, if a replaces an array with a string,
that would invalidate a splice operation at that path */
if ( b . type === 'splice' && A . some ( function ( a ) {
if ( a . type === 'splice' && pathOverlaps ( a . path , b . path )) {
if ( a . path . length - b . path . length < 0 ) {
if ( ! a . removals ) { return ; }
var start = a . offset ;
var end = a . offset + a . removals ;
for (; start < end ; start ++ ) {
if ( start === b . path [ a . path . length ]) {
/*
if (typeof(arbiter) === 'function' &&
deepEqual(a.path, b.path) &&
a.value.length === 1 &&
b.value.length === 1 &&
typeof(a.value[0]) === 'string' &&
typeof(b.value[0]) === 'string') {
console.log('strings');
return arbiter(a, b, CASES.splice.splice);
}
*/
// b is a descendant of a removal
return true ;
}
}
}
}
})) { return false ; }
if ( ! A . some ( function ( a ) {
return b . type === 'remove' && deepEqual ( a . path , b . path );
})) { return true ; }
})
. filter ( function ( b ) {
// let A win conflicts over b if no arbiter is supplied here
// Arbiter is required here
return ! A . some ( function ( a ) {
if ( b . type === 'replace' && a . type === 'replace' ) {
// remove any operations which return true
if ( deepEqual ( a . path , b . path )) {
if ( typeof ( a . value ) === 'string' && typeof ( b . value ) === 'string' ) {
if ( arbiter && a . prev === b . prev && a . value !== b . value ) {
return arbiter ( a , b , CASES . replace . replace );
}
return true ;
}
return true ;
}
}
});
})
. map ( function ( b ) {
// if a splice in A modifies the path to b
// update b's path to reflect that
A . forEach ( function ( a ) {
if ( a . type === 'splice' ) {
// TODO
// what if a.path == b.path
// what if a removes elements (splice) and b also removes elements
// (generally we merge these two together but it is probably best to allow the api customer to decide via a "strategy")
// Note that A might be removing *and* inserting because a splice is roughly equivilent to a ChainPad Operation
// Consult Transform0 :)
// resolve insertion overlaps array.push conflicts
// iterate over A such that each overlapping splice
// adjusts the path/offset of b
if ( deepEqual ( a . path , b . path )) {
if ( b . type === 'splice' ) {
// what if the splice is a removal?
b . offset += ( a . value . length - a . removals );
// if both A and B are removing the same thing
// be careful
} else {
// adjust the path of b to account for the splice
// TODO
}
return ;
}
if ( pathOverlaps ( a . path , b . path )) {
// TODO validate that this isn't an off-by-one error
var pos = a . path . length ;
if ( typeof ( b . path [ pos ]) === 'number' && a . offset <= b . path [ pos ]) { // FIXME a.value is undefined
b . path [ pos ] += ( a . value . length - a . removals );
}
}
}
});
return b ;
});
return B ;
};
// A, B, f, path, ops
var objects = function ( A , B , path , ops ) {
var Akeys = Object . keys ( A );
var Bkeys = Object . keys ( B );
Bkeys . forEach ( function ( b ) {
var t_b = type ( B [ b ]);
var old = A [ b ];
var nextPath = path . concat ( b );
if ( Akeys . indexOf ( b ) === - 1 ) {
// there was an insertion
// mind the fallthrough behaviour
if ( t_b === 'undefined' ) {
throw new Error ( "undefined type has key. this shouldn't happen?" );
}
if ( old ) { throw new Error ( "no such key existed in b, so 'old' should be falsey" ); }
replace ( ops , nextPath , B [ b ], old );
return ;
}
// else the key already existed
var t_a = type ( old );
if ( t_a !== t_b ) {
// its type changed!
console . log ( "type changed from [%s] to [%s]" , t_a , t_b );
// type changes always mean a change happened
if ( t_b === 'undefined' ) {
throw new Error ( "first pass should never reveal undefined keys" );
}
replace ( ops , nextPath , B [ b ], old );
return ;
}
if ( t_a === 'object' ) {
// it's an object
objects ( A [ b ], B [ b ], nextPath , ops );
} else if ( t_a === 'array' ) {
// it's an array
arrays ( A [ b ], B [ b ], nextPath , ops );
} else if ( A [ b ] !== B [ b ]) {
// it's not an array or object, so we can do === comparison
replace ( ops , nextPath , B [ b ], old );
}
});
Akeys . forEach ( function ( a ) {
// the key was deleted
if ( Bkeys . indexOf ( a ) === - 1 || type ( B [ a ]) === 'undefined' ) {
remove ( ops , path . concat ( a ), A [ a ]);
}
});
};
var arrayShallowEquality = function ( A , B ) {
if ( A . length !== B . length ) { return false ; }
for ( var i = 0 ; i < A . length ; i ++ ) {
if ( type ( A [ i ]) !== type ( B [ i ])) { return false ; }
}
return true ;
};
// When an element in an array (number, string, bool) is changed, instead of a replace we
// will do a splice(offset, [element], 1)
var arrays = function ( A_orig , B , path , ops ) {
var A = A_orig . slice ( 0 ); // shallow clone
if ( A . length === 0 ) {
// A is zero length, this is going to be easy...
splice ( ops , path , B , 0 , 0 );
} else if ( arrayShallowEquality ( A , B )) {
// This is a relatively simple case, the elements in A and B are all of the same type and if
// that type happens to be a primitive type, they are also equal.
// This means no change will be needed at the level of this array, only it's children.
A . forEach ( function ( a , i ) {
var b = B [ i ];
if ( b === a ) { return ; }
var old = a ;
var nextPath = path . concat ( i );
var t_a = type ( a );
switch ( t_a ) {
case 'undefined' :
throw new Error ( 'existing key had type `undefined`. this should never happen' );
case 'object' :
objects ( a , b , nextPath , ops );
break ;
case 'array' :
arrays ( a , b , nextPath , ops );
break ;
default :
//console.log('replace: ' + t_a);
//splice(ops, path, [b], i, 1);
replace ( ops , nextPath , b , old );
}
});
} else {
// Something was changed in the length of the array or one of the primitives so we're going
// to make an actual change to this array, not only it's children.
var commonStart = 0 ;
var commonEnd = 0 ;
while ( commonStart < A . length && deepEqual ( A [ commonStart ], B [ commonStart ])) { commonStart ++ ; }
while ( deepEqual ( A [ A . length - 1 - commonEnd ], B [ B . length - 1 - commonEnd ]) &&
commonEnd + commonStart < A . length && commonEnd + commonStart < B . length )
{
commonEnd ++ ;
}
var toRemove = A . length - commonStart - commonEnd ;
var toInsert = [];
if ( B . length !== commonStart + commonEnd ) {
toInsert = B . slice ( commonStart , B . length - commonEnd );
}
splice ( ops , path , toInsert , commonStart , toRemove );
}
};
var diff = function ( A , B ) {
var ops = [];
var t_A = type ( A );
var t_B = type ( B );
if ( t_A !== t_B ) {
throw new Error ( "Can't merge two objects of differing types" );
}
if ( t_B === 'array' ) {
arrays ( A , B , [], ops );
} else if ( t_B === 'object' ) {
objects ( A , B , [], ops );
} else {
throw new Error ( "unsupported datatype" + t_B );
}
return ops ;
};
var applyOp = function ( O , op /*:SmartJSONTransformer_Operation_t*/ ) {
var path ;
var key ;
var result ;
switch ( op . type ) {
case "replace" :
key = op . path [ op . path . length - 1 ];
path = op . path . slice ( 0 , op . path . length - 1 );
var parent = find ( O , path );
if ( ! parent ) {
throw new Error ( "cannot apply change to non-existent element" );
}
parent [ key ] = op . value ;
break ;
case "splice" :
var found = find ( O , op . path );
if ( ! found ) {
console . error ( "[applyOp] expected path [%s] to exist in object" , op . path . join ( ',' ));
throw new Error ( "Path did not exist" );
}
if ( type ( found ) !== 'array' ) {
throw new Error ( "Can't splice non-array" );
}
Array . prototype . splice . apply ( found , [ op . offset , op . removals ]. concat ( op . value ));
break ;
case "remove" :
key = op . path [ op . path . length - 1 ];
path = op . path . slice ( 0 , op . path . length - 1 );
result = find ( O , path );
if ( typeof ( result ) !== 'undefined' ) { delete result [ key ]; }
break ;
default :
throw new Error ( 'unsupported operation type' );
}
};
var patch = function ( O , ops ) {
ops . forEach ( function ( op ) {
applyOp ( O , op );
});
return O ;
};
/////
// We mutate b in this function
// Our operation is p_b and the other person's operation is p_a.
// If we return true here, it means our operation will die off.
var arbiter = function ( p_a , p_b , c ) {
if ( p_a . prev !== p_b . prev ) { throw new Error ( "Parent values don't match!" ); }
if ( c === CASES . splice . splice ) {
// We and the other person are both pushing strings to an array so
// we'll just accept both of them into the array.
console . log ( p_a );
console . log ( p_b );
console . log ( '\n\n\n\n\n\n\n\n\n' );
// TODO: do we really want to kill off our operation in this case ?
return true ;
}
var o = p_a . prev ;
var ops_a = Diff . diff ( o , p_a . value );
var ops_b = Diff . diff ( o , p_b . value );
/* given the parent text, the op to transform, and the incoming op
return a transformed operation which takes the incoming
op into account */
var ops_x = TextTransformer ( ops_b , ops_a , o );
/* Apply the incoming operation to the parent text
*/
var x2 = Operation . applyMulti ( ops_a , o );
/* Apply the transformed operation to the result of the incoming op
*/
var x3 = Operation . applyMulti ( ops_x , x2 );
p_b . value = x3 ;
};
module . exports = function (
opsToTransform /*:Array<Operation_t>*/ ,
opsTransformBy /*:Array<Operation_t>*/ ,
s_orig /*:string*/ ) /*:Array<Operation_t>*/
{
var o_orig = JSON . parse ( s_orig );
var s_transformBy = Operation . applyMulti ( opsTransformBy , s_orig );
var o_transformBy = JSON . parse ( s_transformBy );
// try whole patch at a time, see how it goes...
var s_toTransform = Operation . applyMulti ( opsToTransform , s_orig );
var o_toTransform = JSON . parse ( s_toTransform );
try {
var diffTTF = diff ( o_orig , o_toTransform );
var diffTFB = diff ( o_orig , o_transformBy );
var newDiffTTF = resolve ( diffTFB , diffTTF , arbiter );
// mutates orig
patch ( o_orig , diffTFB );
patch ( o_orig , newDiffTTF );
var result = Sortify ( o_orig );
var ret = Diff . diff ( s_transformBy , result );
return ret ;
} catch ( err ) {
console . error ( err ); // FIXME Path did not exist...
}
return [];
};
module . exports . _ = {
clone : clone ,
pathOverlaps : pathOverlaps ,
deepEqual : deepEqual ,
diff : diff ,
resolve : resolve ,
patch : patch ,
};
},
"transform/NaiveJSONTransformer.js" : function ( module , exports , require ){
/*@flow*/
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict" ;
var TextTransformer = require ( './TextTransformer' );
//var ChainPad = require('../ChainPad');
var Operation = require ( '../Operation' );
var Common = require ( '../Common' );
/*::
import type { Operation_t } from '../Operation';
*/
module . exports = function (
opsToTransform /*:Array<Operation_t>*/ ,
opsTransformBy /*:Array<Operation_t>*/ ,
text /*:string*/ ) /*:Array<Operation_t>*/
{
var DEBUG = Common . global . REALTIME_DEBUG = Common . global . REALTIME_DEBUG || {};
var resultOps , text2 , text3 ;
try {
// text = O (mutual common ancestor)
// toTransform = A (your own operation)
// transformBy = B (the incoming operation)
// threeway merge (0, A, B)
resultOps = TextTransformer ( opsToTransform , opsTransformBy , text );
text2 = Operation . applyMulti ( opsTransformBy , text );
text3 = Operation . applyMulti ( resultOps , text2 );
try {
JSON . parse ( text3 );
return resultOps ;
} catch ( e ) {
console . error ( e );
DEBUG . ot_parseError = {
type : 'resultParseError' ,
resultOps : resultOps ,
toTransform : opsToTransform ,
transformBy : opsTransformBy ,
text1 : text ,
text2 : text2 ,
text3 : text3 ,
error : e
};
console . log ( 'Debugging info available at `window.REALTIME_DEBUG.ot_parseError`' );
}
} catch ( x ) {
console . error ( x );
DEBUG . ot_applyError = {
type : 'resultParseError' ,
resultOps : resultOps ,
toTransform : opsToTransform ,
transformBy : opsTransformBy ,
text1 : text ,
text2 : text2 ,
text3 : text3 ,
error : x
};
console . log ( 'Debugging info available at `window.REALTIME_DEBUG.ot_applyError`' );
}
// return an empty patch in case we can't do anything else
return [];
};
}
};
r . m [ 1 ] = {
"dist/JSON.sortify.js" : function ( module , exports , require ){
"use strict" ;( function ( factory ){ if ( typeof module !== "undefined" && module . exports ) module . exports = factory (); else if ( typeof define == "function" && typeof define . amd == "object" ) define ( "json.sortify" , factory ); else JSON . sortify = factory ()})( function (){ /*!
* Copyright 2015-2017 Thomas Rosenau
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ "use strict" ; var sortKeys = function sortKeys ( o ){ if ( Array . isArray ( o )){ return o . map ( sortKeys )} else if ( o instanceof Object ){ var _ret = function (){ var numeric = []; var nonNumeric = []; Object . keys ( o ). forEach ( function ( key ){ if ( /^(0|[1-9][0-9]*)$/ . test ( key )){ numeric . push ( + key )} else { nonNumeric . push ( key )}}); return { v : numeric . sort ( function ( a , b ){ return a - b }). concat ( nonNumeric . sort ()). reduce ( function ( result , key ){ result [ key ] = sortKeys ( o [ key ]); return result },{})}}(); if ( typeof _ret === "object" ) return _ret . v } return o }; var jsonStringify = JSON . stringify . bind ( JSON ); var sortify = function sortify ( value , replacer , space ){ var nativeJson = jsonStringify ( value , replacer , 0 ); if ( ! nativeJson || nativeJson [ 0 ] !== "{" && nativeJson [ 0 ] !== "[" ){ return nativeJson } var cleanObj = JSON . parse ( nativeJson ); return jsonStringify ( sortKeys ( cleanObj ), null , space )}; return sortify });
}
};
function umd ( n , f ){ "object" == typeof exports && ( module . exports = n ), "function" == typeof define && define . amd && define ( function (){ return n }); var e ; "undefined" != typeof window ? e = window : "undefined" != typeof global ? e = global : "undefined" != typeof self && ( e = self ), e [ f ] = n } umd ( r ( "ChainPad.js" ), "ChainPad" );}());