Skip to content

Commit fa7de9d

Browse files
committed
context: ssr & rsc
1 parent 210bb50 commit fa7de9d

File tree

7 files changed

+57
-26
lines changed

7 files changed

+57
-26
lines changed

core/dev/uix/rsc_example/server/core.clj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@
7979

8080
(def error-boundary
8181
(uix/create-error-boundary
82-
{:derive-error-state (fn [error] {:error error})}
82+
{:derive-error-state (fn [error] {:error error})
83+
:did-catch (fn [error info]
84+
(prn error))}
8385
(fn [[state] {:keys [children]}]
8486
(if-let [error (:error state)]
8587
($ server.root/html-page

core/scripts/rsc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ npm ci
88

99
echo "Starting examples build server..."
1010
npx concurrently "npx patch-package && clojure -A:examples -M -m shadow.cljs.devtools.cli watch rsc" "npx @tailwindcss/cli -i ./dev/uix/main.css -o ./rsc-out/main.css --watch"
11+
#npx concurrently "npx patch-package && clojure -A:examples -M -m shadow.cljs.devtools.cli release rsc" "npx @tailwindcss/cli -i ./dev/uix/main.css -o ./rsc-out/main.css --minify"

core/src/uix/compiler/aot.clj

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,19 @@
119119
[spread-props]))))
120120
v)))
121121

122+
(defn- context-element? [[tag] env]
123+
(and (symbol? tag)
124+
(some-> (resolve env tag) meta :uix/context)))
125+
126+
(defn- compile-context-provider [[var {:keys [value]} & children]]
127+
[:uix/context `(fn [f#] (binding [~var ~value] (f#))) (vec children)])
128+
122129
(defn compile-element [v {:keys [env] :as opts}]
123130
(if (uix.lib/cljs-env? env)
124131
(compile-element* v opts)
125-
(with-meta (with-spread-props v) {:uix/element? true})))
132+
(if (context-element? v env)
133+
(compile-context-provider v)
134+
(with-meta (with-spread-props v) {:uix/element? true}))))
126135

127136
;; ========== forms rewriter ==========
128137

core/src/uix/core.clj

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,18 @@
245245
(defn use-ref [value]
246246
(hooks/use-ref value))
247247

248+
(defmacro defcontext
249+
"cljs: Creates React context with initial value set to `value`.
250+
clj: Create dynamic var bound to `value`."
251+
([name]
252+
(if (uix.lib/cljs-env? &env)
253+
`(def ~(with-meta name {:dynamic true}) (create-context nil))
254+
`(def ~(with-meta name {:dynamic true :uix/context true}))))
255+
([name value]
256+
(if (uix.lib/cljs-env? &env)
257+
`(def ~(with-meta name {:dynamic true}) (create-context ~value))
258+
`(def ~(with-meta name {:dynamic true :uix/context true}) ~value))))
259+
248260
(defn use-context [value]
249261
(hooks/use-context value))
250262

@@ -360,7 +372,7 @@
360372
`(uix.hooks.alpha/use-imperative-handle ~ref ~f ~(->js-deps deps))))
361373

362374
(defui suspense [{:keys [fallback children] :as props}]
363-
[::suspense props])
375+
[:uix/suspense props])
364376

365377
(defui strict-mode [{:keys [children]}]
366378
children)

core/src/uix/hooks/alpha.clj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@
4949
(f))
5050

5151
;; == Context hook ==
52-
;; TODO: requires changes tp how context is created
5352
(defn use-context [v]
54-
(throw (UnsupportedOperationException. "use-context is not implemented yet"))
5553
v)
5654

5755
;; == Imperative Handle hook ==

