You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							170 lines
						
					
					
						
							5.1 KiB
						
					
					
				
			
		
		
	
	
							170 lines
						
					
					
						
							5.1 KiB
						
					
					
				'use strict'; | 
						|
 | 
						|
var GetIntrinsic = require('get-intrinsic'); | 
						|
 | 
						|
var $TypeError = GetIntrinsic('%TypeError%'); | 
						|
 | 
						|
var DefineOwnProperty = require('../helpers/DefineOwnProperty'); | 
						|
var isPropertyDescriptor = require('../helpers/isPropertyDescriptor'); | 
						|
var isSamePropertyDescriptor = require('../helpers/isSamePropertyDescriptor'); | 
						|
 | 
						|
var FromPropertyDescriptor = require('./FromPropertyDescriptor'); | 
						|
var IsAccessorDescriptor = require('./IsAccessorDescriptor'); | 
						|
var IsDataDescriptor = require('./IsDataDescriptor'); | 
						|
var IsGenericDescriptor = require('./IsGenericDescriptor'); | 
						|
var IsPropertyKey = require('./IsPropertyKey'); | 
						|
var SameValue = require('./SameValue'); | 
						|
var Type = require('./Type'); | 
						|
 | 
						|
// https://ecma-international.org/ecma-262/6.0/#sec-validateandapplypropertydescriptor | 
						|
// https://ecma-international.org/ecma-262/8.0/#sec-validateandapplypropertydescriptor | 
						|
 | 
						|
// eslint-disable-next-line max-lines-per-function, max-statements, max-params | 
						|
