Projekt

Obecné

Profil

Stáhnout (2.61 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2

    
3
var GetIntrinsic = require('../GetIntrinsic');
4

    
5
var $RangeError = GetIntrinsic('%RangeError%');
6
var $TypeError = GetIntrinsic('%TypeError%');
7

    
8
var assign = require('object.assign');
9

    
10
var isPropertyDescriptor = require('../helpers/isPropertyDescriptor');
11

    
12
var IsArray = require('./IsArray');
13
var IsAccessorDescriptor = require('./IsAccessorDescriptor');
14
var IsDataDescriptor = require('./IsDataDescriptor');
15
var OrdinaryDefineOwnProperty = require('./OrdinaryDefineOwnProperty');
16
var OrdinaryGetOwnProperty = require('./OrdinaryGetOwnProperty');
17
var ToNumber = require('./ToNumber');
18
var ToString = require('./ToString');
19
var ToUint32 = require('./ToUint32');
20
var Type = require('./Type');
21

    
22
// https://www.ecma-international.org/ecma-262/6.0/#sec-arraysetlength
23

    
24
// eslint-disable-next-line max-statements, max-lines-per-function
25
module.exports = function ArraySetLength(A, Desc) {
26
	if (!IsArray(A)) {
27
		throw new $TypeError('Assertion failed: A must be an Array');
28
	}
29
	if (!isPropertyDescriptor({
30
		Type: Type,
31
		IsDataDescriptor: IsDataDescriptor,
32
		IsAccessorDescriptor: IsAccessorDescriptor
33
	}, Desc)) {
34
		throw new $TypeError('Assertion failed: Desc must be a Property Descriptor');
35
	}
36
	if (!('[[Value]]' in Desc)) {
37
		return OrdinaryDefineOwnProperty(A, 'length', Desc);
38
	}
39
	var newLenDesc = assign({}, Desc);
40
	var newLen = ToUint32(Desc['[[Value]]']);
41
	var numberLen = ToNumber(Desc['[[Value]]']);
42
	if (newLen !== numberLen) {
43
		throw new $RangeError('Invalid array length');
44
	}
45
	newLenDesc['[[Value]]'] = newLen;
46
	var oldLenDesc = OrdinaryGetOwnProperty(A, 'length');
47
	if (!IsDataDescriptor(oldLenDesc)) {
48
		throw new $TypeError('Assertion failed: an array had a non-data descriptor on `length`');
49
	}
50
	var oldLen = oldLenDesc['[[Value]]'];
51
	if (newLen >= oldLen) {
52
		return OrdinaryDefineOwnProperty(A, 'length', newLenDesc);
53
	}
54
	if (!oldLenDesc['[[Writable]]']) {
55
		return false;
56
	}
57
	var newWritable;
58
	if (!('[[Writable]]' in newLenDesc) || newLenDesc['[[Writable]]']) {
59
		newWritable = true;
60
	} else {
61
		newWritable = false;
62
		newLenDesc['[[Writable]]'] = true;
63
	}
64
	var succeeded = OrdinaryDefineOwnProperty(A, 'length', newLenDesc);
65
	if (!succeeded) {
66
		return false;
67
	}
68
	while (newLen < oldLen) {
69
		oldLen -= 1;
70
		// eslint-disable-next-line no-param-reassign
71
		var deleteSucceeded = delete A[ToString(oldLen)];
72
		if (!deleteSucceeded) {
73
			newLenDesc['[[Value]]'] = oldLen + 1;
74
			if (!newWritable) {
75
				newLenDesc['[[Writable]]'] = false;
76
				OrdinaryDefineOwnProperty(A, 'length', newLenDesc);
77
				return false;
78
			}
79
		}
80
	}
81
	if (!newWritable) {
82
		return OrdinaryDefineOwnProperty(A, 'length', { '[[Writable]]': false });
83
	}
84
	return true;
85
};
(2-2/115)