<< Back to previous view

[CLJS-525] Allow hashtable lookup used for numbers and strings to be extended to other built-in types Created: 17/Jun/13  Updated: 17/Jun/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Chas Emerick Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

...which would enable safe extension of key cljs protocols to types without modifying their prototypes, e.g. CLJS-523.



 Comments   
Comment by David Nolen [ 17/Jun/13 2:56 PM ]

Date is the only JS native case that I'm aware of that we don't handle. One tricky bit is that goog.typeOf won't give us the information we need, but I think instanceof should cover us here?

Comment by Fogus [ 17/Jun/13 3:05 PM ]

instanceof or the ever-gruesome toString.call(aDate) == '[object Date]' will work.





[CLJS-1439] Add type annotations to goog-define defined vars Created: 01/Sep/15  Updated: 01/Sep/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Martin Klepsch Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently it's still required to annotate goog-define constants with ^boolean to allow the Closure compiler to safely remove dead branches. The macro could emit the var with ^boolean metadata to make this unnecessary.

In general it would be nice to have similar annotations for the already defined constants like goog.DEBUG although I'm not sure how/if that's possible.






[CLJS-1479] Race condition in browser REPL Created: 03/Nov/15  Updated: 03/Nov/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Daniel Skarda Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File heavy-load.sh     File race-condition.clj     File race-condition.jstack    

 Description   

Evaluation in browser REPL occasionally hangs. It seems that repl environment and browser sometimes miss each other and their "randezvous" fails. Browser is waiting for POST reply and repl is trying to send a command, but they do not meet each other.

I found the issue when we switched our tests from nodejs to browser environment. Luckily I was able to find very small example which hangs during execution. It seems that (simulated) heavy load increases the chance of "hanging".

Minimal setup:

(ns race.condition
  (:require [cljs.repl.browser :as browser]
            [cljs.repl :as repl]
            [cljs.env :as env]
            [cljs.build.api :as api]))


