BetterThanTomorrow / calva

Clojure & ClojureScript Interactive Programming for VS Code
https://marketplace.visualstudio.com/items?itemName=betterthantomorrow.calva
Other
1.65k stars 216 forks source link

CLJS interop issue #1074

Open bpringe opened 3 years ago

bpringe commented 3 years ago

The Issue

In some parts of the code, an error is thrown when a function imported from the cljs-lib is called. The error states that the function "is not a function," even though this same function imported and called in other files in the code base works. I've not yet been able to track down the cause, but this limits us in more widely using CLJS in Calva.

How to Reproduce the Issue

I created a branch from dev called cljs_interop_issue just to freeze the code in its current state for the below repo, but left the steps as an exercise so it's more clear what's going on.

  1. Checkout cljs_interop_issue

  2. Add this import at the top of the annotations.ts file:

    import { setStateValue } from '../../out/cljs-lib/cljs-lib';
  3. Change this line to setStateValue(key, ranges);: https://github.com/BetterThanTomorrow/calva/blob/72dba0ddf25af35b49f558e6e01e375a1a94269a/src/providers/annotations.ts#L93

  4. Run the build task (ctrl+shift+b - or find the command in the command palette)

  5. Hit F5 to run the extension host

  6. Run jack-in

  7. Load a file and evaluate a call to a function in that file.

  8. See the error printed in the debug console of the Calva VS Code window: TypeError: cljs_lib_1.setStateValue is not a function

The Workaround That Only Works in Some Cases

As you can see, I've worked around this issue by importing the cljs-lib in utilities.ts, and exporting it from that module. Then I import the utilities module in the annotations module and use the cljs-lib from the utilities import.

I realized later this doesn't fix all issues, as I later had written some code that indirectly called into the utilities module, into this code, which threw the same type of error, whereas it didn't before: https://github.com/BetterThanTomorrow/calva/blob/72dba0ddf25af35b49f558e6e01e375a1a94269a/src/utilities.ts#L177

In Summary

The workaround is brittle at best and what we need to know is why the cljs functions are not recognized in some call paths, but they are recognized in others. It seems to be some strange linking issue.

I've had the issue happen with the dev build as noted in the repro steps above, as well as not happen in the dev build, but then happen in the release build (bundled by webpack). I've tried changes to the typescript config and the webpack config with no luck.

bpringe commented 3 years ago

I experimented with making a cljs entry point for the extension by making an extension.cljs file that required the extension.js file and called its activate function, but this also produced the error that setStateValue is not a function, here at the first call of it: https://github.com/BetterThanTomorrow/calva/blob/603a96476cfab15ce0796b8067919588778a2e2a/src/extension.ts#L69