Description
version
The latest commit fa434c1b719de62bd676acf27d440ffc8e3868bb
after version v0.8.141
problem
Invalid JavaScript code is produced when an anonymous function appears in a body of statements, such as do
or a function body but not at the last position among those statements.
The following code
(defn get-four []
(fn [] 119)
4)
compiles to
var get_four = function () {
function () {
return 119;
};
return 4;
};
which is not valid JavaScript. Here is part of the error message:
18:35:14 [vite] Internal server error: Transform failed with 1 error:
/Users/osdjn/prog/libtaxonomy-js/public/test/libtaxonomy/db.jsx:46:9: ERROR: Expected identifier but found "("
Plugin: vite:esbuild
File: /Users/osdjn/prog/libtaxonomy-js/public/test/libtaxonomy/db.jsx:46:9
Expected identifier but found "("
44 | };
45 | var get_four = function () {
46 | function () {
| ^
47 | return 119;
48 | };
repro
Here is a good unit test that fails when I try to include it in compiler_test.cljs
:
(deftest fn-statement-test
(is (= 4 (jsv! "(do (fn [] 119) 4)"))))
expected behavior
Either Squint should not emit a function at all, or it should generate a name for the function so that the generated JavaScript code is valid. So I would suggest that Squint would output the following code for the function get-four
:
var get_four = function () {
return 4;
};
attempted fix
I attempted to fix this issue with omit?
, see below. That is, if the function doesn't have a name and we are generating code for a statement, we omit it. But with this fix, another unit test breaks.
(defn emit-function* [env expr opts]
(let [name (when (symbol? (first expr)) (first expr))
expr (if name (rest expr) expr)
expr (if (seq? (first expr))
;; TODO: multi-arity:
(first expr)
expr)
signature (first expr)
arrow? (or (:arrow env) (:=> (meta signature)))
env (assoc env :arrow arrow?)
omit? (and (= :statement (:context env))
(nil? name))]
(when-not omit?
(if (some #(= '& %) signature)
...........