Bug 610038 - apply should not ignore indexed properties on the prototype (r=waldo)
authorLuke Wagner <lw@mozilla.com>
Tue, 09 Nov 2010 09:06:57 -0800
changeset 57744 ebffb2a709e5e07291fad9bcdf2f51b1f1a8d506
parent 57743 d988fa5af84546a617558275d8a2c9b3df38af47
child 57745 8ae5fce0f19b273d3b5248f5df4e177c76e2209e
push idunknown
push userunknown
push dateunknown
reviewerswaldo
bugs610038
milestone2.0b8pre
Bug 610038 - apply should not ignore indexed properties on the prototype (r=waldo)
js/src/jit-test/tests/basic/testHolesAndIndexPropertiesOnThePrototype.js
js/src/jsarray.cpp
js/src/methodjit/MonoIC.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testHolesAndIndexPropertiesOnThePrototype.js
@@ -0,0 +1,29 @@
+function f(x,y,z) {
+    return x + y + z;
+}
+
+Array.prototype[1] = 10;
+
+function g() {
+    var arr = [1, ,3,4,5,6];
+
+    for (var i = 0; i < 10; ++i) {
+        assertEq(f.apply(null, arr), 14);
+    }
+}
+g();
+
+Object.prototype[1] = 20;
+
+function h() {
+    delete arguments[1];
+    return f.apply(null, arguments);
+}
+assertEq(h(1,2,3), 24);
+
+function i() {
+    o = arguments;
+    delete o[1];
+    return f.apply(null, o);
+}
+assertEq(i(1,2,3), 24);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -391,22 +391,25 @@ GetElement(JSContext *cx, JSObject *obj,
     return JS_TRUE;
 }
 
 namespace js {
 
 bool
 GetElements(JSContext *cx, JSObject *aobj, jsuint length, Value *vp)
 {
-    if (aobj->isDenseArray() && length <= aobj->getDenseArrayCapacity()) {
+    if (aobj->isDenseArray() && length <= aobj->getDenseArrayCapacity() &&
+        !js_PrototypeHasIndexedProperties(cx, aobj)) {
+        /* The prototype does not have indexed properties so hole = undefined */
         Value *srcbeg = aobj->getDenseArrayElements();
         Value *srcend = srcbeg + length;
         for (Value *dst = vp, *src = srcbeg; src < srcend; ++dst, ++src)
             *dst = src->isMagic(JS_ARRAY_HOLE) ? UndefinedValue() : *src;
-    } else if (aobj->isArguments() && !aobj->isArgsLengthOverridden()) {
+    } else if (aobj->isArguments() && !aobj->isArgsLengthOverridden() &&
+               !js_PrototypeHasIndexedProperties(cx, aobj)) {
         /*
          * Two cases, two loops: note how in the case of an active stack frame
          * backing aobj, even though we copy from fp->argv, we still must check
          * aobj->getArgsElement(i) for a hole, to handle a delete on the
          * corresponding arguments element. See args_delProperty.
          */
         if (JSStackFrame *fp = (JSStackFrame *) aobj->getPrivate()) {
             JS_ASSERT(fp->numActualArgs() <= JS_ARGS_LENGTH_MAX);
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -984,17 +984,18 @@ ic::SplatApplyArgs(VMFrame &f)
      */
     if (f.u.call.lazyArgsObj) {
         Value *vp = f.regs.sp - 3;
         JS_ASSERT(JS_CALLEE(cx, vp).toObject().getFunctionPrivate()->u.n.native == js_fun_apply);
 
         JSStackFrame *fp = f.regs.fp;
         if (!fp->hasOverriddenArgs() &&
             (!fp->hasArgsObj() ||
-             (fp->hasArgsObj() && !fp->argsObj().isArgsLengthOverridden()))) {
+             (fp->hasArgsObj() && !fp->argsObj().isArgsLengthOverridden() &&
+              !js_PrototypeHasIndexedProperties(cx, &fp->argsObj())))) {
 
             uintN n = fp->numActualArgs();
             if (!BumpStack(f, n))
                 THROWV(false);
             f.regs.sp += n;
 
             Value *argv = JS_ARGV(cx, vp + 1 /* vp[1]'s argv */);
             if (fp->hasArgsObj())