Bug 1214048 - Improve callee-not-a-function error for spread calls. (r=jorendorff)
authorShu-yu Guo <shu@rfrn.org>
Mon, 26 Oct 2015 14:13:25 -0700
changeset 269658 a944e7136866c0a95a0ef18918d04840c4905bf5
parent 269657 f066d7c6b5566699ae3624b59b20ab51d9eda71e
child 269659 a6f01cc9c740cc536a8d4e73565e1ee0db55427b
push id15905
push usercbook@mozilla.com
push dateTue, 27 Oct 2015 09:59:36 +0000
treeherderfx-team@60acc8a9cfb5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1214048
milestone44.0a1
Bug 1214048 - Improve callee-not-a-function error for spread calls. (r=jorendorff)
js/src/vm/Interpreter.cpp
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -4515,16 +4515,41 @@ js::SpreadCallOperation(JSContext* cx, H
 
     if (length > ARGS_LENGTH_MAX) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
                              constructing ? JSMSG_TOO_MANY_CON_SPREADARGS
                                           : JSMSG_TOO_MANY_FUN_SPREADARGS);
         return false;
     }
 
+    // Do our own checks for the callee being a function, as Invoke uses the
+    // expression decompiler to decompile the callee stack operand based on
+    // the number of arguments. Spread operations have the callee at sp - 3
+    // when not constructing, and sp - 4 when constructing.
+    if (callee.isPrimitive()) {
+        return ReportIsNotFunction(cx, callee, 2 + constructing,
+                                   constructing ? CONSTRUCT : NO_CONSTRUCT);
+    }
+
+    const Class* clasp = callee.toObject().getClass();
+    if (MOZ_UNLIKELY(clasp != &JSFunction::class_)) {
+#if JS_HAS_NO_SUCH_METHOD
+        if (MOZ_UNLIKELY(clasp != &js_NoSuchMethodClass)) {
+#endif
+
+            if (!callee.toObject().callHook()) {
+                return ReportIsNotFunction(cx, callee, 2 + constructing,
+                                           constructing ? CONSTRUCT : NO_CONSTRUCT);
+            }
+
+#if JS_HAS_NO_SUCH_METHOD
+        }
+#endif
+    }
+
 #ifdef DEBUG
     // The object must be an array with dense elements and no holes. Baseline's
     // optimized spread call stubs rely on this.
     MOZ_ASSERT(aobj->getDenseInitializedLength() == length);
     MOZ_ASSERT(!aobj->isIndexed());
     for (uint32_t i = 0; i < length; i++)
         MOZ_ASSERT(!aobj->getDenseElement(i).isMagic());
 #endif