         prefix (protocol-prefix p)
         _ (core/doseq [[mname & arities] methods]
             (when (some #{0} (map count (filter vector? arities)))
-              (throw (Exception.
-                       (core/str "Invalid protocol, " psym
-                                 " defines method " mname " with arity 0")))))
+              (throw
+                #?(:clj (Exception.
+                          (core/str "Invalid protocol, " psym
+                            " defines method " mname " with arity 0"))
+                   :cljs (js/Error.
+                           (core/str "Invalid protocol, " psym
+                             " defines method " mname " with arity 0"))))))
         expand-sig (fn [fname slot sig]
                      `(~sig
                        (if (and ~(first sig) (. ~(first sig) ~(symbol (core/str "-" slot)))) ;; Property access needed here.

(defn- ^{:dynamic true} assert-valid-fdecl
  "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn."
  [fdecl]
  (when (empty? fdecl) (throw (IllegalArgumentException.
                                "Parameter declaration missing")))
  (core/let [argdecls (map
                   #(if (seq? %)
                     (first %)
                     (throw (IllegalArgumentException.
                              (if (seq? (first fdecl))
                                (core/str "Invalid signature \""
                                  %
                                  "\" should be a list")
                                (core/str "Parameter declaration \""
                                  %
                                  "\" should be a vector")))))
                   fdecl)
        bad-args (seq (remove #(vector? %) argdecls))]
    (when bad-args
      (throw (IllegalArgumentException.
               (core/str "Parameter declaration \"" (first bad-args)
                         "\" should be a vector"))))))

(def
  ^{:private true}

                                 ifn (first inline)
                                 iname (second inline)]
                        ;; same as: (if (and (= 'fn ifn) (not (symbol? iname))) ...)
                        (if (if #?(:clj (clojure.lang.Util/equiv 'fn ifn)
                                   :cljs (= 'fn ifn))
                              (if #?(:clj (core/instance? clojure.lang.Symbol iname)
                                     :cljs (core/instance? Symbol iname)) false true))
                          ;; inserts the same fn name to the inline fn if it does not have one
                          (assoc m :inline (cons ifn (cons (clojure.lang.Symbol/intern (.concat (.getName ^clojure.lang.Symbol name) "__inliner"))
                                                       (next inline))))
