Skip to content

Instantly share code, notes, and snippets.

@cemerick
Last active December 31, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cemerick/7998162 to your computer and use it in GitHub Desktop.
Save cemerick/7998162 to your computer and use it in GitHub Desktop.
JS natives referenced via `this` do not dispatch on protocols properly
; using 2120
(defprotocol P (m [x]))
(extend-protocol P
number
(m [x] (- x)))
(set! (.-foo js/Number.prototype)
#(this-as this (m this)))
cljs.user> (def j 5)
5
cljs.user> (m j)
-5
cljs.user> (.foo j)
"Error evaluating:" (.foo (inc 5)) :as "(5 + 1).foo();\n"
#<Error: No protocol method P.m defined for type object: 6>
Error: No protocol method P.m defined for type object: 6
at :17
at m (:20)
at :1
at :1
at :5
nil
;; no idea why, but producing the same number via parsing causes the dispatch to succeed
(set! (.-foo js/Number.prototype)
#(this-as this
(m (js/parseFloat (str this)))))
cljs.user> (.foo j)
-5
(ns prototype-dispatch)
(defprotocol P (m [x]))
(extend-protocol P
number
(m [x] (- x)))
(set! (.-foo js/Number.prototype)
#(this-as this (m this)))
(def j 5)
(defn ^:export -main [& args]
(.log js/console (m j))
(.log js/console (.foo j)))
;(set! *main-cli-fn* -main)
(try
(-main)
((aget js/phantom "exit") 0)
(catch js/Error e
(.log js/console e)
((aget js/phantom "exit") 1)))
rm -rf out .repl target
bin/cljsc prototype_dispatch.cljs '{:optimizations :whitespace}' > prototype_dispatch.whitespace.js
phantomjs prototype_dispatch.whitespace.js
# bin/cljsc prototype_dispatch.cljs '{:optimizations :advanced}' > prototype_dispatch.advanced.js
# phantomjs prototype_dispatch.advanced.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment