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
View
@@ -15,3 +15,6 @@ closure
*.zip
clojurescript_release_*
closure-release-*
+.lein-repl-history
+.nrepl-port
+.nrepl-repl-history
View
@@ -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.