|
57 | 57 | Result JSError CheckLevel DiagnosticGroups |
58 | 58 | CommandLineRunner AnonymousFunctionNamingPolicy |
59 | 59 | JSModule JSModuleGraph SourceMap ProcessCommonJSModules |
60 | | - ES6ModuleLoader AbstractCompiler TransformAMDToCJSModule |
| 60 | + AbstractCompiler TransformAMDToCJSModule |
61 | 61 | ProcessEs6Modules CompilerInput] |
62 | 62 | [com.google.javascript.rhino Node] |
63 | 63 | [java.nio.file Path Paths Files StandardWatchEventKinds WatchKey |
|
74 | 74 | (defn random-string [length] |
75 | 75 | (apply str (take length (repeatedly random-char)))) |
76 | 76 |
|
77 | | -(util/compile-if |
78 | | - (.getConstructor ES6ModuleLoader |
79 | | - (into-array java.lang.Class |
80 | | - [java.util.List java.lang.Iterable])) |
81 | | - (do (def is-new-es6-loader? true) |
82 | | - (def default-module-root ES6ModuleLoader/DEFAULT_FILENAME_PREFIX)) |
83 | | - (def is-new-es6-loader? false)) |
84 | | - |
85 | | -(util/compile-if |
86 | | - (.getConstructor ES6ModuleLoader |
87 | | - (into-array java.lang.Class |
88 | | - [AbstractCompiler java.lang.String])) |
89 | | - (def is-old-es6-loader? true) |
90 | | - (def is-old-es6-loader? false)) |
91 | | - |
92 | | -(util/compile-if |
93 | | - (and (.getConstructor ProcessCommonJSModules |
94 | | - (into-array java.lang.Class |
95 | | - [com.google.javascript.jscomp.Compiler ES6ModuleLoader])) |
96 | | - (or is-new-es6-loader? is-old-es6-loader?)) |
97 | | - (def can-convert-commonjs? true) |
98 | | - (def can-convert-commonjs? false)) |
99 | | - |
100 | | -(util/compile-if |
101 | | - (and can-convert-commonjs? |
102 | | - (.getConstructor TransformAMDToCJSModule |
103 | | - (into-array java.lang.Class |
104 | | - [AbstractCompiler]))) |
105 | | - (def can-convert-amd? true) |
106 | | - (def can-convert-amd? false)) |
107 | | - |
108 | | -(util/compile-if |
109 | | - (and (.getConstructor ProcessEs6Modules |
110 | | - (into-array java.lang.Class |
111 | | - [com.google.javascript.jscomp.Compiler ES6ModuleLoader Boolean/TYPE])) |
112 | | - (or is-new-es6-loader? is-old-es6-loader?)) |
113 | | - (def can-convert-es6? true) |
114 | | - (def can-convert-es6? false)) |
115 | | - |
116 | 77 | ;; Closure API |
117 | 78 | ;; =========== |
118 | 79 |
|
|
1514 | 1475 |
|
1515 | 1476 | :else (str (random-string 5) ".js"))))) |
1516 | 1477 |
|
1517 | | -(defn get-js-module-root [js-file] |
1518 | | - (let [path (.getParent (io/file js-file))] |
1519 | | - (cond->> path |
1520 | | - (.startsWith path File/separator) (str ".") |
1521 | | - (not (.startsWith path (str "." File/separator))) (str "." File/separator) |
1522 | | - (not (.endsWith path File/separator)) (#(str % File/separator))))) |
1523 | | - |
1524 | | -(util/compile-if is-new-es6-loader? |
1525 | | - (defn make-es6-loader [source-files] |
1526 | | - (let [^List module-roots (list default-module-root) |
1527 | | - ^List compiler-inputs (map #(CompilerInput. %) source-files)] |
1528 | | - (ES6ModuleLoader. module-roots compiler-inputs))) |
1529 | | - (defn make-es6-loader [closure-compiler file] |
1530 | | - (let [module-root (get-js-module-root file)] |
1531 | | - (ES6ModuleLoader. closure-compiler module-root)))) |
1532 | | - |
1533 | | -(defn ^Node get-root-node [ijs closure-compiler] |
1534 | | - (let [^CompilerInput input (->> (deps/-source ijs) |
1535 | | - (js-source-file (:file ijs)) |
1536 | | - (CompilerInput.))] |
1537 | | - (.getAstRoot input closure-compiler))) |
1538 | | - |
1539 | | -(defn get-source-files [opts] |
1540 | | - (->> (concat (:foreign-libs opts) |
1541 | | - (:ups-foreign-libs opts)) |
1542 | | - (filter #(let [module-type (:module-type %)] |
1543 | | - (or (= module-type :amd) |
1544 | | - (= module-type :commonjs) |
1545 | | - (= module-type :es6)))) |
1546 | | - (map (fn [lib] |
1547 | | - (let [lib (deps/load-foreign-library lib)] |
1548 | | - (js-source-file (:file lib) (deps/-source lib))))))) |
1549 | | - |
1550 | | -(defmulti convert-js-module |
1551 | | - "Takes a JavaScript module as an IJavaScript and rewrites it into a Google |
1552 | | - Closure-compatible form. Returns an IJavaScript with the converted module |
| 1478 | +(defn get-source-files [js-modules] |
| 1479 | + (map (fn [lib] |
| 1480 | + (js-source-file (:file lib) (deps/-source lib))) |
| 1481 | + js-modules)) |
| 1482 | + |
| 1483 | +(defmulti convert-js-modules |
| 1484 | + "Takes a list JavaScript modules as an IJavaScript and rewrites them into a Google |
| 1485 | + Closure-compatible form. Returns list IJavaScript with the converted module |
1553 | 1486 | code set as source." |
1554 | | - (fn [{module-type :module-type :as ijs} opts] |
1555 | | - (if (and (= module-type :amd) can-convert-amd?) |
| 1487 | + (fn [module-type js-modules opts] |
| 1488 | + (if (= module-type :amd) |
1556 | 1489 | ;; AMD modules are converted via CommonJS modules |
1557 | 1490 | :commonjs |
1558 | 1491 | module-type))) |
|
1564 | 1497 | :language-in :language-out]) |
1565 | 1498 | (set-options (CompilerOptions.)))) |
1566 | 1499 |
|
1567 | | -(util/compile-if can-convert-commonjs? |
1568 | | - (defmethod convert-js-module :commonjs [ijs opts] |
1569 | | - (let [{:keys [file module-type]} ijs |
1570 | | - ^List externs '() |
1571 | | - ^List source-files (get-source-files opts) |
1572 | | - ^CompilerOptions options (make-convert-js-module-options opts) |
1573 | | - closure-compiler (doto (make-closure-compiler) |
1574 | | - (.init externs source-files options)) |
1575 | | - es6-loader (if is-new-es6-loader? |
1576 | | - (make-es6-loader source-files) |
1577 | | - (make-es6-loader closure-compiler file)) |
1578 | | - cjs (ProcessCommonJSModules. closure-compiler es6-loader) |
1579 | | - ^Node root (get-root-node ijs closure-compiler)] |
1580 | | - (util/compile-if can-convert-amd? |
1581 | | - (when (= module-type :amd) |
1582 | | - (.process (TransformAMDToCJSModule. closure-compiler) nil root))) |
1583 | | - (.process cjs nil root) |
1584 | | - (report-failure (.getResult closure-compiler)) |
1585 | | - (assoc ijs :source (.toSource closure-compiler root))))) |
1586 | | - |
1587 | | -(util/compile-if can-convert-es6? |
1588 | | - (defmethod convert-js-module :es6 [ijs opts] |
1589 | | - (let [{:keys [file]} ijs |
1590 | | - ^List externs '() |
1591 | | - ^List source-files (get-source-files opts) |
1592 | | - ^CompilerOptions options (doto (make-convert-js-module-options opts) |
1593 | | - (.setLanguageIn CompilerOptions$LanguageMode/ECMASCRIPT6) |
1594 | | - (.setLanguageOut CompilerOptions$LanguageMode/ECMASCRIPT5)) |
1595 | | - closure-compiler (doto (make-closure-compiler) |
1596 | | - (.init externs source-files options)) |
1597 | | - es6-loader (if is-new-es6-loader? |
1598 | | - (make-es6-loader source-files) |
1599 | | - (make-es6-loader closure-compiler file)) |
1600 | | - cjs (ProcessEs6Modules. closure-compiler es6-loader true) |
1601 | | - ^Node root (get-root-node ijs closure-compiler)] |
1602 | | - (.processFile cjs root) |
1603 | | - (report-failure (.getResult closure-compiler)) |
1604 | | - (assoc ijs :source (.toSource closure-compiler root))))) |
1605 | | - |
1606 | | -(defmethod convert-js-module :default [ijs opts] |
1607 | | - (ana/warning :unsupported-js-module-type @env/*compiler* ijs) |
1608 | | - ijs) |
| 1500 | +(defn get-js-root [closure-compiler] |
| 1501 | + (.getSecondChild (.getRoot closure-compiler))) |
| 1502 | + |
| 1503 | +(defn get-closure-sources |
| 1504 | + "Gets map of source file name -> Node, for files in Closure Compiler js root." |
| 1505 | + [closure-compiler] |
| 1506 | + (let [source-nodes (.children (get-js-root closure-compiler))] |
| 1507 | + (into {} (map (juxt #(.getSourceFileName ^Node %) identity) source-nodes)))) |
| 1508 | + |
| 1509 | +(defn add-converted-source [closure-compiler result-nodes {:keys [file] :as ijs}] |
| 1510 | + (assoc ijs :source (.toSource closure-compiler ^Node (get result-nodes file)))) |
| 1511 | + |
| 1512 | +(defmethod convert-js-modules :commonjs [module-type js-modules opts] |
| 1513 | + (let [^List externs '() |
| 1514 | + ^List source-files (get-source-files js-modules) |
| 1515 | + ^CompilerOptions options (doto (make-convert-js-module-options opts) |
| 1516 | + (.setProcessCommonJSModules true) |
| 1517 | + (.setTransformAMDToCJSModules (= module-type :amd))) |
| 1518 | + closure-compiler (doto (make-closure-compiler) |
| 1519 | + (.init externs source-files options))] |
| 1520 | + (.parse closure-compiler) |
| 1521 | + (report-failure (.getResult closure-compiler)) |
| 1522 | + (map (partial add-converted-source closure-compiler (get-closure-sources closure-compiler)) js-modules))) |
| 1523 | + |
| 1524 | +(defmethod convert-js-modules :es6 [module-type js-modules opts] |
| 1525 | + (let [^List externs '() |
| 1526 | + ^List source-files (get-source-files js-modules) |
| 1527 | + ^CompilerOptions options (doto (make-convert-js-module-options opts) |
| 1528 | + (.setLanguageIn CompilerOptions$LanguageMode/ECMASCRIPT6) |
| 1529 | + (.setLanguageOut CompilerOptions$LanguageMode/ECMASCRIPT5)) |
| 1530 | + closure-compiler (doto (make-closure-compiler) |
| 1531 | + (.init externs source-files options))] |
| 1532 | + (.parse closure-compiler) |
| 1533 | + (report-failure (.getResult closure-compiler)) |
| 1534 | + (map (partial add-converted-source closure-compiler (get-closure-sources closure-compiler)) js-modules))) |
| 1535 | + |
| 1536 | +(defmethod convert-js-modules :default [module-type js-modules opts] |
| 1537 | + (ana/warning :unsupported-js-module-type @env/*compiler* (first js-modules)) |
| 1538 | + js-modules) |
1609 | 1539 |
|
1610 | 1540 | (defmulti js-transforms |
1611 | 1541 | "Takes an IJavaScript with the source code set as source, transforms the |
|
1636 | 1566 | (when (and res (or ana/*verbose* (:verbose opts))) |
1637 | 1567 | (util/debug-prn "Copying" (str res) "to" (str out-file))) |
1638 | 1568 | (util/mkdirs out-file) |
1639 | | - (spit out-file |
1640 | | - (cond-> js |
1641 | | - (map? js) (assoc :source (deps/-source js)) |
1642 | | - (:preprocess js) (js-transforms opts) |
1643 | | - (:module-type js) (convert-js-module opts) |
1644 | | - true deps/-source)) |
| 1569 | + (spit out-file (deps/-source js)) |
1645 | 1570 | (when res |
1646 | 1571 | (.setLastModified ^File out-file (util/last-modified res)))) |
1647 | 1572 | (if (map? js) |
|
1908 | 1833 | (not (false? (:static-fns opts))) (assoc :static-fns true) |
1909 | 1834 | (not (false? (:optimize-constants opts))) (assoc :optimize-constants true))))) |
1910 | 1835 |
|
1911 | | -(defn- process-js-modules* |
1912 | | - [opts k] |
1913 | | - (let [js-modules (filter :module-type (k opts))] |
1914 | | - (reduce (fn [new-opts {:keys [file module-type] :as lib}] |
1915 | | - (if (or (and (= module-type :commonjs) can-convert-commonjs?) |
1916 | | - (and (= module-type :amd) can-convert-amd?) |
1917 | | - (and (= module-type :es6) can-convert-es6?)) |
1918 | | - (let [ijs (write-javascript opts (deps/load-foreign-library lib)) |
1919 | | - module-name (-> (deps/load-library (:out-file ijs)) first :provides first)] |
1920 | | - (doseq [provide (:provides ijs)] |
1921 | | - (swap! env/*compiler* |
1922 | | - #(update-in % [:js-module-index] assoc provide module-name))) |
1923 | | - (-> new-opts |
1924 | | - (update-in [:libs] (comp vec conj) (:out-file ijs)) |
1925 | | - (update-in [k] |
1926 | | - (comp vec (fn [libs] (remove #(= (:file %) file) libs)))))) |
1927 | | - new-opts)) |
1928 | | - opts js-modules))) |
1929 | | - |
1930 | 1836 | (defn process-js-modules |
1931 | 1837 | "Given the current compiler options, converts JavaScript modules to Google |
1932 | 1838 | Closure modules and writes them to disk. Adds mapping from original module |
1933 | 1839 | namespace to new module namespace to compiler env. Returns modified compiler |
1934 | 1840 | options where new modules are passed with :libs option." |
1935 | 1841 | [opts] |
1936 | | - (-> opts |
1937 | | - (process-js-modules* :foreign-libs) |
1938 | | - (process-js-modules* :ups-foreign-libs))) |
| 1842 | + (let [;; Modules from both :foreign-libs (compiler options) and :ups-foreign-libs (deps.cljs) |
| 1843 | + ;; are processed together, so that files from both sources can depend on each other. |
| 1844 | + ;; e.g. commonjs module in :foreign-libs can depend on commonjs module from :ups-foreign-libs. |
| 1845 | + js-modules (filter :module-type (concat (:foreign-libs opts) (:ups-foreign-libs opts)))] |
| 1846 | + (if (seq js-modules) |
| 1847 | + (util/measure |
| 1848 | + "Process JS modules" |
| 1849 | + (let [;; Load all modules - add :source so preprocessing and conversion can access it |
| 1850 | + js-modules (map (fn [lib] |
| 1851 | + (let [js (deps/load-foreign-library lib)] |
| 1852 | + (assoc js :source (deps/-source js)))) |
| 1853 | + js-modules) |
| 1854 | + js-modules (map (fn [js] |
| 1855 | + (if (:preprocess js) |
| 1856 | + (js-transforms js opts) |
| 1857 | + js)) |
| 1858 | + js-modules) |
| 1859 | + ;; Conversion is done per module-type, because Compiler needs to process e.g. all CommonJS |
| 1860 | + ;; modules on one go, so it can handle the dependencies between modules. |
| 1861 | + ;; Amdjs modules are converted separate from CommonJS modules so they can't |
| 1862 | + ;; depend on each other. |
| 1863 | + modules-per-type (group-by :module-type js-modules) |
| 1864 | + js-modules (mapcat (fn [[module-type js-modules]] |
| 1865 | + (convert-js-modules module-type js-modules opts)) |
| 1866 | + modules-per-type)] |
| 1867 | + |
| 1868 | + ;; Write modules to disk, update compiler state and build new options |
| 1869 | + (reduce (fn [new-opts {:keys [file] :as ijs}] |
| 1870 | + (let [ijs (write-javascript opts ijs) |
| 1871 | + module-name (-> (deps/load-library (:out-file ijs)) first :provides first)] |
| 1872 | + (doseq [provide (:provides ijs)] |
| 1873 | + (swap! env/*compiler* |
| 1874 | + #(update-in % [:js-module-index] assoc provide module-name))) |
| 1875 | + (-> new-opts |
| 1876 | + (update-in [:libs] (comp vec conj) (:out-file ijs)) |
| 1877 | + ;; js-module might be defined in either, so update both |
| 1878 | + (update-in [:foreign-libs] (comp vec (fn [libs] (remove #(= (:file %) file) libs)))) |
| 1879 | + (update-in [:ups-foreign-libs] (comp vec (fn [libs] (remove #(= (:file %) file) libs))))))) |
| 1880 | + opts js-modules))) |
| 1881 | + opts))) |
1939 | 1882 |
|
1940 | 1883 | (defn build |
1941 | 1884 | "Given a source which can be compiled, produce runnable JavaScript." |
|
0 commit comments