(api/build '[(ns race.repl
               (:require [clojure.browser.repl]))
             (clojure.browser.repl/connect "http://localhost:9000/repl")]
           {:output-to  "target/cljs-race/main.js"
            :output-dir "target/cljs-race"
            :main       'race.repl})

(spit "target/cljs-race/index.html"
      (str "<html>" "<body>"
           "<script type=\"text/javascript\" src=\"main.js\">"
           "</script>" "</body>" "</html>"))

Now start the environment:

(def env (browser/repl-env :static-dir ["target/cljs-race" "."] :port 9000 :src nil))

(env/with-compiler-env (env/default-compiler-env)
  (repl/-setup env {}))

cross your fingers and start this endless loop:

(loop [i 0]
  (println (java.util.Date.) i)
  (dotimes [j 100]
    (let [result (repl/-evaluate env "<exec>" "1"  "true")]
      (when-not (= :success (:status result))
        (println i j result))))
  (recur (inc i)))

To simulate heavy load run heavy-load.sh from attachment.

After some iterations (eg 55 big loop i) execution stops. If you investigate stacks (see race-condition.jstack), you can see in one thread:

at clojure.core$promise$reify__6779.deref(core.clj:6816)
	at clojure.core$deref.invoke(core.clj:2206)
	at cljs.repl.browser$send_for_eval.invoke(browser.clj:65)
	at cljs.repl.browser$browser_eval.invoke(browser.clj:193)
	at cljs.repl.browser.BrowserEnv._evaluate(browser.clj:262)

The code is waiting for a promise with a connection (which already did arive).

My guess is suspicious code in cljs.repl.server functions connection and set-connection. Both functions access an atom in non-standard way. They deref a valua and make a swap! in two steps.

Can somebody with better understanding of REPL internals investigate? Thank you.






[CLJS-1346] Support require outside of ns Created: 18/Jul/15  Updated: 18/Jul/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Jonathan Boston Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Makes http://dev.clojure.org/jira/browse/CLJS-1277 useful.






[CLJS-1508] Extend ns form to support :rename option Created: 09/Dec/15  Updated: 09/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Support a :rename option to :require. Following :rename should be a map of symbol to symbol. Refer to clojure.core/refer for semantics with respect to this allowing avoidance of clashes.

An REPL example:

(require '[fipp.edn :refer (pprint) :rename {pprint fipp}])





[CLJS-1507] Implicit macro loading: macro var inference in :refer Created: 09/Dec/15  Updated: 12/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Mike Fikes Assignee: Mike Fikes
Resolution: Unresolved Votes: 1
Labels: None

Attachments: Text File CLJS-1507-partial.patch    

 Description   

Background: When employing ns, if a namespace is required or used, and that namespace itself requires or uses macros from its own namespace, then the macros will be implicitly required or used using the same specifications.

This ticket asks for a mild extension to the above, automatically inferring when referred symbols are macro vars in two cases:

  1. :require / :refer
  2. :use / :only

Here is a concrete example illustrating the cases:

Assume src/foo/core.clj contains a single macro:

(ns foo.core)

(defmacro unless [pred a b]
  `(if (not ~pred) ~a ~b))

and src/foo/core.cljs requires that macro namespace:

(ns foo.core
  (:require-macros foo.core))

Without loss of generality, assume we do the following in a REPL.

$ java -cp cljs.jar:src clojure.main -m cljs.repl.node
ClojureScript Node.js REPL server listening on 49522
To quit, type: :cljs/quit
cljs.user=> (require '[foo.core :refer [unless]])
;; Currently get an error

Currently, the code assumes that unless is a non-macro var and a "Referred var foo.core/unless does not exist" diagnostic is emitted. To satisfy this ticket, the code should consult the foo.core macro namespace for the existence of an unless macro, and refer it as if

(require-macros '[foo.core :refer [unless]])
had been issued.

Likewise, this should work for the :use / :only dual form: When

(ns bar.core (:use [foo.core :only [unless]]))
is issued.

Additionally, the same behavior should be ensured to work in bootstrapped mode.



 Comments   
Comment by Thomas Heller [ 10/Dec/15 4:26 AM ]

Great to see you pick this up.

My patch for CLJS-948 included an implementation for this if you need a reference, although some things have changed since then and the patch won't apply cleanly. Still the basic idea is still the same.

Comment by Thomas Heller [ 10/Dec/15 4:33 AM ]

Again, just for reference:
https://github.com/thheller/shadow-build/blob/7b2564e9aa33a93c1af90826c837e3f5d307a116/src/clj/shadow/cljs/util.clj#L214-L279

Is the full implementation in use by shadow-build ever since the :refer part was rejected from CLJS-948, that is also where my patch initially came from.

Comment by Mike Fikes [ 11/Dec/15 8:33 PM ]

Attaching a partial patch in case it leads to interesting commentary.

This patch was written prior to my knowledge of Thomas' prior work. I don't have an opinion yet on the values of either approach: This one differs simply by accident of being written independently.

This patch works by transforming things in the sugared domain, thus taking something like

(:require [foo.core :refer [bar unless]])

into

(:require [foo.core :refer [bar] :refer-macros [unless]])

This patch is incomplete because it determines whether a symbol is a macro by attempting to find its macroexpander, and thus encounters the need for the foo.core namespace to have been analyzed, which is not guaranteed.

But, this patch will work if you artificially (say, in a REPL), load foo.core by itself first. Evidently Thomas' approach encountered a similar issue, but he resolved it (presumably by forcing the needed analysis to occur).

Comment by Thomas Heller [ 12/Dec/15 4:09 AM ]

Mike: I had two separate goals with my implementation. In shadow-build I have a discovery phase that inspects all files and parses the ns form in case of .cljs files. I wanted this phase to be completely free of side-effects in regards to the compiler state. I did not want to touch the analyzer env or load macros since I do not know whether the discovered namespace is going to be used later. I only extract the basic requires/provides to build the dependency graphs via :main (forced by shadow-build). Actual compilation always happens in full dependency order and macros are loaded when needed with all checks. The discovery skips some basic checks it cannot know about yet, ie. it checks for self-require but doesn't load macros yet.

The approach chosen by parse-ns in cljs.analyzer is to capture the compiler env and reset it after parsing the ns, your approach moves side-effects into the parsing again which may become a problem later since it cannot reset {{require}}ing a Clojure ns.

Whether or not this is a problem I cannot say, it just didn't agree with my goals. YMMV.

Comment by Mike Fikes [ 12/Dec/15 7:35 AM ]

Thanks @thheller, I'll see if I can come up with a patch that implements the inference in ns-side-effects.





[CLJS-1335] resolve-macro-var: information missing for macros Created: 12/Jul/15  Updated: 26/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bootstrap
Environment:

https://github.com/swannodette/cljs-bootstrap



 Description   

In bootstrapped ClojureScript, if you resolve-var on a function, you get lots of information, but resolve-macro-var doesn't work for macros. (The only reason I have any expectation for this to work is that it appears to do so in ClojureScript JVM).

cljs-bootstrap.core=> (with-compiler-env cenv (ana/resolve-macro-var (ana/empty-env) 'or)))
nil

But:

cljs-bootstrap.core=> (with-compiler-env cenv (ana/resolve-var (ana/empty-env) 'map)))
{:protocol-inline nil, :meta {:file "cljs/core.cljs", :end-column 10, :top-fn {:variadic true, :method-params ([f] [f coll] [f c1 c2] [f c1 c2 c3]), :arglists-meta (nil nil nil nil nil), :max-fixed-arity 4, :arglists ([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])}, :column 7, :line 4128, :end-line 4128, :arglists (quote ([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])), :doc "Returns a lazy sequence consisting of the result of applying f to\n  the set of first items of each coll, followed by applying f to the\n  set of second items in each coll, until any one of the colls is\n  exhausted.  Any remaining items in other colls are ignored. Function\n  f should accept number-of-colls arguments. Returns a transducer when\n  no collection is provided."}, :ns cljs.core, :name cljs.core/map, :variadic true, :file "cljs/core.cljs", :end-column 10, :top-fn {:variadic true, :method-params ([f] [f coll] [f c1 c2] [f c1 c2 c3]), :arglists-meta (nil nil nil nil nil), :max-fixed-arity 4, :arglists ([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])}, :method-params ([f] [f coll] [f c1 c2] [f c1 c2 c3]), :protocol-impl nil, :arglists-meta (nil nil nil nil nil), :column 1, :line 4128, :end-line 4128, :max-fixed-arity 4, :fn-var true, :arglists ([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]), :doc "Returns a lazy sequence consisting of the result of applying f to\n  the set of first items of each coll, followed by applying f to the\n  set of second items in each coll, until any one of the colls is\n  exhausted.  Any remaining items in other colls are ignored. Function\n  f should accept number-of-colls arguments. Returns a transducer when\n  no collection is provided."}

As an aside:

cljs-bootstrap.core=> (with-compiler-env cenv (ana/resolve-var (ana/empty-env) 'or)))
{:name cljs.core/or, :ns cljs.core}


 Comments   
Comment by Andrea Richiardi [ 26/Dec/15 3:06 PM ]

I have a bit had a look at this and cljs.analyzer.api/resolve has the best approach, trying first resolve-var and then resolve-macro-var. At the moment this behavior is duplicated in both replumb and planck. It would be great to have that part of cljs.analyzer.api, and maybe others, ported to cljs.js. Thoughts?

Comment by Andrea Richiardi [ 26/Dec/15 3:29 PM ]

Actually in replumb at the moment I had to do something like:

[DELETED]

But it is just a workaround and probably you guys have a better approach to it.

Comment by Andrea Richiardi [ 26/Dec/15 5:52 PM ]

In replumb at the moment I had to merge the two maps, giving precedence to ana/resolve-var:

(defn resolve
  "From cljs.analyzer.api.clj. Given an analysis environment resolve a
  var. Analogous to clojure.core/resolve"
  [opts env sym]
  ;; AR - we need to merge because ana/resolve-var sometimes returns more
  ;; info than ana/resolve-macro-var, sometimes not
  (merge (ana/resolve-macro-var env sym) (ana/resolve-var env sym ana/confirm-var-exist-warning)))




[CLJS-365] apply needs to put all args after the 20th into an array seq Created: 29/Aug/12  Updated: 29/Aug/12

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Major
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

This ticket is related to CLJS-359






[CLJS-364] compiler needs to put all args of an invocation after 20 into an array-seq Created: 29/Aug/12  Updated: 29/Aug/12

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Major
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

This ticket is related to CLJS-359






[CLJS-1410] Support source maps in deps.cljs Created: 09/Aug/15  Updated: 09/Aug/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Major
Reporter: Martin Klepsch Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

There should be support to package source maps with a foreign-lib using deps.cljs






[CLJS-1466] Absolute paths in :output-dir break Node.js shim for :none Created: 11/Oct/15  Updated: 29/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Sebastian Bensusan Assignee: Sebastian Bensusan
Resolution: Unresolved Votes: 0
Labels: bug

Attachments: Text File cljs_1466.patch    
Patch: Code

 Description   

When compiling a trivial example with the following script:

(require 'cljs.build.api)

(cljs.build.api/build "src"
  {:main 'hello.core
   :output-to "main.js"
   :output-dir "/home/carlos/Playground/node-abs/out"
   :target :nodejs})

It generates code that tries to resolve the following path:

/home/carlos/Playground/node-abs/home/carlos/Playground/node-abs/out/goog/bootstrap/nodejs.js

We should check if the provided path for :output-dir is absolute before resolving it in the Node.js :none shim. The shim has a related ticket in CLJS-1444.

Even if it's uncommon for users to have absolute paths, tooling might need to.



 Comments   
Comment by Sebastian Bensusan [ 11/Oct/15 4:28 PM ]

The attach patch cljs_1466.patch solves the issue by using path.resolve which takes into account relative vs absolute paths when joining paths. Successfully tested in the example repo with both relative and absolute :output-dir

Comment by Martin Klepsch [ 14/Oct/15 3:57 AM ]

Looking at the patch it seems that it might break current behaviour in some cases? Have you thought about that?

CLJS-1444 [1] would probably also break the shim in some way so would be good to get these in together and be very clear about what will break etc. As long as we come up with a robust and predictable impl this is something worth breaking imo.

[1] http://dev.clojure.org/jira/browse/CLJS-1444 for

Comment by David Nolen [ 14/Oct/15 8:05 AM ]

Yes would like to get feedback from people already heavily invested in ClojureScript + Node.js before moving forward on this.

Comment by Sebastian Bensusan [ 14/Oct/15 10:31 AM ]

Martin Klepsch: I did think about breakage but I couldn't find any cases. Do you have an example one? In the example repo I've put together some tests (by running ./script/test.sh) but it boils down to path.join(path.resolve("."),paths) being equivalent to path.resolve(paths) for all relative paths, since the "Resolve to absolute" method is the same for both (process.cwd() inside of path.resolve). When considering absolute paths, only the new version does the right thing.

On the other hand, those tests also reveal that the proposed patch doesn't cover CLJS-1446 as I originally thought since

node main.js

succeeds while:

cd ..
node node-abs/main.js

fails.





[CLJS-1555] make-array macro missing 2 arg arity Created: 31/Jan/16  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.228
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1555.patch    
Patch: Code and Test

 Description   

You can do

(apply make-array [nil 2])
but not
(make-array nil 2)
.






[CLJS-1558] Code allowed to re-define referred var Created: 31/Jan/16  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.228
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

If you refer a var from another namespace, then you can def a new value for that var, and the def will mutate the other namespace, and other things will go wrong as illustrated in the example below.

FWIW, Clojure disallows this, and refuses to allow you to evaluate a def involving a referred var, and emits an error diagnostic like:

CompilerException java.lang.IllegalStateException: foo already refers to: #'some.name.space/foo in namespace: user, compiling:(NO_SOURCE_PATH:2:1)

Here is a complete example illustrating the issues:

Given:

(ns foo.core)

(defn square [x]
  (* x x))

then do this in a REPL:

cljs.user=> (require '[foo.core :refer [square]])
nil
cljs.user=> (var square)
#'foo.core/square
cljs.user=> (square 3)
9
cljs.user=> (ns-interns 'cljs.user)
{}
cljs.user=> (defn square [x] (+ x x))
WARNING: square already refers to: foo.core/square being replaced by: cljs.user/square at line 1 <cljs repl>
#'foo.core/square
cljs.user=> (square 3)
6
cljs.user=> (var square)
#'foo.core/square
cljs.user=> (in-ns 'foo.core)
nil
foo.core=> (square 3)
6
foo.core=> (in-ns 'cljs.user)
nil
cljs.user=> (ns-interns 'cljs.user)
{square #'cljs.user/square}
cljs.user=> (cljs.user/square 3)
TypeError: Cannot read property 'call' of undefined
    at repl:1:105
    at repl:9:3
    at repl:14:4
    at Object.exports.runInThisContext (vm.js:54:17)
    at Domain.<anonymous> ([stdin]:41:34)
    at Domain.run (domain.js:221:14)
    at Socket.<anonymous> ([stdin]:40:25)
    at emitOne (events.js:77:13)
    at Socket.emit (events.js:169:7)
    at readableAddChunk (_stream_readable.js:146:16)
cljs.user=> #'cljs.user/square
#'cljs.user/square
cljs.user=> @#'cljs.user/square
nil





[CLJS-246] Use protocol mask test in protocol fns Created: 09/May/12  Updated: 29/Jul/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: Michał Marczyk
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File 0001-CLJS-246-have-protocol-methods-check-bitmasks-for-fa.patch    

 Description   

This is a performance win on many browsers.

http://jsperf.com/direct-vs-chain/8



 Comments   
Comment by Michał Marczyk [ 10/May/12 1:11 PM ]

See CLJS-247 for comments relevant to this patch.

Comment by David Nolen [ 10/May/12 3:30 PM ]

Not seeing much of a perf benefit from this, though Michal reports differently. More investigation is needed.

Comment by David Nolen [ 17/Jun/12 12:14 PM ]

patch no longer applies. I wonder if I see bad behavior because I was testing with node or it was prior to the fixes around avoiding deoptimization.

Comment by Michał Marczyk [ 17/Jun/12 9:28 PM ]

I'll bring it up to date with the recent changes, thanks for the prod!





[CLJS-338] Incorrect implementation of IReduce by ArrayChunk Created: 22/Jul/12  Updated: 29/Jul/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Anton Frolov Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug


 Description   
(reduce + (array-chunk (array 1 2 3 4) 1 3)) => 2 (instead of 5)
(reduce + 0 (array-chunk (array 1 2 3 4) 1 3)) => 3 (instead of 5)
(reduce + (array-chunk (array 1 2 3 4) 1 1)) => 2 (instead of 0)

In src/cljs/cljs/core.cljs, line #1817:

(deftype ArrayChunk [arr off end]
  ;; ...
  IReduce
  (-reduce [coll f]
    (ci-reduce coll f (aget arr off) (inc off))) ;; should be (if (< off end) (ci-reduce coll f (aget arr off) 1) 0)
  (-reduce [coll f start]
    (ci-reduce coll f start off))) ;; should be (ci-reduce coll f start 0)


 Comments   
Comment by David Nolen [ 14/Aug/12 6:29 AM ]

Thanks for the report. ArrayChunk is an implementation detail - do these conditions actually arise?





[CLJS-650] Optimize all protocols Created: 01/Nov/13  Updated: 01/Nov/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

We should be optimizing all protocols insteads of just putting the core protocols on the fast path. In the current design we put the protocol mask on instance - this wastes a considerable amount of space, instead we should be putting it on the prototype. This benchmark appears to show no performance hit for this approach jsperf.com/prototype-bit-mask.

In order to have fewer tests satisfies? and protocol fns should generate different code for the different compilation modes - in anything but advanced we should just use the boolean property on the prototype, in advanced we should use the bit mask approach.






[CLJS-693] new and dot form work on locals Created: 20/Nov/13  Updated: 02/Dec/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Joshua Headapohl Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Given some JavaScript library included in the same page as CLJS output:

var Lib = {};

Lib.Thing = function (val) {
    this.val = val;
};

Lib.Thing.prototype.log = function () {
    console.log(this.val);
};

I can bind the Thing property to a local and construct it using new or the dot form. This code compiles and runs without errors, and logs three lines to the console.

(ns cljs-construct-locals-bug.core)

; Legit
(let [thing (new js/Lib.Thing "hello")]
  (.log thing))

; Questionable
(let [Thing (.-Thing js/Lib)
      thing1 (new Thing "maybe")
      thing2 (Thing. "no way")]
  (.log thing1)
  (.log thing2))

I talked to David Nolen and he said this behavior is not correct.



 Comments   
Comment by David Nolen [ 02/Dec/13 8:58 PM ]

Upon further consideration this probably requires some feedback from the community. I'd forgotten that (Thing. foo bar ...) is just sugar for (new Thing foo bar ...) ...





[CLJS-720] #queue literal behavior is incorrect Created: 07/Dec/13  Updated: 07/Dec/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In order for queue to work we need to adopt an approach similar to the one for #js data literals - i.e. needs special casing in the analyzer since queues are not "atomic" values.






[CLJS-527] Support dynamic runtime extension of protocols to types Created: 20/Jun/13  Updated: 11/Dec/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Chas Emerick Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: File CLJS-527.diff    
Patch: Code and Test

 Description   

Here is a transliteration of a semi-common pattern used with Clojure protocols to dynamically extend protocols to concrete types implementing other protocols (or interfaces, on the JVM):

(defprotocol P (m [this]))

(extend-protocol P
  object
  (m [this]
    (if (seq? this)
      (do
        (extend-type (type this) P
          (m [this] (count this)))
        (m this))
      (throw (ex-info "Cannot extend m to type" {:type (type this)})))))

(I think dnolen was the first to talk about this outside of irc.) Unfortunately, this does not work in ClojureScript; extend-type currently requires that the type be specified as a symbol:

clojure.lang.ExceptionInfo: clojure.lang.PersistentList cannot be cast to clojure.lang.Named at line 4  {:tag :cljs/analysis-error, :file nil, :line 4, :column 5}

I can (hackily?) make this work by simply not attempting to resolve tsym here. However, that leaves lists in as values for :tag metadata (which might be used by the analyzer and/or other tools that depend upon it?), which I presume is not OK.

If someone can provide guidance on a sane path from here, I'll do what I can to produce a plausible patch.



 Comments   
Comment by Chas Emerick [ 21/Jun/13 12:08 PM ]

Looks like jvm.tools.analyzer emits a :tag of nil for some corresponding Clojure code; this can be seen by running this:

(require '[clojure.tools.analyzer :refer (ast)])
#_= nil
(defprotocol P (m [this]))
#_= P
(ast (fn [x]
       (extend-type (type x)
         P
         (m [this] (count this)))))
#_= ...

(The output is verbose enough that I'm not bothering to paste it here.) So, that's easy enough to do, and makes the original example work in ClojureScript.

However, simply suspending the lookup of what is currently assumed to be a symbol naming the type being extended isn't enough. With only that, dynamic usage of extend-type will affect js native prototypes, e.g.:

ClojureScript:cljs.user> (defprotocol P (m [this]))
nil
ClojureScript:cljs.user> (defn naive-dynamic-extend [x]
  (extend-type (type x)
    P
    (m [this] "hi")))
...
ClojureScript:cljs.user> (naive-dynamic-extend true)
...
ClojureScript:cljs.user> js/Boolean.prototype.cljs$user$P$m$arity$1
#<
function (this$) {
    return "hi";
}
>

So the bits in extend-type that handle base types (boolean, string, function, array, etc) need to be brought over to runtime. Looking into this now.

Comment by Chas Emerick [ 24/Jun/13 8:22 AM ]

Patch attached. All previously-allowed usage of extend-type continues to emit exactly the same code. Extensions without a statically-named type include both possible code paths:

1. When the type is a JavaScript native, the extension is made on the prototype's fns using the same base type names as are used for static extensions to e.g. string, object, etc
2. When the type is some other prototype, the extension is made on it directly.

This yields code like:

ClojureScript:cljs.user> (defprotocol P (m [this]))
nil
ClojureScript:cljs.user> #(extend-type (type %) P (m [this] "hi"))
#<
function (p1__4810_SHARP_) {
    var G__4813 = cljs.core.type.call(null, p1__4810_SHARP_);
    var temp__4090__auto__ = (cljs.core.base_type[G__4813]);
    if (cljs.core.truth_(temp__4090__auto__)) {
        var G__4814 = temp__4090__auto__;
        (cljs.user.P[G__4814] = true);
        return (cljs.user.m[G__4814] = ((function (G__4814, temp__4090__auto__, G__4813) {
            return (function (this$) {
                return "hi";
            });
        })(G__4814, temp__4090__auto__, G__4813)));
    } else {
        G__4813.prototype.cljs$user$P$ = true;
        return G__4813.prototype.cljs$user$P$m$arity$1 = ((function (temp__4090__auto__, G__4813) {
            return (function (this$) {
                return "hi";
            });
        })(temp__4090__auto__, G__4813));
    }
}
>

The duplication of the prototype method implementation bodies is unfortunate, a side effect of keeping the extend-type macro and supporting emit-* fns relatively simple. (Note that advanced compilation doesn't lift and merge those fns.) I'm inclined to say that it's a reasonable tradeoff, at least for now, as it only affects the dynamic type extension case; a reasonable TODO later, perhaps.

Comment by Brandon Bloom [ 03/Jul/13 3:44 PM ]

At Chas' request, I took a look at the patch. Tests pass locally & my few small toy projects run fine. I haven't benchmarked.

My only real concern is pretty minor: I'm terrified of JavaScript's semantics around typeof, toString, etc. The existing code paths leverage goog.typeOf, which has some pretty hairy internals. Meanwhile, Chas is just implicitly toString-ing on some type objects with an array set. The code of goog.typeOf also discusses oddities of Object.prototype.toString in firefox, but presumably that won't matter via the implicit conversion present in the array set. So if this works in all the major browsers, the patch LGTM.

Comment by Chas Emerick [ 03/Jul/13 6:29 PM ]

Just a point of documentation w.r.t. the stringifying of js-native prototypes: given the initial example above, if (type x) (or, whatever expression the user is providing that will return a "type" to extend) returns a js-native prototype, we need some way to map that at runtime to the strings that ClojureScript uses for those types when performing protocol dispatch. Using a js object containing as literal a representation of that mapping as possible seemed like a reasonable option. Providing a fn that cond's through the various options would be equivalent AFAICT.

A separate larger issue is, what is a type in ClojureScript? As far as protocols are concerned, the type of types is approximately the union of all non-native js prototypes, and symbols identifying those natives. However, type (and, really, any user of ClojureScript writing expressions provided to extend-type) doesn't know about the latter or the carve-out w.r.t. prototypes, thus some implicit runtime conversion is needed. Alternatively, one could say that any expression provided to extend-type must respect that contract, but then (a) users would need to explicitly handle js native types, and (b) Clojure/ClojureScript portability would be further complicated in this department.

Comment by David Nolen [ 03/Jul/13 8:02 PM ]

Reviewing the patch, thanks all.

Comment by David Nolen [ 03/Jul/13 8:09 PM ]

Ok what is the base-type js-obj for? Why aren't we using goog.typeOf?

Comment by Chas Emerick [ 03/Jul/13 9:06 PM ]

We can't use goog.typeOf because extend-type works with a type (i.e. the return of (type x)), not a value the type of which should be extended to the given protocol(s). (goog.typeOf will always return "function" for prototypes, js-native or not.)

The ClojureScript cljs.core/base-type js-obj is simply a runtime-accessible analogue of the (Clojure) cljs.core/base-type map, except it maps js-native prototypes to the goog.typeOf strings that are used for protocol dispatch.

Comment by David Nolen [ 16/Jul/13 6:40 AM ]

Ok I looked at the patch some more, I don't really like the string coercion aspect around base-type. Let's switch this to an array-map.

Comment by Chas Emerick [ 16/Jul/13 6:48 AM ]

Sure, I can do that. FWIW, that will rope in PAM and whatever other persistent data structure and printing bits it depends upon by default…is that considered acceptable?

Comment by David Nolen [ 16/Jul/13 10:31 AM ]

Hrm, that's actually a good point. Perhaps better to do a array + scan. I thought about this patch some more and it really needs more work. One thing this doesn't handle is objects from foreign contexts. ClojureScript can currently handle this by combining default cases with goog.typeOf.

I think extend-type should probably work with strings and/or symbols that represent the base types so that objects from other contexts can also be handled. I think automating this will be unweildy but at least it gives users the flexibility to handle these cases themselves.

Comment by Chas Emerick [ 16/Jul/13 7:14 PM ]

What do you mean by "foreign contexts"? I did a bit of searching on the term, and didn't turn up anything promising in connection with either ClojureScript or JavaScript. I assume you're not referring to e.g. types loaded via :foreign-libs, but who knows…

Re "strings and/or symbols", are you suggesting that dynamic usage of extend-type should not perform any translation of js-native prototypes to their string names, i.e. an expression being evaluated to determine the type to extend would need to return "string" (or 'string) rather than js/String?

Comment by David Nolen [ 16/Jul/13 9:00 PM ]

JavaScript objects from other JS execution contexts, IFrames are the most common source of these. This is why goog.typeOf implementation is so complex, it handles these cases.

I'm saying that extend-type should do run time extension to JS natives if the user specifies the extension at runtime via a string or symbol for the native cases because an Array from another JS Execution context is not equal to the Array in the current one.

Comment by Brandon Bloom [ 23/Jul/13 2:04 PM ]

It seems silly to argue about all the edge cases here, considering how many edge cases pertaining to "types" are already broken in ClojureScript.

For example, currently (= (type :foo) (type "foo"))

This is because cljs.core/type simply calls accesses the constructor field, and keywords are strings at runtime. Meanwhile, the (type (type x)) is always a function, since there is no Type type.

There are three problems:

1) Type equality

2) Getting an object's type

3) Runtime protocol extension

This patch delegates #2 to cljs.core/type and properly addresses #3.

#1 is a bit trickier, since there are three valid approaches I can think of:

A) Nominal equality - Enhance cljs.core/type to return sensible symbols, by implementing the crux of the goog/typeOf behavior plus some extra behavior for extracting type names out of function string representations.

B) Constructor equality - Simply compare .constructor; This is basically what happens now, but has 2 problems: B1) Doesn't provide for types at compile time B2) might not work correctly with IFrame execution environments

C) Hybrid/Heuristic - (defprotocol IType ...) and implement some Type objects with equality sensible operators; lazily stuff those type objects into a reflection map of some sort.

Personally, I think that B (the current state of the world) is hopelessly broken. Despite my initial reservations regarding the toString coercion, I think this patch does a reasonable job of eschewing B for a stop-gap A (with compile time interop). Given this analysis, I think the string coercion for natives actually does a better job than one could do with a PAM of constructors: ie the coercion covers the remote execution state. Unless this is provably broken for some key scenarios with IFrames, I think the patch is good as is, but we need to think about a follow on patch for fixing up runtime types in general.

Comment by Brandon Bloom [ 23/Jul/13 2:23 PM ]

I should also point out: Unlike JavaScript, Java has a unified nominal type system. Name equality is type equality (ignoring custom class loaders). However, JavaScript with Google Closure has a stratified type system: The dynamic type system utilizes object identity for equality. The GClosure static type system is (mostly) nominal with some fudge factor for the mismatch with the runtime type system (mostly around inheritance/mixins/array-like/etc). I think that ClojureScript should strive for a runtime reification of the Google Closure type system, since that would be most compatible with the Clojure/JVM type system.

Comment by David Nolen [ 23/Jul/13 3:06 PM ]

We are not going to follow goog.typeOf.

Comment by Brandon Bloom [ 23/Jul/13 3:22 PM ]

Follow it where?

Comment by David Nolen [ 23/Jul/13 3:29 PM ]

We're not going to use it nor follow its example for determining types unless we are trying to detect natives.

Comment by Brandon Bloom [ 23/Jul/13 3:34 PM ]

Getting back on topic: Getting some type-like-thing from an object is not this patch.

This patch is about extend-type, which I think it implements reasonably well given our current failings at runtime type reification.

Chas has this working with user defined types as well as with natives. Are there any particular scenarios that are provably broken? Either in general or on a particular browser/runtime?

Comment by David Nolen [ 23/Jul/13 3:38 PM ]

Chas's patch can't catch natives from IFrame contexts, I'd rather this patch move forward with at least the ability for a user to handle that situation themselves which I said above.

Comment by Brandon Bloom [ 23/Jul/13 3:59 PM ]

I think this does handle natives from iframe contexts, since extend-type takes a "type" not an object. Getting the type from an object does not need to happen here. The patch coerces types to a string via toString, which is precisely how goog.typeOf works internally on natives. Search for Object.prototype.toString.call in http://docs.closure-library.googlecode.com/git/closure_goog_base.js.source.html

Are you speculating that the patch doesn't work, or have you tried it?

If the former, Chas: Can you provide a test project that demonstrates extension of the cross product of these two sets:

1) local type
2) request remote object, coerce to type locally
3) request remote type object

A) native objects
B) deftype-ed objects

Comment by Chas Emerick [ 23/Jul/13 7:42 PM ]

Whatever the semantics and dark corners of JavaScript "types" — or, what they should be, at least w.r.t. ClojureScript — extend-type has very little latitude to operate.

The runtime-dynamic variant of the code it generates will be expecting something typeish coming out of whatever expression the user provides to it.
AFAICT, the only sane possibilities for "typeish" in this context are strings naming javascript natives (e.g. "string", or perhaps 'string if we want to be generous), or a constructor fn (cljs.core/PV, or js/String, or anything else returned by type). The current patch only accepts the latter, done to preserve as much as possible the existing patterns of extend-type usage in Clojure, and hopefully avoid foisting conversion of js/String to "string" at runtime onto users. String coercion is used to normalize the former into the latter; since the code determining the typeish value is entirely in the hands of the user (we don't have access to an object that exemplifies the type to which the user is extending, so we can't wedge in anything particularly clever), I believe it (or something similar) is all we can do.

From here, the only other option I see would be to expand the patch to eliminate this coercion, accepting strings or symbols naming js natives ("string", "boolean", and so on), and allow extensions to js natives at runtime without restriction. This may be a feature for some (perhaps if someone wants to extend a protocol to a js native only withing a particular iframe context?); on the other hand, we should probably document heavily that runtime usage of extend-type should take care to perform the sort of coercion the current patch does (and maybe provide some kind of helper function?), insofar as extension to natives directly is considered harmful in general (e.g. http://dev.clojure.org/jira/browse/CLJS-528, which was viewed favorably in irc some weeks ago?).

I'm happy to produce further tests (up to the suite that Brandon suggested above) if that would be helpful.

Comment by Michał Marczyk [ 26/Jul/13 7:04 PM ]

Just wanted to note that I've run into a situation where runtime extension of protocols to types would AFAICT be the next best thing to "extending protocol to protocol". Here's a link to the relevant ticket in fipp's issue tracker: https://github.com/brandonbloom/fipp/issues/6 (relevant part starts in the 8th comment).





[CLJS-746] clojure.string/replace pattern/function of match API difference with clojure version Created: 10/Jan/14  Updated: 10/Jan/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Curtis Gagliardi Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

[org.clojure/clojurescript "0.0-2138"]



 Description   

When calling clojure.core/replace with a pattern and a function, the Clojurescript version delegates to Javascript's s.replace method, which calls that function with a variable number of arguments, depending on how many match groups are in your pattern. The Clojure version always calls it with a single argument, which may be a vector if you have match groups in your pattern.

I'm not sure if this was intentional. If it wasn't, I think this difference could be fixed through some use of re-find, which appears to return the same string or vector that you'd get in Clojure. If this is intentional for performance reasons, perhaps the doc string should be updated to note this, as there's no warning that the function is being called with too many arguments.



 Comments   
Comment by Curtis Gagliardi [ 10/Jan/14 1:32 AM ]

Afraid I don't see how to edit, but I wanted to include a simple example:

CLJS:
(clojure.string/replace "hello world" #"(hello) world" (fn [m] (.log js/console (str "Match: " m)) m))

will log: "Match: hello world"

CLJ
user=> (clojure.string/replace "hello world" #"(hello) world" (fn [m] (println (str "Match: " m) m)))
Match: ["hello world" "hello"] [hello world hello]

NullPointerException java.util.regex.Matcher.quoteReplacement (Matcher.java:655)





[CLJS-150] Regular expressions don't support Javascript mode flags Created: 16/Feb/12  Updated: 12/Mar/14  Due: 24/Feb/12

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Bobby Calderwood Assignee: Bobby Calderwood
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently, the compiler and cljs.core allow for Java mode flags. Javascript doesn't support many of these, and supports one flag not supported by Java - 'g'.

ClojureScript regular expressions should support only Javascript regex mode flags: 'i', 'm', and 'g'. This applies to Regex literals in the compiler as well as (re-pattern).

This is a defect in the implementation of CLJS-116.



 Comments   
Comment by David Nolen [ 16/Feb/12 3:33 PM ]

The defect existed prior to CLJS-116. The problem is that we're using the Clojure reader and g is not a valid flag for a Java RegexPattern.

Comment by Francis Avila [ 28/Feb/14 1:04 AM ]

This ticket should be rejected. A regular expression created with the global flag is stateful (i.e., the lastIndex property is checked and used by the exec and test methods.) On sufficiently old browsers (pre js 1.5), this makes the RegExp object itself stateful, i.e., not instances, but the RegExp constructor is mutated!

Using a regex with the global flag set will already ruin the results of re-seq, re-find, etc. I could see re-seq using a clone of the input regex with the global flag set as an optimization to avoid string slicing, but we certainly shouldn't provide a public interface to create them.

See also CLJS-776





[CLJS-736] Functions folder and reducer broken for types nil and array + fix for typo Created: 29/Dec/13  Updated: 02/Dec/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Jonas De Vuyst Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-736-alt.patch     Text File CLJS-736.patch     Text File CLJS-736-patch-1-redux.patch     Text File CLJS-alt-satisfies.patch    
Patch: Code and Test

 Description   

1. This currently doesn't work:

(->> nil
(r/map identity)
(r/reduce + 0))
; org.mozilla.javascript.JavaScriptException: Error: No protocol method IReduce.-reduce defined for type null

The reason for this is that reducers created by r/reducer or r/folder, invoke -reduce (of IReduce) directly. They thereby bypass the special case for nil in the function r/reduce.

2. An entirely analogous problem exists for collections of type array.

3. The patch CLJS-700 mistakenly defined coll-fold for the type cljs.core/IPersistentVector. This should have been cljs.core/PersistentVector. (There exists no protocol IPersistentVector in ClojureScript.)

I will shortly attach a patch that addresses all of the above problems by implementing IReduce for nil and array. The patch also includes unit tests.



 Comments   
Comment by Jonas De Vuyst [ 29/Dec/13 2:22 PM ]

Alternative patch in which r/reduce and r/fold treat arrays and nil as special cases – as opposed to having arrays and nil implement IReduce and CollFold.

The functions r/reducer, r/folder, and the protocol methods of r/Cat now call r/reduce and r/fold instead of calling -reduce and coll-fold directly.

This patch also fixes a bug in the coll-fold implementation for Cat, which previously used (reducef) as the initial value rather than (combinef). The new code is copied and pasted from the Clojure implementation and uses the fork-join stubs.

Comment by David Nolen [ 30/Dec/13 8:23 AM ]

The implements? should probably be a satisfies? in the second patch. Have you run any benchmarks of before/after the patch?

Comment by Jonas De Vuyst [ 30/Dec/13 11:24 AM ]

If I understand correctly then (satisfies? x y) is roughly equivalent to (or (implements? x y) (natively-satisfies? x y)).

If native types (nil, array, object currently) are treated as special cases then implements? seems more appropriate.

satisfies? works also, however, so I have attached a new 'alt' patch.

Comment by Jonas De Vuyst [ 30/Dec/13 11:26 AM ]

The first patch is in fact faster when running the following code:

(time (->> (repeat 1000 (vec (range 1000)))
vec
(r/mapcat identity)
(r/map inc)
(r/filter even?)
(r/fold +)))

This takes about 700 msecs. Using the first patch this terminates 100-300 msecs faster. This is after repeated (but informal) testing.

I guess the worry is that the first patch would slow down other random code since it involves extending the types nil, array, and object. I'm not sure what exactly I should test for though.

(Note that the 2nd and 3rd patch also contain a fix for Cat and include more unit tests. The first patch should preferably not be applied as-is.)

Comment by David Nolen [ 30/Dec/13 11:35 AM ]

Yeah you're timing too many things, including vec, range, lazy sequences. Also testing a small N. Take a look at the reducers example on the Mori README - https://github.com/swannodette/mori. Thanks.

Comment by Jonas De Vuyst [ 30/Dec/13 12:52 PM ]

I tried running the following code:

(let [coll (vec (repeat 1000 (vec (range 10))))]
  (time (doseq [n (range 1000)]
               (->> coll
                    (r/mapcat identity)
                    (r/map inc)
                    (r/filter even?)
                    (r/fold +)))))

Some of the last results I got were:

1st patch: 75680 msecs
2nd patch: 76585 msecs

Truth be told, although the first patch seemed to win most of the times, sometimes the second patch was faster.

One other thing I tried was removing the implements?/satisfies? check from the second patch and overriding the protocol method coll-fold for the type object instead (as in the first patch). This 'hybrid' approach generally (but not always) seemed to result in a slowdown.

I'm not sure how I should proceed. Should I perhaps just run both patches simultaneously for several minutes?

Comment by David Nolen [ 30/Dec/13 1:21 PM ]

This is still a bad way to do timing, you're recording the cost of range and seq'ing. Use dotimes.

Comment by Jonas De Vuyst [ 30/Dec/13 4:33 PM ]

Hm. I guess the lazy sequence does lead to a lot of allocations.

Alright, I rewrote my test and ran it a few more times. I now also tested on both vectors and arrays.

Patch 1 needed a slight tweak. When coll-fold is invoked, patch 1 only specifies a fallback for type object (i.e. r/reduce is called). I had to add the same fallback for type array. (This is weird!)

So here are the results.

For vectors:

(let [coll (vec (repeat 100 (vec (range 100))))]
  (time (dotimes [n 3000]
          (->> coll
              (r/mapcat identity)
              (r/map inc)
              (r/filter even?)
              (r/fold +)))))

Patch 1: 205872 msecs
Patch 2: 210756 msecs

For arrays:

(let [coll (into-array (repeat 100 (into-array (range 100))))]
  (time (dotimes [n 3000]
          (->> coll
              (r/mapcat identity)
              (r/map inc)
              (r/filter even?)
              (r/fold +)))))

Patch 1: 123567 msecs
Patch 2: 119704 msecs

I ran my tests a few times and the results were pretty consistent. Patch 1 is faster for vectors and patch 2 is faster for arrays.

This makes sense.

In patch 1 reducer will call -reduce directly. In patch 2, reducer first calls r/reduce, which calls -reduce if the collection is a vector and array-reduce if it's an array. Hence patch 2 contains an extra function call in the case of vectors, but avoids invoking a protocol method on a native type in the case of arrays.

Using macros (or copy and paste) the extra function call can be avoided. Would that be worth trying or is it more important to keep the code clean?

I just realized that patch 2 is semantically slightly different from what Clojure does, although perhaps this is a bug in Clojure: <https://groups.google.com/forum/#!searchin/clojure-dev/kv-reduce/clojure-dev/bEqECvbExGo/iW4B2vEUh8sJ>. My suggestion to use a macro (or copy and paste) to avoid the extra function call in patch 2, could also fix this discrepancy.

Comment by David Nolen [ 30/Dec/13 4:42 PM ]

How are you benchmarking this? With V8? JavaScriptCore? SpiderMonkey? In the browser? What optimization settings, etc.

Comment by Jonas De Vuyst [ 30/Dec/13 4:48 PM ]

I used repljs (Rhino?). I'll test again in a more realistic setting tomorrow.

Comment by David Nolen [ 30/Dec/13 4:54 PM ]

Yeah, benchmarking with Rhino isn't informative.

Comment by Jonas De Vuyst [ 31/Dec/13 1:40 AM ]

I compiled the same code (with n=3000) using cljs with "{:optimizations :advanced}".

I then tested it in the latest stable releases of Firefox, Chrome, and Safari. I closed all my browsers. For each browser I then followed the following procedure:

  • Open the browser
  • Open the developer console
  • Run the benchmark for patch 1
  • Run the benchmark for patch 2
  • Run the benchmark for patch 1 and write down the result
  • Run the benchmark for patch 2 and write down the result
  • Close the browser

Firefox:

  • Patch 1. Vectors: 26057 msecs
  • Patch 1. Arrays: 25026 msecs
  • Patch 2. Vectors: 26258 msecs
  • Patch 2. Arrays: 36653 msecs
  • Summary: Patch 1 is faster for vectors and arrays

Chrome:

  • Patch 1. Vectors: 7804 msecs
  • Patch 1. Arrays: 7092 msecs
  • Patch 2. Vectors: 7754 msecs
  • Patch 2. Arrays: 6768 msecs
  • Summary: Patch 2 is faster for vectors and arrays

Safari:

  • Patch 1. Vectors: 167230 msecs
  • Patch 1. Arrays: 108780 msecs
  • Patch 2. Vectors: 173940 msecs
  • Patch 2. Arrays: 110012 msecs
  • Summary: Patch 1 is faster for vectors and arrays

I'm not sure what to make of this.

Comment by Jonas De Vuyst [ 31/Dec/13 2:47 AM ]

I have attached a new version of the first patch.

This patch fixes an issue with r/Cat. (This issue was also addressed in the second and third patch. A unit test is included.).

This patch also fixes r/fold for arrays.

To summarize, a choice needs to be made between the following patches.

  • CLJS-736-patch-1-redux.patch
  • CLJS-736-alt.patch (uses implements?) / CLJS-alt-satisfies.patch (uses satisfies?)

The implementation details are patch-1-redux is more similar in spirit to the Clojure source code. The alt patches are more similar in spirit to the ClojureScript source code.

As explained above, the alt patches are semantically a bit different from the original Clojure source—but it's not clear which behavior is 'right'.

Comment by David Nolen [ 16/Jan/14 5:27 PM ]

The benchmarks would be more informative if they explained the performance before and after that patch.

Comment by Jonas De Vuyst [ 18/Jan/14 11:55 AM ]

r/reduce previously didn't work for nil or JavaScript arrays.

One reason why I have trouble recommending a patch is that I don't know what use case you would like to optimize for.

Comment by David Nolen [ 18/Jan/14 12:30 PM ]

Yes but now that we have new logic we can at least test the lack of regression on the other types.

Comment by David Nolen [ 18/Jan/14 12:40 PM ]

Ok I tried to apply this patch and run ./script/benchmarks in the repo but the patch will no longer apply. Can we rebase the patch on master. Thanks. If you also want to give the benchmarks a shot follow these instructions to install the JS engines - http://github.com/clojure/clojurescript/wiki/Running-the-tests. Then you can also run the benchmarks at the command line. I see there aren't any reducers benchmarks, I will add some.





[CLJS-900] Parameterize caching strategy Created: 03/Dec/14  Updated: 03/Dec/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently the caching strategy is hard coded to a disk based one. It would be desirable in many situations for the caching to be in memory. We should decouple the caching strategy and support disk / memory out of the box.






[CLJS-797] Nested 'for' loops (3+ deep) in Android Chrome cause "Uncaught RangeError: Maximum call stack size exceeded" Created: 16/Apr/14  Updated: 17/Apr/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: John M. Newman III Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Android 4.3, Chrome 34, ClojureScript 2202



 Description   
(do (println "for loop test: 2 deep")
  (for [a [[1]]]
    (for [b a]
      b)))
;; this compiles and runs fine in the browser

(do (println "for loop test: 3 deep")
  (doall
   (for [a [[[1]]]]
     (for [b a]
       (for [c b]
         c)))))
;; this fails while the page loads, with the error: Uncaught RangeError: Maximum call stack size exceeded

The above works fine in a desktop browser. For some reason the error condition only happens on the Android Chrome browser.

Let me know if any further details are required.






[CLJS-1029] Investigate how ns aliasing can be supported in ClojureScript macro files Created: 11/Feb/15  Updated: 11/Feb/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently we just require the file. Perhaps possible to control compilation of the macro file such that ClojureScript ns aliases are established. This may not bear fruit but worth thinking about.



 Comments   
Comment by David Nolen [ 11/Feb/15 4:05 PM ]

Any design ideas along this path needs to keep .cljc files in mind.





[CLJS-1048] support function values in static vars compile time metadata Created: 20/Feb/15  Updated: 20/Feb/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Ivan Mikushin Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Function values are currently only supported for :test metadata key as a special case.






[CLJS-1067] Shared AOT cache for dependencies in JARs Created: 26/Feb/15  Updated: 27/Feb/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

3rd party library code in JARs shouldn't be recompiled across dev and prod configurations. There should be a shared AOT cache for all builds within a project for all non-project local source.






[CLJS-1076] :nashorn target Created: 02/Mar/15  Updated: 02/Mar/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

To run well on Nashorn the target should supply CLOSURE_IMPORT_SCRIPT as well as setTimeout or setImmediate for core.async.






[CLJS-1109] Record type name and advanced optimization Created: 12/Mar/15  Updated: 12/Mar/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3058
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Daniel Skarda Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

It is not possible to query type name in advanced compilation.
Code below prints correct record name in other compilation modes, but under advanced compilation it prints constructor source code.

(defrecord FooBar [a])

(def fb (FooBar. 1))

(prn (-> fb))
(prn (-> fb type))
(prn (-> fb type pr-str))





[CLJS-1123] this-as unexpectedly binds js/window when used within function with post-condition Created: 15/Mar/15  Updated: 16/Mar/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: J. S. Choi Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Adding a post-condition to any function that uses cljs.core/this-as will unexpectedly cause this-as's "this" symbol to be bound to the root object (e.g., js/window) instead.

(defn f-no-post-condition [argument]
  (this-as this
    (js/console.log argument this)))

(defn f-with-post-condition [argument]
  {:post [true]}
  (this-as this
    (js/console.log argument this)))

(def test-object
  #js {:methodNoPostcondition f-no-post-condition
       :methodWithPostcondition f-with-post-condition})

(f-with-post-condition "A") ; Correctly prints js/window
(.methodNoPostcondition test-object "B") ; Correctly prints test-object
(.methodWithPostcondition test-object "C") ; Incorrectly prints js/window


 Comments   
Comment by David Nolen [ 16/Mar/15 6:17 AM ]

This is almost certainly a different manifestation of CLJS-719.

Comment by Thomas Heller [ 16/Mar/15 6:21 AM ]

Just looked at the generated javascript. As David mentioned the problem is the extra function generated to get the result for the :post condition.

dummy.f_no_post_condition = (function f_no_post_condition(argument){
var this$ = this;
var G__82157 = argument;
var G__82158 = this$;
return console.log(G__82157,G__82158);
});
dummy.f_with_post_condition = (function f_with_post_condition(argument){
var _PERCENT_ = (function (){var this$ = this;
var G__82161 = argument;
var G__82162 = this$;
return console.log(G__82161,G__82162);
})();


return _PERCENT_;
});
dummy.test_object = {"methodWithPostcondition": dummy.f_with_post_condition, "methodNoPostcondition": dummy.f_no_post_condition};
dummy.f_with_post_condition("A");
dummy.test_object.methodNoPostcondition("B");
dummy.test_object.methodWithPostcondition("C");




[CLJS-1151] Noisy errors when referring to symbol in undefined ns Created: 19/Mar/15  Updated: 22/Mar/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3126
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Quick Start / OS X / Chrome



 Description   

Run through the Quick Start to the point where you have the browser REPL running.

If you refer to a symbol in an undefined ns you will get really noisy errors:

ClojureScript:cljs.user> foo.bar/a
WARNING: Use of undeclared Var foo.bar/a at line 1 <cljs repl>
ReferenceError: foo is not defined
ReferenceError: foo is not defined
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:1:89)
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:9:3)
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:14:4)
    at http://localhost:9000/out/clojure/browser/repl.js:42:267
    at clojure$browser$repl$evaluate_javascript (http://localhost:9000/out/clojure/browser/repl.js:45:4)
    at Object.callback (http://localhost:9000/out/clojure/browser/repl.js:242:169)
    at goog.messaging.AbstractChannel.deliver (http://localhost:9000/out/goog/messaging/abstractchannel.js:142:13)
    at goog.net.xpc.CrossPageChannel.xpcDeliver (http://localhost:9000/out/goog/net/xpc/crosspagechannel.js:733:12)
    at Function.goog.net.xpc.NativeMessagingTransport.messageReceived_ (http://localhost:9000/out/goog/net/xpc/nativemessagingtransport.js:321:13)
    at Object.goog.events.fireListener (http://localhost:9000/out/goog/events/events.js:741:21)

Now, define the namespace, but don't actually define the symbol. For example:

(ns foo.bar)

(def z 3)

Now, require the namespace and do the same. The noise will go away.

ClojureScript:cljs.user> (require 'foo.bar)
nil
ClojureScript:cljs.user> foo.bar/a
WARNING: Use of undeclared Var foo.bar/a at line 1 <cljs repl>
nil

Additional info: Now if you attempt to refer to other unknown symbols, you will get different kinds of "noise" depending on whether the ns simply starts with foo:

ClojureScript:cljs.user> foo.baz/a
WARNING: No such namespace: foo.baz, could not locate foo/baz.cljs at line 1 <cljs repl>
WARNING: Use of undeclared Var foo.baz/a at line 1 <cljs repl>
TypeError: Cannot read property 'a' of undefined
TypeError: Cannot read property 'a' of undefined
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:1:96)
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:9:3)
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:14:4)
    at http://localhost:9000/out/clojure/browser/repl.js:42:267
    at clojure$browser$repl$evaluate_javascript (http://localhost:9000/out/clojure/browser/repl.js:45:4)
    at Object.callback (http://localhost:9000/out/clojure/browser/repl.js:242:169)
    at goog.messaging.AbstractChannel.deliver (http://localhost:9000/out/goog/messaging/abstractchannel.js:142:13)
    at goog.net.xpc.CrossPageChannel.xpcDeliver (http://localhost:9000/out/goog/net/xpc/crosspagechannel.js:733:12)
    at Function.goog.net.xpc.NativeMessagingTransport.messageReceived_ (http://localhost:9000/out/goog/net/xpc/nativemessagingtransport.js:321:13)
    at Object.goog.events.fireListener (http://localhost:9000/out/goog/events/events.js:741:21)
ClojureScript:cljs.user> goo.baz/a
WARNING: No such namespace: goo.baz, could not locate goo/baz.cljs at line 1 <cljs repl>
WARNING: Use of undeclared Var goo.baz/a at line 1 <cljs repl>
ReferenceError: goo is not defined
ReferenceError: goo is not defined
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:1:89)
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:9:3)
    at eval (eval at <anonymous> (http://localhost:9000/out/clojure/browser/repl.js:42:272), <anonymous>:14:4)
    at http://localhost:9000/out/clojure/browser/repl.js:42:267
    at clojure$browser$repl$evaluate_javascript (http://localhost:9000/out/clojure/browser/repl.js:45:4)
    at Object.callback (http://localhost:9000/out/clojure/browser/repl.js:242:169)
    at goog.messaging.AbstractChannel.deliver (http://localhost:9000/out/goog/messaging/abstractchannel.js:142:13)
    at goog.net.xpc.CrossPageChannel.xpcDeliver (http://localhost:9000/out/goog/net/xpc/crosspagechannel.js:733:12)
    at Function.goog.net.xpc.NativeMessagingTransport.messageReceived_ (http://localhost:9000/out/goog/net/xpc/nativemessagingtransport.js:321:13)
    at Object.goog.events.fireListener (http://localhost:9000/out/goog/events/events.js:741:21)


 Comments   
Comment by Mike Fikes [ 19/Mar/15 3:47 PM ]

Clarification on the description: When defining the foo.bar ns, I actually created a source file src/foo/bar.cljs containing the ns declaration and the def z.

Comment by David Nolen [ 22/Mar/15 9:49 AM ]

I'm not sure what we can do about this or that suppressing the errors from the JavaScript evaluation environment is a good idea. Property access on something that doesn't exist is what causes the JS environment to emit the error. In the later cases the property access is on something that does exist but doesn't have the property so no error.





[CLJS-1160] Source map js / cljs line number mixup Created: 23/Mar/15  Updated: 23/Mar/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3126
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

QuickStart Browser REPL Chrome OS X



 Description   

Note the source location for cljs.core.LazySeq.sval in the following 0.0-3126 stacktrace:

ClojureScript:cljs.user> (map ffirst (range))
Error: 0 is not ISeqable
	 cljs$core$seq (out/cljs/core.cljs:951:13)
	 cljs$core$first (out/cljs/core.cljs:960:7)
	 cljs$core$ffirst (out/cljs/core.cljs:1393:3)
	 cljs.core.map.cljs$core$map__2 (out/cljs/core.cljs:4046:30)
	 cljs.core.LazySeq.sval (out/cljs/core.cljs:11400:3)
	 cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1 (out/cljs/core.cljs:2884:12)
	 cljs$core$seq (out/cljs/core.cljs:938:7)
	 cljs$core$pr_sequential_writer (out/cljs/core.cljs:8426:13)

It turns out that line 11400 is actually in core.js, but the source map logic is evidently getting tripped up by this one, and core.cljs gets reported with the JS line numbers (core.cljs doesn't even have that many lines).

Note that this also occurs on master (where CLJS-1154 and CLJS-1157 have landed):

ClojureScript:cljs.user> (map ffirst (range))
Error: 0 is not ISeqable
	 cljs.core/seq (out/cljs/core.cljs:951:20)
	 cljs.core/first (out/cljs/core.cljs:960:16)
	 cljs$core$ffirst (out/cljs/core.cljs:1393:11)
	 cljs.core.map.cljs$core$map__2 (out/cljs/core.cljs:4046:30)
	 cljs.core.LazySeq.sval (out/cljs/core.cljs:11400:3)
	 cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1 (out/cljs/core.cljs:2884:12)
	 cljs.core/seq (out/cljs/core.cljs:938:25)
	 cljs$core$pr_sequential_writer (out/cljs/core.cljs:8426:20)





[CLJS-1186] add :postamble option to compiler Created: 02/Apr/15  Updated: 02/Apr/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Michael Bradley Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: cljs

Attachments: Text File cljs_1186.patch    

 Description   

Similar to CLJS-723:

1) :postamble's value will be a vector of paths
2) the compiled output is appended with the contents of the files at those paths
3) the generated source map points to the correct/adjusted line numbers






[CLJS-1211] Automatically requiring :main namespace under :none fails in IE9 Created: 17/Apr/15  Updated: 17/Apr/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3058, 0.0-3115, 0.0-3196, 0.0-3117, 0.0-3119, 0.0-3123, 0.0-3126
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Immo Heikkinen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Internet Explorer 9



 Description   

Automatic goog/base.js inclusion using :none & :main doesn't work in Internet Explorer 9. The following error message is printed to the console:

ClojureScript could not load :main, did you forget to specify :asset-path?

There seems to be a timing issue after writing script tags to the HTML document. Inline JavaScript for requiring the main namespace gets executed while goog is still undefined.

I played a bit with this but couldn't get it working in IE9. I tried moving the require statement to a separate JS file and adding a script tag to load that file, then goog was no longer undefined but I still got an error message:

SCRIPT5022: Undefined nameToPath for goog.string
base.js, line 753 character 9

The feature seems to work fine in other browsers (also IE10). Probably not worth fixing but at least the limitation is documented now in case someone else wonders the why it doesn't work in IE9.






[CLJS-890] Incorrect behaviour of (str obj) when obj has valueOf method Created: 24/Nov/14  Updated: 25/Apr/15

Status: Reopened
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Nikita Beloglazov Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None

Attachments: Text File cljs-890.patch     File cljs-core-str-perf.diff    

 Description   

Example

(str #js {"toString" (fn [] "hello") "valueOf" (fn [] 42)}) ; => "42"

The problem in the fact that ClojureScript uses concatenation to convert values to strings and that doesn't work well with objects which have valueOf() method overriden.

Example in js:

var obj = {
    toString: function() { return 'hello'; },
    valueOf: function() { return 42; }
};
console.log(String(obj)); => 'hello'
console.log(obj.toString()); => 'hello'
console.log('' + obj); => '42'

Potential solution might be to use String() function. Using toString() won't work as described in this issue: http://dev.clojure.org/jira/browse/CLJS-847



 Comments   
Comment by Kevin Neaton [ 24/Nov/14 10:34 AM ]

Is there a valid use case where toString and valueOf are not in sync? E.g.

(not= (.toString x) (js/String (.valueOf x))

If not, is it "incorrect" for the two methods to be out of sync?

Comment by Nikita Beloglazov [ 24/Nov/14 10:40 AM ]

Here is an example of such use case: https://github.com/processing-js/processing-js/blob/master/src/Objects/Char.js
That's how I found this bug.

Comment by Kevin Neaton [ 24/Nov/14 10:49 AM ]

Thanks for the link. I see what you mean.

Comment by David Nolen [ 02/Dec/14 5:08 AM ]

The problem with going with String appears to be a massive performance hit to printing http://jsperf.com/string-vs-tostring2/6.

Unless a brilliant idea is proposed this seems best solved / worked around in user code.

Comment by Nikita Beloglazov [ 02/Dec/14 6:41 AM ]

Append performs better on strings and numbers, but it performs worse on objects so it is not a clear performance hit. If I heavily work with objects and use (str) to convert them into strings then I actually lose on performance with current implementation.
Anyway current implementation of str is incorrect as it doesn't honor toString method. And this is what str function supposed to do. I believe a compiler should be correct first and then worry about performance.

Comment by David Nolen [ 02/Dec/14 7:38 AM ]

Sorry going back over this I believe the issue is really that we simply need to backout CLJS-801.

Comment by David Nolen [ 02/Dec/14 7:41 AM ]

reverted CLJS-801 in master

Comment by Francis Avila [ 02/Dec/14 10:32 AM ]

CLJS-801 only deals with the str macro. Aren't we still going to have str function problem because of CLJS-847? https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642 (also Yet if we use toString there, Safari 6.0.5 blows up. Maybe we need {{[o].join('')}}? Depending on where the bug is this may be wrong in Safari 6.0.5 too.

What we need to do very specifically is somehow get the return value of the (in ECMASCRIPT-ese) ToString abstract operation on the object (or the underlying ToPrimitive abstract operation with the String hint). String concat with the add operator

Options as I see it are:

  • x.toString() : Bad because of CLJS-847
  • {{[x].join('')}} : Should work (and does right thing for null/undefined), but I think we should test in Safari 6.0.5. Also very slow.
  • String
  • String.prototype.concat
  • String.prototype.slice(x,0) String.prototype.substring(x,0) String.prototype.substr(x, 0)
  • x.toString() normally, but String if we detect that we'll trigger CLJS-847. (Can specialize on startup.)
Comment by David Nolen [ 02/Dec/14 10:35 AM ]

Is there any evidence that higher usage of str is actually problematic?

Comment by Francis Avila [ 02/Dec/14 10:44 AM ]

String concat using the addition operator uses an un-hinted ToPrimitive abstract call (which will try x.valueOf() first then x.toString(), usually) and then {{ToString}}s the result of that, so it's not an option unless we are concating primitive values.

Details:

Comment by David Nolen [ 02/Dec/14 10:50 AM ]

I'm not really all that concerned about the specification, only if it matters in the wild. If this doesn't affect Safari 6.05 we don't care.

Comment by Francis Avila [ 02/Dec/14 11:01 AM ]

Is there any evidence that higher usage of str is actually problematic?

Kevin Neaton, who opened CLJS-847, was using a patch in production which only addressed the higher order case and he said the patch fixed the issue for them. He was unaffected by the str macro case because it either used ''+x already (with CLJS-801 applied) or it used {{[x].join('')}} (which hasn't been tested with Safari 6.0.5 yet, but probably works).

So if we had a problem using ''+x with the str macro, we will certainly have a problem with ''+x with a string function as long as CLJS-847 is applied.

I haven't pulled down master yet, but here is a test case which I bet will fail with the CLJS-847 patch:

(def tricky-obj #js {"toString" (fn [] "hello") "valueOf" (fn [] 42)})
(assert (= (apply str tricky-obj) "hello")) ;; will get "42"
Comment by Francis Avila [ 02/Dec/14 11:09 AM ]

I'm not really all that concerned about the specification, only if it matters in the wild. If this doesn't affect Safari 6.05 we don't care.

To be clear, there are two issues here:

CLJS-847: x.toString() fails on Safari 6.0.5. Workaround is ''+x (only done in str macro case).
CLJS-890: ''+x doesn't give expected results for objects which define valueOf. Expectation is that x.toString() is called, instead x.valueOf().toString(). Fix is to use array join instead of string concat in str macro, but it doesn't address the ''+x workaround from CLJS-847.

To make matters worse, it looks like the toString() error on Safari may only be triggered at certain JIT levels!

Comment by Francis Avila [ 02/Dec/14 11:10 AM ]

Workaround is ''+x (only done in str macro case).

I mean "Workaround is ''+x (only done in str function case)."

Comment by Nikita Beloglazov [ 08/Dec/14 6:14 PM ]

Can this bug be reopened meanwhile? If I understand correctly the fix should affect https://github.com/clojure/clojurescript/commit/08b4b1585cf0ef739e903985ee4c6b7fc6c47642 but this code still present in HEAD.

Comment by David Nolen [ 08/Dec/14 6:37 PM ]

We've switched to goog.string.buildString in master https://github.com/clojure/clojurescript/commit/94eb8a960fef6aaca4ba44b251cefbfa04d0f6ac

Comment by Nikita Beloglazov [ 08/Dec/14 8:32 PM ]

Yes, that works. Cool, thanks!

Comment by Thomas Heller [ 01/Jan/15 7:12 AM ]

Sorry for re-opening.

I was doing some profiling of my code and noticed a warning in the profiling output about cljs.core/str.

Chromes complains with: "Not optimized. Bad value context for arguments value", looking further at the implementation of goog.string.buildString

goog.string.buildString = function(var_args) {
  return Array.prototype.join.call(arguments, '');
};

Given that we don't ever call it with more than one argument it is probably not best implementation choice.

Maybe skip the call and inline it ala

(defn str
  "With no args, returns the empty string. With one arg x, returns
  x.toString().  (str nil) returns the empty string. With more than
  one arg, returns the concatenation of the str values of the args."
  ([] "")
  ([x] (if (nil? x)
         ""
         (.join #js [x] "")))
  ([x & ys]
    (loop [sb (StringBuffer. (str x)) more ys]
      (if more
        (recur (. sb  (append (str (first more)))) (next more))
        (.toString sb)))))

I didn't follow this issue but why are we not using .toString? The buildString/array approach seems kind of hackish?

I'm not too sure about the overall impact but since cljs.core/str showed up pretty high in my profile I think this should be investigated further.

Comment by Thomas Heller [ 01/Jan/15 7:28 AM ]

Before:

;;; str
[], (str "1"), 1000000 runs, 254 msecs
[], (str 1), 1000000 runs, 266 msecs
[], (str nil), 1000000 runs, 80 msecs
[], (str "1" "2" "3"), 1000000 runs, 753 msecs

After:

;;; str
[], (str "1"), 1000000 runs, 82 msecs
[], (str 1), 1000000 runs, 86 msecs
[], (str nil), 1000000 runs, 79 msecs
[], (str "1" "2" "3"), 1000000 runs, 242 msecs

But I only tested V8, probably needs some verification.

Comment by Thomas Heller [ 01/Jan/15 7:39 AM ]
(defn str
  "With no args, returns the empty string. With one arg x, returns
  x.toString().  (str nil) returns the empty string. With more than
  one arg, returns the concatenation of the str values of the args."
  ([] "")
  ([x1]
     (.join #js [x1] ""))
  ([x1 x2]
     (.join #js [x1 x2] ""))
  ([x1 x2 x3]
     (.join #js [x1 x2 x3] ""))
  ([x1 x2 x3 x4]
     (.join #js [x1 x2 x3 x4] ""))
  ...)

Does perform even better.

;;; str
[], (str "1"), 1000000 runs, 40 msecs
[], (str 1), 1000000 runs, 43 msecs
[], (str nil), 1000000 runs, 96 msecs
[], (str "1" "2" "3"), 1000000 runs, 117 msecs

How many args should it inline?

Comment by David Nolen [ 01/Jan/15 12:43 PM ]

I'd be OK with up to 4 then variadic.

Comment by Thomas Heller [ 01/Jan/15 5:05 PM ]

There is some weird interaction between the code generated by the cljs.core/str macro and function.

The macro generates

(str "hello" 1 "world" :yo nil)

yields

[cljs.core.str("hello"),cljs.core.str((1)),cljs.core.str("world"),cljs.core.str(new cljs.core.Keyword(null,"yo","yo",1207083126)),cljs.core.str(null)].join('');

Given that str with 1 arg will basically unroll to

[["hello"].join(""), ...]

I think it might be safe to completely remove the macro since cljs.core/str would then do the same and the JIT is probably smart enough to figure this out (or even Closure when compiling).

Comment by Francis Avila [ 02/Jan/15 11:14 AM ]

Chromes complains with: "Not optimized. Bad value context for arguments value", looking further at the implementation of goog.string.buildString

Chrome complains about the variadic function dispatch code in the same way, see CLJS-916 plus patch.

I think it might be safe to completely remove the macro since cljs.core/str would then do the same and the JIT is probably smart enough to figure this out (or even Closure when compiling).

The Closure compiler is not smart enough to remove the intermediate array, which is why I filed CLJS-801 (which this ticket rolled back). I don't think JITs can do it either.

I am beginning to wonder if we should ignore the Safari 6.0.5 problem in CLJS-847 that started all this string mess. To recap:

  1. CLJS-801 is accepted, which removes [123, x].join('') in the str macro case in favor of ''+123+(cljs.core/str$arity$1 x) style code, which the closure compiler can precompute. At this time, the one-arg cljs.core/str function (not macro) calls toString on its argument.
  2. CLJS-847 is filed. On Safari 6.0.5 at higher JIT levels, calling toString on some things (possibly only unboxed numbers? definitely not strings) throws a TypeError. This is unquestionably a bug in Safari. David fixes by making one-arg cljs.core/str function call js-str instead of toString. js-str uses string-concat ''+x.
  3. However, this breaks for objects that define valueOf (issue in current ticket), because in js ''+x is the same as ''+x.valueOf().toString() not ''+x.toString().
  4. David considers using String() and variations but rejects because of performance hit.
  5. David rolls back CLJS-801 from the string-concat back to the array-join style to fix.
  6. Nikita and I point out that rolling back CLJS-801 only fixes the str macro, not the string function, which still uses js-str and hence string-concat.
  7. David fixes the str function to use goog.string.buildString, which has the behavior of array.join. Behavior is now correct even on Safari 6.0.5.
  8. Thomas points out that buildString uses arguments in a way unoptimizable by v8, and now the str function (not macro) has a performance regression. He suggests using [].join() directly.

So, there's a lot of back and forth on this issue, and it's all because of a bug in Safari 6.0.5 which no one has been able to reproduce first-hand because Safari 6.0.5 is old and rare. For some perspective, Safari 6.0.x was only available on Lion and Mountain Lion between July 25,2012 and June 11,2013. Before July 25,2012 Lion used Safari 5.1.x and there was no Mountain Lion. On June 11, 2013, both Lion and Mountain Lion switched to Safari 6.1.x which does not suffer from the toString TypeError bug (I checked--I have an iMac with Lion on it). The only machines on Safari 6.0.5 are (Mountain) Lion machines which used software updates until late 2012-early 2013 and then stopped. I can't imagine this is a large number of people.

It is theoretically possible for me to run Safari 6.0.x on my Lion machine to actually test this, but I can't find a way to downgrade from 6.1.x.

I think the options are:

  1. Use array.join() for all stringification and take the performance hit (which we should quantify). Include a comment that this is only for Safari 6.0.x (only confirmed second-hand on 6.0.4 and 6.0.5) for future generations, who are going to think this is weird.
  2. Use CLJS-801 and toString (status quo before CLJS-847), and ignore this problem for Safari 6.0.x.
  3. Use CLJS-801, but add a number? check (with comment) to cljs.core/str$arity$1 for Safari 6.0.5. The number case should use js-str, and the rest toString. I think this will work, but again we have no way to test--we really need to get our hands on a Safari 6.0.x browser.

Of course we should benchmark these approaches but my hunch is that 2 is faster than 3 is faster than 1.

Comment by David Nolen [ 02/Jan/15 11:16 AM ]

We are not going to ignore Safari 6.0.X. Any decisions made about this ticket will include supporting it.

Comment by Francis Avila [ 10/Jan/15 4:12 AM ]

Update on some research I am doing into this.

I created a jsperf of alternative str implementations that I am trying out. Right now I've only looked at one-arg str. I discovered a few things:

  • {{''+[x]}} is a faster alternative to [x].join('').
  • Advanced compilation can compute {{''+[x]}} at compile time if x is a bool, str, undefined, null, or number, even through function calls! I.e. str_test.str_arr(123) compiles to "123" without macro magic.
  • However, using an intermediate array (even if a preallocated singleton) is still slower than the old (if (nil? x) "" (.toString x))
  • Using a switch statement is as least as fast as the str-tostr baseline, usually faster.
  • I am 99% sure all these implementations (except str-tostr, the baseline, which definitely fails) work on the dreaded Safari 6.0.x. If anyone has this version, point it at the jsperf link above and run the tests. I think Browserstack has this version of Safari.

I'm still investigating the variadic case (str x y z a b c). It might be better to use reduce instead of Stringbuffer+seq. (Stringbuffer just does ''+x now instead of an array-join.)

Comment by Thomas Heller [ 10/Jan/15 6:37 AM ]

Sorry, got side-tracked for a bit.

@Francis: Thanks for the recap.

Don't have Safari 6 available either, but seems wrong that we all have to suffer because is minor percentage still has this (667 users of 190k+ on my site). Don't have a solution cause I can't test whether it works, we might try String.concat.

"".concat(obj); // "42"
"".concat(obj, ""); // "hello"
String.prototype.concat(obj, "") // "hello"
String.prototype.concat("", obj) // "hello"

But no idea if String.concat works, also it behaves odd with regards to valueOf.

http://jsperf.com/js-string-concat-variants

Perf is also inconclusive since Firefox appears to be cheating.

Comment by Francis Avila [ 10/Jan/15 2:04 PM ]

Tested that jsperf with Safari 6.0.5 using Browserstack, results are there.

Note I could not reproduce CLJS-847 because str-tostr does not fail as expected. I will try harder now that I have a browser to test.

Comment by Francis Avila [ 10/Jan/15 6:55 PM ]

Still cannot reproduce CLJS-847.

This script includes my attempt at a minimum reproducible case. My theory was that certain types at higher jit levels would fail. I could not get any case to fail. I also tried flapping back and forth between types and using one type at a time, but still no failures.

In this thread I found this "minimal" script which the OP said he could get to fail reliably. I could not get it to fail. However the original post was from feb 15, 2013, which means the Safari he was using would have to be 6.0.2 or lower.

Hypotheses:

  1. This error does not affect 6.0.5 but maybe 6.0.4 or lower.
  2. BrowserStack's system somehow mitigates the bug, meaning we need a "real" Lion Safari 6.0.x to test.
  3. These tests only fail under the correct phase of the moon.

So I can code up a patch for str using the str-switch implementation (which is at least a bit faster on some browsers), but I have no idea if it may fail on Safari 6.0.5. I only know that it works so far. CLJS-801 should also be safe to reapply because the root cause of all issues is the implementation 1-arity of the cljs.core/str function.

I have also asked for Kevin's help back in CLJS-847. (Kevin was the original reporter of the Safari 6.0.x issue.)

Comment by Francis Avila [ 19/Jan/15 12:51 AM ]

Made a jsperf of variadic cases. Chrome seems to really prefer IReduce to seq+stringbuilder for vectors (other collections not tested), but there is no difference or a small slowdown on other browsers. Not sure if it's worth it.

Also updated arity-one cases with a str using switch and never using toString. Nearly 50% slower than using switch or toString on Chrome, smaller on Safari.

In terms of safety str-switch-notostr does not use toString at all so is probably safer. I think str-switch will likely work too, though, and is significantly faster. However I haven't been able to get any TypeErrors in Safari 6.0.5 so it's anyone's guess.

I suggest something like this as a new str (which doesn't use reduce, but could):

(defn str
 ([x]
  (case (js* "typeof ~{}" x)
   "string" x
   "object" (if (identical? nil x) "" (.toString x))
   ("boolean" "number") (js-str x)
   "undefined" ""
   (js-str #js [x])))                                       ;; insurance against Safari 6.0.x TypeError bug.
 ([a b] (js* "~{}+~{}" (str a) (str b)))
 ([a b c] (js* "~{}+~{}+~{}" (str a) (str b) (str c)))
 ([a b c d] (js* "~{}+~{}+~{}+~{}" (str a) (str b) (str c) (str d)))
 ([a b c d & more]
  (loop [s (str a b c d) [e f g h & r] more]
   (let [s' (js* "~{}+~{}+~{}+~{}+~{}" s e f g h)]
    (if (nil? r)
     s'
     (recur s' r))))))
Comment by Francis Avila [ 19/Jan/15 11:24 PM ]

First cut of a possible patch that resolves this while not breaking CLJS-847. Should wait for confirmation that this does not break Safari 6.0.x.

Comment by Francis Avila [ 19/Jan/15 11:34 PM ]

Oops forgot tests.

Comment by Francis Avila [ 03/Feb/15 10:24 AM ]

Update in CLJS-847: original reporter was not able to reproduce his original bug report in Safari 6.0.x running in BrowserStack. This may be because of BrowserStack, but it's the best we have.

Given how hard this bug is to reproduce, how few people it affects, and how significant the performance regression is, I still think we should go back to the simple (if (nil? x) "" (.toString x)) implementation. However, you could also try the patch on this ticket (using a typeof switch), which at least (handwaving) might fix this bug in Safari 6.0.x and is a little faster than a simple .toString in Chrome and not much slower elsewhere. (The reason I think it might avoid this bug in Safari is that it avoids calling .toString on non-Objects.)

Comment by Antonin Hildebrand [ 25/Apr/15 11:08 PM ]

I wonder if you considered swapping str function at runtime during CLJS init phase.

Implement str function using plain .toString() call (original solution). And at startup check for Safari 6.0.x presence and optionally swap str for implementation wrapping .toString() call in a try-catch block silencing TypeError exceptions by falling back to Safari 6.0.x friendly .toString() alternative.

We would get correct semantics in all cases. And price would be just slower printing execution on Safari 6.0.x not on all systems.





[CLJS-1223] cljs.repl/doc for unqualified .. macro Created: 24/Apr/15  Updated: 24/Apr/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3126
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Note: Also affects 0.0-3211 (not yet available in JIRA pulldown)
Quick Start cljs.jar
OS X



 Description   

In the REPL, (doc ..) fails, while it succeeds for similar macros like (doc ->), and it also succeeds for ns-qualified: (doc cljs.core/..).

$ java -jar cljs.jar -m cljs.repl.node
ClojureScript Node.js REPL server listening on 54359
To quit, type: :cljs/quit
cljs.user=> *clojurescript-version*
"0.0-3211"
cljs.user=> (doc ..)
-------------------------
/.
  nil

nil
cljs.user=> (doc cljs.core/..)
-------------------------
cljs.core/..
([x form] [x form & more])
Macro
  form => fieldName-symbol or (instanceMethodName-symbol args*)

  Expands into a member access (.) of the first member on the first
  argument, followed by the next member on the result, etc. For
  instance:

  (.. System (getProperties) (get "os.name"))

  expands to:

  (. (. System (getProperties)) (get "os.name"))

  but is easier to write, read, and understand.

nil





[CLJS-1091] Compose JavaScript dependency indexes Created: 07/Mar/15  Updated: 29/Apr/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently hard coded to Google Closure deps.js and the one produced for a build. Users should be able to supply JS dependency indexes that can get merged in.






[CLJS-1245] Implement bound-fn Created: 03/May/15  Updated: 05/May/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Brandon Bloom Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

See discussion on http://dev.clojure.org/jira/browse/CLJS-210






[CLJS-1266] Node: Rename .cljs to .cljc -> old filenames in stacktrace Created: 12/May/15  Updated: 12/May/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3269
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Using QuickStart, set up Node REPL.

Manually add a foo/bar.cljs to filesystem with

(ns foo.bar)

(defn throw-ex [] (ffirst 1))

(defn call-me [] (throw-ex))

Check that it works:

cljs.user=> (require 'foo.bar)
nil
cljs.user=> (foo.bar/call-me)
repl:13
throw e__4210__auto__;
      ^
Error: 1 is not ISeqable
    at Object.cljs$core$seq [as seq] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:956:20)
    at Object.cljs$core$first [as first] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:965:16)
    at cljs$core$ffirst (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:1398:11)
    at foo$bar$throw_ex (/Users/mfikes/Desktop/hello_world-node/out/foo/bar.cljs:3:20)
    at foo$bar$call_me (/Users/mfikes/Desktop/hello_world-node/out/foo/bar.cljs:5:19)
    at repl:1:105
    at repl:9:3
    at repl:14:4
    at Object.exports.runInThisContext (vm.js:74:17)
    at Domain.<anonymous> ([stdin]:41:34)

Then manually move bar.cljs to bar.cljc and add a new symbol so it looks like:

(ns foo.bar)

(defn throw-ex [] (ffirst 1))

(defn call-me [] (throw-ex))

(defn call-again [] (call-me))

Then reload the ns and use the new symbol:

cljs.user=> (require 'foo.bar :reload)
nil
cljs.user=> (foo.bar/call-again)
repl:13
throw e__4210__auto__;
      ^
Error: 1 is not ISeqable
    at Object.cljs$core$seq [as seq] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:956:20)
    at Object.cljs$core$first [as first] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:965:16)
    at cljs$core$ffirst (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:1398:11)
    at foo$bar$throw_ex (/Users/mfikes/Desktop/hello_world-node/out/foo/bar.cljs:3:20)
    at foo$bar$call_me (/Users/mfikes/Desktop/hello_world-node/out/foo/bar.cljs:5:19)
    at foo$bar$call_again (/Users/mfikes/Desktop/hello_world-node/out/foo/bar.cljs:5:19)
    at repl:1:108
    at repl:9:3
    at repl:14:4
    at Object.exports.runInThisContext (vm.js:74:17)

This illustrates the defect. call_again and the other symbols are shown as being in the old filename.

Stop the REPL and restart it to see correct behavior:

cljs.user=> :cljs/quit
orion:hello_world-node mfikes$ rlwrap java -cp cljs.jar:src clojure.main node_repl.clj
Reading analysis cache for jar:file:/Users/mfikes/Desktop/hello_world-node/cljs.jar!/cljs/core.cljs
Compiling src/foo/bar.cljc
ClojureScript Node.js REPL server listening on 49397
Watch compilation log available at: out/watch.log
To quit, type: :cljs/quit
cljs.user=> (require 'foo.bar)
nil
cljs.user=> (foo.bar/call-again)
repl:13
throw e__4210__auto__;
      ^
Error: 1 is not ISeqable
    at Object.cljs$core$seq [as seq] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:956:20)
    at Object.cljs$core$first [as first] (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:965:16)
    at cljs$core$ffirst (/Users/mfikes/Desktop/hello_world-node/out/cljs/core.cljs:1398:11)
    at foo$bar$throw_ex (/Users/mfikes/Desktop/hello_world-node/out/foo/bar.cljc:3:20)
    at foo$bar$call_me (/Users/mfikes/Desktop/hello_world-node/out/foo/bar.cljc:5:19)
    at foo$bar$call_again (/Users/mfikes/Desktop/hello_world-node/out/foo/bar.cljc:7:22)
    at repl:1:108
    at repl:9:3
    at repl:14:4
    at Object.exports.runInThisContext (vm.js:74:17)


 Comments   
Comment by Mike Fikes [ 12/May/15 2:04 PM ]

FWIW as a comparison, the same use case works properly with Clojure 1.7.0-beta2.





[CLJS-1274] Allow assignment to namespace-qualified names in current namespace Created: 17/May/15  Updated: 17/May/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3211
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: lvh Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In Clojure, you can def to a namespace-qualified name as long as it's in the current namespace. You can't do that in Clojurescript. This makes writing some macros that def to a local name a bit more annoying, since the syntax-quote will automatically namespace-qualify any symbols, so you have to write the somewhat unsightly and not super obvious ~'sym.






[CLJS-776] re-matches is incorrect Created: 28/Feb/14  Updated: 02/Dec/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Francis Avila Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The re-matches function does not have the correct semantics: it performs a search (not match) against the string and returns nil if the string and matched-string are unequal. This is not the same as true matching, which is like inserting "^" and "$" at the beginning and end of the pattern.

Example in Clojure:

user=> (re-find #"0|[1-9][0-9]+|0[xX][0-9a-zA-Z]+" "0x1")
"0"
user=> (re-matches #"0|[1-9][0-9]+|0[xX][0-9a-zA-Z]+" "0x1")
"0x1"

Compare Clojurescript:

ClojureScript:cljs.user> (re-find  #"0|[1-9][0-9]+|0[xX][0-9a-zA-Z]+" "0x1")
"0"
ClojureScript:cljs.user> (re-matches #"0|[1-9][0-9]+|0[xX][0-9a-zA-Z]+" "0x1")
nil

This bug is (one of the) reasons why CLJS-775.

I'm not completely sure what to do here. My first thought is to have re-matches inspect the -source property of its regex input, wrap the string with "^$", then carefully copy all flags over to a new regexp.

Questions:

  1. Are there any valid patterns where this is not safe? E.g., where we could not put ^ first? Is "^^abc$$" ok?
  2. Can we avoid cloning if ^ and $ are already the first and last chars of the pattern?
  3. How does multiline mode play in to this, if at all?
  4. regexinstance.lastIndex is a piece of mutability on regex instances (or the RegExp global on older browsers) which is used as a string offset for multiple invocations of exec() on the same string. I have no idea what to do if re-* gets a regex with the global flag set. (BTW, this is a very good reason to reject CLJS-150: allowing clojure to accept the global flag makes regular expression objects stateful, and would completely screw up re-seq for example.)


 Comments   
Comment by Francis Avila [ 24/Jun/14 7:37 AM ]

I would like to propose a somewhat radical suggestion that would: fix this issue and CLJS-810, put us in a better position to resolve CLJS-485 CLJS-746 CLJS-794 (clojure.string/replace woes), allow us to add some regex-as-a-value niceties to patterns in js (CLJS-67 and CLJS-68), and bring clojurescript's regular expression handling closer to clojure's by implementing more of the re-* functions.

Example implementation (not a patch) at this cljsfiddle: http://cljsfiddle.net/fiddle/favila.regexp

Essential points:

  1. Create a Pattern object, created by re-pattern, which provides methods to create regexps for search (re-find) or exact match (re-matches) or repeated searches (re-seq, re-matcher + re-find). Each of these must be a different RegExp object in javascript even though they are similar regular expression strings. The re-find and re-matches patterns can be cached. All can generate RegExps lazily.
  2. regular expression literals emit these Pattern objects instead of RegExp objects.
  3. Create a Matcher object to correspond to the currently-unimplemented re-matcher. It combines a global-flagged RegExp object, a search string, and a done flag. If it keeps the last match (similar to java), cljs can also implement re-groups.
  4. Make re-seq use the Matcher object and thus the .lastIndex that native RegExps provide for global matches. (Its implementation no longer requires string slicing after every match.)
  5. If re-find is given a native RegExp object instead of a pattern, it will use it as-is. This matches current behavior.
  6. If re-matches is given a native RegExp object and it isn't suitable for exact-matching, a new RegExp is cloned from the input RegExp with ^ and $ prepended and appended and the global flag added. (This technique is used in clojure.string/replace, but incorrectly.)

Thoughts?

Comment by David Nolen [ 02/Dec/14 5:46 AM ]

This sounds interesting but I'm somewhat concerned about the interop story. I think people will expect functions to take regular RegExps as well as Pattern. You haven't mentioned this issue here?

Comment by Francis Avila [ 02/Dec/14 1:16 PM ]

I apologize if some of my thoughts are vague; I haven't thought about this in a while.

First note that a narrow class of RegExps are effectively "pure": If they do a full-string match (e.g. start with ^ and end with $) and have the global flag set to false then their lastIndex will always seem to be 0.

Interop possibilities:

  • Patterns and RegExps can be created from one another, so coercion is always an option. E.g. re-pattern can accept a RegExp and some other (cljs-specific) function can coerce from Pattern or Matcher to RegExp. (Or maybe re-matcher can return a RegExp-compatible object--see below.)
  • RegExp given to cljs re-*: "Pure" regexes can be used directly, otherwise we create a Pattern and/or Matcher. (I don't remember the details, but the fiddle should cover them.)
  • Pattern used as a RegExp: Patterns can expose all the properties of RegExp instances. If the pattern is pure, it can implement .test and .exec. .lastIndex will always be 0. Not sure what to do about impure patterns: throw exception, act pure anyway, return a new object?
  • Matcher used as a RegExp: A Matcher can exactly replicate a RegExp instance, maybe even use the same prototype. Using it like a RegExp will mutate the object and disturb its internal state, but as long as it's either used consistently as a RegExp or consistently as a Matcher this won't matter. Notes:
    • Matcher holds the matched string in Java. Javascript trusts you to always supply the same string (e.g. in a while loop).
    • Java's Matcher holds the last match (used by re-groups). Javascript's RegExp does not.
    • Javascript's RegExp will automatically reset when lastIndex reaches the end of the source string. Java's Matcher won't.
    • Matcher must be a wrapper and not a normal RegExp because of these three extra bits of state.
    • The return value of re-matcher is only consumed by the 1-arg form of re-find and re-groups.
    • re-seq can use a matcher internally, but since it is private it doesn't have to.
    • Should other Java methods of Matcher be implemented?
  • Pattern given to String.prototype.match, .replace, .search, and .split: I haven't thought about this. Considerations:
    • Problem code is any cljs code using an object created via pattern literals or re-pattern and using it as an argument to these String methods. If they use clojure.string methods instead they would be fine.
    • Such code is also impossible in java clojure: only (.split s "pattern-str") is the same in java/clj and js/cljs and it will continue to work (without flags) on both platforms. Possibly we could just make people fix such code since it is platform-specific, but I need to see how widespread this is.
    • The fix for such code is to either:
      • Use a pattern->regexp coercion function we will provide.
      • Construct those regexps directly with js/RegExp.
      • Use clojure.string functions instead of String methods. This also has the advantage of being portable between clj and cljs.
    • Possibly we can patch the RegExp constructor or mess with the String prototype chain to do pattern->regexp coercion automatically, but this is a violent solution.

Correct me if I'm wrong, but in Clojure (java) code it is extremely uncommon to use Pattern and Match methods or to use them with String methods directly. For the most part they are treated as opaque objects used via re-* and clojure.string/*. Code written in the same style in cljs would be unaffected, and we can declare any other use as platform-specific and require explicit creation of RegExps (and don't bother to make Matcher or Pattern act like RegExps). This is my preferred approach for interop if there isn't too much use of RegExp.prototype.test, .exec, and String.prototype.match, .replace, .search, and .split.





[CLJS-1320] clojure.string/split adds separator matches & failed matches (nil) when the separator is a regex with alternation Created: 26/Jun/15  Updated: 27/Jun/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3308
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: lvh Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

I want to split a string on "; ", and optionally discard a final ";". So, I tried:

(clojure.string/split "ab; ab;" #"(; )|(;$)")

In Clojure, this does what I want:

["ab" "ab"]

In ClojureScript, I get:

["ab" "; " nil "ab" nil ";"]

I'm not sure to what extent this is a platform distinction and to what extent it's a bug. Returning nils and seperators from clojure.string/split's output seems like it's against string.split's contract?






[CLJS-1278] Asserts still fail while :require-ing .js file (either in :libs or in :source-paths) (same as CLJS-1196) Created: 20/May/15  Updated: 14/Jul/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3269
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Michal Till Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs_1278.patch    

 Description   

Following on CLJS-1196, I can't get it to work.

In version 0.0-3264 lein-cljsbuild crashed on weird eception `Caused by: java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil"` but the current version 0.0-3269 gives the same failed assertion as previously.

I've put up a sample project to illustrate the issue.

Steps to reproduce:

`git clone https://github.com/tillda/stackone`
`cd stackone`
`git checkout 537e5c69b844bc53c159e85cafc24310543cc918`
`lein clean && lein cljsbuild once temp`

Expected behaviour: cljs compiled successfully with src/vendor/client/closure.js and env/stackone/helpersjs.js being included.

Actual behaviour:

```
Compiling "resources/public/lein-cljsbuild-temp/dev-mode-deps.js" failed.
Exception in thread "main" java.lang.AssertionError: Assert failed: (or (file? x) (url? x) (string? x)), compiling/private/var/folders/ym/l2qxd7l97kzfzftrdpqsclm40000gn/T/form-init3642888309490821030.clj:1:125)
at clojure.lang.Compiler.load(Compiler.java:7249)
at clojure.lang.Compiler.loadFile(Compiler.java:7175)
at clojure.main$load_script.invoke(main.clj:275)
at clojure.main$init_opt.invoke(main.clj:280)
at clojure.main$initialize.invoke(main.clj:308)
at clojure.main$null_opt.invoke(main.clj:343)
at clojure.main$main.doInvoke(main.clj:421)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.AssertionError: Assert failed: (or (file? x) (url? x) (string? x))
at cljs.util$ext.invoke(util.cljc:115)
at cljs.closure$source_on_disk.invoke(closure.clj:1206)
at cljs.closure$output_unoptimized$fn__3708.invoke(closure.clj:1235)
at clojure.core$map$fn__4551.invoke(core.clj:2622)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:507)
at clojure.core$seq__4126.invoke(core.clj:135)
at clojure.core$filter$fn__4578.invoke(core.clj:2677)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:507)
at clojure.core$seq__4126.invoke(core.clj:135)
at clojure.core$map$fn__4551.invoke(core.clj:2614)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:674)
at clojure.core$next__4110.invoke(core.clj:64)
at clojure.core$str$fn__4186.invoke(core.clj:528)
at clojure.core$str.doInvoke(core.clj:526)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invoke(core.clj:628)
at cljs.closure$deps_file.invoke(closure.clj:1040)
at cljs.closure$output_deps_file.invoke(closure.clj:1060)
at cljs.closure$output_unoptimized.doInvoke(closure.clj:1243)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.core$apply.invoke(core.clj:630)
at cljs.closure$build.invoke(closure.clj:1514)
at cljs.closure$build.invoke(closure.clj:1426)
at cljsbuild.compiler$compile_cljs$fn__3884.invoke(compiler.clj:81)
at cljsbuild.compiler$compile_cljs.invoke(compiler.clj:80)
at cljsbuild.compiler$run_compiler.invoke(compiler.clj:187)
at user$eval4018$iter_40544058$fn4059$fn_4077.invoke(form-init3642888309490821030.clj:1)
at user$eval4018$iter_40544058$fn_4059.invoke(form-init3642888309490821030.clj:1)
at clojure.lang.LazySeq.sval(LazySeq.java:40)
at clojure.lang.LazySeq.seq(LazySeq.java:49)
at clojure.lang.RT.seq(RT.java:507)
at clojure.core$seq__4126.invoke(core.clj:135)
at clojure.core$dorun.invoke(core.clj:3007)
at clojure.core$doall.invoke(core.clj:3023)
at user$eval4018.invoke(form-init3642888309490821030.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6792)
at clojure.lang.Compiler.eval(Compiler.java:6782)
at clojure.lang.Compiler.load(Compiler.java:7237)
... 11 more
Subprocess failed
```



 Comments   
Comment by David Nolen [ 20/May/15 10:21 AM ]

This issue is in danger of being closed. Please supply minimal steps to reproduce that do not involve anything other than the ClojureScript compiler. We no longer have time to wade through the indirection introduced by cljsbuild or any other downstream tooling. Thanks.

Comment by Michal Till [ 20/May/15 11:14 AM ]

@David Nolen: I have created a failing minimal testcase based on the Quick Start document. Here it is: https://github.com/tillda/cljs-testcase/

Comment by David Nolen [ 20/May/15 11:27 AM ]

Michal the failing example is not correct. You are not supplying any :libs option.

Comment by Michal Till [ 20/May/15 11:45 AM ]

Ah! Thank you very much! This additional issue was therefore my error. Now it seems to work even in my "big" example.

However it would be cool if there was a meaningful error message stating that a file path can't be resolved. If one is not an expert in the cljs compiler this is almost impossible to figure out. After all the error message in the CLJS-1196 issue and in this wrongfully reported one are exactly the same.

You may close this issue.

Comment by David Nolen [ 20/May/15 11:55 AM ]

We'll leave it open for the improving the error message.

Comment by Sebastian Bensusan [ 22/May/15 7:16 AM ]

Added the check in cljs.closure/source-on-disk where there is info for the error message.

For the supplied case, the error message is:

java.lang.IllegalArgumentException: The file file:/home/carlos/Playground/cljs-testcase/src/hello_world/closure.js 
lacks an associated source file. If it is a JavaScript library please add it to :libs}}

If a different wording or location of the check is needed, I'll submit a new patch with corrections.

Notes:

  • Changed:(:provides js) to (-provides js) in order to be consistent with IJavaScript.
  • cljs.clojure/source-on-disk takes a js argument that should satisfy with IJavaScript and ISourceMap if :source-map is enabled but the implementation is hardcoded to maps because :source-map and :source-url are used instead of ISourceMap methods -source-map and -source-url. I propose to extend PersistentMap and PersistentArrayMap to ISourceMap to make source-on-disk compliant with both protocols.




[CLJS-1294] Macroexpand only accept quoted lists Created: 01/Jun/15  Updated: 14/Jul/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Julien Eluard Assignee: Julien Eluard
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1294.patch    

 Description   

In Clojure macroexpand and macroexpand-1 accept any quoted argument while in ClojureScript anything but quoted seq will throw an exception.



 Comments   
Comment by Julien Eluard [ 01/Jun/15 2:16 PM ]

In Clojure some special forms are handled specifically i.e. (macroexpand '(Boolean true)) => (new Boolean true).

I am not sure if/how it applies to ClojureScript.

Comment by David Nolen [ 14/Jul/15 5:58 AM ]

This patch needs to be rebased to master. Thanks!





[CLJS-1259] Incorrect warnings on type hinted maths Created: 09/May/15  Updated: 14/Jul/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3255
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Erik Ouchterlony Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug, math, typehints


 Description   

Variables type hinted as int or double are not recognized as numbers, e.g.

(def ^int i 1)
(+ i i)
WARNING: cljs.core/+, all arguments must be numbers, got [int int] instead. at line 1 <cljs repl>
2


 Comments   
Comment by David Nolen [ 14/Jul/15 6:07 AM ]

The real issue is that there is no support for numeric type hints.





[CLJS-1255] cljs.test file-and-line detection is not useful in browser testing Created: 07/May/15  Updated: 14/Jul/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3211
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Stephen Nelson Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Chrome



 Description   

cljs.test reports using do-report, which adds file and line information computed from javascript stack traces. In chrome at least, these stack traces are not useful:

"Error
    at http://localhost:3449/js/cljs/test.js:261:69
    at cljs$test$do_report (http://localhost:3449/js/cljs/test.js:268:3)
    at http://localhost:3449/js/test/test_tests.js:491:21
    at test.test_tests.test_has_fails.cljs$lang$test (http://localhost:3449/js/test/test_tests.js:502:4)
    at http://localhost:3449/js/cljs/test.js:384:42
    at http://localhost:3449/js/cljs/test.js:387:4
    at cljs$test$run_block (http://localhost:3449/js/cljs/test.js:320:13)
    ..."

The `file-and-line` stack trace parser doesn't parse this correctly, resulting in a message like this:

FAIL in (test-function) (at http:384:42)

Note the lack of a useful file/namespace reference, and that the line number refers to the compiled javascript rather than the source clojurescript.



 Comments   
Comment by Stephen Nelson [ 07/May/15 9:15 PM ]

Prior to the release of cljs.test my company maintained an internal port of clojure.test that did better reporting than cljs.test's by adding source metadata from &form to the do-report calls generated by assert-expr. This approach was great for internal use but might not be suitable for cljs.test as it could reduce portability of assert-expr between clojure and clojurescript. Another approach could be dynamically bind source metadata in the body generated by try-expr. I'd be willing to implement and contribute code if you can provide some indication of your preferred approach.

Our version of assert-expr also injected a 'reporter function', {{(function(a,b,c){a.apply(b.c)})}}, which we would invoke from report, e.g. (reporter (.-debug js/console) js/console args). This causes the clickable link on the right hand side of chrome's console output to link to the source map location of the test expression, rather than the report function.

Comment by David Nolen [ 14/Jul/15 6:09 AM ]

The correct thing to do here is to move the browser REPL stacktrace parsing into a shared library i.e. .cljc that can be loaded into either environment to handle browser difference.





[CLJS-1390] clojure.walk treats vectors diffently from Clojure version Created: 03/Aug/15  Updated: 03/Aug/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.28
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Leon Grapenthin Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The latest patch to clojure.walk (https://github.com/clojure/clojurescript/commit/f706fabfd5f952c4dfb4dc2caeea92f9e00d8287) ports the line of the Clojure version

(instance? clojure.lang.IMapEntry form) (outer (vec (map inner form)))

with the line

(satisfies? IMapEntry form) (outer (vec (map inner form)))

ClojureScript implements IMapEntry on any vector which I assume is intended.

In Clojure, for vectors this case falls:

(coll? form) (outer (into (empty form) (map inner form)))

This makes a difference because empty preserves metadata.
I. e.

(meta (prewalk (fn [form]
                  (vary-meta form assoc :foo true))
               []))

gives {:foo true} on earlier ClojureScript versions and Clojure, but nil on the latest version.

I have relied on this which has likely not been a very good idea, but others might have too - Hence I created this ticket for consideration.






[CLJS-1406] macroexpand munging goog.string.StringBuffer Created: 09/Aug/15  Updated: 14/Aug/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.48
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Matthew Molloy Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bootstrap
Environment:

Bootstrapped Planck REPL


Attachments: Text File cljs_1406.patch     Text File cljs_1406_test.patch    

 Description   

(macroexpand '(with-out-str)) on bootstrapped ClojureScript gives (let* [sb__13582__auto__ (string.StringBuffer.)]...
on JVM compiled ClojureScript it is (let* [sb__1155__auto__ (goog.string.StringBuffer.)]...

goog.string.StringBuffer has been incorrectly munged to string.StringBuffer when the cljs.js compiler is used.



 Comments   
Comment by Joel Martin [ 13/Aug/15 7:28 PM ]

I ran into this today. Here is a test case for the self host tests that reproduces the problem.

Comment by Joel Martin [ 13/Aug/15 7:50 PM ]

Fix the test. Propose a fix that just puts "js/" in front to prevent the broken name resolution. Probably not the correct solution, but it does work.

Comment by David Nolen [ 14/Aug/15 7:50 PM ]

Not going to take the current patches. The underlying resolution issue needs to be fixed.





[CLJS-1420] get-in behavior differs from Clojure by always deferring to the 3 arity fn Created: 12/Aug/15  Updated: 14/Aug/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.48
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Kevin Webster Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs_1420.patch    

 Description   

CLJS-464 should be reverted since the commit changes how get-in is handled by types that implement ILookup.

Since get-in always defers to the 3 arity function, the 2 arity ILookup -lookup fn never gets called. This behavior is inconsistent with how Clojure behaves.

clj:

(get-in
  (reify
    clojure.lang.ILookup
    (valAt [o k] :2-arity)
    (valAt [o k not-found] :3-arity))
  [:foo])
=> :2-arity

cljs:

(get-in
  (reify
    ILookup
    (-lookup [o k] :2-arity)
    (-lookup [o k not-found] :3-arity))
  [:foo])
=> :3-arity


 Comments   
Comment by Kevin Webster [ 12/Aug/15 3:30 PM ]

Tested patch in both V8 & Nashorn

Comment by David Nolen [ 14/Aug/15 7:51 PM ]

Please modify the patch to include a test case. The patch should be squashed into a single commit.





[CLJS-1421] Enable Asynchronous cljs.js/*eval-fn* Created: 14/Aug/15  Updated: 16/Aug/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.48
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Matthew Molloy Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: asynchronous, bootstrap


 Description   

In bootstrapped ClojureScript cljs.js/eval-fn receives javascript source and evaluates it, returning a result. In some contexts it is necessary to evaluate the js asynchronously, can we add this functionality?



 Comments   
Comment by David Nolen [ 14/Aug/15 7:49 PM ]

This ticket needs more rationale. Can you elaborate on the usecase?

Comment by Matthew Molloy [ 14/Aug/15 10:08 PM ]

My usecase is an asynchronous eval function

(fn *eval-fn*
  [{:keys [source]}]
  (js/chrome.devtools.inspectedWindow.eval source
    (fn [result err]
      (if result
        (callback result)
        (callback err))))

There must be other people who have situations like this.

Comment by David Nolen [ 16/Aug/15 12:16 AM ]

Interesting. I don't think this is a common use case, most JS engines provide synchronous eval. Not interested in any breaking changes but would be happy to take a patch that gives you the behavior you want via an option flag, :async-eval.





[CLJS-1428] Add a cljs.core/*command-line-args* var Created: 16/Aug/15  Updated: 01/Sep/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.48
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Add a cljs.core/*command-line-args* var that mimics Clojure's:

https://github.com/clojure/clojure/blob/4bb1dbd596f032621c00a670b1609a94acfcfcab/src/clj/clojure/core.clj#L6148

Rationale:
1) Simplifies writing command-line scripts in ClojureScript if this var is universally available.
2) Consistency with Clojure.

Existing tooling can ignore the var (it would be initialized with nil).

Command-line REPLs or other command-line environments can bind a sequence to this var when launched.



 Comments   
Comment by Justin Thomas [ 31/Aug/15 10:14 PM ]

In this file: https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/nodejs.cljs Looks like you could set this: (def *command-line-args* (.-argv process)) and it'd be accessible under nodejs/*command-line-args*. Not sure where the star vars are set in the elsewhere in the code or if that's a good solution putting it in each repo.

Maybe get the target var somehow and set it based on that--similar to how the nodejs file is loaded?

Found this: src/main/clojure/cljs/core.cljc and saw references to a ns called env.

Comment by David Nolen [ 01/Sep/15 6:44 AM ]

This ticket needs more rationale and stronger outline of the design issues before proceeding. As it stands no one should be working on this yet.

Comment by Justin Thomas [ 01/Sep/15 4:27 PM ]

Just trying to learn the code at the moment. As for rationale, using the command line vars in node is a common use case for shell scripts. Accessing the command line vars in a more clojure-y way seems like a good idea.





[CLJS-677] cljs.reader doesn't support keywords starting with a digit Created: 12/Nov/13  Updated: 10/Sep/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Chas Emerick Assignee: Unassigned
Resolution: Unresolved Votes: 3
Labels: None


 Description   
ClojureScript:foo> (r/read-string ":0")
"Error evaluating:" (r/read-string ":0") :as "cljs.reader.read_string.call(null,\":0\")"
org.mozilla.javascript.EcmaError: TypeError: Cannot read property "0.0" from null (file:/home/chas/dev/clojure/cljs/.repl/cljs/reader.js#451)

The topic of leading digits in keywords came up separately, as they've been supported in Clojure for some time, but can now be considered part of the spec, as it were. See CLJ-1286.

BTW, this is another simple-check win...



 Comments   
Comment by Chas Emerick [ 21/Nov/13 9:38 AM ]

This is not a simple regex change, as I had hoped given the recent flurry in Clojure. The symbol pattern in cljs.reader is faithful to Clojure HEAD, but the processing of matches isn't. I think it may be a wash as to whether it'd be easier to fix what's there vs. porting clojure.tools.reader.impl.commons/parse-symbol (which incidentally doesn't use a regex)…either way, leaving it for another day (or someone else, if they're up for it).

Comment by Francis Avila [ 02/Jul/14 12:35 AM ]

I think I fixed the match processing issue you're talking about (CLJS-775 CLJS-776)? However I'm still confused by this and CLJ-1286. The clojure reader docs and edn spec still say they should reject `:0`, but 1.6.0 doesn't. What's the expected behavior? Is the spec going to be fixed, or clojure reader fixed once downstream packages are fixed?

Comment by Jozef Wagner [ 02/Jul/14 1:50 AM ]

AFAIK EDN specs do not reject :0 (no rule that the second character cannot be a digit). See https://github.com/wagjo/serialization-formats for my interpretation of existing specs.

Comment by Francis Avila [ 02/Jul/14 1:35 PM ]

Ah, I think I see the source of the confusion. Both EDN and the clojure reader spec both say something like "keywords are like symbols, except beginning with a colon." The confusion lies in whether we interpret that as meaning

  1. First character is a colon, then the second character and after are matched against the symbol definition.
  2. The first character is a colon, and the whole form is matched against the symbol definition.

CLJ-1003 CLJ-1252 and CLJ-1286 and myself all seem to understand the first meaning. This might be because when we say "the first character of a keyword" we typically mean the first character after the colon, as if the colon is "special" and not part of the keyword (e.g. like a reader macro character).

However clojure 1.6 seems to be following the second meaning (and explains why `:0/a` is ok but not `:0/0`), and I'm not sure from the cited tickets and google group discussions whether this is because of downstream breakage or if this is the intended interpretation and the patch from CLJ-1252 was accepted by Alex Miller erroneously.

Note if we accept the second interpretation, then the restriction "A symbol can contain one or more non-repeating ':'s." from the clojure reader docs is incorrect for keywords. (EDN doesn't allow namespace-expanded keywords, it seems, so it's not an issue there.)

Also EDN allows contiguous colons in symbols, whereas clojure 1.6 and the reader spec do not.

Comment by Francis Avila [ 02/Jul/14 2:11 PM ]

Also clojure 1.6 allows a/:a and :a/:a (where name part violates first-character rule for symbols), even though the specs do not. (This is something your table doesn't mention. Very thorough work BTW! I wish the reader spec was more formalized and unambiguous...)

Comment by Francis Avila [ 02/Jul/14 3:08 PM ]

I think this pattern follows the specs:

#"(?x)
(?!///) # edge case: / only allowed in name part.
# name or namespace part of symbol or keyword
(?:
 #division symbol
 (/
 # normal symbol
 |[a-zA-Z*!_?$%&=<>][0-9a-zA-Z*!_?$%&=<>\#:+.-]*
 # symbol starting with [-+.]
 |[-+.](?:[a-zA-Z*!_?$%&=<>\#:+.-][0-9a-zA-Z*!_?$%&=<>\#:+.-]*)?)
 # keyword
 |(::?)([0-9a-zA-Z*!_?$%&=<>\#:+.-]+))
# name part when namespace is present
(?:/(/ # division symbol
    |[a-zA-Z*!_?$%&=<>][0-9a-zA-Z*!_?$%&=<>\#:+.-]*
    |[-+.](?:[a-zA-Z*!_?$%&=<>\#:+.-][0-9a-zA-Z*!_?$%&=<>\#:+.-]*)?))?
# groups:
# 1: symbol name or namespace 2: keyword colon(s) 3: keyword name or namespace
# 4: keyword or symbol name (and groups 1 and 3 are namespaces)"

Problems:

  1. Does not enforce no-repeating-colon rule (but it is easy to validate after matching).
  2. Rejects violations of first-character-rule in symbols which clojure accepts.
  3. Accepts a trailing colon on namespace (unlike clojure).
  4. Accepts foo// or :foo//, which are not clearly addressed by the specs. (Jozef's table has more background). These are both allowed in Clojure 1.6, but not 1.5 or (arguably) edn.
Comment by Francis Avila [ 02/Jul/14 6:28 PM ]

Another problem: Accepts :::a/b, which I think is ok per the specs but is not read by 1.6. Crazy example:

user=> (require ['clojure.core :as (symbol ":a")])
nil
user=> :::a/map

RuntimeException Invalid token: :::a/map  clojure.lang.Util.runtimeException (Util.java:221)
user=> (resolve (symbol ":a" "map"))
#'clojure.core/map

Theoretically I might expect :::a/map to be read as :clojure.core/map?

Comment by Nicolás Berger [ 10/Sep/15 6:44 AM ]

Bumping this up, as I just scratched my head for an hour to find out this was the culprit

Comment by David Nolen [ 10/Sep/15 7:15 AM ]

Nicolás, the premise of the ticket is that this should be supported when clearly the Clojure documentation about valid keywords states that it isn't. The Clojure implementation just happens to allow it. In anycase, this needs to be sorted out in Clojure first.

Comment by Francis Avila [ 10/Sep/15 9:35 AM ]

I think CLJ-1527 is currently the ticket where this problem is pursued.





[CLJS-1448] lib-rel-path fails on Windows because of File/separator being \\ Created: 14/Sep/15  Updated: 14/Sep/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.48
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Orlando William Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug
Environment:

Windows



 Description   

https://github.com/clojure/clojurescript/blob/cc953d4be7b4a256fd5eae783f9106a2929a4126/src/main/clojure/cljs/closure.clj#L1210

That code calls replace with \ on windows, who ends up calling (.replaceAll "foo.js" "." "\") and fails with
IllegalArgumentException character to be escaped is missing java.util.regex.Matcher.appendReplacement (:-1)



 Comments   
Comment by Orlando William [ 14/Sep/15 1:20 PM ]

I can't find a way to edit the description, I meant \ followed by \ but somehow it got a line break





[CLJS-1474] Warn if reserved symbol is defined Created: 21/Oct/15  Updated: 21/Oct/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Martin Klepsch Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently a definition like

(defn set! [] ...)

will not cause any warning. Any usage of it (without :as namespace aliasing) however will not use the defined var but the set! special form.

A warning seems appropriate.






[CLJS-1473] Require fail on ns/in-ns created namespaces Created: 20/Oct/15  Updated: 21/Oct/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Andrea Richiardi Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug
Environment:

3.13.0-65 x86_64 GNU/Linux



 Description   

Just to report that the following does not work at the repl (in Clojure it does):

(ns first.namespace)
(def a 4)
(ns second.es)
(require 'first.namespace) ;; with :reload is the same
java.lang.IllegalArgumentException: Namespace first.namespace does not exist
	at cljs.closure$source_for_namespace.invoke(closure.clj:605)
	at cljs.repl$load_namespace.invoke(repl.cljc:182)
	at cljs.repl$load_dependencies.invoke(repl.cljc:206)
	at cljs.repl$evaluate_form.invoke(repl.cljc:474)
	at cljs.repl$fn__4470$self__4482.invoke(repl.cljc:673)
	at clojure.lang.AFn.applyToHelper(AFn.java:165)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invoke(core.clj:630)
	at cljs.repl$wrap_self$g__4450.invoke(repl.cljc:630)
	at cljs.repl$repl_STAR_$read_eval_print__4536.invoke(repl.cljc:854)
	at cljs.repl$repl_STAR_$fn__4542$fn__4551.invoke(repl.cljc:895)
	at cljs.repl$repl_STAR_$fn__4542.invoke(repl.cljc:894)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1146)
	at cljs.repl$repl_STAR_.invoke(repl.cljc:858)
	at cljs.repl$repl.doInvoke(repl.cljc:976)
	at clojure.lang.RestFn.invoke(RestFn.java:410)
	at cljsbuild.repl.rhino$run_repl_rhino.invoke(rhino.clj:8)
	at user$eval4946.invoke(form-init5490341798700416710.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:6782)
	at clojure.lang.Compiler.eval(Compiler.java:6772)
	at clojure.lang.Compiler.load(Compiler.java:7227)
	at clojure.lang.Compiler.loadFile(Compiler.java:7165)
	at clojure.main$load_script.invoke(main.clj:275)
	at clojure.main$init_opt.invoke(main.clj:280)
	at clojure.main$initialize.invoke(main.clj:308)
	at clojure.main$null_opt.invoke(main.clj:343)
	at clojure.main$main.doInvoke(main.clj:421)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.lang.Var.invoke(Var.java:383)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.main.main(main.java:37)

I am available for investigating more and/or taking charge of the issue.



 Comments   
Comment by Andrea Richiardi [ 20/Oct/15 9:31 PM ]

sorry about the mistakes...how to edit?

Comment by Andrea Richiardi [ 21/Oct/15 1:32 PM ]

Confirmed using NodeJs repl:

ClojureScript Node.js REPL server listening on 51885
Watch compilation log available at: out/watch.log
To quit, type: :cljs/quit
cljs.user=> (in-ns 'ns.core)
nil
ns.core=> (def a 3)
#'ns.core/a
ns.core=> (in-ns 's.core.repl)
nil
s.core.repl=> (require 'ns.core)
java.lang.IllegalArgumentException: Namespace ns.core does not exist
	at cljs.closure$source_for_namespace.invoke(closure.clj:605)
	at cljs.repl$load_namespace.invoke(repl.cljc:182)
	at cljs.repl$load_dependencies.invoke(repl.cljc:206)
	at cljs.repl$evaluate_form.invoke(repl.cljc:474)
	at cljs.repl$fn__4583$self__4595.invoke(repl.cljc:673)
	at clojure.lang.AFn.applyToHelper(AFn.java:165)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invoke(core.clj:630)
	at cljs.repl$wrap_self$g__4563.invoke(repl.cljc:630)
	at cljs.repl$repl_STAR_$read_eval_print__4649.invoke(repl.cljc:854)
	at cljs.repl$repl_STAR_$fn__4655$fn__4664.invoke(repl.cljc:895)
	at cljs.repl$repl_STAR_$fn__4655.invoke(repl.cljc:894)
	at cljs.compiler$with_core_cljs.invoke(compiler.cljc:1146)
	at cljs.repl$repl_STAR_.invoke(repl.cljc:858)
	at cljs.repl$repl.doInvoke(repl.cljc:976)
	at clojure.lang.RestFn.invoke(RestFn.java:486)
	at user$eval44.invoke(node_repl.clj:10)
	at clojure.lang.Compiler.eval(Compiler.java:6782)
	at clojure.lang.Compiler.load(Compiler.java:7227)
	at clojure.lang.Compiler.loadFile(Compiler.java:7165)
	at clojure.main$load_script.invoke(main.clj:275)
	at clojure.main$script_opt.invoke(main.clj:337)
	at clojure.main$main.doInvoke(main.clj:421)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.lang.Var.invoke(Var.java:379)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.main.main(main.java:37)
Comment by Andrea Richiardi [ 21/Oct/15 1:37 PM ]

I guess it is each repl-env with its -evaluate to be responsible for loading right? Can it be a proble of each and every *load-fn* out there?

Comment by Andrea Richiardi [ 21/Oct/15 2:37 PM ]

I am analyzing `cljs.repl/load-namespace` and it looks like it handles only loading from sources:

line 178 @ clojurescript 1.7.158

 sources (cljsc/add-dependencies
                   (merge (env->opts repl-env) opts)
                   {:requires [(name ns)]
                    :type :seed
                    :url (:uri (cljsc/source-for-namespace
                                 ns env/*compiler*))})

The function `cljs.closure/source-for-namespace` is throwing the exception because of course it cannot find the sources for a manually created namespace.
An idea could be to change `cljs.closure/source-for-namespace` and return nil in case no sources can be found.
Then change `cljs.repl/load-namespace` to check for created namespaces when `souces` is nil.

Mike told me that the namespaces are not reified, so the next question is, is there an atom that contains all the created namespaces?

I am going to wait for input on this, when everybody has time of course.





[CLJS-1407] Exposing output file dependency graph in API Created: 09/Aug/15  Updated: 08/Nov/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Juho Teperi Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Use case for boot-cljs and boot-reload:

After compilation boot-reload reloads the changed JS files. So that the files can be reloaded in correct order, boot-cljs uses dependency graph to sort the files. Currently boot-cljs accesses compiler state directly and uses data from :js-dependency-index to build the graph: https://github.com/adzerk-oss/boot-cljs/blob/0.0-3308/src/adzerk/boot_cljs/impl.clj#L17-L36

Simple solution:

If dependencies (requires) of namespace are exposed through API it is easy to build graph of cljs namespace dependencies: https://github.com/adzerk-oss/boot-cljs/blob/d479f10935be321232e2363e2ae3e9cc515a81af/src/adzerk/boot_cljs/impl.clj#L12-L32

Problem with this solution is that all-ns, ns-dependencies or target-file-for-cljs-ns do not work with foreign-deps. While foreign-dep files don't usually change and thus aren't reloaded, it's possible that user has local JS files in the project using foreign-deps and those can change.

Questions, notes and issues

  • Should cljs-dependency-graph be exposed in the API or is it enough to provide ns-dependencies and such which user can use to create dependency graph?
  • cljs.build.api/parse-js-ns can also be used to read provides and requires from compiled JS files, but this doesn't work with foreign-deps either
  • Perhaps there is some way in Closure library to reload files in correct order?
  • Supporting foreign-deps is not perhaps necessary, but if there is good way it would be nice to have.


 Comments   
Comment by Juho Teperi [ 11/Aug/15 3:18 AM ]

I would add the call to cljs.compiler.api and it could be called output-dependency-graph.

Creating the graph requires list of all the nodes and dependencies for each node. For Cljs namespaces
these are accessible through all-ns and ns analysis map :requires. Data about foreign-deps
and closure libs is available in the compiler state under :js-dependency-index key. To create the
graph we need to:

1. Get list of all nodes
2. Get dependencies for given node
3. Get output file for given node

Because steps 2 and 3 depend on the type of node, it would probably be easiest to collect those
values in step 1. So step 1 would do something like this:

{{(get-nodes ...) => {:provides "goog.net" :file "out/goog/net.js" :dependencies #{"goog.foo"}} {:provides "frontend.core" :file "out/frontend/core.js" :dependencies #{"cljs.core"}}}}

That could be implemented by concatenating data from cljs namespaces retrieved from all-ns etc. with
data from :js-dependency-index. The next and last step would be to construct the graph using reduce.

Using this implementation there would be just one new API call: output-dependency-graph.

I was thinking alternative approach with all-ns, find-ns etc. versions which would work also with foreign-deps and closure libs, but I don't think it's very easy (or efficient) e.g. to retrieve data for foreign-dep with just a name as they are indexed by file paths.

Comment by David Nolen [ 03/Nov/15 6:34 PM ]

Now that CLJS-1437 is merged what is needed to wrap this one up?

Comment by Juho Teperi [ 08/Nov/15 9:11 AM ]

My current plan with boot-cljs/boot-reload is to use Figwheel client code which uses Google Closure dependency graph for loading the files in correct order. Thus I don't need this anymore. Perhaps it's best to close this if no-one needs this currently?

Comment by David Nolen [ 08/Nov/15 9:28 AM ]

It may still be useful at some point. Will just lower the priority.





[CLJS-1494] turn cljs.core/*assert* into a goog-define Created: 25/Nov/15  Updated: 25/Nov/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Thomas Heller Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File goog-define-assert.patch    
Patch: Code

 Description   

This patch turns the cljs.core/*assert* boolean into a goog.define and also checks *assert* at runtime (instead of only at compile-time).

The closure define option allows the closure compiler to eliminate asserts in :advanced, while :none builds can keep the asserts. This is one of the few remaining issues that prevent :advanced builds to re-use :none compiled (cached) files.

:elide-asserts is unaffected to keep this as simple as possible, but could be built on top of the goog.define instead of actually affecting the compiled output.






[CLJS-1495] Internal ast? assertion for var in fn in def Created: 28/Nov/15  Updated: 29/Nov/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Also affects 170 (not in pulldown yet)
Same behavior in regular and bootstrapped



 Description   

This form, when issued at the REPL, fails to compile, triggering an ana/ast? :pre violation:

(def f (fn [] #'f))

There appears to be nothing fundamentally wrong with the construct, as it can be worked around in multiple ways.

These workarounds, which move the var special out, succeed:

(def f (let [vf #'f] (fn [] vf)))
(declare f)
(let [x (fn [] #'f)] (def f x))

Also, these subtler workarounds succeed in avoiding the issue:

(def f (fn [] #'cljs.user/f))
(def f (fn x [] #'f))


 Comments   
Comment by Mike Fikes [ 28/Nov/15 7:49 PM ]

Analysis of the issue:

tl;dr: A synthetic local is shadowing the top-level var that the var special is being applied to.

Detailed analysis:

The form

(def f (fn [] #'f))

can be reduced to this simpler self-named form to consider, which also exhibits the issue:

(fn f [] #'f)

Analyzing (def f (fn [])) will show that :fn-self-name true is set.

A consequence is that the self name, f in the running example, is carried into the function body as a local symbol, and thus f is no longer a symbol resolving to the top-level var. This leads to a analyzing code that is, in essence, like this sequence

(declare g)
#'g ;; OK
(let [g 1] #'g) ;; exhibits error

Another way of saying the above: The locally introduced self-name, which is otherwise fine with respect to self-recursion, thwarts the var special in this situation, effectively shadowing the top-level var.

Comment by Mike Fikes [ 29/Nov/15 11:08 AM ]

A similar situation occurred for Clojure and that it defeated memoization until fixed http://dev.clojure.org/jira/browse/CLJ-809

Given this

(defn fib [n]
  (if (< n 2)
    n
    (+ (fib (dec n))
      (fib (dec (dec n))))))

Clojure takes a few seconds to compute (fib 41) but is instantaneous after (def fib (memoize fib)).

The synthetic local defeats this attempt at memoization in ClojureScript.





[CLJS-1490] Watch macro files in cljs.build.api/watch Created: 23/Nov/15  Updated: 24/Nov/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Sebastian Bensusan Assignee: Sebastian Bensusan
Resolution: Unresolved Votes: 0
Labels: None


 Description   

The cljs.build.api/watch function is great for writing scripts or tooling but it doesn't track .clj macro files as noted in here. Direct users face unexpected behavior and tooling developers need to reimplement the watch functionality.

The undesired behavior can be tested with this repo (instructions there).

I propose to add the functionality into the watch function, or at least propose a mechanism so that tooling authors can reuse the functionality.



 Comments   
Comment by David Nolen [ 24/Nov/15 12:00 PM ]

Happy to see a fix for this.





[CLJS-1502] Browser REPL broken when started with :optimizations :none Created: 05/Dec/15  Updated: 06/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: ewen grosjean Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs-1502.patch    
Patch: Code

 Description   

Creating a browser-repl env like this: (cljs.repl.browser/repl-env :optimizations :none) does not work because client.js is not compiled in a single file. The browser throws the following error: goog is not defined.
:optimizations :simple (the default) works fine.
A quick fix would be to force :optimizations :simple in the REPL options. However, being able to set :optimizations :none would probably speed up compilation times.






[CLJS-1513] Javascript emitted for cljs.pprint is misinterpreted under Mobile Safari 7.0 Created: 14/Dec/15  Updated: 14/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.28
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Ruslan Prokopchuk Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Tested with 1.7.28 and 1.7.170 versions of ClojureScript.

browser = Mobile Safari 7.0
os = iOS 7.1.2



 Description   

Create minimal ClojureScript project, add {{(:require [cljs.pprint :refer [pprint]])}} to the source file and compile with :optimizations :advanced. Output js will contain strings like

~\x3c\x3c-(~;~@{~w~^ ~_~}~;)-\x3c~:\x3e
which lead to the following error in the Mobile Safari 7.0:

Error: Directive "{" is undefined
~<<-(~;~@{~w~^ ~_~}~;)-<~:>
         ^





[CLJS-901] Protocolize compiler access to the file system Created: 03/Dec/14  Updated: 22/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

Currently builds are based on files on disk. It is desirable to be able to instead get in memory builds, WebDAV based builds, S3 based builds, etc. Many of these alternative strategies are not in scope for the ClojureScript compiler but this does not mean we should not supply the needed hooks for users to control the behavior.



 Comments   
Comment by Thomas Heller [ 03/Dec/14 9:31 AM ]

This and some other issues opened recently (CLJS-900, CLJS-851, CLJS-899, ...) have some overlap with what I have done in shadow-build [1]. Memory based builds are actually already possible cause it will only touch the disk when asked to, although the API could use some cleanup.

Anyways, might be worthwhile to coordinate these efforts to make CLJS more accessible for everyone.

[1] https://github.com/thheller/shadow-build

Comment by Alan Dipert [ 04/Feb/15 11:36 AM ]

I too think it would be totally awesome to have builds based on sources from disparate places.

One alternative in this spirit I have been thinking about is a "SourceSet" approach. The idea is, instead of teaching CLJS how to consume various place-types directly via protocols, provide an API for building a "SourceSet" value and also a build function that takes the SourceSet as input. I imagine the SourceSet in its simplest form as a map of namespaces to string sources.

With a value to represent sources that is place-agnostic and immutable, 3rd party tools can consume/emit/transform these values before invoking a compile without knowledge or interest in CLJS internals. Conversely CLJS need not be concerned with how SourceSets are constructed.

This whole idea is inspired by boot's FileSets, which work basically the same but can't have the "it fits in memory" assumption.





[CLJS-1104] Compute SHA for ClojureScript compiled file Created: 10/Mar/15  Updated: 22/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Needed for shared AOT cache






[CLJS-713] optimized case Created: 04/Dec/13  Updated: 22/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File 0001-CLJS-713-Allow-test-expressions-for-case-to-be-chars.patch     Text File 0001-CLJS-713-first-cut-at-compiling-case-to-switch.patch    

 Description   

With the advent of asm.js many engines will like compile switch statements over integers into jump tables. We should provide a real `case*` ast node that compiles to JS `switch` when possible - i.e. numbers, strings, keywords etc.



 Comments   
Comment by Michał Marczyk [ 18/Feb/14 5:56 PM ]

First cut impl also available here:

https://github.com/michalmarczyk/clojurescript/tree/713-compile-case-to-switch

With this patch applied, case expressions are compiled to switch + some extra bits when all tests are numbers or strings, otherwise old logic is used.

For example, {{(fn [] (let [x 1] (case x 1 :foo (2 3) :bar :quux)))}} gets compiled to

function () {
    var x = 1;
    var G__6469 = x;
    var caseval__6470;
    switch (G__6469) {
      case 1:
        caseval__6470 = new cljs.core.Keyword(null, "foo", "foo", 1014005816);
        break;
      case 2:
      case 3:
        caseval__6470 = new cljs.core.Keyword(null, "bar", "bar", 1014001541);
        break;
      default:
        caseval__6470 = new cljs.core.Keyword(null, "quux", "quux", 1017386809);
    }
    return caseval__6470;
}

The existing test suite passes, but I suppose it wouldn't hurt to add some tests with case in all possible contexts.

Comment by Michał Marczyk [ 18/Feb/14 6:05 PM ]

As a next step, I was planning to arrange things so that numbers/strings are fished out from among the tests and compiled to switch always, with any leftover tests put in an old-style nested-ifs-based case under default:. Does this sound good?

It seems to me that to deal with symbols and keywords in a similar manner we'd have to do one of two things:

1. check symbol? and keyword? at the top, then compile separate switches (the one for keywords would extract the name from the given keyword and use strings in the switch);

2. use hashes for dispatch.

Which one sounds better? Or is there a third way?

Comment by Michał Marczyk [ 18/Feb/14 6:11 PM ]

Of course we'd need to compute hashes statically to go with 2. I'd kind of like it if it were impossible (randomized seed / universal hashing), but currently it isn't.

Comment by Francis Avila [ 19/Feb/14 12:22 AM ]

At least on v8, there are surprisingly few cases where a switch statement will be optimized to a jump table. Basically the type of the switched-over value must always (across calls) match the type of every case, and there must be fewer than 128 cases, and integer cases must be 31-bit ints (v8's smi type). So mixing string and number cases in the same switch guarantees the statement will never be compiled. In many cases an equivalent if-else will end up being significantly faster on v8 just because the optimizing jit recognizes them better. There's an oldish bug filed against v8 switch performance. Looking at the many jsperfs of switch statements, it doesn't seem that v8 has improved. Relevant jsperf

Firefox is much better at optimizing switch statements (maybe because of their asm.js/emscripten work) but I don't know what conditions trigger (de)optimization.

I suspect the best approach is probably going to be your option one: if-else dispatch on type if any case is not a number, and then a switch statement covering the values for each of the keyword/string/symbol types present (no nested switch statements, and outlining the nested switches might be necessary). Even with a good hash, to guarantee v8 optimizing-compilation you would need to truncate the hashes into an smi (signed-left-shift once?) inside the case*.

Comment by David Nolen [ 19/Feb/14 12:50 AM ]

There's no need for invention here. We should follow the strategy that Clojure adopts - compile time hash calculation.

Comment by Francis Avila [ 19/Feb/14 3:09 PM ]

The problem, as Michal alluded to, is that the hash functions in cljs's runtime environment are not available at compile-time (unlike in Clojure). This might be a good opportunity to clean up that situation or even use identical hash values across Clojure and Clojurescript (i.e. CLJS-754), but that's a much bigger project. Especially considering it will probably not bring much of a speedup over an if-else-if implementation except in very narrow circumstances.

Comment by David Nolen [ 19/Feb/14 4:38 PM ]

Francis Avila I would make no such assumptions about performance without benchmarks. One of the critical uses for case is over keywords. Keyword hashes are computed at compile time, so that's one function call and a jump on some JavaScript engines. This is particularly useful for the performance of records where you want to lookup a field via keyword before checking the extension map.

This ticket should probably wait for CLJS-754 before proceeding.

Comment by Francis Avila [ 22/Feb/14 4:44 AM ]

Record field lookup is a good narrow use case to test. I put together a jsperf to compare if-else (current) vs switch with string cases vs switch with int cases (i.e., hash-compares, assuming perfect hashing).

Comment by David Nolen [ 10/May/14 3:59 PM ]

I've merged the case* analyzer and emitter bits by hand into master.

Comment by David Nolen [ 10/May/14 4:42 PM ]

I'v merged the rest of the patch into master. If any further optimizations are done it will be around dispatching on hash code a la Clojure.

Comment by Francis Avila [ 11/May/14 12:53 AM ]

Your keyword-test optimization has a bug: https://github.com/clojure/clojurescript/commit/9872788b3caa86f639633ff14dc0db49f16d3e2a

Test case:

(let [x "a"] (case x :a 1 "a"))
;=> 1
;;; Should be "a"

Github comment suggests two possible fixes.

Comment by David Nolen [ 11/May/14 10:50 AM ]

Thanks fix in master.

Comment by Christoffer Sawicki [ 23/Jun/14 3:41 PM ]

case over "chars" is currently not being optimized to switch (in other words: (case c (\a) :a :other) uses if instead of switch).

Given that ClojureScript chars are just strings of length 1, could this perhaps simply be fixed by tweaking https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/core.clj#L1187 ?

Comment by Christoffer Sawicki [ 23/Jun/14 4:11 PM ]

OK, I couldn't resist trying and it seems to be that easy. Would be great if somebody more knowledgeable could look at it and say if it has any side-effects. (See patch with name 0001-CLJS-713-Allow-test-expressions-for-case-to-be-chars.patch.)

Comment by David Nolen [ 23/Jun/14 4:15 PM ]

The patch looks good I would have applied it if I hadn't already gone and done it master myself just now

Comment by Christoffer Sawicki [ 23/Jun/14 4:22 PM ]

Hehe. Thanks! Don't forget to update the "case* tests must be numbers or strings" message on line 496 too.

Comment by David Nolen [ 23/Jun/14 4:48 PM ]

The existing docstring is inaccurate - case supports all compile time literals.

Comment by David Nolen [ 22/Dec/15 4:59 PM ]

There are quite a few optimization in master now.





[CLJS-1075] Generic inline source map support Created: 02/Mar/15  Updated: 22/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Currently hard coded to REPLs. Would simplify jsbin and similar integration.






[CLJS-1444] Node.js shim requires `node` invocation to be in the same directory as shim script Created: 10/Sep/15  Updated: 22/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Martin Klepsch Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Don't have time to provide a proper repro now but the basic issue can be illustrated by this:

~/c/boot-cljs-example (master=) node target/main.js
module.js:338
    throw err;
          ^
Error: Cannot find module '/Users/martin/code/boot-cljs-example/out/goog/bootstrap/nodejs.js'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:278:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/martin/code/boot-cljs-example/target/main.js:6:1)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
~/c/boot-cljs-example (master=) cd target/
~/c/b/target (master=) node main.js
Starting...

This is compiled with boot because that was what I had at hand right now. The compiled shim looks like this:

var path = require("path");
try {
    require("source-map-support").install();
} catch(err) {
}
require(path.join(path.resolve("."),"out","goog","bootstrap","nodejs.js"));
require(path.join(path.resolve("."),"out","cljs_deps.js"));
goog.global.CLOSURE_UNCOMPILED_DEFINES = {"cljs.core._STAR_target_STAR_":"nodejs"};
goog.require("boot.cljs.main");
goog.require("cljs.nodejscli");

The problem here is that path.resolve(".") will return the directory the node command was invoked in and not the directory of the shim. (See the "Cannot find module..." error above)

A solution could be to use __dirname which always resolves to the directory of the current file. This might result in some breakage for existing setups.



 Comments   
Comment by Sebastian Bensusan [ 14/Oct/15 11:31 AM ]

I have a proposed solution but I fear that supporting "run from anywhere" adds essential complexity to the resulting code. My thought process:

1. Relative paths are desirable to produce "context free code." If the user chooses absolute paths, then that behavior is respected and there's nothing to handle (no "path algebra") .

2. When dealing with relative paths, the whole system needs to establish a "frame of reference", a root path. The ClojureScript compiler assumes the path from which it is compiling to be that frame of reference, which usually coincides with the top root of the project. Though arbitrary, it is the only choice that makes sense.

3. The frame of reference is not explicit anywhere in the code, since it is defined as ".". If it were explicit, it would reveal context, as in "/home/some-user/their-folder/this-project/".

4. When we approach the code from another reference point (executing the script from another directory), we first need to find the original compiler path (reference point,) and then resolve all paths from there. The compiler uses `cljs.closure/path-relative-to` for this purpose.

Path algebra:
compiler-path = __dirname - output-to

Node.js

var compiler-path = __dirname.replace(output-to, "")
path.resolve (compiler-path, output-dir, "goog", "base.js")
path.resolve (compiler-path, output-dir, "cljs_deps.js")

which assumes that if output-to was given relatively, then output-dir is also relative. If they are not in sync, more work needs to be done to keep them that way.

It's not up to me to decide if the extra complexity is worth the use-case. I actually hope there is a simpler solution to solve this that I'm not seeing.





[CLJS-1519] Collection invoke errors off by 1 Created: 22/Dec/15  Updated: 22/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Runtime collection invokes will report arity that is off by one. This is because we use the generic function arity dispatching logic which doesn't account for the 1st self argument.






[CLJS-1522] Self-host: Update parameters on root *load-fn* / *eval-fn* Created: 23/Dec/15  Updated: 23/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bootstrap

Attachments: Text File CLJS-1522.patch    
Patch: Code

 Description   

There are root functions set up for the dynamic vars *load-fn* and *eval-fn*, but the named parameters on those dynamic vars reflect earlier versions of the code, prior to the values being updated to being maps. This ticket asks the names to be updated in order to avoid confusing any developers that may derive meaning from the parameter names.






[CLJS-1521] Self-host: Macro namespaces cannot be aliased Created: 23/Dec/15  Updated: 24/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bootstrap

Attachments: Text File CLJS-1521-2.patch     Text File CLJS-1521.patch    
Patch: Code and Test

 Description   

If, for example, you employ code like

(ns cljs.user (:require-macros [foo.core :as foo]))

you cannot successfully invoke macros in the foo.core namespace using the alias foo.

Will supply a battery of unit tests that exercise various ways in which you can make use of macros and in those tests, the ones involving alias will fail without the patch.



 Comments   
Comment by Mike Fikes [ 23/Dec/15 9:25 PM ]

Attached patch fixes things so you can use namespace aliases when invoking macros in bootstrapped ClojureScript.

Comment by Andrea Richiardi [ 23/Dec/15 9:53 PM ]

I will try it in replumb for issue 108.

Comment by Mike Fikes [ 24/Dec/15 8:26 AM ]

CLJS-1521-2.patch contains the same content as CLJS-1521.patch but moves a form so it can be applied with the patch in CLJS-1515.

Comment by Andrea Richiardi [ 24/Dec/15 7:18 PM ]

I applied the patch locally with replumb and I reciprocate the LGTM (while before it was failing).

...:~/git/replumb (cljs-1.7.202 $=)$ rlwrap lein node-repl
...
cljs.user=> (ns my.namespace (:require-macros [foo.bar.baz :as f]))
nil
my.namespace=> (f/mul-baz 10 20)
200




[CLJS-1536] REPL def symbol init collision Created: 03/Jan/16  Updated: 04/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

In a REPL, if you try def where the init is a local matching the symbol being defined, then analysis fails.

(let [x 1]
  (def x x))

This can be verified in script/noderepljs and you can see it is some bad interaction with REPL var emission because if :def-emits-var false is added to the script, things work.



 Comments   
Comment by Txus Bach [ 04/Jan/16 3:01 PM ]

Confirmed that evaluating this breaks:

(require 'clojure.tools.reader
         'cljs.analyzer
         'cljs.compiler)

(let [env '{:ns {:name cljs.user}
            :def-emits-var true
            :locals {}}]
  (->> "(let [x 1] (def x 3))"
       clojure.tools.reader/read-string
       (cljs.analyzer/analyze env)
       cljs.compiler/emit-str))

(When emitting, not when just analyzing.)

Removing `:def-emits-var true` makes the bug disappear.

Looking into how to fix it – any clues are welcome, it's my first time around the codebase

Comment by Txus Bach [ 04/Jan/16 3:45 PM ]

Seems that var-ast is returning nil, because resolve-var doesn't return a map with an :ns key. Not sure if this code should work, but it returns nil:

(let [env {:ns {:name 'cljs.user},
 :def-emits-var true,
 :locals
 {'x
  {:init
   {:op :constant,
    :env
    {:ns {:name 'cljs.user},
     :def-emits-var true,
     :locals {},
     :line nil,
     :column nil,
     :context :expr},
    :form 1,
    :tag 'number},
   :name 'x,
   :binding-form? true,
   :op :var,
   :env {:line nil, :column nil},
   :column nil,
   :line nil,
   :info {:name 'x, :shadow nil},
   :tag 'number,
   :shadow nil,
   :local true}}}]
  (ana/resolve-var env 'x))

Will continue tomorrow. It's so much fun!





[CLJS-575] cljsc.bat emit FileNotFoundException when compile samples in windows Created: 25/Aug/13  Updated: 05/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Park Sang Kyu Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: Compiler, bug, patch
Environment:

in windows 7


Attachments: File cljsc.bat.diff     File cljsc-path.bat    
Patch: Code

 Description   

cljsc.bat emit FileNotFoundException when it compile samples of the ClojureScript project in windows like below.

------------------------------------------------
Exception in thread "main" java.io.FileNotFoundException: Could not locate cljs/closure__init.class
or cljs/closure.clj on classpath:
------------------------------------------------

It is caused by lack of a backslash in the end of path of the system environment variable, %CLOJURESCRIPT_HOME% set by a user.
In the case CLASSPATH is set to "C:\\clojure\clojurescriptsrc\clj;C:\\clojure\clojurescriptsrc\cljs" and this make it impossible for javac to find cljs/clojure.clj file.

So it can be solved by adding a backslash to the path of %CLOJURESCRIPT_HOME%.

I attached the patched file, "cljsc-path.bat"



 Comments   
Comment by David Nolen [ 04/Sep/13 11:04 PM ]

Can we please get a proper git diff thanks (and please send in your CA)! Also would be nice to get Windows users to check this out.

Comment by Park Sang Kyu [ 15/Sep/13 3:16 AM ]

git diff

Comment by David Nolen [ 05/Oct/13 11:55 AM ]

Thank you! Have you sent in your CA? http://clojure.org/contributing

Comment by Park Sang Kyu [ 19/Jun/14 10:24 AM ]

Yes i have sent my CA.

Comment by David Nolen [ 19/Jun/14 10:27 AM ]

Excellent, the patch is not correctly formatted. Can we get a new patch that conforms to http://github.com/clojure/clojurescript/wiki/Patches





[CLJS-404] Automate Browser REPL testing Created: 23/Oct/12  Updated: 05/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

It's worth investigating Selenium, PhantomJS, etc. as solutions to sanity check the Browser REPL when we run the other tests.



 Comments   
Comment by Robert Krahn [ 22/Dec/14 1:22 PM ]

An attempt: https://github.com/clojure/clojurescript/pull/42

Comment by David Nolen [ 24/Dec/14 8:57 AM ]

This looks like an interesting patch, thanks!

Comment by Robert Krahn [ 26/Dec/14 10:57 AM ]

I'll post a patch here, first I'll investigate the load-file issue, though.





[CLJS-981] Better benchmarking infrastructure Created: 17/Jan/15  Updated: 05/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

We should use ProcessBuilder to run the various benchmark scripts and control which benchmarks we test and which engines we run. Benchmarks should produce EDN data that can be written to a file, loaded into Incanter, etc.






[CLJS-374] satisfies? produces strange code when the protocol is not in the fast-path list Created: 06/Sep/12  Updated: 05/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: David Nolen Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None





[CLJS-1543] Support Closure libs using goog.module Created: 12/Jan/16  Updated: 13/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Juho Teperi Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

goog.module is a new way to define Closure namespaces: https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide

It is used for example in https://github.com/google/incremental-dom

I didn't do full check of how Closure libraries are handled, but one function which is definitely used by cljs.closure is cljs.js-deps/find-classpath-lib which calls cljs.js-deps/parse-js-ns to read a JS file and parse module information from it. Currently the function reads lines before first function declaration and uses a regex to find goog.provide and goog.require calls. Probably Closure Compiler has some built-in functionality to parse files which could be leveraged.

Besides reading module information from files, another question is if using goog.module defined namespaces for traditional/legacy namespaces generated by ClojureScript compiler needs something special. When goog.module is required, goog.require returns the exported object but no global is set. There is however a function to create the globals: https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide#how-do-i-use-a-googmodule-from-a-traditional-closure-file

Notes:

  • Can we still assume that goog.requires all occur before first function declaration?
    • Would be fixed by using possible Closure Compiler functionality
    • Class com.google.javascript.jscomp.deps.JsFileParser looks promising
  • "GCL hasn't switched to it so it may be something driven by some users not something that Google uses more broadly" (David at slack)





[CLJS-1548] cannot reference a JS global var with same name as current namespace Created: 19/Jan/16  Updated: 19/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Shaun LeBron Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Steps to reproduce:

1. Create a JS global var `foo`.
2. Create a `foo.core` namespace.
3. Try referencing `js/foo` in `foo.core`.

Problem:

`js/foo` does not resolve to the JS global var `foo`
(in advanced optimizations, but not w/ optimizations off).

Solution: Proposing we issue a warning.

Will put together a diagnostic project soon and see about working on a patch.






[CLJS-1492] Warn when using :optimisations instead of :optimizations Created: 24/Nov/15  Updated: 29/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Daniel Compton Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Coming from British English, it is easy to accidentally type the Anglicised :optimisations, instead of the American english :optimizations. Would it be ok to add a warning when users pass in :optimisations to use :optimizations instead?



 Comments   
Comment by Mike Fikes [ 29/Jan/16 8:26 PM ]

Perhaps if we maintained a collection of all known compiler and REPL option keys somewhere in the code, we could warn (and even suggest a correction) if an unknown key is passed with a small Levenshtein distance from a known key.





[CLJS-1411] make-array signature differs from clojure Created: 10/Aug/15  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.48
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Lars Andersen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: newbie

Attachments: Text File CLJS-1411.patch    
Patch: Code

 Description   

When I was porting clj code using a two-dimensional array I noticed the cljs version only accepts size, instead of dim & more-dims.

Signature in cljs: ([size] [type size])
signature int clj: ([type len] [type dim & more-dims])



 Comments   
Comment by David Nolen [ 10/Aug/15 7:28 AM ]

Unlike on the JVM there's no efficient way to allocate multi-dimensional arrays. An enhancement patch that includes a modification to the docstring that warns about the computational cost is welcome.

Comment by Lars Andersen [ 10/Aug/15 8:00 AM ]

What I want is for the signatures to be the same, so I don't have to use reader conditionals to get the same behavior on the two platforms.

When I'm asking for a two-dimensional array, I'm presumably going to do work that is O(m*n), so even though the pre-allocation is O(m*n) too it won't affect the runtime of the program significantly.

Comment by David Nolen [ 10/Aug/15 8:13 AM ]

Lars, yes I understood As I said patch welcome. This is a very ClojureScript newbie friendly ticket.

Comment by António Nuno Monteiro [ 19/Oct/15 12:30 PM ]

Submitted patch with suggested changes

Comment by Erik Assum [ 26/Nov/15 11:27 AM ]

@Antonio: Out of curiosity, isn't the "will run in polynomial time" a bit unprecise, since I guess all array-allocations run in polynomial time?

Comment by António Nuno Monteiro [ 03/Dec/15 5:46 AM ]

You're right. I misunderstood what David mentioned regarding the JVM performance. should it just say "Note that there is no efficient way to allocate multi-dimensional arrays in JavaScript" and stop there?

Comment by Mike Fikes [ 31/Jan/16 9:51 AM ]

This patch fails for me if I try using it with make-array in operator position. In fact, there's an underlying issue CLJS-1555 that probably needs to be fixed first, and then a patch could be made that takes care of the extra arity in the macro version of make-array as well.





[CLJS-1059] Simple interface wanted to convert cljs forms to js Created: 22/Feb/15  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3211
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Stuart Mitchell Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: analyzer, compiler


 Description   

In our project (a clojurescript debugger) we want to convert cljs forms or a sequence of forms into javascript so that they can be executed in the javascript console.

We would like something similar to closure/compile-form-seq (https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/closure.clj#L308)

However, we need to supply, the namespace requires and locals in an env like this

{:ns {:name "test.core" :requires {(quote gstring) (quote goog.string)}} :locals {}}

This code seems to do what we want.

(defn compile-form-seq
    \"Compile a sequence of forms to a JavaScript source string.\"
    [forms env]
    (env/ensure
    (compiler/with-core-cljs nil
      (fn []
        (with-out-str
            (doseq [form forms]
              (compiler/emit (analyzer/analyze env form))))))))

I am not sure why I need env/ensure.

Would you be able to patch compile-form-seq to provide the needed interface, or suggest what we should be doing.

Thanks
Stu



 Comments   
Comment by Mike Thompson [ 22/Feb/15 10:09 PM ]

Just to be clear:
1. when our debugger is at a breakpoint,
2. the user can type in an expression at the repl
3. in response, our debugger has to compile the user-typed-in expression to javascript (and then execute it, showing a result)
4. taking into account any local bindings. <---- this is the key bit.

To satisfy point 4, our tool extracts all the 'locals' from the current call-frame, and then supplies all these local bindings in env/locals, so the compiler doesn't stick a namespace on the front of them.

For example, if there was a local binding for 'x' in the callstack, and the user's repl-entered-expression involves 'x', then we want the compiler to leave the symbol 'x' alone and to not put some namespace on the front of it. In the final javascript, it must still be 'x', not 'some.namespace.x'

Our method to achieve this is to put 'x' into env/locals when compiling – and it all works. Except, with the recent changes this has become more of a challenge. Hence this ticket asking for a way to pass in env.

Comment by Thomas Heller [ 23/Feb/15 3:19 AM ]

You could wrap the user expression in an fn, that would allow you to skip messing with the locals. The REPL basically does the same trick for *1,*2,...

(fn [x]
  ~user-expression-here)
Comment by David Nolen [ 29/Apr/15 7:21 AM ]

Seems like something useful to add to a cljs.compiler.api namespace.





[CLJS-1164] quot and rem are inefficient Created: 24/Mar/15  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Francis Avila Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: math

Attachments: Text File cljs-1164.patch    
Patch: Code and Test

 Description   

The implementation of the quot and rem functions are needlessly complicated. Currently they are:

(defn quot [n d] (fix (/ (- n (js-mod n d)) d)))
(defn rem [n d] (- n (* d (quot n d))))

However all numbers in js are doubles already, so all this is unnecessary:

(defn quot [n d] (fix (/ n d)))
(defn rem [n d] (js-mod n d)))

Notice that "rem" is simply js-mod, and I'm not sure why no one noticed this before. I keep js-mod for now since a lot of code uses it, and if cljs ever grows a number tower the distinction may be important.

Patch attached, which also:

  • Creates a macro version of quot and rem.
  • Updates documentation for quot, rem, js-mod and mod for clarity.
  • Implement fix (private function to round to zero) with ES6 Math.trunc() if available.

Existing quot and rem tests pass, although there could be some better tests of edge cases (negative decimal num or div, NaN and +-Infinity args).



 Comments   
Comment by Francis Avila [ 24/Mar/15 12:27 PM ]

Better tests found rounding errors in my updated rem, which should stay as-is. (Not simply js-mod after all! Seems to round args first? Not obvious from the spec.) Changed quot however is correct and introduces less error than the current one. Will update patch and tests when I get a chance.

Comment by Francis Avila [ 29/Mar/15 12:39 AM ]

Working patch with tests attached. Tests expanded to cover floating-point cases. rem is now fundamentally the same as master (was more accurate than js-mod!!), but returns results consistent with js-mod for non-finite args or zero divisor.

Comment by Mike Fikes [ 31/Jan/16 3:23 PM ]

cljs-1164.patch no longer applies on master





[CLJS-651] optimize true branch of satisfies? usage Created: 01/Nov/13  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs_651.patch    
Patch: Code

 Description   

The true branch of a satisfies? test should be hinted so that the type doesn't need type hints



 Comments   
Comment by Peter Schuck [ 16/Dec/14 2:51 PM ]

All paths taken on satisfies are now hinted as boolean

Comment by Mike Fikes [ 31/Jan/16 3:26 PM ]

cljs_651.patch no longer applies on master





[CLJS-1458] re-matches might give false negative when using match groups Created: 25/Sep/15  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Nikita Prokopov Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs-1458-re-matches-might-give-false-negative.patch    
Patch: Code and Test

 Description   

Current behaviour:

(re-matches #"(a|aa)" "aa") => nil

Expected:

(re-matches #"(a|aa)" "aa") => ["aa" "aa"]

JVM version works as expected, only CLJS is affected



 Comments   
Comment by David Nolen [ 14/Oct/15 11:36 AM ]

This is the kind of ticket that tends to break existing code. We should get some people who are interested in this ticket to actually try it out.

Comment by Mike Fikes [ 31/Jan/16 3:45 PM ]

FWIW, I gave cljs-1458-re-matches-might-give-false-negative.patch a try in bootstrapped ClojureScript and it is working fine there (each of the additional unit tests produce the expected results in bootstrapped).





[CLJS-1556] Invalid code emit for obj literal Created: 31/Jan/16  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.228
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1556.patch    
Patch: Code and Test

 Description   

For some legal ClojureScript expressions involving #js object literals, invalid JavaScript is emitted. Specifically this has to do with object literals appearing at the beginning of statements where the opening brace can be interpreted as the beginning of a JavaScript block.

One way to reproduce this is to evaluate

(do #js {:a 1} 
    #js {:b 2})

in the Node REPL. In this case it is the first object literal that causes the problem; the second one emitted follows a return statement and is OK.

Rationale for marking it as minor: This appears to only really occur in places where the object literal won't actually be used.






[CLJS-1241] Add cljs.core/boolean? predicate Created: 03/May/15  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Brandon Bloom Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: patch

Attachments: Text File CLJS-1241_v01.patch    
Patch: Code and Test

 Description   

I'm constantly re-implementing this predicate...

It's also important for clj/cljs compatibility.



 Comments   
Comment by Brandon Bloom [ 03/May/15 2:32 PM ]

See also: http://dev.clojure.org/jira/browse/CLJ-1719

Comment by Mike Fikes [ 03/May/15 2:52 PM ]

I tried this patch and it works correctly for me.

The docstring uses "typeof". Perhaps "type of" was intended?

cljs.user=> (doc boolean?)
-------------------------
cljs.core/boolean?
([x])
  Returns true if the typeof x is boolean, false otherwise.

nil
Comment by Brandon Bloom [ 03/May/15 7:41 PM ]

I did mean "typeof", which is a javascript-ism. A better doc string may be less javascript-specific...

Comment by Mike Fikes [ 31/Jan/16 3:17 PM ]

Patch CLJS-1241_v01.patch no longer applies on master.

Comment by Brandon Bloom [ 31/Jan/16 7:13 PM ]

Not going to bother updating patch until there is movement on http://dev.clojure.org/jira/browse/CLJ-1719





[CLJS-1553] browser repl "EOF while reading string" when evaluating symbol "enable-console-print!" Created: 28/Jan/16  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.228
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Scott Bale Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: repl
Environment:

On client side: Chrome browser (47.0.2526.111) On Mac OS 10.10.5 Yosemite

On server side:

  • Amazon EC2 instance running amazon linux

java -version
openjdk version "1.8.0_65"
OpenJDK Runtime Environment (build 1.8.0_65-b17)
OpenJDK 64-Bit Server VM (build 25.65-b01, mixed mode)


Attachments: GZip Archive cljs-hello-world.tar.gz    

 Description   

Just playing around in the browser repl, running through the CLJS quickstart, I happened upon this. I crashed the repl by attempting to evaluate enable-console-print!.

Below is output of my repl. As you can see, I can doc, source, or even invoke the function, but if I try to simply evaluate the symbol, the repl crashes with a Java runtime exception. (I was expecting the repl to output a toString representation of the enable-console-print! function object, as it would for any other symbol that resolves to a function.)

I've attached a .tar.gz file of my project, but I excluded the cljs.jar file from the root. (The IP address in core.cljs is the public IP address of the ec2 instance I was using.)

The command I used to start the repl is:

java -cp cljs.jar:src clojure.main repl.clj

REPL output:

cljs.user=> (doc enable-console-print!)
-------------------------
cljs.core/enable-console-print!
([])
  Set *print-fn* to console.log
nil
cljs.user=> (source enable-console-print!)
(defn enable-console-print!
  "Set *print-fn* to console.log"
  []
  (set! *print-newline* false)
  (set! *print-fn*
    (fn [& args]
      (.apply (.-log js/console) js/console (into-array args))))
  (set! *print-err-fn*
    (fn [& args]
      (.apply (.-error js/console) js/console (into-array args))))
  nil)
nil
cljs.user=> (enable-console-print!)
nil
cljs.user=> enable-console-print!
Exception in thread "Thread-138" java.lang.RuntimeException: EOF while reading string
        at clojure.lang.Util.runtimeException(Util.java:221)
        at clojure.lang.LispReader$StringReader.invoke(LispReader.java:525)
        at clojure.lang.LispReader.read(LispReader.java:263)
        at clojure.lang.LispReader.readDelimitedList(LispReader.java:1200)
        at clojure.lang.LispReader$MapReader.invoke(LispReader.java:1158)
        at clojure.lang.LispReader.read(LispReader.java:263)
        at clojure.lang.LispReader.read(LispReader.java:196)
        at clojure.lang.LispReader.read(LispReader.java:185)
        at clojure.lang.RT.readString(RT.java:1821)
        at clojure.lang.RT.readString(RT.java:1816)
        at clojure.core$read_string.invoke(core.clj:3663)
        at cljs.repl.server$dispatch_request.invoke(server.clj:148)
        at cljs.repl.server$handle_connection.invoke(server.clj:157)
        at cljs.repl.server$server_loop$fn__5056.invoke(server.clj:167)
        at clojure.core$binding_conveyor_fn$fn__4444.invoke(core.clj:1916)
        at clojure.lang.AFn.run(AFn.java:22)
        at java.lang.Thread.run(Thread.java:745)


 Comments   
Comment by Mike Fikes [ 31/Jan/16 8:34 PM ]

I tried reproducing with the attached cljs-hello-world.tar.gz, revising the IP address to be localhost, and running everything on my local Mac with Chrome 48.0.2564.97, and I was unable to repro.

Perhaps, since this involved a network connection between AWS and your local Mac, the connection was closed during the phase when it was reading the response? In other words, I wonder if this is reproducible in general or was just a connectivity outage.





[CLJS-1518] Case macro expansion evaluates expression twice Created: 21/Dec/15  Updated: 31/Jan/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145, 1.7.228
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Darrick Wiebe Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None
Environment:

The issue is present in version 1.7.189.


Attachments: Text File CLJS-1518.patch    
Patch: Code and Test

 Description   

The value being checked is evaluated twice if all of the test values are keywords.

(macroexpand-1 '(case (expensive) :a 1 2))
(cljs.core/let [G__123555 (if (cljs.core/keyword? (expensive)) (.-fqn (expensive)) nil)]
  (case* G__123555 [["a"]] [1] 2))


 Comments   
Comment by Mike Fikes [ 31/Jan/16 11:38 PM ]

Patch takes advantage of the existing gensym as a temp place to stash the evaluated value before test / FQN conversion.

Adds a unit test specifically checking for single evaluation in this case.

Comment by Mike Fikes [ 31/Jan/16 11:40 PM ]

With the patch, Darrick's macroexpansion example becomes:

(cljs.core/let [G__7663 (expensive) 
                G__7663 (if (cljs.core/keyword? G__7663) (.-fqn G__7663) nil)] 
  (case* G__7663 [["a"]] [1] 2))




[CLJS-1523] Expose an undocumented Closure compiler DiagnosticGroup Created: 24/Dec/15  Updated: 05/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Rohit Aggarwal Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1523-1.patch    
Patch: Code

 Description   

Following the tutorial on (Compile Time Type checking wiki)https://github.com/clojure/clojurescript/wiki/Compile-Time-Type-Checking, I noticed that the compiler is producing a lot of warning and errors by default such as:

```
ERROR: JSC_WRONG_ARGUMENT_COUNT. Function cljs.core.array_seq: called with 2 argument(s). Function requires at least 1 argument(s) and no more than 1 argument(s). at ..../hello_world/out/cljs/core.js line 17738 : 186
```

These errors and warnings can be disabled by turning off an undocumented DiagosticGroup: (LINT_CHECKS)https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/DiagnosticGroups.java#L465



 Comments   
Comment by David Nolen [ 04/Feb/16 4:03 PM ]

This patch looks ok, Rohit have you submitted your CA? Thanks.

Comment by Rohit Aggarwal [ 05/Feb/16 2:52 AM ]

Hi David,
I've signed the Clojure CA and my name is listed here. Thanks a lot!

Comment by Mike Fikes [ 05/Feb/16 11:19 AM ]

I tried validating the patch, but I cannot reproduce the problem in the description, even with 1.7.170.

Comment by Rohit Aggarwal [ 05/Feb/16 11:27 AM ]

Hi Mike,
I just created a project using the mies template and changed the release.clj file to:

(require '[cljs.build.api :as b])

(println "Building ...")

(let [start (System/nanoTime)]
  (b/build "src"
    {:output-to "release/hello_world.js"
     :output-dir "release"
     :optimizations :advanced
     :closure-warnings {:check-types :error}
     :verbose true})
  (println "... done. Elapsed" (/ (- (System/nanoTime) start) 1e9) "seconds"))

Now when I do

scripts/release

I get warning like:

ERROR: JSC_WRONG_ARGUMENT_COUNT. Function cljs.core.println: called with 0 argument(s). Function requires at least 1 argument(s) and no more than 1 argument(s). at .../hello-world/release/cljs/repl.js line 174 : 0
Comment by Mike Fikes [ 05/Feb/16 11:57 AM ]

Thanks Rohit,

I get errors for a lein new mies hello-world project, but they are different than the one you quote above.

I do get two JSC_WRONG_ARGUMENT_COUNT diagnostics:

ERROR: JSC_WRONG_ARGUMENT_COUNT. Function goog.net.WebSocket.prototype.isOpen: called with 1 argument(s). Function requires at least 0 argument(s) and no more than 0 argument(s). at /Users/mfikes/Desktop/foobar/hello-world/release/clojure/browser/net.js line 591 : 7
ERROR: JSC_WRONG_ARGUMENT_COUNT. Function goog.net.WebSocket.prototype.close: called with 1 argument(s). Function requires at least 0 argument(s) and no more than 0 argument(s). at /Users/mfikes/Desktop/foobar/hello-world/release/clojure/browser/net.js line 613 : 7

Then when revising the project to use the compiler built with the attached patch, I tried adding

:lint-checks :off

to the :closure-warnings map, but this doesn't make these go away.

Hrm... I wonder what explains the difference.

Comment by Rohit Aggarwal [ 05/Feb/16 12:24 PM ]

Mike,
You are correct about the warning with the patch.

:lint-checks :off

But I see that the number of errors is greatly reduced for me.

If it helps, I am using OS X 10.11.4 and Java 1.8.0_71

Comment by Mike Fikes [ 05/Feb/16 12:49 PM ]

I'm seeing no effect with :lint-checks :off.

I'm on OS X 10.11.3 with Java 1.8.0_72, and I'm trying this against the current master of the ClojureScript tree.





[CLJS-1559] Closure :libs ignored Created: 05/Feb/16  Updated: 05/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.228
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Dominykas Mostauskis Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

:libs compilation option doesn't work. Whether specifying directories, or specific files. If trying to `import` one of the js classes (properly namespaced with `goog.provide`) into clojurescript, compilation fails with "no such namespace". If the libs code is not referenced in clojurescript, it compiles, and the output directory does not contain the libs js files.

Compilation options:

(cljs.closure/build
    "src/main/clojurescript"
    {:main 'example.core
     :libs ["/src/main/javascript/"]
     :optimizations :none
     :output-dir "js"
     :output-to "js/main.js"
     :source-map true
     :asset-path "/js"
     })

Javascript file:

goog.provide("test.Test");

test.Test = function(x) {
  this.x = x;
};


 Comments   
Comment by Mike Fikes [ 05/Feb/16 1:51 PM ]

Hi Dominykas, is the absolute path intentional? I suspect the intent was to not have the leading /.

Comment by Dominykas Mostauskis [ 05/Feb/16 2:01 PM ]

I made this typo when posting. On my setup paths are relative to project root.

Comment by David Nolen [ 05/Feb/16 2:38 PM ]

As far as I know quite a few people rely on this functionality. Please provide a complete minimal example or this issue will be closed. All source should be in the ticket or in this comment thread, no external links. Thanks.

Comment by Dominykas Mostauskis [ 05/Feb/16 3:50 PM ]

Can't reproduce. Tips would be appreciated. Banging my head against the wall here.





[CLJS-1540] Arity-1 version of js->clj should pass keyword arguments for default options, as expected by js->clj Created: 07/Jan/16  Updated: 04/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Nicolás Berger Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File js-clj-keyword-opts.patch    
Patch: Code

 Description   

Arity-1 version of js->clj is passing the map {:keywordize-keys false} as the default options of js->clj, when it should pass the keyword arguments :keywordize-keys false. It's working by luck, because keywordize-keys ends being nil by default, which is falsey. But it's confusing for anyone reading the code and trying to pass {:keywordize-keys true} with the expectation that it would keywordize the keys.

References: http://dev.clojure.org/jira/browse/CLJS-750 and https://groups.google.com/forum/#!topic/clojurescript/Dis6845WL5U



 Comments   
Comment by Mike Fikes [ 29/Jan/16 7:59 PM ]
Comment by David Nolen [ 04/Feb/16 4:05 PM ]

Patch looks OK, Nicolas have you submitted your CA? Thanks.

Comment by Nicolás Berger [ 04/Feb/16 5:00 PM ]

Yes I did, David





[CLJS-1515] Self-host: Allow :file key in cljs.js/*load-fn* callback Created: 17/Dec/15  Updated: 05/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bootstrap

Attachments: Text File CLJS-1515-1.patch     Text File CLJS-1515-2.patch     Text File CLJS-1515-3.patch     Text File CLJS-1515-4.patch     Text File CLJS-1515-5.patch    
Patch: Code and Test

 Description   

Bootstrapped ClojureScript is abstracted away from direct I/O by use of a *load-fn* callback. A result is that when a namespace is loaded, the :file attribute associated with def s in [:cljs.analyzer/namespaces 'foo.ns :defs] in the AST is nil, because cljs.analyzer/*cljs-file* cannot be set to a meaningful value.

This ticket asks for an extension to *load-fn*, allowing a :file key to be optionally included by cljs.js clients, and for cljs.analyzer/*cljs-file* to be bound to that value in appropriate places in cljs.js so that the :file info appears in the AST.

One rationale for this :file attribute is that it makes it easier for clients of cljs.js to look up the file for a def, say, for use when implementing a source REPL special, for example.



 Comments   
Comment by Andrea Richiardi [ 17/Dec/15 4:31 PM ]

Initial patch, adding a :file key to load-fn and a :file-env key inside opts and then assigning it to cljs.analyzer/cljs-file in eval-str. This approach can be discussed and we can create an ad-hoc function for binding. It felt right there.
Moreover, cljs.analyzer/cljs-file gets overridden every time with the payload coming from load-fn.
All this was very quickly done in order to have a feedback from who's more expert than me about the consequences. This is also my very first ClojureScript patch

Comment by Mike Fikes [ 17/Dec/15 5:33 PM ]

I tried this patch. It is working fine for me when loading namespaces, but if I use cljs.js/analyze-str where the string is an ns form referring other namespaces loaded via *load-fn*, along with a def, things are off. (I have that ns referring macros from a clj file and a symbol from a cljs file, and the clj file gets associated with the top-level def and the macro, and the def in the referred file ends up with nil.

As a minor aside, the patch has a spurious whitespace change at the end.

Comment by Mike Fikes [ 17/Dec/15 5:56 PM ]

With respect to the last comment: The patch employs the pattern of conveying the :file passed in the cb via a :file-env opt to the consuming fn. It is consumed in eval-str* but not in analyze-str*. If the same logic is added to analyze-str* then the problem mentioned in the last comment goes away.

Comment by David Miller [ 17/Dec/15 6:48 PM ]

I'm hopeful someone will assign this to a responsible party. I am not that person.

Comment by Andrea Richiardi [ 17/Dec/15 7:21 PM ]

sorry David (Miller) and thanks Mike, I will rework it, adding some tests as well

Comment by Andrea Richiardi [ 17/Dec/15 7:23 PM ]

By the way this makes me think that maybe a better choice is to consider this a side effect and directly modify cljs.analyzer/*cljs-file* returning from *load-fn*, who knows how many other spots I am not covering...

Comment by Mike Fikes [ 18/Dec/15 5:36 AM ]

Two more comments:

1) Broadening the scope of the binding doesn't appear to work properly for me. But things do work if the bindings are done as in the patch now (next to where the other bindings are done).

2) Perhaps :file should be only set if the :lang being called back with is :clj. Maybe this could at least be documented. (It is not clear to me if it is useful for :js, as the patch is setting ana/*cljs-file*.)

Comment by Andrea Richiardi [ 18/Dec/15 10:27 AM ]

About 2), is any AST generated for .js files at all? If yes maybe then we should add it too...I need to explore that code path as well.

Comment by Andrea Richiardi [ 18/Dec/15 3:33 PM ]

So basically with ana/*cljs-file* binding the :file in :meta is not changed at all (I fixed following Mike's advice) but :file is, are we ok with this? In replumb (from planck) we check both so no problem, nonetheless it would be great to know why..

:defs {foo {:protocol-inline nil, :meta {:file bootstrap-test.core, :line 3, :column 7, :end-line 3, :end-column 10, :arglists (quote ([a b]))}, :name bootstrap-test.core/foo, :variadic false, :file /.../clojurescript/src/test/self/bootstrap_test/core.cljs, :end-column 10, :method-params ([a b]), :protocol-impl nil, :arglists-meta (nil nil), :column 1, :line 3, :end-line 3, :max-fixed-arity 2, :fn-var true, :arglists (quote ([a b]))}}, :require-macros nil, :doc nil

Comment by Andrea Richiardi [ 18/Dec/15 3:44 PM ]

It looks like the information in :meta comes directly from the multimethod parse which I dont' think we can change easily. So either we override :file in :meta or we leave as it is with a note in the documentation for :file in *load-fn*

Comment by Andrea Richiardi [ 18/Dec/15 4:10 PM ]

About :js files at least to me it looks like the only trace of importing, say, goog.sting in the AST is in the :imports of the parent namespace. No :file key anywhere, but please correct me if I am wrong as the AST is difficult to untangle

Comment by Andrea Richiardi [ 18/Dec/15 5:29 PM ]

Patch and test

Comment by Mike Fikes [ 18/Dec/15 7:43 PM ]

Comments on {{CLJS-1515-2.patch}} (mostly just opinion):

  1. (Opinion): Introduces new public API, especially with respect to AST exposure. Perhaps fn could instead be added to the test namespace.
  2. (Opinion): I wouldn't try anything complicated to try to patch up the :file that is in the :meta map. (Maybe we'll ultimately figure out why setting cljs.analyzer/*cljs-file* is insufficient for that bit.)
  3. (Opinion): For the :file docstring, I'd avoid mentioning AST. (Even though that was the true motivation for this ticket.) I'd only indicate that it represents the location where :source was obtained. (Which I guess would leave open it being perfectly fine for clients to provide it in the case that :lang is :js.)
  4. script/test-self-host passes for me.
  5. Inadvertent whitespace changes in append-source-map.
Comment by Andrea Richiardi [ 18/Dec/15 7:49 PM ]

1. Sorry Mike I don't understand when you say fn...what do you mean? Can you expand?
2. Yes and it would change a lot of code, that's why I didn't even try
3. Ok can change that, but where should be mentioned that we are modifying :file but not inside :meta?
4. Great!
5. You know I really tried hard not to have that, I will try again to disable all the auto indent my emacs has.

Comment by Mike Fikes [ 18/Dec/15 8:30 PM ]

1. The three new public functions in cljs.js: (var-ast, ns-ast, file->lang) could perhaps be moved to be utility functions in the self-host test namespace.
3. Dunno about the :meta question. But on the :lang :js question, perhaps the patch should only bind :cljs.analyzer/*cljs-file* if :lang :clj?

Comment by Andrea Richiardi [ 18/Dec/15 8:38 PM ]

1. I know it looks like they are used in test only, but I put them there as public because both replumb and planck use them and I was kind of "proposing" this kind of AST utils to be part of the official API (so that the poor dev does not have to go through cljs.analyzer in order to query the AST. I understand if no though.
3. This I don't really know, and seek guidance. I have not noticed any significant change in the AST for .js file, maybe *cljs-file* is never queried in that code path. I could not even find a way to test it. But I could, of course, be very wrong.

Comment by Andrea Richiardi [ 21/Dec/15 2:13 PM ]

This puts the utils functions in the test namespace for now, maybe thinking about exposing some API in the future.

Comment by Andrea Richiardi [ 21/Dec/15 8:19 PM ]

About :js:

  • it looks like the analyze-str code path simply recurs to fetch the next dep. So I guess that branch does not touch the AST.
  • for the require code path it looks like it -> is -> similar.

Therefore I don't see the point in adding :file for :js and I will not bind *cljs-file* if this is the case, as you suggested.

Comment by Andrea Richiardi [ 21/Dec/15 9:48 PM ]

Patch #4 changes the conveying key to :cljs-file, after Mike's good suggestion, and moves the assoc to the (condp ... :clj) branch only. I also added a test to check that *cljs-file* does not match the file path when in the :js branch.

Comment by Andrea Richiardi [ 21/Dec/15 11:56 PM ]

Another note, the *cljs-file* test works because the binding form does not actually restore the old value when it exits...In Clojure it would not probably work.

^ This is plain wrong, I was not considering the "when" my tests are executed, please disregard.

Comment by Mike Fikes [ 23/Dec/15 5:13 PM ]

CLJS-1515-4.patch LGTM.

Details: I tested against current ClojureScript master, using downstream Planck to load regular and macro namespaces and the :file portion of the AST gets properly updated. This also occurs if I instead use cljs.js/analyze-str passing in an ns form that causes code to be loaded. Additionally unit tests (regular and bootstrap) pass for me. I think this patch is functionally good to go.

Comment by David Nolen [ 26/Dec/15 6:54 AM ]

Copying goog.string into the source tree is not desirable. Please fix the tests to remove this. If you must, copy it to a temporary a location from the Google Closure Library JAR and remove it after the test has completed, thanks.

Comment by Andrea Richiardi [ 26/Dec/15 2:20 PM ]

Patch 5 avoid copying string.js and re-uses self_host/test.js.

Comment by Andrea Richiardi [ 26/Dec/15 2:22 PM ]

Done what you asked

Comment by Mike Fikes [ 05/Feb/16 8:05 PM ]

CLJS-1515-5.patch no longer applies





[CLJS-1153] Typed Array backed PersistentVector based on clojure.core/Vec Created: 19/Mar/15  Updated: 05/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Adrian Medina Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: enhancement

Attachments: Text File 1153.patch    
Patch: Code

 Description   

Goal is to add support for vectors based on clojure.core/Vec, built on top of JavaScript Typed Arrays.

My hope is that this would allow for both efficient creation of vectors from existing Typed Arrays without intermediate conversion to normal JavaScript arrays, as well as efficient concatenation of the composite arrays of the vector back into a Typed Array when necessary via an enhanced cljs.core/into-array.

Implementation is based heavily on clojure/core/gvec.clj, cljs.core/PersistentVector, and cljs.core/TransientVector.

Performance should be comparable to cljs.core/PersistentVector, although there is additional constant overhead with TypedArray instantiation compared to js/Array.

Adds cljs.core/Vec, cljs.core/TransientVec, cljs.core/vector-of, and updates cljs.core/into-array.



 Comments   
Comment by Adrian Medina [ 19/Mar/15 8:39 PM ]

I still have to test, I will update the issue when that is complete. I just wanted to get my first patch up for review as quickly as possible.

Comment by Francis Avila [ 19/Mar/15 11:59 PM ]

No mention of Uint8ClampedArray.

Should Vec type- or range-check assignments? In Clojure these fail (even with unchecked-math):

  • (vector-of :byte 128) returns [-128]
  • (vector-of :byte "1") returns [1]
  • (vector-of :byte (js-obj)) returns [0]

If we're going to expose host primitive arrays via cljs apis, should we also bring the various other array functions in line with Clojure (and ClojureCLR, which also has extra uint, ubyte, etc types) like you are doing with into-array? Some or all of these issues may warrant another ticket instead, or maybe even a design page:

  • make-array ignores type argument and lacks higher dimensions.
  • object-array, int-array, etc. maybe should return TypedArrays.
  • Missing ubyte-array, ushort-array, uint-array (like ClojureCLR)
  • Missing aset-* setters. (Meaningless in js unless we range-check.)
  • aclone and amap preserve type of input array in Clojure, but not in cljs.
  • missing array casters: bytes, shorts, chars, ints, etc.
  • While we're at it, primitive coercion functions (e.g. int, long, unchecked-int, etc) are either no-ops or differ from clojure. (e.g., int in cljs is like unchecked-int in clojure, but unchecked-int in cljs does nothing). Maybe these should be dropped or should match the javascript ToInt32, ToInt16, etc abstract operations (i.e. those used when assigning to TypedArrays). Maybe these match java semantics also?
Comment by Mike Fikes [ 05/Feb/16 8:18 PM ]

Patch 1153.patch no longer applies





[CLJS-1242] Add cljs.core/pattern? predicate Created: 03/May/15  Updated: 27/Jul/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Brandon Bloom Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: patch

Attachments: Text File CLJS-1242_v01.patch    
Patch: Code and Test

 Description   

Just like http://dev.clojure.org/jira/browse/CLJS-1241 , this helps with clj/cljs cross-platform development.



 Comments   
Comment by Brandon Bloom [ 03/May/15 2:38 PM ]

See also http://dev.clojure.org/jira/browse/CLJ-1720

Comment by Brandon Bloom [ 10/May/15 11:36 PM ]

Note that there already is a cljs.core/regexp?, since it's used in a few places by core.

Comment by Samuel Miller [ 27/Jul/15 9:27 PM ]

The patch needs to be updated because of the folder changes

Tested on Linux with V8, SpiderMonkey, and Nashorn. Repljs also functions correctly.

You could have the `pattern?` function point to the `regexp?` function. Maybe there is some reason to keep separate (ability to have non-regex patterns?)





[CLJS-1541] Self-host: Cannot require 'cljs.js using cljs.jar Created: 10/Jan/16  Updated: 06/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: bootstrap
Environment:

Affects 1.7.228 and earlier


Attachments: Text File CLJS-1541.patch    
Patch: Code

 Description   

If you use script/noderepljs you can (require 'cljs.js) but not with the shipping JAR:

$ java -jar cljs.jar -m cljs.repl.node
ClojureScript Node.js REPL server listening on 56432
To quit, type: :cljs/quit
cljs.user=> (require 'cljs.js)
WARNING: Use of undeclared Var cljs.core/defmacro at line 99 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/-> at line 99 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 105 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 105 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/->> at line 115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 120 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 120 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 120 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 121 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 121 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 131 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/.. at line 131 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 145 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/form at line 145 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 145 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/form at line 145 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/form at line 146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/form at line 146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 149 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/comment at line 149 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 151 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 151 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 154 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/cond at line 154 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 160 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 160 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 161 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 166 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 163 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 164 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 162 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 169 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/declare at line 169 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 171 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/names at line 171 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/names at line 171 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 174 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doto at line 174 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 180 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 180 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 180 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 182 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 187 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 207 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/extend-protocol at line 207 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/p at line 242 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 242 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/specs at line 242 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/p at line 243 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/specs at line 243 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 265 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fn at line 265 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 273 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sigs at line 273 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sigs at line 274 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sigs at line 274 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sigs at line 275 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sigs at line 275 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&form at line 324 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 327 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/defn- at line 327 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 329 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/decls at line 329 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/decls at line 330 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 333 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/if-let at line 333 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 338 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 338 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 339 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 339 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 340 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 340 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/else at line 340 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 340 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/oldform at line 340 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 345 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 345 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 349 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/else at line 350 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 353 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/if-not at line 353 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 356 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 356 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 356 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 356 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 357 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 357 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/else at line 357 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 358 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 358 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/else at line 358 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 361 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/letfn at line 361 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fnspecs at line 369 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 369 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 369 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fnspecs at line 370 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fnspecs at line 371 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 372 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 375 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/memfn at line 375 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 381 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/args at line 381 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/args at line 384 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/args at line 385 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 388 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/when at line 388 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 390 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 390 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 390 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 391 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 391 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 394 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/when-first at line 394 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 398 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 398 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 398 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 402 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 405 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 408 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/when-let at line 408 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 412 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 412 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 412 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 416 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 416 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 420 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 423 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/when-not at line 423 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 425 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 425 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 425 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 426 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 426 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 429 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/while at line 429 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 432 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 432 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 432 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/test at line 434 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 435 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 439 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/cond-> at line 439 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 444 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 444 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 444 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 445 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 448 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 449 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 453 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/cond->> at line 453 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 458 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 458 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 458 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 459 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 462 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 463 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 467 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/as-> at line 467 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 471 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 471 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 471 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 472 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 473 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 477 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/some-> at line 477 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 480 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 480 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 480 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 483 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 484 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 488 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/some->> at line 488 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 491 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 491 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 491 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 494 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/forms at line 495 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 499 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/if-some at line 499 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 504 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 504 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 505 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 505 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 506 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 506 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/else at line 506 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 506 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/oldform at line 506 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 511 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 511 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/else at line 514 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/then at line 516 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 519 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/when-some at line 519 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 524 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 524 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 524 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 528 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 528 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 533 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 601 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/defonce at line 601 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 601 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/init at line 601 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 602 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 603 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/init at line 603 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 605 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/assert-args at line 605 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fnname at line 605 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 605 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/pairs at line 605 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/pairs at line 612 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fnname at line 614 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/pairs at line 614 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/pairs at line 615 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fnname at line 617 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 690 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/goog-define at line 690 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sym at line 704 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 704 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/assert-args at line 705 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/goog-define at line 705 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 706 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 707 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 708 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 709 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 706 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 707 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 708 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 709 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sym at line 710 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 712 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 713 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 714 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 714 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 714 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 714 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sym at line 716 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/default at line 718 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 720 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/let at line 720 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 726 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 726 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 726 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/assert-args at line 727 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/let at line 727 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 728 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 729 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 730 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 730 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 732 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/loop at line 732 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 736 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 736 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 736 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/assert-args at line 737 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/loop at line 737 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 738 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 739 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 740 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 741 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 742 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 742 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 743 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 744 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 754 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 781 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/str at line 781 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 781 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 781 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 782 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 785 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 795 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/and at line 795 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 801 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 801 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 802 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 802 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 803 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 804 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 805 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 810 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 813 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/or at line 813 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 819 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 819 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 820 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 820 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 821 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 822 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 823 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 828 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 831 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/nil? at line 831 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 831 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 832 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 835 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/coercive-not at line 835 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 835 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 836 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 839 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/coercive-not= at line 839 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 839 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 839 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 840 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 840 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 843 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/coercive-= at line 843 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 843 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 843 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 844 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 844 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 847 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/coercive-boolean at line 847 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 847 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 848 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 852 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/truth_ at line 852 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 852 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 853 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 854 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 854 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 857 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-arguments at line 857 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 860 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-delete at line 860 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/obj at line 860 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/obj at line 861 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 863 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-in at line 863 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/obj at line 863 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/obj at line 864 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 866 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-debugger at line 866 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 871 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-comment at line 871 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/comment at line 874 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/comment at line 875 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 885 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unsafe-cast at line 885 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 887 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 887 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 888 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 889 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 889 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 891 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-inline-comment at line 891 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/comment at line 893 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/comment at line 894 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 896 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/true? at line 896 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 896 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 897 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 899 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/false? at line 899 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 899 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 900 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 902 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/string? at line 902 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 902 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 903 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 906 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/exists? at line 906 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 909 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 912 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 914 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/undefined? at line 914 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 916 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 917 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 919 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/identical? at line 919 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 919 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/b at line 919 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/b at line 920 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 920 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 922 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/instance? at line 922 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 922 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/o at line 922 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 926 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 927 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/o at line 927 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 928 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/o at line 928 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 931 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/number? at line 931 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 931 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 932 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 934 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/symbol? at line 934 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 934 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 935 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 937 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/keyword? at line 937 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 937 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 938 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 940 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/aget at line 940 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 941 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/i at line 941 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/i at line 942 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 942 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 943 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/i at line 943 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 943 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idxs at line 943 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idxs at line 944 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 945 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/i at line 945 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idxs at line 945 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 947 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/aset at line 947 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 948 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/i at line 948 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/v at line 948 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/v at line 949 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/i at line 949 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 949 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 950 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 950 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx2 at line 950 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 950 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idxv at line 950 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idxv at line 951 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 953 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 953 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx2 at line 953 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idxv at line 953 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 955 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/+ at line 955 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 957 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 957 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 958 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 958 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 958 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 958 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 959 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 959 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 959 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 959 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 959 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 959 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 959 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 961 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/byte at line 961 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 961 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 961 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 962 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/short at line 962 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 962 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 962 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 963 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/float at line 963 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 963 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 963 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 964 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/double at line 964 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 964 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 964 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 966 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-byte at line 966 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 966 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 966 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 967 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-char at line 967 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 967 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 967 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 968 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-short at line 968 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 968 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 968 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 969 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-float at line 969 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 969 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 969 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 970 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-double at line 970 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 970 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 970 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 972 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-add at line 972 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 973 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 973 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 973 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 975 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-add-int at line 975 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 976 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 976 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 976 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 978 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-dec at line 978 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 979 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 979 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 981 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-dec-int at line 981 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 982 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 982 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 984 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-divide-int at line 984 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 985 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 985 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 985 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 987 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-inc at line 987 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 988 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 988 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 990 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-inc-int at line 990 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 991 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 991 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 993 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-multiply at line 993 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 994 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 994 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 994 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 996 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-multiply-int at line 996 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 997 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 997 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 997 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 999 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-negate at line 999 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1000 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1000 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1002 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-negate-int at line 1002 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1003 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1003 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1005 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-remainder-int at line 1005 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1006 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1006 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1006 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1006 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1008 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-subtract at line 1008 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1009 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 1009 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 1009 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1011 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unchecked-subtract-int at line 1011 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1012 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 1012 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 1012 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1014 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/- at line 1014 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1015 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1015 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1016 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1016 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1016 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1016 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1017 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1017 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1017 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1017 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1017 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1017 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1017 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1019 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/* at line 1019 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1021 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1021 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1022 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1022 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1022 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1022 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1023 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1023 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1023 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1023 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1023 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1023 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1023 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1025 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros// at line 1025 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1026 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1026 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1027 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1027 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1027 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1027 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1028 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1028 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1028 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1028 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1028 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1028 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1028 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1030 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/divide at line 1030 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1031 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1031 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1032 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1032 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1032 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1032 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1033 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1033 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1033 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1033 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1033 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1033 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1033 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1035 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/< at line 1035 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1036 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1037 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1037 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1037 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1037 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1038 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1038 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1038 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1038 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1038 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1038 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1038 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1038 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1040 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/<= at line 1040 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1041 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1042 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1042 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1042 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1042 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1043 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1043 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1043 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1043 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1043 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1043 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1043 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1043 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1045 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/> at line 1045 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1046 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1047 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1047 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1047 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1047 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1048 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1048 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1048 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1048 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1048 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1048 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1048 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1048 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1050 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/>= at line 1050 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1051 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1052 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1052 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1052 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1052 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1053 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1053 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1053 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1053 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1053 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1053 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1053 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1053 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1055 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/== at line 1055 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1056 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1057 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1057 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1057 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1057 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1058 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1058 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1058 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1058 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1058 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1058 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1058 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1058 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1060 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/dec at line 1060 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1060 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1061 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1063 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/inc at line 1063 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1063 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1064 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1066 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/zero? at line 1066 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1066 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1067 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1069 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/pos? at line 1069 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1069 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1070 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1072 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/neg? at line 1072 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1072 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1073 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1075 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/max at line 1075 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1076 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1076 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1077 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1077 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1077 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1077 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1079 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1079 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1079 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1079 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1079 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1079 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1079 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1081 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/min at line 1081 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1082 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1082 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1083 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1083 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1083 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1083 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1085 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1085 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1085 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1085 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1085 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1085 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1085 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1087 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-mod at line 1087 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/num at line 1087 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/div at line 1087 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/div at line 1088 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/num at line 1088 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1090 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-not at line 1090 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1090 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1091 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1093 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-and at line 1093 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1094 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1094 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1094 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1094 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1095 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1095 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1095 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1095 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1095 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1095 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1095 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1098 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unsafe-bit-and at line 1098 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1099 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1099 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1099 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1099 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1100 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1100 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1100 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1100 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1100 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1100 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1100 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1102 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-or at line 1102 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1103 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1103 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1103 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1103 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1104 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1106 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/int at line 1106 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1106 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1107 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1109 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-xor at line 1109 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1110 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1110 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1110 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1110 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1111 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1111 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1111 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1111 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1111 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1111 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1111 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1113 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-and-not at line 1113 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1114 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1114 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1114 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1114 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/y at line 1115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/more at line 1115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1117 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-clear at line 1117 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1117 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1117 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1118 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1118 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1120 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-flip at line 1120 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1120 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1120 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1121 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1121 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1123 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-test at line 1123 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1123 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1123 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1124 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1124 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1126 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-shift-left at line 1126 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1126 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1126 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1127 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1127 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1129 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-shift-right at line 1129 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1129 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1129 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1130 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1130 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1132 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-shift-right-zero-fill at line 1132 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1132 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1132 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1133 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1133 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1135 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/unsigned-bit-shift-right at line 1135 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1135 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1135 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1136 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1136 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1138 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bit-set at line 1138 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1138 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1138 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/n at line 1139 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1139 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1142 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/mask at line 1142 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/shift at line 1142 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/shift at line 1143 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bitpos at line 1146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/shift at line 1146 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/shift at line 1147 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1150 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/caching-hash at line 1150 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/coll at line 1150 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/hash-fn at line 1150 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/hash-key at line 1150 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/hash-key at line 1151 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/hash-key at line 1152 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/hash-fn at line 1155 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/coll at line 1155 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/hash-key at line 1156 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1168 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/defcurried at line 1168 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doc at line 1171 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/args at line 1171 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1171 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1171 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doc at line 1172 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/args at line 1172 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1172 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1185 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/rfn at line 1185 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/f1 at line 1187 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/k at line 1187 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fkv at line 1187 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/f1 at line 1188 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/k at line 1188 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fkv at line 1188 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1216 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/reify at line 1216 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1254 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1254 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1262 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1263 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1273 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&form at line 1274 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1276 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/specify! at line 1276 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 1278 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1278 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1278 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 1280 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1281 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1284 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/specify at line 1284 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 1287 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1287 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1287 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 1288 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1289 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1291 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-this at line 1291 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1294 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/this-as at line 1294 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1296 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1296 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1298 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1483 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/extend-type at line 1483 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/type-sym at line 1494 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1494 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1494 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1495 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1496 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1498 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/type-sym at line 1499 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/type-sym at line 1501 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/type-sym at line 1503 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/type-sym at line 1505 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/type-sym at line 1505 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/type-sym at line 1506 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1574 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/deftype at line 1574 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 1623 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1623 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1623 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1623 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 1624 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1624 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1625 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 1626 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1627 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1628 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/t at line 1629 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1633 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1634 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1635 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1635 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1636 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1641 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1738 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/defrecord at line 1738 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/rsym at line 1791 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1791 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1791 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1791 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/rsym at line 1792 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1792 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/rsym at line 1793 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1795 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1798 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1798 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/impls at line 1798 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1799 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1803 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fields at line 1804 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1807 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/defprotocol at line 1807 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1847 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1847 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doc+methods at line 1847 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1848 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1848 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doc+methods at line 1849 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doc+methods at line 1850 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doc+methods at line 1850 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doc+methods at line 1851 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1852 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1855 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1902 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1919 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/implements? at line 1919 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1921 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1921 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1924 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1924 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1930 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1931 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1938 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1939 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1940 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1945 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/satisfies? at line 1945 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1947 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1947 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 1950 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1950 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1956 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1957 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1963 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1965 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1966 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1967 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1968 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1970 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1971 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1971 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/psym at line 1973 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 1973 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1975 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/lazy-seq at line 1975 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1980 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1980 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1981 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1983 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/delay at line 1983 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1988 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1988 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1989 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 1991 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/with-redefs at line 1991 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 1999 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 1999 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 1999 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2000 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2001 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2009 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2013 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/binding at line 2013 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2021 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2021 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2021 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2022 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2023 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2024 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2024 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2026 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/condp at line 2026 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/pred at line 2047 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2047 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2047 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2047 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/pred at line 2064 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2065 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2066 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2090 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/case at line 2090 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/e at line 2113 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2113 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2113 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2114 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2115 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/e at line 2118 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2119 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2135 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2140 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2140 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/clauses at line 2140 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/e at line 2143 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/e at line 2151 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/e at line 2151 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/e at line 2156 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2161 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/assert at line 2161 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 2164 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 2166 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 2168 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 2169 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/message at line 2169 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 2171 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/message at line 2173 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 2173 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2175 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/for at line 2175 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2185 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body-expr at line 2185 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/assert-args at line 2186 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/for at line 2186 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2187 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2188 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body-expr at line 2214 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body-expr at line 2237 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2259 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2260 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2262 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doseq at line 2262 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2266 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2266 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2266 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/assert-args at line 2267 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/doseq at line 2267 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2268 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2269 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2273 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/seq-exprs at line 2316 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2318 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/array at line 2318 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2318 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2327 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/make-array at line 2327 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/size at line 2328 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/size at line 2330 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/size at line 2331 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/size at line 2332 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2335 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/list at line 2335 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 2337 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2337 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2337 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2338 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/x at line 2338 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2340 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/vector at line 2340 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2342 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2342 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2343 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2346 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2348 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2351 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/array-map at line 2351 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2353 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/kvs at line 2353 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/kvs at line 2354 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2356 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2356 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/kvs at line 2358 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/kvs at line 2358 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/kvs at line 2359 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2361 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/hash-map at line 2361 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2363 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/kvs at line 2363 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/kvs at line 2364 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2371 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/hash-set at line 2371 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2373 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2373 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2374 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2376 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2376 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2377 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2377 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2374 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2376 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2376 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2377 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2377 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2379 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2379 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/xs at line 2382 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2394 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-obj at line 2394 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2394 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2414 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/alength at line 2414 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 2414 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 2416 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2419 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/amap at line 2419 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 2424 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2424 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ret at line 2424 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2424 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 2425 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ret at line 2426 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2427 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2428 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ret at line 2430 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2430 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2430 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2431 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ret at line 2432 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2434 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/areduce at line 2434 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 2438 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2438 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ret at line 2438 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/init at line 2438 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2438 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/a at line 2439 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2440 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ret at line 2440 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/init at line 2440 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2441 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/idx at line 2442 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2442 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ret at line 2443 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2445 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/dotimes at line 2445 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2450 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2450 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2450 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2451 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2452 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2456 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2469 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/defmulti at line 2469 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/mm-name at line 2477 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2477 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/options at line 2477 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/options at line 2478 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/options at line 2479 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/options at line 2481 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/options at line 2482 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/options at line 2483 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/mm-name at line 2495 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/mm-name at line 2496 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2498 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/mm-name at line 2506 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/mm-name at line 2512 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2515 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/defmethod at line 2515 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/multifn at line 2517 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/dispatch-val at line 2517 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2517 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fn-tail at line 2517 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/multifn at line 2518 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/dispatch-val at line 2518 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/fn-tail at line 2518 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2520 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/time at line 2520 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2522 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2524 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2530 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/simple-benchmark at line 2530 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2537 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2537 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/iterations at line 2537 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2537 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/print-fn at line 2537 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/print-fn at line 2537 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2538 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2539 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/bindings at line 2540 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/iterations at line 2542 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/expr at line 2542 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/print-fn at line 2545 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/iterations at line 2546 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2565 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/gen-apply-to at line 2565 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2575 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/with-out-str at line 2575 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2579 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2579 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/body at line 2583 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2586 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/lazy-cat at line 2586 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2592 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/colls at line 2592 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/colls at line 2593 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2595 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/js-str at line 2595 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/s at line 2595 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/s at line 2596 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2598 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/es6-iterable at line 2598 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ty at line 2598 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ty at line 2599 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2604 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns-interns at line 2604 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote at line 2606 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2606 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote at line 2607 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2607 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote at line 2607 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2607 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2612 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2613 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2615 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns-unmap at line 2615 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote0 at line 2617 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2617 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote1 at line 2617 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sym at line 2617 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote0 at line 2618 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2618 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote1 at line 2619 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sym at line 2619 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote0 at line 2618 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2618 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quote1 at line 2619 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sym at line 2619 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2621 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sym at line 2621 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/ns at line 2622 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/sym at line 2622 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2624 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/vswap! at line 2624 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/vol at line 2628 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/f at line 2628 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/& at line 2628 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/args at line 2628 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/vol at line 2629 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/f at line 2629 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/vol at line 2629 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/args at line 2629 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2632 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/load-file* at line 2632 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/f at line 2632 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/f at line 2633 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2635 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/macroexpand-1 at line 2635 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quoted at line 2638 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quoted at line 2639 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quoted at line 2641 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2642 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2644 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/macroexpand at line 2644 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quoted at line 2648 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quoted at line 2649 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/quoted at line 2651 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/&env at line 2652 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core/defmacro at line 2697 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/copy-arguments at line 2697 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/dest at line 2697 .cljs_node_repl/cljs/core.cljc
WARNING: Use of undeclared Var cljs.core$macros/dest at line 2701 .cljs_node_repl/cljs/core.cljc
TypeError: Cannot read property 'call' of undefined
    at Object.<anonymous> (/Users/mfikes/Downloads/.cljs_node_repl/cljs/core$macros.js:11:19)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at global.CLOSURE_IMPORT_SCRIPT (repl:75:3)
    at Object.goog.require (repl:21:8)
    at Object.<anonymous> (/Users/mfikes/Downloads/.cljs_node_repl/cljs/js.js:14:6)
cljs.user=>


 Comments   
Comment by Mike Fikes [ 05/Feb/16 5:06 PM ]

Some analysis:

A more fundamental issue is that, in script/noderepljs, the defmacro underlying function exists:

cljs.user=> (defmacro x [])
true

while this is not the case with cljs.jar

cljs.user=> (defmacro x [])
WARNING: Use of undeclared Var cljs.user/defmacro at line 1 <cljs repl>
WARNING: Use of undeclared Var cljs.user/x at line 1 <cljs repl>
TypeError: Cannot read property 'call' of undefined
    at repl:1:107
    at repl:9:3
    at repl:14:4
    at Object.exports.runInThisContext (vm.js:54:17)
    at Domain.<anonymous> ([stdin]:41:34)
    at Domain.run (domain.js:221:14)
    at Socket.<anonymous> ([stdin]:40:25)
    at emitOne (events.js:77:13)
    at Socket.emit (events.js:169:7)
    at readableAddChunk (_stream_readable.js:146:16)

Perhaps this is associated with the difference that is causing compilation of the core.cljc file to fail. There is also some circularity to sort out with respect to this.

Comment by Mike Fikes [ 06/Feb/16 8:21 AM ]

The attached patch addresses the issue. The rationale is that it copies the working approach for defn.

Here is an example testing it with Nashorn (it also works with Node):

$ java -jar ~/Projects/clojurescript/target/cljs.jar -m cljs.repl.nashorn
To quit, type: :cljs/quit
cljs.user=> (require 'cljs.js)
nil
cljs.user=> (cljs.js/eval-str (cljs.js/empty-state) 
              "(+ 1 2)" nil {:eval cljs.js/js-eval} identity)
{:ns cljs.user, :value 3}




[CLJS-1561] WARN if recur passes non-inferred type Created: 06/Feb/16  Updated: 06/Feb/16

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.228
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Mike Fikes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Take this code as an example:

(defn f [^boolean b]
  (loop [x b]
    (if x
      (recur 0)
      :done)))

The type of x is inferred to be Boolean, but there is a recur form that can be statically deduced to be passing a non-Boolean.

This ticket asks that a WARN be issued for this case, and perhaps others (where maybe x itself is directly type hinted).






[CLJS-633] Missing Java type hints in closure.clj Created: 22/Oct/13  Updated: 22/Oct/13

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Julien Eluard Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs_ticket_633.patch    

 Description   

A number of reflection warnings are generated from closure.clj. Fixing those probably would not improved performance but it would be cleaner anyway.



 Comments   
Comment by Julien Eluard [ 22/Oct/13 8:03 AM ]

Attached patch.

There are a couple warnings left, similar to:
Reflection warning, cljs/closure.clj:232:1 - reference to field url can't be resolved.
They appear to be due to some unexpected protocol method name? It looks harmless.





[CLJS-872] Ordered collections printed as if they were unordered at the REPL Created: 13/Oct/14  Updated: 14/Oct/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Michał Marczyk Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

This is due to cljs.repl's read-then-print processing of string representations of return values that come back from the JS env. As of release 2371, the relevant code fragment lives here:

https://github.com/clojure/clojurescript/blob/r2371/src/clj/cljs/repl.clj#L156

A larger snippet to demonstrate this:

ClojureScript:cljs.user> (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14)
{1 2, 3 4, 5 6, 7 8, 9 10, 11 12, 13 14}
ClojureScript:cljs.user> (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
{7 8, 1 2, 15 16, 13 14, 17 18, 3 4, 11 12, 9 10, 5 6}
ClojureScript:cljs.user> (seq (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18))
([1 2] [3 4] [5 6] [7 8] [9 10] [11 12] [13 14] [15 16] [17 18])
ClojureScript:cljs.user> (hash-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
{7 8, 1 2, 15 16, 13 14, 17 18, 3 4, 11 12, 9 10, 5 6}

This issue seems to be the most likely cause of the problem described in this StackOverflow question. It would be nice to print ordered collections in the "expected" way to prevent user confusion.



 Comments   
Comment by David Nolen [ 14/Oct/14 5:23 AM ]

How is this handled in Clojure?

Comment by Michał Marczyk [ 14/Oct/14 7:40 AM ]

The built-in REPL simply prints string representations of values to *out* without attempting to read them back in first.

Comment by David Nolen [ 14/Oct/14 7:54 AM ]

Well the result of REPL evaluation is a string unlike Clojure, in order to get a proper print at the ClojureScript REPL it seems necessary to read back the result. I will say it's not clear to me array-map promises anything about order anyway.

Comment by Michał Marczyk [ 14/Oct/14 8:02 AM ]

It does – see http://clojure.org/data_structures, where it says

ArrayMaps
When doing code form manipulation it is often desirable to have a map which maintains key order. An array map is such a map - it is simply implemented as an array of key val key val... As such, it has linear lookup performance, and is only suitable for very small maps. It implements the full map interface. New ArrayMaps can be created with the array-map function. Note that an array map will only maintain sort order when un-'modified'. Subsequent assoc-ing will eventually cause it to 'become' a hash-map.

This snippet has been there for as long as I can remember; and this particular feature comes up in various online discussions from time to time. The docstrings for array-map (the core function) are unambiguous in their promise to construct array maps in both Clojure and ClojureScript.

As for the issue at hand, I do think it's a very minor one (hence the "Trivial" priority), but it is real – the representation printed at the REPL is out of line with the string returned from pr-str on the same value. In fact, one way to fix this would be to use pr-str representations computed on the CLJS side. (There may be some complications here, though, which we'd have to work out.)

Comment by David Nolen [ 14/Oct/14 8:07 AM ]

Thanks for pointing out the API promise. OK, yeah I don't really have a good idea for how do this but a patch that isn't too ugly is welcome





[CLJS-507] Persistent Data Structure Benchmark Created: 20/May/13  Updated: 02/Dec/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Trivial
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Put together an easy to run series of persistent data structure benchmarks that can be easily run. For example we would like to submit to this Mozilla ticket http://bugzilla.mozilla.org/show_bug.cgi?id=874174






[CLJS-450] (ns) within (do) inconsistent with Clojure behaviour Created: 27/Dec/12  Updated: 21/Feb/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Stuart Campbell Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

An (ns) within a (do) doesn't quite work as expected at the REPL:

ClojureScript:cljs.user> (do (ns foo) (def x 42))   
nil
ClojureScript:foo> x
nil
ClojureScript:cljs.user> cljs.user/x
42

The Clojure equivalent:

user=> (do (ns foo) (def x 42))
#'foo/x
foo=> x
42


 Comments   
Comment by David Nolen [ 05/Jan/13 2:05 PM ]

Looks like we need to do something similar to what is done in Clojure with top level do - http://github.com/frenchy64/typed-clojure/pull/4





[CLJS-1009] Allow deps.cljs to declare a foreign lib as remote Created: 05/Feb/15  Updated: 21/Feb/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Martin Klepsch Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None


 Description   

When using things like the Google Maps JS API [1] the Javascript that is required can't be bundled inside a jar as it depends on the used API key.

To be able to provide externs for those kind of libraries there should be a way to declare them as "remote" in deps.cljs.

[1] https://developers.google.com/maps/documentation/javascript/tutorial






[CLJS-555] CLONE - Implement ratios Created: 27/Jul/13  Updated: 02/Dec/14

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Stuart Halloway Assignee: Unassigned
Resolution: Unresolved Votes: 2
Labels: None


 Description   

Clojure.java contains support for Ratio types. It would be nice to have them in Clojurescript as well, but as far as I can tell this would be new development (please comment if I'm wrong). That is, there is no implementation of Ratio types in GClosure so this feature would need to be implemented from the ground up. In additional to the Ratio type, the following corresponding functions would also need implementations:

  • `ratio?`
  • `numerator`
  • `denominator`
  • `rationalize`

Plus the ratio type would need to be rolled into the existing mathematical frameworkings.

Imported from github issue #66



 Comments   
Comment by David Nolen [ 02/Dec/14 6:14 AM ]

Lower priority, unsolvable without numerics overhaul.





[CLJS-1185] Support preambles when our target is node.js and we are compiler a main file Created: 02/Apr/15  Updated: 02/Apr/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Ivan Willig Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1185.patch    




[CLJS-1251] Missing semicolons when emitting deftype and defrecord Created: 07/May/15  Updated: 07/May/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Antonin Hildebrand Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File cljs_1251.patch    

 Description   

Emitted code for deftype and defrecord has to separate the var assignment from body content by a semicolon (do not rely on automatic javascript semicolon insertion).

The bad case:
If body has the first statement wrapped in (...), javascript will treat it as a function call on the constructor definition.






[CLJS-1295] Improve doc for instance Created: 01/Jun/15  Updated: 01/Jun/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Julien Eluard Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1295.patch    

 Description   

Doc for instance? does not reflect argument names.






[CLJS-1378] JARs that end in .exe are problematic Created: 29/Jul/15  Updated: 30/Jul/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 0.0-3308
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: David Nolen Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

compile-from-jar cannot handle the later form

{{jar:file:/Users/candera/cognitect/walmart/walsim/deploy/walsim-v0.3.5.jar!/cljs/com/walmart/test/app.cljs}}
{{jar:file:/Users/candera/cognitect/walmart/walsim/deploy/walsim-v0.3.5.exe!/cljs/com/walmart/test/app.cljs}}






[CLJS-1450] Arithmetic warning thrown for impossible condition Created: 15/Sep/15  Updated: 15/Sep/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.48
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Quest Yarbrough Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: bug, compiler


 Description   

The following code triggers an arithmetic warning even though the condition it's warning about is impossible to reach. I tested this code in Clojure and it did not generate a warning. I would guess that the CLJS compiler doesn't take note of the (js/Error) in the same way that the Clojure compiler treats (Error.)

The exact warning triggered is below, followed by the code.

WARNING: cljs.core/+, all arguments must be numbers, got [number clj-nil] instead. at line 22 src\spurious_arithmetic\core.cljs
(def x [0 1 2 3 4 nil])
(def index (atom -1))
(defn take-value []
  (->> (swap! index inc)
       (nth x)))

(-> (loop [result (take-value)
           prev nil]
      (if (= nil result prev) (throw (js/Error. "This condition prevents nil arithmetic.")))
      (if (some? result)
        (recur (take-value) result)
        (+ 1 prev)))                                        ; this triggers the [number cljs-nil] warning
    (print)) ; 5





[CLJS-844] Optimize js->clj by switching to transients Created: 22/Aug/14  Updated: 09/Oct/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Darrick Wiebe Assignee: Darrick Wiebe
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File use-transducers-in-js-to-clj.patch     Text File use-transducers-in-js-to-clj.patch    

 Comments   
Comment by David Nolen [ 23/Aug/14 1:19 PM ]

Did you any benchmarks on other JS engines?

Comment by Darrick Wiebe [ 23/Aug/14 2:14 PM ]

No. My main concern was to check if there was any startup overhead that might offset the basic efficiency improvements for processing small collections. Using into with a transducer turned out to be faster in every scenario, significantly in most.

Comment by David Nolen [ 23/Aug/14 2:19 PM ]

It would be nice to see a jsperf of before and after on this ticket. Thanks.

Comment by Darrick Wiebe [ 23/Aug/14 2:23 PM ]

Is there a existing one that I can work from?

Comment by David Nolen [ 23/Aug/14 2:35 PM ]

There is not. I generally just make a simple project, create an advanced compiled artifact and copy and paste it into jsperf.

Comment by Darrick Wiebe [ 24/Aug/14 7:24 PM ]

Turns out reducing into a transient is considerably better than using a transducer (which was itself a little faster) for this.

http://jsperf.com/js-clj-transducer-test

The code is at:

https://gist.github.com/pangloss/591d77231fda460c2fbe

Let me know if you want me to prepare an updated patch.

Comment by David Nolen [ 25/Aug/14 7:34 AM ]

Thanks for putting this together. Yes please provide an updated patch.

Comment by Darrick Wiebe [ 26/Aug/14 11:19 AM ]

Not sure whether the convention is to comment that I've uploaded a new patch. Regardless, I uploaded it yesterday.

Comment by Marcin Kulik [ 07/Oct/15 1:46 PM ]

I have tested and benchmarked the patch on a big js objects (5MB+ json files) and I confirm that new-js->clj3 function is more than 2x faster. It runs now in the player on https://asciinema.org and all seems good so far.

Comment by David Nolen [ 08/Oct/15 2:33 PM ]

Marcin thanks for the feedback. Experience reports always help push tickets forward.

Darrick, the patch need to be rebased to master. Please remove all patches except the one that will be applied.

Comment by Rohit Aggarwal [ 08/Oct/15 3:06 PM ]

[ClojureScript beginner here. so do ignore this if I am mistaken]

The patch of 25/Aug uses `(aget x k)` instead of `(goog.object/get x k)` for getting the value of a key if x is an object. I believe it isn't the right way even though it works.

This contains why the latter is preferred over the former.

Comment by David Nolen [ 09/Oct/15 12:33 PM ]

Rohit good catch. Yes that should be changed.





[CLJS-324] cljs.core/format Created: 24/Jun/12  Updated: 11/Mar/15

Status: Reopened
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Gary Fredericks Assignee: Unassigned
Resolution: Unresolved Votes: 1
Labels: None

Attachments: Text File 0001-CLJS-324-implement-cljs.core-format-as-wrapper-for-g.patch     File goog.string.format-0.0-1913.tgz    

 Description   

Implement cljs.core/format. Make sure there is nothing in gclosure for this. I suppose we should try to emulate the jvm version as much as that makes sense?



 Comments   
Comment by Michał Marczyk [ 28/Jun/12 11:29 AM ]

GClosure does actually include a string formatter – goog.string.format. Note that that's both a non-ctor function name and the GClosure "namespace" name, so in order to use it one must require goog.string.format on top of gstring and say gstring/format (or perhaps leave out the gstring require spec and use goog.string/format – not tested, but should work).

The patch to introduce format and printf as wrappers for goog.string.format is naturally extremely simple, so here it is. Note that this particular patch must be applied on top of CLJS-328.

I have no idea how goog.string.format compares to the JVM's String/format (basic number formatting seems to work as it should in sprintf-like functions, but other than that I haven't tested it much).

Comment by David Nolen [ 29/Jun/12 10:44 AM ]

The tests fail for me with this patch applied.

Comment by David Nolen [ 29/Jun/12 11:07 AM ]

fixed, http://github.com/clojure/clojurescript/commit/8f518760a3df8b351208e97bb70270856623bb0a

Comment by David Nolen [ 11/Sep/13 5:05 PM ]

Backing this one out, goog.string.format defies advanced optimization and it provides few of the capabilities of Clojure's format - which does a lot because of java.util.Formatter. Apologies for the churn, but this is a simple thing for people to stub in themselves for the little bit of functionality it actually delivers.

Comment by Lars Bohl [ 12/Oct/13 6:33 AM ]

Uploading a slighly modified version lein-cljsbuild's "advanced" demo, to demonstrate that using goog.string.format produces a runtime error with clojurescript 0.0.1913. Run "lein ring server" and navigate to http://localhost:3000/

The code in hello.cljs shows that goog.string.toTitleCase works, but not goog.string.format.

Comment by Julien Eluard [ 12/Oct/13 6:43 AM ]

It looks like you are not requiring correctly format. See a working example here.

Comment by Lars Bohl [ 12/Oct/13 6:58 AM ]

Julent, thanks! It needs another [goog.string.format] after [goog.string :as gstring] before you can use gstring/format. hello.cljs now looks like this, and throws no exceptions: https://www.refheap.com/19693





[CLJS-1510] Invalid refer message mentions var twice Created: 11/Dec/15  Updated: 11/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1510.patch    
Patch: Code

 Description   
cljs.user=> (require '[clojure.string :refer [foo]])
clojure.lang.ExceptionInfo: Invalid :refer, var var clojure.string/foo does not exist in file <cljs repl> {:tag :cljs/analysis-error}

Note "var var" above.






[CLJS-1364] cljs.js: Update default *load-fn* args to reflect docstring Created: 23/Jul/15  Updated: 18/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Trivial
Reporter: Mike Fikes Assignee: Andrea Richiardi
Resolution: Unresolved Votes: 0
Labels: None

Attachments: Text File CLJS-1364-1.patch    

 Description   

The default *load-fn* :

(fn [name cb]
    (throw (js/Error. "No *load-fn* set")))

But the name arg reflects an older impl, with the new arg actually being a map.

To avoid confusion for anyone reading this code, perhaps

(fn [_ _]
    (throw (js/Error. "No *load-fn* set")))

or maybe name the first argument something meaningful?



 Comments   
Comment by Andrea Richiardi [ 18/Dec/15 6:52 PM ]

I decided to give it a try





[CLJS-1526] Doc for *print-err-fn* refers to *print-fn* Created: 30/Dec/15  Updated: 30/Dec/15

Status: Open
Project: ClojureScript
Component/s: None
Affects Version/s: 1.7.145
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Mike Fikes Assignee: David Nolen
Resolution: Unresolved Votes: 0
Labels: docstring

Attachments: Text File CLJS-1526.patch    
Patch: Code

 Description