Skip to content

Commit ca5dda1

Browse files
mfikesswannodette
authored andcommitted
CLJS-1521: Self-host: Macro namespaces cannot be aliased
Use find-macro-ns when looking for macro expander so that aliased macro namespaces can properly resolve in bootstrap. Adds unit tests excercising the various ways you can require and make use of macros.
1 parent 16666f3 commit ca5dda1

File tree

2 files changed

+183
-1
lines changed

2 files changed

+183
-1
lines changed

src/main/clojure/cljs/analyzer.cljc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2322,7 +2322,8 @@
23222322
:cljs [(identical? "clojure.repl" nstr) (find-macros-ns 'cljs.repl)])
23232323
#?@(:clj [(.contains nstr ".") (find-ns (symbol nstr))]
23242324
:cljs [(goog.string/contains nstr ".") (find-macros-ns (symbol nstr))])
2325-
:else (some-> env :ns :require-macros (get (symbol nstr)) find-ns)))
2325+
:else (some-> env :ns :require-macros (get (symbol nstr)) #?(:clj find-ns
2326+
:cljs find-macros-ns))))
23262327

23272328
(defn get-expander* [sym env]
23282329
(when-not (or (not (nil? (gets env :locals sym))) ; locals hide macros

src/test/self/self_host/test.cljs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,187 @@
189189
(is (= "1\n2\n" value))
190190
(inc! l))))))
191191