dom/src/uix/dom/server.clj

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -520,12 +520,11 @@
520520
(when-not (empty? element)
521521
(let [tag (nth element 0 nil)]
522522
(cond
523-
(identical? :uix/bind-context tag)
524-
(let [binder (nth element 1 nil)
525-
children (seq (nth element 2 nil))]
523+
(identical? :uix/context tag)
524+
(let [[_ binder children] element]
526525
(binder #(-render-html children *state sb)))
527526
(identical? :<> tag) (render-fragment! element *state sb)
528-
(identical? :uix.core/suspense tag) (render-suspense! element *state sb)
527+
(identical? :uix/suspense tag) (render-suspense! element *state sb)
529528
(keyword? tag) (render-html-element! element *state sb)
530529
:else (render-component! element *state sb)))))
531530

dom/src/uix/dom/server/flight.clj

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
(client-component? tag) (render-component-element-client-ref el sb)
164164
(fn? tag) (render-component-element-server el sb)
165165
(= :<> tag) (render-fragment-element el sb)
166-
(= :uix.core/suspense tag) (render-suspense-element el sb)
166+
(= :uix/suspense tag) (render-suspense-element el sb)
167167
(keyword? tag) (render-dom-element el sb)
168168
:else (throw (IllegalArgumentException. (str (type tag) " " tag " is not a valid element type")))))
169169

@@ -225,7 +225,7 @@
225225

226226
(defn- source-fn [v]
227227
(when-let [filepath (:file (meta v))]
228-
(with-open [rdr (LineNumberReader. (io/reader (io/resource filepath)))]
228+
(with-open [rdr (LineNumberReader. (io/reader (or (io/resource filepath) (io/file filepath))))]
229229
(dotimes [_ (dec (:line (meta v)))] (.readLine rdr))
230230
(let [text (StringBuilder.)
231231
pbr (proxy [PushbackReader] [rdr]
@@ -243,17 +243,21 @@
243243
st (.getStackTrace error)
244244
stack (->> st
245245
(mapv (fn [^java.lang.StackTraceElement frame]
246-
(str/join " "
247-
[" at"
248-
(str (.getClassName frame)
249-
" "
250-
(.getMethodName frame))
251-
(str
252-
"("
253-
(.getFileName frame)
254-
":"
255-
(.getLineNumber frame)
256-
")")])))
246+
(let [filename (.getFileName frame)
247+
clj? (re-find #"\.cljc?$" filename)
248+
class-name (cond-> (.getClassName frame)
249+
clj? (clojure.lang.Compiler/demunge))]
250+
(str/join " "
251+
[" at"
252+
(str class-name
253+
" "
254+
(.getMethodName frame))
255+
(str
256+
"("
257+
filename
258+
":"
259+
(.getLineNumber frame)
260+
")")]))))
257261
(into [(str (type error) ": " (ex-message error))])
258262
(str/join "\n"))
259263
component-src (source-fn var)
@@ -292,22 +296,28 @@
292296
(-> (render-fn [(derive-error-state e) identity] props)
293297
(-unwrap sb))))))
294298

299+
(defn- unwrap-context-element [element sb]
300+
(let [[_ binder children] element]
301+
(binder #(-unwrap children sb))))
302+
295303
(defn unwrap-element [[tag :as el] sb]
296304
(cond
297305
(client-component? tag) el
298306
(fn? tag) (unwrap-component-element el sb)
299307
(= :<> tag) (unwrap-fragment-element el sb)
300-
(= :uix.core/suspense tag) (unwrap-suspense-element el sb)
308+
(= :uix/suspense tag) (unwrap-suspense-element el sb)
309+
(= :uix/context tag) (unwrap-context-element el sb)
301310
(keyword? tag) (unwrap-dom-element el sb)
302311
(and (map? tag) (-> tag meta :uix.core/error-boundary)) (unwrap-error-boundary el sb)
303312
:else (throw (IllegalArgumentException. (str (type tag) " " tag " is not a valid element type")))))
304313

305314
(extend-protocol FlightRenderer
306315
IPersistentVector
307316
(-unwrap [this sb]
308-
(if (vector? (first this))
309-
(map #(-unwrap % sb) this)
310-
(unwrap-element this sb)))
317+
(let [tag (first this)]
318+
(if (vector? tag)
319+
(doall (map #(-unwrap % sb) this))
320+
(unwrap-element this sb))))
311321
(-render [this sb]
312322
(if (vector? (first this))
313323
(map #(-render % sb) this)

0 commit comments

Comments
 (0)