I'm trying to connect to a ClojureScript browser REPL, and I'm having trouble with clojure.browser.repl/connect
. My compiled JavaScript throws a TypeError
trying to call appendChild
on a null
object in the block of Google Closure code at the top. I'm following the instructions in ClojureScript: Up and Running (Chapter 9, p.78, available in the preview), and wondering if the tooling for this has changed since it was published.
I'm using Leiningen 2.0.0, Java 1.6.0_37, OS X 10.7.5, plus the dependencies in my project.clj
:
(defproject brepl-hello "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.4.0"]
[org.clojure/clojurescript "0.0-1552"]
[compojure "1.1.5"]
[ring/ring-jetty-adapter "1.1.8"]]
:plugins [[lein-cljsbuild "0.3.0"]]
:source-paths ["src/clj"]
:cljsbuild {:builds [{
:source-paths ["src/cljs"]
:compiler {
:output-to "resources/public/brepl-hello.js"
:optimizations :whitespace
:pretty-print true}}]})
Here's the only ClojureScript source file, src/cljs/brepl_hello/brepl-hello.cljs
:
(ns brepl-hello
(:require [clojure.browser.repl :as repl]))
(repl/connect "http://localhost:9000/repl")
This compiles to the file resources/public/brepl-hello.js
, which I've inserted into index.html
in the same directory:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="brepl-hello.js"></script>
</head>
<body>
</body>
</html>
I've been serving this on port 3000 with Ring/Jetty from the REPL or Python SimpleHTTPServer. When I open this page in Chrome, the dev console shows Uncaught TypeError: Cannot call method 'appendChild' of null
, with a traceback to this if
/else
block in the Google Closure code at the top of the complied js file, where parentElm
(passed in to the containing function as a parameter) is null
.
if(goog.userAgent.GECKO || goog.userAgent.WEBKIT) {
window.setTimeout(goog.bind(function() {
parentElm.appendChild(iframeElm);
iframeElm.src = peerUri.toString();
goog.net.xpc.logger.info("peer iframe created (" + iframeId + ")")
}, this), 1)
}else {
iframeElm.src = peerUri.toString();
parentElm.appendChild(iframeElm);
goog.net.xpc.logger.info("peer iframe created (" + iframeId + ")")
}
This seems to be a problem with clojure.browser.repl/connect
. Swapping out this line in the ClojureScript source for something like:
(ns brepl-hello
(:require [clojure.browser.repl :as repl]))
(.write js/document "Hello World!")
Will compile and run in the browser just fine. I suspect something is misconfigured in my build settings or directory structure, or I'm making a noob mistake somewhere in all this. What's changed since the time the instructions I'm following were published? I found a couple references to this problem in the #clojure irc logs, but no solution.
Finally, here's an abbreviated directory tree for reference:
├── out
│ ├── cljs
│ │ ├── core.cljs
│ │ └── core.js
│ ├── clojure
│ │ └── browser
│ │ ├── event.cljs
│ │ ├── event.js
│ │ ├── net.cljs
│ │ ├── net.js
│ │ ├── repl.cljs
│ │ └── repl.js
│ └── goog
│ └── [...]
├── pom.xml
├── project.clj
├── resources
│ └── public
│ ├── brepl-hello.js
│ └── index.html
├── src
│ ├── clj
│ │ └── brepl_hello
│ │ └── core.clj
│ └── cljs
│ └── brepl_hello
│ └── brepl-hello.cljs
└─── target
├── brepl-hello-0.1.0-SNAPSHOT.jar
├── classes
├── cljsbuild-compiler-0
│ ├── brepl_hello
│ │ └── brepl-hello.js
│ ├── cljs
│ │ ├── core.cljs
│ │ └── core.js
│ └── clojure
│ └── browser
│ ├── event.cljs
│ ├── event.js
│ ├── net.cljs
│ ├── net.js
│ ├── repl.cljs
│ └── repl.js
└── stale
└── extract-native.dependencies