lib/differ.js
function diffMaps(propDesc, propPath, mapOld, mapNew, patchSpec) {

	const objects = (propDesc.scalarValueType === 'object');

	const keysToRemove = new Set(Object.keys(mapOld));
	for (let key of Object.keys(mapNew)) {

		const valOld = mapOld[key];
		const valNew = mapNew[key];

		if ((valNew === undefined) || (valNew === null)) {
			if ((valOld === undefined) || (valOld === null))
				keysToRemove.delete(key);
			continue;
		}

		keysToRemove.delete(key);

		if ((valOld === undefined) || (valOld === null)) {
			patchSpec.push({
				op: 'add',
				path: `${propPath}/${ptrSafe(key)}`,
				value: valNew
			});
		} else if (objects) {
			diffObjects(
				propDesc.nestedProperties,
				`${propPath}/${ptrSafe(key)}/`,
				valOld, valNew, patchSpec);
		} else if (valNew !== valOld) {
			patchSpec.push({
				op: 'replace',
				path: `${propPath}/${ptrSafe(key)}`,
				value: valNew
			});
		}
	}

	for (let key of keysToRemove)
		patchSpec.push({
			op: 'remove',
			path: `${propPath}/${ptrSafe(key)}`
		});
}
function diffMaps(propDesc, propPath, mapOld, mapNew, patchSpec) {

	const objects = (propDesc.scalarValueType === 'object');

	const keysToRemove = new Set(Object.keys(mapOld));
	for (let key of Object.keys(mapNew)) {

		const valOld = mapOld[key];
		const valNew = mapNew[key];

		if ((valNew === undefined) || (valNew === null)) {
			if ((valOld === undefined) || (valOld === null))
				keysToRemove.delete(key);
			continue;
		}

		keysToRemove.delete(key);

		if ((valOld === undefined) || (valOld === null)) {
			patchSpec.push({
				op: 'add',
				path: `${propPath}/${ptrSafe(key)}`,
				value: valNew
			});
		} else if (objects) {
			diffObjects(
				propDesc.nestedProperties,
				`${propPath}/${ptrSafe(key)}/`,
				valOld, valNew, patchSpec);
		} else if (valNew !== valOld) {
			patchSpec.push({
				op: 'replace',
				path: `${propPath}/${ptrSafe(key)}`,
				value: valNew
			});
		}
	}

	for (let key of keysToRemove)
		patchSpec.push({
			op: 'remove',
			path: `${propPath}/${ptrSafe(key)}`
		});
}
function diffMaps ( propDesc , propPath , mapOld , mapNew , patchSpec ) { const objects = ( propDesc . scalarValueType === 'object' ) ; const keysToRemove = new Set ( Object . keys ( mapOld ) ) ; for ( let key of Object . keys ( mapNew ) ) { const valOld = mapOld [ key ] ; const valNew = mapNew [ key ] ; if ( ( valNew === undefined ) || ( valNew === null ) ) { if ( ( valOld === undefined ) || ( valOld === null ) ) keysToRemove . delete ( key ) ; continue ; } keysToRemove . delete ( key ) ; if ( ( valOld === undefined ) || ( valOld === null ) ) { patchSpec . push ( { op : 'add' , path : ` ${ propPath } ${ ptrSafe ( key ) } ` , value : valNew } ) ; } else if ( objects ) { diffObjects ( propDesc . nestedProperties , ` ${ propPath } ${ ptrSafe ( key ) } ` , valOld , valNew , patchSpec ) ; } else if ( valNew !== valOld ) { patchSpec . push ( { op : 'replace' , path : ` ${ propPath } ${ ptrSafe ( key ) } ` , value : valNew } ) ; } } for ( let key of keysToRemove ) patchSpec . push ( { op : 'remove' , path : ` ${ propPath } ${ ptrSafe ( key ) } ` } ) ; }
Recursively diff two maps and generate corresponding patch operations.

@private
@param {module:x2node-records~PropertyDescriptor} propDesc Descriptor of the
map property.
@param {string} propPath JSON pointer path of the map property.
@param {Object.<string,*>} mapOld Original map.
@param {Object.<string,*>} mapNew New map.
@param {Array.<Object>} patchSpec The patch specification, to which to add
generated operations.
Recursively diff two maps and generate corresponding patch operations .