Fork me on GitHub
#clojurescript
<
2022-03-02
>
Gerome08:03:24

Good morning! I'm working on a SPA with re-frame and I'm seeing this error in the browser`Uncaught SyntaxError: Unexpected end of input`. However, linting and parens in my own code are fine, my code compiles everything works as expected. If I open the file where the error occurs I get the file you see in the screenshot. Has anyone ever had this before? I already dumped ./target, ./.lsp and ./cpcache because I thought it might be a build issue but the error persists. 🤯

Gerome12:03:42

For future reference: The error message was Uncaught SyntaxError: Unexpected end of input. And the reason the error occurred is because I used javascript:void in the href attributes of a link instead of javascript:void(0) facepalm

Gerome08:03:16

The file in the screenshot is a mostly empty file that just has the js keyword void in it.

jumar08:03:24

When speaking of imprecise representation of floating point numbers. Is this enough to convert price in cents to dollars? https://github.com/jumarko/learn-reagent/pull/3/files#diff-dc56e408d84e6cdf5dc2847b3bc8f062ff6789d3849221fd7049ce811c38c054R6

(defn format-price [cents]
  ;; TODO: is it enough to just divide by 100?
  (str " € " (/ cents 100)))
I have a feeling it's not completely correct but I cannot break it using the usual stuff like (format-price 10) In Java you typically use BigDecimal for monetary calculations but it seems that this simple format-price implementation just works.

jumar08:03:56

I think I found the answer here: https://stackoverflow.com/questions/55127530/handling-money-value-is-it-safe-to-divide-a-number-by-100 The lowest price that I found that breaks the conversion: 1234567890123456*7*

(str (/ 12345678901234567 100))
"123456789012345.69"

p-himik09:03:11

Since it's for a string, you can use java.text.DecimalFormat:

(import '(java.text DecimalFormat))
=> java.text.DecimalFormat
(let [df (DecimalFormat. "0.00")]
  (.format df 1.119))
=> "1.12"

p-himik09:03:33

And BTW you can include " € " in the format itself to avoid having to concatenate strings later on. One tangential thing - I don't usually see the space between the euro sign and the amount. And if there is a space, it's only when the euro sign is after the amount and not before. This seems to corroborate my observations: https://en.wikipedia.org/wiki/Euro_sign#Use And if your app has localization support, seems like it should be able to handle that as well.

jumar11:03:47

Thanks for all the comments. This is actually from a reagent video course so it's not super important but good remarks. Independently, I also found this code in my other project

(defn currency-format
  "Formats given value using given currency-code as a locale.
  This is two-arity version of `currency-format` from reagent-utils library.
  See also "
  ([value currency-code]
   (.format (goog.i18n.NumberFormat. (.-CURRENCY goog.i18n.NumberFormat.Format) currency-code)
            value)))

p-himik11:03:29

Ah, sorry - thought we were in #clojure. Yeah, JS and goog have their own facilities to deal with that.

jumar11:03:55

I'm trying to port an old (4.5 years) cljs app based on re-frame and lein-figwheel to figwheel-main And it's a pain. I of course haven't touched it for such a long time and didn't work with Clojurescript either. I updated tons of dependencies and added somewhat minimal configuration for figwheel-main but I'm now getting this repl upon lein repl

Exception in thread "main" Syntax error compiling at (figwheel/main.cljc:1:1).
        at clojure.lang.Compiler.load(Compiler.java:7652)
...
        at figwheel.main.api$eval46733$loading__6737__auto____46734.invoke(api.clj:1)
        at figwheel.main.api$eval46733.invokeStatic(api.clj:1)
        at figwheel.main.api$eval46733.invoke(api.clj:1)
...
        at portal.figwheel$eval46727$loading__6737__auto____46728.invoke(figwheel.clj:1)
        at portal.figwheel$eval46727.invokeStatic(figwheel.clj:1)
        at portal.figwheel$eval46727.invoke(figwheel.clj:1)
....
        at user$eval138$loading__6737__auto____139.invoke(user.clj:1)
        at user$eval138.invokeStatic(user.clj:1)
        at user$eval138.invoke(user.clj:1)
...
        at clojure.main.main(main.java:38)
Caused by: java.lang.NoSuchMethodError: 'java.util.stream.Collector com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet(java.util.Comparator)'
        at com.google.javascript.jscomp.deps.ModuleLoader.createRootPaths(ModuleLoader.java:257)
        at com.google.javascript.jscomp.deps.ModuleLoader.<init>(ModuleLoader.java:147)
        at com.google.javascript.jscomp.deps.ModuleLoader.<init>(ModuleLoader.java:48)
        at com.google.javascript.jscomp.deps.ModuleLoader$Builder.build(ModuleLoader.java:139)
        at com.google.javascript.jscomp.deps.ModuleLoader.<clinit>(ModuleLoader.java:408)
        at com.google.javascript.jscomp.DiagnosticGroups.<clinit>(DiagnosticGroups.java:182)
Where should I look or which dependency to check?

p-himik11:03:40

What do your dependencies look like?

jumar11:03:20

It's a huge list but now I'm looking at com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet and it looks like it's guava - I thought this is a javascript library problem.

p-himik11:03:03

That probably comes from Google Closure Compiler. If you specify its version explicitly - don't. Just use what CLJS itself depends on. If you specify the CLJS version explicitly - maybe don't. Depends on what figwheel-main recommends. FWIW, shadow-cljs does not recommend setting CLJS version explicitly because it itself brings it in and there might be some inconsistencies between what a particular version of shadow-cljs needs and what version of CLJS your project depends on.

jumar11:03:44

Interesting, I'll have a look. There can be a transitive dependency that brings a special version of Google Closure Compiler too...

jumar11:03:20

Well lein :deps tree gives me only this:

[org.clojure/clojurescript "1.10.914" :scope "provided"]
   [com.google.javascript/closure-compiler-unshaded "v20210808" :scope "provided"]
   [org.clojure/data.json "0.2.6"]
   [org.clojure/google-closure-library "0.0-20211011-0726fdeb" :scope "provided"]
     [org.clojure/google-closure-library-third-party "0.0-20211011-0726fdeb" :scope "provided"]

p-himik11:03:44

Only this? But you said your dependency list is huge.

jumar11:03:27

Oh, that's just the part relevant to closure-compiler Sure there are many more things. I don't really want to post it as is since it's a private project and I would need to check all those things.

p-himik11:03:03

I have happily forgotten how to do things with lein but there should be a way to report not just the dependencies that go directly to the classpath but also all the conflicting and overridden dependencies. Maybe guava is there, maybe GCC, maybe something else. In either case, it's a good idea to look at all conflicts and see how important they are.

jumar11:03:51

Oh, right - removing the clojurescript depedency seems to help! I can now at least start the repl. I'm gonna continue with fixing my figwheel-main config. Thanks!

👍 1
p-himik11:03:33

One more thing - no clue how lein/figwheel-main approach that, but your CLJ and CLJS classpaths should ideally be completely separate. It's much easier to deal with two conceptually independent classpaths as, well, independent classpaths rather than to try and reconcile all the dependencies.

p-himik11:03:42

Just as an example - your backend might depend on library A v2 and your frontend might depend on library A v1 (either your app's code itself or the compiler's code). And now you can't combine them at all - something will end up being broken.

👍 1
jumar12:03:15

Sorry for all the spam today but I really have hard time to make this thing work O:-) I somewhat progressed with updating my app's dependencies and the figwheel-main config but I'm now facing this error. Is react dependency something that you typically need to add?

