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.
		
		
		
		
			
				
					171 lines
				
				5.1 KiB
			
		
		
			
		
	
	
					171 lines
				
				5.1 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'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;
							 | 
						||
| 
								 | 
							
								};
							 |