private bool ArraySetLength([NotNull] PropertyDescriptor descriptor) { //https://tc39.github.io/ecma262/#sec-arraysetlength var descriptorValue = descriptor.Value; if (!descriptorValue.HasValue) { return(base.DefineOwnProperty("length", descriptor)); } var newLengthDescriptor = descriptor.Copy(); var newLength = Agent.ToUint32(descriptorValue.Value); var numberLength = Agent.ToNumber(descriptorValue.Value); // ReSharper disable once CompareOfFloatsByEqualityOperator if (newLength != numberLength) { throw Agent.CreateRangeError(); } newLengthDescriptor.Value = newLength; var oldLengthDescriptor = GetOwnProperty("length"); Debug.Assert(!oldLengthDescriptor?.IsAccessorDescriptor == true); Debug.Assert(oldLengthDescriptor.Value != null, "oldLengthDescriptor.Value != null"); var oldLength = (uint)(double)oldLengthDescriptor.Value.Value; if (newLength >= oldLength) { return(base.DefineOwnProperty("length", newLengthDescriptor)); } if (!oldLengthDescriptor.Writable) { return(false); } bool newWritable; if (!newLengthDescriptor.Writable.HasValue || newLengthDescriptor.Writable) { newWritable = true; } else { //Need to defer setting the [[Writable]] attribute to false in case any elements cannot be deleted. newWritable = false; newLengthDescriptor.Writable = true; } var succeeded = base.DefineOwnProperty("length", newLengthDescriptor); if (!succeeded) { return(false); } while (newLength < oldLength) { oldLength--; var deleteSucceeded = Delete(oldLength.ToString(CultureInfo.InvariantCulture)); if (!deleteSucceeded) { newLengthDescriptor.Value = oldLength + 1; if (!newWritable) { newLengthDescriptor.Writable = false; } base.DefineOwnProperty("length", newLengthDescriptor); return(false); } } if (!newWritable) { return(base.DefineOwnProperty("length", new PropertyDescriptor { Writable = false })); } return(true); }