Fork me on GitHub
#clojurescript
<
2015-11-21
>
pandeiro01:11:53

Can goog.require be set as the cljs.js/*load-fn* for in-browser retrieving of dependencies?

pandeiro01:11:56

I'm guessing not, reading the contract specified in *load-fn*'s docstring...

pandeiro01:11:56

I'm wondering what is the easiest way to make something like (ns cljs.user (:require [goog.string :as string])) work in a bootstrapped CLJS environment in the browser

richiardiandrea01:11:06

@pandeiro: I will need to solve the same problem as you because of https://github.com/ScalaConsultants/replumb (BTW have a look if you're thinking about bootstrapped repl)

richiardiandrea01:11:41

what I came up so far is a simple way to pass your own load-fn from outside

pandeiro01:11:59

@richiardiandrea: Neat, let me have a look.

pandeiro01:11:08

From looking at David's original clojurescript next blogpost, it seems like the load fn would have to resolve a namespace into a URL path

richiardiandrea01:11:05

well, the protocol is, doesn't matter how, but call back weth :source in it, or nil if you can't resolve

richiardiandrea01:11:57

from what I gather get-file returns the actual content taken from somewhere remote

(defn get-file [url cb]
  (.send XhrIo url
    (fn [e]
      (cb (.. e -target getResponseText)))))

richiardiandrea01:11:17

and you put it in the map as :source

pandeiro01:11:35

but it could probably be turned into a fn that knows how to take a ns and generate a URL based on it

richiardiandrea01:11:51

this makes me test require without depending on the filesystem

richiardiandrea01:11:06

basically it is loading the files he put in assets through an ajax call to itself if I understand correctly

pandeiro01:11:46

@richiardiandrea: Yep, indeed. I am still wondering if I can somehow use existing machinery (i.e., like how the browser REPL resolves (require 'foo)) instead of having to hack together something to generate URLs... I feel like there's probably a better way than that...

richiardiandrea01:11:13

I don't think you can avoid using a load-fn...it is part of the require protocol

richiardiandrea01:11:39

only if the required ns is already required load-fn is not called

venantius02:11:44

Just out of curiosity, what do people think of as being the coolest / most popular ClojureScript projects?

venantius02:11:25

holy crap @ cljs-devools, I’d never heard of that before but that is awesome

richiardiandrea02:11:19

but also what is behind the React "movement", from Reagent to the latest Mike Fikes post 😄

dnolen02:11:56

@pandeiro: you need to solve the IO problem yourself, that’s what the *load-fn* stuff is for. You can do whatever you like.

pandeiro02:11:56

@dnolen: could it not use the same mechanism as the browser repl's require?

dnolen02:11:42

because bootstrapped ClojureScript doesn’t care about browsers

dnolen02:11:07

you can run it Node.js, Rhino, Nashorn, JavaScriptCore, etc.

dnolen02:11:54

all the current REPLs have to define the semantics of goog.require, not interested in supporting all these cases anymore

dnolen02:11:56

user problem now

dnolen02:11:14

for bootstrapped anyway

pandeiro02:11:04

@dnolen: fair enough. what approach would you recommend then for the browser case? surely w/ the machinery that already exists, one shouldn't have to re-invent the wheel traversing dependency graph, etc? or am i missing something?

dnolen02:11:13

I don’t recommend anything

dnolen02:11:18

it’s something for you to figure out

dnolen02:11:51

or provide a library for your preferred use case and to share that with other people

dnolen02:11:34

and it’s inaccurate to say this machinery exists

dnolen02:11:52

all the REPLs are strictly oriented around development - not production

dnolen02:11:19

hardly anyone is deploying :none compiled files

dnolen02:11:44

even really basic loads of simple namespaces can cause 40 files to load

dnolen02:11:53

goog.require is completely naive wrt network latency

pandeiro02:11:41

sure point taken, my use case is also development tooling, but i thought this could be re-used somehow from within a bootstrapped context (in the browser): https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl.cljc#L664-L681

dnolen02:11:07

@pandeiro: you can re-use but we’re (the core) not going to spend anymore time on bootstrapped

dnolen02:11:37

beyond fixing the real compiler bugs

richiardiandrea03:11:02

probably the best would be to port it to replumb now as I am trying to put there every REPL needs, so feel free to open a PR there and I will take a look

richiardiandrea03:11:27

just so that we concentrate the effort in one point @pandeiro

dnolen03:11:46

this is the kind of thing I would recommend ^

richiardiandrea03:11:51

@dnolen: with your blessing of course 😄

dnolen03:11:04

we’re not going to add anything along these lines to ClojureScript at all

dnolen03:11:21

@richiardiandrea: no need for my blessing

dnolen03:11:31

this is exactly the reason I spent so much time on bootstrapped

dnolen03:11:44

so people can solve the numerous problems outside of ClojureScript mainline development

pandeiro03:11:38

@dnolen: I wasn't asking for any code to be added to cljs, just orientation to figure out just what is missing to be able to cljs.js/eval-str (ns ...) forms, that's all.

dnolen03:11:01

@pandeiro: right but I told you simple_smile no IO support

dnolen03:11:09

you must solve all those problems yourself

pandeiro03:11:23

yes but the scope of that solution is what i am trying to understand

pandeiro03:11:30

it's a pretty big thing, i see

dnolen03:11:40

@pandeiro: the scope is you don’t have IO, because JS doesn’t have IO

dnolen03:11:51

and we’re not going to spend anytime on that

richiardiandrea03:11:40

@pandeiro: the require machinery is there, you just need to plug IO for reading and returning the source, see here https://github.com/ScalaConsultants/replumb/blob/master/src/cljs/replumb/target/nodejs.cljs#L35-L44

richiardiandrea03:11:16

we are plugging it in this way in replumb, and it can be made generic for browsers too

richiardiandrea03:11:36

you pass in a read-file that uses Chrome FS api and that should be it

pandeiro03:11:00

@richiardiandrea: cool, i see the approach involved... for resolving stuff like cljsjs libs, you'd need to include their convention too (`*.inc.js`)

richiardiandrea03:11:28

well that's true

pandeiro03:11:34

chrome FS api? not sure what that is

pandeiro03:11:44

I figured it would be xhr as in david's example

richiardiandrea03:11:40

can be anything really

dnolen03:11:17

@mfikes that’s really cool simple_smile Lisping eat your heart out!

ian09:11:50

@mfikes: should we expect an update to replete soon, in that case?

viesti10:11:29

hum, wonder why I’m sometimes getting compilation error related to cached analysis files

file: #object[java.io.File 0x4a574aa3 "src/cljs/shopping_list/components/login.cljs"]
clojure.lang.ExceptionInfo: Map literal must contain an even number of forms
    tag: :cljs/analysis-error
java.lang.RuntimeException: Map literal must contain an even number of forms
                                              ...
                          clojure.edn/read-string                           edn.clj:   46
                          clojure.edn/read-string                           edn.clj:   45
      cljs.analyzer$analyze_file$fn__11176.invoke                     analyzer.cljc: 2857
                                              ...
                               clojure.core/swap!                          core.clj: 2238
                cljs.analyzer$analyze_file.invoke                     analyzer.cljc: 2855

hans10:11:04

viesti: it is a long shot, but do you by chance use :global-vars to set your *print-length*?

viesti10:11:07

have it on clj side, but not on cljs side

viesti10:11:58

at least the two edn cache files in components directory are readable by clojure.edn/read-string

hans10:11:02

the clojurescript compiler is written in clj

hans10:11:45

give it a try, dump your compiled clojurescript, remove the *print-length* setting, recompile.

viesti10:11:33

15 hours ago, love this immediate reponse simple_smile

viesti10:11:15

was thinking that “bleh, I’ll just wipe out compilation directory”, but then though about opening slack simple_smile

hans11:11:20

viesti: simple_smile glad that it helped you. dynamic scope is a pain.

tony.kay17:11:38

I’m working on devcards, and trying to make it support formatting clojurescript code. Unfortunately, when I pass it code that has data reader for #js it barfs (No reader for tag #js). I grepped the clojurescript source, but don’t see the “No reader” error message, so I’m assuming it is leveraging a macro to format stuff on the JVM. I tried putting a js reader in data-readers.clj and that didn’t work….perhaps because data-readers isn’t supposed to use root level tags? Not sure….anyone have any hints for my next step? I don’t mind patching things, I am just having trouble finding the spot.

tony.kay17:11:10

I found a helpful stack trace that got me down to the clojure reader code…so I’m teasing it apart now

yogthos18:11:27

would anybody have any idea why the externs aren't working here? https://github.com/yogthos/mojs-reagent

jaen19:11:19

@yogthos: I think they work and your problem lies elsewhere

jaen19:11:22

 = function(b) {
        console.log(mojs);
        console.log(mojs.Tween);
        return (new mojs.Tween(Yf(new pa(null ,3,[Ag, 999, Ig, 2E3, ig, mojs.Pa.Dc(b.getDOMNode())],null )))).Pc()
    }

jaen19:11:30

what happens

jaen19:11:48

Is what bit me when I was experimenting with implementing Common JS module translation into the Clojurescript compiler

jaen19:11:52

React creates a top-level object named React and when I generated a Clojurescript module named React it overwrote that top-level object

jaen19:11:59

Because Google Closure modules work

jaen19:11:11

By defining their objects in the top level

jaen19:11:19

And it just tramples over wahtever happened to be there

jaen19:11:21

In your case

jaen19:11:30

You have a mojs object created by your lib

jaen19:11:35

And a mojs namespace

jaen19:11:44

At least, that's what I suspect is happening.

yogthos19:11:34

hmm so the lib creates both an object and a namespace called mosj then?

jaen19:11:00

Maybe, I overcomplicated the explanation bringing my Common JS thing into this.

jaen19:11:02

Basically

jaen19:11:10

Google Closure modules namespaces compile to

jaen19:11:17

Create object structure

jaen19:11:21

That follows the namespaces

jaen19:11:43

So if you have a namespace top.kek.core you'll end up with a top level object that represents it.

jaen19:11:53

And since your external lib defines an object with the same namespace

jaen19:11:57

It will just get overwritten

yogthos19:11:25

I didn't even notice that I named my ns the same way

jaen19:11:36

I renamed it and got a different error this time

jaen19:11:40

So that should be it

yogthos19:11:42

well now I feel dumb having spent an hour on this simple_smile

yogthos19:11:59

thank for the help!

jaen19:11:01

I would complain something about dynamic languages here, but well - tradeoffs : D

jaen19:11:02

No problem

yogthos19:11:10

hehe indeed

yogthos19:11:56

in theory the compiler could be clever enough to track the namespaces defined and warn on collisions

yogthos19:11:01

maybe one day simple_smile

jaen19:11:18

Well, I guess it would be doable, since it already has at least the externs.

Tim19:11:47

how would I use a function like this in cljs:

function isEllipsisActive(e) {
     return (e.offsetWidth < e.scrollWidth);
}

Tim19:11:56

I am not good with cljs interop

Tim19:11:12

could I use it as is?

Tim19:11:41

(defn isEllipsisActive
  [e]
  (< (.-offsetWidth e) (.-scrollWidth e)))

Tim19:11:45

like this perhaps?

Tim19:11:08

I guess I have to somehow pass in the react element

yogthos19:11:58

@tmtwd if you have an external function that expects a browser DOM node and you're using react then you have to run the function in the state where the node is mounted

Tim19:11:20

yeah, thats what I want to do, I think

yogthos19:11:21

then you can get the actual DOM node there and everything should work as normal

Tim19:11:41

but I can declare the function anywhere?

Tim19:11:55

and call the function where the node is mounted

yogthos19:11:11

as long as you're passing it what it needs

Tim19:11:29

cool thanks

mrg23:11:11

In a figwheel repl, using leiningen checkout dependencies, is there a way to get the repl to pick up on the library changes without restarting the repl?

mrg23:11:47

Just requiring the library again doesn't seem to work

darwin23:11:23

@mrg: what I usually do is adding checkouts/my-lib/src (or whatever lib needs) into cljsbuild’s source-paths temporarily

darwin23:11:29

I’m not sure about REPL, but figwheel then picks up changes in library and applies them in my browser session

mrg23:11:47

huh that's a great idea

mrg23:11:54

thanks @darwin, i will give that a try!

mrg23:11:13

Works like a charm! Thanks!