| Index: src/array.js
|
| diff --git a/src/array.js b/src/array.js
|
| index a1cc5b6a7d1a7663b10270ee07e047e54066f4fd..cb2a623a8d736e5726ebb2ba5d6160bc5295d821 100644
|
| --- a/src/array.js
|
| +++ b/src/array.js
|
| @@ -486,11 +486,56 @@ function ArrayConcat(arg1) { // length == 1
|
| }
|
|
|
|
|
| +// Check if property is writable
|
| +// return true if there is no property descriptor
|
| +function PropertyIsWritable(o, p) {
|
| + var d = ObjectGetOwnPropertyDescriptor(o, p);
|
| + return !d || d.writable === true;
|
| +}
|
| +
|
| +
|
| +// Check if property is configurable
|
| +// return true if there is no property descriptor
|
| +function PropertyIsConfigurable(o, p) {
|
| + var d = ObjectGetOwnPropertyDescriptor(o, p);
|
| + return !d || d.configurable === true;
|
| +}
|
| +
|
| +
|
| +// Prepare and return TypeError object for array method
|
| +function MakeTypeErrorForReadOnly(method_name) {
|
| + return MakeTypeError("called_on_read_only",
|
| + ["Array.prototype." + method_name]);
|
| +}
|
| +
|
| +
|
| +function MakeTypeErrorForNonConfigurableProperty(method_name) {
|
| + return MakeTypeError("cant_delete_non_configurable_property",
|
| + ["Array.prototype." + method_name]);
|
| +}
|
| +
|
| +
|
| +function ThrowTypeErrorIfNotWritable(method_name, a, p) {
|
| + if (!PropertyIsWritable(a, p)) {
|
| + throw MakeTypeErrorForReadOnly(method_name);
|
| + }
|
| +}
|
| +
|
| +
|
| +function ThrowTypeErrorIfNotConfigurable(method_name, a, p) {
|
| + if (!PropertyIsConfigurable(a, p)) {
|
| + throw MakeTypeErrorForNonConfigurableProperty(method_name);
|
| + }
|
| +}
|
| +
|
| +
|
| // For implementing reverse() on large, sparse arrays.
|
| function SparseReverse(array, len) {
|
| var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
|
| var high_counter = keys.length - 1;
|
| var low_counter = 0;
|
| + var method_name = "reverse";
|
| +
|
| while (low_counter <= high_counter) {
|
| var i = keys[low_counter];
|
| var j = keys[high_counter];
|
| @@ -513,16 +558,25 @@ function SparseReverse(array, len) {
|
| if (!IS_UNDEFINED(current_i) || low in array) {
|
| var current_j = array[high];
|
| if (!IS_UNDEFINED(current_j) || high in array) {
|
| + ThrowTypeErrorIfNotWritable(method_name, array, low);
|
| array[low] = current_j;
|
| +
|
| + ThrowTypeErrorIfNotWritable(method_name, array, high);
|
| array[high] = current_i;
|
| } else {
|
| + ThrowTypeErrorIfNotWritable(method_name, array, high);
|
| array[high] = current_i;
|
| +
|
| + ThrowTypeErrorIfNotConfigurable(method_name, array, low);
|
| delete array[low];
|
| }
|
| } else {
|
| var current_j = array[high];
|
| if (!IS_UNDEFINED(current_j) || high in array) {
|
| + ThrowTypeErrorIfNotWritable(method_name, array, low);
|
| array[low] = current_j;
|
| +
|
| + ThrowTypeErrorIfNotConfigurable(method_name, array, high);
|
| delete array[high];
|
| }
|
| }
|
| @@ -535,29 +589,44 @@ function ArrayReverse() {
|
| throw MakeTypeError("called_on_null_or_undefined",
|
| ["Array.prototype.reverse"]);
|
| }
|
| -
|
| +
|
| + var method_name = "reverse";
|
| +
|
| + if (ObjectIsFrozen(this)) {
|
| + throw MakeTypeErrorForReadOnly(method_name);
|
| + }
|
| +
|
| var j = TO_UINT32(this.length) - 1;
|
|
|
| if (UseSparseVariant(this, j, IS_ARRAY(this))) {
|
| SparseReverse(this, j+1);
|
| return this;
|
| }
|
| -
|
| +
|
| for (var i = 0; i < j; i++, j--) {
|
| var current_i = this[i];
|
| if (!IS_UNDEFINED(current_i) || i in this) {
|
| var current_j = this[j];
|
| if (!IS_UNDEFINED(current_j) || j in this) {
|
| + ThrowTypeErrorIfNotWritable(method_name, this, i);
|
| this[i] = current_j;
|
| +
|
| + ThrowTypeErrorIfNotWritable(method_name, this, j);
|
| this[j] = current_i;
|
| } else {
|
| + ThrowTypeErrorIfNotWritable(method_name, this, j);
|
| this[j] = current_i;
|
| +
|
| + ThrowTypeErrorIfNotConfigurable(method_name, this, i);
|
| delete this[i];
|
| }
|
| } else {
|
| var current_j = this[j];
|
| if (!IS_UNDEFINED(current_j) || j in this) {
|
| + ThrowTypeErrorIfNotWritable(method_name, this, i);
|
| this[i] = current_j;
|
| +
|
| + ThrowTypeErrorIfNotConfigurable(method_name, this, j);
|
| delete this[j];
|
| }
|
| }
|
|
|