Skip to content

Commit 637ef83

Browse files
authored
Fix #343: support :reload for reloading CLJS namespaces and JS code (#369)
1 parent a68d2c9 commit 637ef83

File tree

6 files changed

+72
-26
lines changed

6 files changed

+72
-26
lines changed

.github/workflows/ci.yml

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ on: [push, pull_request]
44

55
jobs:
66
build:
7+
78
runs-on: windows-latest
9+
810
env:
911
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
12+
1013
steps:
1114
- name: Git checkout
1215
uses: actions/checkout@v4
@@ -34,8 +37,8 @@ jobs:
3437
cli: latest
3538
bb: latest
3639

37-
- name: Setup tmate session
38-
uses: mxschmitt/action-tmate@v3
40+
# - name: Setup tmate session
41+
# uses: mxschmitt/action-tmate@v3
3942

4043
- name: Run tests
4144
run: |

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ For a list of breaking changes, check [here](#breaking-changes).
44

55
[Nbb](https://github.com/babashka/nbb): Scripting in Clojure on Node.js using [SCI](https://github.com/babashka/sci)
66

7+
## 1.3.195 (2024-11-07)
8+
9+
- [#343](https://github.com/babashka/nbb/issues/343): support `:reload` for reloading CLJS namespaces and JS code
10+
711
## 1.3.194 (2024-10-23)
812

913
- Fix issue with loading `cljs.spec.alpha` by upgrading shadow-cljs

src/nbb/core.cljs

+43-24
Original file line numberDiff line numberDiff line change
@@ -138,19 +138,28 @@
138138
(defn register-module [mod internal-name]
139139
(swap! loaded-modules assoc internal-name mod))
140140

141-
(defn load-js-module [libname internal-name]
141+
(defn debug [& xs]
142+
(binding [*print-fn* *print-err-fn*]
143+
(apply prn xs)))
144+
145+
(defn load-js-module [libname internal-name reload?]
142146
(-> (if-let [resolve (:resolve @ctx)]
143147
(-> (resolve libname)
144148
(.catch
145149
(fn [_]
146150
((.-resolve (:require @ctx)) libname))))
147151
(js/Promise.resolve ((.-resolve (:require @ctx)) libname)))
148152
(.then (fn [path]
149-
(esm/dynamic-import
150-
(let [path (if (and windows? (fs/existsSync path))
151-
(str (url/pathToFileURL path))
152-
path)]
153-
path))))
153+
(let [file-url (if (str/starts-with? (str path) "file:")
154+
path
155+
(when (and (or windows? reload?) (fs/existsSync path))
156+
(str (url/pathToFileURL path))))
157+
path (if (and reload?
158+
;; not "node:fs" etc
159+
file-url)
160+
(str file-url "?uuid=" (random-uuid))
161+
(or file-url path))]
162+
(esm/dynamic-import path))))
154163
(.then (fn [mod]
155164
(register-module mod internal-name)
156165
mod))))
@@ -237,7 +246,8 @@
237246
feat (load-module feat libname as refer rename libspecs ns-opts)
238247
(string? libname)
239248
(let [libname (if (str/starts-with? libname "./")
240-
(path/resolve (path/dirname (:file ns-opts)) libname)
249+
(path/resolve (path/dirname (or (:file ns-opts) "."))
250+
libname)
241251
libname)
242252
[libname properties*] (split-libname libname)
243253
munged (munge libname)
@@ -266,24 +276,27 @@
266276
(sci/add-class! internal-subname mod-field)
267277
(sci/add-import! current-ns internal-subname field))))))
268278
(handle-libspecs (next libspecs) ns-opts))
269-
mod (js/Promise.resolve
270-
(->
271-
(or
272-
;; skip loading if module was already loaded
273-
(some-> (get @loaded-modules internal-name)
274-
js/Promise.resolve)
275-
(load-js-module libname internal-name)
276-
;; else load module and register in loaded-modules under internal-name
277-
)
278-
(.then (fn [mod]
279-
(if properties
280-
(gobj/getValueByKeys mod properties)
281-
mod)))))]
279+
mod (let [reload? (contains? (:opts ns-opts) :reload)]
280+
(js/Promise.resolve
281+
(->
282+
(or
283+
;; skip loading if module was already loaded
284+
(and (not reload?)
285+
(some-> (get @loaded-modules internal-name)
286+
js/Promise.resolve))
287+
(load-js-module libname internal-name reload?)
288+
;; else load module and register in loaded-modules under internal-name
289+
)
290+
(.then (fn [mod]
291+
(if properties
292+
(gobj/getValueByKeys mod properties)
293+
mod))))))]
282294
(-> mod
283295
(.then after-load)))
284296
:else
285297
;; assume symbol
286-
(if (sci/eval-form (ctx/get-ctx) (list 'clojure.core/find-ns (list 'quote libname)))
298+
(if (and (not (contains? (:opts ns-opts) :reload))
299+
(sci/eval-form (ctx/get-ctx) (list 'clojure.core/find-ns (list 'quote libname))))
287300
;; built-in namespace
288301
(do (sci/binding [sci/ns (:ns ns-opts)
289302
sci/file (:file ns-opts)]
@@ -336,11 +349,14 @@
336349
ns-obj (sci/binding [sci/ns @sci/ns]
337350
(sci/eval-form (ctx/get-ctx) (list 'do (list* 'ns ns-name other-forms) '*ns*)))
338351
libspecs (mapcat rest require-forms)
352+
ns-opts (into #{} (filter keyword? libspecs))
353+
libspecs (remove keyword? libspecs)
339354
opts (assoc opts :ns ns-obj)]
340-
(handle-libspecs libspecs opts)))
355+
(handle-libspecs libspecs (assoc opts :opts ns-opts))))
341356

342357
(defn eval-require [require-form]
343358
(let [args (rest require-form)
359+
args (remove keyword? args)
344360
libspecs (mapv #(sci/eval-form (ctx/get-ctx) %) args)
345361
sci-ns @sci/ns
346362
sci-file @sci/file]
@@ -681,8 +697,11 @@
681697
(if *old-require*
682698
(apply old-require args)
683699
(await (.then (identity ;; with-async-bindings {sci/file @sci/file}
684-
(handle-libspecs args {:ns @sci/ns
685-
:file @sci/file}))
700+
(let [opts (into #{} (filter keyword? args))
701+
args (remove keyword? args)]
702+
(handle-libspecs args {:ns @sci/ns
703+
:file @sci/file
704+
:opts opts})))
686705
(fn [_]))))))
687706

688707
(def ^:dynamic *file* sci/file) ;; make clj-kondo+lsp happy

test-scripts/reload.cljs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
(ns reload
2+
(:require ["./reload.js"] :reload))
3+
4+
(defonce my-atom (atom 0))
5+
6+
(swap! my-atom inc)
7+
8+
(def x js/globalThis.x)
9+

test-scripts/reload.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var x = globalThis.x || 0;
2+
globalThis.x = x + 1;
3+

test/nbb/main_test.cljs

+8
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,14 @@ result")
337337
(fn [val]
338338
(is (number? val))))))
339339

340+
(deftest-async reload-test
341+
(is (.then (nbb/load-string "(require 'reload)
342+
(require 'reload :reload)
343+
344+
[@reload/my-atom reload/x]")
345+
(fn [val]
346+
(is (= [2 2] val))))))
347+
340348
(defn init []
341349
(t/run-tests 'nbb.main-test 'nbb.test-test))
342350

0 commit comments

Comments
 (0)