Push and pop on a frozen array in Chrome not throwing an exception
ecma262, ecmascript-5, javascript
Solution
ECMA 262 5.1 says the following of `Array.prototype.push`:
15.4.4.7 `Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )`
....
- Let `O` be the result of calling `ToObject` passing the this value as the argument.
- Let `lenVal` be the result of calling the `[[Get]]` internal method of `O` with argument "`length`".
- Let `n` be `ToUint32(lenVal)`.
- Let `items` be an internal List whose elements are, in left to right order, the arguments that were passed to this function invocation.
- Repeat, while items is not empty
- Remove the first element from items and let `E` be the value of the element.
- Call the `[[Put]]` internal method of `O` with arguments `ToString(n)`, `E`, and `true`.
- Increase `n` by 1.
- Call the `[[Put]]` internal method of O with arguments "length", n, and true.
- Return n.
Notice how the argument 3 to `[[Put]]` is `true`. Now, `[[Put]]` is defined as
8.12.5 `[[Put]] ( P, V, Throw )`
When the `[[Put]]` internal method of `O` is called with property `P`, value `V`, and Boolean flag `Throw`, the following steps are taken:
- If the result of calling the `[[CanPut]]` internal method of `O` with argument `P` is `false`, then
- If `Throw` is `true`, then throw a `TypeError` exception.
- Else return.
...
`[[CanPut]]` then returns `false` among others, in the case of array if `[[Extensible]]` on `O` is `false`.
Thus, your Chrome is in violation of the ECMA 262 5.1 specification.
Update:
Chrome developers are talking about making the `push`, `pop` run under strict mode; however the difference is not just "strict" vs "non-strict" as the behaviour of `push` and `pop` is specified very specifically in the ECMA 262 5.1 specification.
Problem
The following code does not seem to run as expected under Chrome, and runs differently in Firefox. ``` (function () { 'use strict'; var arr = Object.freeze([1, 2, 3]); try { arr.push(4); } catch (e) { console.log(e); } try { console.log(arr.pop()); }catch (e) { console.log(e); } console.log(arr); })(); ``` I expected that the output would be: ``` Error : (for `arr.push(4)`) Error : (for `arr.pop()`) [1, 2, 3] ``` but when running this code on Chrome 29.0.1547.49 (Official Build 216092) beta-m, I receive the following output: ``` 3 [1, 2, 3] ``` Why is there no exception? I ran this code on Firefox Nightly 26.0a1(2013-08-12), and the result is ``` TypeError: arr.push(...) is not extensible TypeError: property arr.pop(...) is non-configurable and can't be deleted [1, 2, 3] ``` as I had expected. I thought about why the difference between Chrome and Firefox, then I realized that it could be because of strict mode of `pop` and `push` methods. To sum up, in Firefox (SpiderMonkey) `pop` and `push` methods are defined in strict mode, but in Chrome (V8) these methods isn't defined in strict mode. I don't know what is the actual specification. (I read some ECMA-262 5.1th Edition, but I can't find such section.)