Index: src/array.js |
diff --git a/src/array.js b/src/array.js |
index e98d7f5b53aba315558d9297950d093c7f308195..26bf7282e18ba1a90b7e7c5569cedf0334ef89b6 100644 |
--- a/src/array.js |
+++ b/src/array.js |
@@ -425,6 +425,11 @@ function ArrayPop() { |
return; |
} |
+ if ($Object.isSealed(this)) { |
+ throw MakeTypeError("array_functions_change_sealed", |
+ ["Array.prototype.pop"]); |
+ } |
+ |
if (%IsObserved(this)) |
return ObservedArrayPop.call(this, n); |
@@ -462,11 +467,16 @@ function ArrayPush() { |
["Array.prototype.push"]); |
} |
+ var n = TO_UINT32(this.length); |
+ var m = %_ArgumentsLength(); |
+ if (m > 0 && $Object.isSealed(this)) { |
+ throw MakeTypeError("array_functions_change_sealed", |
+ ["Array.prototype.push"]); |
+ } |
+ |
if (%IsObserved(this)) |
return ObservedArrayPush.apply(this, arguments); |
- var n = TO_UINT32(this.length); |
- var m = %_ArgumentsLength(); |
for (var i = 0; i < m; i++) { |
this[i+n] = %_Arguments(i); |
} |
@@ -604,6 +614,11 @@ function ArrayShift() { |
return; |
} |
+ if ($Object.isSealed(this)) { |
+ throw MakeTypeError("array_functions_change_sealed", |
+ ["Array.prototype.shift"]); |
+ } |
+ |
if (%IsObserved(this)) |
return ObservedArrayShift.call(this, len); |
@@ -645,15 +660,32 @@ function ArrayUnshift(arg1) { // length == 1 |
["Array.prototype.unshift"]); |
} |
- if (%IsObserved(this)) |
- return ObservedArrayUnshift.apply(this, arguments); |
- |
var len = TO_UINT32(this.length); |
var num_arguments = %_ArgumentsLength(); |
+ var is_sealed = $Object.isSealed(this); |
- if (IS_ARRAY(this)) { |
+ if (num_arguments > 0 && is_sealed) { |
+ throw MakeTypeError("array_functions_change_sealed", |
+ ["Array.prototype.unshift"]); |
+ } |
+ |
+ if (%IsObserved(this)) |
+ return ObservedArrayUnshift.apply(this, arguments); |
+ |
+ if (IS_ARRAY(this) && !is_sealed) { |
SmartMove(this, 0, 0, len, num_arguments); |
} else { |
+ if (num_arguments == 0 && $Object.isFrozen(this)) { |
+ // In the zero argument case, values from the prototype come into the |
+ // object. This can't be allowed on frozen arrays. |
+ for (var i = 0; i < len; i++) { |
+ if (!this.hasOwnProperty(i) && !IS_UNDEFINED(this[i])) { |
+ throw MakeTypeError("array_functions_on_frozen", |
+ ["Array.prototype.shift"]); |
+ } |
+ } |
+ } |
+ |
SimpleMove(this, 0, 0, len, num_arguments); |
} |
@@ -663,7 +695,7 @@ function ArrayUnshift(arg1) { // length == 1 |
this.length = len + num_arguments; |
- return len + num_arguments; |
+ return this.length; |
} |
@@ -802,6 +834,14 @@ function ArraySplice(start, delete_count) { |
deleted_elements.length = del_count; |
var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0; |
+ if (del_count != num_elements_to_add && $Object.isSealed(this)) { |
+ throw MakeTypeError("array_functions_change_sealed", |
+ ["Array.prototype.splice"]); |
+ } else if (del_count > 0 && $Object.isFrozen(this)) { |
+ throw MakeTypeError("array_functions_on_frozen", |
+ ["Array.prototype.splice"]); |
+ } |
+ |
var use_simple_splice = true; |
if (IS_ARRAY(this) && |
num_elements_to_add !== del_count) { |