| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 | 'use strict';var $TypeError = require('es-errors/type');var DefineOwnProperty = require('../helpers/DefineOwnProperty');var isPropertyDescriptor = require('../helpers/records/property-descriptor');var isSamePropertyDescriptor = require('../helpers/isSamePropertyDescriptor');var FromPropertyDescriptor = require('./FromPropertyDescriptor');var IsAccessorDescriptor = require('./IsAccessorDescriptor');var IsDataDescriptor = require('./IsDataDescriptor');var IsGenericDescriptor = require('./IsGenericDescriptor');var isPropertyKey = require('../helpers/isPropertyKey');var SameValue = require('./SameValue');var isObject = require('../helpers/isObject');// https://262.ecma-international.org/6.0/#sec-validateandapplypropertydescriptor// https://262.ecma-international.org/8.0/#sec-validateandapplypropertydescriptor// eslint-disable-next-line max-lines-per-function, max-statementsmodule.exports = function ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current) {	// this uses the ES2017+ logic, since it fixes a number of bugs in the ES2015 logic.	if (typeof O !== 'undefined' && !isObject(O)) {		throw new $TypeError('Assertion failed: O must be undefined or an Object');	}	if (typeof extensible !== 'boolean') {		throw new $TypeError('Assertion failed: extensible must be a Boolean');	}	if (!isPropertyDescriptor(Desc)) {		throw new $TypeError('Assertion failed: Desc must be a Property Descriptor');	}	if (typeof current !== 'undefined' && !isPropertyDescriptor(current)) {		throw new $TypeError('Assertion failed: current must be a Property Descriptor, or undefined');	}	if (typeof O !== 'undefined' && !isPropertyKey(P)) {		throw new $TypeError('Assertion failed: if O is not undefined, P must be a Property Key');	}	if (typeof current === 'undefined') {		if (!extensible) {			return false;		}		if (IsGenericDescriptor(Desc) || IsDataDescriptor(Desc)) {			if (typeof O !== '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 (typeof O !== '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 (typeof O !== 'undefined') {				DefineOwnProperty(					IsDataDescriptor,					SameValue,					FromPropertyDescriptor,					O,					P,					{						'[[Configurable]]': current['[[Configurable]]'],						'[[Enumerable]]': current['[[Enumerable]]'],						'[[Get]]': undefined					}				);			}		} else if (typeof O !== '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 (typeof O !== 'undefined') {		return DefineOwnProperty(			IsDataDescriptor,			SameValue,			FromPropertyDescriptor,			O,			P,			Desc		);	}	return true;};
 |