File tree 3 files changed +68
-12
lines changed
3 files changed +68
-12
lines changed Original file line number Diff line number Diff line change 2126
2126
type (::type form-meta)
2127
2127
proto-impl (::protocol-impl form-meta)
2128
2128
proto-inline (::protocol-inline form-meta)
2129
- menv (if (> (count meths) 1 )
2130
- (assoc env :context :expr )
2131
- env)
2132
- menv (merge menv
2133
- {:protocol-impl proto-impl
2134
- :protocol-inline proto-inline})
2129
+ menv (-> env
2130
+ (cond->
2131
+ (> (count meths) 1 )
2132
+ (assoc :context :expr ))
2133
+ ; ; clear loop flag since method bodies won't be in a loop at first
2134
+ ; ; only tracking this to keep track of locals we need to capture
2135
+ (dissoc :in-loop )
2136
+ (merge {:protocol-impl proto-impl
2137
+ :protocol-inline proto-inline}))
2135
2138
methods (map #(disallowing-ns* (analyze-fn-method menv locals % type (nil? name))) meths)
2136
2139
mfa (transduce (map :fixed-arity ) max 0 methods)
2137
2140
variadic (boolean (some :variadic? methods))
2166
2169
:tag 'function
2167
2170
:inferred-ret-tag inferred-ret-tag
2168
2171
:recur-frames *recur-frames*
2172
+ :in-loop (:in-loop env)
2169
2173
:loop-lets *loop-lets*
2170
2174
:jsdoc [js-doc]
2171
2175
:max-fixed-arity mfa
2343
2347
(partition 2 bindings)
2344
2348
widened-tags))
2345
2349
bindings)
2346
- [bes env] (analyze-let-bindings encl-env bindings op)
2350
+ [bes env] (-> encl-env
2351
+ (cond->
2352
+ (true ? is-loop) (assoc :in-loop true ))
2353
+ (analyze-let-bindings bindings op))
2347
2354
recur-frame (when (true ? is-loop)
2348
2355
{:params bes
2349
2356
:flag (atom nil )
Original file line number Diff line number Diff line change 957
957
(emitln " })()" ))))
958
958
959
959
(defmethod emit* :fn
960
- [{variadic :variadic? :keys [name env methods max-fixed-arity recur-frames loop-lets]}]
960
+ [{variadic :variadic? :keys [name env methods max-fixed-arity recur-frames in-loop loop-lets]}]
961
961
; ;fn statements get erased, serve no purpose and can pollute scope if named
962
962
(when-not (= :statement (:context env))
963
- (let [loop-locals (->> (concat (mapcat :params (filter #(and % @(:flag %)) recur-frames))
964
- (mapcat :params loop-lets))
965
- (map munge)
966
- seq)]
963
+ (let [recur-params (mapcat :params (filter #(and % @(:flag %)) recur-frames))
964
+ loop-locals
965
+ (->> (concat recur-params
966
+ ; ; need to capture locals only if in recur fn or loop
967
+ (when (or in-loop (seq recur-params))
968
+ (mapcat :params loop-lets)))
969
+ (map munge)
970
+ seq)]
967
971
(when loop-locals
968
972
(when (= :return (:context env))
969
973
(emits " return " ))
Original file line number Diff line number Diff line change 286
286
(is (str/includes? content " cljs.invoke_test.foo_record.foo_field_a;" )))))
287
287
#_(test-vars [#'test-optimized-invoke-emit])
288
288
289
+ (deftest test-cljs-3077
290
+ (let [opts {}
291
+ cenv (env/default-compiler-env opts )
292
+
293
+ test-compile
294
+ (fn [code]
295
+ (env/with-compiler-env cenv
296
+ (with-out-str
297
+ (emit
298
+ (comp/with-core-cljs
299
+ opts
300
+ (fn [] (analyze aenv code nil opts)))))))
301
+
302
+ snippet1
303
+ (test-compile
304
+ '(defn wrapper1 [foo]
305
+ (let [x 1 ]
306
+ (prn (fn inner [] foo))
307
+ (recur (inc foo)))))
308
+
309
+ snippet2
310
+ (test-compile
311
+ '(defn wrapper2 [foo]
312
+ (loop [x 1 ]
313
+ (prn (fn inner [] x))
314
+ (recur (inc x))
315
+ )))
316
+
317
+ snippet3
318
+ (test-compile
319
+ '(defn no-wrapper1 [foo]
320
+ (let [x 1 ]
321
+ (prn (fn inner [] foo)))))]
322
+
323
+ ; ; FIXME: not exactly a clean way to test if function wrappers are created or not
324
+ ; ; captures foo,x
325
+ (is (str/includes? snippet1 " (function (foo,x){" ))
326
+ ; ; captures x
327
+ (is (str/includes? snippet2 " (function (x){" ))
328
+ ; ; no capture, no loop or recur
329
+ (is (not (str/includes? snippet3 " (function (foo,x){" )))
330
+ (is (not (str/includes? snippet3 " (function (foo){" )))
331
+ (is (not (str/includes? snippet3 " (function (x){" )))
332
+ ))
333
+
289
334
; ; CLJS-1225
290
335
291
336
(comment
You can’t perform that action at this time.
0 commit comments