No such namespace: react, could not locate react.cljs, react.cljc, or JavaScript source providing "react" in file target/public/cljs-out/dev/reagent/impl/component.cljs

  1  (ns reagent.impl.component
  2    (:require [goog.object :as gobj]
  3              [react :as react]
                  ^---
  4              [reagent.impl.util :as util]
  5              [reagent.impl.batching :as batch]
  6              [reagent.impl.protocols :as p]
  7              [reagent.ratom :as ratom]
  8              [reagent.debug :refer-macros [dev? warn error warn-unless assert-callable]]))

[Figwheel:SEVERE] failed compiling file:target/public/cljs-out/dev/reagent/impl/component.cljs
[Figwheel] Starting Server at 
[Figwheel] Starting REPL
It looks like reagent is requiring that but I haven't seen it added to the example project.clj file supplied with figwheel. On the contrary, it's explicitly excluded:
lein new figwheel-main hello-world.core -- +npm-bundle --reagent

cat hello-world.core/project.clj
...
  :dependencies [[org.clojure/clojure "1.10.0"]
                 [org.clojure/clojurescript "1.10.773"]
                 [reagent "0.10.0"  :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server]]]
But in an old demo project it's added explicitly: https://github.com/bhauman/flappy-bird-demo-new/blob/master/project.clj#L9-L11

jumar12:03:20

In my project, I'm using latest reagent, that is 1.1.0

p-himik13:03:01

> Is react dependency something that you typically need to add? Nowadays - yes, via NPM. People used to use vendored JS libraries or cljsjs - the former has become needed only when something is not on NPM an the latter has become obsolete (and was always prone to issues). With shadow-cljs, you just install react and react-dom (and react-dom-server if you're using SSR via NodeJS) with NPM and that's it - no need to specify anything else, they'll be treated as regular CLJS dependencies. I don't know about figwheel-main but it probably supports NPM dependencies in a similar way.

👍 1
Richard Bowen20:03:30

Hey, how does one handle CORS using re-frame-http-fx ? Also, is this effects handler structured properly?

(reg-event-fx
 :print
 (fn [cofx [_ html title]]
   {:http-xhrio {:method            :post
                 :with-credentials  true
                 :uri               ""
                 :timeout           8000
                 :format            (ajax/json-request-format)
                 :response-format   (ajax/json-response-format {:keywords? true})
                 :params            {:access_key    "access_key"
                                     :document_html html
                                     :document_name title
                                     :page_size     "A4"}
                 :on-success      ""
                 :on-failure      ""}}))
[button {:on-click (dispatch [:print (.. js/document -documentElement -outerHTML) "Document Title"])
Thanks.

p-himik20:03:27

CORS is configured mostly on the server, not on the client. If the server doesn't allow CORS, the browser will refuse to load the resource, regardless of what you do on the frontend.

p-himik20:03:07

The only think that's definitely not right with your request that I can see right away is the :on-success and :on-failure handlers. Those should be event vectors, not strings.

Richard Bowen20:03:02

So empty vectors if nothing?

p-himik20:03:02

No key if nothing.

Richard Bowen20:03:43

So,

{:http-xhrio {:method :post
              ...
              :on-success
              :on-failure}}))

p-himik20:03:10

No. Not "no value" but "no key". A map cannot have a key without a value. Just don't specify :on-success and :on-failure if you don't care about the results.

Richard Bowen20:03:27

I see. Thanks.

👍 1