Skip to content

Commit

Permalink
ensure the emittance of properly escaped non ascii characters (includ…
Browse files Browse the repository at this point in the history
…ing the full unicode range) for maximum host compatibility (Internet Explorer), fixing CLJS-139, 133 and 56
  • Loading branch information
shyblower authored and swannodette committed Feb 25, 2012
1 parent 251a300 commit 965dc50
Showing 1 changed file with 40 additions and 9 deletions.
49 changes: 40 additions & 9 deletions src/clj/cljs/compiler.clj
Expand Up @@ -11,7 +11,8 @@
(ns cljs.compiler
(:refer-clojure :exclude [munge macroexpand-1])
(:require [clojure.java.io :as io]
[clojure.string :as string]))
[clojure.string :as string])
(:import java.lang.StringBuilder))

(declare resolve-var)
(require 'cljs.core)
Expand Down Expand Up @@ -154,30 +155,60 @@
(defn- comma-sep [xs]
(apply str (interpose "," xs)))

(defn- escape-char [^Character c]
(let [cp (.hashCode c)]
(case cp
; Handle printable escapes before ASCII
34 "\\\""
92 "\\\\"
47 "\\/"
; Handle non-printable escapes
8 "\\b"
12 "\\f"
10 "\\n"
13 "\\r"
9 "\\t"
(if (< 31 cp 127)
c ; Print simple ASCII characters
(format "\\u%04X" cp))))) ; Any other character is Unicode

(defn- escape-string [^CharSequence s]
(let [sb (StringBuilder. (count s))]
(doseq [c s]
(.append sb (escape-char c)))
(.toString sb)))

(defn- wrap-in-double-quotes [x]
(str \" x \"))

(defmulti emit-constant class)
(defmethod emit-constant nil [x] (print "null"))
(defmethod emit-constant Long [x] (print x))
(defmethod emit-constant Integer [x] (print x)) ; reader puts Integers in metadata
(defmethod emit-constant Double [x] (print x))
(defmethod emit-constant String [x] (pr x))
(defmethod emit-constant String [x]
(print (wrap-in-double-quotes (escape-string x))))
(defmethod emit-constant Boolean [x] (print (if x "true" "false")))
(defmethod emit-constant Character [x] (pr (str x)))
(defmethod emit-constant Character [x]
(print (wrap-in-double-quotes (escape-char x))))

(defmethod emit-constant java.util.regex.Pattern [x]
(let [[_ flags pattern] (re-find #"^(?:\(\?([idmsux]*)\))?(.*)" (str x))]
(print (str \/ (.replaceAll (re-matcher #"/" pattern) "\\\\/") \/ flags))))

(defmethod emit-constant clojure.lang.Keyword [x]
(pr (str \uFDD0 \'
(if (namespace x)
(str (namespace x) "/") "")
(name x))))
(print (str \" "\\uFDD0" \'
(if (namespace x)
(str (namespace x) "/") "")
(name x)
\")))

(defmethod emit-constant clojure.lang.Symbol [x]
(pr (str \uFDD1 \'
(print (str \" "\\uFDD1" \'
(if (namespace x)
(str (namespace x) "/") "")
(name x))))
(name x)
\")))

(defn- emit-meta-constant [x string]
(if (meta x)
Expand Down

0 comments on commit 965dc50

Please sign in to comment.