ClojureScript

cljs.main: Failure to load user.cljs if temp out dir

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Environment:
    {:deps {org.clojure/clojurescript {:mvn/version "1.10.339"}}}
  • Patch:
    Code

Description

src/user.cljs
(def a 3)
$ clj -Srepro -m cljs.main
java.lang.IllegalArgumentException: /var/folders/gx/nymj3l7x4zq3gxb97v2zwzb40000gn/T/out6255758032123683761473031144485066/cljs/user/userAE725FA.js is not a relative path
	at clojure.java.io$as_relative_path.invokeStatic(io.clj:414)
	at clojure.java.io$file.invokeStatic(io.clj:426)
	at clojure.java.io$file.invoke(io.clj:418)
	at cljs.closure$compile_file.invokeStatic(closure.clj:633)
	at cljs.closure$compile_file.invoke(closure.clj:625)
	at cljs.closure$fn__5175.invokeStatic(closure.clj:721)
	at cljs.closure$fn__5175.invoke(closure.clj:715)
	at cljs.closure$fn__5088$G__5081__5095.invoke(closure.clj:543)
	at cljs.closure$compile.invokeStatic(closure.clj:595)
	at cljs.closure$compile.invoke(closure.clj:592)
	at cljs.repl$load_file$fn__6454.invoke(repl.cljc:601)
	at cljs.repl$load_file.invokeStatic(repl.cljc:600)
	at cljs.repl$load_file.invoke(repl.cljc:592)
	at cljs.repl$repl_STAR_$maybe_load_user_file__6612.invoke(repl.cljc:958)
	at cljs.repl$repl_STAR_$fn__6621$fn__6622.invoke(repl.cljc:989)
	at cljs.repl$repl_STAR_$fn__6621.invoke(repl.cljc:982)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1289)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1278)
	at cljs.repl$repl_STAR_.invokeStatic(repl.cljc:979)
	at cljs.repl$repl_STAR_.invoke(repl.cljc:855)
	at cljs.cli$repl_opt.invokeStatic(cli.clj:305)
	at cljs.cli$repl_opt.invoke(cli.clj:292)
	at cljs.cli$main.invokeStatic(cli.clj:638)
	at cljs.cli$main.doInvoke(cli.clj:625)
	at clojure.lang.RestFn.invoke(RestFn.java:410)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.main$_main.invokeStatic(main.clj:61)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.invoke(RestFn.java:397)
	at clojure.lang.AFn.applyToHelper(AFn.java:152)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)
ClojureScript 1.10.339
cljs.user=>

If, on the other hand you specify an output directory (via -d) things work.

  1. CLJS-2917.patch
    01/Oct/18 12:34 PM
    2 kB
    Herald Reierskog
  2. CLJS-2917.patch
    29/Sep/18 5:06 PM
    2 kB
    Herald Reierskog

Activity

Hide
Herald Reierskog added a comment -

Error occurred because cljs.closure/compile-file is passed a File with an absolute path as output-file when run without temp out dir. compile-file only works with an output-file that is either a relative path string or File, so I modified it to support absolute path File as well. This way you can use cljs.closure/src-file->target-file with it.

Show
Herald Reierskog added a comment - Error occurred because cljs.closure/compile-file is passed a File with an absolute path as output-file when run without temp out dir. compile-file only works with an output-file that is either a relative path string or File, so I modified it to support absolute path File as well. This way you can use cljs.closure/src-file->target-file with it.
Hide
Mike Fikes added a comment -

Note, Herald indicated via private Slack message to me that the CA has been signed.

Show
Mike Fikes added a comment - Note, Herald indicated via private Slack message to me that the CA has been signed.
Hide
Mike Fikes added a comment -

The patch works for the ticket description if you go with the default browser REPL, but on macOS if you specify the Node REPL you will see a failure related to the canonicalization of the temp directory path:

