Skip to content
Permalink
Newer
Older
100644 85 lines (78 sloc) 2.6 KB
Ignoring revisions in .git-blame-ignore-revs.
1
'use strict';
2
3
var GetIntrinsic = require('get-intrinsic');
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://262.ecma-international.org/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
};