192+
(deftest test-load-and-invoke-macros
193+
(async done
194+
(let [l (latch 9 done)]
195+
;; Normal require macros
196+
(let [st (cljs/empty-state)]
197+
(cljs/eval-str st
198+
"(ns cljs.user (:require-macros foo.core))"
199+
nil
200+
{:eval node-eval
201+
:load (fn [_ cb] (cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"}))}
202+
(fn [{:keys [value error]}]
203+
(is (nil? error))
204+
(cljs/eval-str st
205+
"(foo.core/add 1 2)"
206+
nil
207+
{:eval node-eval
208+
:context :expr}
209+
(fn [{:keys [error value]}]
210+
(is (nil? error))
211+
(is (= 3 value))
212+
(inc! l))))))
213+
(let [st (cljs/empty-state)]
214+
;; Refer macro symbol
215+
(cljs/eval-str st
216+
"(ns cljs.user (:require-macros [foo.core :refer [add]]))"
217+
nil
218+
{:eval node-eval
219+
:load (fn [_ cb] (cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"}))}
220+
(fn [{:keys [value error]}]
221+
(is (nil? error))
222+
(cljs/eval-str st
223+
"(add 1 3)"
224+
nil
225+
{:eval node-eval
226+
:context :expr}
227+
(fn [{:keys [error value]}]
228+
(is (nil? error))
229+
(is (= 4 value))
230+
(inc! l))))))
231+
(let [st (cljs/empty-state)]
232+
;; Alias the macro namespace
233+
(cljs/eval-str st
234+
"(ns cljs.user (:require-macros [foo.core :as foo]))"
235+
nil
236+
{:eval node-eval
237+
:load (fn [_ cb] (cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"}))}
238+
(fn [{:keys [value error]}]
239+
(is (nil? error))
240+
(cljs/eval-str st
241+
"(foo/add 1 5)"
242+
nil
243+
{:eval node-eval
244+
:context :expr}
245+
(fn [{:keys [error value]}]
246+
(is (nil? error))
247+
(is (= 6 value))
248+
(inc! l))))))
249+
(let [st (cljs/empty-state)]
250+
;; Use instead of require
251+
(cljs/eval-str st
252+
"(ns cljs.user (:use-macros [foo.core :only [add]]))"
253+
nil
254+
{:eval node-eval
255+
:load (fn [_ cb] (cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"}))}
256+
(fn [{:keys [value error]}]
257+
(is (nil? error))
258+
(cljs/eval-str st
259+
"(add 1 8)"
260+
nil
261+
{:eval node-eval
262+
:context :expr}
263+
(fn [{:keys [error value]}]
264+
(is (nil? error))
265+
(is (= 9 value))
266+
(inc! l))))))
267+
(let [st (cljs/empty-state)]
268+
;; Employ inline macro specification sugar (include)
269+
(cljs/eval-str st
270+
"(ns cljs.user (:require [foo.core :include-macros true]))"
271+
nil
272+
{:eval node-eval
273+
:load (fn [{:keys [macros]} cb]
274+
(if macros
275+
(cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"})
276+
(cb {:lang :clj :source "(ns foo.core)"})))}
277+
(fn [{:keys [value error]}]
278+
(is (nil? error))
279+
(cljs/eval-str st
280+
"(foo.core/add 1 13)"
281+
nil
282+
{:eval node-eval
283+
:context :expr}
284+
(fn [{:keys [error value]}]
285+
(is (nil? error))
286+
(is (= 14 value))
287+
(inc! l))))))
288+
(let [st (cljs/empty-state)]
289+
;; Employ inline macro specification sugar (include with alias)
290+
(cljs/eval-str st
291+
"(ns cljs.user (:require [foo.core :as foo :include-macros true]))"
292+
nil
293+
{:eval node-eval
294+
:load (fn [{:keys [macros]} cb]
295+
(if macros
296+
(cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"})
297+
(cb {:lang :clj :source "(ns foo.core)"})))}
298+
(fn [{:keys [value error]}]
299+
(is (nil? error))
300+
(cljs/eval-str st
301+
"(foo/add 1 21)"
302+
nil
303+
{:eval node-eval
304+
:context :expr}
305+
(fn [{:keys [error value]}]
306+
(is (nil? error))
307+
(is (= 22 value))
308+
(inc! l))))))
309+
(let [st (cljs/empty-state)]
310+
;; Employ inline macro specification sugar (refer)
311+
(cljs/eval-str st
312+
"(ns cljs.user (:require [foo.core :refer-macros [add]]))"
313+
nil
314+
{:eval node-eval
315+
:load (fn [{:keys [macros]} cb]
316+
(if macros
317+
(cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"})
318+
(cb {:lang :clj :source "(ns foo.core)"})))}
319+
(fn [{:keys [value error]}]
320+
(is (nil? error))
321+
(cljs/eval-str st
322+
"(add 1 34)"
323+
nil
324+
{:eval node-eval
325+
:context :expr}
326+
(fn [{:keys [error value]}]
327+
(is (nil? error))
328+
(is (= 35 value))
329+
(inc! l))))))
330+
(let [st (cljs/empty-state)]
331+
;; Employ inline macro specification sugar (refer with alias)
332+
(cljs/eval-str st
333+
"(ns cljs.user (:require [foo.core :as foo :refer-macros [add]]))"
334+
nil
335+
{:eval node-eval
336+
:load (fn [{:keys [macros]} cb]
337+
(if macros
338+
(cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"})
339+
(cb {:lang :clj :source "(ns foo.core)"})))}
340+
(fn [{:keys [value error]}]
341+
(is (nil? error))
342+
(cljs/eval-str st
343+
"(+ (add 2 3) (foo/add 5 8))"
344+
nil
345+
{:eval node-eval
346+
:context :expr}
347+
(fn [{:keys [error value]}]
348+
(is (nil? error))
349+
(is (= 18 value))
350+
(inc! l))))))
351+
(let [st (cljs/empty-state)]
352+
;; Rely on implicit macro loading (ns loads its own macros)
353+
(cljs/eval-str st
354+
"(ns cljs.user (:require foo.core))"
355+
nil
356+
{:eval node-eval
357+
:load (fn [{:keys [macros]} cb]
358+
(if macros
359+
(cb {:lang :clj :source "(ns foo.core) (defmacro add [a b] `(+ ~a ~b))"})
360+
(cb {:lang :clj :source "(ns foo.core (:require-macros foo.core))"})))}
361+
(fn [{:keys [value error]}]
362+
(is (nil? error))
363+
(cljs/eval-str st
364+
"(foo.core/add 100 200)"
365+
nil
366+
{:eval node-eval
367+
:context :expr}
368+
(fn [{:keys [error value]}]
369+
(is (nil? error))
370+
(is (= 300 value))
371+
(inc! l)))))))))
372+
192373
(deftest test-eval-str-with-require-macros
193374
(async done
194375
(let [l (latch 2 done)]

0 commit comments

Comments
 (0)