|
108 | 108 | (first acc) |
109 | 109 | (list* 'do acc))))) |
110 | 110 |
|
| 111 | +(defn transform-try |
| 112 | + "Transform try/catch/finally with await into Promise .catch/.finally chains. |
| 113 | + (try (await p) (catch :default e handler) (finally cleanup)) |
| 114 | + -> |
| 115 | + (-> (js/Promise.resolve p) (.catch (fn [e] handler)) (.finally (fn [] cleanup)))" |
| 116 | + [ctx exprs] |
| 117 | + (let [;; Separate body from catch/finally clauses |
| 118 | + catch-finally? (fn [form] |
| 119 | + (and (seq? form) |
| 120 | + (#{'catch 'finally} (first form)))) |
| 121 | + body-exprs (take-while (complement catch-finally?) exprs) |
| 122 | + clauses (drop-while (complement catch-finally?) exprs) |
| 123 | + catch-clauses (filter #(and (seq? %) (= 'catch (first %))) clauses) |
| 124 | + finally-clause (first (filter #(and (seq? %) (= 'finally (first %))) clauses)) |
| 125 | + ;; Transform body as a do block |
| 126 | + transformed-body (if (= 1 (count body-exprs)) |
| 127 | + (transform-async-body ctx (first body-exprs)) |
| 128 | + (transform-do ctx body-exprs)) |
| 129 | + ;; Wrap in Promise.resolve if not already a promise chain |
| 130 | + promise-chain (if (and (seq? transformed-body) |
| 131 | + (or (= '.then (first transformed-body)) |
| 132 | + (= 'js/Promise.resolve (first transformed-body)))) |
| 133 | + transformed-body |
| 134 | + (wrap-promise transformed-body))] |
| 135 | + ;; Add .catch clauses |
| 136 | + (let [with-catch (reduce |
| 137 | + (fn [chain catch-clause] |
| 138 | + ;; (catch Type e handler-body...) |
| 139 | + (let [[_ _type binding & handler-body] catch-clause |
| 140 | + transformed-handler (if (= 1 (count handler-body)) |
| 141 | + (transform-async-body ctx (first handler-body)) |
| 142 | + (transform-do ctx handler-body))] |
| 143 | + (list '.catch chain (list 'fn [binding] transformed-handler)))) |
| 144 | + promise-chain |
| 145 | + catch-clauses) |
| 146 | + ;; Add .finally if present |
| 147 | + with-finally (if finally-clause |
| 148 | + (let [[_ & finally-body] finally-clause |
| 149 | + transformed-finally (if (= 1 (count finally-body)) |
| 150 | + (transform-async-body ctx (first finally-body)) |
| 151 | + (transform-do ctx finally-body))] |
| 152 | + (list '.finally with-catch (list 'fn [] transformed-finally))) |
| 153 | + with-catch)] |
| 154 | + with-finally))) |
| 155 | + |
111 | 156 | (defn transform-expr-with-await |
112 | 157 | "Transform an expression containing await by extracting the await |
113 | 158 | and wrapping in .then." |
|
147 | 192 | expanded (if (and (seq? body) |
148 | 193 | (symbol? (first body)) |
149 | 194 | (not (await-call? body)) |
150 | | - (not (#{'let 'let* 'do 'fn 'fn* 'if 'quote} (first body)))) |
| 195 | + (not (#{'let 'let* 'do 'fn 'fn* 'if 'quote 'try} (first body)))) |
151 | 196 | (macroexpand/macroexpand ctx body) |
152 | 197 | body) |
153 | 198 | ;; If expansion changed the form, recursively transform |
|
162 | 207 | (and (seq? body) (= 'do (first body))) |
163 | 208 | (transform-do ctx (rest body)) |
164 | 209 |
|
| 210 | + (and (seq? body) (= 'try (first body))) |
| 211 | + (transform-try ctx (rest body)) |
| 212 | + |
165 | 213 | ;; Handle any other expression containing await |
166 | 214 | (contains-await? body) |
167 | 215 | (transform-expr-with-await ctx body) |
|
0 commit comments