lib/record-patch-builder.js
function isCompatibleObjects(objectPropDesc1, objectPropDesc2) {

	const propNames2 = new Set(objectPropDesc2.allPropertyNames);
	const container1 = objectPropDesc1.nestedProperties;
	const container2 = objectPropDesc2.nestedProperties;
	for (let propName of objectPropDesc1.allPropertyNames) {
		const propDesc1 = container1.getPropertyDesc(propName);
		if (propDesc1.isView() || propDesc1.isCalculated())
			continue;
		if (!propNames2.has(propName)) {
			if (!propDesc1.optional)
				return false;
			continue;
		}
		propNames2.delete(propName);
		const propDesc2 = container2.getPropertyDesc(propName);
		if (!propDesc1.optional && propDesc2.optional)
			return false;
		if ((propDesc1.isArray() && !propDesc2.isArray()) ||
			(propDesc1.isMap() && !propDesc2.isMap()) ||
			(propDesc1.isScalar() && !propDesc2.isScalar()))
			return false;
		if (propDesc1.scalarValueType !== propDesc2.scalarValueType)
			return false;
		if (propDesc1.isRef() && (propDesc1.refTarget !== propDesc2.refTarget))
			return false;
		if ((propDesc1.scalarValueType === 'object') &&
			!isCompatibleObjects(propDesc1, propDesc2))
			return false;
	}

	for (let propName of propNames2) {
		const propDesc2 = container2.getPropertyDesc(propName);
		if (!propDesc2.isView() && !propDesc2.isCalculated())
			return false;
	}

	return true;
}
function isCompatibleObjects(objectPropDesc1, objectPropDesc2) {

	const propNames2 = new Set(objectPropDesc2.allPropertyNames);
	const container1 = objectPropDesc1.nestedProperties;
	const container2 = objectPropDesc2.nestedProperties;
	for (let propName of objectPropDesc1.allPropertyNames) {
		const propDesc1 = container1.getPropertyDesc(propName);
		if (propDesc1.isView() || propDesc1.isCalculated())
			continue;
		if (!propNames2.has(propName)) {
			if (!propDesc1.optional)
				return false;
			continue;
		}
		propNames2.delete(propName);
		const propDesc2 = container2.getPropertyDesc(propName);
		if (!propDesc1.optional && propDesc2.optional)
			return false;
		if ((propDesc1.isArray() && !propDesc2.isArray()) ||
			(propDesc1.isMap() && !propDesc2.isMap()) ||
			(propDesc1.isScalar() && !propDesc2.isScalar()))
			return false;
		if (propDesc1.scalarValueType !== propDesc2.scalarValueType)
			return false;
		if (propDesc1.isRef() && (propDesc1.refTarget !== propDesc2.refTarget))
			return false;
		if ((propDesc1.scalarValueType === 'object') &&
			!isCompatibleObjects(propDesc1, propDesc2))
			return false;
	}

	for (let propName of propNames2) {
		const propDesc2 = container2.getPropertyDesc(propName);
		if (!propDesc2.isView() && !propDesc2.isCalculated())
			return false;
	}

	return true;
}
function isCompatibleObjects ( objectPropDesc1 , objectPropDesc2 ) { const propNames2 = new Set ( objectPropDesc2 . allPropertyNames ) ; const container1 = objectPropDesc1 . nestedProperties ; const container2 = objectPropDesc2 . nestedProperties ; for ( let propName of objectPropDesc1 . allPropertyNames ) { const propDesc1 = container1 . getPropertyDesc ( propName ) ; if ( propDesc1 . isView ( ) || propDesc1 . isCalculated ( ) ) continue ; if ( ! propNames2 . has ( propName ) ) { if ( ! propDesc1 . optional ) return false ; continue ; } propNames2 . delete ( propName ) ; const propDesc2 = container2 . getPropertyDesc ( propName ) ; if ( ! propDesc1 . optional && propDesc2 . optional ) return false ; if ( ( propDesc1 . isArray ( ) && ! propDesc2 . isArray ( ) ) || ( propDesc1 . isMap ( ) && ! propDesc2 . isMap ( ) ) || ( propDesc1 . isScalar ( ) && ! propDesc2 . isScalar ( ) ) ) return false ; if ( propDesc1 . scalarValueType !== propDesc2 . scalarValueType ) return false ; if ( propDesc1 . isRef ( ) && ( propDesc1 . refTarget !== propDesc2 . refTarget ) ) return false ; if ( ( propDesc1 . scalarValueType === 'object' ) && ! isCompatibleObjects ( propDesc1 , propDesc2 ) ) return false ; } for ( let propName of propNames2 ) { const propDesc2 = container2 . getPropertyDesc ( propName ) ; if ( ! propDesc2 . isView ( ) && ! propDesc2 . isCalculated ( ) ) return false ; } return true ; }
Tell if a value of the nested object property 2 can be used as a value of the
nested object property 1.

@private
@param {module:x2node-records~PropertyDescriptor} objectPropDesc1 Nested
object property 1.
@param {module:x2node-records~PropertyDescriptor} objectPropDesc2 Nested
object property 2.
@returns {boolean} <code>true</code> if compatible nested object properties.
Tell if a value of the nested object property 2 can be used as a value of the nested object property 1 .