$ clj -Sdeps '{:deps {org.clojure/clojurescript {:local/root "/Users/mfikes/Projects/clojurescript"}}}' -m cljs.main -re node -r
cljs.user=> Exception in thread "main" java.lang.AssertionError: Assert failed: Output file /private/tmp/cljs-2917/cljs/core.js is not in output directory /var/folders/gx/nymj3l7x4zq3gxb97v2zwzb40000gn/T/out5998260788018592691311499618489419
(string/starts-with? (util/path output-file) out-dir)
	at cljs.closure$compile_file.invokeStatic(closure.clj:636)
	at cljs.closure$compile_file.invoke(closure.clj:625)
	at cljs.closure$eval7272$fn__7273.invoke(closure.clj:730)
	at cljs.closure$eval7175$fn__7176$G__7164__7183.invoke(closure.clj:543)
	at cljs.closure$eval7278$fn__7279.invoke(closure.clj:739)
	at cljs.closure$eval7175$fn__7176$G__7164__7183.invoke(closure.clj:543)
	at cljs.closure$compile.invokeStatic(closure.clj:595)
	at cljs.closure$compile.invoke(closure.clj:592)
	at cljs.repl.node$setup$fn__9880.invoke(node.clj:164)
	at cljs.repl.node$setup.invokeStatic(node.clj:131)
	at cljs.repl.node$setup.invoke(node.clj:124)
	at cljs.repl.node.NodeEnv._setup(node.clj:236)
	at cljs.repl$repl_STAR_$fn__8878.invoke(repl.cljc:951)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1416)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1405)
	at cljs.repl$repl_STAR_.invokeStatic(repl.cljc:949)
	at cljs.repl$repl_STAR_.invoke(repl.cljc:861)
	at cljs.cli$repl_opt.invokeStatic(cli.clj:314)
	at cljs.cli$repl_opt.invoke(cli.clj:301)
	at cljs.cli$main.invokeStatic(cli.clj:646)
	at cljs.cli$main.doInvoke(cli.clj:635)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.main$_main.invokeStatic(main.clj:61)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)

I think that this can be fixed by asserting

(same-or-subdirectory-of? out-dir output-file)

instead of

(string/starts-with? (util/path output-file) out-dir)

Another issue that concerns me about the patch is that output-file could be a relative File, in which case

(io/file out-dir output-file)

is a legitimate construct and the code should probably take that branch. In my opinion, it is only when out-file is absolute (either a string or File) that it should be take "as is" and not relative to out-dir. In other words, the condition is probably not that it satisfies util/file? but rather absolute-path?.

If we consider those two changes (using absolute-path? to trigger the logic and same-or-subdirectory-of? for the assert), this might cover all bases. (Both fns would need to be declare d as they occur after compile-file.)

Show
Mike Fikes added a comment - The patch works for the ticket description if you go with the default browser REPL, but on macOS if you specify the Node REPL you will see a failure related to the canonicalization of the temp directory path:
$ clj -Sdeps '{:deps {org.clojure/clojurescript {:local/root "/Users/mfikes/Projects/clojurescript"}}}' -m cljs.main -re node -r
cljs.user=> Exception in thread "main" java.lang.AssertionError: Assert failed: Output file /private/tmp/cljs-2917/cljs/core.js is not in output directory /var/folders/gx/nymj3l7x4zq3gxb97v2zwzb40000gn/T/out5998260788018592691311499618489419
(string/starts-with? (util/path output-file) out-dir)
	at cljs.closure$compile_file.invokeStatic(closure.clj:636)
	at cljs.closure$compile_file.invoke(closure.clj:625)
	at cljs.closure$eval7272$fn__7273.invoke(closure.clj:730)
	at cljs.closure$eval7175$fn__7176$G__7164__7183.invoke(closure.clj:543)
	at cljs.closure$eval7278$fn__7279.invoke(closure.clj:739)
	at cljs.closure$eval7175$fn__7176$G__7164__7183.invoke(closure.clj:543)
	at cljs.closure$compile.invokeStatic(closure.clj:595)
	at cljs.closure$compile.invoke(closure.clj:592)
	at cljs.repl.node$setup$fn__9880.invoke(node.clj:164)
	at cljs.repl.node$setup.invokeStatic(node.clj:131)
	at cljs.repl.node$setup.invoke(node.clj:124)
	at cljs.repl.node.NodeEnv._setup(node.clj:236)
	at cljs.repl$repl_STAR_$fn__8878.invoke(repl.cljc:951)
	at cljs.compiler$with_core_cljs.invokeStatic(compiler.cljc:1416)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1405)
	at cljs.repl$repl_STAR_.invokeStatic(repl.cljc:949)
	at cljs.repl$repl_STAR_.invoke(repl.cljc:861)
	at cljs.cli$repl_opt.invokeStatic(cli.clj:314)
	at cljs.cli$repl_opt.invoke(cli.clj:301)
	at cljs.cli$main.invokeStatic(cli.clj:646)
	at cljs.cli$main.doInvoke(cli.clj:635)
	at clojure.lang.RestFn.applyTo(RestFn.java:139)
	at clojure.core$apply.invokeStatic(core.clj:659)
	at clojure.core$apply.invoke(core.clj:652)
	at cljs.main$_main.invokeStatic(main.clj:61)
	at cljs.main$_main.doInvoke(main.clj:52)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.main$main_opt.invokeStatic(main.clj:317)
	at clojure.main$main_opt.invoke(main.clj:313)
	at clojure.main$main.invokeStatic(main.clj:424)
	at clojure.main$main.doInvoke(main.clj:387)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:702)
	at clojure.main.main(main.java:37)
