Skip to content
Permalink
Browse files

CLJS-674: Relativize source files in source maps while checking intra…

…nsigents

Check option intransigents around :output-to, :output-dir,
:source-map, and :source-map-path and properly relativize source-map
source files in a host independent fashion.
  • Loading branch information...
timvisher authored and swannodette committed Nov 20, 2013
1 parent 2b9424a commit 047dbb3d2bd7c3a2e00805ec2f2480e449451521
Showing with 120 additions and 34 deletions.
  1. +3 −0 .gitignore
  2. +77 −10 src/clj/cljs/closure.clj
  3. +40 −24 src/clj/cljs/source_map.clj
@@ -15,3 +15,6 @@ closure
*.zip
clojurescript_release_*
closure-release-*
.lein-repl-history
.nrepl-port
.nrepl-repl-history
@@ -720,9 +720,8 @@
;; compiler.getSourceMap().reset()
(let [source (.toSource closure-compiler)]
(when-let [name (:source-map opts)]
(let [out (io/writer name)]
(.appendTo (.getSourceMap closure-compiler) out name)
(.close out))
(with-open [out (io/writer name)]
(.appendTo (.getSourceMap closure-compiler) out name))
(let [sm-json (-> (io/file name) slurp
(json/read-str :key-fn keyword))
closure-source-map (sm/decode sm-json)]
@@ -758,12 +757,13 @@
(assoc merged path (get closure-source-map path))))
merged)))
(spit (io/file name)
(sm/encode merged
{:lines (+ (:lineCount sm-json) 2)
:file (:file sm-json)
:output-dir (output-directory opts)
:source-map-path (:source-map-path opts)
:relpaths relpaths}))))))
(sm/encode merged
{:lines (+ (:lineCount sm-json) 2)
:file (:file sm-json)
:output-dir (output-directory opts)
:source-map-path (:source-map-path opts)
:source-map (:source-map opts)
:relpaths relpaths}))))))
source)
(report-failure result))))

@@ -974,7 +974,70 @@
(str js "\n//# sourceMappingURL=" (path-relative-to (io/file output-to) {:url source-map})))
js))


(defn absolute-path? [path]
(.isAbsolute (io/file path)))

(defn absolute-parent [path]
(.getParent (.getAbsoluteFile (io/file path))))

(defn in-same-dir? [path-1 path-2]
"Checks that path-1 and path-2 are siblings in the same logical directory."
(= (absolute-parent path-1)
(absolute-parent path-2)))

(defn same-or-subdirectory-of? [dir path]
"Checks that path names a file or directory that is the dir or a subdirectory there of."
(let [dir-path (.toAbsolutePath (.toPath (io/file dir)))
path-path (.toAbsolutePath (.toPath (io/file path)))]
(.startsWith path-path dir-path)))

(defn check-output-to [{:keys [output-to] :as opts}]
(when (contains? opts :output-to)
(assert (or (string? output-to)
(= :print output-to))
(format ":output-to `%s` must specify a file or be `:print`"
(pr-str output-to))))
true)

(defn check-output-dir [{:keys [output-dir] :as opts}]
(when (contains? opts :output-dir)
(assert (string? output-dir)
(format ":output-dir `%s` must specify a directory"
(pr-str output-dir)))
(assert (contains? opts :output-to)
(format ":output-dir cannot be specified without also specifying :output-to")))
true)

(defn check-source-map [{:keys [output-to source-map output-dir] :as opts}]
"When :source-map is specified in opts, "
(when (contains? opts :source-map)
(assert (and (contains? opts :output-to)
(contains? opts :output-dir))
":source-map cannot be specied without also specifying :output-to and :output-dir")
(assert (string? source-map)
(format ":source-map `%s` must specify a file in the same directory as :output-to `%s`"
(pr-str source-map)
(pr-str output-to)))
(assert (same-or-subdirectory-of? (absolute-parent output-to) output-dir)
(format ":output-dir `%s` must specify a directory in :output-to's parent `%s`"
(pr-str output-dir)
(pr-str (absolute-parent output-to))))
(assert (in-same-dir? source-map output-to)
(format ":source-map `%s` must specify a file in the same directory as :output-to `%s`"
(pr-str source-map)
(pr-str output-to))))
true)

(defn check-source-map-path [{:keys [source-map-path] :as opts}]
(when (contains? opts :source-map-path)
(assert (string? source-map-path)
(format ":source-map-path `%s` must be a directory"
source-map-path))
(assert (and (contains? opts :output-to)
(contains? opts :output-dir)
(contains? opts :source-map))
":source-map-path cannot be specified without also specifying :output-to, :output-dir, and :source-map"))
true)

(defn build
"Given a source which can be compiled, produce runnable JavaScript."
@@ -996,6 +1059,10 @@
emit-constants (or (and (= (:optimizations opts) :advanced)
(not (false? (:optimize-constants opts))))
(:optimize-constants opts))]
(check-output-to opts)
(check-output-dir opts)
(check-source-map opts)
(check-source-map-path opts)
(swap! compiler-env assoc-in [:opts :emit-constants] emit-constants)
(binding [ana/*cljs-static-fns*
(or (and (= (:optimizations opts) :advanced)
@@ -152,13 +152,27 @@
[] cols)))
[] lines)))

(defn relativize-path [path {:keys [output-dir source-map-path relpaths]}]
(cond
(re-find #"\.jar!/" path)
(str (or source-map-path output-dir) (second (string/split path #"\.jar!")))
(defn relativize-path [path {:keys [output-dir source-map-path source-map relpaths]}]
(let [bare-munged-path (cond
(re-find #"\.jar!/" path)
(str (or source-map-path output-dir) (second (string/split path #"\.jar!")))

:else
(str (or source-map-path output-dir) "/" (get relpaths path))))
:else
(str (or source-map-path output-dir) "/" (get relpaths path)))]
(cond source-map-path
bare-munged-path

:default
(let [unrelativized-jpath (-> bare-munged-path
io/file
.toPath
.toAbsolutePath)
source-map-parent-jpath (-> source-map
io/file
.toPath
.toAbsolutePath
.getParent)]
(str (.relativize source-map-parent-jpath unrelativized-jpath))))))

(defn encode
"Take an internal source map representation represented as nested
@@ -197,24 +211,26 @@
(doseq [[line cols] lines]
(doseq [[col infos] cols]
(encode-cols infos source-idx line col))))
(with-out-str
(json/pprint
{"version" 3
"file" (:file opts)
"sources" (into []
(let [paths (keys m)
f (if (:output-dir opts)
#(relativize-path % opts)
#(last (string/split % #"/")))]
(map f paths)))
"lineCount" (:lines opts)
"mappings" (->> (lines->segs @lines)
(map #(string/join "," %))
(string/join ";"))
"names" (into []
(map (set/map-invert @names->idx)
(range (count @names->idx))))}
:escape-slash false))))
(let [source-map-file-contents
{"version" 3
"file" (:file opts)
"sources" (into []
(let [paths (keys m)
f (if (or (:output-dir opts) (:source-map-path opts))
#(relativize-path % opts)
#(last (string/split % #"/")))]
(map f paths)))
"lineCount" (:lines opts)
"mappings" (->> (lines->segs @lines)
(map #(string/join "," %))
(string/join ";"))
"names" (into []
(map (set/map-invert @names->idx)
(range (count @names->idx))))}]
(with-out-str
(json/pprint
source-map-file-contents
:escape-slash false)))))

;; -----------------------------------------------------------------------------
;; Merging

0 comments on commit 047dbb3

Please sign in to comment.
You can’t perform that action at this time.