File tree Expand file tree Collapse file tree 3 files changed +68
-12
lines changed Expand file tree Collapse file tree 3 files changed +68
-12
lines changed Original file line number Diff line number Diff line change 21262126 type (::type form-meta)
21272127 proto-impl (::protocol-impl form-meta)
21282128 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}))
21352138 methods (map #(disallowing-ns* (analyze-fn-method menv locals % type (nil? name))) meths)
21362139 mfa (transduce (map :fixed-arity ) max 0 methods)
21372140 variadic (boolean (some :variadic? methods))
21662169 :tag 'function
21672170 :inferred-ret-tag inferred-ret-tag
21682171 :recur-frames *recur-frames*
2172+ :in-loop (:in-loop env)
21692173 :loop-lets *loop-lets*
21702174 :jsdoc [js-doc]
21712175 :max-fixed-arity mfa
23432347 (partition 2 bindings)
23442348 widened-tags))
23452349 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))
23472354 recur-frame (when (true ? is-loop)
23482355 {:params bes
23492356 :flag (atom nil )
Original file line number Diff line number Diff line change 957957 (emitln " })()" ))))
958958
959959(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]}]
961961 ; ;fn statements get erased, serve no purpose and can pollute scope if named
962962 (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)]
967971 (when loop-locals
968972 (when (= :return (:context env))
969973 (emits " return " ))
Original file line number Diff line number Diff line change 286286 (is (str/includes? content " cljs.invoke_test.foo_record.foo_field_a;" )))))
287287#_(test-vars [#'test-optimized-invoke-emit])
288288
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+
289334; ; CLJS-1225
290335
291336(comment
You can’t perform that action at this time.
0 commit comments