I think that this can be fixed by asserting
(same-or-subdirectory-of? out-dir output-file)
instead of
(string/starts-with? (util/path output-file) out-dir)
Another issue that concerns me about the patch is that output-file could be a relative File, in which case
(io/file out-dir output-file)
is a legitimate construct and the code should probably take that branch. In my opinion, it is only when out-file is absolute (either a string or File) that it should be take "as is" and not relative to out-dir. In other words, the condition is probably not that it satisfies util/file? but rather absolute-path?. If we consider those two changes (using absolute-path? to trigger the logic and same-or-subdirectory-of? for the assert), this might cover all bases. (Both fns would need to be declare d as they occur after compile-file.)
Hide
Herald Reierskog added a comment -

Thanks again, Mike. I managed to reproduce your error on Linux, made the changes you suggested to both the logic and assert, and confirmed that it was fixed. I also wrapped the output-file returned in the if truthy branch in an io/file call, as otherwise if an absolute path string was supplied, I'm concerned it would fail the (.exists out-file) expression further down.

Show
Herald Reierskog added a comment - Thanks again, Mike. I managed to reproduce your error on Linux, made the changes you suggested to both the logic and assert, and confirmed that it was fixed. I also wrapped the output-file returned in the if truthy branch in an io/file call, as otherwise if an absolute path string was supplied, I'm concerned it would fail the (.exists out-file) expression further down.
Hide
Mike Fikes added a comment -

Latest patch LGTM, behaves properly, and passes in CI.

Show
Mike Fikes added a comment - Latest patch LGTM, behaves properly, and passes in CI.
Hide
Herald Reierskog added a comment -

While working on the patch for CLJS-2753, I noticed that the fix for that bug also fixes this issue. If supporting absolute paths in compile-file isn't desired, this patch can be dropped and the CLJS-2753 patch used instead. My commit messages in CLJS-2917.patch regarding cljs.repl.rhino... are incorrect; these files dissoc :output-dir from opts, so they end up passing cljs.closure/compile-file a relative path. (which wasn't done for cljs.repl/load-file, resulting in these two issues)

Show
Herald Reierskog added a comment - While working on the patch for CLJS-2753, I noticed that the fix for that bug also fixes this issue. If supporting absolute paths in compile-file isn't desired, this patch can be dropped and the CLJS-2753 patch used instead. My commit messages in CLJS-2917.patch regarding cljs.repl.rhino... are incorrect; these files dissoc :output-dir from opts, so they end up passing cljs.closure/compile-file a relative path. (which wasn't done for cljs.repl/load-file, resulting in these two issues)

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: