cemerick / austin

The ClojureScript browser-REPL rebuilt stronger, faster, easier.
510 stars 31 forks source link

Cljs compiler env doesn't correspond to a refreshed browser env, with (disastrous!) consequences #54

Closed gtrak closed 10 years ago

gtrak commented 10 years ago

Had an interesting conversation about it http://clojure-log.n01se.net/date/2014-03-01.html#21:08

Symptoms: load-file in the piggieback repl doesn't seem to be loading transitive deps due to stale compiler state, however my tooling/auto-complete stuff still thinks things exist.

This was on my fork of austin + clojurescript master.

Normal functioning:

cljs-app.core> body
#<function body(){return (goog.dom.getElemfentsByTagNameAndClass("body")[0]);
}>
nil

After a refresh:

cljs-app.core> body
"Error evaluating:" body :as ""
#<ReferenceError: cljs_app is not defined>
ReferenceError: cljs_app is not defined
    at eval (repl-1393737033414.js:1:65)
    at eval (repl-1393737033414.js:5:3)
    at http://localhost:54162/6802/repl/start:1480:313
    at clojure.browser.repl.evaluate_javascript (http://localhost:54162/6802/repl/start:1481:238)
    at Object.callback (http://localhost:54162/6802/repl/start:1489:111)
    at goog.messaging.AbstractChannel.deliver (http://localhost:54162/6802/repl/start:1354:393)
    at goog.net.xpc.CrossPageChannel.xpcDeliver (http://localhost:54162/6802/repl/start:1450:350)
    at Function.goog.net.xpc.NativeMessagingTransport.messageReceived_ (http://localhost:54162/6802/repl/start:1409:389)
    at goog.events.Listener.handleEvent (http://localhost:54162/6802/repl/start:1089:102)
    at Object.goog.events.fireListener (http://localhost:54162/6802/repl/start:1104:448)

I think there are two obvious solutions.

  1. Re-initialize the compiler state for the session on a reconnect to a clean state, fixing reloads.
  2. Emit a JS string corresponding to the CLJS compiler state via internal compiler stuffs, and use that as the browser's client-js string upon a refresh.

I feel like 2 would be more awesome than ill-conceived.

Further investigation reveals: Seems like compiled-cljs files are enumerated and stored in the compiler state map, we could load those up. This doesn't address normal eval'd code, though. No biggie.

In closure.clj

(defprotocol Compilable
  (-compile [this opts] "Returns one or more IJavaScripts."))

Seems like this could be specified to return the pre-existing compiled sources that are already on disk (in dependency order) via closure/compiled-file, then clojurescript/closure's build function can continue to handle bundling everything up.

cemerick commented 10 years ago

I don't seem to experience any serious consequences upon reloading the browser then reloading sources; dependencies appear to be loaded as expected…

That said, a refresh should yield option (1), not (2); though surely awesome, the intent of reloading the browser is to yield a clean slate, not a JS environment that has all previously-loaded code loaded again. Conveniently, it also has the benefit of being really easy to implement. :-P

gtrak commented 10 years ago

I'll try to get to this in the next couple of days (the clean slate option, I've spent a few hours already trying to figure out the reload option, and I need more closure experience and hammock time to pull it off, I think :-), not sure what's the timeline for 0.1.5.

gtrak commented 10 years ago

I'll just save off a snapshot of the env state in-memory after the first compilation so we can continue to cache it as a file.

cemerick commented 10 years ago

Is this something that you've already implemented in your tooling middleware, or is there a change/patch that should land here?

gtrak commented 10 years ago

I think I worked around this by always running a cljsbuild environment in addition to the repl, I haven't seen the behavior in a while. I tried to hack Austin to always reload whatever code has already been eval'd via compiler state, but that became a mess very quickly.

On Saturday, August 23, 2014, Chas Emerick notifications@github.com wrote:

Is this something that you've already implemented in your tooling middleware, or is there a change/patch that should land here?

— Reply to this email directly or view it on GitHub https://github.com/cemerick/austin/issues/54#issuecomment-53153816.

cemerick commented 10 years ago

Yeah, not surprising, especially since the compiler state will include all sorts of random snippets evaluated interactively (i.e. not whole files).