7

This question is related to What are the best practices to follow when declaring an array in Javascript?


Let's say a client, let's call them "D. B. Cooper", has a first requirement that the following code must run before any other JavaScript code:

Array = function(){
    alert('Mwahahahaha');
};

Furthermore, Cooper requires that custom functions must be added to the built in Array object (not the hijacked one). For example, if Array was unhijacked, this would be done with:

Array.prototype.coolCustomFunction = function(){
    alert('I have ' + this.length + ' elements!  Cool!');
};

Which would afford:

var myArray = [];
myArray.coolCustomFunction();

However, this is not compatible with the first requirement. Thus, how can you best fulfill both of D. B. Cooper's requirements?

Note: D.B. even wrote a test fiddle to help make sure solutions meet his requirements...what a guy!


Update: For those of you who like a challenge: please try to find an unhijackable cross-browser solution to this problem. For example, here's an even more hijacked test case (thanks for reformatting this Bergi) that hijacks Array, Object, Array.prototype.constructor, and Object.prototype.constructor. Thus far, it looks like there may be a browser-specific solution to this (see Bergi's comment on his answer, and let us know if you find a way to hijack it in FF), but it is unclear at this point if there is a cross-browser solution to this.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Briguy37
  • 8,342
  • 3
  • 33
  • 53

3 Answers3

3

Since Array is not necessarily equal to [].constructor, you could use [].constructor to refer to the original Array function since this is hardwired and Array = function(){} won't alter it.

Array = function () { alert("foo")};

// this will always point to the original Array
[].constructor.prototype.foo = "bar";

var myArray = [0, 1];
alert(myArray.foo) // alerts "bar"

http://jsfiddle.net/yXPJ8/5/

Torsten Walter
  • 5,614
  • 23
  • 26
  • Your first solution makes D.B. happy :) (the second would violate his first requirement) – Briguy37 Jul 17 '12 at 17:04
  • Okay, missed the "before any other" bit. ;) – Torsten Walter Jul 17 '12 at 17:09
  • `[].constructor = function(){};` still only refers to the constructor of that instance. a subsequent call to `[].constructor` would have an intact reference since it is created new for each instance. You could however try to overwrite the `constructor.prototype` which would do nothing since it is protected (unless the JS engine is broken). – Torsten Walter Jul 17 '12 at 17:39
  • @TorstenWalter: (the good) `Array.prototype.constructor` is *not* protected (you can easily check that), and that's exactly what I mean. – Bergi Jul 17 '12 at 17:50
  • 1
    @Bergi Nice catch - Interestingly enough even though `Array.prototype.constructor` will point to a different function creating an array still works. If you remove all the references to the prototype's constructor, then of course there is no way to get it back without reloading the page or opening a new window and getting it from there. `var win = window.open(); Array.prototype.constructor = win.Array.prototype.constructor;` – Torsten Walter Jul 17 '12 at 18:06
  • 1
    @TorstenWalter: Although I can't get it to work. Can you demonstrate this [in here](http://jsfiddle.net/yXPJ8/9/)? – Bergi Jul 17 '12 at 18:31
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/14023/discussion-between-torsten-walter-and-bergi) – Torsten Walter Jul 17 '12 at 19:26
3

Whatever your Array function/constructor is, the literal syntax for arrays will always generate "real" arrays with their [[prototype]] set to the native array prototype object (once, this was a security vulnerability). So, you can always access that by using

Object.getPrototypeOf([])

even if Array or [].constructor are hijacked. (Will of course not work when Object is hijacked, then it get's really complicated)

(Brought D.B. down!)


If you want to use a workaround, in FF the following line will always work (and is not hijackable):

[].__proto__.coolCustomFunction = coolCustomFunction;
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Interesting! I decided to try hijacking the constructor of the array object: `[].constructor.prototype.constructor = ..`, and that caused Torsten's solution to fail. Then, I hijacked Object and that caused your solution to fail, but it works with `({}).constructor`. Then I hijacked the constructor of the Object object: `({}).constructor.prototype.constructor = ..` which caused everything to fail. At that point, I'm stuck, so I haven't found an un-hijackable solution to this yet :) Here's an updated fiddle: http://jsfiddle.net/briguy37/yXPJ8/8/ – Briguy37 Jul 17 '12 at 17:50
  • 1
    That was exactly my line of thought :-) However, I've [restructed your heavy-hijacked fiddle](http://jsfiddle.net/yXPJ8/9/) to be more readable. Now, you can only use non-standard `__proto__` in FF (unhijackable, I think) – Bergi Jul 17 '12 at 18:14
  • Very nice, I don't see a way to hijack that in FF either! I'm still interested to see if @Torsten's suggestion to get the constructor from a new window object or another method could lead to a cross-browser un-hijackable solution to this. – Briguy37 Jul 17 '12 at 18:50
  • Actually, `__proto__` is just a getter/setter property not a built-in. You can `delete Object.prototype.__proto__`. – Bergi Jul 09 '14 at 14:04
1

Yes ... you just did ... but you created the array using [] .. if you use new Array() it works fine ...

See example here

Manse
  • 37,765
  • 10
  • 83
  • 108
  • 2
    Sorry, that does not fulfill the test case. You are not allowed to edit it. – Briguy37 Jul 17 '12 at 16:47
  • @Briguy37 then it cant - you cannot overwrite the `[]` function - this points to an internal constructor – Manse Jul 17 '12 at 16:49
  • That may very well be the case. However, if you modify `Array`'s prototype to add a function before you hijack it, you can use that function on an object created with `[]`. Thus, I was wondering if there was a way to do this after Array was hijacked. – Briguy37 Jul 17 '12 at 16:53