How to compile ES2018 javascript dependency? - clojurescript

I have a project with some NPM deps, noteably "#grafana/data": "7.0.1". These dependencies bring in several other libs like apache-arrow. When I try to require deps via (require '"#grafana/data"), I get a bunch of compiler errors like:
ERROR: JSC_LANGUAGE_FEATURE. This language feature is only supported for ECMASCRIPT8 mode or better: async function.
I found similar kinds of errors addressed in google closure compiler issues which leads me to beleive that I cant have library dependencies that require modern javascript as the closure compiler can't handle them. Similarly the closurescript docs don't allow for a :language-in argument for es-2018 et. al.
The the clojure build.edn settings I set are:
:language-in :es-next
:language-out :es5
:rewrite-polyfills
Unfortunately, this doesn't work.
Is there any way that I can get the closure compiler to handle modern javascript dependencies? Are there some crazy hacks that I can do to make this work?

Related

Clojurescript core.matrix aljabr implementation must be explicitly set

Using core.matrix in a ClojureScript project. For javascript interop I need aljabr as explained in https://github.com/mikera/core.matrix/wiki/Matrix-implementations
After I try to specify the implementation (as I do with other Clojure implementations)
(require '[clojure.core.matrix :as mat])
(require '[thinktopic.aljabr.core :as imp])
(mat/set-current-implementation :aljabr)
I get this error and I can't use the matrix implementation for Javascript
INFO: No dynamic loading of implementations in Clojurescript.
You must require an implementation explicitly in a namespace, for example thinktopic.aljabr.core
Looking on github I only find the implementation used as I mention above (e.g. https://github.com/mars0i/free/commit/71dbbe4d58645ad4e25f2ac2d4ccba6ccef93968), how can I make aljabr work in cljs?
You need to set the implementation statically, that means not at the beginning of the file like you did but when you actually declare your matrix
(mat/matrix :aljabr [[1.0 2.0 3.0][4.0 5.0 7.0]])
(I answered to myself just cause there is no result on the internet for that error and took me a while to understand the error message explanation, even with git blames)

Remove debugger keyword during compilation in google closure

UPDATE:
The JS version of closure-compiler is no longer supported or maintained.
https://github.com/google/closure-compiler-npm/blob/master/packages/google-closure-compiler-js/readme.md
Im trying to find if there is a way to remove the "debugger" keyword during compilation process, im using the javascript version google-closure-compiler with gulp.
Looking through the documentation it is clear we can set the flag to stop/show error messages during compilation by doing the following.
https://github.com/google/closure-compiler/wiki/Flags-and-Options
--jscomp_off
translating this to gulp, it is:
const googleClosureOptions = {
...
jscomp_error:"checkDebuggerStatement"
}
however this works on stopping the compilation by throwing error or to show a warning.
zyxcdafg.js:1444: ERROR - [JSC_DEBUGGER_STATEMENT_PRESENT] Using the debugger statement can halt your application if the user has a JavaScript debugger running.
debugger;
^^^^^^^^^
but what I am trying to achieve is to remove the debugger keyword. Is this possible to achieve using googleclosure. I can not find any flags or options relating to this.
UPDATE:
The JS version of closure-compiler is no longer supported or maintained.
https://github.com/google/closure-compiler-npm/blob/master/packages/google-closure-compiler-js/readme.md
No I don't think so. I'd suggest you use something else to do it. Like sed:
find dist -name "*.js" -exec sed -i 's/\sdebugger;//' {} +
Something like that will find files in your dist folder that end with .js and then exec-ute sed to replace all instances of debugger; with nothing.
You could add that to a script that calls your Closure Compiler build.
The compiler doesn't have a command-line api for defining custom code removal passes, but the compiler's architecture does allow for registering custom passes and a pass to remove a debugger statement should be trivial:
if (n.isDebugger()) {
compiler.reportChangeToEnclosingScope(n);
n.detach();
}
The general structure would follow:
https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/CheckDebuggerStatement.java

How can I stop the ClojureScript compiler from resolving certain `require`s?

In my ClojureScript code I am requiring a JavaScript module called seedrandom which is in the node_modules folder, like this:
(ns something.core
(:require ["seedrandom" :as rnd]))
(js/console.log (.quick (rnd "x")))
According to the seedrandom documentation it is intended for both nodejs and the browser, and I've previously included and used it successfully in ClojureScript code via a <script> tag, confirming it works in the browser.
Running this cljs file in lumo on the command line works well and outputs a deterministically random number.
When I try to use this same cljs file in my Reagent frontend project I see the following error:
Compiling build :app to "public/js/app.js" from ["src" "env/dev/cljs"]...
events.js:183
throw er; // Unhandled 'error' event
^
Error: module not found: "crypto" from file /home/chrism/dev/something/node_modules/seedrandom/seedrandom.js
at onresolve (/home/chrism/dev/something/node_modules/#cljs-oss/module-deps/index.js:181:30)
...
Inside seedrandom.js we see the following:
// When in node.js, try using crypto package for autoseeding.
try {
nodecrypto = require('crypto');
} catch (ex) {}
Clearly this code is intended to ignore the built-in nodejs crypto module when running in the browser. The problem, as far as I can tell, is that the ClojureScript compiler does not know that - it sees that require('crypto') and tries to pull it into the compilation phase, but can't find it because it's a nodejs built-in.
Is there some way I can tell the compiler to ignore that particular require? Or can I shim the 'crypto' module somehow? What is the cleanest way to solve this?
Note: I have previously experienced this same issue with JavaScript modules which check for the fs node module. Hope we can find a general solution to use again in future. Thanks!
Relevant versions: [org.clojure/clojurescript "1.10.520"] and [reagent "0.8.1"].
This answer is related, asking a similar question from the perspective of Google Closure, which ClojureScript uses, but I'm looking for an answer I can use specifically with cljs.

ClojureScript Eval. How to use libraries included in the calling code

I have a Clojurescript program running in the browser.
It imports a number of libraries, and then I want to allow the user to enter some small clojurescript "glue-code" that calls those libraries.
I can see (from https://cljs.github.io/api/cljs.js/eval) that you call eval with four arguments, the first being the state of the environment, which is an atom. But can I actually turn my current environment with all the functions I've required from elsewhere, into an appropriate argument to eval?
Update :
I thought that maybe I could set the namesspace for the eval using the :ns option of the third, opts-map, argument. I set it to the namespace of my application :
:ns "fig-pat.core"
But no difference.
Looking at the console, it's definitely the case that it's trying to do the evaluation, but it's complaining that names referenced in the eval-ed code are NOT recognised :
WARNING: Use of undeclared Var /square
for example. (square is a function I'm requiring. It's visible in the application itself ie. the fig-pat.core namespace)
I then get :
SyntaxError: expected expression, got '.'[Learn More]
Which I'm assuming this the failure of eval-ed expression as a whole.
Update 2 :
I'm guessing this problem might actually be related to : How can I get the Clojurescript namespace I am in from within a clojurescript program?
(println *ns*)
is just printing nil. So maybe Clojurescript can't see its own namespace.
And therefore the :ns in eval doesn't work?
Calling eval inside a clojurescript program is part of what is called "self-hosted clojurescript".
In self-hosted clojurescript, namespaces are not available unless you implement a resolve policy. It means that have to let the browser know how to resolve the namespace e.g. loads a cljs file from a cdn.
It's not so trivial to implement namespace resolving properly.
This is explained in a cryptic way in the docstring of load-fn from cljs.js namespace.
Several tools support namespaces resolving in self-host cljs running in the browser e.g Klipse and crepl

NPAPI plugin: nsScriptablePeer.obj : error LNK2019: unresolved external symbol _NPN_Evaluate referenced in function

I am trying to compile NPAPI plugin under Win-XP and VS 2008.
Its giving me error as nsScriptablePeer.obj : error LNK2019: unresolved external symbol _NPN_Evaluate referenced in function when I try to use NPN_Evaluate to call javascript function . I have added all libraries from xulrunner-sdk/lib and xullrunner-sdk/sdk/lib in additional library directories. Is there any other library needs to be included to use NPN_Evaluate function ?
The functions beginning with NPN_ are only accessible through the pointer passed during the initialization NP_Initialize phase. I've been caught by this situation and I decided to document a bit here.
In other words, you don't have to link a library but you have to catch the pointer to the NPN browser functions during the NP_Initialize call to your plugin.
You can find a brief rundown of npapi plugins in general here:
http://colonelpanic.net/2009/03/building-a-firefox-plugin-part-one/
it's a little disjointed, but my goal was to answer some of the not-well-explained parts of NPAPI, like the one you ran into here =]
Incidently, if you're using nsScriptablePeer, you're using an outdated example that still uses XPCOM instead of NPObjects. XPCOM will no longer be supported in future versions of firefox (starting 3.6, I believe)
A little more about that here: http://colonelpanic.net/2009/08/building-a-firefox-plugin-%E2%80%93-part-three/

Categories