Ok, I've made it somewhat more generic, but this was harder than expected to deal with all cases and not break something, while also a lot more complex than I would have liked. I'm also not completely happy with how it turned out, but since I've spent so much time rewriting it over and over to deal with corner cases, I figured some input would help.
More importantly, though, is that it's now mostly split from the Typed Array patch, except for the true typed array special cases needed.
Note that I did **not** add a new member in the vtbl: I couldn't find a use for it. I mean, sure, I can use it instead of checking for typed arrays but I think that's overkill since it's only two places (find_prop_name and jsdisp_define_property), and both would need two separate member functions in the vtbl in this regard. I don't think it's worth it.
Here's the main list of reasons it's complicated:
* Normal indexed props can be redefined if writable (e.g. `arguments`) to some arbitrary jsval. This means they won't even be `PROP_IDX` anymore, and so to handle them correctly (see first patch which adds a test) we need to lookup props first *before* attempting any optimization by avoiding `PROP_IDX` allocation. Which is why I had to integrate this whole thing in find_prop_name.
* Typed Arrays are special in three different ways, unlike any other indexed prop. This is actually per spec, and they're supposed to override **any** number as index, but native only does that for positive integers (not even negative), which simplifies it a bit for us. But still, they are actually special.
* The first special case is that they override any positive index, even if out of bounds. However, they **do** have bounds. The suggested override of `idx_length` to handle all indices does not work, because for instance when obtaining an ID or when testing if a prop "exists" (hasOwnProperty), they would be reported as available, even though they're **not**. A Typed Array with 5 elements does **not** have the property "10", even though you cannot redefine it. You also cannot access a prototype's "10" prop with it because, even if it doesn't exist and is out of bounds, it's still intercepted!
* The second special case is that they have differing behavior when a prop is out of bounds in some cases (deleting them, attempting to create props with them, or enumerating with prototypes, since they override them). They don't behave as normal "deleted" or "non-existing" props in those cases. This makes my patches have a bit of a kludge: I use `ret_idx` to signify this with an UINT_MAX despite returning DISP_E_UNKNOWNNAME (the latter works in most other cases directly), but it still needs special handling in those 3 special cases I mentioned (deletion, ensure_prop_name and enumeration). Sigh. I'm not too happy about this kludge, let me know if you have a better idea.
* The third special case is when defining a Typed Array prop. For out of bounds, as previously mentioned, it's simply ignored. But for props that do exist, they act as *setters*, which is completely unlike normal props. That is, defining a prop does coerce the value into the typed array's type! And defining accessors simply throws an error. This is handle in jsdisp_define_property as a special case.
Of course, all of those behaviors above are tested. And this is the best I could do for now while still passing all tests.