Fork me on GitHub
#shadow-cljs
<
2018-07-12
>
lsnape14:07:11

I'm trying to add an extern for an ES6 class ctor in one of my js files. I'm requiring like this:

["/js/audio/wavesurfer.cursor-time" :default wavesurfer-cursor-time-plugin]
The js file looks like:
class CursorTimePlugin {
  static create(params) { ... }
}
...
export default CursorTimePlugin;
The runtime error I get when I compile a release build is: Uncaught TypeError: $module$js$audio$wavesurfer_cursor_time$$.default.create is not a function

lsnape14:07:29

Oh and I'm calling the function in my cljs namespace like: (.create ^js wavesurfer-cursor-time-plugin (clj->js (:cursor-time options))) I've experimented with all sorts of defs in my externs file, but none make the problem go away! For example, the following doesn't work:

var $module$js$audio$wavesurfer_cursor_time$$ = {};
$module$js$audio$wavesurfer_cursor_time$$.default = {};
$module$js$audio$wavesurfer_cursor_time$$.default.create = function(params) { };

justinlee15:07:20

that doesn’t look like an externs issue because the name isn’t getting munged

justinlee15:07:13

if was an advanced compilation issue it would say something like g432 is not a function

oscar15:07:54

@lsnape I think your require string is probably wrong. "/" Means filesystem root. https://nodejs.org/api/modules.html#modules_all_together

lsnape15:07:43

Sorry @lee.justin.m should have mentioned I''ve added :pseudo-names true. If I turn it off then I do indeed get wpa.default.create is not a function.

lsnape15:07:16

And @oscar the above code works in development.

justinlee15:07:28

that’s weird that the typehinting didn’t work. if you use a string accessor it works, I assume?

lsnape15:07:43

Yes I'd expect it to work too. What do you mean by a string accessor?

justinlee15:07:02

(def thing #js{:getSomething (fn [] :a)})
=> #'cljs.user/thing
(goog.object/get thing "getSomething")
=> #object[getSomething]
((goog.object/get thing "getSomething"))
=> :a

justinlee15:07:28

you can just use goog.object/get to grab the create function off of the imported object and then invoke that value

justinlee15:07:49

because the closure compiler does not munge strings, it won’t be subject to advanced compilation

justinlee15:07:28

it’s just a way of confirming that the issue is symbol munging rather than the actual create symbol somehow not being there at all

thheller18:07:51

@lsnape @lee.justin.m this is probably not a munging issue. if you use /js/... to import the file it will be imported by the closure compiler and passed through :advanced. meaning it needs to externs.

justinlee18:07:30

ooh i missed that this was a direct include

thheller18:07:32

@oscar starting with / has a different meaning in shadow-cljs and means importing from the classpath root. https://shadow-cljs.github.io/docs/UsersGuide.html#_requiring_js

oscar18:07:56

Ah. I've only ever imported node modules. That makes sense.

thheller18:07:38

@lsnape judging by the compiler output it appears that the static create method is getting removed by closure. which I believe is documented somewhere. let me see if I can find it

thheller18:07:31

class SomeClass {
    /** @nocollapse */
    static create(params) {
        return ["SomeClass.create",1,2,params];
    }
}

thheller18:07:32

this works. I don't think the issue is solvable by externs alone.

lsnape19:07:59

Thanks thheller! I'll give that a go.

lsnape19:07:42

That's done it. Thanks, not sure how long it would have taken me to stumble across that. You rock metal

dfcarpenter22:07:31

New shadow-cljs user here. So on shadow-cljs watch app I am getting The required JS dependency "jquery" is not available, it was required by "cljsjs/jquery.cljs". How can I figure out which dependency needs that so I can assess whether I want it or not?

justinlee22:07:07

@dfcarpenter just do a npm i jquery --save

justinlee22:07:56

shadow-cljs basically ignores the foreign-libs dependency in the cljsjs package because it reads js code directly from the node_modules directory, so you need to install the js modules directly

justinlee22:07:11

oh sorry you were asking a different question

dfcarpenter22:07:54

I figured it out by checking each dep repo. Looks like the re-pressed library ( capturing keyboard events in re-frame ) uses jquery ( which is overkill )

justinlee22:07:27

i suspect there is a lein deps :tree type command in the shadow repl but i don’t know what it is

gadfly36123:07:13

@dfcarpenter Yeah, re-pressed does unfortunately use jQuery 😬 (I didn't want to go through the trouble of making an abstracted way to guarantee cross-browser support ... so leaned on jquery to do it for me with which)

dfcarpenter23:07:14

@gadfly361 Ahh, of course cross browser support. Totally understand; there be dragons for cross browser/legacy browsers. Anyways, does the google closure library not handle this or does it only handle chrome?

gadfly36123:07:10

@dfcarpenter I am not actually sure, but if it does, then that would be a good approach 🙂

dfcarpenter23:07:51

@gadfly361 Actually since gmail and I think the google office suite uses the closure library and it does have really good cross browser support I think it may be a good option.

parrot 4
👍 4