module.exports = function ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current) { | 
						|
	// this uses the ES2017+ logic, since it fixes a number of bugs in the ES2015 logic. | 
						|
	var oType = Type(O); | 
						|
	if (oType !== 'Undefined' && oType !== 'Object') { | 
						|
		throw new $TypeError('Assertion failed: O must be undefined or an Object'); | 
						|
	} | 
						|
	if (Type(extensible) !== 'Boolean') { | 
						|
		throw new $TypeError('Assertion failed: extensible must be a Boolean'); | 
						|
	} | 
						|
	if (!isPropertyDescriptor({ | 
						|
		Type: Type, | 
						|
		IsDataDescriptor: IsDataDescriptor, | 
						|
		IsAccessorDescriptor: IsAccessorDescriptor | 
						|
	}, Desc)) { | 
						|
		throw new $TypeError('Assertion failed: Desc must be a Property Descriptor'); | 
						|
	} | 
						|
	if (Type(current) !== 'Undefined' && !isPropertyDescriptor({ | 
						|
		Type: Type, | 
						|
		IsDataDescriptor: IsDataDescriptor, | 
						|
		IsAccessorDescriptor: IsAccessorDescriptor | 
						|
	}, current)) { | 
						|
		throw new $TypeError('Assertion failed: current must be a Property Descriptor, or undefined'); | 
						|
	} | 
						|
	if (oType !== 'Undefined' && !IsPropertyKey(P)) { | 
						|
		throw new $TypeError('Assertion failed: if O is not undefined, P must be a Property Key'); | 
						|
	} | 
						|
	if (Type(current) === 'Undefined') { | 
						|
		if (!extensible) { | 
						|
			return false; | 
						|
		} | 
						|
		if (IsGenericDescriptor(Desc) || IsDataDescriptor(Desc)) { | 
						|
			if (oType !== 'Undefined') { | 
						|
				DefineOwnProperty( | 
						|
					IsDataDescriptor, | 
						|
					SameValue, | 
						|
					FromPropertyDescriptor, | 
						|
					O, | 
						|
					P, | 
						|
					{ | 
						|
						'[[Configurable]]': Desc['[[Configurable]]'], | 
						|
						'[[Enumerable]]': Desc['[[Enumerable]]'], | 
						|
						'[[Value]]': Desc['[[Value]]'], | 
						|
						'[[Writable]]': Desc['[[Writable]]'] | 
						|
					} | 
						|
				); | 
						|
			} | 
						|
		} else { | 
						|
			if (!IsAccessorDescriptor(Desc)) { | 
						|
				throw new $TypeError('Assertion failed: Desc is not an accessor descriptor'); | 
						|
			} | 
						|
			if (oType !== 'Undefined') { | 
						|
				return DefineOwnProperty( | 
						|
					IsDataDescriptor, | 
						|
					SameValue, | 
						|
					FromPropertyDescriptor, | 
						|
					O, | 
						|
					P, | 
						|
					Desc | 
						|
				); | 
						|
			} | 
						|
		} | 
						|
		return true; | 
						|
	} | 
						|
	if (IsGenericDescriptor(Desc) && !('[[Configurable]]' in Desc) && !('[[Enumerable]]' in Desc)) { | 
						|
		return true; | 
						|
	} | 
						|
	if (isSamePropertyDescriptor({ SameValue: SameValue }, Desc, current)) { | 
						|
		return true; // removed by ES2017, but should still be correct | 
						|
	} | 
						|
	// "if every field in Desc is absent, return true" can't really match the assertion that it's a Property Descriptor | 
						|
	if (!current['[[Configurable]]']) { | 
						|
		if (Desc['[[Configurable]]']) { | 
						|
			return false; | 
						|
		} | 
						|
		if ('[[Enumerable]]' in Desc && !Desc['[[Enumerable]]'] === !!current['[[Enumerable]]']) { | 
						|
			return false; | 
						|
		} | 
						|
	} | 
						|
	if (IsGenericDescriptor(Desc)) { | 
						|
		// no further validation is required. | 
						|
	} else if (IsDataDescriptor(current) !== IsDataDescriptor(Desc)) { | 
						|
		if (!current['[[Configurable]]']) { | 
						|
			return false; | 
						|
		} | 
						|
		if (IsDataDescriptor(current)) { | 
						|
			if (oType !== 'Undefined') { | 
						|
				DefineOwnProperty( | 
						|
					IsDataDescriptor, | 
						|
					SameValue, | 
						|
					FromPropertyDescriptor, | 
						|
					O, | 
						|
					P, | 
						|
					{ | 
						|
						'[[Configurable]]': current['[[Configurable]]'], | 
						|
						'[[Enumerable]]': current['[[Enumerable]]'], | 
						|
						'[[Get]]': undefined | 
						|
					} | 
						|
				); | 
						|
			} | 
						|
		} else if (oType !== 'Undefined') { | 
						|
			DefineOwnProperty( | 
						|
				IsDataDescriptor, | 
						|
				SameValue, | 
						|
				FromPropertyDescriptor, | 
						|
				O, | 
						|
				P, | 
						|
				{ | 
						|
					'[[Configurable]]': current['[[Configurable]]'], | 
						|
					'[[Enumerable]]': current['[[Enumerable]]'], | 
						|
					'[[Value]]': undefined | 
						|
				} | 
						|
			); | 
						|
		} | 
						|
	} else if (IsDataDescriptor(current) && IsDataDescriptor(Desc)) { | 
						|
		if (!current['[[Configurable]]'] && !current['[[Writable]]']) { | 
						|
			if ('[[Writable]]' in Desc && Desc['[[Writable]]']) { | 
						|
				return false; | 
						|
			} | 
						|
			if ('[[Value]]' in Desc && !SameValue(Desc['[[Value]]'], current['[[Value]]'])) { | 
						|
				return false; | 
						|
			} | 
						|
			return true; | 
						|
		} | 
						|
	} else if (IsAccessorDescriptor(current) && IsAccessorDescriptor(Desc)) { | 
						|
		if (!current['[[Configurable]]']) { | 
						|
			if ('[[Set]]' in Desc && !SameValue(Desc['[[Set]]'], current['[[Set]]'])) { | 
						|
				return false; | 
						|
			} | 
						|
			if ('[[Get]]' in Desc && !SameValue(Desc['[[Get]]'], current['[[Get]]'])) { | 
						|
				return false; | 
						|
			} | 
						|
			return true; | 
						|
		} | 
						|
	} else { | 
						|
		throw new $TypeError('Assertion failed: current and Desc are not both data, both accessors, or one accessor and one data.'); | 
						|
	} | 
						|
	if (oType !== 'Undefined') { | 
						|
		return DefineOwnProperty( | 
						|
			IsDataDescriptor, | 
						|
			SameValue, | 
						|
			FromPropertyDescriptor, | 
						|
			O, | 
						|
			P, | 
						|
			Desc | 
						|
		); | 
						|
	} | 
						|
	return true; | 
						|
};
 | 
						|
 |